diff --git a/.drone.yml b/.drone.yml index 4b14bce0b8aa38dfc975b5d0f3253130d2025dca..085a07acf94a57cbcaf076c149cebdf243f8ff74 100644 --- a/.drone.yml +++ b/.drone.yml @@ -23,6 +23,7 @@ steps: branch: - develop - master + - 2.0 --- kind: pipeline name: test_arm64_bionic @@ -150,6 +151,7 @@ steps: branch: - develop - master + - 2.0 --- kind: pipeline name: build_trusty @@ -176,6 +178,7 @@ steps: branch: - develop - master + - 2.0 --- kind: pipeline name: build_xenial @@ -201,7 +204,7 @@ steps: branch: - develop - master - + - 2.0 --- kind: pipeline name: build_bionic @@ -226,6 +229,7 @@ steps: branch: - develop - master + - 2.0 --- kind: pipeline name: build_centos7 @@ -249,4 +253,4 @@ steps: branch: - develop - master - + - 2.0 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 50f4251320abc80358b67eab22c02672d5f26bd6..2c37aa92f77dd14bd274be94568dfe904f48c5f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ build/ +.ycm_extra_conf.py .vscode/ .idea/ cmake-build-debug/ diff --git a/Jenkinsfile b/Jenkinsfile index 882d224407c27a06bacd96ff246dfc8d84e264a8..91855a92fb811a7380ea9dca75745d21386f8496 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -234,11 +234,12 @@ pipeline { cd ${WKC}/tests/examples/nodejs npm install td2.0-connector > /dev/null 2>&1 node nodejsChecker.js host=localhost + node test1970.js ''' sh ''' cd ${WKC}/tests/examples/C#/taosdemo mcs -out:taosdemo *.cs > /dev/null 2>&1 - echo '' |./taosdemo + echo '' |./taosdemo -c /etc/taos ''' sh ''' cd ${WKC}/tests/gotest @@ -256,21 +257,19 @@ pipeline { steps { pre_test() - catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { - timeout(time: 60, unit: 'MINUTES'){ - sh ''' - cd ${WKC}/tests/pytest - ./crash_gen.sh -a -p -t 4 -s 2000 - ''' - } - } timeout(time: 60, unit: 'MINUTES'){ sh ''' cd ${WKC}/tests/pytest - rm -rf /var/lib/taos/* - rm -rf /var/log/taos/* - ./handle_crash_gen_val_log.sh + ./crash_gen.sh -a -p -t 4 -s 2000 ''' + } + timeout(time: 60, unit: 'MINUTES'){ + // sh ''' + // cd ${WKC}/tests/pytest + // rm -rf /var/lib/taos/* + // rm -rf /var/log/taos/* + // ./handle_crash_gen_val_log.sh + // ''' sh ''' cd ${WKC}/tests/pytest rm -rf /var/lib/taos/* @@ -453,4 +452,4 @@ pipeline { ) } } -} \ No newline at end of file +} diff --git a/cmake/define.inc b/cmake/define.inc index 9ee09c86b066afb9edb56d0cd97f671b0bb4df6a..337a143e1f129d433f12d6772e9ed9c43d57c423 100755 --- a/cmake/define.inc +++ b/cmake/define.inc @@ -133,8 +133,10 @@ IF (TD_LINUX) IF (TD_MEMORY_SANITIZER) SET(DEBUG_FLAGS "-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment -static-libasan -O0 -g3 -DDEBUG") + MESSAGE(STATUS "memory sanitizer detected as true") ELSE () SET(DEBUG_FLAGS "-O0 -g3 -DDEBUG") + MESSAGE(STATUS "memory sanitizer detected as false") ENDIF () SET(RELEASE_FLAGS "-O3 -Wno-error") diff --git a/cmake/version.inc b/cmake/version.inc index ffceecf49215bcef9136c0b5d2f0f1e1290c9ed1..dfeb26454f9b6278132c3a92640a6aa8611456da 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.6.0") + SET(TD_VER_NUMBER "2.1.7.2") ENDIF () IF (DEFINED VERCOMPATIBLE) @@ -86,7 +86,7 @@ ENDIF () MESSAGE(STATUS "============= compile version parameter information start ============= ") MESSAGE(STATUS "ver number:" ${TD_VER_NUMBER}) MESSAGE(STATUS "compatible ver number:" ${TD_VER_COMPATIBLE}) -MESSAGE(STATUS "communit commit id:" ${TD_VER_GIT}) +MESSAGE(STATUS "community commit id:" ${TD_VER_GIT}) MESSAGE(STATUS "internal commit id:" ${TD_VER_GIT_INTERNAL}) MESSAGE(STATUS "build date:" ${TD_VER_DATE}) MESSAGE(STATUS "ver type:" ${TD_VER_VERTYPE}) diff --git a/deps/MsvcLibX/src/iconv.c b/deps/MsvcLibX/src/iconv.c index 40b6e6462d9d0a6dc53509e8645cfba50b446256..1ec0dc73547852e37a23ff308cb740bbd88d872c 100644 --- a/deps/MsvcLibX/src/iconv.c +++ b/deps/MsvcLibX/src/iconv.c @@ -98,6 +98,7 @@ int ConvertString(char *buf, size_t nBytes, UINT cpFrom, UINT cpTo, LPCSTR lpDef char *DupAndConvert(const char *string, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar) { int nBytes; char *pBuf; + char *pBuf1; nBytes = 4 * ((int)lstrlen(string) + 1); /* Worst case for the size needed */ pBuf = (char *)malloc(nBytes); if (!pBuf) { @@ -110,8 +111,9 @@ char *DupAndConvert(const char *string, UINT cpFrom, UINT cpTo, LPCSTR lpDefault free(pBuf); return NULL; } - pBuf = realloc(pBuf, nBytes+1); - return pBuf; + pBuf1 = realloc(pBuf, nBytes+1); + if(pBuf1 == NULL && pBuf != NULL) free(pBuf); + return pBuf1; } int CountCharacters(const char *string, UINT cp) { diff --git a/deps/MsvcLibX/src/main.c b/deps/MsvcLibX/src/main.c index f366b081ad688e15dc62dd0c8a7ccf9bb409afe0..85f4c83f24400e12c4a4b996b863df94e07cf819 100644 --- a/deps/MsvcLibX/src/main.c +++ b/deps/MsvcLibX/src/main.c @@ -68,6 +68,7 @@ int BreakArgLine(LPSTR pszCmdLine, char ***pppszArg) { int iString = FALSE; /* TRUE = string mode; FALSE = non-string mode */ int nBackslash = 0; char **ppszArg; + char **ppszArg1; int iArg = FALSE; /* TRUE = inside an argument; FALSE = between arguments */ ppszArg = (char **)malloc((argc+1)*sizeof(char *)); @@ -89,7 +90,10 @@ int BreakArgLine(LPSTR pszCmdLine, char ***pppszArg) { if ((!iArg) && (c != ' ') && (c != '\t')) { /* Beginning of a new argument */ iArg = TRUE; ppszArg[argc++] = pszCopy+j; - ppszArg = (char **)realloc(ppszArg, (argc+1)*sizeof(char *)); + ppszArg1 = (char **)realloc(ppszArg, (argc+1)*sizeof(char *)); + if(ppszArg1 == NULL && ppszArg != NULL) + free(ppszArg); + ppszArg = ppszArg1; if (!ppszArg) return -1; pszCopy[j] = c0 = '\0'; } @@ -212,7 +216,7 @@ int _initU(void) { fprintf(stderr, "Warning: Can't convert the argument line to UTF-8\n"); _acmdln[0] = '\0'; } - realloc(_acmdln, n+1); /* Resize the memory block to fit the UTF-8 line */ + //realloc(_acmdln, n+1); /* Resize the memory block to fit the UTF-8 line */ /* Should not fail since we make it smaller */ /* Record the console code page, to allow converting the output accordingly */ diff --git a/deps/MsvcLibX/src/realpath.c b/deps/MsvcLibX/src/realpath.c index 5fbcf773a24d0950ac8099cd9274fcbb3157a954..e2ba755f2d8b60e545e8ead71d198e60ca7a47c0 100644 --- a/deps/MsvcLibX/src/realpath.c +++ b/deps/MsvcLibX/src/realpath.c @@ -196,6 +196,7 @@ not_compact_enough: /* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */ char *realpath(const char *path, char *outbuf) { char *pOutbuf = outbuf; + char *pOutbuf1 = NULL; int iErr; const char *pc; @@ -242,8 +243,11 @@ realpath_failed: return NULL; } - if (!outbuf) pOutbuf = realloc(pOutbuf, strlen(pOutbuf) + 1); - return pOutbuf; + if (!outbuf) { + pOutbuf1 = realloc(pOutbuf, strlen(pOutbuf) + 1); + if(pOutbuf1 == NULL && pOutbuf) free(pOutbuf); + } + return pOutbuf1; } #endif @@ -517,6 +521,7 @@ int ResolveLinksA(const char *path, char *buf, size_t bufsize) { /* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */ char *realpathU(const char *path, char *outbuf) { char *pOutbuf = outbuf; + char *pOutbuf1 = NULL; char *pPath1 = NULL; char *pPath2 = NULL; int iErr; @@ -590,10 +595,13 @@ realpathU_failed: } DEBUG_LEAVE(("return 0x%p; // \"%s\"\n", pOutbuf, pOutbuf)); - if (!outbuf) pOutbuf = realloc(pOutbuf, strlen(pOutbuf) + 1); + if (!outbuf) { + pOutbuf1 = realloc(pOutbuf, strlen(pOutbuf) + 1); + if(pOutbuf1 == NULL && pOutbuf) free(pOutbuf); + } free(pPath1); free(pPath2); - return pOutbuf; + return pOutbuf1; } #endif /* defined(_WIN32) */ diff --git a/documentation20/cn/01.evaluation/docs.md b/documentation20/cn/01.evaluation/docs.md index f7cdc31034670f86ada1951d1000b88f814a62e8..edfa7af7e9a24be9a6d6ab1de3591deb48e22b3a 100644 --- a/documentation20/cn/01.evaluation/docs.md +++ b/documentation20/cn/01.evaluation/docs.md @@ -2,18 +2,18 @@ ## TDengine 简介 -TDengine是涛思数据面对高速增长的物联网大数据市场和技术挑战推出的创新性的大数据处理产品,它不依赖任何第三方软件,也不是优化或包装了一个开源的数据库或流式计算产品,而是在吸取众多传统关系型数据库、NoSQL数据库、流式计算引擎、消息队列等软件的优点之后自主开发的产品,在时序空间大数据处理上,有着自己独到的优势。 +TDengine 是涛思数据面对高速增长的物联网大数据市场和技术挑战推出的创新性的大数据处理产品,它不依赖任何第三方软件,也不是优化或包装了一个开源的数据库或流式计算产品,而是在吸取众多传统关系型数据库、NoSQL 数据库、流式计算引擎、消息队列等软件的优点之后自主开发的产品,在时序空间大数据处理上,有着自己独到的优势。 -TDengine的模块之一是时序数据库。但除此之外,为减少研发的复杂度、系统维护的难度,TDengine还提供缓存、消息队列、订阅、流式计算等功能,为物联网、工业互联网大数据的处理提供全栈的技术方案,是一个高效易用的物联网大数据平台。与Hadoop等典型的大数据平台相比,它具有如下鲜明的特点: +TDengine 的模块之一是时序数据库。但除此之外,为减少研发的复杂度、系统维护的难度,TDengine 还提供缓存、消息队列、订阅、流式计算等功能,为物联网、工业互联网大数据的处理提供全栈的技术方案,是一个高效易用的物联网大数据平台。与 Hadoop 等典型的大数据平台相比,它具有如下鲜明的特点: -* __10倍以上的性能提升__:定义了创新的数据存储结构,单核每秒能处理至少2万次请求,插入数百万个数据点,读出一千万以上数据点,比现有通用数据库快十倍以上。 -* __硬件或云服务成本降至1/5__:由于超强性能,计算资源不到通用大数据方案的1/5;通过列式存储和先进的压缩算法,存储空间不到通用数据库的1/10。 -* __全栈时序数据处理引擎__:将数据库、消息队列、缓存、流式计算等功能融为一体,应用无需再集成Kafka/Redis/HBase/Spark/HDFS等软件,大幅降低应用开发和维护的复杂度成本。 -* __强大的分析功能__:无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过Shell, Python, R, MATLAB随时进行。 -* __与第三方工具无缝连接__:不用一行代码,即可与Telegraf, Grafana, EMQ, HiveMQ, Prometheus, MATLAB, R等集成。后续将支持OPC, Hadoop, Spark等,BI工具也将无缝连接。 -* __零运维成本、零学习成本__:安装集群简单快捷,无需分库分表,实时备份。类标准SQL,支持RESTful,支持Python/Java/C/C++/C#/Go/Node.js, 与MySQL相似,零学习成本。 +* __10 倍以上的性能提升__:定义了创新的数据存储结构,单核每秒能处理至少 2 万次请求,插入数百万个数据点,读出一千万以上数据点,比现有通用数据库快十倍以上。 +* __硬件或云服务成本降至 1/5__:由于超强性能,计算资源不到通用大数据方案的 1/5;通过列式存储和先进的压缩算法,存储空间不到通用数据库的 1/10。 +* __全栈时序数据处理引擎__:将数据库、消息队列、缓存、流式计算等功能融为一体,应用无需再集成 Kafka/Redis/HBase/Spark/HDFS 等软件,大幅降低应用开发和维护的复杂度成本。 +* __强大的分析功能__:无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过 Shell, Python, R, MATLAB 随时进行。 +* __与第三方工具无缝连接__:不用一行代码,即可与 Telegraf, Grafana, EMQ, HiveMQ, Prometheus, MATLAB, R 等集成。后续将支持 OPC, Hadoop, Spark 等,BI 工具也将无缝连接。 +* __零运维成本、零学习成本__:安装集群简单快捷,无需分库分表,实时备份。类标准 SQL,支持 RESTful,支持 Python/Java/C/C++/C#/Go/Node.js, 与 MySQL 相似,零学习成本。 -采用TDengine,可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。但需要指出的是,因充分利用了物联网时序数据的特点,它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM等通用型数据。 +采用 TDengine,可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。但需要指出的是,因充分利用了物联网时序数据的特点,它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM 等通用型数据。 ![TDengine技术生态图](page://images/eco_system.png)
图 1. TDengine技术生态图
@@ -21,42 +21,47 @@ TDengine的模块之一是时序数据库。但除此之外,为减少研发的 ## TDengine 总体适用场景 -作为一个IOT大数据平台,TDengine的典型适用场景是在IOT范畴,而且用户有一定的数据量。本文后续的介绍主要针对这个范畴里面的系统。范畴之外的系统,比如CRM,ERP等,不在本文讨论范围内。 +作为一个 IoT 大数据平台,TDengine 的典型适用场景是在 IoT 范畴,而且用户有一定的数据量。本文后续的介绍主要针对这个范畴里面的系统。范畴之外的系统,比如 CRM,ERP 等,不在本文讨论范围内。 ### 数据源特点和需求 -从数据源角度,设计人员可以从下面几个角度分析TDengine在目标应用系统里面的适用性。 + +从数据源角度,设计人员可以从下面几个角度分析 TDengine 在目标应用系统里面的适用性。 |数据源特点和需求|不适用|可能适用|非常适用|简单说明| |---|---|---|---|---| -|总体数据量巨大| | | √ |TDengine在容量方面提供出色的水平扩展功能,并且具备匹配高压缩的存储结构,达到业界最优的存储效率。| -|数据输入速度偶尔或者持续巨大| | | √ | TDengine的性能大大超过同类产品,可以在同样的硬件环境下持续处理大量的输入数据,并且提供很容易在用户环境里面运行的性能评估工具。| -|数据源数目巨大| | | √ |TDengine设计中包含专门针对大量数据源的优化,包括数据的写入和查询,尤其适合高效处理海量(千万或者更多量级)的数据源。| +|总体数据量巨大| | | √ | TDengine 在容量方面提供出色的水平扩展功能,并且具备匹配高压缩的存储结构,达到业界最优的存储效率。| +|数据输入速度偶尔或者持续巨大| | | √ | TDengine 的性能大大超过同类产品,可以在同样的硬件环境下持续处理大量的输入数据,并且提供很容易在用户环境里面运行的性能评估工具。| +|数据源数目巨大| | | √ | TDengine 设计中包含专门针对大量数据源的优化,包括数据的写入和查询,尤其适合高效处理海量(千万或者更多量级)的数据源。| ### 系统架构要求 + |系统架构要求|不适用|可能适用|非常适用|简单说明| |---|---|---|---|---| -|要求简单可靠的系统架构| | | √ |TDengine的系统架构非常简单可靠,自带消息队列,缓存,流式计算,监控等功能,无需集成额外的第三方产品。| -|要求容错和高可靠| | | √ |TDengine的集群功能,自动提供容错灾备等高可靠功能。| -|标准化规范| | | √ |TDengine使用标准的SQL语言提供主要功能,遵守标准化规范。| +|要求简单可靠的系统架构| | | √ | TDengine 的系统架构非常简单可靠,自带消息队列,缓存,流式计算,监控等功能,无需集成额外的第三方产品。| +|要求容错和高可靠| | | √ | TDengine 的集群功能,自动提供容错灾备等高可靠功能。| +|标准化规范| | | √ | TDengine 使用标准的 SQL 语言提供主要功能,遵守标准化规范。| ### 系统功能需求 + |系统功能需求|不适用|可能适用|非常适用|简单说明| |---|---|---|---|---| -|要求完整的内置数据处理算法| | √ | |TDengine的实现了通用的数据处理算法,但是还没有做到妥善处理各行各业的所有要求,因此特殊类型的处理还需要应用层面处理。| -|需要大量的交叉查询处理| | √ | |这种类型的处理更多应该用关系型数据系统处理,或者应该考虑TDengine和关系型数据系统配合实现系统功能。| +|要求完整的内置数据处理算法| | √ | | TDengine 的实现了通用的数据处理算法,但是还没有做到妥善处理各行各业的所有要求,因此特殊类型的处理还需要应用层面处理。| +|需要大量的交叉查询处理| | √ | |这种类型的处理更多应该用关系型数据系统处理,或者应该考虑 TDengine 和关系型数据系统配合实现系统功能。| ### 系统性能需求 + |系统性能需求|不适用|可能适用|非常适用|简单说明| |---|---|---|---|---| -|要求较大的总体处理能力| | | √ |TDengine的集群功能可以轻松地让多服务器配合达成处理能力的提升。| -|要求高速处理数据 | | | √ |TDengine的专门为IOT优化的存储和数据处理的设计,一般可以让系统得到超出同类产品多倍数的处理速度提升。| -|要求快速处理小粒度数据| | | √ |这方面TDengine性能可以完全对标关系型和NoSQL型数据处理系统。| +|要求较大的总体处理能力| | | √ | TDengine 的集群功能可以轻松地让多服务器配合达成处理能力的提升。| +|要求高速处理数据 | | | √ | TDengine 的专门为 IoT 优化的存储和数据处理的设计,一般可以让系统得到超出同类产品多倍数的处理速度提升。| +|要求快速处理小粒度数据| | | √ |这方面 TDengine 性能可以完全对标关系型和 NoSQL 型数据处理系统。| ### 系统维护需求 + |系统维护需求|不适用|可能适用|非常适用|简单说明| |---|---|---|---|---| -|要求系统可靠运行| | | √ |TDengine的系统架构非常稳定可靠,日常维护也简单便捷,对维护人员的要求简洁明了,最大程度上杜绝人为错误和事故。| +|要求系统可靠运行| | | √ | TDengine 的系统架构非常稳定可靠,日常维护也简单便捷,对维护人员的要求简洁明了,最大程度上杜绝人为错误和事故。| |要求运维学习成本可控| | | √ |同上。| -|要求市场有大量人才储备| √ | | |TDengine作为新一代产品,目前人才市场里面有经验的人员还有限。但是学习成本低,我们作为厂家也提供运维的培训和辅助服务。| +|要求市场有大量人才储备| √ | | | TDengine 作为新一代产品,目前人才市场里面有经验的人员还有限。但是学习成本低,我们作为厂家也提供运维的培训和辅助服务。| diff --git a/documentation20/cn/02.getting-started/01.docker/docs.md b/documentation20/cn/02.getting-started/01.docker/docs.md index 30803d977704606b042c589b96b649d99a850106..d262589a6fa757179a267aa55066b3a6c255df27 100644 --- a/documentation20/cn/02.getting-started/01.docker/docs.md +++ b/documentation20/cn/02.getting-started/01.docker/docs.md @@ -1,6 +1,6 @@ # 通过 Docker 快速体验 TDengine -虽然并不推荐在生产环境中通过 Docker 来部署 TDengine 服务,但 Docker 工具能够很好地屏蔽底层操作系统的环境差异,很适合在开发测试或初次体验时用于安装运行 TDengine 的工具集。特别是,借助 Docker,能够比较方便地在 Mac OSX 和 Windows 系统上尝试 TDengine,而无需安装虚拟机或额外租用 Linux 服务器。 +虽然并不推荐在生产环境中通过 Docker 来部署 TDengine 服务,但 Docker 工具能够很好地屏蔽底层操作系统的环境差异,很适合在开发测试或初次体验时用于安装运行 TDengine 的工具集。特别是,借助 Docker,能够比较方便地在 Mac OSX 和 Windows 系统上尝试 TDengine,而无需安装虚拟机或额外租用 Linux 服务器。另外,从2.0.14.0版本开始,TDengine提供的镜像已经可以同时支持X86-64、X86、arm64、arm32平台,像NAS、树莓派、嵌入式开发板之类可以运行docker的非主流计算机也可以基于本文档轻松体验TDengine。 下文通过 Step by Step 风格的介绍,讲解如何通过 Docker 快速建立 TDengine 的单节点运行环境,以支持开发和测试。 @@ -12,7 +12,7 @@ Docker 工具自身的下载请参考 [Docker官网文档](https://docs.docker.c ```bash $ docker -v -Docker version 20.10.5, build 55c4c88 +Docker version 20.10.3, build 48d30b5 ``` ## 在 Docker 容器中运行 TDengine @@ -20,21 +20,22 @@ Docker version 20.10.5, build 55c4c88 1,使用命令拉取 TDengine 镜像,并使它在后台运行。 ```bash -$ docker run -d tdengine/tdengine -cdf548465318c6fc2ad97813f89cc60006393392401cae58a27b15ca9171f316 +$ docker run -d --name tdengine tdengine/tdengine +7760c955f225d72e9c1ec5a4cef66149a7b94dae7598b11eb392138877e7d292 ``` -- **docker run**:通过 Docker 运行一个容器。 -- **-d**:让容器在后台运行。 -- **tdengine/tdengine**:拉取的 TDengine 官方发布的应用镜像。 -- **cdf548465318c6fc2ad97813f89cc60006393392401cae58a27b15ca9171f316**:这个返回的长字符是容器 ID,我们可以通过容器 ID 来查看对应的容器。 +- **docker run**:通过 Docker 运行一个容器 +- **--name tdengine**:设置容器名称,我们可以通过容器名称来查看对应的容器 +- **-d**:让容器在后台运行 +- **tdengine/tdengine**:拉取的 TDengine 官方发布的应用镜像 +- **7760c955f225d72e9c1ec5a4cef66149a7b94dae7598b11eb392138877e7d292**:这个返回的长字符是容器 ID,我们也可以通过容器 ID 来查看对应的容器 2,确认容器是否已经正确运行。 ```bash $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS ··· -cdf548465318 tdengine/tdengine "taosd" 14 minutes ago Up 14 minutes ··· +c452519b0f9b tdengine/tdengine "taosd" 14 minutes ago Up 14 minutes ··· ``` - **docker ps**:列出所有正在运行状态的容器信息。 @@ -47,25 +48,25 @@ cdf548465318 tdengine/tdengine "taosd" 14 minutes ago Up 14 minutes · 3,进入 Docker 容器内,使用 TDengine。 ```bash -$ docker exec -it cdf548465318 /bin/bash -root@cdf548465318:~/TDengine-server-2.0.13.0# +$ docker exec -it tdengine /bin/bash +root@c452519b0f9b:~/TDengine-server-2.0.20.13# ``` - **docker exec**:通过 docker exec 命令进入容器,如果退出,容器不会停止。 - **-i**:进入交互模式。 - **-t**:指定一个终端。 -- **cdf548465318**:容器 ID,需要根据 docker ps 指令返回的值进行修改。 +- **c452519b0f9b**:容器 ID,需要根据 docker ps 指令返回的值进行修改。 - **/bin/bash**:载入容器后运行 bash 来进行交互。 4,进入容器后,执行 taos shell 客户端程序。 ```bash -$ root@cdf548465318:~/TDengine-server-2.0.13.0# taos +$ root@c452519b0f9b:~/TDengine-server-2.0.20.13# taos -Welcome to the TDengine shell from Linux, Client Version:2.0.13.0 +Welcome to the TDengine shell from Linux, Client Version:2.0.20.13 Copyright (c) 2020 by TAOS Data, Inc. All rights reserved. -taos> +taos> ``` TDengine 终端成功连接服务端,打印出了欢迎消息和版本信息。如果失败,会有错误信息打印出来。 @@ -78,45 +79,74 @@ TDengine 终端成功连接服务端,打印出了欢迎消息和版本信息 ```bash $ taos> q -root@cdf548465318:~/TDengine-server-2.0.13.0# +root@c452519b0f9b:~/TDengine-server-2.0.20.13# ``` 2,在命令行界面执行 taosdemo。 ```bash -$ root@cdf548465318:~/TDengine-server-2.0.13.0# taosdemo -################################################################### -# Server IP: localhost:0 -# User: root -# Password: taosdata -# Use metric: true -# Datatype of Columns: int int int int int int int float -# Binary Length(If applicable): -1 -# Number of Columns per record: 3 -# Number of Threads: 10 -# Number of Tables: 10000 -# Number of Data per Table: 100000 -# Records/Request: 1000 -# Database name: test -# Table prefix: t -# Delete method: 0 -# Test time: 2021-04-13 02:05:20 -################################################################### +root@c452519b0f9b:~/TDengine-server-2.0.20.13# taosdemo + +taosdemo is simulating data generated by power equipments monitoring... + +host: 127.0.0.1:6030 +user: root +password: taosdata +configDir: +resultFile: ./output.txt +thread num of insert data: 10 +thread num of create table: 10 +top insert interval: 0 +number of records per req: 30000 +max sql length: 1048576 +database count: 1 +database[0]: + database[0] name: test + drop: yes + replica: 1 + precision: ms + super table count: 1 + super table[0]: + stbName: meters + autoCreateTable: no + childTblExists: no + childTblCount: 10000 + childTblPrefix: d + dataSource: rand + iface: taosc + insertRows: 10000 + interlaceRows: 0 + disorderRange: 1000 + disorderRatio: 0 + maxSqlLen: 1048576 + timeStampStep: 1 + startTimestamp: 2017-07-14 10:40:00.000 + sampleFormat: + sampleFile: + tagsFile: + columnCount: 3 +column[0]:FLOAT column[1]:INT column[2]:FLOAT + tagCount: 2 + tag[0]:INT tag[1]:BINARY(16) + + Press enter key to continue or Ctrl-C to stop ``` -回车后,该命令将新建一个数据库 test,并且自动创建一张超级表 meters,并以超级表 meters 为模版创建了 1 万张表,表名从 "t0" 到 "t9999"。每张表有 10 万条记录,每条记录有 f1,f2,f3 三个字段,时间戳 ts 字段从 "2017-07-14 10:40:00 000" 到 "2017-07-14 10:41:39 999"。每张表带有 areaid 和 loc 两个标签 TAG,areaid 被设置为 1 到 10,loc 被设置为 "beijing" 或 "shanghai"。 +回车后,该命令将在数据库 test 下面自动创建一张超级表 meters,该超级表下有 1 万张表,表名为 "d0" 到 "d9999",每张表有 1 万条记录,每条记录有 (ts, current, voltage, phase) 四个字段,时间戳从 "2017-07-14 10:40:00 000" 到 "2017-07-14 10:40:09 999",每张表带有标签 location 和 groupId,groupId 被设置为 1 到 10, location 被设置为 "beijing" 或者 "shanghai"。 + +执行这条命令大概需要几分钟,最后共插入 1 亿条记录。 3,进入 TDengine 终端,查看 taosdemo 生成的数据。 - **进入命令行。** ```bash -$ root@cdf548465318:~/TDengine-server-2.0.13.0# taos +$ root@c452519b0f9b:~/TDengine-server-2.0.20.13# taos -Welcome to the TDengine shell from Linux, Client Version:2.0.13.0 +Welcome to the TDengine shell from Linux, Client Version:2.0.20.13 Copyright (c) 2020 by TAOS Data, Inc. All rights reserved. -taos> +taos> ``` - **查看数据库。** @@ -124,8 +154,8 @@ taos> ```bash $ taos> show databases; name | created_time | ntables | vgroups | ··· - test | 2021-04-13 02:14:15.950 | 10000 | 6 | ··· - log | 2021-04-12 09:36:37.549 | 4 | 1 | ··· + test | 2021-08-18 06:01:11.021 | 10000 | 6 | ··· + log | 2021-08-18 05:51:51.065 | 4 | 1 | ··· ``` @@ -136,10 +166,10 @@ $ taos> use test; Database changed. $ taos> show stables; - name | created_time | columns | tags | tables | -===================================================================================== - meters | 2021-04-13 02:14:15.955 | 4 | 2 | 10000 | -Query OK, 1 row(s) in set (0.001737s) + name | created_time | columns | tags | tables | +============================================================================================ + meters | 2021-08-18 06:01:11.116 | 4 | 2 | 10000 | +Query OK, 1 row(s) in set (0.003259s) ``` @@ -147,42 +177,45 @@ Query OK, 1 row(s) in set (0.001737s) ```bash $ taos> select * from test.t0 limit 10; - ts | f1 | f2 | f3 | -==================================================================== - 2017-07-14 02:40:01.000 | 3 | 9 | 0 | - 2017-07-14 02:40:02.000 | 0 | 1 | 2 | - 2017-07-14 02:40:03.000 | 7 | 2 | 3 | - 2017-07-14 02:40:04.000 | 9 | 4 | 5 | - 2017-07-14 02:40:05.000 | 1 | 2 | 5 | - 2017-07-14 02:40:06.000 | 6 | 3 | 2 | - 2017-07-14 02:40:07.000 | 4 | 7 | 8 | - 2017-07-14 02:40:08.000 | 4 | 6 | 6 | - 2017-07-14 02:40:09.000 | 5 | 7 | 7 | - 2017-07-14 02:40:10.000 | 1 | 5 | 0 | -Query OK, 10 row(s) in set (0.003638s) + +DB error: Table does not exist (0.002857s) +taos> select * from test.d0 limit 10; + ts | current | voltage | phase | +====================================================================================== + 2017-07-14 10:40:00.000 | 10.12072 | 223 | 0.34167 | + 2017-07-14 10:40:00.001 | 10.16103 | 224 | 0.34445 | + 2017-07-14 10:40:00.002 | 10.00204 | 220 | 0.33334 | + 2017-07-14 10:40:00.003 | 10.00030 | 220 | 0.33333 | + 2017-07-14 10:40:00.004 | 9.84029 | 216 | 0.32222 | + 2017-07-14 10:40:00.005 | 9.88028 | 217 | 0.32500 | + 2017-07-14 10:40:00.006 | 9.88110 | 217 | 0.32500 | + 2017-07-14 10:40:00.007 | 10.08137 | 222 | 0.33889 | + 2017-07-14 10:40:00.008 | 10.12063 | 223 | 0.34167 | + 2017-07-14 10:40:00.009 | 10.16086 | 224 | 0.34445 | +Query OK, 10 row(s) in set (0.016791s) ``` -- **查看 t0 表的标签值。** +- **查看 d0 表的标签值。** ```bash -$ taos> select areaid, loc from test.t0; - areaid | loc | -=========================== - 10 | shanghai | -Query OK, 1 row(s) in set (0.002904s) +$ taos> select groupid, location from test.d0; + groupid | location | +================================= + 0 | shanghai | +Query OK, 1 row(s) in set (0.003490s) ``` ## 停止正在 Docker 中运行的 TDengine 服务 ```bash -$ docker stop cdf548465318 -cdf548465318 +$ docker stop tdengine +tdengine ``` - **docker stop**:通过 docker stop 停止指定的正在运行中的 docker 镜像。 -- **cdf548465318**:容器 ID,根据 docker ps 指令返回的结果进行修改。 +- **tdengine**:容器名称。 ## 编程开发时连接在 Docker 中的 TDengine @@ -191,11 +224,11 @@ cdf548465318 1,通过端口映射(-p),将容器内部开放的网络端口映射到宿主机的指定端口上。通过挂载本地目录(-v),可以实现宿主机与容器内部的数据同步,防止容器删除后,数据丢失。 ```bash -$ docker run -d -v /etc/taos:/etc/taos -p 6041:6041 tdengine/tdengine +$ docker run -d -v /etc/taos:/etc/taos -P 6041:6041 tdengine/tdengine 526aa188da767ae94b244226a2b2eec2b5f17dd8eff592893d9ec0cd0f3a1ccd $ curl -u root:taosdata -d 'show databases' 127.0.0.1:6041/rest/sql -{"status":"succ","head":["name","created_time","ntables","vgroups","replica","quorum","days","keep1,keep2,keep(D)","cache(MB)","blocks","minrows","maxrows","wallevel","fsync","comp","precision","status"],"data":[],"rows":0} +{"status":"succ","head":["name","created_time","ntables","vgroups","replica","quorum","days","keep0,keep1,keep(D)","cache(MB)","blocks","minrows","maxrows","wallevel","fsync","comp","cachelast","precision","update","status"],"column_meta":[["name",8,32],["created_time",9,8],["ntables",4,4],["vgroups",4,4],["replica",3,2],["quorum",3,2],["days",3,2],["keep0,keep1,keep(D)",8,24],["cache(MB)",4,4],["blocks",4,4],["minrows",4,4],["maxrows",4,4],["wallevel",2,1],["fsync",4,4],["comp",2,1],["cachelast",2,1],["precision",8,3],["update",2,1],["status",8,10]],"data":[["test","2021-08-18 06:01:11.021",10000,4,1,1,10,"3650,3650,3650",16,6,100,4096,1,3000,2,0,"ms",0,"ready"],["log","2021-08-18 05:51:51.065",4,1,1,1,10,"30,30,30",1,3,100,4096,1,3000,2,0,"us",0,"ready"]],"rows":2} ``` - 第一条命令,启动一个运行了 TDengine 的 docker 容器,并且将容器的 6041 端口映射到宿主机的 6041 端口上。 @@ -206,6 +239,5 @@ $ curl -u root:taosdata -d 'show databases' 127.0.0.1:6041/rest/sql 2,直接通过 exec 命令,进入到 docker 容器中去做开发。也即,把程序代码放在 TDengine 服务端所在的同一个 Docker 容器中,连接容器本地的 TDengine 服务。 ```bash -$ docker exec -it 526aa188da /bin/bash +$ docker exec -it tdengine /bin/bash ``` - diff --git a/documentation20/cn/02.getting-started/docs.md b/documentation20/cn/02.getting-started/docs.md index dd7c20fe186270f1130c3916512a25df3d131169..a37afa9212911f4e48efe5e923607f3f2e05422a 100644 --- a/documentation20/cn/02.getting-started/docs.md +++ b/documentation20/cn/02.getting-started/docs.md @@ -208,7 +208,7 @@ taos> select avg(current), max(voltage), min(phase) from test.d10 interval(10s); | **C#** | ● | ● | ○ | ○ | ○ | ○ | ○ | -- | -- | | **RESTful** | ● | ● | ● | ● | ● | ● | ● | ● | ● | -注: ● 表示经过官方测试验证, ○ 表示非官方测试验证。 +注:● 表示官方测试验证通过,○ 表示非官方测试验证通过,-- 表示未经验证。 请跳转到 [连接器](https://www.taosdata.com/cn/documentation/connector) 查看更详细的信息。 diff --git a/documentation20/cn/04.model/docs.md b/documentation20/cn/04.model/docs.md index ccdca64c105942342aad7fbb71130e746584bee4..586997373726c835c0fcdb6d80820b534f21d758 100644 --- a/documentation20/cn/04.model/docs.md +++ b/documentation20/cn/04.model/docs.md @@ -2,7 +2,7 @@ # TDengine数据建模 -TDengine采用关系型数据模型,需要建库、建表。因此对于一个具体的应用场景,需要考虑库的设计,超级表和普通表的设计。本节不讨论细致的语法规则,只介绍概念。 +TDengine采用关系型数据模型,需要建库、建表。因此对于一个具体的应用场景,需要考虑库、超级表和普通表的设计。本节不讨论细致的语法规则,只介绍概念。 关于数据建模请参考[视频教程](https://www.taosdata.com/blog/2020/11/11/1945.html)。 @@ -13,7 +13,7 @@ TDengine采用关系型数据模型,需要建库、建表。因此对于一个 ```mysql CREATE DATABASE power KEEP 365 DAYS 10 BLOCKS 6 UPDATE 1; ``` -上述语句将创建一个名为power的库,这个库的数据将保留365天(超过365天将被自动删除),每10天一个数据文件,内存块数为4,允许更新数据。详细的语法及参数请见 [TAOS SQL 的数据管理](https://www.taosdata.com/cn/documentation/taos-sql#management) 章节。 +上述语句将创建一个名为power的库,这个库的数据将保留365天(超过365天将被自动删除),每10天一个数据文件,内存块数为6,允许更新数据。详细的语法及参数请见 [TAOS SQL 的数据管理](https://www.taosdata.com/cn/documentation/taos-sql#management) 章节。 创建库之后,需要使用SQL命令USE将当前库切换过来,例如: @@ -43,7 +43,7 @@ CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAG 每一种类型的数据采集点需要建立一个超级表,因此一个物联网系统,往往会有多个超级表。对于电网,我们就需要对智能电表、变压器、母线、开关等都建立一个超级表。在物联网中,一个设备就可能有多个数据采集点(比如一台风力发电的风机,有的采集点采集电流、电压等电参数,有的采集点采集温度、湿度、风向等环境参数),这个时候,对这一类型的设备,需要建立多张超级表。一张超级表里包含的采集物理量必须是同时采集的(时间戳是一致的)。 -一张超级表最多容许1024列,如果一个采集点采集的物理量个数超过1024,需要建多张超级表来处理。一个系统可以有多个DB,一个DB里可以有一到多个超级表。 +一张超级表最多容许 1024 列,如果一个采集点采集的物理量个数超过 1024,需要建多张超级表来处理。一个系统可以有多个 DB,一个 DB 里可以有一到多个超级表。(从 2.1.7.0 版本开始,列数限制由 1024 列放宽到了 4096 列。) ## 创建表 diff --git a/documentation20/cn/08.connector/01.java/docs.md b/documentation20/cn/08.connector/01.java/docs.md index ab9af42cf8c0901c9a07bc7098759a74235300dd..def8d4a905eaa6ab63256673aad04bd159a5478d 100644 --- a/documentation20/cn/08.connector/01.java/docs.md +++ b/documentation20/cn/08.connector/01.java/docs.md @@ -1,70 +1,6 @@ # Java Connector -## 安装 - -Java连接器支持的系统有: Linux 64/Windows x64/Windows x86。 - -**安装前准备:** - -- 已安装TDengine服务器端 -- 已安装好TDengine应用驱动,具体请参照 [安装连接器驱动步骤](https://www.taosdata.com/cn/documentation/connector#driver) 章节 - -TDengine 为了方便 Java 应用使用,提供了遵循 JDBC 标准(3.0)API 规范的 `taos-jdbcdriver` 实现。目前可以通过 [Sonatype Repository](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) 搜索并下载。 - -由于 TDengine 的应用驱动是使用C语言开发的,使用 taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。 - -- libtaos.so 在 Linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。 - -- taos.dll 在 Windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。 - -注意:在 Windows 环境开发时需要安装 TDengine 对应的 [windows 客户端](https://www.taosdata.com/cn/all-downloads/#TDengine-Windows-Client),Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端](https://www.taosdata.com/cn/getting-started/#快速上手) 连接远程 TDengine Server。 - -### 如何获取 TAOS-JDBCDriver - -**maven仓库** - -目前 taos-jdbcdriver 已经发布到 [Sonatype Repository](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) 仓库,且各大仓库都已同步。 - -- [sonatype](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) -- [mvnrepository](https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver) -- [maven.aliyun](https://maven.aliyun.com/mvn/search) - -maven 项目中使用如下 pom.xml 配置即可: -```xml-dtd - - com.taosdata.jdbc - taos-jdbcdriver - 2.0.18 - -``` -**源码编译打包** - -下载 TDengine 源码之后,进入 taos-jdbcdriver 源码目录 `src/connector/jdbc` 执行 `mvn clean package -Dmaven.test.skip=true` 即可生成相应 jar 包。 - -### 示例程序 - -示例程序源码位于install_directory/examples/JDBC,有如下目录: - -JDBCDemo JDBC示例源程序 - -JDBCConnectorChecker JDBC安装校验源程序及jar包 - -Springbootdemo springboot示例源程序 - -SpringJdbcTemplate SpringJDBC模板 - -### 安装验证 - -运行如下指令: - -```Bash -cd {install_directory}/examples/JDBC/JDBCConnectorChecker -java -jar JDBCConnectorChecker.jar -host -``` - -验证通过将打印出成功信息。 - -## Java连接器的使用 +## 总体介绍 `taos-jdbcdriver` 的实现包括 2 种形式: JDBC-JNI 和 JDBC-RESTful(taos-jdbcdriver-2.0.18 开始支持 JDBC-RESTful)。 JDBC-JNI 通过调用客户端 libtaos.so(或 taos.dll )的本地方法实现, JDBC-RESTful 则在内部封装了 RESTful 接口实现。 @@ -76,49 +12,51 @@ java -jar JDBCConnectorChecker.jar -host * RESTful:应用将 SQL 发送给位于物理节点2(pnode2)上的 RESTful 连接器,再调用客户端 API(libtaos.so)。 * JDBC-RESTful:Java 应用通过 JDBC-RESTful 的 API ,将 SQL 封装成一个 RESTful 请求,发送给物理节点2的 RESTful 连接器。 -TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致,但时序空间数据库与关系对象型数据库服务的对象和技术特征存在差异,导致 `taos-jdbcdriver` 与传统的 JDBC driver 也存在一定差异。在使用时需要注意以下几点: +TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致,但TDengine与关系对象型数据库的使用场景和技术特征存在差异,导致 `taos-jdbcdriver` 与传统的 JDBC driver 也存在一定差异。在使用时需要注意以下几点: * TDengine 目前不支持针对单条数据记录的删除操作。 * 目前不支持事务操作。 -* 目前不支持嵌套查询(nested query)。 -* 对每个 Connection 的实例,至多只能有一个打开的 ResultSet 实例;如果在 ResultSet 还没关闭的情况下执行了新的查询,taos-jdbcdriver 会自动关闭上一个 ResultSet。 ### JDBC-JNI和JDBC-RESTful的对比 - - - + + + - - - + + + - - - + + + - - + + - - + +
对比项JDBC-JNIJDBC-RESTful
支持的操作系统linux、windows全平台支持的操作系统linux、windows全平台
是否需要安装 client需要不需要是否需要安装 client需要不需要
server 升级后是否需要升级 client需要不需要server 升级后是否需要升级 client需要不需要
写入性能JDBC-RESTful 是 JDBC-JNI 的 50%~90% 写入性能JDBC-RESTful 是 JDBC-JNI 的 50%~90%
查询性能JDBC-RESTful 与 JDBC-JNI 没有差别查询性能JDBC-RESTful 与 JDBC-JNI 没有差别
-注意:与 JNI 方式不同,RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,RESTful 下所有对表名、超级表名的引用都需要指定数据库名前缀。 +注意:与 JNI 方式不同,RESTful 接口是无状态的。在使用JDBC-RESTful时,需要在sql中指定表、超级表的数据库名称。(从 TDengine 2.2.0.0 版本开始,也可以在 RESTful url 中指定当前 SQL 语句所使用的默认数据库名。)例如: +```sql +INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('beijing') VALUES(now, 24.6); +``` -### TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本 +## TAOS-JDBCDriver 版本以及支持的 TDengine 版本和 JDK 版本 | taos-jdbcdriver 版本 | TDengine 版本 | JDK 版本 | | -------------------- | ----------------- | -------- | -| 2.0.31 | 2.1.3.0 及以上 | 1.8.x | +| 2.0.33 - 2.0.34 | 2.0.3.0 及以上 | 1.8.x | +| 2.0.31 - 2.0.32 | 2.1.3.0 及以上 | 1.8.x | | 2.0.22 - 2.0.30 | 2.0.18.0 - 2.1.2.x | 1.8.x | | 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.x | 1.8.x | | 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x | @@ -126,7 +64,7 @@ TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致 | 1.0.2 | 1.6.1.x 及以上 | 1.8.x | | 1.0.1 | 1.6.1.x 及以上 | 1.8.x | -### TDengine DataType 和 Java DataType +## TDengine DataType 和 Java DataType TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下: @@ -143,6 +81,50 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对 | BINARY | byte array | | NCHAR | java.lang.String | +## 安装Java Connector + +### 安装前准备 + +使用Java Connector连接数据库前,需要具备以下条件: +1. Linux或Windows操作系统 +2. Java 1.8以上运行时环境 +3. TDengine-client(使用JDBC-JNI时必须,使用JDBC-RESTful时非必须) + +**注意**:由于 TDengine 的应用驱动是使用C语言开发的,使用 taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。 +- libtaos.so 在 Linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。 +- taos.dll 在 Windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。 + +**注意**:在 Windows 环境开发时需要安装 TDengine 对应的 [windows 客户端](https://www.taosdata.com/cn/all-downloads/#TDengine-Windows-Client),Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端](https://www.taosdata.com/cn/getting-started/#快速上手) 连接远程 TDengine Server。 + +### 通过maven获取JDBC driver + +目前 taos-jdbcdriver 已经发布到 [Sonatype Repository](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) 仓库,且各大仓库都已同步。 +- [sonatype](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) +- [mvnrepository](https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver) +- [maven.aliyun](https://maven.aliyun.com/mvn/search) + +maven 项目中,在pom.xml 中添加以下依赖: +```xml-dtd + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.18 + +``` + +### 通过源码编译获取JDBC driver + +可以通过下载TDengine的源码,自己编译最新版本的java connector +```shell +git clone https://github.com/taosdata/TDengine.git +cd TDengine/src/connector/jdbc +mvn clean package -Dmaven.test.skip=true +``` + +编译后,在target目录下会产生taos-jdbcdriver-2.0.XX-dist.jar的jar包。 + +## Java连接器的使用 + ### 获取连接 #### 指定URL获取连接 @@ -158,13 +140,11 @@ Connection conn = DriverManager.getConnection(jdbcUrl); 以上示例,使用 **JDBC-RESTful** 的 driver,建立了到 hostname 为 taosdemo.com,端口为 6041,数据库名为 test 的连接。这个 URL 中指定用户名(user)为 root,密码(password)为 taosdata。 使用 JDBC-RESTful 接口,不需要依赖本地函数库。与 JDBC-JNI 相比,仅需要: - 1. driverClass 指定为“com.taosdata.jdbc.rs.RestfulDriver”; 2. jdbcUrl 以“jdbc:TAOS-RS://”开头; 3. 使用 6041 作为连接端口。 如果希望获得更好的写入和查询性能,Java 应用可以使用 **JDBC-JNI** 的driver,如下所示: - ```java Class.forName("com.taosdata.jdbc.TSDBDriver"); String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata"; @@ -173,15 +153,9 @@ Connection conn = DriverManager.getConnection(jdbcUrl); 以上示例,使用了 JDBC-JNI 的 driver,建立了到 hostname 为 taosdemo.com,端口为 6030(TDengine 的默认端口),数据库名为 test 的连接。这个 URL 中指定用户名(user)为 root,密码(password)为 taosdata。 -**注意**:使用 JDBC-JNI 的 driver,taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库。 - -* libtaos.so - 在 Linux 系统中成功安装 TDengine 后,依赖的本地函数库 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。 - -* taos.dll - 在 Windows 系统中安装完客户端之后,驱动包依赖的 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。 +**注意**:使用 JDBC-JNI 的 driver,taos-jdbcdriver 驱动包时需要依赖系统对应的本地函数库(Linux 下是 libtaos.so;Windows 下是 taos.dll)。 -> 在 Windows 环境开发时需要安装 TDengine 对应的 [windows 客户端][14],Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端][15] 连接远程 TDengine Server。 +> 在 Windows 环境开发时需要安装 TDengine 对应的 [windows 客户端](https://www.taosdata.com/cn/all-downloads/#TDengine-Windows-Client),Linux 服务器安装完 TDengine 之后默认已安装 client,也可以单独安装 [Linux 客户端](https://www.taosdata.com/cn/getting-started/#%E5%AE%A2%E6%88%B7%E7%AB%AF) 连接远程 TDengine Server。 JDBC-JNI 的使用请参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1955.html)。 @@ -189,12 +163,15 @@ TDengine 的 JDBC URL 规范格式为: `jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]` url中的配置参数如下: -* user:登录 TDengine 用户名,默认值 root。 -* password:用户登录密码,默认值 taosdata。 -* cfgdir:客户端配置文件目录路径,Linux OS 上默认值 /etc/taos ,Windows OS 上默认值 C:/TDengine/cfg。 +* user:登录 TDengine 用户名,默认值 'root'。 +* password:用户登录密码,默认值 'taosdata'。 +* cfgdir:客户端配置文件目录路径,Linux OS 上默认值 `/etc/taos`,Windows OS 上默认值 `C:/TDengine/cfg`。 * charset:客户端使用的字符集,默认值为系统字符集。 * locale:客户端语言环境,默认值系统当前 locale。 * timezone:客户端使用的时区,默认值为系统当前时区。 +* batchfetch: 仅在使用JDBC-JNI时生效。true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:false。 +* timestampFormat: 仅在使用JDBC-RESTful时生效. 'TIMESTAMP':结果集中timestamp类型的字段为一个long值; 'UTC':结果集中timestamp类型的字段为一个UTC时间格式的字符串; 'STRING':结果集中timestamp类型的字段为一个本地时间格式的字符串。默认值为'STRING'。 +* batchErrorIgnore:true:在执行Statement的executeBatch时,如果中间有一条sql执行失败,继续执行下面的sq了。false:不再执行失败sql后的任何语句。默认值为:false。 #### 指定URL和Properties获取连接 @@ -217,12 +194,15 @@ public Connection getConn() throws Exception{ 以上示例,建立一个到 hostname 为 taosdemo.com,端口为 6030,数据库名为 test 的连接。注释为使用 JDBC-RESTful 时的方法。这个连接在 url 中指定了用户名(user)为 root,密码(password)为 taosdata,并在 connProps 中指定了使用的字符集、语言环境、时区等信息。 properties 中的配置参数如下: -* TSDBDriver.PROPERTY_KEY_USER:登录 TDengine 用户名,默认值 root。 -* TSDBDriver.PROPERTY_KEY_PASSWORD:用户登录密码,默认值 taosdata。 -* TSDBDriver.PROPERTY_KEY_CONFIG_DIR:客户端配置文件目录路径,Linux OS 上默认值 /etc/taos ,Windows OS 上默认值 C:/TDengine/cfg。 +* TSDBDriver.PROPERTY_KEY_USER:登录 TDengine 用户名,默认值 'root'。 +* TSDBDriver.PROPERTY_KEY_PASSWORD:用户登录密码,默认值 'taosdata'。 +* TSDBDriver.PROPERTY_KEY_CONFIG_DIR:客户端配置文件目录路径,Linux OS 上默认值 `/etc/taos`,Windows OS 上默认值 `C:/TDengine/cfg`。 * TSDBDriver.PROPERTY_KEY_CHARSET:客户端使用的字符集,默认值为系统字符集。 * TSDBDriver.PROPERTY_KEY_LOCALE:客户端语言环境,默认值系统当前 locale。 * TSDBDriver.PROPERTY_KEY_TIME_ZONE:客户端使用的时区,默认值为系统当前时区。 +* TSDBDriver.PROPERTY_KEY_BATCH_LOAD: 仅在使用JDBC-JNI时生效。true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:false。 +* TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT: 仅在使用JDBC-RESTful时生效. 'TIMESTAMP':结果集中timestamp类型的字段为一个long值; 'UTC':结果集中timestamp类型的字段为一个UTC时间格式的字符串; 'STRING':结果集中timestamp类型的字段为一个本地时间格式的字符串。默认值为'STRING'。 +* TSDBDriver.PROPERTY_KEY_BATCH_ERROR_IGNORE:true:在执行Statement的executeBatch时,如果中间有一条sql执行失败,继续执行下面的sq了。false:不再执行失败sql后的任何语句。默认值为:false。 #### 使用客户端配置文件建立连接 @@ -260,6 +240,7 @@ secondEp cluster_node2:6030 ``` 以上示例,jdbc 会使用客户端的配置文件,建立到 hostname 为 cluster_node1、端口为 6030、数据库名为 test 的连接。当集群中 firstEp 节点失效时,JDBC 会尝试使用 secondEp 连接集群。 + TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可以正常建立到集群的连接。 > 注意:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件,Linux OS 上默认值 /etc/taos/taos.cfg ,Windows OS 上默认值 C://TDengine/cfg/taos.cfg。 @@ -343,6 +324,7 @@ try (Statement statement = connection.createStatement()) { ``` JDBC连接器可能报错的错误码包括3种:JDBC driver本身的报错(错误码在0x2301到0x2350之间),JNI方法的报错(错误码在0x2351到0x2400之间),TDengine其他功能模块的报错。 + 具体的错误码请参考: * https://github.com/taosdata/TDengine/blob/develop/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java * https://github.com/taosdata/TDengine/blob/develop/src/inc/taoserror.h @@ -423,11 +405,12 @@ public void setShort(int columnIndex, ArrayList list) throws SQLException public void setString(int columnIndex, ArrayList list, int size) throws SQLException public void setNString(int columnIndex, ArrayList list, int size) throws SQLException ``` + 其中 setString 和 setNString 都要求用户在 size 参数里声明表定义中对应列的列宽。 -### 订阅 +## 订阅 -#### 创建 +### 创建 ```java TSDBSubscribe sub = ((TSDBConnection)conn).subscribe("topic", "select * from meters", false); @@ -441,7 +424,7 @@ TSDBSubscribe sub = ((TSDBConnection)conn).subscribe("topic", "select * from met 如上面的例子将使用 SQL 语句 `select * from meters` 创建一个名为 `topic` 的订阅,如果这个订阅已经存在,将继续之前的查询进度,而不是从头开始消费所有的数据。 -#### 消费数据 +### 消费数据 ```java int total = 0; @@ -459,7 +442,7 @@ while(true) { `consume` 方法返回一个结果集,其中包含从上次 `consume` 到目前为止的所有新数据。请务必按需选择合理的调用 `consume` 的频率(如例子中的 `Thread.sleep(1000)`),否则会给服务端造成不必要的压力。 -#### 关闭订阅 +### 关闭订阅 ```java sub.close(true); @@ -467,7 +450,7 @@ sub.close(true); `close` 方法关闭一个订阅。如果其参数为 `true` 表示保留订阅进度信息,后续可以创建同名订阅继续消费数据;如为 `false` 则不保留订阅进度。 -### 关闭资源 +## 关闭资源 ```java resultSet.close(); @@ -479,19 +462,9 @@ conn.close(); ## 与连接池使用 -**HikariCP** - -* 引入相应 HikariCP maven 依赖: - -```xml - - com.zaxxer - HikariCP - 3.4.1 - -``` +### HikariCP -* 使用示例如下: +使用示例如下: ```java public static void main(String[] args) throws SQLException { @@ -523,19 +496,9 @@ conn.close(); > 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。 > 更多 HikariCP 使用问题请查看[官方说明](https://github.com/brettwooldridge/HikariCP)。 -**Druid** +### Druid -* 引入相应 Druid maven 依赖: - -```xml - - com.alibaba - druid - 1.1.20 - -``` - -* 使用示例如下: +使用示例如下: ```java public static void main(String[] args) throws Exception { @@ -581,6 +544,16 @@ Query OK, 1 row(s) in set (0.000141s) * Spring JdbcTemplate 中使用 taos-jdbcdriver,可参考 [SpringJdbcTemplate](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/SpringJdbcTemplate) * Springboot + Mybatis 中使用,可参考 [springbootdemo](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo) +## 示例程序 + +示例程序源码位于TDengine/test/examples/JDBC下: +* JDBCDemo:JDBC示例源程序 +* JDBCConnectorChecker:JDBC安装校验源程序及jar包 +* Springbootdemo:springboot示例源程序 +* SpringJdbcTemplate:SpringJDBC模板 + +请参考:[JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC) + ## 常见问题 * java.lang.UnsatisfiedLinkError: no taos in java.library.path diff --git a/documentation20/cn/08.connector/docs.md b/documentation20/cn/08.connector/docs.md index 364961ca632b3075b2877a42f587f405101904bb..f132ff979df39cd36cd554a6e83ffbd950ef9bb8 100644 --- a/documentation20/cn/08.connector/docs.md +++ b/documentation20/cn/08.connector/docs.md @@ -17,7 +17,7 @@ TDengine提供了丰富的应用程序开发接口,其中包括C/C++、Java、 | **C#** | ● | ● | ○ | ○ | ○ | ○ | ○ | -- | -- | | **RESTful** | ● | ● | ● | ● | ● | ● | ○ | ○ | ○ | -其中 ● 表示经过官方测试验证, ○ 表示非官方测试验证。 +其中 ● 表示官方测试验证通过,○ 表示非官方测试验证通过,-- 表示未经验证。 注意: @@ -64,7 +64,10 @@ TDengine提供了丰富的应用程序开发接口,其中包括C/C++、Java、 编辑taos.cfg文件(默认路径/etc/taos/taos.cfg),将firstEP修改为TDengine服务器的End Point,例如:h1.taos.com:6030 -**提示: 如本机没有部署TDengine服务,仅安装了应用驱动,则taos.cfg中仅需配置firstEP,无需配置FQDN。** +**提示: ** + +1. **如本机没有部署TDengine服务,仅安装了应用驱动,则taos.cfg中仅需配置firstEP,无需配置FQDN。** +2. **为防止与服务器端连接时出现“unable to resolve FQDN”错误,建议确认客户端的hosts文件已经配置正确的FQDN值。** **Windows x64/x86** @@ -96,7 +99,7 @@ TDengine提供了丰富的应用程序开发接口,其中包括C/C++、Java、 **提示:** 1. **如利用FQDN连接服务器,必须确认本机网络环境DNS已配置好,或在hosts文件中添加FQDN寻址记录,如编辑C:\Windows\system32\drivers\etc\hosts,添加如下的记录:`192.168.1.99 h1.taos.com` ** -2.**卸载:运行unins000.exe可卸载TDengine应用驱动。** +2. **卸载:运行unins000.exe可卸载TDengine应用驱动。** ### 安装验证 @@ -654,22 +657,23 @@ conn.close() 为支持各种不同类型平台的开发,TDengine 提供符合 REST 设计标准的 API,即 RESTful API。为最大程度降低学习成本,不同于其他数据库 RESTful API 的设计方法,TDengine 直接通过 HTTP POST 请求 BODY 中包含的 SQL 语句来操作数据库,仅需要一个 URL。RESTful 连接器的使用参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1965.html)。 -注意:与标准连接器的一个区别是,RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,所有对表名、超级表名的引用都需要指定数据库名前缀。 +注意:与标准连接器的一个区别是,RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,所有对表名、超级表名的引用都需要指定数据库名前缀。(从 2.2.0.0 版本开始,支持在 RESTful url 中指定 db_name,这时如果 SQL 语句中没有指定数据库名前缀的话,会使用 url 中指定的这个 db_name。) ### 安装 -RESTful接口不依赖于任何TDengine的库,因此客户端不需要安装任何TDengine的库,只要客户端的开发语言支持HTTP协议即可。 +RESTful 接口不依赖于任何 TDengine 的库,因此客户端不需要安装任何 TDengine 的库,只要客户端的开发语言支持 HTTP 协议即可。 ### 验证 -在已经安装TDengine服务器端的情况下,可以按照如下方式进行验证。 +在已经安装 TDengine 服务器端的情况下,可以按照如下方式进行验证。 -下面以Ubuntu环境中使用curl工具(确认已经安装)来验证RESTful接口的正常。 +下面以 Ubuntu 环境中使用 curl 工具(确认已经安装)来验证 RESTful 接口的正常。 -下面示例是列出所有的数据库,请把h1.taosdata.com和6041(缺省值)替换为实际运行的TDengine服务fqdn和端口号: +下面示例是列出所有的数据库,请把 h1.taosdata.com 和 6041(缺省值)替换为实际运行的 TDengine 服务 fqdn 和端口号: ```html curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' h1.taosdata.com:6041/rest/sql ``` + 返回值结果如下表示验证通过: ```json { @@ -682,22 +686,23 @@ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' h1.taos } ``` -### RESTful连接器的使用 +### RESTful 连接器的使用 -#### HTTP请求格式 +#### HTTP 请求格式 ``` -http://:/rest/sql +http://:/rest/sql/[db_name] ``` 参数说明: -- fqnd: 集群中的任一台主机FQDN或IP地址 -- port: 配置文件中httpPort配置项,缺省为6041 +- fqnd: 集群中的任一台主机 FQDN 或 IP 地址 +- port: 配置文件中 httpPort 配置项,缺省为 6041 +- db_name: 可选参数,指定本次所执行的 SQL 语句的默认数据库库名。(从 2.2.0.0 版本开始支持) -例如:http://h1.taos.com:6041/rest/sql 是指向地址为h1.taos.com:6041的url。 +例如:http://h1.taos.com:6041/rest/sql/test 是指向地址为 h1.taos.com:6041 的 url,并将默认使用的数据库库名设置为 test。 -HTTP请求的Header里需带有身份认证信息,TDengine支持Basic认证与自定义认证两种机制,后续版本将提供标准安全的数字签名机制来做身份验证。 +HTTP 请求的 Header 里需带有身份认证信息,TDengine 支持 Basic 认证与自定义认证两种机制,后续版本将提供标准安全的数字签名机制来做身份验证。 - 自定义身份认证信息如下所示(稍后介绍) @@ -711,25 +716,25 @@ Authorization: Taosd Authorization: Basic ``` -HTTP请求的BODY里就是一个完整的SQL语句,SQL语句中的数据表应提供数据库前缀,例如\.\。如果表名不带数据库前缀,系统会返回错误。因为HTTP模块只是一个简单的转发,没有当前DB的概念。 +HTTP 请求的 BODY 里就是一个完整的 SQL 语句,SQL 语句中的数据表应提供数据库前缀,例如 \.\。如果表名不带数据库前缀,又没有在 url 中指定数据库名的话,系统会返回错误。因为 HTTP 模块只是一个简单的转发,没有当前 DB 的概念。 -使用curl通过自定义身份认证方式来发起一个HTTP Request,语法如下: +使用 curl 通过自定义身份认证方式来发起一个 HTTP Request,语法如下: ```bash -curl -H 'Authorization: Basic ' -d '' :/rest/sql +curl -H 'Authorization: Basic ' -d '' :/rest/sql/[db_name] ``` 或者 ```bash -curl -u username:password -d '' :/rest/sql +curl -u username:password -d '' :/rest/sql/[db_name] ``` -其中,`TOKEN`为`{username}:{password}`经过Base64编码之后的字符串,例如`root:taosdata`编码后为`cm9vdDp0YW9zZGF0YQ==` +其中,`TOKEN` 为 `{username}:{password}` 经过 Base64 编码之后的字符串,例如 `root:taosdata` 编码后为 `cm9vdDp0YW9zZGF0YQ==` -### HTTP返回格式 +### HTTP 返回格式 -返回值为JSON格式,如下: +返回值为 JSON 格式,如下: ```json { @@ -747,9 +752,9 @@ curl -u username:password -d '' :/rest/sql 说明: - status: 告知操作结果是成功还是失败。 -- head: 表的定义,如果不返回结果集,则仅有一列“affected_rows”。(从 2.0.17.0 版本开始,建议不要依赖 head 返回值来判断数据列类型,而推荐使用 column_meta。在未来版本中,有可能会从返回值中去掉 head 这一项。) +- head: 表的定义,如果不返回结果集,则仅有一列 “affected_rows”。(从 2.0.17.0 版本开始,建议不要依赖 head 返回值来判断数据列类型,而推荐使用 column_meta。在未来版本中,有可能会从返回值中去掉 head 这一项。) - column_meta: 从 2.0.17.0 版本开始,返回值中增加这一项来说明 data 里每一列的数据类型。具体每个列会用三个值来说明,分别为:列名、列类型、类型长度。例如`["current",6,4]`表示列名为“current”;列类型为 6,也即 float 类型;类型长度为 4,也即对应 4 个字节表示的 float。如果列类型为 binary 或 nchar,则类型长度表示该列最多可以保存的内容长度,而不是本次返回值中的具体数据长度。当列类型是 nchar 的时候,其类型长度表示可以保存的 unicode 字符数量,而不是 bytes。 -- data: 具体返回的数据,一行一行的呈现,如果不返回结果集,那么就仅有[[affected_rows]]。data 中每一行的数据列顺序,与 column_meta 中描述数据列的顺序完全一致。 +- data: 具体返回的数据,一行一行的呈现,如果不返回结果集,那么就仅有 [[affected_rows]]。data 中每一行的数据列顺序,与 column_meta 中描述数据列的顺序完全一致。 - rows: 表明总共多少行数据。 column_meta 中的列类型说明: @@ -766,13 +771,13 @@ column_meta 中的列类型说明: ### 自定义授权码 -HTTP请求中需要带有授权码``,用于身份识别。授权码通常由管理员提供,可简单的通过发送`HTTP GET`请求来获取授权码,操作如下: +HTTP 请求中需要带有授权码 ``,用于身份识别。授权码通常由管理员提供,可简单的通过发送 `HTTP GET` 请求来获取授权码,操作如下: ```bash curl http://:/rest/login// ``` -其中,`fqdn`是TDengine数据库的fqdn或ip地址,port是TDengine服务的端口号,`username`为数据库用户名,`password`为数据库密码,返回值为`JSON`格式,各字段含义如下: +其中,`fqdn` 是 TDengine 数据库的 fqdn 或 ip 地址,port 是 TDengine 服务的端口号,`username` 为数据库用户名,`password` 为数据库密码,返回值为 `JSON` 格式,各字段含义如下: - status:请求结果的标志位 @@ -798,7 +803,7 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata ### 使用示例 -- 在demo库里查询表d1001的所有记录: +- 在 demo 库里查询表 d1001 的所有记录: ```bash curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sql @@ -818,7 +823,7 @@ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001 } ``` -- 创建库demo: +- 创建库 demo: ```bash curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'create database demo' 192.168.0.1:6041/rest/sql @@ -837,9 +842,9 @@ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'create database demo' 19 ### 其他用法 -#### 结果集采用Unix时间戳 +#### 结果集采用 Unix 时间戳 -HTTP请求URL采用`sqlt`时,返回结果集的时间戳将采用Unix时间戳格式表示,例如 +HTTP 请求 URL 采用 `sqlt` 时,返回结果集的时间戳将采用 Unix 时间戳格式表示,例如 ```bash curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001' 192.168.0.1:6041/rest/sqlt @@ -860,9 +865,9 @@ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.d1001 } ``` -#### 结果集采用UTC时间字符串 +#### 结果集采用 UTC 时间字符串 -HTTP请求URL采用`sqlutc`时,返回结果集的时间戳将采用UTC时间字符串表示,例如 +HTTP 请求 URL 采用 `sqlutc` 时,返回结果集的时间戳将采用 UTC 时间字符串表示,例如 ```bash curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'select * from demo.t1' 192.168.0.1:6041/rest/sqlutc ``` @@ -884,13 +889,14 @@ HTTP请求URL采用`sqlutc`时,返回结果集的时间戳将采用UTC时间 ### 重要配置项 -下面仅列出一些与RESTful接口有关的配置参数,其他系统参数请看配置文件里的说明。(注意:配置修改后,需要重启taosd服务才能生效) +下面仅列出一些与 RESTful 接口有关的配置参数,其他系统参数请看配置文件里的说明。(注意:配置修改后,需要重启 taosd 服务才能生效) -- 对外提供RESTful服务的端口号,默认绑定到 6041(实际取值是 serverPort + 11,因此可以通过修改 serverPort 参数的设置来修改) -- httpMaxThreads: 启动的线程数量,默认为2(2.0.17.0版本开始,默认值改为CPU核数的一半向下取整) -- restfulRowLimit: 返回结果集(JSON格式)的最大条数,默认值为10240 -- httpEnableCompress: 是否支持压缩,默认不支持,目前TDengine仅支持gzip压缩格式 -- httpDebugFlag: 日志开关,默认131。131:仅错误和报警信息,135:调试信息,143:非常详细的调试信息,默认131 +- 对外提供 RESTful 服务的端口号,默认绑定到 6041(实际取值是 serverPort + 11,因此可以通过修改 serverPort 参数的设置来修改)。 +- httpMaxThreads: 启动的线程数量,默认为 2(2.0.17.0 版本开始,默认值改为 CPU 核数的一半向下取整)。 +- restfulRowLimit: 返回结果集(JSON 格式)的最大条数,默认值为 10240。 +- httpEnableCompress: 是否支持压缩,默认不支持,目前 TDengine 仅支持 gzip 压缩格式。 +- httpDebugFlag: 日志开关,默认 131。131:仅错误和报警信息,135:调试信息,143:非常详细的调试信息,默认 131。 +- httpDbNameMandatory: 是否必须在 RESTful url 中指定默认的数据库名。默认为 0,即关闭此检查。如果设置为 1,那么每个 RESTful url 中都必须设置一个默认数据库名,否则无论此时执行的 SQL 语句是否需要指定数据库,都会返回一个执行错误,拒绝执行此 SQL 语句。 ## CSharp Connector @@ -966,26 +972,33 @@ Go连接器支持的系统有: **提示:建议Go版本是1.13及以上,并开启模块支持:** ```sh - go env -w GO111MODULE=on - go env -w GOPROXY=https://goproxy.io,direct +go env -w GO111MODULE=on +go env -w GOPROXY=https://goproxy.io,direct ``` 在taosdemo.go所在目录下进行编译和执行: ```sh - go mod init *demo* - go build ./demo -h fqdn -p serverPort +go mod init taosdemo +go get github.com/taosdata/driver-go/taosSql +# use win branch in Windows platform. +#go get github.com/taosdata/driver-go/taosSql@win +go build +./taosdemo -h fqdn -p serverPort ``` ### Go连接器的使用 -TDengine提供了GO驱动程序包`taosSql`.`taosSql`实现了GO语言的内置接口`database/sql/driver`。用户只需按如下方式引入包就可以在应用程序中访问TDengine。 +TDengine提供了GO驱动程序包`taosSql`。`taosSql`实现了GO语言的内置接口`database/sql/driver`。用户只需按如下方式引入包就可以在应用程序中访问TDengine。 ```go import ( "database/sql" - _ "github.com/taosdata/driver-go/taosSql" + _ "github.com/taosdata/driver-go/v2/taosSql" ) ``` + **提示**:下划线与双引号之间必须有一个空格。 +`taosSql` 的 v2 版本进行了重构,分离出内置数据库操作接口 `database/sql/driver` 到目录 `taosSql`;订阅、stmt等其他功能放到目录 `af`。 + ### 常用API - `sql.Open(DRIVER_NAME string, dataSourceName string) *DB` diff --git a/documentation20/cn/10.cluster/docs.md b/documentation20/cn/10.cluster/docs.md index f995597db016ed693ef6c3a37d15163a00160fde..1f6f84dd1a3e66da5a64d07358d97e6f89bdc8c0 100644 --- a/documentation20/cn/10.cluster/docs.md +++ b/documentation20/cn/10.cluster/docs.md @@ -14,7 +14,7 @@ TDengine的集群管理极其简单,除添加和删除节点需要人工干预 **第一步**:如果搭建集群的物理节点中,存有之前的测试数据、装过1.X的版本,或者装过其他版本的TDengine,请先将其删除,并清空所有数据(如果需要保留原有数据,请联系涛思交付团队进行旧版本升级、数据迁移),具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html)。 **注意1:**因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(`rm -rf /var/lib/taos/*`); -**注意2:**客户端也需要配置,确保它可以正确解析每个节点的FQDN配置,不管是通过DNS服务,还是 Host 文件。 +**注意2:**客户端也需要配置,确保它可以正确解析每个节点的FQDN配置,不管是通过DNS服务,还是修改 hosts 文件。 **第二步**:建议关闭所有物理节点的防火墙,至少保证端口:6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口; @@ -79,13 +79,13 @@ Query OK, 1 row(s) in set (0.006385s) taos> ``` -上述命令里,可以看到这个刚启动的这个数据节点的End Point是:h1.taos.com:6030,就是这个新集群的firstEP。 +上述命令里,可以看到这个刚启动的这个数据节点的End Point是:h1.taos.com:6030,就是这个新集群的firstEp。 ## 启动后续数据节点 将后续的数据节点添加到现有集群,具体有以下几步: -1. 按照[《立即开始》](https://www.taosdata.com/cn/documentation/getting-started/)一章的方法在每个物理节点启动taosd;(注意:每个物理节点都需要在 taos.cfg 文件中将 firstEP 参数配置为新集群首个节点的 End Point——在本例中是 h1.taos.com:6030) +1. 按照[《立即开始》](https://www.taosdata.com/cn/documentation/getting-started/)一章的方法在每个物理节点启动taosd;(注意:每个物理节点都需要在 taos.cfg 文件中将 firstEp参数配置为新集群首个节点的 End Point——在本例中是 h1.taos.com:6030) 2. 在第一个数据节点,使用CLI程序taos,登录进TDengine系统,执行命令: @@ -110,7 +110,7 @@ taos> **提示:** -- 任何已经加入集群在线的数据节点,都可以作为后续待加入节点的 firstEP。 +- 任何已经加入集群在线的数据节点,都可以作为后续待加入节点的 firstEp。 - firstEp 这个参数仅仅在该数据节点首次加入集群时有作用,加入集群后,该数据节点会保存最新的 mnode 的 End Point 列表,不再依赖这个参数。 - 接下来,配置文件中的 firstEp 参数就主要在客户端连接的时候使用了,例如 taos shell 如果不加参数,会默认连接由 firstEp 指定的节点。 - 两个没有配置 firstEp 参数的数据节点 dnode 启动后,会独立运行起来。这个时候,无法将其中一个数据节点加入到另外一个数据节点,形成集群。**无法将两个独立的集群合并成为新的集群**。 @@ -119,9 +119,14 @@ taos> 上面已经介绍如何从零开始搭建集群。集群组建完后,还可以随时添加新的数据节点进行扩容,或删除数据节点,并检查集群当前状态。 + +**提示:** + +- 以下所有执行命令的操作需要先登陆进TDengine系统,必要时请使用root权限。 + ### 添加数据节点 -执行CLI程序taos,使用root账号登录进系统,执行: +执行CLI程序taos,执行: ``` CREATE DNODE "fqdn:port"; @@ -131,7 +136,7 @@ CREATE DNODE "fqdn:port"; ### 删除数据节点 -执行CLI程序taos,使用root账号登录进TDengine系统,执行: +执行CLI程序taos,执行: ```mysql DROP DNODE "fqdn:port | dnodeID"; @@ -153,7 +158,7 @@ DROP DNODE "fqdn:port | dnodeID"; 手动将某个vnode迁移到指定的dnode。 -执行CLI程序taos,使用root账号登录进TDengine系统,执行: +执行CLI程序taos,执行: ```mysql ALTER DNODE BALANCE "VNODE:-DNODE:"; @@ -169,7 +174,7 @@ ALTER DNODE BALANCE "VNODE:-DNODE:"; ### 查看数据节点 -执行CLI程序taos,使用root账号登录进TDengine系统,执行: +执行CLI程序taos,执行: ```mysql SHOW DNODES; ``` @@ -180,8 +185,9 @@ SHOW DNODES; 为充分利用多核技术,并提供scalability,数据需要分片处理。因此TDengine会将一个DB的数据切分成多份,存放在多个vnode里。这些vnode可能分布在多个数据节点dnode里,这样就实现了水平扩展。一个vnode仅仅属于一个DB,但一个DB可以有多个vnode。vnode的是mnode根据当前系统资源的情况,自动进行分配的,无需任何人工干预。 -执行CLI程序taos,使用root账号登录进TDengine系统,执行: +执行CLI程序taos,执行: ```mysql +USE SOME_DATABASE; SHOW VGROUPS; ``` diff --git a/documentation20/cn/11.administrator/docs.md b/documentation20/cn/11.administrator/docs.md index c4bdecf29457279dd6ffbea293c984ff466f3ba9..35eff03423e1400ff3339bb493e1816e9d899056 100644 --- a/documentation20/cn/11.administrator/docs.md +++ b/documentation20/cn/11.administrator/docs.md @@ -217,7 +217,7 @@ taosd -C | 99 | queryBufferSize | | **S** | MB | 为所有并发查询占用保留的内存大小。 | | | 计算规则可以根据实际应用可能的最大并发数和表的数字相乘,再乘 170 。(2.0.15 以前的版本中,此参数的单位是字节) | | 100 | ratioOfQueryCores | | **S** | | 设置查询线程的最大数量。 | | | 最小值0 表示只有1个查询线程;最大值2表示最大建立2倍CPU核数的查询线程。默认为1,表示最大和CPU核数相等的查询线程。该值可以为小数,即0.5表示最大建立CPU核数一半的查询线程。 | | 101 | update | | **S** | | 允许更新已存在的数据行 | 0 \| 1 | 0 | 从 2.0.8.0 版本开始 | -| 102 | cacheLast | | **S** | | 是否在内存中缓存子表的最近数据 | 0:关闭;1:缓存子表最近一行数据;2:缓存子表每一列的最近的非NULL值;3:同时打开缓存最近行和列功能。 | 0 | 2.1.2.0 版本之前、2.0.20.7 版本之前在 taos.cfg 文件中不支持此参数。 | +| 102 | cacheLast | | **S** | | 是否在内存中缓存子表的最近数据 | 0:关闭;1:缓存子表最近一行数据;2:缓存子表每一列的最近的非NULL值;3:同时打开缓存最近行和列功能。(2.1.2.0 版本开始此参数支持 0~3 的取值范围,在此之前取值只能是 [0, 1]) | 0 | 2.1.2.0 版本之前、2.0.20.7 版本之前在 taos.cfg 文件中不支持此参数。 | | 103 | numOfCommitThreads | YES | **S** | | 设置写入线程的最大数量 | | | | | 104 | maxWildCardsLength | | **C** | bytes | 设定 LIKE 算子的通配符字符串允许的最大长度 | 0-16384 | 100 | 2.1.6.1 版本新增。 | @@ -375,7 +375,7 @@ taos -C 或 taos --dump-config timezone GMT-8 timezone Asia/Shanghai ``` - 均是合法的设置东八区时区的格式。 + 均是合法的设置东八区时区的格式。但需注意,Windows 下并不支持 `timezone Asia/Shanghai` 这样的写法,而必须写成 `timezone UTC-8`。 时区的设置对于查询和写入SQL语句中非Unix时间戳的内容(时间戳字符串、关键词now的解析)产生影响。例如: ```sql @@ -652,7 +652,7 @@ rmtaos - 表名:不能包含“.”以及特殊字符,与所属数据库名一起,不能超过 192 个字符,每行数据最大长度 16k 个字符 - 表的列名:不能包含特殊字符,不能超过 64 个字符 - 数据库名、表名、列名,都不能以数字开头,合法的可用字符集是“英文字符、数字和下划线” -- 表的列数:不能超过 1024 列,最少需要 2 列,第一列必须是时间戳 +- 表的列数:不能超过 1024 列,最少需要 2 列,第一列必须是时间戳(从 2.1.7.0 版本开始,改为最多支持 4096 列) - 记录的最大长度:包括时间戳 8 byte,不能超过 16KB(每个 BINARY/NCHAR 类型的列还会额外占用 2 个 byte 的存储位置) - 单条 SQL 语句默认最大字符串长度:65480 byte,但可通过系统配置参数 maxSQLLength 修改,最长可配置为 1048576 byte - 数据库副本数:不能超过 3 @@ -665,7 +665,7 @@ rmtaos - 库的个数:仅受节点个数限制 - 单个库上虚拟节点个数:不能超过 64 个 - 库的数目,超级表的数目、表的数目,系统不做限制,仅受系统资源限制 -- SELECT 语句的查询结果,最多允许返回 1024 列(语句中的函数调用可能也会占用一些列空间),超限时需要显式指定较少的返回数据列,以避免语句执行报错。 +- SELECT 语句的查询结果,最多允许返回 1024 列(语句中的函数调用可能也会占用一些列空间),超限时需要显式指定较少的返回数据列,以避免语句执行报错。(从 2.1.7.0 版本开始,改为最多允许 4096 列) 目前 TDengine 有将近 200 个内部保留关键字,这些关键字无论大小写均不可以用作库名、表名、STable 名、数据列名及标签列名等。这些关键字列表如下: @@ -800,7 +800,7 @@ taos -n sync -P 6042 -h `taos -n speed -h -P 6030 -N 10 -l 10000000 -S TCP` -从 2.1.7.0 版本开始,taos 工具新提供了一个网络速度诊断的模式,可以对一个正在运行中的 taosd 实例或者 `taos -n server` 方式模拟的一个服务端实例,以非压缩传输的方式进行网络测速。这个模式下可供调整的参数如下: +从 2.2.0.0 版本开始,taos 工具新提供了一个网络速度诊断的模式,可以对一个正在运行中的 taosd 实例或者 `taos -n server` 方式模拟的一个服务端实例,以非压缩传输的方式进行网络测速。这个模式下可供调整的参数如下: -n:设为“speed”时,表示对网络速度进行诊断。 -h:所要连接的服务端的 FQDN 或 ip 地址。如果不设置这一项,会使用本机 taos.cfg 文件中 FQDN 参数的设置作为默认值。 @@ -809,6 +809,15 @@ taos -n sync -P 6042 -h -l:单个网络包的大小(单位:字节)。最小值是 1024、最大值是 1024*1024*1024,默认值为 1000。 -S:网络封包的类型。可以是 TCP 或 UDP,默认值为 TCP。 +#### FQDN 解析速度诊断 + +`taos -n fqdn -h ` + +从 2.2.0.0 版本开始,taos 工具新提供了一个 FQDN 解析速度的诊断模式,可以对一个目标 FQDN 地址尝试解析,并记录解析过程中所消耗的时间。这个模式下可供调整的参数如下: + +-n:设为“fqdn”时,表示对 FQDN 解析进行诊断。 +-h:所要解析的目标 FQDN 地址。如果不设置这一项,会使用本机 taos.cfg 文件中 FQDN 参数的设置作为默认值。 + #### 服务端日志 taosd 服务端日志文件标志位 debugflag 默认为 131,在 debug 时往往需要将其提升到 135 或 143 。 diff --git a/documentation20/cn/12.taos-sql/docs.md b/documentation20/cn/12.taos-sql/docs.md index 372070d081538d2d506d8c56ab6b968cb9a5ae20..b96a9c3d285e76384ac8dad64473764bcc76942b 100644 --- a/documentation20/cn/12.taos-sql/docs.md +++ b/documentation20/cn/12.taos-sql/docs.md @@ -35,7 +35,7 @@ taos> DESCRIBE meters; - 内部函数 now 是客户端的当前时间 - 插入记录时,如果时间戳为 now,插入数据时使用提交这条记录的客户端的当前时间 - Epoch Time:时间戳也可以是一个长整数,表示从格林威治时间 1970-01-01 00:00:00.000 (UTC/GMT) 开始的毫秒数(相应地,如果所在 Database 的时间精度设置为“微秒”,则长整型格式的时间戳含义也就对应于从格林威治时间 1970-01-01 00:00:00.000 (UTC/GMT) 开始的微秒数;纳秒精度的逻辑也是类似的。) -- 时间可以加减,比如 now-2h,表明查询时刻向前推 2 个小时(最近 2 小时)。数字后面的时间单位可以是 b(纳秒)、u(微秒)、a(毫秒)、s(秒)、m(分)、h(小时)、d(天)、w(周)。 比如 `select * from t1 where ts > now-2w and ts <= now-1w`,表示查询两周前整整一周的数据。在指定降频操作(down sampling)的时间窗口(interval)时,时间单位还可以使用 n(自然月) 和 y(自然年)。 +- 时间可以加减,比如 now-2h,表明查询时刻向前推 2 个小时(最近 2 小时)。数字后面的时间单位可以是 b(纳秒)、u(微秒)、a(毫秒)、s(秒)、m(分)、h(小时)、d(天)、w(周)。 比如 `select * from t1 where ts > now-2w and ts <= now-1w`,表示查询两周前整整一周的数据。在指定降采样操作(down sampling)的时间窗口(interval)时,时间单位还可以使用 n(自然月) 和 y(自然年)。 TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传递的 PRECISION 参数就可以支持微秒和纳秒。(从 2.1.5.0 版本开始支持纳秒精度) @@ -206,10 +206,6 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传 显示当前数据库下的所有数据表信息。 - 说明:可在 like 中使用通配符进行名称的匹配,这一通配符字符串最长不能超过 20 字节。( 从 2.1.6.1 版本开始,通配符字符串的长度放宽到了 100 字节,并可以通过 taos.cfg 中的 maxWildCardsLength 参数来配置这一长度限制。但不建议使用太长的通配符字符串,将有可能严重影响 LIKE 操作的执行性能。) - - 通配符匹配:1)'%'(百分号)匹配0到任意个字符;2)'\_'下划线匹配单个任意字符。 - - **显示一个数据表的创建语句** ```mysql @@ -237,7 +233,7 @@ TDengine 缺省的时间戳是毫秒精度,但通过在 CREATE DATABASE 时传 ``` 说明: - 1) 列的最大个数为1024,最小个数为2; + 1) 列的最大个数为1024,最小个数为2;(从 2.1.7.0 版本开始,改为最多允许 4096 列) 2) 列名最大长度为64。 @@ -717,16 +713,48 @@ Query OK, 1 row(s) in set (0.001091s) | <= | smaller than or equal to | **`timestamp`** and all numeric types | | = | equal to | all types | | <> | not equal to | all types | +| is [not] null | is null or is not null | all types | | between and | within a certain range | **`timestamp`** and all numeric types | -| in | matches any value in a set | all types except first column `timestamp` | -| % | match with any char sequences | **`binary`** **`nchar`** | -| _ | match with a single char | **`binary`** **`nchar`** | +| in | match any value in a set | all types except first column `timestamp` | +| like | match a wildcard string | **`binary`** **`nchar`** | 1. <> 算子也可以写为 != ,请注意,这个算子不能用于数据表第一列的 timestamp 字段。 -2. 同时进行多个字段的范围过滤,需要使用关键词 AND 来连接不同的查询条件,暂不支持 OR 连接的不同列之间的查询过滤条件。 -3. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如: `((value > 20 AND value < 30) OR (value < 12))`。 -4. 从 2.0.17.0 版本开始,条件过滤开始支持 BETWEEN AND 语法,例如 `WHERE col2 BETWEEN 1.5 AND 3.25` 表示查询条件为“1.5 ≤ col2 ≤ 3.25”。 -5. 从 2.1.4.0 版本开始,条件过滤开始支持 IN 算子,例如 `WHERE city IN ('Beijing', 'Shanghai')`。说明:BOOL 类型写作 `{true, false}` 或 `{0, 1}` 均可,但不能写作 0、1 之外的整数;FLOAT 和 DOUBLE 类型会受到浮点数精度影响,集合内的值在精度范围内认为和数据行的值完全相等才能匹配成功;TIMESTAMP 类型支持非主键的列。 +2. like 算子使用通配符字符串进行匹配检查。 + * 在通配符字符串中:'%'(百分号)匹配 0 到任意个字符;'\_'(下划线)匹配单个任意字符。 + * 如果希望匹配字符串中原本就带有的 \_(下划线)字符,那么可以在通配符字符串中写作 `\_`,也即加一个反斜线来进行转义。(从 2.2.0.0 版本开始支持) + * 通配符字符串最长不能超过 20 字节。(从 2.1.6.1 版本开始,通配符字符串的长度放宽到了 100 字节,并可以通过 taos.cfg 中的 maxWildCardsLength 参数来配置这一长度限制。但不建议使用太长的通配符字符串,将有可能严重影响 LIKE 操作的执行性能。) +3. 同时进行多个字段的范围过滤,需要使用关键词 AND 来连接不同的查询条件,暂不支持 OR 连接的不同列之间的查询过滤条件。 + * 从 2.3.0.0 版本开始,已支持完整的同一列和/或不同列间的 AND/OR 运算。 +4. 针对单一字段的过滤,如果是时间过滤条件,则一条语句中只支持设定一个;但针对其他的(普通)列或标签列,则可以使用 `OR` 关键字进行组合条件的查询过滤。例如: `((value > 20 AND value < 30) OR (value < 12))`。 + * 从 2.3.0.0 版本开始,允许使用多个时间过滤条件,但首列时间戳的过滤运算结果只能包含一个区间。 +5. 从 2.0.17.0 版本开始,条件过滤开始支持 BETWEEN AND 语法,例如 `WHERE col2 BETWEEN 1.5 AND 3.25` 表示查询条件为“1.5 ≤ col2 ≤ 3.25”。 +6. 从 2.1.4.0 版本开始,条件过滤开始支持 IN 算子,例如 `WHERE city IN ('Beijing', 'Shanghai')`。说明:BOOL 类型写作 `{true, false}` 或 `{0, 1}` 均可,但不能写作 0、1 之外的整数;FLOAT 和 DOUBLE 类型会受到浮点数精度影响,集合内的值在精度范围内认为和数据行的值完全相等才能匹配成功;TIMESTAMP 类型支持非主键的列。 + + +### 嵌套查询 + +“嵌套查询”又称为“子查询”,也即在一条 SQL 语句中,“内层查询”的计算结果可以作为“外层查询”的计算对象来使用。 + +从 2.2.0.0 版本开始,TDengine 的查询引擎开始支持在 FROM 子句中使用非关联子查询(“非关联”的意思是,子查询不会用到父查询中的参数)。也即在普通 SELECT 语句的 tb_name_list 位置,用一个独立的 SELECT 语句来代替(这一 SELECT 语句被包含在英文圆括号内),于是完整的嵌套查询 SQL 语句形如: + +```mysql +SELECT ... FROM (SELECT ... FROM ...) ...; +``` + +说明: +1. 目前仅支持一层嵌套,也即不能在子查询中再嵌入子查询。 +2. 内层查询的返回结果将作为“虚拟表”供外层查询使用,此虚拟表可以使用 AS 语法做重命名,以便于外层查询中方便引用。 +3. 目前不能在“连续查询”功能中使用子查询。 +4. 在内层和外层查询中,都支持普通的表间/超级表间 JOIN。内层查询的计算结果也可以再参与数据子表的 JOIN 操作。 +5. 目前内层查询、外层查询均不支持 UNION 操作。 +6. 内层查询支持的功能特性与非嵌套的查询语句能力是一致的。 + * 内层查询的 ORDER BY 子句一般没有意义,建议避免这样的写法以免无谓的资源消耗。 +7. 与非嵌套的查询语句相比,外层查询所能支持的功能特性存在如下限制: + * 计算函数部分: + 1. 如果内层查询的结果数据未提供时间戳,那么计算过程依赖时间戳的函数在外层会无法正常工作。例如:TOP, BOTTOM, FIRST, LAST, DIFF。 + 2. 计算过程需要两遍扫描的函数,在外层查询中无法正常工作。例如:此类函数包括:STDDEV, PERCENTILE。 + * 外层查询中不支持 IN 算子,但在内层中可以使用。 + * 外层查询不支持 GROUP BY。 ### UNION ALL 操作符 @@ -1036,7 +1064,7 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ```mysql SELECT LAST(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` - 功能说明:统计表/超级表中某列的值最后写入的非NULL值。 + 功能说明:统计表/超级表中某列的值最后写入的非 NULL 值。 返回结果数据类型:同应用的字段。 @@ -1046,9 +1074,11 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 说明: - 1)如果要返回各个列的最后(时间戳最大)一个非NULL值,可以使用LAST(\*); + 1)如果要返回各个列的最后(时间戳最大)一个非 NULL 值,可以使用 LAST(\*); + + 2)如果结果集中的某列全部为 NULL 值,则该列的返回结果也是 NULL;如果结果集中所有列全部为 NULL 值,则不返回结果。 - 2)如果结果集中的某列全部为NULL值,则该列的返回结果也是NULL;如果结果集中所有列全部为NULL值,则不返回结果。 + 3)在用于超级表时,时间戳完全一样且同为最大的数据行可能有多个,那么会从中随机返回一条,而并不保证多次运行所挑选的数据行必然一致。 示例: ```mysql @@ -1197,9 +1227,9 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 适用于:**表、超级表**。 - 说明:与LAST函数不同,LAST_ROW不支持时间范围限制,强制返回最后一条记录。 + 限制:LAST_ROW() 不能与 INTERVAL 一起使用。 - 限制:LAST_ROW()不能与INTERVAL一起使用。 + 说明:在用于超级表时,时间戳完全一样且同为最大的数据行可能有多个,那么会从中随机返回一条,而并不保证多次运行所挑选的数据行必然一致。 示例: ```mysql @@ -1222,27 +1252,36 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 ``` 功能说明:返回表/超级表的指定时间截面、指定字段的记录。 - 返回结果数据类型:同应用的字段。 + 返回结果数据类型:同字段类型。 - 应用字段:所有字段。 + 应用字段:数值型字段。 适用于:**表、超级表**。 - 说明:(从 2.0.15.0 版本开始新增此函数)INTERP 必须指定时间断面,如果该时间断面不存在直接对应的数据,那么会根据 FILL 参数的设定进行插值。其中,条件语句里面可以附带更多的筛选条件,例如标签、tbname。 + 说明:(从 2.0.15.0 版本开始新增此函数)INTERP 必须指定时间断面,如果该时间断面不存在直接对应的数据,那么会根据 FILL 参数的设定进行插值。此外,条件语句里面可附带筛选条件,例如标签、tbname。 + + INTERP 查询要求查询的时间区间必须位于数据集合(表)的所有记录的时间范围之内。如果给定的时间戳位于时间范围之外,即使有插值指令,仍然不返回结果。 示例: - ```mysql - taos> select interp(*) from meters where ts='2017-7-14 10:42:00.005' fill(prev); - interp(ts) | interp(f1) | interp(f2) | interp(f3) | - ==================================================================== - 2017-07-14 10:42:00.005 | 5 | 9 | 6 | - Query OK, 1 row(s) in set (0.002912s) + ```sql + taos> SELECT INTERP(*) FROM meters WHERE ts='2017-7-14 18:40:00.004'; + interp(ts) | interp(current) | interp(voltage) | interp(phase) | + ========================================================================================== + 2017-07-14 18:40:00.004 | 9.84020 | 216 | 0.32222 | + Query OK, 1 row(s) in set (0.002652s) + ``` + + 如果给定的时间戳无对应的数据,在不指定插值生成策略的情况下,不会返回结果,如果指定了插值策略,会根据插值策略返回结果。 + + ```sql + taos> SELECT INTERP(*) FROM meters WHERE tbname IN ('d636') AND ts='2017-7-14 18:40:00.005'; + Query OK, 0 row(s) in set (0.004022s) - taos> select interp(*) from meters where tbname in ('t1') and ts='2017-7-14 10:42:00.005' fill(prev); - interp(ts) | interp(f1) | interp(f2) | interp(f3) | - ==================================================================== - 2017-07-14 10:42:00.005 | 5 | 6 | 7 | - Query OK, 1 row(s) in set (0.002005s) + taos> SELECT INTERP(*) FROM meters WHERE tbname IN ('d636') AND ts='2017-7-14 18:40:00.005' FILL(PREV);; + interp(ts) | interp(current) | interp(voltage) | interp(phase) | + ========================================================================================== + 2017-07-14 18:40:00.005 | 9.88150 | 217 | 0.32500 | + Query OK, 1 row(s) in set (0.003056s) ``` ### 计算函数 @@ -1285,6 +1324,19 @@ TDengine支持针对数据的聚合查询。提供支持的聚合和选择函数 说明:(从 2.1.3.0 版本开始新增此函数)输出结果行数是范围内总行数减一,第一行没有结果输出。DERIVATIVE 函数可以在由 GROUP BY 划分出单独时间线的情况下用于超级表(也即 GROUP BY tbname)。 + 示例: + ```mysql + taos> select derivative(current, 10m, 0) from t1; + ts | derivative(current, 10m, 0) | + ======================================================== + 2021-08-20 10:11:22.790 | 0.500000000 | + 2021-08-20 11:11:22.791 | 0.166666620 | + 2021-08-20 12:11:22.791 | 0.000000000 | + 2021-08-20 13:11:22.792 | 0.166666620 | + 2021-08-20 14:11:22.792 | -0.666666667 | + Query OK, 5 row(s) in set (0.004883s) + ``` + - **SPREAD** ```mysql SELECT SPREAD(field_name) FROM { tb_name | stb_name } [WHERE clause]; @@ -1406,23 +1458,25 @@ SELECT AVG(current), MAX(current), LEASTSQUARES(current, start_val, step_val), P - 数据库名最大长度为 32。 - 表名最大长度为 192,每行数据最大长度 16k 个字符(注意:数据行内每个 BINARY/NCHAR 类型的列还会额外占用 2 个字节的存储位置)。 -- 列名最大长度为 64,最多允许 1024 列,最少需要 2 列,第一列必须是时间戳。 +- 列名最大长度为 64,最多允许 1024 列,最少需要 2 列,第一列必须是时间戳。(从 2.1.7.0 版本开始,改为最多允许 4096 列) - 标签名最大长度为 64,最多允许 128 个,可以 1 个,一个表中标签值的总长度不超过 16k 个字符。 - SQL 语句最大长度 65480 个字符,但可通过系统配置参数 maxSQLLength 修改,最长可配置为 1M。 -- SELECT 语句的查询结果,最多允许返回 1024 列(语句中的函数调用可能也会占用一些列空间),超限时需要显式指定较少的返回数据列,以避免语句执行报错。 +- SELECT 语句的查询结果,最多允许返回 1024 列(语句中的函数调用可能也会占用一些列空间),超限时需要显式指定较少的返回数据列,以避免语句执行报错。(从 2.1.7.0 版本开始,改为最多允许 4096 列) - 库的数目,超级表的数目、表的数目,系统不做限制,仅受系统资源限制。 -## TAOS SQL其他约定 +## TAOS SQL 其他约定 **GROUP BY的限制** -TAOS SQL支持对标签、TBNAME进行GROUP BY操作,也支持普通列进行GROUP BY,前提是:仅限一列且该列的唯一值小于10万个。 +TAOS SQL 支持对标签、TBNAME 进行 GROUP BY 操作,也支持普通列进行 GROUP BY,前提是:仅限一列且该列的唯一值小于 10 万个。 + +**JOIN 操作的限制** -**JOIN操作的限制** +TAOS SQL 支持表之间按主键时间戳来 join 两张表的列,暂不支持两个表之间聚合后的四则运算。 -TAOS SQL支持表之间按主键时间戳来join两张表的列,暂不支持两个表之间聚合后的四则运算。 +JOIN 查询的不同表的过滤条件之间不能为 OR。 -**IS NOT NULL与不为空的表达式适用范围** +**IS NOT NULL 与不为空的表达式适用范围** -IS NOT NULL支持所有类型的列。不为空的表达式为 <>"",仅对非数值类型的列适用。 +IS NOT NULL 支持所有类型的列。不为空的表达式为 <>"",仅对非数值类型的列适用。 diff --git a/documentation20/cn/13.faq/docs.md b/documentation20/cn/13.faq/docs.md index d89b2adeb8561586abb6201fc639415a8347254f..3d6f03b30353524d55a4a49ea69625a519fe3ebe 100644 --- a/documentation20/cn/13.faq/docs.md +++ b/documentation20/cn/13.faq/docs.md @@ -98,7 +98,7 @@ TDengine 目前尚不支持删除功能,未来根据用户需求可能会支 ## 10. 我怎么创建超过1024列的表? -使用2.0及其以上版本,默认支持1024列;2.0之前的版本,TDengine最大允许创建250列的表。但是如果确实超过限值,建议按照数据特性,逻辑地将这个宽表分解成几个小表。 +使用 2.0 及其以上版本,默认支持 1024 列;2.0 之前的版本,TDengine 最大允许创建 250 列的表。但是如果确实超过限值,建议按照数据特性,逻辑地将这个宽表分解成几个小表。(从 2.1.7.0 版本开始,表的最大列数增加到了 4096 列。) ## 11. 最有效的写入数据的方法是什么? diff --git a/documentation20/en/00.index/docs.md b/documentation20/en/00.index/docs.md index a10c22ee622fe71f4215c981774b637fc7c177d9..258b2f718feb87a2fa8d92b17a403919ac2e8f56 100644 --- a/documentation20/en/00.index/docs.md +++ b/documentation20/en/00.index/docs.md @@ -1,37 +1,50 @@ # TDengine Documentation -TDengine is a highly efficient platform to store, query, and analyze time-series data. It is specially designed and optimized for IoT, Internet of Vehicles, Industrial IoT, IT Infrastructure and Application Monitoring, etc. It works like a relational database, such as MySQL, but you are strongly encouraged to read through the following documentation before you experience it, especially the Data Model and Data Modeling sections. In addition to this document, you should also download and read our technology white paper. For the older TDengine version 1.6 documentation, please click here. +TDengine is a highly efficient platform to store, query, and analyze time-series data. It is specially designed and optimized for IoT, Internet of Vehicles, Industrial IoT, IT Infrastructure and Application Monitoring, etc. It works like a relational database, such as MySQL, but you are strongly encouraged to read through the following documentation before you experience it, especially the Data Modeling sections. In addition to this document, you should also download and read the technology white paper. For the older TDengine version 1.6 documentation, please click [here](https://www.taosdata.com/en/documentation16/). ## [TDengine Introduction](/evaluation) * [TDengine Introduction and Features](/evaluation#intro) * [TDengine Use Scenes](/evaluation#scenes) -* [TDengine Performance Metrics and Verification]((/evaluation#)) +* [TDengine Performance Metrics and Verification](/evaluation#) ## [Getting Started](/getting-started) -* [Quickly Install](/getting-started#install): install via source code/package / Docker within seconds - -- [Easy to Launch](/getting-started#start): start / stop TDengine with systemctl -- [Command-line](/getting-started#console) : an easy way to access TDengine server -- [Experience Lightning Speed](/getting-started#demo): running a demo, inserting/querying data to experience faster speed -- [List of Supported Platforms](/getting-started#platforms): a list of platforms supported by TDengine server and client -- [Deploy to Kubernetes](https://taosdata.github.io/TDengine-Operator/en/index.html):a detailed guide for TDengine deployment in Kubernetes environment +* [Quick Install](/getting-started#install): install via source code/package / Docker within seconds +* [Quick Launch](/getting-started#start): start / stop TDengine quickly with systemctl +* [Command-line](/getting-started#console) : an easy way to access TDengine server +* [Experience Lightning Speed](/getting-started#demo): running a demo, inserting/querying data to experience faster speed +* [List of Supported Platforms](/getting-started#platforms): a list of platforms supported by TDengine server and client +* [Deploy to Kubernetes](https://taosdata.github.io/TDengine-Operator/en/index.html):a detailed guide for TDengine deployment in Kubernetes environment ## [Overall Architecture](/architecture) -- [Data Model](/architecture#model): relational database model, but one table for one device with static tags -- [Cluster and Primary Logical Unit](/architecture#cluster): Take advantage of NoSQL, support scale-out and high-reliability -- [Storage Model and Data Partitioning/Sharding](/architecture#sharding): tag data will be separated from time-series data, segmented by vnode and time -- [Data Writing and Replication Process](/architecture#replication): records received are written to WAL, cached, with acknowledgement is sent back to client, while supporting multi-replicas +- [Data Model](/architecture#model): relational database model, but one table for one data collection point with static tags +- [Cluster and Primary Logical Unit](/architecture#cluster): Take advantage of NoSQL architecture, high availability and horizontal scalability +- [Storage Model and Data Partitioning/Sharding](/architecture#sharding): tag data is separated from time-series data, sharded by vnodes and partitioned by time +- [Data Writing and Replication Process](/architecture#replication): records received are written to WAL, cached, with acknowledgement sent back to client, while supporting data replications - [Caching and Persistence](/architecture#persistence): latest records are cached in memory, but are written in columnar format with an ultra-high compression ratio -- [Data Query](/architecture#query): support various functions, time-axis aggregation, interpolation, and multi-table aggregation +- [Data Query](/architecture#query): support various SQL functions, downsampling, interpolation, and multi-table aggregation ## [Data Modeling](/model) -- [Create a Database](/model#create-db): create a database for all data collection points with similar features +- [Create a Database](/model#create-db): create a database for all data collection points with similar data characteristics - [Create a Super Table(STable)](/model#create-stable): create a STable for all data collection points with the same type -- [Create a Table](/model#create-table): use STable as the template, to create a table for each data collecting point +- [Create a Table](/model#create-table): use STable as the template to create a table for each data collecting point + +## [Efficient Data Ingestion](/insert) + +- [Data Writing via SQL](/insert#sql): write one or multiple records into one or multiple tables via SQL insert command +- [Data Writing via Prometheus](/insert#prometheus): Configure Prometheus to write data directly without any code +- [Data Writing via Telegraf](/insert#telegraf): Configure Telegraf to write collected data directly without any code +- [Data Writing via EMQ X](/insert#emq): Configure EMQ X to write MQTT data directly without any code +- [Data Writing via HiveMQ Broker](/insert#hivemq): Configure HiveMQ to write MQTT data directly without any code + +## [Efficient Data Querying](/queries) + +- [Major Features](/queries#queries): support various standard query functions, setting filter conditions, and querying per time segment +- [Multi-table Aggregation](/queries#aggregation): use STable and set tag filter conditions to perform efficient aggregation +- [Downsampling](/queries#sampling): aggregate data in successive time windows, support interpolation ## [TAOS SQL](/taos-sql) @@ -40,27 +53,13 @@ TDengine is a highly efficient platform to store, query, and analyze time-series - [Table Management](/taos-sql#table): add, drop, check, alter tables - [STable Management](/taos-sql#super-table): add, drop, check, alter STables - [Tag Management](/taos-sql#tags): add, drop, alter tags -- [Inserting Records](/taos-sql#insert): support to write single/multiple items per table, multiple items across tables, and support to write historical data +- [Inserting Records](/taos-sql#insert): write single/multiple records a table, multiple records across tables, and historical data - [Data Query](/taos-sql#select): support time segment, value filtering, sorting, manual paging of query results, etc - [SQL Function](/taos-sql#functions): support various aggregation functions, selection functions, and calculation functions, such as avg, min, diff, etc -- [Time Dimensions Aggregation](/taos-sql#aggregation): aggregate and reduce the dimension after cutting table data by time segment +- [Cutting and Aggregation](/taos-sql#aggregation): aggregate and reduce the dimension after cutting table data by time segment - [Boundary Restrictions](/taos-sql#limitation): restrictions for the library, table, SQL, and others - [Error Code](/taos-sql/error-code): TDengine 2.0 error codes and corresponding decimal codes -## [Efficient Data Ingestion](/insert) - -- [SQL Ingestion](/insert#sql): write one or multiple records into one or multiple tables via SQL insert command -- [Prometheus Ingestion](/insert#prometheus): Configure Prometheus to write data directly without any code -- [Telegraf Ingestion](/insert#telegraf): Configure Telegraf to write collected data directly without any code -- [EMQ X Broker](/insert#emq): Configure EMQ X to write MQTT data directly without any code -- [HiveMQ Broker](/insert#hivemq): Configure HiveMQ to write MQTT data directly without any code - -## [Efficient Data Querying](/queries) - -- [Main Query Features](/queries#queries): support various standard functions, setting filter conditions, and querying per time segment -- [Multi-table Aggregation Query](/queries#aggregation): use STable and set tag filter conditions to perform efficient aggregation queries -- [Downsampling to Query Value](/queries#sampling): aggregate data in successive time windows, support interpolation - ## [Advanced Features](/advanced-features) - [Continuous Query](/advanced-features#continuous-query): Based on sliding windows, the data stream is automatically queried and calculated at regular intervals @@ -71,7 +70,7 @@ TDengine is a highly efficient platform to store, query, and analyze time-series ## [Connector](/connector) - [C/C++ Connector](/connector#c-cpp): primary method to connect to TDengine server through libtaos client library -- [Java Connector(JDBC)]: driver for connecting to the server from Java applications using the JDBC API +- [Java Connector(JDBC)](/connector/java): driver for connecting to the server from Java applications using the JDBC API - [Python Connector](/connector#python): driver for connecting to TDengine server from Python applications - [RESTful Connector](/connector#restful): a simple way to interact with TDengine via HTTP - [Go Connector](/connector#go): driver for connecting to TDengine server from Go applications @@ -88,12 +87,12 @@ TDengine is a highly efficient platform to store, query, and analyze time-series ## [Installation and Management of TDengine Cluster](/cluster) -- [Preparation](/cluster#prepare): important considerations before deploying TDengine for production usage -- [Create Your First Node](/cluster#node-one): simple to follow the quick setup +- [Preparation](/cluster#prepare): important steps before deploying TDengine for production usage +- [Create the First Node](/cluster#node-one): just follow the steps in quick start - [Create Subsequent Nodes](/cluster#node-other): configure taos.cfg for new nodes to add more to the existing cluster - [Node Management](/cluster#management): add, delete, and check nodes in the cluster -- [High-availability of Vnode](/cluster#high-availability): implement high-availability of Vnode through multi-replicas -- [Mnode Management](/cluster#mnode): automatic system creation without any manual intervention +- [High-availability of Vnode](/cluster#high-availability): implement high-availability of Vnode through replicas +- [Mnode Management](/cluster#mnode): mnodes are created automatically without any manual intervention - [Load Balancing](/cluster#load-balancing): automatically performed once the number of nodes or load changes - [Offline Node Processing](/cluster#offline): any node that offline for more than a certain period will be removed from the cluster - [Arbitrator](/cluster#arbitrator): used in the case of an even number of replicas to prevent split-brain @@ -108,27 +107,14 @@ TDengine is a highly efficient platform to store, query, and analyze time-series - [Export Data](/administrator#export): export data either from TDengine shell or from the taosdump tool - [System Monitor](/administrator#status): monitor the system connections, queries, streaming calculation, logs, and events - [File Directory Structure](/administrator#directories): directories where TDengine data files and configuration files located -- [Parameter Restrictions and Reserved Keywords](/administrator#keywords): TDengine’s list of parameter restrictions and reserved keywords - -## TDengine Technical Design - -- [System Module]: taosd functions and modules partitioning -- [Data Replication]: support real-time synchronous/asynchronous replication, to ensure high-availability of the system -- [Technical Blog](https://www.taosdata.com/cn/blog/?categories=3): More technical analysis and architecture design articles - -## Common Tools - -- [TDengine sample import tools](https://www.taosdata.com/blog/2020/01/18/1166.html) -- [TDengine performance comparison test tools](https://www.taosdata.com/blog/2020/01/18/1166.html) -- [Use TDengine visually through IDEA Database Management Tool](https://www.taosdata.com/blog/2020/08/27/1767.html) +- [Parameter Limitss and Reserved Keywords](/administrator#keywords): TDengine’s list of parameter limits and reserved keywords ## Performance: TDengine vs Others -- [Performance: TDengine vs InfluxDB with InfluxDB’s open-source performance testing tool](https://www.taosdata.com/blog/2020/01/13/1105.html) -- [Performance: TDengine vs OpenTSDB](https://www.taosdata.com/blog/2019/08/21/621.html) -- [Performance: TDengine vs Cassandra](https://www.taosdata.com/blog/2019/08/14/573.html) -- [Performance: TDengine vs InfluxDB](https://www.taosdata.com/blog/2019/07/19/419.html) -- [Performance Test Reports of TDengine vs InfluxDB/OpenTSDB/Cassandra/MySQL/ClickHouse](https://www.taosdata.com/downloads/TDengine_Testing_Report_cn.pdf) +- [Performance: TDengine vs OpenTSDB](https://www.taosdata.com/blog/2019/09/12/710.html) +- [Performance: TDengine vs Cassandra](https://www.taosdata.com/blog/2019/09/12/708.html) +- [Performance: TDengine vs InfluxDB](https://www.taosdata.com/blog/2019/09/12/706.html) +- [Performance Test Reports of TDengine vs InfluxDB/OpenTSDB/Cassandra/MySQL/ClickHouse](https://www.taosdata.com/downloads/TDengine_Testing_Report_en.pdf) ## More on IoT Big Data @@ -136,7 +122,8 @@ TDengine is a highly efficient platform to store, query, and analyze time-series - [Features and Functions of IoT Big Data platforms](https://www.taosdata.com/blog/2019/07/29/542.html) - [Why don’t General Big Data Platforms Fit IoT Scenarios?](https://www.taosdata.com/blog/2019/07/09/why-does-the-general-big-data-platform-not-fit-iot-data-processing/) - [Why TDengine is the best choice for IoT, Internet of Vehicles, and Industry Internet Big Data platforms?](https://www.taosdata.com/blog/2019/07/09/why-tdengine-is-the-best-choice-for-iot-big-data-processing/) +- [Technical Blog](https://www.taosdata.com/cn/blog/?categories=3): More technical analysis and architecture design articles ## FAQ -- [FAQ: Common questions and answers](/faq) +- [FAQ: Common questions and answers](/faq) \ No newline at end of file diff --git a/documentation20/en/01.evaluation/docs.md b/documentation20/en/01.evaluation/docs.md index 250f465d7b1280a78e18250f95aefaeca0c95415..ecbde8c5776e3bd3735aed2bd64906f8bef1afc1 100644 --- a/documentation20/en/01.evaluation/docs.md +++ b/documentation20/en/01.evaluation/docs.md @@ -2,18 +2,18 @@ ## About TDengine -TDengine is an innovative Big Data processing product launched by Taos Data in the face of the fast-growing Internet of Things (IoT) Big Data market and technical challenges. It does not rely on any third-party software, nor does it optimize or package any open-source database or stream computing product. Instead, it is a product independently developed after absorbing the advantages of many traditional relational databases, NoSQL databases, stream computing engines, message queues, and other software. TDengine has its own unique Big Data processing advantages in time-series space. +TDengine is an innovative Big Data processing product launched by TAOS Data in the face of the fast-growing Internet of Things (IoT) Big Data market and technical challenges. It does not rely on any third-party software, nor does it optimize or package any open-source database or stream computing product. Instead, it is a product independently developed after absorbing the advantages of many traditional relational databases, NoSQL databases, stream computing engines, message queues, and other software. TDengine has its own unique Big Data processing advantages in time-series space. One of the modules of TDengine is the time-series database. However, in addition to this, to reduce the complexity of research and development and the difficulty of system operation, TDengine also provides functions such as caching, message queuing, subscription, stream computing, etc. TDengine provides a full-stack technical solution for the processing of IoT and Industrial Internet BigData. It is an efficient and easy-to-use IoT Big Data platform. Compared with typical Big Data platforms such as Hadoop, TDengine has the following distinct characteristics: - **Performance improvement over 10 times**: An innovative data storage structure is defined, with each single core can process at least 20,000 requests per second, insert millions of data points, and read more than 10 million data points, which is more than 10 times faster than other existing general database. - **Reduce the cost of hardware or cloud services to 1/5**: Due to its ultra-performance, TDengine’s computing resources consumption is less than 1/5 of other common Big Data solutions; through columnar storage and advanced compression algorithms, the storage consumption is less than 1/10 of other general databases. - **Full-stack time-series data processing engine**: Integrate database, message queue, cache, stream computing, and other functions, and the applications do not need to integrate with software such as Kafka/Redis/HBase/Spark/HDFS, thus greatly reducing the complexity cost of application development and maintenance. -- **Powerful analysis functions**: Data from ten years ago or one second ago, can all be queried based on a specified time range. Data can be aggregated on a timeline or multiple devices. Ad-hoc queries can be made at any time through Shell, Python, R, and MATLAB. -- **Seamless connection with third-party tools**: Integration with Telegraf, Grafana, EMQ, HiveMQ, Prometheus, MATLAB, R, etc. without even one single line of code. OPC, Hadoop, Spark, etc. will be supported in the future, and more BI tools will be seamlessly connected to. +- **Highly Available and Horizontal Scalable **: With the distributed architecture and consistency algorithm, via multi-replication and clustering features, TDengine ensures high availability and horizontal scalability to support the mission-critical applications. - **Zero operation cost & zero learning cost**: Installing clusters is simple and quick, with real-time backup built-in, and no need to split libraries or tables. Similar to standard SQL, TDengine can support RESTful, Python/Java/C/C++/C#/Go/Node.js, and similar to MySQL with zero learning cost. +- **Core is Open Sourced:** Except some auxiliary features, the core of TDengine is open sourced. Enterprise won't be locked by the database anymore. Ecosystem is more strong, product is more stable, and developer communities are more active. -With TDengine, the total cost of ownership of typical IoT, Internet of Vehicles, and Industrial Internet Big Data platforms can be greatly reduced. However, it should be pointed out that due to making full use of the characteristics of IoT time-series data, TDengine cannot be used to process general data from web crawlers, microblogs, WeChat, e-commerce, ERP, CRM, and other sources. +With TDengine, the total cost of ownership of typical IoT, Internet of Vehicles, and Industrial Internet Big Data platforms can be greatly reduced. However, since it makes full use of the characteristics of IoT time-series data, TDengine cannot be used to process general data from web crawlers, microblogs, WeChat, e-commerce, ERP, CRM, and other sources. ![TDengine Technology Ecosystem](page://images/eco_system.png) @@ -62,4 +62,4 @@ From the perspective of data sources, designers can analyze the applicability of | ------------------------------------------------- | ------------------ | ----------------------- | ------------------- | ------------------------------------------------------------ | | Require system with high-reliability | | | √ | TDengine has a very robust and reliable system architecture to implement simple and convenient daily operation with streamlined experiences for operators, thus human errors and accidents are eliminated to the greatest extent. | | Require controllable operation learning cost | | | √ | As above. | -| Require abundant talent supply | √ | | | As a new-generation product, it’s still difficult to find talents with TDengine experiences from market. However, the learning cost is low. As the vendor, we also provide extensive operation training and counselling services. | +| Require abundant talent supply | √ | | | As a new-generation product, it’s still difficult to find talents with TDengine experiences from market. However, the learning cost is low. As the vendor, we also provide extensive operation training and counselling services. | \ No newline at end of file diff --git a/documentation20/en/02.getting-started/01.docker/docs.md b/documentation20/en/02.getting-started/01.docker/docs.md new file mode 100644 index 0000000000000000000000000000000000000000..daa89ef1016179e7860e4178c52481aef2760243 --- /dev/null +++ b/documentation20/en/02.getting-started/01.docker/docs.md @@ -0,0 +1,243 @@ +# Quickly experience TDengine through Docker + +While it is not recommended to deploy TDengine services via Docker in a production environment, Docker tools do a good job of shielding the environmental differences in the underlying operating system and are well suited for use in development testing or first-time experience with the toolset for installing and running TDengine. In particular, Docker makes it relatively easy to try TDengine on Mac OSX and Windows systems without having to install a virtual machine or rent an additional Linux server. In addition, starting from version 2.0.14.0, TDengine provides images that support both X86-64, X86, arm64, and arm32 platforms, so non-mainstream computers that can run docker, such as NAS, Raspberry Pi, and embedded development boards, can also easily experience TDengine based on this document. + +The following article explains how to quickly build a single-node TDengine runtime environment via Docker to support development and testing through a Step by Step style introduction. + +## Docker download + +The Docker tools themselves can be downloaded from [Docker official site](https://docs.docker.com/get-docker/). + +After installation, you can check the Docker version in the command line terminal. If the version number is output properly, the Docker environment has been installed successfully. + +```bash +$ docker -v +Docker version 20.10.3, build 48d30b5 +``` + +## Running TDengine in a Docker container + +1, Use the command to pull the TDengine image and make it run in the background. + +```bash +$ docker run -d --name tdengine tdengine/tdengine +7760c955f225d72e9c1ec5a4cef66149a7b94dae7598b11eb392138877e7d292 +``` + +- **docker run**: Running a container via Docker +- **--name tdengine**: Set the container name, we can see the corresponding container by the container name +- **-d**: Keeping containers running in the background +- **tdengine/tdengine**: Pulled from the official TDengine published application image +- **7760c955f225d72e9c1ec5a4cef66149a7b94dae7598b11eb392138877e7d292**: The long character returned is the container ID, and we can also view the corresponding container by its container ID + +2, Verify that the container is running correctly. + +```bash +$ docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS ··· +c452519b0f9b tdengine/tdengine "taosd" 14 minutes ago Up 14 minutes ··· +``` + +- **docker ps**: Lists information about all containers that are in running state. +- **CONTAINER ID**: Container ID. +- **IMAGE**: The mirror used. +- **COMMAND**: The command to run when starting the container. +- **CREATED**: The time when the container was created. +- **STATUS**: The container status. Up means running. + +3, Go inside the Docker container and use TDengine. + +```bash +$ docker exec -it tdengine /bin/bash +root@c452519b0f9b:~/TDengine-server-2.0.20.13# +``` + +- **docker exec**: Enter the container via the docker exec command; if you exit, the container will not stop. +- **-i**: Enter the interactive mode. +- **-t**: Specify a terminal. +- **c452519b0f9b**: The container ID, which needs to be modified according to the value returned by the docker ps command. +- **/bin/bash**: Load the container and run bash to interact with it. + +4, After entering the container, execute the taos shell client program. + +```bash +$ root@c452519b0f9b:~/TDengine-server-2.0.20.13# taos + +Welcome to the TDengine shell from Linux, Client Version:2.0.20.13 +Copyright (c) 2020 by TAOS Data, Inc. All rights reserved. + +taos> +``` + +The TDengine terminal successfully connects to the server and prints out a welcome message and version information. If it fails, an error message is printed. + +In the TDengine terminal, you can create/delete databases, tables, super tables, etc., and perform insert and query operations via SQL commands. For details, you can refer to [TAOS SQL guide](https://www.taosdata.com/en/documentation/taos-sql). + +## Learn more about TDengine with taosdemo + +1, Following the above steps, exit the TDengine terminal program first. + +```bash +$ taos> q +root@c452519b0f9b:~/TDengine-server-2.0.20.13# +``` + +2, Execute taosdemo from the command line interface. + +```bash +root@c452519b0f9b:~/TDengine-server-2.0.20.13# taosdemo + +taosdemo is simulating data generated by power equipments monitoring... + +host: 127.0.0.1:6030 +user: root +password: taosdata +configDir: +resultFile: ./output.txt +thread num of insert data: 10 +thread num of create table: 10 +top insert interval: 0 +number of records per req: 30000 +max sql length: 1048576 +database count: 1 +database[0]: + database[0] name: test + drop: yes + replica: 1 + precision: ms + super table count: 1 + super table[0]: + stbName: meters + autoCreateTable: no + childTblExists: no + childTblCount: 10000 + childTblPrefix: d + dataSource: rand + iface: taosc + insertRows: 10000 + interlaceRows: 0 + disorderRange: 1000 + disorderRatio: 0 + maxSqlLen: 1048576 + timeStampStep: 1 + startTimestamp: 2017-07-14 10:40:00.000 + sampleFormat: + sampleFile: + tagsFile: + columnCount: 3 +column[0]:FLOAT column[1]:INT column[2]:FLOAT + tagCount: 2 + tag[0]:INT tag[1]:BINARY(16) + + Press enter key to continue or Ctrl-C to stop +``` + +After enter, this command will automatically create a super table meters under the database test, there are 10,000 tables under this super table, the table name is "d0" to "d9999", each table has 10,000 records, each record has four fields (ts, current, voltage, phase), the time stamp is from "2017-07-14 10:40:00 000" to "2017-07-14 10:40:09 999", each table has a tag location and groupId, groupId is set from 1 to 10 and location is set to "beijing" or "shanghai". + +It takes about a few minutes to execute this command and ends up inserting a total of 100 million records. + +3, Go to the TDengine terminal and view the data generated by taosdemo. + +- **Go to the terminal interface.** + +```bash +$ root@c452519b0f9b:~/TDengine-server-2.0.20.13# taos + +Welcome to the TDengine shell from Linux, Client Version:2.0.20.13 +Copyright (c) 2020 by TAOS Data, Inc. All rights reserved. + +taos> +``` + +- **View the database.** + +```bash +$ taos> show databases; + name | created_time | ntables | vgroups | ··· + test | 2021-08-18 06:01:11.021 | 10000 | 6 | ··· + log | 2021-08-18 05:51:51.065 | 4 | 1 | ··· + +``` + +- **View Super Tables.** + +```bash +$ taos> use test; +Database changed. + +$ taos> show stables; + name | created_time | columns | tags | tables | +============================================================================================ + meters | 2021-08-18 06:01:11.116 | 4 | 2 | 10000 | +Query OK, 1 row(s) in set (0.003259s) + +``` + +- **View the table and limit the output to 10 entries.** + +```bash +$ taos> select * from test.t0 limit 10; + +DB error: Table does not exist (0.002857s) +taos> select * from test.d0 limit 10; + ts | current | voltage | phase | +====================================================================================== + 2017-07-14 10:40:00.000 | 10.12072 | 223 | 0.34167 | + 2017-07-14 10:40:00.001 | 10.16103 | 224 | 0.34445 | + 2017-07-14 10:40:00.002 | 10.00204 | 220 | 0.33334 | + 2017-07-14 10:40:00.003 | 10.00030 | 220 | 0.33333 | + 2017-07-14 10:40:00.004 | 9.84029 | 216 | 0.32222 | + 2017-07-14 10:40:00.005 | 9.88028 | 217 | 0.32500 | + 2017-07-14 10:40:00.006 | 9.88110 | 217 | 0.32500 | + 2017-07-14 10:40:00.007 | 10.08137 | 222 | 0.33889 | + 2017-07-14 10:40:00.008 | 10.12063 | 223 | 0.34167 | + 2017-07-14 10:40:00.009 | 10.16086 | 224 | 0.34445 | +Query OK, 10 row(s) in set (0.016791s) + +``` + +- **View the tag values for the d0 table.** + +```bash +$ taos> select groupid, location from test.d0; + groupid | location | +================================= + 0 | shanghai | +Query OK, 1 row(s) in set (0.003490s) + +``` + +## Stop the TDengine service that is running in Docker + +```bash +$ docker stop tdengine +tdengine +``` + +- **docker stop**: Stop the specified running docker image with docker stop. +- **tdengine**: The name of the container. + +## TDengine connected in Docker during programming development + +There are two ideas for connecting from outside of Docker to use TDengine services running inside a Docker container: + +1, By port mapping (-p), the open network port inside the container is mapped to the specified port of the host. By mounting the local directory (-v), you can synchronize the data inside the host and the container to prevent data loss after the container is deleted. + +```bash +$ docker run -d -v /etc/taos:/etc/taos -P 6041:6041 tdengine/tdengine +526aa188da767ae94b244226a2b2eec2b5f17dd8eff592893d9ec0cd0f3a1ccd + +$ curl -u root:taosdata -d 'show databases' 127.0.0.1:6041/rest/sql +{"status":"succ","head":["name","created_time","ntables","vgroups","replica","quorum","days","keep0,keep1,keep(D)","cache(MB)","blocks","minrows","maxrows","wallevel","fsync","comp","cachelast","precision","update","status"],"column_meta":[["name",8,32],["created_time",9,8],["ntables",4,4],["vgroups",4,4],["replica",3,2],["quorum",3,2],["days",3,2],["keep0,keep1,keep(D)",8,24],["cache(MB)",4,4],["blocks",4,4],["minrows",4,4],["maxrows",4,4],["wallevel",2,1],["fsync",4,4],["comp",2,1],["cachelast",2,1],["precision",8,3],["update",2,1],["status",8,10]],"data":[["test","2021-08-18 06:01:11.021",10000,4,1,1,10,"3650,3650,3650",16,6,100,4096,1,3000,2,0,"ms",0,"ready"],["log","2021-08-18 05:51:51.065",4,1,1,1,10,"30,30,30",1,3,100,4096,1,3000,2,0,"us",0,"ready"]],"rows":2} +``` + +- The first command starts a docker container with TDengine running and maps the 6041 port of the container to port 6041 of the host. +- The second command, accessing TDengine through the RESTful interface, connects to port 6041 on the local machine, so the connection is successful. + +Note: In this example, for convenience reasons, only port 6041 is mapped, which is required for RESTful. If you wish to connect to the TDengine service in a non-RESTful manner, you will need to map a total of 11 ports starting at 6030. In the example, mounting the local directory also only deals with the /etc/taos directory where the configuration files are located, but not the data storage directory. + +2, Go directly to the docker container to do development via the exec command. That is, put the program code in the same Docker container where the TDengine server is located and connect to the TDengine service local to the container. + +```bash +$ docker exec -it tdengine /bin/bash +``` diff --git a/documentation20/en/02.getting-started/docs.md b/documentation20/en/02.getting-started/docs.md index 3c9d9ac6af54cfd49a4b2700c8c79773f08a2120..50a8c2fabb8c93a847a79a4de47c218de7ccd60a 100644 --- a/documentation20/en/02.getting-started/docs.md +++ b/documentation20/en/02.getting-started/docs.md @@ -10,15 +10,15 @@ Please visit our [TDengine github page](https://github.com/taosdata/TDengine) fo ### Install from Docker Container -Please visit our [TDengine Official Docker Image: Distribution, Downloading, and Usage](https://www.taosdata.com/blog/2020/05/13/1509.html). +For the time being, it is not recommended to use Docker to deploy the client or server side of TDengine in production environments, but it is convenient to use Docker to deploy in development environments or when trying it for the first time. In particular, with Docker, it is easy to try TDengine in Mac OS X and Windows environments. -### Install from Package +Please refer to the detailed operation in [Quickly experience TDengine through Docker](https://www.taosdata.com/en/documentation/getting-started/docker). -It’s extremely easy to install for TDengine, which takes only a few seconds from downloaded to successful installed. The server installation package includes clients and connectors. We provide 3 installation packages, which you can choose according to actual needs: +### Install from Package -Click [here](https://www.taosdata.com/cn/getting-started/#%E9%80%9A%E8%BF%87%E5%AE%89%E8%A3%85%E5%8C%85%E5%AE%89%E8%A3%85) to download the install package. +Three different packages for TDengine server are provided, please pick up the one you like. (Lite packages only have execution files and connector of C/C++, but standard packages support connectors of nearly all programming languages.) Beta version has more features, but we suggest you to install stable version for production or testing. -For more about installation process, please refer [TDengine Installation Packages: Install and Uninstall](https://www.taosdata.com/blog/2019/08/09/566.html), and [Video Tutorials](https://www.taosdata.com/blog/2020/11/11/1941.html). +Click [here](https://www.taosdata.com/en/getting-started/#Install-from-Package) to download the install package. ## Quick Launch @@ -131,7 +131,7 @@ After starting the TDengine server, you can execute the command `taosdemo` in th $ taosdemo ``` -Using this command, a STable named `meters` will be created in the database `test` There are 10k tables under this stable, named from `t0` to `t9999`. In each table there are 100k rows of records, each row with columns (`f1`, `f2` and `f3`. The timestamp is from "2017-07-14 10:40:00 000" to "2017-07-14 10:41:39 999". Each table also has tags `areaid` and `loc`: `areaid` is set from 1 to 10, `loc` is set to "beijing" or "shanghai". +Using this command, a STable named `meters` will be created in the database `test`. There are 10k tables under this STable, named from `t0` to `t9999`. In each table there are 100k rows of records, each row with columns (`f1`, `f2` and `f3`. The timestamp is from "2017-07-14 10:40:00 000" to "2017-07-14 10:41:39 999". Each table also has tags `areaid` and `loc`: `areaid` is set from 1 to 10, `loc` is set to "beijing" or "shanghai". It takes about 10 minutes to execute this command. Once finished, 1 billion rows of records will be inserted. @@ -201,7 +201,7 @@ Note: ● has been verified by official tests; ○ has been verified by unoffici List of platforms supported by TDengine client and connectors -At the moment, TDengine connectors can support a wide range of platforms, including hardware platforms such as X64/X86/ARM64/ARM32/MIPS/Alpha, and development environments such as Linux/Win64/Win32. +At the moment, TDengine connectors can support a wide range of platforms, including hardware platforms such as X64/X86/ARM64/ARM32/MIPS/Alpha, and operating system such as Linux/Win64/Win32. Comparison matrix as following: @@ -218,4 +218,4 @@ Comparison matrix as following: Note: ● has been verified by official tests; ○ has been verified by unofficial tests. -Please visit [Connectors](https://www.taosdata.com/en/documentation/connector) section for more detailed information. +Please visit Connectors section for more detailed information. \ No newline at end of file diff --git a/documentation20/en/03.architecture/docs.md b/documentation20/en/03.architecture/docs.md index ce8dd6c8be75ae87afcd51fbbecbaf97a274ba3e..bc686aebbf0b7696b1355fe45be6d09fcca63411 100644 --- a/documentation20/en/03.architecture/docs.md +++ b/documentation20/en/03.architecture/docs.md @@ -4,7 +4,7 @@ ### A Typical IoT Scenario -In typical IoT, Internet of Vehicles and Operation Monitoring scenarios, there are often many different types of data collecting devices that collect one or more different physical metrics. However, for the collection devices of the same type, there are often many specific collection devices distributed in places. BigData processing system aims to collect all kinds of data, and then calculate and analyze them. For the same kind of devices, the data collected are very regular. Taking smart meters as an example, assuming that each smart meter collects three metrics of current, voltage and phase, the collected data are similar to the following table: +In typical industry IoT, Internet of Vehicles and Operation Monitoring scenarios, there are often many different types of data collecting devices that collect one or more different physical metrics. However, for the data collection devices of the same type, there are often many specific collection devices distributed in places. Big Data processing system aims to collect all kinds of data, then store and analyze them. For the same kind of devices, the data collected are very structured. Taking smart meters as an example, assuming that each smart meter collects three metrics of current, voltage and phase, the collected data are similar to the following table:
@@ -108,48 +108,48 @@ Each data record contains the device ID, timestamp, collected metrics (current, As the data points are a series of data points over time, the data points generated by IoT, Internet of Vehicles, and Operation Monitoring have some strong common characteristics: -1. Metrics are always structured data; -2. There are rarely delete/update operations on collected data; -3. No need for transactions of traditional databases -4. The ratio of reading is lower but write is higher than typical Internet applications; -5. data flow is uniform and can be predicted according to the number of devices and collection frequency; +1. metrics are always structured data; +2. there are rarely delete/update operations on collected data; +3. unlike traditional databases, transaction processing is not required; +4. the ratio of writing over reading is much higher than typical Internet applications; +5. data volume is stable and can be predicted according to the number of devices and sampling rate; 6. the user pays attention to the trend of data, not a specific value at a specific time; 7. there is always a data retention policy; 8. the data query is always executed in a given time range and a subset of space; -9. in addition to storage and query operations, various statistical and real-time calculation operations are also required; +9. in addition to storage and query operations, various statistical and real-time computing are also required; 10. data volume is huge, a system may generate over 10 billion data points in a day. By utilizing the above characteristics, TDengine designs the storage and computing engine in a special and optimized way for time-series data, resulting in massive improvements in system efficiency. ### Relational Database Model -Since time-series data is most likely to be structured data, TDengine adopts the traditional relational database model to process them with a shallow learning curve. You need to create a database, create tables with schema definitions, then insert data points and execute queries to explore the data. Standard SQL is used, instead of NoSQL’s key-value storage. +Since time-series data is most likely to be structured data, TDengine adopts the traditional relational database model to process them with a short learning curve. You need to create a database, create tables with schema definitions, then insert data points and execute queries to explore the data. SQL like syntax is used, instead of NoSQL’s key-value storage. -### One Table for One Collection Point +### One Table for One Data Collection Point -To utilize this time-series and other data features, TDengine requires the user to create a table for each collection point to store collected time-series data. For example, if there are over 10 millions smart meters, means 10 millions tables shall be created. For the table above, 4 tables shall be created for devices D1001, D1002, D1003, and D1004 to store the data collected. This design has several advantages: +To utilize this time-series and other data features, TDengine requires the user to create a table for each data collection point to store collected time-series data. For example, if there are over 10 million smart meters, it means 10 million tables shall be created. For the table above, 4 tables shall be created for devices D1001, D1002, D1003, and D1004 to store the data collected. This design has several advantages: -1. Guarantee that all data from a collection point can be saved in a continuous memory/hard disk space block by block. If queries are applied only on one point in a time range, this design will reduce the random read latency significantly, thus increase read and query speed by orders of magnitude. -2. Since the data generation process of each collection device is completely independent, means each device has its unique data source, thus writes can be carried out in a lock-free manner to greatly improve the speed. +1. Guarantee that all data from a data collection point can be saved in a continuous memory/hard disk space block by block. If queries are applied only on one data collection point in a time range, this design will reduce the random read latency significantly, thus increase read and query speed by orders of magnitude. +2. Since the data generation process of each data collection device is completely independent, and each data collection point has its unique data source, thus writes can be carried out in a lock-free manner to greatly improve the performance. 3. Write latency can be significantly reduced too as the data points generated by the same device will arrive in time order, the new data point will be simply appended to a block. -If the data of multiple devices are written into a table in the traditional way, due to the uncontrollable network delay, the timing of the data from different devices arriving at the server cannot be guaranteed, the writing operation must be protected by locks, and the data of one device cannot be guaranteed to continuously stored together. **The method of one table for each data collection point can ensure the optimal performance of insertion and query of a single data collection point to the greatest extent.** +If the data of multiple devices are traditionally written into a table, due to the uncontrollable network delay, the timing of the data from different devices arriving at the server cannot be guaranteed, the writing operation must be protected by locks, and the data of one device cannot be guaranteed to be continuously stored together. **One table for each data collection point can ensure the optimal performance of insert and query of a single data collection point to the greatest extent.** -TDengine suggests using collection point ID as the table name (like D1001 in the above table). Each point may collect one or more metrics (like the current, voltage, phase as above). Each metric has a column in the table. The data type for a column can be int, float, string and others. In addition, the first column in the table must be a timestamp. TDengine uses the time stamp as the index, and won’t build the index on any metrics stored. All data will be stored in columns. +TDengine suggests using data collection point ID as the table name (like D1001 in the above table). Each point may collect one or more metrics (like the current, voltage, phase as above). Each metric has a column in the table. The data type for a column can be int, float, string and others. In addition, the first column in the table must be a timestamp. TDengine uses the time stamp as the index, and won’t build the index on any metrics stored. All data will be stored in columns. ### STable: A Collection of Data Points in the Same Type -The method of one table for each point will bring a greatly increasing number of tables, which is difficult to manage. Moreover, applications often need to take aggregation operations between collection points, thus aggregation operations will become complicated. To support aggregation over multiple tables efficiently, the [STable(Super Table)](https://www.taosdata.com/en/documentation/super-table) concept is introduced by TDengine. +The design of one table for each data collection point will require a huge number of tables, which is difficult to manage. Moreover, applications often need to take aggregation operations between data collection points, thus aggregation operations will become complicated. To support aggregation over multiple tables efficiently, the [STable(Super Table)](https://www.taosdata.com/en/documentation/super-table) concept is introduced by TDengine. -STable is an abstract collection for a type of data point. A STable contains a set of points (tables) that have the same schema or data structure, but with different static attributes (tags). To describe a STable (a combination of data collection points of a specific type), in addition to defining the table structure of the collected metrics, it is also necessary to define the schema of its tag. The data type of tags can be int, float, string, and there can be multiple tags, which can be added, deleted, or modified afterward. If the whole system has N different types of data collection points, N STables need to be established. +STable is an abstract set for a type of data collection point. A STable contains a set of data collection points (tables) that have the same schema or data structure, but with different static attributes (tags). To describe a STable (a set of data collection points of a specific type), in addition to defining the table structure of the collected metrics, it is also necessary to define the schema of its tags. The data type of tags can be int, float, string, and there can be multiple tags, which can be added, deleted, or modified afterward. If the whole system has N different types of data collection points, N STables need to be established. In the design of TDengine, **a table is used to represent a specific data collection point, and STable is used to represent a set of data collection points of the same type**. When creating a table for a specific data collection point, the user uses the definition of STable as a template and specifies the tag value of the specific collection point (table). Compared with the traditional relational database, the table (a data collection point) has static tags, and these tags can be added, deleted, and modified afterward. **A STable contains multiple tables with the same time-series data schema but different tag values.** -When aggregating multiple data collection points with the same data type, TDEngine will first find out the tables that meet the tag filters from the STables, and then scan the time-series data of these tables to perform aggregation operation, which can greatly reduce the data sets to be scanned, thus greatly improving the performance of aggregation calculation. +When aggregating multiple data collection points with the same data type, TDengine will first find out the tables that meet the tag filter conditions from the STables, then scan the time-series data of these tables to perform aggregation operation, which can greatly reduce the data sets to be scanned, thus greatly improving the performance of data aggregation. ## Cluster and Primary Logic Unit -The design of TDengine is based on the assumption that one single hardware or software system is unreliable and that no single computer can provide sufficient computing and storage resources to process massive data. Therefore, TDengine has been designed according to a distributed and high-reliability architecture since Day One of R&D, which supports scale-out, so that hardware failure or software failure of any single or multiple servers will not affect the availability and reliability of the system. At the same time, through node virtualization and automatic load-balancing technology, TDengine can make the most efficient use of computing and storage resources in heterogeneous clusters to reduce hardware investment. +The design of TDengine is based on the assumption that one single node or software system is unreliable and that no single node can provide sufficient computing and storage resources to process massive data. Therefore, TDengine has been designed in a distributed and high-reliability architecture since day one of the development, so that hardware failure or software failure of any single or multiple servers will not affect the availability and reliability of the system. At the same time, through node virtualization and automatic load-balancing technology, TDengine can make the most efficient use of computing and storage resources in heterogeneous clusters to reduce hardware investment. ### Primary Logic Unit @@ -162,37 +162,37 @@ Logical structure diagram of TDengine distributed architecture as following: A complete TDengine system runs on one or more physical nodes. Logically, it includes data node (dnode), TDEngine application driver (taosc) and application (app). There are one or more data nodes in the system, which form a cluster. The application interacts with the TDengine cluster through taosc's API. The following is a brief introduction to each logical unit. -**Physical node (pnode)**: A pnode is a computer that runs independently and has its own computing, storage and network capabilities. It can be a physical machine, virtual machine or Docker container installed with OS. The physical node is identified by its configured FQDN (Fully Qualified Domain Name). TDengine relies entirely on FQDN for network communication. If you don't know about FQDN, please read the blog post "[All about FQDN of TDengine](https://www.taosdata.com/blog/2020/09/11/1824.html)". +**Physical node (pnode)**: A pnode is a computer that runs independently and has its own computing, storage and network capabilities. It can be a physical machine, virtual machine, or Docker container installed with OS. The physical node is identified by its configured FQDN (Fully Qualified Domain Name). TDengine relies entirely on FQDN for network communication. If you don't know about FQDN, please read the blog post "[All about FQDN of TDengine](https://www.taosdata.com/blog/2020/09/11/1824.html)". **Data node (dnode):** A dnode is a running instance of the TDengine server-side execution code taosd on a physical node. A working system must have at least one data node. A dnode contains zero to multiple logical virtual nodes (VNODE), zero or at most one logical management node (mnode). The unique identification of a dnode in the system is determined by the instance's End Point (EP). EP is a combination of FQDN (Fully Qualified Domain Name) of the physical node where the dnode is located and the network port number (Port) configured by the system. By configuring different ports, a physical node (a physical machine, virtual machine or container) can run multiple instances or have multiple data nodes. -**Virtual node (vnode)**: In order to better support data sharding, load balancing and prevent data from overheating or skewing, data nodes are virtualized into multiple virtual nodes (vnode, V2, V3, V4, etc. in the figure). Each vnode is a relatively independent work unit, which is the basic unit of time-series data storage, and has independent running threads, memory space and persistent storage path. A vnode contains a certain number of tables (data collection points). When a new table is created, the system checks whether a new vnode needs to be created. The number of vnodes that can be created on a data node depends on the hardware capacities of the physical node where the data node is located. A vnode belongs to only one DB, but a DB can have multiple vnodes. In addition to the stored time-series data, a vnode also stores the schema and tag values of the included tables. A virtual node is uniquely identified in the system by the EP of the data node and the VGroup ID to which it belongs, and is created and managed by the management node. +**Virtual node (vnode)**: To better support data sharding, load balancing and prevent data from overheating or skewing, data nodes are virtualized into multiple virtual nodes (vnode, V2, V3, V4, etc. in the figure). Each vnode is a relatively independent work unit, which is the basic unit of time-series data storage and has independent running threads, memory space and persistent storage path. A vnode contains a certain number of tables (data collection points). When a new table is created, the system checks whether a new vnode needs to be created. The number of vnodes that can be created on a data node depends on the hardware capacities of the physical node where the data node is located. A vnode belongs to only one DB, but a DB can have multiple vnodes. In addition to the stored time-series data, a vnode also stores the schema and tag values of the included tables. A virtual node is uniquely identified in the system by the EP of the data node and the VGroup ID to which it belongs and is created and managed by the management node. -**Management node (mnode)**: A virtual logical unit responsible for monitoring and maintaining the running status of all data nodes and load balancing among nodes (M in figure). At the same time, the management node is also responsible for the storage and management of metadata (including users, databases, tables, static tags, etc.), so it is also called Meta Node. Multiple (up to 5) mnodes can be configured in a TDengine cluster, and they are automatically constructed into a virtual management node group (M0, M1, M2 in the figure). The master/slave mechanism is used to manage between mnodes, and the data synchronization is carried out in a strong consistent way. Any data update operation can only be done on the master. The creation of mnode cluster is completed automatically by the system without manual intervention. There is at most one mnode on each dnode, which is uniquely identified by the EP of the data node to which it belongs. Each dnode automatically obtains the EP of the dnode where all mnodes in the whole cluster are located through internal messaging interaction. +**Management node (mnode)**: A virtual logical unit responsible for monitoring and maintaining the running status of all data nodes and load balancing among nodes (M in the figure). At the same time, the management node is also responsible for the storage and management of metadata (including users, databases, tables, static tags, etc.), so it is also called Meta Node. Multiple (up to 5) mnodes can be configured in a TDengine cluster, and they are automatically constructed into a virtual management node group (M0, M1, M2 in the figure). The master/slave mechanism is adopted for the mnode group and the data synchronization is carried out in a strongly consistent way. Any data update operation can only be executed on the master. The creation of mnode cluster is completed automatically by the system without manual intervention. There is at most one mnode on each dnode, which is uniquely identified by the EP of the data node to which it belongs. Each dnode automatically obtains the EP of the dnode where all mnodes in the whole cluster are located through internal messaging interaction. -**Virtual node group (VGroup)**: Vnodes on different data nodes can form a virtual node group to ensure the high reliability of the system. The virtual node group is managed in a master/slave structure. Write operations can only be performed on the master vnode, and the system synchronizes data to the slave vnode via replication, thus ensuring that one single replica of data is copied on multiple physical nodes. The number of virtual nodes in a vgroup equals the number of data replicas. If the number of replicas of a DB is N, the system must have at least N data nodes. The number of replicas can be specified by the parameter replica when creating DB, and the default is 1. Using the multi-replica feature of TDengine, the same high data reliability can be done without the need for expensive storage devices such as disk arrays. Virtual node group is created and managed by management node, and the management node assigns a system unique ID, aka VGroup ID. If two virtual nodes has the same vnode group ID, means that they belong to the same group and the data is backed up to each other. The number of virtual nodes in a virtual node group can be dynamically changed, allowing only one, that is, no data replication. VGroup ID is never changed. Even if a virtual node group is deleted, its ID will not be reused. +**Virtual node group (VGroup)**: Vnodes on different data nodes can form a virtual node group to ensure the high availability of the system. The virtual node group is managed in a master/slave mechanism. Write operations can only be performed on the master vnode, and then replicated to slave vnodes, thus ensuring that one single replica of data is copied on multiple physical nodes. The number of virtual nodes in a vgroup equals the number of data replicas. If the number of replicas of a DB is N, the system must have at least N data nodes. The number of replicas can be specified by the parameter `replica` when creating DB, and the default is 1. Using the multi-replication feature of TDengine, the same high data reliability can be achieved without the need for expensive storage devices such as disk arrays. Virtual node group is created and managed by the management node, and the management node assigns a system unique ID, aka VGroup ID. If two virtual nodes have the same vnode group ID, means that they belong to the same group and the data is backed up to each other. The number of virtual nodes in a virtual node group can be dynamically changed, allowing only one, that is, no data replication. VGroup ID is never changed. Even if a virtual node group is deleted, its ID will not be reused. -**TAOSC**: TAOSC is the driver provided by TDengine to applications, which is responsible for dealing with the interface interaction between application and cluster, and provides the native interface of C/C++ language, which is embedded in JDBC, C #, Python, Go, Node.js language connection libraries. Applications interact with the whole cluster through taosc instead of directly connecting to data nodes in the cluster. This module is responsible for obtaining and caching metadata; forwarding requests for insertion, query, etc. to the correct data node; when returning the results to the application, taosc also need to be responsible for the final level of aggregation, sorting, filtering and other operations. For JDBC, C/C++/C #/Python/Go/Node.js interfaces, this module runs on the physical node where the application is located. At the same time, in order to support the fully distributed RESTful interface, taosc has a running instance on each dnode of TDengine cluster. +**TAOSC**: TAOSC is the driver provided by TDengine to applications, which is responsible for dealing with the interaction between application and cluster, and provides the native interface of C/C++ language, which is embedded in JDBC, C #, Python, Go, Node.js language connection libraries. Applications interact with the whole cluster through taosc instead of directly connecting to data nodes in the cluster. This module is responsible for obtaining and caching metadata; forwarding requests for insertion, query, etc. to the correct data node; when returning the results to the application, taosc also needs to be responsible for the final level of aggregation, sorting, filtering and other operations. For JDBC, C/C++/C #/Python/Go/Node.js interfaces, this module runs on the physical node where the application is located. At the same time, in order to support the fully distributed RESTful interface, taosc has a running instance on each dnode of TDengine cluster. ### Node Communication -**Communication mode**: The communication among each data node of TDengine system, and among application driver and each data node is carried out through TCP/UDP. Considering an IoT scenario, the data writing packets are generally not large, so TDengine uses UDP in addition to TCP for transmission, because UDP is more efficient and is not limited by the number of connections. TDengine implements its own timeout, retransmission, confirmation and other mechanisms to ensure reliable transmission of UDP. For packets with a data volume of less than 15K, UDP is adopted for transmission, and TCP is automatically adopted for transmission of packets with a data volume of more than 15K or query operations. At the same time, TDengine will automatically compress/decompress the data, digital sign/authenticate the data according to the configuration and data packet. For data replication among data nodes, only TCP is used for data transmission. +**Communication mode**: The communication among each data node of TDengine system, and among the application driver and each data node is carried out through TCP/UDP. Considering an IoT scenario, the data writing packets are generally not large, so TDengine uses UDP in addition to TCP for transmission, because UDP is more efficient and is not limited by the number of connections. TDengine implements its own timeout, retransmission, confirmation and other mechanisms to ensure reliable transmission of UDP. For packets with a data volume of less than 15K, UDP is adopted for transmission, and TCP is automatically adopted for transmission of packets with a data volume of more than 15K or query operations. At the same time, TDengine will automatically compress/decompress the data, digital sign/authenticate the data according to the configuration and data packet. For data replication among data nodes, only TCP is used for data transportation. -**FQDN configuration:** A data node has one or more FQDNs, which can be specified in the system configuration file taos.cfg with the parameter "fqdn". If it is not specified, the system will automatically use the hostname of the computer as its FQDN. If the node is not configured with FQDN, you can directly set the configuration parameter fqdn of the node to its IP address. However, IP is not recommended because IP address is variable, and once it changes, the cluster will not work properly. The EP (End Point) of a data node consists of FQDN + Port. With FQDN, it is necessary to ensure the normal operation of DNS service, or configure hosts files on nodes and the nodes where applications are located. +**FQDN configuration:** A data node has one or more FQDNs, which can be specified in the system configuration file taos.cfg with the parameter "fqdn". If it is not specified, the system will automatically use the hostname of the computer as its FQDN. If the node is not configured with FQDN, you can directly set the configuration parameter fqdn of the node to its IP address. However, IP is not recommended because IP address may be changed, and once it changes, the cluster will not work properly. The EP (End Point) of a data node consists of FQDN + Port. With FQDN, it is necessary to ensure the DNS service is running, or hosts files on nodes are configured properly. -**Port configuration**: The external port of a data node is determined by the system configuration parameter serverPort in TDengine, and the port for internal communication of cluster is serverPort+5. The data replication operation among data nodes in the cluster also occupies a TCP port, which is serverPort+10. In order to support multithreading and efficient processing of UDP data, each internal and external UDP connection needs to occupy 5 consecutive ports. Therefore, the total port range of a data node will be serverPort to serverPort + 10, for a total of 11 TCP/UDP ports. When using, make sure that the firewall keeps these ports open. Each data node can be configured with a different serverPort. +**Port configuration**: The external port of a data node is determined by the system configuration parameter serverPort in TDengine, and the port for internal communication of cluster is serverPort+5. The data replication operation among data nodes in the cluster also occupies a TCP port, which is serverPort+10. In order to support multithreading and efficient processing of UDP data, each internal and external UDP connection needs to occupy 5 consecutive ports. Therefore, the total port range of a data node will be serverPort to serverPort + 10, for a total of 11 TCP/UDP ports. To run the system, make sure that the firewall keeps these ports open. Each data node can be configured with a different serverPort. -**Cluster external connection**: TDengine cluster can accommodate one single, multiple or even thousands of data nodes. The application only needs to initiate a connection to any data node in the cluster. The network parameter required for connection is the End Point (FQDN plus configured port number) of a data node. When starting the application taos through CLI, the FQDN of the data node can be specified through the option-h, and the configured port number can be specified through -p. If the port is not configured, the system configuration parameter serverPort of TDengine will be adopted. +**Cluster external connection**: TDengine cluster can accommodate one single, multiple or even thousands of data nodes. The application only needs to initiate a connection to any data node in the cluster. The network parameter required for connection is the End Point (FQDN plus configured port number) of a data node. When starting the application taos through CLI, the FQDN of the data node can be specified through the option `-h`, and the configured port number can be specified through `-p`. If the port is not configured, the system configuration parameter serverPort of TDengine will be adopted. -**Inter-cluster communication**: Data nodes connect with each other through TCP/UDP. When a data node starts, it will obtain the EP information of the dnode where the mnode is located, and then establish a connection with the mnode in the system to exchange information. There are three steps to obtain EP information of the mnode: 1. Check whether the mnodeEpList file exists, if it does not exist or cannot be opened normally to obtain EP information of the mnode, skip to the second step; 2: Check the system configuration file taos.cfg to obtain node configuration parameters firstEp and secondEp (the node specified by these two parameters can be a normal node without mnode, in this case, the node will try to redirect to the mnode node when connected). If these two configuration parameters do not exist or do not exist in taos.cfg, or are invalid, skip to the third step; 3: Set your own EP as a mnode EP and run it independently. After obtaining the mnode EP list, the data node initiates the connection. It will successfully join the working cluster after connected. If not successful, it will try the next item in the mnode EP list. If all attempts are made, but the connection still fails, sleep for a few seconds before trying again. +**Inter-cluster communication**: Data nodes connect with each other through TCP/UDP. When a data node starts, it will obtain the EP information of the dnode where the mnode is located, and then establish a connection with the mnode in the system to exchange information. There are three steps to obtain EP information of the mnode: 1. Check whether the mnodeEpList file exists, if it does not exist or cannot be opened normally to obtain EP information of the mnode, skip to the second step; 2: Check the system configuration file taos.cfg to obtain node configuration parameters firstEp and secondEp (the node specified by these two parameters can be a normal node without mnode, in this case, the node will try to redirect to the mnode node when connected). If these two configuration parameters do not exist or do not exist in taos.cfg, or are invalid, skip to the third step; 3: Set your own EP as a mnode EP and run it independently. After obtaining the mnode EP list, the data node initiates the connection. It will successfully join the working cluster after connection. If not successful, it will try the next item in the mnode EP list. If all attempts are made, but the connection still fails, sleep for a few seconds before trying again. -**The choice of MNODE**: TDengine logically has a management node, but there is no separated execution code. The server side only has a set of execution code taosd. So which data node will be the management node? This is determined automatically by the system without any manual intervention. The principle is as follows: when a data node starts, it will check its End Point and compare it with the obtained mnode EP List. If its EP exists in it, the data node shall start the mnode module and become a mnode. If your own EP is not in the mnode EP List, the mnode module will not start. During the system operation, due to load balancing, downtime and other reasons, mnode may migrate to the new dnode, while totally transparent without manual intervention. The modification of configuration parameters is the decision made by mnode itself according to resources usage. +**The choice of MNODE**: TDengine logically has a management node, but there is no separated execution code. The server-side only has a set of execution code taosd. So which data node will be the management node? This is determined automatically by the system without any manual intervention. The principle is as follows: when a data node starts, it will check its End Point and compare it with the obtained mnode EP List. If its EP exists in it, the data node shall start the mnode module and become a mnode. If your own EP is not in the mnode EP List, the mnode module will not start. During the system operation, due to load balancing, downtime and other reasons, mnode may migrate to the new dnode, while totally transparent without manual intervention. The modification of configuration parameters is the decision made by mnode itself according to resources usage. **Add new data nodes:** After the system has a data node, it has become a working system. There are two steps to add a new node into the cluster. Step1: Connect to the existing working data node using TDengine CLI, and then add the End Point of the new data node with the command "create dnode"; Step 2: In the system configuration parameter file taos.cfg of the new data node, set the firstEp and secondEp parameters to the EP of any two data nodes in the existing cluster. Please refer to the detailed user tutorial for detailed steps. In this way, the cluster will be established step by step. -**Redirection**: No matter about dnode or taosc, the connection to the mnode shall be initiated first, but the mnode is automatically created and maintained by the system, so user does not know which dnode is running the mnode. TDengine only requires a connection to any working dnode in the system. Because any running dnode maintains the currently running mnode EP List, when receiving a connecting request from the newly started dnode or taosc, if it’s not an mnode by self, it will reply the mnode EP List back. After receiving this list, taosc or the newly started dnode will try to establish the connection again. When the mnode EP List changes, each data node quickly obtains the latest list and notifies taosc through messaging interaction among nodes. +**Redirection**: No matter about dnode or taosc, the connection to the mnode shall be initiated first, but the mnode is automatically created and maintained by the system, so the user does not know which dnode is running the mnode. TDengine only requires a connection to any working dnode in the system. Because any running dnode maintains the currently running mnode EP List, when receiving a connecting request from the newly started dnode or taosc, if it’s not a mnode by self, it will reply to the mnode EP List back. After receiving this list, taosc or the newly started dnode will try to establish the connection again. When the mnode EP List changes, each data node quickly obtains the latest list and notifies taosc through messaging interaction among nodes. -### A Typical Messaging Process +### A Typical Data Writinfg Process To explain the relationship between vnode, mnode, taosc and application and their respective roles, the following is an analysis of a typical data writing process. @@ -200,62 +200,62 @@ To explain the relationship between vnode, mnode, taosc and application and thei
Picture 2 typical process of TDengine
1. Application initiates a request to insert data through JDBC, ODBC, or other APIs. -2. Cache be checked by taosc that if meta data existing for the table. If so, go straight to Step 4. If not, taosc sends a get meta-data request to mnode. +2. taosc checks if meta data existing for the table in the cache. If so, go straight to Step 4. If not, taosc sends a get meta-data request to mnode. 3. Mnode returns the meta-data of the table to taosc. Meta-data contains the schema of the table, and also the vgroup information to which the table belongs (the vnode ID and the End Point of the dnode where the table belongs. If the number of replicas is N, there will be N groups of End Points). If taosc does not receive a response from the mnode for a long time, and there are multiple mnodes, taosc will send a request to the next mnode. 4. Taosc initiates an insert request to master vnode. -5. After vnode inserts the data, it gives a reply to taosc, indicating that the insertion is successful. If taosc doesn't get a response from vnode for a long time, taosc will judge the node as offline. In this case, if there are multiple replicas of the inserted database, taosc will issue an insert request to the next vnode in vgroup. +5. After vnode inserts the data, it gives a reply to taosc, indicating that the insertion is successful. If taosc doesn't get a response from vnode for a long time, taosc will treat this node as offline. In this case, if there are multiple replicas of the inserted database, taosc will issue an insert request to the next vnode in vgroup. 6. Taosc notifies APP that writing is successful. -For Step 2 and 3, when taosc starts, it does not know the End Point of mnode, so it will directly initiate a request to the externally serving End Point of the configured cluster. If the dnode that received the request does not have an mnode configured, it will inform the mnode EP list in a reply message, so that taosc will re-issue a request to obtain meta-data to the EP of another new mnode. +For Step 2 and 3, when taosc starts, it does not know the End Point of mnode, so it will directly initiate a request to the configured serving End Point of the cluster. If the dnode that receives the request does not have a mnode configured, it will inform the mnode EP list in a reply message, so that taosc will re-issue a request to obtain meta-data to the EP of another new mnode. -For Step 4 and 5, without caching, taosc can't recognize the master in the virtual node group, so assumes that the first vnodeID is the master and send a request to it. If the requested vnode is not the master, it will reply the actual master as a new target taosc makes a request to. Once the reply of successful insertion is obtained, taosc will cache the information of master node. +For Step 4 and 5, without caching, taosc can't recognize the master in the virtual node group, so assumes that the first vnode is the master and sends a request to it. If this vnode is not the master, it will reply to the actual master as a new target where taosc shall send a request to. Once the reply of successful insertion is obtained, taosc will cache the information of master node. -The above is the process of inserting data, and the processes of querying and calculating are completely consistent. Taosc encapsulates and shields all these complicated processes, and has no perception and no special treatment for applications. +The above is the process of inserting data, and the processes of querying and computing are the same. Taosc encapsulates and hides all these complicated processes, and it is transparent to applications. -Through taosc caching mechanism, mnode needs to be accessed only when a table is operated for the first time, so mnode will not become a system bottleneck. However, because schema and vgroup may change (such as load balancing), taosc will interact with mnode regularly to automatically update the cache. +Through taosc caching mechanism, mnode needs to be accessed only when a table is accessed for the first time, so mnode will not become a system bottleneck. However, because schema and vgroup may change (such as load balancing), taosc will interact with mnode regularly to automatically update the cache. ## Storage Model and Data Partitioning/Sharding ### Storage Model -The data stored by TDengine include collected time-series data, metadata related to libraries and tables, tag data, etc. These data are specifically divided into three parts: +The data stored by TDengine include collected time-series data, metadata related to database and tables, tag data, etc. These data are specifically divided into three parts: -- Time-series data: stored in vnode and composed of data, head and last files. The amount of data is large and query amount depends on the application scenario. Out-of-order writing is allowed, but delete operation is not supported for the time being, and update operation is only allowed when update parameter is set to 1. By adopting the model with one table for each collection point, the data of a given time period is continuously stored, and the writing against one single table is a simple add operation. Multiple records can be read at one time, thus ensuring the insert and query operation of a single collection point with best performance. -- Tag data: meta files stored in vnode support four standard operations of add, delete, modify and check. The amount of data is not large. If there are N tables, there are N records, so all can be stored in memory. If there are many tag filtering operations, queries will be very frequent and TDengine supports multi-core and multi-threaded concurrent queries. As long as the computing resources are sufficient, even in face of millions of tables, the filtering results will return in milliseconds. -- Metadata: stored in mnode, including system node, user, DB, Table Schema and other information. Four standard operations of add, delete, modify and query are supported. The amount of these data are not large and can be stored in memory, moreover the query amount is not large because of the client cache. Therefore, TDengine uses centralized storage management, however, there will be no performance bottleneck. +- Time-series data: stored in vnode and composed of data, head and last files. The amount of data is large and query amount depends on the application scenario. Out-of-order writing is allowed, but delete operation is not supported for the time being, and update operation is only allowed when database update parameter is set to 1. By adopting the model with one table for each data collection point, the data of a given time period is continuously stored, and the writing against one single table is a simple appending operation. Multiple records can be read at one time, thus ensuring the insert and query operation of a single data collection point with the best performance. +- Tag data: meta files stored in vnode. Four standard operations of create, read, update and delete are supported. The amount of data is not large. If there are N tables, there are N records, so all can be stored in memory. To make tag filtering efficient, TDengine supports multi-core and multi-threaded concurrent queries. As long as the computing resources are sufficient, even in face of millions of tables, the tag filtering results will return in milliseconds. +- Metadata: stored in mnode, including system node, user, DB, Table Schema and other information. Four standard operations of create, delete, update and read are supported. The amount of these data are not large and can be stored in memory, moreover, the query amount is not large because of the client cache. Therefore, TDengine uses centralized storage management, however, there will be no performance bottleneck. Compared with the typical NoSQL storage model, TDengine stores tag data and time-series data completely separately, which has two major advantages: -- Greatly reduce the redundancy of tag data storage: general NoSQL database or time-series database adopts K-V storage, in which Key includes timestamp, device ID and various tags. Each record carries these duplicates, so wasting storage space. Moreover, if the application needs to add, modify or delete tags on historical data, it has to traverse the data and rewrite again, which is extremely expensive to operate. -- Realize extremely efficient aggregation query between multiple tables: when doing aggregation query between multiple tables, it firstly finds out the tag filtered tables, and then find out the corresponding data blocks of these tables to greatly reduce the data sets to be scanned, thus greatly improving the query efficiency. Moreover, tag data is managed and maintained in a full-memory structure, and tag data queries in tens of millions can return in milliseconds. +- Greatly reduce the redundancy of tag data storage: general NoSQL database or time-series database adopts K-V storage, in which Key includes a timestamp, a device ID and various tags. Each record carries these duplicated tags, so storage space is wasted. Moreover, if the application needs to add, modify or delete tags on historical data, it has to traverse the data and rewrite them again, which is extremely expensive to operate. +- Aggregate data efficiently between multiple tables: when aggregating data between multiple tables, it first finds out the tables which satisfy the filtering conditions, and then find out the corresponding data blocks of these tables to greatly reduce the data sets to be scanned, thus greatly improving the aggregation efficiency. Moreover, tag data is managed and maintained in a full-memory structure, and tag data queries in tens of millions can return in milliseconds. ### Data Sharding -For large-scale data management, to achieve scale-out, it is generally necessary to adopt the a Partitioning strategy as Sharding. TDengine implements data sharding via vnode, and time-series data partitioning via one data file for each time range. +For large-scale data management, to achieve scale-out, it is generally necessary to adopt the Partitioning or Sharding strategy. TDengine implements data sharding via vnode, and time-series data partitioning via one data file for each time range. -VNode (Virtual Data Node) is responsible for providing writing, query and calculation functions for collected time-series data. To facilitate load balancing, data recovery and support heterogeneous environments, TDengine splits a data node into multiple vnodes according to its computing and storage resources. The management of these vnodes is done automatically by TDengine and completely transparent to the application. +VNode (Virtual Data Node) is responsible for providing writing, query and computing functions for collected time-series data. To facilitate load balancing, data recovery and support heterogeneous environments, TDengine splits a data node into multiple vnodes according to its computing and storage resources. The management of these vnodes is done automatically by TDengine and is completely transparent to the application. For a single data collection point, regardless of the amount of data, a vnode (or vnode group, if the number of replicas is greater than 1) has enough computing resource and storage resource to process (if a 16-byte record is generated per second, the original data generated in one year will be less than 0.5 G), so TDengine stores all the data of a table (a data collection point) in one vnode instead of distributing the data to two or more dnodes. Moreover, a vnode can store data from multiple data collection points (tables), and the upper limit of the tables’ quantity for a vnode is one million. By design, all tables in a vnode belong to the same DB. On a data node, unless specially configured, the number of vnodes owned by a DB will not exceed the number of system cores. When creating a DB, the system does not allocate resources immediately. However, when creating a table, the system will check if there is an allocated vnode with free tablespace. If so, the table will be created in the vacant vnode immediately. If not, the system will create a new vnode on a dnode from the cluster according to the current workload, and then a table. If there are multiple replicas of a DB, the system does not create only one vnode, but a vgroup (virtual data node group). The system has no limit on the number of vnodes, which is just limited by the computing and storage resources of physical nodes. -The meda data of each table (including schema, tags, etc.) is also stored in vnode instead of centralized storage in mnode. In fact, this means sharding of meta data, which is convenient for efficient and parallel tag filtering operations. +The meta data of each table (including schema, tags, etc.) is also stored in vnode instead of centralized storage in mnode. In fact, this means sharding of meta data, which is good for efficient and parallel tag filtering operations. ### Data Partitioning -In addition to vnode sharding, TDengine partitions the time-series data by time range. Each data file contains only one time range of time-series data, and the length of the time range is determined by DB's configuration parameter “days”. This method of partitioning by time rang is also convenient to efficiently implement the data retention strategy. As long as the data file exceeds the specified number of days (system configuration parameter ‘keep’), it will be automatically deleted. Moreover, different time ranges can be stored in different paths and storage media, so as to facilitate the cold/hot management of big data and realize tiered-storage. +In addition to vnode sharding, TDengine partitions the time-series data by time range. Each data file contains only one time range of time-series data, and the length of the time range is determined by DB's configuration parameter `days`. This method of partitioning by time rang is also convenient to efficiently implement the data retention policy. As long as the data file exceeds the specified number of days (system configuration parameter `keep`), it will be automatically deleted. Moreover, different time ranges can be stored in different paths and storage media, so as to facilitate the tiered-storage. Cold/hot data can be stored in different storage meida to reduce the storage cost. -In general, **TDengine splits big data by vnode and time as two dimensions**, which is convenient for parallel and efficient management with scale-out. +In general, **TDengine splits big data by vnode and time range in two dimensions** to manage the data efficiently with horizontal scalability. ### Load Balancing -Each dnode regularly reports its status (including hard disk space, memory size, CPU, network, number of virtual nodes, etc.) to the mnode (virtual management node) for declaring the status of the entire cluster. Based on the overall state, when an mnode finds an overloaded dnode, it will migrate one or more vnodes to other dnodes. In the process, external services keep running and the data insertion, query and calculation operations are not affected. +Each dnode regularly reports its status (including hard disk space, memory size, CPU, network, number of virtual nodes, etc.) to the mnode (virtual management node), so mnode knows the status of the entire cluster. Based on the overall status, when the mnode finds a dnode is overloaded, it will migrate one or more vnodes to other dnodes. During the process, TDengine services keep running and the data insertion, query and computing operations are not affected. -If the mnode has not received the dnode status for a period of time, the dnode will be judged as offline. When offline lasts a certain period of time (the duration is determined by the configuration parameter ‘offlineThreshold’), the dnode will be forcibly removed from the cluster by mnode. If the number of replicas of vnodes on this dnode is greater than one, the system will automatically create new replicas on other dnodes to ensure the replica number. If there are other mnodes on this dnode and the number of mnodes replicas is greater than one, the system will automatically create new mnodes on other dnodes to ensure t the replica number. +If the mnode has not received the dnode status for a period of time, the dnode will be treated as offline. When offline lasts a certain period of time (configured by parameter `offlineThreshold`), the dnode will be forcibly removed from the cluster by mnode. If the number of replicas of vnodes on this dnode is greater than one, the system will automatically create new replicas on other dnodes to ensure the replica number. If there are other mnodes on this dnode and the number of mnodes replicas is greater than one, the system will automatically create new mnodes on other dnodes to ensure the replica number. -When new data nodes are added to the cluster, with new computing and storage are added, the system will automatically start the load balancing process. +When new data nodes are added to the cluster, with new computing and storage resources are added, the system will automatically start the load balancing process. -The load balancing process does not require any manual intervention without application restarted. It will automatically connect new nodes with completely transparence. **Note: load balancing is controlled by parameter “balance”, which determines to turn on/off automatic load balancing.** +The load balancing process does not require any manual intervention, and it is transparent to the application. **Note: load balancing is controlled by parameter “balance”, which determines to turn on/off automatic load balancing.** ## Data Writing and Replication Process @@ -267,8 +267,8 @@ Master Vnode uses a writing process as follows: Figure 3: TDengine Master writing process -1. Master vnode receives the application data insertion request, verifies, and to next step; -2. If the system configuration parameter “walLevel” is greater than 0, vnode will write the original request packet into database log file WAL. If walLevel is set to 2 and fsync is set to 0, TDengine will make WAL data written immediately to ensure that even system goes down, all data can be recovered from database log file; +1. Master vnode receives the application data insertion request, verifies, and moves to next step; +2. If the system configuration parameter `walLevel` is greater than 0, vnode will write the original request packet into database log file WAL. If walLevel is set to 2 and fsync is set to 0, TDengine will make WAL data written immediately to ensure that even system goes down, all data can be recovered from database log file; 3. If there are multiple replicas, vnode will forward data packet to slave vnodes in the same virtual node group, and the forwarded packet has a version number with data; 4. Write into memory and add the record to “skip list”; 5. Master vnode returns a confirmation message to the application, indicating a successful writing. @@ -282,30 +282,30 @@ For a slave vnode, the write process as follows:
Picture 3 TDengine Slave Writing Process
1. Slave vnode receives a data insertion request forwarded by Master vnode. -2. If the system configuration parameter “walLevel” is greater than 0, vnode will write the original request packet into database log file WAL. If walLevel is set to 2 and fsync is set to 0, TDengine will make WAL data written immediately to ensure that even system goes down, all data can be recovered from database log file; +2. If the system configuration parameter `walLevel` is greater than 0, vnode will write the original request packet into database log file WAL. If walLevel is set to 2 and fsync is set to 0, TDengine will make WAL data written immediately to ensure that even system goes down, all data can be recovered from database log file; 3. Write into memory and add the record to “skip list”; -Compared with Master vnode, slave vnode has no forwarding or reply confirmation step, means two steps less. But writing into memory is exactly the same as WAL. +Compared with Master vnode, slave vnode has no forwarding or reply confirmation step, means two steps less. But writing into memory and WAL is exactly the same. ### Remote Disaster Recovery and IDC Migration -As above Master and Slave processes discussed, TDengine adopts asynchronous replication for data synchronization. This method can greatly improve the writing performance, with not obvious impact from network delay. By configuring IDC and rack number for each physical node, it can be ensured that for a virtual node group, virtual nodes are composed of physical nodes from different IDC and different racks, thus implementing remote disaster recovery without other tools. +As above Master and Slave processes discussed, TDengine adopts asynchronous replication for data synchronization. This method can greatly improve the writing performance, with no obvious impact from network delay. By configuring IDC and rack number for each physical node, it can be ensured that for a virtual node group, virtual nodes are composed of physical nodes from different IDC and different racks, thus implementing remote disaster recovery without other tools. -On the other hand, TDengine supports dynamic modification of the replicas number. Once the number of replicas increases, the newly added virtual nodes will immediately enter the data synchronization process. After synchronization completed, added virtual nodes can provide services. In the synchronization process, master and other synchronized virtual nodes keep serving. With this feature, TDengine can realize IDC room migration without service interruption. It is only necessary to add new physical nodes to the existing IDC cluster, and then remove old physical nodes after the data synchronization is completed. +On the other hand, TDengine supports dynamic modification of the replicas number. Once the number of replicas increases, the newly added virtual nodes will immediately enter the data synchronization process. After synchronization completed, added virtual nodes can provide services. In the synchronization process, master and other synchronized virtual nodes keep serving. With this feature, TDengine can provide IDC migration without service interruption. It is only necessary to add new physical nodes to the existing IDC cluster, and then remove old physical nodes after the data synchronization is completed. -However, this asynchronous replication method has a tiny time window of written data lost. The specific scenario is as follows: +However, the asynchronous replication has a tiny time window where data can be lost. The specific scenario is as follows: -1. Master vnode has completed its 5-step operations, confirmed the success of writing to APP, and then went down; +1. Master vnode has finished its 5-step operations, confirmed the success of writing to APP, and then went down; 2. Slave vnode receives the write request, then processing fails before writing to the log in Step 2; 3. Slave vnode will become the new master, thus losing one record -In theory, as long as in asynchronous replication, there is no guarantee for no losing. However, this window is extremely small, only if mater and slave fail at the same time, and just confirm the successful write to the application before. +In theory, for asynchronous replication, there is no guarantee to prevent data loss. However, this window is extremely small, only if mater and slave fail at the same time, and just confirm the successful write to the application before. Note: Remote disaster recovery and no-downtime IDC migration are only supported by Enterprise Edition. **Hint: This function is not available yet** ### Master/slave Selection -Vnode maintains a Version number. When memory data is persisted, the version number will also be persisted. For each data update operation, whether it is collecting time-series data or metadata, this version number will be increased by one. +Vnode maintains a version number. When memory data is persisted, the version number will also be persisted. For each data update operation, whether it is time-series data or metadata, this version number will be increased by one. When a vnode starts, the roles (master, slave) are uncertain, and the data is in an unsynchronized state. It’s necessary to establish TCP connections with other nodes in the virtual node group and exchange status, including version and its own roles. Through the exchange, the system implements a master-selection process. The rules are as follows: @@ -318,7 +318,7 @@ See [TDengine 2.0 Data Replication Module Design](https://www.taosdata.com/cn/do ### Synchronous Replication -For scenarios with higher data consistency requirements, asynchronous data replication is not applicable, because there is some small probability of data loss. So, TDengine provides a synchronous replication mechanism for users. When creating a database, in addition to specifying the number of replicas, user also needs to specify a new parameter “quorum”. If quorum is greater than one, it means that every time the Master forwards a message to the replica, it needs to wait for “quorum-1” reply confirms before informing the application that data has been successfully written in slave. If “quorum-1” reply confirms are not received within a certain period of time, the master vnode will return an error to the application. +For scenarios with strong data consistency requirements, asynchronous data replication is not applicable, because there is a small probability of data loss. So, TDengine provides a synchronous replication mechanism for users. When creating a database, in addition to specifying the number of replicas, user also needs to specify a new parameter “quorum”. If quorum is greater than one, it means that every time the Master forwards a message to the replica, it needs to wait for “quorum-1” reply confirms before informing the application that data has been successfully written in slave. If “quorum-1” reply confirms are not received within a certain period of time, the master vnode will return an error to the application. With synchronous replication, performance of system will decrease and latency will increase. Because metadata needs strong consistent, the default for data synchronization between mnodes is synchronous replication. @@ -336,17 +336,17 @@ Each vnode has its own independent memory, and it is composed of multiple memory TDengine uses a data-driven method to write the data from buffer into hard disk for persistent storage. When the cached data in vnode reaches a certain volume, TDengine will also pull up the disk-writing thread to write the cached data into persistent storage in order not to block subsequent data writing. TDengine will open a new database log file when the data is written, and delete the old database log file after written successfully to avoid unlimited log growth. -To make full use of the characteristics of time-series data, TDengine splits the data stored in persistent storage by a vnode into multiple files, each file only saves data for a fixed number of days, which is determined by the system configuration parameter “days”. By so, for the given start and end date of a query, you can locate the data files to open immediately without any index, thus greatly speeding up reading operations. +To make full use of the characteristics of time-series data, TDengine splits the data stored in persistent storage by a vnode into multiple files, each file only saves data for a fixed number of days, which is determined by the system configuration parameter `days`. By so, for the given start and end date of a query, you can locate the data files to open immediately without any index, thus greatly speeding up reading operations. -For collected data, there is generally a retention period, which is determined by the system configuration parameter “keep”. Data files exceeding this set number of days will be automatically deleted by the system to free up storage space. +For time-series data, there is generally a retention policy, which is determined by the system configuration parameter `keep`. Data files exceeding this set number of days will be automatically deleted by the system to free up storage space. Given “days” and “keep” parameters, the total number of data files in a vnode is: keep/days. The total number of data files should not be too large or too small. 10 to 100 is appropriate. Based on this principle, reasonable days can be set. In the current version, parameter “keep” can be modified, but parameter “days” cannot be modified once it is set. -In each data file, the data of a table is stored by blocks. A table can have one or more data file blocks. In a file block, data is stored in columns, occupying a continuous storage space, thus greatly improving the reading speed. The size of file block is determined by the system parameter “maxRows” (the maximum number of records per block), and the default value is 4096. This value should not be too large or too small. If it is too large, the data locating in search will cost longer; if too small, the index of data block is too large, and the compression efficiency will be low with slower reading speed. +In each data file, the data of a table is stored by blocks. A table can have one or more data file blocks. In a file block, data is stored in columns, occupying a continuous storage space, thus greatly improving the reading speed. The size of file block is determined by the system parameter `maxRows` (the maximum number of records per block), and the default value is 4096. This value should not be too large or too small. If it is too large, the data locating in search will cost longer; if too small, the index of data block is too large, and the compression efficiency will be low with slower reading speed. -Each data file (with a .data postfix) has a corresponding index file (with a .head postfix). The index file has summary information of a data block for each table, recording the offset of each data block in the data file, start and end time of data and other information, so as to lead system quickly locate the data to be found. Each data file also has a corresponding last file (with a .last postfix), which is designed to prevent data block fragmentation when written in disk. If the number of written records from a table does not reach the system configuration parameter “minRows” (minimum number of records per block), it will be stored in the last file first. When write to disk next time, the newly written records will be merged with the records in last file and then written into data file. +Each data file (with a .data postfix) has a corresponding index file (with a .head postfix). The index file has summary information of a data block for each table, recording the offset of each data block in the data file, start and end time of data and other information, so as to lead system quickly locate the data to be found. Each data file also has a corresponding last file (with a .last postfix), which is designed to prevent data block fragmentation when written in disk. If the number of written records from a table does not reach the system configuration parameter `minRows` (minimum number of records per block), it will be stored in the last file first. When write to disk next time, the newly written records will be merged with the records in last file and then written into data file. -When data is written to disk, it is decided whether to compress the data according to system configuration parameter “comp”. TDengine provides three compression options: no compression, one-stage compression and two-stage compression, corresponding to comp values of 0, 1 and 2 respectively. One-stage compression is carried out according to the type of data. Compression algorithms include delta-delta coding, simple 8B method, zig-zag coding, LZ4 and other algorithms. Two-stage compression is based on one-stage compression and compressed by general compression algorithm, which has higher compression ratio. +When data is written to disk, it is decided whether to compress the data according to system configuration parameter `comp`. TDengine provides three compression options: no compression, one-stage compression and two-stage compression, corresponding to comp values of 0, 1 and 2 respectively. One-stage compression is carried out according to the type of data. Compression algorithms include delta-delta coding, simple 8B method, zig-zag coding, LZ4 and other algorithms. Two-stage compression is based on one-stage compression and compressed by general compression algorithm, which has higher compression ratio. ### Tiered Storage @@ -393,17 +393,15 @@ When client obtains query result, the worker thread in query execution queue of ### Aggregation by Time Axis, Downsampling, Interpolation -The remarkable feature that time-series data is different from ordinary data is that each record has a timestamp, so aggregating data with timestamps on the time axis is an important and unique function from common databases. From this point of view, it is similar to the window query of stream computing engine. +The remarkable feature that time-series data is different from ordinary data is that each record has a timestamp, so aggregating data with timestamps on the time axis is an important and distinct feature from common databases. From this point of view, it is similar to the window query of stream computing engine. -The keyword “interval” is introduced into TDengine to split fixed length time windows on time axis, and the data are aggregated according to time windows, and the data within window range are aggregated as needed. For example: +The keyword `interval` is introduced into TDengine to split fixed length time windows on time axis, and the data are aggregated based on time windows, and the data within window range are aggregated as needed. For example: ```mysql select count(*) from d1001 interval(1h); ``` -According to the data collected by device D1001, the number of records stored per hour is returned by a 1-hour time window. - - +For the data collected by device D1001, the number of records stored per hour is returned by a 1-hour time window. In application scenarios where query results need to be obtained continuously, if there is data missing in a given time interval, the data results in this interval will also be lost. TDengine provides a strategy to interpolate the results of timeline aggregation calculation. The results of time axis aggregation can be interpolated by using keyword Fill. For example: @@ -411,11 +409,11 @@ In application scenarios where query results need to be obtained continuously, i select count(*) from d1001 interval(1h) fill(prev); ``` -According to the data collected by device D1001, the number of records per hour is counted. If there is no data in a certain hour, statistical data of the previous hour is returned. TDengine provides forward interpolation (prev), linear interpolation (linear), NULL value populating (NULL), and specific value populating (value). +For the data collected by device D1001, the number of records per hour is counted. If there is no data in a certain hour, statistical data of the previous hour is returned. TDengine provides forward interpolation (prev), linear interpolation (linear), NULL value populating (NULL), and specific value populating (value). ### Multi-table Aggregation Query -TDengine creates a separate table for each data collection point, but in practical applications, it is often necessary to aggregate data from different collection points. In order to perform aggregation operations efficiently, TDengine introduces the concept of STable. STable is used to represent a specific type of data collection point. It is a table set containing multiple tables. The schema of each table in the set is completely consistent, but each table has its own static tag. The tags can be multiple and be added, deleted and modified at any time. Applications can aggregate or statistically operate all or a subset of tables under a STABLE by specifying tag filters, thus greatly simplifying the development of applications. The process is shown in the following figure: +TDengine creates a separate table for each data collection point, but in practical applications, it is often necessary to aggregate data from different data collection points. In order to perform aggregation operations efficiently, TDengine introduces the concept of STable. STable is used to represent a specific type of data collection point. It is a table set containing multiple tables. The schema of each table in the set is the same, but each table has its own static tag. The tags can be multiple and be added, deleted and modified at any time. Applications can aggregate or statistically operate all or a subset of tables under a STABLE by specifying tag filters, thus greatly simplifying the development of applications. The process is shown in the following figure: ![Diagram of multi-table aggregation query](page://images/architecture/multi_tables.png)
Picture 4 Diagram of multi-table aggregation query
@@ -427,8 +425,9 @@ TDengine creates a separate table for each data collection point, but in practic 5. Each vnode first finds out the set of tables within its own node that meet the tag filters from memory, then scans the stored time-series data, completes corresponding aggregation calculations, and returns result to taosc; 6. taosc finally aggregates the results returned by multiple data nodes and send them back to application. -Since TDengine stores tag data and time-series data separately in vnode, by filtering tag data in memory, the set of tables that need to participate in aggregation operation is first found, which greatly reduces the volume of data scanned and improves aggregation calculation speed. At the same time, because the data is distributed in multiple vnodes/dnodes, the aggregation calculation operation is carried out concurrently in multiple vnodes, which further improves the aggregation speed. Aggregation functions for ordinary tables and most operations are applicable to STables. The syntax is exactly the same. Please see TAOS SQL for details. +Since TDengine stores tag data and time-series data separately in vnode, by filtering tag data in memory, the set of tables that need to participate in aggregation operation is first found, which greatly reduces the volume of data scanned and improves aggregation speed. At the same time, because the data is distributed in multiple vnodes/dnodes, the aggregation operation is carried out concurrently in multiple vnodes, which further improves the aggregation speed. Aggregation functions for ordinary tables and most operations are applicable to STables. The syntax is exactly the same. Please see TAOS SQL for details. ### Precomputation In order to effectively improve the performance of query processing, based-on the unchangeable feature of IoT data, statistical information of data stored in data block is recorded in the head of data block, including max value, min value, and sum. We call it a precomputing unit. If the query processing involves all the data of a whole data block, the pre-calculated results are directly used, and no need to read the data block contents at all. Since the amount of pre-calculated data is much smaller than the actual size of data block stored on disk, for query processing with disk IO as bottleneck, the use of pre-calculated results can greatly reduce the pressure of reading IO and accelerate the query process. The precomputation mechanism is similar to the index BRIN (Block Range Index) of PostgreSQL. + diff --git a/documentation20/en/04.model/docs.md b/documentation20/en/04.model/docs.md index 1bf6c6787846b65ec9b56b65b80470cad2224756..e28dd906f3b1fae76cf6657c8f946468b92788f0 100644 --- a/documentation20/en/04.model/docs.md +++ b/documentation20/en/04.model/docs.md @@ -2,17 +2,15 @@ TDengine adopts a relational data model, so we need to build the "database" and "table". Therefore, for a specific application scenario, it is necessary to consider the design of the database, STable and ordinary table. This section does not discuss detailed syntax rules, but only concepts. -Please watch the [video tutorial](https://www.taosdata.com/blog/2020/11/11/1945.html) for data modeling. - ## Create a Database -Different types of data collection points often have different data characteristics, including frequency of data collecting, length of data retention time, number of replicas, size of data blocks, whether to update data or not, and so on. To ensure TDengine working with great efficiency in various scenarios, TDengine suggests creating tables with different data characteristics in different databases, because each database can be configured with different storage strategies. When creating a database, in addition to SQL standard options, the application can also specify a variety of parameters such as retention duration, number of replicas, number of memory blocks, time accuracy, max and min number of records in a file block, whether it is compressed or not, and number of days a data file will be overwritten. For example: +Different types of data collection points often have different data characteristics, including data sampling rate, length of data retention time, number of replicas, size of data blocks, whether to update data or not, and so on. To ensure TDengine working with great efficiency in various scenarios, TDengine suggests creating tables with different data characteristics in different databases, because each database can be configured with different storage strategies. When creating a database, in addition to SQL standard options, the application can also specify a variety of parameters such as retention duration, number of replicas, number of memory blocks, time resolution, max and min number of records in a file block, whether it is compressed or not, and number of days covered by a data file. For example: ```mysql CREATE DATABASE power KEEP 365 DAYS 10 BLOCKS 6 UPDATE 1; ``` -The above statement will create a database named “power”. The data of this database will be kept for 365 days (it will be automatically deleted 365 days later), one data file created per 10 days, and the number of memory blocks is 4 for data updating. For detailed syntax and parameters, please refer to [Data Management section of TAOS SQL](https://www.taosdata.com/en/documentation/taos-sql#management). +The above statement will create a database named “power”. The data of this database will be kept for 365 days (data will be automatically deleted 365 days later), one data file will be created per 10 days, the number of memory blocks is 4, and data updating is allowed. For detailed syntax and parameters, please refer to [Data Management section of TAOS SQL](https://www.taosdata.com/en/documentation/taos-sql#management). After the database created, please use SQL command USE to switch to the new database, for example: @@ -20,7 +18,7 @@ After the database created, please use SQL command USE to switch to the new data USE power; ``` -Replace the database operating in the current connection with “power”, otherwise, before operating on a specific table, you need to use "database name. table name" to specify the name of database to use. +Specify the database operating in the current connection with “power”, otherwise, before operating on a specific table, you need to use "database-name.table-name" to specify the name of database to use. **Note:** @@ -37,11 +35,11 @@ CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAG **Note:** The STABLE keyword in this instruction needs to be written as TABLE in versions before 2.0.15. -Just like creating an ordinary table, you need to provide the table name (‘meters’ in the example) and the table structure Schema, that is, the definition of data columns. The first column must be a timestamp (‘ts’ in the example), the other columns are the physical metrics collected (current, volume, phase in the example), and the data types can be int, float, string, etc. In addition, you need to provide the schema of the tag (location, groupId in the example), and the data types of the tag can be int, float, string and so on. Static attributes of collection points can often be used as tags, such as geographic location of collection points, device model, device group ID, administrator ID, etc. The schema of the tag can be added, deleted and modified afterwards. Please refer to the [STable Management section of TAOS SQL](https://www.taosdata.com/cn/documentation/taos-sql#super-table) for specific definitions and details. +Just like creating an ordinary table, you need to provide the table name (‘meters’ in the example) and the table structure Schema, that is, the definition of data columns. The first column must be a timestamp (‘ts’ in the example), the other columns are the physical metrics collected (current, volume, phase in the example), and the data types can be int, float, string, etc. In addition, you need to provide the schema of the tag (location, groupId in the example), and the data types of the tag can be int, float, string and so on. Static attributes of data collection points can often be used as tags, such as geographic location of collection points, device model, device group ID, administrator ID, etc. The schema of the tags can be added, deleted and modified afterwards. Please refer to the [STable Management section of TAOS SQL](https://www.taosdata.com/cn/documentation/taos-sql#super-table) for specific definitions and details. -Each type of data collection point needs an established STable, so an IoT system often has multiple STables. For the power grid, we need to build a STable for smart meters, transformers, buses, switches, etc. For IoT, a device may have multiple data collection points (for example, a fan for wind-driven generator, some collection points capture parameters such as current and voltage, and some capture environmental parameters such as temperature, humidity and wind direction). In this case, multiple STables need to be established for corresponding types of devices. All collected physical metrics contained in one and the same STable must be collected at the same time (with a consistent timestamp). +A STable must be created for each type of data collection point, so an IoT system often has multiple STables. For the power grid, we need to build a STable for smart meters, a STable for transformers, a STable for buses, a STable for switches, etc. For IoT, a device may have multiple data collection points (for example, a fan for wind-driven generator, one data collection point captures metrics such as current and voltage, and one data collection point captures environmental parameters such as temperature, humidity and wind direction). In this case, multiple STables need to be established for corresponding types of devices. All metrics contained in a STable must be collected at the same time (with the same timestamp). -A STable allows up to 1024 columns. If the number of physical metrics collected at a collection point exceeds 1024, multiple STables need to be built to process them. A system can have multiple DBs, and a DB can have one or more STables. +A STable allows up to 1024 columns. If the number of metrics collected at a data collection point exceeds 1024, multiple STables need to be built to process them. A system can have multiple DBs, and a DB can have one or more STables. ## Create a Table @@ -53,22 +51,23 @@ CREATE TABLE d1001 USING meters TAGS ("Beijing.Chaoyang", 2); Where d1001 is the table name, meters is the name of the STable, followed by the specific tag value of tag Location as "Beijing.Chaoyang", and the specific tag value of tag groupId 2. Although the tag value needs to be specified when creating the table, it can be modified afterwards. Please refer to the [Table Management section of TAOS SQL](https://www.taosdata.com/en/documentation/taos-sql#table) for details. -**Note: ** At present, TDengine does not technically restrict the use of a STable of a database (dbA) as a template to create a sub-table of another database (dbB). This usage will be prohibited later, and it is not recommended to use this method to create a table. +**Note: ** At present, TDengine does not technically restrict the use of a STable of a database (dbA) as a template to create a sub-table of another database (dbB). This usage will be prohibited later, and it is not recommended to use this way to create a table. TDengine suggests to use the globally unique ID of data collection point as a table name (such as device serial number). However, in some scenarios, there is no unique ID, and multiple IDs can be combined into a unique ID. It is not recommended to use a unique ID as tag value. -**Automatic table creating** : In some special scenarios, user is not sure whether the table of a certain data collection point exists when writing data. In this case, the non-existent table can be created by using automatic table building syntax when writing data. If the table already exists, no new table will be created. For example: +**Automatic table creating** : In some special scenarios, user is not sure whether the table of a certain data collection point exists when writing data. In this case, the non-existent table can be created by using automatic table creating syntax when writing data. If the table already exists, no new table will be created. For example: ```mysql INSERT INTO d1001 USING METERS TAGS ("Beijng.Chaoyang", 2) VALUES (now, 10.2, 219, 0.32); ``` -The SQL statement above inserts records (now, 10.2, 219, 0.32) into table d1001. If table d1001 has not been created yet, the STable meters is used as the template to automatically create it, and the tag value "Beijing.Chaoyang", 2 is marked at the same time. +The SQL statement above inserts records (now, 10.2, 219, 0.32) into table d1001. If table d1001 has not been created yet, the STable meters is used as the template to create it automatically, and the tag value "Beijing.Chaoyang", 2 is set at the same time. For detailed syntax of automatic table building, please refer to the "[Automatic Table Creation When Inserting Records](https://www.taosdata.com/en/documentation/taos-sql#auto_create_table)" section. ## Multi-column Model vs Single-column Model -TDengine supports multi-column model. As long as physical metrics are collected simultaneously by a data collection point (with a consistent timestamp), these metrics can be placed in a STable as different columns. However, there is also an extreme design, a single-column model, in which each collected physical metric is set up separately, so each type of physical metrics is set up separately with a STable. For example, create 3 Stables, one each for current, voltage and phase. +TDengine supports multi-column model. As long as metrics are collected simultaneously by a data collection point (with the same timestamp), these metrics can be placed in a STable as different columns. However, there is also an extreme design, a single-column model, in which a STable is created for each metric. For smart meter example, we need to create 3 Stables, one for current, one for voltage and one for phase. + +TDengine recommends using multi-column model as much as possible because of higher insertion and storage efficiency. However, for some scenarios, types of collected metrics often change. In this case, if multi-column model is adopted, the schema definition of STable needs to be modified frequently and the application becomes complicated. To avoid that, single-column model is recommended. -TDengine recommends using multi-column model as much as possible because of higher insertion and storage efficiency. However, for some scenarios, types of collected metrics often change. In this case, if multi-column model is adopted, the structure definition of STable needs to be frequently modified so make the application complicated. To avoid that, single-column model is recommended. diff --git a/documentation20/en/05.insert/docs.md b/documentation20/en/05.insert/docs.md index 88746ea60867b37e5956075f88c48ebd8276dfaa..7e99cf09dbae6a09429c83810f07db6ef4dafbe7 100644 --- a/documentation20/en/05.insert/docs.md +++ b/documentation20/en/05.insert/docs.md @@ -1,22 +1,22 @@ # Efficient Data Writing -TDengine supports multiple interfaces to write data, including SQL, Prometheus, Telegraf, EMQ MQTT Broker, HiveMQ Broker, CSV file, etc. Kafka, OPC and other interfaces will be provided in the future. Data can be inserted in a single piece or in batches, data from one or multiple data collection points can be inserted at the same time. TDengine supports multi-thread insertion, nonsequential data insertion, and also historical data insertion. +TDengine supports multiple ways to write data, including SQL, Prometheus, Telegraf, EMQ MQTT Broker, HiveMQ Broker, CSV file, etc. Kafka, OPC and other interfaces will be provided in the future. Data can be inserted in one single record or in batches, data from one or multiple data collection points can be inserted at the same time. TDengine supports multi-thread insertion, out-of-order data insertion, and also historical data insertion. -## SQL Writing +## Data Writing via SQL -Applications insert data by executing SQL insert statements through C/C++, JDBC, GO, or Python Connector, and users can manually enter SQL insert statements to insert data through TAOS Shell. For example, the following insert writes a record to table d1001: +Applications insert data by executing SQL insert statements through C/C++, JDBC, GO, C#, or Python Connector, and users can manually enter SQL insert statements to insert data through TAOS Shell. For example, the following insert writes a record to table d1001: ```mysql INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31); ``` -TDengine supports writing multiple records at a time. For example, the following command writes two records to table d1001: +TDengine supports writing multiple records in a single statement. For example, the following command writes two records to table d1001: ```mysql INSERT INTO d1001 VALUES (1538548684000, 10.2, 220, 0.23) (1538548696650, 10.3, 218, 0.25); ``` -TDengine also supports writing data to multiple tables at a time. For example, the following command writes two records to d1001 and one record to d1002: +TDengine also supports writing data to multiple tables in a single statement. For example, the following command writes two records to d1001 and one record to d1002: ```mysql INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6, 218, 0.33) d1002 VALUES (1538548696800, 12.3, 221, 0.31); @@ -26,22 +26,22 @@ For the SQL INSERT Grammar, please refer to [Taos SQL insert](https://www.taosd **Tips:** -- To improve writing efficiency, batch writing is required. The more records written in a batch, the higher the insertion efficiency. However, a record cannot exceed 16K, and the total length of an SQL statement cannot exceed 64K (it can be configured by parameter maxSQLLength, and the maximum can be configured to 1M). -- TDengine supports multi-thread parallel writing. To further improve writing speed, a client needs to open more than 20 threads to write parallelly. However, after the number of threads reaches a certain threshold, it cannot be increased or even become decreased, because too much frequent thread switching brings extra overhead. -- For a same table, if the timestamp of a newly inserted record already exists, (no database was created using UPDATE 1) the new record will be discarded as default, that is, the timestamp must be unique in a table. If an application automatically generates records, it is very likely that the generated timestamps will be the same, so the number of records successfully inserted will be smaller than the number of records the application try to insert. If you use UPDATE 1 option when creating a database, inserting a new record with the same timestamp will overwrite the original record. +- To improve writing efficiency, batch writing is required. The more records written in a batch, the higher the insertion efficiency. However, a record size cannot exceed 16K, and the total length of an SQL statement cannot exceed 64K (it can be configured by parameter maxSQLLength, and the maximum can be configured to 1M). +- TDengine supports multi-thread parallel writing. To further improve writing speed, a client needs to open more than 20 threads to write parallelly. However, after the number of threads reaches a certain threshold, it cannot be increased or even become decreased, because too much thread switching brings extra overhead. +- For the same table, if the timestamp of a newly inserted record already exists, the new record will be discarded as default (database option update = 0), that is, the timestamp must be unique in a table. If an application automatically generates records, it is very likely that the generated timestamps will be the same, so the number of records successfully inserted will be smaller than the number of records the application try to insert. If you use UPDATE 1 option when creating a database, inserting a new record with the same timestamp will overwrite the original record. - The timestamp of written data must be greater than the current time minus the time of configuration parameter keep. If keep is configured for 3650 days, data older than 3650 days cannot be written. The timestamp for writing data cannot be greater than the current time plus configuration parameter days. If days is configured to 2, data 2 days later than the current time cannot be written. -## Direct Writing of Prometheus +## Data Writing via Prometheus As a graduate project of Cloud Native Computing Foundation, [Prometheus](https://www.prometheus.io/) is widely used in the field of performance monitoring and K8S performance monitoring. TDengine provides a simple tool [Bailongma](https://github.com/taosdata/Bailongma), which only needs to be simply configured in Prometheus without any code, and can directly write the data collected by Prometheus into TDengine, then automatically create databases and related table entries in TDengine according to rules. Blog post [Use Docker Container to Quickly Build a Devops Monitoring Demo](https://www.taosdata.com/blog/2020/02/03/1189.html), which is an example of using bailongma to write Prometheus and Telegraf data into TDengine. ### Compile blm_prometheus From Source -Users need to download the source code of [Bailongma](https://github.com/taosdata/Bailongma) from github, then compile and generate an executable file using Golang language compiler. Before you start compiling, you need to complete following prepares: +Users need to download the source code of [Bailongma](https://github.com/taosdata/Bailongma) from github, then compile and generate an executable file using Golang language compiler. Before you start compiling, you need to prepare: - A server running Linux OS - Golang version 1.10 and higher installed -- An appropriated TDengine version. Because the client dynamic link library of TDengine is used, it is necessary to install the same version of TDengine as the server-side; for example, if the server version is TDengine 2.0. 0, ensure install the same version on the linux server where bailongma is located (can be on the same server as TDengine, or on a different server) +- Since the client dynamic link library of TDengine is used, it is necessary to install the same version of TDengine as the server-side. For example, if the server version is TDengine 2.0. 0, ensure install the same version on the linux server where bailongma is located (can be on the same server as TDengine, or on a different server) Bailongma project has a folder, blm_prometheus, which holds the prometheus writing API. The compiling process is as follows: @@ -134,7 +134,7 @@ The format of generated data by Prometheus is as follows: } ``` -Where apiserver_request_latencies_bucket is the name of the time-series data collected by prometheus, and the tag of the time-series data is in the following {}. blm_prometheus automatically creates a STable in TDengine with the name of the time series data, and converts the tag in {} into the tag value of TDengine, with Timestamp as the timestamp and value as the value of the time-series data. Therefore, in the client of TDEngine, you can check whether this data was successfully written through the following instruction. +Where apiserver_request_latencies_bucket is the name of the time-series data collected by prometheus, and the tag of the time-series data is in the following {}. blm_prometheus automatically creates a STable in TDengine with the name of the time series data, and converts the tag in {} into the tag value of TDengine, with Timestamp as the timestamp and value as the value of the time-series data. Therefore, in the client of TDengine, you can check whether this data was successfully written through the following instruction. ```mysql use prometheus; @@ -144,7 +144,7 @@ select * from apiserver_request_latencies_bucket; -## Direct Writing of Telegraf +## Data Writing via Telegraf [Telegraf](https://www.influxdata.com/time-series-platform/telegraf/) is a popular open source tool for IT operation data collection. TDengine provides a simple tool [Bailongma](https://github.com/taosdata/Bailongma), which only needs to be simply configured in Telegraf without any code, and can directly write the data collected by Telegraf into TDengine, then automatically create databases and related table entries in TDengine according to rules. Blog post [Use Docker Container to Quickly Build a Devops Monitoring Demo](https://www.taosdata.com/blog/2020/02/03/1189.html), which is an example of using bailongma to write Prometheus and Telegraf data into TDengine. @@ -271,12 +271,12 @@ select * from cpu; MQTT is a popular data transmission protocol in the IoT. TDengine can easily access the data received by MQTT Broker and write it to TDengine. -## Direct Writing of EMQ Broker +## Data Writing via EMQ Broker [EMQ](https://github.com/emqx/emqx) is an open source MQTT Broker software, with no need of coding, only to use "rules" in EMQ Dashboard for simple configuration, and MQTT data can be directly written into TDengine. EMQ X supports storing data to the TDengine by sending it to a Web service, and also provides a native TDengine driver on Enterprise Edition for direct data store. Please refer to [EMQ official documents](https://docs.emqx.io/broker/latest/cn/rule/rule-example.html#%E4%BF%9D%E5%AD%98%E6%95%B0%E6%8D%AE%E5%88%B0-tdengine) for more details. -## Direct Writing of HiveMQ Broker +## Data Writing via HiveMQ Broker -[HiveMQ](https://www.hivemq.com/) is an MQTT agent that provides Free Personal and Enterprise Edition versions. It is mainly used for enterprises, emerging machine-to-machine(M2M) communication and internal transmission to meet scalability, easy management and security features. HiveMQ provides an open source plug-in development kit. You can store data to TDengine via HiveMQ extension-TDengine. Refer to the [HiveMQ extension-TDengine documentation](https://github.com/huskar-t/hivemq-tdengine-extension/blob/b62a26ecc164a310104df57691691b237e091c89/README.md) for more details. +[HiveMQ](https://www.hivemq.com/) is an MQTT agent that provides Free Personal and Enterprise Edition versions. It is mainly used for enterprises, emerging machine-to-machine(M2M) communication and internal transmission to meet scalability, easy management and security features. HiveMQ provides an open source plug-in development kit. You can store data to TDengine via HiveMQ extension-TDengine. Refer to the [HiveMQ extension-TDengine documentation](https://github.com/huskar-t/hivemq-tdengine-extension/blob/b62a26ecc164a310104df57691691b237e091c89/README.md) for more details. \ No newline at end of file diff --git a/documentation20/en/06.queries/docs.md b/documentation20/en/06.queries/docs.md index c4f1359820a28b390e84be93e077fecb1d5ede0e..7688a941f0fb5b685f592833322906e4c4760b79 100644 --- a/documentation20/en/06.queries/docs.md +++ b/documentation20/en/06.queries/docs.md @@ -28,7 +28,7 @@ For specific query syntax, please see the [Data Query section of TAOS SQL](https ## Multi-table Aggregation Query -In an IoT scenario, there are often multiple data collection points in a same type. TDengine uses the concept of STable to describe a certain type of data collection point, and an ordinary table to describe a specific data collection point. At the same time, TDengine uses tags to describe the statical attributes of data collection points. A given data collection point has a specific tag value. By specifying the filters of tags, TDengine provides an efficient method to aggregate and query the sub-tables of STables (data collection points of a certain type). Aggregation functions and most operations on ordinary tables are applicable to STables, and the syntax is exactly the same. +In an IoT scenario, there are often multiple data collection points in a same type. TDengine uses the concept of STable to describe a certain type of data collection point, and an ordinary table to describe a specific data collection point. At the same time, TDengine uses tags to describe the static attributes of data collection points. A given data collection point has a specific tag value. By specifying the filters of tags, TDengine provides an efficient method to aggregate and query the sub-tables of STables (data collection points of a certain type). Aggregation functions and most operations on ordinary tables are applicable to STables, and the syntax is exactly the same. **Example 1**: In TAOS Shell, look up the average voltages collected by all smart meters in Beijing and group them by location @@ -55,7 +55,7 @@ TDengine only allows aggregation queries between tables belonging to a same STab ## Down Sampling Query, Interpolation -In a scenario of IoT, it is often necessary to aggregate the collected data by intervals through down sampling. TDengine provides a simple keyword interval, which makes query operations according to time windows extremely simple. For example, the current values collected by smart meter d1001 are summed every 10 seconds. +In a scenario of IoT, it is often necessary to aggregate the collected data by intervals through down sampling. TDengine provides a simple keyword `interval`, which makes query operations according to time windows extremely simple. For example, the current values collected by smart meter d1001 are summed every 10 seconds. ```mysql taos> SELECT sum(current) FROM d1001 INTERVAL(10s); @@ -94,6 +94,6 @@ taos> SELECT SUM(current) FROM meters INTERVAL(1s, 500a); Query OK, 5 row(s) in set (0.001521s) ``` -In a scenario of IoT, it is difficult to synchronize the time stamp of collected data at each point, but many analysis algorithms (such as FFT) need to align the collected data strictly at equal intervals of time. In many systems, it’s required to write their own programs to process, but the down sampling operation of TDengine can be easily solved. If there is no collected data in an interval, TDengine also provides interpolation calculation function. +In IoT scenario, it is difficult to synchronize the time stamp of collected data at each point, but many analysis algorithms (such as FFT) need to align the collected data strictly at equal intervals of time. In many systems, it’s required to write their own programs to process, but the down sampling operation of TDengine can be used to solve the problem easily. If there is no collected data in an interval, TDengine also provides interpolation calculation function. For details of syntax rules, please refer to the [Time-dimension Aggregation section of TAOS SQL](https://www.taosdata.com/en/documentation/taos-sql#aggregation). \ No newline at end of file diff --git a/documentation20/en/07.advanced-features/docs.md b/documentation20/en/07.advanced-features/docs.md index d9103c70216772a9ce24f67c719b379b106a9055..38c70862b637daf5840606535971e412d938b9e8 100644 --- a/documentation20/en/07.advanced-features/docs.md +++ b/documentation20/en/07.advanced-features/docs.md @@ -9,8 +9,8 @@ Continuous query of TDengine adopts time-driven mode, which can be defined direc The continuous query provided by TDengine differs from the time window calculation in ordinary stream computing in the following ways: - Unlike the real-time feedback calculated results of stream computing, continuous query only starts calculation after the time window is closed. For example, if the time period is 1 day, the results of that day will only be generated after 23:59:59. -- If a history record is written to the time interval that has been calculated, the continuous query will not recalculate and will not push the results to the user again. For the mode of writing back to TDengine, the existing calculated results will not be updated. -- Using the mode of continuous query pushing results, the server does not cache the client's calculation status, nor does it provide Exactly-Once semantic guarantee. If the user's application side crashed, the continuous query pulled up again would only recalculate the latest complete time window from the time pulled up again. If writeback mode is used, TDengine can ensure the validity and continuity of data writeback. +- If a history record is written to the time interval that has been calculated, the continuous query will not re-calculate and will not push the new results to the user again. +- TDengine server does not cache or save the client's status, nor does it provide Exactly-Once semantic guarantee. If the application crashes, the continuous query will be pull up again and starting time must be provided by the application. ### How to use continuous query @@ -29,7 +29,7 @@ We already know that the average voltage of these meters can be counted with one select avg(voltage) from meters interval(1m) sliding(30s); ``` -Every time this statement is executed, all data will be recalculated. If you need to execute every 30 seconds to incrementally calculate the data of the latest minute, you can improve the above statement as following, using a different `startTime` each time and executing it regularly: +Every time this statement is executed, all data will be re-calculated. If you need to execute every 30 seconds to incrementally calculate the data of the latest minute, you can improve the above statement as following, using a different `startTime` each time and executing it regularly: ```sql select avg(voltage) from meters where ts > {startTime} interval(1m) sliding(30s); @@ -65,7 +65,7 @@ It should be noted that now in the above example refers to the time when continu ### Manage the Continuous Query -Users can view all continuous queries running in the system through the show streams command in the console, and can kill the corresponding continuous queries through the kill stream command. Subsequent versions will provide more finer-grained and convenient continuous query management commands. +Users can view all continuous queries running in the system through the `show streams` command in the console, and can kill the corresponding continuous queries through the `kill stream` command. Subsequent versions will provide more finer-grained and convenient continuous query management commands. ## Publisher/Subscriber @@ -101,7 +101,7 @@ Another method is to query the STable. In this way, no matter how many meters th select * from meters where ts > {last_timestamp} and current > 10; ``` -However, how to choose `last_timestamp` has become a new problem. Because, on the one hand, the time of data generation (the data timestamp) and the time of data storage are generally not the same, and sometimes the deviation is still very large; On the other hand, the time when the data of different meters arrive at TDengine will also vary. Therefore, if we use the timestamp of the data from the slowest meter as `last_timestamp` in the query, we may repeatedly read the data of other meters; If the timestamp of the fastest meter is used, the data of other meters may be missed. +However, how to choose `last_timestamp` has become a new problem. Because, on the one hand, the time of data generation (the data timestamp) and the time of data writing are generally not the same, and sometimes the deviation is still very large; On the other hand, the time when the data of different meters arrive at TDengine will also vary. Therefore, if we use the timestamp of the data from the slowest meter as `last_timestamp` in the query, we may repeatedly read the data of other meters; If the timestamp of the fastest meter is used, the data of other meters may be missed. The subscription function of TDengine provides a thorough solution to the above problem. @@ -357,4 +357,4 @@ This SQL statement will obtain the last recorded voltage value of all smart mete In scenarios of TDengine, alarm monitoring is a common requirement. Conceptually, it requires the program to filter out data that meet certain conditions from the data of the latest period of time, and calculate a result according to a defined formula based on these data. When the result meets certain conditions and lasts for a certain period of time, it will notify the user in some form. -In order to meet the needs of users for alarm monitoring, TDengine provides this function in the form of an independent module. For its installation and use, please refer to the blog [How to Use TDengine for Alarm Monitoring](https://www.taosdata.com/blog/2020/04/14/1438.html). +In order to meet the needs of users for alarm monitoring, TDengine provides this function in the form of an independent module. For its installation and use, please refer to the blog [How to Use TDengine for Alarm Monitoring](https://www.taosdata.com/blog/2020/04/14/1438.html). \ No newline at end of file diff --git a/documentation20/en/08.connector/01.java/docs.md b/documentation20/en/08.connector/01.java/docs.md new file mode 100644 index 0000000000000000000000000000000000000000..bd5df5a4952d5b56badde4eb3d6c88051cfa7b51 --- /dev/null +++ b/documentation20/en/08.connector/01.java/docs.md @@ -0,0 +1,525 @@ +# Java connector + +## Introduction + +The taos-jdbcdriver is implemented in two forms: JDBC-JNI and JDBC-RESTful (supported from taos-jdbcdriver-2.0.18). JDBC-JNI is implemented by calling the local methods of libtaos.so (or taos.dll) on the client, while JDBC-RESTful encapsulates the RESTful interface implementation internally. + +![tdengine-connector](page://images/tdengine-jdbc-connector.png) + +The figure above shows the three ways Java applications can access the TDengine: + +* JDBC-JNI: The Java application uses JDBC-JNI's API on physical node1 (pnode1) and directly calls the client API (libtaos.so or taos.dll) to send write or query requests to the taosd instance on physical node2 (pnode2). +* RESTful: The Java application sends the SQL to the RESTful connector on physical node2 (pnode2), which then calls the client API (libtaos.so). +* JDBC-RESTful: The Java application uses the JDBC-restful API to encapsulate SQL into a RESTful request and send it to the RESTful connector of physical node 2. + +In terms of implementation, the JDBC driver of TDengine is as consistent as possible with the behavior of the relational database driver. However, due to the differences between TDengine and relational database in the object and technical characteristics of services, there are some differences between taos-jdbcdriver and traditional relational database JDBC driver. The following points should be watched: + +* deleting a record is not supported in TDengine. +* transaction is not supported in TDengine. + +### Difference between JDBC-JNI and JDBC-restful + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
DifferenceJDBC-JNIJDBC-RESTful
Supported OSlinux、windowsall platform
Whether to install the Clientneeddo not need
Whether to upgrade the client after the server is upgradedneeddo not need
Write performanceJDBC-RESTful is 50% to 90% of JDBC-JNI
Read performanceJDBC-RESTful is no different from JDBC-JNI
+ +**Note**: RESTful interfaces are stateless. Therefore, when using JDBC-restful, you should specify the database name in SQL before all table names and super table names, for example: + +```sql +INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('beijing') VALUES(now, 24.6); +``` + +## JDBC driver version and supported TDengine and JDK versions + +| taos-jdbcdriver | TDengine | JDK | +| -------------------- | ----------------- | -------- | +| 2.0.33 - 2.0.34 | 2.0.3.0 and above | 1.8.x | +| 2.0.31 - 2.0.32 | 2.1.3.0 and above | 1.8.x | +| 2.0.22 - 2.0.30 | 2.0.18.0 - 2.1.2.x | 1.8.x | +| 2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.x | 1.8.x | +| 2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.x | 1.8.x | +| 1.0.3 | 1.6.1.x and above | 1.8.x | +| 1.0.2 | 1.6.1.x and above | 1.8.x | +| 1.0.1 | 1.6.1.x and above | 1.8.x | + +## DataType in TDengine and Java connector + +The TDengine supports the following data types and Java data types: + +| TDengine DataType | Java DataType | +| ----------------- | ------------------ | +| TIMESTAMP | java.sql.Timestamp | +| INT | java.lang.Integer | +| BIGINT | java.lang.Long | +| FLOAT | java.lang.Float | +| DOUBLE | java.lang.Double | +| SMALLINT | java.lang.Short | +| TINYINT | java.lang.Byte | +| BOOL | java.lang.Boolean | +| BINARY | byte[] | +| NCHAR | java.lang.String | + +## Install Java connector + +### Runtime Requirements + +To run TDengine's Java connector, the following requirements shall be met: + +1. A Linux or Windows System + +2. Java Runtime Environment 1.8 or later + +3. TDengine client (required for JDBC-JNI, not required for JDBC-restful) + +**Note**: + +* After the TDengine client is successfully installed on Linux, the libtaos.so file is automatically copied to /usr/lib/libtaos.so, which is included in the Linux automatic scan path and does not need to be specified separately. +* After the TDengine client is installed on Windows, the taos.dll file that the driver package depends on is automatically copied to the default search path C:/Windows/System32. You do not need to specify it separately. + +### Obtain JDBC driver by maven + +To Java delevopers, TDengine provides `taos-jdbcdriver` according to the JDBC(3.0) API. Users can find and download it through [Sonatype Repository](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver). Add the following dependencies in pom.xml for your maven projects. + +```xml + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.34 + + +``` + +### Obtain JDBC driver by compiling source code + +You can download the TDengine source code and compile the latest version of the JDBC Connector. + + ```shell + git clone https://github.com/taosdata/TDengine.git + cd TDengine/src/connector/jdbc + mvn clean package -Dmaven.test.skip=true + ``` + +a taos-jdbcdriver-2.0.xx-dist.jar will be released in the target directory. + +## Usage of java connector + +### Establishing a Connection + +#### Establishing a connection with URL + +Establish the connection by specifying the URL, as shown below: + +```java +String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata"; +Connection conn = DriverManager.getConnection(jdbcUrl); +``` + +In the example above, the JDBC-RESTful driver is used to establish a connection to the hostname of 'taosdemo.com', port of 6041, and database name of 'test'. This URL specifies the user name as 'root' and the password as 'taosdata'. + +The JDBC-RESTful does not depend on the local function library. Compared with JDBC-JNI, only the following is required: + +* DriverClass designated as "com.taosdata.jdbc.rs.RestfulDriver" +* JdbcUrl starts with "JDBC:TAOS-RS://" +* Use port 6041 as the connection port + +For better write and query performance, Java applications can use the JDBC-JNI driver, as shown below: + +```java +String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata"; +Connection conn = DriverManager.getConnection(jdbcUrl); +``` + +In the example above, The JDBC-JNI driver is used to establish a connection to the hostname of 'taosdemo.com', port 6030 (TDengine's default port), and database name of 'test'. This URL specifies the user name as 'root' and the password as 'taosdata'. + + + +The format of JDBC URL is: + +```url +jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}] +``` + +The configuration parameters in the URL are as follows: + +* user: user name for logging in to the TDengine. The default value is 'root'. +* password: the user login password. The default value is 'taosdata'. +* cfgdir: directory of the client configuration file. It is valid only for JDBC-JNI. The default value is `/etc/taos` on Linux and `C:/TDengine/cfg` on Windows. +* charset: character set used by the client. The default value is the system character set. +* locale: client locale. The default value is the current system locale. +* timezone: timezone used by the client. The default value is the current timezone of the system. +* batchfetch: only valid for JDBC-JNI. True if batch ResultSet fetching is enabled; false if row-by-row ResultSet fetching is enabled. Default value is flase. +* timestampFormat: only valid for JDBC-RESTful. 'TIMESTAMP' if you want to get a long value in a ResultSet; 'UTC' if you want to get a string in UTC date-time format in a ResultSet; 'STRING' if you want to get a local date-time format string in ResultSet. Default value is 'STRING'. +* batchErrorIgnore: true if you want to continue executing the rest of the SQL when error happens during execute the executeBatch method in Statement; false, false if the remaining SQL statements are not executed. Default value is false. + +#### Establishing a connection with URL and Properties + +In addition to establish the connection with the specified URL, you can also use Properties to specify the parameters to set up the connection, as shown below: + +```java +public Connection getConn() throws Exception{ + String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata"; + // String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata"; + Properties connProps = new Properties(); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + Connection conn = DriverManager.getConnection(jdbcUrl, connProps); + return conn; +} +``` + +In the example above, JDBC-JNI is used to establish a connection to hostname of 'taosdemo.com', port at 6030, and database name of 'test'. The annotation is the method when using JDBC-RESTful. The connection specifies the user name as 'root' and the password as 'taosdata' in the URL, and the character set to use, locale, time zone, and so on in connProps. + +The configuration parameters in properties are as follows: + +* TSDBDriver.PROPERTY_KEY_USER: user name for logging in to the TDengine. The default value is 'root'. +* TSDBDriver.PROPERTY_KEY_PASSWORD: the user login password. The default value is 'taosdata'. +* TSDBDriver.PROPERTY_KEY_CONFIG_DIR: directory of the client configuration file. It is valid only for JDBC-JNI. The default value is `/etc/taos` on Linux and `C:/TDengine/cfg on Windows`. +* TSDBDriver.PROPERTY_KEY_CHARSET: character set used by the client. The default value is the system character set. +* TSDBDriver.PROPERTY_KEY_LOCALE: client locale. The default value is the current system locale. +* TSDBDriver.PROPERTY_KEY_TIME_ZONE: timezone used by the client. The default value is the current timezone of the system. +* TSDBDriver.PROPERTY_KEY_BATCH_LOAD: only valid for JDBC-JNI. True if batch ResultSet fetching is enabled; false if row-by-row ResultSet fetching is enabled. Default value is flase. +* TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT: only valid for JDBC-RESTful. 'TIMESTAMP' if you want to get a long value in a ResultSet; 'UTC' if you want to get a string in UTC date-time format in a ResultSet; 'STRING' if you want to get a local date-time format string in ResultSet. Default value is 'STRING'. +* TSDBDriver.PROPERTY_KEY_BATCH_ERROR_IGNORE: true if you want to continue executing the rest of the SQL when error happens during execute the executeBatch method in Statement; false, false if the remaining SQL statements are not executed. Default value is false. + +#### Establishing a connection with configuration file + +When JDBC-JNI is used to connect to the TDengine cluster, you can specify firstEp and secondEp parameters of the cluster in the client configuration file. As follows: + +1. The hostname and port are not specified in Java applications + +```java +public Connection getConn() throws Exception{ + String jdbcUrl = "jdbc:TAOS://:/test?user=root&password=taosdata"; + Properties connProps = new Properties(); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); + connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + Connection conn = DriverManager.getConnection(jdbcUrl, connProps); + return conn; +} +``` + +2. Specify firstEp and secondEp in the configuration file + +```txt +# first fully qualified domain name (FQDN) for TDengine system +firstEp cluster_node1:6030 +# second fully qualified domain name (FQDN) for TDengine system, for cluster only +secondEp cluster_node2:6030 +``` + +In the above example, JDBC driver uses the client configuration file to establish a connection to the hostname of 'cluster_node1', port 6030, and database name of 'test'. When the firstEp node in the cluster fails, JDBC will try to connect to the cluster using secondEp. In the TDengine, as long as one node in firstEp and secondEp is valid, the connection to the cluster can be established. + +**Note**: In this case, the configuration file belongs to TDengine client which is running inside a Java application. default file path of Linux OS is '/etc/taos/taos.cfg', and default file path of Windows OS is 'C://TDengine/cfg/taos.cfg'. + +#### Priority of the parameters + +If the parameters in the URL, Properties, and client configuration file are repeated set, the priorities of the parameters in descending order are as follows: + +1. URL parameters +2. Properties +3. Client configuration file in taos.cfg + +For example, if you specify password as 'taosdata' in the URL and password as 'taosdemo' in the Properties, JDBC will establish a connection using the password in the URL. + +For details, see Client Configuration:[client configuration](https://www.taosdata.com/en/documentation/administrator#client) + +### Create database and table + +```java +Statement stmt = conn.createStatement(); +// create database +stmt.executeUpdate("create database if not exists db"); +// use database +stmt.executeUpdate("use db"); +// create table +stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)"); +``` + +### Insert + +```java +// insert data +int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now + 1s, 20, 9.3)"); +System.out.println("insert " + affectedRows + " rows."); +``` + +**Note**: 'now' is an internal system function. The default value is the current time of the computer where the client resides. 'now + 1s' indicates that the current time on the client is added by one second. The following time units are a(millisecond), s (second), m(minute), h(hour), d(day), w(week), n(month), and y(year). + +### Query + +```java +// query data +ResultSet resultSet = stmt.executeQuery("select * from tb"); +Timestamp ts = null; +int temperature = 0; +float humidity = 0; +while(resultSet.next()){ + ts = resultSet.getTimestamp(1); + temperature = resultSet.getInt(2); + humidity = resultSet.getFloat("humidity"); + System.out.printf("%s, %d, %s\n", ts, temperature, humidity); +} +``` + +**Note**: The query is consistent with the operation of the relational database, and the index in ResultSet starts from 1. + +### Handle exceptions + +```java +try (Statement statement = connection.createStatement()) { + // executeQuery + ResultSet resultSet = statement.executeQuery(sql); + // print result + printResult(resultSet); +} catch (SQLException e) { + System.out.println("ERROR Message: " + e.getMessage()); + System.out.println("ERROR Code: " + e.getErrorCode()); + e.printStackTrace(); +} +``` + +The Java connector may report three types of error codes: JDBC Driver (error codes ranging from 0x2301 to 0x2350), JNI method (error codes ranging from 0x2351 to 0x2400), and TDengine Error. For details about the error code, see: + +- https://github.com/taosdata/TDengine/blob/develop/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java +- https://github.com/taosdata/TDengine/blob/develop/src/inc/taoserror.h + +### Write data through parameter binding + +Since version 2.1.2.0, TDengine's JDBC-JNI implementation has significantly improved parameter binding support for data write (INSERT) scenarios. Data can be written in the following way, avoiding SQL parsing and significantly improving the write performance.(**Note**: parameter binding is not supported in JDBC-RESTful) + +```java +Statement stmt = conn.createStatement(); +Random r = new Random(); + +// In the INSERT statement, the VALUES clause allows you to specify a specific column; If automatic table creation is adopted, the TAGS clause needs to set the parameter values of all TAGS columns +TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? using weather_test tags (?, ?) (ts, c1, c2) values(?, ?, ?)"); + +s.setTableName("w1"); + +// set tags +s.setTagInt(0, r.nextInt(10)); +s.setTagString(1, "Beijing"); +int numOfRows = 10; + +// set values +ArrayList ts = new ArrayList<>(); +for (int i = 0; i < numOfRows; i++){ + ts.add(System.currentTimeMillis() + i); +} +s.setTimestamp(0, ts); +ArrayList s1 = new ArrayList<>(); +for (int i = 0; i < numOfRows; i++){ + s1.add(r.nextInt(100)); +} +s.setInt(1, s1); +ArrayList s2 = new ArrayList<>(); +for (int i = 0; i < numOfRows; i++){ + s2.add("test" + r.nextInt(100)); +} +s.setString(2, s2, 10); + +// The cache is not cleared after AddBatch. Do not bind new data again before ExecuteBatch +s.columnDataAddBatch(); +s.columnDataExecuteBatch(); +// Clear the cache, after which you can bind new data(including table names, tags, values): +s.columnDataClearBatch(); +s.columnDataCloseBatch(); +``` + +The methods used to set tags are: + +```java +public void setTagNull(int index, int type) +public void setTagBoolean(int index, boolean value) +public void setTagInt(int index, int value) +public void setTagByte(int index, byte value) +public void setTagShort(int index, short value) +public void setTagLong(int index, long value) +public void setTagTimestamp(int index, long value) +public void setTagFloat(int index, float value) +public void setTagDouble(int index, double value) +public void setTagString(int index, String value) +public void setTagNString(int index, String value) +``` + +The methods used to set columns are: + +```java +public void setInt(int columnIndex, ArrayList list) throws SQLException +public void setFloat(int columnIndex, ArrayList list) throws SQLException +public void setTimestamp(int columnIndex, ArrayList list) throws SQLException +public void setLong(int columnIndex, ArrayList list) throws SQLException +public void setDouble(int columnIndex, ArrayList list) throws SQLException +public void setBoolean(int columnIndex, ArrayList list) throws SQLException +public void setByte(int columnIndex, ArrayList list) throws SQLException +public void setShort(int columnIndex, ArrayList list) throws SQLException +public void setString(int columnIndex, ArrayList list, int size) throws SQLException +public void setNString(int columnIndex, ArrayList list, int size) throws SQLException +``` + +**Note**: Both setString and setNString require the user to declare the column width of the corresponding column in the table definition in the size parameter. + +### Data Subscription + +#### Subscribe + +```java +TSDBSubscribe sub = ((TSDBConnection)conn).subscribe("topic", "select * from meters", false); +``` + +parameters: + +* topic: the unique topic name of the subscription. +* sql: a select statement. +* restart: true if restart the subscription already exists; false if continue the previous subscription. + +In the example above, a subscription named 'topic' is created which use the SQL statement 'select * from meters'. If the subscription already exists, it will continue with the previous query progress, rather than consuming all the data from scratch. + +#### Consume + +```java +int total = 0; +while(true) { + TSDBResultSet rs = sub.consume(); + int count = 0; + while(rs.next()) { + count++; + } + total += count; + System.out.printf("%d rows consumed, total %d\n", count, total); + Thread.sleep(1000); +} +``` + +The consume method returns a result set containing all the new data so far since the last consume. Make sure to call consume as often as you need (like Thread.sleep(1000) in the example), otherwise you will put unnecessary stress on the server. + +#### Close + +```java +sub.close(true); +// release resources +resultSet.close(); +stmt.close(); +conn.close(); +``` + +The close method closes a subscription. If the parameter is true, the subscription progress information is reserved, and a subscription with the same name can be created later to continue consuming data. If false, the subscription progress is not retained. + +**Note**: the connection must be closed; otherwise, a connection leak may occur. + +## Connection Pool + +### HikariCP example + +```java +public static void main(String[] args) throws SQLException { + HikariConfig config = new HikariConfig(); + // jdbc properties + config.setJdbcUrl("jdbc:TAOS://127.0.0.1:6030/log"); + config.setUsername("root"); + config.setPassword("taosdata"); + // connection pool configurations + config.setMinimumIdle(10); //minimum number of idle connection + config.setMaximumPoolSize(10); //maximum number of connection in the pool + config.setConnectionTimeout(30000); //maximum wait milliseconds for get connection from pool + config.setMaxLifetime(0); // maximum life time for each connection + config.setIdleTimeout(0); // max idle time for recycle idle connection + config.setConnectionTestQuery("select server_status()"); //validation query + HikariDataSource ds = new HikariDataSource(config); //create datasource + Connection connection = ds.getConnection(); // get connection + Statement statement = connection.createStatement(); // get statement + //query or insert + // ... + connection.close(); // put back to conneciton pool +} +``` + +### Druid example + +```java +public static void main(String[] args) throws Exception { + DruidDataSource dataSource = new DruidDataSource(); + // jdbc properties + dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver"); + dataSource.setUrl(url); + dataSource.setUsername("root"); + dataSource.setPassword("taosdata"); + // pool configurations + dataSource.setInitialSize(10); + dataSource.setMinIdle(10); + dataSource.setMaxActive(10); + dataSource.setMaxWait(30000); + dataSource.setValidationQuery("select server_status()"); + Connection connection = dataSource.getConnection(); // get connection + Statement statement = connection.createStatement(); // get statement + //query or insert + // ... + connection.close(); // put back to conneciton pool +} +``` + +**Note**: + +As of TDengine V1.6.4.1, the function select server_status() is supported specifically for heartbeat detection, so it is recommended to use select server_status() for Validation queries when using connection pools. + +Select server_status() returns 1 on success, as shown below. + +```sql +taos> select server_status(); +server_status()| +================ +1 | +Query OK, 1 row(s) in set (0.000141s) +``` + +## Integrated with framework + +- Please refer to [SpringJdbcTemplate](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/SpringJdbcTemplate) if using taos-jdbcdriver in Spring JdbcTemplate. +- Please refer to [springbootdemo](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC/springbootdemo) if using taos-jdbcdriver in Spring JdbcTemplate. + +## Example Codes + +you see sample code here: [JDBC example](https://github.com/taosdata/TDengine/tree/develop/tests/examples/JDBC) + +## FAQ + +- java.lang.UnsatisfiedLinkError: no taos in java.library.path + + **Cause**:The application program cannot find Library function *taos* + + **Answer**:Copy `C:\TDengine\driver\taos.dll` to `C:\Windows\System32\` on Windows and make a soft link through `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` on Linux. + +- java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform + + **Cause**:Currently TDengine only support 64bit JDK + + **Answer**:re-install 64bit JDK. + +- For other questions, please refer to [Issues](https://github.com/taosdata/TDengine/issues) + diff --git a/documentation20/en/08.connector/docs.md b/documentation20/en/08.connector/docs.md index 9cbd3952068d8eac23ffa9bcd7497ff158a21d86..a0126ceb6455249bf24e60783221cef7142890af 100644 --- a/documentation20/en/08.connector/docs.md +++ b/documentation20/en/08.connector/docs.md @@ -66,7 +66,11 @@ Run install_client.sh to install. Edit the taos.cfg file (default path/etc/taos/taos.cfg) and change firstEP to End Point of the TDengine server, for example: [h1.taos.com](http://h1.taos.com/):6030. -**Tip: If no TDengine service deployed in this machine, but only the application driver is installed, only firstEP needs to be configured in taos.cfg, and FQDN does not.** +**Tip: ** + +**1. If no TDengine service deployed in this machine, but only the application driver is installed, only firstEP needs to be configured in taos.cfg, and FQDN does not.** + +**2. To prevent “unable to resolve FQDN” error when connecting to the server, ensure that the hosts file of the client has the correct FQDN value.** **Windows x64/x86** @@ -296,9 +300,7 @@ Asynchronous APIs have relatively high requirements for users, who can selective The asynchronous APIs of TDengine all use non-blocking calling mode. Applications can use multithreading to open multiple tables at the same time, and can query or insert to each open table at the same time. It should be pointed out that the **application client must ensure that the operation on the same table is completely serialized**, that is, when the insertion or query operation on the same table is not completed (when no result returned), the second insertion or query operation cannot be performed. - - ### Parameter binding API In addition to calling `taos_query` directly for queries, TDengine also provides a Prepare API that supports parameter binding. Like MySQL, these APIs currently only support using question mark `?` to represent the parameters to be bound, as follows: @@ -823,12 +825,12 @@ https://www.taosdata.com/blog/2020/11/02/1901.html The TDengine provides the GO driver taosSql. taosSql implements the GO language's built-in interface database/sql/driver. Users can access TDengine in the application by simply importing the package as follows, see https://github.com/taosdata/driver-go/blob/develop/taosSql/driver_test.go for details. -Sample code for using the Go connector can be found in https://github.com/taosdata/TDengine/tree/develop/tests/examples/go and the [video tutorial](https://www.taosdata.com/blog/2020/11/11/1951.html). +Sample code for using the Go connector can be found in https://github.com/taosdata/TDengine/tree/develop/tests/examples/go . ```Go import ( "database/sql" - _ "github.com/taosdata/driver-go/taosSql" + _ "github.com/taosdata/driver-go/v2/taosSql" ) ``` @@ -839,6 +841,8 @@ go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.io,direct ``` +`taosSql` v2 completed refactoring of the v1 version and separated the built-in database operation interface `database/sql/driver` to the directory `taosSql`, and put other advanced functions such as subscription and stmt into the directory `af`. + ### Common APIs - `sql.Open(DRIVER_NAME string, dataSourceName string) *DB` @@ -937,7 +941,7 @@ After installing the TDengine client, the nodejsChecker.js program can verify wh Steps: -1. Create a new installation verification directory, for example: ~/tdengine-test, copy the nodejsChecker.js source program on github. Download address: (https://github.com/taosdata/TDengine/tree/develop/tests/examples/nodejs/nodejsChecker.js). +1. Create a new installation verification directory, for example: `~/tdengine-test`, copy the nodejsChecker.js source program on github. Download address: (https://github.com/taosdata/TDengine/tree/develop/tests/examples/nodejs/nodejsChecker.js). 2. Execute the following command: diff --git a/documentation20/en/09.connections/docs.md b/documentation20/en/09.connections/docs.md index b693d228cff808661caa4cc22afdc2721709bdc2..19544af0fa50af258f975532ad8399fcb8588b42 100644 --- a/documentation20/en/09.connections/docs.md +++ b/documentation20/en/09.connections/docs.md @@ -2,7 +2,7 @@ ## Grafana -TDengine can quickly integrate with [Grafana](https://www.grafana.com/), an open source data visualization system, to build a data monitoring and alarming system. The whole process does not require any code to write. The contents of the data table in TDengine can be visually showed on DashBoard. +TDengine can be quickly integrated with [Grafana](https://www.grafana.com/), an open source data visualization system, to build a data monitoring and alarming system. The whole process does not require any code to write. The contents of the data table in TDengine can be visually showed on DashBoard. ### Install Grafana diff --git a/documentation20/en/10.cluster/docs.md b/documentation20/en/10.cluster/docs.md index d7d908ff424270d9aa33f89eefd36e73f6ab68b2..864bc46200767468561ff940f3ac271d558c833c 100644 --- a/documentation20/en/10.cluster/docs.md +++ b/documentation20/en/10.cluster/docs.md @@ -1,8 +1,8 @@ # TDengine Cluster Management -Multiple TDengine servers, that is, multiple running instances of taosd, can form a cluster to ensure the highly reliable operation of TDengine and provide scale-out features. To understand cluster management in TDengine 2.0, it is necessary to understand the basic concepts of clustering. Please refer to the chapter "Overall Architecture of TDengine 2.0". And before installing the cluster, please follow the chapter ["Getting started"](https://www.taosdata.com/en/documentation/getting-started/) to install and experience the single node function. +Multiple TDengine servers, that is, multiple running instances of taosd, can form a cluster to ensure the highly reliable operation of TDengine and provide scale-out features. To understand cluster management in TDengine 2.0, it is necessary to understand the basic concepts of clustering. Please refer to the chapter "Overall Architecture of TDengine 2.0". And before installing the cluster, please follow the chapter ["Getting started"](https://www.taosdata.com/en/documentation/getting-started/) to install and experience the single node TDengine. -Each data node of the cluster is uniquely identified by End Point, which is composed of FQDN (Fully Qualified Domain Name) plus Port, such as [h1.taosdata.com](http://h1.taosdata.com/):6030. The general FQDN is the hostname of the server, which can be obtained through the Linux command `hostname -f` (how to configure FQDN, please refer to: [All about FQDN of TDengine](https://www.taosdata.com/blog/2020/09/11/1824.html)). Port is the external service port number of this data node. The default is 6030, but it can be modified by configuring the parameter serverPort in taos.cfg. A physical node may be configured with multiple hostnames, and TDengine will automatically get the first one, but it can also be specified through the configuration parameter fqdn in taos.cfg. If you are accustomed to direct IP address access, you can set the parameter fqdn to the IP address of this node. +Each data node of the cluster is uniquely identified by End Point, which is composed of FQDN (Fully Qualified Domain Name) plus Port, such as [h1.taosdata.com](http://h1.taosdata.com/):6030. The general FQDN is the hostname of the server, which can be obtained through the Linux command `hostname -f` (how to configure FQDN, please refer to: [All about FQDN of TDengine](https://www.taosdata.com/blog/2020/09/11/1824.html)). Port is the external service port number of this data node. The default is 6030, but it can be modified by configuring the parameter serverPort in taos.cfg. A physical node may be configured with multiple hostnames, and TDengine will automatically get the first one, but it can also be specified through the configuration parameter `fqdn` in taos.cfg. If you want to access via direct IP address, you can set the parameter `fqdn` to the IP address of this node. The cluster management of TDengine is extremely simple. Except for manual intervention in adding and deleting nodes, all other tasks are completed automatically, thus minimizing the workload of operation. This chapter describes the operations of cluster management in detail. @@ -12,11 +12,11 @@ Please refer to the [video tutorial](https://www.taosdata.com/blog/2020/11/11/19 **Step 0:** Plan FQDN of all physical nodes in the cluster, and add the planned FQDN to /etc/hostname of each physical node respectively; modify the /etc/hosts of each physical node, and add the corresponding IP and FQDN of all cluster physical nodes. [If DNS is deployed, contact your network administrator to configure it on DNS] -**Step 1:** If the physical nodes have previous test data, installed with version 1. x, or installed with other versions of TDengine, please delete it first and drop all data. For specific steps, please refer to the blog "[Installation and Uninstallation of Various Packages of TDengine](https://www.taosdata.com/blog/2019/08/09/566.html)" +**Step 1:** If the physical nodes have previous test data, installed with version 1. x, or installed with other versions of TDengine, please backup all data, then delete it and drop all data. For specific steps, please refer to the blog "[Installation and Uninstallation of Various Packages of TDengine](https://www.taosdata.com/blog/2019/08/09/566.html)" **Note 1:** Because the information of FQDN will be written into a file, if FQDN has not been configured or changed before, and TDengine has been started, be sure to clean up the previous data (`rm -rf /var/lib/taos/*`)on the premise of ensuring that the data is useless or backed up; -**Note 2:** The client also needs to be configured to ensure that it can correctly parse the FQDN configuration of each node, whether through DNS service or Host file. +**Note 2:** The client also needs to be configured to ensure that it can correctly parse the FQDN configuration of each node, whether through DNS service or modify hosts file. **Step 2:** It is recommended to close the firewall of all physical nodes, and at least ensure that the TCP and UDP ports of ports 6030-6042 are open. It is **strongly recommended** to close the firewall first and configure the ports after the cluster is built; @@ -136,7 +136,7 @@ Execute the CLI program taos, log in to the TDengine system using the root accou DROP DNODE "fqdn:port"; ``` -Where fqdn is the FQDN of the deleted node, and port is the port number of its external server. +Where fqdn is the FQDN of the deleted node, and port is the port number. **【Note】** @@ -185,7 +185,7 @@ Because of the introduction of vnode, it is impossible to simply draw a conclusi TDengine cluster is managed by mnode (a module of taosd, management node). In order to ensure the high-availability of mnode, multiple mnode replicas can be configured. The number of replicas is determined by system configuration parameter numOfMnodes, and the effective range is 1-3. In order to ensure the strong consistency of metadata, mnode replicas are duplicated synchronously. -A cluster has multiple data node dnodes, but a dnode runs at most one mnode instance. In the case of multiple dnodes, which dnode can be used as an mnode? This is automatically specified by the system according to the resource situation on the whole. User can execute the following command in the console of TDengine through the CLI program taos: +A cluster has multiple data node dnodes, but a dnode runs at most one mnode instance. In the case of multiple dnodes, which dnode can be used as an mnode? This is automatically selected by the system based on the resource on the whole. User can execute the following command in the console of TDengine through the CLI program taos: ``` SHOW MNODES; @@ -213,7 +213,7 @@ When the above three situations occur, the system will start a load computing of If a data node is offline, the TDengine cluster will automatically detect it. There are two detailed situations: -- If the data node is offline for more than a certain period of time (configuration parameter offlineThreshold in taos.cfg controls the duration), the system will automatically delete the data node, generate system alarm information and trigger the load balancing process. If the deleted data node is online again, it will not be able to join the cluster, and the system administrator will need to add it to the cluster again. +- If the data node is offline for more than a certain period of time (configuration parameter `offlineThreshold` in taos.cfg controls the duration), the system will automatically delete the data node, generate system alarm information and trigger the load balancing process. If the deleted data node is online again, it will not be able to join the cluster, and the system administrator will need to add it to the cluster again. - After offline, the system will automatically start the data recovery process if it goes online again within the duration of offlineThreshold. After the data is fully recovered, the node will start to work normally. **Note:** If each data node belonging to a virtual node group (including mnode group) is in offline or unsynced state, Master can only be elected after all data nodes in the virtual node group are online and can exchange status information, and the virtual node group can serve externally. For example, the whole cluster has 3 data nodes with 3 replicas. If all 3 data nodes go down and then 2 data nodes restart, it will not work. Only when all 3 data nodes restart successfully can serve externally again. @@ -229,7 +229,7 @@ The name of the executable for Arbitrator is tarbitrator. The executable has alm 1. Click [Package Download](https://www.taosdata.com/cn/all-downloads/), and in the TDengine Arbitrator Linux section, select the appropriate version to download and install. -2. The command line parameter -p of this application can specify the port number of its external service, and the default is 6042. +2. The command line parameter -p of this application can specify the port number of its service, and the default is 6042. 3. Modify the configuration file of each taosd instance, and set parameter arbitrator to the End Point corresponding to the tarbitrator in taos.cfg. (If this parameter is configured, when the number of replicas is even, the system will automatically connect the configured Arbitrator. If the number of replicas is odd, even if the Arbitrator is configured, the system will not establish a connection.) 4. The Arbitrator configured in the configuration file will appear in the return result of instruction `SHOW DNODES`; the value of the corresponding role column will be "arb". diff --git a/documentation20/en/11.administrator/docs.md b/documentation20/en/11.administrator/docs.md index 3817a41766d515d663661fd4382c883e0d8f179b..a2c2486b8e96cab95fad0f90470726d508dd63f7 100644 --- a/documentation20/en/11.administrator/docs.md +++ b/documentation20/en/11.administrator/docs.md @@ -22,8 +22,8 @@ If there is plenty of memory, the configuration of Blocks can be increased so th CPU requirements depend on the following two aspects: -- **Data insertion** TDengine single core can handle at least 10,000 insertion requests per second. Each insertion request can take multiple records, and inserting one record at a time is almost the same as inserting 10 records in computing resources consuming. Therefore, the larger the number of inserts, the higher the insertion efficiency. If an insert request has more than 200 records, a single core can insert 1 million records per second. However, the faster the insertion speed, the higher the requirement for front-end data collection, because records need to be cached and then inserted in batches. -- **Query requirements** TDengine to provide efficient queries, but the queries in each scenario vary greatly and the query frequency too, making it difficult to give objective figures. Users need to write some query statements for their own scenes to determine. +- **Data insertion**: TDengine single core can handle at least 10,000 insertion requests per second. Each insertion request can take multiple records, and inserting one record at a time is almost the same as inserting 10 records in computing resources consuming. Therefore, the larger the number of records per insert, the higher the insertion efficiency. If an insert request has more than 200 records, a single core can insert 1 million records per second. However, the faster the insertion speed, the higher the requirement for front-end data collection, because records need to be cached and then inserted in batches. +- **Query**: TDengine provides efficient queries, but the queries in each scenario vary greatly and the query frequency too, making it difficult to give objective figures. Users need to write some query statements for their own scenes to estimate. Therefore, only for data insertion, CPU can be estimated, but the computing resources consumed by query cannot be that clear. In the actual operation, it is not recommended to make CPU utilization rate over 50%. After that, new nodes need to be added to bring more computing resources. @@ -78,7 +78,7 @@ When the nodes in TDengine cluster are deployed on different physical machines a ## Server-side Configuration -The background service of TDengine system is provided by taosd, and the configuration parameters can be modified in the configuration file taos.cfg to meet the requirements of different scenarios. The default location of the configuration file is the /etc/taos directory, which can be specified by executing the parameter -c from the taosd command line. Such as taosd-c/home/user, to specify that the configuration file is located in the /home/user directory. +The background service of TDengine system is provided by taosd, and the configuration parameters can be modified in the configuration file taos.cfg to meet the requirements of different scenarios. The default location of the configuration file is the /etc/taos directory, which can be specified by executing the parameter `-c` from the taosd command line. Such as `taosd -c /home/user`, to specify that the configuration file is located in the /home/user directory. You can also use “-C” to show the current server configuration parameters: @@ -88,14 +88,14 @@ taosd -C Only some important configuration parameters are listed below. For more parameters, please refer to the instructions in the configuration file. Please refer to the previous chapters for detailed introduction and function of each parameter, and the default of these parameters is working and generally does not need to be set. **Note: After the configuration is modified, \*taosd service\* needs to be restarted to take effect.** -- firstEp: end point of the first dnode in the actively connected cluster when taosd starts, the default value is localhost: 6030. -- fqdn: FQDN of the data node, which defaults to the first hostname configured by the operating system. If you are accustomed to IP address access, you can set it to the IP address of the node. +- firstEp: end point of the first dnode which will be connected in the cluster when taosd starts, the default value is localhost: 6030. +- fqdn: FQDN of the data node, which defaults to the first hostname configured by the operating system. If you want to access via IP address directly, you can set it to the IP address of the node. - serverPort: the port number of the external service after taosd started, the default value is 6030. - httpPort: the port number used by the RESTful service to which all HTTP requests (TCP) require a query/write request. The default value is 6041. - dataDir: the data file directory to which all data files will be written. [Default:/var/lib/taos](http://default/var/lib/taos). - logDir: the log file directory to which the running log files of the client and server will be written. [Default:/var/log/taos](http://default/var/log/taos). -- arbitrator: the end point of the arbiter in the system; the default value is null. -- role: optional role for dnode. 0-any; it can be used as an mnode and to allocate vnodes; 1-mgmt; It can only be an mnode, but not to allocate vnodes; 2-dnode; caannot be an mnode, only vnode can be allocated +- arbitrator: the end point of the arbitrator in the system; the default value is null. +- role: optional role for dnode. 0-any; it can be used as an mnode and to allocate vnodes; 1-mgmt; It can only be an mnode, but not to allocate vnodes; 2-dnode; cannot be an mnode, only vnode can be allocated - debugFlage: run the log switch. 131 (output error and warning logs), 135 (output error, warning, and debug logs), 143 (output error, warning, debug, and trace logs). Default value: 131 or 135 (different modules have different default values). - numOfLogLines: the maximum number of lines allowed for a single log file. Default: 10,000,000 lines. - logKeepDays: the maximum retention time of the log file. When it is greater than 0, the log file will be renamed to taosdlog.xxx, where xxx is the timestamp of the last modification of the log file in seconds. Default: 0 days. @@ -161,18 +161,18 @@ For example: ## Client Configuration -The foreground interactive client application of TDengine system is taos and application driver, which shares the same configuration file taos.cfg with taosd. When running taos, use the parameter -c to specify the configuration file directory, such as taos-c/home/cfg, which means using the parameters in the taos.cfg configuration file under the /home/cfg/ directory. The default directory is /etc/taos. For more information on how to use taos, see the help information taos --help. This section mainly describes the parameters used by the taos client application in the configuration file taos.cfg. +The foreground interactive client application of TDengine system is taos and application driver, which shares the same configuration file taos.cfg with taosd. When running taos, use the parameter `-c` to specify the configuration file directory, such as `taos -c /home/cfg`, which means using the parameters in the taos.cfg configuration file under the /home/cfg/ directory. The default directory is /etc/taos. For more information on how to use taos, see the help information `taos --help`. This section mainly describes the parameters used by the taos client application in the configuration file taos.cfg. **Versions after 2.0. 10.0 support the following parameters on command line to display the current client configuration parameters** ```bash -taos -C 或 taos --dump-config +taos -C or taos --dump-config ``` Client configuration parameters: - firstEp: end point of the first taosd instance in the actively connected cluster when taos is started, the default value is localhost: 6030. -- secondEp: when taos starts, if not impossible to connect to firstEp, it will try to connect to secondEp. +- secondEp: when taos starts, if unable to connect to firstEp, it will try to connect to secondEp. - locale Default value: obtained dynamically from the system. If the automatic acquisition fails, user needs to set it in the configuration file or through API @@ -493,4 +493,4 @@ At the moment, TDengine has nearly 200 internal reserved keywords, which cannot | CONCAT | GLOB | METRICS | SET | VIEW | | CONFIGS | GRANTS | MIN | SHOW | WAVG | | CONFLICT | GROUP | MINUS | SLASH | WHERE | -| CONNECTION | | | | | +| CONNECTION | | | | | \ No newline at end of file diff --git a/documentation20/en/12.taos-sql/docs.md b/documentation20/en/12.taos-sql/docs.md index dfa1742c999adbf4a3e7846955dc8a564339d0c2..630fbd1cdbeab7d9500b88ab979d708b14441f0a 100644 --- a/documentation20/en/12.taos-sql/docs.md +++ b/documentation20/en/12.taos-sql/docs.md @@ -1,8 +1,8 @@ # TAOS SQL -TDengine provides a SQL-style language, TAOS SQL, to insert or query data, and support other common tips. To finish this document, you should have some understanding about SQL. +TDengine provides a SQL-style language, TAOS SQL, to insert or query data. To read through this document, you should have some basic understanding about SQL. -TAOS SQL is the main tool for users to write and query data to TDengine. TAOS SQL provides a style and mode similar to standard SQL to facilitate users to get started quickly. Strictly speaking, TAOS SQL is not and does not attempt to provide SQL standard syntax. In addition, since TDengine does not provide deletion function for temporal structured data, the relevant function of data deletion is non-existent in TAO SQL. +TAOS SQL is the main way for users to write and query data to TDengine. TAOS SQL is similar to standard SQL to facilitate users to get started quickly. Strictly speaking, TAOS SQL is not and does not attempt to provide SQL standard syntax. In addition, since TDengine does not provide deletion function for time-series data, the relevant function of data deletion is non-existent in TAO SQL. Let’s take a look at the conventions used for syntax descriptions. @@ -127,7 +127,7 @@ Note: ALTER DATABASE db_name CACHELAST 0; ``` CACHELAST parameter controls whether last_row of the data subtable is cached in memory. The default value is 0, and the value range is [0, 1]. Where 0 means not enabled and 1 means enabled. (supported from version 2.0. 11) - + **Tips**: After all the above parameters are modified, show databases can be used to confirm whether the modification is successful. - **Show all databases in system** @@ -138,14 +138,17 @@ Note: ## Table Management -- Create a table -Note: +- **Create a table** -1. The first field must be a timestamp, and system will set it as the primary key; -2. The max length of table name is 192; -3. The length of each row of the table cannot exceed 16k characters; -4. Sub-table names can only consist of letters, numbers, and underscores, and cannot begin with numbers -5. If the data type binary or nchar is used, the maximum number of bytes should be specified, such as binary (20), which means 20 bytes; + ```mysql + CREATE TABLE [IF NOT EXISTS] tb_name (timestamp_field_name TIMESTAMP, field1_name data_type1 [, field2_name data_type2 ...]); + ``` + Note: + 1. The first field must be a timestamp, and system will set it as the primary key; + 2. The max length of table name is 192; + 3. The length of each row of the table cannot exceed 16k characters; + 4. Sub-table names can only consist of letters, numbers, and underscores, and cannot begin with numbers + 5. If the data type binary or nchar is used, the maximum number of bytes should be specified, such as binary (20), which means 20 bytes; - **Create a table via STable** @@ -171,10 +174,10 @@ Note: Note: 1. The method of batch creating tables requires that the data table must use STable as a template. - 2. On the premise of not exceeding the length limit of SQL statements, it is suggested that the number of tables in a single statement should be controlled between 1000 and 3000, which will obtain an ideal speed of table building. + 2. On the premise of not exceeding the length limit of SQL statements, it is suggested that the number of tables in a single statement should be controlled between 1000 and 3000, which will obtain an ideal speed of table creating. - **Drop a table** - + ```mysql DROP TABLE [IF EXISTS] tb_name; ``` @@ -218,7 +221,7 @@ Note: ## STable Management -Note: In 2.0. 15.0 and later versions, STABLE reserved words are supported. That is, in the instruction description later in this section, the three instructions of CREATE, DROP and ALTER need to write TABLE instead of STABLE in the old version as the reserved word. +Note: In 2.0.15.0 and later versions, STABLE reserved words are supported. That is, in the instruction description later in this section, the three instructions of CREATE, DROP and ALTER need to write TABLE instead of STABLE in the old version as the reserved word. - **Create a STable** @@ -290,7 +293,7 @@ Note: In 2.0. 15.0 and later versions, STABLE reserved words are supported. That Modify a tag name of STable. After modifying, all sub-tables under the STable will automatically update the new tag name. - **Modify a tag value of sub-table** - + ```mysql ALTER TABLE tb_name SET TAG tag_name=new_tag_value; ``` @@ -306,7 +309,7 @@ Note: In 2.0. 15.0 and later versions, STABLE reserved words are supported. That Insert a record into table tb_name. - **Insert a record with data corresponding to a given column** - + ```mysql INSERT INTO tb_name (field1_name, ...) VALUES (field1_value1, ...); ``` @@ -320,14 +323,14 @@ Note: In 2.0. 15.0 and later versions, STABLE reserved words are supported. That Insert multiple records into table tb_name. - **Insert multiple records into a given column** - + ```mysql INSERT INTO tb_name (field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) ...; ``` Insert multiple records into a given column of table tb_name. - **Insert multiple records into multiple tables** - + ```mysql INSERT INTO tb1_name VALUES (field1_value1, ...) (field1_value2, ...) ... tb2_name VALUES (field1_value1, ...) (field1_value2, ...) ...; @@ -421,7 +424,7 @@ taos> SELECT * FROM d1001; Query OK, 3 row(s) in set (0.001165s) ``` -For Stables, wildcards contain *tag columns*. +For STables, wildcards contain *tag columns*. ```mysql taos> SELECT * FROM meters; @@ -720,7 +723,7 @@ TDengine supports aggregations over data, they are listed below: ================================================ 9 | 9 | Query OK, 1 row(s) in set (0.004475s) - + taos> SELECT COUNT(*), COUNT(voltage) FROM d1001; count(*) | count(voltage) | ================================================ @@ -758,7 +761,7 @@ TDengine supports aggregations over data, they are listed below: ``` - **TWA** - + ```mysql SELECT TWA(field_name) FROM tb_name WHERE clause; ``` @@ -799,7 +802,7 @@ TDengine supports aggregations over data, they are listed below: ================================================================================ 35.200000763 | 658 | 0.950000018 | Query OK, 1 row(s) in set (0.000980s) - ``` + ``` - **STDDEV** @@ -896,7 +899,7 @@ TDengine supports aggregations over data, they are listed below: ====================================== 13.40000 | 223 | Query OK, 1 row(s) in set (0.001123s) - + taos> SELECT MAX(current), MAX(voltage) FROM d1001; max(current) | max(voltage) | ====================================== @@ -937,8 +940,6 @@ TDengine supports aggregations over data, they are listed below: Query OK, 1 row(s) in set (0.001023s) ``` -- - - **LAST** ```mysql @@ -972,7 +973,7 @@ TDengine supports aggregations over data, they are listed below: ``` - **TOP** - + ```mysql SELECT TOP(field_name, K) FROM { tb_name | stb_name } [WHERE clause]; ``` @@ -1029,7 +1030,7 @@ TDengine supports aggregations over data, they are listed below: 2018-10-03 14:38:15.000 | 218 | 2018-10-03 14:38:16.650 | 218 | Query OK, 2 row(s) in set (0.001332s) - + taos> SELECT BOTTOM(current, 2) FROM d1001; ts | bottom(current, 2) | ================================================= @@ -1092,7 +1093,7 @@ TDengine supports aggregations over data, they are listed below: ======================= 12.30000 | Query OK, 1 row(s) in set (0.001238s) - + taos> SELECT LAST_ROW(current) FROM d1002; last_row(current) | ======================= @@ -1146,7 +1147,7 @@ TDengine supports aggregations over data, they are listed below: ============================ 5.000000000 | Query OK, 1 row(s) in set (0.001792s) - + taos> SELECT SPREAD(voltage) FROM d1001; spread(voltage) | ============================ @@ -1172,7 +1173,7 @@ TDengine supports aggregations over data, they are listed below: ## Time-dimension Aggregation -TDengine supports aggregating by intervals. Data in a table can partitioned by intervals and aggregated to generate results. For example, a temperature sensor collects data once per second, but the average temperature needs to be queried every 10 minutes. This aggregation is suitable for down sample operation, and the syntax is as follows: +TDengine supports aggregating by intervals (time range). Data in a table can partitioned by intervals and aggregated to generate results. For example, a temperature sensor collects data once per second, but the average temperature needs to be queried every 10 minutes. This aggregation is suitable for down sample operation, and the syntax is as follows: ```mysql SELECT function_list FROM tb_name @@ -1235,12 +1236,12 @@ SELECT AVG(current), MAX(current), LEASTSQUARES(current, start_val, step_val), P **Restrictions on group by** -TAOS SQL supports group by operation on tags, tbnames and ordinary columns, required that only one column and whichhas less than 100,000 unique values. +TAOS SQL supports group by operation on tags, tbnames and ordinary columns, required that only one column and which has less than 100,000 unique values. **Restrictions on join operation** -TAOS SQL supports join columns of two tables by Primary Key timestamp between them, and does not support four operations after tables aggregated for the time being. +TAOS SQL supports join columns of two tables by Primary Key timestamp between them, and does not support four arithmetic operations after tables aggregated for the time being. **Availability of is no null** -Is not null supports all types of columns. Non-null expression is < > "" and only applies to columns of non-numeric types. +Is not null supports all types of columns. Non-null expression is < > "" and only applies to columns of non-numeric types. \ No newline at end of file diff --git a/packaging/cfg/taos.cfg b/packaging/cfg/taos.cfg index 3ae4e9941e96abb4c93b99ae86c40b3e3583bd08..310369aa14ad5e9e6ccb49843605a92fdc333563 100644 --- a/packaging/cfg/taos.cfg +++ b/packaging/cfg/taos.cfg @@ -194,6 +194,9 @@ keepColumnName 1 # maximum number of rows returned by the restful interface # restfulRowLimit 10240 +# database name must be specified in restful interface if the following parameter is set, off by default +# httpDbNameMandatory 1 + # The following parameter is used to limit the maximum number of lines in log files. # max number of lines per log filters # numOfLogLines 10000000 @@ -284,3 +287,5 @@ keepColumnName 1 # 0 no query allowed, queries are disabled # queryBufferSize -1 +# percent of redundant data in tsdb meta will compact meta data,0 means donot compact +# tsdbMetaCompactRatio 0 diff --git a/packaging/tools/make_install.sh b/packaging/tools/make_install.sh index 7851587c826c1667386d6dc9c91f1eef748927db..d400d0b91a2d02e9b3e0232d67e2ed6b00cdf541 100755 --- a/packaging/tools/make_install.sh +++ b/packaging/tools/make_install.sh @@ -19,35 +19,35 @@ else fi # Dynamic directory -data_dir="/var/lib/taos" if [ "$osType" != "Darwin" ]; then + data_dir="/var/lib/taos" log_dir="/var/log/taos" -else - log_dir=~/TDengine/log -fi - -data_link_dir="/usr/local/taos/data" -log_link_dir="/usr/local/taos/log" -cfg_install_dir="/etc/taos" + cfg_install_dir="/etc/taos" -if [ "$osType" != "Darwin" ]; then bin_link_dir="/usr/bin" lib_link_dir="/usr/lib" lib64_link_dir="/usr/lib64" inc_link_dir="/usr/include" + + install_main_dir="/usr/local/taos" + + bin_dir="/usr/local/taos/bin" else + data_dir="/usr/local/var/lib/taos" + log_dir="/usr/local/var/log/taos" + + cfg_install_dir="/usr/local/etc/taos" + bin_link_dir="/usr/local/bin" lib_link_dir="/usr/local/lib" inc_link_dir="/usr/local/include" -fi -#install main path -install_main_dir="/usr/local/taos" + install_main_dir="/usr/local/Cellar/tdengine/${verNumber}" -# old bin dir -bin_dir="/usr/local/taos/bin" + bin_dir="/usr/local/Cellar/tdengine/${verNumber}/bin" +fi service_config_dir="/etc/systemd/system" @@ -59,12 +59,11 @@ GREEN_UNDERLINE='\033[4;32m' NC='\033[0m' csudo="" -if command -v sudo > /dev/null; then - csudo="sudo" -fi if [ "$osType" != "Darwin" ]; then - + if command -v sudo > /dev/null; then + csudo="sudo" + fi initd_mod=0 service_mod=2 if pidof systemd &> /dev/null; then @@ -137,17 +136,17 @@ function install_main_path() { function install_bin() { # Remove links - ${csudo} rm -f ${bin_link_dir}/taos || : + ${csudo} rm -f ${bin_link_dir}/taos || : + ${csudo} rm -f ${bin_link_dir}/taosd || : + ${csudo} rm -f ${bin_link_dir}/taosdemo || : + ${csudo} rm -f ${bin_link_dir}/taosdump || : if [ "$osType" != "Darwin" ]; then - ${csudo} rm -f ${bin_link_dir}/taosd || : - ${csudo} rm -f ${bin_link_dir}/taosdemo || : - ${csudo} rm -f ${bin_link_dir}/taosdump || : + ${csudo} rm -f ${bin_link_dir}/perfMonitor || : ${csudo} rm -f ${bin_link_dir}/set_core || : + ${csudo} rm -f ${bin_link_dir}/rmtaos || : fi - - ${csudo} rm -f ${bin_link_dir}/rmtaos || : - + ${csudo} cp -r ${binary_dir}/build/bin/* ${install_main_dir}/bin ${csudo} cp -r ${script_dir}/taosd-dump-cfg.gdb ${install_main_dir}/bin @@ -161,19 +160,18 @@ function install_bin() { ${csudo} chmod 0555 ${install_main_dir}/bin/* #Make link - [ -x ${install_main_dir}/bin/taos ] && ${csudo} ln -s ${install_main_dir}/bin/taos ${bin_link_dir}/taos || : + [ -x ${install_main_dir}/bin/taos ] && ${csudo} ln -s ${install_main_dir}/bin/taos ${bin_link_dir}/taos || : + [ -x ${install_main_dir}/bin/taosd ] && ${csudo} ln -s ${install_main_dir}/bin/taosd ${bin_link_dir}/taosd || : + [ -x ${install_main_dir}/bin/taosdump ] && ${csudo} ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump || : + [ -x ${install_main_dir}/bin/taosdemo ] && ${csudo} ln -s ${install_main_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || : if [ "$osType" != "Darwin" ]; then - [ -x ${install_main_dir}/bin/taosd ] && ${csudo} ln -s ${install_main_dir}/bin/taosd ${bin_link_dir}/taosd || : - [ -x ${install_main_dir}/bin/taosdump ] && ${csudo} ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump || : - [ -x ${install_main_dir}/bin/taosdemo ] && ${csudo} ln -s ${install_main_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || : + [ -x ${install_main_dir}/bin/perfMonitor ] && ${csudo} ln -s ${install_main_dir}/bin/perfMonitor ${bin_link_dir}/perfMonitor || : [ -x ${install_main_dir}/set_core.sh ] && ${csudo} ln -s ${install_main_dir}/bin/set_core.sh ${bin_link_dir}/set_core || : fi - + if [ "$osType" != "Darwin" ]; then - [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo} ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/rmtaos || : - else - [ -x ${install_main_dir}/bin/remove_client.sh ] && ${csudo} ln -s ${install_main_dir}/bin/remove_client.sh ${bin_link_dir}/rmtaos || : + [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo} ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/rmtaos || : fi } @@ -220,7 +218,7 @@ function install_jemalloc() { fi if [ -d /etc/ld.so.conf.d ]; then - ${csudo} echo "/usr/local/lib" > /etc/ld.so.conf.d/jemalloc.conf + echo "/usr/local/lib" | ${csudo} tee /etc/ld.so.conf.d/jemalloc.conf ${csudo} ldconfig else echo "/etc/ld.so.conf.d not found!" @@ -245,11 +243,12 @@ function install_lib() { ${csudo} ln -sf ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so fi else - ${csudo} cp -Rf ${binary_dir}/build/lib/libtaos.* ${install_main_dir}/driver && ${csudo} chmod 777 ${install_main_dir}/driver/* - ${csudo} ln -sf ${install_main_dir}/driver/libtaos.1.dylib ${lib_link_dir}/libtaos.1.dylib + ${csudo} cp -Rf ${binary_dir}/build/lib/libtaos.${verNumber}.dylib ${install_main_dir}/driver && ${csudo} chmod 777 ${install_main_dir}/driver/* + + ${csudo} ln -sf ${install_main_dir}/driver/libtaos.* ${lib_link_dir}/libtaos.1.dylib ${csudo} ln -sf ${lib_link_dir}/libtaos.1.dylib ${lib_link_dir}/libtaos.dylib fi - + install_jemalloc if [ "$osType" != "Darwin" ]; then @@ -259,10 +258,14 @@ function install_lib() { function install_header() { - ${csudo} rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taoserror.h || : + if [ "$osType" != "Darwin" ]; then + ${csudo} rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taoserror.h || : + fi ${csudo} cp -f ${source_dir}/src/inc/taos.h ${source_dir}/src/inc/taoserror.h ${install_main_dir}/include && ${csudo} chmod 644 ${install_main_dir}/include/* - ${csudo} ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h - ${csudo} ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h + if [ "$osType" != "Darwin" ]; then + ${csudo} ln -s ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h + ${csudo} ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h + fi } function install_config() { @@ -270,23 +273,20 @@ function install_config() { if [ ! -f ${cfg_install_dir}/taos.cfg ]; then ${csudo} mkdir -p ${cfg_install_dir} - [ -f ${script_dir}/../cfg/taos.cfg ] && ${csudo} cp ${script_dir}/../cfg/taos.cfg ${cfg_install_dir} + [ -f ${script_dir}/../cfg/taos.cfg ] && + ${csudo} cp ${script_dir}/../cfg/taos.cfg ${cfg_install_dir} ${csudo} chmod 644 ${cfg_install_dir}/* fi ${csudo} cp -f ${script_dir}/../cfg/taos.cfg ${install_main_dir}/cfg/taos.cfg.org - ${csudo} ln -s ${cfg_install_dir}/taos.cfg ${install_main_dir}/cfg + + if [ "$osType" != "Darwin" ]; then ${csudo} ln -s ${cfg_install_dir}/taos.cfg ${install_main_dir}/cfg + fi } function install_log() { ${csudo} rm -rf ${log_dir} || : - - if [ "$osType" != "Darwin" ]; then - ${csudo} mkdir -p ${log_dir} && ${csudo} chmod 777 ${log_dir} - else - mkdir -p ${log_dir} && chmod 777 ${log_dir} - fi - + ${csudo} mkdir -p ${log_dir} && ${csudo} chmod 777 ${log_dir} ${csudo} ln -s ${log_dir} ${install_main_dir}/log } @@ -307,7 +307,6 @@ function install_connector() { echo "WARNING: go connector not found, please check if want to use it!" fi ${csudo} cp -rf ${source_dir}/src/connector/python ${install_main_dir}/connector - ${csudo} cp ${binary_dir}/build/lib/*.jar ${install_main_dir}/connector &> /dev/null && ${csudo} chmod 777 ${install_main_dir}/connector/*.jar || echo &> /dev/null } @@ -487,24 +486,21 @@ function install_TDengine() { else echo -e "${GREEN}Start to install TDEngine Client ...${NC}" fi - + install_main_path - if [ "$osType" != "Darwin" ]; then - install_data - fi + install_data install_log install_header install_lib install_connector install_examples - install_bin - + if [ "$osType" != "Darwin" ]; then install_service fi - + install_config if [ "$osType" != "Darwin" ]; then diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index c04fa3298bd3acdee8fb88fb4f2eead2632a441f..ea5ce3bc52468d7efcc1ece78f46cbbc8c2c3a7e 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,6 +1,6 @@ name: tdengine base: core18 -version: '2.1.6.0' +version: '2.1.7.2' 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.6.0 + - usr/lib/libtaos.so.2.1.7.2 - usr/lib/libtaos.so.1 - usr/lib/libtaos.so diff --git a/src/balance/src/bnScore.c b/src/balance/src/bnScore.c index 7d94df1c23ab7824dbada0423beec14530a2101c..04a14357c9e602807f5aa254d8a5ea25bc4b328d 100644 --- a/src/balance/src/bnScore.c +++ b/src/balance/src/bnScore.c @@ -116,8 +116,17 @@ void bnCleanupDnodes() { static void bnCheckDnodesSize(int32_t dnodesNum) { if (tsBnDnodes.maxSize <= dnodesNum) { - tsBnDnodes.maxSize = dnodesNum * 2; - tsBnDnodes.list = realloc(tsBnDnodes.list, tsBnDnodes.maxSize * sizeof(SDnodeObj *)); + int32_t maxSize = dnodesNum * 2; + SDnodeObj** list1 = NULL; + int32_t retry = 0; + + while(list1 == NULL && retry++ < 3) { + list1 = realloc(tsBnDnodes.list, maxSize * sizeof(SDnodeObj *)); + } + if(list1) { + tsBnDnodes.list = list1; + tsBnDnodes.maxSize = maxSize; + } } } diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index 2f83557d63c288173f8b541caf32fe9fe2e73338..0d06e5d39c0ed1916e0c2af7ccce5918e31ac42f 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -4,6 +4,8 @@ PROJECT(TDengine) INCLUDE_DIRECTORIES(inc) INCLUDE_DIRECTORIES(jni) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/zlib-1.2.11/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/plugins/http/inc) AUX_SOURCE_DIRECTORY(src SRC) IF (TD_LINUX) diff --git a/src/client/inc/tscParseLine.h b/src/client/inc/tscParseLine.h new file mode 100644 index 0000000000000000000000000000000000000000..401dcafdfbefd28e79ebdf30d810e194564a5056 --- /dev/null +++ b/src/client/inc/tscParseLine.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 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_TSCPARSELINE_H +#define TDENGINE_TSCPARSELINE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char* key; + uint8_t type; + int16_t length; + char* value; +} TAOS_SML_KV; + +typedef struct { + char* stableName; + + char* childTableName; + TAOS_SML_KV* tags; + int32_t tagNum; + + // first kv must be timestamp + TAOS_SML_KV* fields; + int32_t fieldNum; +} TAOS_SML_DATA_POINT; + +typedef enum { + SML_TIME_STAMP_NOW, + SML_TIME_STAMP_SECONDS, + SML_TIME_STAMP_MILLI_SECONDS, + SML_TIME_STAMP_MICRO_SECONDS, + SML_TIME_STAMP_NANO_SECONDS +} SMLTimeStampType; + +typedef struct { + uint64_t id; + SHashObj* smlDataToSchema; +} SSmlLinesInfo; + +int tscSmlInsert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint, SSmlLinesInfo* info); +bool checkDuplicateKey(char *key, SHashObj *pHash, SSmlLinesInfo* info); +int32_t isValidChildTableName(const char *pTbName, int16_t len); + +bool convertSmlValueType(TAOS_SML_KV *pVal, char *value, + uint16_t len, SSmlLinesInfo* info); +int32_t convertSmlTimeStamp(TAOS_SML_KV *pVal, char *value, + uint16_t len, SSmlLinesInfo* info); + +void destroySmlDataPoint(TAOS_SML_DATA_POINT* point); + +#ifdef __cplusplus +} +#endif + +#endif // TDENGINE_TSCPARSELINE_H diff --git a/src/client/inc/tscSubquery.h b/src/client/inc/tscSubquery.h index f0349c2b3dc5b03b44afdca682f314709ecf6886..a012ca5a7fe741b8859465504cbc971a7e46952c 100644 --- a/src/client/inc/tscSubquery.h +++ b/src/client/inc/tscSubquery.h @@ -50,6 +50,12 @@ void tscUnlockByThread(int64_t *lockedBy); int tsInsertInitialCheck(SSqlObj *pSql); +void doCleanupSubqueries(SSqlObj *pSql, int32_t numOfSubs); + +void tscFreeRetrieveSup(SSqlObj *pSql); + + + #ifdef __cplusplus } #endif diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index 8c1037127a92206a4b390c1846f8acdefc1e492d..ebd5de1ab3a7faa85badd81165168347aa65f7b5 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -36,7 +36,7 @@ extern "C" { (((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_CHILD_TABLE)) #define UTIL_TABLE_IS_NORMAL_TABLE(metaInfo) \ - (!(UTIL_TABLE_IS_SUPER_TABLE(metaInfo) || UTIL_TABLE_IS_CHILD_TABLE(metaInfo) || UTIL_TABLE_IS_TMP_TABLE(metaInfo))) + (!(UTIL_TABLE_IS_SUPER_TABLE(metaInfo) || UTIL_TABLE_IS_CHILD_TABLE(metaInfo))) #define UTIL_TABLE_IS_TMP_TABLE(metaInfo) \ (((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_TEMP_TABLE)) @@ -144,6 +144,7 @@ bool tscIsSessionWindowQuery(SQueryInfo* pQueryInfo); bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo); bool tsIsArithmeticQueryOnAggResult(SQueryInfo* pQueryInfo); bool tscGroupbyColumn(SQueryInfo* pQueryInfo); +int32_t tscGetTopBotQueryExprIndex(SQueryInfo* pQueryInfo); bool tscIsTopBotQuery(SQueryInfo* pQueryInfo); bool hasTagValOutput(SQueryInfo* pQueryInfo); bool timeWindowInterpoRequired(SQueryInfo *pQueryInfo); @@ -190,6 +191,7 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo); void tscFieldInfoCopy(SFieldInfo* pFieldInfo, const SFieldInfo* pSrc, const SArray* pExprList); static FORCE_INLINE int32_t tscNumOfFields(SQueryInfo* pQueryInfo) { return pQueryInfo->fieldsInfo.numOfOutput; } +int32_t tscGetFirstInvisibleFieldPos(SQueryInfo* pQueryInfo); int32_t tscFieldInfoCompare(const SFieldInfo* pFieldInfo1, const SFieldInfo* pFieldInfo2, int32_t *diffSize); void tscInsertPrimaryTsSourceColumn(SQueryInfo* pQueryInfo, uint64_t uid); @@ -214,6 +216,7 @@ SExprInfo* tscExprUpdate(SQueryInfo* pQueryInfo, int32_t index, int16_t function int16_t size); size_t tscNumOfExprs(SQueryInfo* pQueryInfo); +int32_t tscExprTopBottomIndex(SQueryInfo* pQueryInfo); SExprInfo *tscExprGet(SQueryInfo* pQueryInfo, int32_t index); int32_t tscExprCopy(SArray* dst, const SArray* src, uint64_t uid, bool deepcopy); int32_t tscExprCopyAll(SArray* dst, const SArray* src, bool deepcopy); @@ -315,6 +318,7 @@ void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex, SSqlC int16_t tscGetJoinTagColIdByUid(STagCond* pTagCond, uint64_t uid); int16_t tscGetTagColIndexById(STableMeta* pTableMeta, int16_t colId); +int32_t doInitSubState(SSqlObj* pSql, int32_t numOfSubqueries); void tscPrintSelNodeList(SSqlObj* pSql, int32_t subClauseIndex); @@ -362,6 +366,8 @@ STblCond* tsGetTableFilter(SArray* filters, uint64_t uid, int16_t idx); void tscRemoveCachedTableMeta(STableMetaInfo* pTableMetaInfo, uint64_t id); +char* cloneCurrentDBName(SSqlObj* pSql); + #ifdef __cplusplus } #endif diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index b6821de87aed8831d4a8d7dd7bc8c46ac8fde551..b8eb0a5286a7b72b3ddd1d34b103e5b6239a496c 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -38,6 +38,11 @@ extern "C" { #include "qUtil.h" #include "tcmdtype.h" +typedef enum { + TAOS_REQ_FROM_SHELL, + TAOS_REQ_FROM_HTTP +} SReqOrigin; + // forward declaration struct SSqlInfo; @@ -123,17 +128,15 @@ typedef struct { int32_t kvLen; // len of SKVRow } SMemRowInfo; typedef struct { - uint8_t memRowType; - uint8_t compareStat; // 0 unknown, 1 need compare, 2 no need - TDRowTLenT dataRowInitLen; + uint8_t memRowType; // default is 0, that is SDataRow + uint8_t compareStat; // 0 no need, 1 need compare TDRowTLenT kvRowInitLen; SMemRowInfo *rowInfo; } SMemRowBuilder; typedef enum { - ROW_COMPARE_UNKNOWN = 0, + ROW_COMPARE_NO_NEED = 0, ROW_COMPARE_NEED = 1, - ROW_COMPARE_NO_NEED = 2, } ERowCompareStat; int tsParseTime(SStrToken *pToken, int64_t *time, char **next, char *error, int16_t timePrec); @@ -342,6 +345,7 @@ typedef struct STscObj { SRpcCorEpSet *tscCorMgmtEpSet; pthread_mutex_t mutex; int32_t numOfObj; // number of sqlObj from this tscObj + SReqOrigin from; } STscObj; typedef struct SSubqueryState { @@ -488,6 +492,7 @@ bool tscHasReachLimitation(SQueryInfo *pQueryInfo, SSqlRes *pRes); void tscSetBoundColumnInfo(SParsedDataColInfo *pColInfo, SSchema *pSchema, int32_t numOfCols); char *tscGetErrorMsgPayload(SSqlCmd *pCmd); +int32_t tscErrorMsgWithCode(int32_t code, char* dstBuffer, const char* errMsg, const char* sql); int32_t tscInvalidOperationMsg(char *msg, const char *additionalInfo, const char *sql); int32_t tscSQLSyntaxErrMsg(char* msg, const char* additionalInfo, const char* sql); diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c index 7ba613de88f2d358e4a359cfa5fb0d5f32a1071e..506c8d64b9f4213713656ecd08612a103e0b1b2d 100644 --- a/src/client/src/TSDBJNIConnector.c +++ b/src/client/src/TSDBJNIConnector.c @@ -20,12 +20,42 @@ #include "com_taosdata_jdbc_TSDBJNIConnector.h" -#define jniFatal(...) { if (jniDebugFlag & DEBUG_FATAL) { taosPrintLog("JNI FATAL ", tscEmbedded ? 255 : jniDebugFlag, __VA_ARGS__); }} -#define jniError(...) { if (jniDebugFlag & DEBUG_ERROR) { taosPrintLog("JNI ERROR ", tscEmbedded ? 255 : jniDebugFlag, __VA_ARGS__); }} -#define jniWarn(...) { if (jniDebugFlag & DEBUG_WARN) { taosPrintLog("JNI WARN ", tscEmbedded ? 255 : jniDebugFlag, __VA_ARGS__); }} -#define jniInfo(...) { if (jniDebugFlag & DEBUG_INFO) { taosPrintLog("JNI ", tscEmbedded ? 255 : jniDebugFlag, __VA_ARGS__); }} -#define jniDebug(...) { if (jniDebugFlag & DEBUG_DEBUG) { taosPrintLog("JNI ", jniDebugFlag, __VA_ARGS__); }} -#define jniTrace(...) { if (jniDebugFlag & DEBUG_TRACE) { taosPrintLog("JNI ", jniDebugFlag, __VA_ARGS__); }} +#define jniFatal(...) \ + { \ + if (jniDebugFlag & DEBUG_FATAL) { \ + taosPrintLog("JNI FATAL ", tscEmbedded ? 255 : jniDebugFlag, __VA_ARGS__); \ + } \ + } +#define jniError(...) \ + { \ + if (jniDebugFlag & DEBUG_ERROR) { \ + taosPrintLog("JNI ERROR ", tscEmbedded ? 255 : jniDebugFlag, __VA_ARGS__); \ + } \ + } +#define jniWarn(...) \ + { \ + if (jniDebugFlag & DEBUG_WARN) { \ + taosPrintLog("JNI WARN ", tscEmbedded ? 255 : jniDebugFlag, __VA_ARGS__); \ + } \ + } +#define jniInfo(...) \ + { \ + if (jniDebugFlag & DEBUG_INFO) { \ + taosPrintLog("JNI ", tscEmbedded ? 255 : jniDebugFlag, __VA_ARGS__); \ + } \ + } +#define jniDebug(...) \ + { \ + if (jniDebugFlag & DEBUG_DEBUG) { \ + taosPrintLog("JNI ", jniDebugFlag, __VA_ARGS__); \ + } \ + } +#define jniTrace(...) \ + { \ + if (jniDebugFlag & DEBUG_TRACE) { \ + taosPrintLog("JNI ", jniDebugFlag, __VA_ARGS__); \ + } \ + } int __init = 0; @@ -60,14 +90,14 @@ jmethodID g_blockdataSetByteArrayFp; jmethodID g_blockdataSetNumOfRowsFp; jmethodID g_blockdataSetNumOfColsFp; -#define JNI_SUCCESS 0 -#define JNI_TDENGINE_ERROR -1 +#define JNI_SUCCESS 0 +#define JNI_TDENGINE_ERROR -1 #define JNI_CONNECTION_NULL -2 #define JNI_RESULT_SET_NULL -3 #define JNI_NUM_OF_FIELDS_0 -4 -#define JNI_SQL_NULL -5 -#define JNI_FETCH_END -6 -#define JNI_OUT_OF_MEMORY -7 +#define JNI_SQL_NULL -5 +#define JNI_FETCH_END -6 +#define JNI_OUT_OF_MEMORY -7 static void jniGetGlobalMethod(JNIEnv *env) { // make sure init function executed once @@ -129,13 +159,13 @@ static void jniGetGlobalMethod(JNIEnv *env) { } static int32_t check_for_params(jobject jobj, jlong conn, jlong res) { - if ((TAOS*) conn == NULL) { + if ((TAOS *)conn == NULL) { jniError("jobj:%p, connection is closed", jobj); return JNI_CONNECTION_NULL; } - if ((TAOS_RES *) res == NULL) { - jniError("jobj:%p, conn:%p, res is null", jobj, (TAOS*) conn); + if ((TAOS_RES *)res == NULL) { + jniError("jobj:%p, conn:%p, res is null", jobj, (TAOS *)conn); return JNI_RESULT_SET_NULL; } @@ -216,7 +246,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEnv *env, jobject jobj, jstring jhost, jint jport, jstring jdbName, jstring juser, jstring jpass) { - jlong ret = 0; + jlong ret = 0; const char *host = NULL; const char *user = NULL; const char *pass = NULL; @@ -246,7 +276,7 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEn jniDebug("jobj:%p, pass not specified, use default password", jobj); } - ret = (jlong) taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport); + ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport); if (ret == 0) { jniError("jobj:%p, conn:%p, connect to database failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret, (char *)host, (char *)user, (char *)dbname, (int32_t)jport); @@ -289,7 +319,7 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp( jsize len = (*env)->GetArrayLength(env, jsql); - char *str = (char *) calloc(1, sizeof(char) * (len + 1)); + char *str = (char *)calloc(1, sizeof(char) * (len + 1)); if (str == NULL) { jniError("jobj:%p, conn:%p, alloc memory failed", jobj, tscon); return JNI_OUT_OF_MEMORY; @@ -315,16 +345,17 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp( } free(str); - return (jlong) pSql; + return (jlong)pSql; } -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrCodeImp(JNIEnv *env, jobject jobj, jlong con, jlong tres) { +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrCodeImp(JNIEnv *env, jobject jobj, jlong con, + jlong tres) { int32_t code = check_for_params(jobj, con, tres); if (code != JNI_SUCCESS) { return code; } - return (jint)taos_errno((TAOS_RES*) tres); + return (jint)taos_errno((TAOS_RES *)tres); } JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(JNIEnv *env, jobject jobj, jlong tres) { @@ -334,7 +365,7 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getErrMsgImp(J JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultSetImp(JNIEnv *env, jobject jobj, jlong con, jlong tres) { - TAOS *tscon = (TAOS *)con; + TAOS * tscon = (TAOS *)con; int32_t code = check_for_params(jobj, con, tres); if (code != JNI_SUCCESS) { return code; @@ -359,7 +390,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_isUpdateQueryImp( SSqlObj *pSql = (TAOS_RES *)tres; - return (tscIsUpdateQuery(pSql)? 1:0); + return (tscIsUpdateQuery(pSql) ? 1 : 0); } JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp(JNIEnv *env, jobject jobj, jlong con, @@ -370,21 +401,22 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_freeResultSetImp( } taos_free_result((void *)res); - jniDebug("jobj:%p, conn:%p, free resultset:%p", jobj, (TAOS*) con, (void *)res); + jniDebug("jobj:%p, conn:%p, free resultset:%p", jobj, (TAOS *)con, (void *)res); return JNI_SUCCESS; } JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsImp(JNIEnv *env, jobject jobj, jlong con, jlong res) { - TAOS *tscon = (TAOS *)con; + TAOS * tscon = (TAOS *)con; int32_t code = check_for_params(jobj, con, res); if (code != JNI_SUCCESS) { return code; } jint ret = taos_affected_rows((SSqlObj *)res); - jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (TAOS *)con, (TAOS_RES *)res, (int32_t)ret); + jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (TAOS *)con, (TAOS_RES *)res, + (int32_t)ret); return ret; } @@ -392,13 +424,13 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsIm JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getSchemaMetaDataImp(JNIEnv *env, jobject jobj, jlong con, jlong res, jobject arrayListObj) { - TAOS *tscon = (TAOS *)con; + TAOS * tscon = (TAOS *)con; int32_t code = check_for_params(jobj, con, res); if (code != JNI_SUCCESS) { return code; } - TAOS_RES* tres = (TAOS_RES*) res; + TAOS_RES * tres = (TAOS_RES *)res; TAOS_FIELD *fields = taos_fetch_fields(tres); int32_t num_fields = taos_num_fields(tres); @@ -452,7 +484,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn int32_t numOfFields = taos_num_fields(result); if (numOfFields == 0) { - jniError("jobj:%p, conn:%p, resultset:%p, fields size %d", jobj, tscon, (void*)res, numOfFields); + jniError("jobj:%p, conn:%p, resultset:%p, fields size %d", jobj, tscon, (void *)res, numOfFields); return JNI_NUM_OF_FIELDS_0; } @@ -460,7 +492,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn if (row == NULL) { int code = taos_errno(result); if (code == TSDB_CODE_SUCCESS) { - jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void*)res, numOfFields); + jniDebug("jobj:%p, conn:%p, resultset:%p, fields size is %d, fetch row to the end", jobj, tscon, (void *)res, + numOfFields); return JNI_FETCH_END; } else { jniDebug("jobj:%p, conn:%p, interrupted query", jobj, tscon); @@ -468,7 +501,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn } } - int32_t* length = taos_fetch_lengths(result); + int32_t *length = taos_fetch_lengths(result); char tmp[TSDB_MAX_BYTES_PER_ROW] = {0}; @@ -533,7 +566,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn } JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNIEnv *env, jobject jobj, jlong con, - jlong res, jobject rowobj) { + jlong res, jobject rowobj) { TAOS * tscon = (TAOS *)con; int32_t code = check_for_params(jobj, con, res); if (code != JNI_SUCCESS) { @@ -564,8 +597,13 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNI (*env)->CallVoidMethod(env, rowobj, g_blockdataSetNumOfColsFp, (jint)numOfFields); for (int i = 0; i < numOfFields; i++) { - (*env)->CallVoidMethod(env, rowobj, g_blockdataSetByteArrayFp, i, fields[i].bytes * numOfRows, - jniFromNCharToByteArray(env, (char *)row[i], fields[i].bytes * numOfRows)); + int bytes = fields[i].bytes; + + if (fields[i].type == TSDB_DATA_TYPE_BINARY || fields[i].type == TSDB_DATA_TYPE_NCHAR) { + bytes += 2; + } + (*env)->CallVoidMethod(env, rowobj, g_blockdataSetByteArrayFp, i, bytes * numOfRows, + jniFromNCharToByteArray(env, (char *)row[i], bytes * numOfRows)); } return JNI_SUCCESS; @@ -585,7 +623,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeConnectionIm } JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_subscribeImp(JNIEnv *env, jobject jobj, jlong con, - jboolean restart, jstring jtopic, jstring jsql, jint jinterval) { + jboolean restart, jstring jtopic, + jstring jsql, jint jinterval) { jlong sub = 0; TAOS *taos = (TAOS *)con; char *topic = NULL; @@ -682,8 +721,8 @@ JNIEXPORT jstring JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getTsCharset(J * @param res the TAOS_RES object, i.e. the SSqlObject * @return precision 0:ms 1:us 2:ns */ -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultTimePrecisionImp(JNIEnv *env, jobject jobj, jlong con, - jlong res) { +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultTimePrecisionImp(JNIEnv *env, jobject jobj, + jlong con, jlong res) { TAOS *tscon = (TAOS *)con; if (tscon == NULL) { jniError("jobj:%p, connection is closed", jobj); @@ -699,7 +738,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getResultTimePrec return taos_result_precision(result); } -JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp(JNIEnv *env, jobject jobj, jbyteArray jsql, jlong con) { +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp(JNIEnv *env, jobject jobj, + jbyteArray jsql, jlong con) { TAOS *tscon = (TAOS *)con; if (tscon == NULL) { jniError("jobj:%p, connection already closed", jobj); @@ -713,7 +753,7 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp(J jsize len = (*env)->GetArrayLength(env, jsql); - char *str = (char *) calloc(1, sizeof(char) * (len + 1)); + char *str = (char *)calloc(1, sizeof(char) * (len + 1)); if (str == NULL) { jniError("jobj:%p, conn:%p, alloc memory failed", jobj, tscon); return JNI_OUT_OF_MEMORY; @@ -724,25 +764,27 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp(J // todo handle error } - TAOS_STMT* pStmt = taos_stmt_init(tscon); - int32_t code = taos_stmt_prepare(pStmt, str, len); + TAOS_STMT *pStmt = taos_stmt_init(tscon); + int32_t code = taos_stmt_prepare(pStmt, str, len); tfree(str); if (code != TSDB_CODE_SUCCESS) { jniError("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); return JNI_TDENGINE_ERROR; } - return (jlong) pStmt; + return (jlong)pStmt; } -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameImp(JNIEnv *env, jobject jobj, jlong stmt, jstring jname, jlong conn) { +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameImp(JNIEnv *env, jobject jobj, + jlong stmt, jstring jname, + jlong conn) { TAOS *tsconn = (TAOS *)conn; if (tsconn == NULL) { jniError("jobj:%p, connection already closed", jobj); return JNI_CONNECTION_NULL; } - TAOS_STMT* pStmt = (TAOS_STMT*) stmt; + TAOS_STMT *pStmt = (TAOS_STMT *)stmt; if (pStmt == NULL) { jniError("jobj:%p, conn:%p, invalid stmt handle", jobj, tsconn); return JNI_SQL_NULL; @@ -750,7 +792,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameI const char *name = (*env)->GetStringUTFChars(env, jname, NULL); - int32_t code = taos_stmt_set_tbname((void*)stmt, name); + int32_t code = taos_stmt_set_tbname((void *)stmt, name); if (code != TSDB_CODE_SUCCESS) { (*env)->ReleaseStringUTFChars(env, jname, name); @@ -763,8 +805,9 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameI return JNI_SUCCESS; } -JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(JNIEnv *env, jobject jobj, jlong stmt, - jbyteArray colDataList, jbyteArray lengthList, jbyteArray nullList, jint dataType, jint dataBytes, jint numOfRows, jint colIndex, jlong con) { +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp( + JNIEnv *env, jobject jobj, jlong stmt, jbyteArray colDataList, jbyteArray lengthList, jbyteArray nullList, + jint dataType, jint dataBytes, jint numOfRows, jint colIndex, jlong con) { TAOS *tscon = (TAOS *)con; if (tscon == NULL) { jniError("jobj:%p, connection already closed", jobj); @@ -798,14 +841,14 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(J } // bind multi-rows with only one invoke. - TAOS_MULTI_BIND* b = calloc(1, sizeof(TAOS_MULTI_BIND)); + TAOS_MULTI_BIND *b = calloc(1, sizeof(TAOS_MULTI_BIND)); - b->num = numOfRows; - b->buffer_type = dataType; // todo check data type - b->buffer_length = IS_VAR_DATA_TYPE(dataType)? dataBytes:tDataTypes[dataType].bytes; - b->is_null = nullArray; - b->buffer = colBuf; - b->length = (int32_t*)lengthArray; + b->num = numOfRows; + b->buffer_type = dataType; // todo check data type + b->buffer_length = IS_VAR_DATA_TYPE(dataType) ? dataBytes : tDataTypes[dataType].bytes; + b->is_null = nullArray; + b->buffer = colBuf; + b->length = (int32_t *)lengthArray; // set the length and is_null array if (!IS_VAR_DATA_TYPE(dataType)) { @@ -829,14 +872,15 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp(J return JNI_SUCCESS; } -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(JNIEnv *env, jobject jobj, jlong stmt, jlong con) { +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(JNIEnv *env, jobject jobj, jlong stmt, + jlong con) { TAOS *tscon = (TAOS *)con; if (tscon == NULL) { jniError("jobj:%p, connection already closed", jobj); return JNI_CONNECTION_NULL; } - TAOS_STMT *pStmt = (TAOS_STMT*) stmt; + TAOS_STMT *pStmt = (TAOS_STMT *)stmt; if (pStmt == NULL) { jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon); return JNI_SQL_NULL; @@ -853,14 +897,15 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(J return JNI_SUCCESS; } -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt, jlong con) { +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv *env, jobject jobj, jlong stmt, + jlong con) { TAOS *tscon = (TAOS *)con; if (tscon == NULL) { jniError("jobj:%p, connection already closed", jobj); return JNI_CONNECTION_NULL; } - TAOS_STMT *pStmt = (TAOS_STMT*) stmt; + TAOS_STMT *pStmt = (TAOS_STMT *)stmt; if (pStmt == NULL) { jniError("jobj:%p, conn:%p, invalid stmt", jobj, tscon); return JNI_SQL_NULL; @@ -876,15 +921,16 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv return JNI_SUCCESS; } -JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp(JNIEnv *env, jobject jobj, - jlong stmt, jstring tableName, jint numOfTags, jbyteArray tags, jbyteArray typeList, jbyteArray lengthList, jbyteArray nullList, jlong conn) { +JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsImp( + JNIEnv *env, jobject jobj, jlong stmt, jstring tableName, jint numOfTags, jbyteArray tags, jbyteArray typeList, + jbyteArray lengthList, jbyteArray nullList, jlong conn) { TAOS *tsconn = (TAOS *)conn; if (tsconn == NULL) { jniError("jobj:%p, connection already closed", jobj); return JNI_CONNECTION_NULL; } - TAOS_STMT* pStmt = (TAOS_STMT*) stmt; + TAOS_STMT *pStmt = (TAOS_STMT *)stmt; if (pStmt == NULL) { jniError("jobj:%p, conn:%p, invalid stmt handle", jobj, tsconn); return JNI_SQL_NULL; @@ -898,39 +944,39 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsI } len = (*env)->GetArrayLength(env, lengthList); - int64_t *lengthArray = (int64_t*) calloc(1, len); - (*env)->GetByteArrayRegion(env, lengthList, 0, len, (jbyte*) lengthArray); + int64_t *lengthArray = (int64_t *)calloc(1, len); + (*env)->GetByteArrayRegion(env, lengthList, 0, len, (jbyte *)lengthArray); if ((*env)->ExceptionCheck(env)) { } len = (*env)->GetArrayLength(env, typeList); - char *typeArray = (char*) calloc(1, len); - (*env)->GetByteArrayRegion(env, typeList, 0, len, (jbyte*) typeArray); + char *typeArray = (char *)calloc(1, len); + (*env)->GetByteArrayRegion(env, typeList, 0, len, (jbyte *)typeArray); if ((*env)->ExceptionCheck(env)) { } len = (*env)->GetArrayLength(env, nullList); - int32_t *nullArray = (int32_t*) calloc(1, len); - (*env)->GetByteArrayRegion(env, nullList, 0, len, (jbyte*) nullArray); + int32_t *nullArray = (int32_t *)calloc(1, len); + (*env)->GetByteArrayRegion(env, nullList, 0, len, (jbyte *)nullArray); if ((*env)->ExceptionCheck(env)) { } const char *name = (*env)->GetStringUTFChars(env, tableName, NULL); - char* curTags = tagsData; + char * curTags = tagsData; TAOS_BIND *tagsBind = calloc(numOfTags, sizeof(TAOS_BIND)); - for(int32_t i = 0; i < numOfTags; ++i) { + for (int32_t i = 0; i < numOfTags; ++i) { tagsBind[i].buffer_type = typeArray[i]; - tagsBind[i].buffer = curTags; + tagsBind[i].buffer = curTags; tagsBind[i].is_null = &nullArray[i]; - tagsBind[i].length = (uintptr_t*) &lengthArray[i]; + tagsBind[i].length = (uintptr_t *)&lengthArray[i]; curTags += lengthArray[i]; } - int32_t code = taos_stmt_set_tbname_tags((void*)stmt, name, tagsBind); + int32_t code = taos_stmt_set_tbname_tags((void *)stmt, name, tagsBind); - int32_t nTags = (int32_t) numOfTags; + int32_t nTags = (int32_t)numOfTags; jniDebug("jobj:%p, conn:%p, set table name:%s, numOfTags:%d", jobj, tsconn, name, nTags); tfree(tagsData); @@ -948,28 +994,28 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsI } JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JNIEnv *env, jobject jobj, - jobjectArray lines, jlong conn) { + jobjectArray lines, jlong conn) { TAOS *taos = (TAOS *)conn; if (taos == NULL) { jniError("jobj:%p, connection already closed", jobj); return JNI_CONNECTION_NULL; } - int numLines = (*env)->GetArrayLength(env, lines); - char** c_lines = calloc(numLines, sizeof(char*)); + int numLines = (*env)->GetArrayLength(env, lines); + char **c_lines = calloc(numLines, sizeof(char *)); if (c_lines == NULL) { jniError("c_lines:%p, alloc memory failed", c_lines); return JNI_OUT_OF_MEMORY; } for (int i = 0; i < numLines; ++i) { - jstring line = (jstring) ((*env)->GetObjectArrayElement(env, lines, i)); - c_lines[i] = (char*)(*env)->GetStringUTFChars(env, line, 0); + jstring line = (jstring)((*env)->GetObjectArrayElement(env, lines, i)); + c_lines[i] = (char *)(*env)->GetStringUTFChars(env, line, 0); } int code = taos_insert_lines(taos, c_lines, numLines); for (int i = 0; i < numLines; ++i) { - jstring line = (jstring) ((*env)->GetObjectArrayElement(env, lines, i)); + jstring line = (jstring)((*env)->GetObjectArrayElement(env, lines, i)); (*env)->ReleaseStringUTFChars(env, line, c_lines[i]); } diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c index eaad78333160a8c7dc0622ec5c670cd28bc517c8..6b12cd0da04c0f791201182c793d647fc54c00b1 100644 --- a/src/client/src/tscAsync.c +++ b/src/client/src/tscAsync.c @@ -363,15 +363,6 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) { } if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_STMT_INSERT)) { // stmt insert - STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); - code = tscGetTableMeta(pSql, pTableMetaInfo); - if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) { - taosReleaseRef(tscObjRef, pSql->self); - return; - } else { - assert(code == TSDB_CODE_SUCCESS); - } - (*pSql->fp)(pSql->param, pSql, code); } else if (TSDB_QUERY_HAS_TYPE(pCmd->insertParam.insertType, TSDB_QUERY_TYPE_FILE_INSERT)) { // file insert tscImportDataFromFile(pSql); diff --git a/src/client/src/tscGlobalmerge.c b/src/client/src/tscGlobalmerge.c index e696d54abd91ad45eccae23f2650088dab3c91ce..6acbfe3e8929c9a5a46ed0370f6cfb883988ef3e 100644 --- a/src/client/src/tscGlobalmerge.c +++ b/src/client/src/tscGlobalmerge.c @@ -35,6 +35,7 @@ typedef struct SCompareParam { static bool needToMerge(SSDataBlock* pBlock, SArray* columnIndexList, int32_t index, char **buf) { int32_t ret = 0; + size_t size = taosArrayGetSize(columnIndexList); if (size > 0) { ret = compare_aRv(pBlock, columnIndexList, (int32_t) size, index, buf, TSDB_ORDER_ASC); @@ -564,9 +565,11 @@ static void savePrevOrderColumns(char** prevRow, SArray* pColumnList, SSDataBloc (*hasPrev) = true; } +// tsdb_func_tag function only produce one row of result. Therefore, we need to copy the +// output value to multiple rows static void setTagValueForMultipleRows(SQLFunctionCtx* pCtx, int32_t numOfOutput, int32_t numOfRows) { if (numOfRows <= 1) { - return ; + return; } for (int32_t k = 0; k < numOfOutput; ++k) { @@ -574,12 +577,49 @@ static void setTagValueForMultipleRows(SQLFunctionCtx* pCtx, int32_t numOfOutput continue; } - int32_t inc = numOfRows - 1; // tsdb_func_tag function only produce one row of result - char* src = pCtx[k].pOutput; + char* src = pCtx[k].pOutput; + char* dst = pCtx[k].pOutput + pCtx[k].outputBytes; + + // Let's start from the second row, as the first row has result value already. + for (int32_t i = 1; i < numOfRows; ++i) { + memcpy(dst, src, (size_t)pCtx[k].outputBytes); + dst += pCtx[k].outputBytes; + } + } +} + +static void doMergeResultImpl(SMultiwayMergeInfo* pInfo, SQLFunctionCtx *pCtx, int32_t numOfExpr, int32_t rowIndex, char** pDataPtr) { + for (int32_t j = 0; j < numOfExpr; ++j) { + pCtx[j].pInput = pDataPtr[j] + pCtx[j].inputBytes * rowIndex; + } + + for (int32_t j = 0; j < numOfExpr; ++j) { + int32_t functionId = pCtx[j].functionId; + if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) { + continue; + } + + if (functionId < 0) { + SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1); + doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE); + } else { + aAggs[functionId].mergeFunc(&pCtx[j]); + } + } +} + +static void doFinalizeResultImpl(SMultiwayMergeInfo* pInfo, SQLFunctionCtx *pCtx, int32_t numOfExpr) { + for(int32_t j = 0; j < numOfExpr; ++j) { + int32_t functionId = pCtx[j].functionId; + if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) { + continue; + } - for (int32_t i = 0; i < inc; ++i) { - pCtx[k].pOutput += pCtx[k].outputBytes; - memcpy(pCtx[k].pOutput, src, (size_t)pCtx[k].outputBytes); + if (functionId < 0) { + SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1); + doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE); + } else { + aAggs[functionId].xFinalize(&pCtx[j]); } } } @@ -588,52 +628,18 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD SMultiwayMergeInfo* pInfo = pOperator->info; SQLFunctionCtx* pCtx = pInfo->binfo.pCtx; - char** add = calloc(pBlock->info.numOfCols, POINTER_BYTES); + char** addrPtr = calloc(pBlock->info.numOfCols, POINTER_BYTES); for(int32_t i = 0; i < pBlock->info.numOfCols; ++i) { - add[i] = pCtx[i].pInput; + addrPtr[i] = pCtx[i].pInput; pCtx[i].size = 1; } for(int32_t i = 0; i < pBlock->info.rows; ++i) { if (pInfo->hasPrev) { if (needToMerge(pBlock, pInfo->orderColumnList, i, pInfo->prevRow)) { - for (int32_t j = 0; j < numOfExpr; ++j) { - pCtx[j].pInput = add[j] + pCtx[j].inputBytes * i; - } - - for (int32_t j = 0; j < numOfExpr; ++j) { - int32_t functionId = pCtx[j].functionId; - if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) { - continue; - } - - if (functionId < 0) { - SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1); - - doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE); - - continue; - } - - aAggs[functionId].mergeFunc(&pCtx[j]); - } + doMergeResultImpl(pInfo, pCtx, numOfExpr, i, addrPtr); } else { - for(int32_t j = 0; j < numOfExpr; ++j) { // TODO refactor - int32_t functionId = pCtx[j].functionId; - if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) { - continue; - } - - if (functionId < 0) { - SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1); - - doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE); - - continue; - } - - aAggs[functionId].xFinalize(&pCtx[j]); - } + doFinalizeResultImpl(pInfo, pCtx, numOfExpr); int32_t numOfRows = getNumOfResult(pOperator->pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput); setTagValueForMultipleRows(pCtx, pOperator->numOfOutput, numOfRows); @@ -643,7 +649,7 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD for(int32_t j = 0; j < numOfExpr; ++j) { pCtx[j].pOutput += (pCtx[j].outputBytes * numOfRows); if (pCtx[j].functionId == TSDB_FUNC_TOP || pCtx[j].functionId == TSDB_FUNC_BOTTOM) { - pCtx[j].ptsOutputBuf = pCtx[0].pOutput; + if(j > 0) pCtx[j].ptsOutputBuf = pCtx[j - 1].pOutput; } } @@ -655,48 +661,10 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD aAggs[pCtx[j].functionId].init(&pCtx[j], pCtx[j].resultInfo); } - for (int32_t j = 0; j < numOfExpr; ++j) { - pCtx[j].pInput = add[j] + pCtx[j].inputBytes * i; - } - - for (int32_t j = 0; j < numOfExpr; ++j) { - int32_t functionId = pCtx[j].functionId; - if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) { - continue; - } - - if (functionId < 0) { - SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1); - - doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE); - - continue; - } - - aAggs[functionId].mergeFunc(&pCtx[j]); - } + doMergeResultImpl(pInfo, pCtx, numOfExpr, i, addrPtr); } } else { - for (int32_t j = 0; j < numOfExpr; ++j) { - pCtx[j].pInput = add[j] + pCtx[j].inputBytes * i; - } - - for (int32_t j = 0; j < numOfExpr; ++j) { - int32_t functionId = pCtx[j].functionId; - if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) { - continue; - } - - if (functionId < 0) { - SUdfInfo* pUdfInfo = taosArrayGet(pInfo->udfInfo, -1 * functionId - 1); - - doInvokeUdf(pUdfInfo, &pCtx[j], 0, TSDB_UDF_FUNC_MERGE); - - continue; - } - - aAggs[functionId].mergeFunc(&pCtx[j]); - } + doMergeResultImpl(pInfo, pCtx, numOfExpr, i, addrPtr); } savePrevOrderColumns(pInfo->prevRow, pInfo->orderColumnList, pBlock, i, &pInfo->hasPrev); @@ -704,11 +672,11 @@ static void doExecuteFinalMerge(SOperatorInfo* pOperator, int32_t numOfExpr, SSD { for(int32_t i = 0; i < pBlock->info.numOfCols; ++i) { - pCtx[i].pInput = add[i]; + pCtx[i].pInput = addrPtr[i]; } } - tfree(add); + tfree(addrPtr); } static bool isAllSourcesCompleted(SGlobalMerger *pMerger) { @@ -816,6 +784,8 @@ SSDataBlock* doMultiwayMergeSort(void* param, bool* newgroup) { SLocalDataSource *pOneDataSrc = pMerger->pLocalDataSrc[pTree->pNode[0].index]; bool sameGroup = true; if (pInfo->hasPrev) { + + // todo refactor extract method int32_t numOfCols = (int32_t)taosArrayGetSize(pInfo->orderColumnList); // if this row belongs to current result set group @@ -955,9 +925,10 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) { break; } + bool sameGroup = true; if (pAggInfo->hasGroupColData) { - bool sameGroup = isSameGroup(pAggInfo->groupColumnList, pBlock, pAggInfo->currentGroupColData); - if (!sameGroup) { + sameGroup = isSameGroup(pAggInfo->groupColumnList, pBlock, pAggInfo->currentGroupColData); + if (!sameGroup && !pAggInfo->multiGroupResults) { *newgroup = true; pAggInfo->hasDataBlockForNewGroup = true; pAggInfo->pExistBlock = pBlock; @@ -976,26 +947,10 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) { } if (handleData) { // data in current group is all handled - for(int32_t j = 0; j < pOperator->numOfOutput; ++j) { - int32_t functionId = pAggInfo->binfo.pCtx[j].functionId; - if (functionId == TSDB_FUNC_TAG_DUMMY || functionId == TSDB_FUNC_TS_DUMMY) { - continue; - } - - if (functionId < 0) { - SUdfInfo* pUdfInfo = taosArrayGet(pAggInfo->udfInfo, -1 * functionId - 1); - - doInvokeUdf(pUdfInfo, &pAggInfo->binfo.pCtx[j], 0, TSDB_UDF_FUNC_FINALIZE); - - continue; - } - - aAggs[functionId].xFinalize(&pAggInfo->binfo.pCtx[j]); - } - + doFinalizeResultImpl(pAggInfo, pAggInfo->binfo.pCtx, pOperator->numOfOutput); int32_t numOfRows = getNumOfResult(pOperator->pRuntimeEnv, pAggInfo->binfo.pCtx, pOperator->numOfOutput); - pAggInfo->binfo.pRes->info.rows += numOfRows; + pAggInfo->binfo.pRes->info.rows += numOfRows; setTagValueForMultipleRows(pAggInfo->binfo.pCtx, pOperator->numOfOutput, numOfRows); } @@ -1019,71 +974,127 @@ SSDataBlock* doGlobalAggregate(void* param, bool* newgroup) { return (pRes->info.rows != 0)? pRes:NULL; } -static SSDataBlock* skipGroupBlock(SOperatorInfo* pOperator, bool* newgroup) { - SSLimitOperatorInfo *pInfo = pOperator->info; - assert(pInfo->currentGroupOffset >= 0); +static void doHandleDataInCurrentGroup(SSLimitOperatorInfo* pInfo, SSDataBlock* pBlock, int32_t rowIndex) { + if (pInfo->currentOffset > 0) { + pInfo->currentOffset -= 1; + } else { + // discard the data rows in current group + if (pInfo->limit.limit < 0 || (pInfo->limit.limit >= 0 && pInfo->rowsTotal < pInfo->limit.limit)) { + size_t num1 = taosArrayGetSize(pInfo->pRes->pDataBlock); + for (int32_t i = 0; i < num1; ++i) { + SColumnInfoData *pColInfoData = taosArrayGet(pBlock->pDataBlock, i); + SColumnInfoData *pDstInfoData = taosArrayGet(pInfo->pRes->pDataBlock, i); - SSDataBlock* pBlock = NULL; - if (pInfo->currentGroupOffset == 0) { - publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); - pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); - publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); - if (pBlock == NULL) { - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; - } + SColumnInfo *pColInfo = &pColInfoData->info; + + char *pSrc = rowIndex * pColInfo->bytes + (char *)pColInfoData->pData; + char *pDst = (char *)pDstInfoData->pData + (pInfo->pRes->info.rows * pColInfo->bytes); - if (*newgroup == false && pInfo->limit.limit > 0 && pInfo->rowsTotal >= pInfo->limit.limit) { - while ((*newgroup) == false) { // ignore the remain blocks - publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); - pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); - publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); - if (pBlock == NULL) { - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; - return NULL; - } + memcpy(pDst, pSrc, pColInfo->bytes); } + + pInfo->rowsTotal += 1; + pInfo->pRes->info.rows += 1; } + } +} + +static void ensureOutputBuf(SSLimitOperatorInfo * pInfo, SSDataBlock *pResultBlock, int32_t numOfRows) { + if (pInfo->capacity < pResultBlock->info.rows + numOfRows) { + int32_t total = pResultBlock->info.rows + numOfRows; + + size_t num = taosArrayGetSize(pResultBlock->pDataBlock); + for (int32_t i = 0; i < num; ++i) { + SColumnInfoData *pInfoData = taosArrayGet(pResultBlock->pDataBlock, i); + + char *tmp = realloc(pInfoData->pData, total * pInfoData->info.bytes); + if (tmp != NULL) { + pInfoData->pData = tmp; + } else { + // todo handle the malloc failure + } - return pBlock; + pInfo->capacity = total; + pInfo->threshold = (int64_t)(total * 0.8); + } } +} - publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); - pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); - publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); +enum { + BLOCK_NEW_GROUP = 1, + BLOCK_NO_GROUP = 2, + BLOCK_SAME_GROUP = 3, +}; - if (pBlock == NULL) { - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; - return NULL; +static int32_t doSlimitImpl(SOperatorInfo* pOperator, SSLimitOperatorInfo* pInfo, SSDataBlock* pBlock) { + int32_t rowIndex = 0; + + while (rowIndex < pBlock->info.rows) { + int32_t numOfCols = (int32_t)taosArrayGetSize(pInfo->orderColumnList); + + bool samegroup = true; + if (pInfo->hasPrev) { + for (int32_t i = 0; i < numOfCols; ++i) { + SColIndex *pIndex = taosArrayGet(pInfo->orderColumnList, i); + SColumnInfoData *pColInfoData = taosArrayGet(pBlock->pDataBlock, pIndex->colIndex); + + SColumnInfo *pColInfo = &pColInfoData->info; + + char *d = rowIndex * pColInfo->bytes + (char *)pColInfoData->pData; + int32_t ret = columnValueAscendingComparator(pInfo->prevRow[i], d, pColInfo->type, pColInfo->bytes); + if (ret != 0) { // it is a new group + samegroup = false; + break; + } + } } - while(1) { - if (*newgroup) { - pInfo->currentGroupOffset -= 1; - *newgroup = false; + if (!samegroup || !pInfo->hasPrev) { + pInfo->ignoreCurrentGroup = false; + savePrevOrderColumns(pInfo->prevRow, pInfo->orderColumnList, pBlock, rowIndex, &pInfo->hasPrev); + + pInfo->currentOffset = pInfo->limit.offset; // reset the offset value for a new group + pInfo->rowsTotal = 0; + + if (pInfo->currentGroupOffset > 0) { + pInfo->ignoreCurrentGroup = true; + pInfo->currentGroupOffset -= 1; // now we are in the next group data + rowIndex += 1; + continue; + } + + // A new group has arrived according to the result rows, and the group limitation has already reached. + // Let's jump out of current loop and return immediately. + if (pInfo->slimit.limit >= 0 && pInfo->groupTotal >= pInfo->slimit.limit) { + setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); + pOperator->status = OP_EXEC_DONE; + return BLOCK_NO_GROUP; } - while ((*newgroup) == false) { - publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); - pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); - publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); + pInfo->groupTotal += 1; - if (pBlock == NULL) { - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; - return NULL; - } + // data in current group not allowed, return if current result does not belong to the previous group.And there + // are results exists in current SSDataBlock + if (!pInfo->multigroupResult && !samegroup && pInfo->pRes->info.rows > 0) { + return BLOCK_NEW_GROUP; } - // now we have got the first data block of the next group. - if (pInfo->currentGroupOffset == 0) { - return pBlock; + doHandleDataInCurrentGroup(pInfo, pBlock, rowIndex); + + } else { // handle the offset in the same group + // All the data in current group needs to be discarded, due to the limit parameter in the SQL statement + if (pInfo->ignoreCurrentGroup) { + rowIndex += 1; + continue; } + + doHandleDataInCurrentGroup(pInfo, pBlock, rowIndex); } - return NULL; + rowIndex += 1; + } + + return BLOCK_SAME_GROUP; } SSDataBlock* doSLimit(void* param, bool* newgroup) { @@ -1093,63 +1104,41 @@ SSDataBlock* doSLimit(void* param, bool* newgroup) { } SSLimitOperatorInfo *pInfo = pOperator->info; + pInfo->pRes->info.rows = 0; - SSDataBlock *pBlock = NULL; - while (1) { - pBlock = skipGroupBlock(pOperator, newgroup); - if (pBlock == NULL) { - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; - return NULL; - } - - if (*newgroup) { // a new group arrives - pInfo->groupTotal += 1; - pInfo->rowsTotal = 0; - pInfo->currentOffset = pInfo->limit.offset; - } + if (pInfo->pPrevBlock != NULL) { + ensureOutputBuf(pInfo, pInfo->pRes, pInfo->pPrevBlock->info.rows); + int32_t ret = doSlimitImpl(pOperator, pInfo, pInfo->pPrevBlock); + assert(ret != BLOCK_NEW_GROUP); - assert(pInfo->currentGroupOffset == 0); - - if (pInfo->currentOffset >= pBlock->info.rows) { - pInfo->currentOffset -= pBlock->info.rows; - } else { - if (pInfo->currentOffset == 0) { - break; - } - - int32_t remain = (int32_t)(pBlock->info.rows - pInfo->currentOffset); - pBlock->info.rows = remain; + pInfo->pPrevBlock = NULL; + } - // move the remain rows of this data block to the front. - for (int32_t i = 0; i < pBlock->info.numOfCols; ++i) { - SColumnInfoData *pColInfoData = taosArrayGet(pBlock->pDataBlock, i); + assert(pInfo->currentGroupOffset >= 0); - int16_t bytes = pColInfoData->info.bytes; - memmove(pColInfoData->pData, pColInfoData->pData + bytes * pInfo->currentOffset, remain * bytes); - } + while(1) { + publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC); + SSDataBlock *pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup); + publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); - pInfo->currentOffset = 0; - break; + if (pBlock == NULL) { + return pInfo->pRes->info.rows == 0 ? NULL : pInfo->pRes; } - } - - if (pInfo->slimit.limit > 0 && pInfo->groupTotal > pInfo->slimit.limit) { // reach the group limit, abort - return NULL; - } - if (pInfo->limit.limit > 0 && (pInfo->rowsTotal + pBlock->info.rows >= pInfo->limit.limit)) { - pBlock->info.rows = (int32_t)(pInfo->limit.limit - pInfo->rowsTotal); - pInfo->rowsTotal = pInfo->limit.limit; + ensureOutputBuf(pInfo, pInfo->pRes, pBlock->info.rows); + int32_t ret = doSlimitImpl(pOperator, pInfo, pBlock); + if (ret == BLOCK_NEW_GROUP) { + pInfo->pPrevBlock = pBlock; + return pInfo->pRes; + } - if (pInfo->slimit.limit > 0 && pInfo->groupTotal >= pInfo->slimit.limit) { - pOperator->status = OP_EXEC_DONE; + if (pOperator->status == OP_EXEC_DONE) { + return pInfo->pRes->info.rows == 0 ? NULL : pInfo->pRes; } - // setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - } else { - pInfo->rowsTotal += pBlock->info.rows; + // now the number of rows in current group is enough, let's return to the invoke function + if (pInfo->pRes->info.rows > pInfo->threshold) { + return pInfo->pRes; + } } - - return pBlock; } diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c index f1ca6b77545f3884cf272760342f5516a7b5746c..1bf27e6cad1d57fdfd4b786d1cdcea981bf3333b 100644 --- a/src/client/src/tscParseInsert.c +++ b/src/client/src/tscParseInsert.c @@ -51,20 +51,18 @@ int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, uint3 } } + // default compareStat is ROW_COMPARE_NO_NEED if (nBoundCols == 0) { // file input pBuilder->memRowType = SMEM_ROW_DATA; - pBuilder->compareStat = ROW_COMPARE_NO_NEED; return TSDB_CODE_SUCCESS; } else { float boundRatio = ((float)nBoundCols / (float)nCols); if (boundRatio < KVRatioKV) { pBuilder->memRowType = SMEM_ROW_KV; - pBuilder->compareStat = ROW_COMPARE_NO_NEED; return TSDB_CODE_SUCCESS; } else if (boundRatio > KVRatioData) { pBuilder->memRowType = SMEM_ROW_DATA; - pBuilder->compareStat = ROW_COMPARE_NO_NEED; return TSDB_CODE_SUCCESS; } pBuilder->compareStat = ROW_COMPARE_NEED; @@ -76,7 +74,6 @@ int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, uint3 } } - pBuilder->dataRowInitLen = TD_MEM_ROW_DATA_HEAD_SIZE + allNullLen; pBuilder->kvRowInitLen = TD_MEM_ROW_KV_HEAD_SIZE + nBoundCols * sizeof(SColIdx); if (nRows > 0) { @@ -86,7 +83,7 @@ int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, uint3 } for (int i = 0; i < nRows; ++i) { - (pBuilder->rowInfo + i)->dataLen = pBuilder->dataRowInitLen; + (pBuilder->rowInfo + i)->dataLen = TD_MEM_ROW_DATA_HEAD_SIZE + allNullLen; (pBuilder->rowInfo + i)->kvLen = pBuilder->kvRowInitLen; } } @@ -460,7 +457,7 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i STableMeta * pTableMeta = pDataBlocks->pTableMeta; SSchema * schema = tscGetTableSchema(pTableMeta); SMemRowBuilder * pBuilder = &pDataBlocks->rowBuilder; - int32_t dataLen = pBuilder->dataRowInitLen; + int32_t dataLen = spd->allNullLen + TD_MEM_ROW_DATA_HEAD_SIZE; int32_t kvLen = pBuilder->kvRowInitLen; bool isParseBindParam = false; @@ -809,13 +806,12 @@ int tscSortRemoveDataBlockDupRows(STableDataBlocks *dataBuf, SBlockKeyInfo *pBlk // allocate memory size_t nAlloc = nRows * sizeof(SBlockKeyTuple); if (pBlkKeyInfo->pKeyTuple == NULL || pBlkKeyInfo->maxBytesAlloc < nAlloc) { - size_t nRealAlloc = nAlloc + 10 * sizeof(SBlockKeyTuple); - char * tmp = trealloc(pBlkKeyInfo->pKeyTuple, nRealAlloc); + char *tmp = trealloc(pBlkKeyInfo->pKeyTuple, nAlloc); if (tmp == NULL) { return TSDB_CODE_TSC_OUT_OF_MEMORY; } pBlkKeyInfo->pKeyTuple = (SBlockKeyTuple *)tmp; - pBlkKeyInfo->maxBytesAlloc = (int32_t)nRealAlloc; + pBlkKeyInfo->maxBytesAlloc = (int32_t)nAlloc; } memset(pBlkKeyInfo->pKeyTuple, 0, nAlloc); @@ -1697,7 +1693,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int32_t numOfRow STableMeta * pTableMeta = pTableMetaInfo->pTableMeta; STableComInfo tinfo = tscGetTableInfo(pTableMeta); - SInsertStatementParam* pInsertParam = &pCmd->insertParam; + SInsertStatementParam *pInsertParam = &pCmd->insertParam; destroyTableNameList(pInsertParam); pInsertParam->pDataBlocks = tscDestroyBlockArrayList(pInsertParam->pDataBlocks); @@ -1726,12 +1722,6 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int32_t numOfRow goto _error; } - if (TSDB_CODE_SUCCESS != - (ret = initMemRowBuilder(&pTableDataBlock->rowBuilder, 0, tinfo.numOfColumns, pTableDataBlock->numOfParams, - pTableDataBlock->boundColumnInfo.allNullLen))) { - goto _error; - } - while ((readLen = tgetline(&line, &n, fp)) != -1) { if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) { line[--readLen] = 0; @@ -1787,6 +1777,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int32_t numOfRow } _error: + pParentSql->res.code = code; tfree(tokenBuf); tfree(line); taos_free_result(pSql); diff --git a/src/client/src/tscParseLineProtocol.c b/src/client/src/tscParseLineProtocol.c index 2a16f1aad6525a25da652f643dc7b7f91debd432..c9ad7361efa3ade3e3e221a0128a5ad1f3e22ccb 100644 --- a/src/client/src/tscParseLineProtocol.c +++ b/src/client/src/tscParseLineProtocol.c @@ -17,6 +17,7 @@ #include "tscLog.h" #include "taos.h" +#include "tscParseLine.h" typedef struct { char sTableName[TSDB_TABLE_NAME_LEN]; @@ -27,44 +28,19 @@ typedef struct { uint8_t precision; } SSmlSTableSchema; -typedef struct { - char* key; - uint8_t type; - int16_t length; - char* value; - - //=================================== - uint32_t fieldSchemaIdx; -} TAOS_SML_KV; - -typedef struct { - char* stableName; - - char* childTableName; - TAOS_SML_KV* tags; - int32_t tagNum; - - // first kv must be timestamp - TAOS_SML_KV* fields; - int32_t fieldNum; - - //================================ - uint32_t schemaIdx; -} TAOS_SML_DATA_POINT; +//================================================================================================= -typedef enum { - SML_TIME_STAMP_NOW, - SML_TIME_STAMP_SECONDS, - SML_TIME_STAMP_MILLI_SECONDS, - SML_TIME_STAMP_MICRO_SECONDS, - SML_TIME_STAMP_NANO_SECONDS -} SMLTimeStampType; +static uint64_t linesSmlHandleId = 0; -typedef struct { +uint64_t genLinesSmlId() { uint64_t id; -} SSmlLinesInfo; -//================================================================================================= + do { + id = atomic_add_fetch_64(&linesSmlHandleId, 1); + } while (id == 0); + + return id; +} int compareSmlColKv(const void* p1, const void* p2) { TAOS_SML_KV* kv1 = (TAOS_SML_KV*)p1; @@ -168,11 +144,46 @@ static int32_t buildSmlKvSchema(TAOS_SML_KV* smlKv, SHashObj* hash, SArray* arra taosHashPut(hash, field.name, tagKeyLen, &fieldIdx, sizeof(fieldIdx)); } - smlKv->fieldSchemaIdx = (uint32_t)fieldIdx; + uintptr_t valPointer = (uintptr_t)smlKv; + taosHashPut(info->smlDataToSchema, &valPointer, sizeof(uintptr_t), &fieldIdx, sizeof(fieldIdx)); return 0; } +static int32_t getSmlMd5ChildTableName(TAOS_SML_DATA_POINT* point, char* tableName, int* tableNameLen, + SSmlLinesInfo* info) { + tscDebug("SML:0x%"PRIx64" taos_sml_insert get child table name through md5", info->id); + qsort(point->tags, point->tagNum, sizeof(TAOS_SML_KV), compareSmlColKv); + + SStringBuilder sb; memset(&sb, 0, sizeof(sb)); + char sTableName[TSDB_TABLE_NAME_LEN] = {0}; + strtolower(sTableName, point->stableName); + taosStringBuilderAppendString(&sb, sTableName); + for (int j = 0; j < point->tagNum; ++j) { + taosStringBuilderAppendChar(&sb, ','); + TAOS_SML_KV* tagKv = point->tags + j; + char tagName[TSDB_COL_NAME_LEN] = {0}; + strtolower(tagName, tagKv->key); + taosStringBuilderAppendString(&sb, tagName); + taosStringBuilderAppendChar(&sb, '='); + taosStringBuilderAppend(&sb, tagKv->value, tagKv->length); + } + size_t len = 0; + char* keyJoined = taosStringBuilderGetResult(&sb, &len); + MD5_CTX context; + MD5Init(&context); + MD5Update(&context, (uint8_t *)keyJoined, (uint32_t)len); + MD5Final(&context); + *tableNameLen = snprintf(tableName, *tableNameLen, + "t_%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", context.digest[0], + context.digest[1], context.digest[2], context.digest[3], context.digest[4], context.digest[5], context.digest[6], + context.digest[7], context.digest[8], context.digest[9], context.digest[10], context.digest[11], + context.digest[12], context.digest[13], context.digest[14], context.digest[15]); + taosStringBuilderDestroy(&sb); + tscDebug("SML:0x%"PRIx64" child table name: %s", info->id, tableName); + return 0; +} + static int32_t buildDataPointSchemas(TAOS_SML_DATA_POINT* points, int numPoint, SArray* stableSchemas, SSmlLinesInfo* info) { int32_t code = 0; SHashObj* sname2shema = taosHashInit(32, @@ -203,6 +214,15 @@ static int32_t buildDataPointSchemas(TAOS_SML_DATA_POINT* points, int numPoint, for (int j = 0; j < point->tagNum; ++j) { TAOS_SML_KV* tagKv = point->tags + j; + if (!point->childTableName) { + char childTableName[TSDB_TABLE_NAME_LEN]; + int32_t tableNameLen = TSDB_TABLE_NAME_LEN; + getSmlMd5ChildTableName(point, childTableName, &tableNameLen, info); + point->childTableName = calloc(1, tableNameLen+1); + strncpy(point->childTableName, childTableName, tableNameLen); + point->childTableName[tableNameLen] = '\0'; + } + code = buildSmlKvSchema(tagKv, pStableSchema->tagHash, pStableSchema->tags, info); if (code != 0) { tscError("SML:0x%"PRIx64" build data point schema failed. point no.: %d, tag key: %s", info->id, i, tagKv->key); @@ -219,7 +239,8 @@ static int32_t buildDataPointSchemas(TAOS_SML_DATA_POINT* points, int numPoint, } } - point->schemaIdx = (uint32_t)stableIdx; + uintptr_t valPointer = (uintptr_t)point; + taosHashPut(info->smlDataToSchema, &valPointer, sizeof(uintptr_t), &stableIdx, sizeof(stableIdx)); } size_t numStables = taosArrayGetSize(stableSchemas); @@ -319,7 +340,22 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf buildColumnDescription(action->alterSTable.field, result+n, capacity-n, &outBytes); TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery code = taos_errno(res); + char* errStr = taos_errstr(res); + char* begin = strstr(errStr, "duplicated column names"); + bool tscDupColNames = (begin != NULL); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%"PRIx64" apply schema action. error: %s", info->id, errStr); + } taos_free_result(res); + + if (code == TSDB_CODE_MND_FIELD_ALREAY_EXIST || code == TSDB_CODE_MND_TAG_ALREAY_EXIST || tscDupColNames) { + TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + } break; } case SCHEMA_ACTION_ADD_TAG: { @@ -328,7 +364,22 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf result+n, capacity-n, &outBytes); TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery code = taos_errno(res); + char* errStr = taos_errstr(res); + char* begin = strstr(errStr, "duplicated column names"); + bool tscDupColNames = (begin != NULL); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res)); + } taos_free_result(res); + + if (code == TSDB_CODE_MND_TAG_ALREAY_EXIST || code == TSDB_CODE_MND_FIELD_ALREAY_EXIST || tscDupColNames) { + TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + } break; } case SCHEMA_ACTION_CHANGE_COLUMN_SIZE: { @@ -337,7 +388,19 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf capacity-n, &outBytes); TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery code = taos_errno(res); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res)); + } taos_free_result(res); + + if (code == TSDB_CODE_MND_INVALID_COLUMN_LENGTH || code == TSDB_CODE_TSC_INVALID_COLUMN_LENGTH) { + TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + } break; } case SCHEMA_ACTION_CHANGE_TAG_SIZE: { @@ -346,7 +409,19 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf capacity-n, &outBytes); TAOS_RES* res = taos_query(taos, result); //TODO async doAsyncQuery code = taos_errno(res); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res)); + } taos_free_result(res); + + if (code == TSDB_CODE_MND_INVALID_TAG_LENGTH || code == TSDB_CODE_TSC_INVALID_TAG_LENGTH) { + TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + } break; } case SCHEMA_ACTION_CREATE_STABLE: { @@ -375,7 +450,19 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf outBytes = snprintf(pos, freeBytes, ")"); TAOS_RES* res = taos_query(taos, result); code = taos_errno(res); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%"PRIx64" apply schema action. error : %s", info->id, taos_errstr(res)); + } taos_free_result(res); + + if (code == TSDB_CODE_MND_TABLE_ALREADY_EXIST) { + TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE"); + code = taos_errno(res2); + if (code != TSDB_CODE_SUCCESS) { + tscError("SML:0x%" PRIx64 " apply schema action. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + } break; } @@ -385,7 +472,7 @@ static int32_t applySchemaAction(TAOS* taos, SSchemaAction* action, SSmlLinesInf free(result); if (code != 0) { - tscError("SML:0x%"PRIx64 "apply schema action failure. %s", info->id, tstrerror(code)); + tscError("SML:0x%"PRIx64 " apply schema action failure. %s", info->id, tstrerror(code)); } return code; } @@ -398,70 +485,12 @@ static int32_t destroySmlSTableSchema(SSmlSTableSchema* schema) { return 0; } -int32_t loadTableMeta(TAOS* taos, char* tableName, SSmlSTableSchema* schema, SSmlLinesInfo* info) { - int32_t code = 0; - - STscObj *pObj = (STscObj *)taos; - if (pObj == NULL || pObj->signature != pObj) { - terrno = TSDB_CODE_TSC_DISCONNECTED; - return TSDB_CODE_TSC_DISCONNECTED; - } - - tscDebug("SML:0x%"PRIx64" load table schema. super table name: %s", info->id, tableName); - - char tableNameLowerCase[TSDB_TABLE_NAME_LEN]; - strtolower(tableNameLowerCase, tableName); - - char sql[256]; - snprintf(sql, 256, "describe %s", tableNameLowerCase); - TAOS_RES* res = taos_query(taos, sql); - code = taos_errno(res); - if (code != 0) { - tscError("SML:0x%"PRIx64" describe table failure. %s", info->id, taos_errstr(res)); - taos_free_result(res); - return code; - } - taos_free_result(res); - - SSqlObj* pSql = calloc(1, sizeof(SSqlObj)); - if (pSql == NULL){ - tscError("failed to allocate memory, reason:%s", strerror(errno)); - code = TSDB_CODE_TSC_OUT_OF_MEMORY; - return code; - } - pSql->pTscObj = taos; - pSql->signature = pSql; - pSql->fp = NULL; - - SStrToken tableToken = {.z=tableNameLowerCase, .n=(uint32_t)strlen(tableNameLowerCase), .type=TK_ID}; - tGetToken(tableNameLowerCase, &tableToken.type); - // Check if the table name available or not - if (tscValidateName(&tableToken) != TSDB_CODE_SUCCESS) { - code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; - sprintf(pSql->cmd.payload, "table name is invalid"); - tscFreeSqlObj(pSql); - return code; - } - - SName sname = {0}; - if ((code = tscSetTableFullName(&sname, &tableToken, pSql)) != TSDB_CODE_SUCCESS) { - tscFreeSqlObj(pSql); - return code; - } - char fullTableName[TSDB_TABLE_FNAME_LEN] = {0}; - memset(fullTableName, 0, tListLen(fullTableName)); - tNameExtractFullName(&sname, fullTableName); - tscFreeSqlObj(pSql); - +static int32_t fillDbSchema(STableMeta* tableMeta, char* tableName, SSmlSTableSchema* schema, SSmlLinesInfo* info) { schema->tags = taosArrayInit(8, sizeof(SSchema)); schema->fields = taosArrayInit(64, sizeof(SSchema)); schema->tagHash = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false); schema->fieldHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false); - size_t size = 0; - STableMeta* tableMeta = NULL; - taosHashGetCloneExt(tscTableMetaMap, fullTableName, strlen(fullTableName), NULL, (void **)&tableMeta, &size); - tstrncpy(schema->sTableName, tableName, strlen(tableName)+1); schema->precision = tableMeta->tableInfo.precision; for (int i=0; itableInfo.numOfColumns; ++i) { @@ -484,9 +513,93 @@ int32_t loadTableMeta(TAOS* taos, char* tableName, SSmlSTableSchema* schema, SSm size_t tagIndex = taosArrayGetSize(schema->tags) - 1; taosHashPut(schema->tagHash, field.name, strlen(field.name), &tagIndex, sizeof(tagIndex)); } - tscDebug("SML:0x%"PRIx64 " load table meta succeed. table name: %s, columns number: %d, tag number: %d, precision: %d", + tscDebug("SML:0x%"PRIx64 " load table schema succeed. table name: %s, columns number: %d, tag number: %d, precision: %d", info->id, tableName, tableMeta->tableInfo.numOfColumns, tableMeta->tableInfo.numOfTags, schema->precision); - free(tableMeta); tableMeta = NULL; + return TSDB_CODE_SUCCESS; +} + +static int32_t retrieveTableMeta(TAOS* taos, char* tableName, STableMeta** pTableMeta, SSmlLinesInfo* info) { + int32_t code = 0; + int32_t retries = 0; + STableMeta* tableMeta = NULL; + while (retries++ < TSDB_MAX_REPLICA && tableMeta == NULL) { + STscObj* pObj = (STscObj*)taos; + if (pObj == NULL || pObj->signature != pObj) { + terrno = TSDB_CODE_TSC_DISCONNECTED; + return TSDB_CODE_TSC_DISCONNECTED; + } + + tscDebug("SML:0x%" PRIx64 " retrieve table meta. super table name: %s", info->id, tableName); + + char tableNameLowerCase[TSDB_TABLE_NAME_LEN]; + strtolower(tableNameLowerCase, tableName); + + char sql[256]; + snprintf(sql, 256, "describe %s", tableNameLowerCase); + TAOS_RES* res = taos_query(taos, sql); + code = taos_errno(res); + if (code != 0) { + tscError("SML:0x%" PRIx64 " describe table failure. %s", info->id, taos_errstr(res)); + taos_free_result(res); + return code; + } + taos_free_result(res); + + SSqlObj* pSql = calloc(1, sizeof(SSqlObj)); + if (pSql == NULL) { + tscError("SML:0x%" PRIx64 " failed to allocate memory, reason:%s", info->id, strerror(errno)); + code = TSDB_CODE_TSC_OUT_OF_MEMORY; + return code; + } + pSql->pTscObj = taos; + pSql->signature = pSql; + pSql->fp = NULL; + + registerSqlObj(pSql); + SStrToken tableToken = {.z = tableNameLowerCase, .n = (uint32_t)strlen(tableNameLowerCase), .type = TK_ID}; + tGetToken(tableNameLowerCase, &tableToken.type); + // Check if the table name available or not + if (tscValidateName(&tableToken) != TSDB_CODE_SUCCESS) { + code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; + sprintf(pSql->cmd.payload, "table name is invalid"); + tscFreeRegisteredSqlObj(pSql); + return code; + } + + SName sname = {0}; + if ((code = tscSetTableFullName(&sname, &tableToken, pSql)) != TSDB_CODE_SUCCESS) { + tscFreeRegisteredSqlObj(pSql); + return code; + } + char fullTableName[TSDB_TABLE_FNAME_LEN] = {0}; + memset(fullTableName, 0, tListLen(fullTableName)); + tNameExtractFullName(&sname, fullTableName); + tscFreeRegisteredSqlObj(pSql); + + size_t size = 0; + taosHashGetCloneExt(tscTableMetaMap, fullTableName, strlen(fullTableName), NULL, (void**)&tableMeta, &size); + } + + if (tableMeta != NULL) { + *pTableMeta = tableMeta; + return TSDB_CODE_SUCCESS; + } else { + tscError("SML:0x%" PRIx64 " failed to retrieve table meta. super table name: %s", info->id, tableName); + return TSDB_CODE_TSC_NO_META_CACHED; + } +} + +static int32_t loadTableSchemaFromDB(TAOS* taos, char* tableName, SSmlSTableSchema* schema, SSmlLinesInfo* info) { + int32_t code = 0; + STableMeta* tableMeta = NULL; + code = retrieveTableMeta(taos, tableName, &tableMeta, info); + if (code == TSDB_CODE_SUCCESS) { + assert(tableMeta != NULL); + fillDbSchema(tableMeta, tableName, schema, info); + free(tableMeta); + tableMeta = NULL; + } + return code; } @@ -498,7 +611,7 @@ static int32_t modifyDBSchemas(TAOS* taos, SArray* stableSchemas, SSmlLinesInfo* SSmlSTableSchema dbSchema; memset(&dbSchema, 0, sizeof(SSmlSTableSchema)); - code = loadTableMeta(taos, pointSchema->sTableName, &dbSchema, info); + code = loadTableSchemaFromDB(taos, pointSchema->sTableName, &dbSchema, info); if (code == TSDB_CODE_MND_INVALID_TABLE_NAME) { SSchemaAction schemaAction = {0}; schemaAction.action = SCHEMA_ACTION_CREATE_STABLE; @@ -507,7 +620,7 @@ static int32_t modifyDBSchemas(TAOS* taos, SArray* stableSchemas, SSmlLinesInfo* schemaAction.createSTable.tags = pointSchema->tags; schemaAction.createSTable.fields = pointSchema->fields; applySchemaAction(taos, &schemaAction, info); - code = loadTableMeta(taos, pointSchema->sTableName, &dbSchema, info); + code = loadTableSchemaFromDB(taos, pointSchema->sTableName, &dbSchema, info); if (code != 0) { tscError("SML:0x%"PRIx64" reconcile point schema failed. can not create %s", info->id, pointSchema->sTableName); return code; @@ -567,74 +680,6 @@ static int32_t modifyDBSchemas(TAOS* taos, SArray* stableSchemas, SSmlLinesInfo* return 0; } -static int32_t getSmlMd5ChildTableName(TAOS_SML_DATA_POINT* point, char* tableName, int* tableNameLen, - SSmlLinesInfo* info) { - tscDebug("SML:0x%"PRIx64" taos_sml_insert get child table name through md5", info->id); - qsort(point->tags, point->tagNum, sizeof(TAOS_SML_KV), compareSmlColKv); - - SStringBuilder sb; memset(&sb, 0, sizeof(sb)); - char sTableName[TSDB_TABLE_NAME_LEN] = {0}; - strtolower(sTableName, point->stableName); - taosStringBuilderAppendString(&sb, sTableName); - for (int j = 0; j < point->tagNum; ++j) { - taosStringBuilderAppendChar(&sb, ','); - TAOS_SML_KV* tagKv = point->tags + j; - char tagName[TSDB_COL_NAME_LEN] = {0}; - strtolower(tagName, tagKv->key); - taosStringBuilderAppendString(&sb, tagName); - taosStringBuilderAppendChar(&sb, '='); - taosStringBuilderAppend(&sb, tagKv->value, tagKv->length); - } - size_t len = 0; - char* keyJoined = taosStringBuilderGetResult(&sb, &len); - MD5_CTX context; - MD5Init(&context); - MD5Update(&context, (uint8_t *)keyJoined, (uint32_t)len); - MD5Final(&context); - *tableNameLen = snprintf(tableName, *tableNameLen, - "t_%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", context.digest[0], - context.digest[1], context.digest[2], context.digest[3], context.digest[4], context.digest[5], context.digest[6], - context.digest[7], context.digest[8], context.digest[9], context.digest[10], context.digest[11], - context.digest[12], context.digest[13], context.digest[14], context.digest[15]); - taosStringBuilderDestroy(&sb); - tscDebug("SML:0x%"PRIx64" child table name: %s", info->id, tableName); - return 0; -} - - -static int32_t changeChildTableTagValue(TAOS* taos, const char* cTableName, const char* tagName, TAOS_BIND* bind, SSmlLinesInfo* info) { - char sql[512]; - sprintf(sql, "alter table %s set tag %s=?", cTableName, tagName); - - int32_t code; - TAOS_STMT* stmt = taos_stmt_init(taos); - code = taos_stmt_prepare(stmt, sql, (unsigned long)strlen(sql)); - - if (code != 0) { - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); - return code; - } - - code = taos_stmt_bind_param(stmt, bind); - if (code != 0) { - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); - return code; - } - - code = taos_stmt_execute(stmt); - if (code != 0) { - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); - return code; - } - - code = taos_stmt_close(stmt); - if (code != 0) { - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); - return code; - } - return code; -} - static int32_t creatChildTableIfNotExists(TAOS* taos, const char* cTableName, const char* sTableName, SArray* tagsSchema, SArray* tagsBind, SSmlLinesInfo* info) { size_t numTags = taosArrayGetSize(tagsSchema); @@ -673,28 +718,28 @@ static int32_t creatChildTableIfNotExists(TAOS* taos, const char* cTableName, co free(sql); if (code != 0) { - tfree(stmt); - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); + tscError("SML:0x%"PRIx64" taos_stmt_prepare returns %d:%s", info->id, code, tstrerror(code)); + taos_stmt_close(stmt); return code; } code = taos_stmt_bind_param(stmt, TARRAY_GET_START(tagsBind)); if (code != 0) { - tfree(stmt); - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); + tscError("SML:0x%"PRIx64" taos_stmt_bind_param returns %d:%s", info->id, code, tstrerror(code)); + taos_stmt_close(stmt); return code; } code = taos_stmt_execute(stmt); if (code != 0) { - tfree(stmt); - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); + tscError("SML:0x%"PRIx64" taos_stmt_execute returns %d:%s", info->id, code, tstrerror(code)); + taos_stmt_close(stmt); return code; } code = taos_stmt_close(stmt); if (code != 0) { - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); + tscError("SML:0x%"PRIx64" taos_stmt_close return %d:%s", info->id, code, tstrerror(code)); return code; } return code; @@ -726,27 +771,29 @@ static int32_t insertChildTableBatch(TAOS* taos, char* cTableName, SArray* cols tscDebug("SML:0x%"PRIx64" insert rows into child table %s. num of rows: %zu", info->id, cTableName, taosArrayGetSize(rowsBind)); int32_t code = 0; - int32_t try = 0; TAOS_STMT* stmt = taos_stmt_init(taos); if (stmt == NULL) { tfree(sql); return TSDB_CODE_TSC_OUT_OF_MEMORY; } + code = taos_stmt_prepare(stmt, sql, (unsigned long)strlen(sql)); tfree(sql); if (code != 0) { - tfree(stmt); - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); + tscError("SML:0x%"PRIx64" taos_stmt_prepare return %d:%s", info->id, code, tstrerror(code)); + taos_stmt_close(stmt); return code; } + bool tryAgain = false; + int32_t try = 0; do { code = taos_stmt_set_tbname(stmt, cTableName); if (code != 0) { - tfree(stmt); - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); + tscError("SML:0x%"PRIx64" taos_stmt_set_tbname return %d:%s", info->id, code, tstrerror(code)); + taos_stmt_close(stmt); return code; } @@ -755,31 +802,52 @@ static int32_t insertChildTableBatch(TAOS* taos, char* cTableName, SArray* cols TAOS_BIND* colsBinds = taosArrayGetP(rowsBind, i); code = taos_stmt_bind_param(stmt, colsBinds); if (code != 0) { - tfree(stmt); - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); + tscError("SML:0x%"PRIx64" taos_stmt_bind_param return %d:%s", info->id, code, tstrerror(code)); + taos_stmt_close(stmt); return code; } code = taos_stmt_add_batch(stmt); if (code != 0) { - tfree(stmt); - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); + tscError("SML:0x%"PRIx64" taos_stmt_add_batch return %d:%s", info->id, code, tstrerror(code)); + taos_stmt_close(stmt); return code; } } code = taos_stmt_execute(stmt); if (code != 0) { - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); + tscError("SML:0x%"PRIx64" taos_stmt_execute return %d:%s, try:%d", info->id, code, tstrerror(code), try); } - } while (code == TSDB_CODE_TDB_TABLE_RECONFIGURE && try++ < TSDB_MAX_REPLICA); - if (code != 0) { - tscError("SML:0x%"PRIx64" %s", info->id, taos_stmt_errstr(stmt)); - taos_stmt_close(stmt); - } else { - taos_stmt_close(stmt); - } + tryAgain = false; + if ((code == TSDB_CODE_TDB_INVALID_TABLE_ID + || code == TSDB_CODE_VND_INVALID_VGROUP_ID + || code == TSDB_CODE_TDB_TABLE_RECONFIGURE + || code == TSDB_CODE_APP_NOT_READY + || code == TSDB_CODE_RPC_NETWORK_UNAVAIL) && try++ < TSDB_MAX_REPLICA) { + tryAgain = true; + } + + if (code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) { + TAOS_RES* res2 = taos_query(taos, "RESET QUERY CACHE"); + int32_t code2 = taos_errno(res2); + if (code2 != TSDB_CODE_SUCCESS) { + tscError("SML:0x%" PRIx64 " insert child table. reset query cache. error: %s", info->id, taos_errstr(res2)); + } + taos_free_result(res2); + if (tryAgain) { + taosMsleep(50 * (2 << try)); + } + } + if (code == TSDB_CODE_APP_NOT_READY || code == TSDB_CODE_RPC_NETWORK_UNAVAIL) { + if (tryAgain) { + taosMsleep( 50 * (2 << try)); + } + } + } while (tryAgain); + + taos_stmt_close(stmt); return code; } @@ -787,16 +855,10 @@ static int32_t arrangePointsByChildTableName(TAOS_SML_DATA_POINT* points, int nu SHashObj* cname2points, SArray* stableSchemas, SSmlLinesInfo* info) { for (int32_t i = 0; i < numPoints; ++i) { TAOS_SML_DATA_POINT * point = points + i; - if (!point->childTableName) { - char childTableName[TSDB_TABLE_NAME_LEN]; - int32_t tableNameLen = TSDB_TABLE_NAME_LEN; - getSmlMd5ChildTableName(point, childTableName, &tableNameLen, info); - point->childTableName = calloc(1, tableNameLen+1); - strncpy(point->childTableName, childTableName, tableNameLen); - point->childTableName[tableNameLen] = '\0'; - } - - SSmlSTableSchema* stableSchema = taosArrayGet(stableSchemas, point->schemaIdx); + uintptr_t valPointer = (uintptr_t)point; + size_t* pSchemaIndex = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t)); + assert(pSchemaIndex != NULL); + SSmlSTableSchema* stableSchema = taosArrayGet(stableSchemas, *pSchemaIndex); for (int j = 0; j < point->tagNum; ++j) { TAOS_SML_KV* kv = point->tags + j; @@ -840,16 +902,10 @@ static int32_t applyChildTableTags(TAOS* taos, char* cTableName, char* sTableNam TAOS_SML_DATA_POINT * pDataPoint = taosArrayGetP(cTablePoints, i); for (int j = 0; j < pDataPoint->tagNum; ++j) { TAOS_SML_KV* kv = pDataPoint->tags + j; - tagKVs[kv->fieldSchemaIdx] = kv; - } - } - - int32_t notNullTagsIndices[TSDB_MAX_TAGS] = {0}; - int32_t numNotNullTags = 0; - for (int32_t i = 0; i < numTags; ++i) { - if (tagKVs[i] != NULL) { - notNullTagsIndices[numNotNullTags] = i; - ++numNotNullTags; + uintptr_t valPointer = (uintptr_t)kv; + size_t* pFieldSchemaIdx = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t)); + assert(pFieldSchemaIdx != NULL); + tagKVs[*pFieldSchemaIdx] = kv; } } @@ -863,7 +919,10 @@ static int32_t applyChildTableTags(TAOS* taos, char* cTableName, char* sTableNam for (int j = 0; j < numTags; ++j) { if (tagKVs[j] == NULL) continue; TAOS_SML_KV* kv = tagKVs[j]; - TAOS_BIND* bind = taosArrayGet(tagBinds, kv->fieldSchemaIdx); + uintptr_t valPointer = (uintptr_t)kv; + size_t* pFieldSchemaIdx = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t)); + assert(pFieldSchemaIdx != NULL); + TAOS_BIND* bind = taosArrayGet(tagBinds, *pFieldSchemaIdx); bind->buffer_type = kv->type; bind->length = malloc(sizeof(uintptr_t*)); *bind->length = kv->length; @@ -871,65 +930,8 @@ static int32_t applyChildTableTags(TAOS* taos, char* cTableName, char* sTableNam bind->is_null = NULL; } - // select tag1,tag2,... from stable where tbname in (ctable) - char* sql = malloc(tsMaxSQLStringLen+1); - int freeBytes = tsMaxSQLStringLen + 1; - snprintf(sql, freeBytes, "select tbname, "); - for (int i = 0; i < numNotNullTags ; ++i) { - snprintf(sql + strlen(sql), freeBytes-strlen(sql), "%s,", tagKVs[notNullTagsIndices[i]]->key); - } - snprintf(sql + strlen(sql) - 1, freeBytes - strlen(sql) + 1, - " from %s where tbname in (\'%s\')", sTableName, cTableName); - sql[strlen(sql)] = '\0'; - - TAOS_RES* result = taos_query(taos, sql); - free(sql); - - int32_t code = taos_errno(result); - if (code != 0) { - tscError("SML:0x%"PRIx64" get child table %s tags failed. error string %s", info->id, cTableName, taos_errstr(result)); - goto cleanup; - } - - // check tag value and set tag values if different - TAOS_ROW row = taos_fetch_row(result); - if (row != NULL) { - int numFields = taos_field_count(result); - TAOS_FIELD* fields = taos_fetch_fields(result); - int* lengths = taos_fetch_lengths(result); - for (int i = 1; i < numFields; ++i) { - uint8_t dbType = fields[i].type; - int32_t length = lengths[i]; - char* val = row[i]; - - TAOS_SML_KV* tagKV = tagKVs[notNullTagsIndices[i-1]]; - if (tagKV->type != dbType) { - tscError("SML:0x%"PRIx64" child table %s tag %s type mismatch. point type : %d, db type : %d", - info->id, cTableName, tagKV->key, tagKV->type, dbType); - return TSDB_CODE_TSC_INVALID_VALUE; - } - - assert(tagKV->value); - - if (val == NULL || length != tagKV->length || memcmp(tagKV->value, val, length) != 0) { - TAOS_BIND* bind = taosArrayGet(tagBinds, tagKV->fieldSchemaIdx); - code = changeChildTableTagValue(taos, cTableName, tagKV->key, bind, info); - if (code != 0) { - tscError("SML:0x%"PRIx64" change child table tag failed. table name %s, tag %s", info->id, cTableName, tagKV->key); - goto cleanup; - } - } - } - tscDebug("SML:0x%"PRIx64" successfully applied point tags. child table: %s", info->id, cTableName); - } else { - code = creatChildTableIfNotExists(taos, cTableName, sTableName, sTableSchema->tags, tagBinds, info); - if (code != 0) { - goto cleanup; - } - } + int32_t code = creatChildTableIfNotExists(taos, cTableName, sTableName, sTableSchema->tags, tagBinds, info); -cleanup: - taos_free_result(result); for (int i = 0; i < taosArrayGetSize(tagBinds); ++i) { TAOS_BIND* bind = taosArrayGet(tagBinds, i); free(bind->length); @@ -963,7 +965,10 @@ static int32_t applyChildTableFields(TAOS* taos, SSmlSTableSchema* sTableSchema, } for (int j = 0; j < point->fieldNum; ++j) { TAOS_SML_KV* kv = point->fields + j; - TAOS_BIND* bind = colBinds + kv->fieldSchemaIdx; + uintptr_t valPointer = (uintptr_t)kv; + size_t* pFieldSchemaIdx = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t)); + assert(pFieldSchemaIdx != NULL); + TAOS_BIND* bind = colBinds + *pFieldSchemaIdx; bind->buffer_type = kv->type; bind->length = malloc(sizeof(uintptr_t*)); *bind->length = kv->length; @@ -1000,9 +1005,11 @@ static int32_t applyDataPoints(TAOS* taos, TAOS_SML_DATA_POINT* points, int32_t while (pCTablePoints) { SArray* cTablePoints = *pCTablePoints; - TAOS_SML_DATA_POINT* point = taosArrayGetP(cTablePoints, 0); - SSmlSTableSchema* sTableSchema = taosArrayGet(stableSchemas, point->schemaIdx); + uintptr_t valPointer = (uintptr_t)point; + size_t* pSchemaIndex = taosHashGet(info->smlDataToSchema, &valPointer, sizeof(uintptr_t)); + assert(pSchemaIndex != NULL); + SSmlSTableSchema* sTableSchema = taosArrayGet(stableSchemas, *pSchemaIndex); tscDebug("SML:0x%"PRIx64" apply child table tags. child table: %s", info->id, point->childTableName); code = applyChildTableTags(taos, point->childTableName, point->stableName, sTableSchema, cTablePoints, info); @@ -1014,7 +1021,7 @@ static int32_t applyDataPoints(TAOS* taos, TAOS_SML_DATA_POINT* points, int32_t tscDebug("SML:0x%"PRIx64" apply child table points. child table: %s", info->id, point->childTableName); code = applyChildTableFields(taos, sTableSchema, point->childTableName, cTablePoints, info); if (code != 0) { - tscError("Apply child table fields failed. child table %s, error %s", point->childTableName, tstrerror(code)); + tscError("SML:0x%"PRIx64" Apply child table fields failed. child table %s, error %s", info->id, point->childTableName, tstrerror(code)); goto cleanup; } @@ -1034,10 +1041,11 @@ cleanup: return code; } -int taos_sml_insert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint, SSmlLinesInfo* info) { +int tscSmlInsert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint, SSmlLinesInfo* info) { tscDebug("SML:0x%"PRIx64" taos_sml_insert. number of points: %d", info->id, numPoint); int32_t code = TSDB_CODE_SUCCESS; + info->smlDataToSchema = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), true, false); tscDebug("SML:0x%"PRIx64" build data point schemas", info->id); SArray* stableSchemas = taosArrayInit(32, sizeof(SSmlSTableSchema)); // SArray @@ -1067,6 +1075,15 @@ clean_up: taosArrayDestroy(schema->tags); } taosArrayDestroy(stableSchemas); + taosHashCleanup(info->smlDataToSchema); + return code; +} + +int taos_sml_insert(TAOS* taos, TAOS_SML_DATA_POINT* points, int numPoint) { + SSmlLinesInfo* info = calloc(1, sizeof(SSmlLinesInfo)); + info->id = genLinesSmlId(); + int code = tscSmlInsert(taos, points, numPoint, info); + free(info); return code; } @@ -1517,8 +1534,8 @@ static bool convertStrToNumber(TAOS_SML_KV *pVal, char*str, SSmlLinesInfo* info) return true; } //len does not include '\0' from value. -static bool convertSmlValueType(TAOS_SML_KV *pVal, char *value, - uint16_t len, SSmlLinesInfo* info) { +bool convertSmlValueType(TAOS_SML_KV *pVal, char *value, + uint16_t len, SSmlLinesInfo* info) { if (len <= 0) { return false; } @@ -1660,7 +1677,7 @@ static int32_t getTimeStampValue(char *value, uint16_t len, if (len >= 2) { for (int i = 0; i < len - 2; ++i) { if(!isdigit(value[i])) { - return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + return TSDB_CODE_TSC_INVALID_TIME_STAMP; } } } @@ -1695,20 +1712,20 @@ static int32_t getTimeStampValue(char *value, uint16_t len, break; } default: { - return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + return TSDB_CODE_TSC_INVALID_TIME_STAMP; } } return TSDB_CODE_SUCCESS; } -static int32_t convertSmlTimeStamp(TAOS_SML_KV *pVal, char *value, - uint16_t len, SSmlLinesInfo* info) { +int32_t convertSmlTimeStamp(TAOS_SML_KV *pVal, char *value, + uint16_t len, SSmlLinesInfo* info) { int32_t ret; SMLTimeStampType type; int64_t tsVal; if (!isTimeStamp(value, len, &type)) { - return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + return TSDB_CODE_TSC_INVALID_TIME_STAMP; } ret = getTimeStampValue(value, len, type, &tsVal); @@ -1757,7 +1774,7 @@ static int32_t parseSmlTimeStamp(TAOS_SML_KV **pTS, const char **index, SSmlLine return ret; } -static bool checkDuplicateKey(char *key, SHashObj *pHash, SSmlLinesInfo* info) { +bool checkDuplicateKey(char *key, SHashObj *pHash, SSmlLinesInfo* info) { char *val = NULL; char *cur = key; char keyLower[TSDB_COL_NAME_LEN]; @@ -1794,7 +1811,7 @@ static int32_t parseSmlKey(TAOS_SML_KV *pKV, const char **index, SHashObj *pHash while (*cur != '\0') { if (len > TSDB_COL_NAME_LEN) { tscError("SML:0x%"PRIx64" Key field cannot exceeds 65 characters", info->id); - return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; } //unescaped '=' identifies a tag key if (*cur == '=' && *(cur - 1) != '\\') { @@ -1854,7 +1871,7 @@ static bool parseSmlValue(TAOS_SML_KV *pKV, const char **index, free(pKV->key); pKV->key = NULL; free(value); - return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + return TSDB_CODE_TSC_INVALID_VALUE; } free(value); @@ -1883,7 +1900,7 @@ static int32_t parseSmlMeasurement(TAOS_SML_DATA_POINT *pSml, const char **index tscError("SML:0x%"PRIx64" Measurement field cannot exceeds 193 characters", info->id); free(pSml->stableName); pSml->stableName = NULL; - return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; } //first unescaped comma or space identifies measurement //if space detected first, meaning no tag in the input @@ -1910,7 +1927,7 @@ static int32_t parseSmlMeasurement(TAOS_SML_DATA_POINT *pSml, const char **index } //Table name can only contain digits(0-9),alphebet(a-z),underscore(_) -static int32_t isValidChildTableName(const char *pTbName, int16_t len) { +int32_t isValidChildTableName(const char *pTbName, int16_t len) { const char *cur = pTbName; for (int i = 0; i < len; ++i) { if(!isdigit(cur[i]) && !isalpha(cur[i]) && (cur[i] != '_')) { @@ -2076,18 +2093,6 @@ int32_t tscParseLine(const char* sql, TAOS_SML_DATA_POINT* smlData, SSmlLinesInf //========================================================================= -static uint64_t linesSmlHandleId = 0; - -uint64_t genLinesSmlId() { - uint64_t id; - - do { - id = atomic_add_fetch_64(&linesSmlHandleId, 1); - } while (id == 0); - - return id; -} - void destroySmlDataPoint(TAOS_SML_DATA_POINT* point) { for (int i=0; itagNum; ++i) { free((point->tags+i)->key); @@ -2110,14 +2115,14 @@ int32_t tscParseLines(char* lines[], int numLines, SArray* points, SArray* faile if (code != TSDB_CODE_SUCCESS) { tscError("SML:0x%"PRIx64" data point line parse failed. line %d : %s", info->id, i, lines[i]); destroySmlDataPoint(&point); - return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + return code; } else { tscDebug("SML:0x%"PRIx64" data point line parse success. line %d", info->id, i); } taosArrayPush(points, &point); } - return 0; + return TSDB_CODE_SUCCESS; } int taos_insert_lines(TAOS* taos, char* lines[], int numLines) { @@ -2157,7 +2162,7 @@ int taos_insert_lines(TAOS* taos, char* lines[], int numLines) { } TAOS_SML_DATA_POINT* points = TARRAY_GET_START(lpPoints); - code = taos_sml_insert(taos, points, (int)numPoints, info); + code = tscSmlInsert(taos, points, (int)numPoints, info); if (code != 0) { tscError("SML:0x%"PRIx64" taos_sml_insert error: %s", info->id, tstrerror((code))); } diff --git a/src/client/src/tscParseOpenTSDB.c b/src/client/src/tscParseOpenTSDB.c new file mode 100644 index 0000000000000000000000000000000000000000..397b5d3e97c2ed7fc1a42bd0e773bcff8f659c65 --- /dev/null +++ b/src/client/src/tscParseOpenTSDB.c @@ -0,0 +1,424 @@ +#include +#include +#include +#include + +#include "hash.h" +#include "taos.h" + +#include "tscUtil.h" +#include "tsclient.h" +#include "tscLog.h" + +#include "tscParseLine.h" + +#define MAX_TELNET_FILEDS_NUM 2 +#define OTS_TIMESTAMP_COLUMN_NAME "ts" +#define OTS_METRIC_VALUE_COLUMN_NAME "value" + +/* telnet style API parser */ +static uint64_t HandleId = 0; + +static uint64_t genUID() { + uint64_t id; + + do { + id = atomic_add_fetch_64(&HandleId, 1); + } while (id == 0); + + return id; +} + +static int32_t parseTelnetMetric(TAOS_SML_DATA_POINT *pSml, const char **index, SSmlLinesInfo* info) { + const char *cur = *index; + uint16_t len = 0; + + pSml->stableName = tcalloc(TSDB_TABLE_NAME_LEN + 1, 1); // +1 to avoid 1772 line over write + if (pSml->stableName == NULL){ + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + if (isdigit(*cur)) { + tscError("OTD:0x%"PRIx64" Metric cannnot start with digit", info->id); + tfree(pSml->stableName); + return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + } + + while (*cur != '\0') { + if (len > TSDB_TABLE_NAME_LEN) { + tscError("OTD:0x%"PRIx64" Metric cannot exceeds 193 characters", info->id); + tfree(pSml->stableName); + return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; + } + + if (*cur == ' ') { + break; + } + + pSml->stableName[len] = *cur; + cur++; + len++; + } + if (len == 0 || *cur == '\0') { + tfree(pSml->stableName); + return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + } + + pSml->stableName[len] = '\0'; + *index = cur + 1; + tscDebug("OTD:0x%"PRIx64" Stable name in metric:%s|len:%d", info->id, pSml->stableName, len); + + return TSDB_CODE_SUCCESS; +} + +static int32_t parseTelnetTimeStamp(TAOS_SML_KV **pTS, int *num_kvs, const char **index, SSmlLinesInfo* info) { + //Timestamp must be the first KV to parse + assert(*num_kvs == 0); + + const char *start, *cur; + int32_t ret = TSDB_CODE_SUCCESS; + int len = 0; + char key[] = OTS_TIMESTAMP_COLUMN_NAME; + char *value = NULL; + + start = cur = *index; + //allocate fields for timestamp and value + *pTS = tcalloc(MAX_TELNET_FILEDS_NUM, sizeof(TAOS_SML_KV)); + + while(*cur != '\0') { + if (*cur == ' ') { + break; + } + cur++; + len++; + } + + if (len > 0 && *cur != '\0') { + value = tcalloc(len + 1, 1); + memcpy(value, start, len); + } else { + tfree(*pTS); + return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + } + + ret = convertSmlTimeStamp(*pTS, value, len, info); + if (ret) { + tfree(value); + tfree(*pTS); + return ret; + } + tfree(value); + + (*pTS)->key = tcalloc(sizeof(key), 1); + memcpy((*pTS)->key, key, sizeof(key)); + + *num_kvs += 1; + *index = cur + 1; + + return ret; +} + +static int32_t parseTelnetMetricValue(TAOS_SML_KV **pKVs, int *num_kvs, const char **index, SSmlLinesInfo* info) { + //skip timestamp + TAOS_SML_KV *pVal = *pKVs + 1; + const char *start, *cur; + int32_t ret = TSDB_CODE_SUCCESS; + int len = 0; + char key[] = OTS_METRIC_VALUE_COLUMN_NAME; + char *value = NULL; + + start = cur = *index; + + while(*cur != '\0') { + if (*cur == ' ') { + break; + } + cur++; + len++; + } + + if (len > 0 && *cur != '\0') { + value = tcalloc(len + 1, 1); + memcpy(value, start, len); + } else { + return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + } + + if (!convertSmlValueType(pVal, value, len, info)) { + tscError("OTD:0x%"PRIx64" Failed to convert metric value string(%s) to any type", + info->id, value); + tfree(value); + return TSDB_CODE_TSC_INVALID_VALUE; + } + tfree(value); + + pVal->key = tcalloc(sizeof(key), 1); + memcpy(pVal->key, key, sizeof(key)); + *num_kvs += 1; + + *index = cur + 1; + return ret; +} + +static int32_t parseTelnetTagKey(TAOS_SML_KV *pKV, const char **index, SHashObj *pHash, SSmlLinesInfo* info) { + const char *cur = *index; + char key[TSDB_COL_NAME_LEN + 1]; // +1 to avoid key[len] over write + uint16_t len = 0; + + //key field cannot start with digit + if (isdigit(*cur)) { + tscError("OTD:0x%"PRIx64" Tag key cannnot start with digit", info->id); + return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + } + while (*cur != '\0') { + if (len > TSDB_COL_NAME_LEN) { + tscError("OTD:0x%"PRIx64" Tag key cannot exceeds 65 characters", info->id); + return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; + } + if (*cur == '=') { + break; + } + + key[len] = *cur; + cur++; + len++; + } + if (len == 0 || *cur == '\0') { + return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + } + key[len] = '\0'; + + if (checkDuplicateKey(key, pHash, info)) { + return TSDB_CODE_TSC_DUP_TAG_NAMES; + } + + pKV->key = tcalloc(len + 1, 1); + memcpy(pKV->key, key, len + 1); + //tscDebug("OTD:0x%"PRIx64" Key:%s|len:%d", info->id, pKV->key, len); + *index = cur + 1; + return TSDB_CODE_SUCCESS; +} + + +static int32_t parseTelnetTagValue(TAOS_SML_KV *pKV, const char **index, + bool *is_last_kv, SSmlLinesInfo* info) { + const char *start, *cur; + char *value = NULL; + uint16_t len = 0; + start = cur = *index; + + while (1) { + // ',' or '\0' identifies a value + if (*cur == ',' || *cur == '\0') { + // '\0' indicates end of value + *is_last_kv = (*cur == '\0') ? true : false; + break; + } + cur++; + len++; + } + + if (len == 0) { + tfree(pKV->key); + return TSDB_CODE_TSC_LINE_SYNTAX_ERROR; + } + + value = tcalloc(len + 1, 1); + memcpy(value, start, len); + value[len] = '\0'; + if (!convertSmlValueType(pKV, value, len, info)) { + tscError("OTD:0x%"PRIx64" Failed to convert sml value string(%s) to any type", + info->id, value); + //free previous alocated key field + tfree(pKV->key); + tfree(value); + return TSDB_CODE_TSC_INVALID_VALUE; + } + tfree(value); + + *index = (*cur == '\0') ? cur : cur + 1; + return TSDB_CODE_SUCCESS; +} + +static int32_t parseTelnetTagKvs(TAOS_SML_KV **pKVs, int *num_kvs, + const char **index, char **childTableName, + SHashObj *pHash, SSmlLinesInfo* info) { + const char *cur = *index; + int32_t ret = TSDB_CODE_SUCCESS; + TAOS_SML_KV *pkv; + bool is_last_kv = false; + + int32_t capacity = 4; + *pKVs = tcalloc(capacity, sizeof(TAOS_SML_KV)); + pkv = *pKVs; + + while (*cur != '\0') { + ret = parseTelnetTagKey(pkv, &cur, pHash, info); + if (ret) { + tscError("OTD:0x%"PRIx64" Unable to parse key", info->id); + return ret; + } + ret = parseTelnetTagValue(pkv, &cur, &is_last_kv, info); + if (ret) { + tscError("OTD:0x%"PRIx64" Unable to parse value", info->id); + return ret; + } + if ((strcasecmp(pkv->key, "ID") == 0) && pkv->type == TSDB_DATA_TYPE_BINARY) { + ret = isValidChildTableName(pkv->value, pkv->length); + if (ret) { + return ret; + } + *childTableName = malloc(pkv->length + 1); + memcpy(*childTableName, pkv->value, pkv->length); + (*childTableName)[pkv->length] = '\0'; + tfree(pkv->key); + tfree(pkv->value); + } else { + *num_kvs += 1; + } + + if (is_last_kv) { + break; + } + + //reallocate addtional memory for more kvs + if ((*num_kvs + 1) > capacity) { + TAOS_SML_KV *more_kvs = NULL; + capacity *= 3; capacity /= 2; + more_kvs = realloc(*pKVs, capacity * sizeof(TAOS_SML_KV)); + if (!more_kvs) { + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + *pKVs = more_kvs; + } + + //move pKV points to next TAOS_SML_KV block + pkv = *pKVs + *num_kvs; + } + + return ret; +} + +int32_t tscParseTelnetLine(const char* line, TAOS_SML_DATA_POINT* smlData, SSmlLinesInfo* info) { + const char* index = line; + int32_t ret = TSDB_CODE_SUCCESS; + + //Parse metric + ret = parseTelnetMetric(smlData, &index, info); + if (ret) { + tscError("OTD:0x%"PRIx64" Unable to parse metric", info->id); + return ret; + } + tscDebug("OTD:0x%"PRIx64" Parse metric finished", info->id); + + //Parse timestamp + ret = parseTelnetTimeStamp(&smlData->fields, &smlData->fieldNum, &index, info); + if (ret) { + tscError("OTD:0x%"PRIx64" Unable to parse timestamp", info->id); + return ret; + } + tscDebug("OTD:0x%"PRIx64" Parse timestamp finished", info->id); + + //Parse value + ret = parseTelnetMetricValue(&smlData->fields, &smlData->fieldNum, &index, info); + if (ret) { + tscError("OTD:0x%"PRIx64" Unable to parse metric value", info->id); + return ret; + } + tscDebug("OTD:0x%"PRIx64" Parse metric value finished", info->id); + + //Parse tagKVs + SHashObj *keyHashTable = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, false); + ret = parseTelnetTagKvs(&smlData->tags, &smlData->tagNum, &index, &smlData->childTableName, keyHashTable, info); + if (ret) { + tscError("OTD:0x%"PRIx64" Unable to parse tags", info->id); + taosHashCleanup(keyHashTable); + return ret; + } + tscDebug("OTD:0x%"PRIx64" Parse tags finished", info->id); + taosHashCleanup(keyHashTable); + + + return TSDB_CODE_SUCCESS; +} + +int32_t tscParseTelnetLines(char* lines[], int numLines, SArray* points, SArray* failedLines, SSmlLinesInfo* info) { + for (int32_t i = 0; i < numLines; ++i) { + TAOS_SML_DATA_POINT point = {0}; + int32_t code = tscParseTelnetLine(lines[i], &point, info); + if (code != TSDB_CODE_SUCCESS) { + tscError("OTD:0x%"PRIx64" data point line parse failed. line %d : %s", info->id, i, lines[i]); + destroySmlDataPoint(&point); + return code; + } else { + tscDebug("OTD:0x%"PRIx64" data point line parse success. line %d", info->id, i); + } + + taosArrayPush(points, &point); + } + return TSDB_CODE_SUCCESS; +} + +int taos_insert_telnet_lines(TAOS* taos, char* lines[], int numLines) { + int32_t code = 0; + + SSmlLinesInfo* info = tcalloc(1, sizeof(SSmlLinesInfo)); + info->id = genUID(); + + if (numLines <= 0 || numLines > 65536) { + tscError("OTD:0x%"PRIx64" taos_insert_telnet_lines numLines should be between 1 and 65536. numLines: %d", info->id, numLines); + tfree(info); + code = TSDB_CODE_TSC_APP_ERROR; + return code; + } + + for (int i = 0; i < numLines; ++i) { + if (lines[i] == NULL) { + tscError("OTD:0x%"PRIx64" taos_insert_telnet_lines line %d is NULL", info->id, i); + tfree(info); + code = TSDB_CODE_TSC_APP_ERROR; + return code; + } + } + + SArray* lpPoints = taosArrayInit(numLines, sizeof(TAOS_SML_DATA_POINT)); + if (lpPoints == NULL) { + tscError("OTD:0x%"PRIx64" taos_insert_telnet_lines failed to allocate memory", info->id); + tfree(info); + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + + tscDebug("OTD:0x%"PRIx64" taos_insert_telnet_lines begin inserting %d lines, first line: %s", info->id, numLines, lines[0]); + code = tscParseTelnetLines(lines, numLines, lpPoints, NULL, info); + size_t numPoints = taosArrayGetSize(lpPoints); + + if (code != 0) { + goto cleanup; + } + + TAOS_SML_DATA_POINT* points = TARRAY_GET_START(lpPoints); + code = tscSmlInsert(taos, points, (int)numPoints, info); + if (code != 0) { + tscError("OTD:0x%"PRIx64" taos_insert_telnet_lines error: %s", info->id, tstrerror((code))); + } + +cleanup: + tscDebug("OTD:0x%"PRIx64" taos_insert_telnet_lines finish inserting %d lines. code: %d", info->id, numLines, code); + points = TARRAY_GET_START(lpPoints); + numPoints = taosArrayGetSize(lpPoints); + for (int i=0; iid = genUID(); + int code = tscSmlInsert(taos, points, numPoint, info); + tfree(info); + return code; +} diff --git a/src/client/src/tscPrepare.c b/src/client/src/tscPrepare.c index 7f7966559bf50d352e83e0a29ec69a9c7e3c034a..bbddc4bff925de1a7d0b67fd233b6e2e88a618a3 100644 --- a/src/client/src/tscPrepare.c +++ b/src/client/src/tscPrepare.c @@ -206,6 +206,8 @@ static int normalStmtPrepare(STscStmt* stmt) { return code; } start = i + token.n; + } else if (token.type == TK_ILLEGAL) { + return invalidOperationMsg(tscGetErrorMsgPayload(&stmt->pSql->cmd), "invalid sql"); } i += token.n; @@ -1527,8 +1529,9 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) { pCmd->insertParam.insertType = TSDB_QUERY_TYPE_STMT_INSERT; pCmd->insertParam.objectId = pSql->self; - pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1); - + char* sqlstr = realloc(pSql->sqlstr, sqlLen + 1); + if(sqlstr == NULL && pSql->sqlstr) free(pSql->sqlstr); + pSql->sqlstr = sqlstr; if (pSql->sqlstr == NULL) { tscError("%p failed to malloc sql string buffer", pSql); STMT_RET(TSDB_CODE_TSC_OUT_OF_MEMORY); @@ -1537,6 +1540,8 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) { pRes->qId = 0; pRes->numOfRows = 1; + registerSqlObj(pSql); + strtolower(pSql->sqlstr, sql); tscDebugL("0x%"PRIx64" SQL: %s", pSql->self, pSql->sqlstr); @@ -1546,8 +1551,6 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) { pSql->cmd.insertParam.numOfParams = 0; pSql->cmd.batchSize = 0; - registerSqlObj(pSql); - int32_t ret = stmtParseInsertTbTags(pSql, pStmt); if (ret != TSDB_CODE_SUCCESS) { STMT_RET(ret); diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 612a3d4798791c9632ac89b9fc701935294f17e8..87b6b076527a17b48dabfcf73e8423128a0e7128 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -22,6 +22,7 @@ #include #include "os.h" +#include "regex.h" #include "qPlan.h" #include "qSqlparser.h" #include "qTableMeta.h" @@ -71,7 +72,6 @@ static int convertTimestampStrToInt64(tVariant *pVar, int32_t precision); static bool serializeExprListToVariant(SArray* pList, tVariant **dst, int16_t colType, uint8_t precision); static bool has(SArray* pFieldList, int32_t startIdx, const char* name); -static char* cloneCurrentDBName(SSqlObj* pSql); static int32_t getDelimiterIndex(SStrToken* pTableName); static bool validateTableColumnInfo(SArray* pFieldList, SSqlCmd* pCmd); static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pCmd); @@ -116,7 +116,7 @@ static int32_t validateColumnName(char* name); static int32_t setKillInfo(SSqlObj* pSql, struct SSqlInfo* pInfo, int32_t killType); static int32_t setCompactVnodeInfo(SSqlObj* pSql, struct SSqlInfo* pInfo); -static bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField); +static int32_t validateOneTag(SSqlCmd* pCmd, TAOS_FIELD* pTagField); static bool hasTimestampForPointInterpQuery(SQueryInfo* pQueryInfo); static bool hasNormalColumnFilter(SQueryInfo* pQueryInfo); @@ -279,6 +279,8 @@ static uint8_t convertRelationalOperator(SStrToken *pToken) { return TSDB_BINARY_OP_REMAINDER; case TK_LIKE: return TSDB_RELATION_LIKE; + case TK_MATCH: + return TSDB_RELATION_MATCH; case TK_ISNULL: return TSDB_RELATION_ISNULL; case TK_NOTNULL: @@ -426,13 +428,12 @@ int32_t readFromFile(char *name, uint32_t *len, void **buf) { return TSDB_CODE_TSC_APP_ERROR; } close(fd); - tfree(*buf); return TSDB_CODE_SUCCESS; } int32_t handleUserDefinedFunc(SSqlObj* pSql, struct SSqlInfo* pInfo) { - const char *msg1 = "function name is too long"; + const char *msg1 = "invalidate function name"; const char *msg2 = "path is too long"; const char *msg3 = "invalid outputtype"; const char *msg4 = "invalid script"; @@ -449,7 +450,10 @@ int32_t handleUserDefinedFunc(SSqlObj* pSql, struct SSqlInfo* pInfo) { } createInfo->name.z[createInfo->name.n] = 0; - + // funcname's naming rule is same to column + if (validateColumnName(createInfo->name.z) != TSDB_CODE_SUCCESS) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); + } strdequote(createInfo->name.z); if (strlen(createInfo->name.z) >= TSDB_FUNC_NAME_LEN) { @@ -892,6 +896,7 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { } case TSDB_SQL_SELECT: { + const char * msg1 = "no nested query supported in union clause"; code = loadAllTableMeta(pSql, pInfo); if (code != TSDB_CODE_SUCCESS) { return code; @@ -905,6 +910,10 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { tscTrace("0x%"PRIx64" start to parse the %dth subclause, total:%"PRIzu, pSql->self, i, size); + if (size > 1 && pSqlNode->from && pSqlNode->from->type == SQL_NODE_FROM_SUBQUERY) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); + } + // normalizeSqlNode(pSqlNode); // normalize the column name in each function if ((code = validateSqlNode(pSql, pSqlNode, pQueryInfo)) != TSDB_CODE_SUCCESS) { return code; @@ -925,7 +934,6 @@ int32_t tscValidateSqlInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { pQueryInfo = pCmd->active; pQueryInfo->pUdfInfo = pUdfInfo; pQueryInfo->udfCopy = true; - } } @@ -1079,12 +1087,13 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS const char* msg1 = "sliding cannot be used without interval"; const char* msg2 = "interval cannot be less than 1 us"; const char* msg3 = "interval value is too small"; + const char* msg4 = "only point interpolation query requires keyword EVERY"; SSqlCmd* pCmd = &pSql->cmd; STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta); - + if (!TPARSER_HAS_TOKEN(pSqlNode->interval.interval)) { if (TPARSER_HAS_TOKEN(pSqlNode->sliding)) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); @@ -1110,7 +1119,6 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS } if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit != 'y') { - // interval cannot be less than 10 milliseconds if (convertTimePrecision(pQueryInfo->interval.interval, tinfo.precision, TSDB_TIME_PRECISION_MICRO) < tsMinIntervalTime) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); @@ -1125,9 +1133,15 @@ int32_t validateIntervalNode(SSqlObj* pSql, SQueryInfo* pQueryInfo, SSqlNode* pS return TSDB_CODE_TSC_INVALID_OPERATION; } + bool interpQuery = tscIsPointInterpQuery(pQueryInfo); + if ((pSqlNode->interval.token == TK_EVERY && (!interpQuery)) || (pSqlNode->interval.token == TK_INTERVAL && interpQuery)) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); + } + // The following part is used to check for the invalid query expression. return checkInvalidExprForTimeWindow(pCmd, pQueryInfo); } + static int32_t validateStateWindowNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, bool isStable) { const char* msg1 = "invalid column name"; @@ -1534,9 +1548,7 @@ static bool validateTagParams(SArray* pTagsList, SArray* pFieldList, SSqlCmd* pC /* * tags name /column name is truncated in sql.y */ -bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) { - //const char* msg1 = "timestamp not allowed in tags"; - const char* msg2 = "duplicated column names"; +int32_t validateOneTag(SSqlCmd* pCmd, TAOS_FIELD* pTagField) { const char* msg3 = "tag length too long"; const char* msg4 = "invalid tag name"; const char* msg5 = "invalid binary/nchar tag length"; @@ -1551,8 +1563,7 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) { // no more max columns if (numOfTags + numOfCols >= TSDB_MAX_COLUMNS) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7); } // no more than 6 tags @@ -1560,8 +1571,7 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) { char msg[128] = {0}; sprintf(msg, "tags no more than %d", TSDB_MAX_TAGS); - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg); } // no timestamp allowable @@ -1571,8 +1581,7 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) { //} if ((pTagField->type < TSDB_DATA_TYPE_BOOL) || (pTagField->type > TSDB_DATA_TYPE_UBIGINT)) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); } SSchema* pTagSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta); @@ -1584,20 +1593,17 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) { // length less than TSDB_MAX_TASG_LEN if (nLen + pTagField->bytes > TSDB_MAX_TAGS_LEN) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); } // tags name can not be a keyword if (validateColumnName(pTagField->name) != TSDB_CODE_SUCCESS) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); } // binary(val), val can not be equalled to or less than 0 if ((pTagField->type == TSDB_DATA_TYPE_BINARY || pTagField->type == TSDB_DATA_TYPE_NCHAR) && pTagField->bytes <= 0) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); } // field name must be unique @@ -1605,17 +1611,16 @@ bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField) { for (int32_t i = 0; i < numOfTags + numOfCols; ++i) { if (strncasecmp(pTagField->name, pSchema[i].name, sizeof(pTagField->name) - 1) == 0) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); - return false; + //return tscErrorMsgWithCode(TSDB_CODE_TSC_DUP_COL_NAMES, tscGetErrorMsgPayload(pCmd), pTagField->name, NULL); + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "duplicated column names"); } } - return true; + return TSDB_CODE_SUCCESS; } -bool validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) { +int32_t validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) { const char* msg1 = "too many columns"; - const char* msg2 = "duplicated column names"; const char* msg3 = "column length too long"; const char* msg4 = "invalid data type"; const char* msg5 = "invalid column name"; @@ -1630,18 +1635,15 @@ bool validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) { // no more max columns if (numOfCols >= TSDB_MAX_COLUMNS || numOfTags + numOfCols >= TSDB_MAX_COLUMNS) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); } if (pColField->type < TSDB_DATA_TYPE_BOOL || pColField->type > TSDB_DATA_TYPE_UBIGINT) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4); } if (validateColumnName(pColField->name) != TSDB_CODE_SUCCESS) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); } SSchema* pSchema = tscGetTableSchema(pTableMeta); @@ -1652,25 +1654,23 @@ bool validateOneColumn(SSqlCmd* pCmd, TAOS_FIELD* pColField) { } if (pColField->bytes <= 0) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); } // length less than TSDB_MAX_BYTES_PER_ROW if (nLen + pColField->bytes > TSDB_MAX_BYTES_PER_ROW) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); - return false; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3); } // field name must be unique for (int32_t i = 0; i < numOfTags + numOfCols; ++i) { if (strncasecmp(pColField->name, pSchema[i].name, sizeof(pColField->name) - 1) == 0) { - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); - return false; + //return tscErrorMsgWithCode(TSDB_CODE_TSC_DUP_COL_NAMES, tscGetErrorMsgPayload(pCmd), pColField->name, NULL); + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), "duplicated column names"); } } - return true; + return TSDB_CODE_SUCCESS; } /* is contained in pFieldList or not */ @@ -1686,14 +1686,6 @@ static bool has(SArray* pFieldList, int32_t startIdx, const char* name) { static char* getAccountId(SSqlObj* pSql) { return pSql->pTscObj->acctId; } -static char* cloneCurrentDBName(SSqlObj* pSql) { - pthread_mutex_lock(&pSql->pTscObj->mutex); - char *p = strdup(pSql->pTscObj->db); - pthread_mutex_unlock(&pSql->pTscObj->mutex); - - return p; -} - /* length limitation, strstr cannot be applied */ static int32_t getDelimiterIndex(SStrToken* pTableName) { for (uint32_t i = 0; i < pTableName->n; ++i) { @@ -2049,9 +2041,10 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES); } + bool hasDistinct = false; bool hasAgg = false; - size_t numOfExpr = taosArrayGetSize(pSelNodeList); + size_t numOfExpr = taosArrayGetSize(pSelNodeList); int32_t distIdx = -1; for (int32_t i = 0; i < numOfExpr; ++i) { int32_t outputIndex = (int32_t)tscNumOfExprs(pQueryInfo); @@ -2106,7 +2099,6 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS } } - //TODO(dengyihao), refactor as function //handle distinct func mixed with other func if (hasDistinct == true) { @@ -2122,6 +2114,7 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS if (pQueryInfo->pDownstream != NULL) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg8); } + pQueryInfo->distinct = true; } @@ -2606,13 +2599,12 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col // set the first column ts for diff query if (functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_DERIVATIVE) { - colIndex += 1; SColumnIndex indexTS = {.tableIndex = index.tableIndex, .columnIndex = 0}; SExprInfo* pExpr = tscExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &indexTS, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, getNewResColId(pCmd), TSDB_KEYSIZE, false); SColumnList ids = createColumnList(1, 0, 0); - insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[TSDB_FUNC_TS_DUMMY].name, pExpr); + insertResultField(pQueryInfo, colIndex, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[TSDB_FUNC_TS_DUMMY].name, pExpr); } SExprInfo* pExpr = tscExprAppend(pQueryInfo, functionId, &index, resultType, resultSize, getNewResColId(pCmd), intermediateResSize, false); @@ -2646,7 +2638,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col tickPerSec /= TSDB_TICK_PER_SECOND(TSDB_TIME_PRECISION_MICRO); } else if (info.precision == TSDB_TIME_PRECISION_MICRO) { tickPerSec /= TSDB_TICK_PER_SECOND(TSDB_TIME_PRECISION_MILLI); - } + } if (tickPerSec <= 0 || tickPerSec < TSDB_TICK_PER_SECOND(info.precision)) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg10); @@ -2680,8 +2672,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col assert(ids.num == 1); tscColumnListInsert(pQueryInfo->colList, ids.ids[0].columnIndex, pExpr->base.uid, pSchema); } - tscInsertPrimaryTsSourceColumn(pQueryInfo, pExpr->base.uid); + return TSDB_CODE_SUCCESS; } @@ -2885,7 +2877,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col const int32_t TS_COLUMN_INDEX = PRIMARYKEY_TIMESTAMP_COL_INDEX; SColumnList ids = createColumnList(1, index.tableIndex, TS_COLUMN_INDEX); - insertResultField(pQueryInfo, TS_COLUMN_INDEX, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, + insertResultField(pQueryInfo, colIndex, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, aAggs[TSDB_FUNC_TS].name, pExpr); colIndex += 1; // the first column is ts @@ -3063,7 +3055,6 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col tscColumnListInsert(pQueryInfo->colList, index.columnIndex, uid, &s); } } - tscInsertPrimaryTsSourceColumn(pQueryInfo, pTableMetaInfo->pTableMeta->id.uid); return TSDB_CODE_SUCCESS; } @@ -3788,6 +3779,9 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, case TK_LIKE: pColumnFilter->lowerRelOptr = TSDB_RELATION_LIKE; break; + case TK_MATCH: + pColumnFilter->lowerRelOptr = TSDB_RELATION_MATCH; + break; case TK_ISNULL: pColumnFilter->lowerRelOptr = TSDB_RELATION_ISNULL; break; @@ -3851,9 +3845,15 @@ static int32_t tablenameListToString(tSqlExpr* pExpr, SStringBuilder* sb) { return TSDB_CODE_SUCCESS; } -static int32_t tablenameCondToString(tSqlExpr* pExpr, SStringBuilder* sb) { - taosStringBuilderAppendStringLen(sb, QUERY_COND_REL_PREFIX_LIKE, QUERY_COND_REL_PREFIX_LIKE_LEN); - taosStringBuilderAppendString(sb, pExpr->value.pz); +static int32_t tablenameCondToString(tSqlExpr* pExpr, uint32_t opToken, SStringBuilder* sb) { + assert(opToken == TK_LIKE || opToken == TK_MATCH); + if (opToken == TK_LIKE) { + taosStringBuilderAppendStringLen(sb, QUERY_COND_REL_PREFIX_LIKE, QUERY_COND_REL_PREFIX_LIKE_LEN); + taosStringBuilderAppendString(sb, pExpr->value.pz); + } else if (opToken == TK_MATCH) { + taosStringBuilderAppendStringLen(sb, QUERY_COND_REL_PREFIX_MATCH, QUERY_COND_REL_PREFIX_MATCH_LEN); + taosStringBuilderAppendString(sb, pExpr->value.pz); + } return TSDB_CODE_SUCCESS; } @@ -3874,7 +3874,7 @@ static int32_t checkColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCol 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* msg1 = "non binary column not support like/match 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"; @@ -3902,12 +3902,13 @@ static int32_t checkColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCol && pExpr->tokenId != TK_ISNULL && pExpr->tokenId != TK_NOTNULL && pExpr->tokenId != TK_LIKE + && pExpr->tokenId != TK_MATCH && pExpr->tokenId != TK_IN) { ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); goto _err_ret; } } else { - if (pExpr->tokenId == TK_LIKE) { + if (pExpr->tokenId == TK_LIKE || pExpr->tokenId == TK_MATCH) { ret = invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); goto _err_ret; } @@ -3955,12 +3956,12 @@ static int32_t getTablenameCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr* if (pTableCond->tokenId == TK_IN) { ret = tablenameListToString(pRight, sb); - } else if (pTableCond->tokenId == TK_LIKE) { + } else if (pTableCond->tokenId == TK_LIKE || pTableCond->tokenId == TK_MATCH) { if (pRight->tokenId != TK_STRING) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); } - ret = tablenameCondToString(pRight, sb); + ret = tablenameCondToString(pRight, pTableCond->tokenId, sb); } if (ret != TSDB_CODE_SUCCESS) { @@ -4409,7 +4410,7 @@ static bool validateJoinExprNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSqlExpr } static bool validTableNameOptr(tSqlExpr* pExpr) { - const char nameFilterOptr[] = {TK_IN, TK_LIKE}; + const char nameFilterOptr[] = {TK_IN, TK_LIKE, TK_MATCH}; for (int32_t i = 0; i < tListLen(nameFilterOptr); ++i) { if (pExpr->tokenId == nameFilterOptr[i]) { @@ -4501,6 +4502,45 @@ static int32_t validateLikeExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t return TSDB_CODE_SUCCESS; } +// check for match expression +static int32_t validateMatchExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t index, char* msgBuf) { + const char* msg1 = "regular expression string should be less than %d characters"; + const char* msg2 = "illegal column type for match"; + const char* msg3 = "invalid regular expression"; + + tSqlExpr* pLeft = pExpr->pLeft; + tSqlExpr* pRight = pExpr->pRight; + + if (pExpr->tokenId == TK_MATCH) { + if (pRight->value.nLen > tsMaxRegexStringLen) { + char tmp[64] = {0}; + sprintf(tmp, msg1, tsMaxRegexStringLen); + return invalidOperationMsg(msgBuf, tmp); + } + + SSchema* pSchema = tscGetTableSchema(pTableMeta); + if ((!isTablenameToken(&pLeft->columnName)) && !IS_VAR_DATA_TYPE(pSchema[index].type)) { + return invalidOperationMsg(msgBuf, msg2); + } + + int errCode = 0; + regex_t regex; + char regErrBuf[256] = {0}; + + const char* pattern = pRight->value.pz; + int cflags = REG_EXTENDED; + if ((errCode = regcomp(®ex, pattern, cflags)) != 0) { + regerror(errCode, ®ex, regErrBuf, sizeof(regErrBuf)); + tscError("Failed to compile regex pattern %s. reason %s", pattern, regErrBuf); + return invalidOperationMsg(msgBuf, msg3); + } + regfree(®ex); + } + + return TSDB_CODE_SUCCESS; +} + + int32_t handleNeOptr(tSqlExpr** rexpr, tSqlExpr* expr) { tSqlExpr* left = tSqlExprClone(expr); tSqlExpr* right = expr; @@ -4552,6 +4592,12 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql return code; } + // validate the match expression + code = validateMatchExpr(*pExpr, pTableMeta, index.columnIndex, tscGetErrorMsgPayload(pCmd)); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, index.columnIndex); if (pSchema->type == TSDB_DATA_TYPE_TIMESTAMP && index.columnIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) { // query on time range if (!validateJoinExprNode(pCmd, pQueryInfo, *pExpr, &index)) { @@ -4661,7 +4707,7 @@ 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); + ret = setExprToCond(&pCondExpr->pJoinExpr, *pExpr, NULL, parentOptr, pCmd->payload); *pExpr = NULL; if (type) { *type |= TSQL_EXPR_JOIN; @@ -4879,65 +4925,66 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, STagCond* pTagCond = &pQueryInfo->tagCond; pTagCond->tbnameCond.uid = pTableMetaInfo->pTableMeta->id.uid; - assert(pExpr->tokenId == TK_LIKE || pExpr->tokenId == TK_IN); + assert(pExpr->tokenId == TK_LIKE || pExpr->tokenId == TK_MATCH || pExpr->tokenId == TK_IN); - if (pExpr->tokenId == TK_LIKE) { + if (pExpr->tokenId == TK_LIKE || pExpr->tokenId == TK_MATCH) { char* str = taosStringBuilderGetResult(sb, NULL); pQueryInfo->tagCond.tbnameCond.cond = strdup(str); pQueryInfo->tagCond.tbnameCond.len = (int32_t) strlen(str); return TSDB_CODE_SUCCESS; - } - - SStringBuilder sb1; memset(&sb1, 0, sizeof(sb1)); - taosStringBuilderAppendStringLen(&sb1, QUERY_COND_REL_PREFIX_IN, QUERY_COND_REL_PREFIX_IN_LEN); + } else { + SStringBuilder sb1; + memset(&sb1, 0, sizeof(sb1)); + taosStringBuilderAppendStringLen(&sb1, QUERY_COND_REL_PREFIX_IN, QUERY_COND_REL_PREFIX_IN_LEN); - // remove the duplicated input table names - int32_t num = 0; - char* tableNameString = taosStringBuilderGetResult(sb, NULL); + // remove the duplicated input table names + int32_t num = 0; + char* tableNameString = taosStringBuilderGetResult(sb, NULL); - char** segments = strsplit(tableNameString + QUERY_COND_REL_PREFIX_IN_LEN, TBNAME_LIST_SEP, &num); - qsort(segments, num, POINTER_BYTES, tableNameCompar); + char** segments = strsplit(tableNameString + QUERY_COND_REL_PREFIX_IN_LEN, TBNAME_LIST_SEP, &num); + qsort(segments, num, POINTER_BYTES, tableNameCompar); - int32_t j = 1; - for (int32_t i = 1; i < num; ++i) { - if (strcmp(segments[i], segments[i - 1]) != 0) { - segments[j++] = segments[i]; + int32_t j = 1; + for (int32_t i = 1; i < num; ++i) { + if (strcmp(segments[i], segments[i - 1]) != 0) { + segments[j++] = segments[i]; + } } - } - num = j; + num = j; - char name[TSDB_DB_NAME_LEN] = {0}; - tNameGetDbName(&pTableMetaInfo->name, name); - SStrToken dbToken = { .type = TK_STRING, .z = name, .n = (uint32_t)strlen(name) }; - - for (int32_t i = 0; i < num; ++i) { - if (i >= 1) { - taosStringBuilderAppendStringLen(&sb1, TBNAME_LIST_SEP, 1); - } + char name[TSDB_DB_NAME_LEN] = {0}; + tNameGetDbName(&pTableMetaInfo->name, name); + SStrToken dbToken = {.type = TK_STRING, .z = name, .n = (uint32_t)strlen(name)}; - char idBuf[TSDB_TABLE_FNAME_LEN] = {0}; - int32_t xlen = (int32_t)strlen(segments[i]); - SStrToken t = {.z = segments[i], .n = xlen, .type = TK_STRING}; + for (int32_t i = 0; i < num; ++i) { + if (i >= 1) { + taosStringBuilderAppendStringLen(&sb1, TBNAME_LIST_SEP, 1); + } - int32_t ret = setObjFullName(idBuf, account, &dbToken, &t, &xlen); - if (ret != TSDB_CODE_SUCCESS) { - taosStringBuilderDestroy(&sb1); - tfree(segments); + char idBuf[TSDB_TABLE_FNAME_LEN] = {0}; + int32_t xlen = (int32_t)strlen(segments[i]); + SStrToken t = {.z = segments[i], .n = xlen, .type = TK_STRING}; - invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg); - return ret; - } + int32_t ret = setObjFullName(idBuf, account, &dbToken, &t, &xlen); + if (ret != TSDB_CODE_SUCCESS) { + taosStringBuilderDestroy(&sb1); + tfree(segments); - taosStringBuilderAppendString(&sb1, idBuf); - } + invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg); + return ret; + } - char* str = taosStringBuilderGetResult(&sb1, NULL); - pQueryInfo->tagCond.tbnameCond.cond = strdup(str); - pQueryInfo->tagCond.tbnameCond.len = (int32_t) strlen(str); + taosStringBuilderAppendString(&sb1, idBuf); + } - taosStringBuilderDestroy(&sb1); - tfree(segments); - return TSDB_CODE_SUCCESS; + char* str = taosStringBuilderGetResult(&sb1, NULL); + pQueryInfo->tagCond.tbnameCond.cond = strdup(str); + pQueryInfo->tagCond.tbnameCond.len = (int32_t)strlen(str); + + taosStringBuilderDestroy(&sb1); + tfree(segments); + return TSDB_CODE_SUCCESS; + } } int32_t mergeTimeRange(SSqlCmd* pCmd, STimeWindow* res, STimeWindow* win, int32_t optr) { @@ -5083,10 +5130,6 @@ static void cleanQueryExpr(SCondExpr* pCondExpr) { tSqlExprDestroy(pCondExpr->pTableCond); } - if (pCondExpr->pTagCond) { - tSqlExprDestroy(pCondExpr->pTagCond); - } - if (pCondExpr->pColumnCond) { tSqlExprDestroy(pCondExpr->pColumnCond); } @@ -5643,6 +5686,7 @@ int32_t validateFillNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNo const char* msg3 = "top/bottom not support fill"; const char* msg4 = "illegal value or data overflow"; const char* msg5 = "fill only available for interval query"; + const char* msg6 = "not supported function now"; if ((!isTimeWindowQuery(pQueryInfo)) && (!tscIsPointInterpQuery(pQueryInfo))) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5); @@ -5681,6 +5725,9 @@ int32_t validateFillNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNo } } else if (strncasecmp(pItem->pVar.pz, "prev", 4) == 0 && pItem->pVar.nLen == 4) { pQueryInfo->fillType = TSDB_FILL_PREV; + if (tscIsPointInterpQuery(pQueryInfo) && pQueryInfo->order.order == TSDB_ORDER_DESC) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6); + } } else if (strncasecmp(pItem->pVar.pz, "next", 4) == 0 && pItem->pVar.nLen == 4) { pQueryInfo->fillType = TSDB_FILL_NEXT; } else if (strncasecmp(pItem->pVar.pz, "linear", 6) == 0 && pItem->pVar.nLen == 6) { @@ -5785,14 +5832,13 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq const char* msg7 = "only primary timestamp/column in groupby clause allowed as order column"; const char* msg8 = "only column in groupby clause allowed as order column"; const char* msg9 = "orderby column must projected in subquery"; + const char* msg10 = "not support distinct mixed with order by"; setDefaultOrderInfo(pQueryInfo); STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); - - if (pQueryInfo->distinct || pSqlNode->pSortOrder == NULL) { - return TSDB_CODE_SUCCESS; - } - + if (pSqlNode->pSortOrder == NULL) { + return TSDB_CODE_SUCCESS; + } char* pMsgBuf = tscGetErrorMsgPayload(pCmd); SArray* pSortOrder = pSqlNode->pSortOrder; @@ -5812,6 +5858,9 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq return invalidOperationMsg(pMsgBuf, msg2); } } + if (size > 0 && pQueryInfo->distinct) { + return invalidOperationMsg(pMsgBuf, msg10); + } // handle the first part of order by tVariant* pVar = taosArrayGet(pSortOrder, 0); @@ -5880,10 +5929,14 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId; } else if (isTopBottomQuery(pQueryInfo)) { /* order of top/bottom query in interval is not valid */ - SExprInfo* pExpr = tscExprGet(pQueryInfo, 0); + + int32_t pos = tscExprTopBottomIndex(pQueryInfo); + assert(pos > 0); + SExprInfo* pExpr = tscExprGet(pQueryInfo, pos - 1); assert(pExpr->base.functionId == TSDB_FUNC_TS); - pExpr = tscExprGet(pQueryInfo, 1); + pExpr = tscExprGet(pQueryInfo, pos); + if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) { return invalidOperationMsg(pMsgBuf, msg5); } @@ -5974,11 +6027,13 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq return invalidOperationMsg(pMsgBuf, msg8); } } else { - /* order of top/bottom query in interval is not valid */ - SExprInfo* pExpr = tscExprGet(pQueryInfo, 0); + int32_t pos = tscExprTopBottomIndex(pQueryInfo); + assert(pos > 0); + SExprInfo* pExpr = tscExprGet(pQueryInfo, pos - 1); assert(pExpr->base.functionId == TSDB_FUNC_TS); - pExpr = tscExprGet(pQueryInfo, 1); + pExpr = tscExprGet(pQueryInfo, pos); + if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) { return invalidOperationMsg(pMsgBuf, msg5); } @@ -6037,7 +6092,6 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { const char* msg19 = "invalid new tag name"; const char* msg20 = "table is not super table"; const char* msg21 = "only binary/nchar column length could be modified"; - const char* msg22 = "new column length should be bigger than old one"; const char* msg23 = "only column length coulbe be modified"; const char* msg24 = "invalid binary/nchar column length"; @@ -6089,8 +6143,9 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { } TAOS_FIELD* p = taosArrayGet(pFieldList, 0); - if (!validateOneTags(pCmd, p)) { - return TSDB_CODE_TSC_INVALID_OPERATION; + int32_t ret = validateOneTag(pCmd, p); + if (ret != TSDB_CODE_SUCCESS) { + return ret; } tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p); @@ -6267,8 +6322,9 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { } TAOS_FIELD* p = taosArrayGet(pFieldList, 0); - if (!validateOneColumn(pCmd, p)) { - return TSDB_CODE_TSC_INVALID_OPERATION; + int32_t ret = validateOneColumn(pCmd, p); + if (ret != TSDB_CODE_SUCCESS) { + return ret; } tscFieldInfoAppend(&pQueryInfo->fieldsInfo, p); @@ -6331,7 +6387,7 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { } if (pItem->bytes <= pColSchema->bytes) { - return invalidOperationMsg(pMsg, msg22); + return tscErrorMsgWithCode(TSDB_CODE_TSC_INVALID_COLUMN_LENGTH, pMsg, pItem->name, NULL); } SSchema* pSchema = (SSchema*) pTableMetaInfo->pTableMeta->schema; @@ -6382,7 +6438,7 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { } if (pItem->bytes <= pColSchema->bytes) { - return invalidOperationMsg(pMsg, msg22); + return tscErrorMsgWithCode(TSDB_CODE_TSC_INVALID_TAG_LENGTH, pMsg, pItem->name, NULL); } SSchema* pSchema = tscGetTableTagSchema(pTableMetaInfo->pTableMeta); @@ -7172,7 +7228,6 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo const char* msg1 = "interval not allowed in group by normal column"; STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); - SSchema* pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta); SSchema* tagSchema = NULL; @@ -7198,9 +7253,7 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo s = &pSchema[colIndex]; } } - - size_t size = tscNumOfExprs(pQueryInfo); - + if (TSDB_COL_IS_TAG(pColIndex->flag)) { int32_t f = TSDB_FUNC_TAG; @@ -7208,8 +7261,10 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo f = TSDB_FUNC_TAGPRJ; } + int32_t pos = tscGetFirstInvisibleFieldPos(pQueryInfo); + SColumnIndex index = {.tableIndex = pQueryInfo->groupbyExpr.tableIndex, .columnIndex = colIndex}; - SExprInfo* pExpr = tscExprAppend(pQueryInfo, f, &index, s->type, s->bytes, getNewResColId(pCmd), s->bytes, true); + SExprInfo* pExpr = tscExprInsert(pQueryInfo, pos, f, &index, s->type, s->bytes, getNewResColId(pCmd), s->bytes, true); memset(pExpr->base.aliasName, 0, sizeof(pExpr->base.aliasName)); tstrncpy(pExpr->base.aliasName, s->name, sizeof(pExpr->base.aliasName)); @@ -7219,13 +7274,15 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo // NOTE: tag column does not add to source column list SColumnList ids = createColumnList(1, 0, pColIndex->colIndex); - insertResultField(pQueryInfo, (int32_t)size, &ids, s->bytes, (int8_t)s->type, s->name, pExpr); + insertResultField(pQueryInfo, pos, &ids, s->bytes, (int8_t)s->type, s->name, pExpr); } else { // if this query is "group by" normal column, time window query is not allowed if (isTimeWindowQuery(pQueryInfo)) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); } + size_t size = tscNumOfExprs(pQueryInfo); + bool hasGroupColumn = false; for (int32_t j = 0; j < size; ++j) { SExprInfo* pExpr = tscExprGet(pQueryInfo, j); @@ -8114,7 +8171,7 @@ int32_t tscGetExprFilters(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pSelect } static int32_t handleExprInHavingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pSelectNodeList, tSqlExpr* pExpr, int32_t sqlOptr) { - const char* msg1 = "non binary column not support like operator"; + const char* msg1 = "non binary column not support like/match operator"; const char* msg2 = "invalid operator for binary column in having clause"; const char* msg3 = "invalid operator for bool column in having clause"; @@ -8166,11 +8223,12 @@ static int32_t handleExprInHavingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, S && pExpr->tokenId != TK_ISNULL && pExpr->tokenId != TK_NOTNULL && pExpr->tokenId != TK_LIKE + && pExpr->tokenId != TK_MATCH ) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2); } } else { - if (pExpr->tokenId == TK_LIKE) { + if (pExpr->tokenId == TK_LIKE || pExpr->tokenId == TK_MATCH) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); } @@ -8453,7 +8511,10 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) { size_t len = strlen(name); - taosHashGetCloneExt(tscTableMetaMap, name, len, NULL, (void **)&pTableMeta, &tableMetaCapacity); + if (NULL == taosHashGetCloneExt(tscTableMetaMap, name, len, NULL, (void **)&pTableMeta, &tableMetaCapacity)) { + // not found + tfree(pTableMeta); + } if (pTableMeta && pTableMeta->id.uid > 0) { tscDebug("0x%"PRIx64" retrieve table meta %s from local buf", pSql->self, name); @@ -8683,8 +8744,8 @@ static STableMeta* extractTempTableMetaFromSubquery(SQueryInfo* pUpstream) { n += 1; } + info->numOfColumns = n; - return meta; } @@ -8697,6 +8758,7 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SSqlObj* pS if (taosArrayGetSize(subInfo->pSubquery) >= 2) { return invalidOperationMsg(msgBuf, "not support union in subquery"); } + SQueryInfo* pSub = calloc(1, sizeof(SQueryInfo)); tscInitQueryInfo(pSub); @@ -8714,12 +8776,12 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SSqlObj* pS return code; } - // create dummy table meta info STableMetaInfo* pTableMetaInfo1 = calloc(1, sizeof(STableMetaInfo)); if (pTableMetaInfo1 == NULL) { return TSDB_CODE_TSC_OUT_OF_MEMORY; } + pTableMetaInfo1->pTableMeta = extractTempTableMetaFromSubquery(pSub); pTableMetaInfo1->tableMetaCapacity = tscGetTableMetaSize(pTableMetaInfo1->pTableMeta); @@ -8785,7 +8847,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf * select server_status(); * select server_version(); * select client_version(); - * select current_database(); + * select database(); */ if (pSqlNode->from == NULL) { assert(pSqlNode->fillType == NULL && pSqlNode->pGroupby == NULL && pSqlNode->pWhere == NULL && @@ -8803,7 +8865,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf // check if there is 3 level select SRelElementPair* subInfo = taosArrayGet(pSqlNode->from->list, i); SSqlNode* p = taosArrayGetP(subInfo->pSubquery, 0); - if (p->from->type == SQL_NODE_FROM_SUBQUERY){ + if (p->from->type == SQL_NODE_FROM_SUBQUERY) { return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg9); } @@ -8896,6 +8958,15 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf } } + // disable group result mixed up if interval/session window query exists. + if (isTimeWindowQuery(pQueryInfo)) { + size_t num = taosArrayGetSize(pQueryInfo->pUpstream); + for(int32_t i = 0; i < num; ++i) { + SQueryInfo* pUp = taosArrayGetP(pQueryInfo->pUpstream, i); + pUp->multigroupResult = false; + } + } + // parse the having clause in the first place int32_t joinQuery = (pSqlNode->from != NULL && taosArrayGetSize(pSqlNode->from->list) > 1); if (validateHavingClause(pQueryInfo, pSqlNode->pHaving, pCmd, pSqlNode->pSelNodeList, joinQuery, timeWindowQuery) != diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 29c0eb693f481ccfbf522e49fe9a8257e94f40ec..9d523f273016e258940c67eaa1596153de0998eb 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -331,22 +331,42 @@ int tscSendMsgToServer(SSqlObj *pSql) { .handle = NULL, .code = 0 }; - rpcSendRequest(pObj->pRpcObj->pDnodeConn, &pSql->epSet, &rpcMsg, &pSql->rpcRid); return TSDB_CODE_SUCCESS; } -static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { - SRpcMsg* rpcMsg = pSchedMsg->ahandle; - SRpcEpSet* pEpSet = pSchedMsg->thandle; +// handle three situation +// 1. epset retry, only return last failure ep +// 2. no epset retry, like 'taos -h invalidFqdn', return invalidFqdn +// 3. other situation, no expected +void tscSetFqdnErrorMsg(SSqlObj* pSql, SRpcEpSet* pEpSet) { + SSqlCmd* pCmd = &pSql->cmd; + SSqlRes* pRes = &pSql->res; + + char* msgBuf = tscGetErrorMsgPayload(pCmd); + + if (pEpSet) { + sprintf(msgBuf, "%s\"%s\"", tstrerror(pRes->code),pEpSet->fqdn[(pEpSet->inUse)%(pEpSet->numOfEps)]); + } else if (pCmd->command >= TSDB_SQL_MGMT) { + SRpcEpSet tEpset; + + SRpcCorEpSet *pCorEpSet = pSql->pTscObj->tscCorMgmtEpSet; + taosCorBeginRead(&pCorEpSet->version); + tEpset = pCorEpSet->epSet; + taosCorEndRead(&pCorEpSet->version); + + sprintf(msgBuf, "%s\"%s\"", tstrerror(pRes->code),tEpset.fqdn[(tEpset.inUse)%(tEpset.numOfEps)]); + } else { + sprintf(msgBuf, "%s", tstrerror(pRes->code)); + } +} +void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) { TSDB_CACHE_PTR_TYPE handle = (TSDB_CACHE_PTR_TYPE) rpcMsg->ahandle; SSqlObj* pSql = (SSqlObj*)taosAcquireRef(tscObjRef, handle); if (pSql == NULL) { rpcFreeCont(rpcMsg->pCont); - free(rpcMsg); - free(pEpSet); return; } @@ -357,28 +377,23 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { SSqlCmd *pCmd = &pSql->cmd; pSql->rpcRid = -1; - if (pObj->signature != pObj) { tscDebug("0x%"PRIx64" DB connection is closed, cmd:%d pObj:%p signature:%p", pSql->self, pCmd->command, pObj, pObj->signature); taosRemoveRef(tscObjRef, handle); taosReleaseRef(tscObjRef, handle); rpcFreeCont(rpcMsg->pCont); - free(rpcMsg); - free(pEpSet); return; } SQueryInfo* pQueryInfo = tscGetQueryInfo(pCmd); if (pQueryInfo != NULL && pQueryInfo->type == TSDB_QUERY_TYPE_FREE_RESOURCE) { tscDebug("0x%"PRIx64" sqlObj needs to be released or DB connection is closed, cmd:%d type:%d, pObj:%p signature:%p", - pSql->self, pCmd->command, pQueryInfo->type, pObj, pObj->signature); + pSql->self, pCmd->command, pQueryInfo->type, pObj, pObj->signature); taosRemoveRef(tscObjRef, handle); taosReleaseRef(tscObjRef, handle); rpcFreeCont(rpcMsg->pCont); - free(rpcMsg); - free(pEpSet); return; } @@ -407,9 +422,9 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { // 1. super table subquery // 2. nest queries are all not updated the tablemeta and retry parse the sql after cleanup local tablemeta/vgroup id buffer if ((TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY | TSDB_QUERY_TYPE_SUBQUERY | - TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) && - !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY)) || - (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_NEST_SUBQUERY)) || (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_STABLE_SUBQUERY) && pQueryInfo->distinct)) { + TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) && + !TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY)) || + (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_NEST_SUBQUERY)) || (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_STABLE_SUBQUERY) && pQueryInfo->distinct)) { // do nothing in case of super table subquery } else { pSql->retry += 1; @@ -432,8 +447,6 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { if (rpcMsg->code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) { taosReleaseRef(tscObjRef, handle); rpcFreeCont(rpcMsg->pCont); - free(rpcMsg); - free(pEpSet); return; } } @@ -485,7 +498,7 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { pRes->numOfRows += pMsg->affectedRows; tscDebug("0x%"PRIx64" SQL cmd:%s, code:%s inserted rows:%d rspLen:%d", pSql->self, sqlCmd[pCmd->command], - tstrerror(pRes->code), pMsg->affectedRows, pRes->rspLen); + tstrerror(pRes->code), pMsg->affectedRows, pRes->rspLen); } else { tscDebug("0x%"PRIx64" SQL cmd:%s, code:%s rspLen:%d", pSql->self, sqlCmd[pCmd->command], tstrerror(pRes->code), pRes->rspLen); } @@ -500,28 +513,13 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { if (rpcMsg->code != TSDB_CODE_SUCCESS) { 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) { - tscAllocPayload(pCmd, TSDB_FQDN_LEN + 64); - // handle three situation - // 1. epset retry, only return last failure ep - // 2. no epset retry, like 'taos -h invalidFqdn', return invalidFqdn - // 3. other situation, no expected - if (pEpSet) { - sprintf(tscGetErrorMsgPayload(pCmd), "%s\"%s\"", tstrerror(pRes->code),pEpSet->fqdn[(pEpSet->inUse)%(pEpSet->numOfEps)]); - } else if (pCmd->command >= TSDB_SQL_MGMT) { - SRpcEpSet tEpset; - - SRpcCorEpSet *pCorEpSet = pSql->pTscObj->tscCorMgmtEpSet; - taosCorBeginRead(&pCorEpSet->version); - tEpset = pCorEpSet->epSet; - taosCorEndRead(&pCorEpSet->version); - - sprintf(tscGetErrorMsgPayload(pCmd), "%s\"%s\"", tstrerror(pRes->code),tEpset.fqdn[(tEpset.inUse)%(tEpset.numOfEps)]); - } else { - sprintf(tscGetErrorMsgPayload(pCmd), "%s", tstrerror(pRes->code)); - } + if (rpcMsg->code == TSDB_CODE_RPC_FQDN_ERROR) { + tscAllocPayload(pCmd, TSDB_FQDN_LEN + 64); + tscSetFqdnErrorMsg(pSql, pEpSet); } + (*pSql->fp)(pSql->param, pSql, rpcMsg->code); } @@ -532,35 +530,6 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) { taosReleaseRef(tscObjRef, handle); rpcFreeCont(rpcMsg->pCont); - free(rpcMsg); - free(pEpSet); -} - -void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) { - int64_t st = taosGetTimestampUs(); - SSchedMsg schedMsg = {0}; - - schedMsg.fp = doProcessMsgFromServer; - - SRpcMsg* rpcMsgCopy = calloc(1, sizeof(SRpcMsg)); - memcpy(rpcMsgCopy, rpcMsg, sizeof(struct SRpcMsg)); - schedMsg.ahandle = (void*)rpcMsgCopy; - - SRpcEpSet* pEpSetCopy = NULL; - if (pEpSet != NULL) { - pEpSetCopy = calloc(1, sizeof(SRpcEpSet)); - memcpy(pEpSetCopy, pEpSet, sizeof(SRpcEpSet)); - } - - schedMsg.thandle = (void*)pEpSetCopy; - schedMsg.msg = NULL; - - taosScheduleTask(tscQhandle, &schedMsg); - - int64_t et = taosGetTimestampUs(); - if (et - st > 100) { - tscDebug("add message to task queue, elapsed time:%"PRId64, et - st); - } } int doBuildAndSendMsg(SSqlObj *pSql) { @@ -733,8 +702,13 @@ static int32_t tscEstimateQueryMsgSize(SSqlObj *pSql) { } } - return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + srcColFilterSize + srcTagFilterSize + exprSize + tsBufSize + - tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen; + SCond* pCond = &pQueryInfo->tagCond.tbnameCond; + if (pCond->len > 0) { + srcColListSize += pCond->len; + } + + return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + srcColFilterSize + srcTagFilterSize + + exprSize + tsBufSize + tableSerialize + sqlLen + 4096 + pQueryInfo->bufLen; } static char *doSerializeTableInfo(SQueryTableMsg *pQueryMsg, SSqlObj *pSql, STableMetaInfo *pTableMetaInfo, char *pMsg, @@ -1429,7 +1403,6 @@ int32_t tscBuildSyncDbReplicaMsg(SSqlObj* pSql, SSqlInfo *pInfo) { } int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) { - STscObj *pObj = pSql->pTscObj; SSqlCmd *pCmd = &pSql->cmd; pCmd->msgType = TSDB_MSG_TYPE_CM_SHOW; pCmd->payloadLen = sizeof(SShowMsg) + 100; @@ -1452,9 +1425,9 @@ int32_t tscBuildShowMsg(SSqlObj *pSql, SSqlInfo *pInfo) { } if (tNameIsEmpty(&pTableMetaInfo->name)) { - pthread_mutex_lock(&pObj->mutex); - tstrncpy(pShowMsg->db, pObj->db, sizeof(pShowMsg->db)); - pthread_mutex_unlock(&pObj->mutex); + char *p = cloneCurrentDBName(pSql); + tstrncpy(pShowMsg->db, p, sizeof(pShowMsg->db)); + tfree(p); } else { tNameGetFullDbName(&pTableMetaInfo->name, pShowMsg->db); } @@ -2678,7 +2651,7 @@ int tscProcessQueryRsp(SSqlObj *pSql) { return 0; } -static void decompressQueryColData(SSqlRes *pRes, SQueryInfo* pQueryInfo, char **data, int8_t compressed, int compLen) { +static void decompressQueryColData(SSqlObj *pSql, SSqlRes *pRes, SQueryInfo* pQueryInfo, char **data, int8_t compressed, int32_t compLen) { int32_t decompLen = 0; int32_t numOfCols = pQueryInfo->fieldsInfo.numOfOutput; int32_t *compSizes; @@ -2715,6 +2688,9 @@ static void decompressQueryColData(SSqlRes *pRes, SQueryInfo* pQueryInfo, char * pData = *data + compLen + numOfCols * sizeof(int32_t); } + tscDebug("0x%"PRIx64" decompress col data, compressed size:%d, decompressed size:%d", + pSql->self, (int32_t)(compLen + numOfCols * sizeof(int32_t)), decompLen); + int32_t tailLen = pRes->rspLen - sizeof(SRetrieveTableRsp) - decompLen; memmove(*data + decompLen, pData, tailLen); memmove(*data, outputBuf, decompLen); @@ -2749,7 +2725,7 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) { //Decompress col data if compressed from server if (pRetrieve->compressed) { int32_t compLen = htonl(pRetrieve->compLen); - decompressQueryColData(pRes, pQueryInfo, &pRes->data, pRetrieve->compressed, compLen); + decompressQueryColData(pSql, pRes, pQueryInfo, &pRes->data, pRetrieve->compressed, compLen); } STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); @@ -2947,11 +2923,15 @@ int32_t tscGetTableMetaImpl(SSqlObj* pSql, STableMetaInfo *pTableMetaInfo, bool // just make runtime happy if (pTableMetaInfo->tableMetaCapacity != 0 && pTableMetaInfo->pTableMeta != NULL) { memset(pTableMetaInfo->pTableMeta, 0, pTableMetaInfo->tableMetaCapacity); - } - taosHashGetCloneExt(tscTableMetaMap, name, len, NULL, (void **)&(pTableMetaInfo->pTableMeta), &pTableMetaInfo->tableMetaCapacity); + } + + if (NULL == taosHashGetCloneExt(tscTableMetaMap, name, len, NULL, (void **)&(pTableMetaInfo->pTableMeta), &pTableMetaInfo->tableMetaCapacity)) { + tfree(pTableMetaInfo->pTableMeta); + } STableMeta* pMeta = pTableMetaInfo->pTableMeta; STableMeta* pSTMeta = (STableMeta *)(pSql->pBuf); + if (pMeta && pMeta->id.uid > 0) { // in case of child table, here only get the if (pMeta->tableType == TSDB_CHILD_TABLE) { @@ -2961,6 +2941,8 @@ int32_t tscGetTableMetaImpl(SSqlObj* pSql, STableMetaInfo *pTableMetaInfo, bool return getTableMetaFromMnode(pSql, pTableMetaInfo, autocreate); } } + + tscDebug("0x%"PRIx64 " %s retrieve tableMeta from cache, numOfCols:%d, numOfTags:%d", pSql->self, name, pMeta->tableInfo.numOfColumns, pMeta->tableInfo.numOfTags); return TSDB_CODE_SUCCESS; } diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index 5f55e1c50d3ef75d6036a7d71419f142bff8cfb9..5fdaad0d667c19548f699a9a8cfed7c9f017ad1b 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -892,7 +892,9 @@ int taos_validate_sql(TAOS *taos, const char *sql) { return TSDB_CODE_TSC_EXCEED_SQL_LIMIT; } - pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1); + char* sqlstr = realloc(pSql->sqlstr, sqlLen + 1); + if(sqlstr == NULL && pSql->sqlstr) free(pSql->sqlstr); + pSql->sqlstr = sqlstr; if (pSql->sqlstr == NULL) { tscError("0x%"PRIx64" failed to malloc sql string buffer", pSql->self); tfree(pSql); diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index f3af685cebfc8daea679777362d55fc09cc3c3a1..edc3dbfc82aa6c6c7dcbb9fa6548c9f49864e324 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -15,8 +15,9 @@ #define _GNU_SOURCE #include "os.h" - #include "texpr.h" + +#include "tsched.h" #include "qTsbuf.h" #include "tcompare.h" #include "tscLog.h" @@ -2038,17 +2039,14 @@ void tscHandleMasterJoinQuery(SSqlObj* pSql) { tscAsyncResultOnError(pSql); } -static void doCleanupSubqueries(SSqlObj *pSql, int32_t numOfSubs) { +void doCleanupSubqueries(SSqlObj *pSql, int32_t numOfSubs) { assert(numOfSubs <= pSql->subState.numOfSub && numOfSubs >= 0); for(int32_t i = 0; i < numOfSubs; ++i) { SSqlObj* pSub = pSql->pSubs[i]; assert(pSub != NULL); - - SRetrieveSupport* pSupport = pSub->param; - - tfree(pSupport->localBuffer); - tfree(pSupport); + + tscFreeRetrieveSup(pSub); taos_free_result(pSub); } @@ -2406,6 +2404,10 @@ int32_t tscHandleFirstRoundStableQuery(SSqlObj *pSql) { } else { SSchema ss = {.type = (uint8_t)pCol->info.type, .bytes = pCol->info.bytes, .colId = (int16_t)pCol->columnIndex}; tscColumnListInsert(pNewQueryInfo->colList, pCol->columnIndex, pCol->tableUid, &ss); + int32_t ti = tscColumnExists(pNewQueryInfo->colList, pCol->columnIndex, pCol->tableUid); + assert(ti >= 0); + SColumn* x = taosArrayGetP(pNewQueryInfo->colList, ti); + tscColumnCopy(x, pCol); } } } @@ -2433,11 +2435,72 @@ int32_t tscHandleFirstRoundStableQuery(SSqlObj *pSql) { return terrno; } +typedef struct SPair { + int32_t first; + int32_t second; +} SPair; + +static void doSendQueryReqs(SSchedMsg* pSchedMsg) { + SSqlObj* pSql = pSchedMsg->ahandle; + SPair* p = pSchedMsg->msg; + + for (int32_t i = p->first; i < p->second; ++i) { + if (i >= pSql->subState.numOfSub) { + tfree(p); + return; + } + SSqlObj* pSub = pSql->pSubs[i]; + SRetrieveSupport* pSupport = pSub->param; + + tscDebug("0x%"PRIx64" sub:0x%"PRIx64" launch subquery, orderOfSub:%d.", pSql->self, pSub->self, pSupport->subqueryIndex); + tscBuildAndSendRequest(pSub, NULL); + } + + tfree(p); +} + +static void doConcurrentlySendSubQueries(SSqlObj* pSql) { + SSubqueryState *pState = &pSql->subState; + + // concurrently sent the query requests. + const int32_t MAX_REQUEST_PER_TASK = 8; + + int32_t numOfTasks = (pState->numOfSub + MAX_REQUEST_PER_TASK - 1)/MAX_REQUEST_PER_TASK; + assert(numOfTasks >= 1); + + int32_t num; + if (pState->numOfSub / numOfTasks == MAX_REQUEST_PER_TASK) { + num = MAX_REQUEST_PER_TASK; + } else { + num = pState->numOfSub / numOfTasks + 1; + } + tscDebug("0x%"PRIx64 " query will be sent by %d threads", pSql->self, numOfTasks); + + for(int32_t j = 0; j < numOfTasks; ++j) { + SSchedMsg schedMsg = {0}; + schedMsg.fp = doSendQueryReqs; + schedMsg.ahandle = (void*)pSql; + + schedMsg.thandle = NULL; + SPair* p = calloc(1, sizeof(SPair)); + p->first = j * num; + + if (j == numOfTasks - 1) { + p->second = pState->numOfSub; + } else { + p->second = (j + 1) * num; + } + + schedMsg.msg = p; + taosScheduleTask(tscQhandle, &schedMsg); + } +} + int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { SSqlRes *pRes = &pSql->res; SSqlCmd *pCmd = &pSql->cmd; - // pRes->code check only serves in launching metric sub-queries + // pRes->code check only serves in launching super table sub-queries if (pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED) { pCmd->command = TSDB_SQL_RETRIEVE_GLOBALMERGE; // enable the abort of kill super table function. return pRes->code; @@ -2448,22 +2511,23 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { pRes->qId = 0x1; // hack the qhandle check - const uint32_t nBufferSize = (1u << 18u); // 256KB + const uint32_t nBufferSize = (1u << 18u); // 256KB, default buffer size SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd); STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0); + SSubqueryState *pState = &pSql->subState; - pState->numOfSub = 0; - if (pTableMetaInfo->pVgroupTables == NULL) { - pState->numOfSub = pTableMetaInfo->vgroupList->numOfVgroups; - } else { - pState->numOfSub = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables); + int32_t numOfSub = (pTableMetaInfo->pVgroupTables == NULL) ? pTableMetaInfo->vgroupList->numOfVgroups + : (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables); + + int32_t ret = doInitSubState(pSql, numOfSub); + if (ret != 0) { + tscAsyncResultOnError(pSql); + return ret; } - assert(pState->numOfSub > 0); - - int32_t ret = tscCreateGlobalMergerEnv(pQueryInfo, &pMemoryBuf, pSql->subState.numOfSub, &pDesc, nBufferSize, pSql->self); + ret = tscCreateGlobalMergerEnv(pQueryInfo, &pMemoryBuf, pSql->subState.numOfSub, &pDesc, nBufferSize, pSql->self); if (ret != 0) { pRes->code = ret; tscAsyncResultOnError(pSql); @@ -2473,32 +2537,6 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { } tscDebug("0x%"PRIx64" retrieved query data from %d vnode(s)", pSql->self, pState->numOfSub); - pSql->pSubs = calloc(pState->numOfSub, POINTER_BYTES); - if (pSql->pSubs == NULL) { - tfree(pSql->pSubs); - pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; - tscDestroyGlobalMergerEnv(pMemoryBuf, pDesc,pState->numOfSub); - - tscAsyncResultOnError(pSql); - return ret; - } - - if (pState->states == NULL) { - pState->states = calloc(pState->numOfSub, sizeof(*pState->states)); - if (pState->states == NULL) { - pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; - tscDestroyGlobalMergerEnv(pMemoryBuf, pDesc,pState->numOfSub); - - tscAsyncResultOnError(pSql); - return ret; - } - - pthread_mutex_init(&pState->mutex, NULL); - } - - memset(pState->states, 0, sizeof(*pState->states) * pState->numOfSub); - tscDebug("0x%"PRIx64" reset all sub states to 0", pSql->self); - pRes->code = TSDB_CODE_SUCCESS; int32_t i = 0; @@ -2519,8 +2557,8 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { break; } - trs->subqueryIndex = i; - trs->pParentSql = pSql; + trs->subqueryIndex = i; + trs->pParentSql = pSql; SSqlObj *pNew = tscCreateSTableSubquery(pSql, trs, NULL); if (pNew == NULL) { @@ -2555,19 +2593,12 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) { doCleanupSubqueries(pSql, i); return pRes->code; } - - for(int32_t j = 0; j < pState->numOfSub; ++j) { - SSqlObj* pSub = pSql->pSubs[j]; - SRetrieveSupport* pSupport = pSub->param; - - tscDebug("0x%"PRIx64" sub:0x%"PRIx64" launch subquery, orderOfSub:%d.", pSql->self, pSub->self, pSupport->subqueryIndex); - tscBuildAndSendRequest(pSub, NULL); - } + doConcurrentlySendSubQueries(pSql); return TSDB_CODE_SUCCESS; } -static void tscFreeRetrieveSup(SSqlObj *pSql) { +void tscFreeRetrieveSup(SSqlObj *pSql) { SRetrieveSupport *trsupport = pSql->param; void* p = atomic_val_compare_exchange_ptr(&pSql->param, trsupport, 0); @@ -2698,7 +2729,7 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO } } else { // reach the maximum retry count, abort atomic_val_compare_exchange_32(&pParentSql->res.code, TSDB_CODE_SUCCESS, numOfRows); - tscError("0x%"PRIx64" sub:0x%"PRIx64" retrieve failed,code:%s,orderOfSub:%d failed.no more retry,set global code:%s", pParentSql->self, pSql->self, + tscError("0x%"PRIx64" sub:0x%"PRIx64" retrieve failed, code:%s, orderOfSub:%d FAILED. no more retry, set global code:%s", pParentSql->self, pSql->self, tstrerror(numOfRows), subqueryIndex, tstrerror(pParentSql->res.code)); } } @@ -2725,27 +2756,43 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO if (!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE)) { int32_t code = pParentSql->res.code; - if ((code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) && pParentSql->retry < pParentSql->maxRetry) { - // remove the cached tableMeta and vgroup id list, and then parse the sql again - tscResetSqlCmd( &pParentSql->cmd, true, pParentSql->self); + SSqlObj *userSql = NULL; + if (pParentSql->param) { + userSql = ((SRetrieveSupport*)pParentSql->param)->pParentSql; + } - pParentSql->retry++; - pParentSql->res.code = TSDB_CODE_SUCCESS; - tscDebug("0x%"PRIx64" retry parse sql and send query, prev error: %s, retry:%d", pParentSql->self, - tstrerror(code), pParentSql->retry); + if (userSql == NULL) { + userSql = pParentSql; + } + + if ((code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) && userSql->retry < userSql->maxRetry) { + if (userSql != pParentSql) { + tscFreeRetrieveSup(pParentSql); + } - code = tsParseSql(pParentSql, true); + tscFreeSubobj(userSql); + tfree(userSql->pSubs); + + userSql->res.code = TSDB_CODE_SUCCESS; + userSql->retry++; + + tscDebug("0x%"PRIx64" retry parse sql and send query, prev error: %s, retry:%d", userSql->self, + tstrerror(code), userSql->retry); + + tscResetSqlCmd(&userSql->cmd, true, userSql->self); + code = tsParseSql(userSql, true); if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) { return; } if (code != TSDB_CODE_SUCCESS) { - pParentSql->res.code = code; - tscAsyncResultOnError(pParentSql); + userSql->res.code = code; + tscAsyncResultOnError(userSql); return; } - executeQuery(pParentSql, pQueryInfo); + pQueryInfo = tscGetQueryInfo(&userSql->cmd); + executeQuery(userSql, pQueryInfo); } else { (*pParentSql->fp)(pParentSql->param, pParentSql, pParentSql->res.code); } @@ -2815,7 +2862,6 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p pParentSql->self, pState->numOfSub, pState->numOfRetrievedRows); SQueryInfo *pPQueryInfo = tscGetQueryInfo(&pParentSql->cmd); - tscClearInterpInfo(pPQueryInfo); code = tscCreateGlobalMerger(trsupport->pExtMemBuffer, pState->numOfSub, pDesc, pPQueryInfo, &pParentSql->res.pMerger, pParentSql->self); pParentSql->res.code = code; @@ -2930,7 +2976,7 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR tscDebug("0x%"PRIx64" sub:0x%"PRIx64" retrieve numOfRows:%d totalNumOfRows:%" PRIu64 " from ep:%s, orderOfSub:%d", pParentSql->self, pSql->self, pRes->numOfRows, pState->numOfRetrievedRows, pSql->epSet.fqdn[pSql->epSet.inUse], idx); - if (num > tsMaxNumOfOrderedResults && /*tscIsProjectionQueryOnSTable(pQueryInfo, 0) &&*/ !(tscGetQueryInfo(&pParentSql->cmd)->distinct)) { + if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0) && !(tscGetQueryInfo(&pParentSql->cmd)->distinct)) { tscError("0x%"PRIx64" sub:0x%"PRIx64" num of OrderedRes is too many, max allowed:%" PRId32 " , current:%" PRId64, pParentSql->self, pSql->self, tsMaxNumOfOrderedResults, num); tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_SORTED_RES_TOO_MANY); diff --git a/src/client/src/tscSystem.c b/src/client/src/tscSystem.c index c04765b0651f59066dd5897f2eaf0924b7113a21..8af340030cccee1431a82eb88344642011f2e019 100644 --- a/src/client/src/tscSystem.c +++ b/src/client/src/tscSystem.c @@ -122,6 +122,10 @@ int32_t tscAcquireRpc(const char *key, const char *user, const char *secretEncry void taos_init_imp(void) { char temp[128] = {0}; + + // In the APIs of other program language, taos_cleanup is not available yet. + // So, to make sure taos_cleanup will be invoked to clean up the allocated resource to suppress the valgrind warning. + atexit(taos_cleanup); errno = TSDB_CODE_SUCCESS; srand(taosGetTimestampSec()); @@ -197,10 +201,6 @@ void taos_init_imp(void) { tscRefId = taosOpenRef(200, tscCloseTscObj); - // In the APIs of other program language, taos_cleanup is not available yet. - // So, to make sure taos_cleanup will be invoked to clean up the allocated resource to suppress the valgrind warning. - atexit(taos_cleanup); - tscDebug("client is initialized successfully"); } diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 591a6bba344eaffb93117668e7a3dcc91761abad..fe3e330aa97bb217a596df6fe428c115f29103b5 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -29,6 +29,7 @@ #include "tsclient.h" #include "ttimer.h" #include "ttokendef.h" +#include "httpInt.h" static void freeQueryInfoImpl(SQueryInfo* pQueryInfo); @@ -403,6 +404,27 @@ bool tscGroupbyColumn(SQueryInfo* pQueryInfo) { return false; } +int32_t tscGetTopBotQueryExprIndex(SQueryInfo* pQueryInfo) { + size_t numOfExprs = tscNumOfExprs(pQueryInfo); + + for (int32_t i = 0; i < numOfExprs; ++i) { + SExprInfo* pExpr = tscExprGet(pQueryInfo, i); + if (pExpr == NULL) { + continue; + } + + if (pExpr->base.functionId == TSDB_FUNC_TS) { + continue; + } + + if (pExpr->base.functionId == TSDB_FUNC_TOP || pExpr->base.functionId == TSDB_FUNC_BOTTOM) { + return i; + } + } + + return -1; +} + bool tscIsTopBotQuery(SQueryInfo* pQueryInfo) { size_t numOfExprs = tscNumOfExprs(pQueryInfo); @@ -659,8 +681,10 @@ static void setResRawPtrImpl(SSqlRes* pRes, SInternalField* pInfo, int32_t i, bo } else if (convertNchar && pInfo->field.type == TSDB_DATA_TYPE_NCHAR) { // convert unicode to native code in a temporary buffer extra one byte for terminated symbol - pRes->buffer[i] = realloc(pRes->buffer[i], pInfo->field.bytes * pRes->numOfRows); - + char* buffer = realloc(pRes->buffer[i], pInfo->field.bytes * pRes->numOfRows); + if(buffer == NULL) + return ; + pRes->buffer[i] = buffer; // string terminated char for binary data memset(pRes->buffer[i], 0, pInfo->field.bytes * pRes->numOfRows); @@ -1236,6 +1260,7 @@ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQue } SOperatorInfo* pSourceOperator = createDummyInputOperator(pSqlObjList[0], pSchema, numOfCol1, pFilters); + pOutput->precision = pSqlObjList[0]->res.precision; SSchema* schema = NULL; @@ -2096,6 +2121,22 @@ TAOS_FIELD tscCreateField(int8_t type, const char* name, int16_t bytes) { return f; } +int32_t tscGetFirstInvisibleFieldPos(SQueryInfo* pQueryInfo) { + if (pQueryInfo->fieldsInfo.numOfOutput <= 0 || pQueryInfo->fieldsInfo.internalField == NULL) { + return 0; + } + + for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) { + SInternalField* pField = taosArrayGet(pQueryInfo->fieldsInfo.internalField, i); + if (!pField->visible) { + return i; + } + } + + return pQueryInfo->fieldsInfo.numOfOutput; +} + + SInternalField* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) { assert(pFieldInfo != NULL); pFieldInfo->numOfOutput++; @@ -2419,6 +2460,19 @@ size_t tscNumOfExprs(SQueryInfo* pQueryInfo) { return taosArrayGetSize(pQueryInfo->exprList); } +int32_t tscExprTopBottomIndex(SQueryInfo* pQueryInfo){ + size_t numOfExprs = tscNumOfExprs(pQueryInfo); + for(int32_t i = 0; i < numOfExprs; ++i) { + SExprInfo* pExpr = tscExprGet(pQueryInfo, i); + if (pExpr == NULL) + continue; + if (pExpr->base.functionId == TSDB_FUNC_TOP || pExpr->base.functionId == TSDB_FUNC_BOTTOM) { + return i; + } + } + return -1; +} + // todo REFACTOR void tscExprAddParams(SSqlExpr* pExpr, char* argument, int32_t type, int32_t bytes) { assert (pExpr != NULL || argument != NULL || bytes != 0); @@ -3128,6 +3182,7 @@ void tscInitQueryInfo(SQueryInfo* pQueryInfo) { pQueryInfo->slimit.offset = 0; pQueryInfo->pUpstream = taosArrayInit(4, POINTER_BYTES); pQueryInfo->window = TSWINDOW_INITIALIZER; + pQueryInfo->multigroupResult = true; } int32_t tscAddQueryInfo(SSqlCmd* pCmd) { @@ -3139,7 +3194,6 @@ int32_t tscAddQueryInfo(SSqlCmd* pCmd) { } tscInitQueryInfo(pQueryInfo); - pQueryInfo->msg = pCmd->payload; // pointer to the parent error message buffer if (pCmd->pQueryInfo == NULL) { @@ -3188,6 +3242,7 @@ static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) { taosArrayDestroy(pQueryInfo->pUpstream); pQueryInfo->pUpstream = NULL; + pQueryInfo->bufLen = 0; } void tscClearSubqueryInfo(SSqlCmd* pCmd) { @@ -3222,6 +3277,7 @@ int32_t tscQueryInfoCopy(SQueryInfo* pQueryInfo, const SQueryInfo* pSrc) { pQueryInfo->window = pSrc->window; pQueryInfo->sessionWindow = pSrc->sessionWindow; pQueryInfo->pTableMetaInfo = NULL; + pQueryInfo->multigroupResult = pSrc->multigroupResult; pQueryInfo->bufLen = pSrc->bufLen; pQueryInfo->orderProjectQuery = pSrc->orderProjectQuery; @@ -3607,24 +3663,25 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, __async_cb_func_t pnCmd->active = pNewQueryInfo; memcpy(&pNewQueryInfo->interval, &pQueryInfo->interval, sizeof(pNewQueryInfo->interval)); - pNewQueryInfo->type = pQueryInfo->type; - pNewQueryInfo->window = pQueryInfo->window; - pNewQueryInfo->limit = pQueryInfo->limit; - pNewQueryInfo->slimit = pQueryInfo->slimit; - pNewQueryInfo->order = pQueryInfo->order; - pNewQueryInfo->vgroupLimit = pQueryInfo->vgroupLimit; - pNewQueryInfo->tsBuf = NULL; - pNewQueryInfo->fillType = pQueryInfo->fillType; - pNewQueryInfo->fillVal = NULL; + pNewQueryInfo->type = pQueryInfo->type; + pNewQueryInfo->window = pQueryInfo->window; + pNewQueryInfo->limit = pQueryInfo->limit; + pNewQueryInfo->slimit = pQueryInfo->slimit; + pNewQueryInfo->order = pQueryInfo->order; + pNewQueryInfo->tsBuf = NULL; + pNewQueryInfo->fillType = pQueryInfo->fillType; + pNewQueryInfo->fillVal = NULL; + pNewQueryInfo->clauseLimit = pQueryInfo->clauseLimit; + pNewQueryInfo->prjOffset = pQueryInfo->prjOffset; pNewQueryInfo->numOfFillVal = 0; - pNewQueryInfo->clauseLimit = pQueryInfo->clauseLimit; - pNewQueryInfo->prjOffset = pQueryInfo->prjOffset; - pNewQueryInfo->numOfTables = 0; + pNewQueryInfo->numOfTables = 0; pNewQueryInfo->pTableMetaInfo = NULL; - pNewQueryInfo->bufLen = pQueryInfo->bufLen; - pNewQueryInfo->distinct = pQueryInfo->distinct; + pNewQueryInfo->bufLen = pQueryInfo->bufLen; + pNewQueryInfo->vgroupLimit = pQueryInfo->vgroupLimit; + pNewQueryInfo->distinct = pQueryInfo->distinct; + pNewQueryInfo->multigroupResult = pQueryInfo->multigroupResult; - pNewQueryInfo->buf = malloc(pQueryInfo->bufLen); + pNewQueryInfo->buf = malloc(pQueryInfo->bufLen); if (pNewQueryInfo->buf == NULL) { terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; goto _error; @@ -3840,8 +3897,7 @@ static void tscSubqueryCompleteCallback(void* param, TAOS_RES* tres, int code) { int32_t index = ps->subqueryIndex; bool ret = subAndCheckDone(pSql, pParentSql, index); - tfree(ps); - pSql->param = NULL; + tscFreeRetrieveSup(pSql); if (!ret) { tscDebug("0x%"PRIx64" sub:0x%"PRIx64" orderOfSub:%d completed, not all subquery finished", pParentSql->self, pSql->self, index); @@ -3850,7 +3906,15 @@ static void tscSubqueryCompleteCallback(void* param, TAOS_RES* tres, int code) { // todo refactor tscDebug("0x%"PRIx64" all subquery response received, retry", pParentSql->self); - tscResetSqlCmd(&pParentSql->cmd, true, pParentSql->self); + if (code && !((code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) && pParentSql->retry < pParentSql->maxRetry)) { + pParentSql->res.code = code; + + tscAsyncResultOnError(pParentSql); + return; + } + + tscFreeSubobj(pParentSql); + tfree(pParentSql->pSubs); pParentSql->res.code = TSDB_CODE_SUCCESS; pParentSql->retry++; @@ -3858,6 +3922,9 @@ static void tscSubqueryCompleteCallback(void* param, TAOS_RES* tres, int code) { tscDebug("0x%"PRIx64" retry parse sql and send query, prev error: %s, retry:%d", pParentSql->self, tstrerror(code), pParentSql->retry); + + tscResetSqlCmd(&pParentSql->cmd, true, pParentSql->self); + code = tsParseSql(pParentSql, true); if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) { return; @@ -3877,6 +3944,21 @@ static void tscSubqueryCompleteCallback(void* param, TAOS_RES* tres, int code) { taos_fetch_rows_a(tres, tscSubqueryRetrieveCallback, param); } +int32_t doInitSubState(SSqlObj* pSql, int32_t numOfSubqueries) { + assert(pSql->subState.numOfSub == 0 && pSql->pSubs == NULL && pSql->subState.states == NULL); + pSql->subState.numOfSub = numOfSubqueries; + + pSql->pSubs = calloc(pSql->subState.numOfSub, POINTER_BYTES); + pSql->subState.states = calloc(pSql->subState.numOfSub, sizeof(int8_t)); + + int32_t code = pthread_mutex_init(&pSql->subState.mutex, NULL); + if (pSql->pSubs == NULL || pSql->subState.states == NULL || code != 0) { + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } + + return TSDB_CODE_SUCCESS; +} + // do execute the query according to the query execution plan void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) { int32_t code = TSDB_CODE_SUCCESS; @@ -3892,14 +3974,8 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) { } if (taosArrayGetSize(pQueryInfo->pUpstream) > 0) { // nest query. do execute it firstly - pSql->subState.numOfSub = (int32_t) taosArrayGetSize(pQueryInfo->pUpstream); - - pSql->pSubs = calloc(pSql->subState.numOfSub, POINTER_BYTES); - pSql->subState.states = calloc(pSql->subState.numOfSub, sizeof(int8_t)); - code = pthread_mutex_init(&pSql->subState.mutex, NULL); - - if (pSql->pSubs == NULL || pSql->subState.states == NULL || code != TSDB_CODE_SUCCESS) { - code = TSDB_CODE_TSC_OUT_OF_MEMORY; + code = doInitSubState(pSql, (int32_t) taosArrayGetSize(pQueryInfo->pUpstream)); + if (code != TSDB_CODE_SUCCESS) { goto _error; } @@ -3919,7 +3995,11 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) { pNew->signature = pNew; pNew->sqlstr = strdup(pSql->sqlstr); pNew->fp = tscSubqueryCompleteCallback; + pNew->fetchFp = tscSubqueryCompleteCallback; pNew->maxRetry = pSql->maxRetry; + + pNew->cmd.resColumnId = TSDB_RES_COL_ID; + tsem_init(&pNew->rspSem, 0, 0); SRetrieveSupport* ps = calloc(1, sizeof(SRetrieveSupport)); // todo use object id @@ -4096,6 +4176,31 @@ int32_t tscInvalidOperationMsg(char* msg, const char* additionalInfo, const char return TSDB_CODE_TSC_INVALID_OPERATION; } +int32_t tscErrorMsgWithCode(int32_t code, char* dstBuffer, const char* errMsg, const char* sql) { + const char* msgFormat1 = "%s:%s"; + const char* msgFormat2 = "%s:\'%s\' (%s)"; + const char* msgFormat3 = "%s:\'%s\'"; + + const int32_t BACKWARD_CHAR_STEP = 0; + + if (sql == NULL) { + assert(errMsg != NULL); + sprintf(dstBuffer, msgFormat1, tstrerror(code), errMsg); + return code; + } + + char buf[64] = {0}; // only extract part of sql string + strncpy(buf, (sql - BACKWARD_CHAR_STEP), tListLen(buf) - 1); + + if (errMsg != NULL) { + sprintf(dstBuffer, msgFormat2, tstrerror(code), buf, errMsg); + } else { + sprintf(dstBuffer, msgFormat3, tstrerror(code), buf); // no additional information for invalid sql error + } + + return code; +} + bool tscHasReachLimitation(SQueryInfo* pQueryInfo, SSqlRes* pRes) { assert(pQueryInfo != NULL && pQueryInfo->clauseLimit != 0); return (pQueryInfo->clauseLimit > 0 && pRes->numOfClauseTotal >= pQueryInfo->clauseLimit); @@ -4217,7 +4322,9 @@ void tscTryQueryNextClause(SSqlObj* pSql, __async_cb_func_t fp) { } tfree(pSql->pSubs); + tfree(pSql->subState.states); pSql->subState.numOfSub = 0; + pthread_mutex_destroy(&pSql->subState.mutex); pSql->fp = fp; @@ -4452,21 +4559,27 @@ int32_t tscCreateTableMetaFromSTableMeta(STableMeta** ppChild, const char* name, assert(*ppChild != NULL); STableMeta* p = *ppSTable; STableMeta* pChild = *ppChild; - size_t sz = (p != NULL) ? tscGetTableMetaSize(p) : 0; //ppSTableBuf actually capacity may larger than sz, dont care + + size_t sz = (p != NULL) ? tscGetTableMetaSize(p) : 0; //ppSTableBuf actually capacity may larger than sz, dont care if (p != NULL && sz != 0) { memset((char *)p, 0, sz); } - taosHashGetCloneExt(tscTableMetaMap, pChild->sTableName, strnlen(pChild->sTableName, TSDB_TABLE_FNAME_LEN), NULL, (void **)&p, &sz); - *ppSTable = p; + + if (NULL == taosHashGetCloneExt(tscTableMetaMap, pChild->sTableName, strnlen(pChild->sTableName, TSDB_TABLE_FNAME_LEN), NULL, (void **)&p, &sz)) { + tfree(p); + } else { + *ppSTable = p; + } // tableMeta exists, build child table meta according to the super table meta // the uid need to be checked in addition to the general name of the super table. if (p && p->id.uid > 0 && pChild->suid == p->id.uid) { - int32_t totalBytes = (p->tableInfo.numOfColumns + p->tableInfo.numOfTags) * sizeof(SSchema); int32_t tableMetaSize = sizeof(STableMeta) + totalBytes; if (*tableMetaCapacity < tableMetaSize) { - pChild = realloc(pChild, tableMetaSize); + STableMeta* pChild1 = realloc(pChild, tableMetaSize); + if(pChild1 == NULL) return -1; + pChild = pChild1; *tableMetaCapacity = (size_t)tableMetaSize; } @@ -4736,6 +4849,7 @@ int32_t tscCreateQueryFromQueryInfo(SQueryInfo* pQueryInfo, SQueryAttr* pQueryAt pQueryAttr->distinct = pQueryInfo->distinct; pQueryAttr->sw = pQueryInfo->sessionWindow; pQueryAttr->stateWindow = pQueryInfo->stateWindow; + pQueryAttr->multigroupResult = pQueryInfo->multigroupResult; pQueryAttr->numOfCols = numOfCols; pQueryAttr->numOfOutput = numOfOutput; @@ -5008,3 +5122,31 @@ void tscRemoveCachedTableMeta(STableMetaInfo* pTableMetaInfo, uint64_t id) { taosHashRemove(tscTableMetaMap, fname, len); tscDebug("0x%"PRIx64" remove table meta %s, numOfRemain:%d", id, fname, (int32_t) taosHashGetSize(tscTableMetaMap)); } + +char* cloneCurrentDBName(SSqlObj* pSql) { + char *p = NULL; + HttpContext *pCtx = NULL; + + pthread_mutex_lock(&pSql->pTscObj->mutex); + STscObj *pTscObj = pSql->pTscObj; + switch (pTscObj->from) { + case TAOS_REQ_FROM_HTTP: + pCtx = pSql->param; + if (pCtx && pCtx->db[0] != '\0') { + char db[TSDB_ACCT_ID_LEN + TSDB_DB_NAME_LEN] = {0}; + int32_t len = sprintf(db, "%s%s%s", pTscObj->acctId, TS_PATH_DELIMITER, pCtx->db); + assert(len <= sizeof(db)); + + p = strdup(db); + } + break; + default: + break; + } + if (p == NULL) { + p = strdup(pSql->pTscObj->db); + } + pthread_mutex_unlock(&pSql->pTscObj->mutex); + + return p; +} diff --git a/src/common/inc/tdataformat.h b/src/common/inc/tdataformat.h index 46259c8488617b77a940736d073454d4349a7774..a01c3775397e25849d9e8ff70409db7ac0af90ba 100644 --- a/src/common/inc/tdataformat.h +++ b/src/common/inc/tdataformat.h @@ -547,8 +547,9 @@ SKVRow tdGetKVRowFromBuilder(SKVRowBuilder *pBuilder); static FORCE_INLINE int tdAddColToKVRow(SKVRowBuilder *pBuilder, int16_t colId, int8_t type, void *value) { if (pBuilder->nCols >= pBuilder->tCols) { pBuilder->tCols *= 2; - pBuilder->pColIdx = (SColIdx *)realloc((void *)(pBuilder->pColIdx), sizeof(SColIdx) * pBuilder->tCols); - if (pBuilder->pColIdx == NULL) return -1; + SColIdx* pColIdx = (SColIdx *)realloc((void *)(pBuilder->pColIdx), sizeof(SColIdx) * pBuilder->tCols); + if (pColIdx == NULL) return -1; + pBuilder->pColIdx = pColIdx; } pBuilder->pColIdx[pBuilder->nCols].colId = colId; @@ -561,8 +562,9 @@ static FORCE_INLINE int tdAddColToKVRow(SKVRowBuilder *pBuilder, int16_t colId, while (tlen > pBuilder->alloc - pBuilder->size) { pBuilder->alloc *= 2; } - pBuilder->buf = realloc(pBuilder->buf, pBuilder->alloc); - if (pBuilder->buf == NULL) return -1; + void* buf = realloc(pBuilder->buf, pBuilder->alloc); + if (buf == NULL) return -1; + pBuilder->buf = buf; } memcpy(POINTER_SHIFT(pBuilder->buf, pBuilder->size), value, tlen); diff --git a/src/common/inc/texpr.h b/src/common/inc/texpr.h index 2e49a69366c2277c98ec32a1d8419c141ddecc0f..db71559df6334ed935a44f3822f78ff671e8dab2 100644 --- a/src/common/inc/texpr.h +++ b/src/common/inc/texpr.h @@ -33,9 +33,11 @@ struct SSchema; #define QUERY_COND_REL_PREFIX_IN "IN|" #define QUERY_COND_REL_PREFIX_LIKE "LIKE|" +#define QUERY_COND_REL_PREFIX_MATCH "MATCH|" #define QUERY_COND_REL_PREFIX_IN_LEN 3 #define QUERY_COND_REL_PREFIX_LIKE_LEN 5 +#define QUERY_COND_REL_PREFIX_MATCH_LEN 6 typedef bool (*__result_filter_fn_t)(const void *, void *); typedef void (*__do_filter_suppl_fn_t)(void *, void *); diff --git a/src/common/inc/tglobal.h b/src/common/inc/tglobal.h index 4b8347ead02b8aca7b681b15adb93154c668956d..360a83eea8df9392b059e73ac59075b27a96f7c3 100644 --- a/src/common/inc/tglobal.h +++ b/src/common/inc/tglobal.h @@ -74,6 +74,7 @@ extern int8_t tsKeepOriginalColumnName; // client extern int32_t tsMaxSQLStringLen; extern int32_t tsMaxWildCardsLen; +extern int32_t tsMaxRegexStringLen; extern int8_t tsTscEnableRecordSql; extern int32_t tsMaxNumOfOrderedResults; extern int32_t tsMinSlidingTime; @@ -130,6 +131,7 @@ extern int32_t tsHttpMaxThreads; extern int8_t tsHttpEnableCompress; extern int8_t tsHttpEnableRecordSql; extern int8_t tsTelegrafUseFieldNum; +extern int8_t tsHttpDbNameMandatory; // mqtt extern int8_t tsEnableMqttModule; @@ -163,6 +165,7 @@ extern char tsDataDir[]; extern char tsLogDir[]; extern char tsScriptDir[]; extern int64_t tsTickPerDay[3]; +extern int32_t tsTopicBianryLen; // system info extern char tsOsName[]; diff --git a/src/common/src/tarithoperator.c b/src/common/src/tarithoperator.c index 3779303e1a41275996c52f828d433d2d68805fdf..000ef79fcf9b5ee9e52dae65b99f719cec6a8059 100644 --- a/src/common/src/tarithoperator.c +++ b/src/common/src/tarithoperator.c @@ -21,187 +21,6 @@ #include "tcompare.h" //GET_TYPED_DATA(v, double, _right_type, (char *)&((right)[i])); -#define ARRAY_LIST_OP_DIV(left, right, _left_type, _right_type, len1, len2, out, op, _res_type, _ord) \ - { \ - int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; \ - int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; \ - \ - if ((len1) == (len2)) { \ - for (; i < (len2) && i >= 0; i += step, (out) += 1) { \ - if (isNull((char *)&((left)[i]), _left_type) || isNull((char *)&((right)[i]), _right_type)) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - double v, z = 0.0; \ - GET_TYPED_DATA(v, double, _right_type, (char *)&((right)[i])); \ - if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &z) == 0) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - *(out) = (double)(left)[i] op(right)[i]; \ - } \ - } else if ((len1) == 1) { \ - for (; i >= 0 && i < (len2); i += step, (out) += 1) { \ - if (isNull((char *)(left), _left_type) || isNull((char *)&(right)[i], _right_type)) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - double v, z = 0.0; \ - GET_TYPED_DATA(v, double, _right_type, (char *)&((right)[i])); \ - if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &z) == 0) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - *(out) = (double)(left)[0] op(right)[i]; \ - } \ - } else if ((len2) == 1) { \ - for (; i >= 0 && i < (len1); i += step, (out) += 1) { \ - if (isNull((char *)&(left)[i], _left_type) || isNull((char *)(right), _right_type)) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - double v, z = 0.0; \ - GET_TYPED_DATA(v, double, _right_type, (char *)&((right)[0])); \ - if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &z) == 0) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - *(out) = (double)(left)[i] op(right)[0]; \ - } \ - } \ - } -#define ARRAY_LIST_OP(left, right, _left_type, _right_type, len1, len2, out, op, _res_type, _ord) \ - { \ - int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; \ - int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; \ - \ - if ((len1) == (len2)) { \ - for (; i < (len2) && i >= 0; i += step, (out) += 1) { \ - if (isNull((char *)&((left)[i]), _left_type) || isNull((char *)&((right)[i]), _right_type)) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - *(out) = (double)(left)[i] op(right)[i]; \ - } \ - } else if ((len1) == 1) { \ - for (; i >= 0 && i < (len2); i += step, (out) += 1) { \ - if (isNull((char *)(left), _left_type) || isNull((char *)&(right)[i], _right_type)) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - *(out) = (double)(left)[0] op(right)[i]; \ - } \ - } else if ((len2) == 1) { \ - for (; i >= 0 && i < (len1); i += step, (out) += 1) { \ - if (isNull((char *)&(left)[i], _left_type) || isNull((char *)(right), _right_type)) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - *(out) = (double)(left)[i] op(right)[0]; \ - } \ - } \ - } - -#define ARRAY_LIST_OP_REM(left, right, _left_type, _right_type, len1, len2, out, op, _res_type, _ord) \ - { \ - int32_t i = (_ord == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; \ - int32_t step = (_ord == TSDB_ORDER_ASC) ? 1 : -1; \ - \ - if (len1 == (len2)) { \ - for (; i >= 0 && i < (len2); i += step, (out) += 1) { \ - if (isNull((char *)&(left[i]), _left_type) || isNull((char *)&(right[i]), _right_type)) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - double v, z = 0.0; \ - GET_TYPED_DATA(v, double, _right_type, (char *)&((right)[i])); \ - if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &z) == 0) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - *(out) = (double)(left)[i] - ((int64_t)(((double)(left)[i]) / (right)[i])) * (right)[i]; \ - } \ - } else if (len1 == 1) { \ - for (; i >= 0 && i < (len2); i += step, (out) += 1) { \ - if (isNull((char *)(left), _left_type) || isNull((char *)&((right)[i]), _right_type)) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - double v, z = 0.0; \ - GET_TYPED_DATA(v, double, _right_type, (char *)&((right)[i])); \ - if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &z) == 0) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - *(out) = (double)(left)[0] - ((int64_t)(((double)(left)[0]) / (right)[i])) * (right)[i]; \ - } \ - } else if ((len2) == 1) { \ - for (; i >= 0 && i < len1; i += step, (out) += 1) { \ - if (isNull((char *)&((left)[i]), _left_type) || isNull((char *)(right), _right_type)) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - double v, z = 0.0; \ - GET_TYPED_DATA(v, double, _right_type, (char *)&((right)[0])); \ - if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &z) == 0) { \ - SET_DOUBLE_NULL(out); \ - continue; \ - } \ - *(out) = (double)(left)[i] - ((int64_t)(((double)(left)[i]) / (right)[0])) * (right)[0]; \ - } \ - } \ - } - -#define ARRAY_LIST_ADD(left, right, _left_type, _right_type, len1, len2, out, _ord) \ - ARRAY_LIST_OP(left, right, _left_type, _right_type, len1, len2, out, +, TSDB_DATA_TYPE_DOUBLE, _ord) -#define ARRAY_LIST_SUB(left, right, _left_type, _right_type, len1, len2, out, _ord) \ - ARRAY_LIST_OP(left, right, _left_type, _right_type, len1, len2, out, -, TSDB_DATA_TYPE_DOUBLE, _ord) -#define ARRAY_LIST_MULTI(left, right, _left_type, _right_type, len1, len2, out, _ord) \ - ARRAY_LIST_OP(left, right, _left_type, _right_type, len1, len2, out, *, TSDB_DATA_TYPE_DOUBLE, _ord) -#define ARRAY_LIST_DIV(left, right, _left_type, _right_type, len1, len2, out, _ord) \ - ARRAY_LIST_OP_DIV(left, right, _left_type, _right_type, len1, len2, out, /, TSDB_DATA_TYPE_DOUBLE, _ord) -#define ARRAY_LIST_REM(left, right, _left_type, _right_type, len1, len2, out, _ord) \ - ARRAY_LIST_OP_REM(left, right, _left_type, _right_type, len1, len2, out, %, TSDB_DATA_TYPE_DOUBLE, _ord) - -#define TYPE_CONVERT_DOUBLE_RES(left, right, out, _type_left, _type_right, _type_res) \ - _type_left * pLeft = (_type_left *)(left); \ - _type_right *pRight = (_type_right *)(right); \ - _type_res * pOutput = (_type_res *)(out); - -#define DO_VECTOR_ADD(left, numLeft, leftType, leftOriginType, right, numRight, rightType, rightOriginType, _output, \ - _order) \ - do { \ - TYPE_CONVERT_DOUBLE_RES(left, right, _output, leftOriginType, rightOriginType, double); \ - ARRAY_LIST_ADD(pLeft, pRight, leftType, rightType, numLeft, numRight, pOutput, _order); \ - } while (0) - -#define DO_VECTOR_SUB(left, numLeft, leftType, leftOriginType, right, numRight, rightType, rightOriginType, _output, \ - _order) \ - do { \ - TYPE_CONVERT_DOUBLE_RES(left, right, _output, leftOriginType, rightOriginType, double); \ - ARRAY_LIST_SUB(pLeft, pRight, leftType, rightType, numLeft, numRight, pOutput, _order); \ - } while (0) - -#define DO_VECTOR_MULTIPLY(left, numLeft, leftType, leftOriginType, right, numRight, rightType, rightOriginType, \ - _output, _order) \ - do { \ - TYPE_CONVERT_DOUBLE_RES(left, right, _output, leftOriginType, rightOriginType, double); \ - ARRAY_LIST_MULTI(pLeft, pRight, leftType, rightType, numLeft, numRight, pOutput, _order); \ - } while (0) - -#define DO_VECTOR_DIVIDE(left, numLeft, leftType, leftOriginType, right, numRight, rightType, rightOriginType, \ - _output, _order) \ - do { \ - TYPE_CONVERT_DOUBLE_RES(left, right, _output, leftOriginType, rightOriginType, double); \ - ARRAY_LIST_DIV(pLeft, pRight, leftType, rightType, numLeft, numRight, pOutput, _order); \ - } while (0) - -#define DO_VECTOR_REMAINDER(left, numLeft, leftType, leftOriginType, right, numRight, rightType, rightOriginType, \ - _output, _order) \ - do { \ - TYPE_CONVERT_DOUBLE_RES(left, right, _output, leftOriginType, rightOriginType, double); \ - ARRAY_LIST_REM(pLeft, pRight, leftType, rightType, numLeft, numRight, pOutput, _order); \ - } while (0) void calc_i32_i32_add(void *left, void *right, int32_t numLeft, int32_t numRight, void *output, int32_t order) { int32_t *pLeft = (int32_t *)left; @@ -240,2389 +59,338 @@ void calc_i32_i32_add(void *left, void *right, int32_t numLeft, int32_t numRight } } -void vectorAdd(void *left, int32_t numLeft, int32_t leftType, void *right, int32_t numRight, int32_t rightType, - void *output, int32_t order) { - switch(leftType) { - case TSDB_DATA_TYPE_TINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, int8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, uint8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, int16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, uint16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_INT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, int32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, uint32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_BIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, int64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, uint64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_FLOAT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, float, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_ADD(left, numLeft, leftType, double, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - default:; - } -} +typedef double (*_arithmetic_getVectorDoubleValue_fn_t)(void *src, int32_t index); -void vectorSub(void *left, int32_t numLeft, int32_t leftType, void *right, int32_t numRight, int32_t rightType, - void *output, int32_t order) { - switch(leftType) { - case TSDB_DATA_TYPE_TINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, int8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, uint8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, int16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, uint16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_INT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, int32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, uint32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_BIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, int64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, uint64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_FLOAT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, float, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_SUB(left, numLeft, leftType, double, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - default:; - } +double getVectorDoubleValue_TINYINT(void *src, int32_t index) { + return (double)*((int8_t *)src + index); +} +double getVectorDoubleValue_UTINYINT(void *src, int32_t index) { + return (double)*((uint8_t *)src + index); +} +double getVectorDoubleValue_SMALLINT(void *src, int32_t index) { + return (double)*((int16_t *)src + index); +} +double getVectorDoubleValue_USMALLINT(void *src, int32_t index) { + return (double)*((uint16_t *)src + index); +} +double getVectorDoubleValue_INT(void *src, int32_t index) { + return (double)*((int32_t *)src + index); +} +double getVectorDoubleValue_UINT(void *src, int32_t index) { + return (double)*((uint32_t *)src + index); +} +double getVectorDoubleValue_BIGINT(void *src, int32_t index) { + return (double)*((int64_t *)src + index); +} +double getVectorDoubleValue_UBIGINT(void *src, int32_t index) { + return (double)*((uint64_t *)src + index); +} +double getVectorDoubleValue_FLOAT(void *src, int32_t index) { + return (double)*((float *)src + index); +} +double getVectorDoubleValue_DOUBLE(void *src, int32_t index) { + return (double)*((double *)src + index); +} +_arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFn(int32_t srcType) { + _arithmetic_getVectorDoubleValue_fn_t p = NULL; + if(srcType==TSDB_DATA_TYPE_TINYINT) { + p = getVectorDoubleValue_TINYINT; + }else if(srcType==TSDB_DATA_TYPE_UTINYINT) { + p = getVectorDoubleValue_UTINYINT; + }else if(srcType==TSDB_DATA_TYPE_SMALLINT) { + p = getVectorDoubleValue_SMALLINT; + }else if(srcType==TSDB_DATA_TYPE_USMALLINT) { + p = getVectorDoubleValue_USMALLINT; + }else if(srcType==TSDB_DATA_TYPE_INT) { + p = getVectorDoubleValue_INT; + }else if(srcType==TSDB_DATA_TYPE_UINT) { + p = getVectorDoubleValue_UINT; + }else if(srcType==TSDB_DATA_TYPE_BIGINT) { + p = getVectorDoubleValue_BIGINT; + }else if(srcType==TSDB_DATA_TYPE_UBIGINT) { + p = getVectorDoubleValue_UBIGINT; + }else if(srcType==TSDB_DATA_TYPE_FLOAT) { + p = getVectorDoubleValue_FLOAT; + }else if(srcType==TSDB_DATA_TYPE_DOUBLE) { + p = getVectorDoubleValue_DOUBLE; + }else { + assert(0); + } + return p; } -void vectorMultiply(void *left, int32_t numLeft, int32_t leftType, void *right, int32_t numRight, int32_t rightType, - void *output, int32_t order) { - switch(leftType) { - case TSDB_DATA_TYPE_TINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_INT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_BIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, int64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, uint64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_FLOAT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, float, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_MULTIPLY(left, numLeft, leftType, double, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - default:; - } + +typedef void* (*_arithmetic_getVectorValueAddr_fn_t)(void *src, int32_t index); + +void* getVectorValueAddr_TINYINT(void *src, int32_t index) { + return (void*)((int8_t *)src + index); +} +void* getVectorValueAddr_UTINYINT(void *src, int32_t index) { + return (void*)((uint8_t *)src + index); +} +void* getVectorValueAddr_SMALLINT(void *src, int32_t index) { + return (void*)((int16_t *)src + index); +} +void* getVectorValueAddr_USMALLINT(void *src, int32_t index) { + return (void*)((uint16_t *)src + index); +} +void* getVectorValueAddr_INT(void *src, int32_t index) { + return (void*)((int32_t *)src + index); +} +void* getVectorValueAddr_UINT(void *src, int32_t index) { + return (void*)((uint32_t *)src + index); +} +void* getVectorValueAddr_BIGINT(void *src, int32_t index) { + return (void*)((int64_t *)src + index); +} +void* getVectorValueAddr_UBIGINT(void *src, int32_t index) { + return (void*)((uint64_t *)src + index); +} +void* getVectorValueAddr_FLOAT(void *src, int32_t index) { + return (void*)((float *)src + index); +} +void* getVectorValueAddr_DOUBLE(void *src, int32_t index) { + return (void*)((double *)src + index); } -void vectorDivide(void *left, int32_t numLeft, int32_t leftType, void *right, int32_t numRight, int32_t rightType, - void *output, int32_t order) { - switch(leftType) { - case TSDB_DATA_TYPE_TINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_INT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_BIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, int64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, uint64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_FLOAT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, float, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_DIVIDE(left, numLeft, leftType, double, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - default:; - } +_arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFn(int32_t srcType) { + _arithmetic_getVectorValueAddr_fn_t p = NULL; + if(srcType==TSDB_DATA_TYPE_TINYINT) { + p = getVectorValueAddr_TINYINT; + }else if(srcType==TSDB_DATA_TYPE_UTINYINT) { + p = getVectorValueAddr_UTINYINT; + }else if(srcType==TSDB_DATA_TYPE_SMALLINT) { + p = getVectorValueAddr_SMALLINT; + }else if(srcType==TSDB_DATA_TYPE_USMALLINT) { + p = getVectorValueAddr_USMALLINT; + }else if(srcType==TSDB_DATA_TYPE_INT) { + p = getVectorValueAddr_INT; + }else if(srcType==TSDB_DATA_TYPE_UINT) { + p = getVectorValueAddr_UINT; + }else if(srcType==TSDB_DATA_TYPE_BIGINT) { + p = getVectorValueAddr_BIGINT; + }else if(srcType==TSDB_DATA_TYPE_UBIGINT) { + p = getVectorValueAddr_UBIGINT; + }else if(srcType==TSDB_DATA_TYPE_FLOAT) { + p = getVectorValueAddr_FLOAT; + }else if(srcType==TSDB_DATA_TYPE_DOUBLE) { + p = getVectorValueAddr_DOUBLE; + }else { + assert(0); + } + return p; } -void vectorRemainder(void *left, int32_t numLeft, int32_t leftType, void *right, int32_t numRight, int32_t rightType, - void *output, int32_t order) { - switch(leftType) { - case TSDB_DATA_TYPE_TINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint8_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint16_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_INT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint32_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_BIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, int64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, uint64_t, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_FLOAT: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, float, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - switch (rightType) { - case TSDB_DATA_TYPE_TINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, int8_t, output, order); - break; - } - case TSDB_DATA_TYPE_UTINYINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, uint8_t, output, order); - break; - } - case TSDB_DATA_TYPE_SMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, int16_t, output, order); - break; - } - case TSDB_DATA_TYPE_USMALLINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, uint16_t, output, order); - break; - } - case TSDB_DATA_TYPE_INT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, int32_t, output, order); - break; - } - case TSDB_DATA_TYPE_UINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, uint32_t, output, order); - break; - } - case TSDB_DATA_TYPE_BIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, int64_t, output, order); - break; - } - case TSDB_DATA_TYPE_UBIGINT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, uint64_t, output, order); - break; - } - case TSDB_DATA_TYPE_FLOAT: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, float, output, order); - break; - } - case TSDB_DATA_TYPE_DOUBLE: { - DO_VECTOR_REMAINDER(left, numLeft, leftType, double, right, numRight, rightType, double, output, order); - break; - } - default: - assert(0); - } - break; - } - default:; - } +void vectorAdd(void *left, int32_t len1, int32_t _left_type, void *right, int32_t len2, int32_t _right_type, void *out, int32_t _ord) { + int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; + int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; + double *output=(double*)out; + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(_left_type); + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(_right_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(_left_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(_right_type); + + if ((len1) == (len2)) { + for (; i < (len2) && i >= 0; i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) + getVectorDoubleValueFnRight(right,i)); + } + } else if ((len1) == 1) { + for (; i >= 0 && i < (len2); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,0), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,0) + getVectorDoubleValueFnRight(right,i)); + } + } else if ((len2) == 1) { + for (; i >= 0 && i < (len1); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,0), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) + getVectorDoubleValueFnRight(right,0)); + } + } +} +void vectorSub(void *left, int32_t len1, int32_t _left_type, void *right, int32_t len2, int32_t _right_type, void *out, int32_t _ord) { + int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; + int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; + double *output=(double*)out; + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(_left_type); + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(_right_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(_left_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(_right_type); + + if ((len1) == (len2)) { + for (; i < (len2) && i >= 0; i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) - getVectorDoubleValueFnRight(right,i)); + } + } else if ((len1) == 1) { + for (; i >= 0 && i < (len2); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,0), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,0) - getVectorDoubleValueFnRight(right,i)); + } + } else if ((len2) == 1) { + for (; i >= 0 && i < (len1); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,0), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) - getVectorDoubleValueFnRight(right,0)); + } + } +} +void vectorMultiply(void *left, int32_t len1, int32_t _left_type, void *right, int32_t len2, int32_t _right_type, void *out, int32_t _ord) { + int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; + int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; + double *output=(double*)out; + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(_left_type); + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(_right_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(_left_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(_right_type); + + if ((len1) == (len2)) { + for (; i < (len2) && i >= 0; i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) * getVectorDoubleValueFnRight(right,i)); + } + } else if ((len1) == 1) { + for (; i >= 0 && i < (len2); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,0), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,0) * getVectorDoubleValueFnRight(right,i)); + } + } else if ((len2) == 1) { + for (; i >= 0 && i < (len1); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,0), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) * getVectorDoubleValueFnRight(right,0)); + } + } +} +void vectorDivide(void *left, int32_t len1, int32_t _left_type, void *right, int32_t len2, int32_t _right_type, void *out, int32_t _ord) { + int32_t i = ((_ord) == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; + int32_t step = ((_ord) == TSDB_ORDER_ASC) ? 1 : -1; + double *output=(double*)out; + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(_left_type); + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(_right_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(_left_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(_right_type); + + if ((len1) == (len2)) { + for (; i < (len2) && i >= 0; i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + double v, u = 0.0; + GET_TYPED_DATA(v, double, _right_type, getVectorValueAddrFnRight(right,i)); + if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &u) == 0) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) /getVectorDoubleValueFnRight(right,i)); + } + } else if ((len1) == 1) { + for (; i >= 0 && i < (len2); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,0), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + double v, u = 0.0; + GET_TYPED_DATA(v, double, _right_type, getVectorValueAddrFnRight(right,i)); + if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &u) == 0) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,0) /getVectorDoubleValueFnRight(right,i)); + } + } else if ((len2) == 1) { + for (; i >= 0 && i < (len1); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,0), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + double v, u = 0.0; + GET_TYPED_DATA(v, double, _right_type, getVectorValueAddrFnRight(right,0)); + if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &u) == 0) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) /getVectorDoubleValueFnRight(right,0)); + } + } +} +void vectorRemainder(void *left, int32_t len1, int32_t _left_type, void *right, int32_t len2, int32_t _right_type, void *out, int32_t _ord) { + int32_t i = (_ord == TSDB_ORDER_ASC) ? 0 : MAX(len1, len2) - 1; + int32_t step = (_ord == TSDB_ORDER_ASC) ? 1 : -1; + double *output=(double*)out; + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnLeft = getVectorValueAddrFn(_left_type); + _arithmetic_getVectorValueAddr_fn_t getVectorValueAddrFnRight = getVectorValueAddrFn(_right_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnLeft = getVectorDoubleValueFn(_left_type); + _arithmetic_getVectorDoubleValue_fn_t getVectorDoubleValueFnRight = getVectorDoubleValueFn(_right_type); + + if (len1 == (len2)) { + for (; i >= 0 && i < (len2); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + double v, u = 0.0; + GET_TYPED_DATA(v, double, _right_type, getVectorValueAddrFnRight(right,i)); + if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &u) == 0) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) - ((int64_t)(getVectorDoubleValueFnLeft(left,i) / getVectorDoubleValueFnRight(right,i))) * getVectorDoubleValueFnRight(right,i)); + } + } else if (len1 == 1) { + for (; i >= 0 && i < (len2); i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,0), _left_type) || isNull(getVectorValueAddrFnRight(right,i), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + double v, u = 0.0; + GET_TYPED_DATA(v, double, _right_type, getVectorValueAddrFnRight(right,i)); + if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &u) == 0) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,0) - ((int64_t)(getVectorDoubleValueFnLeft(left,0) / getVectorDoubleValueFnRight(right,i))) * getVectorDoubleValueFnRight(right,i)); + } + } else if ((len2) == 1) { + for (; i >= 0 && i < len1; i += step, output += 1) { + if (isNull(getVectorValueAddrFnLeft(left,i), _left_type) || isNull(getVectorValueAddrFnRight(right,0), _right_type)) { + SET_DOUBLE_NULL(output); + continue; + } + double v, u = 0.0; + GET_TYPED_DATA(v, double, _right_type, getVectorValueAddrFnRight(right,0)); + if (getComparFunc(TSDB_DATA_TYPE_DOUBLE, 0)(&v, &u) == 0) { + SET_DOUBLE_NULL(output); + continue; + } + SET_DOUBLE_VAL(output,getVectorDoubleValueFnLeft(left,i) - ((int64_t)(getVectorDoubleValueFnLeft(left,i) / getVectorDoubleValueFnRight(right,0))) * getVectorDoubleValueFnRight(right,0)); + } + } } _arithmetic_operator_fn_t getArithmeticOperatorFn(int32_t arithmeticOptr) { diff --git a/src/common/src/tdataformat.c b/src/common/src/tdataformat.c index a3a6c0fed40e053b33dd8c77a031ea9eabf00664..61378c79c4b5c44ffa11ae9132aa6f8b89ab5f71 100644 --- a/src/common/src/tdataformat.c +++ b/src/common/src/tdataformat.c @@ -138,8 +138,9 @@ int tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int16_t colId, int1 if (pBuilder->nCols >= pBuilder->tCols) { pBuilder->tCols *= 2; - pBuilder->columns = (STColumn *)realloc(pBuilder->columns, sizeof(STColumn) * pBuilder->tCols); - if (pBuilder->columns == NULL) return -1; + STColumn* columns = (STColumn *)realloc(pBuilder->columns, sizeof(STColumn) * pBuilder->tCols); + if (columns == NULL) return -1; + pBuilder->columns = columns; } STColumn *pCol = &(pBuilder->columns[pBuilder->nCols]); @@ -447,6 +448,7 @@ static void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols int dcol = 0; while (dcol < pCols->numOfCols) { + bool setCol = 0; SDataCol *pDataCol = &(pCols->cols[dcol]); if (rcol >= schemaNCols(pSchema)) { dataColAppendVal(pDataCol, getNullValue(pDataCol->type), pCols->numOfRows, pCols->maxPoints); @@ -457,13 +459,14 @@ static void tdAppendDataRowToDataCol(SDataRow row, STSchema *pSchema, SDataCols STColumn *pRowCol = schemaColAt(pSchema, rcol); if (pRowCol->colId == pDataCol->colId) { void *value = tdGetRowDataOfCol(row, pRowCol->type, pRowCol->offset + TD_DATA_ROW_HEAD_SIZE); + if(!isNull(value, pDataCol->type)) setCol = 1; dataColAppendVal(pDataCol, value, pCols->numOfRows, pCols->maxPoints); dcol++; rcol++; } else if (pRowCol->colId < pDataCol->colId) { rcol++; } else { - if(forceSetNull) { + if(forceSetNull || setCol) { dataColAppendVal(pDataCol, getNullValue(pDataCol->type), pCols->numOfRows, pCols->maxPoints); } dcol++; @@ -481,6 +484,7 @@ static void tdAppendKvRowToDataCol(SKVRow row, STSchema *pSchema, SDataCols *pCo int nRowCols = kvRowNCols(row); while (dcol < pCols->numOfCols) { + bool setCol = 0; SDataCol *pDataCol = &(pCols->cols[dcol]); if (rcol >= nRowCols || rcol >= schemaNCols(pSchema)) { dataColAppendVal(pDataCol, getNullValue(pDataCol->type), pCols->numOfRows, pCols->maxPoints); @@ -492,13 +496,14 @@ static void tdAppendKvRowToDataCol(SKVRow row, STSchema *pSchema, SDataCols *pCo if (colIdx->colId == pDataCol->colId) { void *value = tdGetKvRowDataOfCol(row, colIdx->offset); + if(!isNull(value, pDataCol->type)) setCol = 1; dataColAppendVal(pDataCol, value, pCols->numOfRows, pCols->maxPoints); ++dcol; ++rcol; } else if (colIdx->colId < pDataCol->colId) { ++rcol; } else { - if (forceSetNull) { + if(forceSetNull || setCol) { dataColAppendVal(pDataCol, getNullValue(pDataCol->type), pCols->numOfRows, pCols->maxPoints); } ++dcol; @@ -532,7 +537,7 @@ int tdMergeDataCols(SDataCols *target, SDataCols *source, int rowsToMerge, int * ASSERT(target->numOfRows + rowsToMerge <= target->maxPoints); for (int i = 0; i < rowsToMerge; i++) { for (int j = 0; j < source->numOfCols; j++) { - if (source->cols[j].len > 0) { + if (source->cols[j].len > 0 || target->cols[j].len > 0) { dataColAppendVal(target->cols + j, tdGetColDataOfRow(source->cols + j, i + (*pOffset)), target->numOfRows, target->maxPoints); } @@ -576,7 +581,7 @@ static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, i if (key1 < key2) { for (int i = 0; i < src1->numOfCols; i++) { ASSERT(target->cols[i].type == src1->cols[i].type); - if (src1->cols[i].len > 0) { + if (src1->cols[i].len > 0 || target->cols[i].len > 0) { dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src1->cols + i, *iter1), target->numOfRows, target->maxPoints); } @@ -594,6 +599,8 @@ static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, i } else if(!forceSetNull && key1 == key2 && src1->cols[i].len > 0) { dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src1->cols + i, *iter1), target->numOfRows, target->maxPoints); + } else if(target->cols[i].len > 0) { + dataColSetNullAt(&target->cols[i], target->numOfRows); } } target->numOfRows++; diff --git a/src/common/src/texpr.c b/src/common/src/texpr.c index ebdb33fd5b804e169a5e8ffc0b9a59e8dc0a331e..2c72b7bd591ab4cb2d11d1420ae97e7cc2123272 100644 --- a/src/common/src/texpr.c +++ b/src/common/src/texpr.c @@ -430,6 +430,17 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) { pVal->nType = TSDB_DATA_TYPE_BINARY; pVal->nLen = (int32_t)len; + } else if (strncmp(tbnameCond, QUERY_COND_REL_PREFIX_MATCH, QUERY_COND_REL_PREFIX_MATCH_LEN) == 0) { + right->nodeType = TSQL_NODE_VALUE; + expr->_node.optr = TSDB_RELATION_MATCH; + tVariant* pVal = exception_calloc(1, sizeof(tVariant)); + right->pVal = pVal; + size_t len = strlen(tbnameCond + QUERY_COND_REL_PREFIX_MATCH_LEN) + 1; + pVal->pz = exception_malloc(len); + memcpy(pVal->pz, tbnameCond + QUERY_COND_REL_PREFIX_MATCH_LEN, len); + pVal->nType = TSDB_DATA_TYPE_BINARY; + pVal->nLen = (int32_t)len; + } else if (strncmp(tbnameCond, QUERY_COND_REL_PREFIX_IN, QUERY_COND_REL_PREFIX_IN_LEN) == 0) { right->nodeType = TSQL_NODE_VALUE; expr->_node.optr = TSDB_RELATION_IN; diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c index b7930dd43e4aab7e3b21ce503c953663566917e7..6e73227233591fa076893174b65a774f229ca4e5 100644 --- a/src/common/src/tglobal.c +++ b/src/common/src/tglobal.c @@ -76,16 +76,17 @@ int32_t tsMaxBinaryDisplayWidth = 30; int32_t tsCompressMsgSize = -1; /* denote if server needs to compress the retrieved column data before adding to the rpc response message body. - * 0: disable column data compression - * 1: enable column data compression - * This option is default to disabled. Once enabled, compression will be conducted if any column has size more - * than QUERY_COMP_THRESHOLD. Otherwise, no further compression is needed. + * 0: all data are compressed + * -1: all data are not compressed + * other values: if any retrieved column size is greater than the tsCompressColData, all data will be compressed. */ -int32_t tsCompressColData = 0; +int32_t tsCompressColData = -1; // client int32_t tsMaxSQLStringLen = TSDB_MAX_ALLOWED_SQL_LEN; -int32_t tsMaxWildCardsLen = TSDB_PATTERN_STRING_MAX_LEN; +int32_t tsMaxWildCardsLen = TSDB_PATTERN_STRING_DEFAULT_LEN; +int32_t tsMaxRegexStringLen = TSDB_REGEX_STRING_DEFAULT_LEN; + int8_t tsTscEnableRecordSql = 0; // the maximum number of results for projection query on super table that are returned from @@ -95,7 +96,7 @@ int32_t tsMaxNumOfOrderedResults = 100000; // 10 ms for sliding time, the value will changed in case of time precision changed int32_t tsMinSlidingTime = 10; -// the maxinum number of distict query result +// the maxinum number of distict query result int32_t tsMaxNumOfDistinctResults = 1000 * 10000; // 1 us for interval time range, changed accordingly @@ -150,9 +151,9 @@ int32_t tsMaxVgroupsPerDb = 0; int32_t tsMinTablePerVnode = TSDB_TABLES_STEP; int32_t tsMaxTablePerVnode = TSDB_DEFAULT_TABLES; int32_t tsTableIncStepPerVnode = TSDB_TABLES_STEP; +int32_t tsTsdbMetaCompactRatio = TSDB_META_COMPACT_RATIO; // tsdb config - // For backward compatibility bool tsdbForceKeepFile = false; @@ -176,6 +177,7 @@ int32_t tsHttpMaxThreads = 2; int8_t tsHttpEnableCompress = 1; int8_t tsHttpEnableRecordSql = 0; int8_t tsTelegrafUseFieldNum = 0; +int8_t tsHttpDbNameMandatory = 0; // mqtt int8_t tsEnableMqttModule = 0; // not finished yet, not started it by default @@ -210,6 +212,7 @@ char tsScriptDir[PATH_MAX] = {0}; char tsTempDir[PATH_MAX] = "/tmp/"; int32_t tsDiskCfgNum = 0; +int32_t tsTopicBianryLen = 16000; #ifndef _STORAGE SDiskCfg tsDiskCfg[1]; @@ -570,7 +573,6 @@ static void doInitGlobalConfig(void) { cfg.unitType = TAOS_CFG_UTYPE_NONE; taosInitConfigOption(cfg); - cfg.option = "numOfMnodes"; cfg.ptr = &tsNumOfMnodes; cfg.valType = TAOS_CFG_VTYPE_INT32; @@ -1006,10 +1008,10 @@ static void doInitGlobalConfig(void) { cfg.option = "compressColData"; cfg.ptr = &tsCompressColData; - cfg.valType = TAOS_CFG_VTYPE_INT8; - cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW; - cfg.minValue = 0; - cfg.maxValue = 1; + 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 = -1; + cfg.maxValue = 100000000.0f; cfg.ptrLength = 0; cfg.unitType = TAOS_CFG_UTYPE_NONE; taosInitConfigOption(cfg); @@ -1238,6 +1240,16 @@ static void doInitGlobalConfig(void) { cfg.unitType = TAOS_CFG_UTYPE_NONE; taosInitConfigOption(cfg); + cfg.option = "topicBianryLen"; + cfg.ptr = &tsTopicBianryLen; + cfg.valType = TAOS_CFG_VTYPE_INT32; + cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG; + cfg.minValue = 16; + cfg.maxValue = 16000; + cfg.ptrLength = 0; + cfg.unitType = TAOS_CFG_UTYPE_NONE; + taosInitConfigOption(cfg); + cfg.option = "httpEnableRecordSql"; cfg.ptr = &tsHttpEnableRecordSql; cfg.valType = TAOS_CFG_VTYPE_INT8; @@ -1278,6 +1290,16 @@ static void doInitGlobalConfig(void) { cfg.unitType = TAOS_CFG_UTYPE_NONE; taosInitConfigOption(cfg); + cfg.option = "httpDbNameMandatory"; + cfg.ptr = &tsHttpDbNameMandatory; + cfg.valType = TAOS_CFG_VTYPE_INT8; + cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG; + cfg.minValue = 0; + cfg.maxValue = 1; + cfg.ptrLength = 0; + cfg.unitType = TAOS_CFG_UTYPE_NONE; + taosInitConfigOption(cfg); + // debug flag cfg.option = "numOfLogLines"; cfg.ptr = &tsNumOfLogLines; @@ -1581,6 +1603,16 @@ static void doInitGlobalConfig(void) { cfg.unitType = TAOS_CFG_UTYPE_NONE; taosInitConfigOption(cfg); + cfg.option = "tsdbMetaCompactRatio"; + cfg.ptr = &tsTsdbMetaCompactRatio; + cfg.valType = TAOS_CFG_VTYPE_INT32; + cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG; + cfg.minValue = 0; + cfg.maxValue = 100; + cfg.ptrLength = 0; + cfg.unitType = TAOS_CFG_UTYPE_NONE; + taosInitConfigOption(cfg); + assert(tsGlobalConfigNum <= TSDB_CFG_MAX_NUM); #ifdef TD_TSZ // lossy compress diff --git a/src/common/src/tvariant.c b/src/common/src/tvariant.c index a491df6f988ef4b2abac44b12066df236e6ba90d..ca3bb956a2fef4fa98450181b4378025013bb735 100644 --- a/src/common/src/tvariant.c +++ b/src/common/src/tvariant.c @@ -38,12 +38,12 @@ void tVariantCreate(tVariant *pVar, SStrToken *token) { switch (token->type) { case TSDB_DATA_TYPE_BOOL: { - int32_t k = strncasecmp(token->z, "true", 4); - if (k == 0) { + if (strncasecmp(token->z, "true", 4) == 0) { pVar->i64 = TSDB_TRUE; - } else { - assert(strncasecmp(token->z, "false", 5) == 0); + } else if (strncasecmp(token->z, "false", 5) == 0) { pVar->i64 = TSDB_FALSE; + } else { + return; } break; diff --git a/src/connector/jdbc/pom.xml b/src/connector/jdbc/pom.xml index fbeeeb56d30357294663a5ebf64608c57e066a7d..6b9fc9d96ce16700ee1243ef7c148a423a965d0b 100644 --- a/src/connector/jdbc/pom.xml +++ b/src/connector/jdbc/pom.xml @@ -117,7 +117,6 @@ **/DatetimeBefore1970Test.java **/FailOverTest.java **/InvalidResultSetPointerTest.java - **/RestfulConnectionTest.java **/TSDBJNIConnectorTest.java **/TaosInfoMonitorTest.java **/UnsignedNumberJniTest.java 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 977ae665152fd1627cf25005061a4ca2aaa4e488..bdb3ea410005cadd865de1d9e080dd5b9f20834f 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 @@ -40,13 +40,13 @@ public class TSDBError { TSDBErrorMap.put(TSDBErrorNumbers.ERROR_SUBSCRIBE_FAILED, "failed to create subscription"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING, "Unsupported encoding"); - TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR, "internal error of database"); + TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR, "internal error of database, please see taoslog for more details"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL, "JNI connection is NULL"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_RESULT_SET_NULL, "JNI result set is NULL"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_NUM_OF_FIELDS_0, "invalid num of fields"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_SQL_NULL, "empty sql string"); TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_FETCH_END, "fetch to the end of resultSet"); - TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_OUT_OF_MEMORY, "JNI alloc memory failed"); + TSDBErrorMap.put(TSDBErrorNumbers.ERROR_JNI_OUT_OF_MEMORY, "JNI alloc memory failed, please see taoslog for more details"); } public static SQLException createSQLException(int errorCode) { 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 c634fe2e9503ff19afae85f285d921f330562612..4a9e80ba53b096f057840eab67e61418332dbf81 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 @@ -278,25 +278,20 @@ public class TSDBJNIConnector { private native int validateCreateTableSqlImp(long connection, byte[] sqlBytes); public long prepareStmt(String sql) throws SQLException { - long stmt; - try { - stmt = prepareStmtImp(sql.getBytes(), this.taos); - } catch (Exception e) { - e.printStackTrace(); - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNSUPPORTED_ENCODING); - } + long stmt = prepareStmtImp(sql.getBytes(), this.taos); if (stmt == TSDBConstants.JNI_CONNECTION_NULL) { - throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL); + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_CONNECTION_NULL, "connection already closed"); } - if (stmt == TSDBConstants.JNI_SQL_NULL) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_SQL_NULL); } - if (stmt == TSDBConstants.JNI_OUT_OF_MEMORY) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_OUT_OF_MEMORY); } + if (stmt == TSDBConstants.JNI_TDENGINE_ERROR) { + throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_JNI_TDENGINE_ERROR); + } return stmt; } @@ -313,8 +308,7 @@ public class TSDBJNIConnector { private native int setBindTableNameImp(long stmt, String name, long conn); public void setBindTableNameAndTags(long stmt, String tableName, int numOfTags, ByteBuffer tags, ByteBuffer typeList, ByteBuffer lengthList, ByteBuffer nullList) throws SQLException { - int code = setTableNameTagsImp(stmt, tableName, numOfTags, tags.array(), typeList.array(), lengthList.array(), - nullList.array(), this.taos); + int code = setTableNameTagsImp(stmt, tableName, numOfTags, tags.array(), typeList.array(), lengthList.array(), nullList.array(), this.taos); if (code != TSDBConstants.JNI_SUCCESS) { throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_UNKNOWN, "failed to bind table name and corresponding tags"); } diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java index 6211f61dc505d2ccba5f11f3aacc980771b1a110..ff49677b01fa1c3a4d482cebd51269d5f1589e43 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetBlockData.java @@ -32,6 +32,7 @@ import java.util.List; import com.taosdata.jdbc.utils.NullType; public class TSDBResultSetBlockData { + private static final int BINARY_LENGTH_OFFSET = 2; private int numOfRows = 0; private int rowIndex = 0; @@ -404,10 +405,8 @@ public class TSDBResultSetBlockData { case TSDBConstants.TSDB_DATA_TYPE_BINARY: { ByteBuffer bb = (ByteBuffer) this.colData.get(col); - bb.position(fieldSize * this.rowIndex); - + bb.position((fieldSize + BINARY_LENGTH_OFFSET) * this.rowIndex); int length = bb.getShort(); - byte[] dest = new byte[length]; bb.get(dest, 0, length); if (NullType.isBinaryNull(dest, length)) { @@ -419,16 +418,13 @@ public class TSDBResultSetBlockData { case TSDBConstants.TSDB_DATA_TYPE_NCHAR: { ByteBuffer bb = (ByteBuffer) this.colData.get(col); - bb.position(fieldSize * this.rowIndex); - + bb.position((fieldSize + BINARY_LENGTH_OFFSET) * this.rowIndex); int length = bb.getShort(); - byte[] dest = new byte[length]; bb.get(dest, 0, length); if (NullType.isNcharNull(dest, length)) { return null; } - try { String charset = TaosGlobalConfig.getCharset(); return new String(dest, charset); diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java index 12a0ab57e2c35c7f1f550dd213db19a0effd4ebc..e818736096355c4937e5af0470b77c95486c86db 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/rs/RestfulConnection.java @@ -18,7 +18,7 @@ public class RestfulConnection extends AbstractConnection { private final String url; private final String database; private final String token; - /******************************************************/ + private boolean isClosed; private final DatabaseMetaData metadata; 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 a88dc411f333fea82fa5310ee87f263b117f7e70..21c76f73b287e55ef14f5d70cf6a911a9cb543db 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 @@ -88,17 +88,24 @@ public class RestfulStatement extends AbstractStatement { } private String getUrl() throws SQLException { + String dbname = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_DBNAME); + if (dbname == null || dbname.trim().isEmpty()) { + dbname = ""; + } else { + dbname = "/" + dbname.toLowerCase(); + } TimestampFormat timestampFormat = TimestampFormat.valueOf(conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).trim().toUpperCase()); String url; + switch (timestampFormat) { case TIMESTAMP: - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt"; + url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt" + dbname; break; case UTC: - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc"; + url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc" + dbname; break; default: - url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql"; + url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql" + dbname; } return url; } diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java index 6bddd3f42835e6706ef922f2175d6e9a36dcf509..3d76e1f98d4f8aa1d0ba3d68395e4036c5b069e6 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/TSDBPreparedStatementTest.java @@ -586,6 +586,130 @@ public class TSDBPreparedStatementTest { Assert.assertEquals(numOfRows, rows); } + @Test + public void bindDataQueryTest() throws SQLException { + Statement stmt = conn.createStatement(); + + stmt.execute("drop table if exists weather_test"); + stmt.execute("create table weather_test(ts timestamp, f1 nchar(10), f2 binary(10)) tags (t1 int, t2 binary(10))"); + + int numOfRows = 1; + + TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? using weather_test tags(?,?) (ts, f2) values(?, ?)"); + s.setTableName("w2"); + s.setTagInt(0, 1); + s.setTagString(1, "test"); + + + ArrayList ts = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + ts.add(System.currentTimeMillis() + i); + } + s.setTimestamp(0, ts); + + ArrayList s2 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + s2.add("test" + i % 4); + } + s.setString(1, s2, 10); + + s.columnDataAddBatch(); + s.columnDataExecuteBatch(); + s.columnDataCloseBatch(); + + String sql = "select * from weather_test where t1 >= ? and t1 <= ?"; + TSDBPreparedStatement s1 = (TSDBPreparedStatement) conn.prepareStatement(sql); + s1.setInt(1, 0); + s1.setInt(2, 10); + + ResultSet rs = s1.executeQuery(); + int rows = 0; + while (rs.next()) { + rows++; + } + Assert.assertEquals(numOfRows, rows); + } + + @Test + public void setTagNullTest()throws SQLException { + Statement stmt = conn.createStatement(); + + stmt.execute("drop table if exists weather_test"); + stmt.execute("create table weather_test(ts timestamp, c1 int) tags (t1 tinyint, t2 smallint, t3 int, t4 bigint, t5 float, t6 double, t7 bool, t8 binary(10), t9 nchar(10))"); + + int numOfRows = 1; + + TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? using weather_test tags(?,?,?,?,?,?,?,?,?) values(?, ?)"); + s.setTableName("w3"); + s.setTagNull(0, TSDBConstants.TSDB_DATA_TYPE_TINYINT); + s.setTagNull(1, TSDBConstants.TSDB_DATA_TYPE_SMALLINT); + s.setTagNull(2, TSDBConstants.TSDB_DATA_TYPE_INT); + s.setTagNull(3, TSDBConstants.TSDB_DATA_TYPE_BIGINT); + s.setTagNull(4, TSDBConstants.TSDB_DATA_TYPE_FLOAT); + s.setTagNull(5, TSDBConstants.TSDB_DATA_TYPE_DOUBLE); + s.setTagNull(6, TSDBConstants.TSDB_DATA_TYPE_BOOL); + s.setTagNull(7, TSDBConstants.TSDB_DATA_TYPE_BINARY); + s.setTagNull(8, TSDBConstants.TSDB_DATA_TYPE_NCHAR); + + ArrayList ts = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + ts.add(System.currentTimeMillis() + i); + } + s.setTimestamp(0, ts); + + ArrayList s2 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + s2.add(i); + } + s.setInt(1, s2); + + s.columnDataAddBatch(); + s.columnDataExecuteBatch(); + s.columnDataCloseBatch(); + } + + private String stringGenerator(int length) { + String source = "abcdefghijklmnopqrstuvwxyz"; + StringBuilder sb = new StringBuilder(); + Random rand = new Random(); + for(int i = 0; i < length; i++) { + sb.append(source.charAt(rand.nextInt(26))); + } + return sb.toString(); + } + + @Test(expected = SQLException.class) + public void setMaxTableNameTest()throws SQLException { + Statement stmt = conn.createStatement(); + + stmt.execute("drop table if exists weather_test"); + stmt.execute("create table weather_test(ts timestamp, c1 int) tags (t1 int)"); + + TSDBPreparedStatement s = (TSDBPreparedStatement) conn.prepareStatement("insert into ? using weather_test tags(?) values(?, ?)"); + String tbname = stringGenerator(193); + s.setTableName(tbname); + s.setTagInt(0, 1); + + int numOfRows = 1; + + ArrayList ts = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + ts.add(System.currentTimeMillis() + i); + } + s.setTimestamp(0, ts); + + ArrayList s2 = new ArrayList<>(); + for (int i = 0; i < numOfRows; i++) { + s2.add(i); + } + s.setInt(1, s2); + + s.columnDataAddBatch(); + s.columnDataExecuteBatch(); + s.columnDataCloseBatch(); + } + + @Test(expected = SQLException.class) public void createTwoSameDbTest() throws SQLException { // when diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiConnectionWithDifferentDbTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiConnectionWithDifferentDbTest.java new file mode 100644 index 0000000000000000000000000000000000000000..18a2c32aca0535567dd42e886bc87ae618596a40 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/MultiConnectionWithDifferentDbTest.java @@ -0,0 +1,101 @@ +package com.taosdata.jdbc.cases; + +import org.junit.Before; +import org.junit.Test; + +import java.sql.*; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class MultiConnectionWithDifferentDbTest { + + private static String host = "127.0.0.1"; + private static String db1 = "db1"; + private static String db2 = "db2"; + + private long ts; + + @Test + public void test() { + List threads = IntStream.range(1, 3).mapToObj(i -> new Thread(new Runnable() { + @Override + public void run() { + for (int j = 0; j < 10; j++) { + queryDb(); + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void queryDb() { + String url = "jdbc:TAOS-RS://" + host + ":6041/db" + i + "?user=root&password=taosdata"; + try (Connection connection = DriverManager.getConnection(url)) { + Statement stmt = connection.createStatement(); + + ResultSet rs = stmt.executeQuery("select * from weather"); + assertNotNull(rs); + rs.next(); + long actual = rs.getTimestamp("ts").getTime(); + assertEquals(ts, actual); + + int f1 = rs.getInt("f1"); + assertEquals(i, f1); + + String loc = i == 1 ? "beijing" : "shanghai"; + String loc_actual = rs.getString("loc"); + assertEquals(loc, loc_actual); + + stmt.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + }, "thread-" + i)).collect(Collectors.toList()); + + threads.forEach(Thread::start); + + for (Thread t : threads) { + try { + t.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + } + + @Before + public void before() { + ts = System.currentTimeMillis(); + + try { + Connection conn = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"); + + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists " + db1); + stmt.execute("create database if not exists " + db1); + stmt.execute("use " + db1); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("insert into t1 using weather tags('beijing') values(" + ts + ", 1)"); + + stmt.execute("drop database if exists " + db2); + stmt.execute("create database if not exists " + db2); + stmt.execute("use " + db2); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("insert into t1 using weather tags('shanghai') values(" + ts + ", 2)"); + + conn.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UseNowInsertTimestampTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UseNowInsertTimestampTest.java new file mode 100644 index 0000000000000000000000000000000000000000..fbce021d1bff3655eedcf487dbcbf4747d5f9897 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/UseNowInsertTimestampTest.java @@ -0,0 +1,84 @@ +package com.taosdata.jdbc.cases; + +import org.junit.Before; +import org.junit.Test; + +import java.sql.*; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class UseNowInsertTimestampTest { + String url = "jdbc:TAOS://127.0.0.1:6030/?user=root&password=taosdata"; + + @Test + public void millisec() { + try (Connection conn = DriverManager.getConnection(url)) { + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists test"); + stmt.execute("create database if not exists test precision 'ms'"); + stmt.execute("use test"); + stmt.execute("create table weather(ts timestamp, f1 int)"); + stmt.execute("insert into weather values(now, 1)"); + + ResultSet rs = stmt.executeQuery("select * from weather"); + rs.next(); + Timestamp ts = rs.getTimestamp("ts"); + assertEquals(13, Long.toString(ts.getTime()).length()); + + int nanos = ts.getNanos(); + assertEquals(0, nanos % 1000_000); + + stmt.execute("drop database if exists test"); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void microsec() { + try (Connection conn = DriverManager.getConnection(url)) { + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists test"); + stmt.execute("create database if not exists test precision 'us'"); + stmt.execute("use test"); + stmt.execute("create table weather(ts timestamp, f1 int)"); + stmt.execute("insert into weather values(now, 1)"); + + ResultSet rs = stmt.executeQuery("select * from weather"); + rs.next(); + Timestamp ts = rs.getTimestamp("ts"); + int nanos = ts.getNanos(); + + assertEquals(0, nanos % 1000); + + stmt.execute("drop database if exists test"); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Test + public void nanosec() { + try (Connection conn = DriverManager.getConnection(url)) { + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists test"); + stmt.execute("create database if not exists test precision 'ns'"); + stmt.execute("use test"); + stmt.execute("create table weather(ts timestamp, f1 int)"); + stmt.execute("insert into weather values(now, 1)"); + + ResultSet rs = stmt.executeQuery("select * from weather"); + rs.next(); + + Timestamp ts = rs.getTimestamp("ts"); + + int nanos = ts.getNanos(); + assertTrue(nanos % 1000 != 0); + + stmt.execute("drop database if exists test"); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/DatabaseSpecifiedTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/DatabaseSpecifiedTest.java new file mode 100644 index 0000000000000000000000000000000000000000..9fe51e7203fac7133783e47fd5b0cc07f33b2494 --- /dev/null +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/DatabaseSpecifiedTest.java @@ -0,0 +1,69 @@ +package com.taosdata.jdbc.rs; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.*; + +import static org.junit.Assert.*; + +public class DatabaseSpecifiedTest { + + private static String host = "127.0.0.1"; + private static String dbname = "test_db_spec"; + + private Connection connection; + private long ts; + + @Test + public void test() throws SQLException { + // when + connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/" + dbname + "?user=root&password=taosdata"); + try (Statement stmt = connection.createStatement();) { + ResultSet rs = stmt.executeQuery("select * from weather"); + + //then + assertNotNull(rs); + rs.next(); + long now = rs.getTimestamp("ts").getTime(); + assertEquals(ts, now); + int f1 = rs.getInt(2); + assertEquals(1, f1); + String loc = rs.getString("loc"); + assertEquals("beijing", loc); + } + connection.close(); + } + + @Before + public void before() { + ts = System.currentTimeMillis(); + try { + Connection connection = DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata"); + Statement stmt = connection.createStatement(); + + stmt.execute("drop database if exists " + dbname); + stmt.execute("create database if not exists " + dbname); + stmt.execute("use " + dbname); + stmt.execute("create table weather(ts timestamp, f1 int) tags(loc nchar(10))"); + stmt.execute("insert into t1 using weather tags('beijing') values( " + ts + ", 1)"); + + stmt.close(); + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @After + public void after() { + try { + if (connection != null) + connection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulConnectionTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulConnectionTest.java index abd60f5b63d46b406f19b6be9dcbbab6b786de12..1c5c03aacb5e7ed5683c75414975224a67d49e21 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulConnectionTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/rs/RestfulConnectionTest.java @@ -9,6 +9,8 @@ import org.junit.Test; import java.sql.*; import java.util.Properties; +import static org.junit.Assert.assertEquals; + public class RestfulConnectionTest { private static final String host = "127.0.0.1"; @@ -26,7 +28,7 @@ public class RestfulConnectionTest { ResultSet rs = stmt.executeQuery("select server_status()"); rs.next(); int status = rs.getInt("server_status()"); - Assert.assertEquals(1, status); + assertEquals(1, status); } catch (SQLException e) { e.printStackTrace(); } @@ -38,7 +40,7 @@ public class RestfulConnectionTest { ResultSet rs = pstmt.executeQuery(); rs.next(); int status = rs.getInt("server_status()"); - Assert.assertEquals(1, status); + assertEquals(1, status); } @Test(expected = SQLFeatureNotSupportedException.class) @@ -49,7 +51,7 @@ public class RestfulConnectionTest { @Test public void nativeSQL() throws SQLException { String nativeSQL = conn.nativeSQL("select * from log.log"); - Assert.assertEquals("select * from log.log", nativeSQL); + assertEquals("select * from log.log", nativeSQL); } @Test @@ -87,7 +89,7 @@ public class RestfulConnectionTest { public void getMetaData() throws SQLException { DatabaseMetaData meta = conn.getMetaData(); Assert.assertNotNull(meta); - Assert.assertEquals("com.taosdata.jdbc.rs.RestfulDriver", meta.getDriverName()); + assertEquals("com.taosdata.jdbc.rs.RestfulDriver", meta.getDriverName()); } @Test @@ -103,25 +105,25 @@ public class RestfulConnectionTest { @Test public void setCatalog() throws SQLException { conn.setCatalog("test"); - Assert.assertEquals("test", conn.getCatalog()); + assertEquals("test", conn.getCatalog()); } @Test public void getCatalog() throws SQLException { conn.setCatalog("log"); - Assert.assertEquals("log", conn.getCatalog()); + assertEquals("log", conn.getCatalog()); } @Test(expected = SQLFeatureNotSupportedException.class) public void setTransactionIsolation() throws SQLException { conn.setTransactionIsolation(Connection.TRANSACTION_NONE); - Assert.assertEquals(Connection.TRANSACTION_NONE, conn.getTransactionIsolation()); + assertEquals(Connection.TRANSACTION_NONE, conn.getTransactionIsolation()); conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); } @Test public void getTransactionIsolation() throws SQLException { - Assert.assertEquals(Connection.TRANSACTION_NONE, conn.getTransactionIsolation()); + assertEquals(Connection.TRANSACTION_NONE, conn.getTransactionIsolation()); } @Test @@ -140,7 +142,7 @@ public class RestfulConnectionTest { ResultSet rs = stmt.executeQuery("select server_status()"); rs.next(); int status = rs.getInt("server_status()"); - Assert.assertEquals(1, status); + assertEquals(1, status); conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); } @@ -152,7 +154,7 @@ public class RestfulConnectionTest { ResultSet rs = pstmt.executeQuery(); rs.next(); int status = rs.getInt("server_status()"); - Assert.assertEquals(1, status); + assertEquals(1, status); conn.prepareStatement("select server_status", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); } @@ -175,13 +177,13 @@ public class RestfulConnectionTest { @Test(expected = SQLFeatureNotSupportedException.class) public void setHoldability() throws SQLException { conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); - Assert.assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn.getHoldability()); + assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn.getHoldability()); conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); } @Test public void getHoldability() throws SQLException { - Assert.assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn.getHoldability()); + assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn.getHoldability()); } @Test(expected = SQLFeatureNotSupportedException.class) @@ -210,7 +212,7 @@ public class RestfulConnectionTest { ResultSet rs = stmt.executeQuery("select server_status()"); rs.next(); int status = rs.getInt("server_status()"); - Assert.assertEquals(1, status); + assertEquals(1, status); conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); } @@ -222,7 +224,7 @@ public class RestfulConnectionTest { ResultSet rs = pstmt.executeQuery(); rs.next(); int status = rs.getInt("server_status()"); - Assert.assertEquals(1, status); + assertEquals(1, status); conn.prepareStatement("select server_status", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); } @@ -299,11 +301,11 @@ public class RestfulConnectionTest { Properties info = conn.getClientInfo(); String charset = info.getProperty(TSDBDriver.PROPERTY_KEY_CHARSET); - Assert.assertEquals("UTF-8", charset); + assertEquals("UTF-8", charset); String locale = info.getProperty(TSDBDriver.PROPERTY_KEY_LOCALE); - Assert.assertEquals("en_US.UTF-8", locale); + assertEquals("en_US.UTF-8", locale); String timezone = info.getProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE); - Assert.assertEquals("UTC-8", timezone); + assertEquals("UTC-8", timezone); } @Test @@ -313,11 +315,11 @@ public class RestfulConnectionTest { conn.setClientInfo(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); String charset = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_CHARSET); - Assert.assertEquals("UTF-8", charset); + assertEquals("UTF-8", charset); String locale = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_LOCALE); - Assert.assertEquals("en_US.UTF-8", locale); + assertEquals("en_US.UTF-8", locale); String timezone = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIME_ZONE); - Assert.assertEquals("UTC-8", timezone); + assertEquals("UTC-8", timezone); } @Test(expected = SQLFeatureNotSupportedException.class) @@ -345,14 +347,15 @@ public class RestfulConnectionTest { conn.abort(null); } - @Test(expected = SQLFeatureNotSupportedException.class) + @Test public void setNetworkTimeout() throws SQLException { conn.setNetworkTimeout(null, 1000); } - @Test(expected = SQLFeatureNotSupportedException.class) + @Test public void getNetworkTimeout() throws SQLException { - conn.getNetworkTimeout(); + int timeout = conn.getNetworkTimeout(); + assertEquals(0, timeout); } @Test diff --git a/src/connector/python/examples/demo.py b/src/connector/python/examples/demo.py index 6c7c03f3e2c9630fab2af661d5c589066c21755f..3bc09046f3a33557e513425c06373c66958f2a2f 100644 --- a/src/connector/python/examples/demo.py +++ b/src/connector/python/examples/demo.py @@ -2,7 +2,7 @@ import taos conn = taos.connect(host='127.0.0.1', user='root', - passworkd='taodata', + password='taosdata', database='log') cursor = conn.cursor() diff --git a/src/connector/python/taos/bind.py b/src/connector/python/taos/bind.py index ede6381628ae0fd5ff8794ef23db2f5afcfb5f3d..083ddc99aea8dc6f39b1f22ac5f77d2584a2fe69 100644 --- a/src/connector/python/taos/bind.py +++ b/src/connector/python/taos/bind.py @@ -10,7 +10,8 @@ import sys _datetime_epoch = datetime.utcfromtimestamp(0) def _is_not_none(obj): - obj != None + return obj != None + class TaosBind(ctypes.Structure): _fields_ = [ ("buffer_type", c_int), @@ -299,27 +300,14 @@ class TaosMultiBind(ctypes.Structure): self.buffer = cast(buffer, c_void_p) self.num = len(values) - def binary(self, values): + def _str_to_buffer(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 + is_null = [1 if v == None else 0 for v in values] + self.is_null = cast((c_byte * self.num)(*is_null), c_char_p) + + if sum(is_null) == self.num: + self.length = (c_int32 * len(values))(0 * self.num) + return 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) @@ -347,9 +335,26 @@ class TaosMultiBind(ctypes.Structure): ) self.length = (c_int32 * len(values))(*[len(b) if b is not None else 0 for b in _bytes]) self.buffer_length = buffer_length + def binary(self, values): + self.buffer_type = FieldType.C_BINARY + self._str_to_buffer(values) + + 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) - self.is_null = cast((c_byte * self.num)(*[1 if v == None else 0 for v in values]), c_char_p) + + def nchar(self, values): + # type: (list[str]) -> None self.buffer_type = FieldType.C_NCHAR + self._str_to_buffer(values) def tinyint_unsigned(self, values): self.buffer_type = FieldType.C_TINYINT_UNSIGNED diff --git a/src/connector/python/taos/cinterface.py b/src/connector/python/taos/cinterface.py index 51e9a8667ddcab3d5d67da8be429f460f33d9eed..aad9d1fdbfd4f900fe2db96dadbf343ea922be22 100644 --- a/src/connector/python/taos/cinterface.py +++ b/src/connector/python/taos/cinterface.py @@ -49,7 +49,7 @@ def _load_taos(): try: return load_func[platform.system()]() except: - sys.exit("unsupported platform to TDengine connector") + raise InterfaceError('unsupported platform or failed to load taos client library') _libtaos = _load_taos() @@ -102,9 +102,7 @@ _libtaos.taos_get_client_info.restype = c_char_p def taos_get_client_info(): # type: () -> str - """Get client version info. - 获取客户端版本信息。 - """ + """Get client version info.""" return _libtaos.taos_get_client_info().decode() @@ -114,6 +112,7 @@ _libtaos.taos_get_server_info.argtypes = (c_void_p,) def taos_get_server_info(connection): # type: (c_void_p) -> str + """Get server version as string.""" return _libtaos.taos_get_server_info(connection).decode() @@ -134,11 +133,10 @@ _libtaos.taos_connect.argtypes = c_char_p, c_char_p, c_char_p, c_char_p, c_uint1 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 / 用户密码 + - host: server hostname/FQDN + - user: user name + - password: user password - db: database name (optional) - port: server port @@ -187,11 +185,10 @@ _libtaos.taos_connect_auth.argtypes = c_char_p, c_char_p, c_char_p, c_char_p, c_ def taos_connect_auth(host=None, user="root", auth="", db=None, port=0): # type: (None|str, str, str, None|str, int) -> c_void_p - """ - 创建数据库连接,初始化连接上下文。其中需要用户提供的参数包含: + """Connect server with auth token. - - host: server hostname/FQDN, TDengine管理主节点的FQDN - - user: user name/用户名 + - host: server hostname/FQDN + - user: user name - auth: base64 encoded auth token - db: database name (optional) - port: server port @@ -830,6 +827,16 @@ def taos_insert_lines(connection, lines): if errno != 0: raise LinesError("insert lines error", errno) +def taos_insert_telnet_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_telnet_lines(connection, p_lines, num_of_lines) + if errno != 0: + raise LinesError("insert telnet lines error", errno) + class CTaosInterface(object): def __init__(self, config=None): diff --git a/src/connector/python/taos/connection.py b/src/connector/python/taos/connection.py index 7857c8c706dbe27fd9440e6bf2eb698b6822650e..a8a71ecc3a8a5f2bdc960df364213e80018a70fe 100644 --- a/src/connector/python/taos/connection.py +++ b/src/connector/python/taos/connection.py @@ -145,6 +145,15 @@ class TaosConnection(object): """ return taos_insert_lines(self._conn, lines) + def insert_telnet_lines(self, lines): + """OpenTSDB telnet style API format support + + ## Example + cpu_load 1626056811855516532ns 2.0f32 id="tb1",host="host0",interface="eth0" + + """ + return taos_insert_telnet_lines(self._conn, lines) + def cursor(self): # type: () -> TaosCursor """Return a new Cursor object using the connection.""" diff --git a/src/connector/python/taos/constants.py b/src/connector/python/taos/constants.py index b500df627c22919e7aab964504ccbe50c573c1c5..8ad5b69fc099718fa4f4b8c08cf689b17663eae0 100644 --- a/src/connector/python/taos/constants.py +++ b/src/connector/python/taos/constants.py @@ -3,6 +3,9 @@ """Constants in TDengine python """ +import ctypes, struct + + class FieldType(object): """TDengine Field Types""" @@ -33,8 +36,8 @@ 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_FLOAT_NULL = ctypes.c_float(struct.unpack("is_raw_time = true; break; case 'f': - if (wordexp(arg, &full_path, 0) != 0) { + if ((0 == strlen(arg)) || (wordexp(arg, &full_path, 0) != 0)) { fprintf(stderr, "Invalid path %s\n", arg); return -1; } @@ -190,7 +190,9 @@ static void parse_args( fprintf(stderr, "password reading error\n"); } taosSetConsoleEcho(true); - getchar(); + if (EOF == getchar()) { + fprintf(stderr, "getchar() return EOF\n"); + } } else { tstrncpy(g_password, (char *)(argv[i] + 2), SHELL_MAX_PASSWORD_LEN); strcpy(argv[i], "-p"); diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index bfd55c52fafd4205d993433b8349e16fc9640611..87102cc1c76206a0c6f779efc9ef22e9607409ef 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -53,14 +53,6 @@ #include "taoserror.h" #include "tutil.h" -#define STMT_IFACE_ENABLED 1 -#define NANO_SECOND_ENABLED 1 -#define SET_THREADNAME_ENABLED 1 - -#if SET_THREADNAME_ENABLED == 0 -#define setThreadName(name) -#endif - #define REQ_EXTRA_BUF_LEN 1024 #define RESP_BUF_LEN 4096 @@ -83,6 +75,8 @@ extern char configDir[]; #define OPT_ABORT 1 /* –abort */ #define MAX_FILE_NAME_LEN 256 // max file name length on linux is 255. +#define DEFAULT_START_TIME 1500000000000 + #define MAX_PREPARED_RAND 1000000 #define INT_BUFF_LEN 11 #define BIGINT_BUFF_LEN 21 @@ -110,6 +104,9 @@ extern char configDir[]; #define NOTE_BUFF_LEN (SMALL_BUFF_LEN*16) #define DEFAULT_TIMESTAMP_STEP 1 +#define DEFAULT_INTERLACE_ROWS 0 +#define DEFAULT_DATATYPE_NUM 1 +#define DEFAULT_CHILDTABLES 10000 enum TEST_MODE { @@ -209,9 +206,9 @@ enum _describe_table_index { static char *g_dupstr = NULL; typedef struct SArguments_S { - char * metaFile; + char *metaFile; uint32_t test_mode; - char * host; + char *host; uint16_t port; uint16_t iface; char * user; @@ -230,7 +227,7 @@ typedef struct SArguments_S { char * output_file; bool async_mode; char * datatype[MAX_NUM_COLUMNS + 1]; - uint32_t len_of_binary; + uint32_t binwidth; uint32_t num_of_CPR; uint32_t num_of_threads; uint64_t insert_interval; @@ -294,9 +291,6 @@ typedef struct SSuperTable_S { uint64_t lenOfTagOfOneRow; char* sampleDataBuf; -#if STMT_IFACE_ENABLED == 1 - char* sampleBindArray; -#endif //int sampleRowCount; //int sampleUsePos; @@ -373,7 +367,7 @@ typedef struct SDbs_S { bool asyncMode; uint32_t threadCount; - uint32_t threadCountByCreateTbl; + uint32_t threadCountForCreateTbl; uint32_t dbCount; SDataBase db[MAX_DB_COUNT]; @@ -443,7 +437,8 @@ typedef struct SQueryMetaInfo_S { typedef struct SThreadInfo_S { TAOS * taos; TAOS_STMT *stmt; - int64_t *bind_ts; + char* sampleBindArray; + int64_t *bind_ts; int threadID; char db_name[TSDB_DB_NAME_LEN]; uint32_t time_precision; @@ -453,6 +448,7 @@ typedef struct SThreadInfo_S { uint64_t start_table_from; uint64_t end_table_to; int64_t ntables; + int64_t tables_created; uint64_t data_of_rate; int64_t start_time; char* cols; @@ -591,24 +587,22 @@ char *g_randdouble_buff = NULL; char *g_aggreFunc[] = {"*", "count(*)", "avg(col0)", "sum(col0)", "max(col0)", "min(col0)", "first(col0)", "last(col0)"}; -#define DEFAULT_DATATYPE_NUM 3 - SArguments g_args = { - NULL, // metaFile - 0, // test_mode - "127.0.0.1", // host - 6030, // port - INTERFACE_BUT, // iface - "root", // user + NULL, // metaFile + 0, // test_mode + "localhost", // host + 6030, // port + INTERFACE_BUT, // iface + "root", // user #ifdef _TD_POWER_ "powerdb", // password #elif (_TD_TQ_ == true) - "tqueue", // password + "tqueue", // password #else - "taosdata", // password + "taosdata", // password #endif - "test", // database - 1, // replica + "test", // database + 1, // replica "d", // tb_prefix NULL, // sqlFile true, // use_metric @@ -625,16 +619,16 @@ SArguments g_args = { "INT", // datatype "FLOAT", // datatype. DEFAULT_DATATYPE_NUM is 3 }, - 64, // len_of_binary + 64, // binwidth 4, // num_of_CPR 10, // num_of_connections/thread 0, // insert_interval DEFAULT_TIMESTAMP_STEP, // timestamp_step 1, // query_times - 0, // interlace_rows; + DEFAULT_INTERLACE_ROWS, // interlace_rows; 30000, // num_of_RPR (1024*1024), // max_sql_len - 10000, // num_of_tables + DEFAULT_CHILDTABLES, // num_of_tables 10000, // num_of_DPT 0, // abort 0, // disorderRatio @@ -645,10 +639,9 @@ SArguments g_args = { true, // demo_mode; }; - - static SDbs g_Dbs; -static int64_t g_totalChildTables = 0; +static int64_t g_totalChildTables = DEFAULT_CHILDTABLES; +static int64_t g_actualChildTables = 0; static SQueryMetaInfo g_queryInfo; static FILE * g_fpOfInsertResult = NULL; @@ -669,7 +662,28 @@ static FILE * g_fpOfInsertResult = NULL; fprintf(stderr, "PERF: "fmt, __VA_ARGS__); } while(0) #define errorPrint(fmt, ...) \ - do { fprintf(stderr, " \033[31m"); fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); fprintf(stderr, " \033[0m"); } while(0) + do {\ + fprintf(stderr, " \033[31m");\ + fprintf(stderr, "ERROR: "fmt, __VA_ARGS__);\ + fprintf(stderr, " \033[0m");\ + } while(0) + +#define errorPrint2(fmt, ...) \ + do {\ + struct tm Tm, *ptm;\ + struct timeval timeSecs; \ + time_t curTime;\ + gettimeofday(&timeSecs, NULL); \ + curTime = timeSecs.tv_sec;\ + ptm = localtime_r(&curTime, &Tm);\ + fprintf(stderr, " \033[31m");\ + fprintf(stderr, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " ",\ + ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour,\ + ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec,\ + taosGetSelfPthreadId());\ + fprintf(stderr, " \033[0m");\ + errorPrint(fmt, __VA_ARGS__);\ + } while(0) // for strncpy buffer overflow #define min(a, b) (((a) < (b)) ? (a) : (b)) @@ -706,92 +720,99 @@ static void printVersion() { } static void printHelp() { - char indent[10] = " "; - printf("%s%s%s%s\n", indent, "-f", indent, + char indent[10] = " "; + printf("%s\n\n", "Usage: taosdemo [OPTION...]"); + printf("%s%s%s%s\n", indent, "-f, --file=FILE", "\t\t", "The meta file to the execution procedure. Default is './meta.json'."); - printf("%s%s%s%s\n", indent, "-u", indent, - "The TDengine user name to use when connecting to the server. Default is 'root'."); + printf("%s%s%s%s\n", indent, "-u, --user=USER", "\t\t", + "The user name to use when connecting to the server."); #ifdef _TD_POWER_ - 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, + printf("%s%s%s%s\n", indent, "-p, --password", "\t\t", + "The password to use when connecting to the server. Default is 'powerdb'"); + printf("%s%s%s%s\n", indent, "-c, --config-dir=CONFIG_DIR", "\t", "Configuration directory. Default is '/etc/power/'."); #elif (_TD_TQ_ == true) - 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, + printf("%s%s%s%s\n", indent, "-p, --password", "\t\t", + "The password to use when connecting to the server. Default is 'tqueue'"); + printf("%s%s%s%s\n", indent, "-c, --config-dir=CONFIG_DIR", "\t", "Configuration directory. Default is '/etc/tq/'."); #else - 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/'."); + printf("%s%s%s%s\n", indent, "-p, --password", "\t\t", + "The password to use when connecting to the server."); + printf("%s%s%s%s\n", indent, "-c, --config-dir=CONFIG_DIR", "\t", + "Configuration directory."); #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, - "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 + printf("%s%s%s%s\n", indent, "-h, --host=HOST", "\t\t", + "TDengine server FQDN to connect. The default host is localhost."); + printf("%s%s%s%s\n", indent, "-P, --port=PORT", "\t\t", + "The TCP/IP port number to use for the connection."); + printf("%s%s%s%s\n", indent, "-I, --interface=INTERFACE", "\t", "The interface (taosc, rest, and stmt) taosdemo uses. Default is 'taosc'."); -#else - "The interface (taosc, rest) taosdemo uses. Default is 'taosc'."); -#endif - printf("%s%s%s%s\n", indent, "-d", indent, + printf("%s%s%s%s\n", indent, "-d, --database=DATABASE", "\t", "Destination database. Default is 'test'."); - printf("%s%s%s%s\n", indent, "-a", indent, + printf("%s%s%s%s\n", indent, "-a, --replica=REPLICA", "\t\t", "Set the replica parameters of the database, Default 1, min: 1, max: 3."); - printf("%s%s%s%s\n", indent, "-m", indent, + printf("%s%s%s%s\n", indent, "-m, --table-prefix=TABLEPREFIX", "\t", "Table prefix name. Default is 'd'."); - printf("%s%s%s%s\n", indent, "-s", indent, "The select sql file."); - printf("%s%s%s%s\n", indent, "-N", indent, "Use normal table flag."); - printf("%s%s%s%s\n", indent, "-o", indent, + printf("%s%s%s%s\n", indent, "-s, --sql-file=FILE", "\t\t", + "The select sql file."); + printf("%s%s%s%s\n", indent, "-N, --normal-table", "\t\t", "Use normal table flag."); + printf("%s%s%s%s\n", indent, "-o, --output=FILE", "\t\t", "Direct output to the named file. Default is './output.txt'."); - printf("%s%s%s%s\n", indent, "-q", indent, + printf("%s%s%s%s\n", indent, "-q, --query-mode=MODE", "\t\t", "Query mode -- 0: SYNC, 1: ASYNC. Default is SYNC."); - printf("%s%s%s%s\n", indent, "-b", indent, + printf("%s%s%s%s\n", indent, "-b, --data-type=DATATYPE", "\t", "The data_type of columns, default: FLOAT, INT, FLOAT."); - printf("%s%s%s%s\n", indent, "-w", indent, - "The length of data_type 'BINARY' or 'NCHAR'. Default is 16"); - printf("%s%s%s%s%d%s%d\n", indent, "-l", indent, - "The number of columns per record. Default is ", + printf("%s%s%s%s%d\n", indent, "-w, --binwidth=WIDTH", "\t\t", + "The width of data_type 'BINARY' or 'NCHAR'. Default is ", + g_args.binwidth); + printf("%s%s%s%s%d%s%d\n", indent, "-l, --columns=COLUMNS", "\t\t", + "The number of columns per record. Demo mode by default is ", DEFAULT_DATATYPE_NUM, - ". Max values is ", + " (float, int, float). Max values is ", MAX_NUM_COLUMNS); printf("%s%s%s%s\n", indent, indent, indent, - "All of the new column(s) type is INT. If use -b to specify column type, -l will be ignored."); - printf("%s%s%s%s\n", indent, "-T", indent, + "\t\t\t\tAll of the new column(s) type is INT. If use -b to specify column type, -l will be ignored."); + printf("%s%s%s%s\n", indent, "-T, --threads=NUMBER", "\t\t", "The number of threads. Default is 10."); - printf("%s%s%s%s\n", indent, "-i", indent, + printf("%s%s%s%s\n", indent, "-i, --insert-interval=NUMBER", "\t", "The sleep time (ms) between insertion. Default is 0."); - printf("%s%s%s%s%d.\n", indent, "-S", indent, + printf("%s%s%s%s%d.\n", indent, "-S, --time-step=TIME_STEP", "\t", "The timestamp step between insertion. Default is ", DEFAULT_TIMESTAMP_STEP); - printf("%s%s%s%s\n", indent, "-r", indent, + printf("%s%s%s%s%d.\n", indent, "-B, --interlace-rows=NUMBER", "\t", + "The interlace rows of insertion. Default is ", + DEFAULT_INTERLACE_ROWS); + printf("%s%s%s%s\n", indent, "-r, --rec-per-req=NUMBER", "\t", "The number of records per request. Default is 30000."); - printf("%s%s%s%s\n", indent, "-t", indent, + printf("%s%s%s%s\n", indent, "-t, --tables=NUMBER", "\t\t", "The number of tables. Default is 10000."); - printf("%s%s%s%s\n", indent, "-n", indent, + printf("%s%s%s%s\n", indent, "-n, --records=NUMBER", "\t\t", "The number of records per table. Default is 10000."); - printf("%s%s%s%s\n", indent, "-M", indent, + printf("%s%s%s%s\n", indent, "-M, --random", "\t\t\t", "The value of records generated are totally random."); - printf("%s%s%s%s\n", indent, indent, indent, - " The default is to simulate power equipment senario."); - printf("%s%s%s%s\n", indent, "-x", indent, "Not insert only flag."); - printf("%s%s%s%s\n", indent, "-y", indent, "Default input yes for prompt."); - printf("%s%s%s%s\n", indent, "-O", indent, - "Insert mode--0: In order, 1 ~ 50: disorder ratio. Default is in order."); - printf("%s%s%s%s\n", indent, "-R", indent, + printf("%s\n", "\t\t\t\tThe default is to simulate power equipment senario."); + printf("%s%s%s%s\n", indent, "-x, --no-insert", "\t\t", + "No-insert flag."); + printf("%s%s%s%s\n", indent, "-y, --answer-yes", "\t\t", "Default input yes for prompt."); + printf("%s%s%s%s\n", indent, "-O, --disorder=NUMBER", "\t\t", + "Insert order mode--0: In order, 1 ~ 50: disorder ratio. Default is in order."); + printf("%s%s%s%s\n", indent, "-R, --disorder-range=NUMBER", "\t", "Out of order data's range, ms, default is 1000."); - printf("%s%s%s%s\n", indent, "-g", indent, + printf("%s%s%s%s\n", indent, "-g, --debug", "\t\t\t", "Print debug info."); - printf("%s%s%s\n", indent, "-V, --version\t", - "Print version info."); - printf("%s%s%s%s\n", indent, "--help\t", indent, - "Print command line arguments list info."); + printf("%s%s%s%s\n", indent, "-?, --help\t", "\t\t", + "Give this help list"); + printf("%s%s%s%s\n", indent, " --usage\t", "\t\t", + "Give a short usage message"); + printf("%s%s\n", indent, "-V, --version\t\t\tPrint program version."); /* printf("%s%s%s%s\n", indent, "-D", indent, "Delete database if exists. 0: no, 1: yes, default is 1"); */ + printf("\nMandatory or optional arguments to long options are also mandatory or optional\n\ +for any corresponding short options.\n\ +\n\ +Report bugs to .\n"); } static bool isStringNumber(char *input) @@ -809,62 +830,236 @@ static bool isStringNumber(char *input) return true; } +static void errorWrongValue(char *program, char *wrong_arg, char *wrong_value) +{ + fprintf(stderr, "%s %s: %s is an invalid value\n", program, wrong_arg, wrong_value); + fprintf(stderr, "Try `taosdemo --help' or `taosdemo --usage' for more information.\n"); +} + +static void errorUnreconized(char *program, char *wrong_arg) +{ + fprintf(stderr, "%s: unrecognized options '%s'\n", program, wrong_arg); + fprintf(stderr, "Try `taosdemo --help' or `taosdemo --usage' for more information.\n"); +} + +static void errorPrintReqArg(char *program, char *wrong_arg) +{ + fprintf(stderr, + "%s: option requires an argument -- '%s'\n", + program, wrong_arg); + fprintf(stderr, + "Try `taosdemo --help' or `taosdemo --usage' for more information.\n"); +} + +static void errorPrintReqArg2(char *program, char *wrong_arg) +{ + fprintf(stderr, + "%s: option requires a number argument '-%s'\n", + program, wrong_arg); + fprintf(stderr, + "Try `taosdemo --help' or `taosdemo --usage' for more information.\n"); +} + +static void errorPrintReqArg3(char *program, char *wrong_arg) +{ + fprintf(stderr, + "%s: option '%s' requires an argument\n", + program, wrong_arg); + fprintf(stderr, + "Try `taosdemo --help' or `taosdemo --usage' for more information.\n"); +} + static void parse_args(int argc, char *argv[], SArguments *arguments) { for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "-f") == 0) { + if ((0 == strncmp(argv[i], "-f", strlen("-f"))) + || (0 == strncmp(argv[i], "--file", strlen("--file")))) { arguments->demo_mode = false; - arguments->metaFile = argv[++i]; - } else if (strcmp(argv[i], "-c") == 0) { - if (argc == i+1) { - printHelp(); - errorPrint("%s", "\n\t-c need a valid path following!\n"); + + if (2 == strlen(argv[i])) { + if (i+1 == argc) { + errorPrintReqArg(argv[0], "f"); + exit(EXIT_FAILURE); + } + arguments->metaFile = argv[++i]; + } else if (0 == strncmp(argv[i], "-f", strlen("-f"))) { + arguments->metaFile = (char *)(argv[i] + strlen("-f")); + } else if (strlen("--file") == strlen(argv[i])) { + if (i+1 == argc) { + errorPrintReqArg3(argv[0], "--file"); + exit(EXIT_FAILURE); + } + arguments->metaFile = argv[++i]; + } else if (0 == strncmp(argv[i], "--file=", strlen("--file="))) { + arguments->metaFile = (char *)(argv[i] + strlen("--file=")); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN); - } else if (strcmp(argv[i], "-h") == 0) { - if (argc == i+1) { - printHelp(); - errorPrint("%s", "\n\t-h need a valid string following!\n"); + } else if ((0 == strncmp(argv[i], "-c", strlen("-c"))) + || (0 == strncmp(argv[i], "--config-dir", strlen("--config-dir")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "c"); + exit(EXIT_FAILURE); + } + tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN); + } else if (0 == strncmp(argv[i], "-c", strlen("-c"))) { + tstrncpy(configDir, (char *)(argv[i] + strlen("-c")), TSDB_FILENAME_LEN); + } else if (strlen("--config-dir") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--config-dir"); + exit(EXIT_FAILURE); + } + tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN); + } else if (0 == strncmp(argv[i], "--config-dir=", strlen("--config-dir="))) { + tstrncpy(configDir, (char *)(argv[i] + strlen("--config-dir=")), TSDB_FILENAME_LEN); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->host = argv[++i]; - } 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"); + } else if ((0 == strncmp(argv[i], "-h", strlen("-h"))) + || (0 == strncmp(argv[i], "--host", strlen("--host")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "h"); + exit(EXIT_FAILURE); + } + arguments->host = argv[++i]; + } else if (0 == strncmp(argv[i], "-h", strlen("-h"))) { + arguments->host = (char *)(argv[i] + strlen("-h")); + } else if (strlen("--host") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--host"); + exit(EXIT_FAILURE); + } + arguments->host = argv[++i]; + } else if (0 == strncmp(argv[i], "--host=", strlen("--host="))) { + arguments->host = (char *)(argv[i] + strlen("--host=")); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->port = atoi(argv[++i]); - } else if (strcmp(argv[i], "-I") == 0) { - if (argc == i+1) { - printHelp(); - errorPrint("%s", "\n\t-I need a valid string following!\n"); + } else if (strcmp(argv[i], "-PP") == 0) { + arguments->performance_print = true; + } else if ((0 == strncmp(argv[i], "-P", strlen("-P"))) + || (0 == strncmp(argv[i], "--port", strlen("--port")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "P"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "P"); + exit(EXIT_FAILURE); + } + arguments->port = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--port=", strlen("--port="))) { + if (isStringNumber((char *)(argv[i] + strlen("--port=")))) { + arguments->port = atoi((char *)(argv[i]+strlen("--port="))); + } + } else if (0 == strncmp(argv[i], "-P", strlen("-P"))) { + if (isStringNumber((char *)(argv[i] + strlen("-P")))) { + arguments->port = atoi((char *)(argv[i]+strlen("-P"))); + } + } else if (strlen("--port") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--port"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--port"); + exit(EXIT_FAILURE); + } + arguments->port = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - ++i; - if (0 == strcasecmp(argv[i], "taosc")) { - arguments->iface = TAOSC_IFACE; - } else if (0 == strcasecmp(argv[i], "rest")) { - arguments->iface = REST_IFACE; -#if STMT_IFACE_ENABLED == 1 - } else if (0 == strcasecmp(argv[i], "stmt")) { - arguments->iface = STMT_IFACE; -#endif + } else if ((0 == strncmp(argv[i], "-I", strlen("-I"))) + || (0 == strncmp(argv[i], "--interface", strlen("--interface")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "I"); + exit(EXIT_FAILURE); + } + if (0 == strcasecmp(argv[i+1], "taosc")) { + arguments->iface = TAOSC_IFACE; + } else if (0 == strcasecmp(argv[i+1], "rest")) { + arguments->iface = REST_IFACE; + } else if (0 == strcasecmp(argv[i+1], "stmt")) { + arguments->iface = STMT_IFACE; + } else { + errorWrongValue(argv[0], "-I", argv[i+1]); + exit(EXIT_FAILURE); + } + i++; + } else if (0 == strncmp(argv[i], "--interface=", strlen("--interface="))) { + if (0 == strcasecmp((char *)(argv[i] + strlen("--interface=")), "taosc")) { + arguments->iface = TAOSC_IFACE; + } else if (0 == strcasecmp((char *)(argv[i] + strlen("--interface=")), "rest")) { + arguments->iface = REST_IFACE; + } else if (0 == strcasecmp((char *)(argv[i] + strlen("--interface=")), "stmt")) { + arguments->iface = STMT_IFACE; + } else { + errorPrintReqArg3(argv[0], "--interface"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-I", strlen("-I"))) { + if (0 == strcasecmp((char *)(argv[i] + strlen("-I")), "taosc")) { + arguments->iface = TAOSC_IFACE; + } else if (0 == strcasecmp((char *)(argv[i] + strlen("-I")), "rest")) { + arguments->iface = REST_IFACE; + } else if (0 == strcasecmp((char *)(argv[i] + strlen("-I")), "stmt")) { + arguments->iface = STMT_IFACE; + } else { + errorWrongValue(argv[0], "-I", + (char *)(argv[i] + strlen("-I"))); + exit(EXIT_FAILURE); + } + } else if (strlen("--interface") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--interface"); + exit(EXIT_FAILURE); + } + if (0 == strcasecmp(argv[i+1], "taosc")) { + arguments->iface = TAOSC_IFACE; + } else if (0 == strcasecmp(argv[i+1], "rest")) { + arguments->iface = REST_IFACE; + } else if (0 == strcasecmp(argv[i+1], "stmt")) { + arguments->iface = STMT_IFACE; + } else { + errorWrongValue(argv[0], "--interface", argv[i+1]); + exit(EXIT_FAILURE); + } + i++; } else { - errorPrint("%s", "\n\t-I need a valid string following!\n"); + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - } else if (strcmp(argv[i], "-u") == 0) { - if (argc == i+1) { - printHelp(); - errorPrint("%s", "\n\t-u need a valid string following!\n"); + } else if ((0 == strncmp(argv[i], "-u", strlen("-u"))) + || (0 == strncmp(argv[i], "--user", strlen("--user")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "u"); + exit(EXIT_FAILURE); + } + arguments->user = argv[++i]; + } else if (0 == strncmp(argv[i], "-u", strlen("-u"))) { + arguments->user = (char *)(argv[i++] + strlen("-u")); + } else if (0 == strncmp(argv[i], "--user=", strlen("--user="))) { + arguments->user = (char *)(argv[i++] + strlen("--user=")); + } else if (strlen("--user") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--user"); + exit(EXIT_FAILURE); + } + arguments->user = argv[++i]; + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->user = argv[++i]; - } else if (strncmp(argv[i], "-p", 2) == 0) { - if (strlen(argv[i]) == 2) { + } else if ((0 == strncmp(argv[i], "-p", strlen("-p"))) + || (0 == strcmp(argv[i], "--password"))) { + if ((strlen(argv[i]) == 2) || (0 == strcmp(argv[i], "--password"))) { printf("Enter password: "); taosSetConsoleEcho(false); if (scanf("%s", arguments->password) > 1) { @@ -874,52 +1069,202 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { } else { tstrncpy(arguments->password, (char *)(argv[i] + 2), SHELL_MAX_PASSWORD_LEN); } - } else if (strcmp(argv[i], "-o") == 0) { - if (argc == i+1) { - printHelp(); - errorPrint("%s", "\n\t-o need a valid string following!\n"); + } else if ((0 == strncmp(argv[i], "-o", strlen("-o"))) + || (0 == strncmp(argv[i], "--output", strlen("--output")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--output"); + exit(EXIT_FAILURE); + } + arguments->output_file = argv[++i]; + } else if (0 == strncmp(argv[i], "--output=", strlen("--output="))) { + arguments->output_file = (char *)(argv[i++] + strlen("--output=")); + } else if (0 == strncmp(argv[i], "-o", strlen("-o"))) { + arguments->output_file = (char *)(argv[i++] + strlen("-o")); + } else if (strlen("--output") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--output"); + exit(EXIT_FAILURE); + } + arguments->output_file = argv[++i]; + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->output_file = argv[++i]; - } else if (strcmp(argv[i], "-s") == 0) { - if (argc == i+1) { - printHelp(); - errorPrint("%s", "\n\t-s need a valid string following!\n"); + } else if ((0 == strncmp(argv[i], "-s", strlen("-s"))) + || (0 == strncmp(argv[i], "--sql-file", strlen("--sql-file")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "s"); + exit(EXIT_FAILURE); + } + arguments->sqlFile = argv[++i]; + } else if (0 == strncmp(argv[i], "--sql-file=", strlen("--sql-file="))) { + arguments->sqlFile = (char *)(argv[i++] + strlen("--sql-file=")); + } else if (0 == strncmp(argv[i], "-s", strlen("-s"))) { + arguments->sqlFile = (char *)(argv[i++] + strlen("-s")); + } else if (strlen("--sql-file") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--sql-file"); + exit(EXIT_FAILURE); + } + arguments->sqlFile = argv[++i]; + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->sqlFile = argv[++i]; - } else if (strcmp(argv[i], "-q") == 0) { - if ((argc == i+1) - || (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-q need a number following!\nQuery mode -- 0: SYNC, not-0: ASYNC. Default is SYNC.\n"); + } else if ((0 == strncmp(argv[i], "-q", strlen("-q"))) + || (0 == strncmp(argv[i], "--query-mode", strlen("--query-mode")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "q"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "q"); + exit(EXIT_FAILURE); + } + arguments->async_mode = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--query-mode=", strlen("--query-mode="))) { + if (isStringNumber((char *)(argv[i] + strlen("--query-mode=")))) { + arguments->async_mode = atoi((char *)(argv[i]+strlen("--query-mode="))); + } else { + errorPrintReqArg2(argv[0], "--query-mode"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-q", strlen("-q"))) { + if (isStringNumber((char *)(argv[i] + strlen("-q")))) { + arguments->async_mode = atoi((char *)(argv[i]+strlen("-q"))); + } else { + errorPrintReqArg2(argv[0], "-q"); + exit(EXIT_FAILURE); + } + } else if (strlen("--query-mode") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--query-mode"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--query-mode"); + exit(EXIT_FAILURE); + } + arguments->async_mode = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->async_mode = atoi(argv[++i]); - } else if (strcmp(argv[i], "-T") == 0) { - if ((argc == i+1) - || (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-T need a number following!\n"); + } else if ((0 == strncmp(argv[i], "-T", strlen("-T"))) + || (0 == strncmp(argv[i], "--threads", strlen("--threads")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "T"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "T"); + exit(EXIT_FAILURE); + } + arguments->num_of_threads = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--threads=", strlen("--threads="))) { + if (isStringNumber((char *)(argv[i] + strlen("--threads=")))) { + arguments->num_of_threads = atoi((char *)(argv[i]+strlen("--threads="))); + } else { + errorPrintReqArg2(argv[0], "--threads"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-T", strlen("-T"))) { + if (isStringNumber((char *)(argv[i] + strlen("-T")))) { + arguments->num_of_threads = atoi((char *)(argv[i]+strlen("-T"))); + } else { + errorPrintReqArg2(argv[0], "-T"); + exit(EXIT_FAILURE); + } + } else if (strlen("--threads") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--threads"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--threads"); + exit(EXIT_FAILURE); + } + arguments->num_of_threads = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->num_of_threads = atoi(argv[++i]); - } else if (strcmp(argv[i], "-i") == 0) { - if ((argc == i+1) || - (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-i need a number following!\n"); + } else if ((0 == strncmp(argv[i], "-i", strlen("-i"))) + || (0 == strncmp(argv[i], "--insert-interval", strlen("--insert-interval")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "i"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "i"); + exit(EXIT_FAILURE); + } + arguments->insert_interval = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--insert-interval=", strlen("--insert-interval="))) { + if (isStringNumber((char *)(argv[i] + strlen("--insert-interval=")))) { + arguments->insert_interval = atoi((char *)(argv[i]+strlen("--insert-interval="))); + } else { + errorPrintReqArg3(argv[0], "--insert-innterval"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-i", strlen("-i"))) { + if (isStringNumber((char *)(argv[i] + strlen("-i")))) { + arguments->insert_interval = atoi((char *)(argv[i]+strlen("-i"))); + } else { + errorPrintReqArg3(argv[0], "-i"); + exit(EXIT_FAILURE); + } + } else if (strlen("--insert-interval")== strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--insert-interval"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--insert-interval"); + exit(EXIT_FAILURE); + } + arguments->insert_interval = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->insert_interval = atoi(argv[++i]); - } else if (strcmp(argv[i], "-S") == 0) { - if ((argc == i+1) || - (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("\n\t%s%s", argv[i], " need a number following!\n"); + } else if ((0 == strncmp(argv[i], "-S", strlen("-S"))) + || (0 == strncmp(argv[i], "--time-step", strlen("--time-step")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "S"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "S"); + exit(EXIT_FAILURE); + } + arguments->async_mode = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--time-step=", strlen("--time-step="))) { + if (isStringNumber((char *)(argv[i] + strlen("--time-step=")))) { + arguments->async_mode = atoi((char *)(argv[i]+strlen("--time-step="))); + } else { + errorPrintReqArg2(argv[0], "--time-step"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-S", strlen("-S"))) { + if (isStringNumber((char *)(argv[i] + strlen("-S")))) { + arguments->async_mode = atoi((char *)(argv[i]+strlen("-S"))); + } else { + errorPrintReqArg2(argv[0], "-S"); + exit(EXIT_FAILURE); + } + } else if (strlen("--time-step") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--time-step"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--time-step"); + exit(EXIT_FAILURE); + } + arguments->async_mode = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->timestamp_step = atoi(argv[++i]); } else if (strcmp(argv[i], "-qt") == 0) { if ((argc == i+1) || (!isStringNumber(argv[i+1]))) { @@ -928,55 +1273,221 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { exit(EXIT_FAILURE); } arguments->query_times = atoi(argv[++i]); - } else if (strcmp(argv[i], "-B") == 0) { - if ((argc == i+1) - || (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-B need a number following!\n"); + } else if ((0 == strncmp(argv[i], "-B", strlen("-B"))) + || (0 == strncmp(argv[i], "--interlace-rows", strlen("--interlace-rows")))) { + if (strlen("-B") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "B"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "B"); + exit(EXIT_FAILURE); + } + arguments->interlace_rows = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--interlace-rows=", strlen("--interlace-rows="))) { + if (isStringNumber((char *)(argv[i] + strlen("--interlace-rows=")))) { + arguments->interlace_rows = atoi((char *)(argv[i]+strlen("--interlace-rows="))); + } else { + errorPrintReqArg2(argv[0], "--interlace-rows"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-B", strlen("-B"))) { + if (isStringNumber((char *)(argv[i] + strlen("-B")))) { + arguments->interlace_rows = atoi((char *)(argv[i]+strlen("-B"))); + } else { + errorPrintReqArg2(argv[0], "-B"); + exit(EXIT_FAILURE); + } + } else if (strlen("--interlace-rows")== strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--interlace-rows"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--interlace-rows"); + exit(EXIT_FAILURE); + } + arguments->interlace_rows = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->interlace_rows = atoi(argv[++i]); - } else if (strcmp(argv[i], "-r") == 0) { - if ((argc == i+1) - || (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-r need a number following!\n"); + } else if ((0 == strncmp(argv[i], "-r", strlen("-r"))) + || (0 == strncmp(argv[i], "--rec-per-req", 13))) { + if (strlen("-r") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "r"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "r"); + exit(EXIT_FAILURE); + } + arguments->num_of_RPR = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--rec-per-req=", strlen("--rec-per-req="))) { + if (isStringNumber((char *)(argv[i] + strlen("--rec-per-req=")))) { + arguments->num_of_RPR = atoi((char *)(argv[i]+strlen("--rec-per-req="))); + } else { + errorPrintReqArg2(argv[0], "--rec-per-req"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-r", strlen("-r"))) { + if (isStringNumber((char *)(argv[i] + strlen("-r")))) { + arguments->num_of_RPR = atoi((char *)(argv[i]+strlen("-r"))); + } else { + errorPrintReqArg2(argv[0], "-r"); + exit(EXIT_FAILURE); + } + } else if (strlen("--rec-per-req")== strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--rec-per-req"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--rec-per-req"); + exit(EXIT_FAILURE); + } + arguments->num_of_RPR = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->num_of_RPR = atoi(argv[++i]); - } else if (strcmp(argv[i], "-t") == 0) { - if ((argc == i+1) || - (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-t need a number following!\n"); + } else if ((0 == strncmp(argv[i], "-t", strlen("-t"))) + || (0 == strncmp(argv[i], "--tables", strlen("--tables")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "t"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "t"); + exit(EXIT_FAILURE); + } + arguments->num_of_tables = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--tables=", strlen("--tables="))) { + if (isStringNumber((char *)(argv[i] + strlen("--tables=")))) { + arguments->num_of_tables = atoi((char *)(argv[i]+strlen("--tables="))); + } else { + errorPrintReqArg2(argv[0], "--tables"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-t", strlen("-t"))) { + if (isStringNumber((char *)(argv[i] + strlen("-t")))) { + arguments->num_of_tables = atoi((char *)(argv[i]+strlen("-t"))); + } else { + errorPrintReqArg2(argv[0], "-t"); + exit(EXIT_FAILURE); + } + } else if (strlen("--tables") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--tables"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--tables"); + exit(EXIT_FAILURE); + } + arguments->num_of_tables = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->num_of_tables = atoi(argv[++i]); - } else if (strcmp(argv[i], "-n") == 0) { - if ((argc == i+1) || - (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-n need a number following!\n"); + + g_totalChildTables = arguments->num_of_tables; + } else if ((0 == strncmp(argv[i], "-n", strlen("-n"))) + || (0 == strncmp(argv[i], "--records", strlen("--records")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "n"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "n"); + exit(EXIT_FAILURE); + } + arguments->num_of_DPT = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--records=", strlen("--records="))) { + if (isStringNumber((char *)(argv[i] + strlen("--records=")))) { + arguments->num_of_DPT = atoi((char *)(argv[i]+strlen("--records="))); + } else { + errorPrintReqArg2(argv[0], "--records"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-n", strlen("-n"))) { + if (isStringNumber((char *)(argv[i] + strlen("-n")))) { + arguments->num_of_DPT = atoi((char *)(argv[i]+strlen("-n"))); + } else { + errorPrintReqArg2(argv[0], "-n"); + exit(EXIT_FAILURE); + } + } else if (strlen("--records") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--records"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--records"); + exit(EXIT_FAILURE); + } + arguments->num_of_DPT = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->num_of_DPT = atoi(argv[++i]); - } else if (strcmp(argv[i], "-d") == 0) { - if (argc == i+1) { - printHelp(); - errorPrint("%s", "\n\t-d need a valid string following!\n"); + } else if ((0 == strncmp(argv[i], "-d", strlen("-d"))) + || (0 == strncmp(argv[i], "--database", strlen("--database")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "d"); + exit(EXIT_FAILURE); + } + arguments->database = argv[++i]; + } else if (0 == strncmp(argv[i], "--database=", strlen("--database="))) { + arguments->output_file = (char *)(argv[i] + strlen("--database=")); + } else if (0 == strncmp(argv[i], "-d", strlen("-d"))) { + arguments->output_file = (char *)(argv[i] + strlen("-d")); + } else if (strlen("--database") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--database"); + exit(EXIT_FAILURE); + } + arguments->database = argv[++i]; + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->database = argv[++i]; - } else if (strcmp(argv[i], "-l") == 0) { + } else if ((0 == strncmp(argv[i], "-l", strlen("-l"))) + || (0 == strncmp(argv[i], "--columns", strlen("--columns")))) { arguments->demo_mode = false; - if (argc == i+1) { - if (!isStringNumber(argv[i+1])) { - printHelp(); - errorPrint("%s", "\n\t-l need a number following!\n"); + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "l"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "l"); + exit(EXIT_FAILURE); + } + arguments->num_of_CPR = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--columns=", strlen("--columns="))) { + if (isStringNumber((char *)(argv[i] + strlen("--columns=")))) { + arguments->num_of_CPR = atoi((char *)(argv[i]+strlen("--columns="))); + } else { + errorPrintReqArg2(argv[0], "--columns"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-l", strlen("-l"))) { + if (isStringNumber((char *)(argv[i] + strlen("-l")))) { + arguments->num_of_CPR = atoi((char *)(argv[i]+strlen("-l"))); + } else { + errorPrintReqArg2(argv[0], "-l"); + exit(EXIT_FAILURE); + } + } else if (strlen("--columns")== strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--columns"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--columns"); exit(EXIT_FAILURE); } + arguments->num_of_CPR = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); + exit(EXIT_FAILURE); } - arguments->num_of_CPR = atoi(argv[++i]); if (arguments->num_of_CPR > MAX_NUM_COLUMNS) { printf("WARNING: max acceptible columns count is %d\n", MAX_NUM_COLUMNS); @@ -990,36 +1501,54 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { for (int col = arguments->num_of_CPR; col < MAX_NUM_COLUMNS; col++) { arguments->datatype[col] = NULL; } - } else if (strcmp(argv[i], "-b") == 0) { + } else if ((0 == strncmp(argv[i], "-b", strlen("-b"))) + || (0 == strncmp(argv[i], "--data-type", strlen("--data-type")))) { arguments->demo_mode = false; - if (argc == i+1) { - printHelp(); - errorPrint("%s", "\n\t-b need valid string following!\n"); + + char *dataType; + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "b"); + exit(EXIT_FAILURE); + } + dataType = argv[++i]; + } else if (0 == strncmp(argv[i], "--data-type=", strlen("--data-type="))) { + dataType = (char *)(argv[i] + strlen("--data-type=")); + } else if (0 == strncmp(argv[i], "-b", strlen("-b"))) { + dataType = (char *)(argv[i] + strlen("-b")); + } else if (strlen("--data-type") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--data-type"); + exit(EXIT_FAILURE); + } + dataType = argv[++i]; + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - ++i; - if (strstr(argv[i], ",") == NULL) { + + if (strstr(dataType, ",") == NULL) { // only one col - if (strcasecmp(argv[i], "INT") - && strcasecmp(argv[i], "FLOAT") - && strcasecmp(argv[i], "TINYINT") - && strcasecmp(argv[i], "BOOL") - && strcasecmp(argv[i], "SMALLINT") - && strcasecmp(argv[i], "BIGINT") - && strcasecmp(argv[i], "DOUBLE") - && strcasecmp(argv[i], "BINARY") - && strcasecmp(argv[i], "TIMESTAMP") - && strcasecmp(argv[i], "NCHAR")) { + if (strcasecmp(dataType, "INT") + && strcasecmp(dataType, "FLOAT") + && strcasecmp(dataType, "TINYINT") + && strcasecmp(dataType, "BOOL") + && strcasecmp(dataType, "SMALLINT") + && strcasecmp(dataType, "BIGINT") + && strcasecmp(dataType, "DOUBLE") + && strcasecmp(dataType, "BINARY") + && strcasecmp(dataType, "TIMESTAMP") + && strcasecmp(dataType, "NCHAR")) { printHelp(); errorPrint("%s", "-b: Invalid data_type!\n"); exit(EXIT_FAILURE); } - arguments->datatype[0] = argv[i]; + arguments->datatype[0] = dataType; arguments->datatype[1] = NULL; } else { // more than one col int index = 0; - g_dupstr = strdup(argv[i]); + g_dupstr = strdup(dataType); char *running = g_dupstr; char *token = strsep(&running, ","); while(token != NULL) { @@ -1044,75 +1573,227 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { } arguments->datatype[index] = NULL; } - } else if (strcmp(argv[i], "-w") == 0) { - if ((argc == i+1) || - (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-w need a number following!\n"); + } else if ((0 == strncmp(argv[i], "-w", strlen("-w"))) + || (0 == strncmp(argv[i], "--binwidth", strlen("--binwidth")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "w"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "w"); + exit(EXIT_FAILURE); + } + arguments->binwidth = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--binwidth=", strlen("--binwidth="))) { + if (isStringNumber((char *)(argv[i] + strlen("--binwidth=")))) { + arguments->binwidth = atoi((char *)(argv[i]+strlen("--binwidth="))); + } else { + errorPrintReqArg2(argv[0], "--binwidth"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-w", strlen("-w"))) { + if (isStringNumber((char *)(argv[i] + strlen("-w")))) { + arguments->binwidth = atoi((char *)(argv[i]+strlen("-w"))); + } else { + errorPrintReqArg2(argv[0], "-w"); + exit(EXIT_FAILURE); + } + } else if (strlen("--binwidth") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--binwidth"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--binwidth"); + exit(EXIT_FAILURE); + } + arguments->binwidth = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->len_of_binary = atoi(argv[++i]); - } else if (strcmp(argv[i], "-m") == 0) { - if ((argc == i+1) || - (isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-m need a letter-initial string following!\n"); + } else if ((0 == strncmp(argv[i], "-m", strlen("-m"))) + || (0 == strncmp(argv[i], "--table-prefix", strlen("--table-prefix")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "m"); + exit(EXIT_FAILURE); + } + arguments->tb_prefix = argv[++i]; + } else if (0 == strncmp(argv[i], "--table-prefix=", strlen("--table-prefix="))) { + arguments->tb_prefix = (char *)(argv[i] + strlen("--table-prefix=")); + } else if (0 == strncmp(argv[i], "-m", strlen("-m"))) { + arguments->tb_prefix = (char *)(argv[i] + strlen("-m")); + } else if (strlen("--table-prefix") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--table-prefix"); + exit(EXIT_FAILURE); + } + arguments->tb_prefix = argv[++i]; + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->tb_prefix = argv[++i]; - } else if (strcmp(argv[i], "-N") == 0) { + } else if ((strcmp(argv[i], "-N") == 0) + || (0 == strcmp(argv[i], "--normal-table"))) { arguments->use_metric = false; - } else if (strcmp(argv[i], "-M") == 0) { + } else if ((strcmp(argv[i], "-M") == 0) + || (0 == strcmp(argv[i], "--random"))) { arguments->demo_mode = false; - } else if (strcmp(argv[i], "-x") == 0) { + } else if ((strcmp(argv[i], "-x") == 0) + || (0 == strcmp(argv[i], "--no-insert"))) { arguments->insert_only = false; - } else if (strcmp(argv[i], "-y") == 0) { + } else if ((strcmp(argv[i], "-y") == 0) + || (0 == strcmp(argv[i], "--answer-yes"))) { arguments->answer_yes = true; - } else if (strcmp(argv[i], "-g") == 0) { + } else if ((strcmp(argv[i], "-g") == 0) + || (0 == strcmp(argv[i], "--debug"))) { arguments->debug_print = true; } else if (strcmp(argv[i], "-gg") == 0) { arguments->verbose_print = true; - } else if (strcmp(argv[i], "-PP") == 0) { - arguments->performance_print = true; - } else if (strcmp(argv[i], "-O") == 0) { - if ((argc == i+1) || - (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-O need a number following!\n"); + } else if ((0 == strncmp(argv[i], "-R", strlen("-R"))) + || (0 == strncmp(argv[i], "--disorder-range", + strlen("--disorder-range")))) { + if (strlen("-R") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "R"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "R"); + exit(EXIT_FAILURE); + } + arguments->disorderRange = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--disorder-range=", + strlen("--disorder-range="))) { + if (isStringNumber((char *)(argv[i] + strlen("--disorder-range=")))) { + arguments->disorderRange = + atoi((char *)(argv[i]+strlen("--disorder-range="))); + } else { + errorPrintReqArg2(argv[0], "--disorder-range"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-R", strlen("-R"))) { + if (isStringNumber((char *)(argv[i] + strlen("-R")))) { + arguments->disorderRange = + atoi((char *)(argv[i]+strlen("-R"))); + } else { + errorPrintReqArg2(argv[0], "-R"); + exit(EXIT_FAILURE); + } + + if (arguments->disorderRange < 0) { + errorPrint("Invalid disorder range %d, will be set to %d\n", + arguments->disorderRange, 1000); + arguments->disorderRange = 1000; + } + } else if (strlen("--disorder-range") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--disorder-range"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--disorder-range"); + exit(EXIT_FAILURE); + } + arguments->disorderRange = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); + exit(EXIT_FAILURE); + } + } else if ((0 == strncmp(argv[i], "-O", strlen("-O"))) + || (0 == strncmp(argv[i], "--disorder", strlen("--disorder")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "O"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "O"); + exit(EXIT_FAILURE); + } + arguments->disorderRatio = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--disorder=", strlen("--disorder="))) { + if (isStringNumber((char *)(argv[i] + strlen("--disorder=")))) { + arguments->disorderRatio = atoi((char *)(argv[i]+strlen("--disorder="))); + } else { + errorPrintReqArg2(argv[0], "--disorder"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-O", strlen("-O"))) { + if (isStringNumber((char *)(argv[i] + strlen("-O")))) { + arguments->disorderRatio = atoi((char *)(argv[i]+strlen("-O"))); + } else { + errorPrintReqArg2(argv[0], "-O"); + exit(EXIT_FAILURE); + } + } else if (strlen("--disorder") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--disorder"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--disorder"); + exit(EXIT_FAILURE); + } + arguments->disorderRatio = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - - arguments->disorderRatio = atoi(argv[++i]); if (arguments->disorderRatio > 50) { + errorPrint("Invalid disorder ratio %d, will be set to %d\n", + arguments->disorderRatio, 50); arguments->disorderRatio = 50; } if (arguments->disorderRatio < 0) { + errorPrint("Invalid disorder ratio %d, will be set to %d\n", + arguments->disorderRatio, 0); arguments->disorderRatio = 0; } - - } else if (strcmp(argv[i], "-R") == 0) { - if ((argc == i+1) || - (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-R need a number following!\n"); + } else if ((0 == strncmp(argv[i], "-a", strlen("-a"))) + || (0 == strncmp(argv[i], "--replica", + strlen("--replica")))) { + if (2 == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg(argv[0], "a"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "a"); + exit(EXIT_FAILURE); + } + arguments->replica = atoi(argv[++i]); + } else if (0 == strncmp(argv[i], "--replica=", + strlen("--replica="))) { + if (isStringNumber((char *)(argv[i] + strlen("--replica=")))) { + arguments->replica = + atoi((char *)(argv[i]+strlen("--replica="))); + } else { + errorPrintReqArg2(argv[0], "--replica"); + exit(EXIT_FAILURE); + } + } else if (0 == strncmp(argv[i], "-a", strlen("-a"))) { + if (isStringNumber((char *)(argv[i] + strlen("-a")))) { + arguments->replica = + atoi((char *)(argv[i]+strlen("-a"))); + } else { + errorPrintReqArg2(argv[0], "-a"); + exit(EXIT_FAILURE); + } + } else if (strlen("--replica") == strlen(argv[i])) { + if (argc == i+1) { + errorPrintReqArg3(argv[0], "--replica"); + exit(EXIT_FAILURE); + } else if (!isStringNumber(argv[i+1])) { + errorPrintReqArg2(argv[0], "--replica"); + exit(EXIT_FAILURE); + } + arguments->replica = atoi(argv[++i]); + } else { + errorUnreconized(argv[0], argv[i]); exit(EXIT_FAILURE); } - arguments->disorderRange = atoi(argv[++i]); - if (arguments->disorderRange < 0) - arguments->disorderRange = 1000; - - } else if (strcmp(argv[i], "-a") == 0) { - if ((argc == i+1) || - (!isStringNumber(argv[i+1]))) { - printHelp(); - errorPrint("%s", "\n\t-a need a number following!\n"); - exit(EXIT_FAILURE); - } - arguments->replica = atoi(argv[++i]); if (arguments->replica > 3 || arguments->replica < 1) { + errorPrint("Invalid replica value %d, will be set to %d\n", + arguments->replica, 1); arguments->replica = 1; } } else if (strcmp(argv[i], "-D") == 0) { @@ -1121,16 +1802,40 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { errorPrint("%s", "\n\t-D need a valud (0~3) number following!\n"); exit(EXIT_FAILURE); } - } else if ((strcmp(argv[i], "--version") == 0) || - (strcmp(argv[i], "-V") == 0)){ + } else if ((strcmp(argv[i], "--version") == 0) + || (strcmp(argv[i], "-V") == 0)) { printVersion(); exit(0); - } else if (strcmp(argv[i], "--help") == 0) { + } else if ((strcmp(argv[i], "--help") == 0) + || (strcmp(argv[i], "-?") == 0)) { printHelp(); exit(0); + } else if (strcmp(argv[i], "--usage") == 0) { + printf(" Usage: taosdemo [-f JSONFILE] [-u USER] [-p PASSWORD] [-c CONFIG_DIR]\n\ + [-h HOST] [-P PORT] [-I INTERFACE] [-d DATABASE] [-a REPLICA]\n\ + [-m TABLEPREFIX] [-s SQLFILE] [-N] [-o OUTPUTFILE] [-q QUERYMODE]\n\ + [-b DATATYPES] [-w WIDTH_OF_BINARY] [-l COLUNNS] [-T THREADNUMBER]\n\ + [-i SLEEPTIME] [-S TIME_STEP] [-B INTERLACE_ROWS] [-t TABLES]\n\ + [-n RECORDS] [-M] [-x] [-y] [-O ORDERMODE] [-R RANGE] [-a REPLIcA][-g]\n\ + [--help] [--usage] [--version]\n"); + exit(0); } else { - printHelp(); - errorPrint("%s", "ERROR: wrong options\n"); + // to simulate argp_option output + if (strlen(argv[i]) > 2) { + if (0 == strncmp(argv[i], "--", 2)) { + fprintf(stderr, "%s: unrecognized options '%s'\n", argv[0], argv[i]); + } else if (0 == strncmp(argv[i], "-", 1)) { + char tmp[2] = {0}; + tstrncpy(tmp, argv[i]+1, 2); + fprintf(stderr, "%s: invalid options -- '%s'\n", argv[0], tmp); + } else { + fprintf(stderr, "%s: Too many arguments\n", argv[0]); + } + } else { + fprintf(stderr, "%s invalid options -- '%s'\n", argv[0], + (char *)((char *)argv[i])+1); + } + fprintf(stderr, "Try `taosdemo --help' or `taosdemo --usage' for more information.\n"); exit(EXIT_FAILURE); } } @@ -1147,7 +1852,7 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { } g_args.num_of_CPR = columnCount; - if (((arguments->debug_print) && (arguments->metaFile == NULL)) + if (((arguments->debug_print) && (NULL != arguments->metaFile)) || arguments->verbose_print) { printf("###################################################################\n"); printf("# meta file: %s\n", arguments->metaFile); @@ -1160,9 +1865,9 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { arguments->use_metric ? "true" : "false"); if (*(arguments->datatype)) { printf("# Specified data type: "); - for (int i = 0; i < MAX_NUM_COLUMNS; i++) - if (arguments->datatype[i]) - printf("%s,", arguments->datatype[i]); + for (int c = 0; c < MAX_NUM_COLUMNS; c++) + if (arguments->datatype[c]) + printf("%s,", arguments->datatype[c]); else break; printf("\n"); @@ -1173,7 +1878,7 @@ static void parse_args(int argc, char *argv[], SArguments *arguments) { arguments->num_of_RPR); printf("# Max SQL length: %"PRIu64"\n", arguments->max_sql_len); - printf("# Length of Binary: %d\n", arguments->len_of_binary); + printf("# Length of Binary: %d\n", arguments->binwidth); printf("# Number of Threads: %d\n", arguments->num_of_threads); printf("# Number of Tables: %"PRId64"\n", arguments->num_of_tables); @@ -1228,7 +1933,7 @@ static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) { verbosePrint("%s() LN%d - command: %s\n", __func__, __LINE__, command); if (code != 0) { if (!quiet) { - errorPrint("Failed to execute %s, reason: %s\n", + errorPrint2("Failed to execute %s, reason: %s\n", command, taos_errstr(res)); } taos_free_result(res); @@ -1250,7 +1955,7 @@ static void appendResultBufToFile(char *resultBuf, threadInfo *pThreadInfo) { pThreadInfo->fp = fopen(pThreadInfo->filePath, "at"); if (pThreadInfo->fp == NULL) { - errorPrint( + errorPrint2( "%s() LN%d, failed to open result file: %s, result will not save to file\n", __func__, __LINE__, pThreadInfo->filePath); return; @@ -1269,7 +1974,7 @@ static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) { char* databuf = (char*) calloc(1, 100*1024*1024); if (databuf == NULL) { - errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n", + errorPrint2("%s() LN%d, failed to malloc, warning: save result to file slowly!\n", __func__, __LINE__); return ; } @@ -1309,7 +2014,7 @@ static void selectAndGetResult( if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", strlen("taosc"))) { TAOS_RES *res = taos_query(pThreadInfo->taos, command); if (res == NULL || taos_errno(res) != 0) { - errorPrint("%s() LN%d, failed to execute sql:%s, reason:%s\n", + errorPrint2("%s() LN%d, failed to execute sql:%s, reason:%s\n", __func__, __LINE__, command, taos_errstr(res)); taos_free_result(res); return; @@ -1328,19 +2033,19 @@ static void selectAndGetResult( } } else { - errorPrint("%s() LN%d, unknown query mode: %s\n", + errorPrint2("%s() LN%d, unknown query mode: %s\n", __func__, __LINE__, g_queryInfo.queryMode); } } -static char *rand_bool_str(){ +static char *rand_bool_str() { static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; - return g_randbool_buff + (cursor * BOOL_BUFF_LEN); + return g_randbool_buff + ((cursor % MAX_PREPARED_RAND) * BOOL_BUFF_LEN); } -static int32_t rand_bool(){ +static int32_t rand_bool() { static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; @@ -1352,7 +2057,8 @@ static char *rand_tinyint_str() static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; - return g_randtinyint_buff + (cursor * TINYINT_BUFF_LEN); + return g_randtinyint_buff + + ((cursor % MAX_PREPARED_RAND) * TINYINT_BUFF_LEN); } static int32_t rand_tinyint() @@ -1368,7 +2074,8 @@ static char *rand_smallint_str() static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; - return g_randsmallint_buff + (cursor * SMALLINT_BUFF_LEN); + return g_randsmallint_buff + + ((cursor % MAX_PREPARED_RAND) * SMALLINT_BUFF_LEN); } static int32_t rand_smallint() @@ -1384,7 +2091,7 @@ static char *rand_int_str() static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; - return g_randint_buff + (cursor * INT_BUFF_LEN); + return g_randint_buff + ((cursor % MAX_PREPARED_RAND) * INT_BUFF_LEN); } static int32_t rand_int() @@ -1400,7 +2107,8 @@ static char *rand_bigint_str() static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; - return g_randbigint_buff + (cursor * BIGINT_BUFF_LEN); + return g_randbigint_buff + + ((cursor % MAX_PREPARED_RAND) * BIGINT_BUFF_LEN); } static int64_t rand_bigint() @@ -1416,7 +2124,7 @@ static char *rand_float_str() static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; - return g_randfloat_buff + (cursor * FLOAT_BUFF_LEN); + return g_randfloat_buff + ((cursor % MAX_PREPARED_RAND) * FLOAT_BUFF_LEN); } @@ -1433,7 +2141,8 @@ static char *demo_current_float_str() static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; - return g_rand_current_buff + (cursor * FLOAT_BUFF_LEN); + return g_rand_current_buff + + ((cursor % MAX_PREPARED_RAND) * FLOAT_BUFF_LEN); } static float UNUSED_FUNC demo_current_float() @@ -1450,7 +2159,8 @@ static char *demo_voltage_int_str() static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; - return g_rand_voltage_buff + (cursor * INT_BUFF_LEN); + return g_rand_voltage_buff + + ((cursor % MAX_PREPARED_RAND) * INT_BUFF_LEN); } static int32_t UNUSED_FUNC demo_voltage_int() @@ -1465,10 +2175,10 @@ static char *demo_phase_float_str() { static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; - return g_rand_phase_buff + (cursor * FLOAT_BUFF_LEN); + return g_rand_phase_buff + ((cursor % MAX_PREPARED_RAND) * FLOAT_BUFF_LEN); } -static float UNUSED_FUNC demo_phase_float(){ +static float UNUSED_FUNC demo_phase_float() { static int cursor; cursor++; if (cursor > (MAX_PREPARED_RAND - 1)) cursor = 0; @@ -1547,7 +2257,7 @@ static void init_rand_data() { g_randdouble_buff = calloc(1, DOUBLE_BUFF_LEN * MAX_PREPARED_RAND); assert(g_randdouble_buff); - for (int i = 0; i < MAX_PREPARED_RAND; i++){ + for (int i = 0; i < MAX_PREPARED_RAND; i++) { g_randint[i] = (int)(taosRandom() % 65535); sprintf(g_randint_buff + i * INT_BUFF_LEN, "%d", g_randint[i]); @@ -1624,7 +2334,7 @@ static int printfInsertMeta() { printf("resultFile: \033[33m%s\033[0m\n", g_Dbs.resultFile); printf("thread num of insert data: \033[33m%d\033[0m\n", g_Dbs.threadCount); printf("thread num of create table: \033[33m%d\033[0m\n", - g_Dbs.threadCountByCreateTbl); + g_Dbs.threadCountForCreateTbl); printf("top insert interval: \033[33m%"PRIu64"\033[0m\n", g_args.insert_interval); printf("number of records per req: \033[33m%u\033[0m\n", @@ -1693,9 +2403,7 @@ static int printfInsertMeta() { } if (g_Dbs.db[i].dbCfg.precision[0] != 0) { if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2)) -#if NANO_SECOND_ENABLED == 1 || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2)) -#endif || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ns", 2))) { printf(" precision: \033[33m%s\033[0m\n", g_Dbs.db[i].dbCfg.precision); @@ -1834,7 +2542,7 @@ static void printfInsertMetaToFile(FILE* fp) { fprintf(fp, "configDir: %s\n", configDir); fprintf(fp, "resultFile: %s\n", g_Dbs.resultFile); fprintf(fp, "thread num of insert data: %d\n", g_Dbs.threadCount); - fprintf(fp, "thread num of create table: %d\n", g_Dbs.threadCountByCreateTbl); + fprintf(fp, "thread num of create table: %d\n", g_Dbs.threadCountForCreateTbl); fprintf(fp, "number of records per req: %u\n", g_args.num_of_RPR); fprintf(fp, "max sql length: %"PRIu64"\n", g_args.max_sql_len); fprintf(fp, "database count: %d\n", g_Dbs.dbCount); @@ -1886,9 +2594,7 @@ static void printfInsertMetaToFile(FILE* fp) { } if (g_Dbs.db[i].dbCfg.precision[0] != 0) { if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2)) -#if NANO_SECOND_ENABLED == 1 || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ns", 2)) -#endif || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) { fprintf(fp, " precision: %s\n", g_Dbs.db[i].dbCfg.precision); @@ -2091,10 +2797,8 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) { time_t tt; if (precision == TSDB_TIME_PRECISION_MICRO) { tt = (time_t)(val / 1000000); -#if NANO_SECOND_ENABLED == 1 } if (precision == TSDB_TIME_PRECISION_NANO) { tt = (time_t)(val / 1000000000); -#endif } else { tt = (time_t)(val / 1000); } @@ -2116,10 +2820,8 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) { if (precision == TSDB_TIME_PRECISION_MICRO) { sprintf(buf + pos, ".%06d", (int)(val % 1000000)); -#if NANO_SECOND_ENABLED == 1 } else if (precision == TSDB_TIME_PRECISION_NANO) { sprintf(buf + pos, ".%09d", (int)(val % 1000000000)); -#endif } else { sprintf(buf + pos, ".%03d", (int)(val % 1000)); } @@ -2150,7 +2852,7 @@ static void xDumpFieldToFile(FILE* fp, const char* val, fprintf(fp, "%d", *((int32_t *)val)); break; case TSDB_DATA_TYPE_BIGINT: - fprintf(fp, "%" PRId64, *((int64_t *)val)); + fprintf(fp, "%"PRId64"", *((int64_t *)val)); break; case TSDB_DATA_TYPE_FLOAT: fprintf(fp, "%.5f", GET_FLOAT_VAL(val)); @@ -2181,7 +2883,7 @@ static int xDumpResultToFile(const char* fname, TAOS_RES* tres) { FILE* fp = fopen(fname, "at"); if (fp == NULL) { - errorPrint("%s() LN%d, failed to open file: %s\n", + errorPrint2("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname); return -1; } @@ -2228,7 +2930,7 @@ static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { int32_t code = taos_errno(res); if (code != 0) { - errorPrint( "failed to run , reason: %s\n", + errorPrint2("failed to run , reason: %s\n", taos_errstr(res)); return -1; } @@ -2244,7 +2946,7 @@ static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) { dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo)); if (dbInfos[count] == NULL) { - errorPrint( "failed to allocate memory for some dbInfo[%d]\n", count); + errorPrint2("failed to allocate memory for some dbInfo[%d]\n", count); return -1; } @@ -2397,7 +3099,7 @@ static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port request_buf = malloc(req_buf_len); if (NULL == request_buf) { - errorPrint("%s", "ERROR, cannot allocate memory.\n"); + errorPrint("%s", "cannot allocate memory.\n"); exit(EXIT_FAILURE); } @@ -2536,7 +3238,7 @@ static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) { char* dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1); if (NULL == dataBuf) { - errorPrint("%s() LN%d, calloc failed! size:%d\n", + errorPrint2("%s() LN%d, calloc failed! size:%d\n", __func__, __LINE__, TSDB_MAX_SQL_LEN+1); return NULL; } @@ -2636,7 +3338,7 @@ static char* generateTagValuesForStb(SSuperTable* stbInfo, int64_t tableSeq) { dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "%"PRId64",", rand_bigint()); } else { - errorPrint("No support data type: %s\n", stbInfo->tags[i].dataType); + errorPrint2("No support data type: %s\n", stbInfo->tags[i].dataType); tmfree(dataBuf); return NULL; } @@ -2675,7 +3377,7 @@ static int calcRowLen(SSuperTable* superTbls) { } else if (strcasecmp(dataType, "TIMESTAMP") == 0) { lenOfOneRow += TIMESTAMP_BUFF_LEN; } else { - errorPrint("get error data type : %s\n", dataType); + errorPrint2("get error data type : %s\n", dataType); exit(EXIT_FAILURE); } } @@ -2706,7 +3408,7 @@ static int calcRowLen(SSuperTable* superTbls) { } else if (strcasecmp(dataType, "DOUBLE") == 0) { lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + DOUBLE_BUFF_LEN; } else { - errorPrint("get error tag type : %s\n", dataType); + errorPrint2("get error tag type : %s\n", dataType); exit(EXIT_FAILURE); } } @@ -2743,7 +3445,7 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, if (code != 0) { taos_free_result(res); taos_close(taos); - errorPrint("%s() LN%d, failed to run command %s\n", + errorPrint2("%s() LN%d, failed to run command %s\n", __func__, __LINE__, command); exit(EXIT_FAILURE); } @@ -2755,7 +3457,7 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, if (NULL == childTblName) { taos_free_result(res); taos_close(taos); - errorPrint("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__); + errorPrint2("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__); exit(EXIT_FAILURE); } } @@ -2765,7 +3467,7 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, int32_t* len = taos_fetch_lengths(res); if (0 == strlen((char *)row[0])) { - errorPrint("%s() LN%d, No.%"PRId64" table return empty name\n", + errorPrint2("%s() LN%d, No.%"PRId64" table return empty name\n", __func__, __LINE__, count); exit(EXIT_FAILURE); } @@ -2786,7 +3488,7 @@ static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos, tmfree(childTblName); taos_free_result(res); taos_close(taos); - errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n", + errorPrint2("%s() LN%d, realloc fail for save child table name of %s.%s\n", __func__, __LINE__, dbName, sTblName); exit(EXIT_FAILURE); } @@ -2883,7 +3585,7 @@ static int getSuperTableFromServer(TAOS * taos, char* dbName, int childTblCount = 10000; superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN); if (superTbls->childTblName == NULL) { - errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__); + errorPrint2("%s() LN%d, alloc memory failed!\n", __func__, __LINE__); return -1; } getAllChildNameOfSuperTable(taos, dbName, @@ -2909,7 +3611,7 @@ static int createSuperTable( int lenOfOneRow = 0; if (superTbl->columnCount == 0) { - errorPrint("%s() LN%d, super table column count is %d\n", + errorPrint2("%s() LN%d, super table column count is %d\n", __func__, __LINE__, superTbl->columnCount); free(command); return -1; @@ -2973,7 +3675,7 @@ static int createSuperTable( } else { taos_close(taos); free(command); - errorPrint("%s() LN%d, config error data type : %s\n", + errorPrint2("%s() LN%d, config error data type : %s\n", __func__, __LINE__, dataType); exit(EXIT_FAILURE); } @@ -2986,7 +3688,7 @@ static int createSuperTable( if (NULL == superTbl->colsOfCreateChildTable) { taos_close(taos); free(command); - errorPrint("%s() LN%d, Failed when calloc, size:%d", + errorPrint2("%s() LN%d, Failed when calloc, size:%d", __func__, __LINE__, len+1); exit(EXIT_FAILURE); } @@ -2996,7 +3698,7 @@ static int createSuperTable( __func__, __LINE__, superTbl->colsOfCreateChildTable); if (superTbl->tagCount == 0) { - errorPrint("%s() LN%d, super table tag count is %d\n", + errorPrint2("%s() LN%d, super table tag count is %d\n", __func__, __LINE__, superTbl->tagCount); free(command); return -1; @@ -3063,7 +3765,7 @@ static int createSuperTable( } else { taos_close(taos); free(command); - errorPrint("%s() LN%d, config error tag type : %s\n", + errorPrint2("%s() LN%d, config error tag type : %s\n", __func__, __LINE__, dataType); exit(EXIT_FAILURE); } @@ -3078,7 +3780,7 @@ static int createSuperTable( "create table if not exists %s.%s (ts timestamp%s) tags %s", dbName, superTbl->sTblName, cols, tags); if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) { - errorPrint( "create supertable %s failed!\n\n", + errorPrint2("create supertable %s failed!\n\n", superTbl->sTblName); free(command); return -1; @@ -3094,7 +3796,7 @@ int createDatabasesAndStables(char *command) { int ret = 0; taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, NULL, g_Dbs.port); if (taos == NULL) { - errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); + errorPrint2("Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); return -1; } @@ -3180,10 +3882,8 @@ int createDatabasesAndStables(char *command) { " fsync %d", g_Dbs.db[i].dbCfg.fsync); } if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2)) -#if NANO_SECOND_ENABLED == 1 || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ns", 2)) -#endif || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) { dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen, @@ -3192,7 +3892,7 @@ int createDatabasesAndStables(char *command) { if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) { taos_close(taos); - errorPrint( "\ncreate database %s failed!\n\n", + errorPrint("\ncreate database %s failed!\n\n", g_Dbs.db[i].dbName); return -1; } @@ -3222,7 +3922,7 @@ int createDatabasesAndStables(char *command) { ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName, &g_Dbs.db[i].superTbls[j]); if (0 != ret) { - errorPrint("\nget super table %s.%s info failed!\n\n", + errorPrint2("\nget super table %s.%s info failed!\n\n", g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName); continue; } @@ -3250,7 +3950,7 @@ static void* createTable(void *sarg) pThreadInfo->buffer = calloc(buff_len, 1); if (pThreadInfo->buffer == NULL) { - errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__); + errorPrint2("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__); exit(EXIT_FAILURE); } @@ -3269,10 +3969,11 @@ static void* createTable(void *sarg) pThreadInfo->db_name, g_args.tb_prefix, i, pThreadInfo->cols); + batchNum ++; } else { if (stbInfo == NULL) { free(pThreadInfo->buffer); - errorPrint("%s() LN%d, use metric, but super table info is NULL\n", + errorPrint2("%s() LN%d, use metric, but super table info is NULL\n", __func__, __LINE__); exit(EXIT_FAILURE); } else { @@ -3317,14 +4018,16 @@ static void* createTable(void *sarg) } len = 0; + if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer, - NO_INSERT_TYPE, false)){ - errorPrint( "queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer); + NO_INSERT_TYPE, false)) { + errorPrint2("queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer); free(pThreadInfo->buffer); return NULL; } + pThreadInfo->tables_created += batchNum; - uint64_t currentPrintTime = taosGetTimestampMs(); + uint64_t currentPrintTime = taosGetTimestampMs(); if (currentPrintTime - lastPrintTime > 30*1000) { printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n", pThreadInfo->threadID, pThreadInfo->start_table_from, i); @@ -3335,7 +4038,7 @@ static void* createTable(void *sarg) if (0 != len) { if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer, NO_INSERT_TYPE, false)) { - errorPrint( "queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer); + errorPrint2("queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer); } } @@ -3380,7 +4083,7 @@ static int startMultiThreadCreateChildTable( db_name, g_Dbs.port); if (pThreadInfo->taos == NULL) { - errorPrint( "%s() LN%d, Failed to connect to TDengine, reason:%s\n", + errorPrint2("%s() LN%d, Failed to connect to TDengine, reason:%s\n", __func__, __LINE__, taos_errstr(NULL)); free(pids); free(infos); @@ -3394,6 +4097,7 @@ static int startMultiThreadCreateChildTable( pThreadInfo->use_metric = true; pThreadInfo->cols = cols; pThreadInfo->minDelay = UINT64_MAX; + pThreadInfo->tables_created = 0; pthread_create(pids + i, NULL, createTable, pThreadInfo); } @@ -3404,6 +4108,8 @@ static int startMultiThreadCreateChildTable( for (int i = 0; i < threads; i++) { threadInfo *pThreadInfo = infos + i; taos_close(pThreadInfo->taos); + + g_actualChildTables += pThreadInfo->tables_created; } free(pids); @@ -3430,14 +4136,13 @@ static void createChildTables() { verbosePrint("%s() LN%d: %s\n", __func__, __LINE__, g_Dbs.db[i].superTbls[j].colsOfCreateChildTable); uint64_t startFrom = 0; - g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount; verbosePrint("%s() LN%d: create %"PRId64" child tables from %"PRIu64"\n", __func__, __LINE__, g_totalChildTables, startFrom); startMultiThreadCreateChildTable( g_Dbs.db[i].superTbls[j].colsOfCreateChildTable, - g_Dbs.threadCountByCreateTbl, + g_Dbs.threadCountForCreateTbl, startFrom, g_Dbs.db[i].superTbls[j].childTblCount, g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j])); @@ -3451,7 +4156,7 @@ static void createChildTables() { || (strncasecmp(g_args.datatype[j], "NCHAR", strlen("NCHAR")) == 0)) { snprintf(tblColsBuf + len, TSDB_MAX_BYTES_PER_ROW - len, - ",C%d %s(%d)", j, g_args.datatype[j], g_args.len_of_binary); + ",C%d %s(%d)", j, g_args.datatype[j], g_args.binwidth); } else { snprintf(tblColsBuf + len, TSDB_MAX_BYTES_PER_ROW - len, ",C%d %s", j, g_args.datatype[j]); @@ -3466,7 +4171,7 @@ static void createChildTables() { g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf); startMultiThreadCreateChildTable( tblColsBuf, - g_Dbs.threadCountByCreateTbl, + g_Dbs.threadCountForCreateTbl, 0, g_args.num_of_tables, g_Dbs.db[i].dbName, @@ -3555,7 +4260,7 @@ static int readSampleFromCsvFileToMem( FILE* fp = fopen(stbInfo->sampleFile, "r"); if (fp == NULL) { - errorPrint( "Failed to open sample file: %s, reason:%s\n", + errorPrint("Failed to open sample file: %s, reason:%s\n", stbInfo->sampleFile, strerror(errno)); return -1; } @@ -3567,7 +4272,7 @@ static int readSampleFromCsvFileToMem( readLen = tgetline(&line, &n, fp); if (-1 == readLen) { if(0 != fseek(fp, 0, SEEK_SET)) { - errorPrint( "Failed to fseek file: %s, reason:%s\n", + errorPrint("Failed to fseek file: %s, reason:%s\n", stbInfo->sampleFile, strerror(errno)); fclose(fp); return -1; @@ -3610,7 +4315,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( // columns cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns"); if (columns && columns->type != cJSON_Array) { - printf("ERROR: failed to read json, columns not found\n"); + errorPrint("%s", "failed to read json, columns not found\n"); goto PARSE_OVER; } else if (NULL == columns) { superTbls->columnCount = 0; @@ -3620,8 +4325,8 @@ static bool getColumnAndTagTypeFromInsertJsonFile( int columnSize = cJSON_GetArraySize(columns); if ((columnSize + 1/* ts */) > TSDB_MAX_COLUMNS) { - errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n", - __func__, __LINE__, TSDB_MAX_COLUMNS); + errorPrint("failed to read json, column size overflow, max column size is %d\n", + TSDB_MAX_COLUMNS); goto PARSE_OVER; } @@ -3639,8 +4344,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( if (countObj && countObj->type == cJSON_Number) { count = countObj->valueint; } else if (countObj && countObj->type != cJSON_Number) { - errorPrint("%s() LN%d, failed to read json, column count not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, column count not found\n"); goto PARSE_OVER; } else { count = 1; @@ -3651,8 +4355,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( cJSON *dataType = cJSON_GetObjectItem(column, "type"); if (!dataType || dataType->type != cJSON_String || dataType->valuestring == NULL) { - errorPrint("%s() LN%d: failed to read json, column type not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, column type not found\n"); goto PARSE_OVER; } //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, DATATYPE_BUFF_LEN); @@ -3680,8 +4383,8 @@ static bool getColumnAndTagTypeFromInsertJsonFile( } if ((index + 1 /* ts */) > MAX_NUM_COLUMNS) { - errorPrint("%s() LN%d, failed to read json, column size overflow, allowed max column size is %d\n", - __func__, __LINE__, MAX_NUM_COLUMNS); + errorPrint("failed to read json, column size overflow, allowed max column size is %d\n", + MAX_NUM_COLUMNS); goto PARSE_OVER; } @@ -3692,15 +4395,14 @@ static bool getColumnAndTagTypeFromInsertJsonFile( // tags cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags"); if (!tags || tags->type != cJSON_Array) { - errorPrint("%s() LN%d, failed to read json, tags not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, tags not found\n"); goto PARSE_OVER; } int tagSize = cJSON_GetArraySize(tags); if (tagSize > TSDB_MAX_TAGS) { - errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n", - __func__, __LINE__, TSDB_MAX_TAGS); + errorPrint("failed to read json, tags size overflow, max tag size is %d\n", + TSDB_MAX_TAGS); goto PARSE_OVER; } @@ -3714,7 +4416,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( if (countObj && countObj->type == cJSON_Number) { count = countObj->valueint; } else if (countObj && countObj->type != cJSON_Number) { - printf("ERROR: failed to read json, column count not found\n"); + errorPrint("%s", "failed to read json, column count not found\n"); goto PARSE_OVER; } else { count = 1; @@ -3725,8 +4427,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( cJSON *dataType = cJSON_GetObjectItem(tag, "type"); if (!dataType || dataType->type != cJSON_String || dataType->valuestring == NULL) { - errorPrint("%s() LN%d, failed to read json, tag type not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, tag type not found\n"); goto PARSE_OVER; } tstrncpy(columnCase.dataType, dataType->valuestring, @@ -3736,8 +4437,7 @@ static bool getColumnAndTagTypeFromInsertJsonFile( if (dataLen && dataLen->type == cJSON_Number) { columnCase.dataLen = dataLen->valueint; } else if (dataLen && dataLen->type != cJSON_Number) { - errorPrint("%s() LN%d, failed to read json, column len not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, column len not found\n"); goto PARSE_OVER; } else { columnCase.dataLen = 0; @@ -3752,16 +4452,16 @@ static bool getColumnAndTagTypeFromInsertJsonFile( } if (index > TSDB_MAX_TAGS) { - errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n", - __func__, __LINE__, TSDB_MAX_TAGS); + errorPrint("failed to read json, tags size overflow, allowed max tag count is %d\n", + TSDB_MAX_TAGS); goto PARSE_OVER; } superTbls->tagCount = index; if ((superTbls->columnCount + superTbls->tagCount + 1 /* ts */) > TSDB_MAX_COLUMNS) { - errorPrint("%s() LN%d, columns + tags is more than allowed max columns count: %d\n", - __func__, __LINE__, TSDB_MAX_COLUMNS); + errorPrint("columns + tags is more than allowed max columns count: %d\n", + TSDB_MAX_COLUMNS); goto PARSE_OVER; } ret = true; @@ -3784,7 +4484,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!host) { tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE); } else { - printf("ERROR: failed to read json, host not found\n"); + errorPrint("%s", "failed to read json, host not found\n"); goto PARSE_OVER; } @@ -3822,42 +4522,38 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!threads) { g_Dbs.threadCount = 1; } else { - printf("ERROR: failed to read json, threads not found\n"); + errorPrint("%s", "failed to read json, threads not found\n"); goto PARSE_OVER; } cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl"); if (threads2 && threads2->type == cJSON_Number) { - g_Dbs.threadCountByCreateTbl = threads2->valueint; + g_Dbs.threadCountForCreateTbl = threads2->valueint; } else if (!threads2) { - g_Dbs.threadCountByCreateTbl = 1; + g_Dbs.threadCountForCreateTbl = 1; } else { - errorPrint("%s() LN%d, failed to read json, threads2 not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, threads2 not found\n"); goto PARSE_OVER; } cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval"); if (gInsertInterval && gInsertInterval->type == cJSON_Number) { if (gInsertInterval->valueint <0) { - errorPrint("%s() LN%d, failed to read json, insert interval input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, insert interval input mistake\n"); goto PARSE_OVER; } g_args.insert_interval = gInsertInterval->valueint; } else if (!gInsertInterval) { g_args.insert_interval = 0; } else { - errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, insert_interval input mistake\n"); goto PARSE_OVER; } cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows"); if (interlaceRows && interlaceRows->type == cJSON_Number) { if (interlaceRows->valueint < 0) { - errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, interlace_rows input mistake\n"); goto PARSE_OVER; } @@ -3865,8 +4561,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!interlaceRows) { g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req } else { - errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, interlace_rows input mistake\n"); goto PARSE_OVER; } @@ -3939,14 +4634,14 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON* dbs = cJSON_GetObjectItem(root, "databases"); if (!dbs || dbs->type != cJSON_Array) { - printf("ERROR: failed to read json, databases not found\n"); + errorPrint("%s", "failed to read json, databases not found\n"); goto PARSE_OVER; } int dbSize = cJSON_GetArraySize(dbs); if (dbSize > MAX_DB_COUNT) { errorPrint( - "ERROR: failed to read json, databases size overflow, max database is %d\n", + "failed to read json, databases size overflow, max database is %d\n", MAX_DB_COUNT); goto PARSE_OVER; } @@ -3959,13 +4654,13 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { // dbinfo cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo"); if (!dbinfo || dbinfo->type != cJSON_Object) { - printf("ERROR: failed to read json, dbinfo not found\n"); + errorPrint("%s", "failed to read json, dbinfo not found\n"); goto PARSE_OVER; } cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name"); if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) { - printf("ERROR: failed to read json, db name not found\n"); + errorPrint("%s", "failed to read json, db name not found\n"); goto PARSE_OVER; } tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, TSDB_DB_NAME_LEN); @@ -3980,8 +4675,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!drop) { g_Dbs.db[i].drop = g_args.drop_database; } else { - errorPrint("%s() LN%d, failed to read json, drop input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, drop input mistake\n"); goto PARSE_OVER; } @@ -3993,7 +4687,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!precision) { memset(g_Dbs.db[i].dbCfg.precision, 0, SMALL_BUFF_LEN); } else { - printf("ERROR: failed to read json, precision not found\n"); + errorPrint("%s", "failed to read json, precision not found\n"); goto PARSE_OVER; } @@ -4003,7 +4697,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!update) { g_Dbs.db[i].dbCfg.update = -1; } else { - printf("ERROR: failed to read json, update not found\n"); + errorPrint("%s", "failed to read json, update not found\n"); goto PARSE_OVER; } @@ -4013,7 +4707,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!replica) { g_Dbs.db[i].dbCfg.replica = -1; } else { - printf("ERROR: failed to read json, replica not found\n"); + errorPrint("%s", "failed to read json, replica not found\n"); goto PARSE_OVER; } @@ -4023,7 +4717,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!keep) { g_Dbs.db[i].dbCfg.keep = -1; } else { - printf("ERROR: failed to read json, keep not found\n"); + errorPrint("%s", "failed to read json, keep not found\n"); goto PARSE_OVER; } @@ -4033,7 +4727,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!days) { g_Dbs.db[i].dbCfg.days = -1; } else { - printf("ERROR: failed to read json, days not found\n"); + errorPrint("%s", "failed to read json, days not found\n"); goto PARSE_OVER; } @@ -4043,7 +4737,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!cache) { g_Dbs.db[i].dbCfg.cache = -1; } else { - printf("ERROR: failed to read json, cache not found\n"); + errorPrint("%s", "failed to read json, cache not found\n"); goto PARSE_OVER; } @@ -4053,7 +4747,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!blocks) { g_Dbs.db[i].dbCfg.blocks = -1; } else { - printf("ERROR: failed to read json, block not found\n"); + errorPrint("%s", "failed to read json, block not found\n"); goto PARSE_OVER; } @@ -4073,7 +4767,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!minRows) { g_Dbs.db[i].dbCfg.minRows = 0; // 0 means default } else { - printf("ERROR: failed to read json, minRows not found\n"); + errorPrint("%s", "failed to read json, minRows not found\n"); goto PARSE_OVER; } @@ -4083,7 +4777,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!maxRows) { g_Dbs.db[i].dbCfg.maxRows = 0; // 0 means default } else { - printf("ERROR: failed to read json, maxRows not found\n"); + errorPrint("%s", "failed to read json, maxRows not found\n"); goto PARSE_OVER; } @@ -4093,7 +4787,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!comp) { g_Dbs.db[i].dbCfg.comp = -1; } else { - printf("ERROR: failed to read json, comp not found\n"); + errorPrint("%s", "failed to read json, comp not found\n"); goto PARSE_OVER; } @@ -4103,7 +4797,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!walLevel) { g_Dbs.db[i].dbCfg.walLevel = -1; } else { - printf("ERROR: failed to read json, walLevel not found\n"); + errorPrint("%s", "failed to read json, walLevel not found\n"); goto PARSE_OVER; } @@ -4113,7 +4807,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!cacheLast) { g_Dbs.db[i].dbCfg.cacheLast = -1; } else { - printf("ERROR: failed to read json, cacheLast not found\n"); + errorPrint("%s", "failed to read json, cacheLast not found\n"); goto PARSE_OVER; } @@ -4133,24 +4827,22 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!fsync) { g_Dbs.db[i].dbCfg.fsync = -1; } else { - errorPrint("%s() LN%d, failed to read json, fsync input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, fsync input mistake\n"); goto PARSE_OVER; } // super_talbes cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables"); if (!stables || stables->type != cJSON_Array) { - errorPrint("%s() LN%d, failed to read json, super_tables not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, super_tables not found\n"); goto PARSE_OVER; } int stbSize = cJSON_GetArraySize(stables); if (stbSize > MAX_SUPER_TABLE_COUNT) { errorPrint( - "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n", - __func__, __LINE__, MAX_SUPER_TABLE_COUNT); + "failed to read json, supertable size overflow, max supertable is %d\n", + MAX_SUPER_TABLE_COUNT); goto PARSE_OVER; } @@ -4163,8 +4855,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name"); if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) { - errorPrint("%s() LN%d, failed to read json, stb name not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, stb name not found\n"); goto PARSE_OVER; } tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, @@ -4172,7 +4863,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix"); if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) { - printf("ERROR: failed to read json, childtable_prefix not found\n"); + errorPrint("%s", "failed to read json, childtable_prefix not found\n"); goto PARSE_OVER; } tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, @@ -4193,7 +4884,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!autoCreateTbl) { g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL; } else { - printf("ERROR: failed to read json, auto_create_table not found\n"); + errorPrint("%s", "failed to read json, auto_create_table not found\n"); goto PARSE_OVER; } @@ -4201,9 +4892,9 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { if (batchCreateTbl && batchCreateTbl->type == cJSON_Number) { g_Dbs.db[i].superTbls[j].batchCreateTableNum = batchCreateTbl->valueint; } else if (!batchCreateTbl) { - g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000; + g_Dbs.db[i].superTbls[j].batchCreateTableNum = 10; } else { - printf("ERROR: failed to read json, batch_create_tbl_num not found\n"); + errorPrint("%s", "failed to read json, batch_create_tbl_num not found\n"); goto PARSE_OVER; } @@ -4223,8 +4914,8 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!childTblExists) { g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS; } else { - errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n", - __func__, __LINE__); + errorPrint("%s", + "failed to read json, child_table_exists not found\n"); goto PARSE_OVER; } @@ -4234,11 +4925,12 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count"); if (!count || count->type != cJSON_Number || 0 >= count->valueint) { - errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n", - __func__, __LINE__); + errorPrint("%s", + "failed to read json, childtable_count input mistake\n"); goto PARSE_OVER; } g_Dbs.db[i].superTbls[j].childTblCount = count->valueint; + g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount; cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source"); if (dataSource && dataSource->type == cJSON_String @@ -4250,8 +4942,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", min(SMALL_BUFF_LEN, strlen("rand") + 1)); } else { - errorPrint("%s() LN%d, failed to read json, data_source not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, data_source not found\n"); goto PARSE_OVER; } @@ -4262,13 +4953,11 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { g_Dbs.db[i].superTbls[j].iface= TAOSC_IFACE; } else if (0 == strcasecmp(stbIface->valuestring, "rest")) { g_Dbs.db[i].superTbls[j].iface= REST_IFACE; -#if STMT_IFACE_ENABLED == 1 } else if (0 == strcasecmp(stbIface->valuestring, "stmt")) { g_Dbs.db[i].superTbls[j].iface= STMT_IFACE; -#endif } else { - errorPrint("%s() LN%d, failed to read json, insert_mode %s not recognized\n", - __func__, __LINE__, stbIface->valuestring); + errorPrint("failed to read json, insert_mode %s not recognized\n", + stbIface->valuestring); goto PARSE_OVER; } } else if (!stbIface) { @@ -4282,7 +4971,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { if ((childTbl_limit) && (g_Dbs.db[i].drop != true) && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) { if (childTbl_limit->type != cJSON_Number) { - printf("ERROR: failed to read json, childtable_limit\n"); + errorPrint("%s", "failed to read json, childtable_limit\n"); goto PARSE_OVER; } g_Dbs.db[i].superTbls[j].childTblLimit = childTbl_limit->valueint; @@ -4295,7 +4984,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) { if ((childTbl_offset->type != cJSON_Number) || (0 > childTbl_offset->valueint)) { - printf("ERROR: failed to read json, childtable_offset\n"); + errorPrint("%s", "failed to read json, childtable_offset\n"); goto PARSE_OVER; } g_Dbs.db[i].superTbls[j].childTblOffset = childTbl_offset->valueint; @@ -4311,7 +5000,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp, "now", TSDB_DB_NAME_LEN); } else { - printf("ERROR: failed to read json, start_timestamp not found\n"); + errorPrint("%s", "failed to read json, start_timestamp not found\n"); goto PARSE_OVER; } @@ -4321,7 +5010,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!timestampStep) { g_Dbs.db[i].superTbls[j].timeStampStep = g_args.timestamp_step; } else { - printf("ERROR: failed to read json, timestamp_step not found\n"); + errorPrint("%s", "failed to read json, timestamp_step not found\n"); goto PARSE_OVER; } @@ -4336,7 +5025,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", SMALL_BUFF_LEN); } else { - printf("ERROR: failed to read json, sample_format not found\n"); + errorPrint("%s", "failed to read json, sample_format not found\n"); goto PARSE_OVER; } @@ -4351,7 +5040,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN); } else { - printf("ERROR: failed to read json, sample_file not found\n"); + errorPrint("%s", "failed to read json, sample_file not found\n"); goto PARSE_OVER; } @@ -4369,7 +5058,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { memset(g_Dbs.db[i].superTbls[j].tagsFile, 0, MAX_FILE_NAME_LEN); g_Dbs.db[i].superTbls[j].tagSource = 0; } else { - printf("ERROR: failed to read json, tags_file not found\n"); + errorPrint("%s", "failed to read json, tags_file not found\n"); goto PARSE_OVER; } @@ -4385,8 +5074,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!maxSqlLen) { g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len; } else { - errorPrint("%s() LN%d, failed to read json, stbMaxSqlLen input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, stbMaxSqlLen input mistake\n"); goto PARSE_OVER; } /* @@ -4403,31 +5091,28 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!multiThreadWriteOneTbl) { g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0; } else { - printf("ERROR: failed to read json, multiThreadWriteOneTbl not found\n"); + errorPrint("%s", "failed to read json, multiThreadWriteOneTbl not found\n"); goto PARSE_OVER; } */ cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows"); if (insertRows && insertRows->type == cJSON_Number) { if (insertRows->valueint < 0) { - errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, insert_rows input mistake\n"); goto PARSE_OVER; } g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint; } else if (!insertRows) { g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF; } else { - errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, insert_rows input mistake\n"); goto PARSE_OVER; } cJSON* stbInterlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows"); if (stbInterlaceRows && stbInterlaceRows->type == cJSON_Number) { if (stbInterlaceRows->valueint < 0) { - errorPrint("%s() LN%d, failed to read json, interlace rows input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, interlace rows input mistake\n"); goto PARSE_OVER; } g_Dbs.db[i].superTbls[j].interlaceRows = stbInterlaceRows->valueint; @@ -4445,8 +5130,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { g_Dbs.db[i].superTbls[j].interlaceRows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req } else { errorPrint( - "%s() LN%d, failed to read json, interlace rows input mistake\n", - __func__, __LINE__); + "%s", "failed to read json, interlace rows input mistake\n"); goto PARSE_OVER; } @@ -4462,7 +5146,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!disorderRatio) { g_Dbs.db[i].superTbls[j].disorderRatio = 0; } else { - printf("ERROR: failed to read json, disorderRatio not found\n"); + errorPrint("%s", "failed to read json, disorderRatio not found\n"); goto PARSE_OVER; } @@ -4472,7 +5156,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { } else if (!disorderRange) { g_Dbs.db[i].superTbls[j].disorderRange = 1000; } else { - printf("ERROR: failed to read json, disorderRange not found\n"); + errorPrint("%s", "failed to read json, disorderRange not found\n"); goto PARSE_OVER; } @@ -4480,8 +5164,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { if (insertInterval && insertInterval->type == cJSON_Number) { g_Dbs.db[i].superTbls[j].insertInterval = insertInterval->valueint; if (insertInterval->valueint < 0) { - errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, insert_interval input mistake\n"); goto PARSE_OVER; } } else if (!insertInterval) { @@ -4489,8 +5172,7 @@ static bool getMetaFromInsertJsonFile(cJSON* root) { __func__, __LINE__, g_args.insert_interval); g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval; } else { - errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, insert_interval input mistake\n"); goto PARSE_OVER; } @@ -4522,7 +5204,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } else if (!host) { tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE); } else { - printf("ERROR: failed to read json, host not found\n"); + errorPrint("%s", "failed to read json, host not found\n"); goto PARSE_OVER; } @@ -4560,23 +5242,21 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } else if (!answerPrompt) { g_args.answer_yes = false; } else { - printf("ERROR: failed to read json, confirm_parameter_prompt not found\n"); + errorPrint("%s", "failed to read json, confirm_parameter_prompt not found\n"); goto PARSE_OVER; } cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times"); if (gQueryTimes && gQueryTimes->type == cJSON_Number) { if (gQueryTimes->valueint <= 0) { - errorPrint("%s() LN%d, failed to read json, query_times input mistake\n", - __func__, __LINE__); + errorPrint("%s()", "failed to read json, query_times input mistake\n"); goto PARSE_OVER; } g_args.query_times = gQueryTimes->valueint; } else if (!gQueryTimes) { g_args.query_times = 1; } else { - errorPrint("%s() LN%d, failed to read json, query_times input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, query_times input mistake\n"); goto PARSE_OVER; } @@ -4584,7 +5264,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) { tstrncpy(g_queryInfo.dbName, dbs->valuestring, TSDB_DB_NAME_LEN); } else if (!dbs) { - printf("ERROR: failed to read json, databases not found\n"); + errorPrint("%s", "failed to read json, databases not found\n"); goto PARSE_OVER; } @@ -4598,7 +5278,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { tstrncpy(g_queryInfo.queryMode, "taosc", min(SMALL_BUFF_LEN, strlen("taosc") + 1)); } else { - printf("ERROR: failed to read json, query_mode not found\n"); + errorPrint("%s", "failed to read json, query_mode not found\n"); goto PARSE_OVER; } @@ -4608,7 +5288,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { g_queryInfo.specifiedQueryInfo.concurrent = 1; g_queryInfo.specifiedQueryInfo.sqlCount = 0; } else if (specifiedQuery->type != cJSON_Object) { - printf("ERROR: failed to read json, super_table_query not found\n"); + errorPrint("%s", "failed to read json, super_table_query not found\n"); goto PARSE_OVER; } else { cJSON* queryInterval = cJSON_GetObjectItem(specifiedQuery, "query_interval"); @@ -4623,8 +5303,8 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) { if (specifiedQueryTimes->valueint <= 0) { errorPrint( - "%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n", - __func__, __LINE__, specifiedQueryTimes->valueint); + "failed to read json, query_times: %"PRId64", need be a valid (>0) number\n", + specifiedQueryTimes->valueint); goto PARSE_OVER; } @@ -4641,8 +5321,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { if (concurrent && concurrent->type == cJSON_Number) { if (concurrent->valueint <= 0) { errorPrint( - "%s() LN%d, query sqlCount %d or concurrent %d is not correct.\n", - __func__, __LINE__, + "query sqlCount %d or concurrent %d is not correct.\n", g_queryInfo.specifiedQueryInfo.sqlCount, g_queryInfo.specifiedQueryInfo.concurrent); goto PARSE_OVER; @@ -4660,8 +5339,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } else if (0 == strcmp("async", specifiedAsyncMode->valuestring)) { g_queryInfo.specifiedQueryInfo.asyncMode = ASYNC_MODE; } else { - errorPrint("%s() LN%d, failed to read json, async mode input error\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, async mode input error\n"); goto PARSE_OVER; } } else { @@ -4684,7 +5362,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } else if (0 == strcmp("no", restart->valuestring)) { g_queryInfo.specifiedQueryInfo.subscribeRestart = false; } else { - printf("ERROR: failed to read json, subscribe restart error\n"); + errorPrint("%s", "failed to read json, subscribe restart error\n"); goto PARSE_OVER; } } else { @@ -4700,7 +5378,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } else if (0 == strcmp("no", keepProgress->valuestring)) { g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0; } else { - printf("ERROR: failed to read json, subscribe keepProgress error\n"); + errorPrint("%s", "failed to read json, subscribe keepProgress error\n"); goto PARSE_OVER; } } else { @@ -4712,15 +5390,13 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { if (!specifiedSqls) { g_queryInfo.specifiedQueryInfo.sqlCount = 0; } else if (specifiedSqls->type != cJSON_Array) { - errorPrint("%s() LN%d, failed to read json, super sqls not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, super sqls not found\n"); goto PARSE_OVER; } else { int superSqlSize = cJSON_GetArraySize(specifiedSqls); if (superSqlSize * g_queryInfo.specifiedQueryInfo.concurrent > MAX_QUERY_SQL_COUNT) { - errorPrint("%s() LN%d, failed to read json, query sql(%d) * concurrent(%d) overflow, max is %d\n", - __func__, __LINE__, + errorPrint("failed to read json, query sql(%d) * concurrent(%d) overflow, max is %d\n", superSqlSize, g_queryInfo.specifiedQueryInfo.concurrent, MAX_QUERY_SQL_COUNT); @@ -4734,7 +5410,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql"); if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) { - printf("ERROR: failed to read json, sql not found\n"); + errorPrint("%s", "failed to read json, sql not found\n"); goto PARSE_OVER; } tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j], @@ -4774,7 +5450,8 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { memset(g_queryInfo.specifiedQueryInfo.result[j], 0, MAX_FILE_NAME_LEN); } else { - printf("ERROR: failed to read json, super query result file not found\n"); + errorPrint("%s", + "failed to read json, super query result file not found\n"); goto PARSE_OVER; } } @@ -4787,7 +5464,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { g_queryInfo.superQueryInfo.threadCnt = 1; g_queryInfo.superQueryInfo.sqlCount = 0; } else if (superQuery->type != cJSON_Object) { - printf("ERROR: failed to read json, sub_table_query not found\n"); + errorPrint("%s", "failed to read json, sub_table_query not found\n"); ret = true; goto PARSE_OVER; } else { @@ -4801,24 +5478,22 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times"); if (superQueryTimes && superQueryTimes->type == cJSON_Number) { if (superQueryTimes->valueint <= 0) { - errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n", - __func__, __LINE__, superQueryTimes->valueint); + errorPrint("failed to read json, query_times: %"PRId64", need be a valid (>0) number\n", + superQueryTimes->valueint); goto PARSE_OVER; } g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint; } else if (!superQueryTimes) { g_queryInfo.superQueryInfo.queryTimes = g_args.query_times; } else { - errorPrint("%s() LN%d, failed to read json, query_times input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, query_times input mistake\n"); goto PARSE_OVER; } cJSON* threads = cJSON_GetObjectItem(superQuery, "threads"); if (threads && threads->type == cJSON_Number) { if (threads->valueint <= 0) { - errorPrint("%s() LN%d, failed to read json, threads input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, threads input mistake\n"); goto PARSE_OVER; } @@ -4840,8 +5515,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring, TSDB_TABLE_NAME_LEN); } else { - errorPrint("%s() LN%d, failed to read json, super table name input error\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, super table name input error\n"); goto PARSE_OVER; } @@ -4853,8 +5527,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } else if (0 == strcmp("async", superAsyncMode->valuestring)) { g_queryInfo.superQueryInfo.asyncMode = ASYNC_MODE; } else { - errorPrint("%s() LN%d, failed to read json, async mode input error\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, async mode input error\n"); goto PARSE_OVER; } } else { @@ -4864,8 +5537,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { cJSON* superInterval = cJSON_GetObjectItem(superQuery, "interval"); if (superInterval && superInterval->type == cJSON_Number) { if (superInterval->valueint < 0) { - errorPrint("%s() LN%d, failed to read json, interval input mistake\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, interval input mistake\n"); goto PARSE_OVER; } g_queryInfo.superQueryInfo.subscribeInterval = superInterval->valueint; @@ -4883,7 +5555,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } else if (0 == strcmp("no", subrestart->valuestring)) { g_queryInfo.superQueryInfo.subscribeRestart = false; } else { - printf("ERROR: failed to read json, subscribe restart error\n"); + errorPrint("%s", "failed to read json, subscribe restart error\n"); goto PARSE_OVER; } } else { @@ -4899,7 +5571,8 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { } else if (0 == strcmp("no", superkeepProgress->valuestring)) { g_queryInfo.superQueryInfo.subscribeKeepProgress = 0; } else { - printf("ERROR: failed to read json, subscribe super table keepProgress error\n"); + errorPrint("%s", + "failed to read json, subscribe super table keepProgress error\n"); goto PARSE_OVER; } } else { @@ -4936,14 +5609,13 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { if (!superSqls) { g_queryInfo.superQueryInfo.sqlCount = 0; } else if (superSqls->type != cJSON_Array) { - errorPrint("%s() LN%d: failed to read json, super sqls not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, super sqls not found\n"); goto PARSE_OVER; } else { int superSqlSize = cJSON_GetArraySize(superSqls); if (superSqlSize > MAX_QUERY_SQL_COUNT) { - errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n", - __func__, __LINE__, MAX_QUERY_SQL_COUNT); + errorPrint("failed to read json, query sql size overflow, max is %d\n", + MAX_QUERY_SQL_COUNT); goto PARSE_OVER; } @@ -4955,8 +5627,7 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql"); if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) { - errorPrint("%s() LN%d, failed to read json, sql not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, sql not found\n"); goto PARSE_OVER; } tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring, @@ -4964,14 +5635,13 @@ static bool getMetaFromQueryJsonFile(cJSON* root) { cJSON *result = cJSON_GetObjectItem(sql, "result"); if (result != NULL && result->type == cJSON_String - && result->valuestring != NULL){ + && result->valuestring != NULL) { tstrncpy(g_queryInfo.superQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN); } else if (NULL == result) { memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN); } else { - errorPrint("%s() LN%d, failed to read json, sub query result file not found\n", - __func__, __LINE__); + errorPrint("%s", "failed to read json, sub query result file not found\n"); goto PARSE_OVER; } } @@ -4989,7 +5659,7 @@ static bool getInfoFromJsonFile(char* file) { FILE *fp = fopen(file, "r"); if (!fp) { - printf("failed to read %s, reason:%s\n", file, strerror(errno)); + errorPrint("failed to read %s, reason:%s\n", file, strerror(errno)); return false; } @@ -5000,14 +5670,14 @@ static bool getInfoFromJsonFile(char* file) { if (len <= 0) { free(content); fclose(fp); - printf("failed to read %s, content is null", file); + errorPrint("failed to read %s, content is null", file); return false; } content[len] = 0; cJSON* root = cJSON_Parse(content); if (root == NULL) { - printf("ERROR: failed to cjson parse %s, invalid json format\n", file); + errorPrint("failed to cjson parse %s, invalid json format\n", file); goto PARSE_OVER; } @@ -5020,13 +5690,13 @@ static bool getInfoFromJsonFile(char* file) { } else if (0 == strcasecmp("subscribe", filetype->valuestring)) { g_args.test_mode = SUBSCRIBE_TEST; } else { - printf("ERROR: failed to read json, filetype not support\n"); + errorPrint("%s", "failed to read json, filetype not support\n"); goto PARSE_OVER; } } else if (!filetype) { g_args.test_mode = INSERT_TEST; } else { - printf("ERROR: failed to read json, filetype not found\n"); + errorPrint("%s", "failed to read json, filetype not found\n"); goto PARSE_OVER; } @@ -5036,8 +5706,8 @@ static bool getInfoFromJsonFile(char* file) { || (SUBSCRIBE_TEST == g_args.test_mode)) { ret = getMetaFromQueryJsonFile(root); } else { - errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n", - __func__, __LINE__); + errorPrint("%s", + "input json file type error! please input correct file type: insert or query or subscribe\n"); goto PARSE_OVER; } @@ -5074,22 +5744,6 @@ static void postFreeResource() { free(g_Dbs.db[i].superTbls[j].sampleDataBuf); g_Dbs.db[i].superTbls[j].sampleDataBuf = NULL; } -#if STMT_IFACE_ENABLED == 1 - if (g_Dbs.db[i].superTbls[j].sampleBindArray) { - for (int k = 0; k < MAX_SAMPLES_ONCE_FROM_FILE; k++) { - uintptr_t *tmp = (uintptr_t *)(*(uintptr_t *)( - g_Dbs.db[i].superTbls[j].sampleBindArray - + sizeof(uintptr_t *) * k)); - for (int c = 1; c < g_Dbs.db[i].superTbls[j].columnCount + 1; c++) { - TAOS_BIND *bind = (TAOS_BIND *)((char *)tmp + (sizeof(TAOS_BIND) * c)); - if (bind) - tmfree(bind->buffer); - } - tmfree((char *)tmp); - } - } - tmfree((char *)g_Dbs.db[i].superTbls[j].sampleBindArray); -#endif if (0 != g_Dbs.db[i].superTbls[j].tagDataBuf) { free(g_Dbs.db[i].superTbls[j].tagDataBuf); @@ -5157,7 +5811,7 @@ static int64_t generateStbRowData( || (0 == strncasecmp(stbInfo->columns[i].dataType, "NCHAR", 5))) { if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) { - errorPrint( "binary or nchar length overflow, max size:%u\n", + errorPrint2("binary or nchar length overflow, max size:%u\n", (uint32_t)TSDB_MAX_BINARY_LEN); return -1; } @@ -5169,7 +5823,7 @@ static int64_t generateStbRowData( } char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1); if (NULL == buf) { - errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen); + errorPrint2("calloc failed! size:%d\n", stbInfo->columns[i].dataLen); return -1; } rand_string(buf, stbInfo->columns[i].dataLen); @@ -5214,7 +5868,8 @@ static int64_t generateStbRowData( "SMALLINT", 8)) { tmp = rand_smallint_str(); tmpLen = strlen(tmp); - tstrncpy(pstr + dataLen, tmp, min(tmpLen + 1, SMALLINT_BUFF_LEN)); + tstrncpy(pstr + dataLen, tmp, + min(tmpLen + 1, SMALLINT_BUFF_LEN)); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "TINYINT", 7)) { tmp = rand_tinyint_str(); @@ -5227,11 +5882,12 @@ static int64_t generateStbRowData( tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, BOOL_BUFF_LEN)); } else if (0 == strncasecmp(stbInfo->columns[i].dataType, "TIMESTAMP", 9)) { - tmp = rand_int_str(); + tmp = rand_bigint_str(); tmpLen = strlen(tmp); - tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, INT_BUFF_LEN)); + tstrncpy(pstr + dataLen, tmp, min(tmpLen +1, BIGINT_BUFF_LEN)); } else { - errorPrint( "Not support data type: %s\n", stbInfo->columns[i].dataType); + errorPrint2("Not support data type: %s\n", + stbInfo->columns[i].dataType); return -1; } @@ -5244,8 +5900,7 @@ static int64_t generateStbRowData( return 0; } - dataLen -= 1; - dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")"); + tstrncpy(pstr + dataLen - 1, ")", 2); verbosePrint("%s() LN%d, dataLen:%"PRId64"\n", __func__, __LINE__, dataLen); verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf); @@ -5257,7 +5912,7 @@ static int64_t generateData(char *recBuf, char **data_type, int64_t timestamp, int lenOfBinary) { memset(recBuf, 0, MAX_DATA_SIZE); char *pstr = recBuf; - pstr += sprintf(pstr, "(%" PRId64, timestamp); + pstr += sprintf(pstr, "(%"PRId64"", timestamp); int columnCount = g_args.num_of_CPR; @@ -5269,9 +5924,9 @@ static int64_t generateData(char *recBuf, char **data_type, } else if (strcasecmp(data_type[i % columnCount], "INT") == 0) { pstr += sprintf(pstr, ",%d", rand_int()); } else if (strcasecmp(data_type[i % columnCount], "BIGINT") == 0) { - pstr += sprintf(pstr, ",%" PRId64, rand_bigint()); + pstr += sprintf(pstr, ",%"PRId64"", rand_bigint()); } else if (strcasecmp(data_type[i % columnCount], "TIMESTAMP") == 0) { - pstr += sprintf(pstr, ",%" PRId64, rand_bigint()); + pstr += sprintf(pstr, ",%"PRId64"", rand_bigint()); } else if (strcasecmp(data_type[i % columnCount], "FLOAT") == 0) { pstr += sprintf(pstr, ",%10.4f", rand_float()); } else if (strcasecmp(data_type[i % columnCount], "DOUBLE") == 0) { @@ -5283,7 +5938,7 @@ static int64_t generateData(char *recBuf, char **data_type, } else if (strcasecmp(data_type[i % columnCount], "BINARY") == 0) { char *s = malloc(lenOfBinary + 1); if (s == NULL) { - errorPrint("%s() LN%d, memory allocation %d bytes failed\n", + errorPrint2("%s() LN%d, memory allocation %d bytes failed\n", __func__, __LINE__, lenOfBinary + 1); exit(EXIT_FAILURE); } @@ -5293,7 +5948,7 @@ static int64_t generateData(char *recBuf, char **data_type, } else if (strcasecmp(data_type[i % columnCount], "NCHAR") == 0) { char *s = malloc(lenOfBinary + 1); if (s == NULL) { - errorPrint("%s() LN%d, memory allocation %d bytes failed\n", + errorPrint2("%s() LN%d, memory allocation %d bytes failed\n", __func__, __LINE__, lenOfBinary + 1); exit(EXIT_FAILURE); } @@ -5314,26 +5969,102 @@ static int64_t generateData(char *recBuf, char **data_type, return (int32_t)strlen(recBuf); } +static int generateSampleMemoryFromRand(SSuperTable *stbInfo) +{ + char data[MAX_DATA_SIZE]; + memset(data, 0, MAX_DATA_SIZE); + + char *buff = malloc(stbInfo->lenOfOneRow); + if (NULL == buff) { + errorPrint2("%s() LN%d, memory allocation %"PRId64" bytes failed\n", + __func__, __LINE__, stbInfo->lenOfOneRow); + exit(EXIT_FAILURE); + } + + for (int i=0; i < MAX_SAMPLES_ONCE_FROM_FILE; i++) { + uint64_t pos = 0; + memset(buff, 0, stbInfo->lenOfOneRow); + + for (int c = 0; c < stbInfo->columnCount; c++) { + char *tmp; + if (0 == strncasecmp(stbInfo->columns[c].dataType, + "BINARY", strlen("BINARY"))) { + rand_string(data, stbInfo->columns[c].dataLen); + pos += sprintf(buff + pos, "%s,", data); + } else if (0 == strncasecmp(stbInfo->columns[c].dataType, + "NCHAR", strlen("NCHAR"))) { + rand_string(data, stbInfo->columns[c].dataLen); + pos += sprintf(buff + pos, "%s,", data); + } else if (0 == strncasecmp(stbInfo->columns[c].dataType, + "INT", strlen("INT"))) { + if ((g_args.demo_mode) && (c == 1)) { + tmp = demo_voltage_int_str(); + } else { + tmp = rand_int_str(); + } + pos += sprintf(buff + pos, "%s,", tmp); + } else if (0 == strncasecmp(stbInfo->columns[c].dataType, + "BIGINT", strlen("BIGINT"))) { + pos += sprintf(buff + pos, "%s,", rand_bigint_str()); + } else if (0 == strncasecmp(stbInfo->columns[c].dataType, + "FLOAT", strlen("FLOAT"))) { + if (g_args.demo_mode) { + if (c == 0) { + tmp = demo_current_float_str(); + } else { + tmp = demo_phase_float_str(); + } + } else { + tmp = rand_float_str(); + } + pos += sprintf(buff + pos, "%s,", tmp); + } else if (0 == strncasecmp(stbInfo->columns[c].dataType, + "DOUBLE", strlen("DOUBLE"))) { + pos += sprintf(buff + pos, "%s,", rand_double_str()); + } else if (0 == strncasecmp(stbInfo->columns[c].dataType, + "SMALLINT", strlen("SMALLINT"))) { + pos += sprintf(buff + pos, "%s,", rand_smallint_str()); + } else if (0 == strncasecmp(stbInfo->columns[c].dataType, + "TINYINT", strlen("TINYINT"))) { + pos += sprintf(buff + pos, "%s,", rand_tinyint_str()); + } else if (0 == strncasecmp(stbInfo->columns[c].dataType, + "BOOL", strlen("BOOL"))) { + pos += sprintf(buff + pos, "%s,", rand_bool_str()); + } else if (0 == strncasecmp(stbInfo->columns[c].dataType, + "TIMESTAMP", strlen("TIMESTAMP"))) { + pos += sprintf(buff + pos, "%s,", rand_bigint_str()); + } + } + *(buff + pos - 1) = 0; + memcpy(stbInfo->sampleDataBuf + i * stbInfo->lenOfOneRow, buff, pos); + } + + free(buff); + return 0; +} + static int prepareSampleDataForSTable(SSuperTable *stbInfo) { - char* sampleDataBuf = NULL; - sampleDataBuf = calloc( + stbInfo->sampleDataBuf = calloc( stbInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1); - if (sampleDataBuf == NULL) { - errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n", + if (NULL == stbInfo->sampleDataBuf) { + errorPrint2("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n", __func__, __LINE__, stbInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, strerror(errno)); return -1; } - stbInfo->sampleDataBuf = sampleDataBuf; - int ret = readSampleFromCsvFileToMem(stbInfo); + int ret; + if (0 == strncasecmp(stbInfo->dataSource, "sample", strlen("sample"))) + ret = readSampleFromCsvFileToMem(stbInfo); + else + ret = generateSampleMemoryFromRand(stbInfo); if (0 != ret) { - errorPrint("%s() LN%d, read sample from csv file failed.\n", + errorPrint2("%s() LN%d, read sample from csv file failed.\n", __func__, __LINE__); - tmfree(sampleDataBuf); + tmfree(stbInfo->sampleDataBuf); stbInfo->sampleDataBuf = NULL; return -1; } @@ -5346,9 +6077,6 @@ static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k) int32_t affectedRows; SSuperTable* stbInfo = pThreadInfo->stbInfo; - verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID, - __func__, __LINE__, pThreadInfo->buffer); - uint16_t iface; if (stbInfo) iface = stbInfo->iface; @@ -5366,12 +6094,18 @@ static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k) switch(iface) { case TAOSC_IFACE: + verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID, + __func__, __LINE__, pThreadInfo->buffer); + affectedRows = queryDbExec( pThreadInfo->taos, pThreadInfo->buffer, INSERT_TYPE, false); break; case REST_IFACE: + verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID, + __func__, __LINE__, pThreadInfo->buffer); + if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port, pThreadInfo->buffer, pThreadInfo)) { affectedRows = -1; @@ -5382,12 +6116,11 @@ static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k) } break; -#if STMT_IFACE_ENABLED == 1 case STMT_IFACE: debugPrint("%s() LN%d, stmt=%p", __func__, __LINE__, pThreadInfo->stmt); if (0 != taos_stmt_execute(pThreadInfo->stmt)) { - errorPrint("%s() LN%d, failied to execute insert statement. reason: %s\n", + errorPrint2("%s() LN%d, failied to execute insert statement. reason: %s\n", __func__, __LINE__, taos_stmt_errstr(pThreadInfo->stmt)); fprintf(stderr, "\n\033[31m === Please reduce batch number if WAL size exceeds limit. ===\033[0m\n\n"); @@ -5395,10 +6128,9 @@ static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k) } affectedRows = k; break; -#endif default: - errorPrint("%s() LN%d: unknown insert mode: %d\n", + errorPrint2("%s() LN%d: unknown insert mode: %d\n", __func__, __LINE__, stbInfo->iface); affectedRows = 0; } @@ -5453,7 +6185,7 @@ static int32_t generateDataTailWithoutStb( int64_t retLen = 0; char **data_type = g_args.datatype; - int lenOfBinary = g_args.len_of_binary; + int lenOfBinary = g_args.binwidth; if (g_args.disorderRatio) { retLen = generateData(data, data_type, @@ -5626,7 +6358,7 @@ static int generateStbSQLHead( tableSeq % stbInfo->tagSampleCount); } if (NULL == tagsValBuf) { - errorPrint("%s() LN%d, tag buf failed to allocate memory\n", + errorPrint2("%s() LN%d, tag buf failed to allocate memory\n", __func__, __LINE__); return -1; } @@ -5768,7 +6500,6 @@ static int64_t generateInterlaceDataWithoutStb( return k; } -#if STMT_IFACE_ENABLED == 1 static int32_t prepareStmtBindArrayByType( TAOS_BIND *bind, char *dataType, int32_t dataLen, @@ -5778,7 +6509,7 @@ static int32_t prepareStmtBindArrayByType( if (0 == strncasecmp(dataType, "BINARY", strlen("BINARY"))) { if (dataLen > TSDB_MAX_BINARY_LEN) { - errorPrint( "binary length overflow, max size:%u\n", + errorPrint2("binary length overflow, max size:%u\n", (uint32_t)TSDB_MAX_BINARY_LEN); return -1; } @@ -5801,7 +6532,7 @@ static int32_t prepareStmtBindArrayByType( } else if (0 == strncasecmp(dataType, "NCHAR", strlen("NCHAR"))) { if (dataLen > TSDB_MAX_BINARY_LEN) { - errorPrint( "nchar length overflow, max size:%u\n", + errorPrint2("nchar length overflow, max size:%u\n", (uint32_t)TSDB_MAX_BINARY_LEN); return -1; } @@ -5949,7 +6680,7 @@ static int32_t prepareStmtBindArrayByType( value, &tmpEpoch, strlen(value), timePrec, 0)) { free(bind_ts2); - errorPrint("Input %s, time format error!\n", value); + errorPrint2("Input %s, time format error!\n", value); return -1; } *bind_ts2 = tmpEpoch; @@ -5965,7 +6696,7 @@ static int32_t prepareStmtBindArrayByType( bind->length = &bind->buffer_length; bind->is_null = NULL; } else { - errorPrint( "No support data type: %s\n", dataType); + errorPrint2("Not support data type: %s\n", dataType); return -1; } @@ -5982,7 +6713,7 @@ static int32_t prepareStmtBindArrayByTypeForRand( if (0 == strncasecmp(dataType, "BINARY", strlen("BINARY"))) { if (dataLen > TSDB_MAX_BINARY_LEN) { - errorPrint( "binary length overflow, max size:%u\n", + errorPrint2("binary length overflow, max size:%u\n", (uint32_t)TSDB_MAX_BINARY_LEN); return -1; } @@ -6005,7 +6736,7 @@ static int32_t prepareStmtBindArrayByTypeForRand( } else if (0 == strncasecmp(dataType, "NCHAR", strlen("NCHAR"))) { if (dataLen > TSDB_MAX_BINARY_LEN) { - errorPrint( "nchar length overflow, max size:%u\n", + errorPrint2("nchar length overflow, max size: %u\n", (uint32_t)TSDB_MAX_BINARY_LEN); return -1; } @@ -6157,7 +6888,7 @@ static int32_t prepareStmtBindArrayByTypeForRand( if (TSDB_CODE_SUCCESS != taosParseTime( value, &tmpEpoch, strlen(value), timePrec, 0)) { - errorPrint("Input %s, time format error!\n", value); + errorPrint2("Input %s, time format error!\n", value); return -1; } *bind_ts2 = tmpEpoch; @@ -6175,7 +6906,7 @@ static int32_t prepareStmtBindArrayByTypeForRand( *ptr += bind->buffer_length; } else { - errorPrint( "No support data type: %s\n", dataType); + errorPrint2("No support data type: %s\n", dataType); return -1; } @@ -6193,7 +6924,7 @@ static int32_t prepareStmtWithoutStb( TAOS_STMT *stmt = pThreadInfo->stmt; int ret = taos_stmt_set_tbname(stmt, tableName); if (ret != 0) { - errorPrint("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n", + errorPrint2("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n", tableName, ret, taos_stmt_errstr(stmt)); return ret; } @@ -6202,7 +6933,7 @@ static int32_t prepareStmtWithoutStb( char *bindArray = malloc(sizeof(TAOS_BIND) * (g_args.num_of_CPR + 1)); if (bindArray == NULL) { - errorPrint("Failed to allocate %d bind params\n", + errorPrint2("Failed to allocate %d bind params\n", (g_args.num_of_CPR + 1)); return -1; } @@ -6236,20 +6967,20 @@ static int32_t prepareStmtWithoutStb( if ( -1 == prepareStmtBindArrayByType( bind, data_type[i], - g_args.len_of_binary, + g_args.binwidth, pThreadInfo->time_precision, NULL)) { return -1; } } if (0 != taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray)) { - errorPrint("%s() LN%d, stmt_bind_param() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); break; } // if msg > 3MB, break if (0 != taos_stmt_add_batch(stmt)) { - errorPrint("%s() LN%d, stmt_add_batch() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); break; } @@ -6270,9 +7001,9 @@ static int32_t prepareStbStmtBindTag( char *tagsVal, int32_t timePrec) { - char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.len_of_binary); + char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.binwidth); if (bindBuffer == NULL) { - errorPrint("%s() LN%d, Failed to allocate %d bind buffer\n", + errorPrint2("%s() LN%d, Failed to allocate %d bind buffer\n", __func__, __LINE__, DOUBLE_BUFF_LEN); return -1; } @@ -6302,9 +7033,9 @@ static int32_t prepareStbStmtBindRand( int64_t startTime, int32_t recSeq, int32_t timePrec) { - char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.len_of_binary); + char *bindBuffer = calloc(1, DOUBLE_BUFF_LEN); // g_args.binwidth); if (bindBuffer == NULL) { - errorPrint("%s() LN%d, Failed to allocate %d bind buffer\n", + errorPrint2("%s() LN%d, Failed to allocate %d bind buffer\n", __func__, __LINE__, DOUBLE_BUFF_LEN); return -1; } @@ -6352,12 +7083,12 @@ static int32_t prepareStbStmtBindRand( return 0; } -static int32_t prepareStbStmtBindWithSample( +static int32_t prepareStbStmtBindStartTime( + char *tableName, int64_t *ts, char *bindArray, SSuperTable *stbInfo, int64_t startTime, int32_t recSeq, - int32_t timePrec, - int64_t samplePos) + int32_t timePrec) { TAOS_BIND *bind; @@ -6374,6 +7105,10 @@ static int32_t prepareStbStmtBindWithSample( } else { *bind_ts = startTime + stbInfo->timeStampStep * recSeq; } + + verbosePrint("%s() LN%d, tableName: %s, bind_ts=%"PRId64"\n", + __func__, __LINE__, tableName, *bind_ts); + bind->buffer_length = sizeof(int64_t); bind->buffer = bind_ts; bind->length = &bind->buffer_length; @@ -6382,7 +7117,7 @@ static int32_t prepareStbStmtBindWithSample( return 0; } -static int32_t prepareStbStmtRand( +UNUSED_FUNC static int32_t prepareStbStmtRand( threadInfo *pThreadInfo, char *tableName, int64_t tableSeq, @@ -6407,7 +7142,7 @@ static int32_t prepareStbStmtRand( } if (NULL == tagsValBuf) { - errorPrint("%s() LN%d, tag buf failed to allocate memory\n", + errorPrint2("%s() LN%d, tag buf failed to allocate memory\n", __func__, __LINE__); return -1; } @@ -6415,7 +7150,7 @@ static int32_t prepareStbStmtRand( char *tagsArray = calloc(1, sizeof(TAOS_BIND) * stbInfo->tagCount); if (NULL == tagsArray) { tmfree(tagsValBuf); - errorPrint("%s() LN%d, tag buf failed to allocate memory\n", + errorPrint2("%s() LN%d, tag buf failed to allocate memory\n", __func__, __LINE__); return -1; } @@ -6434,14 +7169,14 @@ static int32_t prepareStbStmtRand( tmfree(tagsArray); if (0 != ret) { - errorPrint("%s() LN%d, stmt_set_tbname_tags() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_set_tbname_tags() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); return -1; } } else { ret = taos_stmt_set_tbname(stmt, tableName); if (0 != ret) { - errorPrint("%s() LN%d, stmt_set_tbname() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_set_tbname() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); return -1; } @@ -6449,7 +7184,7 @@ static int32_t prepareStbStmtRand( char *bindArray = calloc(1, sizeof(TAOS_BIND) * (stbInfo->columnCount + 1)); if (bindArray == NULL) { - errorPrint("%s() LN%d, Failed to allocate %d bind params\n", + errorPrint2("%s() LN%d, Failed to allocate %d bind params\n", __func__, __LINE__, (stbInfo->columnCount + 1)); return -1; } @@ -6468,7 +7203,7 @@ static int32_t prepareStbStmtRand( } ret = taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray); if (0 != ret) { - errorPrint("%s() LN%d, stmt_bind_param() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); free(bindArray); return -1; @@ -6476,7 +7211,7 @@ static int32_t prepareStbStmtRand( // if msg > 3MB, break ret = taos_stmt_add_batch(stmt); if (0 != ret) { - errorPrint("%s() LN%d, stmt_add_batch() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); free(bindArray); return -1; @@ -6520,7 +7255,7 @@ static int32_t prepareStbStmtWithSample( } if (NULL == tagsValBuf) { - errorPrint("%s() LN%d, tag buf failed to allocate memory\n", + errorPrint2("%s() LN%d, tag buf failed to allocate memory\n", __func__, __LINE__); return -1; } @@ -6528,7 +7263,7 @@ static int32_t prepareStbStmtWithSample( char *tagsArray = calloc(1, sizeof(TAOS_BIND) * stbInfo->tagCount); if (NULL == tagsArray) { tmfree(tagsValBuf); - errorPrint("%s() LN%d, tag buf failed to allocate memory\n", + errorPrint2("%s() LN%d, tag buf failed to allocate memory\n", __func__, __LINE__); return -1; } @@ -6547,14 +7282,14 @@ static int32_t prepareStbStmtWithSample( tmfree(tagsArray); if (0 != ret) { - errorPrint("%s() LN%d, stmt_set_tbname_tags() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_set_tbname_tags() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); return -1; } } else { ret = taos_stmt_set_tbname(stmt, tableName); if (0 != ret) { - errorPrint("%s() LN%d, stmt_set_tbname() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_set_tbname() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); return -1; } @@ -6563,27 +7298,27 @@ static int32_t prepareStbStmtWithSample( uint32_t k; for (k = 0; k < batch;) { char *bindArray = (char *)(*((uintptr_t *) - (stbInfo->sampleBindArray + (sizeof(char *)) * (*pSamplePos)))); + (pThreadInfo->sampleBindArray + (sizeof(char *)) * (*pSamplePos)))); /* columnCount + 1 (ts) */ - if (-1 == prepareStbStmtBindWithSample( + if (-1 == prepareStbStmtBindStartTime( + tableName, pThreadInfo->bind_ts, bindArray, stbInfo, startTime, k, - pThreadInfo->time_precision, - *pSamplePos + pThreadInfo->time_precision /* is column */)) { return -1; } ret = taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray); if (0 != ret) { - errorPrint("%s() LN%d, stmt_bind_param() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_bind_param() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); return -1; } // if msg > 3MB, break ret = taos_stmt_add_batch(stmt); if (0 != ret) { - errorPrint("%s() LN%d, stmt_add_batch() failed! reason: %s\n", + errorPrint2("%s() LN%d, stmt_add_batch() failed! reason: %s\n", __func__, __LINE__, taos_stmt_errstr(stmt)); return -1; } @@ -6603,7 +7338,6 @@ static int32_t prepareStbStmtWithSample( return k; } -#endif static int32_t generateStbProgressiveData( SSuperTable *stbInfo, @@ -6692,8 +7426,6 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { int64_t nTimeStampStep; uint64_t insert_interval; - bool sourceRand; - SSuperTable* stbInfo = pThreadInfo->stbInfo; if (stbInfo) { @@ -6708,18 +7440,12 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { maxSqlLen = stbInfo->maxSqlLen; nTimeStampStep = stbInfo->timeStampStep; insert_interval = stbInfo->insertInterval; - if (0 == strncasecmp(stbInfo->dataSource, "rand", 4)) { - sourceRand = true; - } else { - sourceRand = false; // from sample data file - } } else { insertRows = g_args.num_of_DPT; interlaceRows = g_args.interlace_rows; maxSqlLen = g_args.max_sql_len; nTimeStampStep = g_args.timestamp_step; insert_interval = g_args.insert_interval; - sourceRand = true; } debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRId64" insertRows=%"PRIu64"\n", @@ -6745,7 +7471,7 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { pThreadInfo->buffer = calloc(maxSqlLen, 1); if (NULL == pThreadInfo->buffer) { - errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n", + errorPrint2( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n", __func__, __LINE__, maxSqlLen, strerror(errno)); return NULL; } @@ -6793,7 +7519,7 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { getTableName(tableName, pThreadInfo, tableSeq); if (0 == strlen(tableName)) { - errorPrint("[%d] %s() LN%d, getTableName return null\n", + errorPrint2("[%d] %s() LN%d, getTableName return null\n", pThreadInfo->threadID, __func__, __LINE__); free(pThreadInfo->buffer); return NULL; @@ -6804,29 +7530,14 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { int32_t generated; if (stbInfo) { if (stbInfo->iface == STMT_IFACE) { -#if STMT_IFACE_ENABLED == 1 - if (sourceRand) { - generated = prepareStbStmtRand( - pThreadInfo, - tableName, - tableSeq, - batchPerTbl, - insertRows, 0, - startTime - ); - } else { - generated = prepareStbStmtWithSample( - pThreadInfo, - tableName, - tableSeq, - batchPerTbl, - insertRows, 0, - startTime, - &(pThreadInfo->samplePos)); - } -#else - generated = -1; -#endif + generated = prepareStbStmtWithSample( + pThreadInfo, + tableName, + tableSeq, + batchPerTbl, + insertRows, 0, + startTime, + &(pThreadInfo->samplePos)); } else { generated = generateStbInterlaceData( pThreadInfo, @@ -6844,16 +7555,12 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { pThreadInfo->threadID, __func__, __LINE__, tableName, batchPerTbl, startTime); -#if STMT_IFACE_ENABLED == 1 generated = prepareStmtWithoutStb( pThreadInfo, tableName, batchPerTbl, insertRows, i, startTime); -#else - generated = -1; -#endif } else { generated = generateInterlaceDataWithoutStb( tableName, batchPerTbl, @@ -6868,7 +7575,7 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { debugPrint("[%d] %s() LN%d, generated records is %d\n", pThreadInfo->threadID, __func__, __LINE__, generated); if (generated < 0) { - errorPrint("[%d] %s() LN%d, generated records is %d\n", + errorPrint2("[%d] %s() LN%d, generated records is %d\n", pThreadInfo->threadID, __func__, __LINE__, generated); goto free_of_interlace; } else if (generated == 0) { @@ -6922,7 +7629,7 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { startTs = taosGetTimestampUs(); if (recOfBatch == 0) { - errorPrint("[%d] %s() LN%d Failed to insert records of batch %d\n", + errorPrint2("[%d] %s() LN%d Failed to insert records of batch %d\n", pThreadInfo->threadID, __func__, __LINE__, batchPerTbl); if (batchPerTbl > 0) { @@ -6949,7 +7656,7 @@ static void* syncWriteInterlace(threadInfo *pThreadInfo) { pThreadInfo->totalDelay += delay; if (recOfBatch != affectedRows) { - errorPrint("[%d] %s() LN%d execInsert insert %d, affected rows: %"PRId64"\n%s\n", + errorPrint2("[%d] %s() LN%d execInsert insert %d, affected rows: %"PRId64"\n%s\n", pThreadInfo->threadID, __func__, __LINE__, recOfBatch, affectedRows, pThreadInfo->buffer); goto free_of_interlace; @@ -7007,7 +7714,7 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { pThreadInfo->buffer = calloc(maxSqlLen, 1); if (NULL == pThreadInfo->buffer) { - errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n", + errorPrint2("Failed to alloc %"PRIu64" bytes, reason:%s\n", maxSqlLen, strerror(errno)); return NULL; @@ -7020,17 +7727,6 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { pThreadInfo->totalInsertRows = 0; pThreadInfo->totalAffectedRows = 0; - bool sourceRand; - if (stbInfo) { - if (0 == strncasecmp(stbInfo->dataSource, "rand", 4)) { - sourceRand = true; - } else { - sourceRand = false; // from sample data file - } - } else { - sourceRand = true; - } - pThreadInfo->samplePos = 0; int percentComplete = 0; @@ -7048,7 +7744,7 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { __func__, __LINE__, pThreadInfo->threadID, tableSeq, tableName); if (0 == strlen(tableName)) { - errorPrint("[%d] %s() LN%d, getTableName return null\n", + errorPrint2("[%d] %s() LN%d, getTableName return null\n", pThreadInfo->threadID, __func__, __LINE__); free(pThreadInfo->buffer); return NULL; @@ -7063,31 +7759,19 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { pstr += len; remainderBufLen -= len; + // measure prepare + insert + startTs = taosGetTimestampUs(); + int32_t generated; if (stbInfo) { if (stbInfo->iface == STMT_IFACE) { -#if STMT_IFACE_ENABLED == 1 - if (sourceRand) { - generated = prepareStbStmtRand( - pThreadInfo, - tableName, - tableSeq, - g_args.num_of_RPR, - insertRows, - i, start_time - ); - } else { - generated = prepareStbStmtWithSample( - pThreadInfo, - tableName, - tableSeq, - g_args.num_of_RPR, - insertRows, i, start_time, - &(pThreadInfo->samplePos)); - } -#else - generated = -1; -#endif + generated = prepareStbStmtWithSample( + pThreadInfo, + tableName, + tableSeq, + g_args.num_of_RPR, + insertRows, i, start_time, + &(pThreadInfo->samplePos)); } else { generated = generateStbProgressiveData( stbInfo, @@ -7099,16 +7783,12 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { } } else { if (g_args.iface == STMT_IFACE) { -#if STMT_IFACE_ENABLED == 1 generated = prepareStmtWithoutStb( pThreadInfo, tableName, g_args.num_of_RPR, insertRows, i, start_time); -#else - generated = -1; -#endif } else { generated = generateProgressiveDataWithoutStb( tableName, @@ -7119,6 +7799,11 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { &remainderBufLen); } } + + verbosePrint("[%d] %s() LN%d generated=%d\n", + pThreadInfo->threadID, + __func__, __LINE__, generated); + if (generated > 0) i += generated; else @@ -7127,7 +7812,8 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { start_time += generated * timeStampStep; pThreadInfo->totalInsertRows += generated; - startTs = taosGetTimestampUs(); + // only measure insert + // startTs = taosGetTimestampUs(); int32_t affectedRows = execInsert(pThreadInfo, generated); @@ -7145,7 +7831,7 @@ static void* syncWriteProgressive(threadInfo *pThreadInfo) { pThreadInfo->totalDelay += delay; if (affectedRows < 0) { - errorPrint("%s() LN%d, affected rows: %d\n", + errorPrint2("%s() LN%d, affected rows: %d\n", __func__, __LINE__, affectedRows); goto free_of_progressive; } @@ -7307,7 +7993,7 @@ static int convertHostToServAddr(char *host, uint16_t port, struct sockaddr_in * uint16_t rest_port = port + TSDB_PORT_HTTP; struct hostent *server = gethostbyname(host); if ((server == NULL) || (server->h_addr == NULL)) { - errorPrint("%s", "ERROR, no such host"); + errorPrint2("%s", "no such host"); return -1; } @@ -7328,26 +8014,28 @@ static int convertHostToServAddr(char *host, uint16_t port, struct sockaddr_in * return 0; } -#if STMT_IFACE_ENABLED == 1 -static int parseSampleFileToStmt(SSuperTable *stbInfo, uint32_t timePrec) +static int parseSampleFileToStmt( + threadInfo *pThreadInfo, + SSuperTable *stbInfo, uint32_t timePrec) { - stbInfo->sampleBindArray = calloc(1, sizeof(char *) * MAX_SAMPLES_ONCE_FROM_FILE); - if (stbInfo->sampleBindArray == NULL) { - errorPrint("%s() LN%d, Failed to allocate %"PRIu64" bind array buffer\n", - __func__, __LINE__, (uint64_t)sizeof(char *) * MAX_SAMPLES_ONCE_FROM_FILE); + pThreadInfo->sampleBindArray = + calloc(1, sizeof(char *) * MAX_SAMPLES_ONCE_FROM_FILE); + if (pThreadInfo->sampleBindArray == NULL) { + errorPrint2("%s() LN%d, Failed to allocate %"PRIu64" bind array buffer\n", + __func__, __LINE__, + (uint64_t)sizeof(char *) * MAX_SAMPLES_ONCE_FROM_FILE); return -1; } - for (int i=0; i < MAX_SAMPLES_ONCE_FROM_FILE; i++) { - char *bindArray = calloc(1, sizeof(TAOS_BIND) * (stbInfo->columnCount + 1)); + char *bindArray = + calloc(1, sizeof(TAOS_BIND) * (stbInfo->columnCount + 1)); if (bindArray == NULL) { - errorPrint("%s() LN%d, Failed to allocate %d bind params\n", + errorPrint2("%s() LN%d, Failed to allocate %d bind params\n", __func__, __LINE__, (stbInfo->columnCount + 1)); return -1; } - TAOS_BIND *bind; int cursor = 0; @@ -7374,7 +8062,7 @@ static int parseSampleFileToStmt(SSuperTable *stbInfo, uint32_t timePrec) char *bindBuffer = calloc(1, index + 1); if (bindBuffer == NULL) { - errorPrint("%s() LN%d, Failed to allocate %d bind buffer\n", + errorPrint2("%s() LN%d, Failed to allocate %d bind buffer\n", __func__, __LINE__, DOUBLE_BUFF_LEN); return -1; } @@ -7394,12 +8082,12 @@ static int parseSampleFileToStmt(SSuperTable *stbInfo, uint32_t timePrec) free(bindBuffer); } } - *((uintptr_t *)(stbInfo->sampleBindArray + (sizeof(char *)) * i)) = (uintptr_t)bindArray; + *((uintptr_t *)(pThreadInfo->sampleBindArray + (sizeof(char *)) * i)) = + (uintptr_t)bindArray; } return 0; } -#endif static void startMultiThreadInsertData(int threads, char* db_name, char* precision, SSuperTable* stbInfo) { @@ -7410,12 +8098,10 @@ static void startMultiThreadInsertData(int threads, char* db_name, timePrec = TSDB_TIME_PRECISION_MILLI; } else if (0 == strncasecmp(precision, "us", 2)) { timePrec = TSDB_TIME_PRECISION_MICRO; -#if NANO_SECOND_ENABLED == 1 } else if (0 == strncasecmp(precision, "ns", 2)) { timePrec = TSDB_TIME_PRECISION_NANO; -#endif } else { - errorPrint("Not support precision: %s\n", precision); + errorPrint2("Not support precision: %s\n", precision); exit(EXIT_FAILURE); } } @@ -7434,18 +8120,15 @@ static void startMultiThreadInsertData(int threads, char* db_name, } } } else { - start_time = 1500000000000; + start_time = DEFAULT_START_TIME; } debugPrint("%s() LN%d, start_time= %"PRId64"\n", __func__, __LINE__, start_time); - int64_t start = taosGetTimestampMs(); - // read sample data from file first - if ((stbInfo) && (0 == strncasecmp(stbInfo->dataSource, - "sample", strlen("sample")))) { + if (stbInfo) { if (0 != prepareSampleDataForSTable(stbInfo)) { - errorPrint("%s() LN%d, prepare sample data for stable failed!\n", + errorPrint2("%s() LN%d, prepare sample data for stable failed!\n", __func__, __LINE__); exit(EXIT_FAILURE); } @@ -7455,7 +8138,7 @@ static void startMultiThreadInsertData(int threads, char* db_name, g_Dbs.host, g_Dbs.user, g_Dbs.password, db_name, g_Dbs.port); if (NULL == taos0) { - errorPrint("%s() LN%d, connect to server fail , reason: %s\n", + errorPrint2("%s() LN%d, connect to server fail , reason: %s\n", __func__, __LINE__, taos_errstr(NULL)); exit(EXIT_FAILURE); } @@ -7510,7 +8193,7 @@ static void startMultiThreadInsertData(int threads, char* db_name, limit * TSDB_TABLE_NAME_LEN); if (stbInfo->childTblName == NULL) { taos_close(taos0); - errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__); + errorPrint2("%s() LN%d, alloc memory failed!\n", __func__, __LINE__); exit(EXIT_FAILURE); } @@ -7556,7 +8239,6 @@ static void startMultiThreadInsertData(int threads, char* db_name, memset(pids, 0, threads * sizeof(pthread_t)); memset(infos, 0, threads * sizeof(threadInfo)); -#if STMT_IFACE_ENABLED == 1 char *stmtBuffer = calloc(1, BUFFER_SIZE); assert(stmtBuffer); if ((g_args.iface == STMT_IFACE) @@ -7591,13 +8273,7 @@ static void startMultiThreadInsertData(int threads, char* db_name, pstr += sprintf(pstr, ")"); debugPrint("%s() LN%d, stmtBuffer: %s", __func__, __LINE__, stmtBuffer); - - if ((stbInfo) && (0 == strncasecmp(stbInfo->dataSource, - "sample", strlen("sample")))) { - parseSampleFileToStmt(stbInfo, timePrec); - } } -#endif for (int i = 0; i < threads; i++) { threadInfo *pThreadInfo = infos + i; @@ -7618,24 +8294,22 @@ static void startMultiThreadInsertData(int threads, char* db_name, g_Dbs.password, db_name, g_Dbs.port); if (NULL == pThreadInfo->taos) { free(infos); - errorPrint( + errorPrint2( "%s() LN%d, connect to server fail from insert sub thread, reason: %s\n", __func__, __LINE__, taos_errstr(NULL)); exit(EXIT_FAILURE); } -#if STMT_IFACE_ENABLED == 1 if ((g_args.iface == STMT_IFACE) || ((stbInfo) && (stbInfo->iface == STMT_IFACE))) { - pThreadInfo->stmt = taos_stmt_init(pThreadInfo->taos); if (NULL == pThreadInfo->stmt) { free(pids); free(infos); - errorPrint( + errorPrint2( "%s() LN%d, failed init stmt, reason: %s\n", __func__, __LINE__, taos_errstr(NULL)); @@ -7643,17 +8317,20 @@ static void startMultiThreadInsertData(int threads, char* db_name, } int ret = taos_stmt_prepare(pThreadInfo->stmt, stmtBuffer, 0); - if (ret != 0){ + if (ret != 0) { free(pids); free(infos); free(stmtBuffer); - errorPrint("failed to execute taos_stmt_prepare. return 0x%x. reason: %s\n", + errorPrint2("failed to execute taos_stmt_prepare. return 0x%x. reason: %s\n", ret, taos_stmt_errstr(pThreadInfo->stmt)); exit(EXIT_FAILURE); } pThreadInfo->bind_ts = malloc(sizeof(int64_t)); + + if (stbInfo) { + parseSampleFileToStmt(pThreadInfo, stbInfo, timePrec); + } } -#endif } else { pThreadInfo->taos = NULL; } @@ -7679,9 +8356,9 @@ static void startMultiThreadInsertData(int threads, char* db_name, } } -#if STMT_IFACE_ENABLED == 1 free(stmtBuffer); -#endif + + int64_t start = taosGetTimestampUs(); for (int i = 0; i < threads; i++) { pthread_join(pids[i], NULL); @@ -7696,15 +8373,28 @@ static void startMultiThreadInsertData(int threads, char* db_name, for (int i = 0; i < threads; i++) { threadInfo *pThreadInfo = infos + i; -#if STMT_IFACE_ENABLED == 1 if (pThreadInfo->stmt) { taos_stmt_close(pThreadInfo->stmt); tmfree((char *)pThreadInfo->bind_ts); } -#endif tsem_destroy(&(pThreadInfo->lock_sem)); taos_close(pThreadInfo->taos); + if (pThreadInfo->sampleBindArray) { + for (int k = 0; k < MAX_SAMPLES_ONCE_FROM_FILE; k++) { + uintptr_t *tmp = (uintptr_t *)(*(uintptr_t *)( + pThreadInfo->sampleBindArray + + sizeof(uintptr_t *) * k)); + for (int c = 1; c < pThreadInfo->stbInfo->columnCount + 1; c++) { + TAOS_BIND *bind = (TAOS_BIND *)((char *)tmp + (sizeof(TAOS_BIND) * c)); + if (bind) + tmfree(bind->buffer); + } + tmfree((char *)tmp); + } + tmfree(pThreadInfo->sampleBindArray); + } + debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n", __func__, __LINE__, pThreadInfo->threadID, pThreadInfo->totalInsertRows, @@ -7727,43 +8417,40 @@ static void startMultiThreadInsertData(int threads, char* db_name, if (cntDelay == 0) cntDelay = 1; avgDelay = (double)totalDelay / cntDelay; - int64_t end = taosGetTimestampMs(); + int64_t end = taosGetTimestampUs(); int64_t t = end - start; + if (0 == t) t = 1; - double tInMs = t/1000.0; + double tInMs = (double) t / 1000000.0; if (stbInfo) { - fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n", + fprintf(stderr, "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n", tInMs, stbInfo->totalInsertRows, stbInfo->totalAffectedRows, threads, db_name, stbInfo->sTblName, - (tInMs)? - (double)(stbInfo->totalInsertRows/tInMs):FLT_MAX); + (double)(stbInfo->totalInsertRows/tInMs)); if (g_fpOfInsertResult) { fprintf(g_fpOfInsertResult, - "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n", + "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n", tInMs, stbInfo->totalInsertRows, stbInfo->totalAffectedRows, threads, db_name, stbInfo->sTblName, - (tInMs)? - (double)(stbInfo->totalInsertRows/tInMs):FLT_MAX); + (double)(stbInfo->totalInsertRows/tInMs)); } } else { - fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n", + fprintf(stderr, "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n", tInMs, g_args.totalInsertRows, g_args.totalAffectedRows, threads, db_name, - (tInMs)? - (double)(g_args.totalInsertRows/tInMs):FLT_MAX); + (double)(g_args.totalInsertRows/tInMs)); if (g_fpOfInsertResult) { fprintf(g_fpOfInsertResult, - "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n", + "Spent %.4f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n", tInMs, g_args.totalInsertRows, g_args.totalAffectedRows, threads, db_name, - (tInMs)? - (double)(g_args.totalInsertRows/tInMs):FLT_MAX); + (double)(g_args.totalInsertRows/tInMs)); } } @@ -7796,7 +8483,7 @@ static void *readTable(void *sarg) { 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)); + errorPrint2("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno)); free(command); return NULL; } @@ -7832,7 +8519,7 @@ static void *readTable(void *sarg) { int32_t code = taos_errno(pSql); if (code != 0) { - errorPrint( "Failed to query:%s\n", taos_errstr(pSql)); + errorPrint2("Failed to query:%s\n", taos_errstr(pSql)); taos_free_result(pSql); taos_close(taos); fclose(fp); @@ -7914,7 +8601,7 @@ static void *readMetric(void *sarg) { int32_t code = taos_errno(pSql); if (code != 0) { - errorPrint( "Failed to query:%s\n", taos_errstr(pSql)); + errorPrint2("Failed to query:%s\n", taos_errstr(pSql)); taos_free_result(pSql); taos_close(taos); fclose(fp); @@ -7961,7 +8648,7 @@ static int insertTestProcess() { debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile); g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a"); if (NULL == g_fpOfInsertResult) { - errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile); + errorPrint("Failed to open %s for save result\n", g_Dbs.resultFile); return -1; } @@ -7994,18 +8681,30 @@ static int insertTestProcess() { double start; double end; - // create child tables - start = taosGetTimestampMs(); - createChildTables(); - end = taosGetTimestampMs(); - if (g_totalChildTables > 0) { - fprintf(stderr, "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n", - (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl); + fprintf(stderr, + "creating %"PRId64" table(s) with %d thread(s)\n\n", + g_totalChildTables, g_Dbs.threadCountForCreateTbl); if (g_fpOfInsertResult) { fprintf(g_fpOfInsertResult, - "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n", - (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl); + "creating %"PRId64" table(s) with %d thread(s)\n\n", + g_totalChildTables, g_Dbs.threadCountForCreateTbl); + } + + // create child tables + start = taosGetTimestampMs(); + createChildTables(); + end = taosGetTimestampMs(); + + fprintf(stderr, + "\nSpent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n", + (end - start)/1000.0, g_totalChildTables, + g_Dbs.threadCountForCreateTbl, g_actualChildTables); + if (g_fpOfInsertResult) { + fprintf(g_fpOfInsertResult, + "\nSpent %.4f seconds to create %"PRId64" table(s) with %d thread(s), actual %"PRId64" table(s) created\n\n", + (end - start)/1000.0, g_totalChildTables, + g_Dbs.threadCountForCreateTbl, g_actualChildTables); } } @@ -8063,7 +8762,7 @@ static void *specifiedTableQuery(void *sarg) { NULL, g_queryInfo.port); if (taos == NULL) { - errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", + errorPrint2("[%d] Failed to connect to TDengine, reason:%s\n", pThreadInfo->threadID, taos_errstr(NULL)); return NULL; } else { @@ -8075,7 +8774,7 @@ static void *specifiedTableQuery(void *sarg) { sprintf(sqlStr, "use %s", g_queryInfo.dbName); if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) { taos_close(pThreadInfo->taos); - errorPrint( "use database %s failed!\n\n", + errorPrint("use database %s failed!\n\n", g_queryInfo.dbName); return NULL; } @@ -8116,7 +8815,7 @@ static void *specifiedTableQuery(void *sarg) { uint64_t currentPrintTime = taosGetTimestampMs(); uint64_t endTs = taosGetTimestampMs(); if (currentPrintTime - lastPrintTime > 30*1000) { - debugPrint("%s() LN%d, endTs=%"PRIu64"ms, startTs=%"PRIu64"ms\n", + debugPrint("%s() LN%d, endTs=%"PRIu64" ms, startTs=%"PRIu64" ms\n", __func__, __LINE__, endTs, startTs); printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n", pThreadInfo->threadID, @@ -8241,7 +8940,7 @@ static int queryTestProcess() { NULL, g_queryInfo.port); if (taos == NULL) { - errorPrint( "Failed to connect to TDengine, reason:%s\n", + errorPrint("Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); exit(EXIT_FAILURE); } @@ -8299,7 +8998,7 @@ static int queryTestProcess() { taos_close(taos); free(infos); free(pids); - errorPrint( "use database %s failed!\n\n", + errorPrint2("use database %s failed!\n\n", g_queryInfo.dbName); return -1; } @@ -8397,7 +9096,7 @@ static int queryTestProcess() { static void stable_sub_callback( TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) { if (res == NULL || taos_errno(res) != 0) { - errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n", + errorPrint2("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n", __func__, __LINE__, code, taos_errstr(res)); return; } @@ -8410,7 +9109,7 @@ static void stable_sub_callback( static void specified_sub_callback( TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) { if (res == NULL || taos_errno(res) != 0) { - errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n", + errorPrint2("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n", __func__, __LINE__, code, taos_errstr(res)); return; } @@ -8449,7 +9148,7 @@ static TAOS_SUB* subscribeImpl( } if (tsub == NULL) { - errorPrint("failed to create subscription. topic:%s, sql:%s\n", topic, sql); + errorPrint2("failed to create subscription. topic:%s, sql:%s\n", topic, sql); return NULL; } @@ -8480,7 +9179,7 @@ static void *superSubscribe(void *sarg) { g_queryInfo.dbName, g_queryInfo.port); if (pThreadInfo->taos == NULL) { - errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", + errorPrint2("[%d] Failed to connect to TDengine, reason:%s\n", pThreadInfo->threadID, taos_errstr(NULL)); free(subSqlStr); return NULL; @@ -8491,7 +9190,7 @@ static void *superSubscribe(void *sarg) { sprintf(sqlStr, "USE %s", g_queryInfo.dbName); if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) { taos_close(pThreadInfo->taos); - errorPrint( "use database %s failed!\n\n", + errorPrint2("use database %s failed!\n\n", g_queryInfo.dbName); free(subSqlStr); return NULL; @@ -8627,7 +9326,7 @@ static void *specifiedSubscribe(void *sarg) { g_queryInfo.dbName, g_queryInfo.port); if (pThreadInfo->taos == NULL) { - errorPrint("[%d] Failed to connect to TDengine, reason:%s\n", + errorPrint2("[%d] Failed to connect to TDengine, reason:%s\n", pThreadInfo->threadID, taos_errstr(NULL)); return NULL; } @@ -8734,7 +9433,7 @@ static int subscribeTestProcess() { g_queryInfo.dbName, g_queryInfo.port); if (taos == NULL) { - errorPrint( "Failed to connect to TDengine, reason:%s\n", + errorPrint2("Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); exit(EXIT_FAILURE); } @@ -8762,7 +9461,7 @@ static int subscribeTestProcess() { g_queryInfo.specifiedQueryInfo.sqlCount); } else { if (g_queryInfo.specifiedQueryInfo.concurrent <= 0) { - errorPrint("%s() LN%d, sepcified query sqlCount %d.\n", + errorPrint2("%s() LN%d, sepcified query sqlCount %d.\n", __func__, __LINE__, g_queryInfo.specifiedQueryInfo.sqlCount); exit(EXIT_FAILURE); @@ -8779,7 +9478,7 @@ static int subscribeTestProcess() { g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo)); if ((NULL == pids) || (NULL == infos)) { - errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__); + errorPrint2("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__); exit(EXIT_FAILURE); } @@ -8814,7 +9513,7 @@ static int subscribeTestProcess() { g_queryInfo.superQueryInfo.threadCnt * sizeof(threadInfo)); if ((NULL == pidsOfStable) || (NULL == infosOfStable)) { - errorPrint("%s() LN%d, malloc failed for create threads\n", + errorPrint2("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__); // taos_close(taos); exit(EXIT_FAILURE); @@ -8920,7 +9619,7 @@ static void setParaFromArg() { } g_Dbs.threadCount = g_args.num_of_threads; - g_Dbs.threadCountByCreateTbl = g_args.num_of_threads; + g_Dbs.threadCountForCreateTbl = g_args.num_of_threads; g_Dbs.dbCount = 1; g_Dbs.db[0].drop = true; @@ -8952,7 +9651,7 @@ static void setParaFromArg() { tstrncpy(g_Dbs.db[0].superTbls[0].sTblName, "meters", TSDB_TABLE_NAME_LEN); g_Dbs.db[0].superTbls[0].childTblCount = g_args.num_of_tables; g_Dbs.threadCount = g_args.num_of_threads; - g_Dbs.threadCountByCreateTbl = g_args.num_of_threads; + g_Dbs.threadCountForCreateTbl = g_args.num_of_threads; g_Dbs.asyncMode = g_args.async_mode; g_Dbs.db[0].superTbls[0].autoCreateTable = PRE_CREATE_SUBTBL; @@ -8983,7 +9682,7 @@ static void setParaFromArg() { tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType, data_type[i], min(DATATYPE_BUFF_LEN, strlen(data_type[i]) + 1)); - g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary; + g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.binwidth; g_Dbs.db[0].superTbls[0].columnCount++; } @@ -9005,10 +9704,10 @@ static void setParaFromArg() { tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", min(DATATYPE_BUFF_LEN, strlen("BINARY") + 1)); - g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary; + g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.binwidth; g_Dbs.db[0].superTbls[0].tagCount = 2; } else { - g_Dbs.threadCountByCreateTbl = g_args.num_of_threads; + g_Dbs.threadCountForCreateTbl = g_args.num_of_threads; g_Dbs.db[0].superTbls[0].tagCount = 0; } } @@ -9080,7 +9779,7 @@ static void querySqlFile(TAOS* taos, char* sqlFile) memcpy(cmd + cmd_len, line, read_len); if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) { - errorPrint("%s() LN%d, queryDbExec %s failed!\n", + errorPrint2("%s() LN%d, queryDbExec %s failed!\n", __func__, __LINE__, cmd); tmfree(cmd); tmfree(line); @@ -9130,7 +9829,7 @@ static void queryResult() { pthread_t read_id; threadInfo *pThreadInfo = calloc(1, sizeof(threadInfo)); assert(pThreadInfo); - pThreadInfo->start_time = 1500000000000; // 2017-07-14 10:40:00.000 + pThreadInfo->start_time = DEFAULT_START_TIME; // 2017-07-14 10:40:00.000 pThreadInfo->start_table_from = 0; //pThreadInfo->do_aggreFunc = g_Dbs.do_aggreFunc; @@ -9154,7 +9853,7 @@ static void queryResult() { g_Dbs.port); if (pThreadInfo->taos == NULL) { free(pThreadInfo); - errorPrint( "Failed to connect to TDengine, reason:%s\n", + errorPrint2("Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL)); exit(EXIT_FAILURE); } @@ -9176,7 +9875,7 @@ static void testCmdLine() { if (strlen(configDir)) { wordexp_t full_path; if (wordexp(configDir, &full_path, 0) != 0) { - errorPrint( "Invalid path %s\n", configDir); + errorPrint("Invalid path %s\n", configDir); return; } taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]); @@ -9196,6 +9895,7 @@ int main(int argc, char *argv[]) { debugPrint("meta file: %s\n", g_args.metaFile); if (g_args.metaFile) { + g_totalChildTables = 0; initOfInsertMeta(); initOfQueryMeta(); diff --git a/src/kit/taosdump/taosdump.c b/src/kit/taosdump/taosdump.c index 6b553b382435bf2351d0b05c58f729cf0170aa73..ae2193a82eb447f0e948abc1757c21cab46ccf34 100644 --- a/src/kit/taosdump/taosdump.c +++ b/src/kit/taosdump/taosdump.c @@ -62,6 +62,20 @@ typedef struct { #define errorPrint(fmt, ...) \ do { fprintf(stderr, "\033[31m"); fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); fprintf(stderr, "\033[0m"); } while(0) +static bool isStringNumber(char *input) +{ + int len = strlen(input); + if (0 == len) { + return false; + } + + for (int i = 0; i < len; i++) { + if (!isdigit(input[i])) + return false; + } + + return true; +} // -------------------------- SHOW DATABASE INTERFACE----------------------- enum _show_db_index { @@ -211,16 +225,15 @@ static struct argp_option options[] = { {"password", 'p', 0, 0, "User password to connect to server. Default is taosdata.", 0}, #endif {"port", 'P', "PORT", 0, "Port to connect", 0}, - {"cversion", 'v', "CVERION", 0, "client version", 0}, {"mysqlFlag", 'q', "MYSQLFLAG", 0, "mysqlFlag, Default is 0", 0}, // input/output file {"outpath", 'o', "OUTPATH", 0, "Output file path.", 1}, {"inpath", 'i', "INPATH", 0, "Input file path.", 1}, {"resultFile", 'r', "RESULTFILE", 0, "DumpOut/In Result file path and name.", 1}, #ifdef _TD_POWER_ - {"config", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/power/taos.cfg.", 1}, + {"config-dir", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/power/taos.cfg.", 1}, #else - {"config", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/taos/taos.cfg.", 1}, + {"config-dir", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/taos/taos.cfg.", 1}, #endif {"encode", 'e', "ENCODE", 0, "Input file encoding.", 1}, // dump unit options @@ -230,7 +243,7 @@ static struct argp_option options[] = { // dump format 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}, + {"avro", 'v', 0, 0, "Dump apache avro format data file. By default, dump sql command sequence.", 2}, {"start-time", 'S', "START_TIME", 0, "Start time to dump. Either epoch or ISO8601/RFC3339 format is acceptable. ISO8601 format example: 2017-10-01T00:00:00.000+0800 or 2017-10-0100:00:00:000+0800 or '2017-10-01 00:00:00.000+0800'", 4}, {"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 @@ -253,7 +266,6 @@ typedef struct arguments { char *user; char password[SHELL_MAX_PASSWORD_LEN]; uint16_t port; - char cversion[12]; uint16_t mysqlFlag; // output file char outpath[MAX_FILE_NAME_LEN]; @@ -324,7 +336,6 @@ struct arguments g_args = { "taosdata", #endif 0, - "", 0, // outpath and inpath "", @@ -356,6 +367,24 @@ struct arguments g_args = { false // performance_print }; +static void errorPrintReqArg2(char *program, char *wrong_arg) +{ + fprintf(stderr, + "%s: option requires a number argument '-%s'\n", + program, wrong_arg); + fprintf(stderr, + "Try `taosdump --help' or `taosdump --usage' for more information.\n"); +} + +static void errorPrintReqArg3(char *program, char *wrong_arg) +{ + fprintf(stderr, + "%s: option '%s' requires an argument\n", + program, wrong_arg); + fprintf(stderr, + "Try `taosdump --help' or `taosdump --usage' for more information.\n"); +} + /* Parse a single option. */ static error_t parse_opt(int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we @@ -376,20 +405,15 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { case 'p': break; case 'P': + if (!isStringNumber(arg)) { + errorPrintReqArg2("taosdump", "P"); + exit(EXIT_FAILURE); + } g_args.port = atoi(arg); break; case 'q': g_args.mysqlFlag = atoi(arg); break; - case 'v': - if (wordexp(arg, &full_path, 0) != 0) { - errorPrint("Invalid client vesion %s\n", arg); - return -1; - } - tstrncpy(g_args.cversion, full_path.we_wordv[0], 11); - wordfree(&full_path); - break; - // output file path case 'o': if (wordexp(arg, &full_path, 0) != 0) { errorPrint("Invalid path %s\n", arg); @@ -416,9 +440,13 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { g_args.resultFile = arg; break; case 'c': + if (0 == strlen(arg)) { + errorPrintReqArg3("taosdump", "-c or --config-dir"); + exit(EXIT_FAILURE); + } if (wordexp(arg, &full_path, 0) != 0) { errorPrint("Invalid path %s\n", arg); - return -1; + exit(EXIT_FAILURE); } tstrncpy(configDir, full_path.we_wordv[0], MAX_FILE_NAME_LEN); wordfree(&full_path); @@ -439,7 +467,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { case 'N': g_args.with_property = false; break; - case 'V': + case 'v': g_args.avro = true; break; case 'S': @@ -472,6 +500,10 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) { g_args.table_batch = atoi(arg); break; case 'T': + if (!isStringNumber(arg)) { + errorPrint("%s", "\n\t-T need a number following!\n"); + exit(EXIT_FAILURE); + } g_args.thread_num = atoi(arg); break; case OPT_ABORT: @@ -642,6 +674,9 @@ static void parse_timestamp( } int main(int argc, char *argv[]) { + static char verType[32] = {0}; + sprintf(verType, "version: %s\n", version); + argp_program_version = verType; int ret = 0; /* Parse our arguments; every option seen by parse_opt will be @@ -668,7 +703,6 @@ int main(int argc, char *argv[]) { printf("user: %s\n", g_args.user); printf("password: %s\n", g_args.password); printf("port: %u\n", g_args.port); - printf("cversion: %s\n", g_args.cversion); printf("mysqlFlag: %d\n", g_args.mysqlFlag); printf("outpath: %s\n", g_args.outpath); printf("inpath: %s\n", g_args.inpath); @@ -697,11 +731,6 @@ int main(int argc, char *argv[]) { } } printf("==============================\n"); - - if (g_args.cversion[0] != 0){ - tstrncpy(version, g_args.cversion, 11); - } - if (taosCheckParam(&g_args) < 0) { exit(EXIT_FAILURE); } @@ -719,7 +748,6 @@ int main(int argc, char *argv[]) { fprintf(g_fpOfResult, "user: %s\n", g_args.user); fprintf(g_fpOfResult, "password: %s\n", g_args.password); fprintf(g_fpOfResult, "port: %u\n", g_args.port); - fprintf(g_fpOfResult, "cversion: %s\n", g_args.cversion); fprintf(g_fpOfResult, "mysqlFlag: %d\n", g_args.mysqlFlag); fprintf(g_fpOfResult, "outpath: %s\n", g_args.outpath); fprintf(g_fpOfResult, "inpath: %s\n", g_args.inpath); diff --git a/src/kit/taospack/taospack.c b/src/kit/taospack/taospack.c index 33d779dfcf7abd1315107fd45f79eaed57581768..ddb9e660af4b4c479c0d8bc4b8be47c9f900dfce 100644 --- a/src/kit/taospack/taospack.c +++ b/src/kit/taospack/taospack.c @@ -18,6 +18,7 @@ #include #include + #if defined(WINDOWS) int main(int argc, char *argv[]) { printf("welcome to use taospack tools v1.3 for windows.\n"); @@ -148,7 +149,10 @@ float* read_float(const char* inFile, int* pcount){ //printf(" buff=%s float=%.50f \n ", buf, floats[fi]); if ( ++fi == malloc_cnt ) { malloc_cnt += 100000; - floats = realloc(floats, malloc_cnt*sizeof(float)); + float* floats1 = realloc(floats, malloc_cnt*sizeof(float)); + if(floats1 == NULL) + break; + floats = floats1; } memset(buf, 0, sizeof(buf)); } @@ -601,7 +605,6 @@ void test_threadsafe_double(int thread_count){ } - void unitTestFloat() { float ft1 [] = {1.11, 2.22, 3.333}; @@ -662,7 +665,50 @@ void unitTestFloat() { free(ft2); free(buff); free(output); - +} + +void leakFloat() { + + int cnt = sizeof(g_ft1)/sizeof(float); + float* floats = g_ft1; + int algorithm = 2; + + // compress + const char* input = (const char*)floats; + int input_len = cnt * sizeof(float); + int output_len = input_len + 1024; + char* output = (char*) malloc(output_len); + char* buff = (char*) malloc(input_len); + int buff_len = input_len; + + int ret_len = 0; + ret_len = tsCompressFloatLossy(input, input_len, cnt, output, output_len, algorithm, buff, buff_len); + + if(ret_len == 0) { + printf(" compress float error.\n"); + free(buff); + free(output); + return ; + } + + float* ft2 = (float*)malloc(input_len); + ret_len = tsDecompressFloatLossy(output, ret_len, cnt, (char*)ft2, input_len, algorithm, buff, buff_len); + if(ret_len == 0) { + printf(" decompress float error.\n"); + } + + free(ft2); + free(buff); + free(output); +} + + +void leakTest(){ + for(int i=0; i< 90000000000000; i++){ + if(i%10000==0) + printf(" ---------- %d ---------------- \n", i); + leakFloat(); + } } #define DB_CNT 500 @@ -689,7 +735,7 @@ extern char Compressor []; // ----------------- main ---------------------- // int main(int argc, char *argv[]) { - printf("welcome to use taospack tools v1.3\n"); + printf("welcome to use taospack tools v1.6\n"); //printf(" sizeof(int)=%d\n", (int)sizeof(int)); //printf(" sizeof(long)=%d\n", (int)sizeof(long)); @@ -753,6 +799,9 @@ int main(int argc, char *argv[]) { if(strcmp(argv[1], "-mem") == 0) { memTest(); } + else if(strcmp(argv[1], "-leak") == 0) { + leakTest(); + } } else{ unitTestFloat(); diff --git a/src/mnode/src/mnodeTable.c b/src/mnode/src/mnodeTable.c index 0bc114ffdfe8d59f4941536b56bd95be96a03d0b..68529ab8a240c2313ae9417bef9f4112759b0c9f 100644 --- a/src/mnode/src/mnodeTable.c +++ b/src/mnode/src/mnodeTable.c @@ -1518,6 +1518,13 @@ static int32_t mnodeChangeSuperTableColumn(SMnodeMsg *pMsg) { // update SSchema *schema = (SSchema *) (pStable->schema + col); ASSERT(schema->type == TSDB_DATA_TYPE_BINARY || schema->type == TSDB_DATA_TYPE_NCHAR); + + if (pAlter->schema[0].bytes <= schema->bytes) { + mError("msg:%p, app:%p stable:%s, modify column len. column:%s, len from %d to %d", pMsg, pMsg->rpcMsg.ahandle, + pStable->info.tableId, name, schema->bytes, pAlter->schema[0].bytes); + return TSDB_CODE_MND_INVALID_COLUMN_LENGTH; + } + schema->bytes = pAlter->schema[0].bytes; pStable->sversion++; mInfo("msg:%p, app:%p stable %s, start to modify column %s len to %d", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, @@ -1548,6 +1555,12 @@ static int32_t mnodeChangeSuperTableTag(SMnodeMsg *pMsg) { // update SSchema *schema = (SSchema *) (pStable->schema + col + pStable->numOfColumns); ASSERT(schema->type == TSDB_DATA_TYPE_BINARY || schema->type == TSDB_DATA_TYPE_NCHAR); + if (pAlter->schema[0].bytes <= schema->bytes) { + mError("msg:%p, app:%p stable:%s, modify tag len. tag:%s, len from %d to %d", pMsg, pMsg->rpcMsg.ahandle, + pStable->info.tableId, name, schema->bytes, pAlter->schema[0].bytes); + return TSDB_CODE_MND_INVALID_TAG_LENGTH; + } + schema->bytes = pAlter->schema[0].bytes; pStable->tversion++; mInfo("msg:%p, app:%p stable %s, start to modify tag len %s to %d", pMsg, pMsg->rpcMsg.ahandle, pStable->info.tableId, @@ -2921,10 +2934,11 @@ static SMultiTableMeta* ensureMsgBufferSpace(SMultiTableMeta *pMultiMeta, SArray (*totalMallocLen) *= 2; } - pMultiMeta = realloc(pMultiMeta, *totalMallocLen); - if (pMultiMeta == NULL) { + SMultiTableMeta* pMultiMeta1 = realloc(pMultiMeta, *totalMallocLen); + if (pMultiMeta1 == NULL) { return NULL; } + pMultiMeta = pMultiMeta1; } return pMultiMeta; diff --git a/src/os/src/detail/osMemory.c b/src/os/src/detail/osMemory.c index d8194feab4011501097fdcce937d88b87ea41af0..22954f1523dc229b8446e339a2d142a0b4b7b023 100644 --- a/src/os/src/detail/osMemory.c +++ b/src/os/src/detail/osMemory.c @@ -504,8 +504,9 @@ void * taosTRealloc(void *ptr, size_t size) { void * tptr = (void *)((char *)ptr - sizeof(size_t)); size_t tsize = size + sizeof(size_t); - tptr = realloc(tptr, tsize); - if (tptr == NULL) return NULL; + void* tptr1 = realloc(tptr, tsize); + if (tptr1 == NULL) return NULL; + tptr = tptr1; *(size_t *)tptr = size; diff --git a/src/os/src/linux/linuxEnv.c b/src/os/src/linux/linuxEnv.c index b7b268b19e6b6f92babb74cfd3f23793be037cd0..650a45aae42c8d2dfba63d8f4e7e6ec35b385ae8 100644 --- a/src/os/src/linux/linuxEnv.c +++ b/src/os/src/linux/linuxEnv.c @@ -50,14 +50,20 @@ void osInit() { char* taosGetCmdlineByPID(int pid) { static char cmdline[1024]; sprintf(cmdline, "/proc/%d/cmdline", pid); - FILE* f = fopen(cmdline, "r"); - if (f) { - size_t size; - size = fread(cmdline, sizeof(char), 1024, f); - if (size > 0) { - if ('\n' == cmdline[size - 1]) cmdline[size - 1] = '\0'; - } - fclose(f); + + int fd = open(cmdline, O_RDONLY); + if (fd >= 0) { + int n = read(fd, cmdline, sizeof(cmdline) - 1); + if (n < 0) n = 0; + + if (n > 0 && cmdline[n - 1] == '\n') --n; + + cmdline[n] = 0; + + close(fd); + } else { + cmdline[0] = 0; } + return cmdline; } diff --git a/src/os/src/linux/osSystem.c b/src/os/src/linux/osSystem.c index 0cdb20dbdb2feb764beaa231fa785e880625cf63..a82149dccb1f71e6fbdc2b62d066f04ff52c251d 100644 --- a/src/os/src/linux/osSystem.c +++ b/src/os/src/linux/osSystem.c @@ -63,12 +63,12 @@ int taosSetConsoleEcho(bool on) } if (on) - term.c_lflag|=ECHOFLAGS; + term.c_lflag |= ECHOFLAGS; else - term.c_lflag &=~ECHOFLAGS; + term.c_lflag &= ~ECHOFLAGS; - err = tcsetattr(STDIN_FILENO,TCSAFLUSH,&term); - if (err == -1 && err == EINTR) { + err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &term); + if (err == -1 || err == EINTR) { perror("Cannot set the attribution of the terminal"); return -1; } diff --git a/src/os/src/windows/wGetline.c b/src/os/src/windows/wGetline.c index 553aecaf0a9be65fb5d532668d28ee1a77fbbd39..aa458548843b977ac7fed4070047ac8d693b2d31 100644 --- a/src/os/src/windows/wGetline.c +++ b/src/os/src/windows/wGetline.c @@ -81,11 +81,13 @@ int32_t getstr(char **lineptr, size_t *n, FILE *stream, char terminator, int32_t *n += MIN_CHUNK; nchars_avail = (int32_t)(*n + *lineptr - read_pos); - *lineptr = realloc(*lineptr, *n); - if (!*lineptr) { + char* lineptr1 = realloc(*lineptr, *n); + if (!lineptr1) { errno = ENOMEM; return -1; } + *lineptr = lineptr1; + read_pos = *n - nchars_avail + *lineptr; assert((*lineptr + *n) == (read_pos + nchars_avail)); } diff --git a/src/plugins/http/CMakeLists.txt b/src/plugins/http/CMakeLists.txt index 57fc2ee3a2692c239d7fa36d6e55ddae738a2720..89fdc141b66adafb9f882dd6f59eca54053aff6c 100644 --- a/src/plugins/http/CMakeLists.txt +++ b/src/plugins/http/CMakeLists.txt @@ -6,6 +6,7 @@ INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(inc) AUX_SOURCE_DIRECTORY(src SRC) diff --git a/src/plugins/http/inc/httpInt.h b/src/plugins/http/inc/httpInt.h index 0a5822b90893861eb12aea756bf877bc81730413..6c567e23bc817957d7f376ef101f8e5ca88559e6 100644 --- a/src/plugins/http/inc/httpInt.h +++ b/src/plugins/http/inc/httpInt.h @@ -147,9 +147,11 @@ typedef struct HttpContext { int32_t state; uint8_t reqType; uint8_t parsed; + uint8_t error; char ipstr[22]; char user[TSDB_USER_LEN]; // parsed from auth token or login message char pass[HTTP_PASSWORD_LEN]; + char db[/*TSDB_ACCT_ID_LEN + */TSDB_DB_NAME_LEN]; TAOS * taos; void * ppContext; HttpSession *session; diff --git a/src/plugins/http/inc/httpRestHandle.h b/src/plugins/http/inc/httpRestHandle.h index 632a1dc64739e39d1e9671fd41f9c224597eff07..df405685e91a520d8b948fdc056d9386626368a2 100644 --- a/src/plugins/http/inc/httpRestHandle.h +++ b/src/plugins/http/inc/httpRestHandle.h @@ -22,12 +22,12 @@ #include "httpResp.h" #include "httpSql.h" -#define REST_ROOT_URL_POS 0 -#define REST_ACTION_URL_POS 1 -#define REST_USER_URL_POS 2 -#define REST_PASS_URL_POS 3 +#define REST_ROOT_URL_POS 0 +#define REST_ACTION_URL_POS 1 +#define REST_USER_USEDB_URL_POS 2 +#define REST_PASS_URL_POS 3 void restInitHandle(HttpServer* pServer); bool restProcessRequest(struct HttpContext* pContext); -#endif \ No newline at end of file +#endif diff --git a/src/plugins/http/src/httpContext.c b/src/plugins/http/src/httpContext.c index 51adef11b9af3ebb83537024edbb3ba369aaeb03..11945453c56ab7fdd1fc8b0c4f2510bbbdda1a6e 100644 --- a/src/plugins/http/src/httpContext.c +++ b/src/plugins/http/src/httpContext.c @@ -188,11 +188,12 @@ void httpCloseContextByApp(HttpContext *pContext) { pContext->parsed = false; bool keepAlive = true; - if (parser && parser->httpVersion == HTTP_VERSION_10 && parser->keepAlive != HTTP_KEEPALIVE_ENABLE) { + if (pContext->error == true) { + keepAlive = false; + } else if (parser && parser->httpVersion == HTTP_VERSION_10 && parser->keepAlive != HTTP_KEEPALIVE_ENABLE) { keepAlive = false; } else if (parser && parser->httpVersion != HTTP_VERSION_10 && parser->keepAlive == HTTP_KEEPALIVE_DISABLE) { keepAlive = false; - } else { } if (keepAlive) { diff --git a/src/plugins/http/src/httpJson.c b/src/plugins/http/src/httpJson.c index 3c72b795eef69186ef4e6308937678589224c60d..86e0f2f40beffdf7d035ba3329d51bb69c2cf796 100644 --- a/src/plugins/http/src/httpJson.c +++ b/src/plugins/http/src/httpJson.c @@ -272,26 +272,35 @@ void httpJsonTimestamp(JsonBuf* buf, int64_t t, int32_t timePrecision) { switch (timePrecision) { case TSDB_TIME_PRECISION_MILLI: { + mod = ((t) % 1000 + 1000) % 1000; + if (t < 0 && mod != 0) { + t -= 1000; + } quot = t / 1000; fractionLen = 5; format = ".%03" PRId64; - mod = t % 1000; break; } case TSDB_TIME_PRECISION_MICRO: { + mod = ((t) % 1000000 + 1000000) % 1000000; + if (t < 0 && mod != 0) { + t -= 1000000; + } quot = t / 1000000; fractionLen = 8; format = ".%06" PRId64; - mod = t % 1000000; break; } case TSDB_TIME_PRECISION_NANO: { + mod = ((t) % 1000000000 + 1000000000) % 1000000000; + if (t < 0 && mod != 0) { + t -= 1000000000; + } quot = t / 1000000000; fractionLen = 11; format = ".%09" PRId64; - mod = t % 1000000000; break; } @@ -319,26 +328,35 @@ void httpJsonUtcTimestamp(JsonBuf* buf, int64_t t, int32_t timePrecision) { switch (timePrecision) { case TSDB_TIME_PRECISION_MILLI: { + mod = ((t) % 1000 + 1000) % 1000; + if (t < 0 && mod != 0) { + t -= 1000; + } quot = t / 1000; fractionLen = 5; format = ".%03" PRId64; - mod = t % 1000; break; } case TSDB_TIME_PRECISION_MICRO: { + mod = ((t) % 1000000 + 1000000) % 1000000; + if (t < 0 && mod != 0) { + t -= 1000000; + } quot = t / 1000000; fractionLen = 8; format = ".%06" PRId64; - mod = t % 1000000; break; } case TSDB_TIME_PRECISION_NANO: { + mod = ((t) % 1000000000 + 1000000000) % 1000000000; + if (t < 0 && mod != 0) { + t -= 1000000000; + } quot = t / 1000000000; fractionLen = 11; format = ".%09" PRId64; - mod = t % 1000000000; break; } diff --git a/src/plugins/http/src/httpParser.c b/src/plugins/http/src/httpParser.c index 02f21037b8592cc847f02f1b2fbe3c01acd508d8..62b1737f6fe7128ee132727b2870fca5f62b737a 100644 --- a/src/plugins/http/src/httpParser.c +++ b/src/plugins/http/src/httpParser.c @@ -663,7 +663,7 @@ static int32_t httpParserOnTarget(HttpParser *parser, HTTP_PARSER_STATE state, c HttpContext *pContext = parser->pContext; int32_t ok = 0; do { - if (!isspace(c) && c != '\r' && c != '\n') { + if (!isspace(c)) { if (httpAppendString(&parser->str, &c, 1)) { httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c); ok = -1; @@ -1157,6 +1157,10 @@ static int32_t httpParseChar(HttpParser *parser, const char c, int32_t *again) { httpOnError(parser, HTTP_CODE_INTERNAL_SERVER_ERROR, TSDB_CODE_HTTP_PARSE_ERROR_STATE); } + if (ok != 0) { + pContext->error = true; + } + return ok; } diff --git a/src/plugins/http/src/httpRestHandle.c b/src/plugins/http/src/httpRestHandle.c index a285670d20ae1e5a9c8bd6c41971fc57cda3320a..24e4f90244cf52799fde1a45054875a4bf3d1850 100644 --- a/src/plugins/http/src/httpRestHandle.c +++ b/src/plugins/http/src/httpRestHandle.c @@ -19,6 +19,7 @@ #include "httpLog.h" #include "httpRestHandle.h" #include "httpRestJson.h" +#include "tglobal.h" static HttpDecodeMethod restDecodeMethod = {"rest", restProcessRequest}; static HttpDecodeMethod restDecodeMethod2 = {"restful", restProcessRequest}; @@ -62,11 +63,11 @@ void restInitHandle(HttpServer* pServer) { bool restGetUserFromUrl(HttpContext* pContext) { HttpParser* pParser = pContext->parser; - if (pParser->path[REST_USER_URL_POS].pos >= TSDB_USER_LEN || pParser->path[REST_USER_URL_POS].pos <= 0) { + if (pParser->path[REST_USER_USEDB_URL_POS].pos >= TSDB_USER_LEN || pParser->path[REST_USER_USEDB_URL_POS].pos <= 0) { return false; } - tstrncpy(pContext->user, pParser->path[REST_USER_URL_POS].str, TSDB_USER_LEN); + tstrncpy(pContext->user, pParser->path[REST_USER_USEDB_URL_POS].str, TSDB_USER_LEN); return true; } @@ -107,6 +108,24 @@ bool restProcessSqlRequest(HttpContext* pContext, int32_t timestampFmt) { HttpSqlCmd* cmd = &(pContext->singleCmd); cmd->nativSql = sql; + /* find if there is db_name in url */ + pContext->db[0] = '\0'; + + HttpString *path = &pContext->parser->path[REST_USER_USEDB_URL_POS]; + if (tsHttpDbNameMandatory) { + if (path->pos == 0) { + httpError("context:%p, fd:%d, user:%s, database name is mandatory", pContext, pContext->fd, pContext->user); + httpSendErrorResp(pContext, TSDB_CODE_HTTP_INVALID_URL); + return false; + } + } + + if (path->pos > 0 && !(strlen(sql) > 4 && (sql[0] == 'u' || sql[0] == 'U') && + (sql[1] == 's' || sql[1] == 'S') && (sql[2] == 'e' || sql[2] == 'E') && sql[3] == ' ')) + { + snprintf(pContext->db, /*TSDB_ACCT_ID_LEN + */TSDB_DB_NAME_LEN, "%s", path->str); + } + pContext->reqType = HTTP_REQTYPE_SINGLE_SQL; if (timestampFmt == REST_TIMESTAMP_FMT_LOCAL_STRING) { pContext->encodeMethod = &restEncodeSqlLocalTimeStringMethod; diff --git a/src/plugins/http/src/httpSql.c b/src/plugins/http/src/httpSql.c index c2e723732a0f9d786994527c6cd1ac77f273a736..0dd451f72dbd78233ac8f73d552b6815e3a3fab8 100644 --- a/src/plugins/http/src/httpSql.c +++ b/src/plugins/http/src/httpSql.c @@ -419,6 +419,11 @@ void httpProcessRequest(HttpContext *pContext) { &(pContext->taos)); httpDebug("context:%p, fd:%d, user:%s, try connect tdengine, taos:%p", pContext, pContext->fd, pContext->user, pContext->taos); + + if (pContext->taos != NULL) { + STscObj *pObj = pContext->taos; + pObj->from = TAOS_REQ_FROM_HTTP; + } } else { httpExecCmd(pContext); } diff --git a/src/plugins/monitor/src/monMain.c b/src/plugins/monitor/src/monMain.c index 6e583fe0dfd809bac8c0aabf56e48bb33bd910ce..fea793fa860fd17ff30bcecae1436180bc6b34bf 100644 --- a/src/plugins/monitor/src/monMain.c +++ b/src/plugins/monitor/src/monMain.c @@ -34,7 +34,7 @@ #define monTrace(...) { if (monDebugFlag & DEBUG_TRACE) { taosPrintLog("MON ", monDebugFlag, __VA_ARGS__); }} #define SQL_LENGTH 1030 -#define LOG_LEN_STR 100 +#define LOG_LEN_STR 512 #define IP_LEN_STR TSDB_EP_LEN #define CHECK_INTERVAL 1000 diff --git a/src/query/inc/qExecutor.h b/src/query/inc/qExecutor.h index 6e8eec2456ea9cdbab675a62bb67efd4db30e882..31db6492f69c35904970cc5f48cc4a10c9fecd39 100644 --- a/src/query/inc/qExecutor.h +++ b/src/query/inc/qExecutor.h @@ -43,9 +43,7 @@ typedef int32_t (*__block_search_fn_t)(char* data, int32_t num, int64_t key, int #define GET_NUM_OF_RESULTS(_r) (((_r)->outputBuf) == NULL? 0:((_r)->outputBuf)->info.rows) -//TODO: may need to fine tune this threshold -#define QUERY_COMP_THRESHOLD (1024 * 512) -#define NEEDTO_COMPRESS_QUERY(size) ((size) > QUERY_COMP_THRESHOLD ? 1 : 0) +#define NEEDTO_COMPRESS_QUERY(size) ((size) > tsCompressColData? 1 : 0) enum { // when query starts to execute, this status will set @@ -223,6 +221,7 @@ typedef struct SQueryAttr { bool distinct; // distinct query or not bool stateWindow; // window State on sub/normal table bool createFilterOperator; // if filter operator is needed + bool multigroupResult; // multigroup result can exist in one SSDataBlock int32_t interBufSize; // intermediate buffer sizse int32_t havingNum; // having expr number @@ -469,16 +468,23 @@ typedef struct SLimitOperatorInfo { } SLimitOperatorInfo; typedef struct SSLimitOperatorInfo { - int64_t groupTotal; - int64_t currentGroupOffset; - - int64_t rowsTotal; - int64_t currentOffset; - SLimitVal limit; - SLimitVal slimit; - - char **prevRow; - SArray *orderColumnList; + int64_t groupTotal; + int64_t currentGroupOffset; + + int64_t rowsTotal; + int64_t currentOffset; + SLimitVal limit; + SLimitVal slimit; + + char **prevRow; + SArray *orderColumnList; + bool hasPrev; + bool ignoreCurrentGroup; + bool multigroupResult; + SSDataBlock *pRes; // result buffer + SSDataBlock *pPrevBlock; + int64_t capacity; + int64_t threshold; } SSLimitOperatorInfo; typedef struct SFilterOperatorInfo { @@ -490,8 +496,9 @@ typedef struct SFillOperatorInfo { SFillInfo *pFillInfo; SSDataBlock *pRes; int64_t totalInputRows; - + void **p; SSDataBlock *existNewGroupBlock; + bool multigroupResult; } SFillOperatorInfo; typedef struct SGroupbyOperatorInfo { @@ -553,9 +560,9 @@ typedef struct SMultiwayMergeInfo { bool hasDataBlockForNewGroup; SSDataBlock *pExistBlock; - bool hasPrev; - bool groupMix; SArray *udfInfo; + bool hasPrev; + bool multiGroupResults; } SMultiwayMergeInfo; // todo support the disk-based sort @@ -577,7 +584,7 @@ SOperatorInfo* createLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorI SOperatorInfo* createTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createAllTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createSWindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); -SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); +SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, bool multigroupResult); SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createMultiTableAggOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createMultiTableTimeIntervalOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); @@ -586,10 +593,10 @@ SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInf SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); SOperatorInfo* createTableBlockInfoScanOperator(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv); SOperatorInfo* createMultiwaySortOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInfo* pExpr, int32_t numOfOutput, - int32_t numOfRows, void* merger, bool groupMix); -SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* param, SArray* pUdfInfo); + int32_t numOfRows, void* merger); +SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* param, SArray* pUdfInfo, bool groupResultMixedUp); SOperatorInfo* createStatewindowOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput); -SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* merger); +SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* merger, bool multigroupResult); SOperatorInfo* createFilterOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, SColumnInfo* pCols, int32_t numOfFilter); @@ -606,6 +613,7 @@ bool doFilterDataBlock(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilter void doCompactSDataBlock(SSDataBlock* pBlock, int32_t numOfRows, int8_t* p); SSDataBlock* createOutputBuf(SExprInfo* pExpr, int32_t numOfOutput, int32_t numOfRows); + void* destroyOutputBuf(SSDataBlock* pBlock); void* doDestroyFilterInfo(SSingleColumnFilterInfo* pFilterInfo, int32_t numOfFilterCols); @@ -614,6 +622,7 @@ int32_t getNumOfResult(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx* pCtx, int3 void finalizeQueryResult(SOperatorInfo* pOperator, SQLFunctionCtx* pCtx, SResultRowInfo* pResultRowInfo, int32_t* rowCellInfoOffset); void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity, int32_t numOfInputRows); void clearOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity); +void copyTsColoum(SSDataBlock* pRes, SQLFunctionCtx* pCtx, int32_t numOfOutput); void freeParam(SQueryParam *param); int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param); diff --git a/src/query/inc/qExtbuffer.h b/src/query/inc/qExtbuffer.h index b5ea9932b9092c1e037e2b9f815f4c07c55d8dd5..d4a9ed0cbcef0a52085dcd60569270037fb57908 100644 --- a/src/query/inc/qExtbuffer.h +++ b/src/query/inc/qExtbuffer.h @@ -220,6 +220,8 @@ tOrderDescriptor *tOrderDesCreate(const int32_t *orderColIdx, int32_t numOfOrder void tOrderDescDestroy(tOrderDescriptor *pDesc); +void taoscQSort(void** pCols, SSchema* pSchema, int32_t numOfCols, int32_t numOfRows, int32_t index, __compar_fn_t compareFn); + void tColModelAppend(SColumnModel *dstModel, tFilePage *dstPage, void *srcData, int32_t srcStartRows, int32_t numOfRowsToWrite, int32_t srcCapacity); diff --git a/src/query/inc/qSqlparser.h b/src/query/inc/qSqlparser.h index 531ff06565dba837c696c6069d409ccf536cbe8c..c231c90996e00d84a70c7141eac69c5a59e20254 100644 --- a/src/query/inc/qSqlparser.h +++ b/src/query/inc/qSqlparser.h @@ -80,6 +80,7 @@ typedef struct tVariantListItem { } tVariantListItem; typedef struct SIntervalVal { + int32_t token; SStrToken interval; SStrToken offset; } SIntervalVal; diff --git a/src/query/inc/qTableMeta.h b/src/query/inc/qTableMeta.h index d6b04b033062bd17e451c0f9af4d2bf8f84190a1..746c5f8569ac98c465e8283a2401e27c18cadcc4 100644 --- a/src/query/inc/qTableMeta.h +++ b/src/query/inc/qTableMeta.h @@ -165,6 +165,7 @@ typedef struct SQueryInfo { bool orderProjectQuery; bool stateWindow; bool globalMerge; + bool multigroupResult; } SQueryInfo; /** diff --git a/src/query/inc/queryLog.h b/src/query/inc/queryLog.h index 5c48c43c45fdb5cffdcc01901f1ede4a3b98d240..87a221943a566cae3f873d5859a1a5cc09cf9989 100644 --- a/src/query/inc/queryLog.h +++ b/src/query/inc/queryLog.h @@ -24,10 +24,10 @@ extern "C" { extern uint32_t qDebugFlag; -#define qFatal(...) do { if (qDebugFlag & DEBUG_FATAL) { taosPrintLog("QRY FATAL ", 255, __VA_ARGS__); }} while(0) -#define qError(...) do { if (qDebugFlag & DEBUG_ERROR) { taosPrintLog("QRY ERROR ", 255, __VA_ARGS__); }} while(0) -#define qWarn(...) do { if (qDebugFlag & DEBUG_WARN) { taosPrintLog("QRY WARN ", 255, __VA_ARGS__); }} while(0) -#define qInfo(...) do { if (qDebugFlag & DEBUG_INFO) { taosPrintLog("QRY ", 255, __VA_ARGS__); }} while(0) +#define qFatal(...) do { if (qDebugFlag & DEBUG_FATAL) { taosPrintLog("QRY FATAL ", qDebugFlag, __VA_ARGS__); }} while(0) +#define qError(...) do { if (qDebugFlag & DEBUG_ERROR) { taosPrintLog("QRY ERROR ", qDebugFlag, __VA_ARGS__); }} while(0) +#define qWarn(...) do { if (qDebugFlag & DEBUG_WARN) { taosPrintLog("QRY WARN ", qDebugFlag, __VA_ARGS__); }} while(0) +#define qInfo(...) do { if (qDebugFlag & DEBUG_INFO) { taosPrintLog("QRY ", qDebugFlag, __VA_ARGS__); }} while(0) #define qDebug(...) do { if (qDebugFlag & DEBUG_DEBUG) { taosPrintLog("QRY ", qDebugFlag, __VA_ARGS__); }} while(0) #define qTrace(...) do { if (qDebugFlag & DEBUG_TRACE) { taosPrintLog("QRY ", qDebugFlag, __VA_ARGS__); }} while(0) #define qDump(a, l) do { if (qDebugFlag & DEBUG_DUMP) { taosDumpData((unsigned char *)a, l); }} while(0) diff --git a/src/query/inc/sql.y b/src/query/inc/sql.y index 8b43e55693c53fffb19e73b5b9ef7ccada4383a2..d72bcacddcdfe1c9e1a59eff3f94b474a4e4839e 100644 --- a/src/query/inc/sql.y +++ b/src/query/inc/sql.y @@ -11,7 +11,7 @@ %left OR. %left AND. %right NOT. -%left EQ NE ISNULL NOTNULL IS LIKE GLOB BETWEEN IN. +%left EQ NE ISNULL NOTNULL IS LIKE MATCH GLOB BETWEEN IN. %left GT GE LT LE. %left BITAND BITOR LSHIFT RSHIFT. %left PLUS MINUS. @@ -162,7 +162,10 @@ cmd ::= DESCRIBE ids(X) cpxName(Y). { X.n += Y.n; setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &X); } - +cmd ::= DESC ids(X) cpxName(Y). { + X.n += Y.n; + setDCLSqlElems(pInfo, TSDB_SQL_DESCRIBE_TABLE, 1, &X); +} /////////////////////////////////THE ALTER STATEMENT//////////////////////////////////////// cmd ::= ALTER USER ids(X) PASS ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PASSWD, &X, &Y, NULL); } cmd ::= ALTER USER ids(X) PRIVILEGE ids(Y). { setAlterUserSql(pInfo, TSDB_ALTER_USER_PRIVILEGES, &X, NULL, &Y);} @@ -479,7 +482,7 @@ tagitem(A) ::= PLUS(X) FLOAT(Y). { //////////////////////// The SELECT statement ///////////////////////////////// %type select {SSqlNode*} %destructor select {destroySqlNode($$);} -select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_opt(K) sliding_opt(S) session_option(H) windowstate_option(D) fill_opt(F)groupby_opt(P) having_opt(N) orderby_opt(Z) slimit_opt(G) limit_opt(L). { +select(A) ::= SELECT(T) selcollist(W) from(X) where_opt(Y) interval_option(K) sliding_opt(S) session_option(H) windowstate_option(D) fill_opt(F)groupby_opt(P) having_opt(N) orderby_opt(Z) slimit_opt(G) limit_opt(L). { A = tSetQuerySqlNode(&T, W, X, Y, P, Z, &K, &H, &D, &S, F, &L, &G, N); } @@ -493,7 +496,7 @@ union(Y) ::= union(Z) UNION ALL select(X). { Y = appendSelectClause(Z, X); } cmd ::= union(X). { setSqlInfo(pInfo, X, NULL, TSDB_SQL_SELECT); } // Support for the SQL exprssion without from & where subclauses, e.g., -// select current_database() +// select database() // select server_version() // select client_version() // select server_state() @@ -569,10 +572,14 @@ tablelist(A) ::= tablelist(Y) COMMA ids(X) cpxName(Z) ids(F). { %type tmvar {SStrToken} tmvar(A) ::= VARIABLE(X). {A = X;} -%type interval_opt {SIntervalVal} -interval_opt(N) ::= INTERVAL LP tmvar(E) RP. {N.interval = E; N.offset.n = 0;} -interval_opt(N) ::= INTERVAL LP tmvar(E) COMMA tmvar(X) RP. {N.interval = E; N.offset = X;} -interval_opt(N) ::= . {memset(&N, 0, sizeof(N));} +%type interval_option {SIntervalVal} +interval_option(N) ::= intervalKey(A) LP tmvar(E) RP. {N.interval = E; N.offset.n = 0; N.token = A;} +interval_option(N) ::= intervalKey(A) LP tmvar(E) COMMA tmvar(X) RP. {N.interval = E; N.offset = X; N.token = A;} +interval_option(N) ::= . {memset(&N, 0, sizeof(N));} + +%type intervalKey {int32_t} +intervalKey(A) ::= INTERVAL. {A = TK_INTERVAL;} +intervalKey(A) ::= EVERY. {A = TK_EVERY; } %type session_option {SSessionWindowVal} session_option(X) ::= . {X.col.n = 0; X.gap.n = 0;} @@ -581,6 +588,7 @@ session_option(X) ::= SESSION LP ids(V) cpxName(Z) COMMA tmvar(Y) RP. { X.col = V; X.gap = Y; } + %type windowstate_option {SWindowStateVal} windowstate_option(X) ::= . { X.col.n = 0; X.col.z = NULL;} windowstate_option(X) ::= STATE_WINDOW LP ids(V) RP. { X.col = V; } @@ -743,6 +751,9 @@ expr(A) ::= expr(X) REM expr(Y). {A = tSqlExprCreate(X, Y, TK_REM); } // like expression expr(A) ::= expr(X) LIKE expr(Y). {A = tSqlExprCreate(X, Y, TK_LIKE); } +// match expression +expr(A) ::= expr(X) MATCH expr(Y). {A = tSqlExprCreate(X, Y, TK_MATCH); } + //in expression expr(A) ::= expr(X) IN LP exprlist(Y) RP. {A = tSqlExprCreate(X, (tSqlExpr*)Y, TK_IN); } diff --git a/src/query/src/qAggMain.c b/src/query/src/qAggMain.c index c19628eb370a5db7d6e5940531b9954879e213ee..c0c6d7a1404dbef6bdb00bd676a30fcfc908671a 100644 --- a/src/query/src/qAggMain.c +++ b/src/query/src/qAggMain.c @@ -1214,6 +1214,31 @@ static int32_t minmax_merge_impl(SQLFunctionCtx *pCtx, int32_t bytes, char *outp DUPATE_DATA_WITHOUT_TS(pCtx, *(int64_t *)output, v, notNullElems, isMin); break; } + + case TSDB_DATA_TYPE_UTINYINT: { + uint8_t v = GET_UINT8_VAL(input); + DUPATE_DATA_WITHOUT_TS(pCtx, *(uint8_t *)output, v, notNullElems, isMin); + break; + } + + case TSDB_DATA_TYPE_USMALLINT: { + uint16_t v = GET_UINT16_VAL(input); + DUPATE_DATA_WITHOUT_TS(pCtx, *(uint16_t *)output, v, notNullElems, isMin); + break; + } + + case TSDB_DATA_TYPE_UINT: { + uint32_t v = GET_UINT32_VAL(input); + DUPATE_DATA_WITHOUT_TS(pCtx, *(uint32_t *)output, v, notNullElems, isMin); + break; + } + + case TSDB_DATA_TYPE_UBIGINT: { + uint64_t v = GET_UINT64_VAL(input); + DUPATE_DATA_WITHOUT_TS(pCtx, *(uint64_t *)output, v, notNullElems, isMin); + break; + } + default: break; } @@ -3670,6 +3695,8 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { return; } + bool ascQuery = (pCtx->order == TSDB_ORDER_ASC); + if (pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP) { *(TSKEY *)pCtx->pOutput = pCtx->startTs; } else if (type == TSDB_FILL_NULL) { @@ -3677,7 +3704,7 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { } else if (type == TSDB_FILL_SET_VALUE) { tVariantDump(&pCtx->param[1], pCtx->pOutput, pCtx->inputType, true); } else { - if (pCtx->start.key != INT64_MIN && pCtx->start.key < pCtx->startTs && pCtx->end.key > pCtx->startTs) { + if (pCtx->start.key != INT64_MIN && ((ascQuery && pCtx->start.key <= pCtx->startTs && pCtx->end.key >= pCtx->startTs) || ((!ascQuery) && pCtx->start.key >= pCtx->startTs && pCtx->end.key <= pCtx->startTs))) { if (type == TSDB_FILL_PREV) { if (IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL) { SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, pCtx->start.val); @@ -3716,13 +3743,14 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { TSKEY skey = GET_TS_DATA(pCtx, 0); if (type == TSDB_FILL_PREV) { - if (skey > pCtx->startTs) { + if ((ascQuery && skey > pCtx->startTs) || ((!ascQuery) && skey < pCtx->startTs)) { return; } if (pCtx->size > 1) { TSKEY ekey = GET_TS_DATA(pCtx, 1); - if (ekey > skey && ekey <= pCtx->startTs) { + if ((ascQuery && ekey > skey && ekey <= pCtx->startTs) || + ((!ascQuery) && ekey < skey && ekey >= pCtx->startTs)){ skey = ekey; } } @@ -3731,10 +3759,10 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { TSKEY ekey = skey; char* val = NULL; - if (ekey < pCtx->startTs) { + if ((ascQuery && ekey < pCtx->startTs) || ((!ascQuery) && ekey > pCtx->startTs)) { if (pCtx->size > 1) { ekey = GET_TS_DATA(pCtx, 1); - if (ekey < pCtx->startTs) { + if ((ascQuery && ekey < pCtx->startTs) || ((!ascQuery) && ekey > pCtx->startTs)) { return; } @@ -3755,12 +3783,11 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { TSKEY ekey = GET_TS_DATA(pCtx, 1); // no data generated yet - if (!(skey < pCtx->startTs && ekey > pCtx->startTs)) { + if ((ascQuery && !(skey <= pCtx->startTs && ekey >= pCtx->startTs)) + || ((!ascQuery) && !(skey >= pCtx->startTs && ekey <= pCtx->startTs))) { return; } - assert(pCtx->start.key == INT64_MIN && skey < pCtx->startTs && ekey > pCtx->startTs); - char *start = GET_INPUT_DATA(pCtx, 0); char *end = GET_INPUT_DATA(pCtx, 1); @@ -3788,11 +3815,37 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) { static void interp_function(SQLFunctionCtx *pCtx) { // at this point, the value is existed, return directly if (pCtx->size > 0) { - // impose the timestamp check - TSKEY key = GET_TS_DATA(pCtx, 0); + bool ascQuery = (pCtx->order == TSDB_ORDER_ASC); + TSKEY key; + char *pData; + int32_t typedData = 0; + + if (ascQuery) { + key = GET_TS_DATA(pCtx, 0); + pData = GET_INPUT_DATA(pCtx, 0); + } else { + key = pCtx->start.key; + if (key == INT64_MIN) { + key = GET_TS_DATA(pCtx, 0); + pData = GET_INPUT_DATA(pCtx, 0); + } else { + if (!(IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL)) { + pData = pCtx->start.ptr; + } else { + typedData = 1; + pData = (char *)&pCtx->start.val; + } + } + } + + //if (key == pCtx->startTs && (ascQuery || !(IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL))) { if (key == pCtx->startTs) { - char *pData = GET_INPUT_DATA(pCtx, 0); - assignVal(pCtx->pOutput, pData, pCtx->inputBytes, pCtx->inputType); + if (typedData) { + SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, *(double *)pData); + } else { + assignVal(pCtx->pOutput, pData, pCtx->inputBytes, pCtx->inputType); + } + SET_VAL(pCtx, 1, 1); } else { interp_function_impl(pCtx); @@ -4061,7 +4114,7 @@ static void mergeTableBlockDist(SResultRowCellInfo* pResInfo, const STableBlockD } else { pDist->maxRows = pSrc->maxRows; pDist->minRows = pSrc->minRows; - + int32_t maxSteps = TSDB_MAX_MAX_ROW_FBLOCK/TSDB_BLOCK_DIST_STEP_ROWS; if (TSDB_MAX_MAX_ROW_FBLOCK % TSDB_BLOCK_DIST_STEP_ROWS != 0) { ++maxSteps; @@ -4195,7 +4248,7 @@ void blockinfo_func_finalizer(SQLFunctionCtx* pCtx) { taosArrayDestroy(pDist->dataBlockInfos); pDist->dataBlockInfos = NULL; } - + // cannot set the numOfIteratedElems again since it is set during previous iteration pResInfo->numOfRes = 1; pResInfo->hasResult = DATA_SET_FLAG; diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 303612fc8e663e0a304ee1556500456be7720c10..8fefed51c8c8e80d6a6f05d0da74dc1c6075d1bd 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -38,15 +38,12 @@ #define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN) #define TSWINDOW_IS_EQUAL(t1, t2) (((t1).skey == (t2).skey) && ((t1).ekey == (t2).ekey)) - #define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC)) #define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0} #define MULTI_KEY_DELIM "-" -#define HASH_CAPACITY_LIMIT 10000000 - #define TIME_WINDOW_COPY(_dst, _src) do {\ (_dst).skey = (_src).skey;\ (_dst).ekey = (_src).ekey;\ @@ -233,6 +230,12 @@ static void destroyStateWindowOperatorInfo(void* param, int32_t numOfOutput); static void destroyAggOperatorInfo(void* param, int32_t numOfOutput); static void destroyOperatorInfo(SOperatorInfo* pOperator); +static void doSetOperatorCompleted(SOperatorInfo* pOperator) { + pOperator->status = OP_EXEC_DONE; + if (pOperator->pRuntimeEnv != NULL) { + setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); + } +} static int32_t doCopyToSDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SGroupResInfo* pGroupResInfo, int32_t orderType, SSDataBlock* pBlock); @@ -1327,6 +1330,16 @@ void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo, pCtx[k].end.key = curTs; pCtx[k].end.val = v2; + + if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) { + if (prevRowIndex == -1) { + pCtx[k].start.ptr = (char *)pRuntimeEnv->prevRow[index]; + } else { + pCtx[k].start.ptr = (char *)pColInfo->pData + prevRowIndex * pColInfo->info.bytes; + } + + pCtx[k].end.ptr = (char *)pColInfo->pData + curRowIndex * pColInfo->info.bytes; + } } } else if (functionId == TSDB_FUNC_TWA) { SPoint point1 = (SPoint){.key = prevTs, .val = &v1}; @@ -1596,6 +1609,7 @@ static void hashAllIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pRe SResultRow* pResult = NULL; int32_t forwardStep = 0; int32_t ret = 0; + STimeWindow preWin = win; while (1) { // null data, failed to allocate more memory buffer @@ -1610,12 +1624,13 @@ static void hashAllIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pRe // window start(end) key interpolation doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep); - doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput); + doApplyFunctions(pRuntimeEnv, pInfo->pCtx, ascQuery ? &win : &preWin, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput); + preWin = win; int32_t prevEndPos = (forwardStep - 1) * step + startPos; startPos = getNextQualifiedWindow(pQueryAttr, &win, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos); if (startPos < 0) { - if (win.skey <= pQueryAttr->window.ekey) { + if ((ascQuery && win.skey <= pQueryAttr->window.ekey) || ((!ascQuery) && win.ekey >= pQueryAttr->window.ekey)) { int32_t code = setResultOutputBufByKey(pRuntimeEnv, pResultRowInfo, pSDataBlock->info.tid, &win, masterScan, &pResult, tableGroupId, pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset); if (code != TSDB_CODE_SUCCESS || pResult == NULL) { @@ -1626,7 +1641,7 @@ static void hashAllIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pRe // window start(end) key interpolation doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep); - doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput); + doApplyFunctions(pRuntimeEnv, pInfo->pCtx, ascQuery ? &win : &preWin, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput); } break; @@ -2250,30 +2265,30 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf case OP_Fill: { SOperatorInfo* pInfo = pRuntimeEnv->proot; - pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput); + pRuntimeEnv->proot = createFillOperatorInfo(pRuntimeEnv, pInfo, pInfo->pExpr, pInfo->numOfOutput, pQueryAttr->multigroupResult); break; } case OP_MultiwayMergeSort: { - bool groupMix = true; - if (pQueryAttr->slimit.offset != 0 || pQueryAttr->slimit.limit != -1) { - groupMix = false; - } - - pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput, - 4096, merger, groupMix); // TODO hack it + pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput, 4096, merger); break; } - case OP_GlobalAggregate: { + case OP_GlobalAggregate: { // If fill operator exists, the result rows of different group can not be in the same SSDataBlock. + bool multigroupResult = pQueryAttr->multigroupResult; + if (pQueryAttr->multigroupResult) { + multigroupResult = (pQueryAttr->fillType == TSDB_FILL_NONE); + } + pRuntimeEnv->proot = createGlobalAggregateOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, - pQueryAttr->numOfExpr3, merger, pQueryAttr->pUdfInfo); + pQueryAttr->numOfExpr3, merger, pQueryAttr->pUdfInfo, multigroupResult); break; } case OP_SLimit: { - pRuntimeEnv->proot = createSLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr3, - pQueryAttr->numOfExpr3, merger); + int32_t num = pRuntimeEnv->proot->numOfOutput; + SExprInfo* pExpr = pRuntimeEnv->proot->pExpr; + pRuntimeEnv->proot = createSLimitOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pExpr, num, merger, pQueryAttr->multigroupResult); break; } @@ -3570,7 +3585,7 @@ void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, i SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo; int64_t tid = 0; - pRuntimeEnv->keyBuf = realloc(pRuntimeEnv->keyBuf, sizeof(tid) + sizeof(int64_t) + POINTER_BYTES); + pRuntimeEnv->keyBuf = realloc(pRuntimeEnv->keyBuf, sizeof(tid) + sizeof(int64_t) + POINTER_BYTES); SResultRow* pRow = doSetResultOutBufByKey(pRuntimeEnv, pResultRowInfo, tid, (char *)&tid, sizeof(tid), true, uid); for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) { @@ -3591,7 +3606,7 @@ void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, i // set the timestamp output buffer for top/bottom/diff query int32_t fid = pCtx[i].functionId; if (fid == TSDB_FUNC_TOP || fid == TSDB_FUNC_BOTTOM || fid == TSDB_FUNC_DIFF || fid == TSDB_FUNC_DERIVATIVE) { - pCtx[i].ptsOutputBuf = pCtx[0].pOutput; + if (i > 0) pCtx[i].ptsOutputBuf = pCtx[i-1].pOutput; } } @@ -3619,14 +3634,46 @@ void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity, int32_t numOf } } + for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) { SColumnInfoData *pColInfo = taosArrayGet(pDataBlock->pDataBlock, i); pBInfo->pCtx[i].pOutput = pColInfo->pData + pColInfo->info.bytes * pDataBlock->info.rows; - // re-estabilish output buffer pointer. + // set the correct pointer after the memory buffer reallocated. int32_t functionId = pBInfo->pCtx[i].functionId; + if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_DERIVATIVE) { - pBInfo->pCtx[i].ptsOutputBuf = pBInfo->pCtx[i-1].pOutput; + if (i > 0) pBInfo->pCtx[i].ptsOutputBuf = pBInfo->pCtx[i-1].pOutput; + } + } +} + +void copyTsColoum(SSDataBlock* pRes, SQLFunctionCtx* pCtx, int32_t numOfOutput) { + bool needCopyTs = false; + int32_t tsNum = 0; + char *src = NULL; + for (int32_t i = 0; i < numOfOutput; i++) { + int32_t functionId = pCtx[i].functionId; + if (functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_DERIVATIVE) { + needCopyTs = true; + if (i > 0 && pCtx[i-1].functionId == TSDB_FUNC_TS_DUMMY){ + SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, i - 1); // find ts data + src = pColRes->pData; + } + }else if(functionId == TSDB_FUNC_TS_DUMMY) { + tsNum++; + } + } + + if (!needCopyTs) return; + if (tsNum < 2) return; + if (src == NULL) return; + + for (int32_t i = 0; i < numOfOutput; i++) { + int32_t functionId = pCtx[i].functionId; + if(functionId == TSDB_FUNC_TS_DUMMY) { + SColumnInfoData* pColRes = taosArrayGet(pRes->pDataBlock, i); + memcpy(pColRes->pData, src, pColRes->info.bytes * pRes->info.rows); } } } @@ -3644,8 +3691,6 @@ void clearOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity) { } } - - void initCtxOutputBuffer(SQLFunctionCtx* pCtx, int32_t size) { for (int32_t j = 0; j < size; ++j) { SResultRowCellInfo* pResInfo = GET_RES_INFO(&pCtx[j]); @@ -3826,7 +3871,7 @@ void setResultRowOutputBufInitCtx(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pRe } if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF) { - pCtx[i].ptsOutputBuf = pCtx[0].pOutput; + if(i > 0) pCtx[i].ptsOutputBuf = pCtx[i-1].pOutput; } if (!pResInfo->initialized) { @@ -3887,7 +3932,7 @@ void setResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SResultRow *pResult, SQLF int32_t functionId = pCtx[i].functionId; if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_DERIVATIVE) { - pCtx[i].ptsOutputBuf = pCtx[0].pOutput; + if(i > 0) pCtx[i].ptsOutputBuf = pCtx[i-1].pOutput; } /* @@ -4158,6 +4203,7 @@ static void toSSDataBlock(SGroupResInfo *pGroupResInfo, SQueryRuntimeEnv* pRunti // refactor : extract method SColumnInfoData* pInfoData = taosArrayGet(pBlock->pDataBlock, 0); + //add condition (pBlock->info.rows >= 1) just to runtime happy if (pInfoData->info.type == TSDB_DATA_TYPE_TIMESTAMP && pBlock->info.rows >= 1) { STimeWindow* w = &pBlock->info.window; @@ -4265,21 +4311,22 @@ static void doCopyQueryResultToMsg(SQInfo *pQInfo, int32_t numOfRows, char *data } qDebug("QInfo:0x%"PRIx64" set %d subscribe info", pQInfo->qId, total); + // Check if query is completed or not for stable query or normal table query respectively. if (Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) && pRuntimeEnv->proot->status == OP_EXEC_DONE) { setQueryStatus(pRuntimeEnv, QUERY_OVER); } } -int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity) { - void** p = calloc(pFillInfo->numOfCols, POINTER_BYTES); +int32_t doFillTimeIntervalGapsInResults(SFillInfo* pFillInfo, SSDataBlock *pOutput, int32_t capacity, void** p) { for(int32_t i = 0; i < pFillInfo->numOfCols; ++i) { SColumnInfoData* pColInfoData = taosArrayGet(pOutput->pDataBlock, i); - p[i] = pColInfoData->pData; + p[i] = pColInfoData->pData + (pColInfoData->info.bytes * pOutput->info.rows); } - pOutput->info.rows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity); - tfree(p); + int32_t numOfRows = (int32_t)taosFillResultDataBlock(pFillInfo, p, capacity - pOutput->info.rows); + pOutput->info.rows += numOfRows; + return pOutput->info.rows; } @@ -5323,11 +5370,12 @@ static void destroyGlobalAggOperatorInfo(void* param, int32_t numOfOutput) { static void destroySlimitOperatorInfo(void* param, int32_t numOfOutput) { SSLimitOperatorInfo *pInfo = (SSLimitOperatorInfo*) param; taosArrayDestroy(pInfo->orderColumnList); + pInfo->pRes = destroyOutputBuf(pInfo->pRes); tfree(pInfo->prevRow); } SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, - SExprInfo* pExpr, int32_t numOfOutput, void* param, SArray* pUdfInfo) { + SExprInfo* pExpr, int32_t numOfOutput, void* param, SArray* pUdfInfo, bool groupResultMixedUp) { SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo)); pInfo->resultRowFactor = @@ -5335,15 +5383,14 @@ SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, pRuntimeEnv->scanFlag = MERGE_STAGE; // TODO init when creating pCtx - pInfo->pMerge = param; - pInfo->bufCapacity = 4096; - pInfo->udfInfo = pUdfInfo; - - pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity * pInfo->resultRowFactor); - pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset); - - pInfo->orderColumnList = getOrderCheckColumns(pRuntimeEnv->pQueryAttr); - pInfo->groupColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr); + pInfo->multiGroupResults = groupResultMixedUp; + pInfo->pMerge = param; + pInfo->bufCapacity = 4096; + pInfo->udfInfo = pUdfInfo; + pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pInfo->bufCapacity * pInfo->resultRowFactor); + pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset); + pInfo->orderColumnList = getOrderCheckColumns(pRuntimeEnv->pQueryAttr); + pInfo->groupColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr); // TODO refactor int32_t len = 0; @@ -5396,17 +5443,15 @@ SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, } SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SExprInfo *pExpr, int32_t numOfOutput, - int32_t numOfRows, void *merger, bool groupMix) { + int32_t numOfRows, void *merger) { SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo)); - pInfo->pMerge = merger; - pInfo->groupMix = groupMix; - pInfo->bufCapacity = numOfRows; - + pInfo->pMerge = merger; + pInfo->bufCapacity = numOfRows; pInfo->orderColumnList = getResultGroupCheckColumns(pRuntimeEnv->pQueryAttr); - pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows); + pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows); - { + { // todo extract method to create prev compare buffer int32_t len = 0; for(int32_t i = 0; i < numOfOutput; ++i) { len += pExpr[i].base.colBytes; @@ -5414,8 +5459,8 @@ SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SEx int32_t numOfCols = (pInfo->orderColumnList != NULL)? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0; pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len)); - int32_t offset = POINTER_BYTES * numOfCols; + int32_t offset = POINTER_BYTES * numOfCols; for(int32_t i = 0; i < numOfCols; ++i) { pInfo->prevRow[i] = (char*)pInfo->prevRow + offset; @@ -5431,7 +5476,8 @@ SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SEx pOperator->status = OP_IN_EXECUTING; pOperator->info = pInfo; pOperator->pRuntimeEnv = pRuntimeEnv; - pOperator->numOfOutput = pRuntimeEnv->pQueryAttr->numOfCols; + pOperator->numOfOutput = numOfOutput; + pOperator->pExpr = pExpr; pOperator->exec = doMultiwayMergeSort; pOperator->cleanup = destroyGlobalAggOperatorInfo; return pOperator; @@ -5477,8 +5523,7 @@ static SSDataBlock* doSort(void* param, bool* newgroup) { // start to flush data into disk and try do multiway merge sort if (pBlock == NULL) { - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); break; } @@ -5589,8 +5634,7 @@ static SSDataBlock* doAggregate(void* param, bool* newgroup) { doAggregateImpl(pOperator, pQueryAttr->window.skey, pInfo->pCtx, pBlock); } - pOperator->status = OP_EXEC_DONE; - setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); + doSetOperatorCompleted(pOperator); finalizeQueryResult(pOperator, pInfo->pCtx, &pInfo->resultRowInfo, pInfo->rowCellInfoOffset); pInfo->pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput); @@ -5666,7 +5710,7 @@ static SSDataBlock* doSTableAggregate(void* param, bool* newgroup) { toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pInfo->pRes); if (pInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); } return pInfo->pRes; @@ -5707,6 +5751,7 @@ static SSDataBlock* doProjectOperation(void* param, bool* newgroup) { pRes->info.rows = getNumOfResult(pRuntimeEnv, pInfo->pCtx, pOperator->numOfOutput); if (pRes->info.rows >= pRuntimeEnv->resultInfo.threshold) { + copyTsColoum(pRes, pInfo->pCtx, pOperator->numOfOutput); clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput); return pRes; } @@ -5732,8 +5777,7 @@ static SSDataBlock* doProjectOperation(void* param, bool* newgroup) { if (*newgroup) { if (pRes->info.rows > 0) { pProjectInfo->existDataBlock = pBlock; - clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput); - return pInfo->pRes; + break; } else { // init output buffer for a new group data for (int32_t j = 0; j < pOperator->numOfOutput; ++j) { aAggs[pInfo->pCtx[j].functionId].xFinalize(&pInfo->pCtx[j]); @@ -5763,7 +5807,7 @@ static SSDataBlock* doProjectOperation(void* param, bool* newgroup) { break; } } - + copyTsColoum(pRes, pInfo->pCtx, pOperator->numOfOutput); clearNumOfRes(pInfo->pCtx, pOperator->numOfOutput); return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL; } @@ -5784,8 +5828,7 @@ static SSDataBlock* doLimit(void* param, bool* newgroup) { publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); return NULL; } @@ -5813,8 +5856,7 @@ static SSDataBlock* doLimit(void* param, bool* newgroup) { pBlock->info.rows = (int32_t)(pInfo->limit - pInfo->total); pInfo->total = pInfo->limit; - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); } else { pInfo->total += pBlock->info.rows; } @@ -5849,8 +5891,7 @@ static SSDataBlock* doFilter(void* param, bool* newgroup) { } } - setQueryStatus(pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); return NULL; } @@ -5865,9 +5906,8 @@ static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) { SQueryRuntimeEnv* pRuntimeEnv = pOperator->pRuntimeEnv; if (pOperator->status == OP_RES_TO_RETURN) { toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes); - if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); } return pIntervalInfo->pRes; @@ -5908,7 +5948,7 @@ static SSDataBlock* doIntervalAgg(void* param, bool* newgroup) { toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes); if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); } return pIntervalInfo->pRes->info.rows == 0? NULL:pIntervalInfo->pRes; @@ -5927,7 +5967,7 @@ static SSDataBlock* doAllIntervalAgg(void* param, bool* newgroup) { toSSDataBlock(&pRuntimeEnv->groupResInfo, pRuntimeEnv, pIntervalInfo->pRes); if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainDataInCurrentGroup(&pRuntimeEnv->groupResInfo)) { - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); } return pIntervalInfo->pRes; @@ -5985,9 +6025,10 @@ static SSDataBlock* doSTableIntervalAgg(void* param, bool* newgroup) { if (pOperator->status == OP_RES_TO_RETURN) { int64_t st = taosGetTimestampUs(); + copyToSDataBlock(pRuntimeEnv, 3000, pIntervalInfo->pRes, pIntervalInfo->rowCellInfoOffset); if (pIntervalInfo->pRes->info.rows == 0 || !hasRemainData(&pRuntimeEnv->groupResInfo)) { - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); } SQInfo* pQInfo = pRuntimeEnv->qinfo; @@ -6347,34 +6388,48 @@ static SSDataBlock* hashGroupbyAggregate(void* param, bool* newgroup) { return pInfo->binfo.pRes; } -static SSDataBlock* doFill(void* param, bool* newgroup) { - SOperatorInfo* pOperator = (SOperatorInfo*) param; - if (pOperator->status == OP_EXEC_DONE) { - return NULL; - } +static void doHandleRemainBlockForNewGroupImpl(SFillOperatorInfo *pInfo, SQueryRuntimeEnv* pRuntimeEnv, bool* newgroup) { + pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows; + int64_t ekey = Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)?pRuntimeEnv->pQueryAttr->window.ekey:pInfo->existNewGroupBlock->info.window.ekey; + taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start); - SFillOperatorInfo *pInfo = pOperator->info; - SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv; + taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey); + taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock); + + doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity, pInfo->p); + pInfo->existNewGroupBlock = NULL; + *newgroup = true; +} +static void doHandleRemainBlockFromNewGroup(SFillOperatorInfo *pInfo, SQueryRuntimeEnv *pRuntimeEnv, bool *newgroup) { if (taosFillHasMoreResults(pInfo->pFillInfo)) { *newgroup = false; - doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity); - return pInfo->pRes; + doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, (int32_t)pRuntimeEnv->resultInfo.capacity, pInfo->p); + if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold || (!pInfo->multigroupResult)) { + return; + } } // handle the cached new group data block if (pInfo->existNewGroupBlock) { - pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows; - int64_t ekey = Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED)?pRuntimeEnv->pQueryAttr->window.ekey:pInfo->existNewGroupBlock->info.window.ekey; - taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start); + doHandleRemainBlockForNewGroupImpl(pInfo, pRuntimeEnv, newgroup); + } +} + +static SSDataBlock* doFill(void* param, bool* newgroup) { + SOperatorInfo* pOperator = (SOperatorInfo*) param; - taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey); - taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock); + SFillOperatorInfo *pInfo = pOperator->info; + pInfo->pRes->info.rows = 0; - doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity); - pInfo->existNewGroupBlock = NULL; - *newgroup = true; - return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } + + SQueryRuntimeEnv *pRuntimeEnv = pOperator->pRuntimeEnv; + doHandleRemainBlockFromNewGroup(pInfo, pRuntimeEnv, newgroup); + if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold || (!pInfo->multigroupResult && pInfo->pRes->info.rows > 0)) { + return pInfo->pRes; } while(1) { @@ -6390,8 +6445,8 @@ static SSDataBlock* doFill(void* param, bool* newgroup) { pInfo->existNewGroupBlock = pBlock; *newgroup = false; - // fill the previous group data block - // before handle a new data block, close the fill operation for previous group data block + // Fill the previous group data block, before handle the data block of new group. + // Close the fill operation for previous group data block taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey); } else { if (pBlock == NULL) { @@ -6403,36 +6458,35 @@ static SSDataBlock* doFill(void* param, bool* newgroup) { taosFillSetStartInfo(pInfo->pFillInfo, 0, pRuntimeEnv->pQueryAttr->window.ekey); } else { pInfo->totalInputRows += pBlock->info.rows; - - int64_t ekey = /*Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) ? pRuntimeEnv->pQueryAttr->window.ekey - : */pBlock->info.window.ekey; - - taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, ekey); + taosFillSetStartInfo(pInfo->pFillInfo, pBlock->info.rows, pBlock->info.window.ekey); taosFillSetInputDataBlock(pInfo->pFillInfo, pBlock); } } - doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity); - if (pInfo->pRes->info.rows > 0) { // current group has no more result to return - return pInfo->pRes; - } else if (pInfo->existNewGroupBlock) { // try next group - pInfo->totalInputRows = pInfo->existNewGroupBlock->info.rows; - int64_t ekey = /*Q_STATUS_EQUAL(pRuntimeEnv->status, QUERY_COMPLETED) ? pRuntimeEnv->pQueryAttr->window.ekey - :*/ pInfo->existNewGroupBlock->info.window.ekey; - taosResetFillInfo(pInfo->pFillInfo, pInfo->pFillInfo->start); + doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity, pInfo->p); - taosFillSetStartInfo(pInfo->pFillInfo, pInfo->existNewGroupBlock->info.rows, ekey); - taosFillSetInputDataBlock(pInfo->pFillInfo, pInfo->existNewGroupBlock); + // current group has no more result to return + if (pInfo->pRes->info.rows > 0) { + // 1. The result in current group not reach the threshold of output result, continue + // 2. If multiple group results existing in one SSDataBlock is not allowed, return immediately + if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold || pBlock == NULL || (!pInfo->multigroupResult)) { + return pInfo->pRes; + } - doFillTimeIntervalGapsInResults(pInfo->pFillInfo, pInfo->pRes, pRuntimeEnv->resultInfo.capacity); - pInfo->existNewGroupBlock = NULL; - *newgroup = true; + doHandleRemainBlockFromNewGroup(pInfo, pRuntimeEnv, newgroup); + if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold || pBlock == NULL) { + return pInfo->pRes; + } + } else if (pInfo->existNewGroupBlock) { // try next group + assert(pBlock != NULL); + doHandleRemainBlockForNewGroupImpl(pInfo, pRuntimeEnv, newgroup); - return (pInfo->pRes->info.rows > 0) ? pInfo->pRes : NULL; + if (pInfo->pRes->info.rows > pRuntimeEnv->resultInfo.threshold) { + return pInfo->pRes; + } } else { return NULL; } - // return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL; } } @@ -6533,6 +6587,7 @@ static void destroySFillOperatorInfo(void* param, int32_t numOfOutput) { SFillOperatorInfo* pInfo = (SFillOperatorInfo*) param; pInfo->pFillInfo = taosDestroyFillInfo(pInfo->pFillInfo); pInfo->pRes = destroyOutputBuf(pInfo->pRes); + tfree(pInfo->p); } static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput) { @@ -6876,10 +6931,10 @@ SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperato return pOperator; } -SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, - int32_t numOfOutput) { +SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, bool multigroupResult) { SFillOperatorInfo* pInfo = calloc(1, sizeof(SFillOperatorInfo)); pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity); + pInfo->multigroupResult = multigroupResult; { SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; @@ -6894,6 +6949,8 @@ SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorIn taosCreateFillInfo(pQueryAttr->order.order, w.skey, 0, (int32_t)pRuntimeEnv->resultInfo.capacity, numOfOutput, pQueryAttr->interval.sliding, pQueryAttr->interval.slidingUnit, (int8_t)pQueryAttr->precision, pQueryAttr->fillType, pColInfo, pRuntimeEnv->qinfo); + + pInfo->p = calloc(pInfo->pFillInfo->numOfCols, POINTER_BYTES); } SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); @@ -6913,7 +6970,7 @@ SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorIn return pOperator; } -SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* pMerger) { +SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, void* pMerger, bool multigroupResult) { SSLimitOperatorInfo* pInfo = calloc(1, sizeof(SSLimitOperatorInfo)); SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr; @@ -6921,9 +6978,11 @@ SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperator pInfo->orderColumnList = getResultGroupCheckColumns(pQueryAttr); pInfo->slimit = pQueryAttr->slimit; pInfo->limit = pQueryAttr->limit; - + pInfo->capacity = pRuntimeEnv->resultInfo.capacity; + pInfo->threshold = (int64_t)(pInfo->capacity * 0.8); + pInfo->currentOffset = pQueryAttr->limit.offset; pInfo->currentGroupOffset = pQueryAttr->slimit.offset; - pInfo->currentOffset = pQueryAttr->limit.offset; + pInfo->multigroupResult= multigroupResult; // TODO refactor int32_t len = 0; @@ -6931,10 +6990,10 @@ SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperator len += pExpr[i].base.resBytes; } - int32_t numOfCols = pInfo->orderColumnList != NULL? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0; + int32_t numOfCols = (pInfo->orderColumnList != NULL)? (int32_t) taosArrayGetSize(pInfo->orderColumnList):0; pInfo->prevRow = calloc(1, (POINTER_BYTES * numOfCols + len)); - int32_t offset = POINTER_BYTES * numOfCols; + int32_t offset = POINTER_BYTES * numOfCols; for(int32_t i = 0; i < numOfCols; ++i) { pInfo->prevRow[i] = (char*)pInfo->prevRow + offset; @@ -6942,6 +7001,8 @@ SOperatorInfo* createSLimitOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperator offset += pExpr[index->colIndex].base.resBytes; } + pInfo->pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity); + SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo)); pOperator->name = "SLimitOperator"; @@ -7079,6 +7140,10 @@ static SSDataBlock* doTagScan(void* param, bool* newgroup) { qDebug("QInfo:0x%"PRIx64" create tag values results completed, rows:%d", GET_QID(pRuntimeEnv), count); } + if (pOperator->status == OP_EXEC_DONE) { + setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); + } + pRes->info.rows = count; return (pRes->info.rows == 0)? NULL:pInfo->pRes; } @@ -7122,14 +7187,14 @@ static bool initMultiDistinctInfo(SDistinctOperatorInfo *pInfo, SOperatorInfo* p SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, j); if (pColDataInfo->info.colId == pOperator->pExpr[i].base.resColId) { SDistinctDataInfo item = {.index = j, .type = pColDataInfo->info.type, .bytes = pColDataInfo->info.bytes}; - taosArrayInsert(pInfo->pDistinctDataInfo, i, &item); + taosArrayInsert(pInfo->pDistinctDataInfo, i, &item); } } } pInfo->totalBytes += (int32_t)strlen(MULTI_KEY_DELIM) * (pOperator->numOfOutput); pInfo->buf = calloc(1, pInfo->totalBytes); return taosArrayGetSize(pInfo->pDistinctDataInfo) == pOperator->numOfOutput ? true : false; -} +} static void buildMultiDistinctKey(SDistinctOperatorInfo *pInfo, SSDataBlock *pBlock, int32_t rowId) { char *p = pInfo->buf; @@ -7154,11 +7219,13 @@ static void buildMultiDistinctKey(SDistinctOperatorInfo *pInfo, SSDataBlock *pBl p += strlen(MULTI_KEY_DELIM); } } + static SSDataBlock* hashDistinct(void* param, bool* newgroup) { SOperatorInfo* pOperator = (SOperatorInfo*) param; if (pOperator->status == OP_EXEC_DONE) { return NULL; } + SDistinctOperatorInfo* pInfo = pOperator->info; SSDataBlock* pRes = pInfo->pRes; @@ -7171,13 +7238,11 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) { publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC); if (pBlock == NULL) { - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); break; } if (!initMultiDistinctInfo(pInfo, pOperator, pBlock)) { - setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED); - pOperator->status = OP_EXEC_DONE; + doSetOperatorCompleted(pOperator); break; } // ensure result output buf @@ -7213,11 +7278,11 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) { pRes->info.rows += 1; } } + if (pRes->info.rows >= pInfo->threshold) { break; } } - return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL; } @@ -7434,12 +7499,15 @@ int32_t convertQueryMsg(SQueryTableMsg *pQueryMsg, SQueryParam* param) { pQueryMsg->numOfCols = htons(pQueryMsg->numOfCols); pQueryMsg->numOfOutput = htons(pQueryMsg->numOfOutput); pQueryMsg->numOfGroupCols = htons(pQueryMsg->numOfGroupCols); + 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); pQueryMsg->tsBuf.tsOrder = htonl(pQueryMsg->tsBuf.tsOrder); + pQueryMsg->numOfTags = htonl(pQueryMsg->numOfTags); pQueryMsg->tbnameCondLen = htonl(pQueryMsg->tbnameCondLen); pQueryMsg->secondStageOutput = htonl(pQueryMsg->secondStageOutput); diff --git a/src/query/src/qExtbuffer.c b/src/query/src/qExtbuffer.c index 9f9347b327cbe5328db5c1b209b7f2ba582d5a97..5994099a0d1ad6b1a87aa19edb6151680128f6df 100644 --- a/src/query/src/qExtbuffer.c +++ b/src/query/src/qExtbuffer.c @@ -768,60 +768,6 @@ void tColDataQSort(tOrderDescriptor *pDescriptor, int32_t numOfRows, int32_t sta free(buf); } -void taoscQSort(void** pCols, SSchema* pSchema, int32_t numOfCols, int32_t numOfRows, int32_t index, __compar_fn_t compareFn) { - assert(numOfRows > 0 && numOfCols > 0 && index >= 0 && index < numOfCols); - - int32_t bytes = pSchema[index].bytes; - int32_t size = bytes + sizeof(int32_t); - - char* buf = calloc(1, size * numOfRows); - - for(int32_t i = 0; i < numOfRows; ++i) { - char* dest = buf + size * i; - memcpy(dest, ((char*)pCols[index]) + bytes * i, bytes); - *(int32_t*)(dest+bytes) = i; - } - - qsort(buf, numOfRows, size, compareFn); - - int32_t prevLength = 0; - char* p = NULL; - - for(int32_t i = 0; i < numOfCols; ++i) { - int32_t bytes1 = pSchema[i].bytes; - - if (i == index) { - for(int32_t j = 0; j < numOfRows; ++j){ - char* src = buf + (j * size); - char* dest = (char*) pCols[i] + (j * bytes1); - memcpy(dest, src, bytes1); - } - } else { - // make sure memory buffer is enough - if (prevLength < bytes1) { - char *tmp = realloc(p, bytes1 * numOfRows); - assert(tmp); - - p = tmp; - prevLength = bytes1; - } - - memcpy(p, pCols[i], bytes1 * numOfRows); - - for(int32_t j = 0; j < numOfRows; ++j){ - char* dest = (char*) pCols[i] + bytes1 * j; - - int32_t newPos = *(int32_t*)(buf + (j * size) + bytes); - char* src = p + (newPos * bytes1); - memcpy(dest, src, bytes1); - } - } - } - - tfree(buf); - tfree(p); -} - /* * deep copy of sschema */ @@ -1157,3 +1103,57 @@ void tOrderDescDestroy(tOrderDescriptor *pDesc) { destroyColumnModel(pDesc->pColumnModel); tfree(pDesc); } + +void taoscQSort(void** pCols, SSchema* pSchema, int32_t numOfCols, int32_t numOfRows, int32_t index, __compar_fn_t compareFn) { + assert(numOfRows > 0 && numOfCols > 0 && index >= 0 && index < numOfCols); + + int32_t bytes = pSchema[index].bytes; + int32_t size = bytes + sizeof(int32_t); + + char* buf = calloc(1, size * numOfRows); + + for(int32_t i = 0; i < numOfRows; ++i) { + char* dest = buf + size * i; + memcpy(dest, ((char*) pCols[index]) + bytes * i, bytes); + *(int32_t*)(dest+bytes) = i; + } + + qsort(buf, numOfRows, size, compareFn); + + int32_t prevLength = 0; + char* p = NULL; + + for(int32_t i = 0; i < numOfCols; ++i) { + int32_t bytes1 = pSchema[i].bytes; + + if (i == index) { + for(int32_t j = 0; j < numOfRows; ++j){ + char* src = buf + (j * size); + char* dest = ((char*)pCols[i]) + (j * bytes1); + memcpy(dest, src, bytes1); + } + } else { + // make sure memory buffer is enough + if (prevLength < bytes1) { + char *tmp = realloc(p, bytes1 * numOfRows); + assert(tmp); + + p = tmp; + prevLength = bytes1; + } + + memcpy(p, pCols[i], bytes1 * numOfRows); + + for(int32_t j = 0; j < numOfRows; ++j){ + char* dest = ((char*)pCols[i]) + bytes1 * j; + + int32_t newPos = *(int32_t*)(buf + (j * size) + bytes); + char* src = p + (newPos * bytes1); + memcpy(dest, src, bytes1); + } + } + } + + tfree(buf); + tfree(p); +} diff --git a/src/query/src/qFill.c b/src/query/src/qFill.c index 1a86bbae36697224585522b5be836c61394c7cc4..cdcc164152dddbc34d03508a2bdd7379d6e50892 100644 --- a/src/query/src/qFill.c +++ b/src/query/src/qFill.c @@ -430,7 +430,7 @@ void taosFillSetInputDataBlock(SFillInfo* pFillInfo, const SSDataBlock* pInput) SColumnInfoData* pColData = taosArrayGet(pInput->pDataBlock, i); pFillInfo->pData[i] = pColData->pData; - if (TSDB_COL_IS_TAG(pCol->flag)/* || IS_VAR_DATA_TYPE(pCol->col.type)*/) { // copy the tag value to tag value buffer + if (TSDB_COL_IS_TAG(pCol->flag)) { // copy the tag value to tag value buffer SFillTagColInfo* pTag = &pFillInfo->pTags[pCol->tagIndex]; assert (pTag->col.colId == pCol->col.colId); memcpy(pTag->tagVal, pColData->pData, pCol->col.bytes); // TODO not memcpy?? diff --git a/src/query/src/qFilter.c b/src/query/src/qFilter.c index 72f8376af6d5b7d25ba154a95e034be4eb0e6f66..a6988d7adc403cd518e6fce91899a515305ab5c0 100644 --- a/src/query/src/qFilter.c +++ b/src/query/src/qFilter.c @@ -28,6 +28,7 @@ OptrStr gOptrStr[] = { {TSDB_RELATION_GREATER_EQUAL, ">="}, {TSDB_RELATION_NOT_EQUAL, "!="}, {TSDB_RELATION_LIKE, "like"}, + {TSDB_RELATION_MATCH, "match"}, {TSDB_RELATION_ISNULL, "is null"}, {TSDB_RELATION_NOTNULL, "not null"}, {TSDB_RELATION_IN, "in"}, @@ -156,7 +157,7 @@ int8_t filterGetRangeCompFuncFromOptrs(uint8_t optr, uint8_t optr2) { __compar_fn_t gDataCompare[] = {compareInt32Val, compareInt8Val, compareInt16Val, compareInt64Val, compareFloatVal, compareDoubleVal, compareLenPrefixedStr, compareStrPatternComp, compareFindItemInSet, compareWStrPatternComp, compareLenPrefixedWStr, compareUint8Val, compareUint16Val, compareUint32Val, compareUint64Val, - setCompareBytes1, setCompareBytes2, setCompareBytes4, setCompareBytes8 + setCompareBytes1, setCompareBytes2, setCompareBytes4, setCompareBytes8, compareStrRegexComp, }; int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) { @@ -195,7 +196,9 @@ int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) { 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 */ + if (optr == TSDB_RELATION_MATCH) { + comparFn = 19; + } else if (optr == TSDB_RELATION_LIKE) { /* wildcard query using like operator */ comparFn = 7; } else if (optr == TSDB_RELATION_IN) { comparFn = 8; @@ -207,7 +210,9 @@ int8_t filterGetCompFuncIdx(int32_t type, int32_t optr) { } case TSDB_DATA_TYPE_NCHAR: { - if (optr == TSDB_RELATION_LIKE) { + if (optr == TSDB_RELATION_MATCH) { + comparFn = 19; + } else if (optr == TSDB_RELATION_LIKE) { comparFn = 9; } else if (optr == TSDB_RELATION_IN) { comparFn = 8; @@ -1871,6 +1876,9 @@ bool filterDoCompare(__compar_fn_t func, uint8_t optr, void *left, void *right) case TSDB_RELATION_LIKE: { return ret == 0; } + case TSDB_RELATION_MATCH: { + return ret == 0; + } case TSDB_RELATION_IN: { return ret == 1; } @@ -2641,7 +2649,7 @@ int32_t filterRmUnitByRange(SFilterInfo *info, SDataStatis *pDataStatis, int32_t } if (cunit->optr == TSDB_RELATION_ISNULL || cunit->optr == TSDB_RELATION_NOTNULL - || cunit->optr == TSDB_RELATION_IN || cunit->optr == TSDB_RELATION_LIKE + || cunit->optr == TSDB_RELATION_IN || cunit->optr == TSDB_RELATION_LIKE || cunit->optr == TSDB_RELATION_MATCH || cunit->optr == TSDB_RELATION_NOT_EQUAL) { continue; } diff --git a/src/query/src/qPlan.c b/src/query/src/qPlan.c index f72f70c91179eac860a831cf02821f88651da2ac..1988fc9df7710f15770ca8a9994542d9f4bc8c66 100644 --- a/src/query/src/qPlan.c +++ b/src/query/src/qPlan.c @@ -698,7 +698,7 @@ SArray* createGlobalMergePlan(SQueryAttr* pQueryAttr) { } // fill operator - if (pQueryAttr->fillType != TSDB_FILL_NONE && (!pQueryAttr->pointInterpQuery)) { + if (pQueryAttr->fillType != TSDB_FILL_NONE && pQueryAttr->interval.interval > 0) { op = OP_Fill; taosArrayPush(plan, &op); } diff --git a/src/query/src/qSqlParser.c b/src/query/src/qSqlParser.c index 011892fe93f3dc941b17ef7b22313c11fca23d74..d156230efbc75c46205637747bb58f86d13763fe 100644 --- a/src/query/src/qSqlParser.c +++ b/src/query/src/qSqlParser.c @@ -766,7 +766,7 @@ SSqlNode *tSetQuerySqlNode(SStrToken *pSelectToken, SArray *pSelNodeList, SRelat pSqlNode->pSortOrder = pSortOrder; pSqlNode->pWhere = pWhere; pSqlNode->fillType = pFill; - pSqlNode->pHaving = pHaving; + pSqlNode->pHaving = pHaving; if (pLimit != NULL) { pSqlNode->limit = *pLimit; diff --git a/src/query/src/qTsbuf.c b/src/query/src/qTsbuf.c index 825b7960defc2547dfd7248bdc15d157e5808b24..4cf05dd2c7703c7879410faa2632e17a16d595fd 100644 --- a/src/query/src/qTsbuf.c +++ b/src/query/src/qTsbuf.c @@ -223,8 +223,11 @@ static STSGroupBlockInfoEx* addOneGroupInfo(STSBuf* pTSBuf, int32_t id) { static void shrinkBuffer(STSList* ptsData) { // shrink tmp buffer size if it consumes too many memory compared to the pre-defined size if (ptsData->allocSize >= ptsData->threshold * 2) { - ptsData->rawBuf = realloc(ptsData->rawBuf, MEM_BUF_SIZE); - ptsData->allocSize = MEM_BUF_SIZE; + char* rawBuf = realloc(ptsData->rawBuf, MEM_BUF_SIZE); + if(rawBuf) { + ptsData->rawBuf = rawBuf; + ptsData->allocSize = MEM_BUF_SIZE; + } } } diff --git a/src/query/src/queryMain.c b/src/query/src/queryMain.c index d25f5eab7a60569f13d0602ebbaac3c0d7ff2aac..d56c12ab8735d0683db146f7000429d4d554dda5 100644 --- a/src/query/src/queryMain.c +++ b/src/query/src/queryMain.c @@ -357,7 +357,7 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co } (*pRsp)->precision = htons(pQueryAttr->precision); - (*pRsp)->compressed = (int8_t)(tsCompressColData && checkNeedToCompressQueryCol(pQInfo)); + (*pRsp)->compressed = (int8_t)((tsCompressColData != -1) && checkNeedToCompressQueryCol(pQInfo)); if (GET_NUM_OF_RESULTS(&(pQInfo->runtimeEnv)) > 0 && pQInfo->code == TSDB_CODE_SUCCESS) { doDumpQueryResult(pQInfo, (*pRsp)->data, (*pRsp)->compressed, &compLen); @@ -367,8 +367,12 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co if ((*pRsp)->compressed && compLen != 0) { int32_t numOfCols = pQueryAttr->pExpr2 ? pQueryAttr->numOfExpr2 : pQueryAttr->numOfOutput; - *contLen = *contLen - pQueryAttr->resultRowSize * s + compLen + numOfCols * sizeof(int32_t); + int32_t origSize = pQueryAttr->resultRowSize * s; + int32_t compSize = compLen + numOfCols * sizeof(int32_t); + *contLen = *contLen - origSize + compSize; *pRsp = (SRetrieveTableRsp *)rpcReallocCont(*pRsp, *contLen); + qDebug("QInfo:0x%"PRIx64" compress col data, uncompressed size:%d, compressed size:%d, ratio:%.2f", + pQInfo->qId, origSize, compSize, (float)origSize / (float)compSize); } (*pRsp)->compLen = htonl(compLen); diff --git a/src/query/src/sql.c b/src/query/src/sql.c index 09be4c0cf09df7560b52fc0704a856369946cf38..f66c2968a6cebf805579dc3fe4c123331f9ecfc8 100644 --- a/src/query/src/sql.c +++ b/src/query/src/sql.c @@ -102,28 +102,29 @@ #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 275 +#define YYNOCODE 277 #define YYACTIONTYPE unsigned short int #define ParseTOKENTYPE SStrToken typedef union { int yyinit; ParseTOKENTYPE yy0; - 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; + SCreateTableSql* yy56; + int yy70; + SCreatedTableInfo yy84; + SRelationInfo* yy114; + int32_t yy202; + SIntervalVal yy222; + SSqlNode* yy224; + SCreateDbInfo yy246; + tSqlExpr* yy260; + TAOS_FIELD yy363; + SSessionWindowVal yy365; + SCreateAcctInfo yy377; + int64_t yy387; + SArray* yy403; + SLimitVal yy404; + tVariant yy488; + SWindowStateVal yy544; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -139,18 +140,18 @@ typedef union { #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 -#define YY_MAX_SHIFTREDUCE 855 -#define YY_ERROR_ACTION 856 -#define YY_ACCEPT_ACTION 857 -#define YY_NO_ACTION 858 -#define YY_MIN_REDUCE 859 -#define YY_MAX_REDUCE 1147 +#define YYNSTATE 366 +#define YYNRULE 293 +#define YYNRULE_WITH_ACTION 293 +#define YYNTOKEN 196 +#define YY_MAX_SHIFT 365 +#define YY_MIN_SHIFTREDUCE 574 +#define YY_MAX_SHIFTREDUCE 866 +#define YY_ERROR_ACTION 867 +#define YY_ACCEPT_ACTION 868 +#define YY_NO_ACTION 869 +#define YY_MIN_REDUCE 870 +#define YY_MAX_REDUCE 1162 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -217,288 +218,291 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (754) +#define YY_ACTTAB_COUNT (766) static const YYACTIONTYPE yy_action[] = { - /* 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, 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, 858, 145, 146, + /* 0 */ 1020, 626, 239, 626, 364, 233, 1026, 1039, 210, 627, + /* 10 */ 662, 627, 38, 58, 59, 38, 62, 63, 1048, 1138, + /* 20 */ 253, 52, 51, 236, 61, 322, 66, 64, 67, 65, + /* 30 */ 1039, 810, 245, 813, 57, 56, 1026, 23, 55, 54, + /* 40 */ 53, 58, 59, 626, 62, 63, 237, 246, 253, 52, + /* 50 */ 51, 627, 61, 322, 66, 64, 67, 65, 868, 365, + /* 60 */ 235, 1022, 57, 56, 1023, 250, 55, 54, 53, 988, + /* 70 */ 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, + /* 80 */ 986, 987, 989, 990, 156, 29, 1045, 81, 575, 576, + /* 90 */ 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, + /* 100 */ 587, 588, 154, 163, 234, 172, 58, 59, 1039, 62, + /* 110 */ 63, 1012, 804, 253, 52, 51, 72, 61, 322, 66, + /* 120 */ 64, 67, 65, 284, 275, 210, 352, 57, 56, 262, + /* 130 */ 163, 55, 54, 53, 58, 60, 1139, 62, 63, 75, + /* 140 */ 177, 253, 52, 51, 626, 61, 322, 66, 64, 67, + /* 150 */ 65, 817, 627, 282, 281, 57, 56, 267, 73, 55, + /* 160 */ 54, 53, 59, 163, 62, 63, 271, 270, 253, 52, + /* 170 */ 51, 320, 61, 322, 66, 64, 67, 65, 1087, 76, + /* 180 */ 294, 247, 57, 56, 207, 1026, 55, 54, 53, 62, + /* 190 */ 63, 38, 249, 253, 52, 51, 320, 61, 322, 66, + /* 200 */ 64, 67, 65, 296, 710, 92, 87, 57, 56, 769, + /* 210 */ 770, 55, 54, 53, 44, 318, 359, 358, 317, 316, + /* 220 */ 315, 357, 314, 313, 312, 356, 311, 355, 354, 24, + /* 230 */ 163, 252, 819, 342, 341, 808, 243, 811, 1086, 814, + /* 240 */ 1023, 252, 819, 45, 208, 808, 213, 811, 254, 814, + /* 250 */ 57, 56, 210, 220, 55, 54, 53, 96, 262, 138, + /* 260 */ 137, 136, 219, 1139, 231, 232, 327, 87, 323, 178, + /* 270 */ 99, 5, 41, 181, 231, 232, 360, 957, 180, 105, + /* 280 */ 110, 101, 109, 363, 362, 147, 66, 64, 67, 65, + /* 290 */ 1009, 1010, 35, 1013, 57, 56, 919, 307, 55, 54, + /* 300 */ 53, 256, 929, 191, 45, 93, 1014, 734, 210, 191, + /* 310 */ 731, 38, 732, 68, 733, 261, 262, 214, 44, 1139, + /* 320 */ 359, 358, 124, 68, 215, 357, 274, 1024, 79, 356, + /* 330 */ 1134, 355, 354, 1133, 352, 227, 122, 116, 127, 258, + /* 340 */ 259, 750, 809, 126, 812, 132, 135, 125, 820, 815, + /* 350 */ 920, 1025, 38, 38, 129, 816, 244, 191, 820, 815, + /* 360 */ 1023, 201, 199, 197, 38, 816, 80, 38, 196, 142, + /* 370 */ 141, 140, 139, 996, 14, 994, 995, 257, 95, 255, + /* 380 */ 997, 330, 329, 786, 998, 38, 999, 1000, 38, 324, + /* 390 */ 38, 263, 84, 260, 85, 337, 336, 331, 332, 38, + /* 400 */ 1011, 1023, 1023, 55, 54, 53, 94, 1132, 98, 333, + /* 410 */ 1, 179, 334, 1023, 3, 192, 1023, 153, 151, 150, + /* 420 */ 82, 747, 276, 735, 736, 34, 754, 766, 776, 278, + /* 430 */ 338, 278, 777, 339, 1023, 340, 39, 1023, 806, 1023, + /* 440 */ 785, 158, 69, 720, 344, 299, 26, 9, 1023, 251, + /* 450 */ 722, 301, 721, 841, 821, 625, 78, 39, 302, 39, + /* 460 */ 229, 16, 818, 15, 69, 97, 69, 25, 25, 25, + /* 470 */ 115, 6, 114, 1158, 18, 807, 17, 739, 737, 740, + /* 480 */ 738, 20, 121, 19, 120, 22, 230, 21, 709, 134, + /* 490 */ 133, 211, 823, 212, 216, 1150, 209, 1097, 217, 218, + /* 500 */ 222, 223, 224, 221, 206, 1096, 241, 1093, 1092, 242, + /* 510 */ 343, 272, 155, 48, 1047, 1058, 1055, 1056, 1060, 157, + /* 520 */ 1040, 279, 1079, 162, 290, 1078, 173, 1021, 174, 1019, + /* 530 */ 175, 176, 934, 283, 238, 152, 167, 165, 304, 305, + /* 540 */ 765, 1037, 164, 306, 309, 310, 285, 46, 204, 42, + /* 550 */ 321, 928, 287, 328, 1157, 112, 1156, 77, 1153, 297, + /* 560 */ 182, 335, 1149, 74, 50, 166, 295, 168, 293, 291, + /* 570 */ 118, 289, 286, 1148, 1145, 183, 954, 43, 40, 47, + /* 580 */ 205, 916, 128, 914, 130, 131, 49, 912, 911, 264, + /* 590 */ 194, 195, 908, 907, 906, 905, 904, 903, 902, 198, + /* 600 */ 200, 899, 897, 895, 893, 202, 890, 203, 308, 886, + /* 610 */ 353, 123, 277, 83, 88, 345, 288, 1080, 346, 347, + /* 620 */ 348, 349, 228, 350, 351, 248, 303, 361, 866, 265, + /* 630 */ 266, 865, 269, 225, 226, 268, 864, 847, 846, 933, + /* 640 */ 932, 106, 107, 273, 278, 10, 298, 742, 280, 86, + /* 650 */ 30, 910, 909, 89, 767, 143, 159, 144, 955, 186, + /* 660 */ 184, 185, 188, 187, 189, 190, 901, 2, 145, 992, + /* 670 */ 900, 892, 171, 169, 33, 170, 956, 146, 891, 4, + /* 680 */ 778, 160, 161, 772, 90, 240, 774, 1002, 91, 292, + /* 690 */ 31, 11, 32, 12, 13, 27, 300, 28, 98, 100, + /* 700 */ 103, 36, 102, 640, 37, 104, 675, 673, 672, 671, + /* 710 */ 669, 668, 667, 664, 630, 319, 108, 7, 824, 822, + /* 720 */ 325, 8, 326, 111, 113, 70, 71, 117, 39, 712, + /* 730 */ 119, 711, 708, 656, 654, 646, 652, 648, 650, 644, + /* 740 */ 642, 678, 677, 676, 674, 670, 666, 665, 193, 628, + /* 750 */ 592, 870, 869, 869, 869, 869, 869, 869, 869, 869, + /* 760 */ 869, 869, 869, 869, 148, 149, }; static const YYCODETYPE yy_lookahead[] = { - /* 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, 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, + /* 0 */ 198, 1, 244, 1, 198, 199, 248, 246, 265, 9, + /* 10 */ 5, 9, 198, 13, 14, 198, 16, 17, 198, 276, + /* 20 */ 20, 21, 22, 262, 24, 25, 26, 27, 28, 29, + /* 30 */ 246, 5, 244, 7, 34, 35, 248, 265, 38, 39, + /* 40 */ 40, 13, 14, 1, 16, 17, 262, 245, 20, 21, + /* 50 */ 22, 9, 24, 25, 26, 27, 28, 29, 196, 197, + /* 60 */ 243, 247, 34, 35, 247, 205, 38, 39, 40, 222, + /* 70 */ 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, + /* 80 */ 233, 234, 235, 236, 198, 83, 266, 87, 46, 47, + /* 90 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 100 */ 58, 59, 60, 198, 62, 252, 13, 14, 246, 16, + /* 110 */ 17, 0, 84, 20, 21, 22, 98, 24, 25, 26, + /* 120 */ 27, 28, 29, 270, 262, 265, 91, 34, 35, 198, + /* 130 */ 198, 38, 39, 40, 13, 14, 276, 16, 17, 98, + /* 140 */ 209, 20, 21, 22, 1, 24, 25, 26, 27, 28, + /* 150 */ 29, 125, 9, 267, 268, 34, 35, 143, 140, 38, + /* 160 */ 39, 40, 14, 198, 16, 17, 152, 153, 20, 21, + /* 170 */ 22, 85, 24, 25, 26, 27, 28, 29, 273, 138, + /* 180 */ 275, 244, 34, 35, 265, 248, 38, 39, 40, 16, + /* 190 */ 17, 198, 205, 20, 21, 22, 85, 24, 25, 26, + /* 200 */ 27, 28, 29, 271, 5, 273, 83, 34, 35, 126, + /* 210 */ 127, 38, 39, 40, 99, 100, 101, 102, 103, 104, + /* 220 */ 105, 106, 107, 108, 109, 110, 111, 112, 113, 45, + /* 230 */ 198, 1, 2, 34, 35, 5, 243, 7, 273, 9, + /* 240 */ 247, 1, 2, 120, 265, 5, 62, 7, 205, 9, + /* 250 */ 34, 35, 265, 69, 38, 39, 40, 206, 198, 75, + /* 260 */ 76, 77, 78, 276, 34, 35, 82, 83, 38, 209, + /* 270 */ 206, 63, 64, 65, 34, 35, 220, 221, 70, 71, + /* 280 */ 72, 73, 74, 66, 67, 68, 26, 27, 28, 29, + /* 290 */ 239, 240, 241, 242, 34, 35, 204, 89, 38, 39, + /* 300 */ 40, 69, 204, 211, 120, 273, 242, 2, 265, 211, + /* 310 */ 5, 198, 7, 83, 9, 69, 198, 265, 99, 276, + /* 320 */ 101, 102, 79, 83, 265, 106, 142, 209, 144, 110, + /* 330 */ 265, 112, 113, 265, 91, 151, 63, 64, 65, 34, + /* 340 */ 35, 38, 5, 70, 7, 72, 73, 74, 118, 119, + /* 350 */ 204, 248, 198, 198, 81, 125, 243, 211, 118, 119, + /* 360 */ 247, 63, 64, 65, 198, 125, 206, 198, 70, 71, + /* 370 */ 72, 73, 74, 222, 83, 224, 225, 145, 87, 147, + /* 380 */ 229, 149, 150, 77, 233, 198, 235, 236, 198, 15, + /* 390 */ 198, 145, 84, 147, 84, 149, 150, 243, 243, 198, + /* 400 */ 240, 247, 247, 38, 39, 40, 249, 265, 117, 243, + /* 410 */ 207, 208, 243, 247, 202, 203, 247, 63, 64, 65, + /* 420 */ 263, 98, 84, 118, 119, 83, 123, 84, 84, 121, + /* 430 */ 243, 121, 84, 243, 247, 243, 98, 247, 1, 247, + /* 440 */ 134, 98, 98, 84, 243, 84, 98, 124, 247, 61, + /* 450 */ 84, 84, 84, 84, 84, 84, 83, 98, 116, 98, + /* 460 */ 265, 146, 125, 148, 98, 98, 98, 98, 98, 98, + /* 470 */ 146, 83, 148, 248, 146, 38, 148, 5, 5, 7, + /* 480 */ 7, 146, 146, 148, 148, 146, 265, 148, 115, 79, + /* 490 */ 80, 265, 118, 265, 265, 248, 265, 238, 265, 265, + /* 500 */ 265, 265, 265, 265, 265, 238, 238, 238, 238, 238, + /* 510 */ 238, 198, 198, 264, 198, 198, 198, 198, 198, 198, + /* 520 */ 246, 246, 274, 198, 198, 274, 250, 246, 198, 198, + /* 530 */ 198, 198, 198, 269, 269, 61, 257, 259, 198, 198, + /* 540 */ 125, 261, 260, 198, 198, 198, 269, 198, 198, 198, + /* 550 */ 198, 198, 269, 198, 198, 198, 198, 137, 198, 132, + /* 560 */ 198, 198, 198, 139, 136, 258, 135, 256, 130, 129, + /* 570 */ 198, 128, 131, 198, 198, 198, 198, 198, 198, 198, + /* 580 */ 198, 198, 198, 198, 198, 198, 141, 198, 198, 198, + /* 590 */ 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, + /* 600 */ 198, 198, 198, 198, 198, 198, 198, 198, 90, 198, + /* 610 */ 114, 97, 200, 200, 200, 96, 200, 200, 52, 93, + /* 620 */ 95, 56, 200, 94, 92, 200, 200, 85, 5, 154, + /* 630 */ 5, 5, 5, 200, 200, 154, 5, 101, 100, 210, + /* 640 */ 210, 206, 206, 143, 121, 83, 116, 84, 98, 122, + /* 650 */ 83, 200, 200, 98, 84, 201, 83, 201, 219, 213, + /* 660 */ 218, 217, 214, 216, 215, 212, 200, 207, 201, 237, + /* 670 */ 200, 200, 253, 255, 251, 254, 221, 201, 200, 202, + /* 680 */ 84, 83, 98, 84, 83, 1, 84, 237, 83, 83, + /* 690 */ 98, 133, 98, 133, 83, 83, 116, 83, 117, 79, + /* 700 */ 71, 88, 87, 5, 88, 87, 9, 5, 5, 5, + /* 710 */ 5, 5, 5, 5, 86, 15, 79, 83, 118, 84, + /* 720 */ 25, 83, 60, 148, 148, 16, 16, 148, 98, 5, + /* 730 */ 148, 5, 84, 5, 5, 5, 5, 5, 5, 5, + /* 740 */ 5, 5, 5, 5, 5, 5, 5, 5, 98, 86, + /* 750 */ 61, 0, 277, 277, 277, 277, 277, 277, 277, 277, + /* 760 */ 277, 277, 277, 277, 21, 21, 277, 277, 277, 277, + /* 770 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 780 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 790 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 800 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 810 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 820 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 830 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 840 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 850 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 860 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 870 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 880 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 890 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 900 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 910 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 920 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 930 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 940 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 950 */ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + /* 960 */ 277, 277, }; -#define YY_SHIFT_COUNT (361) +#define YY_SHIFT_COUNT (365) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (739) +#define YY_SHIFT_MAX (751) static const unsigned short int yy_shift_ofst[] = { - /* 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, + /* 0 */ 184, 115, 115, 219, 219, 86, 230, 240, 240, 2, + /* 10 */ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + /* 20 */ 143, 143, 143, 0, 42, 240, 305, 305, 305, 123, + /* 30 */ 123, 143, 143, 83, 143, 111, 143, 143, 143, 143, + /* 40 */ 243, 86, 35, 35, 5, 766, 766, 766, 240, 240, + /* 50 */ 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + /* 60 */ 240, 240, 240, 240, 240, 240, 240, 240, 240, 305, + /* 70 */ 305, 305, 199, 199, 199, 199, 199, 199, 199, 143, + /* 80 */ 143, 143, 303, 143, 143, 143, 123, 123, 143, 143, + /* 90 */ 143, 143, 306, 306, 323, 123, 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, 143, 143, 143, 143, 474, 474, 474, 415, 415, + /* 160 */ 415, 415, 474, 474, 420, 424, 427, 428, 431, 438, + /* 170 */ 440, 443, 441, 445, 474, 474, 474, 518, 518, 496, + /* 180 */ 86, 86, 474, 474, 514, 519, 566, 526, 525, 565, + /* 190 */ 529, 532, 496, 5, 474, 474, 542, 542, 474, 542, + /* 200 */ 474, 542, 474, 474, 766, 766, 28, 93, 93, 121, + /* 210 */ 93, 148, 173, 208, 260, 260, 260, 260, 260, 273, + /* 220 */ 298, 216, 216, 216, 216, 232, 246, 14, 291, 365, + /* 230 */ 365, 26, 337, 217, 354, 338, 308, 310, 343, 344, + /* 240 */ 348, 18, 41, 359, 361, 366, 367, 368, 342, 369, + /* 250 */ 370, 437, 388, 374, 371, 315, 324, 328, 472, 473, + /* 260 */ 335, 336, 373, 339, 410, 623, 475, 625, 626, 481, + /* 270 */ 627, 631, 536, 538, 500, 523, 530, 562, 527, 563, + /* 280 */ 567, 550, 555, 570, 573, 596, 598, 599, 584, 601, + /* 290 */ 602, 605, 684, 606, 592, 558, 594, 560, 611, 530, + /* 300 */ 612, 580, 614, 581, 620, 613, 615, 629, 698, 616, + /* 310 */ 618, 697, 702, 703, 704, 705, 706, 707, 708, 628, + /* 320 */ 700, 637, 634, 635, 600, 638, 695, 662, 709, 575, + /* 330 */ 576, 630, 630, 630, 630, 710, 579, 582, 630, 630, + /* 340 */ 630, 724, 726, 648, 630, 728, 729, 730, 731, 732, + /* 350 */ 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, + /* 360 */ 650, 663, 743, 744, 689, 751, }; -#define YY_REDUCE_COUNT (202) -#define YY_REDUCE_MIN (-264) -#define YY_REDUCE_MAX (466) +#define YY_REDUCE_COUNT (205) +#define YY_REDUCE_MIN (-257) +#define YY_REDUCE_MAX (478) static const short yy_reduce_ofst[] = { - /* 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, + /* 0 */ -138, -153, -153, 151, 151, 51, -140, -13, 43, -114, + /* 10 */ -183, -95, -68, -7, 113, 154, 155, 166, 169, 187, + /* 20 */ 190, 192, 201, -180, -194, -257, -242, -212, -63, -239, + /* 30 */ -216, -35, 32, -147, -198, 64, -69, 60, 118, -186, + /* 40 */ 92, 160, 98, 146, 56, 157, 203, 212, -228, -81, + /* 50 */ -21, 52, 59, 65, 68, 142, 195, 221, 226, 228, + /* 60 */ 229, 231, 233, 234, 235, 236, 237, 238, 239, 103, + /* 70 */ 225, 247, 259, 267, 268, 269, 270, 271, 272, 313, + /* 80 */ 314, 316, 249, 317, 318, 319, 274, 275, 320, 321, + /* 90 */ 325, 326, 248, 251, 276, 281, 330, 331, 332, 333, + /* 100 */ 334, 340, 341, 345, 346, 347, 349, 350, 351, 352, + /* 110 */ 353, 355, 356, 357, 358, 360, 362, 363, 364, 372, + /* 120 */ 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, + /* 130 */ 385, 386, 387, 389, 390, 391, 392, 393, 394, 395, + /* 140 */ 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, + /* 150 */ 406, 407, 408, 409, 411, 412, 413, 414, 264, 265, + /* 160 */ 277, 283, 416, 417, 280, 282, 278, 307, 279, 311, + /* 170 */ 418, 421, 419, 423, 422, 425, 426, 429, 430, 432, + /* 180 */ 435, 436, 433, 434, 439, 442, 444, 446, 447, 448, + /* 190 */ 449, 453, 450, 455, 451, 452, 454, 456, 466, 467, + /* 200 */ 470, 476, 471, 478, 460, 477, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 856, 979, 918, 989, 905, 915, 1126, 1126, 1126, 856, - /* 10 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 20 */ 856, 856, 856, 1037, 876, 1126, 856, 856, 856, 856, - /* 30 */ 856, 856, 856, 856, 915, 856, 856, 856, 856, 925, - /* 40 */ 915, 925, 925, 856, 1032, 963, 981, 856, 856, 856, - /* 50 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 60 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 70 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 80 */ 1039, 1045, 1042, 856, 856, 856, 1047, 856, 856, 856, - /* 90 */ 1069, 1069, 1030, 856, 856, 856, 856, 856, 856, 856, - /* 100 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 110 */ 856, 856, 856, 856, 856, 856, 856, 856, 856, 856, - /* 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, 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 */ 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, 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, + /* 0 */ 867, 991, 930, 1001, 917, 927, 1141, 1141, 1141, 867, + /* 10 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 20 */ 867, 867, 867, 1049, 887, 1141, 867, 867, 867, 867, + /* 30 */ 867, 867, 867, 1064, 867, 927, 867, 867, 867, 867, + /* 40 */ 937, 927, 937, 937, 867, 1044, 975, 993, 867, 867, + /* 50 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 60 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 70 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 80 */ 867, 867, 1051, 1057, 1054, 867, 867, 867, 1059, 867, + /* 90 */ 867, 867, 1083, 1083, 1042, 867, 867, 867, 867, 867, + /* 100 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 110 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 120 */ 867, 867, 867, 867, 867, 867, 867, 867, 915, 867, + /* 130 */ 913, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 140 */ 867, 867, 867, 867, 867, 867, 867, 898, 867, 867, + /* 150 */ 867, 867, 867, 867, 885, 889, 889, 889, 867, 867, + /* 160 */ 867, 867, 889, 889, 1090, 1094, 1076, 1088, 1084, 1071, + /* 170 */ 1069, 1067, 1075, 1098, 889, 889, 889, 935, 935, 931, + /* 180 */ 927, 927, 889, 889, 953, 951, 949, 941, 947, 943, + /* 190 */ 945, 939, 918, 867, 889, 889, 925, 925, 889, 925, + /* 200 */ 889, 925, 889, 889, 975, 993, 867, 1099, 1089, 867, + /* 210 */ 1140, 1129, 1128, 867, 1136, 1135, 1127, 1126, 1125, 867, + /* 220 */ 867, 1121, 1124, 1123, 1122, 867, 867, 867, 867, 1131, + /* 230 */ 1130, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 240 */ 867, 1095, 1091, 867, 867, 867, 867, 867, 867, 867, + /* 250 */ 867, 867, 1101, 867, 867, 867, 867, 867, 867, 867, + /* 260 */ 867, 867, 1003, 867, 867, 867, 867, 867, 867, 867, + /* 270 */ 867, 867, 867, 867, 867, 1041, 867, 867, 867, 867, + /* 280 */ 867, 1053, 1052, 867, 867, 867, 867, 867, 867, 867, + /* 290 */ 867, 867, 867, 867, 1085, 867, 1077, 867, 867, 1015, + /* 300 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 310 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 320 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 330 */ 867, 1159, 1154, 1155, 1152, 867, 867, 867, 1151, 1146, + /* 340 */ 1147, 867, 867, 867, 1144, 867, 867, 867, 867, 867, + /* 350 */ 867, 867, 867, 867, 867, 867, 867, 867, 867, 867, + /* 360 */ 959, 867, 896, 894, 867, 867, }; /********** End of lemon-generated parsing tables *****************************/ @@ -540,6 +544,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* NOTNULL => nothing */ 0, /* IS => nothing */ 1, /* LIKE => ID */ + 1, /* MATCH => ID */ 1, /* GLOB => ID */ 0, /* BETWEEN => nothing */ 0, /* IN => nothing */ @@ -594,6 +599,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* ACCOUNT => nothing */ 0, /* USE => nothing */ 0, /* DESCRIBE => nothing */ + 1, /* DESC => ID */ 0, /* ALTER => nothing */ 0, /* PASS => nothing */ 0, /* PRIVILEGE => nothing */ @@ -643,6 +649,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* FROM => nothing */ 0, /* VARIABLE => nothing */ 0, /* INTERVAL => nothing */ + 0, /* EVERY => nothing */ 0, /* SESSION => nothing */ 0, /* STATE_WINDOW => nothing */ 0, /* FILL => nothing */ @@ -650,7 +657,6 @@ static const YYCODETYPE yyFallback[] = { 0, /* ORDER => nothing */ 0, /* BY => nothing */ 1, /* ASC => ID */ - 1, /* DESC => ID */ 0, /* GROUP => nothing */ 0, /* HAVING => nothing */ 0, /* LIMIT => nothing */ @@ -692,7 +698,6 @@ static const YYCODETYPE yyFallback[] = { 1, /* IMMEDIATE => ID */ 1, /* INITIALLY => ID */ 1, /* INSTEAD => ID */ - 1, /* MATCH => ID */ 1, /* KEY => ID */ 1, /* OF => ID */ 1, /* RAISE => ID */ @@ -822,259 +827,261 @@ static const char *const yyTokenName[] = { /* 19 */ "NOTNULL", /* 20 */ "IS", /* 21 */ "LIKE", - /* 22 */ "GLOB", - /* 23 */ "BETWEEN", - /* 24 */ "IN", - /* 25 */ "GT", - /* 26 */ "GE", - /* 27 */ "LT", - /* 28 */ "LE", - /* 29 */ "BITAND", - /* 30 */ "BITOR", - /* 31 */ "LSHIFT", - /* 32 */ "RSHIFT", - /* 33 */ "PLUS", - /* 34 */ "MINUS", - /* 35 */ "DIVIDE", - /* 36 */ "TIMES", - /* 37 */ "STAR", - /* 38 */ "SLASH", - /* 39 */ "REM", - /* 40 */ "CONCAT", - /* 41 */ "UMINUS", - /* 42 */ "UPLUS", - /* 43 */ "BITNOT", - /* 44 */ "SHOW", - /* 45 */ "DATABASES", - /* 46 */ "TOPICS", - /* 47 */ "FUNCTIONS", - /* 48 */ "MNODES", - /* 49 */ "DNODES", - /* 50 */ "ACCOUNTS", - /* 51 */ "USERS", - /* 52 */ "MODULES", - /* 53 */ "QUERIES", - /* 54 */ "CONNECTIONS", - /* 55 */ "STREAMS", - /* 56 */ "VARIABLES", - /* 57 */ "SCORES", - /* 58 */ "GRANTS", - /* 59 */ "VNODES", - /* 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", - /* 188 */ "LINEAR", - /* 189 */ "IMPORT", - /* 190 */ "TBNAME", - /* 191 */ "JOIN", - /* 192 */ "INSERT", - /* 193 */ "INTO", - /* 194 */ "VALUES", - /* 195 */ "program", - /* 196 */ "cmd", - /* 197 */ "ids", - /* 198 */ "dbPrefix", - /* 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", + /* 22 */ "MATCH", + /* 23 */ "GLOB", + /* 24 */ "BETWEEN", + /* 25 */ "IN", + /* 26 */ "GT", + /* 27 */ "GE", + /* 28 */ "LT", + /* 29 */ "LE", + /* 30 */ "BITAND", + /* 31 */ "BITOR", + /* 32 */ "LSHIFT", + /* 33 */ "RSHIFT", + /* 34 */ "PLUS", + /* 35 */ "MINUS", + /* 36 */ "DIVIDE", + /* 37 */ "TIMES", + /* 38 */ "STAR", + /* 39 */ "SLASH", + /* 40 */ "REM", + /* 41 */ "CONCAT", + /* 42 */ "UMINUS", + /* 43 */ "UPLUS", + /* 44 */ "BITNOT", + /* 45 */ "SHOW", + /* 46 */ "DATABASES", + /* 47 */ "TOPICS", + /* 48 */ "FUNCTIONS", + /* 49 */ "MNODES", + /* 50 */ "DNODES", + /* 51 */ "ACCOUNTS", + /* 52 */ "USERS", + /* 53 */ "MODULES", + /* 54 */ "QUERIES", + /* 55 */ "CONNECTIONS", + /* 56 */ "STREAMS", + /* 57 */ "VARIABLES", + /* 58 */ "SCORES", + /* 59 */ "GRANTS", + /* 60 */ "VNODES", + /* 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 */ "DESC", + /* 78 */ "ALTER", + /* 79 */ "PASS", + /* 80 */ "PRIVILEGE", + /* 81 */ "LOCAL", + /* 82 */ "COMPACT", + /* 83 */ "LP", + /* 84 */ "RP", + /* 85 */ "IF", + /* 86 */ "EXISTS", + /* 87 */ "AS", + /* 88 */ "OUTPUTTYPE", + /* 89 */ "AGGREGATE", + /* 90 */ "BUFSIZE", + /* 91 */ "PPS", + /* 92 */ "TSERIES", + /* 93 */ "DBS", + /* 94 */ "STORAGE", + /* 95 */ "QTIME", + /* 96 */ "CONNS", + /* 97 */ "STATE", + /* 98 */ "COMMA", + /* 99 */ "KEEP", + /* 100 */ "CACHE", + /* 101 */ "REPLICA", + /* 102 */ "QUORUM", + /* 103 */ "DAYS", + /* 104 */ "MINROWS", + /* 105 */ "MAXROWS", + /* 106 */ "BLOCKS", + /* 107 */ "CTIME", + /* 108 */ "WAL", + /* 109 */ "FSYNC", + /* 110 */ "COMP", + /* 111 */ "PRECISION", + /* 112 */ "UPDATE", + /* 113 */ "CACHELAST", + /* 114 */ "PARTITIONS", + /* 115 */ "UNSIGNED", + /* 116 */ "TAGS", + /* 117 */ "USING", + /* 118 */ "NULL", + /* 119 */ "NOW", + /* 120 */ "SELECT", + /* 121 */ "UNION", + /* 122 */ "ALL", + /* 123 */ "DISTINCT", + /* 124 */ "FROM", + /* 125 */ "VARIABLE", + /* 126 */ "INTERVAL", + /* 127 */ "EVERY", + /* 128 */ "SESSION", + /* 129 */ "STATE_WINDOW", + /* 130 */ "FILL", + /* 131 */ "SLIDING", + /* 132 */ "ORDER", + /* 133 */ "BY", + /* 134 */ "ASC", + /* 135 */ "GROUP", + /* 136 */ "HAVING", + /* 137 */ "LIMIT", + /* 138 */ "OFFSET", + /* 139 */ "SLIMIT", + /* 140 */ "SOFFSET", + /* 141 */ "WHERE", + /* 142 */ "RESET", + /* 143 */ "QUERY", + /* 144 */ "SYNCDB", + /* 145 */ "ADD", + /* 146 */ "COLUMN", + /* 147 */ "MODIFY", + /* 148 */ "TAG", + /* 149 */ "CHANGE", + /* 150 */ "SET", + /* 151 */ "KILL", + /* 152 */ "CONNECTION", + /* 153 */ "STREAM", + /* 154 */ "COLON", + /* 155 */ "ABORT", + /* 156 */ "AFTER", + /* 157 */ "ATTACH", + /* 158 */ "BEFORE", + /* 159 */ "BEGIN", + /* 160 */ "CASCADE", + /* 161 */ "CLUSTER", + /* 162 */ "CONFLICT", + /* 163 */ "COPY", + /* 164 */ "DEFERRED", + /* 165 */ "DELIMITERS", + /* 166 */ "DETACH", + /* 167 */ "EACH", + /* 168 */ "END", + /* 169 */ "EXPLAIN", + /* 170 */ "FAIL", + /* 171 */ "FOR", + /* 172 */ "IGNORE", + /* 173 */ "IMMEDIATE", + /* 174 */ "INITIALLY", + /* 175 */ "INSTEAD", + /* 176 */ "KEY", + /* 177 */ "OF", + /* 178 */ "RAISE", + /* 179 */ "REPLACE", + /* 180 */ "RESTRICT", + /* 181 */ "ROW", + /* 182 */ "STATEMENT", + /* 183 */ "TRIGGER", + /* 184 */ "VIEW", + /* 185 */ "IPTOKEN", + /* 186 */ "SEMI", + /* 187 */ "NONE", + /* 188 */ "PREV", + /* 189 */ "LINEAR", + /* 190 */ "IMPORT", + /* 191 */ "TBNAME", + /* 192 */ "JOIN", + /* 193 */ "INSERT", + /* 194 */ "INTO", + /* 195 */ "VALUES", + /* 196 */ "program", + /* 197 */ "cmd", + /* 198 */ "ids", + /* 199 */ "dbPrefix", + /* 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_option", + /* 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 */ "intervalKey", + /* 271 */ "sortlist", + /* 272 */ "sortitem", + /* 273 */ "item", + /* 274 */ "sortorder", + /* 275 */ "grouplist", + /* 276 */ "expritem", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -1122,255 +1129,259 @@ static const char *const yyRuleName[] = { /* 37 */ "cmd ::= DROP ACCOUNT ids", /* 38 */ "cmd ::= USE ids", /* 39 */ "cmd ::= DESCRIBE ids cpxName", - /* 40 */ "cmd ::= ALTER USER ids PASS ids", - /* 41 */ "cmd ::= ALTER USER ids PRIVILEGE ids", - /* 42 */ "cmd ::= ALTER DNODE ids ids", - /* 43 */ "cmd ::= ALTER DNODE ids ids ids", - /* 44 */ "cmd ::= ALTER LOCAL ids", - /* 45 */ "cmd ::= ALTER LOCAL ids ids", - /* 46 */ "cmd ::= ALTER DATABASE ids alter_db_optr", - /* 47 */ "cmd ::= ALTER TOPIC ids alter_topic_optr", - /* 48 */ "cmd ::= ALTER ACCOUNT ids acct_optr", - /* 49 */ "cmd ::= ALTER ACCOUNT ids PASS ids acct_optr", - /* 50 */ "cmd ::= COMPACT VNODES IN LP exprlist RP", - /* 51 */ "ids ::= ID", - /* 52 */ "ids ::= STRING", - /* 53 */ "ifexists ::= IF EXISTS", - /* 54 */ "ifexists ::=", - /* 55 */ "ifnotexists ::= IF NOT EXISTS", - /* 56 */ "ifnotexists ::=", - /* 57 */ "cmd ::= CREATE DNODE ids", - /* 58 */ "cmd ::= CREATE ACCOUNT ids PASS ids acct_optr", - /* 59 */ "cmd ::= CREATE DATABASE ifnotexists ids db_optr", - /* 60 */ "cmd ::= CREATE TOPIC ifnotexists ids topic_optr", - /* 61 */ "cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize", - /* 62 */ "cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize", - /* 63 */ "cmd ::= CREATE USER ids PASS ids", - /* 64 */ "bufsize ::=", - /* 65 */ "bufsize ::= BUFSIZE INTEGER", - /* 66 */ "pps ::=", - /* 67 */ "pps ::= PPS INTEGER", - /* 68 */ "tseries ::=", - /* 69 */ "tseries ::= TSERIES INTEGER", - /* 70 */ "dbs ::=", - /* 71 */ "dbs ::= DBS INTEGER", - /* 72 */ "streams ::=", - /* 73 */ "streams ::= STREAMS INTEGER", - /* 74 */ "storage ::=", - /* 75 */ "storage ::= STORAGE INTEGER", - /* 76 */ "qtime ::=", - /* 77 */ "qtime ::= QTIME INTEGER", - /* 78 */ "users ::=", - /* 79 */ "users ::= USERS INTEGER", - /* 80 */ "conns ::=", - /* 81 */ "conns ::= CONNS INTEGER", - /* 82 */ "state ::=", - /* 83 */ "state ::= STATE ids", - /* 84 */ "acct_optr ::= pps tseries storage streams qtime dbs users conns state", - /* 85 */ "intitemlist ::= intitemlist COMMA intitem", - /* 86 */ "intitemlist ::= intitem", - /* 87 */ "intitem ::= INTEGER", - /* 88 */ "keep ::= KEEP intitemlist", - /* 89 */ "cache ::= CACHE INTEGER", - /* 90 */ "replica ::= REPLICA INTEGER", - /* 91 */ "quorum ::= QUORUM INTEGER", - /* 92 */ "days ::= DAYS INTEGER", - /* 93 */ "minrows ::= MINROWS INTEGER", - /* 94 */ "maxrows ::= MAXROWS INTEGER", - /* 95 */ "blocks ::= BLOCKS INTEGER", - /* 96 */ "ctime ::= CTIME INTEGER", - /* 97 */ "wal ::= WAL INTEGER", - /* 98 */ "fsync ::= FSYNC INTEGER", - /* 99 */ "comp ::= COMP INTEGER", - /* 100 */ "prec ::= PRECISION STRING", - /* 101 */ "update ::= UPDATE INTEGER", - /* 102 */ "cachelast ::= CACHELAST INTEGER", - /* 103 */ "partitions ::= PARTITIONS INTEGER", - /* 104 */ "db_optr ::=", - /* 105 */ "db_optr ::= db_optr cache", - /* 106 */ "db_optr ::= db_optr replica", - /* 107 */ "db_optr ::= db_optr quorum", - /* 108 */ "db_optr ::= db_optr days", - /* 109 */ "db_optr ::= db_optr minrows", - /* 110 */ "db_optr ::= db_optr maxrows", - /* 111 */ "db_optr ::= db_optr blocks", - /* 112 */ "db_optr ::= db_optr ctime", - /* 113 */ "db_optr ::= db_optr wal", - /* 114 */ "db_optr ::= db_optr fsync", - /* 115 */ "db_optr ::= db_optr comp", - /* 116 */ "db_optr ::= db_optr prec", - /* 117 */ "db_optr ::= db_optr keep", - /* 118 */ "db_optr ::= db_optr update", - /* 119 */ "db_optr ::= db_optr cachelast", - /* 120 */ "topic_optr ::= db_optr", - /* 121 */ "topic_optr ::= topic_optr partitions", - /* 122 */ "alter_db_optr ::=", - /* 123 */ "alter_db_optr ::= alter_db_optr replica", - /* 124 */ "alter_db_optr ::= alter_db_optr quorum", - /* 125 */ "alter_db_optr ::= alter_db_optr keep", - /* 126 */ "alter_db_optr ::= alter_db_optr blocks", - /* 127 */ "alter_db_optr ::= alter_db_optr comp", - /* 128 */ "alter_db_optr ::= alter_db_optr update", - /* 129 */ "alter_db_optr ::= alter_db_optr cachelast", - /* 130 */ "alter_topic_optr ::= alter_db_optr", - /* 131 */ "alter_topic_optr ::= alter_topic_optr partitions", - /* 132 */ "typename ::= ids", - /* 133 */ "typename ::= ids LP signed RP", - /* 134 */ "typename ::= ids UNSIGNED", - /* 135 */ "signed ::= INTEGER", - /* 136 */ "signed ::= PLUS INTEGER", - /* 137 */ "signed ::= MINUS INTEGER", - /* 138 */ "cmd ::= CREATE TABLE create_table_args", - /* 139 */ "cmd ::= CREATE TABLE create_stable_args", - /* 140 */ "cmd ::= CREATE STABLE create_stable_args", - /* 141 */ "cmd ::= CREATE TABLE create_table_list", - /* 142 */ "create_table_list ::= create_from_stable", - /* 143 */ "create_table_list ::= create_table_list create_from_stable", - /* 144 */ "create_table_args ::= ifnotexists ids cpxName LP columnlist RP", - /* 145 */ "create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP", - /* 146 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP", - /* 147 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP", - /* 148 */ "tagNamelist ::= tagNamelist COMMA ids", - /* 149 */ "tagNamelist ::= ids", - /* 150 */ "create_table_args ::= ifnotexists ids cpxName AS select", - /* 151 */ "columnlist ::= columnlist COMMA column", - /* 152 */ "columnlist ::= column", - /* 153 */ "column ::= ids typename", - /* 154 */ "tagitemlist ::= tagitemlist COMMA tagitem", - /* 155 */ "tagitemlist ::= tagitem", - /* 156 */ "tagitem ::= INTEGER", - /* 157 */ "tagitem ::= FLOAT", - /* 158 */ "tagitem ::= STRING", - /* 159 */ "tagitem ::= BOOL", - /* 160 */ "tagitem ::= NULL", - /* 161 */ "tagitem ::= NOW", - /* 162 */ "tagitem ::= MINUS INTEGER", - /* 163 */ "tagitem ::= MINUS FLOAT", - /* 164 */ "tagitem ::= PLUS INTEGER", - /* 165 */ "tagitem ::= PLUS FLOAT", - /* 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", - /* 167 */ "select ::= LP select RP", - /* 168 */ "union ::= select", - /* 169 */ "union ::= union UNION ALL select", - /* 170 */ "cmd ::= union", - /* 171 */ "select ::= SELECT selcollist", - /* 172 */ "sclp ::= selcollist COMMA", - /* 173 */ "sclp ::=", - /* 174 */ "selcollist ::= sclp distinct expr as", - /* 175 */ "selcollist ::= sclp STAR", - /* 176 */ "as ::= AS ids", - /* 177 */ "as ::= ids", - /* 178 */ "as ::=", - /* 179 */ "distinct ::= DISTINCT", - /* 180 */ "distinct ::=", - /* 181 */ "from ::= FROM tablelist", - /* 182 */ "from ::= FROM sub", - /* 183 */ "sub ::= LP union RP", - /* 184 */ "sub ::= LP union RP ids", - /* 185 */ "sub ::= sub COMMA LP union RP ids", - /* 186 */ "tablelist ::= ids cpxName", - /* 187 */ "tablelist ::= ids cpxName ids", - /* 188 */ "tablelist ::= tablelist COMMA ids cpxName", - /* 189 */ "tablelist ::= tablelist COMMA ids cpxName ids", - /* 190 */ "tmvar ::= VARIABLE", - /* 191 */ "interval_opt ::= INTERVAL LP tmvar RP", - /* 192 */ "interval_opt ::= INTERVAL LP tmvar COMMA tmvar RP", - /* 193 */ "interval_opt ::=", - /* 194 */ "session_option ::=", - /* 195 */ "session_option ::= SESSION LP ids cpxName COMMA tmvar RP", - /* 196 */ "windowstate_option ::=", - /* 197 */ "windowstate_option ::= STATE_WINDOW LP ids RP", - /* 198 */ "fill_opt ::=", - /* 199 */ "fill_opt ::= FILL LP ID COMMA tagitemlist RP", - /* 200 */ "fill_opt ::= FILL LP ID RP", - /* 201 */ "sliding_opt ::= SLIDING LP tmvar RP", - /* 202 */ "sliding_opt ::=", - /* 203 */ "orderby_opt ::=", - /* 204 */ "orderby_opt ::= ORDER BY sortlist", - /* 205 */ "sortlist ::= sortlist COMMA item sortorder", - /* 206 */ "sortlist ::= item sortorder", - /* 207 */ "item ::= ids cpxName", - /* 208 */ "sortorder ::= ASC", - /* 209 */ "sortorder ::= DESC", - /* 210 */ "sortorder ::=", - /* 211 */ "groupby_opt ::=", - /* 212 */ "groupby_opt ::= GROUP BY grouplist", - /* 213 */ "grouplist ::= grouplist COMMA item", - /* 214 */ "grouplist ::= item", - /* 215 */ "having_opt ::=", - /* 216 */ "having_opt ::= HAVING expr", - /* 217 */ "limit_opt ::=", - /* 218 */ "limit_opt ::= LIMIT signed", - /* 219 */ "limit_opt ::= LIMIT signed OFFSET signed", - /* 220 */ "limit_opt ::= LIMIT signed COMMA signed", - /* 221 */ "slimit_opt ::=", - /* 222 */ "slimit_opt ::= SLIMIT signed", - /* 223 */ "slimit_opt ::= SLIMIT signed SOFFSET signed", - /* 224 */ "slimit_opt ::= SLIMIT signed COMMA signed", - /* 225 */ "where_opt ::=", - /* 226 */ "where_opt ::= WHERE expr", - /* 227 */ "expr ::= LP expr RP", - /* 228 */ "expr ::= ID", - /* 229 */ "expr ::= ID DOT ID", - /* 230 */ "expr ::= ID DOT STAR", - /* 231 */ "expr ::= INTEGER", - /* 232 */ "expr ::= MINUS INTEGER", - /* 233 */ "expr ::= PLUS INTEGER", - /* 234 */ "expr ::= FLOAT", - /* 235 */ "expr ::= MINUS FLOAT", - /* 236 */ "expr ::= PLUS FLOAT", - /* 237 */ "expr ::= STRING", - /* 238 */ "expr ::= NOW", - /* 239 */ "expr ::= VARIABLE", - /* 240 */ "expr ::= PLUS VARIABLE", - /* 241 */ "expr ::= MINUS VARIABLE", - /* 242 */ "expr ::= BOOL", - /* 243 */ "expr ::= NULL", - /* 244 */ "expr ::= ID LP exprlist RP", - /* 245 */ "expr ::= ID LP STAR RP", - /* 246 */ "expr ::= expr IS NULL", - /* 247 */ "expr ::= expr IS NOT NULL", - /* 248 */ "expr ::= expr LT expr", - /* 249 */ "expr ::= expr GT expr", - /* 250 */ "expr ::= expr LE expr", - /* 251 */ "expr ::= expr GE expr", - /* 252 */ "expr ::= expr NE expr", - /* 253 */ "expr ::= expr EQ expr", - /* 254 */ "expr ::= expr BETWEEN expr AND expr", - /* 255 */ "expr ::= expr AND expr", - /* 256 */ "expr ::= expr OR expr", - /* 257 */ "expr ::= expr PLUS expr", - /* 258 */ "expr ::= expr MINUS expr", - /* 259 */ "expr ::= expr STAR expr", - /* 260 */ "expr ::= expr SLASH expr", - /* 261 */ "expr ::= expr REM expr", - /* 262 */ "expr ::= expr LIKE expr", - /* 263 */ "expr ::= expr IN LP exprlist RP", - /* 264 */ "exprlist ::= exprlist COMMA expritem", - /* 265 */ "exprlist ::= expritem", - /* 266 */ "expritem ::= expr", - /* 267 */ "expritem ::=", - /* 268 */ "cmd ::= RESET QUERY CACHE", - /* 269 */ "cmd ::= SYNCDB ids REPLICA", - /* 270 */ "cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist", - /* 271 */ "cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids", - /* 272 */ "cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist", - /* 273 */ "cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist", - /* 274 */ "cmd ::= ALTER TABLE ids cpxName DROP TAG ids", - /* 275 */ "cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids", - /* 276 */ "cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem", - /* 277 */ "cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist", - /* 278 */ "cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist", - /* 279 */ "cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids", - /* 280 */ "cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist", - /* 281 */ "cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist", - /* 282 */ "cmd ::= ALTER STABLE ids cpxName DROP TAG ids", - /* 283 */ "cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids", - /* 284 */ "cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem", - /* 285 */ "cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist", - /* 286 */ "cmd ::= KILL CONNECTION INTEGER", - /* 287 */ "cmd ::= KILL STREAM INTEGER COLON INTEGER", - /* 288 */ "cmd ::= KILL QUERY INTEGER COLON INTEGER", + /* 40 */ "cmd ::= DESC ids cpxName", + /* 41 */ "cmd ::= ALTER USER ids PASS ids", + /* 42 */ "cmd ::= ALTER USER ids PRIVILEGE ids", + /* 43 */ "cmd ::= ALTER DNODE ids ids", + /* 44 */ "cmd ::= ALTER DNODE ids ids ids", + /* 45 */ "cmd ::= ALTER LOCAL ids", + /* 46 */ "cmd ::= ALTER LOCAL ids ids", + /* 47 */ "cmd ::= ALTER DATABASE ids alter_db_optr", + /* 48 */ "cmd ::= ALTER TOPIC ids alter_topic_optr", + /* 49 */ "cmd ::= ALTER ACCOUNT ids acct_optr", + /* 50 */ "cmd ::= ALTER ACCOUNT ids PASS ids acct_optr", + /* 51 */ "cmd ::= COMPACT VNODES IN LP exprlist RP", + /* 52 */ "ids ::= ID", + /* 53 */ "ids ::= STRING", + /* 54 */ "ifexists ::= IF EXISTS", + /* 55 */ "ifexists ::=", + /* 56 */ "ifnotexists ::= IF NOT EXISTS", + /* 57 */ "ifnotexists ::=", + /* 58 */ "cmd ::= CREATE DNODE ids", + /* 59 */ "cmd ::= CREATE ACCOUNT ids PASS ids acct_optr", + /* 60 */ "cmd ::= CREATE DATABASE ifnotexists ids db_optr", + /* 61 */ "cmd ::= CREATE TOPIC ifnotexists ids topic_optr", + /* 62 */ "cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize", + /* 63 */ "cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize", + /* 64 */ "cmd ::= CREATE USER ids PASS ids", + /* 65 */ "bufsize ::=", + /* 66 */ "bufsize ::= BUFSIZE INTEGER", + /* 67 */ "pps ::=", + /* 68 */ "pps ::= PPS INTEGER", + /* 69 */ "tseries ::=", + /* 70 */ "tseries ::= TSERIES INTEGER", + /* 71 */ "dbs ::=", + /* 72 */ "dbs ::= DBS INTEGER", + /* 73 */ "streams ::=", + /* 74 */ "streams ::= STREAMS INTEGER", + /* 75 */ "storage ::=", + /* 76 */ "storage ::= STORAGE INTEGER", + /* 77 */ "qtime ::=", + /* 78 */ "qtime ::= QTIME INTEGER", + /* 79 */ "users ::=", + /* 80 */ "users ::= USERS INTEGER", + /* 81 */ "conns ::=", + /* 82 */ "conns ::= CONNS INTEGER", + /* 83 */ "state ::=", + /* 84 */ "state ::= STATE ids", + /* 85 */ "acct_optr ::= pps tseries storage streams qtime dbs users conns state", + /* 86 */ "intitemlist ::= intitemlist COMMA intitem", + /* 87 */ "intitemlist ::= intitem", + /* 88 */ "intitem ::= INTEGER", + /* 89 */ "keep ::= KEEP intitemlist", + /* 90 */ "cache ::= CACHE INTEGER", + /* 91 */ "replica ::= REPLICA INTEGER", + /* 92 */ "quorum ::= QUORUM INTEGER", + /* 93 */ "days ::= DAYS INTEGER", + /* 94 */ "minrows ::= MINROWS INTEGER", + /* 95 */ "maxrows ::= MAXROWS INTEGER", + /* 96 */ "blocks ::= BLOCKS INTEGER", + /* 97 */ "ctime ::= CTIME INTEGER", + /* 98 */ "wal ::= WAL INTEGER", + /* 99 */ "fsync ::= FSYNC INTEGER", + /* 100 */ "comp ::= COMP INTEGER", + /* 101 */ "prec ::= PRECISION STRING", + /* 102 */ "update ::= UPDATE INTEGER", + /* 103 */ "cachelast ::= CACHELAST INTEGER", + /* 104 */ "partitions ::= PARTITIONS INTEGER", + /* 105 */ "db_optr ::=", + /* 106 */ "db_optr ::= db_optr cache", + /* 107 */ "db_optr ::= db_optr replica", + /* 108 */ "db_optr ::= db_optr quorum", + /* 109 */ "db_optr ::= db_optr days", + /* 110 */ "db_optr ::= db_optr minrows", + /* 111 */ "db_optr ::= db_optr maxrows", + /* 112 */ "db_optr ::= db_optr blocks", + /* 113 */ "db_optr ::= db_optr ctime", + /* 114 */ "db_optr ::= db_optr wal", + /* 115 */ "db_optr ::= db_optr fsync", + /* 116 */ "db_optr ::= db_optr comp", + /* 117 */ "db_optr ::= db_optr prec", + /* 118 */ "db_optr ::= db_optr keep", + /* 119 */ "db_optr ::= db_optr update", + /* 120 */ "db_optr ::= db_optr cachelast", + /* 121 */ "topic_optr ::= db_optr", + /* 122 */ "topic_optr ::= topic_optr partitions", + /* 123 */ "alter_db_optr ::=", + /* 124 */ "alter_db_optr ::= alter_db_optr replica", + /* 125 */ "alter_db_optr ::= alter_db_optr quorum", + /* 126 */ "alter_db_optr ::= alter_db_optr keep", + /* 127 */ "alter_db_optr ::= alter_db_optr blocks", + /* 128 */ "alter_db_optr ::= alter_db_optr comp", + /* 129 */ "alter_db_optr ::= alter_db_optr update", + /* 130 */ "alter_db_optr ::= alter_db_optr cachelast", + /* 131 */ "alter_topic_optr ::= alter_db_optr", + /* 132 */ "alter_topic_optr ::= alter_topic_optr partitions", + /* 133 */ "typename ::= ids", + /* 134 */ "typename ::= ids LP signed RP", + /* 135 */ "typename ::= ids UNSIGNED", + /* 136 */ "signed ::= INTEGER", + /* 137 */ "signed ::= PLUS INTEGER", + /* 138 */ "signed ::= MINUS INTEGER", + /* 139 */ "cmd ::= CREATE TABLE create_table_args", + /* 140 */ "cmd ::= CREATE TABLE create_stable_args", + /* 141 */ "cmd ::= CREATE STABLE create_stable_args", + /* 142 */ "cmd ::= CREATE TABLE create_table_list", + /* 143 */ "create_table_list ::= create_from_stable", + /* 144 */ "create_table_list ::= create_table_list create_from_stable", + /* 145 */ "create_table_args ::= ifnotexists ids cpxName LP columnlist RP", + /* 146 */ "create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP", + /* 147 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP", + /* 148 */ "create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP", + /* 149 */ "tagNamelist ::= tagNamelist COMMA ids", + /* 150 */ "tagNamelist ::= ids", + /* 151 */ "create_table_args ::= ifnotexists ids cpxName AS select", + /* 152 */ "columnlist ::= columnlist COMMA column", + /* 153 */ "columnlist ::= column", + /* 154 */ "column ::= ids typename", + /* 155 */ "tagitemlist ::= tagitemlist COMMA tagitem", + /* 156 */ "tagitemlist ::= tagitem", + /* 157 */ "tagitem ::= INTEGER", + /* 158 */ "tagitem ::= FLOAT", + /* 159 */ "tagitem ::= STRING", + /* 160 */ "tagitem ::= BOOL", + /* 161 */ "tagitem ::= NULL", + /* 162 */ "tagitem ::= NOW", + /* 163 */ "tagitem ::= MINUS INTEGER", + /* 164 */ "tagitem ::= MINUS FLOAT", + /* 165 */ "tagitem ::= PLUS INTEGER", + /* 166 */ "tagitem ::= PLUS FLOAT", + /* 167 */ "select ::= SELECT selcollist from where_opt interval_option sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt", + /* 168 */ "select ::= LP select RP", + /* 169 */ "union ::= select", + /* 170 */ "union ::= union UNION ALL select", + /* 171 */ "cmd ::= union", + /* 172 */ "select ::= SELECT selcollist", + /* 173 */ "sclp ::= selcollist COMMA", + /* 174 */ "sclp ::=", + /* 175 */ "selcollist ::= sclp distinct expr as", + /* 176 */ "selcollist ::= sclp STAR", + /* 177 */ "as ::= AS ids", + /* 178 */ "as ::= ids", + /* 179 */ "as ::=", + /* 180 */ "distinct ::= DISTINCT", + /* 181 */ "distinct ::=", + /* 182 */ "from ::= FROM tablelist", + /* 183 */ "from ::= FROM sub", + /* 184 */ "sub ::= LP union RP", + /* 185 */ "sub ::= LP union RP ids", + /* 186 */ "sub ::= sub COMMA LP union RP ids", + /* 187 */ "tablelist ::= ids cpxName", + /* 188 */ "tablelist ::= ids cpxName ids", + /* 189 */ "tablelist ::= tablelist COMMA ids cpxName", + /* 190 */ "tablelist ::= tablelist COMMA ids cpxName ids", + /* 191 */ "tmvar ::= VARIABLE", + /* 192 */ "interval_option ::= intervalKey LP tmvar RP", + /* 193 */ "interval_option ::= intervalKey LP tmvar COMMA tmvar RP", + /* 194 */ "interval_option ::=", + /* 195 */ "intervalKey ::= INTERVAL", + /* 196 */ "intervalKey ::= EVERY", + /* 197 */ "session_option ::=", + /* 198 */ "session_option ::= SESSION LP ids cpxName COMMA tmvar RP", + /* 199 */ "windowstate_option ::=", + /* 200 */ "windowstate_option ::= STATE_WINDOW LP ids RP", + /* 201 */ "fill_opt ::=", + /* 202 */ "fill_opt ::= FILL LP ID COMMA tagitemlist RP", + /* 203 */ "fill_opt ::= FILL LP ID RP", + /* 204 */ "sliding_opt ::= SLIDING LP tmvar RP", + /* 205 */ "sliding_opt ::=", + /* 206 */ "orderby_opt ::=", + /* 207 */ "orderby_opt ::= ORDER BY sortlist", + /* 208 */ "sortlist ::= sortlist COMMA item sortorder", + /* 209 */ "sortlist ::= item sortorder", + /* 210 */ "item ::= ids cpxName", + /* 211 */ "sortorder ::= ASC", + /* 212 */ "sortorder ::= DESC", + /* 213 */ "sortorder ::=", + /* 214 */ "groupby_opt ::=", + /* 215 */ "groupby_opt ::= GROUP BY grouplist", + /* 216 */ "grouplist ::= grouplist COMMA item", + /* 217 */ "grouplist ::= item", + /* 218 */ "having_opt ::=", + /* 219 */ "having_opt ::= HAVING expr", + /* 220 */ "limit_opt ::=", + /* 221 */ "limit_opt ::= LIMIT signed", + /* 222 */ "limit_opt ::= LIMIT signed OFFSET signed", + /* 223 */ "limit_opt ::= LIMIT signed COMMA signed", + /* 224 */ "slimit_opt ::=", + /* 225 */ "slimit_opt ::= SLIMIT signed", + /* 226 */ "slimit_opt ::= SLIMIT signed SOFFSET signed", + /* 227 */ "slimit_opt ::= SLIMIT signed COMMA signed", + /* 228 */ "where_opt ::=", + /* 229 */ "where_opt ::= WHERE expr", + /* 230 */ "expr ::= LP expr RP", + /* 231 */ "expr ::= ID", + /* 232 */ "expr ::= ID DOT ID", + /* 233 */ "expr ::= ID DOT STAR", + /* 234 */ "expr ::= INTEGER", + /* 235 */ "expr ::= MINUS INTEGER", + /* 236 */ "expr ::= PLUS INTEGER", + /* 237 */ "expr ::= FLOAT", + /* 238 */ "expr ::= MINUS FLOAT", + /* 239 */ "expr ::= PLUS FLOAT", + /* 240 */ "expr ::= STRING", + /* 241 */ "expr ::= NOW", + /* 242 */ "expr ::= VARIABLE", + /* 243 */ "expr ::= PLUS VARIABLE", + /* 244 */ "expr ::= MINUS VARIABLE", + /* 245 */ "expr ::= BOOL", + /* 246 */ "expr ::= NULL", + /* 247 */ "expr ::= ID LP exprlist RP", + /* 248 */ "expr ::= ID LP STAR RP", + /* 249 */ "expr ::= expr IS NULL", + /* 250 */ "expr ::= expr IS NOT NULL", + /* 251 */ "expr ::= expr LT expr", + /* 252 */ "expr ::= expr GT expr", + /* 253 */ "expr ::= expr LE expr", + /* 254 */ "expr ::= expr GE expr", + /* 255 */ "expr ::= expr NE expr", + /* 256 */ "expr ::= expr EQ expr", + /* 257 */ "expr ::= expr BETWEEN expr AND expr", + /* 258 */ "expr ::= expr AND expr", + /* 259 */ "expr ::= expr OR expr", + /* 260 */ "expr ::= expr PLUS expr", + /* 261 */ "expr ::= expr MINUS expr", + /* 262 */ "expr ::= expr STAR expr", + /* 263 */ "expr ::= expr SLASH expr", + /* 264 */ "expr ::= expr REM expr", + /* 265 */ "expr ::= expr LIKE expr", + /* 266 */ "expr ::= expr MATCH expr", + /* 267 */ "expr ::= expr IN LP exprlist RP", + /* 268 */ "exprlist ::= exprlist COMMA expritem", + /* 269 */ "exprlist ::= expritem", + /* 270 */ "expritem ::= expr", + /* 271 */ "expritem ::=", + /* 272 */ "cmd ::= RESET QUERY CACHE", + /* 273 */ "cmd ::= SYNCDB ids REPLICA", + /* 274 */ "cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist", + /* 275 */ "cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids", + /* 276 */ "cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist", + /* 277 */ "cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist", + /* 278 */ "cmd ::= ALTER TABLE ids cpxName DROP TAG ids", + /* 279 */ "cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids", + /* 280 */ "cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem", + /* 281 */ "cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist", + /* 282 */ "cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist", + /* 283 */ "cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids", + /* 284 */ "cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist", + /* 285 */ "cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist", + /* 286 */ "cmd ::= ALTER STABLE ids cpxName DROP TAG ids", + /* 287 */ "cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids", + /* 288 */ "cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem", + /* 289 */ "cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist", + /* 290 */ "cmd ::= KILL CONNECTION INTEGER", + /* 291 */ "cmd ::= KILL STREAM INTEGER COLON INTEGER", + /* 292 */ "cmd ::= KILL QUERY INTEGER COLON INTEGER", }; #endif /* NDEBUG */ @@ -1496,76 +1507,76 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 204: /* exprlist */ - case 248: /* selcollist */ - case 262: /* sclp */ + case 205: /* exprlist */ + case 249: /* selcollist */ + case 263: /* sclp */ { -#line 750 "sql.y" -tSqlExprListDestroy((yypminor->yy131)); -#line 1506 "sql.c" +#line 761 "sql.y" +tSqlExprListDestroy((yypminor->yy403)); +#line 1517 "sql.c" } break; - 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 */ + 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 271: /* sortlist */ + case 275: /* grouplist */ { -#line 253 "sql.y" -taosArrayDestroy((yypminor->yy131)); -#line 1522 "sql.c" +#line 256 "sql.y" +taosArrayDestroy((yypminor->yy403)); +#line 1533 "sql.c" } break; - case 240: /* create_table_list */ + case 241: /* create_table_list */ { -#line 361 "sql.y" -destroyCreateTableSql((yypminor->yy272)); -#line 1529 "sql.c" +#line 364 "sql.y" +destroyCreateTableSql((yypminor->yy56)); +#line 1540 "sql.c" } break; - case 245: /* select */ + case 246: /* select */ { -#line 481 "sql.y" -destroySqlNode((yypminor->yy256)); -#line 1536 "sql.c" +#line 484 "sql.y" +destroySqlNode((yypminor->yy224)); +#line 1547 "sql.c" } break; - case 249: /* from */ - case 266: /* tablelist */ - case 267: /* sub */ + case 250: /* from */ + case 267: /* tablelist */ + case 268: /* sub */ { -#line 536 "sql.y" -destroyRelationInfo((yypminor->yy544)); -#line 1545 "sql.c" +#line 539 "sql.y" +destroyRelationInfo((yypminor->yy114)); +#line 1556 "sql.c" } break; - case 250: /* where_opt */ - case 257: /* having_opt */ - case 264: /* expr */ - case 274: /* expritem */ + case 251: /* where_opt */ + case 258: /* having_opt */ + case 265: /* expr */ + case 276: /* expritem */ { -#line 683 "sql.y" -tSqlExprDestroy((yypminor->yy46)); -#line 1555 "sql.c" +#line 691 "sql.y" +tSqlExprDestroy((yypminor->yy260)); +#line 1566 "sql.c" } break; - case 261: /* union */ + case 262: /* union */ { -#line 489 "sql.y" -destroyAllSqlNode((yypminor->yy131)); -#line 1562 "sql.c" +#line 492 "sql.y" +destroyAllSqlNode((yypminor->yy403)); +#line 1573 "sql.c" } break; - case 270: /* sortitem */ + case 272: /* sortitem */ { -#line 616 "sql.y" -tVariantDestroy(&(yypminor->yy516)); -#line 1569 "sql.c" +#line 624 "sql.y" +tVariantDestroy(&(yypminor->yy488)); +#line 1580 "sql.c" } break; /********* End destructor definitions *****************************************/ @@ -1854,295 +1865,299 @@ static void yy_shift( /* 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 */ + 196, /* (0) program ::= cmd */ + 197, /* (1) cmd ::= SHOW DATABASES */ + 197, /* (2) cmd ::= SHOW TOPICS */ + 197, /* (3) cmd ::= SHOW FUNCTIONS */ + 197, /* (4) cmd ::= SHOW MNODES */ + 197, /* (5) cmd ::= SHOW DNODES */ + 197, /* (6) cmd ::= SHOW ACCOUNTS */ + 197, /* (7) cmd ::= SHOW USERS */ + 197, /* (8) cmd ::= SHOW MODULES */ + 197, /* (9) cmd ::= SHOW QUERIES */ + 197, /* (10) cmd ::= SHOW CONNECTIONS */ + 197, /* (11) cmd ::= SHOW STREAMS */ + 197, /* (12) cmd ::= SHOW VARIABLES */ + 197, /* (13) cmd ::= SHOW SCORES */ + 197, /* (14) cmd ::= SHOW GRANTS */ + 197, /* (15) cmd ::= SHOW VNODES */ + 197, /* (16) cmd ::= SHOW VNODES ids */ + 199, /* (17) dbPrefix ::= */ + 199, /* (18) dbPrefix ::= ids DOT */ + 200, /* (19) cpxName ::= */ + 200, /* (20) cpxName ::= DOT ids */ + 197, /* (21) cmd ::= SHOW CREATE TABLE ids cpxName */ + 197, /* (22) cmd ::= SHOW CREATE STABLE ids cpxName */ + 197, /* (23) cmd ::= SHOW CREATE DATABASE ids */ + 197, /* (24) cmd ::= SHOW dbPrefix TABLES */ + 197, /* (25) cmd ::= SHOW dbPrefix TABLES LIKE ids */ + 197, /* (26) cmd ::= SHOW dbPrefix STABLES */ + 197, /* (27) cmd ::= SHOW dbPrefix STABLES LIKE ids */ + 197, /* (28) cmd ::= SHOW dbPrefix VGROUPS */ + 197, /* (29) cmd ::= SHOW dbPrefix VGROUPS ids */ + 197, /* (30) cmd ::= DROP TABLE ifexists ids cpxName */ + 197, /* (31) cmd ::= DROP STABLE ifexists ids cpxName */ + 197, /* (32) cmd ::= DROP DATABASE ifexists ids */ + 197, /* (33) cmd ::= DROP TOPIC ifexists ids */ + 197, /* (34) cmd ::= DROP FUNCTION ids */ + 197, /* (35) cmd ::= DROP DNODE ids */ + 197, /* (36) cmd ::= DROP USER ids */ + 197, /* (37) cmd ::= DROP ACCOUNT ids */ + 197, /* (38) cmd ::= USE ids */ + 197, /* (39) cmd ::= DESCRIBE ids cpxName */ + 197, /* (40) cmd ::= DESC ids cpxName */ + 197, /* (41) cmd ::= ALTER USER ids PASS ids */ + 197, /* (42) cmd ::= ALTER USER ids PRIVILEGE ids */ + 197, /* (43) cmd ::= ALTER DNODE ids ids */ + 197, /* (44) cmd ::= ALTER DNODE ids ids ids */ + 197, /* (45) cmd ::= ALTER LOCAL ids */ + 197, /* (46) cmd ::= ALTER LOCAL ids ids */ + 197, /* (47) cmd ::= ALTER DATABASE ids alter_db_optr */ + 197, /* (48) cmd ::= ALTER TOPIC ids alter_topic_optr */ + 197, /* (49) cmd ::= ALTER ACCOUNT ids acct_optr */ + 197, /* (50) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ + 197, /* (51) cmd ::= COMPACT VNODES IN LP exprlist RP */ + 198, /* (52) ids ::= ID */ + 198, /* (53) ids ::= STRING */ + 201, /* (54) ifexists ::= IF EXISTS */ + 201, /* (55) ifexists ::= */ + 206, /* (56) ifnotexists ::= IF NOT EXISTS */ + 206, /* (57) ifnotexists ::= */ + 197, /* (58) cmd ::= CREATE DNODE ids */ + 197, /* (59) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ + 197, /* (60) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ + 197, /* (61) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ + 197, /* (62) cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + 197, /* (63) cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + 197, /* (64) cmd ::= CREATE USER ids PASS ids */ + 210, /* (65) bufsize ::= */ + 210, /* (66) bufsize ::= BUFSIZE INTEGER */ + 211, /* (67) pps ::= */ + 211, /* (68) pps ::= PPS INTEGER */ + 212, /* (69) tseries ::= */ + 212, /* (70) tseries ::= TSERIES INTEGER */ + 213, /* (71) dbs ::= */ + 213, /* (72) dbs ::= DBS INTEGER */ + 214, /* (73) streams ::= */ + 214, /* (74) streams ::= STREAMS INTEGER */ + 215, /* (75) storage ::= */ + 215, /* (76) storage ::= STORAGE INTEGER */ + 216, /* (77) qtime ::= */ + 216, /* (78) qtime ::= QTIME INTEGER */ + 217, /* (79) users ::= */ + 217, /* (80) users ::= USERS INTEGER */ + 218, /* (81) conns ::= */ + 218, /* (82) conns ::= CONNS INTEGER */ + 219, /* (83) state ::= */ + 219, /* (84) state ::= STATE ids */ + 204, /* (85) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ + 220, /* (86) intitemlist ::= intitemlist COMMA intitem */ + 220, /* (87) intitemlist ::= intitem */ + 221, /* (88) intitem ::= INTEGER */ + 222, /* (89) keep ::= KEEP intitemlist */ + 223, /* (90) cache ::= CACHE INTEGER */ + 224, /* (91) replica ::= REPLICA INTEGER */ + 225, /* (92) quorum ::= QUORUM INTEGER */ + 226, /* (93) days ::= DAYS INTEGER */ + 227, /* (94) minrows ::= MINROWS INTEGER */ + 228, /* (95) maxrows ::= MAXROWS INTEGER */ + 229, /* (96) blocks ::= BLOCKS INTEGER */ + 230, /* (97) ctime ::= CTIME INTEGER */ + 231, /* (98) wal ::= WAL INTEGER */ + 232, /* (99) fsync ::= FSYNC INTEGER */ + 233, /* (100) comp ::= COMP INTEGER */ + 234, /* (101) prec ::= PRECISION STRING */ + 235, /* (102) update ::= UPDATE INTEGER */ + 236, /* (103) cachelast ::= CACHELAST INTEGER */ + 237, /* (104) partitions ::= PARTITIONS INTEGER */ + 207, /* (105) db_optr ::= */ + 207, /* (106) db_optr ::= db_optr cache */ + 207, /* (107) db_optr ::= db_optr replica */ + 207, /* (108) db_optr ::= db_optr quorum */ + 207, /* (109) db_optr ::= db_optr days */ + 207, /* (110) db_optr ::= db_optr minrows */ + 207, /* (111) db_optr ::= db_optr maxrows */ + 207, /* (112) db_optr ::= db_optr blocks */ + 207, /* (113) db_optr ::= db_optr ctime */ + 207, /* (114) db_optr ::= db_optr wal */ + 207, /* (115) db_optr ::= db_optr fsync */ + 207, /* (116) db_optr ::= db_optr comp */ + 207, /* (117) db_optr ::= db_optr prec */ + 207, /* (118) db_optr ::= db_optr keep */ + 207, /* (119) db_optr ::= db_optr update */ + 207, /* (120) db_optr ::= db_optr cachelast */ + 208, /* (121) topic_optr ::= db_optr */ + 208, /* (122) topic_optr ::= topic_optr partitions */ + 202, /* (123) alter_db_optr ::= */ + 202, /* (124) alter_db_optr ::= alter_db_optr replica */ + 202, /* (125) alter_db_optr ::= alter_db_optr quorum */ + 202, /* (126) alter_db_optr ::= alter_db_optr keep */ + 202, /* (127) alter_db_optr ::= alter_db_optr blocks */ + 202, /* (128) alter_db_optr ::= alter_db_optr comp */ + 202, /* (129) alter_db_optr ::= alter_db_optr update */ + 202, /* (130) alter_db_optr ::= alter_db_optr cachelast */ + 203, /* (131) alter_topic_optr ::= alter_db_optr */ + 203, /* (132) alter_topic_optr ::= alter_topic_optr partitions */ + 209, /* (133) typename ::= ids */ + 209, /* (134) typename ::= ids LP signed RP */ + 209, /* (135) typename ::= ids UNSIGNED */ + 238, /* (136) signed ::= INTEGER */ + 238, /* (137) signed ::= PLUS INTEGER */ + 238, /* (138) signed ::= MINUS INTEGER */ + 197, /* (139) cmd ::= CREATE TABLE create_table_args */ + 197, /* (140) cmd ::= CREATE TABLE create_stable_args */ + 197, /* (141) cmd ::= CREATE STABLE create_stable_args */ + 197, /* (142) cmd ::= CREATE TABLE create_table_list */ + 241, /* (143) create_table_list ::= create_from_stable */ + 241, /* (144) create_table_list ::= create_table_list create_from_stable */ + 239, /* (145) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ + 240, /* (146) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ + 242, /* (147) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ + 242, /* (148) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ + 245, /* (149) tagNamelist ::= tagNamelist COMMA ids */ + 245, /* (150) tagNamelist ::= ids */ + 239, /* (151) create_table_args ::= ifnotexists ids cpxName AS select */ + 243, /* (152) columnlist ::= columnlist COMMA column */ + 243, /* (153) columnlist ::= column */ + 247, /* (154) column ::= ids typename */ + 244, /* (155) tagitemlist ::= tagitemlist COMMA tagitem */ + 244, /* (156) tagitemlist ::= tagitem */ + 248, /* (157) tagitem ::= INTEGER */ + 248, /* (158) tagitem ::= FLOAT */ + 248, /* (159) tagitem ::= STRING */ + 248, /* (160) tagitem ::= BOOL */ + 248, /* (161) tagitem ::= NULL */ + 248, /* (162) tagitem ::= NOW */ + 248, /* (163) tagitem ::= MINUS INTEGER */ + 248, /* (164) tagitem ::= MINUS FLOAT */ + 248, /* (165) tagitem ::= PLUS INTEGER */ + 248, /* (166) tagitem ::= PLUS FLOAT */ + 246, /* (167) select ::= SELECT selcollist from where_opt interval_option sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt */ + 246, /* (168) select ::= LP select RP */ + 262, /* (169) union ::= select */ + 262, /* (170) union ::= union UNION ALL select */ + 197, /* (171) cmd ::= union */ + 246, /* (172) select ::= SELECT selcollist */ + 263, /* (173) sclp ::= selcollist COMMA */ + 263, /* (174) sclp ::= */ + 249, /* (175) selcollist ::= sclp distinct expr as */ + 249, /* (176) selcollist ::= sclp STAR */ + 266, /* (177) as ::= AS ids */ + 266, /* (178) as ::= ids */ + 266, /* (179) as ::= */ + 264, /* (180) distinct ::= DISTINCT */ + 264, /* (181) distinct ::= */ + 250, /* (182) from ::= FROM tablelist */ + 250, /* (183) from ::= FROM sub */ + 268, /* (184) sub ::= LP union RP */ + 268, /* (185) sub ::= LP union RP ids */ + 268, /* (186) sub ::= sub COMMA LP union RP ids */ + 267, /* (187) tablelist ::= ids cpxName */ + 267, /* (188) tablelist ::= ids cpxName ids */ + 267, /* (189) tablelist ::= tablelist COMMA ids cpxName */ + 267, /* (190) tablelist ::= tablelist COMMA ids cpxName ids */ + 269, /* (191) tmvar ::= VARIABLE */ + 252, /* (192) interval_option ::= intervalKey LP tmvar RP */ + 252, /* (193) interval_option ::= intervalKey LP tmvar COMMA tmvar RP */ + 252, /* (194) interval_option ::= */ + 270, /* (195) intervalKey ::= INTERVAL */ + 270, /* (196) intervalKey ::= EVERY */ + 254, /* (197) session_option ::= */ + 254, /* (198) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ + 255, /* (199) windowstate_option ::= */ + 255, /* (200) windowstate_option ::= STATE_WINDOW LP ids RP */ + 256, /* (201) fill_opt ::= */ + 256, /* (202) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ + 256, /* (203) fill_opt ::= FILL LP ID RP */ + 253, /* (204) sliding_opt ::= SLIDING LP tmvar RP */ + 253, /* (205) sliding_opt ::= */ + 259, /* (206) orderby_opt ::= */ + 259, /* (207) orderby_opt ::= ORDER BY sortlist */ + 271, /* (208) sortlist ::= sortlist COMMA item sortorder */ + 271, /* (209) sortlist ::= item sortorder */ + 273, /* (210) item ::= ids cpxName */ + 274, /* (211) sortorder ::= ASC */ + 274, /* (212) sortorder ::= DESC */ + 274, /* (213) sortorder ::= */ + 257, /* (214) groupby_opt ::= */ + 257, /* (215) groupby_opt ::= GROUP BY grouplist */ + 275, /* (216) grouplist ::= grouplist COMMA item */ + 275, /* (217) grouplist ::= item */ + 258, /* (218) having_opt ::= */ + 258, /* (219) having_opt ::= HAVING expr */ + 261, /* (220) limit_opt ::= */ + 261, /* (221) limit_opt ::= LIMIT signed */ + 261, /* (222) limit_opt ::= LIMIT signed OFFSET signed */ + 261, /* (223) limit_opt ::= LIMIT signed COMMA signed */ + 260, /* (224) slimit_opt ::= */ + 260, /* (225) slimit_opt ::= SLIMIT signed */ + 260, /* (226) slimit_opt ::= SLIMIT signed SOFFSET signed */ + 260, /* (227) slimit_opt ::= SLIMIT signed COMMA signed */ + 251, /* (228) where_opt ::= */ + 251, /* (229) where_opt ::= WHERE expr */ + 265, /* (230) expr ::= LP expr RP */ + 265, /* (231) expr ::= ID */ + 265, /* (232) expr ::= ID DOT ID */ + 265, /* (233) expr ::= ID DOT STAR */ + 265, /* (234) expr ::= INTEGER */ + 265, /* (235) expr ::= MINUS INTEGER */ + 265, /* (236) expr ::= PLUS INTEGER */ + 265, /* (237) expr ::= FLOAT */ + 265, /* (238) expr ::= MINUS FLOAT */ + 265, /* (239) expr ::= PLUS FLOAT */ + 265, /* (240) expr ::= STRING */ + 265, /* (241) expr ::= NOW */ + 265, /* (242) expr ::= VARIABLE */ + 265, /* (243) expr ::= PLUS VARIABLE */ + 265, /* (244) expr ::= MINUS VARIABLE */ + 265, /* (245) expr ::= BOOL */ + 265, /* (246) expr ::= NULL */ + 265, /* (247) expr ::= ID LP exprlist RP */ + 265, /* (248) expr ::= ID LP STAR RP */ + 265, /* (249) expr ::= expr IS NULL */ + 265, /* (250) expr ::= expr IS NOT NULL */ + 265, /* (251) expr ::= expr LT expr */ + 265, /* (252) expr ::= expr GT expr */ + 265, /* (253) expr ::= expr LE expr */ + 265, /* (254) expr ::= expr GE expr */ + 265, /* (255) expr ::= expr NE expr */ + 265, /* (256) expr ::= expr EQ expr */ + 265, /* (257) expr ::= expr BETWEEN expr AND expr */ + 265, /* (258) expr ::= expr AND expr */ + 265, /* (259) expr ::= expr OR expr */ + 265, /* (260) expr ::= expr PLUS expr */ + 265, /* (261) expr ::= expr MINUS expr */ + 265, /* (262) expr ::= expr STAR expr */ + 265, /* (263) expr ::= expr SLASH expr */ + 265, /* (264) expr ::= expr REM expr */ + 265, /* (265) expr ::= expr LIKE expr */ + 265, /* (266) expr ::= expr MATCH expr */ + 265, /* (267) expr ::= expr IN LP exprlist RP */ + 205, /* (268) exprlist ::= exprlist COMMA expritem */ + 205, /* (269) exprlist ::= expritem */ + 276, /* (270) expritem ::= expr */ + 276, /* (271) expritem ::= */ + 197, /* (272) cmd ::= RESET QUERY CACHE */ + 197, /* (273) cmd ::= SYNCDB ids REPLICA */ + 197, /* (274) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ + 197, /* (275) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ + 197, /* (276) cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ + 197, /* (277) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ + 197, /* (278) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ + 197, /* (279) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ + 197, /* (280) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ + 197, /* (281) cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ + 197, /* (282) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ + 197, /* (283) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ + 197, /* (284) cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ + 197, /* (285) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ + 197, /* (286) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ + 197, /* (287) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ + 197, /* (288) cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ + 197, /* (289) cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ + 197, /* (290) cmd ::= KILL CONNECTION INTEGER */ + 197, /* (291) cmd ::= KILL STREAM INTEGER COLON INTEGER */ + 197, /* (292) cmd ::= KILL QUERY INTEGER COLON INTEGER */ }; /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number @@ -2188,255 +2203,259 @@ static const signed char yyRuleInfoNRhs[] = { -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 */ + -3, /* (40) cmd ::= DESC ids cpxName */ + -5, /* (41) cmd ::= ALTER USER ids PASS ids */ + -5, /* (42) cmd ::= ALTER USER ids PRIVILEGE ids */ + -4, /* (43) cmd ::= ALTER DNODE ids ids */ + -5, /* (44) cmd ::= ALTER DNODE ids ids ids */ + -3, /* (45) cmd ::= ALTER LOCAL ids */ + -4, /* (46) cmd ::= ALTER LOCAL ids ids */ + -4, /* (47) cmd ::= ALTER DATABASE ids alter_db_optr */ + -4, /* (48) cmd ::= ALTER TOPIC ids alter_topic_optr */ + -4, /* (49) cmd ::= ALTER ACCOUNT ids acct_optr */ + -6, /* (50) cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ + -6, /* (51) cmd ::= COMPACT VNODES IN LP exprlist RP */ + -1, /* (52) ids ::= ID */ + -1, /* (53) ids ::= STRING */ + -2, /* (54) ifexists ::= IF EXISTS */ + 0, /* (55) ifexists ::= */ + -3, /* (56) ifnotexists ::= IF NOT EXISTS */ + 0, /* (57) ifnotexists ::= */ + -3, /* (58) cmd ::= CREATE DNODE ids */ + -6, /* (59) cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ + -5, /* (60) cmd ::= CREATE DATABASE ifnotexists ids db_optr */ + -5, /* (61) cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ + -8, /* (62) cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + -9, /* (63) cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + -5, /* (64) cmd ::= CREATE USER ids PASS ids */ + 0, /* (65) bufsize ::= */ + -2, /* (66) bufsize ::= BUFSIZE INTEGER */ + 0, /* (67) pps ::= */ + -2, /* (68) pps ::= PPS INTEGER */ + 0, /* (69) tseries ::= */ + -2, /* (70) tseries ::= TSERIES INTEGER */ + 0, /* (71) dbs ::= */ + -2, /* (72) dbs ::= DBS INTEGER */ + 0, /* (73) streams ::= */ + -2, /* (74) streams ::= STREAMS INTEGER */ + 0, /* (75) storage ::= */ + -2, /* (76) storage ::= STORAGE INTEGER */ + 0, /* (77) qtime ::= */ + -2, /* (78) qtime ::= QTIME INTEGER */ + 0, /* (79) users ::= */ + -2, /* (80) users ::= USERS INTEGER */ + 0, /* (81) conns ::= */ + -2, /* (82) conns ::= CONNS INTEGER */ + 0, /* (83) state ::= */ + -2, /* (84) state ::= STATE ids */ + -9, /* (85) acct_optr ::= pps tseries storage streams qtime dbs users conns state */ + -3, /* (86) intitemlist ::= intitemlist COMMA intitem */ + -1, /* (87) intitemlist ::= intitem */ + -1, /* (88) intitem ::= INTEGER */ + -2, /* (89) keep ::= KEEP intitemlist */ + -2, /* (90) cache ::= CACHE INTEGER */ + -2, /* (91) replica ::= REPLICA INTEGER */ + -2, /* (92) quorum ::= QUORUM INTEGER */ + -2, /* (93) days ::= DAYS INTEGER */ + -2, /* (94) minrows ::= MINROWS INTEGER */ + -2, /* (95) maxrows ::= MAXROWS INTEGER */ + -2, /* (96) blocks ::= BLOCKS INTEGER */ + -2, /* (97) ctime ::= CTIME INTEGER */ + -2, /* (98) wal ::= WAL INTEGER */ + -2, /* (99) fsync ::= FSYNC INTEGER */ + -2, /* (100) comp ::= COMP INTEGER */ + -2, /* (101) prec ::= PRECISION STRING */ + -2, /* (102) update ::= UPDATE INTEGER */ + -2, /* (103) cachelast ::= CACHELAST INTEGER */ + -2, /* (104) partitions ::= PARTITIONS INTEGER */ + 0, /* (105) db_optr ::= */ + -2, /* (106) db_optr ::= db_optr cache */ + -2, /* (107) db_optr ::= db_optr replica */ + -2, /* (108) db_optr ::= db_optr quorum */ + -2, /* (109) db_optr ::= db_optr days */ + -2, /* (110) db_optr ::= db_optr minrows */ + -2, /* (111) db_optr ::= db_optr maxrows */ + -2, /* (112) db_optr ::= db_optr blocks */ + -2, /* (113) db_optr ::= db_optr ctime */ + -2, /* (114) db_optr ::= db_optr wal */ + -2, /* (115) db_optr ::= db_optr fsync */ + -2, /* (116) db_optr ::= db_optr comp */ + -2, /* (117) db_optr ::= db_optr prec */ + -2, /* (118) db_optr ::= db_optr keep */ + -2, /* (119) db_optr ::= db_optr update */ + -2, /* (120) db_optr ::= db_optr cachelast */ + -1, /* (121) topic_optr ::= db_optr */ + -2, /* (122) topic_optr ::= topic_optr partitions */ + 0, /* (123) alter_db_optr ::= */ + -2, /* (124) alter_db_optr ::= alter_db_optr replica */ + -2, /* (125) alter_db_optr ::= alter_db_optr quorum */ + -2, /* (126) alter_db_optr ::= alter_db_optr keep */ + -2, /* (127) alter_db_optr ::= alter_db_optr blocks */ + -2, /* (128) alter_db_optr ::= alter_db_optr comp */ + -2, /* (129) alter_db_optr ::= alter_db_optr update */ + -2, /* (130) alter_db_optr ::= alter_db_optr cachelast */ + -1, /* (131) alter_topic_optr ::= alter_db_optr */ + -2, /* (132) alter_topic_optr ::= alter_topic_optr partitions */ + -1, /* (133) typename ::= ids */ + -4, /* (134) typename ::= ids LP signed RP */ + -2, /* (135) typename ::= ids UNSIGNED */ + -1, /* (136) signed ::= INTEGER */ + -2, /* (137) signed ::= PLUS INTEGER */ + -2, /* (138) signed ::= MINUS INTEGER */ + -3, /* (139) cmd ::= CREATE TABLE create_table_args */ + -3, /* (140) cmd ::= CREATE TABLE create_stable_args */ + -3, /* (141) cmd ::= CREATE STABLE create_stable_args */ + -3, /* (142) cmd ::= CREATE TABLE create_table_list */ + -1, /* (143) create_table_list ::= create_from_stable */ + -2, /* (144) create_table_list ::= create_table_list create_from_stable */ + -6, /* (145) create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ + -10, /* (146) create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ + -10, /* (147) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ + -13, /* (148) create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ + -3, /* (149) tagNamelist ::= tagNamelist COMMA ids */ + -1, /* (150) tagNamelist ::= ids */ + -5, /* (151) create_table_args ::= ifnotexists ids cpxName AS select */ + -3, /* (152) columnlist ::= columnlist COMMA column */ + -1, /* (153) columnlist ::= column */ + -2, /* (154) column ::= ids typename */ + -3, /* (155) tagitemlist ::= tagitemlist COMMA tagitem */ + -1, /* (156) tagitemlist ::= tagitem */ + -1, /* (157) tagitem ::= INTEGER */ + -1, /* (158) tagitem ::= FLOAT */ + -1, /* (159) tagitem ::= STRING */ + -1, /* (160) tagitem ::= BOOL */ + -1, /* (161) tagitem ::= NULL */ + -1, /* (162) tagitem ::= NOW */ + -2, /* (163) tagitem ::= MINUS INTEGER */ + -2, /* (164) tagitem ::= MINUS FLOAT */ + -2, /* (165) tagitem ::= PLUS INTEGER */ + -2, /* (166) tagitem ::= PLUS FLOAT */ + -14, /* (167) select ::= SELECT selcollist from where_opt interval_option sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt */ + -3, /* (168) select ::= LP select RP */ + -1, /* (169) union ::= select */ + -4, /* (170) union ::= union UNION ALL select */ + -1, /* (171) cmd ::= union */ + -2, /* (172) select ::= SELECT selcollist */ + -2, /* (173) sclp ::= selcollist COMMA */ + 0, /* (174) sclp ::= */ + -4, /* (175) selcollist ::= sclp distinct expr as */ + -2, /* (176) selcollist ::= sclp STAR */ + -2, /* (177) as ::= AS ids */ + -1, /* (178) as ::= ids */ + 0, /* (179) as ::= */ + -1, /* (180) distinct ::= DISTINCT */ + 0, /* (181) distinct ::= */ + -2, /* (182) from ::= FROM tablelist */ + -2, /* (183) from ::= FROM sub */ + -3, /* (184) sub ::= LP union RP */ + -4, /* (185) sub ::= LP union RP ids */ + -6, /* (186) sub ::= sub COMMA LP union RP ids */ + -2, /* (187) tablelist ::= ids cpxName */ + -3, /* (188) tablelist ::= ids cpxName ids */ + -4, /* (189) tablelist ::= tablelist COMMA ids cpxName */ + -5, /* (190) tablelist ::= tablelist COMMA ids cpxName ids */ + -1, /* (191) tmvar ::= VARIABLE */ + -4, /* (192) interval_option ::= intervalKey LP tmvar RP */ + -6, /* (193) interval_option ::= intervalKey LP tmvar COMMA tmvar RP */ + 0, /* (194) interval_option ::= */ + -1, /* (195) intervalKey ::= INTERVAL */ + -1, /* (196) intervalKey ::= EVERY */ + 0, /* (197) session_option ::= */ + -7, /* (198) session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ + 0, /* (199) windowstate_option ::= */ + -4, /* (200) windowstate_option ::= STATE_WINDOW LP ids RP */ + 0, /* (201) fill_opt ::= */ + -6, /* (202) fill_opt ::= FILL LP ID COMMA tagitemlist RP */ + -4, /* (203) fill_opt ::= FILL LP ID RP */ + -4, /* (204) sliding_opt ::= SLIDING LP tmvar RP */ + 0, /* (205) sliding_opt ::= */ + 0, /* (206) orderby_opt ::= */ + -3, /* (207) orderby_opt ::= ORDER BY sortlist */ + -4, /* (208) sortlist ::= sortlist COMMA item sortorder */ + -2, /* (209) sortlist ::= item sortorder */ + -2, /* (210) item ::= ids cpxName */ + -1, /* (211) sortorder ::= ASC */ + -1, /* (212) sortorder ::= DESC */ + 0, /* (213) sortorder ::= */ + 0, /* (214) groupby_opt ::= */ + -3, /* (215) groupby_opt ::= GROUP BY grouplist */ + -3, /* (216) grouplist ::= grouplist COMMA item */ + -1, /* (217) grouplist ::= item */ + 0, /* (218) having_opt ::= */ + -2, /* (219) having_opt ::= HAVING expr */ + 0, /* (220) limit_opt ::= */ + -2, /* (221) limit_opt ::= LIMIT signed */ + -4, /* (222) limit_opt ::= LIMIT signed OFFSET signed */ + -4, /* (223) limit_opt ::= LIMIT signed COMMA signed */ + 0, /* (224) slimit_opt ::= */ + -2, /* (225) slimit_opt ::= SLIMIT signed */ + -4, /* (226) slimit_opt ::= SLIMIT signed SOFFSET signed */ + -4, /* (227) slimit_opt ::= SLIMIT signed COMMA signed */ + 0, /* (228) where_opt ::= */ + -2, /* (229) where_opt ::= WHERE expr */ + -3, /* (230) expr ::= LP expr RP */ + -1, /* (231) expr ::= ID */ + -3, /* (232) expr ::= ID DOT ID */ + -3, /* (233) expr ::= ID DOT STAR */ + -1, /* (234) expr ::= INTEGER */ + -2, /* (235) expr ::= MINUS INTEGER */ + -2, /* (236) expr ::= PLUS INTEGER */ + -1, /* (237) expr ::= FLOAT */ + -2, /* (238) expr ::= MINUS FLOAT */ + -2, /* (239) expr ::= PLUS FLOAT */ + -1, /* (240) expr ::= STRING */ + -1, /* (241) expr ::= NOW */ + -1, /* (242) expr ::= VARIABLE */ + -2, /* (243) expr ::= PLUS VARIABLE */ + -2, /* (244) expr ::= MINUS VARIABLE */ + -1, /* (245) expr ::= BOOL */ + -1, /* (246) expr ::= NULL */ + -4, /* (247) expr ::= ID LP exprlist RP */ + -4, /* (248) expr ::= ID LP STAR RP */ + -3, /* (249) expr ::= expr IS NULL */ + -4, /* (250) expr ::= expr IS NOT NULL */ + -3, /* (251) expr ::= expr LT expr */ + -3, /* (252) expr ::= expr GT expr */ + -3, /* (253) expr ::= expr LE expr */ + -3, /* (254) expr ::= expr GE expr */ + -3, /* (255) expr ::= expr NE expr */ + -3, /* (256) expr ::= expr EQ expr */ + -5, /* (257) expr ::= expr BETWEEN expr AND expr */ + -3, /* (258) expr ::= expr AND expr */ + -3, /* (259) expr ::= expr OR expr */ + -3, /* (260) expr ::= expr PLUS expr */ + -3, /* (261) expr ::= expr MINUS expr */ + -3, /* (262) expr ::= expr STAR expr */ + -3, /* (263) expr ::= expr SLASH expr */ + -3, /* (264) expr ::= expr REM expr */ + -3, /* (265) expr ::= expr LIKE expr */ + -3, /* (266) expr ::= expr MATCH expr */ + -5, /* (267) expr ::= expr IN LP exprlist RP */ + -3, /* (268) exprlist ::= exprlist COMMA expritem */ + -1, /* (269) exprlist ::= expritem */ + -1, /* (270) expritem ::= expr */ + 0, /* (271) expritem ::= */ + -3, /* (272) cmd ::= RESET QUERY CACHE */ + -3, /* (273) cmd ::= SYNCDB ids REPLICA */ + -7, /* (274) cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ + -7, /* (275) cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ + -7, /* (276) cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ + -7, /* (277) cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ + -7, /* (278) cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ + -8, /* (279) cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ + -9, /* (280) cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ + -7, /* (281) cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ + -7, /* (282) cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ + -7, /* (283) cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ + -7, /* (284) cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ + -7, /* (285) cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ + -7, /* (286) cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ + -8, /* (287) cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ + -9, /* (288) cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ + -7, /* (289) cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ + -3, /* (290) cmd ::= KILL CONNECTION INTEGER */ + -5, /* (291) cmd ::= KILL STREAM INTEGER COLON INTEGER */ + -5, /* (292) cmd ::= KILL QUERY INTEGER COLON INTEGER */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -2527,113 +2546,113 @@ static YYACTIONTYPE yy_reduce( /********** Begin reduce actions **********************************************/ YYMINORTYPE yylhsminor; case 0: /* program ::= cmd */ - 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); + case 139: /* cmd ::= CREATE TABLE create_table_args */ yytestcase(yyruleno==139); + case 140: /* cmd ::= CREATE TABLE create_stable_args */ yytestcase(yyruleno==140); + case 141: /* cmd ::= CREATE STABLE create_stable_args */ yytestcase(yyruleno==141); #line 63 "sql.y" {} -#line 2536 "sql.c" +#line 2555 "sql.c" break; case 1: /* cmd ::= SHOW DATABASES */ #line 66 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_DB, 0, 0);} -#line 2541 "sql.c" +#line 2560 "sql.c" break; case 2: /* cmd ::= SHOW TOPICS */ #line 67 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_TP, 0, 0);} -#line 2546 "sql.c" +#line 2565 "sql.c" break; case 3: /* cmd ::= SHOW FUNCTIONS */ #line 68 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_FUNCTION, 0, 0);} -#line 2551 "sql.c" +#line 2570 "sql.c" break; case 4: /* cmd ::= SHOW MNODES */ #line 69 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_MNODE, 0, 0);} -#line 2556 "sql.c" +#line 2575 "sql.c" break; case 5: /* cmd ::= SHOW DNODES */ #line 70 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_DNODE, 0, 0);} -#line 2561 "sql.c" +#line 2580 "sql.c" break; case 6: /* cmd ::= SHOW ACCOUNTS */ #line 71 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_ACCT, 0, 0);} -#line 2566 "sql.c" +#line 2585 "sql.c" break; case 7: /* cmd ::= SHOW USERS */ #line 72 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_USER, 0, 0);} -#line 2571 "sql.c" +#line 2590 "sql.c" break; case 8: /* cmd ::= SHOW MODULES */ #line 74 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_MODULE, 0, 0); } -#line 2576 "sql.c" +#line 2595 "sql.c" break; case 9: /* cmd ::= SHOW QUERIES */ #line 75 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_QUERIES, 0, 0); } -#line 2581 "sql.c" +#line 2600 "sql.c" break; case 10: /* cmd ::= SHOW CONNECTIONS */ #line 76 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_CONNS, 0, 0);} -#line 2586 "sql.c" +#line 2605 "sql.c" break; case 11: /* cmd ::= SHOW STREAMS */ #line 77 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_STREAMS, 0, 0); } -#line 2591 "sql.c" +#line 2610 "sql.c" break; case 12: /* cmd ::= SHOW VARIABLES */ #line 78 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_VARIABLES, 0, 0); } -#line 2596 "sql.c" +#line 2615 "sql.c" break; case 13: /* cmd ::= SHOW SCORES */ #line 79 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_SCORES, 0, 0); } -#line 2601 "sql.c" +#line 2620 "sql.c" break; case 14: /* cmd ::= SHOW GRANTS */ #line 80 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_GRANTS, 0, 0); } -#line 2606 "sql.c" +#line 2625 "sql.c" break; case 15: /* cmd ::= SHOW VNODES */ #line 82 "sql.y" { setShowOptions(pInfo, TSDB_MGMT_TABLE_VNODES, 0, 0); } -#line 2611 "sql.c" +#line 2630 "sql.c" break; 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" +#line 2635 "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" +#line 2640 "sql.c" break; case 18: /* dbPrefix ::= ids DOT */ #line 88 "sql.y" {yylhsminor.yy0 = yymsp[-1].minor.yy0; } -#line 2626 "sql.c" +#line 2645 "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" +#line 2651 "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" +#line 2656 "sql.c" break; case 21: /* cmd ::= SHOW CREATE TABLE ids cpxName */ #line 94 "sql.y" @@ -2641,7 +2660,7 @@ static YYACTIONTYPE yy_reduce( 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" +#line 2664 "sql.c" break; case 22: /* cmd ::= SHOW CREATE STABLE ids cpxName */ #line 98 "sql.y" @@ -2649,35 +2668,35 @@ static YYACTIONTYPE yy_reduce( 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" +#line 2672 "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" +#line 2679 "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" +#line 2686 "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" +#line 2693 "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" +#line 2700 "sql.c" break; case 27: /* cmd ::= SHOW dbPrefix STABLES LIKE ids */ #line 119 "sql.y" @@ -2686,7 +2705,7 @@ static YYACTIONTYPE yy_reduce( tSetDbName(&token, &yymsp[-3].minor.yy0); setShowOptions(pInfo, TSDB_MGMT_TABLE_METRIC, &token, &yymsp[0].minor.yy0); } -#line 2690 "sql.c" +#line 2709 "sql.c" break; case 28: /* cmd ::= SHOW dbPrefix VGROUPS */ #line 125 "sql.y" @@ -2695,7 +2714,7 @@ static YYACTIONTYPE yy_reduce( tSetDbName(&token, &yymsp[-1].minor.yy0); setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, 0); } -#line 2699 "sql.c" +#line 2718 "sql.c" break; case 29: /* cmd ::= SHOW dbPrefix VGROUPS ids */ #line 131 "sql.y" @@ -2704,7 +2723,7 @@ static YYACTIONTYPE yy_reduce( tSetDbName(&token, &yymsp[-2].minor.yy0); setShowOptions(pInfo, TSDB_MGMT_TABLE_VGROUP, &token, &yymsp[0].minor.yy0); } -#line 2708 "sql.c" +#line 2727 "sql.c" break; case 30: /* cmd ::= DROP TABLE ifexists ids cpxName */ #line 138 "sql.y" @@ -2712,7 +2731,7 @@ static YYACTIONTYPE yy_reduce( 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" +#line 2735 "sql.c" break; case 31: /* cmd ::= DROP STABLE ifexists ids cpxName */ #line 144 "sql.y" @@ -2720,1151 +2739,1170 @@ static YYACTIONTYPE yy_reduce( 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" +#line 2743 "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" +#line 2748 "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" +#line 2753 "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" +#line 2758 "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" +#line 2763 "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" +#line 2768 "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" +#line 2773 "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" +#line 2778 "sql.c" break; case 39: /* cmd ::= DESCRIBE ids cpxName */ + case 40: /* cmd ::= DESC ids cpxName */ yytestcase(yyruleno==40); #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" +#line 2787 "sql.c" break; - case 40: /* cmd ::= ALTER USER ids PASS ids */ -#line 167 "sql.y" + case 41: /* cmd ::= ALTER USER ids PASS ids */ +#line 170 "sql.y" { setAlterUserSql(pInfo, TSDB_ALTER_USER_PASSWD, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, NULL); } -#line 2772 "sql.c" +#line 2792 "sql.c" break; - case 41: /* cmd ::= ALTER USER ids PRIVILEGE ids */ -#line 168 "sql.y" + case 42: /* cmd ::= ALTER USER ids PRIVILEGE ids */ +#line 171 "sql.y" { setAlterUserSql(pInfo, TSDB_ALTER_USER_PRIVILEGES, &yymsp[-2].minor.yy0, NULL, &yymsp[0].minor.yy0);} -#line 2777 "sql.c" +#line 2797 "sql.c" break; - case 42: /* cmd ::= ALTER DNODE ids ids */ -#line 169 "sql.y" + case 43: /* cmd ::= ALTER DNODE ids ids */ +#line 172 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_CFG_DNODE, 2, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } -#line 2782 "sql.c" +#line 2802 "sql.c" break; - case 43: /* cmd ::= ALTER DNODE ids ids ids */ -#line 170 "sql.y" + case 44: /* cmd ::= ALTER DNODE ids ids ids */ +#line 173 "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" +#line 2807 "sql.c" break; - case 44: /* cmd ::= ALTER LOCAL ids */ -#line 171 "sql.y" + case 45: /* cmd ::= ALTER LOCAL ids */ +#line 174 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_CFG_LOCAL, 1, &yymsp[0].minor.yy0); } -#line 2792 "sql.c" +#line 2812 "sql.c" break; - case 45: /* cmd ::= ALTER LOCAL ids ids */ -#line 172 "sql.y" + case 46: /* cmd ::= ALTER LOCAL ids ids */ +#line 175 "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); -#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" +#line 2817 "sql.c" break; - case 48: /* cmd ::= ALTER ACCOUNT ids acct_optr */ + case 47: /* cmd ::= ALTER DATABASE ids alter_db_optr */ + case 48: /* cmd ::= ALTER TOPIC ids alter_topic_optr */ yytestcase(yyruleno==48); #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 */ -#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 */ -#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" +{ SStrToken t = {0}; setCreateDbInfo(pInfo, TSDB_SQL_ALTER_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy246, &t);} +#line 2823 "sql.c" + break; + case 49: /* cmd ::= ALTER ACCOUNT ids acct_optr */ +#line 179 "sql.y" +{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-1].minor.yy0, NULL, &yymsp[0].minor.yy377);} +#line 2828 "sql.c" + break; + case 50: /* cmd ::= ALTER ACCOUNT ids PASS ids acct_optr */ +#line 180 "sql.y" +{ setCreateAcctSql(pInfo, TSDB_SQL_ALTER_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy377);} +#line 2833 "sql.c" + break; + case 51: /* cmd ::= COMPACT VNODES IN LP exprlist RP */ +#line 184 "sql.y" +{ setCompactVnodeSql(pInfo, TSDB_SQL_COMPACT_VNODE, yymsp[-1].minor.yy403);} +#line 2838 "sql.c" + break; + case 52: /* ids ::= ID */ + case 53: /* ids ::= STRING */ yytestcase(yyruleno==53); +#line 190 "sql.y" {yylhsminor.yy0 = yymsp[0].minor.yy0; } -#line 2824 "sql.c" +#line 2844 "sql.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; - case 53: /* ifexists ::= IF EXISTS */ -#line 191 "sql.y" + case 54: /* ifexists ::= IF EXISTS */ +#line 194 "sql.y" { yymsp[-1].minor.yy0.n = 1;} -#line 2830 "sql.c" +#line 2850 "sql.c" break; - case 54: /* ifexists ::= */ - case 56: /* ifnotexists ::= */ yytestcase(yyruleno==56); - case 180: /* distinct ::= */ yytestcase(yyruleno==180); -#line 192 "sql.y" + case 55: /* ifexists ::= */ + case 57: /* ifnotexists ::= */ yytestcase(yyruleno==57); + case 181: /* distinct ::= */ yytestcase(yyruleno==181); +#line 195 "sql.y" { yymsp[1].minor.yy0.n = 0;} -#line 2837 "sql.c" +#line 2857 "sql.c" break; - case 55: /* ifnotexists ::= IF NOT EXISTS */ -#line 195 "sql.y" + case 56: /* ifnotexists ::= IF NOT EXISTS */ +#line 198 "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 */ -#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" +#line 2862 "sql.c" break; - case 59: /* cmd ::= CREATE DATABASE ifnotexists ids db_optr */ - case 60: /* cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ yytestcase(yyruleno==60); + case 58: /* cmd ::= CREATE DNODE ids */ #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" +{ setDCLSqlElems(pInfo, TSDB_SQL_CREATE_DNODE, 1, &yymsp[0].minor.yy0);} +#line 2867 "sql.c" break; - case 61: /* cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + case 59: /* cmd ::= CREATE ACCOUNT ids PASS ids acct_optr */ #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" +{ setCreateAcctSql(pInfo, TSDB_SQL_CREATE_ACCT, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy377);} +#line 2872 "sql.c" break; - case 62: /* cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ + case 60: /* cmd ::= CREATE DATABASE ifnotexists ids db_optr */ + case 61: /* cmd ::= CREATE TOPIC ifnotexists ids topic_optr */ yytestcase(yyruleno==61); #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" +{ setCreateDbInfo(pInfo, TSDB_SQL_CREATE_DB, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy246, &yymsp[-2].minor.yy0);} +#line 2878 "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); - case 68: /* tseries ::= */ yytestcase(yyruleno==68); - case 70: /* dbs ::= */ yytestcase(yyruleno==70); - case 72: /* streams ::= */ yytestcase(yyruleno==72); - case 74: /* storage ::= */ yytestcase(yyruleno==74); - case 76: /* qtime ::= */ yytestcase(yyruleno==76); - case 78: /* users ::= */ yytestcase(yyruleno==78); - case 80: /* conns ::= */ yytestcase(yyruleno==80); - case 82: /* state ::= */ yytestcase(yyruleno==82); + case 62: /* cmd ::= CREATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ +#line 208 "sql.y" +{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-5].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy363, &yymsp[0].minor.yy0, 1);} +#line 2883 "sql.c" + break; + case 63: /* cmd ::= CREATE AGGREGATE FUNCTION ids AS ids OUTPUTTYPE typename bufsize */ #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); - case 69: /* tseries ::= TSERIES INTEGER */ yytestcase(yyruleno==69); - case 71: /* dbs ::= DBS INTEGER */ yytestcase(yyruleno==71); - case 73: /* streams ::= STREAMS INTEGER */ yytestcase(yyruleno==73); - case 75: /* storage ::= STORAGE INTEGER */ yytestcase(yyruleno==75); - case 77: /* qtime ::= QTIME INTEGER */ yytestcase(yyruleno==77); - case 79: /* users ::= USERS INTEGER */ yytestcase(yyruleno==79); - case 81: /* conns ::= CONNS INTEGER */ yytestcase(yyruleno==81); - case 83: /* state ::= STATE ids */ yytestcase(yyruleno==83); +{ setCreateFuncInfo(pInfo, TSDB_SQL_CREATE_FUNCTION, &yymsp[-5].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-1].minor.yy363, &yymsp[0].minor.yy0, 2);} +#line 2888 "sql.c" + break; + case 64: /* cmd ::= CREATE USER ids PASS ids */ #line 210 "sql.y" +{ setCreateUserSql(pInfo, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);} +#line 2893 "sql.c" + break; + case 65: /* bufsize ::= */ + case 67: /* pps ::= */ yytestcase(yyruleno==67); + case 69: /* tseries ::= */ yytestcase(yyruleno==69); + case 71: /* dbs ::= */ yytestcase(yyruleno==71); + case 73: /* streams ::= */ yytestcase(yyruleno==73); + case 75: /* storage ::= */ yytestcase(yyruleno==75); + case 77: /* qtime ::= */ yytestcase(yyruleno==77); + case 79: /* users ::= */ yytestcase(yyruleno==79); + case 81: /* conns ::= */ yytestcase(yyruleno==81); + case 83: /* state ::= */ yytestcase(yyruleno==83); +#line 212 "sql.y" +{ yymsp[1].minor.yy0.n = 0; } +#line 2907 "sql.c" + break; + case 66: /* bufsize ::= BUFSIZE INTEGER */ + case 68: /* pps ::= PPS INTEGER */ yytestcase(yyruleno==68); + case 70: /* tseries ::= TSERIES INTEGER */ yytestcase(yyruleno==70); + case 72: /* dbs ::= DBS INTEGER */ yytestcase(yyruleno==72); + case 74: /* streams ::= STREAMS INTEGER */ yytestcase(yyruleno==74); + case 76: /* storage ::= STORAGE INTEGER */ yytestcase(yyruleno==76); + case 78: /* qtime ::= QTIME INTEGER */ yytestcase(yyruleno==78); + case 80: /* users ::= USERS INTEGER */ yytestcase(yyruleno==80); + case 82: /* conns ::= CONNS INTEGER */ yytestcase(yyruleno==82); + case 84: /* state ::= STATE ids */ yytestcase(yyruleno==84); +#line 213 "sql.y" { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } -#line 2901 "sql.c" +#line 2921 "sql.c" break; - case 84: /* acct_optr ::= pps tseries storage streams qtime dbs users conns state */ -#line 240 "sql.y" + case 85: /* acct_optr ::= pps tseries storage streams qtime dbs users conns state */ +#line 243 "sql.y" { - 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; + yylhsminor.yy377.maxUsers = (yymsp[-2].minor.yy0.n>0)?atoi(yymsp[-2].minor.yy0.z):-1; + yylhsminor.yy377.maxDbs = (yymsp[-3].minor.yy0.n>0)?atoi(yymsp[-3].minor.yy0.z):-1; + yylhsminor.yy377.maxTimeSeries = (yymsp[-7].minor.yy0.n>0)?atoi(yymsp[-7].minor.yy0.z):-1; + yylhsminor.yy377.maxStreams = (yymsp[-5].minor.yy0.n>0)?atoi(yymsp[-5].minor.yy0.z):-1; + yylhsminor.yy377.maxPointsPerSecond = (yymsp[-8].minor.yy0.n>0)?atoi(yymsp[-8].minor.yy0.z):-1; + yylhsminor.yy377.maxStorage = (yymsp[-6].minor.yy0.n>0)?strtoll(yymsp[-6].minor.yy0.z, NULL, 10):-1; + yylhsminor.yy377.maxQueryTime = (yymsp[-4].minor.yy0.n>0)?strtoll(yymsp[-4].minor.yy0.z, NULL, 10):-1; + yylhsminor.yy377.maxConnections = (yymsp[-1].minor.yy0.n>0)?atoi(yymsp[-1].minor.yy0.z):-1; + yylhsminor.yy377.stat = yymsp[0].minor.yy0; } -#line 2916 "sql.c" - yymsp[-8].minor.yy341 = yylhsminor.yy341; +#line 2936 "sql.c" + yymsp[-8].minor.yy377 = yylhsminor.yy377; break; - case 85: /* intitemlist ::= intitemlist COMMA intitem */ - case 154: /* tagitemlist ::= tagitemlist COMMA tagitem */ yytestcase(yyruleno==154); -#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); -#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); + case 86: /* intitemlist ::= intitemlist COMMA intitem */ + case 155: /* tagitemlist ::= tagitemlist COMMA tagitem */ yytestcase(yyruleno==155); #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 */ -#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); - case 91: /* quorum ::= QUORUM INTEGER */ yytestcase(yyruleno==91); - case 92: /* days ::= DAYS INTEGER */ yytestcase(yyruleno==92); - case 93: /* minrows ::= MINROWS INTEGER */ yytestcase(yyruleno==93); - case 94: /* maxrows ::= MAXROWS INTEGER */ yytestcase(yyruleno==94); - case 95: /* blocks ::= BLOCKS INTEGER */ yytestcase(yyruleno==95); - case 96: /* ctime ::= CTIME INTEGER */ yytestcase(yyruleno==96); - case 97: /* wal ::= WAL INTEGER */ yytestcase(yyruleno==97); - case 98: /* fsync ::= FSYNC INTEGER */ yytestcase(yyruleno==98); - case 99: /* comp ::= COMP INTEGER */ yytestcase(yyruleno==99); - case 100: /* prec ::= PRECISION STRING */ yytestcase(yyruleno==100); - 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" +{ yylhsminor.yy403 = tVariantListAppend(yymsp[-2].minor.yy403, &yymsp[0].minor.yy488, -1); } +#line 2943 "sql.c" + yymsp[-2].minor.yy403 = yylhsminor.yy403; + break; + case 87: /* intitemlist ::= intitem */ + case 156: /* tagitemlist ::= tagitem */ yytestcase(yyruleno==156); +#line 260 "sql.y" +{ yylhsminor.yy403 = tVariantListAppend(NULL, &yymsp[0].minor.yy488, -1); } +#line 2950 "sql.c" + yymsp[0].minor.yy403 = yylhsminor.yy403; + break; + case 88: /* intitem ::= INTEGER */ + case 157: /* tagitem ::= INTEGER */ yytestcase(yyruleno==157); + case 158: /* tagitem ::= FLOAT */ yytestcase(yyruleno==158); + case 159: /* tagitem ::= STRING */ yytestcase(yyruleno==159); + case 160: /* tagitem ::= BOOL */ yytestcase(yyruleno==160); +#line 262 "sql.y" +{ toTSDBType(yymsp[0].minor.yy0.type); tVariantCreate(&yylhsminor.yy488, &yymsp[0].minor.yy0); } +#line 2960 "sql.c" + yymsp[0].minor.yy488 = yylhsminor.yy488; + break; + case 89: /* keep ::= KEEP intitemlist */ +#line 266 "sql.y" +{ yymsp[-1].minor.yy403 = yymsp[0].minor.yy403; } +#line 2966 "sql.c" + break; + case 90: /* cache ::= CACHE INTEGER */ + case 91: /* replica ::= REPLICA INTEGER */ yytestcase(yyruleno==91); + case 92: /* quorum ::= QUORUM INTEGER */ yytestcase(yyruleno==92); + case 93: /* days ::= DAYS INTEGER */ yytestcase(yyruleno==93); + case 94: /* minrows ::= MINROWS INTEGER */ yytestcase(yyruleno==94); + case 95: /* maxrows ::= MAXROWS INTEGER */ yytestcase(yyruleno==95); + case 96: /* blocks ::= BLOCKS INTEGER */ yytestcase(yyruleno==96); + case 97: /* ctime ::= CTIME INTEGER */ yytestcase(yyruleno==97); + case 98: /* wal ::= WAL INTEGER */ yytestcase(yyruleno==98); + case 99: /* fsync ::= FSYNC INTEGER */ yytestcase(yyruleno==99); + case 100: /* comp ::= COMP INTEGER */ yytestcase(yyruleno==100); + case 101: /* prec ::= PRECISION STRING */ yytestcase(yyruleno==101); + case 102: /* update ::= UPDATE INTEGER */ yytestcase(yyruleno==102); + case 103: /* cachelast ::= CACHELAST INTEGER */ yytestcase(yyruleno==103); + case 104: /* partitions ::= PARTITIONS INTEGER */ yytestcase(yyruleno==104); +#line 268 "sql.y" { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } -#line 2965 "sql.c" - break; - case 104: /* db_optr ::= */ -#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 */ -#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; +#line 2985 "sql.c" break; - case 106: /* db_optr ::= db_optr replica */ - case 123: /* alter_db_optr ::= alter_db_optr replica */ yytestcase(yyruleno==123); + case 105: /* db_optr ::= */ #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); -#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 */ +{setDefaultCreateDbOption(&yymsp[1].minor.yy246); yymsp[1].minor.yy246.dbType = TSDB_DB_TYPE_DEFAULT;} +#line 2990 "sql.c" + break; + case 106: /* db_optr ::= db_optr cache */ #line 287 "sql.y" -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.daysPerFile = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.cacheBlockSize = strtol(yymsp[0].minor.yy0.z, NULL, 10); } #line 2995 "sql.c" - yymsp[-1].minor.yy42 = yylhsminor.yy42; + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 109: /* db_optr ::= db_optr minrows */ + case 107: /* db_optr ::= db_optr replica */ + case 124: /* alter_db_optr ::= alter_db_optr replica */ yytestcase(yyruleno==124); #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; +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.replica = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3002 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 110: /* db_optr ::= db_optr maxrows */ + case 108: /* db_optr ::= db_optr quorum */ + case 125: /* alter_db_optr ::= alter_db_optr quorum */ yytestcase(yyruleno==125); #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; +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.quorum = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3009 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 111: /* db_optr ::= db_optr blocks */ - case 126: /* alter_db_optr ::= alter_db_optr blocks */ yytestcase(yyruleno==126); + case 109: /* db_optr ::= db_optr days */ #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; +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.daysPerFile = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3015 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 112: /* db_optr ::= db_optr ctime */ + case 110: /* db_optr ::= db_optr minrows */ #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; +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.minRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } +#line 3021 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 113: /* db_optr ::= db_optr wal */ + case 111: /* db_optr ::= db_optr maxrows */ #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; +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.maxRowsPerBlock = strtod(yymsp[0].minor.yy0.z, NULL); } +#line 3027 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 114: /* db_optr ::= db_optr fsync */ + case 112: /* db_optr ::= db_optr blocks */ + case 127: /* alter_db_optr ::= alter_db_optr blocks */ yytestcase(yyruleno==127); #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; +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.numOfBlocks = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3034 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 115: /* db_optr ::= db_optr comp */ - case 127: /* alter_db_optr ::= alter_db_optr comp */ yytestcase(yyruleno==127); + case 113: /* db_optr ::= db_optr ctime */ #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; +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.commitTime = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3040 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 116: /* db_optr ::= db_optr prec */ + case 114: /* db_optr ::= db_optr wal */ #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; +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.walLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3046 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 117: /* db_optr ::= db_optr keep */ - case 125: /* alter_db_optr ::= alter_db_optr keep */ yytestcase(yyruleno==125); + case 115: /* db_optr ::= db_optr fsync */ #line 296 "sql.y" -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.keep = yymsp[0].minor.yy131; } +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.fsyncPeriod = strtol(yymsp[0].minor.yy0.z, NULL, 10); } #line 3052 "sql.c" - yymsp[-1].minor.yy42 = yylhsminor.yy42; + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 118: /* db_optr ::= db_optr update */ - case 128: /* alter_db_optr ::= alter_db_optr update */ yytestcase(yyruleno==128); + case 116: /* db_optr ::= db_optr comp */ + case 128: /* alter_db_optr ::= alter_db_optr comp */ yytestcase(yyruleno==128); #line 297 "sql.y" -{ yylhsminor.yy42 = yymsp[-1].minor.yy42; yylhsminor.yy42.update = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.compressionLevel = strtol(yymsp[0].minor.yy0.z, NULL, 10); } #line 3059 "sql.c" - yymsp[-1].minor.yy42 = yylhsminor.yy42; + yymsp[-1].minor.yy246 = yylhsminor.yy246; break; - case 119: /* db_optr ::= db_optr cachelast */ - case 129: /* alter_db_optr ::= alter_db_optr cachelast */ yytestcase(yyruleno==129); + case 117: /* db_optr ::= db_optr prec */ #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); -#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); -#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 ::= */ -#line 306 "sql.y" -{ setDefaultCreateDbOption(&yymsp[1].minor.yy42); yymsp[1].minor.yy42.dbType = TSDB_DB_TYPE_DEFAULT;} +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.precision = yymsp[0].minor.yy0; } +#line 3065 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; + break; + case 118: /* db_optr ::= db_optr keep */ + case 126: /* alter_db_optr ::= alter_db_optr keep */ yytestcase(yyruleno==126); +#line 299 "sql.y" +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.keep = yymsp[0].minor.yy403; } +#line 3072 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; + break; + case 119: /* db_optr ::= db_optr update */ + case 129: /* alter_db_optr ::= alter_db_optr update */ yytestcase(yyruleno==129); +#line 300 "sql.y" +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.update = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3079 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; + break; + case 120: /* db_optr ::= db_optr cachelast */ + case 130: /* alter_db_optr ::= alter_db_optr cachelast */ yytestcase(yyruleno==130); +#line 301 "sql.y" +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.cachelast = strtol(yymsp[0].minor.yy0.z, NULL, 10); } #line 3086 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; + break; + case 121: /* topic_optr ::= db_optr */ + case 131: /* alter_topic_optr ::= alter_db_optr */ yytestcase(yyruleno==131); +#line 305 "sql.y" +{ yylhsminor.yy246 = yymsp[0].minor.yy246; yylhsminor.yy246.dbType = TSDB_DB_TYPE_TOPIC; } +#line 3093 "sql.c" + yymsp[0].minor.yy246 = yylhsminor.yy246; + break; + case 122: /* topic_optr ::= topic_optr partitions */ + case 132: /* alter_topic_optr ::= alter_topic_optr partitions */ yytestcase(yyruleno==132); +#line 306 "sql.y" +{ yylhsminor.yy246 = yymsp[-1].minor.yy246; yylhsminor.yy246.partitions = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3100 "sql.c" + yymsp[-1].minor.yy246 = yylhsminor.yy246; + break; + case 123: /* alter_db_optr ::= */ +#line 309 "sql.y" +{ setDefaultCreateDbOption(&yymsp[1].minor.yy246); yymsp[1].minor.yy246.dbType = TSDB_DB_TYPE_DEFAULT;} +#line 3106 "sql.c" break; - case 132: /* typename ::= ids */ -#line 326 "sql.y" + case 133: /* typename ::= ids */ +#line 329 "sql.y" { yymsp[0].minor.yy0.type = 0; - tSetColumnType (&yylhsminor.yy163, &yymsp[0].minor.yy0); + tSetColumnType (&yylhsminor.yy363, &yymsp[0].minor.yy0); } -#line 3094 "sql.c" - yymsp[0].minor.yy163 = yylhsminor.yy163; +#line 3114 "sql.c" + yymsp[0].minor.yy363 = yylhsminor.yy363; break; - case 133: /* typename ::= ids LP signed RP */ -#line 332 "sql.y" + case 134: /* typename ::= ids LP signed RP */ +#line 335 "sql.y" { - if (yymsp[-1].minor.yy459 <= 0) { + if (yymsp[-1].minor.yy387 <= 0) { yymsp[-3].minor.yy0.type = 0; - tSetColumnType(&yylhsminor.yy163, &yymsp[-3].minor.yy0); + tSetColumnType(&yylhsminor.yy363, &yymsp[-3].minor.yy0); } else { - yymsp[-3].minor.yy0.type = -yymsp[-1].minor.yy459; // negative value of name length - tSetColumnType(&yylhsminor.yy163, &yymsp[-3].minor.yy0); + yymsp[-3].minor.yy0.type = -yymsp[-1].minor.yy387; // negative value of name length + tSetColumnType(&yylhsminor.yy363, &yymsp[-3].minor.yy0); } } -#line 3108 "sql.c" - yymsp[-3].minor.yy163 = yylhsminor.yy163; +#line 3128 "sql.c" + yymsp[-3].minor.yy363 = yylhsminor.yy363; break; - case 134: /* typename ::= ids UNSIGNED */ -#line 343 "sql.y" + case 135: /* typename ::= ids UNSIGNED */ +#line 346 "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.yy163, &yymsp[-1].minor.yy0); + tSetColumnType (&yylhsminor.yy363, &yymsp[-1].minor.yy0); } -#line 3118 "sql.c" - yymsp[-1].minor.yy163 = yylhsminor.yy163; - break; - case 135: /* signed ::= INTEGER */ -#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 */ -#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 */ -#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 */ -#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" +#line 3138 "sql.c" + yymsp[-1].minor.yy363 = yylhsminor.yy363; + break; + case 136: /* signed ::= INTEGER */ +#line 353 "sql.y" +{ yylhsminor.yy387 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3144 "sql.c" + yymsp[0].minor.yy387 = yylhsminor.yy387; + break; + case 137: /* signed ::= PLUS INTEGER */ +#line 354 "sql.y" +{ yymsp[-1].minor.yy387 = strtol(yymsp[0].minor.yy0.z, NULL, 10); } +#line 3150 "sql.c" + break; + case 138: /* signed ::= MINUS INTEGER */ +#line 355 "sql.y" +{ yymsp[-1].minor.yy387 = -strtol(yymsp[0].minor.yy0.z, NULL, 10);} +#line 3155 "sql.c" + break; + case 142: /* cmd ::= CREATE TABLE create_table_list */ +#line 361 "sql.y" +{ pInfo->type = TSDB_SQL_CREATE_TABLE; pInfo->pCreateTableInfo = yymsp[0].minor.yy56;} +#line 3160 "sql.c" + break; + case 143: /* create_table_list ::= create_from_stable */ +#line 365 "sql.y" { SCreateTableSql* pCreateTable = calloc(1, sizeof(SCreateTableSql)); pCreateTable->childTableInfo = taosArrayInit(4, sizeof(SCreatedTableInfo)); - taosArrayPush(pCreateTable->childTableInfo, &yymsp[0].minor.yy96); + taosArrayPush(pCreateTable->childTableInfo, &yymsp[0].minor.yy84); pCreateTable->type = TSQL_CREATE_TABLE_FROM_STABLE; - yylhsminor.yy272 = pCreateTable; + yylhsminor.yy56 = pCreateTable; } -#line 3152 "sql.c" - yymsp[0].minor.yy272 = yylhsminor.yy272; +#line 3172 "sql.c" + yymsp[0].minor.yy56 = yylhsminor.yy56; break; - case 143: /* create_table_list ::= create_table_list create_from_stable */ -#line 371 "sql.y" + case 144: /* create_table_list ::= create_table_list create_from_stable */ +#line 374 "sql.y" { - taosArrayPush(yymsp[-1].minor.yy272->childTableInfo, &yymsp[0].minor.yy96); - yylhsminor.yy272 = yymsp[-1].minor.yy272; + taosArrayPush(yymsp[-1].minor.yy56->childTableInfo, &yymsp[0].minor.yy84); + yylhsminor.yy56 = yymsp[-1].minor.yy56; } -#line 3161 "sql.c" - yymsp[-1].minor.yy272 = yylhsminor.yy272; +#line 3181 "sql.c" + yymsp[-1].minor.yy56 = yylhsminor.yy56; break; - case 144: /* create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ -#line 377 "sql.y" + case 145: /* create_table_args ::= ifnotexists ids cpxName LP columnlist RP */ +#line 380 "sql.y" { - yylhsminor.yy272 = tSetCreateTableInfo(yymsp[-1].minor.yy131, NULL, NULL, TSQL_CREATE_TABLE); - setSqlInfo(pInfo, yylhsminor.yy272, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy56 = tSetCreateTableInfo(yymsp[-1].minor.yy403, NULL, NULL, TSQL_CREATE_TABLE); + setSqlInfo(pInfo, yylhsminor.yy56, 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); } -#line 3173 "sql.c" - yymsp[-5].minor.yy272 = yylhsminor.yy272; +#line 3193 "sql.c" + yymsp[-5].minor.yy56 = yylhsminor.yy56; break; - case 145: /* create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ -#line 387 "sql.y" + case 146: /* create_stable_args ::= ifnotexists ids cpxName LP columnlist RP TAGS LP columnlist RP */ +#line 390 "sql.y" { - yylhsminor.yy272 = tSetCreateTableInfo(yymsp[-5].minor.yy131, yymsp[-1].minor.yy131, NULL, TSQL_CREATE_STABLE); - setSqlInfo(pInfo, yylhsminor.yy272, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy56 = tSetCreateTableInfo(yymsp[-5].minor.yy403, yymsp[-1].minor.yy403, NULL, TSQL_CREATE_STABLE); + setSqlInfo(pInfo, yylhsminor.yy56, 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); } -#line 3185 "sql.c" - yymsp[-9].minor.yy272 = yylhsminor.yy272; +#line 3205 "sql.c" + yymsp[-9].minor.yy56 = yylhsminor.yy56; break; - case 146: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ -#line 398 "sql.y" + case 147: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName TAGS LP tagitemlist RP */ +#line 401 "sql.y" { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; - yylhsminor.yy96 = createNewChildTableInfo(&yymsp[-5].minor.yy0, NULL, yymsp[-1].minor.yy131, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); + yylhsminor.yy84 = createNewChildTableInfo(&yymsp[-5].minor.yy0, NULL, yymsp[-1].minor.yy403, &yymsp[-8].minor.yy0, &yymsp[-9].minor.yy0); } -#line 3195 "sql.c" - yymsp[-9].minor.yy96 = yylhsminor.yy96; +#line 3215 "sql.c" + yymsp[-9].minor.yy84 = yylhsminor.yy84; break; - case 147: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ -#line 404 "sql.y" + case 148: /* create_from_stable ::= ifnotexists ids cpxName USING ids cpxName LP tagNamelist RP TAGS LP tagitemlist RP */ +#line 407 "sql.y" { yymsp[-8].minor.yy0.n += yymsp[-7].minor.yy0.n; yymsp[-11].minor.yy0.n += yymsp[-10].minor.yy0.n; - yylhsminor.yy96 = createNewChildTableInfo(&yymsp[-8].minor.yy0, yymsp[-5].minor.yy131, yymsp[-1].minor.yy131, &yymsp[-11].minor.yy0, &yymsp[-12].minor.yy0); + yylhsminor.yy84 = createNewChildTableInfo(&yymsp[-8].minor.yy0, yymsp[-5].minor.yy403, yymsp[-1].minor.yy403, &yymsp[-11].minor.yy0, &yymsp[-12].minor.yy0); } -#line 3205 "sql.c" - yymsp[-12].minor.yy96 = yylhsminor.yy96; - break; - case 148: /* tagNamelist ::= tagNamelist COMMA ids */ -#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 */ -#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" +#line 3225 "sql.c" + yymsp[-12].minor.yy84 = yylhsminor.yy84; + break; + case 149: /* tagNamelist ::= tagNamelist COMMA ids */ +#line 415 "sql.y" +{taosArrayPush(yymsp[-2].minor.yy403, &yymsp[0].minor.yy0); yylhsminor.yy403 = yymsp[-2].minor.yy403; } +#line 3231 "sql.c" + yymsp[-2].minor.yy403 = yylhsminor.yy403; + break; + case 150: /* tagNamelist ::= ids */ +#line 416 "sql.y" +{yylhsminor.yy403 = taosArrayInit(4, sizeof(SStrToken)); taosArrayPush(yylhsminor.yy403, &yymsp[0].minor.yy0);} +#line 3237 "sql.c" + yymsp[0].minor.yy403 = yylhsminor.yy403; + break; + case 151: /* create_table_args ::= ifnotexists ids cpxName AS select */ +#line 420 "sql.y" { - yylhsminor.yy272 = tSetCreateTableInfo(NULL, NULL, yymsp[0].minor.yy256, TSQL_CREATE_STREAM); - setSqlInfo(pInfo, yylhsminor.yy272, NULL, TSDB_SQL_CREATE_TABLE); + yylhsminor.yy56 = tSetCreateTableInfo(NULL, NULL, yymsp[0].minor.yy224, TSQL_CREATE_STREAM); + setSqlInfo(pInfo, yylhsminor.yy56, 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); } -#line 3229 "sql.c" - yymsp[-4].minor.yy272 = yylhsminor.yy272; - break; - case 151: /* columnlist ::= columnlist COMMA column */ -#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 */ -#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.yy163, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy163); -} #line 3249 "sql.c" - yymsp[-1].minor.yy163 = yylhsminor.yy163; + yymsp[-4].minor.yy56 = yylhsminor.yy56; break; - case 160: /* tagitem ::= NULL */ -#line 448 "sql.y" -{ yymsp[0].minor.yy0.type = 0; tVariantCreate(&yylhsminor.yy516, &yymsp[0].minor.yy0); } + case 152: /* columnlist ::= columnlist COMMA column */ +#line 431 "sql.y" +{taosArrayPush(yymsp[-2].minor.yy403, &yymsp[0].minor.yy363); yylhsminor.yy403 = yymsp[-2].minor.yy403; } #line 3255 "sql.c" - yymsp[0].minor.yy516 = yylhsminor.yy516; + yymsp[-2].minor.yy403 = yylhsminor.yy403; break; - case 161: /* tagitem ::= NOW */ -#line 449 "sql.y" -{ yymsp[0].minor.yy0.type = TSDB_DATA_TYPE_TIMESTAMP; tVariantCreate(&yylhsminor.yy516, &yymsp[0].minor.yy0);} + case 153: /* columnlist ::= column */ +#line 432 "sql.y" +{yylhsminor.yy403 = taosArrayInit(4, sizeof(TAOS_FIELD)); taosArrayPush(yylhsminor.yy403, &yymsp[0].minor.yy363);} #line 3261 "sql.c" - yymsp[0].minor.yy516 = yylhsminor.yy516; + yymsp[0].minor.yy403 = yylhsminor.yy403; 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); + case 154: /* column ::= ids typename */ +#line 436 "sql.y" +{ + tSetColumnInfo(&yylhsminor.yy363, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy363); +} +#line 3269 "sql.c" + yymsp[-1].minor.yy363 = yylhsminor.yy363; + break; + case 161: /* tagitem ::= NULL */ #line 451 "sql.y" +{ yymsp[0].minor.yy0.type = 0; tVariantCreate(&yylhsminor.yy488, &yymsp[0].minor.yy0); } +#line 3275 "sql.c" + yymsp[0].minor.yy488 = yylhsminor.yy488; + break; + case 162: /* tagitem ::= NOW */ +#line 452 "sql.y" +{ yymsp[0].minor.yy0.type = TSDB_DATA_TYPE_TIMESTAMP; tVariantCreate(&yylhsminor.yy488, &yymsp[0].minor.yy0);} +#line 3281 "sql.c" + yymsp[0].minor.yy488 = yylhsminor.yy488; + break; + case 163: /* tagitem ::= MINUS INTEGER */ + case 164: /* tagitem ::= MINUS FLOAT */ yytestcase(yyruleno==164); + case 165: /* tagitem ::= PLUS INTEGER */ yytestcase(yyruleno==165); + case 166: /* tagitem ::= PLUS FLOAT */ yytestcase(yyruleno==166); +#line 454 "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.yy516, &yymsp[-1].minor.yy0); + tVariantCreate(&yylhsminor.yy488, &yymsp[-1].minor.yy0); } -#line 3275 "sql.c" - yymsp[-1].minor.yy516 = yylhsminor.yy516; +#line 3295 "sql.c" + yymsp[-1].minor.yy488 = yylhsminor.yy488; 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" + case 167: /* select ::= SELECT selcollist from where_opt interval_option sliding_opt session_option windowstate_option fill_opt groupby_opt having_opt orderby_opt slimit_opt limit_opt */ +#line 485 "sql.y" { - 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); + yylhsminor.yy224 = tSetQuerySqlNode(&yymsp[-13].minor.yy0, yymsp[-12].minor.yy403, yymsp[-11].minor.yy114, yymsp[-10].minor.yy260, yymsp[-4].minor.yy403, yymsp[-2].minor.yy403, &yymsp[-9].minor.yy222, &yymsp[-7].minor.yy365, &yymsp[-6].minor.yy544, &yymsp[-8].minor.yy0, yymsp[-5].minor.yy403, &yymsp[0].minor.yy404, &yymsp[-1].minor.yy404, yymsp[-3].minor.yy260); } -#line 3283 "sql.c" - yymsp[-13].minor.yy256 = yylhsminor.yy256; - break; - case 167: /* select ::= LP select RP */ -#line 486 "sql.y" -{yymsp[-2].minor.yy256 = yymsp[-1].minor.yy256;} -#line 3289 "sql.c" - break; - case 168: /* union ::= select */ -#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 */ -#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 */ -#line 493 "sql.y" -{ setSqlInfo(pInfo, yymsp[0].minor.yy131, NULL, TSDB_SQL_SELECT); } -#line 3306 "sql.c" +#line 3303 "sql.c" + yymsp[-13].minor.yy224 = yylhsminor.yy224; break; - case 171: /* select ::= SELECT selcollist */ -#line 500 "sql.y" -{ - yylhsminor.yy256 = tSetQuerySqlNode(&yymsp[-1].minor.yy0, yymsp[0].minor.yy131, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); -} -#line 3313 "sql.c" - yymsp[-1].minor.yy256 = yylhsminor.yy256; - break; - case 172: /* sclp ::= selcollist COMMA */ -#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); -#line 513 "sql.y" -{yymsp[1].minor.yy131 = 0;} + case 168: /* select ::= LP select RP */ +#line 489 "sql.y" +{yymsp[-2].minor.yy224 = yymsp[-1].minor.yy224;} +#line 3309 "sql.c" + break; + case 169: /* union ::= select */ +#line 493 "sql.y" +{ yylhsminor.yy403 = setSubclause(NULL, yymsp[0].minor.yy224); } +#line 3314 "sql.c" + yymsp[0].minor.yy403 = yylhsminor.yy403; + break; + case 170: /* union ::= union UNION ALL select */ +#line 494 "sql.y" +{ yylhsminor.yy403 = appendSelectClause(yymsp[-3].minor.yy403, yymsp[0].minor.yy224); } +#line 3320 "sql.c" + yymsp[-3].minor.yy403 = yylhsminor.yy403; + break; + case 171: /* cmd ::= union */ +#line 496 "sql.y" +{ setSqlInfo(pInfo, yymsp[0].minor.yy403, NULL, TSDB_SQL_SELECT); } #line 3326 "sql.c" break; - case 174: /* selcollist ::= sclp distinct expr as */ -#line 514 "sql.y" + case 172: /* select ::= SELECT selcollist */ +#line 503 "sql.y" { - 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); + yylhsminor.yy224 = tSetQuerySqlNode(&yymsp[-1].minor.yy0, yymsp[0].minor.yy403, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } #line 3333 "sql.c" - yymsp[-3].minor.yy131 = yylhsminor.yy131; + yymsp[-1].minor.yy224 = yylhsminor.yy224; + break; + case 173: /* sclp ::= selcollist COMMA */ +#line 515 "sql.y" +{yylhsminor.yy403 = yymsp[-1].minor.yy403;} +#line 3339 "sql.c" + yymsp[-1].minor.yy403 = yylhsminor.yy403; + break; + case 174: /* sclp ::= */ + case 206: /* orderby_opt ::= */ yytestcase(yyruleno==206); +#line 516 "sql.y" +{yymsp[1].minor.yy403 = 0;} +#line 3346 "sql.c" + break; + case 175: /* selcollist ::= sclp distinct expr as */ +#line 517 "sql.y" +{ + yylhsminor.yy403 = tSqlExprListAppend(yymsp[-3].minor.yy403, yymsp[-1].minor.yy260, yymsp[-2].minor.yy0.n? &yymsp[-2].minor.yy0:0, yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); +} +#line 3353 "sql.c" + yymsp[-3].minor.yy403 = yylhsminor.yy403; break; - case 175: /* selcollist ::= sclp STAR */ -#line 518 "sql.y" + case 176: /* selcollist ::= sclp STAR */ +#line 521 "sql.y" { tSqlExpr *pNode = tSqlExprCreateIdValue(NULL, TK_ALL); - yylhsminor.yy131 = tSqlExprListAppend(yymsp[-1].minor.yy131, pNode, 0, 0); + yylhsminor.yy403 = tSqlExprListAppend(yymsp[-1].minor.yy403, pNode, 0, 0); } -#line 3342 "sql.c" - yymsp[-1].minor.yy131 = yylhsminor.yy131; +#line 3362 "sql.c" + yymsp[-1].minor.yy403 = yylhsminor.yy403; break; - case 176: /* as ::= AS ids */ -#line 526 "sql.y" + case 177: /* as ::= AS ids */ +#line 529 "sql.y" { yymsp[-1].minor.yy0 = yymsp[0].minor.yy0; } -#line 3348 "sql.c" +#line 3368 "sql.c" break; - case 177: /* as ::= ids */ -#line 527 "sql.y" + case 178: /* as ::= ids */ +#line 530 "sql.y" { yylhsminor.yy0 = yymsp[0].minor.yy0; } -#line 3353 "sql.c" +#line 3373 "sql.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; - case 178: /* as ::= */ -#line 528 "sql.y" + case 179: /* as ::= */ +#line 531 "sql.y" { yymsp[1].minor.yy0.n = 0; } -#line 3359 "sql.c" +#line 3379 "sql.c" break; - case 179: /* distinct ::= DISTINCT */ -#line 531 "sql.y" + case 180: /* distinct ::= DISTINCT */ +#line 534 "sql.y" { yylhsminor.yy0 = yymsp[0].minor.yy0; } -#line 3364 "sql.c" +#line 3384 "sql.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; - case 181: /* from ::= FROM tablelist */ - case 182: /* from ::= FROM sub */ yytestcase(yyruleno==182); -#line 537 "sql.y" -{yymsp[-1].minor.yy544 = yymsp[0].minor.yy544;} -#line 3371 "sql.c" - break; - case 183: /* sub ::= LP union RP */ -#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 */ -#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 */ -#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" + case 182: /* from ::= FROM tablelist */ + case 183: /* from ::= FROM sub */ yytestcase(yyruleno==183); +#line 540 "sql.y" +{yymsp[-1].minor.yy114 = yymsp[0].minor.yy114;} +#line 3391 "sql.c" + break; + case 184: /* sub ::= LP union RP */ +#line 545 "sql.y" +{yymsp[-2].minor.yy114 = addSubqueryElem(NULL, yymsp[-1].minor.yy403, NULL);} +#line 3396 "sql.c" + break; + case 185: /* sub ::= LP union RP ids */ +#line 546 "sql.y" +{yymsp[-3].minor.yy114 = addSubqueryElem(NULL, yymsp[-2].minor.yy403, &yymsp[0].minor.yy0);} +#line 3401 "sql.c" + break; + case 186: /* sub ::= sub COMMA LP union RP ids */ +#line 547 "sql.y" +{yylhsminor.yy114 = addSubqueryElem(yymsp[-5].minor.yy114, yymsp[-2].minor.yy403, &yymsp[0].minor.yy0);} +#line 3406 "sql.c" + yymsp[-5].minor.yy114 = yylhsminor.yy114; + break; + case 187: /* tablelist ::= ids cpxName */ +#line 551 "sql.y" { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy544 = setTableNameList(NULL, &yymsp[-1].minor.yy0, NULL); + yylhsminor.yy114 = setTableNameList(NULL, &yymsp[-1].minor.yy0, NULL); } -#line 3395 "sql.c" - yymsp[-1].minor.yy544 = yylhsminor.yy544; +#line 3415 "sql.c" + yymsp[-1].minor.yy114 = yylhsminor.yy114; break; - case 187: /* tablelist ::= ids cpxName ids */ -#line 553 "sql.y" + case 188: /* tablelist ::= ids cpxName ids */ +#line 556 "sql.y" { yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy544 = setTableNameList(NULL, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + yylhsminor.yy114 = setTableNameList(NULL, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } -#line 3404 "sql.c" - yymsp[-2].minor.yy544 = yylhsminor.yy544; +#line 3424 "sql.c" + yymsp[-2].minor.yy114 = yylhsminor.yy114; break; - case 188: /* tablelist ::= tablelist COMMA ids cpxName */ -#line 558 "sql.y" + case 189: /* tablelist ::= tablelist COMMA ids cpxName */ +#line 561 "sql.y" { yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - yylhsminor.yy544 = setTableNameList(yymsp[-3].minor.yy544, &yymsp[-1].minor.yy0, NULL); + yylhsminor.yy114 = setTableNameList(yymsp[-3].minor.yy114, &yymsp[-1].minor.yy0, NULL); } -#line 3413 "sql.c" - yymsp[-3].minor.yy544 = yylhsminor.yy544; +#line 3433 "sql.c" + yymsp[-3].minor.yy114 = yylhsminor.yy114; break; - case 189: /* tablelist ::= tablelist COMMA ids cpxName ids */ -#line 563 "sql.y" + case 190: /* tablelist ::= tablelist COMMA ids cpxName ids */ +#line 566 "sql.y" { yymsp[-2].minor.yy0.n += yymsp[-1].minor.yy0.n; - yylhsminor.yy544 = setTableNameList(yymsp[-4].minor.yy544, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + yylhsminor.yy114 = setTableNameList(yymsp[-4].minor.yy114, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } -#line 3422 "sql.c" - yymsp[-4].minor.yy544 = yylhsminor.yy544; +#line 3442 "sql.c" + yymsp[-4].minor.yy114 = yylhsminor.yy114; break; - case 190: /* tmvar ::= VARIABLE */ -#line 570 "sql.y" + case 191: /* tmvar ::= VARIABLE */ +#line 573 "sql.y" {yylhsminor.yy0 = yymsp[0].minor.yy0;} -#line 3428 "sql.c" +#line 3448 "sql.c" yymsp[0].minor.yy0 = yylhsminor.yy0; break; - case 191: /* interval_opt ::= INTERVAL LP tmvar RP */ -#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 */ -#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" + case 192: /* interval_option ::= intervalKey LP tmvar RP */ +#line 576 "sql.y" +{yylhsminor.yy222.interval = yymsp[-1].minor.yy0; yylhsminor.yy222.offset.n = 0; yylhsminor.yy222.token = yymsp[-3].minor.yy202;} +#line 3454 "sql.c" + yymsp[-3].minor.yy222 = yylhsminor.yy222; break; - case 193: /* interval_opt ::= */ -#line 575 "sql.y" -{memset(&yymsp[1].minor.yy530, 0, sizeof(yymsp[1].minor.yy530));} -#line 3444 "sql.c" + case 193: /* interval_option ::= intervalKey LP tmvar COMMA tmvar RP */ +#line 577 "sql.y" +{yylhsminor.yy222.interval = yymsp[-3].minor.yy0; yylhsminor.yy222.offset = yymsp[-1].minor.yy0; yylhsminor.yy222.token = yymsp[-5].minor.yy202;} +#line 3460 "sql.c" + yymsp[-5].minor.yy222 = yylhsminor.yy222; break; - case 194: /* session_option ::= */ + case 194: /* interval_option ::= */ #line 578 "sql.y" -{yymsp[1].minor.yy39.col.n = 0; yymsp[1].minor.yy39.gap.n = 0;} -#line 3449 "sql.c" +{memset(&yymsp[1].minor.yy222, 0, sizeof(yymsp[1].minor.yy222));} +#line 3466 "sql.c" break; - case 195: /* session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ -#line 579 "sql.y" + case 195: /* intervalKey ::= INTERVAL */ +#line 581 "sql.y" +{yymsp[0].minor.yy202 = TK_INTERVAL;} +#line 3471 "sql.c" + break; + case 196: /* intervalKey ::= EVERY */ +#line 582 "sql.y" +{yymsp[0].minor.yy202 = TK_EVERY; } +#line 3476 "sql.c" + break; + case 197: /* session_option ::= */ +#line 585 "sql.y" +{yymsp[1].minor.yy365.col.n = 0; yymsp[1].minor.yy365.gap.n = 0;} +#line 3481 "sql.c" + break; + case 198: /* session_option ::= SESSION LP ids cpxName COMMA tmvar RP */ +#line 586 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - yymsp[-6].minor.yy39.col = yymsp[-4].minor.yy0; - yymsp[-6].minor.yy39.gap = yymsp[-1].minor.yy0; + yymsp[-6].minor.yy365.col = yymsp[-4].minor.yy0; + yymsp[-6].minor.yy365.gap = yymsp[-1].minor.yy0; } -#line 3458 "sql.c" +#line 3490 "sql.c" break; - case 196: /* windowstate_option ::= */ -#line 585 "sql.y" -{ yymsp[1].minor.yy538.col.n = 0; yymsp[1].minor.yy538.col.z = NULL;} -#line 3463 "sql.c" + case 199: /* windowstate_option ::= */ +#line 593 "sql.y" +{ yymsp[1].minor.yy544.col.n = 0; yymsp[1].minor.yy544.col.z = NULL;} +#line 3495 "sql.c" break; - case 197: /* windowstate_option ::= STATE_WINDOW LP ids RP */ -#line 586 "sql.y" -{ yymsp[-3].minor.yy538.col = yymsp[-1].minor.yy0; } -#line 3468 "sql.c" + case 200: /* windowstate_option ::= STATE_WINDOW LP ids RP */ +#line 594 "sql.y" +{ yymsp[-3].minor.yy544.col = yymsp[-1].minor.yy0; } +#line 3500 "sql.c" break; - case 198: /* fill_opt ::= */ -#line 590 "sql.y" -{ yymsp[1].minor.yy131 = 0; } -#line 3473 "sql.c" + case 201: /* fill_opt ::= */ +#line 598 "sql.y" +{ yymsp[1].minor.yy403 = 0; } +#line 3505 "sql.c" break; - case 199: /* fill_opt ::= FILL LP ID COMMA tagitemlist RP */ -#line 591 "sql.y" + case 202: /* fill_opt ::= FILL LP ID COMMA tagitemlist RP */ +#line 599 "sql.y" { tVariant A = {0}; toTSDBType(yymsp[-3].minor.yy0.type); tVariantCreate(&A, &yymsp[-3].minor.yy0); - tVariantListInsert(yymsp[-1].minor.yy131, &A, -1, 0); - yymsp[-5].minor.yy131 = yymsp[-1].minor.yy131; + tVariantListInsert(yymsp[-1].minor.yy403, &A, -1, 0); + yymsp[-5].minor.yy403 = yymsp[-1].minor.yy403; } -#line 3485 "sql.c" +#line 3517 "sql.c" break; - case 200: /* fill_opt ::= FILL LP ID RP */ -#line 600 "sql.y" + case 203: /* fill_opt ::= FILL LP ID RP */ +#line 608 "sql.y" { toTSDBType(yymsp[-1].minor.yy0.type); - yymsp[-3].minor.yy131 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); + yymsp[-3].minor.yy403 = tVariantListAppendToken(NULL, &yymsp[-1].minor.yy0, -1); } -#line 3493 "sql.c" +#line 3525 "sql.c" break; - case 201: /* sliding_opt ::= SLIDING LP tmvar RP */ -#line 606 "sql.y" + case 204: /* sliding_opt ::= SLIDING LP tmvar RP */ +#line 614 "sql.y" {yymsp[-3].minor.yy0 = yymsp[-1].minor.yy0; } -#line 3498 "sql.c" +#line 3530 "sql.c" break; - case 202: /* sliding_opt ::= */ -#line 607 "sql.y" + case 205: /* sliding_opt ::= */ +#line 615 "sql.y" {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = NULL; yymsp[1].minor.yy0.type = 0; } -#line 3503 "sql.c" +#line 3535 "sql.c" break; - case 204: /* orderby_opt ::= ORDER BY sortlist */ -#line 619 "sql.y" -{yymsp[-2].minor.yy131 = yymsp[0].minor.yy131;} -#line 3508 "sql.c" + case 207: /* orderby_opt ::= ORDER BY sortlist */ +#line 627 "sql.y" +{yymsp[-2].minor.yy403 = yymsp[0].minor.yy403;} +#line 3540 "sql.c" break; - case 205: /* sortlist ::= sortlist COMMA item sortorder */ -#line 621 "sql.y" + case 208: /* sortlist ::= sortlist COMMA item sortorder */ +#line 629 "sql.y" { - yylhsminor.yy131 = tVariantListAppend(yymsp[-3].minor.yy131, &yymsp[-1].minor.yy516, yymsp[0].minor.yy43); + yylhsminor.yy403 = tVariantListAppend(yymsp[-3].minor.yy403, &yymsp[-1].minor.yy488, yymsp[0].minor.yy70); } -#line 3515 "sql.c" - yymsp[-3].minor.yy131 = yylhsminor.yy131; +#line 3547 "sql.c" + yymsp[-3].minor.yy403 = yylhsminor.yy403; break; - case 206: /* sortlist ::= item sortorder */ -#line 625 "sql.y" + case 209: /* sortlist ::= item sortorder */ +#line 633 "sql.y" { - yylhsminor.yy131 = tVariantListAppend(NULL, &yymsp[-1].minor.yy516, yymsp[0].minor.yy43); + yylhsminor.yy403 = tVariantListAppend(NULL, &yymsp[-1].minor.yy488, yymsp[0].minor.yy70); } -#line 3523 "sql.c" - yymsp[-1].minor.yy131 = yylhsminor.yy131; +#line 3555 "sql.c" + yymsp[-1].minor.yy403 = yylhsminor.yy403; break; - case 207: /* item ::= ids cpxName */ -#line 630 "sql.y" + case 210: /* item ::= ids cpxName */ +#line 638 "sql.y" { toTSDBType(yymsp[-1].minor.yy0.type); yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; - tVariantCreate(&yylhsminor.yy516, &yymsp[-1].minor.yy0); + tVariantCreate(&yylhsminor.yy488, &yymsp[-1].minor.yy0); } -#line 3534 "sql.c" - yymsp[-1].minor.yy516 = yylhsminor.yy516; - break; - case 208: /* sortorder ::= ASC */ -#line 638 "sql.y" -{ yymsp[0].minor.yy43 = TSDB_ORDER_ASC; } -#line 3540 "sql.c" +#line 3566 "sql.c" + yymsp[-1].minor.yy488 = yylhsminor.yy488; break; - case 209: /* sortorder ::= DESC */ -#line 639 "sql.y" -{ yymsp[0].minor.yy43 = TSDB_ORDER_DESC;} -#line 3545 "sql.c" + case 211: /* sortorder ::= ASC */ +#line 646 "sql.y" +{ yymsp[0].minor.yy70 = TSDB_ORDER_ASC; } +#line 3572 "sql.c" break; - case 210: /* sortorder ::= */ -#line 640 "sql.y" -{ yymsp[1].minor.yy43 = TSDB_ORDER_ASC; } -#line 3550 "sql.c" + case 212: /* sortorder ::= DESC */ +#line 647 "sql.y" +{ yymsp[0].minor.yy70 = TSDB_ORDER_DESC;} +#line 3577 "sql.c" break; - case 211: /* groupby_opt ::= */ + case 213: /* sortorder ::= */ #line 648 "sql.y" -{ yymsp[1].minor.yy131 = 0;} -#line 3555 "sql.c" +{ yymsp[1].minor.yy70 = TSDB_ORDER_ASC; } +#line 3582 "sql.c" break; - case 212: /* groupby_opt ::= GROUP BY grouplist */ -#line 649 "sql.y" -{ yymsp[-2].minor.yy131 = yymsp[0].minor.yy131;} -#line 3560 "sql.c" + case 214: /* groupby_opt ::= */ +#line 656 "sql.y" +{ yymsp[1].minor.yy403 = 0;} +#line 3587 "sql.c" break; - case 213: /* grouplist ::= grouplist COMMA item */ -#line 651 "sql.y" + case 215: /* groupby_opt ::= GROUP BY grouplist */ +#line 657 "sql.y" +{ yymsp[-2].minor.yy403 = yymsp[0].minor.yy403;} +#line 3592 "sql.c" + break; + case 216: /* grouplist ::= grouplist COMMA item */ +#line 659 "sql.y" { - yylhsminor.yy131 = tVariantListAppend(yymsp[-2].minor.yy131, &yymsp[0].minor.yy516, -1); + yylhsminor.yy403 = tVariantListAppend(yymsp[-2].minor.yy403, &yymsp[0].minor.yy488, -1); } -#line 3567 "sql.c" - yymsp[-2].minor.yy131 = yylhsminor.yy131; +#line 3599 "sql.c" + yymsp[-2].minor.yy403 = yylhsminor.yy403; break; - case 214: /* grouplist ::= item */ -#line 655 "sql.y" + case 217: /* grouplist ::= item */ +#line 663 "sql.y" { - yylhsminor.yy131 = tVariantListAppend(NULL, &yymsp[0].minor.yy516, -1); + yylhsminor.yy403 = tVariantListAppend(NULL, &yymsp[0].minor.yy488, -1); } -#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); -#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); -#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); -#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); -#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 */ +#line 3607 "sql.c" + yymsp[0].minor.yy403 = yylhsminor.yy403; + break; + case 218: /* having_opt ::= */ + case 228: /* where_opt ::= */ yytestcase(yyruleno==228); + case 271: /* expritem ::= */ yytestcase(yyruleno==271); #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" +{yymsp[1].minor.yy260 = 0;} +#line 3615 "sql.c" break; - case 220: /* limit_opt ::= LIMIT signed COMMA signed */ -#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" + case 219: /* having_opt ::= HAVING expr */ + case 229: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==229); +#line 671 "sql.y" +{yymsp[-1].minor.yy260 = yymsp[0].minor.yy260;} +#line 3621 "sql.c" break; - case 223: /* slimit_opt ::= SLIMIT signed SOFFSET signed */ -#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" + case 220: /* limit_opt ::= */ + case 224: /* slimit_opt ::= */ yytestcase(yyruleno==224); +#line 675 "sql.y" +{yymsp[1].minor.yy404.limit = -1; yymsp[1].minor.yy404.offset = 0;} +#line 3627 "sql.c" break; - case 224: /* slimit_opt ::= SLIMIT signed COMMA signed */ -#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" + case 221: /* limit_opt ::= LIMIT signed */ + case 225: /* slimit_opt ::= SLIMIT signed */ yytestcase(yyruleno==225); +#line 676 "sql.y" +{yymsp[-1].minor.yy404.limit = yymsp[0].minor.yy387; yymsp[-1].minor.yy404.offset = 0;} +#line 3633 "sql.c" break; - case 227: /* expr ::= LP expr RP */ -#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 */ -#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 */ -#line 696 "sql.y" -{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ID);} + case 222: /* limit_opt ::= LIMIT signed OFFSET signed */ +#line 678 "sql.y" +{ yymsp[-3].minor.yy404.limit = yymsp[-2].minor.yy387; yymsp[-3].minor.yy404.offset = yymsp[0].minor.yy387;} #line 3638 "sql.c" - yymsp[-2].minor.yy46 = yylhsminor.yy46; - break; - case 230: /* expr ::= ID DOT STAR */ -#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 */ -#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); -#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 */ -#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); + break; + case 223: /* limit_opt ::= LIMIT signed COMMA signed */ +#line 680 "sql.y" +{ yymsp[-3].minor.yy404.limit = yymsp[0].minor.yy387; yymsp[-3].minor.yy404.offset = yymsp[-2].minor.yy387;} +#line 3643 "sql.c" + break; + case 226: /* slimit_opt ::= SLIMIT signed SOFFSET signed */ +#line 686 "sql.y" +{yymsp[-3].minor.yy404.limit = yymsp[-2].minor.yy387; yymsp[-3].minor.yy404.offset = yymsp[0].minor.yy387;} +#line 3648 "sql.c" + break; + case 227: /* slimit_opt ::= SLIMIT signed COMMA signed */ +#line 688 "sql.y" +{yymsp[-3].minor.yy404.limit = yymsp[0].minor.yy387; yymsp[-3].minor.yy404.offset = yymsp[-2].minor.yy387;} +#line 3653 "sql.c" + break; + case 230: /* expr ::= LP expr RP */ +#line 701 "sql.y" +{yylhsminor.yy260 = yymsp[-1].minor.yy260; yylhsminor.yy260->exprToken.z = yymsp[-2].minor.yy0.z; yylhsminor.yy260->exprToken.n = (yymsp[0].minor.yy0.z - yymsp[-2].minor.yy0.z + 1);} +#line 3658 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 231: /* expr ::= ID */ #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);} +{ yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_ID);} +#line 3664 "sql.c" + yymsp[0].minor.yy260 = yylhsminor.yy260; + break; + case 232: /* expr ::= ID DOT ID */ +#line 704 "sql.y" +{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ID);} #line 3670 "sql.c" - yymsp[-1].minor.yy46 = yylhsminor.yy46; + yymsp[-2].minor.yy260 = yylhsminor.yy260; break; - case 237: /* expr ::= STRING */ + case 233: /* expr ::= ID DOT STAR */ #line 705 "sql.y" -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_STRING);} +{ yymsp[-2].minor.yy0.n += (1+yymsp[0].minor.yy0.n); yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[-2].minor.yy0, TK_ALL);} #line 3676 "sql.c" - yymsp[0].minor.yy46 = yylhsminor.yy46; - break; - case 238: /* expr ::= NOW */ -#line 706 "sql.y" -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NOW); } -#line 3682 "sql.c" - yymsp[0].minor.yy46 = yylhsminor.yy46; + yymsp[-2].minor.yy260 = yylhsminor.yy260; break; - case 239: /* expr ::= VARIABLE */ + case 234: /* expr ::= INTEGER */ #line 707 "sql.y" -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_VARIABLE);} -#line 3688 "sql.c" - yymsp[0].minor.yy46 = yylhsminor.yy46; +{ yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_INTEGER);} +#line 3682 "sql.c" + yymsp[0].minor.yy260 = yylhsminor.yy260; break; - case 240: /* expr ::= PLUS VARIABLE */ - case 241: /* expr ::= MINUS VARIABLE */ yytestcase(yyruleno==241); + case 235: /* expr ::= MINUS INTEGER */ + case 236: /* expr ::= PLUS INTEGER */ yytestcase(yyruleno==236); #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; +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_INTEGER; yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_INTEGER);} +#line 3689 "sql.c" + yymsp[-1].minor.yy260 = yylhsminor.yy260; break; - case 242: /* expr ::= BOOL */ + case 237: /* expr ::= FLOAT */ #line 710 "sql.y" -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_BOOL);} -#line 3701 "sql.c" - yymsp[0].minor.yy46 = yylhsminor.yy46; +{ yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_FLOAT);} +#line 3695 "sql.c" + yymsp[0].minor.yy260 = yylhsminor.yy260; break; - case 243: /* expr ::= NULL */ + case 238: /* expr ::= MINUS FLOAT */ + case 239: /* expr ::= PLUS FLOAT */ yytestcase(yyruleno==239); #line 711 "sql.y" -{ yylhsminor.yy46 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NULL);} -#line 3707 "sql.c" - yymsp[0].minor.yy46 = yylhsminor.yy46; +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_FLOAT; yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_FLOAT);} +#line 3702 "sql.c" + yymsp[-1].minor.yy260 = yylhsminor.yy260; + break; + case 240: /* expr ::= STRING */ +#line 713 "sql.y" +{ yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_STRING);} +#line 3708 "sql.c" + yymsp[0].minor.yy260 = yylhsminor.yy260; break; - case 244: /* expr ::= ID LP exprlist RP */ + case 241: /* expr ::= NOW */ #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 */ -#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 */ -#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 */ -#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 */ -#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.yy260 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NOW); } +#line 3714 "sql.c" + yymsp[0].minor.yy260 = yylhsminor.yy260; + break; + case 242: /* expr ::= VARIABLE */ +#line 715 "sql.y" +{ yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_VARIABLE);} +#line 3720 "sql.c" + yymsp[0].minor.yy260 = yylhsminor.yy260; + break; + case 243: /* expr ::= PLUS VARIABLE */ + case 244: /* expr ::= MINUS VARIABLE */ yytestcase(yyruleno==244); +#line 716 "sql.y" +{ yymsp[-1].minor.yy0.n += yymsp[0].minor.yy0.n; yymsp[-1].minor.yy0.type = TK_VARIABLE; yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[-1].minor.yy0, TK_VARIABLE);} +#line 3727 "sql.c" + yymsp[-1].minor.yy260 = yylhsminor.yy260; + break; + case 245: /* expr ::= BOOL */ +#line 718 "sql.y" +{ yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_BOOL);} +#line 3733 "sql.c" + yymsp[0].minor.yy260 = yylhsminor.yy260; + break; + case 246: /* expr ::= NULL */ +#line 719 "sql.y" +{ yylhsminor.yy260 = tSqlExprCreateIdValue(&yymsp[0].minor.yy0, TK_NULL);} +#line 3739 "sql.c" + yymsp[0].minor.yy260 = yylhsminor.yy260; + break; + case 247: /* expr ::= ID LP exprlist RP */ +#line 722 "sql.y" +{ tStrTokenAppend(pInfo->funcs, &yymsp[-3].minor.yy0); yylhsminor.yy260 = tSqlExprCreateFunction(yymsp[-1].minor.yy403, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } +#line 3745 "sql.c" + yymsp[-3].minor.yy260 = yylhsminor.yy260; + break; + case 248: /* expr ::= ID LP STAR RP */ #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 */ -#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 */ -#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 */ +{ tStrTokenAppend(pInfo->funcs, &yymsp[-3].minor.yy0); yylhsminor.yy260 = tSqlExprCreateFunction(NULL, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, yymsp[-3].minor.yy0.type); } +#line 3751 "sql.c" + yymsp[-3].minor.yy260 = yylhsminor.yy260; + break; + case 249: /* expr ::= expr IS NULL */ #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; +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, NULL, TK_ISNULL);} +#line 3757 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; break; - case 253: /* expr ::= expr EQ expr */ + case 250: /* expr ::= expr IS NOT NULL */ #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; +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-3].minor.yy260, NULL, TK_NOTNULL);} +#line 3763 "sql.c" + yymsp[-3].minor.yy260 = yylhsminor.yy260; break; - case 254: /* expr ::= expr BETWEEN expr AND expr */ -#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; + case 251: /* expr ::= expr LT expr */ +#line 732 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_LT);} +#line 3769 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; break; - case 255: /* expr ::= expr AND expr */ + case 252: /* expr ::= expr GT expr */ #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; +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_GT);} +#line 3775 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; break; - case 256: /* expr ::= expr OR expr */ + case 253: /* expr ::= expr LE expr */ #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.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_LE);} +#line 3781 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 254: /* expr ::= expr GE expr */ +#line 735 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_GE);} +#line 3787 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 255: /* expr ::= expr NE expr */ +#line 736 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_NE);} +#line 3793 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 256: /* expr ::= expr EQ expr */ #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; +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_EQ);} +#line 3799 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; break; - case 258: /* expr ::= expr MINUS expr */ -#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 */ + case 257: /* expr ::= expr BETWEEN expr AND expr */ #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 */ -#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; +{ tSqlExpr* X2 = tSqlExprClone(yymsp[-4].minor.yy260); yylhsminor.yy260 = tSqlExprCreate(tSqlExprCreate(yymsp[-4].minor.yy260, yymsp[-2].minor.yy260, TK_GE), tSqlExprCreate(X2, yymsp[0].minor.yy260, TK_LE), TK_AND);} +#line 3805 "sql.c" + yymsp[-4].minor.yy260 = yylhsminor.yy260; break; - case 261: /* expr ::= expr REM expr */ + case 258: /* expr ::= expr AND expr */ #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; +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_AND);} +#line 3811 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 259: /* expr ::= expr OR expr */ +#line 742 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_OR); } +#line 3817 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 260: /* expr ::= expr PLUS expr */ +#line 745 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_PLUS); } +#line 3823 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 261: /* expr ::= expr MINUS expr */ +#line 746 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_MINUS); } +#line 3829 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 262: /* expr ::= expr STAR expr */ +#line 747 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_STAR); } +#line 3835 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 263: /* expr ::= expr SLASH expr */ +#line 748 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_DIVIDE);} +#line 3841 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 264: /* expr ::= expr REM expr */ +#line 749 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_REM); } +#line 3847 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 265: /* expr ::= expr LIKE expr */ +#line 752 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_LIKE); } +#line 3853 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; + break; + case 266: /* expr ::= expr MATCH expr */ +#line 755 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-2].minor.yy260, yymsp[0].minor.yy260, TK_MATCH); } +#line 3859 "sql.c" + yymsp[-2].minor.yy260 = yylhsminor.yy260; break; - case 262: /* expr ::= expr LIKE expr */ -#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; + case 267: /* expr ::= expr IN LP exprlist RP */ +#line 758 "sql.y" +{yylhsminor.yy260 = tSqlExprCreate(yymsp[-4].minor.yy260, (tSqlExpr*)yymsp[-1].minor.yy403, TK_IN); } +#line 3865 "sql.c" + yymsp[-4].minor.yy260 = yylhsminor.yy260; break; - case 263: /* expr ::= expr IN LP exprlist RP */ -#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; + case 268: /* exprlist ::= exprlist COMMA expritem */ +#line 766 "sql.y" +{yylhsminor.yy403 = tSqlExprListAppend(yymsp[-2].minor.yy403,yymsp[0].minor.yy260,0, 0);} +#line 3871 "sql.c" + yymsp[-2].minor.yy403 = yylhsminor.yy403; break; - case 264: /* exprlist ::= exprlist COMMA expritem */ -#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 */ -#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 */ -#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" + case 269: /* exprlist ::= expritem */ +#line 767 "sql.y" +{yylhsminor.yy403 = tSqlExprListAppend(0,yymsp[0].minor.yy260,0, 0);} +#line 3877 "sql.c" + yymsp[0].minor.yy403 = yylhsminor.yy403; + break; + case 270: /* expritem ::= expr */ +#line 768 "sql.y" +{yylhsminor.yy260 = yymsp[0].minor.yy260;} +#line 3883 "sql.c" + yymsp[0].minor.yy260 = yylhsminor.yy260; + break; + case 272: /* cmd ::= RESET QUERY CACHE */ +#line 772 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_RESET_CACHE, 0);} -#line 3851 "sql.c" +#line 3889 "sql.c" break; - case 269: /* cmd ::= SYNCDB ids REPLICA */ -#line 764 "sql.y" + case 273: /* cmd ::= SYNCDB ids REPLICA */ +#line 775 "sql.y" { setDCLSqlElems(pInfo, TSDB_SQL_SYNC_DB_REPLICA, 1, &yymsp[-1].minor.yy0);} -#line 3856 "sql.c" +#line 3894 "sql.c" break; - case 270: /* cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ -#line 767 "sql.y" + case 274: /* cmd ::= ALTER TABLE ids cpxName ADD COLUMN columnlist */ +#line 778 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy403, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } -#line 3865 "sql.c" +#line 3903 "sql.c" break; - case 271: /* cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ -#line 773 "sql.y" + case 275: /* cmd ::= ALTER TABLE ids cpxName DROP COLUMN ids */ +#line 784 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; @@ -3874,28 +3912,28 @@ static YYACTIONTYPE 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" +#line 3916 "sql.c" break; - case 272: /* cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ -#line 783 "sql.y" + case 276: /* cmd ::= ALTER TABLE ids cpxName MODIFY COLUMN columnlist */ +#line 794 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_CHANGE_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy403, NULL, TSDB_ALTER_TABLE_CHANGE_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } -#line 3887 "sql.c" +#line 3925 "sql.c" break; - case 273: /* cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ -#line 790 "sql.y" + case 277: /* cmd ::= ALTER TABLE ids cpxName ADD TAG columnlist */ +#line 801 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy403, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } -#line 3896 "sql.c" +#line 3934 "sql.c" break; - case 274: /* cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ -#line 795 "sql.y" + case 278: /* cmd ::= ALTER TABLE ids cpxName DROP TAG ids */ +#line 806 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; @@ -3905,10 +3943,10 @@ static YYACTIONTYPE 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" +#line 3947 "sql.c" break; - case 275: /* cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ -#line 805 "sql.y" + case 279: /* cmd ::= ALTER TABLE ids cpxName CHANGE TAG ids ids */ +#line 816 "sql.y" { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; @@ -3921,42 +3959,42 @@ static YYACTIONTYPE 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" +#line 3963 "sql.c" break; - case 276: /* cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ -#line 818 "sql.y" + case 280: /* cmd ::= ALTER TABLE ids cpxName SET TAG ids EQ tagitem */ +#line 829 "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.yy516, -1); + A = tVariantListAppend(A, &yymsp[0].minor.yy488, -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" +#line 3977 "sql.c" break; - case 277: /* cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ -#line 829 "sql.y" + case 281: /* cmd ::= ALTER TABLE ids cpxName MODIFY TAG columnlist */ +#line 840 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_MODIFY_TAG_COLUMN, -1); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy403, NULL, TSDB_ALTER_TABLE_MODIFY_TAG_COLUMN, -1); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } -#line 3948 "sql.c" +#line 3986 "sql.c" break; - case 278: /* cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ -#line 836 "sql.y" + case 282: /* cmd ::= ALTER STABLE ids cpxName ADD COLUMN columnlist */ +#line 847 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy403, NULL, TSDB_ALTER_TABLE_ADD_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } -#line 3957 "sql.c" +#line 3995 "sql.c" break; - case 279: /* cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ -#line 842 "sql.y" + case 283: /* cmd ::= ALTER STABLE ids cpxName DROP COLUMN ids */ +#line 853 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; @@ -3966,28 +4004,28 @@ static YYACTIONTYPE 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" +#line 4008 "sql.c" break; - case 280: /* cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ -#line 852 "sql.y" + case 284: /* cmd ::= ALTER STABLE ids cpxName MODIFY COLUMN columnlist */ +#line 863 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_CHANGE_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy403, NULL, TSDB_ALTER_TABLE_CHANGE_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } -#line 3979 "sql.c" +#line 4017 "sql.c" break; - case 281: /* cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ -#line 859 "sql.y" + case 285: /* cmd ::= ALTER STABLE ids cpxName ADD TAG columnlist */ +#line 870 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy403, NULL, TSDB_ALTER_TABLE_ADD_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } -#line 3988 "sql.c" +#line 4026 "sql.c" break; - case 282: /* cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ -#line 864 "sql.y" + case 286: /* cmd ::= ALTER STABLE ids cpxName DROP TAG ids */ +#line 875 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; @@ -3997,10 +4035,10 @@ static YYACTIONTYPE 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" +#line 4039 "sql.c" break; - case 283: /* cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ -#line 874 "sql.y" + case 287: /* cmd ::= ALTER STABLE ids cpxName CHANGE TAG ids ids */ +#line 885 "sql.y" { yymsp[-5].minor.yy0.n += yymsp[-4].minor.yy0.n; @@ -4013,45 +4051,45 @@ static YYACTIONTYPE 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" +#line 4055 "sql.c" break; - case 284: /* cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ -#line 887 "sql.y" + case 288: /* cmd ::= ALTER STABLE ids cpxName SET TAG ids EQ tagitem */ +#line 898 "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.yy516, -1); + A = tVariantListAppend(A, &yymsp[0].minor.yy488, -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" +#line 4069 "sql.c" break; - case 285: /* cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ -#line 898 "sql.y" + case 289: /* cmd ::= ALTER STABLE ids cpxName MODIFY TAG columnlist */ +#line 909 "sql.y" { yymsp[-4].minor.yy0.n += yymsp[-3].minor.yy0.n; - SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy131, NULL, TSDB_ALTER_TABLE_MODIFY_TAG_COLUMN, TSDB_SUPER_TABLE); + SAlterTableInfo* pAlterTable = tSetAlterTableInfo(&yymsp[-4].minor.yy0, yymsp[0].minor.yy403, NULL, TSDB_ALTER_TABLE_MODIFY_TAG_COLUMN, TSDB_SUPER_TABLE); setSqlInfo(pInfo, pAlterTable, NULL, TSDB_SQL_ALTER_TABLE); } -#line 4040 "sql.c" +#line 4078 "sql.c" break; - case 286: /* cmd ::= KILL CONNECTION INTEGER */ -#line 905 "sql.y" + case 290: /* cmd ::= KILL CONNECTION INTEGER */ +#line 916 "sql.y" {setKillSql(pInfo, TSDB_SQL_KILL_CONNECTION, &yymsp[0].minor.yy0);} -#line 4045 "sql.c" +#line 4083 "sql.c" break; - case 287: /* cmd ::= KILL STREAM INTEGER COLON INTEGER */ -#line 906 "sql.y" + case 291: /* cmd ::= KILL STREAM INTEGER COLON INTEGER */ +#line 917 "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" +#line 4088 "sql.c" break; - case 288: /* cmd ::= KILL QUERY INTEGER COLON INTEGER */ -#line 907 "sql.y" + case 292: /* cmd ::= KILL QUERY INTEGER COLON INTEGER */ +#line 918 "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" +#line 4093 "sql.c" break; default: break; @@ -4136,7 +4174,7 @@ static void yy_syntax_error( } assert(len <= outputBufLen); -#line 4140 "sql.c" +#line 4178 "sql.c" /************ End %syntax_error code ******************************************/ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseCTX_STORE @@ -4163,7 +4201,7 @@ static void yy_accept( ** parser accepts */ /*********** Begin %parse_accept code *****************************************/ #line 61 "sql.y" -#line 4167 "sql.c" +#line 4205 "sql.c" /*********** End %parse_accept code *******************************************/ ParseARG_STORE /* Suppress warning about unused %extra_argument variable */ ParseCTX_STORE diff --git a/src/tsdb/inc/tsdbFS.h b/src/tsdb/inc/tsdbFS.h index d63aeb14ac6ca6cd6f59654cf74f11d8e33d6ce4..e89e10f7667e8aa5388ebfa4d2c5b54f1bf3e57f 100644 --- a/src/tsdb/inc/tsdbFS.h +++ b/src/tsdb/inc/tsdbFS.h @@ -18,6 +18,9 @@ #define TSDB_FS_VERSION 0 +// ================== TSDB global config +extern bool tsdbForceKeepFile; + // ================== CURRENT file header info typedef struct { uint32_t version; // Current file system version (relating to code) @@ -42,8 +45,9 @@ typedef struct { typedef struct { pthread_rwlock_t lock; - SFSStatus* cstatus; // current status - SHashObj* metaCache; // meta cache + SFSStatus* cstatus; // current status + SHashObj* metaCache; // meta cache + SHashObj* metaCacheComp; // meta cache for compact bool intxn; SFSStatus* nstatus; // new status } STsdbFS; @@ -109,4 +113,4 @@ static FORCE_INLINE int tsdbUnLockFS(STsdbFS* pFs) { return 0; } -#endif /* _TD_TSDB_FS_H_ */ \ No newline at end of file +#endif /* _TD_TSDB_FS_H_ */ diff --git a/src/tsdb/src/tsdbCommit.c b/src/tsdb/src/tsdbCommit.c index 8f5f885d692f723bc1690a708571093bbe0a2717..03110487807076bf8ac2ac7026ffdb828ea4c7c6 100644 --- a/src/tsdb/src/tsdbCommit.c +++ b/src/tsdb/src/tsdbCommit.c @@ -14,6 +14,8 @@ */ #include "tsdbint.h" +extern int32_t tsTsdbMetaCompactRatio; + #define TSDB_MAX_SUBBLOCKS 8 static FORCE_INLINE int TSDB_KEY_FID(TSKEY key, int32_t days, int8_t precision) { if (key < 0) { @@ -55,8 +57,9 @@ typedef struct { #define TSDB_COMMIT_TXN_VERSION(ch) FS_TXN_VERSION(REPO_FS(TSDB_COMMIT_REPO(ch))) static int tsdbCommitMeta(STsdbRepo *pRepo); -static int tsdbUpdateMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid, void *cont, int contLen); +static int tsdbUpdateMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid, void *cont, int contLen, bool compact); static int tsdbDropMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid); +static int tsdbCompactMetaFile(STsdbRepo *pRepo, STsdbFS *pfs, SMFile *pMFile); static int tsdbCommitTSData(STsdbRepo *pRepo); static void tsdbStartCommit(STsdbRepo *pRepo); static void tsdbEndCommit(STsdbRepo *pRepo, int eno); @@ -261,6 +264,35 @@ int tsdbWriteBlockIdx(SDFile *pHeadf, SArray *pIdxA, void **ppBuf) { // =================== Commit Meta Data +static int tsdbInitCommitMetaFile(STsdbRepo *pRepo, SMFile* pMf, bool open) { + STsdbFS * pfs = REPO_FS(pRepo); + SMFile * pOMFile = pfs->cstatus->pmf; + SDiskID did; + + // Create/Open a meta file or open the existing file + if (pOMFile == NULL) { + // Create a new meta file + did.level = TFS_PRIMARY_LEVEL; + did.id = TFS_PRIMARY_ID; + tsdbInitMFile(pMf, did, REPO_ID(pRepo), FS_TXN_VERSION(REPO_FS(pRepo))); + + if (open && tsdbCreateMFile(pMf, true) < 0) { + tsdbError("vgId:%d failed to create META file since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } + + tsdbInfo("vgId:%d meta file %s is created to commit", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pMf)); + } else { + tsdbInitMFileEx(pMf, pOMFile); + if (open && tsdbOpenMFile(pMf, O_WRONLY) < 0) { + tsdbError("vgId:%d failed to open META file since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } + } + + return 0; +} + static int tsdbCommitMeta(STsdbRepo *pRepo) { STsdbFS * pfs = REPO_FS(pRepo); SMemTable *pMem = pRepo->imem; @@ -269,34 +301,25 @@ static int tsdbCommitMeta(STsdbRepo *pRepo) { SActObj * pAct = NULL; SActCont * pCont = NULL; SListNode *pNode = NULL; - SDiskID did; ASSERT(pOMFile != NULL || listNEles(pMem->actList) > 0); if (listNEles(pMem->actList) <= 0) { // no meta data to commit, just keep the old meta file tsdbUpdateMFile(pfs, pOMFile); - return 0; - } else { - // Create/Open a meta file or open the existing file - if (pOMFile == NULL) { - // Create a new meta file - did.level = TFS_PRIMARY_LEVEL; - did.id = TFS_PRIMARY_ID; - tsdbInitMFile(&mf, did, REPO_ID(pRepo), FS_TXN_VERSION(REPO_FS(pRepo))); - - if (tsdbCreateMFile(&mf, true) < 0) { - tsdbError("vgId:%d failed to create META file since %s", REPO_ID(pRepo), tstrerror(terrno)); + if (tsTsdbMetaCompactRatio > 0) { + if (tsdbInitCommitMetaFile(pRepo, &mf, false) < 0) { return -1; } + int ret = tsdbCompactMetaFile(pRepo, pfs, &mf); + if (ret < 0) tsdbError("compact meta file error"); - tsdbInfo("vgId:%d meta file %s is created to commit", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(&mf)); - } else { - tsdbInitMFileEx(&mf, pOMFile); - if (tsdbOpenMFile(&mf, O_WRONLY) < 0) { - tsdbError("vgId:%d failed to open META file since %s", REPO_ID(pRepo), tstrerror(terrno)); - return -1; - } + return ret; + } + return 0; + } else { + if (tsdbInitCommitMetaFile(pRepo, &mf, true) < 0) { + return -1; } } @@ -305,7 +328,7 @@ static int tsdbCommitMeta(STsdbRepo *pRepo) { pAct = (SActObj *)pNode->data; if (pAct->act == TSDB_UPDATE_META) { pCont = (SActCont *)POINTER_SHIFT(pAct, sizeof(SActObj)); - if (tsdbUpdateMetaRecord(pfs, &mf, pAct->uid, (void *)(pCont->cont), pCont->len) < 0) { + if (tsdbUpdateMetaRecord(pfs, &mf, pAct->uid, (void *)(pCont->cont), pCont->len, false) < 0) { tsdbError("vgId:%d failed to update META record, uid %" PRIu64 " since %s", REPO_ID(pRepo), pAct->uid, tstrerror(terrno)); tsdbCloseMFile(&mf); @@ -338,6 +361,10 @@ static int tsdbCommitMeta(STsdbRepo *pRepo) { tsdbCloseMFile(&mf); tsdbUpdateMFile(pfs, &mf); + if (tsTsdbMetaCompactRatio > 0 && tsdbCompactMetaFile(pRepo, pfs, &mf) < 0) { + tsdbError("compact meta file error"); + } + return 0; } @@ -375,7 +402,7 @@ void tsdbGetRtnSnap(STsdbRepo *pRepo, SRtn *pRtn) { pRtn->minFid, pRtn->midFid, pRtn->maxFid); } -static int tsdbUpdateMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid, void *cont, int contLen) { +static int tsdbUpdateMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid, void *cont, int contLen, bool compact) { char buf[64] = "\0"; void * pBuf = buf; SKVRecord rInfo; @@ -401,13 +428,18 @@ static int tsdbUpdateMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid, void } tsdbUpdateMFileMagic(pMFile, POINTER_SHIFT(cont, contLen - sizeof(TSCKSUM))); - SKVRecord *pRecord = taosHashGet(pfs->metaCache, (void *)&uid, sizeof(uid)); + + SHashObj* cache = compact ? pfs->metaCacheComp : pfs->metaCache; + + pMFile->info.nRecords++; + + SKVRecord *pRecord = taosHashGet(cache, (void *)&uid, sizeof(uid)); if (pRecord != NULL) { pMFile->info.tombSize += (pRecord->size + sizeof(SKVRecord)); } else { pMFile->info.nRecords++; } - taosHashPut(pfs->metaCache, (void *)(&uid), sizeof(uid), (void *)(&rInfo), sizeof(rInfo)); + taosHashPut(cache, (void *)(&uid), sizeof(uid), (void *)(&rInfo), sizeof(rInfo)); return 0; } @@ -442,6 +474,129 @@ static int tsdbDropMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid) { return 0; } +static int tsdbCompactMetaFile(STsdbRepo *pRepo, STsdbFS *pfs, SMFile *pMFile) { + float delPercent = (float)(pMFile->info.nDels) / (float)(pMFile->info.nRecords); + float tombPercent = (float)(pMFile->info.tombSize) / (float)(pMFile->info.size); + float compactRatio = (float)(tsTsdbMetaCompactRatio)/100; + + if (delPercent < compactRatio && tombPercent < compactRatio) { + return 0; + } + + if (tsdbOpenMFile(pMFile, O_RDONLY) < 0) { + tsdbError("open meta file %s compact fail", pMFile->f.rname); + return -1; + } + + tsdbInfo("begin compact tsdb meta file, ratio:%d, nDels:%" PRId64 ",nRecords:%" PRId64 ",tombSize:%" PRId64 ",size:%" PRId64, + tsTsdbMetaCompactRatio, pMFile->info.nDels,pMFile->info.nRecords,pMFile->info.tombSize,pMFile->info.size); + + SMFile mf; + SDiskID did; + + // first create tmp meta file + did.level = TFS_PRIMARY_LEVEL; + did.id = TFS_PRIMARY_ID; + tsdbInitMFile(&mf, did, REPO_ID(pRepo), FS_TXN_VERSION(REPO_FS(pRepo)) + 1); + + if (tsdbCreateMFile(&mf, true) < 0) { + tsdbError("vgId:%d failed to create META file since %s", REPO_ID(pRepo), tstrerror(terrno)); + return -1; + } + + tsdbInfo("vgId:%d meta file %s is created to compact meta data", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(&mf)); + + // second iterator metaCache + int code = -1; + int64_t maxBufSize = 1024; + SKVRecord *pRecord; + void *pBuf = NULL; + + pBuf = malloc((size_t)maxBufSize); + if (pBuf == NULL) { + goto _err; + } + + // init Comp + assert(pfs->metaCacheComp == NULL); + pfs->metaCacheComp = taosHashInit(4096, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK); + if (pfs->metaCacheComp == NULL) { + goto _err; + } + + pRecord = taosHashIterate(pfs->metaCache, NULL); + while (pRecord) { + if (tsdbSeekMFile(pMFile, pRecord->offset + sizeof(SKVRecord), SEEK_SET) < 0) { + tsdbError("vgId:%d failed to seek file %s since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pMFile), + tstrerror(terrno)); + goto _err; + } + if (pRecord->size > maxBufSize) { + maxBufSize = pRecord->size; + void* tmp = realloc(pBuf, (size_t)maxBufSize); + if (tmp == NULL) { + goto _err; + } + pBuf = tmp; + } + int nread = (int)tsdbReadMFile(pMFile, pBuf, pRecord->size); + if (nread < 0) { + tsdbError("vgId:%d failed to read file %s since %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pMFile), + tstrerror(terrno)); + goto _err; + } + + if (nread < pRecord->size) { + tsdbError("vgId:%d failed to read file %s since file corrupted, expected read:%" PRId64 " actual read:%d", + REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pMFile), pRecord->size, nread); + goto _err; + } + + if (tsdbUpdateMetaRecord(pfs, &mf, pRecord->uid, pBuf, (int)pRecord->size, true) < 0) { + tsdbError("vgId:%d failed to update META record, uid %" PRIu64 " since %s", REPO_ID(pRepo), pRecord->uid, + tstrerror(terrno)); + goto _err; + } + + pRecord = taosHashIterate(pfs->metaCache, pRecord); + } + code = 0; + +_err: + if (code == 0) TSDB_FILE_FSYNC(&mf); + tsdbCloseMFile(&mf); + tsdbCloseMFile(pMFile); + + if (code == 0) { + // rename meta.tmp -> meta + tsdbInfo("vgId:%d meta file rename %s -> %s", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(&mf), TSDB_FILE_FULL_NAME(pMFile)); + taosRename(mf.f.aname,pMFile->f.aname); + tstrncpy(mf.f.aname, pMFile->f.aname, TSDB_FILENAME_LEN); + tstrncpy(mf.f.rname, pMFile->f.rname, TSDB_FILENAME_LEN); + // update current meta file info + pfs->nstatus->pmf = NULL; + tsdbUpdateMFile(pfs, &mf); + + taosHashCleanup(pfs->metaCache); + pfs->metaCache = pfs->metaCacheComp; + pfs->metaCacheComp = NULL; + } else { + // remove meta.tmp file + remove(mf.f.aname); + taosHashCleanup(pfs->metaCacheComp); + pfs->metaCacheComp = NULL; + } + + tfree(pBuf); + + ASSERT(mf.info.nDels == 0); + ASSERT(mf.info.tombSize == 0); + + tsdbInfo("end compact tsdb meta file,code:%d,nRecords:%" PRId64 ",size:%" PRId64, + code,mf.info.nRecords,mf.info.size); + return code; +} + // =================== Commit Time-Series Data static int tsdbCommitTSData(STsdbRepo *pRepo) { SMemTable *pMem = pRepo->imem; @@ -1263,13 +1418,11 @@ static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIt while (true) { key1 = (*iter >= pDataCols->numOfRows) ? INT64_MAX : dataColsKeyAt(pDataCols, *iter); - bool isRowDel = false; SMemRow row = tsdbNextIterRow(pCommitIter->pIter); if (row == NULL || memRowKey(row) > maxKey) { key2 = INT64_MAX; } else { key2 = memRowKey(row); - isRowDel = memRowDeleted(row); } if (key1 == INT64_MAX && key2 == INT64_MAX) break; @@ -1284,36 +1437,33 @@ static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIt pTarget->numOfRows++; (*iter)++; } else if (key1 > key2) { - if (!isRowDel) { - if (pSchema == NULL || schemaVersion(pSchema) != memRowVersion(row)) { - pSchema = tsdbGetTableSchemaImpl(pCommitIter->pTable, false, false, memRowVersion(row)); - ASSERT(pSchema != NULL); - } - - tdAppendMemRowToDataCol(row, pSchema, pTarget, true); + if (pSchema == NULL || schemaVersion(pSchema) != memRowVersion(row)) { + pSchema = tsdbGetTableSchemaImpl(pCommitIter->pTable, false, false, memRowVersion(row)); + ASSERT(pSchema != NULL); } + tdAppendMemRowToDataCol(row, pSchema, pTarget, true); + tSkipListIterNext(pCommitIter->pIter); } else { - if (update) { - if (!isRowDel) { - if (pSchema == NULL || schemaVersion(pSchema) != memRowVersion(row)) { - pSchema = tsdbGetTableSchemaImpl(pCommitIter->pTable, false, false, memRowVersion(row)); - ASSERT(pSchema != NULL); - } - - tdAppendMemRowToDataCol(row, pSchema, pTarget, update == TD_ROW_OVERWRITE_UPDATE); - } - } else { - ASSERT(!isRowDel); - + if (update != TD_ROW_OVERWRITE_UPDATE) { + //copy disk data 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); } - pTarget->numOfRows++; + if(update == TD_ROW_DISCARD_UPDATE) pTarget->numOfRows++; + } + if (update != TD_ROW_DISCARD_UPDATE) { + //copy mem data + if (pSchema == NULL || schemaVersion(pSchema) != memRowVersion(row)) { + pSchema = tsdbGetTableSchemaImpl(pCommitIter->pTable, false, false, memRowVersion(row)); + ASSERT(pSchema != NULL); + } + + tdAppendMemRowToDataCol(row, pSchema, pTarget, update == TD_ROW_OVERWRITE_UPDATE); } (*iter)++; tSkipListIterNext(pCommitIter->pIter); diff --git a/src/tsdb/src/tsdbFS.c b/src/tsdb/src/tsdbFS.c index 63f89c1957e82d3a4fda0ae958fe968d920e9b7a..a40e67ca590082dcb7925ab167d7d2c5165f8017 100644 --- a/src/tsdb/src/tsdbFS.c +++ b/src/tsdb/src/tsdbFS.c @@ -37,6 +37,7 @@ static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo, int32_t *nExpired); static int tsdbProcessExpiredFS(STsdbRepo *pRepo); static int tsdbCreateMeta(STsdbRepo *pRepo); +// For backward compatibility // ================== CURRENT file header info static int tsdbEncodeFSHeader(void **buf, SFSHeader *pHeader) { int tlen = 0; @@ -215,6 +216,7 @@ STsdbFS *tsdbNewFS(STsdbCfg *pCfg) { } pfs->intxn = false; + pfs->metaCacheComp = NULL; pfs->nstatus = tsdbNewFSStatus(maxFSet); if (pfs->nstatus == NULL) { diff --git a/src/tsdb/src/tsdbFile.c b/src/tsdb/src/tsdbFile.c index 50fa393e9fc9060941e181f8043d84070d036f98..0f13b6108f6558ab7948df01e38b0c3fd0d2cd9a 100644 --- a/src/tsdb/src/tsdbFile.c +++ b/src/tsdb/src/tsdbFile.c @@ -16,11 +16,11 @@ #include "tsdbint.h" static const char *TSDB_FNAME_SUFFIX[] = { - "head", // TSDB_FILE_HEAD - "data", // TSDB_FILE_DATA - "last", // TSDB_FILE_LAST - "", // TSDB_FILE_MAX - "meta" // TSDB_FILE_META + "head", // TSDB_FILE_HEAD + "data", // TSDB_FILE_DATA + "last", // TSDB_FILE_LAST + "", // TSDB_FILE_MAX + "meta", // TSDB_FILE_META }; static void tsdbGetFilename(int vid, int fid, uint32_t ver, TSDB_FILE_T ftype, char *fname); diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index 96e86a6d99ce05624d72a557f112fa1aa0919e1f..a311868de6f7254d776f08a4f4a247293609aef5 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -43,6 +43,7 @@ static int tsdbRemoveTableFromStore(STsdbRepo *pRepo, STable *pTable); static int tsdbRmTableFromMeta(STsdbRepo *pRepo, STable *pTable); static int tsdbAdjustMetaTables(STsdbRepo *pRepo, int tid); static int tsdbCheckTableTagVal(SKVRow *pKVRow, STSchema *pSchema); +static int tsdbInsertNewTableAction(STsdbRepo *pRepo, STable* pTable); static int tsdbAddSchema(STable *pTable, STSchema *pSchema); static void tsdbFreeTableSchema(STable *pTable); @@ -128,21 +129,16 @@ int tsdbCreateTable(STsdbRepo *repo, STableCfg *pCfg) { tsdbUnlockRepoMeta(pRepo); // Write to memtable action - // TODO: refactor duplicate codes - int tlen = 0; - void *pBuf = NULL; if (newSuper || superChanged) { - tlen = tsdbGetTableEncodeSize(TSDB_UPDATE_META, super); - pBuf = tsdbAllocBytes(pRepo, tlen); - if (pBuf == NULL) goto _err; - void *tBuf = tsdbInsertTableAct(pRepo, TSDB_UPDATE_META, pBuf, super); - ASSERT(POINTER_DISTANCE(tBuf, pBuf) == tlen); + // add insert new super table action + if (tsdbInsertNewTableAction(pRepo, super) != 0) { + goto _err; + } + } + // add insert new table action + if (tsdbInsertNewTableAction(pRepo, table) != 0) { + goto _err; } - tlen = tsdbGetTableEncodeSize(TSDB_UPDATE_META, table); - pBuf = tsdbAllocBytes(pRepo, tlen); - if (pBuf == NULL) goto _err; - void *tBuf = tsdbInsertTableAct(pRepo, TSDB_UPDATE_META, pBuf, table); - ASSERT(POINTER_DISTANCE(tBuf, pBuf) == tlen); if (tsdbCheckCommit(pRepo) < 0) return -1; @@ -383,7 +379,7 @@ int tsdbUpdateTableTagValue(STsdbRepo *repo, SUpdateTableTagValMsg *pMsg) { tdDestroyTSchemaBuilder(&schemaBuilder); } - // Chage in memory + // Change in memory if (pNewSchema != NULL) { // change super table tag schema TSDB_WLOCK_TABLE(pTable->pSuper); STSchema *pOldSchema = pTable->pSuper->tagSchema; @@ -426,6 +422,21 @@ int tsdbUpdateTableTagValue(STsdbRepo *repo, SUpdateTableTagValMsg *pMsg) { } // ------------------ INTERNAL FUNCTIONS ------------------ +static int tsdbInsertNewTableAction(STsdbRepo *pRepo, STable* pTable) { + int tlen = 0; + void *pBuf = NULL; + + tlen = tsdbGetTableEncodeSize(TSDB_UPDATE_META, pTable); + pBuf = tsdbAllocBytes(pRepo, tlen); + if (pBuf == NULL) { + return -1; + } + void *tBuf = tsdbInsertTableAct(pRepo, TSDB_UPDATE_META, pBuf, pTable); + ASSERT(POINTER_DISTANCE(tBuf, pBuf) == tlen); + + return 0; +} + STsdbMeta *tsdbNewMeta(STsdbCfg *pCfg) { STsdbMeta *pMeta = (STsdbMeta *)calloc(1, sizeof(*pMeta)); if (pMeta == NULL) { @@ -617,6 +628,7 @@ int16_t tsdbGetLastColumnsIndexByColId(STable* pTable, int16_t colId) { if (pTable->lastCols == NULL) { return -1; } + // TODO: use binary search instead for (int16_t i = 0; i < pTable->maxColNum; ++i) { if (pTable->lastCols[i].colId == colId) { return i; @@ -734,10 +746,10 @@ void tsdbUpdateTableSchema(STsdbRepo *pRepo, STable *pTable, STSchema *pSchema, TSDB_WUNLOCK_TABLE(pCTable); if (insertAct) { - int tlen = tsdbGetTableEncodeSize(TSDB_UPDATE_META, pCTable); - void *buf = tsdbAllocBytes(pRepo, tlen); - ASSERT(buf != NULL); - tsdbInsertTableAct(pRepo, TSDB_UPDATE_META, buf, pCTable); + if (tsdbInsertNewTableAction(pRepo, pCTable) != 0) { + tsdbError("vgId:%d table %s tid %d uid %" PRIu64 " tsdbInsertNewTableAction fail", REPO_ID(pRepo), TABLE_CHAR_NAME(pTable), + TABLE_TID(pTable), TABLE_UID(pTable)); + } } } @@ -1250,8 +1262,14 @@ static int tsdbEncodeTable(void **buf, STable *pTable) { tlen += taosEncodeFixedU64(buf, TABLE_SUID(pTable)); tlen += tdEncodeKVRow(buf, pTable->tagVal); } else { - tlen += taosEncodeFixedU8(buf, (uint8_t)taosArrayGetSize(pTable->schema)); - for (int i = 0; i < taosArrayGetSize(pTable->schema); i++) { + uint32_t arraySize = (uint32_t)taosArrayGetSize(pTable->schema); + if(arraySize > UINT8_MAX) { + tlen += taosEncodeFixedU8(buf, 0); + tlen += taosEncodeFixedU32(buf, arraySize); + } else { + tlen += taosEncodeFixedU8(buf, (uint8_t)arraySize); + } + for (uint32_t i = 0; i < arraySize; i++) { STSchema *pSchema = taosArrayGetP(pTable->schema, i); tlen += tdEncodeSchema(buf, pSchema); } @@ -1284,8 +1302,11 @@ static void *tsdbDecodeTable(void *buf, STable **pRTable) { buf = taosDecodeFixedU64(buf, &TABLE_SUID(pTable)); buf = tdDecodeKVRow(buf, &(pTable->tagVal)); } else { - uint8_t nSchemas; - buf = taosDecodeFixedU8(buf, &nSchemas); + uint32_t nSchemas = 0; + buf = taosDecodeFixedU8(buf, (uint8_t *)&nSchemas); + if(nSchemas == 0) { + buf = taosDecodeFixedU32(buf, &nSchemas); + } for (int i = 0; i < nSchemas; i++) { STSchema *pSchema; buf = tdDecodeSchema(buf, &pSchema); @@ -1485,4 +1506,4 @@ static void tsdbFreeTableSchema(STable *pTable) { taosArrayDestroy(pTable->schema); } -} \ No newline at end of file +} diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index 9cc9b7224c19978b9dd5df0e4dff7254133b95df..c1b935e0ee3cdbd3177710fbddf8994283319b36 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -1572,7 +1572,7 @@ static void mergeTwoRowFromMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfColsOfRow1 = 0; if (pSchema1 == NULL) { - pSchema1 = tsdbGetTableSchemaByVersion(pTable, dataRowVersion(row1)); + pSchema1 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row1)); } if(isRow1DataRow) { numOfColsOfRow1 = schemaNCols(pSchema1); @@ -1584,7 +1584,7 @@ static void mergeTwoRowFromMem(STsdbQueryHandle* pQueryHandle, int32_t capacity, if(row2) { isRow2DataRow = isDataRow(row2); if (pSchema2 == NULL) { - pSchema2 = tsdbGetTableSchemaByVersion(pTable, dataRowVersion(row2)); + pSchema2 = tsdbGetTableSchemaByVersion(pTable, memRowVersion(row2)); } if(isRow2DataRow) { numOfColsOfRow2 = schemaNCols(pSchema2); @@ -2460,7 +2460,7 @@ int32_t tsdbGetFileBlocksDistInfo(TsdbQueryHandleT* queryHandle, STableBlockDist // current file are not overlapped with query time window, ignore remain files if ((ASCENDING_TRAVERSE(pQueryHandle->order) && win.skey > pQueryHandle->window.ekey) || - (!ASCENDING_TRAVERSE(pQueryHandle->order) && win.ekey < pQueryHandle->window.ekey)) { + (!ASCENDING_TRAVERSE(pQueryHandle->order) && win.ekey < pQueryHandle->window.ekey)) { tsdbUnLockFS(REPO_FS(pQueryHandle->pTsdb)); tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, 0x%"PRIx64, pQueryHandle, pQueryHandle->window.skey, pQueryHandle->window.ekey, pQueryHandle->qId); @@ -3474,18 +3474,19 @@ void filterPrepare(void* expr, void* param) { if (pInfo->optr == TSDB_RELATION_IN) { int dummy = -1; - SHashObj *pObj = NULL; + SHashObj *pObj = NULL; if (pInfo->sch.colId == TSDB_TBNAME_COLUMN_INDEX) { pObj = taosHashInit(256, taosGetDefaultHashFunction(pInfo->sch.type), true, false); SArray *arr = (SArray *)(pCond->arr); for (size_t i = 0; i < taosArrayGetSize(arr); i++) { char* p = taosArrayGetP(arr, i); - taosHashPut(pObj, varDataVal(p),varDataLen(p), &dummy, sizeof(dummy)); + strntolower_s(varDataVal(p), varDataVal(p), varDataLen(p)); + taosHashPut(pObj, varDataVal(p), varDataLen(p), &dummy, sizeof(dummy)); } } else { buildFilterSetFromBinary((void **)&pObj, pCond->pz, pCond->nLen); } - pInfo->q = (char *)pObj; + pInfo->q = (char *)pObj; } else if (pCond != NULL) { uint32_t size = pCond->nLen * TSDB_NCHAR_SIZE; if (size < (uint32_t)pSchema->bytes) { @@ -3708,6 +3709,9 @@ static bool tableFilterFp(const void* pNode, void* param) { case TSDB_RELATION_LIKE: { return ret == 0; } + case TSDB_RELATION_MATCH: { + return ret == 0; + } case TSDB_RELATION_IN: { return ret == 1; } @@ -4041,6 +4045,8 @@ static int32_t setQueryCond(tQueryInfo *queryColInfo, SQueryCond* pCond) { pCond->start->v = queryColInfo->q; } else if (optr == TSDB_RELATION_LIKE) { assert(0); + } else if (optr == TSDB_RELATION_MATCH) { + assert(0); } return TSDB_CODE_SUCCESS; @@ -4198,7 +4204,7 @@ static void queryIndexlessColumn(SSkipList* pSkipList, tQueryInfo* pQueryInfo, S if (pQueryInfo->sch.colId == TSDB_TBNAME_COLUMN_INDEX) { if (pQueryInfo->optr == TSDB_RELATION_IN) { addToResult = pQueryInfo->compare(name, pQueryInfo->q); - } else if (pQueryInfo->optr == TSDB_RELATION_LIKE) { + } else if (pQueryInfo->optr == TSDB_RELATION_LIKE || pQueryInfo->optr == TSDB_RELATION_MATCH) { addToResult = !pQueryInfo->compare(name, pQueryInfo->q); } } else { @@ -4230,7 +4236,8 @@ void getTableListfromSkipList(tExprNode *pExpr, SSkipList *pSkipList, SArray *re param->setupInfoFn(pExpr, param->pExtInfo); tQueryInfo *pQueryInfo = pExpr->_node.info; - if (pQueryInfo->indexed && (pQueryInfo->optr != TSDB_RELATION_LIKE && pQueryInfo->optr != TSDB_RELATION_IN)) { + if (pQueryInfo->indexed && (pQueryInfo->optr != TSDB_RELATION_LIKE && pQueryInfo->optr != TSDB_RELATION_MATCH + && pQueryInfo->optr != TSDB_RELATION_IN)) { queryIndexedColumn(pSkipList, pQueryInfo, result); } else { queryIndexlessColumn(pSkipList, pQueryInfo, result, param->nodeFilterFn); diff --git a/src/util/inc/tcompare.h b/src/util/inc/tcompare.h index d1760ab28c85838e8b8ae1e58eeb2fdeb306bd0e..ef4c1096023bd670335603dee6ab274470de3ed7 100644 --- a/src/util/inc/tcompare.h +++ b/src/util/inc/tcompare.h @@ -25,7 +25,8 @@ extern "C" { #define TSDB_PATTERN_MATCH 0 #define TSDB_PATTERN_NOMATCH 1 #define TSDB_PATTERN_NOWILDCARDMATCH 2 -#define TSDB_PATTERN_STRING_MAX_LEN 100 +#define TSDB_PATTERN_STRING_DEFAULT_LEN 100 +#define TSDB_REGEX_STRING_DEFAULT_LEN 128 #define FLT_COMPAR_TOL_FACTOR 4 #define FLT_EQUAL(_x, _y) (fabs((_x) - (_y)) <= (FLT_COMPAR_TOL_FACTOR * FLT_EPSILON)) @@ -82,6 +83,7 @@ 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 compareStrRegexComp(const void* pLeft, const void* pRight); int32_t compareFindItemInSet(const void *pLeft, const void* pRight); int32_t compareWStrPatternComp(const void* pLeft, const void* pRight); diff --git a/src/util/inc/tutil.h b/src/util/inc/tutil.h index 7c8fd2ed8353a086ec9f145aaaa30f4db57113cb..6bcfb5de295c5719032b81c23d16ec2b1476349e 100644 --- a/src/util/inc/tutil.h +++ b/src/util/inc/tutil.h @@ -32,6 +32,7 @@ char * strnchr(char *haystack, char needle, int32_t len, bool skipquote); char ** strsplit(char *src, const char *delim, int32_t *num); char * strtolower(char *dst, const char *src); char * strntolower(char *dst, const char *src, int32_t n); +char * strntolower_s(char *dst, const char *src, int32_t n); int64_t strnatoi(char *num, int32_t len); char * strbetween(char *string, char *begin, char *end); char * paGetToken(char *src, char **token, int32_t *tokenLen); diff --git a/src/util/src/tarray.c b/src/util/src/tarray.c index d0d126c1e4d7f2e7c0913585df6031b556291fc3..2d6c513cb57ce1d524a1fb69df68702e624ede7b 100644 --- a/src/util/src/tarray.c +++ b/src/util/src/tarray.c @@ -112,14 +112,15 @@ void taosArrayRemoveBatch(SArray *pArray, const int32_t* pData, int32_t numOfEle i += 1; } - assert(i == pData[numOfElems - 1] + 1); + assert(i == pData[numOfElems - 1] + 1 && i <= size); - int32_t dstIndex = pData[numOfElems - 1] - numOfElems + 1; int32_t srcIndex = pData[numOfElems - 1] + 1; - - char* dst = TARRAY_GET_ELEM(pArray, dstIndex); - char* src = TARRAY_GET_ELEM(pArray, srcIndex); - memmove(dst, src, pArray->elemSize * (pArray->size - numOfElems)); + int32_t dstIndex = pData[numOfElems - 1] - numOfElems + 1; + if (pArray->size - srcIndex > 0) { + char* dst = TARRAY_GET_ELEM(pArray, dstIndex); + char* src = TARRAY_GET_ELEM(pArray, srcIndex); + memmove(dst, src, pArray->elemSize * (pArray->size - srcIndex)); + } pArray->size -= numOfElems; } diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index 69b3741e13c9e0b3ee00615a29851a3f690a1e84..6665c25a90a7fcb0db83766b88c9c9c7fe047fbf 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -71,6 +71,8 @@ static pthread_once_t cacheThreadInit = PTHREAD_ONCE_INIT; static pthread_mutex_t guard = PTHREAD_MUTEX_INITIALIZER; static SArray* pCacheArrayList = NULL; static bool stopRefreshWorker = false; +static bool refreshWorkerNormalStopped = false; +static bool refreshWorkerUnexpectedStopped = false; static void doInitRefreshThread(void) { pCacheArrayList = taosArrayInit(4, POINTER_BYTES); @@ -537,7 +539,10 @@ void taosCacheCleanup(SCacheObj *pCacheObj) { pCacheObj->deleting = 1; // wait for the refresh thread quit before destroying the cache object. + // But in the dll, the child thread will be killed before atexit takes effect. while(atomic_load_8(&pCacheObj->deleting) != 0) { + if (refreshWorkerNormalStopped) break; + if (refreshWorkerUnexpectedStopped) return; taosMsleep(50); } @@ -640,7 +645,7 @@ void doCleanupDataCache(SCacheObj *pCacheObj) { // todo memory leak if there are object with refcount greater than 0 in hash table? taosHashCleanup(pCacheObj->pHashTable); - taosTrashcanEmpty(pCacheObj, false); + taosTrashcanEmpty(pCacheObj, true); __cache_lock_destroy(pCacheObj); @@ -676,6 +681,12 @@ static void doCacheRefresh(SCacheObj* pCacheObj, int64_t time, __cache_free_fn_t taosHashCondTraverse(pCacheObj->pHashTable, travHashTableFn, &sup); } +void taosCacheRefreshWorkerUnexpectedStopped(void) { + if(!refreshWorkerNormalStopped) { + refreshWorkerUnexpectedStopped=true; + } +} + void* taosCacheTimedRefresh(void *handle) { assert(pCacheArrayList != NULL); uDebug("cache refresh thread starts"); @@ -684,6 +695,7 @@ void* taosCacheTimedRefresh(void *handle) { const int32_t SLEEP_DURATION = 500; //500 ms int64_t count = 0; + atexit(taosCacheRefreshWorkerUnexpectedStopped); while(1) { taosMsleep(SLEEP_DURATION); @@ -748,6 +760,7 @@ void* taosCacheTimedRefresh(void *handle) { pCacheArrayList = NULL; pthread_mutex_destroy(&guard); + refreshWorkerNormalStopped=true; uDebug("cache refresh thread quits"); return NULL; @@ -762,6 +775,6 @@ void taosCacheRefresh(SCacheObj *pCacheObj, __cache_free_fn_t fp) { doCacheRefresh(pCacheObj, now, fp); } -void taosStopCacheRefreshWorker() { - stopRefreshWorker = false; +void taosStopCacheRefreshWorker(void) { + stopRefreshWorker = true; } \ No newline at end of file diff --git a/src/util/src/tcompare.c b/src/util/src/tcompare.c index 1315f684bc0040197dd902269bac5609804f545c..4c76724921404b2a799479c86166cd462220a99c 100644 --- a/src/util/src/tcompare.c +++ b/src/util/src/tcompare.c @@ -12,11 +12,17 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +#define _BSD_SOURCE +#define _GNU_SOURCE +#define _XOPEN_SOURCE +#define _DEFAULT_SOURCE -#include "os.h" -#include "ttype.h" #include "tcompare.h" +#include "tulog.h" #include "hash.h" +#include "regex.h" +#include "os.h" +#include "ttype.h" int32_t setCompareBytes1(const void *pLeft, const void *pRight) { return NULL != taosHashGet((SHashObj *)pRight, pLeft, 1) ? 1 : 0; @@ -139,8 +145,8 @@ int32_t compareFloatVal(const void *pLeft, const void *pRight) { } if (FLT_EQUAL(p1, p2)) { return 0; - } - return FLT_GREATER(p1, p2) ? 1: -1; + } + return FLT_GREATER(p1, p2) ? 1: -1; } int32_t compareFloatValDesc(const void* pLeft, const void* pRight) { @@ -164,8 +170,8 @@ int32_t compareDoubleVal(const void *pLeft, const void *pRight) { } if (FLT_EQUAL(p1, p2)) { return 0; - } - return FLT_GREATER(p1, p2) ? 1: -1; + } + return FLT_GREATER(p1, p2) ? 1: -1; } int32_t compareDoubleValDesc(const void* pLeft, const void* pRight) { @@ -175,7 +181,7 @@ int32_t compareDoubleValDesc(const void* pLeft, const void* pRight) { int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight) { int32_t len1 = varDataLen(pLeft); int32_t len2 = varDataLen(pRight); - + if (len1 != len2) { return len1 > len2? 1:-1; } else { @@ -199,16 +205,7 @@ int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight) { if (len1 != len2) { return len1 > len2? 1:-1; } else { - char *pLeftTerm = (char *)tcalloc(len1 + 1, sizeof(char)); - char *pRightTerm = (char *)tcalloc(len1 + 1, sizeof(char)); - memcpy(pLeftTerm, varDataVal(pLeft), len1); - memcpy(pRightTerm, varDataVal(pRight), len2); - - int32_t ret = wcsncmp((wchar_t*) pLeftTerm, (wchar_t*) pRightTerm, len1/TSDB_NCHAR_SIZE); - - tfree(pLeftTerm); - tfree(pRightTerm); - + int32_t ret = memcmp((wchar_t*) pLeft, (wchar_t*) pRight, len1); if (ret == 0) { return 0; } else { @@ -233,33 +230,33 @@ int32_t compareLenPrefixedWStrDesc(const void* pLeft, const void* pRight) { */ int patternMatch(const char *patterStr, const char *str, size_t size, const SPatternCompareInfo *pInfo) { char c, c1; - + int32_t i = 0; int32_t j = 0; - + while ((c = patterStr[i++]) != 0) { if (c == pInfo->matchAll) { /* Match "*" */ - + while ((c = patterStr[i++]) == pInfo->matchAll || c == pInfo->matchOne) { if (c == pInfo->matchOne && (j > size || str[j++] == 0)) { // empty string, return not match return TSDB_PATTERN_NOWILDCARDMATCH; } } - + if (c == 0) { return TSDB_PATTERN_MATCH; /* "*" at the end of the pattern matches */ } - + char next[3] = {toupper(c), tolower(c), 0}; while (1) { size_t n = strcspn(str, next); str += n; - + if (str[0] == 0 || (n >= size)) { break; } - + int32_t ret = patternMatch(&patterStr[i], ++str, size - n - 1, pInfo); if (ret != TSDB_PATTERN_NOMATCH) { return ret; @@ -267,18 +264,19 @@ int patternMatch(const char *patterStr, const char *str, size_t size, const SPat } return TSDB_PATTERN_NOWILDCARDMATCH; } - + c1 = str[j++]; - + if (j <= size) { + if (c == '\\' && patterStr[i] == '_' && c1 == '_') { i++; continue; } if (c == c1 || tolower(c) == tolower(c1) || (c == pInfo->matchOne && c1 != 0)) { continue; } } - + return TSDB_PATTERN_NOMATCH; } - + return (str[j] == 0 || j >= size) ? TSDB_PATTERN_MATCH : TSDB_PATTERN_NOMATCH; } @@ -286,13 +284,13 @@ int WCSPatternMatch(const wchar_t *patterStr, const wchar_t *str, size_t size, c wchar_t c, c1; wchar_t matchOne = L'_'; // "_" wchar_t matchAll = L'%'; // "%" - + int32_t i = 0; int32_t j = 0; - + while ((c = patterStr[i++]) != 0) { if (c == matchAll) { /* Match "%" */ - + while ((c = patterStr[i++]) == matchAll || c == matchOne) { if (c == matchOne && (j > size || str[j++] == 0)) { return TSDB_PATTERN_NOWILDCARDMATCH; @@ -301,33 +299,33 @@ int WCSPatternMatch(const wchar_t *patterStr, const wchar_t *str, size_t size, c if (c == 0) { return TSDB_PATTERN_MATCH; } - + wchar_t accept[3] = {towupper(c), towlower(c), 0}; while (1) { size_t n = wcscspn(str, accept); - + str += n; if (str[0] == 0 || (n >= size)) { break; } - + int32_t ret = WCSPatternMatch(&patterStr[i], ++str, size - n - 1, pInfo); if (ret != TSDB_PATTERN_NOMATCH) { return ret; } } - + return TSDB_PATTERN_NOWILDCARDMATCH; } - + c1 = str[j++]; - + if (j <= size) { if (c == c1 || towlower(c) == towlower(c1) || (c == matchOne && c1 != 0)) { continue; } } - + return TSDB_PATTERN_NOMATCH; } @@ -352,6 +350,43 @@ int32_t compareStrPatternComp(const void* pLeft, const void* pRight) { return (ret == TSDB_PATTERN_MATCH) ? 0 : 1; } +int32_t compareStrRegexComp(const void* pLeft, const void* pRight) { + size_t sz = varDataLen(pRight); + char *pattern = malloc(sz + 1); + memcpy(pattern, varDataVal(pRight), varDataLen(pRight)); + pattern[sz] = 0; + + sz = varDataLen(pLeft); + char *str = malloc(sz + 1); + memcpy(str, varDataVal(pLeft), sz); + str[sz] = 0; + + int errCode = 0; + regex_t regex; + char msgbuf[256] = {0}; + + int cflags = REG_EXTENDED; + if ((errCode = regcomp(®ex, pattern, cflags)) != 0) { + regerror(errCode, ®ex, msgbuf, sizeof(msgbuf)); + uError("Failed to compile regex pattern %s. reason %s", pattern, msgbuf); + regfree(®ex); + free(str); + free(pattern); + return 1; + } + + errCode = regexec(®ex, str, 0, NULL, 0); + if (errCode != 0 && errCode != REG_NOMATCH) { + regerror(errCode, ®ex, msgbuf, sizeof(msgbuf)); + uDebug("Failed to match %s with pattern %s, reason %s", str, pattern, msgbuf) + } + int32_t result = (errCode == 0) ? 0 : 1; + regfree(®ex); + free(str); + free(pattern); + return result; +} + int32_t taosArrayCompareString(const void* a, const void* b) { const char* x = *(const char**)a; const char* y = *(const char**)b; @@ -367,12 +402,13 @@ int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) { SPatternCompareInfo pInfo = {'%', '_'}; assert(varDataLen(pRight) <= TSDB_MAX_FIELD_LEN * TSDB_NCHAR_SIZE); - wchar_t *pattern = calloc(varDataLen(pRight) + 1, sizeof(wchar_t)); + wchar_t *pattern = calloc(varDataLen(pRight) + 1, sizeof(wchar_t)); memcpy(pattern, varDataVal(pRight), varDataLen(pRight)); int32_t ret = WCSPatternMatch(pattern, varDataVal(pLeft), varDataLen(pLeft)/TSDB_NCHAR_SIZE, &pInfo); free(pattern); + return (ret == TSDB_PATTERN_MATCH) ? 0 : 1; } @@ -412,19 +448,23 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) { case TSDB_DATA_TYPE_FLOAT: comparFn = compareFloatVal; break; case TSDB_DATA_TYPE_DOUBLE: comparFn = compareDoubleVal; break; case TSDB_DATA_TYPE_BINARY: { - if (optr == TSDB_RELATION_LIKE) { /* wildcard query using like operator */ + if (optr == TSDB_RELATION_MATCH) { + comparFn = compareStrRegexComp; + } else if (optr == TSDB_RELATION_LIKE) { /* wildcard query using like operator */ comparFn = compareStrPatternComp; } else if (optr == TSDB_RELATION_IN) { comparFn = compareFindItemInSet; } else { /* normal relational comparFn */ comparFn = compareLenPrefixedStr; } - + break; } - + case TSDB_DATA_TYPE_NCHAR: { - if (optr == TSDB_RELATION_LIKE) { + if (optr == TSDB_RELATION_MATCH) { + comparFn = compareStrRegexComp; + } else if (optr == TSDB_RELATION_LIKE) { comparFn = compareWStrPatternComp; } else if (optr == TSDB_RELATION_IN) { comparFn = compareFindItemInSet; @@ -443,13 +483,13 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) { comparFn = compareInt32Val; break; } - + return comparFn; } __compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order) { __compar_fn_t comparFn = NULL; - + switch (keyType) { case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_BOOL: @@ -493,7 +533,7 @@ __compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order) { comparFn = (order == TSDB_ORDER_ASC)? compareInt32Val:compareInt32ValDesc; break; } - + return comparFn; } @@ -517,17 +557,7 @@ int32_t doCompare(const char* f1, const char* f2, int32_t type, size_t size) { if (t1->len != t2->len) { return t1->len > t2->len? 1:-1; } - - char *t1_term = (char *)tcalloc(t1->len + 1, sizeof(char)); - char *t2_term = (char *)tcalloc(t2->len + 1, sizeof(char)); - memcpy(t1_term, t1->data, t1->len); - memcpy(t2_term, t2->data, t2->len); - - int32_t ret = wcsncmp((wchar_t*) t1_term, (wchar_t*) t2_term, t2->len/TSDB_NCHAR_SIZE); - - tfree(t1_term); - tfree(t2_term); - + int32_t ret = memcmp((wchar_t*) t1, (wchar_t*) t2, t2->len); if (ret == 0) { return ret; } @@ -536,7 +566,7 @@ int32_t doCompare(const char* f1, const char* f2, int32_t type, size_t size) { default: { // todo refactor tstr* t1 = (tstr*) f1; tstr* t2 = (tstr*) f2; - + if (t1->len != t2->len) { return t1->len > t2->len? 1:-1; } else { diff --git a/src/util/src/terror.c b/src/util/src/terror.c index 49e46cdde8f7689083b65f747df35a13318c4e46..8fb39cd1702fe670e44f2e0db1639a0f48ab5ab0 100644 --- a/src/util/src/terror.c +++ b/src/util/src/terror.c @@ -112,6 +112,10 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSC_EXCEED_SQL_LIMIT, "SQL statement too lon TAOS_DEFINE_ERROR(TSDB_CODE_TSC_FILE_EMPTY, "File is empty") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_LINE_SYNTAX_ERROR, "Syntax error in Line") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_NO_META_CACHED, "No table meta cached") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DUP_COL_NAMES, "duplicated column names") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_TAG_LENGTH, "Invalid tag length") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_COLUMN_LENGTH, "Invalid column length") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DUP_TAG_NAMES, "duplicated tag names") // mnode TAOS_DEFINE_ERROR(TSDB_CODE_MND_MSG_NOT_PROCESSED, "Message not processed") @@ -194,6 +198,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_FUNC_ALREADY_EXIST, "Func already exists") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC, "Invalid func") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC_BUFSIZE, "Invalid func bufSize") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TAG_LENGTH, "invalid tag length") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_COLUMN_LENGTH, "invalid column length") + TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_NOT_SELECTED, "Database not specified or available") TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_ALREADY_EXIST, "Database already exists") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_DB_OPTION, "Invalid database options") diff --git a/src/util/src/tfunctional.c b/src/util/src/tfunctional.c index c470a2b8aefc11141c9125e60c1c45fcbb949f09..8b20f8fc0a6b6e08bcfd501f625c4594b4dff50d 100644 --- a/src/util/src/tfunctional.c +++ b/src/util/src/tfunctional.c @@ -14,23 +14,24 @@ */ #include "tfunctional.h" -#include "tarray.h" - tGenericSavedFunc* genericSavedFuncInit(GenericVaFunc func, int numOfArgs) { tGenericSavedFunc* pSavedFunc = malloc(sizeof(tGenericSavedFunc) + numOfArgs * (sizeof(void*))); + if(pSavedFunc == NULL) return NULL; pSavedFunc->func = func; return pSavedFunc; } tI32SavedFunc* i32SavedFuncInit(I32VaFunc func, int numOfArgs) { tI32SavedFunc* pSavedFunc = malloc(sizeof(tI32SavedFunc) + numOfArgs * sizeof(void *)); + if(pSavedFunc == NULL) return NULL; pSavedFunc->func = func; return pSavedFunc; } tVoidSavedFunc* voidSavedFuncInit(VoidVaFunc func, int numOfArgs) { tVoidSavedFunc* pSavedFunc = malloc(sizeof(tVoidSavedFunc) + numOfArgs * sizeof(void*)); + if(pSavedFunc == NULL) return NULL; pSavedFunc->func = func; return pSavedFunc; } diff --git a/src/util/src/tnettest.c b/src/util/src/tnettest.c index 42fa1f1b9f4c432067d7004da4c74d6aff274972..2a147ee4f17a38e9a00a6110fcc6f2d21fb7b131 100644 --- a/src/util/src/tnettest.c +++ b/src/util/src/tnettest.c @@ -671,7 +671,7 @@ void taosNetTest(char *role, char *host, int32_t port, int32_t pkgLen, taosNetCheckSpeed(host, port, pkgLen, pkgNum, strtolower(type, pkgType)); }else if (0 == strcmp("fqdn", role)) { taosNetTestFqdn(host); - }else { + } else { taosNetTestStartup(host, port); } diff --git a/src/util/src/tsocket.c b/src/util/src/tsocket.c index 77941cba82010a9187227b4740c4100680577403..8d69a87e77bff594e7a99b2a63d4d849214eebe9 100644 --- a/src/util/src/tsocket.c +++ b/src/util/src/tsocket.c @@ -488,7 +488,7 @@ SOCKET taosOpenTcpServerSocket(uint32_t ip, uint16_t port) { return -1; } - if (listen(sockFd, 10) < 0) { + if (listen(sockFd, 1024) < 0) { uError("listen tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno)); taosCloseSocket(sockFd); return -1; diff --git a/src/util/src/ttokenizer.c b/src/util/src/ttokenizer.c index c4d05b2d5a851ee4c2a8232095dd6ea5567213ab..04f2d7fc04cafb5514e4f7df1e6063cad9c096da 100644 --- a/src/util/src/ttokenizer.c +++ b/src/util/src/ttokenizer.c @@ -53,6 +53,7 @@ static SKeyword keywordTable[] = { {"NOTNULL", TK_NOTNULL}, {"IS", TK_IS}, {"LIKE", TK_LIKE}, + {"MATCH", TK_MATCH}, {"GLOB", TK_GLOB}, {"BETWEEN", TK_BETWEEN}, {"IN", TK_IN}, @@ -137,6 +138,7 @@ static SKeyword keywordTable[] = { {"COMMA", TK_COMMA}, {"NULL", TK_NULL}, {"SELECT", TK_SELECT}, + {"EVERY", TK_EVERY}, {"FROM", TK_FROM}, {"VARIABLE", TK_VARIABLE}, {"INTERVAL", TK_INTERVAL}, diff --git a/src/util/src/tutil.c b/src/util/src/tutil.c index 1a73991ade1ea4617fc4d3dab3904652ff46d691..5f8c92898fc5f0abc4c733c0558befd68ac3cac7 100644 --- a/src/util/src/tutil.c +++ b/src/util/src/tutil.c @@ -64,12 +64,15 @@ int32_t strRmquote(char *z, int32_t len){ int32_t j = 0; for (uint32_t k = 1; k < len - 1; ++k) { if (z[k] == '\\' || (z[k] == delim && z[k + 1] == delim)) { + if (z[k] == '\\' && z[k + 1] == '_') { + //match '_' self + } else { z[j] = z[k + 1]; - - cnt++; - j++; - k++; - continue; + cnt++; + j++; + k++; + continue; + } } z[j] = z[k]; @@ -162,6 +165,8 @@ char *strnchr(char *haystack, char needle, int32_t len, bool skipquote) { return NULL; } + + char* strtolower(char *dst, const char *src) { int esc = 0; char quote = 0, *p = dst, c; @@ -197,7 +202,7 @@ char* strntolower(char *dst, const char *src, int32_t n) { if (n == 0) { *p = 0; return dst; - } + } for (c = *src++; n-- > 0; c = *src++) { if (esc) { esc = 0; @@ -219,6 +224,26 @@ char* strntolower(char *dst, const char *src, int32_t n) { return dst; } +char* strntolower_s(char *dst, const char *src, int32_t n) { + char *p = dst, c; + + assert(dst != NULL); + if (n == 0) { + return NULL; + } + + while (n-- > 0) { + c = *src; + if (c >= 'A' && c <= 'Z') { + c -= 'A' - 'a'; + } + *p++ = c; + src++; + } + + return dst; +} + char *paGetToken(char *string, char **token, int32_t *tokenLen) { char quote = 0; diff --git a/src/util/tests/skiplistTest.cpp b/src/util/tests/skiplistTest.cpp index dfbe0f67167ad12cedc0239fc310614ef747b080..df4c5af5e2ab62efab287f3dd00650fc29805c98 100644 --- a/src/util/tests/skiplistTest.cpp +++ b/src/util/tests/skiplistTest.cpp @@ -70,7 +70,7 @@ void doubleSkipListTest() { } void randKeyTest() { - SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_INT, sizeof(int32_t), getKeyComparFunc(TSDB_DATA_TYPE_INT), + SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_INT, sizeof(int32_t), getKeyComparFunc(TSDB_DATA_TYPE_INT, TSDB_ORDER_ASC), false, getkey); int32_t size = 200000; diff --git a/src/wal/src/walWrite.c b/src/wal/src/walWrite.c index cfadafebdda12b7727b42095311dcd9539e15cb7..e991bf02aa68c92d7cf4dfdb09982ebaa6541bdc 100644 --- a/src/wal/src/walWrite.c +++ b/src/wal/src/walWrite.c @@ -540,7 +540,7 @@ static int32_t walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp, ch pWal->version = pHead->version; - //wInfo("writeFp: %ld", offset); + // wInfo("writeFp: %ld", offset); if (0 != walSMemRowCheck(pHead)) { wError("vgId:%d, restore wal, fileId:%" PRId64 " hver:%" PRIu64 " wver:%" PRIu64 " len:%d offset:%" PRId64, pWal->vgId, fileId, pHead->version, pWal->version, pHead->len, offset); diff --git a/tests/examples/C#/taosdemo/Dockerfile b/tests/examples/C#/taosdemo/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..4eefc6c75248b1e1e1d6daf305386cca5b11e606 --- /dev/null +++ b/tests/examples/C#/taosdemo/Dockerfile @@ -0,0 +1,24 @@ +FROM tdengine/tdengine-beta:latest + +ENV DEBIAN_FRONTEND=noninteractive +ARG MIRROR=archive.ubuntu.com +RUN sed -Ei 's/\w+.ubuntu.com/'${MIRROR}'/' /etc/apt/sources.list && apt update && apt install mono-devel -y +RUN apt-get install wget -y \ + && wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \ + && dpkg -i packages-microsoft-prod.deb \ + && rm packages-microsoft-prod.deb \ + && apt-get update && apt-get install -y dotnet-sdk-5.0 +COPY ./*.cs *.csproj /tmp/ +WORKDIR /tmp/ +RUN dotnet build -c Release && cp bin/Release/net5.0/taosdemo bin/Release/net5.0/taosdemo.* /usr/local/bin/ && rm -rf /tmp/* + +FROM tdengine/tdengine-beta:latest + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install wget -y \ + && wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \ + && dpkg -i packages-microsoft-prod.deb \ + && rm packages-microsoft-prod.deb \ + && apt-get update && apt-get install -y dotnet-runtime-5.0 +COPY --from=0 /usr/local/bin/taosdemo* /usr/local/bin/ +CMD ["/usr/local/bin/taosdemo"] diff --git a/tests/examples/C#/taosdemo/README.md b/tests/examples/C#/taosdemo/README.md index 2d125fb140076c46c9abc4c60db330b28b494802..3cba3529bf513e2bf3d4ab0c169e7f3d03b2e6a8 100644 --- a/tests/examples/C#/taosdemo/README.md +++ b/tests/examples/C#/taosdemo/README.md @@ -1,13 +1,41 @@ +# C# Taosdemo + +## For Mono + install build environment -=== + +```sh yum/apt install mono-complete +``` -build C# version taosdemo -=== +build C# version taosdemo. + +```sh mcs -out:taosdemo *.cs +./taosdemo --help +``` + +## For DotNet + +install dotnet environment. + +```sh +wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb \ + && dpkg -i packages-microsoft-prod.deb \ + && rm packages-microsoft-prod.deb \ + && apt-get update && apt-get install -y dotnet-sdk-5.0 +``` + +Build DotNet version taosdemo. + +```sh +dotnet build -c Release +./bin/Release/net5.0/taosdemo --help +``` + +## Usage -run C# version taosdemo -=== +``` Usage: mono taosdemo.exe [OPTION...] --help Show usage. @@ -34,3 +62,4 @@ Usage: mono taosdemo.exe [OPTION...] -v Print verbose output -g Print debug output -y Skip read key for continous test, default is not skip +``` diff --git a/tests/examples/C#/taosdemo/taosdemo.csproj b/tests/examples/C#/taosdemo/taosdemo.csproj new file mode 100644 index 0000000000000000000000000000000000000000..15ec155d45e34aae7276fe596c177619dfddd3e9 --- /dev/null +++ b/tests/examples/C#/taosdemo/taosdemo.csproj @@ -0,0 +1,9 @@ + + + + Exe + net5.0 + false + + + diff --git a/tests/examples/c/apitest.c b/tests/examples/c/apitest.c index 01169715f3e8b5b9d6e212b4b317ecca5fa4dbcd..621950a834c515962f35e000279bc91e4c25b5e0 100644 --- a/tests/examples/c/apitest.c +++ b/tests/examples/c/apitest.c @@ -1,12 +1,15 @@ // sample code to verify all TDengine API // to compile: gcc -o apitest apitest.c -ltaos +#include "taoserror.h" + #include #include #include #include #include + static void prepare_data(TAOS* taos) { TAOS_RES *result; result = taos_query(taos, "drop database if exists test;"); @@ -1014,6 +1017,186 @@ int32_t verify_schema_less(TAOS* taos) { return (code); } +void verify_telnet_insert(TAOS* taos) { + TAOS_RES *result; + + result = taos_query(taos, "drop database if exists test;"); + taos_free_result(result); + usleep(100000); + result = taos_query(taos, "create database db precision 'ms';"); + taos_free_result(result); + usleep(100000); + + (void)taos_select_db(taos, "db"); + int32_t code = 0; + + /* metric */ + char* lines0[] = { + "stb0_0 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"", + "stb0_1 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"", + "stb0_2 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"", + }; + code = taos_insert_telnet_lines(taos, lines0, 3); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + /* timestamp */ + char* lines1[] = { + "stb1 1626006833s 1i8 host=\"host0\"", + "stb1 1626006833639000000ns 2i8 host=\"host0\"", + "stb1 1626006833640000us 3i8 host=\"host0\"", + "stb1 1626006833641123 4i8 host=\"host0\"", + "stb1 1626006833651ms 5i8 host=\"host0\"", + "stb1 0 6i8 host=\"host0\"", + }; + code = taos_insert_telnet_lines(taos, lines1, 6); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + /* metric value */ + //tinyin + char* lines2_0[] = { + "stb2_0 1626006833651ms -127i8 host=\"host0\"", + "stb2_0 1626006833652ms 127i8 host=\"host0\"" + }; + code = taos_insert_telnet_lines(taos, lines2_0, 2); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + //smallint + char* lines2_1[] = { + "stb2_1 1626006833651ms -32767i16 host=\"host0\"", + "stb2_1 1626006833652ms 32767i16 host=\"host0\"" + }; + code = taos_insert_telnet_lines(taos, lines2_1, 2); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + //int + char* lines2_2[] = { + "stb2_2 1626006833651ms -2147483647i32 host=\"host0\"", + "stb2_2 1626006833652ms 2147483647i32 host=\"host0\"" + }; + code = taos_insert_telnet_lines(taos, lines2_2, 2); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + //bigint + char* lines2_3[] = { + "stb2_3 1626006833651ms -9223372036854775807i64 host=\"host0\"", + "stb2_3 1626006833652ms 9223372036854775807i64 host=\"host0\"" + }; + code = taos_insert_telnet_lines(taos, lines2_3, 2); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + //float + char* lines2_4[] = { + "stb2_4 1626006833610ms 3f32 host=\"host0\"", + "stb2_4 1626006833620ms -3f32 host=\"host0\"", + "stb2_4 1626006833630ms 3.4f32 host=\"host0\"", + "stb2_4 1626006833640ms -3.4f32 host=\"host0\"", + "stb2_4 1626006833650ms 3.4E10f32 host=\"host0\"", + "stb2_4 1626006833660ms -3.4e10f32 host=\"host0\"", + "stb2_4 1626006833670ms 3.4E+2f32 host=\"host0\"", + "stb2_4 1626006833680ms -3.4e-2f32 host=\"host0\"", + "stb2_4 1626006833690ms 3.15 host=\"host0\"", + "stb2_4 1626006833700ms 3.4E38f32 host=\"host0\"", + "stb2_4 1626006833710ms -3.4E38f32 host=\"host0\"" + }; + code = taos_insert_telnet_lines(taos, lines2_4, 11); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + //double + char* lines2_5[] = { + "stb2_5 1626006833610ms 3f64 host=\"host0\"", + "stb2_5 1626006833620ms -3f64 host=\"host0\"", + "stb2_5 1626006833630ms 3.4f64 host=\"host0\"", + "stb2_5 1626006833640ms -3.4f64 host=\"host0\"", + "stb2_5 1626006833650ms 3.4E10f64 host=\"host0\"", + "stb2_5 1626006833660ms -3.4e10f64 host=\"host0\"", + "stb2_5 1626006833670ms 3.4E+2f64 host=\"host0\"", + "stb2_5 1626006833680ms -3.4e-2f64 host=\"host0\"", + "stb2_5 1626006833690ms 1.7E308f64 host=\"host0\"", + "stb2_5 1626006833700ms -1.7E308f64 host=\"host0\"" + }; + code = taos_insert_telnet_lines(taos, lines2_5, 10); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + //bool + char* lines2_6[] = { + "stb2_6 1626006833610ms t host=\"host0\"", + "stb2_6 1626006833620ms T host=\"host0\"", + "stb2_6 1626006833630ms true host=\"host0\"", + "stb2_6 1626006833640ms True host=\"host0\"", + "stb2_6 1626006833650ms TRUE host=\"host0\"", + "stb2_6 1626006833660ms f host=\"host0\"", + "stb2_6 1626006833670ms F host=\"host0\"", + "stb2_6 1626006833680ms false host=\"host0\"", + "stb2_6 1626006833690ms False host=\"host0\"", + "stb2_6 1626006833700ms FALSE host=\"host0\"" + }; + code = taos_insert_telnet_lines(taos, lines2_6, 10); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + //binary + char* lines2_7[] = { + "stb2_7 1626006833610ms \"binary_val.!@#$%^&*\" host=\"host0\"", + "stb2_7 1626006833620ms \"binary_val.:;,./?|+-=\" host=\"host0\"", + "stb2_7 1626006833630ms \"binary_val.()[]{}<>\" host=\"host0\"" + }; + code = taos_insert_telnet_lines(taos, lines2_7, 3); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + //nchar + char* lines2_8[] = { + "stb2_8 1626006833610ms L\"nchar_val数值一\" host=\"host0\"", + "stb2_8 1626006833620ms L\"nchar_val数值二\" host=\"host0\"", + }; + code = taos_insert_telnet_lines(taos, lines2_8, 2); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + /* tags */ + //tag value types + char* lines3_0[] = { + "stb3_0 1626006833610ms 1 t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=3.4E38f32,t6=1.7E308f64,t7=true,t8=\"binary_val_1\",t9=L\"标签值1\"", + "stb3_0 1626006833610ms 2 t1=-127i8,t2=-32767i16,t3=-2147483647i32,t4=-9223372036854775807i64,t5=-3.4E38f32,t6=-1.7E308f64,t7=false,t8=\"binary_val_2\",t9=L\"标签值2\"" + }; + code = taos_insert_telnet_lines(taos, lines3_0, 2); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + //tag ID as child table name + char* lines3_1[] = { + "stb3_1 1626006833610ms 1 id=\"child_table1\",host=\"host1\"", + "stb3_1 1626006833610ms 2 host=\"host2\",iD=\"child_table2\"", + "stb3_1 1626006833610ms 3 ID=\"child_table3\",host=\"host3\"" + }; + code = taos_insert_telnet_lines(taos, lines3_1, 3); + if (code) { + printf("code: %d, %s.\n", code, tstrerror(code)); + } + + return; +} + int main(int argc, char *argv[]) { const char* host = "127.0.0.1"; const char* user = "root"; @@ -1034,6 +1217,8 @@ int main(int argc, char *argv[]) { printf("************ verify schema-less *************\n"); verify_schema_less(taos); + printf("************ verify telnet-insert *************\n"); + verify_telnet_insert(taos); printf("************ verify query *************\n"); verify_query(taos); @@ -1051,7 +1236,7 @@ int main(int argc, char *argv[]) { verify_prepare2(taos); printf("************ verify prepare3 *************\n"); verify_prepare3(taos); - + printf("************ verify stream *************\n"); verify_stream(taos); printf("done\n"); diff --git a/tests/examples/c/schemaless.c b/tests/examples/c/schemaless.c index 3ea199c9144950526e4bbf59b9356753e2a88da6..1a551cc5f7bd600ccaf87701953f7109743e8302 100644 --- a/tests/examples/c/schemaless.c +++ b/tests/examples/c/schemaless.c @@ -61,7 +61,7 @@ int main(int argc, char* argv[]) { time_t ct = time(0); int64_t ts = ct * 1000; - char* lineFormat = "sta%d,t0=true,t1=127i8,t2=32767i16,t3=%di32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=255u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" %lldms"; + char* lineFormat = "sta%d,t0=true,t1=127i8,t2=32767i16,t3=%di32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=254u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" %lldms"; char** lines = calloc(numSuperTables * numChildTables * numRowsPerChildTable, sizeof(char*)); int l = 0; @@ -75,7 +75,7 @@ int main(int argc, char* argv[]) { } } } - shuffle(lines, numSuperTables * numChildTables * numRowsPerChildTable); + //shuffle(lines, numSuperTables * numChildTables * numRowsPerChildTable); printf("%s\n", "begin taos_insert_lines"); int64_t begin = getTimeInUs(); @@ -83,119 +83,5 @@ int main(int argc, char* argv[]) { int64_t end = getTimeInUs(); printf("code: %d, %s. time used: %"PRId64"\n", code, tstrerror(code), end-begin); - char* lines_000_0[] = { - "sta1,id=sta1_1,t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=255u8,t6=32770u16,t7=2147483699u32,t8=9223372036854775899u64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=255u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639000us" - }; - - code = taos_insert_lines(taos, lines_000_0 , sizeof(lines_000_0)/sizeof(char*)); - if (0 == code) { - printf("taos_insert_lines() lines_000_0 should return error\n"); - return -1; - } - - char* lines_000_1[] = { - "sta2,id=\"sta2_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=255u8,t6=32770u16,t7=2147483699u32,t8=9223372036854775899u64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=255u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639001" - }; - - code = taos_insert_lines(taos, lines_000_1 , sizeof(lines_000_1)/sizeof(char*)); - if (0 == code) { - printf("taos_insert_lines() lines_000_1 should return error\n"); - return -1; - } - - char* lines_000_2[] = { - "sta3,id=\"sta3_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=255u8,c6=32770u16,c7=2147483699u32,c8=9223372036854775899u64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 0" - }; - - code = taos_insert_lines(taos, lines_000_2 , sizeof(lines_000_2)/sizeof(char*)); - if (0 != code) { - printf("taos_insert_lines() lines_000_2 return code:%d (%s)\n", code, (char*)tstrerror(code)); - return -1; - } - - char* lines_001_0[] = { - "sta4,t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639000us", - - }; - - code = taos_insert_lines(taos, lines_001_0 , sizeof(lines_001_0)/sizeof(char*)); - if (0 != code) { - printf("taos_insert_lines() lines_001_0 return code:%d (%s)\n", code, (char*)tstrerror(code)); - return -1; - } - - char* lines_001_1[] = { - "sta5,id=\"sta5_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639001" - }; - - code = taos_insert_lines(taos, lines_001_1 , sizeof(lines_001_1)/sizeof(char*)); - if (0 != code) { - printf("taos_insert_lines() lines_001_1 return code:%d (%s)\n", code, (char*)tstrerror(code)); - return -1; - } - - char* lines_001_2[] = { - "sta6,id=\"sta6_1\",t0=true,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t9=11.12345f32,t10=22.123456789f64,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c0=true,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c9=11.12345f32,c10=22.123456789f64,c11=\"binaryValue\",c12=L\"ncharValue\" 0" - }; - - code = taos_insert_lines(taos, lines_001_2 , sizeof(lines_001_2)/sizeof(char*)); - if (0 != code) { - printf("taos_insert_lines() lines_001_2 return code:%d (%s)\n", code, (char*)tstrerror(code)); - return -1; - } - - char* lines_002[] = { - "stb,id=\"stb_1\",t20=t,t21=T,t22=true,t23=True,t24=TRUE,t25=f,t26=F,t27=false,t28=False,t29=FALSE,t10=33.12345,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c20=t,c21=T,c22=true,c23=True,c24=TRUE,c25=f,c26=F,c27=false,c28=False,c29=FALSE,c10=33.12345,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639000000ns", - "stc,id=\"stc_1\",t20=t,t21=T,t22=true,t23=True,t24=TRUE,t25=f,t26=F,t27=false,t28=False,t29=FALSE,t10=33.12345,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c20=t,c21=T,c22=true,c23=True,c24=TRUE,c25=f,c26=F,c27=false,c28=False,c29=FALSE,c10=33.12345,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833639019us", - "stc,id=\"stc_1\",t20=t,t21=T,t22=true,t23=True,t24=TRUE,t25=f,t26=F,t27=false,t28=False,t29=FALSE,t10=33.12345,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c20=t,c21=T,c22=true,c23=True,c24=TRUE,c25=f,c26=F,c27=false,c28=False,c29=FALSE,c10=33.12345,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006833640ms", - "stc,id=\"stc_1\",t20=t,t21=T,t22=true,t23=True,t24=TRUE,t25=f,t26=F,t27=false,t28=False,t29=FALSE,t10=33.12345,t11=\"binaryTagValue\",t12=L\"ncharTagValue\" c20=t,c21=T,c22=true,c23=True,c24=TRUE,c25=f,c26=F,c27=false,c28=False,c29=FALSE,c10=33.12345,c11=\"binaryValue\",c12=L\"ncharValue\" 1626006834s" - }; - - code = taos_insert_lines(taos, lines_002 , sizeof(lines_002)/sizeof(char*)); - if (0 != code) { - printf("taos_insert_lines() lines_002 return code:%d (%s)\n", code, (char*)tstrerror(code)); - return -1; - } - - //Duplicate key check; - char* lines_003_1[] = { - "std,id=\"std_3_1\",t1=4i64,Id=\"std\",t2=true c1=true 1626006834s" - }; - - code = taos_insert_lines(taos, lines_003_1 , sizeof(lines_003_1)/sizeof(char*)); - if (0 == code) { - printf("taos_insert_lines() lines_003_1 return code:%d (%s)\n", code, (char*)tstrerror(code)); - return -1; - } - - char* lines_003_2[] = { - "std,id=\"std_3_2\",tag1=4i64,Tag2=true,tAg3=2,TaG2=\"dup!\" c1=true 1626006834s" - }; - - code = taos_insert_lines(taos, lines_003_2 , sizeof(lines_003_2)/sizeof(char*)); - if (0 == code) { - printf("taos_insert_lines() lines_003_2 return code:%d (%s)\n", code, (char*)tstrerror(code)); - return -1; - } - - char* lines_003_3[] = { - "std,id=\"std_3_3\",tag1=4i64 field1=true,Field2=2,FIElD1=\"dup!\",fIeLd4=true 1626006834s" - }; - - code = taos_insert_lines(taos, lines_003_3 , sizeof(lines_003_3)/sizeof(char*)); - if (0 == code) { - printf("taos_insert_lines() lines_003_3 return code:%d (%s)\n", code, (char*)tstrerror(code)); - return -1; - } - - char* lines_003_4[] = { - "std,id=\"std_3_4\",tag1=4i64,dupkey=4i16,tag2=T field1=true,dUpkEy=1e3f32,field2=\"1234\" 1626006834s" - }; - - code = taos_insert_lines(taos, lines_003_4 , sizeof(lines_003_4)/sizeof(char*)); - if (0 == code) { - printf("taos_insert_lines() lines_003_4 return code:%d (%s)\n", code, (char*)tstrerror(code)); - return -1; - } return 0; } diff --git a/tests/examples/nodejs/test1970.js b/tests/examples/nodejs/test1970.js new file mode 100644 index 0000000000000000000000000000000000000000..5177a7371e9a07fa7b548936ff038c1f2a29bc1f --- /dev/null +++ b/tests/examples/nodejs/test1970.js @@ -0,0 +1,125 @@ +const taos = require('td2.0-connector'); +var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0}) +var c1 = conn.cursor(); // Initializing a new cursor + +let stime = new Date(); +let interval = 1000; + +function convertDateToTS(date) { + let tsArr = date.toISOString().split("T") + return "\"" + tsArr[0] + " " + tsArr[1].substring(0, tsArr[1].length - 1) + "\""; +} + +function R(l, r) { + return Math.random() * (r - l) - r; +} + +function randomBool() { + if (Math.random() < 0.5) { + return true; + } + return false; +} + +// Initialize +const dbname = "nodejs_1970_db"; +const tbname = "t1"; + +let dropDB = "drop database if exists " + dbname +console.log(dropDB);//asdasdasd +c1.execute(dropDB);///asdasd + +let createDB = "create database " + dbname + " keep 36500" +console.log(createDB); +c1.execute(createDB); + +let useTbl = "use " + dbname +console.log(useTbl) +c1.execute(useTbl); + +let createTbl = "create table if not exists " + tbname + "(ts timestamp,id int)" +console.log(createTbl); +c1.execute(createTbl); + +//1969-12-31 23:59:59.999 +//1970-01-01 00:00:00.000 +//1970-01-01 07:59:59.999 +//1970-01-01 08:00:00.000a +//1628928479484 2021-08-14 08:07:59.484 +let sql1 = "insert into " + dbname + "." + tbname + " values('1969-12-31 23:59:59.999',1)" +console.log(sql1); +c1.execute(sql1); + +let sql2 = "insert into " + dbname + "." + tbname + " values('1970-01-01 00:00:00.000',2)" +console.log(sql2); +c1.execute(sql2); + +let sql3 = "insert into " + dbname + "." + tbname + " values('1970-01-01 07:59:59.999',3)" +console.log(sql3); +c1.execute(sql3); + +let sql4 = "insert into " + dbname + "." + tbname + " values('1970-01-01 08:00:00.000',4)" +console.log(sql4); +c1.execute(sql4); + +let sql5 = "insert into " + dbname + "." + tbname + " values('2021-08-14 08:07:59.484',5)" +console.log(sql5); +c1.execute(sql5); + +// Select +let query1 = "select * from " + dbname + "." + tbname +console.log(query1); +c1.execute(query1); + +var d = c1.fetchall(); +console.log(c1.fields); +for (let i = 0; i < d.length; i++) + console.log(d[i][0].valueOf()); + +//initialize +let initSql1 = "drop table if exists " + tbname +console.log(initSql1); +c1.execute(initSql1); + +console.log(createTbl); +c1.execute(createTbl); +c1.execute(useTbl) + +//-28800001 1969-12-31 23:59:59.999 +//-28800000 1970-01-01 00:00:00.000 +//-1 1970-01-01 07:59:59.999 +//0 1970-01-01 08:00:00.00 +//1628928479484 2021-08-14 08:07:59.484 +let sql11 = "insert into " + dbname + "." + tbname + " values(-28800001,11)"; +console.log(sql11); +c1.execute(sql11); + +let sql12 = "insert into " + dbname + "." + tbname + " values(-28800000,12)" +console.log(sql12); +c1.execute(sql12); + +let sql13 = "insert into " + dbname + "." + tbname + " values(-1,13)" +console.log(sql13); +c1.execute(sql13); + +let sql14 = "insert into " + dbname + "." + tbname + " values(0,14)" +console.log(sql14); +c1.execute(sql14); + +let sql15 = "insert into " + dbname + "." + tbname + " values(1628928479484,15)" +console.log(sql15); +c1.execute(sql15); + +// Select +console.log(query1); +c1.execute(query1); + +var d = c1.fetchall(); +console.log(c1.fields); +for (let i = 0; i < d.length; i++) + console.log(d[i][0].valueOf()); + +setTimeout(function () { + conn.close(); +}, 2000); + diff --git a/tests/gotest/batchtest.sh b/tests/gotest/batchtest.sh index 0fbbf40714b3349651beea9302e66628b31a22ac..8f5a7fe8f032134e55c9d9675361590ed6d5b19b 100755 --- a/tests/gotest/batchtest.sh +++ b/tests/gotest/batchtest.sh @@ -17,5 +17,5 @@ go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.io,direct bash ./case001/case001.sh $severIp $serverPort -#bash ./case002/case002.sh $severIp $serverPort +bash ./case002/case002.sh $severIp $serverPort #bash ./case003/case003.sh $severIp $serverPort diff --git a/tests/gotest/case001/case001.go b/tests/gotest/case001/case001.go index 9e912aab99e2aa0da1e1490741f04e67ab1d0c8a..9d35888f313461a2ce90c7a6ed4ef2791229866c 100644 --- a/tests/gotest/case001/case001.go +++ b/tests/gotest/case001/case001.go @@ -19,7 +19,7 @@ import ( "database/sql" "flag" "fmt" - _ "github.com/taosdata/driver-go/taosSql" + _ "github.com/taosdata/driver-go/v2/taosSql" "log" "strconv" "time" @@ -63,6 +63,7 @@ func main() { url = "root:taosdata@/tcp(" + configPara.hostName + ":" + strconv.Itoa(configPara.serverPort) + ")/" // open connect to taos server + fmt.Printf("url:%s",url) db, err := sql.Open(taosDriverName, url) if err != nil { log.Fatalf("Open database error: %s\n", err) @@ -168,17 +169,18 @@ func insert_data(db *sql.DB, demot string) { func select_data(db *sql.DB, demot string) { st := time.Now().Nanosecond() - + fmt.Println(demot) rows, err := db.Query("select * from ? ", demot) // go text mode + fmt.Println("end query",err) checkErr(err, "select db.Query") fmt.Printf("%10s%s%8s %5s %9s%s %s %8s%s %7s%s %8s%s %4s%s %5s%s\n", " ", "ts", " ", "id", " ", "name", " ", "len", " ", "flag", " ", "notes", " ", "fv", " ", " ", "dv") var affectd int //decoder := mahonia.NewDecoder("gbk") // 把原来ANSI格式的文本文件里的字符,用gbk进行解码。 - + fmt.Println("start next") for rows.Next() { - var ts string + var ts time.Time var name string var id int var len int8 @@ -188,6 +190,7 @@ func select_data(db *sql.DB, demot string) { var dv float64 err = rows.Scan(&ts, &id, &name, &len, &flag, ¬es, &fv, &dv) + fmt.Println("rows:",err) checkErr(err, "select rows.Scan") fmt.Printf("%s|\t", ts) diff --git a/tests/gotest/case002/case002.bat b/tests/gotest/case002/case002.bat new file mode 100644 index 0000000000000000000000000000000000000000..ebec576e724ccb14319dd380c9783a783ac0db62 --- /dev/null +++ b/tests/gotest/case002/case002.bat @@ -0,0 +1,9 @@ +@echo off +echo ==== start run cases001.go + +del go.* +go mod init demotest +go build +demotest.exe -h %1 -p %2 +cd .. + diff --git a/tests/gotest/case002/case002.go b/tests/gotest/case002/case002.go new file mode 100644 index 0000000000000000000000000000000000000000..c69da04cb271c24e33953ca8fdfea71c67349b4f --- /dev/null +++ b/tests/gotest/case002/case002.go @@ -0,0 +1,81 @@ +package main + +import ( + "database/sql/driver" + "fmt" + "io" + "os" + "time" + + taos "github.com/taosdata/driver-go/v2/af" +) + +func Subscribe_check(topic taos.Subscriber, check int) bool { + count := 0 + rows, err := topic.Consume() + defer func() { rows.Close(); time.Sleep(time.Second) }() + if err != nil { + fmt.Println(err) + os.Exit(3) + } + for { + values := make([]driver.Value, 2) + err := rows.Next(values) + if err == io.EOF { + break + } else if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(4) + } + count++ + } + if count == check { + return false + } else { + return true + } +} +func main() { + ts := 1630461600000 + db, err := taos.Open("127.0.0.1", "", "", "", 0) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + defer db.Close() + db.Exec("drop if exists database test") + db.Exec("create if not exists database test") + db.Exec("use test") + db.Exec("drop if exists database test") + db.Exec("create table test (ts timestamp ,level int)") + for i := 0; i < 10; i++ { + sqlcmd := fmt.Sprintf("insert into test values(%d,%d)", ts+i, i) + db.Exec(sqlcmd) + } + + fmt.Println("consumption 01.") + topic, err := db.Subscribe(false, "test", "select ts, level from test", time.Second) + if Subscribe_check(topic, 10) { + os.Exit(3) + } + + fmt.Println("consumption 02: no new rows inserted") + if Subscribe_check(topic, 0) { + os.Exit(3) + } + + fmt.Println("consumption 03: after one new rows inserted") + sqlcmd := fmt.Sprintf("insert into test values(%d,%d)", ts+10, 10) + db.Exec(sqlcmd) + if Subscribe_check(topic, 1) { + os.Exit(3) + } + + fmt.Println("consumption 04: keep progress and continue previous subscription") + topic.Unsubscribe(true) + topic, err = db.Subscribe(false, "test", "select ts, level from test", time.Second) + if Subscribe_check(topic, 0) { + os.Exit(3) + } + +} diff --git a/tests/gotest/case002/case002.sh b/tests/gotest/case002/case002.sh new file mode 100644 index 0000000000000000000000000000000000000000..94e5bb44e03a1f7d2704752fcf9c080abcb4f23f --- /dev/null +++ b/tests/gotest/case002/case002.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +echo "==== start run cases001.go" + +set +e +#set -x + +script_dir="$(dirname $(readlink -f $0))" +#echo "pwd: $script_dir, para0: $0" + +#execName=$0 +#execName=`echo ${execName##*/}` +#goName=`echo ${execName%.*}` + +###### step 3: start build +cd $script_dir +rm -f go.* +go mod init demotest > /dev/null 2>&1 +go mod tidy > /dev/null 2>&1 +go build > /dev/null 2>&1 +sleep 1s +./demotest -h $1 -p $2 diff --git a/tests/http/restful/http_create_db.c b/tests/http/restful/http_create_db.c new file mode 100644 index 0000000000000000000000000000000000000000..0bc52fa6cc86eaa1105b26472291ab2fca4f9db4 --- /dev/null +++ b/tests/http/restful/http_create_db.c @@ -0,0 +1,429 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RECV_MAX_LINE 2048 +#define ITEM_MAX_LINE 128 +#define REQ_MAX_LINE 2048 +#define REQ_CLI_COUNT 100 + + +typedef enum +{ + uninited, + connecting, + connected, + datasent +} conn_stat; + + +typedef enum +{ + false, + true +} bool; + + +typedef unsigned short u16_t; +typedef unsigned int u32_t; + + +typedef struct +{ + int sockfd; + int index; + conn_stat state; + size_t nsent; + size_t nrecv; + size_t nlen; + bool error; + bool success; + struct sockaddr_in serv_addr; +} socket_ctx; + + +int set_nonblocking(int sockfd) +{ + int ret; + + ret = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); + if (ret == -1) { + printf("failed to fcntl for %d\r\n", sockfd); + return ret; + } + + return ret; +} + + +int create_socket(const char *ip, const u16_t port, socket_ctx *pctx) +{ + int ret; + + if (ip == NULL || port == 0 || pctx == NULL) { + printf("invalid parameter\r\n"); + return -1; + } + + pctx->sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (pctx->sockfd == -1) { + printf("failed to create socket\r\n"); + return -1; + } + + bzero(&pctx->serv_addr, sizeof(struct sockaddr_in)); + + pctx->serv_addr.sin_family = AF_INET; + pctx->serv_addr.sin_port = htons(port); + + ret = inet_pton(AF_INET, ip, &pctx->serv_addr.sin_addr); + if (ret <= 0) { + printf("inet_pton error, ip: %s\r\n", ip); + return -1; + } + + ret = set_nonblocking(pctx->sockfd); + if (ret == -1) { + printf("failed to set %d as nonblocking\r\n", pctx->sockfd); + return -1; + } + + return pctx->sockfd; +} + + +void close_sockets(socket_ctx *pctx, int cnt) +{ + int i; + + if (pctx == NULL) { + return; + } + + for (i = 0; i < cnt; i++) { + if (pctx[i].sockfd > 0) { + close(pctx[i].sockfd); + pctx[i].sockfd = -1; + } + } +} + + +int proc_pending_error(socket_ctx *ctx) +{ + int ret; + int err; + socklen_t len; + + if (ctx == NULL) { + return 0; + } + + err = 0; + len = sizeof(int); + + ret = getsockopt(ctx->sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &len); + if (ret == -1) { + err = errno; + } + + if (err) { + printf("failed to connect at index: %d\r\n", ctx->index); + + close(ctx->sockfd); + ctx->sockfd = -1; + + return -1; + } + + return 0; +} + + +void build_http_request(char *ip, u16_t port, char *url, char *sql, char *req_buf, int len) +{ + char req_line[ITEM_MAX_LINE]; + char req_host[ITEM_MAX_LINE]; + char req_cont_type[ITEM_MAX_LINE]; + char req_cont_len[ITEM_MAX_LINE]; + const char* req_auth = "Authorization: Basic cm9vdDp0YW9zZGF0YQ==\r\n"; + + if (ip == NULL || port == 0 || + url == NULL || url[0] == '\0' || + sql == NULL || sql[0] == '\0' || + req_buf == NULL || len <= 0) + { + return; + } + + snprintf(req_line, ITEM_MAX_LINE, "POST %s HTTP/1.1\r\n", url); + snprintf(req_host, ITEM_MAX_LINE, "HOST: %s:%d\r\n", ip, port); + snprintf(req_cont_type, ITEM_MAX_LINE, "%s\r\n", "Content-Type: text/plain"); + snprintf(req_cont_len, ITEM_MAX_LINE, "Content-Length: %ld\r\n\r\n", strlen(sql)); + + snprintf(req_buf, len, "%s%s%s%s%s%s", req_line, req_host, req_auth, req_cont_type, req_cont_len, sql); +} + + +int add_event(int epfd, int sockfd, u32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &evs_op); +} + + +int mod_event(int epfd, int sockfd, u32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &evs_op); +} + + +int del_event(int epfd, int sockfd) +{ + struct epoll_event evs_op; + + evs_op.events = 0; + evs_op.data.ptr = NULL; + + return epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, &evs_op); +} + + +int main() +{ + int i; + int ret, n, nsent, nrecv; + int epfd; + u32_t events; + char *str; + socket_ctx *pctx, ctx[REQ_CLI_COUNT]; + char *ip = "127.0.0.1"; + char *url = "/rest/sql"; + u16_t port = 6041; + struct epoll_event evs[REQ_CLI_COUNT]; + char sql[REQ_MAX_LINE]; + char send_buf[REQ_CLI_COUNT][REQ_MAX_LINE + 5 * ITEM_MAX_LINE]; + char recv_buf[REQ_CLI_COUNT][RECV_MAX_LINE]; + int count; + + signal(SIGPIPE, SIG_IGN); + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ctx[i].sockfd = -1; + ctx[i].index = i; + ctx[i].state = uninited; + ctx[i].nsent = 0; + ctx[i].nrecv = 0; + ctx[i].error = false; + ctx[i].success = false; + + memset(sql, 0, REQ_MAX_LINE); + memset(send_buf[i], 0, REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + memset(recv_buf[i], 0, RECV_MAX_LINE); + + snprintf(sql, REQ_MAX_LINE, "create database if not exists db%d precision 'us'", i); + build_http_request(ip, port, url, sql, send_buf[i], REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + + ctx[i].nlen = strlen(send_buf[i]); + } + + epfd = epoll_create(REQ_CLI_COUNT); + if (epfd <= 0) { + printf("failed to create epoll\r\n"); + goto failed; + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = create_socket(ip, port, &ctx[i]); + if (ret == -1) { + printf("failed to create socket ar %d\r\n", i); + goto failed; + } + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + events = EPOLLET | EPOLLIN | EPOLLOUT; + ret = add_event(epfd, ctx[i].sockfd, events, (void *) &ctx[i]); + if (ret == -1) { + printf("failed to add sockfd at %d to epoll\r\n", i); + goto failed; + } + } + + count = 0; + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = connect(ctx[i].sockfd, (struct sockaddr *) &ctx[i].serv_addr, sizeof(ctx[i].serv_addr)); + if (ret == -1) { + if (errno != EINPROGRESS) { + printf("connect error, index: %d\r\n", ctx[i].index); + (void) del_event(epfd, ctx[i].sockfd); + close(ctx[i].sockfd); + ctx[i].sockfd = -1; + } else { + ctx[i].state = connecting; + count++; + } + + continue; + } + + ctx[i].state = connected; + count++; + } + + printf("clients: %d\r\n", count); + + while (count > 0) { + n = epoll_wait(epfd, evs, REQ_CLI_COUNT, 0); + if (n == -1) { + if (errno != EINTR) { + printf("epoll_wait error, reason: %s\r\n", strerror(errno)); + break; + } + } else { + for (i = 0; i < n; i++) { + if (evs[i].events & EPOLLERR) { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("event error, index: %d\r\n", pctx->index); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } else if (evs[i].events & EPOLLIN) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nrecv = recv(pctx->sockfd, recv_buf[pctx->index] + pctx->nrecv, RECV_MAX_LINE, 0); + if (nrecv == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to recv, index: %d, reason: %s\r\n", pctx->index, strerror(errno)); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } else if (nrecv == 0) { + printf("peer closed connection, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + break; + } + + pctx->nrecv += nrecv; + if (pctx->nrecv > 12) { + if (pctx->error == false && pctx->success == false) { + str = recv_buf[pctx->index] + 9; + if (str[0] != '2' || str[1] != '0' || str[2] != '0') { + printf("response error, index: %d, recv: %s\r\n", pctx->index, recv_buf[pctx->index]); + pctx->error = true; + } else { + printf("response ok, index: %d\r\n", pctx->index); + pctx->success = true; + } + } + } + } + } else if (evs[i].events & EPOLLOUT) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nsent = send(pctx->sockfd, send_buf[pctx->index] + pctx->nsent, pctx->nlen - pctx->nsent, 0); + if (nsent == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to send, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } + + if (nsent == (int) (pctx->nlen - pctx->nsent)) { + printf("request done, request: %s, index: %d\r\n", send_buf[pctx->index], pctx->index); + + pctx->state = datasent; + + events = EPOLLET | EPOLLIN; + (void) mod_event(epfd, pctx->sockfd, events, (void *)pctx); + + break; + } else { + pctx->nsent += nsent; + } + } + } else { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("unknown event(%u), index: %d\r\n", evs[i].events, pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + } + } + } + +failed: + + if (epfd > 0) { + close(epfd); + } + + close_sockets(ctx, REQ_CLI_COUNT); + + return 0; +} diff --git a/tests/http/restful/http_create_tb.c b/tests/http/restful/http_create_tb.c new file mode 100644 index 0000000000000000000000000000000000000000..91ffc54627724208c6ca5623fbe4df95829530c7 --- /dev/null +++ b/tests/http/restful/http_create_tb.c @@ -0,0 +1,433 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RECV_MAX_LINE 2048 +#define ITEM_MAX_LINE 128 +#define REQ_MAX_LINE 2048 +#define REQ_CLI_COUNT 100 + + +typedef enum +{ + uninited, + connecting, + connected, + datasent +} conn_stat; + + +typedef enum +{ + false, + true +} bool; + + +typedef unsigned short u16_t; +typedef unsigned int u32_t; + + +typedef struct +{ + int sockfd; + int index; + conn_stat state; + size_t nsent; + size_t nrecv; + size_t nlen; + bool error; + bool success; + struct sockaddr_in serv_addr; +} socket_ctx; + + +int set_nonblocking(int sockfd) +{ + int ret; + + ret = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); + if (ret == -1) { + printf("failed to fcntl for %d\r\n", sockfd); + return ret; + } + + return ret; +} + + +int create_socket(const char *ip, const u16_t port, socket_ctx *pctx) +{ + int ret; + + if (ip == NULL || port == 0 || pctx == NULL) { + printf("invalid parameter\r\n"); + return -1; + } + + pctx->sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (pctx->sockfd == -1) { + printf("failed to create socket\r\n"); + return -1; + } + + bzero(&pctx->serv_addr, sizeof(struct sockaddr_in)); + + pctx->serv_addr.sin_family = AF_INET; + pctx->serv_addr.sin_port = htons(port); + + ret = inet_pton(AF_INET, ip, &pctx->serv_addr.sin_addr); + if (ret <= 0) { + printf("inet_pton error, ip: %s\r\n", ip); + return -1; + } + + ret = set_nonblocking(pctx->sockfd); + if (ret == -1) { + printf("failed to set %d as nonblocking\r\n", pctx->sockfd); + return -1; + } + + return pctx->sockfd; +} + + +void close_sockets(socket_ctx *pctx, int cnt) +{ + int i; + + if (pctx == NULL) { + return; + } + + for (i = 0; i < cnt; i++) { + if (pctx[i].sockfd > 0) { + close(pctx[i].sockfd); + pctx[i].sockfd = -1; + } + } +} + + +int proc_pending_error(socket_ctx *ctx) +{ + int ret; + int err; + socklen_t len; + + if (ctx == NULL) { + return 0; + } + + err = 0; + len = sizeof(int); + + ret = getsockopt(ctx->sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &len); + if (ret == -1) { + err = errno; + } + + if (err) { + printf("failed to connect at index: %d\r\n", ctx->index); + + close(ctx->sockfd); + ctx->sockfd = -1; + + return -1; + } + + return 0; +} + + +void build_http_request(char *ip, u16_t port, char *url, char *sql, char *req_buf, int len) +{ + char req_line[ITEM_MAX_LINE]; + char req_host[ITEM_MAX_LINE]; + char req_cont_type[ITEM_MAX_LINE]; + char req_cont_len[ITEM_MAX_LINE]; + const char* req_auth = "Authorization: Basic cm9vdDp0YW9zZGF0YQ==\r\n"; + + if (ip == NULL || port == 0 || + url == NULL || url[0] == '\0' || + sql == NULL || sql[0] == '\0' || + req_buf == NULL || len <= 0) + { + return; + } + + snprintf(req_line, ITEM_MAX_LINE, "POST %s HTTP/1.1\r\n", url); + snprintf(req_host, ITEM_MAX_LINE, "HOST: %s:%d\r\n", ip, port); + snprintf(req_cont_type, ITEM_MAX_LINE, "%s\r\n", "Content-Type: text/plain"); + snprintf(req_cont_len, ITEM_MAX_LINE, "Content-Length: %ld\r\n\r\n", strlen(sql)); + + snprintf(req_buf, len, "%s%s%s%s%s%s", req_line, req_host, req_auth, req_cont_type, req_cont_len, sql); +} + + +int add_event(int epfd, int sockfd, u32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &evs_op); +} + + +int mod_event(int epfd, int sockfd, u32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &evs_op); +} + + +int del_event(int epfd, int sockfd) +{ + struct epoll_event evs_op; + + evs_op.events = 0; + evs_op.data.ptr = NULL; + + return epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, &evs_op); +} + + +int main() +{ + int i; + int ret, n, nsent, nrecv; + int epfd; + u32_t events; + char *str; + socket_ctx *pctx, ctx[REQ_CLI_COUNT]; + char *ip = "127.0.0.1"; + char *url_prefix = "/rest/sql"; + char url[ITEM_MAX_LINE]; + u16_t port = 6041; + struct epoll_event evs[REQ_CLI_COUNT]; + char sql[REQ_MAX_LINE]; + char send_buf[REQ_CLI_COUNT][REQ_MAX_LINE + 5 * ITEM_MAX_LINE]; + char recv_buf[REQ_CLI_COUNT][RECV_MAX_LINE]; + int count; + + signal(SIGPIPE, SIG_IGN); + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ctx[i].sockfd = -1; + ctx[i].index = i; + ctx[i].state = uninited; + ctx[i].nsent = 0; + ctx[i].nrecv = 0; + ctx[i].error = false; + ctx[i].success = false; + + memset(url, 0, ITEM_MAX_LINE); + memset(sql, 0, REQ_MAX_LINE); + memset(send_buf[i], 0, REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + memset(recv_buf[i], 0, RECV_MAX_LINE); + + snprintf(url, ITEM_MAX_LINE, "%s/db%d", url_prefix, i); + snprintf(sql, REQ_MAX_LINE, "create table if not exists tb%d (ts timestamp, index int, val binary(40))", i); + + build_http_request(ip, port, url, sql, send_buf[i], REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + + ctx[i].nlen = strlen(send_buf[i]); + } + + epfd = epoll_create(REQ_CLI_COUNT); + if (epfd <= 0) { + printf("failed to create epoll\r\n"); + goto failed; + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = create_socket(ip, port, &ctx[i]); + if (ret == -1) { + printf("failed to create socket, index: %d\r\n", i); + goto failed; + } + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + events = EPOLLET | EPOLLIN | EPOLLOUT; + ret = add_event(epfd, ctx[i].sockfd, events, (void *) &ctx[i]); + if (ret == -1) { + printf("failed to add sockfd to epoll, index: %d\r\n", i); + goto failed; + } + } + + count = 0; + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = connect(ctx[i].sockfd, (struct sockaddr *) &ctx[i].serv_addr, sizeof(ctx[i].serv_addr)); + if (ret == -1) { + if (errno != EINPROGRESS) { + printf("connect error, index: %d\r\n", ctx[i].index); + (void) del_event(epfd, ctx[i].sockfd); + close(ctx[i].sockfd); + ctx[i].sockfd = -1; + } else { + ctx[i].state = connecting; + count++; + } + + continue; + } + + ctx[i].state = connected; + count++; + } + + printf("clients: %d\r\n", count); + + while (count > 0) { + n = epoll_wait(epfd, evs, REQ_CLI_COUNT, 0); + if (n == -1) { + if (errno != EINTR) { + printf("epoll_wait error, reason: %s\r\n", strerror(errno)); + break; + } + } else { + for (i = 0; i < n; i++) { + if (evs[i].events & EPOLLERR) { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("event error, index: %d\r\n", pctx->index); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } else if (evs[i].events & EPOLLIN) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nrecv = recv(pctx->sockfd, recv_buf[pctx->index] + pctx->nrecv, RECV_MAX_LINE, 0); + if (nrecv == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to recv, index: %d, reason: %s\r\n", pctx->index, strerror(errno)); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } else if (nrecv == 0) { + printf("peer closed connection, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + break; + } + + pctx->nrecv += nrecv; + if (pctx->nrecv > 12) { + if (pctx->error == false && pctx->success == false) { + str = recv_buf[pctx->index] + 9; + if (str[0] != '2' || str[1] != '0' || str[2] != '0') { + printf("response error, index: %d, recv: %s\r\n", pctx->index, recv_buf[pctx->index]); + pctx->error = true; + } else { + printf("response ok, index: %d\r\n", pctx->index); + pctx->success = true; + } + } + } + } + } else if (evs[i].events & EPOLLOUT) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nsent = send(pctx->sockfd, send_buf[pctx->index] + pctx->nsent, pctx->nlen - pctx->nsent, 0); + if (nsent == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to send, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } + + if (nsent == (int) (pctx->nlen - pctx->nsent)) { + printf("request done, request: %s, index: %d\r\n", send_buf[pctx->index], pctx->index); + + pctx->state = datasent; + + events = EPOLLET | EPOLLIN; + (void) mod_event(epfd, pctx->sockfd, events, (void *)pctx); + + break; + } else { + pctx->nsent += nsent; + } + } + } else { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("unknown event(%u), index: %d\r\n", evs[i].events, pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + } + } + } + +failed: + + if (epfd > 0) { + close(epfd); + } + + close_sockets(ctx, REQ_CLI_COUNT); + + return 0; +} diff --git a/tests/http/restful/http_drop_db.c b/tests/http/restful/http_drop_db.c new file mode 100644 index 0000000000000000000000000000000000000000..f82db901dd38becafbc6eba51b8407e4b4488693 --- /dev/null +++ b/tests/http/restful/http_drop_db.c @@ -0,0 +1,433 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RECV_MAX_LINE 2048 +#define ITEM_MAX_LINE 128 +#define REQ_MAX_LINE 2048 +#define REQ_CLI_COUNT 100 + + +typedef enum +{ + uninited, + connecting, + connected, + datasent +} conn_stat; + + +typedef enum +{ + false, + true +} bool; + + +typedef unsigned short u16_t; +typedef unsigned int u32_t; + + +typedef struct +{ + int sockfd; + int index; + conn_stat state; + size_t nsent; + size_t nrecv; + size_t nlen; + bool error; + bool success; + struct sockaddr_in serv_addr; +} socket_ctx; + + +int set_nonblocking(int sockfd) +{ + int ret; + + ret = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); + if (ret == -1) { + printf("failed to fcntl for %d\r\n", sockfd); + return ret; + } + + return ret; +} + + +int create_socket(const char *ip, const u16_t port, socket_ctx *pctx) +{ + int ret; + + if (ip == NULL || port == 0 || pctx == NULL) { + printf("invalid parameter\r\n"); + return -1; + } + + pctx->sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (pctx->sockfd == -1) { + printf("failed to create socket\r\n"); + return -1; + } + + bzero(&pctx->serv_addr, sizeof(struct sockaddr_in)); + + pctx->serv_addr.sin_family = AF_INET; + pctx->serv_addr.sin_port = htons(port); + + ret = inet_pton(AF_INET, ip, &pctx->serv_addr.sin_addr); + if (ret <= 0) { + printf("inet_pton error, ip: %s\r\n", ip); + return -1; + } + + ret = set_nonblocking(pctx->sockfd); + if (ret == -1) { + printf("failed to set %d as nonblocking\r\n", pctx->sockfd); + return -1; + } + + return pctx->sockfd; +} + + +void close_sockets(socket_ctx *pctx, int cnt) +{ + int i; + + if (pctx == NULL) { + return; + } + + for (i = 0; i < cnt; i++) { + if (pctx[i].sockfd > 0) { + close(pctx[i].sockfd); + pctx[i].sockfd = -1; + } + } +} + + +int proc_pending_error(socket_ctx *ctx) +{ + int ret; + int err; + socklen_t len; + + if (ctx == NULL) { + return 0; + } + + err = 0; + len = sizeof(int); + + ret = getsockopt(ctx->sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &len); + if (ret == -1) { + err = errno; + } + + if (err) { + printf("failed to connect at index: %d\r\n", ctx->index); + + close(ctx->sockfd); + ctx->sockfd = -1; + + return -1; + } + + return 0; +} + + +void build_http_request(char *ip, u16_t port, char *url, char *sql, char *req_buf, int len) +{ + char req_line[ITEM_MAX_LINE]; + char req_host[ITEM_MAX_LINE]; + char req_cont_type[ITEM_MAX_LINE]; + char req_cont_len[ITEM_MAX_LINE]; + const char* req_auth = "Authorization: Basic cm9vdDp0YW9zZGF0YQ==\r\n"; + + if (ip == NULL || port == 0 || + url == NULL || url[0] == '\0' || + sql == NULL || sql[0] == '\0' || + req_buf == NULL || len <= 0) + { + return; + } + + snprintf(req_line, ITEM_MAX_LINE, "POST %s HTTP/1.1\r\n", url); + snprintf(req_host, ITEM_MAX_LINE, "HOST: %s:%d\r\n", ip, port); + snprintf(req_cont_type, ITEM_MAX_LINE, "%s\r\n", "Content-Type: text/plain"); + snprintf(req_cont_len, ITEM_MAX_LINE, "Content-Length: %ld\r\n\r\n", strlen(sql)); + + snprintf(req_buf, len, "%s%s%s%s%s%s", req_line, req_host, req_auth, req_cont_type, req_cont_len, sql); +} + + +int add_event(int epfd, int sockfd, u32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &evs_op); +} + + +int mod_event(int epfd, int sockfd, u32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &evs_op); +} + + +int del_event(int epfd, int sockfd) +{ + struct epoll_event evs_op; + + evs_op.events = 0; + evs_op.data.ptr = NULL; + + return epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, &evs_op); +} + + +int main() +{ + int i; + int ret, n, nsent, nrecv; + int epfd; + u32_t events; + char *str; + socket_ctx *pctx, ctx[REQ_CLI_COUNT]; + char *ip = "127.0.0.1"; + char *url_prefix = "/rest/sql"; + char url[ITEM_MAX_LINE]; + u16_t port = 6041; + struct epoll_event evs[REQ_CLI_COUNT]; + char sql[REQ_MAX_LINE]; + char send_buf[REQ_CLI_COUNT][REQ_MAX_LINE + 5 * ITEM_MAX_LINE]; + char recv_buf[REQ_CLI_COUNT][RECV_MAX_LINE]; + int count; + + signal(SIGPIPE, SIG_IGN); + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ctx[i].sockfd = -1; + ctx[i].index = i; + ctx[i].state = uninited; + ctx[i].nsent = 0; + ctx[i].nrecv = 0; + ctx[i].error = false; + ctx[i].success = false; + + memset(url, 0, ITEM_MAX_LINE); + memset(sql, 0, REQ_MAX_LINE); + memset(send_buf[i], 0, REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + memset(recv_buf[i], 0, RECV_MAX_LINE); + + snprintf(url, ITEM_MAX_LINE, "%s/db%d", url_prefix, i); + snprintf(sql, REQ_MAX_LINE, "drop database if exists db%d", i); + + build_http_request(ip, port, url, sql, send_buf[i], REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + + ctx[i].nlen = strlen(send_buf[i]); + } + + epfd = epoll_create(REQ_CLI_COUNT); + if (epfd <= 0) { + printf("failed to create epoll\r\n"); + goto failed; + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = create_socket(ip, port, &ctx[i]); + if (ret == -1) { + printf("failed to create socket, index: %d\r\n", i); + goto failed; + } + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + events = EPOLLET | EPOLLIN | EPOLLOUT; + ret = add_event(epfd, ctx[i].sockfd, events, (void *) &ctx[i]); + if (ret == -1) { + printf("failed to add sockfd to epoll, index: %d\r\n", i); + goto failed; + } + } + + count = 0; + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = connect(ctx[i].sockfd, (struct sockaddr *) &ctx[i].serv_addr, sizeof(ctx[i].serv_addr)); + if (ret == -1) { + if (errno != EINPROGRESS) { + printf("connect error, index: %d\r\n", ctx[i].index); + (void) del_event(epfd, ctx[i].sockfd); + close(ctx[i].sockfd); + ctx[i].sockfd = -1; + } else { + ctx[i].state = connecting; + count++; + } + + continue; + } + + ctx[i].state = connected; + count++; + } + + printf("clients: %d\r\n", count); + + while (count > 0) { + n = epoll_wait(epfd, evs, REQ_CLI_COUNT, 0); + if (n == -1) { + if (errno != EINTR) { + printf("epoll_wait error, reason: %s\r\n", strerror(errno)); + break; + } + } else { + for (i = 0; i < n; i++) { + if (evs[i].events & EPOLLERR) { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("event error, index: %d\r\n", pctx->index); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } else if (evs[i].events & EPOLLIN) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nrecv = recv(pctx->sockfd, recv_buf[pctx->index] + pctx->nrecv, RECV_MAX_LINE, 0); + if (nrecv == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to recv, index: %d, reason: %s\r\n", pctx->index, strerror(errno)); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } else if (nrecv == 0) { + printf("peer closed connection, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + break; + } + + pctx->nrecv += nrecv; + if (pctx->nrecv > 12) { + if (pctx->error == false && pctx->success == false) { + str = recv_buf[pctx->index] + 9; + if (str[0] != '2' || str[1] != '0' || str[2] != '0') { + printf("response error, index: %d, recv: %s\r\n", pctx->index, recv_buf[pctx->index]); + pctx->error = true; + } else { + printf("response ok, index: %d\r\n", pctx->index); + pctx->success = true; + } + } + } + } + } else if (evs[i].events & EPOLLOUT) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nsent = send(pctx->sockfd, send_buf[pctx->index] + pctx->nsent, pctx->nlen - pctx->nsent, 0); + if (nsent == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to send, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } + + if (nsent == (int) (pctx->nlen - pctx->nsent)) { + printf("request done, request: %s, index: %d\r\n", send_buf[pctx->index], pctx->index); + + pctx->state = datasent; + + events = EPOLLET | EPOLLIN; + (void) mod_event(epfd, pctx->sockfd, events, (void *)pctx); + + break; + } else { + pctx->nsent += nsent; + } + } + } else { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("unknown event(%u), index: %d\r\n", evs[i].events, pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + } + } + } + +failed: + + if (epfd > 0) { + close(epfd); + } + + close_sockets(ctx, REQ_CLI_COUNT); + + return 0; +} diff --git a/tests/http/restful/http_insert_tb.c b/tests/http/restful/http_insert_tb.c new file mode 100644 index 0000000000000000000000000000000000000000..f9590d856cc6275d7df250fee920c1b2080f0499 --- /dev/null +++ b/tests/http/restful/http_insert_tb.c @@ -0,0 +1,455 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RECV_MAX_LINE 2048 +#define ITEM_MAX_LINE 128 +#define REQ_MAX_LINE 4096 +#define REQ_CLI_COUNT 100 + + +typedef enum +{ + uninited, + connecting, + connected, + datasent +} conn_stat; + + +typedef enum +{ + false, + true +} bool; + + +typedef struct +{ + int sockfd; + int index; + conn_stat state; + size_t nsent; + size_t nrecv; + size_t nlen; + bool error; + bool success; + struct sockaddr_in serv_addr; +} socket_ctx; + + +int set_nonblocking(int sockfd) +{ + int ret; + + ret = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); + if (ret == -1) { + printf("failed to fcntl for %d\r\n", sockfd); + return ret; + } + + return ret; +} + + +int create_socket(const char *ip, const uint16_t port, socket_ctx *pctx) +{ + int ret; + + if (ip == NULL || port == 0 || pctx == NULL) { + printf("invalid parameter\r\n"); + return -1; + } + + pctx->sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (pctx->sockfd == -1) { + printf("failed to create socket\r\n"); + return -1; + } + + bzero(&pctx->serv_addr, sizeof(struct sockaddr_in)); + + pctx->serv_addr.sin_family = AF_INET; + pctx->serv_addr.sin_port = htons(port); + + ret = inet_pton(AF_INET, ip, &pctx->serv_addr.sin_addr); + if (ret <= 0) { + printf("inet_pton error, ip: %s\r\n", ip); + return -1; + } + + ret = set_nonblocking(pctx->sockfd); + if (ret == -1) { + printf("failed to set %d as nonblocking\r\n", pctx->sockfd); + return -1; + } + + return pctx->sockfd; +} + + +void close_sockets(socket_ctx *pctx, int cnt) +{ + int i; + + if (pctx == NULL) { + return; + } + + for (i = 0; i < cnt; i++) { + if (pctx[i].sockfd > 0) { + close(pctx[i].sockfd); + pctx[i].sockfd = -1; + } + } +} + + +int proc_pending_error(socket_ctx *ctx) +{ + int ret; + int err; + socklen_t len; + + if (ctx == NULL) { + return 0; + } + + err = 0; + len = sizeof(int); + + ret = getsockopt(ctx->sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &len); + if (ret == -1) { + err = errno; + } + + if (err) { + printf("failed to connect at index: %d\r\n", ctx->index); + + close(ctx->sockfd); + ctx->sockfd = -1; + + return -1; + } + + return 0; +} + + +void build_http_request(char *ip, uint16_t port, char *url, char *sql, char *req_buf, int len) +{ + char req_line[ITEM_MAX_LINE]; + char req_host[ITEM_MAX_LINE]; + char req_cont_type[ITEM_MAX_LINE]; + char req_cont_len[ITEM_MAX_LINE]; + const char* req_auth = "Authorization: Basic cm9vdDp0YW9zZGF0YQ==\r\n"; + + if (ip == NULL || port == 0 || + url == NULL || url[0] == '\0' || + sql == NULL || sql[0] == '\0' || + req_buf == NULL || len <= 0) + { + return; + } + + snprintf(req_line, ITEM_MAX_LINE, "POST %s HTTP/1.1\r\n", url); + snprintf(req_host, ITEM_MAX_LINE, "HOST: %s:%d\r\n", ip, port); + snprintf(req_cont_type, ITEM_MAX_LINE, "%s\r\n", "Content-Type: text/plain"); + snprintf(req_cont_len, ITEM_MAX_LINE, "Content-Length: %ld\r\n\r\n", strlen(sql)); + + snprintf(req_buf, len, "%s%s%s%s%s%s", req_line, req_host, req_auth, req_cont_type, req_cont_len, sql); +} + + +int add_event(int epfd, int sockfd, uint32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &evs_op); +} + + +int mod_event(int epfd, int sockfd, uint32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &evs_op); +} + + +int del_event(int epfd, int sockfd) +{ + struct epoll_event evs_op; + + evs_op.events = 0; + evs_op.data.ptr = NULL; + + return epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, &evs_op); +} + + +int main() +{ + int i; + int ret, n, nsent, nrecv, offset; + int epfd; + uint32_t events; + char *str; + socket_ctx *pctx, ctx[REQ_CLI_COUNT]; + char *ip = "127.0.0.1"; + char *url_prefix = "/rest/sql"; + char url[ITEM_MAX_LINE]; + uint16_t port = 6041; + struct epoll_event evs[REQ_CLI_COUNT]; + struct timeval now; + int64_t start_time; + char sql[REQ_MAX_LINE]; + char send_buf[REQ_CLI_COUNT][REQ_MAX_LINE + 5 * ITEM_MAX_LINE]; + char recv_buf[REQ_CLI_COUNT][RECV_MAX_LINE]; + int count; + + signal(SIGPIPE, SIG_IGN); + + gettimeofday(&now, NULL); + start_time = now.tv_sec * 1000000 + now.tv_usec; + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ctx[i].sockfd = -1; + ctx[i].index = i; + ctx[i].state = uninited; + ctx[i].nsent = 0; + ctx[i].nrecv = 0; + ctx[i].error = false; + ctx[i].success = false; + + memset(url, 0, ITEM_MAX_LINE); + memset(sql, 0, REQ_MAX_LINE); + memset(send_buf[i], 0, REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + memset(recv_buf[i], 0, RECV_MAX_LINE); + + snprintf(url, ITEM_MAX_LINE, "%s/db%d", url_prefix, i); + + offset = 0; + + ret = snprintf(sql + offset, REQ_MAX_LINE - offset, "insert into tb%d values ", i); + if (ret <= 0) { + printf("failed to snprintf for sql(prefix), index: %d\r\n ", i); + goto failed; + } + + offset += ret; + + while (offset < REQ_MAX_LINE - 128) { + ret = snprintf(sql + offset, REQ_MAX_LINE - offset, "(%"PRId64", %d, 'test_string_%d') ", start_time + i, i, i); + if (ret <= 0) { + printf("failed to snprintf for sql(values), index: %d\r\n ", i); + goto failed; + } + + offset += ret; + } + + build_http_request(ip, port, url, sql, send_buf[i], REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + + ctx[i].nlen = strlen(send_buf[i]); + } + + epfd = epoll_create(REQ_CLI_COUNT); + if (epfd <= 0) { + printf("failed to create epoll\r\n"); + goto failed; + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = create_socket(ip, port, &ctx[i]); + if (ret == -1) { + printf("failed to create socket, index: %d\r\n", i); + goto failed; + } + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + events = EPOLLET | EPOLLIN | EPOLLOUT; + ret = add_event(epfd, ctx[i].sockfd, events, (void *) &ctx[i]); + if (ret == -1) { + printf("failed to add sockfd to epoll, index: %d\r\n", i); + goto failed; + } + } + + count = 0; + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = connect(ctx[i].sockfd, (struct sockaddr *) &ctx[i].serv_addr, sizeof(ctx[i].serv_addr)); + if (ret == -1) { + if (errno != EINPROGRESS) { + printf("connect error, index: %d\r\n", ctx[i].index); + (void) del_event(epfd, ctx[i].sockfd); + close(ctx[i].sockfd); + ctx[i].sockfd = -1; + } else { + ctx[i].state = connecting; + count++; + } + + continue; + } + + ctx[i].state = connected; + count++; + } + + printf("clients: %d\r\n", count); + + while (count > 0) { + n = epoll_wait(epfd, evs, REQ_CLI_COUNT, 0); + if (n == -1) { + if (errno != EINTR) { + printf("epoll_wait error, reason: %s\r\n", strerror(errno)); + break; + } + } else { + for (i = 0; i < n; i++) { + if (evs[i].events & EPOLLERR) { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("event error, index: %d\r\n", pctx->index); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } else if (evs[i].events & EPOLLIN) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nrecv = recv(pctx->sockfd, recv_buf[pctx->index] + pctx->nrecv, RECV_MAX_LINE, 0); + if (nrecv == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to recv, index: %d, reason: %s\r\n", pctx->index, strerror(errno)); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } else if (nrecv == 0) { + printf("peer closed connection, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + break; + } + + pctx->nrecv += nrecv; + if (pctx->nrecv > 12) { + if (pctx->error == false && pctx->success == false) { + str = recv_buf[pctx->index] + 9; + if (str[0] != '2' || str[1] != '0' || str[2] != '0') { + printf("response error, index: %d, recv: %s\r\n", pctx->index, recv_buf[pctx->index]); + pctx->error = true; + } else { + printf("response ok, index: %d\r\n", pctx->index); + pctx->success = true; + } + } + } + } + } else if (evs[i].events & EPOLLOUT) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nsent = send(pctx->sockfd, send_buf[pctx->index] + pctx->nsent, pctx->nlen - pctx->nsent, 0); + if (nsent == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to send, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } + + if (nsent == (int) (pctx->nlen - pctx->nsent)) { + printf("request done, request: %s, index: %d\r\n", send_buf[pctx->index], pctx->index); + + pctx->state = datasent; + + events = EPOLLET | EPOLLIN; + (void) mod_event(epfd, pctx->sockfd, events, (void *)pctx); + + break; + } else { + pctx->nsent += nsent; + } + } + } else { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("unknown event(%u), index: %d\r\n", evs[i].events, pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + } + } + } + +failed: + + if (epfd > 0) { + close(epfd); + } + + close_sockets(ctx, REQ_CLI_COUNT); + + return 0; +} diff --git a/tests/http/restful/http_query_tb.c b/tests/http/restful/http_query_tb.c new file mode 100644 index 0000000000000000000000000000000000000000..e7ac0d4b01cdeb4b6d3b29fa2741667914fb2e74 --- /dev/null +++ b/tests/http/restful/http_query_tb.c @@ -0,0 +1,432 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RECV_MAX_LINE 2048 +#define ITEM_MAX_LINE 128 +#define REQ_MAX_LINE 4096 +#define REQ_CLI_COUNT 100 + + +typedef enum +{ + uninited, + connecting, + connected, + datasent +} conn_stat; + + +typedef enum +{ + false, + true +} bool; + + +typedef struct +{ + int sockfd; + int index; + conn_stat state; + size_t nsent; + size_t nrecv; + size_t nlen; + bool error; + bool success; + struct sockaddr_in serv_addr; +} socket_ctx; + + +int set_nonblocking(int sockfd) +{ + int ret; + + ret = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); + if (ret == -1) { + printf("failed to fcntl for %d\r\n", sockfd); + return ret; + } + + return ret; +} + + +int create_socket(const char *ip, const uint16_t port, socket_ctx *pctx) +{ + int ret; + + if (ip == NULL || port == 0 || pctx == NULL) { + printf("invalid parameter\r\n"); + return -1; + } + + pctx->sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (pctx->sockfd == -1) { + printf("failed to create socket\r\n"); + return -1; + } + + bzero(&pctx->serv_addr, sizeof(struct sockaddr_in)); + + pctx->serv_addr.sin_family = AF_INET; + pctx->serv_addr.sin_port = htons(port); + + ret = inet_pton(AF_INET, ip, &pctx->serv_addr.sin_addr); + if (ret <= 0) { + printf("inet_pton error, ip: %s\r\n", ip); + return -1; + } + + ret = set_nonblocking(pctx->sockfd); + if (ret == -1) { + printf("failed to set %d as nonblocking\r\n", pctx->sockfd); + return -1; + } + + return pctx->sockfd; +} + + +void close_sockets(socket_ctx *pctx, int cnt) +{ + int i; + + if (pctx == NULL) { + return; + } + + for (i = 0; i < cnt; i++) { + if (pctx[i].sockfd > 0) { + close(pctx[i].sockfd); + pctx[i].sockfd = -1; + } + } +} + + +int proc_pending_error(socket_ctx *ctx) +{ + int ret; + int err; + socklen_t len; + + if (ctx == NULL) { + return 0; + } + + err = 0; + len = sizeof(int); + + ret = getsockopt(ctx->sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &len); + if (ret == -1) { + err = errno; + } + + if (err) { + printf("failed to connect at index: %d\r\n", ctx->index); + + close(ctx->sockfd); + ctx->sockfd = -1; + + return -1; + } + + return 0; +} + + +void build_http_request(char *ip, uint16_t port, char *url, char *sql, char *req_buf, int len) +{ + char req_line[ITEM_MAX_LINE]; + char req_host[ITEM_MAX_LINE]; + char req_cont_type[ITEM_MAX_LINE]; + char req_cont_len[ITEM_MAX_LINE]; + const char* req_auth = "Authorization: Basic cm9vdDp0YW9zZGF0YQ==\r\n"; + + if (ip == NULL || port == 0 || + url == NULL || url[0] == '\0' || + sql == NULL || sql[0] == '\0' || + req_buf == NULL || len <= 0) + { + return; + } + + snprintf(req_line, ITEM_MAX_LINE, "POST %s HTTP/1.1\r\n", url); + snprintf(req_host, ITEM_MAX_LINE, "HOST: %s:%d\r\n", ip, port); + snprintf(req_cont_type, ITEM_MAX_LINE, "%s\r\n", "Content-Type: text/plain"); + snprintf(req_cont_len, ITEM_MAX_LINE, "Content-Length: %ld\r\n\r\n", strlen(sql)); + + snprintf(req_buf, len, "%s%s%s%s%s%s", req_line, req_host, req_auth, req_cont_type, req_cont_len, sql); +} + + +int add_event(int epfd, int sockfd, uint32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &evs_op); +} + + +int mod_event(int epfd, int sockfd, uint32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &evs_op); +} + + +int del_event(int epfd, int sockfd) +{ + struct epoll_event evs_op; + + evs_op.events = 0; + evs_op.data.ptr = NULL; + + return epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, &evs_op); +} + + +int main() +{ + int i; + int ret, n, nsent, nrecv; + int epfd; + uint32_t events; + char *str; + socket_ctx *pctx, ctx[REQ_CLI_COUNT]; + char *ip = "127.0.0.1"; + char *url_prefix = "/rest/sql"; + char url[ITEM_MAX_LINE]; + uint16_t port = 6041; + struct epoll_event evs[REQ_CLI_COUNT]; + char sql[REQ_MAX_LINE]; + char send_buf[REQ_CLI_COUNT][REQ_MAX_LINE + 5 * ITEM_MAX_LINE]; + char recv_buf[REQ_CLI_COUNT][RECV_MAX_LINE]; + int count; + + signal(SIGPIPE, SIG_IGN); + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ctx[i].sockfd = -1; + ctx[i].index = i; + ctx[i].state = uninited; + ctx[i].nsent = 0; + ctx[i].nrecv = 0; + ctx[i].error = false; + ctx[i].success = false; + + memset(url, 0, ITEM_MAX_LINE); + memset(sql, 0, REQ_MAX_LINE); + memset(send_buf[i], 0, REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + memset(recv_buf[i], 0, RECV_MAX_LINE); + + snprintf(url, ITEM_MAX_LINE, "%s/db%d", url_prefix, i); + + snprintf(sql, REQ_MAX_LINE, "select count(*) from tb%d", i); + + build_http_request(ip, port, url, sql, send_buf[i], REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + + ctx[i].nlen = strlen(send_buf[i]); + } + + epfd = epoll_create(REQ_CLI_COUNT); + if (epfd <= 0) { + printf("failed to create epoll\r\n"); + goto failed; + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = create_socket(ip, port, &ctx[i]); + if (ret == -1) { + printf("failed to create socket, index: %d\r\n", i); + goto failed; + } + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + events = EPOLLET | EPOLLIN | EPOLLOUT; + ret = add_event(epfd, ctx[i].sockfd, events, (void *) &ctx[i]); + if (ret == -1) { + printf("failed to add sockfd to epoll, index: %d\r\n", i); + goto failed; + } + } + + count = 0; + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = connect(ctx[i].sockfd, (struct sockaddr *) &ctx[i].serv_addr, sizeof(ctx[i].serv_addr)); + if (ret == -1) { + if (errno != EINPROGRESS) { + printf("connect error, index: %d\r\n", ctx[i].index); + (void) del_event(epfd, ctx[i].sockfd); + close(ctx[i].sockfd); + ctx[i].sockfd = -1; + } else { + ctx[i].state = connecting; + count++; + } + + continue; + } + + ctx[i].state = connected; + count++; + } + + printf("clients: %d\r\n", count); + + while (count > 0) { + n = epoll_wait(epfd, evs, REQ_CLI_COUNT, 2); + if (n == -1) { + if (errno != EINTR) { + printf("epoll_wait error, reason: %s\r\n", strerror(errno)); + break; + } + } else { + for (i = 0; i < n; i++) { + if (evs[i].events & EPOLLERR) { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("event error, index: %d\r\n", pctx->index); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } else if (evs[i].events & EPOLLIN) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nrecv = recv(pctx->sockfd, recv_buf[pctx->index] + pctx->nrecv, RECV_MAX_LINE, 0); + if (nrecv == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to recv, index: %d, reason: %s\r\n", pctx->index, strerror(errno)); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } else if (nrecv == 0) { + printf("peer closed connection, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + break; + } + + pctx->nrecv += nrecv; + if (pctx->nrecv > 12) { + if (pctx->error == false && pctx->success == false) { + str = recv_buf[pctx->index] + 9; + if (str[0] != '2' || str[1] != '0' || str[2] != '0') { + printf("response error, index: %d, recv: %s\r\n", pctx->index, recv_buf[pctx->index]); + pctx->error = true; + } else { + printf("response ok, index: %d\r\n", pctx->index); + pctx->success = true; + } + } + } + } + } else if (evs[i].events & EPOLLOUT) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nsent = send(pctx->sockfd, send_buf[pctx->index] + pctx->nsent, pctx->nlen - pctx->nsent, 0); + if (nsent == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to send, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } + + if (nsent == (int) (pctx->nlen - pctx->nsent)) { + printf("request done, request: %s, index: %d\r\n", send_buf[pctx->index], pctx->index); + + pctx->state = datasent; + + events = EPOLLET | EPOLLIN; + (void) mod_event(epfd, pctx->sockfd, events, (void *)pctx); + + break; + } else { + pctx->nsent += nsent; + } + } + } else { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("unknown event(%u), index: %d\r\n", evs[i].events, pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + } + } + } + +failed: + + if (epfd > 0) { + close(epfd); + } + + close_sockets(ctx, REQ_CLI_COUNT); + + return 0; +} diff --git a/tests/http/restful/http_use_db.c b/tests/http/restful/http_use_db.c new file mode 100644 index 0000000000000000000000000000000000000000..3b270224704b8cf7b9204d68f46f6d499e6f2ecd --- /dev/null +++ b/tests/http/restful/http_use_db.c @@ -0,0 +1,430 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define RECV_MAX_LINE 2048 +#define ITEM_MAX_LINE 128 +#define REQ_MAX_LINE 2048 +#define REQ_CLI_COUNT 100 + + +typedef enum +{ + uninited, + connecting, + connected, + datasent +} conn_stat; + + +typedef enum +{ + false, + true +} bool; + + +typedef unsigned short u16_t; +typedef unsigned int u32_t; + + +typedef struct +{ + int sockfd; + int index; + conn_stat state; + size_t nsent; + size_t nrecv; + size_t nlen; + bool error; + bool success; + struct sockaddr_in serv_addr; +} socket_ctx; + + +int set_nonblocking(int sockfd) +{ + int ret; + + ret = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); + if (ret == -1) { + printf("failed to fcntl for %d\r\n", sockfd); + return ret; + } + + return ret; +} + + +int create_socket(const char *ip, const u16_t port, socket_ctx *pctx) +{ + int ret; + + if (ip == NULL || port == 0 || pctx == NULL) { + printf("invalid parameter\r\n"); + return -1; + } + + pctx->sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (pctx->sockfd == -1) { + printf("failed to create socket\r\n"); + return -1; + } + + bzero(&pctx->serv_addr, sizeof(struct sockaddr_in)); + + pctx->serv_addr.sin_family = AF_INET; + pctx->serv_addr.sin_port = htons(port); + + ret = inet_pton(AF_INET, ip, &pctx->serv_addr.sin_addr); + if (ret <= 0) { + printf("inet_pton error, ip: %s\r\n", ip); + return -1; + } + + ret = set_nonblocking(pctx->sockfd); + if (ret == -1) { + printf("failed to set %d as nonblocking\r\n", pctx->sockfd); + return -1; + } + + return pctx->sockfd; +} + + +void close_sockets(socket_ctx *pctx, int cnt) +{ + int i; + + if (pctx == NULL) { + return; + } + + for (i = 0; i < cnt; i++) { + if (pctx[i].sockfd > 0) { + close(pctx[i].sockfd); + pctx[i].sockfd = -1; + } + } +} + + +int proc_pending_error(socket_ctx *ctx) +{ + int ret; + int err; + socklen_t len; + + if (ctx == NULL) { + return 0; + } + + err = 0; + len = sizeof(int); + + ret = getsockopt(ctx->sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &len); + if (ret == -1) { + err = errno; + } + + if (err) { + printf("failed to connect at index: %d\r\n", ctx->index); + + close(ctx->sockfd); + ctx->sockfd = -1; + + return -1; + } + + return 0; +} + + +void build_http_request(char *ip, u16_t port, char *url, char *sql, char *req_buf, int len) +{ + char req_line[ITEM_MAX_LINE]; + char req_host[ITEM_MAX_LINE]; + char req_cont_type[ITEM_MAX_LINE]; + char req_cont_len[ITEM_MAX_LINE]; + const char* req_auth = "Authorization: Basic cm9vdDp0YW9zZGF0YQ==\r\n"; + + if (ip == NULL || port == 0 || + url == NULL || url[0] == '\0' || + sql == NULL || sql[0] == '\0' || + req_buf == NULL || len <= 0) + { + return; + } + + snprintf(req_line, ITEM_MAX_LINE, "POST %s HTTP/1.1\r\n", url); + snprintf(req_host, ITEM_MAX_LINE, "HOST: %s:%d\r\n", ip, port); + snprintf(req_cont_type, ITEM_MAX_LINE, "%s\r\n", "Content-Type: text/plain"); + snprintf(req_cont_len, ITEM_MAX_LINE, "Content-Length: %ld\r\n\r\n", strlen(sql)); + + snprintf(req_buf, len, "%s%s%s%s%s%s", req_line, req_host, req_auth, req_cont_type, req_cont_len, sql); +} + + +int add_event(int epfd, int sockfd, u32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &evs_op); +} + + +int mod_event(int epfd, int sockfd, u32_t events, void *data) +{ + struct epoll_event evs_op; + + evs_op.data.ptr = data; + evs_op.events = events; + + return epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &evs_op); +} + + +int del_event(int epfd, int sockfd) +{ + struct epoll_event evs_op; + + evs_op.events = 0; + evs_op.data.ptr = NULL; + + return epoll_ctl(epfd, EPOLL_CTL_DEL, sockfd, &evs_op); +} + + +int main() +{ + int i; + int ret, n, nsent, nrecv; + int epfd; + u32_t events; + char *str; + socket_ctx *pctx, ctx[REQ_CLI_COUNT]; + char *ip = "127.0.0.1"; + char *url = "/rest/sql"; + u16_t port = 6041; + struct epoll_event evs[REQ_CLI_COUNT]; + char sql[REQ_MAX_LINE]; + char send_buf[REQ_CLI_COUNT][REQ_MAX_LINE + 5 * ITEM_MAX_LINE]; + char recv_buf[REQ_CLI_COUNT][RECV_MAX_LINE]; + int count; + + signal(SIGPIPE, SIG_IGN); + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ctx[i].sockfd = -1; + ctx[i].index = i; + ctx[i].state = uninited; + ctx[i].nsent = 0; + ctx[i].nrecv = 0; + ctx[i].error = false; + ctx[i].success = false; + + memset(sql, 0, REQ_MAX_LINE); + memset(send_buf[i], 0, REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + memset(recv_buf[i], 0, RECV_MAX_LINE); + + snprintf(sql, REQ_MAX_LINE, "use db%d", i); + + build_http_request(ip, port, url, sql, send_buf[i], REQ_MAX_LINE + 5 * ITEM_MAX_LINE); + + ctx[i].nlen = strlen(send_buf[i]); + } + + epfd = epoll_create(REQ_CLI_COUNT); + if (epfd <= 0) { + printf("failed to create epoll\r\n"); + goto failed; + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = create_socket(ip, port, &ctx[i]); + if (ret == -1) { + printf("failed to create socket, index: %d\r\n", i); + goto failed; + } + } + + for (i = 0; i < REQ_CLI_COUNT; i++) { + events = EPOLLET | EPOLLIN | EPOLLOUT; + ret = add_event(epfd, ctx[i].sockfd, events, (void *) &ctx[i]); + if (ret == -1) { + printf("failed to add sockfd to epoll, index: %d\r\n", i); + goto failed; + } + } + + count = 0; + + for (i = 0; i < REQ_CLI_COUNT; i++) { + ret = connect(ctx[i].sockfd, (struct sockaddr *) &ctx[i].serv_addr, sizeof(ctx[i].serv_addr)); + if (ret == -1) { + if (errno != EINPROGRESS) { + printf("connect error, index: %d\r\n", ctx[i].index); + (void) del_event(epfd, ctx[i].sockfd); + close(ctx[i].sockfd); + ctx[i].sockfd = -1; + } else { + ctx[i].state = connecting; + count++; + } + + continue; + } + + ctx[i].state = connected; + count++; + } + + printf("clients: %d\r\n", count); + + while (count > 0) { + n = epoll_wait(epfd, evs, REQ_CLI_COUNT, 2); + if (n == -1) { + if (errno != EINTR) { + printf("epoll_wait error, reason: %s\r\n", strerror(errno)); + break; + } + } else { + for (i = 0; i < n; i++) { + if (evs[i].events & EPOLLERR) { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("event error, index: %d\r\n", pctx->index); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } else if (evs[i].events & EPOLLIN) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nrecv = recv(pctx->sockfd, recv_buf[pctx->index] + pctx->nrecv, RECV_MAX_LINE, 0); + if (nrecv == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to recv, index: %d, reason: %s\r\n", pctx->index, strerror(errno)); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } else if (nrecv == 0) { + printf("peer closed connection, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + break; + } + + pctx->nrecv += nrecv; + if (pctx->nrecv > 12) { + if (pctx->error == false && pctx->success == false) { + str = recv_buf[pctx->index] + 9; + if (str[0] != '2' || str[1] != '0' || str[2] != '0') { + printf("response error, index: %d, recv: %s\r\n", pctx->index, recv_buf[pctx->index]); + pctx->error = true; + } else { + printf("response ok, index: %d\r\n", pctx->index); + pctx->success = true; + } + } + } + } + } else if (evs[i].events & EPOLLOUT) { + pctx = (socket_ctx *) evs[i].data.ptr; + if (pctx->state == connecting) { + ret = proc_pending_error(pctx); + if (ret == 0) { + printf("client connected, index: %d\r\n", pctx->index); + pctx->state = connected; + } else { + printf("client connect failed, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + + continue; + } + } + + for ( ;; ) { + nsent = send(pctx->sockfd, send_buf[pctx->index] + pctx->nsent, pctx->nlen - pctx->nsent, 0); + if (nsent == -1) { + if (errno != EAGAIN && errno != EINTR) { + printf("failed to send, index: %d\r\n", pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + + break; + } + + if (nsent == (int) (pctx->nlen - pctx->nsent)) { + printf("request done, request: %s, index: %d\r\n", send_buf[pctx->index], pctx->index); + + pctx->state = datasent; + + events = EPOLLET | EPOLLIN; + (void) mod_event(epfd, pctx->sockfd, events, (void *)pctx); + + break; + } else { + pctx->nsent += nsent; + } + } + } else { + pctx = (socket_ctx *) evs[i].data.ptr; + printf("unknown event(%u), index: %d\r\n", evs[i].events, pctx->index); + (void) del_event(epfd, pctx->sockfd); + close(pctx->sockfd); + pctx->sockfd = -1; + count--; + } + } + } + } + +failed: + + if (epfd > 0) { + close(epfd); + } + + close_sockets(ctx, REQ_CLI_COUNT); + + return 0; +} diff --git a/tests/nettest/FQDNnettest.sh b/tests/nettest/FQDNnettest.sh new file mode 100755 index 0000000000000000000000000000000000000000..f4ee5d56bce9842537ea9cea224c22dee28e2a7e --- /dev/null +++ b/tests/nettest/FQDNnettest.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +taos -n fqdn diff --git a/tests/nettest/TCPUDP.sh b/tests/nettest/TCPUDP.sh new file mode 100755 index 0000000000000000000000000000000000000000..3a4b5d77a4f26862b03194488380c8dad172bb42 --- /dev/null +++ b/tests/nettest/TCPUDP.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +for N in -1 0 1 10000 10001 +do + for l in 1023 1024 1073741824 1073741825 + do + for S in udp tcp + do + taos -n speed -h BCC-2 -P 6030 -N $N -l $l -S $S 2>&1 | tee -a result.txt + done + done +done diff --git a/tests/nettest/tcpudp.sh b/tests/nettest/tcpudp.sh index f0f924584b3948f2a3fc2bbd184c6dd083855013..3a4b5d77a4f26862b03194488380c8dad172bb42 100755 --- a/tests/nettest/tcpudp.sh +++ b/tests/nettest/tcpudp.sh @@ -1,13 +1,12 @@ #!/bin/bash - for N in -1 0 1 10000 10001 do for l in 1023 1024 1073741824 1073741825 do for S in udp tcp - do - taos -n speed -h BCC-2 -P 6030 -N $N -l $l -S $S 2>&1 | tee -a result.txt - done + do + taos -n speed -h BCC-2 -P 6030 -N $N -l $l -S $S 2>&1 | tee -a result.txt + done done done diff --git a/tests/pytest/alter/alter_table.py b/tests/pytest/alter/alter_table.py index a5acb7a73e0844ac2235590cbc8b7793ef40746c..33e0aec72756418fca41ef72d48e442da5aa135d 100644 --- a/tests/pytest/alter/alter_table.py +++ b/tests/pytest/alter/alter_table.py @@ -102,6 +102,20 @@ class TDTestCase: print("check2: i=%d colIdx=%d" % (i, colIdx)) tdSql.checkData(0, i, self.rowNum * (colIdx - i + 3)) + def alter_table_255_times(self): # add case for TD-6207 + for i in range(255): + tdLog.info("alter table st add column cb%d int"%i) + tdSql.execute("alter table st add column cb%d int"%i) + tdSql.execute("insert into t0 (ts,c1) values(now,1)") + tdSql.execute("reset query cache") + tdSql.query("select * from st") + tdSql.execute("create table mt(ts timestamp, i int)") + tdSql.execute("insert into mt values(now,11)") + tdSql.query("select * from mt") + tdDnodes.stop(1) + tdDnodes.start(1) + tdSql.query("describe db.st") + def run(self): # Setup params db = "db" @@ -131,12 +145,14 @@ class TDTestCase: tdSql.checkData(0, i, self.rowNum * (size - i)) - tdSql.execute("create table st(ts timestamp, c1 int) tags(t1 float)") - tdSql.execute("create table t0 using st tags(null)") + tdSql.execute("create table st(ts timestamp, c1 int) tags(t1 float,t2 int,t3 double)") + tdSql.execute("create table t0 using st tags(null,1,2.3)") tdSql.execute("alter table t0 set tag t1=2.1") tdSql.query("show tables") tdSql.checkRows(2) + self.alter_table_255_times() + def stop(self): tdSql.close() diff --git a/tests/pytest/client/version.py b/tests/pytest/client/version.py index 7cbeeb60df54e8d89fdcc7815a2b2757793dfaec..5c79380a00c96c03c827071c2bbab4f8eacad897 100644 --- a/tests/pytest/client/version.py +++ b/tests/pytest/client/version.py @@ -15,6 +15,7 @@ import sys from util.log import * from util.cases import * from util.sql import * +from math import floor class TDTestCase: @@ -27,23 +28,22 @@ class TDTestCase: sql = "select server_version()" ret = tdSql.query(sql) - version = tdSql.getData(0, 0)[0:3] - expectedVersion_dev = "2.0" - expectedVersion_master = "2.1" - if(version == expectedVersion_dev or version == expectedVersion_master): - tdLog.info("sql:%s, row:%d col:%d data:%s == expect" % (sql, 0, 0, version)) + version = floor(float(tdSql.getData(0, 0)[0:3])) + expectedVersion = 2 + + if(version == expectedVersion): + tdLog.info("sql:%s, row:%d col:%d data:%d == expect" % (sql, 0, 0, version)) else: - tdLog.exit("sql:%s, row:%d col:%d data:%s != expect:%s or %s " % (sql, 0, 0, version, expectedVersion_dev, expectedVersion_master)) + tdLog.exit("sql:%s, row:%d col:%d data:%d != expect:%d " % (sql, 0, 0, version, expectedVersion)) sql = "select client_version()" ret = tdSql.query(sql) - version = tdSql.getData(0, 0)[0:3] - expectedVersion_dev = "2.0" - expectedVersion_master = "2.1" - if(version == expectedVersion_dev or version == expectedVersion_master): - tdLog.info("sql:%s, row:%d col:%d data:%s == expect" % (sql, 0, 0, version)) + version = floor(float(tdSql.getData(0, 0)[0:3])) + expectedVersion = 2 + if(version == expectedVersion): + tdLog.info("sql:%s, row:%d col:%d data:%d == expect" % (sql, 0, 0, version)) else: - tdLog.exit("sql:%s, row:%d col:%d data:%s != expect:%s or %s " % (sql, 0, 0, version, expectedVersion_dev, expectedVersion_master)) + tdLog.exit("sql:%s, row:%d col:%d data:%d != expect:%d " % (sql, 0, 0, version, expectedVersion)) def stop(self): diff --git a/tests/pytest/concurrent_inquiry.py b/tests/pytest/concurrent_inquiry.py index 333c2a0a578f6f399e742b0967db0185a22b5fde..1bb2081d7f936ccd6df0e6c85d3d451d9c0d9e44 100644 --- a/tests/pytest/concurrent_inquiry.py +++ b/tests/pytest/concurrent_inquiry.py @@ -23,7 +23,7 @@ import string from requests.auth import HTTPBasicAuth func_list=['avg','count','twa','sum','stddev','leastsquares','min', 'max','first','last','top','bottom','percentile','apercentile', -'last_row','diff','spread'] +'last_row','diff','spread','distinct'] condition_list=[ "where _c0 > now -10d ", 'interval(10s)', @@ -33,7 +33,7 @@ condition_list=[ 'fill(null)' ] -where_list = ['_c0>now-10d',' <50','like',' is null'] +where_list = ['_c0>now-10d',' <50','like',' is null','in'] class ConcurrentInquiry: # def __init__(self,ts=1500000001000,host='127.0.0.1',user='root',password='taosdata',dbname='test', # stb_prefix='st',subtb_prefix='t',n_Therads=10,r_Therads=10,probabilities=0.05,loop=5, @@ -152,6 +152,20 @@ class ConcurrentInquiry: elif 'is null' in c: conlist = ' ' + random.choice(tlist) + random.choice([' is null',' is not null']) l.append(conlist) + elif 'in' in c: + in_list = [] + temp = [] + for i in range(random.randint(0,100)): + temp.append(random.randint(-10000,10000)) + temp = (str(i) for i in temp) + in_list.append(temp) + temp1 = [] + for i in range(random.randint(0,100)): + temp1.append("'" + ''.join(random.sample(string.ascii_letters, random.randint(0,10))) + "'") + in_list.append(temp1) + in_list.append(['NULL','NULL']) + conlist = ' ' + random.choice(tlist) + ' in (' + ','.join(random.choice(in_list)) + ')' + l.append(conlist) else: s_all = string.ascii_letters conlist = ' ' + random.choice(tlist) + " like \'%" + random.choice(s_all) + "%\' " @@ -175,12 +189,69 @@ class ConcurrentInquiry: def con_group(self,tlist,col_list,tag_list): rand_tag = random.randint(0,5) rand_col = random.randint(0,1) - return 'group by '+','.join(random.sample(col_list,rand_col) + random.sample(tag_list,rand_tag)) - + if len(tag_list): + return 'group by '+','.join(random.sample(col_list,rand_col) + random.sample(tag_list,rand_tag)) + else: + return 'group by '+','.join(random.sample(col_list,rand_col)) + def con_order(self,tlist,col_list,tag_list): return 'order by '+random.choice(tlist) + + def con_state_window(self,tlist,col_list,tag_list): + return 'state_window(' + random.choice(tlist + tag_list) + ')' + + def con_session_window(self,tlist,col_list,tag_list): + session_window = 'session_window(' + random.choice(tlist + tag_list) + ',' + str(random.randint(0,20)) + random.choice(['a','s','d','w','n','y']) + ')' + return session_window + + def gen_subquery_sql(self): + subsql ,col_num = self.gen_query_sql(1) + if col_num == 0: + return 0 + col_list=[] + tag_list=[] + for i in range(col_num): + col_list.append("taosd%d"%i) + + tlist=col_list+['abc'] #增加不存在的域'abc',是否会引起新bug + con_rand=random.randint(0,len(condition_list)) + func_rand=random.randint(0,len(func_list)) + col_rand=random.randint(0,len(col_list)) + t_rand=random.randint(0,len(tlist)) + sql='select ' #select + random.shuffle(col_list) + random.shuffle(func_list) + sel_col_list=[] + col_rand=random.randint(0,len(col_list)) + loop = 0 + for i,j in zip(col_list[0:col_rand],func_list): #决定每个被查询col的函数 + alias = ' as '+ 'sub%d ' % loop + loop += 1 + pick_func = '' + if j == 'leastsquares': + pick_func=j+'('+i+',1,1)' + elif j == 'top' or j == 'bottom' or j == 'percentile' or j == 'apercentile': + pick_func=j+'('+i+',1)' + else: + pick_func=j+'('+i+')' + if bool(random.getrandbits(1)) : + pick_func+=alias + sel_col_list.append(pick_func) + if col_rand == 0: + sql = sql + '*' + else: + sql=sql+','.join(sel_col_list) #select col & func + sql = sql + ' from ('+ subsql +') ' + con_func=[self.con_where,self.con_interval,self.con_limit,self.con_group,self.con_order,self.con_fill,self.con_state_window,self.con_session_window] + sel_con=random.sample(con_func,random.randint(0,len(con_func))) + sel_con_list=[] + for i in sel_con: + sel_con_list.append(i(tlist,col_list,tag_list)) #获取对应的条件函数 + sql+=' '.join(sel_con_list) # condition + #print(sql) + return sql - def gen_query_sql(self): #生成查询语句 + def gen_query_sql(self,subquery=0): #生成查询语句 tbi=random.randint(0,len(self.subtb_list)+len(self.stb_list)) #随机决定查询哪张表 tbname='' col_list=[] @@ -218,10 +289,10 @@ class ConcurrentInquiry: pick_func=j+'('+i+',1)' else: pick_func=j+'('+i+')' - if bool(random.getrandbits(1)): + if bool(random.getrandbits(1)) | subquery : pick_func+=alias sel_col_list.append(pick_func) - if col_rand == 0: + if col_rand == 0 & subquery : sql = sql + '*' else: sql=sql+','.join(sel_col_list) #select col & func @@ -231,14 +302,14 @@ class ConcurrentInquiry: sql = sql + ' from '+random.choice(self.subtb_list)+' ' else: sql = sql + ' from '+random.choice(self.stb_list)+' ' - con_func=[self.con_where,self.con_interval,self.con_limit,self.con_group,self.con_order,self.con_fill] + con_func=[self.con_where,self.con_interval,self.con_limit,self.con_group,self.con_order,self.con_fill,self.con_state_window,self.con_session_window] sel_con=random.sample(con_func,random.randint(0,len(con_func))) sel_con_list=[] for i in sel_con: sel_con_list.append(i(tlist,col_list,tag_list)) #获取对应的条件函数 sql+=' '.join(sel_con_list) # condition #print(sql) - return sql + return (sql,loop) def gen_query_join(self): #生成join查询语句 tbname = [] @@ -429,9 +500,12 @@ class ConcurrentInquiry: try: if self.random_pick(): - sql=self.gen_query_sql() + if self.random_pick(): + sql,temp=self.gen_query_sql() + else: + sql = self.gen_subquery_sql() else: - sql=self.gen_query_join() + sql = self.gen_query_join() print("sql is ",sql) fo.write(sql+'\n') start = time.time() @@ -496,9 +570,12 @@ class ConcurrentInquiry: while loop: try: if self.random_pick(): - sql=self.gen_query_sql() + if self.random_pick(): + sql,temp=self.gen_query_sql() + else: + sql = self.gen_subquery_sql() else: - sql=self.gen_query_join() + sql = self.gen_query_join() print("sql is ",sql) fo.write(sql+'\n') start = time.time() diff --git a/tests/pytest/fulltest.sh b/tests/pytest/fulltest.sh index 1d7276b8980674ca281cbd1b1193b908153e53c8..06ec3c6bfabfe4d9c378c9d17dda944990f624a8 100755 --- a/tests/pytest/fulltest.sh +++ b/tests/pytest/fulltest.sh @@ -80,6 +80,7 @@ python3 ./test.py -f tag_lite/set.py python3 ./test.py -f tag_lite/smallint.py python3 ./test.py -f tag_lite/tinyint.py python3 ./test.py -f tag_lite/timestamp.py +python3 ./test.py -f tag_lite/TestModifyTag.py #python3 ./test.py -f dbmgmt/database-name-boundary.py python3 test.py -f dbmgmt/nanoSecondCheck.py @@ -171,6 +172,10 @@ python3 test.py -f tools/taosdemoTestSampleData.py python3 test.py -f tools/taosdemoTestInterlace.py python3 test.py -f tools/taosdemoTestQuery.py +# restful test for python +python3 test.py -f restful/restful_bind_db1.py +python3 test.py -f restful/restful_bind_db2.py + # nano support python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py python3 test.py -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoQuery.py @@ -259,7 +264,7 @@ python3 ./test.py -f query/queryTsisNull.py python3 ./test.py -f query/subqueryFilter.py python3 ./test.py -f query/nestedQuery/queryInterval.py python3 ./test.py -f query/queryStateWindow.py -python3 ./test.py -f query/nestedQuery/queryWithOrderLimit.py +# python3 ./test.py -f query/nestedQuery/queryWithOrderLimit.py python3 ./test.py -f query/nestquery_last_row.py python3 ./test.py -f query/queryCnameDisplay.py python3 ./test.py -f query/operator_cost.py @@ -381,8 +386,11 @@ python3 ./test.py -f query/querySession.py python3 test.py -f alter/alter_create_exception.py python3 ./test.py -f insert/flushwhiledrop.py python3 ./test.py -f insert/schemalessInsert.py -python3 ./test.py -f alter/alterColMultiTimes.py - +python3 ./test.py -f alter/alterColMultiTimes.py +python3 ./test.py -f query/queryWildcardLength.py +python3 ./test.py -f query/queryTbnameUpperLower.py +python3 ./test.py -f query/query.py +python3 ./test.py -f query/queryDiffColsOr.py #======================p4-end=============== diff --git a/tests/pytest/functions/function_bottom.py b/tests/pytest/functions/function_bottom.py index abb9ac48e70ac876741c3da2a9f223d537c8644b..e9e5003f6f96a9d04bb70b3a867c3cba239d8bff 100644 --- a/tests/pytest/functions/function_bottom.py +++ b/tests/pytest/functions/function_bottom.py @@ -104,6 +104,21 @@ class TDTestCase: tdSql.checkRows(2) tdSql.checkData(0, 1, 1) tdSql.checkData(1, 1, 2) + + tdSql.query("select ts,bottom(col1, 2),ts from test1") + tdSql.checkRows(2) + tdSql.checkData(0, 0, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 1, "2018-09-17 09:00:00.000") + tdSql.checkData(1, 0, "2018-09-17 09:00:00.001") + tdSql.checkData(1, 3, "2018-09-17 09:00:00.001") + + + tdSql.query("select ts,bottom(col1, 2),ts from test group by tbname") + tdSql.checkRows(2) + tdSql.checkData(0, 0, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 1, "2018-09-17 09:00:00.000") + tdSql.checkData(1, 0, "2018-09-17 09:00:00.001") + tdSql.checkData(1, 3, "2018-09-17 09:00:00.001") #TD-2457 bottom + interval + order by tdSql.error('select top(col2,1) from test interval(1y) order by col2;') diff --git a/tests/pytest/functions/function_derivative.py b/tests/pytest/functions/function_derivative.py index 9d60129672b5516d83e696f67b5c8d5a17630afd..d4d8ab80a6b9587df900890ef18b8c4b1e3906bd 100644 --- a/tests/pytest/functions/function_derivative.py +++ b/tests/pytest/functions/function_derivative.py @@ -54,6 +54,28 @@ class TDTestCase: tdSql.query("select derivative(col, 10s, 0) from stb group by tbname") tdSql.checkRows(10) + tdSql.query("select ts,derivative(col, 10s, 1),ts from stb group by tbname") + tdSql.checkRows(4) + tdSql.checkData(0, 0, "2018-09-17 09:00:10.000") + tdSql.checkData(0, 1, "2018-09-17 09:00:10.000") + tdSql.checkData(0, 3, "2018-09-17 09:00:10.000") + tdSql.checkData(3, 0, "2018-09-17 09:01:20.000") + tdSql.checkData(3, 1, "2018-09-17 09:01:20.000") + tdSql.checkData(3, 3, "2018-09-17 09:01:20.000") + + tdSql.query("select ts,derivative(col, 10s, 1),ts from tb1") + tdSql.checkRows(2) + tdSql.checkData(0, 0, "2018-09-17 09:00:10.000") + tdSql.checkData(0, 1, "2018-09-17 09:00:10.000") + tdSql.checkData(0, 3, "2018-09-17 09:00:10.000") + tdSql.checkData(1, 0, "2018-09-17 09:00:20.009") + tdSql.checkData(1, 1, "2018-09-17 09:00:20.009") + tdSql.checkData(1, 3, "2018-09-17 09:00:20.009") + + tdSql.query("select ts from(select ts,derivative(col, 10s, 0) from stb group by tbname)") + + tdSql.checkData(0, 0, "2018-09-17 09:00:10.000") + tdSql.error("select derivative(col, 10s, 0) from tb1 group by tbname") tdSql.query("select derivative(col, 10s, 1) from tb1") diff --git a/tests/pytest/functions/function_diff.py b/tests/pytest/functions/function_diff.py index fba3b4c0d4bd16533ab9f67b42b3643449288cac..5995b821d1a42e75d7b80e0d564e4281da9b3979 100644 --- a/tests/pytest/functions/function_diff.py +++ b/tests/pytest/functions/function_diff.py @@ -94,6 +94,41 @@ class TDTestCase: tdSql.error("select diff(col13) from test") tdSql.error("select diff(col14) from test") + tdSql.query("select ts,diff(col1),ts from test1") + tdSql.checkRows(10) + tdSql.checkData(0, 0, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 1, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 3, "2018-09-17 09:00:00.000") + tdSql.checkData(9, 0, "2018-09-17 09:00:00.009") + tdSql.checkData(9, 1, "2018-09-17 09:00:00.009") + tdSql.checkData(9, 3, "2018-09-17 09:00:00.009") + + tdSql.query("select ts,diff(col1),ts from test group by tbname") + tdSql.checkRows(10) + tdSql.checkData(0, 0, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 1, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 3, "2018-09-17 09:00:00.000") + tdSql.checkData(9, 0, "2018-09-17 09:00:00.009") + tdSql.checkData(9, 1, "2018-09-17 09:00:00.009") + tdSql.checkData(9, 3, "2018-09-17 09:00:00.009") + + tdSql.query("select ts,diff(col1),ts from test1") + tdSql.checkRows(10) + tdSql.checkData(0, 0, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 1, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 3, "2018-09-17 09:00:00.000") + tdSql.checkData(9, 0, "2018-09-17 09:00:00.009") + tdSql.checkData(9, 1, "2018-09-17 09:00:00.009") + tdSql.checkData(9, 3, "2018-09-17 09:00:00.009") + + tdSql.query("select ts,diff(col1),ts from test group by tbname") + tdSql.checkRows(10) + tdSql.checkData(0, 0, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 1, "2018-09-17 09:00:00.000") + tdSql.checkData(0, 3, "2018-09-17 09:00:00.000") + tdSql.checkData(9, 0, "2018-09-17 09:00:00.009") + tdSql.checkData(9, 1, "2018-09-17 09:00:00.009") + tdSql.checkData(9, 3, "2018-09-17 09:00:00.009") tdSql.query("select diff(col1) from test1") tdSql.checkRows(10) diff --git a/tests/pytest/functions/function_interp.py b/tests/pytest/functions/function_interp.py index 810c90279cd2b7410f97e5eff51be4e9865b6555..469e9186f668ec2c1afb03a79648c5a822cacdbe 100644 --- a/tests/pytest/functions/function_interp.py +++ b/tests/pytest/functions/function_interp.py @@ -11,33 +11,106 @@ # -*- coding: utf-8 -*- -import sys -import taos from util.log import * from util.cases import * from util.sql import * -import numpy as np - - class TDTestCase: def init(self, conn, logSql): tdLog.debug("start to execute %s" % __file__) tdSql.init(conn.cursor()) - self.rowNum = 10 - self.ts = 1537146000000 - def run(self): tdSql.prepare() - tdSql.execute("create table t(ts timestamp, k int)") - tdSql.execute("insert into t values('2021-1-1 1:1:1', 12);") - - tdSql.query("select interp(*) from t where ts='2021-1-1 1:1:1'") - tdSql.checkRows(1) - tdSql.checkData(0, 1, 12) - - tdSql.error("select interp(*) from t where ts >'2021-1-1 1:1:1' and ts < now interval(1s) fill(next)") - + tdSql.execute("create table ap1 (ts timestamp, pav float)") + tdSql.execute("create table ap2 (ts timestamp, pav float) tags (t1 float)") + tdSql.execute("create table ap2_sub1 using ap2 tags (2.90799)") + tdSql.execute("create table ap2_sub2 using ap2 tags (2.90799)") + tdSql.execute("create table ap3 (ts timestamp, pav float) tags (t1 float)") + tdSql.execute("create table ap3_sub1 using ap3 tags (2.90799)") + for tb_name in ["ap1", "ap2_sub1", "ap3_sub1"]: + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:54.119', 2.90799)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:54.317', 3.07399)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:54.517', 0.58117)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:54.717', 0.16150)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:54.918', 1.47885)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:56.569', 1.76472)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:57.381', 2.13722)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:57.574', 4.10256)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:57.776', 3.55345)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:57.976', 1.46624)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:58.187', 0.17943)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:58.372', 2.04101)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:58.573', 3.20924)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:58.768', 1.71807)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:58.964', 4.60900)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:59.155', 4.33907)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:59.359', 0.76940)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:59.553', 0.06458)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:59.742', 4.59857)") + tdSql.execute(f"insert into {tb_name} values ('2021-07-25 02:19:59.938', 1.55081)") + + tdSql.query("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (PREV)") + tdSql.checkRows(0) + tdSql.query("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (NEXT)") + tdSql.checkRows(0) + tdSql.query("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (LINEAR)") + tdSql.checkRows(0) + # check None + tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (None)") + tdSql.checkRows(0) + # check NULL + tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (NULL)") + tdSql.checkRows(6) + for i in range(5): + tdSql.checkData(i,1,None) + # checkout VALUE + tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (VALUE, 1)") + tdSql.checkRows(6) + for i in range(5): + tdSql.checkData(i,1,1.00000) + # check tag group by + tdSql.query("select interp(pav) from ap2 where ts>= '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (VALUE,1) group by t1;") + for i in range(5): + tdSql.checkData(i,1,1.00000) + tdSql.checkData(i,2,2.90799) + # check multi ts lines + tdSql.query("select z1.ts,z1.val1,z2.val2 from (select interp(pav) val1 from ap2 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (value,1)) z1,(select interp(pav) val2 from ap3 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (value,2)) z2 where z1.ts=z2.ts ;") + for i in range(5): + tdSql.checkData(i,1,1.00000) + tdSql.checkData(i,2,2.00000) + tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (LINEAR)") + tdSql.checkRows(6) + tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (NEXT)") + tdSql.checkRows(6) + tdSql.checkData(0,1,2.90799) + tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' every(1000a) FILL (PREV)") + tdSql.checkRows(7) + tdSql.checkData(1,1,1.47885) + tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' every(1000a) FILL (LINEAR)") + tdSql.checkRows(7) + + # check desc order + tdSql.error("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (PREV) order by ts desc") + tdSql.query("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (NEXT) order by ts desc") + tdSql.checkRows(0) + tdSql.query("select interp(pav) from ap1 where ts = '2021-07-25 02:19:54' FILL (LINEAR) order by ts desc") + tdSql.checkRows(0) + tdSql.query("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (LINEAR) order by ts desc") + tdSql.checkRows(6) + tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1000a) FILL (NEXT) order by ts desc") + tdSql.checkRows(6) + tdSql.checkData(0,1,4.60900) + tdSql.error("select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' every(1000a) FILL (PREV) order by ts desc") + tdSql.query("select interp(pav) from ap1 where ts>= '2021-07-25 02:19:54' and ts <= '2021-07-25 02:20:00' every(1000a) FILL (LINEAR) order by ts desc") + tdSql.checkRows(7) + + # check exception + tdSql.error("select interp(*) from ap1") + tdSql.error("select interp(*) from ap1 FILL(NEXT)") + tdSql.error("select interp(*) from ap1 ts >= '2021-07-25 02:19:54' FILL(NEXT)") + tdSql.error("select interp(*) from ap1 ts <= '2021-07-25 02:19:54' FILL(NEXT)") + tdSql.error("select interp(*) from ap1 where ts >'2021-07-25 02:19:59.938' and ts < now every(1s) fill(next)") + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/pytest/functions/function_top.py b/tests/pytest/functions/function_top.py index f8318402b57ab4f362bd4fab8de3c04bbdcf3a5d..03a00d918ae933a83b19c8e18ab040ea4bff95c6 100644 --- a/tests/pytest/functions/function_top.py +++ b/tests/pytest/functions/function_top.py @@ -117,7 +117,22 @@ class TDTestCase: tdSql.checkRows(2) tdSql.checkData(0, 1, 8.1) tdSql.checkData(1, 1, 9.1) - + + tdSql.query("select ts,top(col1, 2),ts from test1") + tdSql.checkRows(2) + tdSql.checkData(0, 0, "2018-09-17 09:00:00.008") + tdSql.checkData(0, 1, "2018-09-17 09:00:00.008") + tdSql.checkData(1, 0, "2018-09-17 09:00:00.009") + tdSql.checkData(1, 3, "2018-09-17 09:00:00.009") + + + tdSql.query("select ts,top(col1, 2),ts from test group by tbname") + tdSql.checkRows(2) + tdSql.checkData(0, 0, "2018-09-17 09:00:00.008") + tdSql.checkData(0, 1, "2018-09-17 09:00:00.008") + tdSql.checkData(1, 0, "2018-09-17 09:00:00.009") + tdSql.checkData(1, 3, "2018-09-17 09:00:00.009") + #TD-2563 top + super_table + interval tdSql.execute("create table meters(ts timestamp, c int) tags (d int)") tdSql.execute("create table t1 using meters tags (1)") diff --git a/tests/pytest/functions/queryTestCases.py b/tests/pytest/functions/queryTestCases.py index b7480fdbd555f97f17d71b5583296d49ffcd4061..1311ad6b3c83e1d4a0ec6fdf73a707a44bd5297c 100644 --- a/tests/pytest/functions/queryTestCases.py +++ b/tests/pytest/functions/queryTestCases.py @@ -13,6 +13,8 @@ import sys import subprocess +import random +import math from util.log import * from util.cases import * @@ -56,7 +58,7 @@ class TDTestCase: def td3690(self): tdLog.printNoPrefix("==========TD-3690==========") tdSql.query("show variables") - tdSql.checkData(51, 1, 864000) + tdSql.checkData(53, 1, 864000) def td4082(self): tdLog.printNoPrefix("==========TD-4082==========") @@ -106,6 +108,9 @@ class TDTestCase: tdSql.execute("drop database if exists db1") tdSql.execute("create database if not exists db keep 3650") tdSql.execute("create database if not exists db1 keep 3650") + tdSql.execute("create database if not exists new keep 3650") + tdSql.execute("create database if not exists private keep 3650") + tdSql.execute("create database if not exists db2 keep 3650") tdSql.execute("create stable db.stb1 (ts timestamp, c1 int) tags(t1 int)") tdSql.execute("create stable db.stb2 (ts timestamp, c1 int) tags(t1 int)") @@ -122,6 +127,14 @@ class TDTestCase: # p1 不进入指定数据库 tdSql.query("show create database db") tdSql.checkRows(1) + tdSql.query("show create database db1") + tdSql.checkRows(1) + tdSql.query("show create database db2") + tdSql.checkRows(1) + tdSql.query("show create database new") + tdSql.checkRows(1) + tdSql.query("show create database private") + tdSql.checkRows(1) tdSql.error("show create database ") tdSql.error("show create databases db ") tdSql.error("show create database db.stb1") @@ -255,7 +268,7 @@ class TDTestCase: tdSql.execute("drop database if exists db") tdSql.execute("create database if not exists db") tdSql.query("show variables") - tdSql.checkData(36, 1, 3650) + tdSql.checkData(38, 1, 3650) tdSql.query("show databases") tdSql.checkData(0,7,"3650,3650,3650") @@ -283,7 +296,7 @@ class TDTestCase: tdSql.query("show databases") tdSql.checkData(0, 7, "3650,3650,3650") tdSql.query("show variables") - tdSql.checkData(36, 1, 3650) + tdSql.checkData(38, 1, 3650) tdSql.execute("alter database db1 keep 365") tdSql.execute("drop database if exists db1") @@ -340,17 +353,673 @@ class TDTestCase: pass + def td4889(self): + tdLog.printNoPrefix("==========TD-4889==========") + tdSql.execute("drop database if exists db") + tdSql.execute("create database if not exists db keep 3650") + + tdSql.execute("use db") + tdSql.execute("create stable db.stb1 (ts timestamp, c1 int) tags(t1 int)") + + for i in range(1000): + tdSql.execute(f"create table db.t1{i} using db.stb1 tags({i})") + for j in range(100): + tdSql.execute(f"insert into db.t1{i} values (now-100d, {i+j})") + + tdSql.query("show vgroups") + index = tdSql.getData(0,0) + tdSql.checkData(0, 6, 0) + tdSql.execute(f"compact vnodes in({index})") + for i in range(3): + tdSql.query("show vgroups") + if tdSql.getData(0, 6) == 1: + tdLog.printNoPrefix("show vgroups row:0 col:6 data:1 == expect:1") + break + if i == 3: + tdLog.exit("compacting not occured") + time.sleep(0.5) + + pass + + def td5168insert(self): + tdSql.execute("drop database if exists db") + tdSql.execute("create database if not exists db keep 3650") + + tdSql.execute("use db") + tdSql.execute("create stable db.stb1 (ts timestamp, c1 float, c2 float, c3 double, c4 double) tags(t1 int)") + tdSql.execute("create table db.t1 using db.stb1 tags(1)") + + for i in range(5): + c1 = 1001.11 + i*0.1 + c2 = 1001.11 + i*0.1 + 1*0.01 + c3 = 1001.11 + i*0.1 + 2*0.01 + c4 = 1001.11 + i*0.1 + 3*0.01 + tdSql.execute(f"insert into db.t1 values ('2021-07-01 08:00:0{i}.000', {c1}, {c2}, {c3}, {c4})") + + # tdSql.execute("insert into db.t1 values ('2021-07-01 08:00:00.000', 1001.11, 1001.12, 1001.13, 1001.14)") + # tdSql.execute("insert into db.t1 values ('2021-07-01 08:00:01.000', 1001.21, 1001.22, 1001.23, 1001.24)") + # tdSql.execute("insert into db.t1 values ('2021-07-01 08:00:02.000', 1001.31, 1001.32, 1001.33, 1001.34)") + # tdSql.execute("insert into db.t1 values ('2021-07-01 08:00:03.000', 1001.41, 1001.42, 1001.43, 1001.44)") + # tdSql.execute("insert into db.t1 values ('2021-07-01 08:00:04.000', 1001.51, 1001.52, 1001.53, 1001.54)") + + # for i in range(1000000): + for i in range(1000000): + random1 = random.uniform(1000,1001) + random2 = random.uniform(1000,1001) + random3 = random.uniform(1000,1001) + random4 = random.uniform(1000,1001) + tdSql.execute(f"insert into db.t1 values (now+{i}a, {random1}, {random2},{random3}, {random4})") + + pass + + def td5168(self): + tdLog.printNoPrefix("==========TD-5168==========") + # 插入小范围内的随机数 + tdLog.printNoPrefix("=====step0: 默认情况下插入数据========") + self.td5168insert() + + # 获取五个时间点的数据作为基准数值,未压缩情况下精准匹配 + for i in range(5): + tdSql.query(f"select * from db.t1 where ts='2021-07-01 08:00:0{i}.000' ") + # c1, c2, c3, c4 = tdSql.getData(0, 1), tdSql.getData(0, 2), tdSql.getData(0, 3), tdSql.getData(0, 4) + for j in range(4): + locals()["f" + str(j) + str(i)] = tdSql.getData(0, j+1) + print(f"f{j}{i}:", locals()["f" + str(j) + str(i)]) + tdSql.checkData(0, j+1, locals()["f" + str(j) + str(i)]) + + # tdSql.query("select * from db.t1 limit 100,1") + # f10, f11, f12, f13 = tdSql.getData(0,1), tdSql.getData(0,2), tdSql.getData(0,3), tdSql.getData(0,4) + # + # tdSql.query("select * from db.t1 limit 1000,1") + # f20, f21, f22, f23 = tdSql.getData(0,1), tdSql.getData(0,2), tdSql.getData(0,3), tdSql.getData(0,4) + # + # tdSql.query("select * from db.t1 limit 10000,1") + # f30, f31, f32, f33 = tdSql.getData(0,1), tdSql.getData(0,2), tdSql.getData(0,3), tdSql.getData(0,4) + # + # tdSql.query("select * from db.t1 limit 100000,1") + # f40, f41, f42, f43 = tdSql.getData(0,1), tdSql.getData(0,2), tdSql.getData(0,3), tdSql.getData(0,4) + # + # tdSql.query("select * from db.t1 limit 1000000,1") + # f50, f51, f52, f53 = tdSql.getData(0,1), tdSql.getData(0,2), tdSql.getData(0,3), tdSql.getData(0,4) + + # 关闭服务并获取未开启压缩情况下的数据容量 + tdSql.query("show dnodes") + index = tdSql.getData(0, 0) + tdDnodes.stop(index) + + cfgdir = self.getCfgDir() + cfgfile = self.getCfgFile() + + lossy_cfg_cmd=f"grep lossyColumns {cfgfile}|awk '{{print $2}}'" + data_size_cmd = f"du -s {cfgdir}/../data/vnode/ | awk '{{print $1}}'" + dsize_init = int(subprocess.check_output(data_size_cmd,shell=True).decode("utf-8")) + lossy_args = subprocess.check_output(lossy_cfg_cmd, shell=True).decode("utf-8") + tdLog.printNoPrefix(f"close the lossyColumns,data size is: {dsize_init};the lossyColumns line is: {lossy_args}") + + ################################################### + float_lossy = "float" + double_lossy = "double" + float_double_lossy = "float|double" + no_loosy = "" + + double_precision_cmd = f"sed -i '$a dPrecision 0.000001' {cfgfile}" + _ = subprocess.check_output(double_precision_cmd, shell=True).decode("utf-8") + + lossy_float_cmd = f"sed -i '$a lossyColumns {float_lossy}' {cfgfile} " + lossy_double_cmd = f"sed -i '$d' {cfgfile} && sed -i '$a lossyColumns {double_lossy}' {cfgfile} " + lossy_float_double_cmd = f"sed -i '$d' {cfgfile} && sed -i '$a lossyColumns {float_double_lossy}' {cfgfile} " + lossy_no_cmd = f"sed -i '$a lossyColumns {no_loosy}' {cfgfile} " + + ################################################### + + # 开启有损压缩,参数float,并启动服务插入数据 + tdLog.printNoPrefix("=====step1: lossyColumns设置为float========") + lossy_float = subprocess.check_output(lossy_float_cmd, shell=True).decode("utf-8") + tdDnodes.start(index) + self.td5168insert() + + # 查询前面所述5个时间数据并与基准数值进行比较 + for i in range(5): + tdSql.query(f"select * from db.t1 where ts='2021-07-01 08:00:0{i}.000' ") + # c1, c2, c3, c4 = tdSql.getData(0, 1), tdSql.getData(0, 2), tdSql.getData(0, 3), tdSql.getData(0, 4) + for j in range(4): + # locals()["f" + str(j) + str(i)] = tdSql.getData(0, j+1) + # print(f"f{j}{i}:", locals()["f" + str(j) + str(i)]) + tdSql.checkData(0, j+1, locals()["f" + str(j) + str(i)]) + + # 关闭服务并获取压缩参数为float情况下的数据容量 + tdDnodes.stop(index) + dsize_float = int(subprocess.check_output(data_size_cmd,shell=True).decode("utf-8")) + lossy_args = subprocess.check_output(lossy_cfg_cmd, shell=True).decode("utf-8") + tdLog.printNoPrefix(f"open the lossyColumns, data size is:{dsize_float};the lossyColumns line is: {lossy_args}") + + # 修改有损压缩,参数double,并启动服务 + tdLog.printNoPrefix("=====step2: lossyColumns设置为double========") + lossy_double = subprocess.check_output(lossy_double_cmd, shell=True).decode("utf-8") + tdDnodes.start(index) + self.td5168insert() + + # 查询前面所述5个时间数据并与基准数值进行比较 + for i in range(5): + tdSql.query(f"select * from db.t1 where ts='2021-07-01 08:00:0{i}.000' ") + for j in range(4): + tdSql.checkData(0, j+1, locals()["f" + str(j) + str(i)]) + + # 关闭服务并获取压缩参数为double情况下的数据容量 + tdDnodes.stop(index) + dsize_double = int(subprocess.check_output(data_size_cmd, shell=True).decode("utf-8")) + lossy_args = subprocess.check_output(lossy_cfg_cmd, shell=True).decode("utf-8") + tdLog.printNoPrefix(f"open the lossyColumns, data size is:{dsize_double};the lossyColumns line is: {lossy_args}") + + # 修改有损压缩,参数 float&&double ,并启动服务 + tdLog.printNoPrefix("=====step3: lossyColumns设置为 float&&double ========") + lossy_float_double = subprocess.check_output(lossy_float_double_cmd, shell=True).decode("utf-8") + tdDnodes.start(index) + self.td5168insert() + + # 查询前面所述5个时间数据并与基准数值进行比较 + for i in range(5): + tdSql.query(f"select * from db.t1 where ts='2021-07-01 08:00:0{i}.000' ") + for j in range(4): + tdSql.checkData(0, j+1, locals()["f" + str(j) + str(i)]) + + # 关闭服务并获取压缩参数为 float&&double 情况下的数据容量 + tdDnodes.stop(index) + dsize_float_double = int(subprocess.check_output(data_size_cmd, shell=True).decode("utf-8")) + lossy_args = subprocess.check_output(lossy_cfg_cmd, shell=True).decode("utf-8") + tdLog.printNoPrefix(f"open the lossyColumns, data size is:{dsize_float_double};the lossyColumns line is: {lossy_args}") + + if not ((dsize_float_double < dsize_init) and (dsize_double < dsize_init) and (dsize_float < dsize_init)) : + tdLog.printNoPrefix(f"When lossyColumns value is float, data size is: {dsize_float}") + tdLog.printNoPrefix(f"When lossyColumns value is double, data size is: {dsize_double}") + tdLog.printNoPrefix(f"When lossyColumns value is float and double, data size is: {dsize_float_double}") + tdLog.printNoPrefix(f"When lossyColumns is closed, data size is: {dsize_init}") + tdLog.exit("压缩未生效") + else: + tdLog.printNoPrefix(f"When lossyColumns value is float, data size is: {dsize_float}") + tdLog.printNoPrefix(f"When lossyColumns value is double, data size is: {dsize_double}") + tdLog.printNoPrefix(f"When lossyColumns value is float and double, data size is: {dsize_float_double}") + tdLog.printNoPrefix(f"When lossyColumns is closed, data size is: {dsize_init}") + tdLog.printNoPrefix("压缩生效") + + pass + + def td5433(self): + tdLog.printNoPrefix("==========TD-5433==========") + tdSql.execute("drop database if exists db") + tdSql.execute("create database if not exists db keep 3650") + + tdSql.execute("use db") + tdSql.execute("create stable db.stb1 (ts timestamp, c1 int) tags(t0 tinyint, t1 int)") + tdSql.execute("create stable db.stb2 (ts timestamp, c1 int) tags(t0 binary(16), t1 binary(16))") + numtab=2000000 + for i in range(numtab): + sql = f"create table db.t{i} using db.stb1 tags({i%128}, {100+i})" + tdSql.execute(sql) + tdSql.execute(f"insert into db.t{i} values (now-10d, {i})") + tdSql.execute(f"insert into db.t{i} values (now-9d, {i*2})") + tdSql.execute(f"insert into db.t{i} values (now-8d, {i*3})") + + tdSql.execute("create table db.t01 using db.stb2 tags('1', '100')") + tdSql.execute("create table db.t02 using db.stb2 tags('2', '200')") + tdSql.execute("create table db.t03 using db.stb2 tags('3', '300')") + tdSql.execute("create table db.t04 using db.stb2 tags('4', '400')") + tdSql.execute("create table db.t05 using db.stb2 tags('5', '500')") + + tdSql.query("select distinct t1 from stb1 where t1 != '150'") + tdSql.checkRows(numtab-1) + tdSql.query("select distinct t1 from stb1 where t1 != 150") + tdSql.checkRows(numtab-1) + tdSql.query("select distinct t1 from stb1 where t1 = 150") + tdSql.checkRows(1) + tdSql.query("select distinct t1 from stb1 where t1 = '150'") + tdSql.checkRows(1) + tdSql.query("select distinct t1 from stb1") + tdSql.checkRows(numtab) + + tdSql.query("select distinct t0 from stb1 where t0 != '2'") + tdSql.checkRows(127) + tdSql.query("select distinct t0 from stb1 where t0 != 2") + tdSql.checkRows(127) + tdSql.query("select distinct t0 from stb1 where t0 = 2") + tdSql.checkRows(1) + tdSql.query("select distinct t0 from stb1 where t0 = '2'") + tdSql.checkRows(1) + tdSql.query("select distinct t0 from stb1") + tdSql.checkRows(128) + + tdSql.query("select distinct t1 from stb2 where t1 != '200'") + tdSql.checkRows(4) + tdSql.query("select distinct t1 from stb2 where t1 != 200") + tdSql.checkRows(4) + tdSql.query("select distinct t1 from stb2 where t1 = 200") + tdSql.checkRows(1) + tdSql.query("select distinct t1 from stb2 where t1 = '200'") + tdSql.checkRows(1) + tdSql.query("select distinct t1 from stb2") + tdSql.checkRows(5) + + tdSql.query("select distinct t0 from stb2 where t0 != '2'") + tdSql.checkRows(4) + tdSql.query("select distinct t0 from stb2 where t0 != 2") + tdSql.checkRows(4) + tdSql.query("select distinct t0 from stb2 where t0 = 2") + tdSql.checkRows(1) + tdSql.query("select distinct t0 from stb2 where t0 = '2'") + tdSql.checkRows(1) + tdSql.query("select distinct t0 from stb2") + tdSql.checkRows(5) + + pass + + def td5798(self): + tdLog.printNoPrefix("==========TD-5798 + TD-5810==========") + tdSql.execute("drop database if exists db") + tdSql.execute("create database if not exists db keep 3650") + + tdSql.execute("use db") + tdSql.execute("create stable db.stb1 (ts timestamp, c1 int, c2 int) tags(t0 tinyint, t1 int, t2 int)") + tdSql.execute("create stable db.stb2 (ts timestamp, c2 int, c3 binary(16)) tags(t2 binary(16), t3 binary(16), t4 int)") + maxRemainderNum=7 + tbnum=101 + for i in range(tbnum-1): + sql = f"create table db.t{i} using db.stb1 tags({i%maxRemainderNum}, {(i-1)%maxRemainderNum}, {i%2})" + tdSql.execute(sql) + tdSql.execute(f"insert into db.t{i} values (now-10d, {i}, {i%3})") + tdSql.execute(f"insert into db.t{i} values (now-9d, {i}, {(i-1)%3})") + tdSql.execute(f"insert into db.t{i} values (now-8d, {i}, {(i-2)%3})") + tdSql.execute(f"insert into db.t{i} (ts )values (now-7d)") + + tdSql.execute(f"create table db.t0{i} using db.stb2 tags('{i%maxRemainderNum}', '{(i-1)%maxRemainderNum}', {i%3})") + tdSql.execute(f"insert into db.t0{i} values (now-10d, {i}, '{(i+1)%3}')") + tdSql.execute(f"insert into db.t0{i} values (now-9d, {i}, '{(i+2)%3}')") + tdSql.execute(f"insert into db.t0{i} values (now-8d, {i}, '{(i)%3}')") + tdSql.execute(f"insert into db.t0{i} (ts )values (now-7d)") + tdSql.execute("create table db.t100num using db.stb1 tags(null, null, null)") + tdSql.execute("create table db.t0100num using db.stb2 tags(null, null, null)") + tdSql.execute(f"insert into db.t100num values (now-10d, {tbnum-1}, 1)") + tdSql.execute(f"insert into db.t100num values (now-9d, {tbnum-1}, 0)") + tdSql.execute(f"insert into db.t100num values (now-8d, {tbnum-1}, 2)") + tdSql.execute(f"insert into db.t100num (ts )values (now-7d)") + tdSql.execute(f"insert into db.t0100num values (now-10d, {tbnum-1}, 1)") + tdSql.execute(f"insert into db.t0100num values (now-9d, {tbnum-1}, 0)") + tdSql.execute(f"insert into db.t0100num values (now-8d, {tbnum-1}, 2)") + tdSql.execute(f"insert into db.t0100num (ts )values (now-7d)") + + #========== TD-5810 suport distinct multi-data-coloumn ========== + tdSql.query(f"select distinct c1 from stb1 where c1 <{tbnum}") + tdSql.checkRows(tbnum) + tdSql.query(f"select distinct c2 from stb1") + tdSql.checkRows(4) + tdSql.query(f"select distinct c1,c2 from stb1 where c1 <{tbnum}") + tdSql.checkRows(tbnum*3) + tdSql.query(f"select distinct c1,c1 from stb1 where c1 <{tbnum}") + tdSql.checkRows(tbnum) + tdSql.query(f"select distinct c1,c2 from stb1 where c1 <{tbnum} limit 3") + tdSql.checkRows(3) + tdSql.query(f"select distinct c1,c2 from stb1 where c1 <{tbnum} limit 3 offset {tbnum*3-2}") + tdSql.checkRows(2) + + tdSql.query(f"select distinct c1 from t1 where c1 <{tbnum}") + tdSql.checkRows(1) + tdSql.query(f"select distinct c2 from t1") + tdSql.checkRows(4) + tdSql.query(f"select distinct c1,c2 from t1 where c1 <{tbnum}") + tdSql.checkRows(3) + tdSql.query(f"select distinct c1,c1 from t1 ") + tdSql.checkRows(2) + tdSql.query(f"select distinct c1,c1 from t1 where c1 <{tbnum}") + tdSql.checkRows(1) + tdSql.query(f"select distinct c1,c2 from t1 where c1 <{tbnum} limit 3") + tdSql.checkRows(3) + tdSql.query(f"select distinct c1,c2 from t1 where c1 <{tbnum} limit 3 offset 2") + tdSql.checkRows(1) + + tdSql.query(f"select distinct c3 from stb2 where c2 <{tbnum} ") + tdSql.checkRows(3) + tdSql.query(f"select distinct c3, c2 from stb2 where c2 <{tbnum} limit 2") + tdSql.checkRows(2) + + tdSql.error("select distinct c5 from stb1") + tdSql.error("select distinct c5 from t1") + tdSql.error("select distinct c1 from db.*") + tdSql.error("select c2, distinct c1 from stb1") + tdSql.error("select c2, distinct c1 from t1") + tdSql.error("select distinct c2 from ") + tdSql.error("distinct c2 from stb1") + tdSql.error("distinct c2 from t1") + tdSql.error("select distinct c1, c2, c3 from stb1") + tdSql.error("select distinct c1, c2, c3 from t1") + tdSql.error("select distinct stb1.c1, stb1.c2, stb2.c2, stb2.c3 from stb1") + tdSql.error("select distinct stb1.c1, stb1.c2, stb2.c2, stb2.c3 from t1") + tdSql.error("select distinct t1.c1, t1.c2, t2.c1, t2.c2 from t1") + tdSql.query(f"select distinct c1 c2, c2 c3 from stb1 where c1 <{tbnum}") + tdSql.checkRows(tbnum*3) + tdSql.query(f"select distinct c1 c2, c2 c3 from t1 where c1 <{tbnum}") + tdSql.checkRows(3) + tdSql.error("select distinct c1, c2 from stb1 order by ts") + #tdSql.checkRows(tbnum*3+1) + tdSql.error("select distinct c1, c2 from t1 order by ts") + #tdSql.checkRows(4) + tdSql.error("select distinct c1, ts from stb1 group by c2") + tdSql.error("select distinct c1, ts from t1 group by c2") + tdSql.error("select distinct c1, max(c2) from stb1 ") + tdSql.error("select distinct c1, max(c2) from t1 ") + tdSql.error("select max(c2), distinct c1 from stb1 ") + tdSql.error("select max(c2), distinct c1 from t1 ") + tdSql.error("select distinct c1, c2 from stb1 where c1 > 3 group by t0") + tdSql.error("select distinct c1, c2 from t1 where c1 > 3 group by t0") + tdSql.error("select distinct c1, c2 from stb1 where c1 > 3 interval(1d) ") + tdSql.error("select distinct c1, c2 from t1 where c1 > 3 interval(1d) ") + tdSql.error("select distinct c1, c2 from stb1 where c1 > 3 interval(1d) fill(next)") + tdSql.error("select distinct c1, c2 from t1 where c1 > 3 interval(1d) fill(next)") + tdSql.error("select distinct c1, c2 from stb1 where ts > now-10d and ts < now interval(1d) fill(next)") + tdSql.error("select distinct c1, c2 from t1 where ts > now-10d and ts < now interval(1d) fill(next)") + tdSql.error("select distinct c1, c2 from stb1 where c1 > 3 slimit 1") + tdSql.error("select distinct c1, c2 from t1 where c1 > 3 slimit 1") + tdSql.query(f"select distinct c1, c2 from stb1 where c1 between {tbnum-2} and {tbnum} ") + tdSql.checkRows(6) + tdSql.query("select distinct c1, c2 from stb1 where c1 in (1,2,3,4,5)") + tdSql.checkRows(15) + tdSql.query("select distinct c1, c2 from stb1 where c1 in (100,1000,10000)") + tdSql.checkRows(3) + + tdSql.query(f"select distinct c1,c2 from (select * from stb1 where c1 > {tbnum-2}) ") + tdSql.checkRows(3) + tdSql.query(f"select distinct c1,c2 from (select * from t1 where c1 < {tbnum}) ") + tdSql.checkRows(3) + tdSql.query(f"select distinct c1,c2 from (select * from stb1 where t2 !=0 and t2 != 1) ") + tdSql.checkRows(4) + tdSql.error("select distinct c1, c2 from (select distinct c1, c2 from stb1 where t0 > 2 and t1 < 3) ") + tdSql.error("select c1, c2 from (select distinct c1, c2 from stb1 where t0 > 2 and t1 < 3) ") + tdSql.query("select distinct c1, c2 from (select c2, c1 from stb1 where c1 > 2 ) where c1 < 4") + tdSql.checkRows(3) + tdSql.error("select distinct c1, c2 from (select c1 from stb1 where t0 > 2 ) where t1 < 3") + tdSql.error("select distinct c1, c2 from (select c2, c1 from stb1 where c1 > 2 order by ts)") + # tdSql.error("select distinct c1, c2 from (select c2, c1 from t1 where c1 > 2 order by ts)") + tdSql.error("select distinct c1, c2 from (select c2, c1 from stb1 where c1 > 2 group by c1)") + # tdSql.error("select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from stb1 group by c1)") + # tdSql.error("select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from t1 group by c1)") + tdSql.query("select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from stb1 )") + tdSql.checkRows(1) + tdSql.query("select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from t1 )") + tdSql.checkRows(1) + tdSql.error("select distinct stb1.c1, stb1.c2 from stb1 , stb2 where stb1.ts=stb2.ts and stb1.t2=stb2.t4") + tdSql.error("select distinct t1.c1, t1.c2 from t1 , t2 where t1.ts=t2.ts ") + + # tdSql.error("select distinct c1, c2 from (select count(c1) c1, count(c2) c2 from stb1 group by ts)") + # tdSql.error("select distinct c1, c2 from (select count(c1) c1, count(c2) c2 from t1 group by ts)") + + + + #========== TD-5798 suport distinct multi-tags-coloumn ========== + tdSql.query("select distinct t1 from stb1") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t0, t1 from stb1") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t1, t0 from stb1") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t1, t2 from stb1") + tdSql.checkRows(maxRemainderNum*2+1) + tdSql.query("select distinct t0, t1, t2 from stb1") + tdSql.checkRows(maxRemainderNum*2+1) + tdSql.query("select distinct t0 t1, t1 t2 from stb1") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t0, t0, t0 from stb1") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t0, t1 from t1") + tdSql.checkRows(1) + tdSql.query("select distinct t0, t1 from t100num") + tdSql.checkRows(1) + + tdSql.query("select distinct t3 from stb2") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t2, t3 from stb2") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t3, t2 from stb2") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t4, t2 from stb2") + tdSql.checkRows(maxRemainderNum*3+1) + tdSql.query("select distinct t2, t3, t4 from stb2") + tdSql.checkRows(maxRemainderNum*3+1) + tdSql.query("select distinct t2 t1, t3 t2 from stb2") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t3, t3, t3 from stb2") + tdSql.checkRows(maxRemainderNum+1) + tdSql.query("select distinct t2, t3 from t01") + tdSql.checkRows(1) + tdSql.query("select distinct t3, t4 from t0100num") + tdSql.checkRows(1) + + + ########## should be error ######### + tdSql.error("select distinct from stb1") + tdSql.error("select distinct t3 from stb1") + tdSql.error("select distinct t1 from db.*") + tdSql.error("select distinct t2 from ") + tdSql.error("distinct t2 from stb1") + tdSql.error("select distinct stb1") + tdSql.error("select distinct t0, t1, t2, t3 from stb1") + tdSql.error("select distinct stb1.t0, stb1.t1, stb2.t2, stb2.t3 from stb1") + + tdSql.error("select dist t0 from stb1") + tdSql.error("select distinct stb2.t2, stb2.t3 from stb1") + tdSql.error("select distinct stb2.t2 t1, stb2.t3 t2 from stb1") + + tdSql.error("select distinct t0, t1 from t1 where t0 < 7") + + ########## add where condition ########## + tdSql.query("select distinct t0, t1 from stb1 where t1 > 3") + tdSql.checkRows(3) + tdSql.query("select distinct t0, t1 from stb1 where t1 > 3 limit 2") + tdSql.checkRows(2) + tdSql.query("select distinct t0, t1 from stb1 where t1 > 3 limit 2 offset 2") + tdSql.checkRows(1) + tdSql.query("select distinct t0, t1 from stb1 where t1 > 3 slimit 2") + tdSql.checkRows(3) + tdSql.error("select distinct t0, t1 from stb1 where c1 > 2") + tdSql.query("select distinct t0, t1 from stb1 where t1 > 3 and t1 < 5") + tdSql.checkRows(1) + tdSql.error("select distinct stb1.t0, stb1.t1 from stb1, stb2 where stb1.t2=stb2.t4") + tdSql.error("select distinct t0, t1 from stb1 where stb2.t4 > 2") + tdSql.error("select distinct t0, t1 from stb1 where t1 > 3 group by t0") + tdSql.error("select distinct t0, t1 from stb1 where t1 > 3 interval(1d) ") + tdSql.error("select distinct t0, t1 from stb1 where t1 > 3 interval(1d) fill(next)") + tdSql.error("select distinct t0, t1 from stb1 where ts > now-10d and ts < now interval(1d) fill(next)") + + tdSql.error("select max(c1), distinct t0 from stb1 where t0 > 2") + tdSql.error("select distinct t0, max(c1) from stb1 where t0 > 2") + tdSql.error("select distinct t0 from stb1 where t0 in (select t0 from stb1 where t0 > 2)") + tdSql.query("select distinct t0, t1 from stb1 where t0 in (1,2,3,4,5)") + tdSql.checkRows(5) + tdSql.query("select distinct t1 from (select t0, t1 from stb1 where t0 > 2) ") + tdSql.checkRows(4) + tdSql.error("select distinct t1 from (select distinct t0, t1 from stb1 where t0 > 2 and t1 < 3) ") + tdSql.error("select distinct t1 from (select distinct t0, t1 from stb1 where t0 > 2 ) where t1 < 3") + tdSql.query("select distinct t1 from (select t0, t1 from stb1 where t0 > 2 ) where t1 < 3") + tdSql.checkRows(1) + tdSql.error("select distinct t1, t0 from (select t1 from stb1 where t0 > 2 ) where t1 < 3") + tdSql.error("select distinct t1, t0 from (select max(t1) t1, max(t0) t0 from stb1 group by t1)") + tdSql.error("select distinct t1, t0 from (select max(t1) t1, max(t0) t0 from stb1)") + tdSql.query("select distinct t1, t0 from (select t1,t0 from stb1 where t0 > 2 ) where t1 < 3") + tdSql.checkRows(1) + tdSql.error(" select distinct t1, t0 from (select t1,t0 from stb1 where t0 > 2 order by ts) where t1 < 3") + tdSql.error("select t1, t0 from (select distinct t1,t0 from stb1 where t0 > 2 ) where t1 < 3") + tdSql.error(" select distinct t1, t0 from (select t1,t0 from stb1 where t0 > 2 group by ts) where t1 < 3") + tdSql.error("select distinct stb1.t1, stb1.t2 from stb1 , stb2 where stb1.ts=stb2.ts and stb1.t2=stb2.t4") + tdSql.error("select distinct t1.t1, t1.t2 from t1 , t2 where t1.ts=t2.ts ") + + pass + + def td5935(self): + tdLog.printNoPrefix("==========TD-5935==========") + tdSql.execute("drop database if exists db") + tdSql.execute("create database if not exists db keep 3650") + + tdSql.execute("use db") + tdSql.execute("create stable db.stb1 (ts timestamp, c1 int, c2 float) tags(t1 int, t2 int)") + nowtime=int(round((time.time()*1000))) + for i in range(100): + sql = f"create table db.t{i} using db.stb1 tags({i % 7}, {i % 2})" + tdSql.execute(sql) + for j in range(1000): + tdSql.execute(f"insert into db.t{i} values ({nowtime-j*10}, {1000-j}, {round(random.random()*j,3)})") + tdSql.execute(f"insert into db.t{i} (ts) values ({nowtime-10000}) ") + + ########### TD-5933 verify the bug of "function stddev with interval return 0 rows" is fixed ########## + stddevAndIntervalSql=f"select last(*) from t0 where ts>={nowtime-10000} interval(10a) limit 10" + tdSql.query(stddevAndIntervalSql) + tdSql.checkRows(10) + + ########## TD-5978 verify the bug of "when start row is null, result by fill(next) is 0 " is fixed ########## + fillsql=f"select last(*) from t0 where ts>={nowtime-10000} and ts<{nowtime} interval(10a) fill(next) limit 10" + tdSql.query(fillsql) + fillResult=False + if (tdSql.getData(0,2) != 0) and (tdSql.getData(0, 2) is not None): + fillResult=True + if fillResult: + tdLog.success(f"sql is :{fillsql}, fill(next) is correct") + else: + tdLog.exit("fill(next) is wrong") + + pass + + def td6068(self): + tdLog.printNoPrefix("==========TD-6068==========") + tdSql.execute("drop database if exists db") + tdSql.execute("create database if not exists db keep 3650") + tdSql.execute("use db") + + tdSql.execute("create stable db.stb1 (ts timestamp, c1 int, c2 float, c3 timestamp, c4 binary(16), c5 double, c6 bool) tags(t1 int)") + + for i in range(100): + sql = f"create table db.t{i} using db.stb1 tags({i})" + tdSql.execute(sql) + tdSql.execute(f"insert into db.t{i} values (now-10h, {i}, {i+random.random()}, now-10h, 'a_{i}', '{i-random.random()}', True)") + tdSql.execute(f"insert into db.t{i} values (now-9h, {i+random.randint(1,10)}, {i+random.random()}, now-9h, 'a_{i}', '{i-random.random()}', FALSE )") + tdSql.execute(f"insert into db.t{i} values (now-8h, {i+random.randint(1,10)}, {i+random.random()}, now-8h, 'b_{i}', '{i-random.random()}', True)") + tdSql.execute(f"insert into db.t{i} values (now-7h, {i+random.randint(1,10)}, {i+random.random()}, now-7h, 'b_{i}', '{i-random.random()}', FALSE )") + tdSql.execute(f"insert into db.t{i} values (now-6h, {i+random.randint(1,10)}, {i+random.random()}, now-6h, 'c_{i}', '{i-random.random()}', True)") + tdSql.execute(f"insert into db.t{i} values (now-5h, {i+random.randint(1,10)}, {i+random.random()}, now-5h, 'c_{i}', '{i-random.random()}', FALSE )") + tdSql.execute(f"insert into db.t{i} (ts)values (now-4h)") + tdSql.execute(f"insert into db.t{i} (ts)values (now-11h)") + tdSql.execute(f"insert into db.t{i} (ts)values (now-450m)") + + tdSql.query("select ts as t,derivative(c1, 10m, 0) from t1") + tdSql.checkRows(5) + tdSql.checkCols(3) + for i in range(5): + data=tdSql.getData(i, 0) + tdSql.checkData(i, 1, data) + tdSql.query("select ts as t, derivative(c1, 1h, 0) from stb1 group by tbname") + tdSql.checkRows(500) + tdSql.checkCols(4) + tdSql.query("select ts as t, derivative(c1, 1s, 0) from t1") + tdSql.query("select ts as t, derivative(c1, 1d, 0) from t1") + tdSql.error("select ts as t, derivative(c1, 1h, 0) from stb1") + tdSql.query("select ts as t, derivative(c2, 1h, 0) from t1") + tdSql.checkRows(5) + tdSql.error("select ts as t, derivative(c3, 1h, 0) from t1") + tdSql.error("select ts as t, derivative(c4, 1h, 0) from t1") + tdSql.query("select ts as t, derivative(c5, 1h, 0) from t1") + tdSql.checkRows(5) + tdSql.error("select ts as t, derivative(c6, 1h, 0) from t1") + tdSql.error("select ts as t, derivative(t1, 1h, 0) from t1") + + tdSql.query("select ts as t, diff(c1) from t1") + tdSql.checkRows(5) + tdSql.checkCols(3) + for i in range(5): + data=tdSql.getData(i, 0) + tdSql.checkData(i, 1, data) + tdSql.query("select ts as t, diff(c1) from stb1 group by tbname") + tdSql.checkRows(500) + tdSql.checkCols(4) + tdSql.query("select ts as t, diff(c1) from t1") + tdSql.query("select ts as t, diff(c1) from t1") + tdSql.error("select ts as t, diff(c1) from stb1") + tdSql.query("select ts as t, diff(c2) from t1") + tdSql.checkRows(5) + tdSql.error("select ts as t, diff(c3) from t1") + tdSql.error("select ts as t, diff(c4) from t1") + tdSql.query("select ts as t, diff(c5) from t1") + tdSql.checkRows(5) + tdSql.error("select ts as t, diff(c6) from t1") + tdSql.error("select ts as t, diff(t1) from t1") + tdSql.error("select ts as t, diff(c1, c2) from t1") + + tdSql.error("select ts as t, bottom(c1, 0) from t1") + tdSql.query("select ts as t, bottom(c1, 5) from t1") + tdSql.checkRows(5) + tdSql.checkCols(3) + for i in range(5): + data=tdSql.getData(i, 0) + tdSql.checkData(i, 1, data) + tdSql.query("select ts as t, bottom(c1, 5) from stb1") + tdSql.checkRows(5) + tdSql.query("select ts as t, bottom(c1, 5) from stb1 group by tbname") + tdSql.checkRows(500) + tdSql.query("select ts as t, bottom(c1, 8) from t1") + tdSql.checkRows(6) + tdSql.query("select ts as t, bottom(c2, 8) from t1") + tdSql.checkRows(6) + tdSql.error("select ts as t, bottom(c3, 5) from t1") + tdSql.error("select ts as t, bottom(c4, 5) from t1") + tdSql.query("select ts as t, bottom(c5, 8) from t1") + tdSql.checkRows(6) + tdSql.error("select ts as t, bottom(c6, 5) from t1") + tdSql.error("select ts as t, bottom(c5, 8) as b from t1 order by b") + tdSql.error("select ts as t, bottom(t1, 1) from t1") + tdSql.error("select ts as t, bottom(t1, 1) from stb1") + tdSql.error("select ts as t, bottom(t1, 3) from stb1 order by c3") + tdSql.error("select ts as t, bottom(t1, 3) from t1 order by c3") + + + tdSql.error("select ts as t, top(c1, 0) from t1") + tdSql.query("select ts as t, top(c1, 5) from t1") + tdSql.checkRows(5) + tdSql.checkCols(3) + for i in range(5): + data=tdSql.getData(i, 0) + tdSql.checkData(i, 1, data) + tdSql.query("select ts as t, top(c1, 5) from stb1") + tdSql.checkRows(5) + tdSql.query("select ts as t, top(c1, 5) from stb1 group by tbname") + tdSql.checkRows(500) + tdSql.query("select ts as t, top(c1, 8) from t1") + tdSql.checkRows(6) + tdSql.query("select ts as t, top(c2, 8) from t1") + tdSql.checkRows(6) + tdSql.error("select ts as t, top(c3, 5) from t1") + tdSql.error("select ts as t, top(c4, 5) from t1") + tdSql.query("select ts as t, top(c5, 8) from t1") + tdSql.checkRows(6) + tdSql.error("select ts as t, top(c6, 5) from t1") + tdSql.error("select ts as t, top(c5, 8) as b from t1 order by b") + tdSql.error("select ts as t, top(t1, 1) from t1") + tdSql.error("select ts as t, top(t1, 1) from stb1") + tdSql.error("select ts as t, top(t1, 3) from stb1 order by c3") + tdSql.error("select ts as t, top(t1, 3) from t1 order by c3") + + pass + + def run(self): # master branch # self.td3690() # self.td4082() # self.td4288() - self.td4724() + # self.td4724() + # self.td5798() + # self.td5935() + self.td6068() # develop branch # self.td4097() - + # self.td4889() + # self.td5168() + # self.td5433() def stop(self): tdSql.close() diff --git a/tests/pytest/insert/insertFromCSVPerformance.py b/tests/pytest/insert/insertFromCSVPerformance.py index f3b9c2734d321fb8c9d374ee16fd7ee99388bc36..487497631a368778c857ce71234a4574837390c1 100644 --- a/tests/pytest/insert/insertFromCSVPerformance.py +++ b/tests/pytest/insert/insertFromCSVPerformance.py @@ -28,7 +28,7 @@ class insertFromCSVPerformace: self.tbName = tbName self.branchName = branchName self.type = buildType - self.ts = 1500074556514 + self.ts = 1500000000000 self.host = "127.0.0.1" self.user = "root" self.password = "taosdata" @@ -46,13 +46,20 @@ class insertFromCSVPerformace: config = self.config) def writeCSV(self): - with open('test3.csv','w', encoding='utf-8', newline='') as csvFile: + tsset = set() + rows = 0 + with open('test4.csv','w', encoding='utf-8', newline='') as csvFile: writer = csv.writer(csvFile, dialect='excel') - for i in range(1000000): - newTimestamp = self.ts + random.randint(10000000, 10000000000) + random.randint(1000, 10000000) + random.randint(1, 1000) - d = datetime.datetime.fromtimestamp(newTimestamp / 1000) - dt = str(d.strftime("%Y-%m-%d %H:%M:%S.%f")) - writer.writerow(["'%s'" % dt, random.randint(1, 100), random.uniform(1, 100), random.randint(1, 100), random.randint(1, 100)]) + while True: + newTimestamp = self.ts + random.randint(1, 10) * 10000000000 + random.randint(1, 10) * 1000000000 + random.randint(1, 10) * 100000000 + random.randint(1, 10) * 10000000 + random.randint(1, 10) * 1000000 + random.randint(1, 10) * 100000 + random.randint(1, 10) * 10000 + random.randint(1, 10) * 1000 + random.randint(1, 10) * 100 + random.randint(1, 10) * 10 + random.randint(1, 10) + if newTimestamp not in tsset: + tsset.add(newTimestamp) + d = datetime.datetime.fromtimestamp(newTimestamp / 1000) + dt = str(d.strftime("%Y-%m-%d %H:%M:%S.%f")) + writer.writerow(["'%s'" % dt, random.randint(1, 100), random.uniform(1, 100), random.randint(1, 100), random.randint(1, 100)]) + rows += 1 + if rows == 2000000: + break def removCSVHeader(self): data = pd.read_csv("ordered.csv") @@ -71,7 +78,9 @@ class insertFromCSVPerformace: cursor.execute("create table if not exists t1(ts timestamp, c1 int, c2 float, c3 int, c4 int)") startTime = time.time() cursor.execute("insert into t1 file 'outoforder.csv'") - totalTime += time.time() - startTime + totalTime += time.time() - startTime + time.sleep(1) + out_of_order_time = (float) (totalTime / 10) print("Out of Order - Insert time: %f" % out_of_order_time) @@ -81,7 +90,8 @@ class insertFromCSVPerformace: cursor.execute("create table if not exists t2(ts timestamp, c1 int, c2 float, c3 int, c4 int)") startTime = time.time() cursor.execute("insert into t2 file 'ordered.csv'") - totalTime += time.time() - startTime + totalTime += time.time() - startTime + time.sleep(1) in_order_time = (float) (totalTime / 10) print("In order - Insert time: %f" % in_order_time) diff --git a/tests/pytest/insert/insertTelnetLines.py b/tests/pytest/insert/insertTelnetLines.py new file mode 100644 index 0000000000000000000000000000000000000000..8ebb6bd3df4bcd4abfbb8c42cf5024fe066fcce3 --- /dev/null +++ b/tests/pytest/insert/insertTelnetLines.py @@ -0,0 +1,313 @@ +################################################################### +# Copyright (c) 2021 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +from util.log import * +from util.cases import * +from util.sql import * + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + self._conn = conn + + def run(self): + print("running {}".format(__file__)) + tdSql.execute("drop database if exists test") + tdSql.execute("create database if not exists test precision 'us'") + tdSql.execute('use test') + + + ### metric ### + print("============= step1 : test metric ================") + lines0 = [ + "stb0_0 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"", + "stb0_1 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"", + "stb0_2 1626006833639000000ns 4i8 host=\"host0\",interface=\"eth0\"", + ] + + code = self._conn.insert_telnet_lines(lines0) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("show stables") + tdSql.checkRows(3) + + tdSql.query("describe stb0_0") + tdSql.checkRows(4) + + tdSql.query("describe stb0_1") + tdSql.checkRows(4) + + tdSql.query("describe stb0_2") + tdSql.checkRows(4) + + ### timestamp ### + print("============= step2 : test timestamp ================") + lines1 = [ + "stb1 1626006833s 1i8 host=\"host0\"", + "stb1 1626006833639000000ns 2i8 host=\"host0\"", + "stb1 1626006833640000us 3i8 host=\"host0\"", + "stb1 1626006833641123 4i8 host=\"host0\"", + "stb1 1626006833651ms 5i8 host=\"host0\"", + "stb1 0 6i8 host=\"host0\"", + ] + + code = self._conn.insert_telnet_lines(lines1) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb1") + tdSql.checkRows(6) + + ### metric value ### + print("============= step3 : test metric value ================") + + #tinyint + lines2_0 = [ + "stb2_0 1626006833651ms -127i8 host=\"host0\"", + "stb2_0 1626006833652ms 127i8 host=\"host0\"" + ] + code = self._conn.insert_telnet_lines(lines2_0) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb2_0") + tdSql.checkRows(2) + + tdSql.query("describe stb2_0") + tdSql.checkRows(3) + tdSql.checkData(1, 1, "TINYINT") + + #smallint + lines2_1 = [ + "stb2_1 1626006833651ms -32767i16 host=\"host0\"", + "stb2_1 1626006833652ms 32767i16 host=\"host0\"" + ] + code = self._conn.insert_telnet_lines(lines2_1) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb2_1") + tdSql.checkRows(2) + + tdSql.query("describe stb2_1") + tdSql.checkRows(3) + tdSql.checkData(1, 1, "SMALLINT") + + #int + lines2_2 = [ + "stb2_2 1626006833651ms -2147483647i32 host=\"host0\"", + "stb2_2 1626006833652ms 2147483647i32 host=\"host0\"" + ] + + code = self._conn.insert_telnet_lines(lines2_2) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb2_2") + tdSql.checkRows(2) + + tdSql.query("describe stb2_2") + tdSql.checkRows(3) + tdSql.checkData(1, 1, "INT") + + #bigint + lines2_3 = [ + "stb2_3 1626006833651ms -9223372036854775807i64 host=\"host0\"", + "stb2_3 1626006833652ms 9223372036854775807i64 host=\"host0\"" + ] + + code = self._conn.insert_telnet_lines(lines2_3) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb2_3") + tdSql.checkRows(2) + + tdSql.query("describe stb2_3") + tdSql.checkRows(3) + tdSql.checkData(1, 1, "BIGINT") + + #float + lines2_4 = [ + "stb2_4 1626006833610ms 3f32 host=\"host0\"", + "stb2_4 1626006833620ms -3f32 host=\"host0\"", + "stb2_4 1626006833630ms 3.4f32 host=\"host0\"", + "stb2_4 1626006833640ms -3.4f32 host=\"host0\"", + "stb2_4 1626006833650ms 3.4E10f32 host=\"host0\"", + "stb2_4 1626006833660ms -3.4e10f32 host=\"host0\"", + "stb2_4 1626006833670ms 3.4E+2f32 host=\"host0\"", + "stb2_4 1626006833680ms -3.4e-2f32 host=\"host0\"", + "stb2_4 1626006833690ms 3.15 host=\"host0\"", + "stb2_4 1626006833700ms 3.4E38f32 host=\"host0\"", + "stb2_4 1626006833710ms -3.4E38f32 host=\"host0\"" + ] + + code = self._conn.insert_telnet_lines(lines2_4) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb2_4") + tdSql.checkRows(11) + + tdSql.query("describe stb2_4") + tdSql.checkRows(3) + tdSql.checkData(1, 1, "FLOAT") + + #double + lines2_5 = [ + "stb2_5 1626006833610ms 3f64 host=\"host0\"", + "stb2_5 1626006833620ms -3f64 host=\"host0\"", + "stb2_5 1626006833630ms 3.4f64 host=\"host0\"", + "stb2_5 1626006833640ms -3.4f64 host=\"host0\"", + "stb2_5 1626006833650ms 3.4E10f64 host=\"host0\"", + "stb2_5 1626006833660ms -3.4e10f64 host=\"host0\"", + "stb2_5 1626006833670ms 3.4E+2f64 host=\"host0\"", + "stb2_5 1626006833680ms -3.4e-2f64 host=\"host0\"", + "stb2_5 1626006833690ms 1.7E308f64 host=\"host0\"", + "stb2_5 1626006833700ms -1.7E308f64 host=\"host0\"" + ] + + code = self._conn.insert_telnet_lines(lines2_5) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb2_5") + tdSql.checkRows(10) + + tdSql.query("describe stb2_5") + tdSql.checkRows(3) + tdSql.checkData(1, 1, "DOUBLE") + + #bool + lines2_6 = [ + "stb2_6 1626006833610ms t host=\"host0\"", + "stb2_6 1626006833620ms T host=\"host0\"", + "stb2_6 1626006833630ms true host=\"host0\"", + "stb2_6 1626006833640ms True host=\"host0\"", + "stb2_6 1626006833650ms TRUE host=\"host0\"", + "stb2_6 1626006833660ms f host=\"host0\"", + "stb2_6 1626006833670ms F host=\"host0\"", + "stb2_6 1626006833680ms false host=\"host0\"", + "stb2_6 1626006833690ms False host=\"host0\"", + "stb2_6 1626006833700ms FALSE host=\"host0\"" + ] + + code = self._conn.insert_telnet_lines(lines2_6) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb2_6") + tdSql.checkRows(10) + + tdSql.query("describe stb2_6") + tdSql.checkRows(3) + tdSql.checkData(1, 1, "BOOL") + + #binary + lines2_7 = [ + "stb2_7 1626006833610ms \"binary_val.!@#$%^&*\" host=\"host0\"", + "stb2_7 1626006833620ms \"binary_val.:;,./?|+-=\" host=\"host0\"", + "stb2_7 1626006833630ms \"binary_val.()[]{}<>\" host=\"host0\"" + ] + + code = self._conn.insert_telnet_lines(lines2_7) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb2_7") + tdSql.checkRows(3) + + tdSql.query("describe stb2_7") + tdSql.checkRows(3) + tdSql.checkData(1, 1, "BINARY") + + #nchar + lines2_8 = [ + "stb2_8 1626006833610ms L\"nchar_val数值一\" host=\"host0\"", + "stb2_8 1626006833620ms L\"nchar_val数值二\" host=\"host0\"" + ] + + code = self._conn.insert_telnet_lines(lines2_8) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb2_8") + tdSql.checkRows(2) + + tdSql.query("describe stb2_8") + tdSql.checkRows(3) + tdSql.checkData(1, 1, "NCHAR") + + ### tags ### + print("============= step3 : test tags ================") + #tag value types + lines3_0 = [ + "stb3_0 1626006833610ms 1 t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=3.4E38f32,t6=1.7E308f64,t7=true,t8=\"binary_val_1\",t9=L\"标签值1\"", + "stb3_0 1626006833610ms 2 t1=-127i8,t2=-32767i16,t3=-2147483647i32,t4=-9223372036854775807i64,t5=-3.4E38f32,t6=-1.7E308f64,t7=false,t8=\"binary_val_2\",t9=L\"标签值2\"" + ] + + code = self._conn.insert_telnet_lines(lines3_0) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb3_0") + tdSql.checkRows(2) + + tdSql.query("describe stb3_0") + tdSql.checkRows(11) + + tdSql.checkData(2, 1, "TINYINT") + tdSql.checkData(2, 3, "TAG") + + tdSql.checkData(3, 1, "SMALLINT") + tdSql.checkData(3, 3, "TAG") + + tdSql.checkData(4, 1, "INT") + tdSql.checkData(4, 3, "TAG") + + tdSql.checkData(5, 1, "BIGINT") + tdSql.checkData(5, 3, "TAG") + + tdSql.checkData(6, 1, "FLOAT") + tdSql.checkData(6, 3, "TAG") + + tdSql.checkData(7, 1, "DOUBLE") + tdSql.checkData(7, 3, "TAG") + + tdSql.checkData(8, 1, "BOOL") + tdSql.checkData(8, 3, "TAG") + + tdSql.checkData(9, 1, "BINARY") + tdSql.checkData(9, 3, "TAG") + + tdSql.checkData(10, 1, "NCHAR") + tdSql.checkData(10, 3, "TAG") + + + #tag ID as child table name + lines3_1 = [ + "stb3_1 1626006833610ms 1 id=\"child_table1\",host=\"host1\"", + "stb3_1 1626006833610ms 2 host=\"host2\",iD=\"child_table2\"", + "stb3_1 1626006833610ms 3 ID=\"child_table3\",host=\"host3\"" + ] + + code = self._conn.insert_telnet_lines(lines3_1) + print("insert_telnet_lines result {}".format(code)) + + tdSql.query("select * from stb3_1") + tdSql.checkRows(3) + + tdSql.query("show tables like \"child%\"") + tdSql.checkRows(3) + + tdSql.checkData(0, 0, "child_table1") + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/insert/openTsdbTelnetLinesInsert.py b/tests/pytest/insert/openTsdbTelnetLinesInsert.py new file mode 100644 index 0000000000000000000000000000000000000000..e0d1c0d9669e77e236d4b1591b302a717c5a93d1 --- /dev/null +++ b/tests/pytest/insert/openTsdbTelnetLinesInsert.py @@ -0,0 +1,1308 @@ +################################################################### +# Copyright (c) 2021 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import traceback +import random +import string +from taos.error import LinesError +import time +from copy import deepcopy +import numpy as np +from util.log import * +from util.cases import * +from util.sql import * +from util.common import tdCom +import threading + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + self._conn = conn + + def createDb(self, name="test", db_update_tag=0): + if db_update_tag == 0: + tdSql.execute(f"drop database if exists {name}") + tdSql.execute(f"create database if not exists {name} precision 'us'") + else: + tdSql.execute(f"drop database if exists {name}") + tdSql.execute(f"create database if not exists {name} precision 'us' update 1") + tdSql.execute(f'use {name}') + + def timeTrans(self, time_value): + if time_value.endswith("ns"): + ts = int(''.join(list(filter(str.isdigit, time_value))))/1000000000 + elif time_value.endswith("us") or time_value.isdigit() and int(time_value) != 0: + ts = int(''.join(list(filter(str.isdigit, time_value))))/1000000 + elif time_value.endswith("ms"): + ts = int(''.join(list(filter(str.isdigit, time_value))))/1000 + elif time_value.endswith("s") and list(time_value)[-1] not in "num": + ts = int(''.join(list(filter(str.isdigit, time_value))))/1 + elif int(time_value) == 0: + ts = time.time() + else: + print("input ts maybe not right format") + ulsec = repr(ts).split('.')[1][:6] + if len(ulsec) < 6 and int(ulsec) != 0: + ulsec = int(ulsec) * (10 ** (6 - len(ulsec))) + elif int(ulsec) == 0: + ulsec *= 6 + # * follow two rows added for tsCheckCase + td_ts = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ts)) + return td_ts + #td_ts = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ts)) + td_ts = time.strftime("%Y-%m-%d %H:%M:%S.{}".format(ulsec), time.localtime(ts)) + return td_ts + #return repr(datetime.datetime.strptime(td_ts, "%Y-%m-%d %H:%M:%S.%f")) + + def dateToTs(self, datetime_input): + return int(time.mktime(time.strptime(datetime_input, "%Y-%m-%d %H:%M:%S.%f"))) + + def getTdTypeValue(self, value): + if value.endswith("i8"): + td_type = "TINYINT" + td_tag_value = ''.join(list(value)[:-2]) + elif value.endswith("i16"): + td_type = "SMALLINT" + td_tag_value = ''.join(list(value)[:-3]) + elif value.endswith("i32"): + td_type = "INT" + td_tag_value = ''.join(list(value)[:-3]) + elif value.endswith("i64"): + td_type = "BIGINT" + td_tag_value = ''.join(list(value)[:-3]) + elif value.endswith("u64"): + td_type = "BIGINT UNSIGNED" + td_tag_value = ''.join(list(value)[:-3]) + elif value.endswith("f32"): + td_type = "FLOAT" + td_tag_value = ''.join(list(value)[:-3]) + td_tag_value = '{}'.format(np.float32(td_tag_value)) + elif value.endswith("f64"): + td_type = "DOUBLE" + td_tag_value = ''.join(list(value)[:-3]) + elif value.startswith('L"'): + td_type = "NCHAR" + td_tag_value = ''.join(list(value)[2:-1]) + elif value.startswith('"') and value.endswith('"'): + td_type = "BINARY" + td_tag_value = ''.join(list(value)[1:-1]) + elif value.lower() == "t" or value == "true" or value == "True" or value == "TRUE": + td_type = "BOOL" + td_tag_value = "True" + elif value.lower() == "f" or value == "false" or value == "False" or value == "FALSE": + td_type = "BOOL" + td_tag_value = "False" + else: + td_type = "FLOAT" + td_tag_value = value + return td_type, td_tag_value + + def typeTrans(self, type_list): + type_num_list = [] + for tp in type_list: + if tp.upper() == "TIMESTAMP": + type_num_list.append(9) + elif tp.upper() == "BOOL": + type_num_list.append(1) + elif tp.upper() == "TINYINT": + type_num_list.append(2) + elif tp.upper() == "SMALLINT": + type_num_list.append(3) + elif tp.upper() == "INT": + type_num_list.append(4) + elif tp.upper() == "BIGINT": + type_num_list.append(5) + elif tp.upper() == "FLOAT": + type_num_list.append(6) + elif tp.upper() == "DOUBLE": + type_num_list.append(7) + elif tp.upper() == "BINARY": + type_num_list.append(8) + elif tp.upper() == "NCHAR": + type_num_list.append(10) + elif tp.upper() == "BIGINT UNSIGNED": + type_num_list.append(14) + return type_num_list + + def inputHandle(self, input_sql): + input_sql_split_list = input_sql.split(" ") + stb_name = input_sql_split_list[0] + + #'stb2_5 1626006833610ms 3f64 host="host0"', + stb_tag_list = input_sql_split_list[3].split(',') + stb_col_value = input_sql_split_list[2] + ts_value = self.timeTrans(input_sql_split_list[1]) + + tag_name_list = [] + tag_value_list = [] + td_tag_value_list = [] + td_tag_type_list = [] + + col_name_list = [] + col_value_list = [] + td_col_value_list = [] + td_col_type_list = [] + + for elm in stb_tag_list: + if "id=" in elm.lower(): + tb_name = elm.split('=')[1] + else: + tag_name_list.append(elm.split("=")[0]) + tag_value_list.append(elm.split("=")[1]) + tb_name = "" + td_tag_value_list.append(self.getTdTypeValue(elm.split("=")[1])[1]) + td_tag_type_list.append(self.getTdTypeValue(elm.split("=")[1])[0]) + + col_name_list.append('value') + col_value_list.append(stb_col_value) + + td_col_value_list.append(self.getTdTypeValue(stb_col_value)[1]) + td_col_type_list.append(self.getTdTypeValue(stb_col_value)[0]) + + final_field_list = [] + final_field_list.extend(col_name_list) + final_field_list.extend(tag_name_list) + + final_type_list = [] + final_type_list.append("TIMESTAMP") + final_type_list.extend(td_col_type_list) + final_type_list.extend(td_tag_type_list) + final_type_list = self.typeTrans(final_type_list) + + final_value_list = [] + final_value_list.append(ts_value) + final_value_list.extend(td_col_value_list) + final_value_list.extend(td_tag_value_list) + return final_value_list, final_field_list, final_type_list, stb_name, tb_name + + def genFullTypeSql(self, stb_name="", tb_name="", value="", t0="", t1="127i8", t2="32767i16", t3="2147483647i32", + t4="9223372036854775807i64", t5="11.12345f32", t6="22.123456789f64", t7="\"binaryTagValue\"", + t8="L\"ncharTagValue\"", ts="1626006833639000000ns", + id_noexist_tag=None, id_change_tag=None, id_upper_tag=None, id_double_tag=None, + t_add_tag=None, t_mul_tag=None, t_multi_tag=None, t_blank_tag=None): + if stb_name == "": + stb_name = tdCom.getLongName(len=6, mode="letters") + if tb_name == "": + tb_name = f'{stb_name}_{random.randint(0, 65535)}_{random.randint(0, 65535)}' + if t0 == "": + t0 = random.choice(["f", "F", "false", "False", "t", "T", "true", "True", "TRUE", "FALSE"]) + if value == "": + value = random.choice(["f", "F", "false", "False", "t", "T", "true", "True", "TRUE", "FALSE"]) + if id_upper_tag is not None: + id = "ID" + else: + id = "id" + sql_seq = f'{stb_name} {ts} {value} {id}=\"{tb_name}\",t0={t0},t1={t1},t2={t2},t3={t3},t4={t4},t5={t5},t6={t6},t7={t7},t8={t8}' + if id_noexist_tag is not None: + sql_seq = f'{stb_name} {ts} {value} t0={t0},t1={t1},t2={t2},t3={t3},t4={t4},t5={t5},t6={t6},t7={t7},t8={t8}' + if t_add_tag is not None: + sql_seq = f'{stb_name} {ts} {value} t0={t0},t1={t1},t2={t2},t3={t3},t4={t4},t5={t5},t6={t6},t7={t7},t8={t8},t9={t8}' + if id_change_tag is not None: + sql_seq = f'{stb_name} {ts} {value} t0={t0},{id}=\"{tb_name}\",t1={t1},t2={t2},t3={t3},t4={t4},t5={t5},t6={t6},t7={t7},t8={t8}' + if id_double_tag is not None: + sql_seq = f'{stb_name} {ts} {value} {id}=\"{tb_name}_1\",t0={t0},t1={t1},{id}=\"{tb_name}_2\",t2={t2},t3={t3},t4={t4},t5={t5},t6={t6},t7={t7},t8={t8}' + if t_add_tag is not None: + sql_seq = f'{stb_name} {ts} {value} {id}=\"{tb_name}\",t0={t0},t1={t1},t2={t2},t3={t3},t4={t4},t5={t5},t6={t6},t7={t7},t8={t8},t11={t1},t10={t8}' + if t_mul_tag is not None: + sql_seq = f'{stb_name} {ts} {value} {id}=\"{tb_name}\",t0={t0},t1={t1},t2={t2},t3={t3},t4={t4},t5={t5},t6={t6}' + if id_noexist_tag is not None: + sql_seq = f'{stb_name} {ts} {value} t0={t0},t1={t1},t2={t2},t3={t3},t4={t4},t5={t5},t6={t6}' + if t_multi_tag is not None: + sql_seq = f'{stb_name} {ts} {value},{value} {id}=\"{tb_name}\",t0={t0},t1={t1},t2={t2},t3={t3},t4={t4},t5={t5},t6={t6}' + if t_blank_tag is not None: + sql_seq = f'{stb_name} {ts} {id}=\"{tb_name}\",t0={t0},t1={t1},t2={t2},t3={t3},t4={t4},t5={t5},t6={t6},t7={t7},t8={t8}' + return sql_seq, stb_name + + def genMulTagColStr(self, genType, count=1): + """ + genType must be tag/col + """ + tag_str = "" + col_str = "" + if genType == "tag": + for i in range(0, count): + if i < (count-1): + tag_str += f't{i}=f,' + else: + tag_str += f't{i}=f' + return tag_str + if genType == "col": + col_str = "t" + return col_str + + def genLongSql(self, tag_count): + stb_name = tdCom.getLongName(7, mode="letters") + tb_name = f'{stb_name}_1' + tag_str = self.genMulTagColStr("tag", tag_count) + col_str = self.genMulTagColStr("col") + ts = "1626006833640000000ns" + long_sql = stb_name + ' ' + ts + ' ' + col_str + ' ' + f'id=\"{tb_name}\"' + ',' + tag_str + return long_sql, stb_name + + def getNoIdTbName(self, stb_name): + query_sql = f"select tbname from {stb_name}" + tb_name = self.resHandle(query_sql, True)[0][0] + return tb_name + + def resHandle(self, query_sql, query_tag): + tdSql.execute('reset query cache') + row_info = tdSql.query(query_sql, query_tag) + print(query_sql) + print(row_info) + col_info = tdSql.getColNameList(query_sql, query_tag) + res_row_list = [] + sub_list = [] + for row_mem in row_info: + for i in row_mem: + sub_list.append(str(i)) + res_row_list.append(sub_list) + res_field_list_without_ts = col_info[0][1:] + res_type_list = col_info[1] + return res_row_list, res_field_list_without_ts, res_type_list + + 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.insert_telnet_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) + res = tdSql.query(f'select * from {stb_name}', True) + print(res) + + res = tdSql.query(f'select * from {stb_name}', True) + print(res) + time.sleep(2) + res = tdSql.query(f'select * from {stb_name}', True) + print(res) + time.sleep(2) + res = tdSql.query(f'select * from {stb_name}', True) + print(res) + time.sleep(2) + res = tdSql.query(f'select * from {stb_name}', True) + print(res) + + + if ts == 0: + res_ts = self.dateToTs(res_row_list[0][0]) + current_time = time.time() + if current_time - res_ts < 60: + tdSql.checkEqual(res_row_list[0][1:], expect_list[0][1:]) + else: + print("timeout") + tdSql.checkEqual(res_row_list[0], expect_list[0]) + else: + if none_check_tag is not None: + none_index_list = [i for i,x in enumerate(res_row_list[0]) if x=="None"] + none_index_list.reverse() + for j in none_index_list: + res_row_list[0].pop(j) + expect_list[0].pop(j) + tdSql.checkEqual(res_row_list[0], expect_list[0]) + tdSql.checkEqual(res_field_list_without_ts, expect_list[1]) + 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 initCheckCase(self): + """ + normal tags and cols, one for every elm + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql() + self.resCmp(input_sql, stb_name) + + def boolTypeCheckCase(self): + """ + check all normal type + """ + tdCom.cleanTb() + full_type_list = ["f", "F", "false", "False", "t", "T", "true", "True"] + for t_type in full_type_list: + input_sql, stb_name = self.genFullTypeSql(t0=t_type) + self.resCmp(input_sql, stb_name) + + def symbolsCheckCase(self): + """ + check symbols = `~!@#$%^&*()_-+={[}]\|:;'\",<.>/? + """ + ''' + please test : + binary_symbols = '\"abcd`~!@#$%^&*()_-{[}]|:;<.>?lfjal"\'\'"\"' + ''' + tdCom.cleanTb() + binary_symbols = '"aaa"' + # binary_symbols = '"abcd`~!@#$%^&*()_-{[}]|:;<.>?lfjal"' + nchar_symbols = f'L{binary_symbols}' + input_sql1, stb_name1 = self.genFullTypeSql(value=binary_symbols, t7=binary_symbols, t8=nchar_symbols) + + # input_sql2, stb_name2 = self.genFullTypeSql(value=nchar_symbols, t7=binary_symbols, t8=nchar_symbols) + self.resCmp(input_sql1, stb_name1) + # self.resCmp(input_sql2, stb_name2) + + def tsCheckCase(self): + """ + test ts list --> ["1626006833639000000ns", "1626006833639019us", "1626006833640ms", "1626006834s", "1626006822639022"] + # ! us级时间戳都为0时,数据库中查询显示,但python接口拿到的结果不显示 .000000的情况请确认,目前修改时间处理代码可以通过 + """ + tdCom.cleanTb() + ts_list = ["1626006833639000000ns", "1626006833639019us", "1626006833640ms", "1626006834s", "1626006822639022", 0] + for ts in ts_list: + input_sql, stb_name = self.genFullTypeSql(ts=ts) + self.resCmp(input_sql, stb_name, ts=ts) + + def idSeqCheckCase(self): + """ + check id.index in tags + eg: t0=**,id=**,t1=** + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql(id_change_tag=True) + self.resCmp(input_sql, stb_name) + + def idUpperCheckCase(self): + """ + check id param + eg: id and ID + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql(id_upper_tag=True) + self.resCmp(input_sql, stb_name) + input_sql, stb_name = self.genFullTypeSql(id_change_tag=True, id_upper_tag=True) + self.resCmp(input_sql, stb_name) + + def noIdCheckCase(self): + """ + id not exist + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql(id_noexist_tag=True) + self.resCmp(input_sql, stb_name) + query_sql = f"select tbname from {stb_name}" + res_row_list = self.resHandle(query_sql, True)[0] + if len(res_row_list[0][0]) > 0: + tdSql.checkColNameList(res_row_list, res_row_list) + else: + tdSql.checkColNameList(res_row_list, "please check noIdCheckCase") + + def maxColTagCheckCase(self): + """ + max tag count is 128 + """ + for input_sql in [self.genLongSql(128)[0]]: + tdCom.cleanTb() + self._conn.insert_telnet_lines([input_sql]) + for input_sql in [self.genLongSql(129)[0]]: + tdCom.cleanTb() + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + def idIllegalNameCheckCase(self): + """ + test illegal id name + mix "`~!@#$¥%^&*()-+={}|[]、「」【】\:;《》<>?" + """ + tdCom.cleanTb() + rstr = list("`~!@#$¥%^&*()-+={}|[]、「」【】\:;《》<>?") + for i in rstr: + input_sql = self.genFullTypeSql(tb_name=f"\"aaa{i}bbb\"")[0] + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + def idStartWithNumCheckCase(self): + """ + id is start with num + """ + tdCom.cleanTb() + input_sql = self.genFullTypeSql(tb_name=f"\"1aaabbb\"")[0] + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + def nowTsCheckCase(self): + """ + check now unsupported + """ + tdCom.cleanTb() + input_sql = self.genFullTypeSql(ts="now")[0] + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + def dateFormatTsCheckCase(self): + """ + check date format ts unsupported + """ + tdCom.cleanTb() + input_sql = self.genFullTypeSql(ts="2021-07-21\ 19:01:46.920")[0] + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + def illegalTsCheckCase(self): + """ + check ts format like 16260068336390us19 + """ + tdCom.cleanTb() + input_sql = self.genFullTypeSql(ts="16260068336390us19")[0] + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + def tagValueLengthCheckCase(self): + """ + check full type tag value limit + """ + tdCom.cleanTb() + # i8 + for t1 in ["-127i8", "127i8"]: + input_sql, stb_name = self.genFullTypeSql(t1=t1) + self.resCmp(input_sql, stb_name) + for t1 in ["-128i8", "128i8"]: + input_sql = self.genFullTypeSql(t1=t1)[0] + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + #i16 + for t2 in ["-32767i16", "32767i16"]: + input_sql, stb_name = self.genFullTypeSql(t2=t2) + self.resCmp(input_sql, stb_name) + for t2 in ["-32768i16", "32768i16"]: + input_sql = self.genFullTypeSql(t2=t2)[0] + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + #i32 + for t3 in ["-2147483647i32", "2147483647i32"]: + input_sql, stb_name = self.genFullTypeSql(t3=t3) + self.resCmp(input_sql, stb_name) + for t3 in ["-2147483648i32", "2147483648i32"]: + input_sql = self.genFullTypeSql(t3=t3)[0] + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + #i64 + for t4 in ["-9223372036854775807i64", "9223372036854775807i64"]: + input_sql, stb_name = self.genFullTypeSql(t4=t4) + self.resCmp(input_sql, stb_name) + for t4 in ["-9223372036854775808i64", "9223372036854775808i64"]: + input_sql = self.genFullTypeSql(t4=t4)[0] + try: + self._conn.insert_telnet_lines([input_sql]) + except LinesError: + pass + + # f32 + for t5 in [f"{-3.4028234663852885981170418348451692544*(10**38)}f32", f"{3.4028234663852885981170418348451692544*(10**38)}f32"]: + input_sql, stb_name = self.genFullTypeSql(t5=t5) + self.resCmp(input_sql, stb_name) + # * 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] + try: + self._conn.insert_telnet_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']: + input_sql, stb_name = self.genFullTypeSql(t6=t6) + self.resCmp(input_sql, stb_name) + # * 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] + try: + self._conn.insert_telnet_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) + + # binary + stb_name = tdCom.getLongName(7, "letters") + input_sql = f'{stb_name} 1626006833639000000ns t t0=t,t1="{tdCom.getLongName(16374, "letters")}"' + self._conn.insert_telnet_lines([input_sql]) + + input_sql = f'{stb_name} 1626006833639000000ns t t0=t,t1="{tdCom.getLongName(16375, "letters")}"' + try: + self._conn.insert_telnet_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 = tdCom.getLongName(7, "letters") + input_sql = f'{stb_name} 1626006833639000000ns t t0=t,t1=L"{tdCom.getLongName(4093, "letters")}"' + self._conn.insert_telnet_lines([input_sql]) + + input_sql = f'{stb_name} 1626006833639000000ns t t0=t,t1=L"{tdCom.getLongName(4094, "letters")}"' + try: + self._conn.insert_telnet_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) + + def colValueLengthCheckCase(self): + """ + check full type col value limit + """ + tdCom.cleanTb() + # i8 + for c1 in ["-127i8", "127i8"]: + input_sql, stb_name = self.genFullTypeSql(c1=c1) + self.resCmp(input_sql, stb_name) + + for c1 in ["-128i8", "128i8"]: + input_sql = self.genFullTypeSql(c1=c1)[0] + try: + self._conn.insert_telnet_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] + try: + self._conn.insert_telnet_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) + + # i32 + for c3 in ["-2147483647i32"]: + input_sql, stb_name = self.genFullTypeSql(c3=c3) + self.resCmp(input_sql, stb_name) + for c3 in ["-2147483648i32", "2147483648i32"]: + input_sql = self.genFullTypeSql(c3=c3)[0] + try: + self._conn.insert_telnet_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) + + # i64 + for c4 in ["-9223372036854775807i64"]: + input_sql, stb_name = self.genFullTypeSql(c4=c4) + self.resCmp(input_sql, stb_name) + for c4 in ["-9223372036854775808i64", "9223372036854775808i64"]: + input_sql = self.genFullTypeSql(c4=c4)[0] + try: + self._conn.insert_telnet_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"]: + input_sql, stb_name = self.genFullTypeSql(c5=c5) + self.resCmp(input_sql, stb_name) + # * 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] + try: + self._conn.insert_telnet_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']: + input_sql, stb_name = self.genFullTypeSql(c6=c6) + self.resCmp(input_sql, stb_name) + # * 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] + try: + self._conn.insert_telnet_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) + + # # binary + stb_name = tdCom.getLongName(7, "letters") + input_sql = f'{stb_name} 1626006833639000000ns "{tdCom.getLongName(16374, "letters")}" t0=t' + self._conn.insert_telnet_lines([input_sql]) + + input_sql = f'{stb_name} 1626006833639000000ns "{tdCom.getLongName(16375, "letters")}" t0=t' + try: + self._conn.insert_telnet_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 = tdCom.getLongName(7, "letters") + input_sql = f'{stb_name} 1626006833639000000ns L"{tdCom.getLongName(4093, "letters")}" t0=t' + self._conn.insert_telnet_lines([input_sql]) + + input_sql = f'{stb_name} 1626006833639000000ns L"{tdCom.getLongName(4094, "letters")}" t0=t' + try: + self._conn.insert_telnet_lines([input_sql]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) + + def tagColIllegalValueCheckCase(self): + + """ + test illegal tag col value + """ + tdCom.cleanTb() + # bool + for i in ["TrUe", "tRue", "trUe", "truE", "FalsE", "fAlse", "faLse", "falSe", "falsE"]: + input_sql1 = self.genFullTypeSql(t0=i)[0] + try: + self._conn.insert_telnet_lines([input_sql1]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) + input_sql2 = self.genFullTypeSql(value=i)[0] + try: + self._conn.insert_telnet_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 [ + self.genFullTypeSql(t1="1s2i8")[0], + self.genFullTypeSql(t2="1s2i16")[0], + self.genFullTypeSql(t3="1s2i32")[0], + self.genFullTypeSql(t4="1s2i64")[0], + self.genFullTypeSql(t5="11.1s45f32")[0], + self.genFullTypeSql(t6="11.1s45f64")[0], + ]: + try: + self._conn.insert_telnet_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 = tdCom.getLongName(7, "letters") + + input_sql1 = f'{stb_name} 1626006833639000000ns "abc aaa" t0=t' + input_sql2 = f'{stb_name} 1626006833639000000ns L"abc aaa" t0=t' + input_sql3 = f'{stb_name} 1626006833639000000ns t t0="abc aaa"' + input_sql4 = f'{stb_name} 1626006833639000000ns t t0=L"abc aaa"' + for input_sql in [input_sql1, input_sql2, input_sql3, input_sql4]: + try: + self._conn.insert_telnet_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} 1626006833639000000ns "abc{symbol}aaa" t0=t' + input_sql2 = f'{stb_name} 1626006833639000000ns t t0=t,t1="abc{symbol}aaa"' + self._conn.insert_telnet_lines([input_sql1]) + self._conn.insert_telnet_lines([input_sql2]) + + + def duplicateIdTagColInsertCheckCase(self): + """ + check duplicate Id Tag Col + """ + tdCom.cleanTb() + input_sql_id = self.genFullTypeSql(id_double_tag=True)[0] + try: + self._conn.insert_telnet_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") + try: + self._conn.insert_telnet_lines([input_sql_tag]) + raise Exception("should not reach here") + except LinesError as err: + tdSql.checkNotEqual(err.errno, 0) + + ##### stb exist ##### + def noIdStbExistCheckCase(self): + """ + case no id when stb exist + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql(tb_name="sub_table_0123456", t0="f", value="f") + self.resCmp(input_sql, stb_name) + input_sql, stb_name = self.genFullTypeSql(stb_name=stb_name, id_noexist_tag=True, t0="f", value="f") + self.resCmp(input_sql, stb_name, condition='where tbname like "t_%"') + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(2) + # TODO cover other case + + def duplicateInsertExistCheckCase(self): + """ + check duplicate insert when stb exist + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql() + self.resCmp(input_sql, stb_name) + self._conn.insert_telnet_lines([input_sql]) + self.resCmp(input_sql, stb_name) + + def tagColBinaryNcharLengthCheckCase(self): + """ + check length increase + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql() + self.resCmp(input_sql, stb_name) + tb_name = tdCom.getLongName(5, "letters") + input_sql, stb_name = self.genFullTypeSql(stb_name=stb_name, tb_name=tb_name,t7="\"binaryTagValuebinaryTagValue\"", t8="L\"ncharTagValuencharTagValue\"", c7="\"binaryTagValuebinaryTagValue\"", c8="L\"ncharTagValuencharTagValue\"") + self.resCmp(input_sql, stb_name, condition=f'where tbname like "{tb_name}"') + + def tagColAddDupIDCheckCase(self): + """ + check column and tag count add, stb and tb duplicate + * tag: alter table ... + * col: when update==0 and ts is same, unchange + * so this case tag&&value will be added, + * col is added without value when update==0 + * col is added with value when update==1 + """ + tdCom.cleanTb() + tb_name = tdCom.getLongName(7, "letters") + for db_update_tag in [0, 1]: + if db_update_tag == 1 : + self.createDb("test_update", db_update_tag=db_update_tag) + input_sql, stb_name = self.genFullTypeSql(tb_name=tb_name, t0="f", value="f") + self.resCmp(input_sql, stb_name) + self.genFullTypeSql(stb_name=stb_name, tb_name=tb_name, t0="f", value="f", ct_add_tag=True) + if db_update_tag == 1 : + self.resCmp(input_sql, stb_name, condition=f'where tbname like "{tb_name}"') + else: + self.resCmp(input_sql, stb_name, condition=f'where tbname like "{tb_name}"', none_check_tag=True) + + def tagColAddCheckCase(self): + """ + check column and tag count add + """ + tdCom.cleanTb() + tb_name = tdCom.getLongName(7, "letters") + input_sql, stb_name = self.genFullTypeSql(tb_name=tb_name, t0="f", value="f") + self.resCmp(input_sql, stb_name) + tb_name_1 = tdCom.getLongName(7, "letters") + input_sql, stb_name = self.genFullTypeSql(stb_name=stb_name, tb_name=tb_name_1, t0="f", value="f", ct_add_tag=True) + self.resCmp(input_sql, stb_name, condition=f'where tbname like "{tb_name_1}"') + res_row_list = self.resHandle(f"select c10,c11,t10,t11 from {tb_name}", True)[0] + tdSql.checkEqual(res_row_list[0], ['None', 'None', 'None', 'None']) + self.resCmp(input_sql, stb_name, condition=f'where tbname like "{tb_name}"', none_check_tag=True) + + def tagMd5Check(self): + """ + condition: stb not change + insert two table, keep tag unchange, change col + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql(t0="f", value="f", id_noexist_tag=True) + self.resCmp(input_sql, stb_name) + tb_name1 = self.getNoIdTbName(stb_name) + input_sql, stb_name = self.genFullTypeSql(stb_name=stb_name, t0="f", value="f", id_noexist_tag=True) + self.resCmp(input_sql, stb_name) + tb_name2 = self.getNoIdTbName(stb_name) + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(1) + tdSql.checkEqual(tb_name1, tb_name2) + input_sql, stb_name = self.genFullTypeSql(stb_name=stb_name, t0="f", value="f", id_noexist_tag=True, ct_add_tag=True) + self._conn.insert_telnet_lines([input_sql]) + tb_name3 = self.getNoIdTbName(stb_name) + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(2) + tdSql.checkNotEqual(tb_name1, tb_name3) + + # * tag binary max is 16384, col+ts binary max 49151 + def tagColBinaryMaxLengthCheckCase(self): + """ + every binary and nchar must be length+2 + """ + tdCom.cleanTb() + stb_name = tdCom.getLongName(7, "letters") + tb_name = f'{stb_name}_1' + input_sql = f'{stb_name},id="{tb_name}",t0=t c0=f 1626006833639000000ns' + self._conn.insert_telnet_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="{tdCom.getLongName(16374, "letters")}",t2="{tdCom.getLongName(5, "letters")}" c0=f 1626006833639000000ns' + self._conn.insert_telnet_lines([input_sql]) + + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(2) + input_sql = f'{stb_name},t0=t,t1="{tdCom.getLongName(16374, "letters")}",t2="{tdCom.getLongName(6, "letters")}" c0=f 1626006833639000000ns' + try: + self._conn.insert_telnet_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="{tdCom.getLongName(16374, "letters")}",c2="{tdCom.getLongName(16374, "letters")}",c3="{tdCom.getLongName(16374, "letters")}",c4="{tdCom.getLongName(12, "letters")}" 1626006833639000000ns' + self._conn.insert_telnet_lines([input_sql]) + + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(3) + input_sql = f'{stb_name},t0=t c0=f,c1="{tdCom.getLongName(16374, "letters")}",c2="{tdCom.getLongName(16374, "letters")}",c3="{tdCom.getLongName(16374, "letters")}",c4="{tdCom.getLongName(13, "letters")}" 1626006833639000000ns' + try: + self._conn.insert_telnet_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) + + # * tag nchar max is 16374/4, col+ts nchar max 49151 + def tagColNcharMaxLengthCheckCase(self): + """ + check nchar length limit + """ + tdCom.cleanTb() + stb_name = tdCom.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.insert_telnet_lines([input_sql]) + + # * legal nchar could not be larger than 16374/4 + input_sql = f'{stb_name},t0=t,t1=L"{tdCom.getLongName(4093, "letters")}",t2=L"{tdCom.getLongName(1, "letters")}" c0=f 1626006833639000000ns' + self._conn.insert_telnet_lines([input_sql]) + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(2) + input_sql = f'{stb_name},t0=t,t1=L"{tdCom.getLongName(4093, "letters")}",t2=L"{tdCom.getLongName(2, "letters")}" c0=f 1626006833639000000ns' + try: + self._conn.insert_telnet_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"{tdCom.getLongName(4093, "letters")}",c2=L"{tdCom.getLongName(4093, "letters")}",c3=L"{tdCom.getLongName(4093, "letters")}",c4=L"{tdCom.getLongName(4, "letters")}" 1626006833639000000ns' + self._conn.insert_telnet_lines([input_sql]) + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(3) + input_sql = f'{stb_name},t0=t c0=f,c1=L"{tdCom.getLongName(4093, "letters")}",c2=L"{tdCom.getLongName(4093, "letters")}",c3=L"{tdCom.getLongName(4093, "letters")}",c4=L"{tdCom.getLongName(5, "letters")}" 1626006833639000000ns' + try: + self._conn.insert_telnet_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) + + def batchInsertCheckCase(self): + """ + test batch insert + """ + tdCom.cleanTb() + stb_name = tdCom.getLongName(8, "letters") + tdSql.execute(f'create stable {stb_name}(ts timestamp, f int) tags(t1 bigint)') + lines = ["st123456,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000ns", + "st123456,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833640000000ns", + f"{stb_name},t2=5f64,t3=L\"ste\" c1=true,c2=4i64,c3=\"iam\" 1626056811823316532ns", + "stf567890,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,t2=5f64,t3=\"t4\" c1=3i64,c3=L\"passitagain\",c2=true,c4=5f64 1626006833642000000ns", + f"{stb_name},t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false 1626056811843316532ns", + f"{stb_name},t2=5f64,t3=L\"ste2\" c3=\"iamszhou\",c4=false,c5=32i8,c6=64i16,c7=32i32,c8=88.88f32 1626056812843316532ns", + "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" + ] + self._conn.insert_telnet_lines(lines) + + def multiInsertCheckCase(self, count): + """ + test multi insert + """ + tdCom.cleanTb() + sql_list = [] + stb_name = tdCom.getLongName(8, "letters") + tdSql.execute(f'create stable {stb_name}(ts timestamp, f int) tags(t1 bigint)') + for i in range(count): + input_sql = self.genFullTypeSql(stb_name=stb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', id_noexist_tag=True)[0] + sql_list.append(input_sql) + self._conn.insert_telnet_lines(sql_list) + + def batchErrorInsertCheckCase(self): + """ + test batch error insert + """ + tdCom.cleanTb() + stb_name = tdCom.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"] + try: + self._conn.insert_telnet_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=""): + """ + stb --> supertable + tb --> table + ts --> timestamp, same default + col --> column, same default + tag --> tag, same default + d --> different + s --> same + a --> add + m --> minus + """ + d_stb_d_tb_list = list() + s_stb_s_tb_list = list() + s_stb_s_tb_a_col_a_tag_list = list() + s_stb_s_tb_m_col_m_tag_list = list() + s_stb_d_tb_list = list() + s_stb_d_tb_a_col_m_tag_list = list() + s_stb_d_tb_a_tag_m_col_list = list() + s_stb_s_tb_d_ts_list = list() + s_stb_s_tb_d_ts_a_col_m_tag_list = list() + s_stb_s_tb_d_ts_a_tag_m_col_list = list() + s_stb_d_tb_d_ts_list = list() + s_stb_d_tb_d_ts_a_col_m_tag_list = list() + s_stb_d_tb_d_ts_a_tag_m_col_list = list() + for i in range(count): + d_stb_d_tb_list.append(self.genFullTypeSql(t0="f", c0="f")) + s_stb_s_tb_list.append(self.genFullTypeSql(stb_name=stb_name, tb_name=tb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"')) + s_stb_s_tb_a_col_a_tag_list.append(self.genFullTypeSql(stb_name=stb_name, tb_name=tb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', ct_add_tag=True)) + s_stb_s_tb_m_col_m_tag_list.append(self.genFullTypeSql(stb_name=stb_name, tb_name=tb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', ct_min_tag=True)) + s_stb_d_tb_list.append(self.genFullTypeSql(stb_name=stb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', id_noexist_tag=True)) + s_stb_d_tb_a_col_m_tag_list.append(self.genFullTypeSql(stb_name=stb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', id_noexist_tag=True, ct_am_tag=True)) + s_stb_d_tb_a_tag_m_col_list.append(self.genFullTypeSql(stb_name=stb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', id_noexist_tag=True, ct_ma_tag=True)) + s_stb_s_tb_d_ts_list.append(self.genFullTypeSql(stb_name=stb_name, tb_name=tb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', ts=0)) + s_stb_s_tb_d_ts_a_col_m_tag_list.append(self.genFullTypeSql(stb_name=stb_name, tb_name=tb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', ts=0, ct_am_tag=True)) + s_stb_s_tb_d_ts_a_tag_m_col_list.append(self.genFullTypeSql(stb_name=stb_name, tb_name=tb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', ts=0, ct_ma_tag=True)) + s_stb_d_tb_d_ts_list.append(self.genFullTypeSql(stb_name=stb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', id_noexist_tag=True, ts=0)) + s_stb_d_tb_d_ts_a_col_m_tag_list.append(self.genFullTypeSql(stb_name=stb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', id_noexist_tag=True, ts=0, ct_am_tag=True)) + s_stb_d_tb_d_ts_a_tag_m_col_list.append(self.genFullTypeSql(stb_name=stb_name, t7=f'"{tdCom.getLongName(8, "letters")}"', c7=f'"{tdCom.getLongName(8, "letters")}"', id_noexist_tag=True, ts=0, ct_ma_tag=True)) + + return d_stb_d_tb_list, s_stb_s_tb_list, s_stb_s_tb_a_col_a_tag_list, s_stb_s_tb_m_col_m_tag_list, \ + s_stb_d_tb_list, s_stb_d_tb_a_col_m_tag_list, s_stb_d_tb_a_tag_m_col_list, s_stb_s_tb_d_ts_list, \ + s_stb_s_tb_d_ts_a_col_m_tag_list, s_stb_s_tb_d_ts_a_tag_m_col_list, s_stb_d_tb_d_ts_list, \ + s_stb_d_tb_d_ts_a_col_m_tag_list, s_stb_d_tb_d_ts_a_tag_m_col_list + + + def genMultiThreadSeq(self, sql_list): + tlist = list() + for insert_sql in sql_list: + t = threading.Thread(target=self._conn.insert_telnet_lines,args=([insert_sql[0]],)) + tlist.append(t) + return tlist + + def multiThreadRun(self, tlist): + for t in tlist: + t.start() + for t in tlist: + t.join() + + def stbInsertMultiThreadCheckCase(self): + """ + thread input different stb + """ + tdCom.cleanTb() + input_sql = self.genSqlList()[0] + self.multiThreadRun(self.genMultiThreadSeq(input_sql)) + tdSql.query(f"show tables;") + tdSql.checkRows(5) + + def sStbStbDdataInsertMultiThreadCheckCase(self): + """ + thread input same stb tb, different data, result keep first data + """ + tdCom.cleanTb() + tb_name = tdCom.getLongName(7, "letters") + input_sql, stb_name = self.genFullTypeSql(tb_name=tb_name) + self.resCmp(input_sql, stb_name) + s_stb_s_tb_list = self.genSqlList(stb_name=stb_name, tb_name=tb_name)[1] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_s_tb_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(1) + expected_tb_name = self.getNoIdTbName(stb_name)[0] + tdSql.checkEqual(tb_name, expected_tb_name) + tdSql.query(f"select * from {stb_name};") + tdSql.checkRows(1) + + def sStbStbDdataAtcInsertMultiThreadCheckCase(self): + """ + thread input same stb tb, different data, add columes and tags, result keep first data + """ + tdCom.cleanTb() + tb_name = tdCom.getLongName(7, "letters") + input_sql, stb_name = self.genFullTypeSql(tb_name=tb_name) + self.resCmp(input_sql, stb_name) + s_stb_s_tb_a_col_a_tag_list = self.genSqlList(stb_name=stb_name, tb_name=tb_name)[2] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_s_tb_a_col_a_tag_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(1) + expected_tb_name = self.getNoIdTbName(stb_name)[0] + tdSql.checkEqual(tb_name, expected_tb_name) + tdSql.query(f"select * from {stb_name};") + tdSql.checkRows(1) + + def sStbStbDdataMtcInsertMultiThreadCheckCase(self): + """ + thread input same stb tb, different data, minus columes and tags, result keep first data + """ + tdCom.cleanTb() + tb_name = tdCom.getLongName(7, "letters") + input_sql, stb_name = self.genFullTypeSql(tb_name=tb_name) + self.resCmp(input_sql, stb_name) + s_stb_s_tb_m_col_m_tag_list = self.genSqlList(stb_name=stb_name, tb_name=tb_name)[3] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_s_tb_m_col_m_tag_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(1) + expected_tb_name = self.getNoIdTbName(stb_name)[0] + tdSql.checkEqual(tb_name, expected_tb_name) + tdSql.query(f"select * from {stb_name};") + tdSql.checkRows(1) + + def sStbDtbDdataInsertMultiThreadCheckCase(self): + """ + thread input same stb, different tb, different data + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql() + self.resCmp(input_sql, stb_name) + s_stb_d_tb_list = self.genSqlList(stb_name=stb_name)[4] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_d_tb_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(6) + + def sStbDtbDdataAcMtInsertMultiThreadCheckCase(self): + """ + #! concurrency conflict + """ + """ + thread input same stb, different tb, different data, add col, mul tag + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql() + self.resCmp(input_sql, stb_name) + s_stb_d_tb_a_col_m_tag_list = self.genSqlList(stb_name=stb_name)[5] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_d_tb_a_col_m_tag_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(6) + + def sStbDtbDdataAtMcInsertMultiThreadCheckCase(self): + """ + #! concurrency conflict + """ + """ + thread input same stb, different tb, different data, add tag, mul col + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql() + self.resCmp(input_sql, stb_name) + s_stb_d_tb_a_tag_m_col_list = self.genSqlList(stb_name=stb_name)[6] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_d_tb_a_tag_m_col_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(6) + + def sStbStbDdataDtsInsertMultiThreadCheckCase(self): + """ + thread input same stb tb, different ts + """ + tdCom.cleanTb() + tb_name = tdCom.getLongName(7, "letters") + input_sql, stb_name = self.genFullTypeSql(tb_name=tb_name) + self.resCmp(input_sql, stb_name) + s_stb_s_tb_d_ts_list = self.genSqlList(stb_name=stb_name, tb_name=tb_name)[7] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_s_tb_d_ts_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(1) + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(6) + + def sStbStbDdataDtsAcMtInsertMultiThreadCheckCase(self): + """ + thread input same stb tb, different ts, add col, mul tag + """ + tdCom.cleanTb() + tb_name = tdCom.getLongName(7, "letters") + input_sql, stb_name = self.genFullTypeSql(tb_name=tb_name) + self.resCmp(input_sql, stb_name) + s_stb_s_tb_d_ts_a_col_m_tag_list = self.genSqlList(stb_name=stb_name, tb_name=tb_name)[8] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_s_tb_d_ts_a_col_m_tag_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(1) + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(6) + tdSql.query(f"select * from {stb_name} where t8 is not NULL") + tdSql.checkRows(6) + tdSql.query(f"select * from {tb_name} where c11 is not NULL;") + tdSql.checkRows(5) + + def sStbStbDdataDtsAtMcInsertMultiThreadCheckCase(self): + """ + thread input same stb tb, different ts, add tag, mul col + """ + tdCom.cleanTb() + tb_name = tdCom.getLongName(7, "letters") + input_sql, stb_name = self.genFullTypeSql(tb_name=tb_name) + self.resCmp(input_sql, stb_name) + s_stb_s_tb_d_ts_a_tag_m_col_list = self.genSqlList(stb_name=stb_name, tb_name=tb_name)[9] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_s_tb_d_ts_a_tag_m_col_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(1) + tdSql.query(f"select * from {stb_name}") + tdSql.checkRows(6) + for c in ["c7", "c8", "c9"]: + tdSql.query(f"select * from {stb_name} where {c} is NULL") + tdSql.checkRows(5) + for t in ["t10", "t11"]: + tdSql.query(f"select * from {stb_name} where {t} is not NULL;") + tdSql.checkRows(6) + + def sStbDtbDdataDtsInsertMultiThreadCheckCase(self): + """ + thread input same stb, different tb, data, ts + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql() + self.resCmp(input_sql, stb_name) + s_stb_d_tb_d_ts_list = self.genSqlList(stb_name=stb_name)[10] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_d_tb_d_ts_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(6) + + def sStbDtbDdataDtsAcMtInsertMultiThreadCheckCase(self): + """ + # ! concurrency conflict + """ + """ + thread input same stb, different tb, data, ts, add col, mul tag + """ + tdCom.cleanTb() + input_sql, stb_name = self.genFullTypeSql() + self.resCmp(input_sql, stb_name) + s_stb_d_tb_d_ts_a_col_m_tag_list = self.genSqlList(stb_name=stb_name)[11] + self.multiThreadRun(self.genMultiThreadSeq(s_stb_d_tb_d_ts_a_col_m_tag_list)) + tdSql.query(f"show tables;") + tdSql.checkRows(6) + + + def test(self): + # input_sql1 = "stb2_5 1626006833610ms 3f64 host=\"host0\",host2=L\"host2\"" + # 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" + try: + input_sql, stb_name = self.genFullTypeSql() + self.resCmp(input_sql, stb_name) + except LinesError as err: + print(err.errno) + # self._conn.insert_telnet_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.insert_telnet_lines([input_sql3]) + # print(code) + # self._conn.insert_telnet_lines([input_sql4]) + + def runAll(self): + # self.initCheckCase() + # self.boolTypeCheckCase() + self.symbolsCheckCase() + + + + + # self.tsCheckCase() + # self.idSeqCheckCase() + # self.idUpperCheckCase() + # self.noIdCheckCase() + # self.maxColTagCheckCase() + + # self.idIllegalNameCheckCase() + # self.idStartWithNumCheckCase() + # self.nowTsCheckCase() + # self.dateFormatTsCheckCase() + # self.illegalTsCheckCase() + # self.tagValueLengthCheckCase() + # self.colValueLengthCheckCase() + # self.tagColIllegalValueCheckCase() + # self.duplicateIdTagColInsertCheckCase() + # self.noIdStbExistCheckCase() + # self.duplicateInsertExistCheckCase() + # self.tagColBinaryNcharLengthCheckCase() + # self.tagColAddDupIDCheckCase() + # self.tagColAddCheckCase() + # self.tagMd5Check() + # self.tagColBinaryMaxLengthCheckCase() + # # self.tagColNcharMaxLengthCheckCase() + # self.batchInsertCheckCase() + # self.multiInsertCheckCase(1000) + # self.batchErrorInsertCheckCase() + # # MultiThreads + # self.stbInsertMultiThreadCheckCase() + # self.sStbStbDdataInsertMultiThreadCheckCase() + # self.sStbStbDdataAtcInsertMultiThreadCheckCase() + # self.sStbStbDdataMtcInsertMultiThreadCheckCase() + # self.sStbDtbDdataInsertMultiThreadCheckCase() + + # # # ! concurrency conflict + # # self.sStbDtbDdataAcMtInsertMultiThreadCheckCase() + # # self.sStbDtbDdataAtMcInsertMultiThreadCheckCase() + + # self.sStbStbDdataDtsInsertMultiThreadCheckCase() + + # # # ! concurrency conflict + # # self.sStbStbDdataDtsAcMtInsertMultiThreadCheckCase() + # # self.sStbStbDdataDtsAtMcInsertMultiThreadCheckCase() + + # self.sStbDtbDdataDtsInsertMultiThreadCheckCase() + + # # ! concurrency conflict + # # self.sStbDtbDdataDtsAcMtInsertMultiThreadCheckCase() + + + + def run(self): + print("running {}".format(__file__)) + self.createDb() + try: + self.runAll() + except Exception as err: + print(''.join(traceback.format_exception(None, err, err.__traceback__))) + raise err + # self.tagColIllegalValueCheckCase() + # self.test() + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/manualTest/TD-5114/continueCreateDn.py b/tests/pytest/manualTest/TD-5114/continueCreateDn.py new file mode 100644 index 0000000000000000000000000000000000000000..4b724f0587a6a2bbe3f477e8a47e283c0924a29e --- /dev/null +++ b/tests/pytest/manualTest/TD-5114/continueCreateDn.py @@ -0,0 +1,97 @@ +################################################################### +# 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 os +import sys +sys.path.insert(0, os.getcwd()) +from util.log import * +from util.sql import * +from util.dnodes import * +import taos +import threading +import subprocess +from random import choice + +class TwoClients: + def initConnection(self): + self.host = "chr03" + self.user = "root" + self.password = "taosdata" + self.config = "/etc/taos/" + self.port =6030 + self.rowNum = 10 + self.ts = 1537146000000 + + def run(self): + + # new taos client + conn1 = taos.connect(host=self.host, user=self.user, password=self.password, config=self.config ) + print(conn1) + cur1 = conn1.cursor() + tdSql.init(cur1, True) + + tdSql.execute("drop database if exists db3") + + # insert data with taosc + for i in range(10): + os.system("taosdemo -f manualTest/TD-5114/insertDataDb3Replica2.json -y ") + # # check data correct + tdSql.execute("show databases") + tdSql.execute("use db3") + tdSql.query("select count (tbname) from stb0") + tdSql.checkData(0, 0, 20000) + tdSql.query("select count (*) from stb0") + tdSql.checkData(0, 0, 4000000) + + # insert data with python connector , if you want to use this case ,cancel note. + + # for x in range(10): + # dataType= [ "tinyint", "smallint", "int", "bigint", "float", "double", "bool", " binary(20)", "nchar(20)", "tinyint unsigned", "smallint unsigned", "int unsigned", "bigint unsigned"] + # tdSql.execute("drop database if exists db3") + # tdSql.execute("create database db3 keep 3650 replica 2 ") + # tdSql.execute("use db3") + # tdSql.execute('''create table test(ts timestamp, col0 tinyint, col1 tinyint, col2 smallint, col3 int, col4 bigint, col5 float, col6 double, + # col7 bool, col8 binary(20), col9 nchar(20), col10 tinyint unsigned, col11 smallint unsigned, col12 int unsigned, col13 bigint unsigned) tags(loc nchar(3000), tag1 int)''') + # rowNum2= 988 + # for i in range(rowNum2): + # tdSql.execute("alter table test add column col%d %s ;" %( i+14, choice(dataType)) ) + # rowNum3= 988 + # for i in range(rowNum3): + # tdSql.execute("alter table test drop column col%d ;" %( i+14) ) + # self.rowNum = 50 + # self.rowNum2 = 2000 + # self.ts = 1537146000000 + # for j in range(self.rowNum2): + # tdSql.execute("create table test%d using test tags('beijing%d', 10)" % (j,j) ) + # for i in range(self.rowNum): + # tdSql.execute("insert into test%d values(%d, %d, %d, %d, %d, %d, %f, %f, %d, 'taosdata%d', '涛思数据%d', %d, %d, %d, %d)" + # % (j, self.ts + i*1000, i + 1, i + 1, i + 1, i + 1, i + 1, i + 0.1, i + 0.1, i % 2, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1)) + + # # check data correct + # tdSql.execute("show databases") + # tdSql.execute("use db3") + # tdSql.query("select count (tbname) from test") + # tdSql.checkData(0, 0, 200) + # tdSql.query("select count (*) from test") + # tdSql.checkData(0, 0, 200000) + + + # delete useless file + testcaseFilename = os.path.split(__file__)[-1] + os.system("rm -rf ./insert_res.txt") + os.system("rm -rf manualTest/TD-5114/%s.sql" % testcaseFilename ) + +clients = TwoClients() +clients.initConnection() +# clients.getBuildPath() +clients.run() \ No newline at end of file diff --git a/tests/pytest/manualTest/TD-5114/insertDataDb3Replica2.json b/tests/pytest/manualTest/TD-5114/insertDataDb3Replica2.json new file mode 100644 index 0000000000000000000000000000000000000000..b2755823ef3e205fe74b16e29dadf0773549a3cf --- /dev/null +++ b/tests/pytest/manualTest/TD-5114/insertDataDb3Replica2.json @@ -0,0 +1,61 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 0, + "num_of_records_per_req": 3000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db3", + "drop": "yes", + "replica": 2, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 20000, + "childtable_prefix": "stb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 1000, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 2000, + "childtable_limit": 0, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }] + }] +} diff --git a/tests/pytest/manualTest/TD-5114/rollingUpgrade.py b/tests/pytest/manualTest/TD-5114/rollingUpgrade.py new file mode 100644 index 0000000000000000000000000000000000000000..f634eb1208b69f263ea89db2440db40ec3e085e6 --- /dev/null +++ b/tests/pytest/manualTest/TD-5114/rollingUpgrade.py @@ -0,0 +1,275 @@ +################################################################### +# 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 sys import version +from fabric import Connection +import random +import time +import datetime +import logging +import subprocess +import os +import sys + +class Node: + def __init__(self, index, username, hostIP, password, version): + self.index = index + self.username = username + self.hostIP = hostIP + # self.hostName = hostName + # self.homeDir = homeDir + self.version = version + self.verName = "TDengine-enterprise-server-%s-Linux-x64.tar.gz" % self.version + self.installPath = "TDengine-enterprise-server-%s" % self.version + # self.corePath = '/coredump' + self.conn = Connection("{}@{}".format(username, hostIP), connect_kwargs={"password": "{}".format(password)}) + + + def buildTaosd(self): + try: + print(self.conn) + # self.conn.run('echo "1234" > /home/chr/installtest/test.log') + self.conn.run("cd /home/chr/installtest/ && tar -xvf %s " %self.verName) + self.conn.run("cd /home/chr/installtest/%s && ./install.sh " % self.installPath) + except Exception as e: + print("Build Taosd error for node %d " % self.index) + logging.exception(e) + pass + + def rebuildTaosd(self): + try: + print(self.conn) + # self.conn.run('echo "1234" > /home/chr/installtest/test.log') + self.conn.run("cd /home/chr/installtest/%s && ./install.sh " % self.installPath) + except Exception as e: + print("Build Taosd error for node %d " % self.index) + logging.exception(e) + pass + + def startTaosd(self): + try: + self.conn.run("sudo systemctl start taosd") + except Exception as e: + print("Start Taosd error for node %d " % self.index) + logging.exception(e) + + def restartTarbi(self): + try: + self.conn.run("sudo systemctl restart tarbitratord ") + except Exception as e: + print("Start Taosd error for node %d " % self.index) + logging.exception(e) + + def clearData(self): + timeNow = datetime.datetime.now() + # timeYes = datetime.datetime.now() + datetime.timedelta(days=-1) + timStr = timeNow.strftime('%Y%m%d%H%M%S') + # timStr = timeNow.strftime('%Y%m%d%H%M%S') + try: + # self.conn.run("mv /var/lib/taos/ /var/lib/taos%s " % timStr) + self.conn.run("rm -rf /home/chr/data/taos*") + except Exception as e: + print("rm -rf /var/lib/taos error %d " % self.index) + logging.exception(e) + + def stopTaosd(self): + try: + self.conn.run("sudo systemctl stop taosd") + except Exception as e: + print("Stop Taosd error for node %d " % self.index) + logging.exception(e) + + def restartTaosd(self): + try: + self.conn.run("sudo systemctl restart taosd") + except Exception as e: + print("Stop Taosd error for node %d " % self.index) + logging.exception(e) + +class oneNode: + + def FirestStartNode(self, id, username, IP, passwd, version): + # get installPackage + verName = "TDengine-enterprise-server-%s-Linux-x64.tar.gz" % version + # installPath = "TDengine-enterprise-server-%s" % self.version + node131 = Node(131, 'ubuntu', '192.168.1.131', 'tbase125!', '2.0.20.0') + node131.conn.run('sshpass -p tbase125! scp /nas/TDengine/v%s/enterprise/%s root@192.168.1.%d:/home/chr/installtest/' % (version,verName,id)) + node131.conn.close() + # install TDengine at 192.168.103/104/141 + try: + node = Node(id, username, IP, passwd, version) + node.conn.run('echo "start taosd"') + node.buildTaosd() + # clear DataPath , if need clear data + node.clearData() + node.startTaosd() + if id == 103 : + node.restartTarbi() + print("start taosd ver:%s node:%d successfully " % (version,id)) + node.conn.close() + + # query_pid = int(subprocess.getstatusoutput('ps aux|grep taosd |grep -v "grep"|awk \'{print $2}\'')[1]) + # assert query_pid == 1 , "node %d: start taosd failed " % id + except Exception as e: + print("Stop Taosd error for node %d " % id) + logging.exception(e) + + def startNode(self, id, username, IP, passwd, version): + # start TDengine + try: + node = Node(id, username, IP, passwd, version) + node.conn.run('echo "restart taosd"') + # clear DataPath , if need clear data + node.clearData() + node.restartTaosd() + time.sleep(5) + if id == 103 : + node.restartTarbi() + print("start taosd ver:%s node:%d successfully " % (version,id)) + node.conn.close() + + # query_pid = int(subprocess.getstatusoutput('ps aux|grep taosd |grep -v "grep"|awk \'{print $2}\'')[1]) + # assert query_pid == 1 , "node %d: start taosd failed " % id + except Exception as e: + print("Stop Taosd error for node %d " % id) + logging.exception(e) + + def firstUpgradeNode(self, id, username, IP, passwd, version): + # get installPackage + verName = "TDengine-enterprise-server-%s-Linux-x64.tar.gz" % version + # installPath = "TDengine-enterprise-server-%s" % self.version + node131 = Node(131, 'ubuntu', '192.168.1.131', 'tbase125!', '2.0.20.0') + node131.conn.run('echo "upgrade cluster"') + node131.conn.run('sshpass -p tbase125! scp /nas/TDengine/v%s/enterprise/%s root@192.168.1.%d:/home/chr/installtest/' % (version,verName,id)) + node131.conn.close() + # upgrade TDengine at 192.168.103/104/141 + try: + node = Node(id, username, IP, passwd, version) + node.conn.run('echo "start taosd"') + node.conn.run('echo "1234" > /home/chr/test.log') + node.buildTaosd() + time.sleep(5) + node.startTaosd() + if id == 103 : + node.restartTarbi() + print("start taosd ver:%s node:%d successfully " % (version,id)) + node.conn.close() + + # query_pid = int(subprocess.getstatusoutput('ps aux|grep taosd |grep -v "grep"|awk \'{print $2}\'')[1]) + # assert query_pid == 1 , "node %d: start taosd failed " % id + except Exception as e: + print("Stop Taosd error for node %d " % id) + logging.exception(e) + + def upgradeNode(self, id, username, IP, passwd, version): + + # backCluster TDengine at 192.168.103/104/141 + try: + node = Node(id, username, IP, passwd, version) + node.conn.run('echo "rollback taos"') + node.rebuildTaosd() + time.sleep(5) + node.startTaosd() + if id == 103 : + node.restartTarbi() + print("start taosd ver:%s node:%d successfully " % (version,id)) + node.conn.close() + except Exception as e: + print("Stop Taosd error for node %d " % id) + logging.exception(e) + + +# how to use : cd TDinternal/commumity/test/pytest && python3 manualTest/rollingUpgrade.py ,when inserting data, we can start " python3 manualTest/rollingUpagrade.py". add example "oneNode().FirestStartNode(103,'root','192.168.1.103','tbase125!','2.0.20.0')" + + +# node103=oneNode().FirestStartNode(103,'root','192.168.1.103','tbase125!','2.0.20.0') +# node104=oneNode().FirestStartNode(104,'root','192.168.1.104','tbase125!','2.0.20.0') +# node141=oneNode().FirestStartNode(141,'root','192.168.1.141','tbase125!','2.0.20.0') + +# node103=oneNode().startNode(103,'root','192.168.1.103','tbase125!','2.0.20.0') +# time.sleep(30) +# node141=oneNode().startNode(141,'root','192.168.1.141','tbase125!','2.0.20.0') +# time.sleep(30) +# node104=oneNode().startNode(104,'root','192.168.1.104','tbase125!','2.0.20.0') +# time.sleep(30) + +# node103=oneNode().firstUpgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.5') +# time.sleep(30) +# node104=oneNode().firstUpgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.5') +# time.sleep(30) +# node141=oneNode().firstUpgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.5') +# time.sleep(30) + +# node141=oneNode().firstUpgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.10') +# time.sleep(30) +# node103=oneNode().firstUpgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.10') +# time.sleep(30) +# node104=oneNode().firstUpgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.10') +# time.sleep(30) + +# node141=oneNode().firstUpgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.12') +# time.sleep(30) +# node103=oneNode().firstUpgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.12') +# time.sleep(30) +# node104=oneNode().firstUpgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.12') +# time.sleep(30) + + + +# node103=oneNode().upgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.0') +# time.sleep(120) +# node104=oneNode().upgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.0') +# time.sleep(180) +# node141=oneNode().upgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.0') +# time.sleep(240) + +# node104=oneNode().upgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.5') +# time.sleep(120) +# node103=oneNode().upgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.5') +# time.sleep(120) +# node141=oneNode().upgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.5') +# time.sleep(180) + +# node141=oneNode().upgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.10') +# time.sleep(120) +# node103=oneNode().upgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.10') +# time.sleep(120) +# node104=oneNode().upgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.10') +# time.sleep(180) + +# node103=oneNode().upgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.12') +# time.sleep(180) +# node141=oneNode().upgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.12') +# time.sleep(180) +# node104=oneNode().upgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.12') + + +# node141=oneNode().firstUpgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.9') +# time.sleep(5) +# node103=oneNode().firstUpgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.9') +# time.sleep(5) +# node104=oneNode().firstUpgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.9') +# time.sleep(30) + +# node141=oneNode().upgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.10') +# time.sleep(12) +# node103=oneNode().upgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.10') +# time.sleep(12) +# node104=oneNode().upgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.10') +# time.sleep(180) + +# node103=oneNode().upgradeNode(103,'root','192.168.1.103','tbase125!','2.0.20.12') +# time.sleep(120) +# node141=oneNode().upgradeNode(141,'root','192.168.1.141','tbase125!','2.0.20.12') +# time.sleep(120) +# node104=oneNode().upgradeNode(104,'root','192.168.1.104','tbase125!','2.0.20.12') diff --git a/tests/pytest/query/filterNoKeyword.py b/tests/pytest/query/filterNoKeyword.py new file mode 100644 index 0000000000000000000000000000000000000000..34d74efd8200dbfae13ec24c9cd8b6792b009a6b --- /dev/null +++ b/tests/pytest/query/filterNoKeyword.py @@ -0,0 +1,83 @@ +################################################################### +# 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 taos +from util.log import * +from util.cases import * +from util.sql import * + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + + self.ts = 1537146000000 + + def run(self): + tdSql.prepare() + + print("======= Verify filter for bool, nchar and binary type =========") + tdLog.debug( + "create table st(ts timestamp, tbcol1 bool, tbcol2 binary(10), tbcol3 nchar(20), tbcol4 tinyint, tbcol5 smallint, tbcol6 int, tbcol7 bigint, tbcol8 float, tbcol9 double) tags(tagcol1 bool, tagcol2 binary(10), tagcol3 nchar(10))") + tdSql.execute( + "create table st(ts timestamp, tbcol1 bool, tbcol2 binary(10), tbcol3 nchar(20), tbcol4 tinyint, tbcol5 smallint, tbcol6 int, tbcol7 bigint, tbcol8 float, tbcol9 double) tags(tagcol1 bool, tagcol2 binary(10), tagcol3 nchar(10))") + + tdSql.execute("create table st1 using st tags(true, 'table1', '水表')") + for i in range(1, 6): + tdSql.execute( + "insert into st1 values(%d, %d, 'taosdata%d', '涛思数据%d', %d, %d, %d, %d, %f, %f)" % + (self.ts + i, i % + 2, i, i, + i, i, i, i, 1.0, 1.0)) + + # =============Data type keywords cannot be used in filter==================== + # timestamp + tdSql.error("select * from st where timestamp = 1629417600") + + # bool + tdSql.error("select * from st where bool = false") + + #binary + tdSql.error("select * from st where binary = 'taosdata'") + + # nchar + tdSql.error("select * from st where nchar = '涛思数据'") + + # tinyint + tdSql.error("select * from st where tinyint = 127") + + # smallint + tdSql.error("select * from st where smallint = 32767") + + # int + tdSql.error("select * from st where INTEGER = 2147483647") + tdSql.error("select * from st where int = 2147483647") + + # bigint + tdSql.error("select * from st where bigint = 2147483647") + + # float + tdSql.error("select * from st where float = 3.4E38") + + # double + tdSql.error("select * from st where double = 1.7E308") + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/query/last_row_cache.py b/tests/pytest/query/last_row_cache.py index 83153841496b9ef4e0b7d919b44cf0a9e05b02c6..0e11e3d60c08362c0114166dcf071990893689f8 100644 --- a/tests/pytest/query/last_row_cache.py +++ b/tests/pytest/query/last_row_cache.py @@ -25,7 +25,7 @@ class TDTestCase: self.tables = 10 self.rows = 20 - self.columns = 5 + self.columns = 100 self.perfix = 't' self.ts = 1601481600000 @@ -33,8 +33,8 @@ class TDTestCase: print("==============step1") sql = "create table st(ts timestamp, " for i in range(self.columns - 1): - sql += "c%d int, " % (i + 1) - sql += "c5 int) tags(t1 int)" + sql += "c%d bigint, " % (i + 1) + sql += "c100 bigint) tags(t1 int)" tdSql.execute(sql) for i in range(self.tables): diff --git a/tests/pytest/query/nestedQuery/queryWithOrderLimit.py b/tests/pytest/query/nestedQuery/queryWithOrderLimit.py index 692b5b7d364bee2164bda6707443b29c4cef4d14..aa16e8cc76e2c09bccf1ae5a8ab969d5ac9cb83e 100644 --- a/tests/pytest/query/nestedQuery/queryWithOrderLimit.py +++ b/tests/pytest/query/nestedQuery/queryWithOrderLimit.py @@ -29,7 +29,6 @@ class TDTestCase: self.tables = 10 self.rowsPerTable = 100 - def run(self): # tdSql.execute("drop database db ") tdSql.prepare() diff --git a/tests/pytest/query/query.py b/tests/pytest/query/query.py index 8cec38780e5e873cb07d8ade45ef56b5d4ee43f7..c759e7766827e9b8e30f1b9ceb812c755fb057ae 100644 --- a/tests/pytest/query/query.py +++ b/tests/pytest/query/query.py @@ -25,6 +25,18 @@ class TDTestCase: self.ts = 1538548685000 + def bug_6387(self): + tdSql.execute("create database bug6387 ") + tdSql.execute("use bug6387 ") + tdSql.execute("create table test(ts timestamp, c1 int) tags(t1 int)") + for i in range(5000): + sql = "insert into t%d using test tags(1) values " % i + for j in range(21): + sql = sql + "(now+%ds,%d)" % (j ,j ) + tdSql.execute(sql) + tdSql.query("select count(*) from test interval(1s) group by tbname") + tdSql.checkData(0,1,1) + def run(self): tdSql.prepare() @@ -121,6 +133,9 @@ class TDTestCase: tdSql.query("select * from tb0") tdSql.checkRows(1) + + #For jira: https://jira.taosdata.com:18080/browse/TD-6387 + self.bug_6387() def stop(self): diff --git a/tests/pytest/query/queryDiffColsOr.py b/tests/pytest/query/queryDiffColsOr.py new file mode 100644 index 0000000000000000000000000000000000000000..e9e791da9f34c881d5c846b9bcc112866e5d992b --- /dev/null +++ b/tests/pytest/query/queryDiffColsOr.py @@ -0,0 +1,578 @@ +################################################################### +# 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 util.log import tdLog +from util.cases import tdCases +from util.sql import tdSql +from util.common import tdCom +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def insertData(self, tb_name): + insert_sql_list = [f'insert into {tb_name} values ("2021-01-01 12:00:00", 1, 1, 1, 3, 1.1, 1.1, "binary", "nchar", true, 1)', + f'insert into {tb_name} values ("2021-01-05 12:00:00", 2, 2, 1, 3, 1.1, 1.1, "binary", "nchar", true, 2)', + f'insert into {tb_name} values ("2021-01-07 12:00:00", 1, 3, 1, 2, 1.1, 1.1, "binary", "nchar", true, 3)', + f'insert into {tb_name} values ("2021-01-09 12:00:00", 1, 2, 4, 3, 1.1, 1.1, "binary", "nchar", true, 4)', + f'insert into {tb_name} values ("2021-01-11 12:00:00", 1, 2, 5, 5, 1.1, 1.1, "binary", "nchar", true, 5)', + f'insert into {tb_name} values ("2021-01-13 12:00:00", 1, 2, 1, 3, 6.6, 1.1, "binary", "nchar", true, 6)', + f'insert into {tb_name} values ("2021-01-15 12:00:00", 1, 2, 1, 3, 1.1, 7.7, "binary", "nchar", true, 7)', + f'insert into {tb_name} values ("2021-01-17 12:00:00", 1, 2, 1, 3, 1.1, 1.1, "binary8", "nchar", true, 8)', + f'insert into {tb_name} values ("2021-01-19 12:00:00", 1, 2, 1, 3, 1.1, 1.1, "binary", "nchar9", true, 9)', + f'insert into {tb_name} values ("2021-01-21 12:00:00", 1, 2, 1, 3, 1.1, 1.1, "binary", "nchar", false, 10)', + f'insert into {tb_name} values ("2021-01-23 12:00:00", 1, 3, 1, 3, 1.1, 1.1, Null, Null, false, 11)' + ] + for sql in insert_sql_list: + tdSql.execute(sql) + + def initTb(self): + tdCom.cleanTb() + tb_name = tdCom.getLongName(8, "letters") + tdSql.execute( + f"CREATE TABLE {tb_name} (ts timestamp, c1 tinyint, c2 smallint, c3 int, c4 bigint, c5 float, c6 double, c7 binary(100), c8 nchar(200), c9 bool, c10 int)") + self.insertData(tb_name) + return tb_name + + def initStb(self): + tdCom.cleanTb() + tb_name = tdCom.getLongName(8, "letters") + tdSql.execute( + f"CREATE TABLE {tb_name} (ts timestamp, c1 tinyint, c2 smallint, c3 int, c4 bigint, c5 float, c6 double, c7 binary(100), c8 nchar(200), c9 bool, c10 int) tags (t1 tinyint, t2 smallint, t3 int, t4 bigint, t5 float, t6 double, t7 binary(100), t8 nchar(200), t9 bool, t10 int)") + tdSql.execute( + f'CREATE TABLE {tb_name}_sub using {tb_name} tags (1, 1, 1, 3, 1.1, 1.1, "binary", "nchar", true, 1)') + self.insertData(f'{tb_name}_sub') + return tb_name + + def queryLastC10(self, query_sql, multi=False): + if multi: + res = tdSql.query(query_sql.replace('c10', 'last(*)'), True) + else: + res = tdSql.query(query_sql.replace('*', 'last(*)'), True) + return int(res[0][-1]) + + def queryFullColType(self, tb_name): + ## ts + query_sql = f'select * from {tb_name} where ts > "2021-01-11 12:00:00" or ts < "2021-01-13 12:00:00"' + tdSql.query(query_sql) + tdSql.checkRows(11) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## != or + query_sql = f'select * from {tb_name} where c1 != 1 or c2 = 3' + tdSql.query(query_sql) + tdSql.checkRows(3) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## <> or + query_sql = f'select * from {tb_name} where c1 <> 1 or c3 = 3' + tdSql.query(query_sql) + tdSql.checkRows(1) + tdSql.checkEqual(self.queryLastC10(query_sql), 2) + + ## >= or + query_sql = f'select * from {tb_name} where c1 >= 2 or c3 = 4' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 4) + + ## <= or + query_sql = f'select * from {tb_name} where c1 <= 1 or c3 = 4' + tdSql.query(query_sql) + tdSql.checkRows(10) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## <> or is Null + query_sql = f'select * from {tb_name} where c1 <> 1 or c7 is Null' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## > or is not Null + query_sql = f'select * from {tb_name} where c2 > 2 or c8 is not Null' + tdSql.query(query_sql) + tdSql.checkRows(11) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## > or < or >= or <= or != or <> or = Null + query_sql = f'select * from {tb_name} where c1 > 1 or c2 < 2 or c3 >= 4 or c4 <= 2 or c5 != 1.1 or c6 <> 1.1 or c7 is Null' + tdSql.query(query_sql) + tdSql.checkRows(8) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## tiny small int big or + query_sql = f'select * from {tb_name} where c1 = 2 or c2 = 3 or c3 = 4 or c4 = 5' + tdSql.query(query_sql) + tdSql.checkRows(5) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## float double binary nchar bool or + query_sql = f'select * from {tb_name} where c5=6.6 or c6=7.7 or c7="binary8" or c8="nchar9" or c9=false' + tdSql.query(query_sql) + tdSql.checkRows(6) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## all types or + query_sql = f'select * from {tb_name} where c1=2 or c2=3 or c3=4 or c4=5 or c5=6.6 or c6=7.7 or c7="binary8" or c8="nchar9" or c9=false' + tdSql.query(query_sql) + tdSql.checkRows(10) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + def queryMultiExpression(self, tb_name): + ## condition_A and condition_B or condition_C (> < >=) + query_sql = f'select * from {tb_name} where c1 > 2 and c2 < 4 or c3 >= 4' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 5) + + ## (condition_A and condition_B) or condition_C (<= != <>) + query_sql = f'select * from {tb_name} where (c1 <= 1 and c2 != 2) or c4 <> 3' + tdSql.query(query_sql) + tdSql.checkRows(4) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## condition_A and (condition_B or condition_C) (Null not Null) + query_sql = f'select * from {tb_name} where c1 is not Null and (c6 = 7.7 or c8 is Null)' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## condition_A or condition_B and condition_C (> < >=) + query_sql = f'select * from {tb_name} where c1 > 2 or c2 < 4 and c3 >= 4' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 5) + + ## (condition_A or condition_B) and condition_C (<= != <>) + query_sql = f'select * from {tb_name} where (c1 <= 1 or c2 != 2) and c4 <> 3' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 5) + + ## condition_A or (condition_B and condition_C) (Null not Null) + query_sql = f'select * from {tb_name} where c6 >= 7.7 or (c1 is not Null and c3 =5)' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 7) + + ## condition_A or (condition_B and condition_C) or condition_D (> != < Null) + query_sql = f'select * from {tb_name} where c1 != 1 or (c2 >2 and c3 < 1) or c7 is Null' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## condition_A and (condition_B or condition_C) and condition_D (>= = <= not Null) + query_sql = f'select * from {tb_name} where c4 >= 4 and (c1 = 2 or c5 <= 1.1) and c7 is not Null' + tdSql.query(query_sql) + tdSql.checkRows(1) + tdSql.checkEqual(self.queryLastC10(query_sql), 5) + + ## (condition_A and condition_B) or (condition_C or condition_D) (Null >= > =) + query_sql = f'select * from {tb_name} where (c8 is Null and c1 >= 1) or (c3 > 3 or c4 =2)' + tdSql.query(query_sql) + tdSql.checkRows(4) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## (condition_A or condition_B) or condition_C or (condition_D and condition_E) (>= <= = not Null <>) + query_sql = f'select * from {tb_name} where (c1 >= 2 or c2 <= 1) or c3 = 4 or (c7 is not Null and c6 <> 1.1)' + tdSql.query(query_sql) + tdSql.checkRows(4) + tdSql.checkEqual(self.queryLastC10(query_sql), 7) + + ## condition_A or (condition_B and condition_C) or (condition_D and condition_E) and condition_F + query_sql = f'select * from {tb_name} where c1 != 1 or (c2 <= 1 and c3 <4) or (c3 >= 4 or c7 is not Null) and c9 <> true' + tdSql.query(query_sql) + tdSql.checkRows(3) + tdSql.checkEqual(self.queryLastC10(query_sql), 10) + + ## (condition_A or (condition_B and condition_C) or (condition_D and condition_E)) and condition_F + query_sql = f'select * from {tb_name} where (c1 != 1 or (c2 <= 2 and c3 >= 4) or (c3 >= 4 or c7 is not Null)) and c9 != false' + tdSql.query(query_sql) + tdSql.checkRows(9) + tdSql.checkEqual(self.queryLastC10(query_sql), 9) + + ## (condition_A or condition_B) or (condition_C or condition_D) and (condition_E or condition_F or condition_G) + query_sql = f'select * from {tb_name} where c1 != 1 or (c2 <= 3 and c3 > 4) and c3 <= 5 and (c7 is not Null and c9 != false)' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 5) + + def queryMultiIn(self, tb_name): + ## in and in + query_sql = f'select * from {tb_name} where c7 in ("binary") and c8 in ("nchar")' + tdSql.query(query_sql) + tdSql.checkRows(8) + tdSql.checkEqual(self.queryLastC10(query_sql), 10) + + ## in or in + query_sql = f'select * from {tb_name} where c1 in (2, 4) or c2 in (1, 4)' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 2) + + ## in and in or condition_A + query_sql = f'select * from {tb_name} where c7 in ("binary") and c8 in ("nchar") or c10 != 10' + tdSql.query(query_sql) + tdSql.checkRows(11) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## in or in and condition_A + query_sql = f'select * from {tb_name} where c7 in ("binary") or c8 in ("nchar") and c10 != 10' + tdSql.query(query_sql) + tdSql.checkRows(10) + tdSql.checkEqual(self.queryLastC10(query_sql), 10) + + ## in or in or condition_A + query_sql = f'select * from {tb_name} where c1 in (2, 4) or c2 in (3, 4) or c9 != true' + tdSql.query(query_sql) + tdSql.checkRows(4) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## in or in or in or in + query_sql = f'select * from {tb_name} where c1 in (2, 4) or c2 in (3, 4) or c9 in (false) or c10 in (5, 6 ,22)' + tdSql.query(query_sql) + tdSql.checkRows(6) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## in or in and in or in + query_sql = f'select * from {tb_name} where c1 in (2, 4) or c2 in (3, 4) and c9 in (false) or c10 in (5, 6 ,22)' + tdSql.query(query_sql) + tdSql.checkRows(4) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## condition_A or in or condition_B and in + query_sql = f'select * from {tb_name} where c1 = 2 or c2 in (2, 4) and c9 = false or c10 in (6 ,22)' + tdSql.query(query_sql) + tdSql.checkRows(3) + tdSql.checkEqual(self.queryLastC10(query_sql), 10) + + ## in and condition_A or in and in and condition_B + query_sql = f'select * from {tb_name} where c1 in (2, 3) and c2 <> 3 or c10 <= 4 and c10 in (4 ,22) and c9 != false' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 4) + + ## (in and condition_A or in) and in and condition_B + query_sql = f'select * from {tb_name} where (c1 in (2, 3) and c2 <> 3 or c10 <= 4) and c10 in (4 ,22) and c9 != false' + tdSql.query(query_sql) + tdSql.checkRows(1) + tdSql.checkEqual(self.queryLastC10(query_sql), 4) + + def queryMultiLike(self, tb_name): + ## like and like + query_sql = f'select * from {tb_name} where c7 like "bi%" and c8 like ("ncha_")' + tdSql.query(query_sql) + tdSql.checkRows(9) + tdSql.checkEqual(self.queryLastC10(query_sql), 10) + + ## like or like + query_sql = f'select * from {tb_name} where c7 like "binar12345" or c8 like "nchar_"' + tdSql.query(query_sql) + tdSql.checkRows(1) + tdSql.checkEqual(self.queryLastC10(query_sql), 9) + + ## like and like or condition_A + query_sql = f'select * from {tb_name} where c7 like "binary_" and c8 like "ncha_" or c1 != 1' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 8) + + ## like or like and condition_A + query_sql = f'select * from {tb_name} where c7 like ("binar_") or c8 like ("nchar_") and c10 != 8' + tdSql.query(query_sql) + tdSql.checkRows(9) + tdSql.checkEqual(self.queryLastC10(query_sql), 10) + + ## like or like or condition_A + query_sql = f'select * from {tb_name} where c7 like ("binary_") or c8 like ("nchar_") or c10 = 6' + tdSql.query(query_sql) + tdSql.checkRows(3) + tdSql.checkEqual(self.queryLastC10(query_sql), 9) + + ## like or like or like or like + query_sql = f'select * from {tb_name} where c7 like ("binary_") or c8 like ("nchar_") or c10 = 6 or c7 is Null' + tdSql.query(query_sql) + tdSql.checkRows(4) + tdSql.checkEqual(self.queryLastC10(query_sql), 11) + + ## like or like and like or like + query_sql = f'select * from {tb_name} where c7 like ("binary_") or c8 like ("ncha_") and c10 = 6 or c10 = 9' + tdSql.query(query_sql) + tdSql.checkRows(3) + tdSql.checkEqual(self.queryLastC10(query_sql), 9) + + ## condition_A or like or condition_B and like + query_sql = f'select * from {tb_name} where c1 = 2 or c7 like "binary_" or c10 = 3 and c8 like "ncha%"' + tdSql.query(query_sql) + tdSql.checkRows(3) + tdSql.checkEqual(self.queryLastC10(query_sql), 8) + + ## like and condition_A or like and like and condition_B + query_sql = f'select * from {tb_name} where c7 like "bin%" and c2 = 3 or c10 <= 4 and c7 like "binar_" and c8 like "ncha_"' + tdSql.query(query_sql) + tdSql.checkRows(4) + tdSql.checkEqual(self.queryLastC10(query_sql), 4) + + ## (like and condition_A or like) and like and condition_B + query_sql = f'select * from {tb_name} where (c7 like "bin%" and c2 = 3 or c8 like "nchar_") and c7 like "binar_" and c9 != false' + tdSql.query(query_sql) + tdSql.checkRows(2) + tdSql.checkEqual(self.queryLastC10(query_sql), 9) + + def queryPreCal(self, tb_name): + ## avg sum condition_A or condition_B + query_sql = f'select avg(c3), sum(c3) from {tb_name} where c10 = 5 or c8 is Null' + res = tdSql.query(query_sql, True)[0] + tdSql.checkEqual(int(res[0]), 3) + tdSql.checkEqual(int(res[1]), 6) + + ## avg sum condition_A or condition_B or condition_C + query_sql = f'select avg(c3), sum(c3) from {tb_name} where c10 = 4 or c8 is Null or c9 = false ' + res = tdSql.query(query_sql, True)[0] + tdSql.checkEqual(int(res[0]), 2) + tdSql.checkEqual(int(res[1]), 6) + + ## count avg sum condition_A or condition_B or condition_C interval + query_sql = f'select count(*), avg(c3), sum(c3) from {tb_name} where c10 = 4 or c8 is Null or c9 = false interval(16d)' + res = tdSql.query(query_sql, True) + tdSql.checkRows(2) + tdSql.checkEqual(int(res[0][1]), 1) + tdSql.checkEqual(int(res[0][2]), 4) + tdSql.checkEqual(int(res[0][3]), 4) + tdSql.checkEqual(int(res[1][1]), 2) + tdSql.checkEqual(int(res[1][2]), 1) + tdSql.checkEqual(int(res[1][3]), 2) + + ## count avg sum condition_A or condition_B or in and like or condition_C interval + query_sql = f'select count(*), sum(c3) from {tb_name} where c10 = 4 or c8 is Null or c2 in (1, 2) and c7 like "binary_" or c1 <> 1 interval(16d)' + res = tdSql.query(query_sql, True) + tdSql.checkRows(2) + tdSql.checkEqual(int(res[0][1]), 2) + tdSql.checkEqual(int(res[0][2]), 5) + tdSql.checkEqual(int(res[1][1]), 2) + tdSql.checkEqual(int(res[1][2]), 2) + + def queryMultiTb(self, tb_name): + ## select from (condition_A or condition_B) + query_sql = f'select c10 from (select * from {tb_name} where c1 >1 or c2 >=3)' + res = tdSql.query(query_sql, True) + tdSql.checkRows(3) + tdSql.checkEqual(int(res[2][0]), 11) + + ## select from (condition_A or condition_B) where condition_A or condition_B + query_sql = f'select c10 from (select * from {tb_name} where c1 >1 or c2 >=3) where c1 =2 or c4 = 2' + res = tdSql.query(query_sql, True) + tdSql.checkRows(2) + tdSql.checkEqual(int(res[1][0]), 3) + + ## select from (condition_A or condition_B and like and in) where condition_A or condition_B or like and in + query_sql = f'select c10 from (select * from {tb_name} where c1 >1 or c2 = 2 and c7 like "binar_" and c4 in (3, 5)) where c1 != 2 or c3 = 1 or c8 like "ncha_" and c9 in (true)' + res = tdSql.query(query_sql, True) + tdSql.checkRows(7) + tdSql.checkEqual(int(res[6][0]), 10) + + ## select count avg sum from (condition_A or condition_B and like and in) where condition_A or condition_B or like and in interval + query_sql = f'select count(*), avg(c6), sum(c3) from (select * from {tb_name} where c1 >1 or c2 = 2 and c7 like "binar_" and c4 in (3, 5)) where c1 != 2 or c3 = 1 or c8 like "ncha_" and c9 in (true) interval(8d)' + res = tdSql.query(query_sql, True) + tdSql.checkRows(3) + tdSql.checkEqual(int(res[0][1]), 3) + tdSql.checkEqual(int(res[0][2]), 1) + tdSql.checkEqual(int(res[0][3]), 10) + tdSql.checkEqual(int(res[1][1]), 3) + tdSql.checkEqual(int(res[1][2]), 3) + tdSql.checkEqual(int(res[1][3]), 3) + tdSql.checkEqual(int(res[2][1]), 1) + tdSql.checkEqual(int(res[2][2]), 1) + tdSql.checkEqual(int(res[2][3]), 1) + + ## cname + query_sql = f'select c10 from (select * from {tb_name} where c1 >1 or c2 = 2 and c7 like "binar_" and c4 in (3, 5)) a where a.c1 != 2 or a.c3 = 1 or a.c8 like "ncha_" and a.c9 in (true)' + res = tdSql.query(query_sql, True) + tdSql.checkRows(7) + tdSql.checkEqual(int(res[6][0]), 10) + + ## multi cname + query_sql = f'select b.c10 from (select * from {tb_name} where c9 = true or c2 = 2) a, (select * from {tb_name} where c7 like "binar_" or c4 in (3, 5)) b where a.ts = b.ts' + res = tdSql.query(query_sql, True) + tdSql.checkRows(10) + tdSql.checkEqual(int(res[9][0]), 10) + + def queryMultiTbWithTag(self, tb_name): + # tags (1, 1, 1, 3, 1.1, 1.1, "binary", "nchar", true, 1)') + + tdSql.execute( + f'CREATE TABLE {tb_name}_sub2 using {tb_name} tags (2, 2, 2, 4, 2.2, 2.2, "binary2", "nchar2", true, 12)') + tdSql.execute( + f'CREATE TABLE {tb_name}_sub3 using {tb_name} tags (3, 3, 3, 3, 3.3, 3.3, "binary3", "nchar3", true, 13)') + tdSql.execute( + f'insert into {tb_name}_sub2 values ("2021-01-25 12:00:00", 2, 2, 2, 4, 2.2, 2.2, "binary2", "nchar2", true, 12)') + tdSql.execute( + f'insert into {tb_name}_sub3 values ("2021-01-27 12:00:00", 3, 3, 3, 3, 3.3, 3.3, "binary3", "nchar3", true, 13)') + ## select count avg sum from (condition_A or condition_B and like and in) where condition_A or condition_B or condition_tag_C or condition_tag_D or like and in interval + query_sql = f'select count(*), avg(c6), sum(c3) from (select * from {tb_name} where c1 >1 or c2 = 2 and c7 like "binar_" and c4 in (3, 5)) where c1 != 2 or c3 = 1 or t1=2 or t1=3 or c8 like "ncha_" and c9 in (true) interval(8d)' + res = tdSql.query(query_sql, True) + tdSql.checkRows(3) + tdSql.checkEqual(int(res[0][1]), 3) + tdSql.checkEqual(int(res[0][2]), 1) + tdSql.checkEqual(int(res[0][3]), 10) + tdSql.checkEqual(int(res[1][1]), 3) + tdSql.checkEqual(int(res[1][2]), 3) + tdSql.checkEqual(int(res[1][3]), 3) + tdSql.checkEqual(int(res[2][1]), 3) + tdSql.checkEqual(int(res[2][2]), 2) + tdSql.checkEqual(int(res[2][3]), 6) + + + # ! to confirm + ## select count avg sum from (condition_A or condition_B or condition_tag_C or condition_tag_D and like and in) where condition_A or condition_B or like and in interval + # query_sql = f'select count(*), avg(c6), sum(c3) from (select * from {tb_name} where t1 = 3 and t1 = 2 or c1 >1 or c2 = 2 and c7 like "binar_" and c4 in (3, 5)) where c1 != 2 or c3 = 1 or c8 like "ncha_" and c9 in (true) interval(8d)' + # res = tdSql.query(query_sql, True) + # tdSql.checkRows(3) + # tdSql.checkEqual(int(res[0][1]), 3) + # tdSql.checkEqual(int(res[0][2]), 1) + # tdSql.checkEqual(int(res[0][3]), 10) + # tdSql.checkEqual(int(res[1][1]), 3) + # tdSql.checkEqual(int(res[1][2]), 3) + # tdSql.checkEqual(int(res[1][3]), 3) + # tdSql.checkEqual(int(res[2][1]), 3) + # tdSql.checkEqual(int(res[2][2]), 2) + # tdSql.checkEqual(int(res[2][3]), 6) + + ## select count avg sum from (condition_A and condition_B and and line and in and ts and condition_tag_A and condition_tag_B and between) where condition_C orr condition_D or condition_tag_C or condition_tag_D or like and in interval + query_sql = f'select count(*), avg(c6), sum(c3) from (select * from {tb_name} where c1 >= 1 and c2 = 2 and c7 like "binar_" and c4 in (3, 5) and ts > "2021-01-11 12:00:00" and t1 < 2 and t1 > 0 and c6 between 0 and 7) where c1 != 2 or c3 = 1 or t1=2 or t1=3 or c8 like "ncha_" and c9 in (true) interval(8d)' + res = tdSql.query(query_sql, True) + tdSql.checkRows(2) + tdSql.checkEqual(int(res[0][1]), 2) + tdSql.checkEqual(int(res[0][2]), 1) + tdSql.checkEqual(int(res[0][3]), 2) + tdSql.checkEqual(int(res[1][1]), 1) + tdSql.checkEqual(int(res[1][2]), 1) + tdSql.checkEqual(int(res[1][3]), 1) + + # ! to confirm + #select * from (select * from pyclqtwi where c1 >1 or c2 = 2 and c7 like "binar_" and c4 in (3, 5) and ts > "2021-01-11 12:00:00") where c1 != 2 or c3 = 1 or t1=2 or t1=3 or c8 like "ncha_" and c9 in (true) ; + #DB error: invalid operation: invalid expression (0.008747s) + + def checkTbColTypeOperator(self): + ''' + Ordinary table full column type and operator + ''' + tb_name = self.initTb() + self.queryFullColType(tb_name) + + def checkStbColTypeOperator(self): + ''' + Super table full column type and operator + ''' + tb_name = self.initStb() + self.queryFullColType(tb_name) + + def checkTbMultiExpression(self): + ''' + Ordinary table multiExpression + ''' + tb_name = self.initTb() + self.queryMultiExpression(tb_name) + + def checkStbMultiExpression(self): + ''' + Super table multiExpression + ''' + tb_name = self.initStb() + self.queryMultiExpression(tb_name) + + def checkTbMultiIn(self): + ''' + Ordinary table multiIn + ''' + tb_name = self.initTb() + self.queryMultiIn(tb_name) + + def checkStbMultiIn(self): + ''' + Super table multiIn + ''' + tb_name = self.initStb() + self.queryMultiIn(tb_name) + + def checkTbMultiLike(self): + ''' + Ordinary table multiLike + ''' + tb_name = self.initTb() + self.queryMultiLike(tb_name) + + def checkStbMultiLike(self): + ''' + Super table multiLike + ''' + tb_name = self.initStb() + self.queryMultiLike(tb_name) + + def checkTbPreCal(self): + ''' + Ordinary table precal + ''' + tb_name = self.initTb() + self.queryPreCal(tb_name) + + def checkStbPreCal(self): + ''' + Super table precal + ''' + tb_name = self.initStb() + self.queryPreCal(tb_name) + + def checkMultiTb(self): + ''' + test "or" in multi ordinary table + ''' + tb_name = self.initTb() + self.queryMultiTb(tb_name) + + def checkMultiStb(self): + ''' + test "or" in multi super table + ''' + tb_name = self.initStb() + self.queryMultiTb(tb_name) + + def checkMultiTbWithTag(self): + ''' + test Multi tb with tag + ''' + tb_name = self.initStb() + self.queryMultiTbWithTag(tb_name) + + def run(self): + tdSql.prepare() + self.checkTbColTypeOperator() + self.checkStbColTypeOperator() + self.checkTbMultiExpression() + self.checkStbMultiExpression() + self.checkTbMultiIn() + self.checkStbMultiIn() + self.checkTbMultiLike() + self.checkStbMultiLike() + self.checkTbPreCal() + self.checkStbPreCal() + self.checkMultiTb() + self.checkMultiStb() + self.checkMultiTbWithTag() + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/query/queryError.py b/tests/pytest/query/queryError.py index ac78c0518f36a847652499aaa5722d4585e42d44..e5c468600ba56a251057f204971084fe2844a85e 100644 --- a/tests/pytest/query/queryError.py +++ b/tests/pytest/query/queryError.py @@ -65,6 +65,10 @@ class TDTestCase: # TD-2208 tdSql.error("select diff(tagtype),top(tagtype,1) from dev_001") + # TD-6006 + tdSql.error("select * from dev_001 where 'name' is not null") + tdSql.error("select * from dev_001 where \"name\" = 'first'") + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/pytest/query/queryJoin.py b/tests/pytest/query/queryJoin.py index cd50a7bf452966306e6811e90802d9d160bfa68b..6d028049e516b4b0f399fcb055793a16ec093eec 100644 --- a/tests/pytest/query/queryJoin.py +++ b/tests/pytest/query/queryJoin.py @@ -13,6 +13,8 @@ import sys import taos +import string +import random from util.log import * from util.cases import * from util.sql import * @@ -23,6 +25,11 @@ class TDTestCase: tdLog.debug("start to execute %s" % __file__) tdSql.init(conn.cursor()) + def get_random_string(self, length): + letters = string.ascii_lowercase + result_str = ''.join(random.choice(letters) for i in range(length)) + return result_str + def run(self): tdSql.prepare() @@ -186,6 +193,20 @@ class TDTestCase: tdSql.query("select t1.ts from t0,t1 where t0.ts = t1.ts") tdSql.checkData(0,0,'2018-10-03 14:38:05.000000') + #TD-6425 join result more than 1MB + tdSql.execute("create database test_join") + tdSql.execute("use test_join") + + ts = 1538548685000 + tdSql.execute("create table stb(ts timestamp, c1 nchar(200)) tags(id int, loc binary(20))") + for i in range(2): + tdSql.execute("create table tb%d using stb tags(1, 'city%d')" % (i, i)) + for j in range(1000): + tdSql.execute("insert into tb%d values(%d, '%s')" % (i, ts + j, self.get_random_string(200))) + + tdSql.query("select tb0.c1, tb1.c1 from tb0, tb1 where tb0.ts = tb1.ts") + tdSql.checkRows(1000) + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/pytest/query/queryLike.py b/tests/pytest/query/queryLike.py index 3c3b030f8f718371867f323f2496fb17b6b962e1..2bcd5906a8eaa505e1702cefce7f8b2594f53f43 100644 --- a/tests/pytest/query/queryLike.py +++ b/tests/pytest/query/queryLike.py @@ -17,7 +17,6 @@ from util.log import * from util.cases import * from util.sql import * - class TDTestCase: def init(self, conn, logSql): tdLog.debug("start to execute %s" % __file__) @@ -25,7 +24,8 @@ class TDTestCase: def run(self): tdSql.prepare() - + tdSql.execute("drop database db ") + tdSql.execute("create database if not exists db ") tdSql.execute("create table cars(ts timestamp, c nchar(2)) tags(t1 nchar(2))") tdSql.execute("insert into car0 using cars tags('aa') values(now, 'bb');") tdSql.query("select count(*) from cars where t1 like '%50 90 30 04 00 00%'") @@ -35,6 +35,132 @@ class TDTestCase: tdSql.execute("insert into car1 using test_cars tags('150 90 30 04 00 002') values(now, 'bb');") tdSql.query("select * from test_cars where t1 like '%50 90 30 04 00 00%'") tdSql.checkRows(1) + + tdSql.execute("create stable st (ts timestamp , id int , name binary(20), data double ) tags (ind int , tagg binary(20)) ") + + # check escape about tbname by show tables like + + tdSql.execute("create table tb_ using st tags (1 , 'tag_' ) ") + tdSql.execute("insert into tb_ values( now , 1 , 'tbname_' , 1.0)") + tdSql.execute("create table tba using st tags (1 , 'taga' ) ") + tdSql.execute("insert into tba values( now , 1 , 'tbnamea' , 1.0)") + tdSql.query("show tables like 'tb_'") + tdSql.checkRows(2) + tdSql.query("show tables like 'tb\_'") + tdSql.checkRows(1) + + # check escape about tbname by show tables like + tdSql.query("select * from st where tbname like 'tb\_'") + tdSql.checkRows(1) + + # check escape about regular cols + tdSql.query("select * from st where name like 'tbname\_';") + tdSql.checkRows(1) + + # check escape about tags + tdSql.query("select * from st where tagg like 'tag\_';") + tdSql.checkRows(1) + + # ======================= check multi escape =================== + + tdSql.execute("create table tb_1 using st tags (1 , 'tag_1' ) ") + tdSql.execute("insert into tb_1 values( now , 1 , 'tbname_1' , 1.0)") + tdSql.execute("create table tb_2 using st tags (2 , 'tag_2' )") + tdSql.execute("insert into tb_2 values( now , 2 , 'tbname_2' , 2.0)") + tdSql.execute("create table tb__ using st tags (3 , 'tag__' )") + tdSql.execute("insert into tb__ values( now , 3 , 'tbname__' , 2.0)") + tdSql.execute("create table tb__1 using st tags (3 , 'tag__1' )") + tdSql.execute("insert into tb__1 values( now , 1 , 'tbname__1' , 1.0)") + tdSql.execute("create table tb__2 using st tags (4 , 'tag__2' )") + tdSql.execute("create table tb___ using st tags (5 , 'tag___' )") + tdSql.execute("insert into tb___ values( now , 1 , 'tbname___' , 1.0)") + tdSql.execute("create table tb_d_ using st tags (5 , 'tag_d_' )") + tdSql.execute("insert into tb_d_ values( now , 1 , 'tbname_d_' , 1.0)") + + tdSql.execute("create table tb_d__ using st tags (5 , 'tag_d__' )") + tdSql.execute("insert into tb_d__ values( now , 1 , 'tbname_d__' , 1.0)") + tdSql.execute("create table tb____ using st tags (5 , 'tag____' )") + tdSql.execute("insert into tb____ values( now , 1 , 'tbname____' , 1.0)") + tdSql.execute("create table tb__a_ using st tags (5 , 'tag__a_' )") + tdSql.execute("insert into tb__a_ values( now , 1 , 'tbname__a_' , 1.0)") + tdSql.execute("create table tb__ab__ using st tags (5 , 'tag__ab__' )") + tdSql.execute("insert into tb__ab__ values( now , 1 , 'tbname__ab__' , 1.0)") + + # check escape about tbname by show tables like + tdSql.query("select * from st where tbname like 'tb__'") + tdSql.checkRows(3) + tdSql.query("select * from st where tbname like 'tb_\_'") + tdSql.checkRows(1) + tdSql.query("select * from st where tbname like 'tb___'") + tdSql.checkRows(4) + tdSql.query("select * from st where tbname like 'tb_\__'") + tdSql.checkRows(3) + tdSql.query("select * from st where tbname like 'tb_\_\_'") + tdSql.checkRows(1) + tdSql.query("select * from st where tbname like 'tb\__\_'") + tdSql.checkRows(1) + tdSql.query("select * from st where tbname like 'tb\__\__'") + tdSql.checkRows(2) + tdSql.query("select * from st where tbname like 'tb\__\_\_'") + tdSql.checkRows(2) + tdSql.query("select * from st where tbname like 'tb\____'") + tdSql.checkRows(3) + tdSql.query("select * from st where tbname like 'tb\_\__\_'") + tdSql.checkRows(2) + tdSql.query("select * from st where tbname like 'tb\_\_\_\_'") + tdSql.checkRows(1) + + # check escape about regular cols + tdSql.query("select * from st where name like 'tbname\_\_';") + tdSql.checkRows(1) + tdSql.query("select * from st where name like 'tbname\__';") + tdSql.checkRows(3) + tdSql.query("select * from st where name like 'tbname___';") + tdSql.checkRows(4) + tdSql.query("select * from st where name like 'tbname_\__';") + tdSql.checkRows(3) + tdSql.query("select * from st where name like 'tbname_\_\_';") + tdSql.checkRows(1) + tdSql.query("select * from st where name like 'tbname\_\__';") + tdSql.checkRows(2) + tdSql.query("select * from st where name like 'tbname____';") + tdSql.checkRows(3) + tdSql.query("select * from st where name like 'tbname\_\___';") + tdSql.checkRows(2) + tdSql.query("select * from st where name like 'tbname\_\_\__';") + tdSql.checkRows(1) + tdSql.query("select * from st where name like 'tbname\_\__\_';") + tdSql.checkRows(2) + tdSql.query("select name from st where name like 'tbname\_\_\__';") + tdSql.checkData(0,0 "tbname____") + + # check escape about tags + tdSql.query("select * from st where tagg like 'tag\_';") + tdSql.checkRows(1) + tdSql.query("select * from st where tagg like 'tag\_\_';") + tdSql.checkRows(1) + tdSql.query("select * from st where tagg like 'tag\__';") + tdSql.checkRows(3) + tdSql.query("select * from st where tagg like 'tag___';") + tdSql.checkRows(4) + tdSql.query("select * from st where tagg like 'tag_\__';") + tdSql.checkRows(3) + tdSql.query("select * from st where tagg like 'tag_\_\_';") + tdSql.checkRows(1) + tdSql.query("select * from st where tagg like 'tag\_\__';") + tdSql.checkRows(2) + tdSql.query("select * from st where tagg like 'tag____';") + tdSql.checkRows(3) + tdSql.query("select * from st where tagg like 'tag\_\___';") + tdSql.checkRows(2) + tdSql.query("select * from st where tagg like 'tag\_\_\__';") + tdSql.checkRows(1) + tdSql.query("select * from st where tagg like 'tag\_\__\_';") + tdSql.checkRows(2) + tdSql.query("select * from st where tagg like 'tag\_\__\_';") + tdSql.checkData(0,0 "tag__a_") + + os.system("rm -rf ./*.py.sql") def stop(self): tdSql.close() diff --git a/tests/pytest/query/queryPerformance.py b/tests/pytest/query/queryPerformance.py index 81103252d8794032ee17b143f814276e171863f2..29e5cb19b75b0943c24382d268e81daebed01cdf 100644 --- a/tests/pytest/query/queryPerformance.py +++ b/tests/pytest/query/queryPerformance.py @@ -17,6 +17,7 @@ import os import taos import time import argparse +import json class taosdemoQueryPerformace: @@ -48,7 +49,7 @@ class taosdemoQueryPerformace: cursor2 = self.conn2.cursor() cursor2.execute("create database if not exists %s" % self.dbName) cursor2.execute("use %s" % self.dbName) - cursor2.execute("create table if not exists %s(ts timestamp, query_time float, commit_id binary(50), branch binary(50), type binary(20)) tags(query_id int, query_sql binary(300))" % self.stbName) + cursor2.execute("create table if not exists %s(ts timestamp, query_time_avg float, query_time_max float, query_time_min float, commit_id binary(50), branch binary(50), type binary(20)) tags(query_id int, query_sql binary(300))" % self.stbName) sql = "select count(*) from test.meters" tableid = 1 @@ -74,7 +75,7 @@ class taosdemoQueryPerformace: tableid = 6 cursor2.execute("create table if not exists %s%d using %s tags(%d, '%s')" % (self.tbPerfix, tableid, self.stbName, tableid, sql)) - sql = "select * from meters" + sql = "select * from meters limit 10000" tableid = 7 cursor2.execute("create table if not exists %s%d using %s tags(%d, '%s')" % (self.tbPerfix, tableid, self.stbName, tableid, sql)) @@ -87,37 +88,96 @@ class taosdemoQueryPerformace: cursor2.execute("create table if not exists %s%d using %s tags(%d, '%s')" % (self.tbPerfix, tableid, self.stbName, tableid, sql)) cursor2.close() + + def generateQueryJson(self): + + sqls = [] + cursor2 = self.conn2.cursor() + cursor2.execute("select query_id, query_sql from %s.%s" % (self.dbName, self.stbName)) + i = 0 + for data in cursor2: + sql = { + "sql": data[1], + "result_mode": "onlyformat", + "result_file": "./query_sql_res%d.txt" % i + } + sqls.append(sql) + i += 1 + + query_data = { + "filetype": "query", + "cfgdir": "/etc/perf", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "databases": "test", + "specified_table_query": { + "query_times": 100, + "concurrent": 1, + "sqls": sqls + } + } + + query_json_file = f"/tmp/query.json" + + with open(query_json_file, 'w') as f: + json.dump(query_data, f) + return query_json_file + + def getBuildPath(self): + selfPath = os.path.dirname(os.path.realpath(__file__)) + + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + for root, dirs, files in os.walk(projPath): + if ("taosdemo" in files): + rootRealPath = os.path.dirname(os.path.realpath(root)) + if ("packaging" not in rootRealPath): + buildPath = root[:len(root) - len("/build/bin")] + break + return buildPath + + def getCMDOutput(self, cmd): + cmd = os.popen(cmd) + output = cmd.read() + cmd.close() + return output def query(self): - cursor = self.conn.cursor() - print("==================== query performance ====================") + buildPath = self.getBuildPath() + if (buildPath == ""): + print("taosdemo not found!") + sys.exit(1) + + binPath = buildPath + "/build/bin/" + os.system( + "%sperfMonitor -f %s > query_res.txt" % + (binPath, self.generateQueryJson())) + cursor = self.conn2.cursor() + print("==================== query performance ====================") cursor.execute("use %s" % self.dbName) - cursor.execute("select tbname, query_id, query_sql from %s" % self.stbName) + cursor.execute("select tbname, query_sql from %s" % self.stbName) + i = 0 for data in cursor: table_name = data[0] - query_id = data[1] - sql = data[2] + sql = data[1] + + self.avgDelay = self.getCMDOutput("grep 'avgDelay' query_res.txt | awk 'NR==%d{print $2}'" % (i + 1)) + self.maxDelay = self.getCMDOutput("grep 'avgDelay' query_res.txt | awk 'NR==%d{print $5}'" % (i + 1)) + self.minDelay = self.getCMDOutput("grep 'avgDelay' query_res.txt | awk 'NR==%d{print $8}'" % (i + 1)) + i += 1 + + print("query time for: %s %f seconds" % (sql, float(self.avgDelay))) + c = self.conn2.cursor() + c.execute("insert into %s.%s values(now, %f, %f, %f, '%s', '%s', '%s')" % (self.dbName, table_name, float(self.avgDelay), float(self.maxDelay), float(self.minDelay), self.commitID, self.branch, self.type)) - totalTime = 0 - cursor2 = self.conn.cursor() - cursor2.execute("use test") - for i in range(100): - if(self.clearCache == True): - # root permission is required - os.system("echo 3 > /proc/sys/vm/drop_caches") - - startTime = time.time() - cursor2.execute(sql) - totalTime += time.time() - startTime - cursor2.close() - print("query time for: %s %f seconds" % (sql, totalTime / 100)) - - cursor3 = self.conn2.cursor() - cursor3.execute("insert into %s.%s values(now, %f, '%s', '%s', '%s')" % (self.dbName, table_name, totalTime / 100, self.commitID, self.branch, self.type)) - - cursor3.close() + c.close() cursor.close() if __name__ == '__main__': @@ -174,4 +234,4 @@ if __name__ == '__main__': args = parser.parse_args() perftest = taosdemoQueryPerformace(args.remove_cache, args.commit_id, args.database_name, args.stable_name, args.table_perfix, args.git_branch, args.build_type) perftest.createPerfTables() - perftest.query() + perftest.query() \ No newline at end of file diff --git a/tests/pytest/query/queryTbnameUpperLower.py b/tests/pytest/query/queryTbnameUpperLower.py new file mode 100644 index 0000000000000000000000000000000000000000..bd4e85c5ca61628093348f520b6e6a04bef07f4a --- /dev/null +++ b/tests/pytest/query/queryTbnameUpperLower.py @@ -0,0 +1,78 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- +from util.log import tdLog +from util.cases import tdCases +from util.sql import tdSql +from util.common import tdCom + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def checkStbWhereIn(self): + ''' + where in ---> upper lower mixed + ''' + tdCom.cleanTb() + table_name = tdCom.getLongName(8, "letters_mixed") + table_name_sub = f'{table_name}_sub' + tb_name_lower = table_name_sub.lower() + tb_name_upper = table_name_sub.upper() + + ## create stb and tb + tdSql.execute(f'CREATE TABLE {table_name} (ts timestamp, id int, bi1 binary(20)) tags (si1 binary(20))') + tdSql.execute(f'create table {table_name_sub}1 using {table_name} tags ("{table_name_sub}1")') + tdSql.execute(f'create table {tb_name_lower}2 using {table_name} tags ("{tb_name_lower}2")') + tdSql.execute(f'create table {tb_name_upper}3 using {table_name} tags ("{tb_name_upper}3")') + + ## insert values + tdSql.execute(f'insert into {table_name_sub}1 values (now-1s, 1, "{table_name_sub}1")') + tdSql.execute(f'insert into {tb_name_lower}2 values (now-2s, 2, "{tb_name_lower}21")') + tdSql.execute(f'insert into {tb_name_lower}2 values (now-3s, 3, "{tb_name_lower}22")') + tdSql.execute(f'insert into {tb_name_upper}3 values (now-4s, 4, "{tb_name_upper}31")') + tdSql.execute(f'insert into {tb_name_upper}3 values (now-5s, 5, "{tb_name_upper}32")') + tdSql.execute(f'insert into {tb_name_upper}3 values (now-6s, 6, "{tb_name_upper}33")') + + ## query where tbname in single + tdSql.query(f'select * from {table_name} where tbname in ("{table_name_sub}1")') + tdSql.checkRows(1) + tdSql.query(f'select * from {table_name} where tbname in ("{table_name_sub.upper()}1")') + tdSql.checkRows(1) + tdSql.query(f'select * from {table_name} where tbname in ("{table_name_sub.lower()}1")') + tdSql.checkRows(1) + tdSql.query(f'select * from {table_name} where tbname in ("{tb_name_lower}2")') + tdSql.checkRows(2) + tdSql.query(f'select * from {table_name} where tbname in ("{tb_name_lower.upper()}2")') + tdSql.checkRows(2) + tdSql.query(f'select * from {table_name} where tbname in ("{tb_name_upper}3")') + tdSql.checkRows(3) + tdSql.query(f'select * from {table_name} where tbname in ("{tb_name_upper.lower()}3")') + tdSql.checkRows(3) + + ## query where tbname in multi + tdSql.query(f'select * from {table_name} where id=5 and tbname in ("{table_name_sub}1", "{tb_name_lower.upper()}2", "{tb_name_upper.lower()}3")') + tdSql.checkRows(1) + tdSql.query(f'select * from {table_name} where tbname in ("{table_name_sub}1", "{tb_name_lower.upper()}2", "{tb_name_upper.lower()}3")') + tdSql.checkRows(6) + + def run(self): + tdSql.prepare() + self.checkStbWhereIn() + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) \ No newline at end of file diff --git a/tests/pytest/query/tbname.py b/tests/pytest/query/tbname.py index 08416ba3eda378cce96fcaa8051e1d06a75d6b28..30d90b1f9dd38077cdb942dac78a28cac0084c47 100644 --- a/tests/pytest/query/tbname.py +++ b/tests/pytest/query/tbname.py @@ -53,6 +53,9 @@ class TDTestCase: "select * from cars where id=0 and tbname in ('carzero', 'cartwo')") tdSql.checkRows(1) + tdSql.query("select * from cars where tbname in ('carZero', 'CARONE')") + tdSql.checkRows(2) + """ tdSql.query("select * from cars where tbname like 'car%'") tdSql.checkRows(2) diff --git a/tests/pytest/restful/restful_bind_db1.py b/tests/pytest/restful/restful_bind_db1.py new file mode 100644 index 0000000000000000000000000000000000000000..9620535fd7c9388d08d0ebae9237b243fc0a099c --- /dev/null +++ b/tests/pytest/restful/restful_bind_db1.py @@ -0,0 +1,123 @@ +# ################################################################# +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. + +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao + +# ################################################################# + +# -*- coding: utf-8 -*- + +# TODO: after TD-4518 and TD-4510 is resolved, add the exception test case for these situations + +from distutils.log import error +import sys + +from requests.api import head +from requests.models import Response +from util.log import * +from util.cases import * +from util.sql import * +import time, datetime +import requests, json +import threading +import string +import random + + +def check_unbind_db(url, data, header): + resp = requests.post(url, data, headers = header ) + resp.encoding='utf-8' + resp = eval(resp.text) + status = resp['status'] + desc = resp['desc'] + sqls = data + if status=="error" and desc == "invalid url format": + print(" %s : check pass" %sqls) + else: + printf(" error occured , ") + sys.exit() + +def check_bind_db(url, data, header): + resp = requests.post(url, data, headers = header ) + resp.encoding='utf-8' + resp_dict = eval(resp.text) + status = resp_dict['status'] + if status =="succ": + print("%s run success!"%data) + # print(resp.text) + else : + print("%s run failed !"%data) + print(resp.text) + sys.exit() + +class TDTestCase(): + updatecfgDict={'httpDbNameMandatory':1} + + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def run(self): + tdSql.prepare() + tdSql.execute('reset query cache') + tdSql.execute('drop database if exists test') + tdSql.execute('drop database if exists db') + tdSql.execute('drop database if exists des') + tdSql.execute('create database test') + tdSql.execute('create database des') + + header = {'Authorization': 'Basic cm9vdDp0YW9zZGF0YQ=='} + url = "http://127.0.0.1:6041/rest/sql/" + + # test with no bind databases + + sqls = ["show databases;", + "use test", + "show tables;", + "show dnodes;", + "show vgroups;", + "create database db;", + "drop database db;", + "select client_version();" , + "use test", + "ALTER DATABASE test COMP 2;", + "create table tb (ts timestamp, id int , data double)", + "insert into tb values (now , 1, 1.0) ", + "select * from tb", + "show test.tables", + "show tables", + "insert into tb values (now , 2, 2.0) ", + "create table test.tb (ts timestamp, id int , data double)", + "insert into test.tb values (now , 2, 2.0) ", + "select * from tb", + "select * from test.tb"] + + for sql in sqls: + print("===================") + check_unbind_db(url,sql,header) + + print("==================="*5) + print(" check bind db about restful ") + print("==================="*5) + url = "http://127.0.0.1:6041/rest/sql/des" + for sql in sqls: + print("===================") + check_bind_db(url,sql,header) + # check data + tdSql.query("select * from test.tb") + tdSql.checkRows(1) + tdSql.query("select * from des.tb") + tdSql.checkRows(2) + + os.system('sudo timedatectl set-ntp on') + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/restful/restful_bind_db2.py b/tests/pytest/restful/restful_bind_db2.py new file mode 100644 index 0000000000000000000000000000000000000000..35aa1408a7690798d66bc0303e64fe4843dab0d8 --- /dev/null +++ b/tests/pytest/restful/restful_bind_db2.py @@ -0,0 +1,133 @@ +# ################################################################# +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. + +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao + +# ################################################################# + +# -*- coding: utf-8 -*- + +# TODO: after TD-4518 and TD-4510 is resolved, add the exception test case for these situations + +from distutils.log import error +import sys + +from requests.api import head +from requests.models import Response +from util.log import * +from util.cases import * +from util.sql import * +import time, datetime +import requests, json +import threading +import string +import random + +def check_res(url, data, header): + resp = requests.post(url, data, headers = header ) + resp.encoding='utf-8' + resp_dict = eval(resp.text) + status = resp_dict['status'] + if status =="succ": + print("%s run success!"%data) + # print(resp.text) + else : + print("%s run failed !"%data) + print(resp.text) + sys.exit() + +class TDTestCase(): + # updatecfgDict={'httpDbNameMandatory':0} + + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def run(self): + tdSql.prepare() + tdSql.execute('reset query cache') + tdSql.execute('drop database if exists test') + tdSql.execute('drop database if exists db') + tdSql.execute('drop database if exists des') + tdSql.execute('create database test') + tdSql.execute('create database des') + header = {'Authorization': 'Basic cm9vdDp0YW9zZGF0YQ=='} + url = "http://127.0.0.1:6041/rest/sql/" + + # test with no bind databases + + sqls = ["show databases;", + "use test", + "show tables;", + "show dnodes;", + "show vgroups;", + "create database db;", + "drop database db;", + "select client_version();" , + "use test", + "ALTER DATABASE test COMP 2;", + "create table tb (ts timestamp, id int , data double)", + "insert into tb values (now , 1, 1.0) ", + "select * from tb", + "show test.tables", + "show tables", + "insert into tb values (now , 2, 2.0) ", + "create table test.tb (ts timestamp, id int , data double)", + "insert into test.tb values (now , 3, 3.0) ", + "select * from tb", + "select * from test.tb", + "create table des.tb (ts timestamp, id int , data double)", + "insert into des.tb values (now , 3, 3.0)"] + for sql in sqls: + print("===================") + if sql == "create table test.tb (ts timestamp, id int , data double)": + resp = requests.post(url, sql, headers = header ) + print(resp.text) + print ("%s run occur error as expect ,check pass!" %(sql)) + else: + check_res(url,sql,header) + + tdSql.query("select * from test.tb") + tdSql.checkRows(3) + tdSql.query("select * from des.tb") + tdSql.checkRows(1) + + print("==================="*5) + print(" check bind db about restful ") + print("==================="*5) + + tdSql.execute('reset query cache') + tdSql.execute('drop database if exists test') + tdSql.execute('drop database if exists db') + tdSql.execute('drop database if exists des') + tdSql.execute('create database test') + tdSql.execute('create database des') + + url = "http://127.0.0.1:6041/rest/sql/des" + for sql in sqls: + print("===================") + if sql in ["create table des.tb (ts timestamp, id int , data double)"]: + resp = requests.post(url, sql, headers = header ) + print(resp.text) + print ("%s run occur error as expect ,check pass!" %(sql)) + else: + check_res(url,sql,header) + # check data + tdSql.query("select * from test.tb") + tdSql.checkRows(1) + tdSql.query("select * from des.tb") + tdSql.checkRows(3) + + os.system('sudo timedatectl set-ntp on') + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/tools/schemalessInsertPerformance.py b/tests/pytest/tools/schemalessInsertPerformance.py new file mode 100644 index 0000000000000000000000000000000000000000..5e009a21296bb09c7210a7109aea9dd43bf7a847 --- /dev/null +++ b/tests/pytest/tools/schemalessInsertPerformance.py @@ -0,0 +1,301 @@ +################################################################### +# Copyright (c) 2021 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import traceback +import random +import string +from taos.error import LinesError +import datetime +import time +from copy import deepcopy +import numpy as np +from util.log import * +from util.cases import * +from util.sql import * +from util.common import tdCom +import threading + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + self._conn = conn + + def genRandomTs(self): + year = random.randint(2000, 2021) + month = random.randint(10, 12) + day = random.randint(10, 29) + hour = random.randint(10, 24) + minute = random.randint(10, 59) + second = random.randint(10, 59) + m_second = random.randint(101, 199) + date_time = f'{year}-{month}-{day} {hour}:{minute}:{second}' + print(date_time) + timeArray = time.strptime(date_time, "%Y-%m-%d %H:%M:%S") + ts = int(time.mktime(timeArray)) + print("------", ts) + # timestamp = time.mktime(datetime.datetime.strptime(date_time, "%Y-%m-%d %H:%M:%S.%f").timetuple()) + return f'{ts}s' + + def genMultiColStr(self, int_count=4, double_count=0, binary_count=0): + """ + genType must be tag/col + """ + col_str = "" + if double_count == 0 and binary_count == 0: + for i in range(0, int_count): + if i < (int_count-1): + col_str += f'c{i}={random.randint(0, 255)}i32,' + else: + col_str += f'c{i}={random.randint(0, 255)}i32 ' + elif double_count > 0 and binary_count == 0: + for i in range(0, int_count): + col_str += f'c{i}={random.randint(0, 255)}i32,' + for i in range(0, double_count): + if i < (double_count-1): + col_str += f'c{i+int_count}={random.randint(1, 255)}.{i}f64,' + else: + col_str += f'c{i+int_count}={random.randint(1, 255)}.{i}f64 ' + elif double_count == 0 and binary_count > 0: + for i in range(0, int_count): + col_str += f'c{i}={random.randint(0, 255)}i32,' + for i in range(0, binary_count): + if i < (binary_count-1): + col_str += f'c{i+int_count}=\"{tdCom.getLongName(5, "letters")}\",' + else: + col_str += f'c{i+int_count}=\"{tdCom.getLongName(5, "letters")}\" ' + elif double_count > 0 and binary_count > 0: + for i in range(0, int_count): + col_str += f'c{i}={random.randint(0, 255)}i32,' + for i in range(0, double_count): + col_str += f'c{i+int_count}={random.randint(1, 255)}.{i}f64,' + for i in range(0, binary_count): + if i < (binary_count-1): + col_str += f'c{i+int_count+double_count}=\"{tdCom.getLongName(5, "letters")}\",' + else: + col_str += f'c{i+int_count+double_count}=\"{tdCom.getLongName(5, "letters")}\" ' + return col_str + + def genLongSql(self, int_count=4, double_count=0, binary_count=0, init=False): + if init: + tag_str = f'id="init",t0={random.randint(0, 65535)}i32,t1=\"{tdCom.getLongName(10, "letters")}\"' + else: + tag_str = f'id="sub_{tdCom.getLongName(5, "letters")}_{tdCom.getLongName(5, "letters")}",t0={random.randint(0, 65535)}i32,t1=\"{tdCom.getLongName(10, "letters")}\"' + col_str = self.genMultiColStr(int_count, double_count, binary_count) + long_sql = 'stb' + ',' + tag_str + ' ' + col_str + '0' + return long_sql + + def getPerfSql(self, count=4, init=False): + if count == 4: + input_sql = self.genLongSql(init=init) + elif count == 1000: + input_sql = self.genLongSql(400, 400, 200, init=init) + elif count == 4000: + input_sql = self.genLongSql(1900, 1900, 200, init=init) + return input_sql + + def tableGenerator(self, count=4, table_count=1000): + for i in range(table_count): + yield self.getPerfSql(count) + + + + + + + + def genTableList(self, count=4, table_count=10000): + table_list = list() + for i in range(1, table_count+1): + table_list.append(self.getPerfSql(count)) + return table_list + + def splitTableList(self, count=4, thread_count=10, table_count=1000): + per_list_len = int(table_count/thread_count) + table_list = self.genTableList(count=count) + # ts = int(time.time()) + list_of_group = zip(*(iter(table_list),) *per_list_len) + end_list = [list(i) for i in list_of_group] # i is a tuple + count = len(table_list) % per_list_len + end_list.append(table_list[-count:]) if count !=0 else end_list + return table_list, end_list + + def rowsGenerator(self, end_list): + ts = int(time.time()) + input_sql_list = list() + for elm_list in end_list: + for elm in elm_list: + for i in range(1, 10000): + ts -= 1 + elm_new = self.replaceLastStr(elm, str(ts)) + 's' + input_sql_list.append(elm_new) + yield input_sql_list + + # def insertRows(self, count=4, thread_count=10): + # table_list = self.splitTableList(count=count, thread_count=thread_count)[0] + # for + + + def replaceLastStr(self, str, new): + list_ori = list(str) + list_ori[-1] = new + return ''.join(list_ori) + + def genDataList(self, table_list, row_count=10): + data_list = list() + ts = int(time.time()) + for table_str in table_list: + for i in range(1, row_count+1): + ts -= 1 + table_str_new = self.replaceLastStr(table_str, f'{str(ts)}s') + data_list.append(table_str_new) + print(data_list) + return data_list + + + def insertRows(self, count=4, table_count=1000): + table_generator = self.tableGenerator(count=count, table_count=table_count) + for table_name in table_generator: + pass + + def perfTableInsert(self): + table_generator = self.tableGenerator() + for input_sql in table_generator: + self._conn.insert_lines([input_sql]) + # for i in range(10): + # self._conn.insert_lines([input_sql]) + + def perfDataInsert(self, count=4): + table_generator = self.tableGenerator(count=count) + ts = int(time.time()) + for input_sql in table_generator: + print("input_sql-----------", input_sql) + self._conn.insert_lines([input_sql]) + for i in range(100000): + ts -= 1 + input_sql_new = self.replaceLastStr(input_sql, str(ts)) + 's' + print("input_sql_new---------", input_sql_new) + self._conn.insert_lines([input_sql_new]) + + def batchInsertTable(self, batch_list): + for insert_list in batch_list: + print(threading.current_thread().name, "length=", len(insert_list)) + print(threading.current_thread().name, 'firstline', insert_list[0]) + print(threading.current_thread().name, 'lastline:', insert_list[-1]) + self._conn.insert_lines(insert_list) + print(threading.current_thread().name, 'end') + + def genTableThread(self, thread_count=10): + threads = list() + for i in range(thread_count): + t = threading.Thread(target=self.perfTableInsert) + threads.append(t) + return threads + + def genMultiThread(self, count, thread_count=10): + threads = list() + for i in range(thread_count): + t = threading.Thread(target=self.perfDataInsert,args=(count,)) + threads.append(t) + return threads + + def multiThreadRun(self, threads): + for t in threads: + t.start() + for t in threads: + t.join() + + def createStb(self, count=4): + input_sql = self.getPerfSql(count=count, init=True) + self._conn.insert_lines([input_sql]) + + def threadInsertTable(self, end_list, thread_count=10): + threads = list() + for i in range(thread_count): + t = threading.Thread(target=self.batchInsertTable, args=(end_list,)) + threads.append(t) + return threads + + + def finalRun(self): + self.createStb() + table_list, end_list = self.splitTableList() + batchInsertTableThread = self.threadInsertTable(end_list=end_list) + self.multiThreadRun(batchInsertTableThread) + # print(end_list) + + # def createTb(self, count=4): + # input_sql = self.getPerfSql(count=count) + # for i in range(10000): + # self._conn.insert_lines([input_sql]) + + # def createTb1(self, count=4): + # start_time = time.time() + # self.multiThreadRun(self.genMultiThread(input_sql)) + # end_time = time.time() + # return end_time - start_time + + # def calInsertTableTime(self): + # start_time = time.time() + # self.createStb() + # self.multiThreadRun(self.genMultiThread()) + # end_time = time.time() + # return end_time - start_time + + def calRunTime(self, count=4): + start_time = time.time() + self.createStb() + self.multiThreadRun(self.genMultiThread(count=count)) + end_time = time.time() + return end_time - start_time + + def calRunTime1(self, count=4): + start_time = time.time() + self.createStb() + self.multiThreadRun(self.perfTableInsert()) + # self.perfTableInsert() + + # def schemalessInsertPerfTest(self, count=4): + # input_sql = self.getPerfSql(count) + # self.calRunTime(input_sql) + + # def test(self): + # sql1 = 'stb,id="init",t0=14865i32,t1="tvnqbjuqck" c0=37i32,c1=217i32,c2=3i32,c3=88i32 1626006833640ms' + # sql2 = 'stb,id="init",t0=14865i32,t1="tvnqbjuqck" c0=38i32,c1=217i32,c2=3i32,c3=88i32 1626006833641ms' + # self._conn.insert_lines([sql1]) + # self._conn.insert_lines([sql2]) + + def run(self): + print("running {}".format(__file__)) + tdSql.prepare() + self.finalRun() + # print(self.calRunTime1(count=4)) + # print(self.calRunTime(count=4)) + # print(self.genRandomTs()) + # self.calInsertTableTime() + # self.test() + # table_list = self.splitTableList()[0] + # data_list = self.genDataList(table_list) + # print(len(data_list)) + # end_list = [['stb,id="sub_vzvfx_dbuxp",t0=9961i32,t1="zjjfayhfep" c0=83i32,c1=169i32,c2=177i32,c3=4i32 0','stb,id="sub_vzvfx_dbuxp",t0=9961i32,t1="zjjfayhfep" c0=83i32,c1=169i32,c2=177i32,c3=4i32 0'], ['stb,id="sub_vzvfx_dbuxp",t0=9961i32,t1="zjjfayhfep" c0=83i32,c1=169i32,c2=177i32,c3=4i32 0','stb,id="sub_vzvfx_dbuxp",t0=9961i32,t1="zjjfayhfep" c0=83i32,c1=169i32,c2=177i32,c3=4i32 0']] + # rowsGenerator = self.rowsGenerator(end_list) + # for i in rowsGenerator: + # print(i) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py index 643886f434d7694f55dce193e5cc2566a4347d3e..f069bb8f7030dbd8d4eec8c9c741d246f261671b 100644 --- a/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py +++ b/tests/pytest/tools/taosdemoAllTest/NanoTestCase/taosdemoTestSupportNanoInsert.py @@ -47,6 +47,7 @@ class TDTestCase: 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 @@ -89,6 +90,7 @@ class TDTestCase: os.system( "%staosdemo -f tools/taosdemoAllTest/NanoTestCase/taosdemoTestNanoDatabaseNow.json -y " % binPath) + tdSql.execute("use nsdb2") tdSql.query("show stables") tdSql.checkData(0, 4, 100) diff --git a/tests/pytest/tools/taosdemoPerformance.py b/tests/pytest/tools/taosdemoPerformance.py index 1d28a2708fa1911e22aca97afa246a124dd2d6fc..51b064a08e5cd55401f9cf803a8683653f722679 100644 --- a/tests/pytest/tools/taosdemoPerformance.py +++ b/tests/pytest/tools/taosdemoPerformance.py @@ -49,24 +49,18 @@ class taosdemoPerformace: def generateJson(self): db = { "name": "%s" % self.insertDB, - "drop": "yes", - "replica": 1 + "drop": "yes" } stb = { "name": "meters", - "child_table_exists": "no", "childtable_count": self.numOfTables, "childtable_prefix": "stb_", - "auto_create_table": "no", - "data_source": "rand", "batch_create_tbl_num": 10, - "insert_mode": "taosc", + "insert_mode": "rand", "insert_rows": self.numOfRows, - "interlace_rows": 0, - "max_sql_len": 1024000, - "disorder_ratio": 0, - "disorder_range": 1000, + "batch_rows": 1000000, + "max_sql_len": 1048576, "timestamp_step": 1, "start_timestamp": "2020-10-01 00:00:00.000", "sample_format": "csv", @@ -100,11 +94,8 @@ class taosdemoPerformace: "user": "root", "password": "taosdata", "thread_count": 10, - "thread_count_create_tbl": 10, + "thread_count_create_tbl": 4, "result_file": "./insert_res.txt", - "confirm_parameter_prompt": "no", - "insert_interval": 0, - "num_of_records_per_req": 30000, "databases": [db] } @@ -145,7 +136,7 @@ class taosdemoPerformace: binPath = buildPath + "/build/bin/" os.system( - "%staosdemo -f %s > /dev/null 2>&1" % + "%sperfMonitor -f %s > /dev/null 2>&1" % (binPath, self.generateJson())) self.createTableTime = self.getCMDOutput( "grep 'Spent' insert_res.txt | awk 'NR==1{print $2}'") diff --git a/tests/pytest/tsdb/insertDataDb1.json b/tests/pytest/tsdb/insertDataDb1.json new file mode 100644 index 0000000000000000000000000000000000000000..60c6def92c9461e2af8e9c0cefc5e574ca61a465 --- /dev/null +++ b/tests/pytest/tsdb/insertDataDb1.json @@ -0,0 +1,87 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 10, + "num_of_records_per_req": 1000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db1", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 1000, + "childtable_prefix": "stb00_", + "auto_create_table": "no", + "batch_create_tbl_num": 1000, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 1000, + "childtable_limit": 0, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }, + { + "name": "stb1", + "child_table_exists":"no", + "childtable_count": 10000, + "childtable_prefix": "stb01_", + "auto_create_table": "no", + "batch_create_tbl_num": 1000, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 200, + "childtable_limit": 0, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }] + }] +} + diff --git a/tests/pytest/tsdb/insertDataDb1Replica2.json b/tests/pytest/tsdb/insertDataDb1Replica2.json new file mode 100644 index 0000000000000000000000000000000000000000..fec38bcdecd9b441ad1c31891e66e7245c43889f --- /dev/null +++ b/tests/pytest/tsdb/insertDataDb1Replica2.json @@ -0,0 +1,87 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 10, + "num_of_records_per_req": 1000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db1", + "drop": "yes", + "replica": 2, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 1000, + "childtable_prefix": "stb00_", + "auto_create_table": "no", + "batch_create_tbl_num": 100, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 100, + "childtable_limit": 0, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }, + { + "name": "stb1", + "child_table_exists":"no", + "childtable_count": 1000, + "childtable_prefix": "stb01_", + "auto_create_table": "no", + "batch_create_tbl_num": 10, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 200, + "childtable_limit": 0, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }] + }] +} + diff --git a/tests/pytest/tsdb/insertDataDb2.json b/tests/pytest/tsdb/insertDataDb2.json new file mode 100644 index 0000000000000000000000000000000000000000..ead5f19716af8071b49e728ba91c523df9dd5139 --- /dev/null +++ b/tests/pytest/tsdb/insertDataDb2.json @@ -0,0 +1,86 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 0, + "num_of_records_per_req": 3000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db2", + "drop": "yes", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 200000, + "childtable_prefix": "stb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 1000, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 0, + "childtable_limit": 0, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }, + { + "name": "stb1", + "child_table_exists":"no", + "childtable_count": 2, + "childtable_prefix": "stb1_", + "auto_create_table": "no", + "batch_create_tbl_num": 1000, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 5, + "childtable_limit": 0, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }] + }] +} diff --git a/tests/pytest/tsdb/insertDataDb2Newstab.json b/tests/pytest/tsdb/insertDataDb2Newstab.json new file mode 100644 index 0000000000000000000000000000000000000000..f9d0713385265282e938838a10b485ca9cfdd603 --- /dev/null +++ b/tests/pytest/tsdb/insertDataDb2Newstab.json @@ -0,0 +1,86 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 0, + "num_of_records_per_req": 3000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db2", + "drop": "no", + "replica": 1, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 1, + "childtable_prefix": "stb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 100, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 0, + "childtable_limit": -1, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }, + { + "name": "stb1", + "child_table_exists":"yes", + "childtable_count": 1, + "childtable_prefix": "stb01_", + "auto_create_table": "no", + "batch_create_tbl_num": 10, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 10, + "childtable_limit": -1, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-11-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }] + }] +} diff --git a/tests/pytest/tsdb/insertDataDb2NewstabReplica2.json b/tests/pytest/tsdb/insertDataDb2NewstabReplica2.json new file mode 100644 index 0000000000000000000000000000000000000000..e052f2850fc2fe1e15c651f6150b79fa65c531c1 --- /dev/null +++ b/tests/pytest/tsdb/insertDataDb2NewstabReplica2.json @@ -0,0 +1,86 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 0, + "num_of_records_per_req": 3000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db2", + "drop": "no", + "replica": 2, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 1, + "childtable_prefix": "stb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 100, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 0, + "childtable_limit": -1, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }, + { + "name": "stb1", + "child_table_exists":"yes", + "childtable_count": 1, + "childtable_prefix": "stb01_", + "auto_create_table": "no", + "batch_create_tbl_num": 10, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 10, + "childtable_limit": -1, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-11-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }] + }] +} diff --git a/tests/pytest/tsdb/insertDataDb2Replica2.json b/tests/pytest/tsdb/insertDataDb2Replica2.json new file mode 100644 index 0000000000000000000000000000000000000000..121f70956a8f1eff31f92bc7fb904835f6bcd0de --- /dev/null +++ b/tests/pytest/tsdb/insertDataDb2Replica2.json @@ -0,0 +1,86 @@ +{ + "filetype": "insert", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "thread_count": 4, + "thread_count_create_tbl": 4, + "result_file": "./insert_res.txt", + "confirm_parameter_prompt": "no", + "insert_interval": 0, + "interlace_rows": 0, + "num_of_records_per_req": 3000, + "max_sql_len": 1024000, + "databases": [{ + "dbinfo": { + "name": "db2", + "drop": "yes", + "replica": 2, + "days": 10, + "cache": 50, + "blocks": 8, + "precision": "ms", + "keep": 365, + "minRows": 100, + "maxRows": 4096, + "comp":2, + "walLevel":1, + "cachelast":0, + "quorum":1, + "fsync":3000, + "update": 0 + }, + "super_tables": [{ + "name": "stb0", + "child_table_exists":"no", + "childtable_count": 2000, + "childtable_prefix": "stb0_", + "auto_create_table": "no", + "batch_create_tbl_num": 100, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 2000, + "childtable_limit": 0, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }, + { + "name": "stb1", + "child_table_exists":"no", + "childtable_count": 2, + "childtable_prefix": "stb1_", + "auto_create_table": "no", + "batch_create_tbl_num": 10, + "data_source": "rand", + "insert_mode": "taosc", + "insert_rows": 5, + "childtable_limit": 0, + "childtable_offset":0, + "interlace_rows": 0, + "insert_interval":0, + "max_sql_len": 1024000, + "disorder_ratio": 0, + "disorder_range": 1000, + "timestamp_step": 1, + "start_timestamp": "2020-10-01 00:00:00.000", + "sample_format": "csv", + "sample_file": "./sample.csv", + "tags_file": "", + "columns": [{"type": "INT"}, {"type": "DOUBLE", "count":1}, {"type": "BINARY", "len": 16, "count":1}, {"type": "BINARY", "len": 32, "count":1}], + "tags": [{"type": "TINYINT", "count":2}, {"type": "BINARY", "len": 16, "count":1}] + }] + }] +} diff --git a/tests/pytest/tsdb/tsdbComp.py b/tests/pytest/tsdb/tsdbComp.py new file mode 100644 index 0000000000000000000000000000000000000000..3563655efe4e69fab4c51a40818da205efb29837 --- /dev/null +++ b/tests/pytest/tsdb/tsdbComp.py @@ -0,0 +1,161 @@ +################################################################### +# 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 distutils.log import debug +import sys +import os +import taos +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * +import subprocess +from random import choice + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def getBuildPath(self): + global selfPath + 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): + + # set path para + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + + binPath = buildPath+ "/build/bin/" + testPath = selfPath+ "/../../../" + walFilePath = testPath + "/sim/dnode1/data/mnode_bak/wal/" + + #new db and insert data + tdSql.execute("drop database if exists db2") + os.system("%staosdemo -f tsdb/insertDataDb1.json -y " % binPath) + tdSql.execute("drop database if exists db1") + os.system("%staosdemo -f tsdb/insertDataDb2.json -y " % binPath) + tdSql.execute("drop table if exists db2.stb0") + os.system("%staosdemo -f tsdb/insertDataDb2Newstab.json -y " % binPath) + + tdSql.execute("use db2") + tdSql.execute("drop table if exists stb1_0") + tdSql.execute("drop table if exists stb1_1") + tdSql.execute("insert into stb0_0 values(1614218412000,8637,78.861045,'R','bf3')(1614218422000,8637,98.861045,'R','bf3')") + tdSql.execute("alter table db2.stb0 add column c4 int") + tdSql.execute("alter table db2.stb0 drop column c2") + tdSql.execute("alter table db2.stb0 add tag t3 int;") + tdSql.execute("alter table db2.stb0 drop tag t1") + tdSql.execute("create table if not exists stb2_0 (ts timestamp, c0 int, c1 float) ") + tdSql.execute("insert into stb2_0 values(1614218412000,8637,78.861045)") + tdSql.execute("alter table stb2_0 add column c2 binary(4)") + tdSql.execute("alter table stb2_0 drop column c1") + tdSql.execute("insert into stb2_0 values(1614218422000,8638,'R')") + + # create db utest + + + dataType= [ "tinyint", "smallint", "int", "bigint", "float", "double", "bool", " binary(20)", "nchar(20)", "tinyint unsigned", "smallint unsigned", "int unsigned", "bigint unsigned"] + + tdSql.execute("drop database if exists utest") + tdSql.execute("create database utest keep 3650") + tdSql.execute("use utest") + tdSql.execute('''create table test(ts timestamp, col0 tinyint, col1 tinyint, col2 smallint, col3 int, col4 bigint, col5 float, col6 double, + col7 bool, col8 binary(20), col9 nchar(20), col10 tinyint unsigned, col11 smallint unsigned, col12 int unsigned, col13 bigint unsigned) tags(loc nchar(200), tag1 int)''') + + # rowNum1 = 13 + # for i in range(rowNum1): + # columnName= "col" + str(i+1) + # tdSql.execute("alter table test drop column %s ;" % columnName ) + + rowNum2= 988 + for i in range(rowNum2): + tdSql.execute("alter table test add column col%d %s ;" %( i+14, choice(dataType)) ) + + rowNum3= 988 + for i in range(rowNum3): + tdSql.execute("alter table test drop column col%d ;" %( i+14) ) + + + self.rowNum = 1 + self.rowNum2 = 100 + self.rowNum3 = 20 + self.ts = 1537146000000 + + for j in range(self.rowNum2): + tdSql.execute("create table test%d using test tags('beijing%d', 10)" % (j,j) ) + for i in range(self.rowNum): + tdSql.execute("insert into test%d values(%d, %d, %d, %d, %d, %d, %f, %f, %d, 'taosdata%d', '涛思数据%d', %d, %d, %d, %d)" + % (j, self.ts + i*1000, i + 1, i + 1, i + 1, i + 1, i + 1, i + 0.1, i + 0.1, i % 2, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1)) + + for j in range(self.rowNum2): + tdSql.execute("drop table if exists test%d" % (j+1)) + + + # stop taosd and restart taosd + tdDnodes.stop(1) + sleep(10) + tdDnodes.start(1) + sleep(5) + tdSql.execute("reset query cache") + query_pid2 = int(subprocess.getstatusoutput('ps aux|grep taosd |grep -v "grep"|awk \'{print $2}\'')[1]) + print(query_pid2) + + # verify that the data is correct + tdSql.execute("use db2") + tdSql.query("select count (tbname) from stb0") + tdSql.checkData(0, 0, 1) + tdSql.query("select count (tbname) from stb1") + tdSql.checkRows(0) + tdSql.query("select count(*) from stb0_0") + tdSql.checkData(0, 0, 2) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 2) + tdSql.query("select count(*) from stb2_0") + tdSql.checkData(0, 0, 2) + + tdSql.execute("use utest") + tdSql.query("select count (tbname) from test") + tdSql.checkData(0, 0, 1) + + # delete useless file + testcaseFilename = os.path.split(__file__)[-1] + os.system("rm -rf ./insert_res.txt") + os.system("rm -rf tsdb/%s.sql" % testcaseFilename ) + + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/tsdb/tsdbCompCluster.py b/tests/pytest/tsdb/tsdbCompCluster.py new file mode 100644 index 0000000000000000000000000000000000000000..3df4c9a9d47744bcf729e3d6b01c3b515626058b --- /dev/null +++ b/tests/pytest/tsdb/tsdbCompCluster.py @@ -0,0 +1,160 @@ +################################################################### +# 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 os +import sys +sys.path.insert(0, os.getcwd()) +from util.log import * +from util.sql import * +from util.dnodes import * +import taos +import threading +import subprocess +from random import choice + + +class TwoClients: + def initConnection(self): + self.host = "chenhaoran02" + self.user = "root" + self.password = "taosdata" + self.config = "/etc/taos/" + self.port =6030 + self.rowNum = 10 + self.ts = 1537146000000 + + 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/" + walFilePath = "/var/lib/taos/mnode_bak/wal/" + + # new taos client + conn1 = taos.connect(host=self.host, user=self.user, password=self.password, config=self.config ) + print(conn1) + cur1 = conn1.cursor() + tdSql.init(cur1, True) + + # new db ,new super tables , child tables, and insert data + tdSql.execute("drop database if exists db2") + os.system("%staosdemo -f tsdb/insertDataDb1.json -y " % binPath) + tdSql.execute("drop database if exists db1") + os.system("%staosdemo -f tsdb/insertDataDb2.json -y " % binPath) + tdSql.execute("drop table if exists db2.stb0") + os.system("%staosdemo -f tsdb/insertDataDb2Newstab.json -y " % binPath) + + # new general tables and modify general tables; + tdSql.execute("use db2") + tdSql.execute("drop table if exists stb1_0") + tdSql.execute("drop table if exists stb1_1") + tdSql.execute("insert into stb0_0 values(1614218412000,8637,78.861045,'R','bf3')(1614218422000,8637,98.861045,'R','bf3')") + tdSql.execute("alter table db2.stb0 add column c4 int") + tdSql.execute("alter table db2.stb0 drop column c2") + tdSql.execute("alter table db2.stb0 add tag t3 int") + tdSql.execute("alter table db2.stb0 drop tag t1") + tdSql.execute("create table if not exists stb2_0 (ts timestamp, c0 int, c1 float) ") + tdSql.execute("insert into stb2_0 values(1614218412000,8637,78.861045)") + tdSql.execute("alter table stb2_0 add column c2 binary(4)") + tdSql.execute("alter table stb2_0 drop column c1") + tdSql.execute("insert into stb2_0 values(1614218422000,8638,'R')") + + # create db utest and modify super tables; + dataType= [ "tinyint", "smallint", "int", "bigint", "float", "double", "bool", " binary(20)", "nchar(20)", "tinyint unsigned", "smallint unsigned", "int unsigned", "bigint unsigned"] + tdSql.execute("drop database if exists utest") + tdSql.execute("create database utest keep 3650") + tdSql.execute("use utest") + tdSql.execute('''create table test(ts timestamp, col0 tinyint, col1 tinyint, col2 smallint, col3 int, col4 bigint, col5 float, col6 double, + col7 bool, col8 binary(20), col9 nchar(20), col10 tinyint unsigned, col11 smallint unsigned, col12 int unsigned, col13 bigint unsigned) tags(loc nchar(200), tag1 int)''') + rowNum2= 988 + for i in range(rowNum2): + tdSql.execute("alter table test add column col%d %s ;" %( i+14, choice(dataType)) ) + rowNum3= 988 + for i in range(rowNum3): + tdSql.execute("alter table test drop column col%d ;" %( i+14) ) + + self.rowNum = 1 + self.rowNum2 = 100 + self.ts = 1537146000000 + for j in range(self.rowNum2): + tdSql.execute("create table test%d using test tags('beijing%d', 10)" % (j,j) ) + for i in range(self.rowNum): + tdSql.execute("insert into test%d values(%d, %d, %d, %d, %d, %d, %f, %f, %d, 'taosdata%d', '涛思数据%d', %d, %d, %d, %d)" + % (j, self.ts + i*1000, i + 1, i + 1, i + 1, i + 1, i + 1, i + 0.1, i + 0.1, i % 2, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1)) + # delete child tables; + for j in range(self.rowNum2): + tdSql.execute("drop table if exists test%d" % (j+1)) + + #restart taosd + os.system("ps -ef |grep taosd |grep -v 'grep' |awk '{print $2}'|xargs kill -2") + sleep(20) + print("123") + os.system("nohup /usr/bin/taosd > /dev/null 2>&1 &") + sleep(4) + tdSql.execute("reset query cache") + query_pid2 = int(subprocess.getstatusoutput('ps aux|grep taosd |grep -v "grep"|awk \'{print $2}\'')[1]) + print(query_pid2) + + # new taos connecting to server + conn2 = taos.connect(host=self.host, user=self.user, password=self.password, config=self.config ) + print(conn2) + cur2 = conn2.cursor() + tdSql.init(cur2, True) + + + # check data correct + tdSql.query("show databases") + tdSql.execute("use db2") + tdSql.query("select count (tbname) from stb0") + tdSql.checkData(0, 0, 1) + tdSql.query("select count (tbname) from stb1") + tdSql.checkRows(0) + tdSql.query("select count(*) from stb0_0") + tdSql.checkData(0, 0, 2) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 2) + tdSql.query("select count(*) from stb2_0") + tdSql.checkData(0, 0, 2) + tdSql.query("select * from stb2_0") + tdSql.checkData(1, 2, 'R') + tdSql.execute("use utest") + tdSql.query("select count (tbname) from test") + tdSql.checkData(0, 0, 1) + + # delete useless file + testcaseFilename = os.path.split(__file__)[-1] + os.system("rm -rf ./insert_res.txt") + os.system("rm -rf tsdb/%s.sql" % testcaseFilename ) + +clients = TwoClients() +clients.initConnection() +# clients.getBuildPath() +clients.run() \ No newline at end of file diff --git a/tests/pytest/tsdb/tsdbCompClusterReplica2.py b/tests/pytest/tsdb/tsdbCompClusterReplica2.py new file mode 100644 index 0000000000000000000000000000000000000000..2e016deea0b78d6cf9f76a917ca49fc2c5744a6e --- /dev/null +++ b/tests/pytest/tsdb/tsdbCompClusterReplica2.py @@ -0,0 +1,170 @@ +################################################################### +# 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 os +import sys +sys.path.insert(0, os.getcwd()) +from util.log import * +from util.sql import * +from util.dnodes import * +import taos +import threading +import subprocess +from random import choice + +class TwoClients: + def initConnection(self): + self.host = "chenhaoran02" + self.user = "root" + self.password = "taosdata" + self.config = "/etc/taos/" + self.port =6030 + self.rowNum = 10 + self.ts = 1537146000000 + + 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/" + walFilePath = "/var/lib/taos/mnode_bak/wal/" + + # new taos client + conn1 = taos.connect(host=self.host, user=self.user, password=self.password, config=self.config ) + print(conn1) + cur1 = conn1.cursor() + tdSql.init(cur1, True) + + # new db ,new super tables , child tables, and insert data + tdSql.execute("drop database if exists db2") + os.system("%staosdemo -f tsdb/insertDataDb1Replica2.json -y " % binPath) + tdSql.execute("drop database if exists db1") + os.system("%staosdemo -f tsdb/insertDataDb2Replica2.json -y " % binPath) + tdSql.execute("drop table if exists db2.stb0") + os.system("%staosdemo -f tsdb/insertDataDb2NewstabReplica2.json -y " % binPath) + + # new general tables and modify general tables; + tdSql.execute("use db2") + tdSql.execute("drop table if exists stb1_0") + tdSql.execute("drop table if exists stb1_1") + tdSql.execute("insert into stb0_0 values(1614218412000,8637,78.861045,'R','bf3')(1614218422000,8637,98.861045,'R','bf3')") + tdSql.execute("alter table db2.stb0 add column c4 int") + tdSql.execute("alter table db2.stb0 drop column c2") + tdSql.execute("alter table db2.stb0 add tag t3 int") + tdSql.execute("alter table db2.stb0 drop tag t1") + tdSql.execute("create table if not exists stb2_0 (ts timestamp, c0 int, c1 float) ") + tdSql.execute("insert into stb2_0 values(1614218412000,8637,78.861045)") + tdSql.execute("alter table stb2_0 add column c2 binary(4)") + tdSql.execute("alter table stb2_0 drop column c1") + tdSql.execute("insert into stb2_0 values(1614218422000,8638,'R')") + + + # create db utest replica 2 and modify super tables; + dataType= [ "tinyint", "smallint", "int", "bigint", "float", "double", "bool", " binary(20)", "nchar(20)", "tinyint unsigned", "smallint unsigned", "int unsigned", "bigint unsigned"] + tdSql.execute("drop database if exists utest") + tdSql.execute("create database utest keep 3650 replica 2 ") + tdSql.execute("use utest") + tdSql.execute('''create table test(ts timestamp, col0 tinyint, col1 tinyint, col2 smallint, col3 int, col4 bigint, col5 float, col6 double, + col7 bool, col8 binary(20), col9 nchar(20), col10 tinyint unsigned, col11 smallint unsigned, col12 int unsigned, col13 bigint unsigned) tags(loc nchar(200), tag1 int)''') + rowNum2= 988 + for i in range(rowNum2): + tdSql.execute("alter table test add column col%d %s ;" %( i+14, choice(dataType)) ) + rowNum3= 988 + for i in range(rowNum3): + tdSql.execute("alter table test drop column col%d ;" %( i+14) ) + self.rowNum = 1 + self.rowNum2 = 100 + self.ts = 1537146000000 + for j in range(self.rowNum2): + tdSql.execute("create table test%d using test tags('beijing%d', 10)" % (j,j) ) + for i in range(self.rowNum): + tdSql.execute("insert into test%d values(%d, %d, %d, %d, %d, %d, %f, %f, %d, 'taosdata%d', '涛思数据%d', %d, %d, %d, %d)" + % (j, self.ts + i*1000, i + 1, i + 1, i + 1, i + 1, i + 1, i + 0.1, i + 0.1, i % 2, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1)) + # delete child tables; + for j in range(self.rowNum2): + tdSql.execute("drop table if exists test%d" % (j+1)) + + # drop dnodes and restart taosd; + sleep(3) + tdSql.execute(" drop dnode 'chenhaoran02:6030'; ") + sleep(20) + os.system("rm -rf /var/lib/taos/*") + print("clear dnode chenhaoran02'data files") + os.system("nohup /usr/bin/taosd > /dev/null 2>&1 &") + print("start taosd") + sleep(10) + tdSql.execute("reset query cache ;") + tdSql.execute("create dnode chenhaoran02 ;") + + # # + # os.system("ps -ef |grep taosd |grep -v 'grep' |awk '{print $2}'|xargs kill -2") + # sleep(20) + # os.system("nohup /usr/bin/taosd > /dev/null 2>&1 &") + # sleep(4) + # tdSql.execute("reset query cache") + # query_pid2 = int(subprocess.getstatusoutput('ps aux|grep taosd |grep -v "grep"|awk \'{print $2}\'')[1]) + # print(query_pid2) + + # new taos connecting to server + conn2 = taos.connect(host=self.host, user=self.user, password=self.password, config=self.config ) + print(conn2) + cur2 = conn2.cursor() + tdSql.init(cur2, True) + + # check data correct + tdSql.query("show databases") + tdSql.execute("use db2") + tdSql.query("select count (tbname) from stb0") + tdSql.checkData(0, 0, 1) + tdSql.query("select count (tbname) from stb1") + tdSql.checkRows(0) + tdSql.query("select count(*) from stb0_0") + tdSql.checkData(0, 0, 2) + tdSql.query("select count(*) from stb0") + tdSql.checkData(0, 0, 2) + tdSql.query("select count(*) from stb2_0") + tdSql.checkData(0, 0, 2) + tdSql.query("select * from stb2_0") + tdSql.checkData(1, 2, 'R') + + tdSql.execute("use utest") + tdSql.query("select count (tbname) from test") + tdSql.checkData(0, 0, 1) + + # delete useless file + testcaseFilename = os.path.split(__file__)[-1] + os.system("rm -rf ./insert_res.txt") + os.system("rm -rf tsdb/%s.sql" % testcaseFilename ) + +clients = TwoClients() +clients.initConnection() +# clients.getBuildPath() +clients.run() \ No newline at end of file diff --git a/tests/pytest/util/common.py b/tests/pytest/util/common.py new file mode 100644 index 0000000000000000000000000000000000000000..35abc4802f9de2080a6b6a166daf833c9cf04578 --- /dev/null +++ b/tests/pytest/util/common.py @@ -0,0 +1,53 @@ +################################################################### +# 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 random +import string +from util.sql import tdSql + +class TDCom: + def init(self, conn, logSql): + 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 getLongName(self, len, mode = "mixed"): + """ + generate long name + mode could be numbers/letters/letters_mixed/mixed + """ + if mode == "numbers": + chars = ''.join(random.choice(string.digits) for i in range(len)) + elif mode == "letters": + chars = ''.join(random.choice(string.ascii_letters.lower()) for i in range(len)) + elif mode == "letters_mixed": + chars = ''.join(random.choice(string.ascii_letters.upper() + string.ascii_letters.lower()) for i in range(len)) + else: + chars = ''.join(random.choice(string.ascii_letters.lower() + string.digits) for i in range(len)) + return chars + + def close(self): + self.cursor.close() + +tdCom = TDCom() diff --git a/tests/pytest/util/dnodes-default.py b/tests/pytest/util/dnodes-default.py index 085e08314907d6d48d02a2512d2caff87cd617e4..8da36f30748251f307a9152fd8907bdebc9e1405 100644 --- a/tests/pytest/util/dnodes-default.py +++ b/tests/pytest/util/dnodes-default.py @@ -60,7 +60,7 @@ class TDSimClient: self.cfgDict.update({option: value}) def cfg(self, option, value): - cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) + cmd = "echo %s %s >> %s" % (option, value, self.cfgPath) if os.system(cmd) != 0: tdLog.exit(cmd) @@ -320,7 +320,7 @@ class TDDnode: tdLog.exit(cmd) def cfg(self, option, value): - cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) + cmd = "echo %s %s >> %s" % (option, value, self.cfgPath) if os.system(cmd) != 0: tdLog.exit(cmd) diff --git a/tests/pytest/util/dnodes-no-random-fail.py b/tests/pytest/util/dnodes-no-random-fail.py index 2627575e615c306afa60c512b4bf8c87f5ee00df..a973f8da52d63aa04ecc3eb4afea47c93419e0c5 100644 --- a/tests/pytest/util/dnodes-no-random-fail.py +++ b/tests/pytest/util/dnodes-no-random-fail.py @@ -58,7 +58,7 @@ class TDSimClient: self.cfgDict.update({option: value}) def cfg(self, option, value): - cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) + cmd = "echo %s %s >> %s" % (option, value, self.cfgPath) if os.system(cmd) != 0: tdLog.exit(cmd) @@ -318,7 +318,7 @@ class TDDnode: tdLog.exit(cmd) def cfg(self, option, value): - cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) + cmd = "echo %s %s >> %s" % (option, value, self.cfgPath) if os.system(cmd) != 0: tdLog.exit(cmd) diff --git a/tests/pytest/util/dnodes-random-fail.py b/tests/pytest/util/dnodes-random-fail.py index 4f4cdcc0d096652dbd0197236cbde95109c4a76b..7cadca64a36e1ee05d339432657b7a6d1bac314c 100644 --- a/tests/pytest/util/dnodes-random-fail.py +++ b/tests/pytest/util/dnodes-random-fail.py @@ -58,7 +58,7 @@ class TDSimClient: self.cfgDict.update({option: value}) def cfg(self, option, value): - cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) + cmd = "echo %s %s >> %s" % (option, value, self.cfgPath) if os.system(cmd) != 0: tdLog.exit(cmd) @@ -318,7 +318,7 @@ class TDDnode: tdLog.exit(cmd) def cfg(self, option, value): - cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) + cmd = "echo %s %s >> %s" % (option, value, self.cfgPath) if os.system(cmd) != 0: tdLog.exit(cmd) diff --git a/tests/pytest/util/dnodes.py b/tests/pytest/util/dnodes.py index 0f4919ba96771804e2a3027f76c5a718ff1e9573..0208f884b691a20e4b4456fe8165797969305674 100644 --- a/tests/pytest/util/dnodes.py +++ b/tests/pytest/util/dnodes.py @@ -14,15 +14,16 @@ import sys import os import os.path +import platform import subprocess from time import sleep from util.log import * class TDSimClient: - def __init__(self): + def __init__(self, path): self.testCluster = False - + self.path = path self.cfgDict = { "numOfLogLines": "100000000", "numOfThreadsPerCore": "2.0", @@ -41,10 +42,7 @@ class TDSimClient: "jnidebugFlag": "135", "qdebugFlag": "135", "telemetryReporting": "0", - } - def init(self, path): - self.__init__() - self.path = path + } def getLogDir(self): self.logDir = "%s/sim/psim/log" % (self.path) @@ -61,7 +59,7 @@ class TDSimClient: self.cfgDict.update({option: value}) def cfg(self, option, value): - cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) + cmd = "echo %s %s >> %s" % (option, value, self.cfgPath) if os.system(cmd) != 0: tdLog.exit(cmd) @@ -125,7 +123,7 @@ class TDDnode: "charset":"UTF-8", "asyncLog":"0", "anyIp":"0", - "tsEnableTelemetryReporting":"0", + "telemetryReporting":"0", "dDebugFlag":"135", "tsdbDebugFlag":"135", "mDebugFlag":"135", @@ -246,7 +244,7 @@ class TDDnode: projPath = selfPath[:selfPath.find("tests")] for root, dirs, files in os.walk(projPath): - if ("taosd" in files): + if (("taosd") in files): rootRealPath = os.path.dirname(os.path.realpath(root)) if ("packaging" not in rootRealPath): buildPath = root[:len(root)-len("/build/bin")] @@ -404,7 +402,7 @@ class TDDnode: tdLog.exit(cmd) def cfg(self, option, value): - cmd = "echo '%s %s' >> %s" % (option, value, self.cfgPath) + cmd = "echo %s %s >> %s" % (option, value, self.cfgPath) if os.system(cmd) != 0: tdLog.exit(cmd) @@ -480,8 +478,7 @@ class TDDnodes: for i in range(len(self.dnodes)): self.dnodes[i].init(self.path) - self.sim = TDSimClient() - self.sim.init(self.path) + self.sim = TDSimClient(self.path) def setTestCluster(self, value): self.testCluster = value diff --git a/tests/pytest/util/sql.py b/tests/pytest/util/sql.py index dfe1e4a582c80f82a982ca270c6a3b2d144fb52f..2b654a379369c67cf906be0dde2f0cc4a309e1ea 100644 --- a/tests/pytest/util/sql.py +++ b/tests/pytest/util/sql.py @@ -21,7 +21,15 @@ import shutil import pandas as pd from util.log import * - +def _parse_datetime(timestr): + try: + return datetime.datetime.strptime(timestr, '%Y-%m-%d %H:%M:%S.%f') + except ValueError: + pass + try: + return datetime.datetime.strptime(timestr, '%Y-%m-%d %H:%M:%S') + except ValueError: + pass class TDSql: def __init__(self): @@ -181,7 +189,7 @@ class TDSql: tdLog.info("sql:%s, row:%d col:%d data:%d == expect:%s" % (self.sql, row, col, self.queryResult[row][col], data)) else: - if self.queryResult[row][col] == datetime.datetime.fromisoformat(data): + if self.queryResult[row][col] == _parse_datetime(data): tdLog.info("sql:%s, row:%d col:%d data:%s == expect:%s" % (self.sql, row, col, self.queryResult[row][col], data)) return diff --git a/tests/script/api/makefile b/tests/script/api/makefile index 7595594cbf2572623dd18648c8c4fa8e65dd966a..92d0a89b0fe0f4b31a43e8981a763922c03d5343 100644 --- a/tests/script/api/makefile +++ b/tests/script/api/makefile @@ -6,7 +6,8 @@ TARGET=exe LFLAGS = '-Wl,-rpath,/usr/local/taos/driver/' -ltaos -lpthread -lm -lrt CFLAGS = -O0 -g -Wall -Wno-deprecated -fPIC -Wno-unused-result -Wconversion \ -Wno-char-subscripts -D_REENTRANT -Wno-format -D_REENTRANT -DLINUX \ - -Wno-unused-function -D_M_X64 -I/usr/local/taos/include -std=gnu99 + -Wno-unused-function -D_M_X64 -I/usr/local/taos/include -std=gnu99 \ + -fsanitize=address all: $(TARGET) @@ -14,8 +15,10 @@ exe: gcc $(CFLAGS) ./batchprepare.c -o $(ROOT)batchprepare $(LFLAGS) gcc $(CFLAGS) ./stmtBatchTest.c -o $(ROOT)stmtBatchTest $(LFLAGS) gcc $(CFLAGS) ./stmtTest.c -o $(ROOT)stmtTest $(LFLAGS) + gcc $(CFLAGS) ./stmt_function.c -o $(ROOT)stmt_function $(LFLAGS) clean: rm $(ROOT)batchprepare rm $(ROOT)stmtBatchTest rm $(ROOT)stmtTest + rm $(ROOT)stmt_function diff --git a/tests/script/api/stmt_function.c b/tests/script/api/stmt_function.c new file mode 100644 index 0000000000000000000000000000000000000000..64573ec9948fb1c6bbadd9f084c3a5a21adb1fa7 --- /dev/null +++ b/tests/script/api/stmt_function.c @@ -0,0 +1,502 @@ +#include +#include +#include +#include "taos.h" +#include +#include +#include +#include + +void execute_simple_sql(void *taos, char *sql) { + TAOS_RES *result = taos_query(taos, sql); + if ( result == NULL || taos_errno(result) != 0) { + printf( "failed to %s, Reason: %s\n" , sql, taos_errstr(result)); + taos_free_result(result); + exit(EXIT_FAILURE); + } + taos_free_result(result); +} + +void print_result(TAOS_RES* res) { + if (res == NULL) { + exit(EXIT_FAILURE); + } + TAOS_ROW row = NULL; + int num_fields = taos_num_fields(res); + TAOS_FIELD* fields = taos_fetch_fields(res); + while ((row = taos_fetch_row(res))) { + char temp[256] = {0}; + taos_print_row(temp, row, fields, num_fields); + printf("get result: %s\n", temp); + } +} + +void taos_stmt_init_test() { + printf("start taos_stmt_init test \n"); + void *taos = NULL; + TAOS_STMT *stmt = NULL; + stmt = taos_stmt_init(taos); + assert(stmt == NULL); + // ASM ERROR + // assert(taos_stmt_close(stmt) != 0); + taos = taos_connect("127.0.0.1","root","taosdata",NULL,0); + if(taos == NULL) { + printf("Cannot connect to tdengine server\n"); + exit(EXIT_FAILURE); + } + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + assert(taos_stmt_close(stmt) == 0); + printf("finish taos_stmt_init test\n"); +} +void taos_stmt_preprare_test() { + printf("start taos_stmt_prepare test\n"); + char *stmt_sql = calloc(1, 1048576); + TAOS_STMT *stmt = NULL; + assert(taos_stmt_prepare(stmt, stmt_sql, 0) != 0); + void *taos = NULL; + taos = taos_connect("127.0.0.1","root","taosdata",NULL,0); + if(taos == NULL) { + printf("Cannot connect to tdengine server\n"); + exit(EXIT_FAILURE); + } + execute_simple_sql(taos, "drop database if exists stmt_test"); + execute_simple_sql(taos, "create database stmt_test"); + execute_simple_sql(taos, "use stmt_test"); + execute_simple_sql(taos, "create table super(ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 binary(8), c6 smallint, c7 tinyint, c8 bool, c9 nchar(8), c10 timestamp) tags (t1 int, t2 bigint, t3 float, t4 double, t5 binary(8), t6 smallint, t7 tinyint, t8 bool, t9 nchar(8))"); + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + // below will make client dead lock + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + + // assert(taos_stmt_close(stmt) == 0); + // stmt = taos_stmt_init(taos); + assert(stmt != NULL); + sprintf(stmt_sql, "select from ?"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) != 0); + assert(taos_stmt_close(stmt) == 0); + + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + sprintf(stmt_sql, "insert into ? values (?,?,?,?,?,?,?,?,?,?,?)"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + assert(taos_stmt_close(stmt) == 0); + + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + sprintf(stmt_sql, "insert into super values (?,?,?,?,?,?,?,?,?,?,?)"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) != 0); + assert(taos_stmt_close(stmt) == 0); + + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + sprintf(stmt_sql, "insert into ? values (?,?,?,?,?,?,?,?,1,?,?,?)"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + assert(taos_stmt_close(stmt) == 0); + + free(stmt_sql); + printf("finish taos_stmt_prepare test\n"); +} + +void taos_stmt_set_tbname_test() { + printf("start taos_stmt_set_tbname test\n"); + TAOS_STMT *stmt = NULL; + char *name = calloc(1, 200); + // ASM ERROR + // assert(taos_stmt_set_tbname(stmt, name) != 0); + void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0); + if(taos == NULL) { + printf("Cannot connect to tdengine server\n"); + exit(EXIT_FAILURE); + } + execute_simple_sql(taos, "drop database if exists stmt_test"); + execute_simple_sql(taos, "create database stmt_test"); + execute_simple_sql(taos, "use stmt_test"); + execute_simple_sql(taos, "create table super(ts timestamp, c1 int)"); + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + assert(taos_stmt_set_tbname(stmt, name) != 0); + char* stmt_sql = calloc(1, 1000); + sprintf(stmt_sql, "insert into ? values (?,?)"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + sprintf(name, "super"); + assert(stmt != NULL); + assert(taos_stmt_set_tbname(stmt, name) == 0); + free(name); + free(stmt_sql); + taos_stmt_close(stmt); + printf("finish taos_stmt_set_tbname test\n"); +} + +void taos_stmt_set_tbname_tags_test() { + printf("start taos_stmt_set_tbname_tags test\n"); + TAOS_STMT *stmt = NULL; + char *name = calloc(1,20); + TAOS_BIND *tags = calloc(1, sizeof(TAOS_BIND)); + // ASM ERROR + // assert(taos_stmt_set_tbname_tags(stmt, name, tags) != 0); + void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0); + if(taos == NULL) { + printf("Cannot connect to tdengine server\n"); + exit(EXIT_FAILURE); + } + execute_simple_sql(taos, "drop database if exists stmt_test"); + execute_simple_sql(taos, "create database stmt_test"); + execute_simple_sql(taos, "use stmt_test"); + execute_simple_sql(taos, "create stable super(ts timestamp, c1 int) tags (id int)"); + execute_simple_sql(taos, "create table tb using super tags (1)"); + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + char* stmt_sql = calloc(1, 1000); + sprintf(stmt_sql, "insert into ? using super tags (?) values (?,?)"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + assert(taos_stmt_set_tbname_tags(stmt, name, tags) != 0); + sprintf(name, "tb"); + assert(taos_stmt_set_tbname_tags(stmt, name, tags) != 0); + int t = 1; + tags->buffer_length = TSDB_DATA_TYPE_INT; + tags->buffer_length = sizeof(uint32_t); + tags->buffer = &t; + tags->length = &tags->buffer_length; + tags->is_null = NULL; + assert(taos_stmt_set_tbname_tags(stmt, name, tags) == 0); + free(stmt_sql); + free(name); + free(tags); + taos_stmt_close(stmt); + printf("finish taos_stmt_set_tbname_tags test\n"); +} + +void taos_stmt_set_sub_tbname_test() { + printf("start taos_stmt_set_sub_tbname test\n"); + TAOS_STMT *stmt = NULL; + char *name = calloc(1, 200); + // ASM ERROR + // assert(taos_stmt_set_sub_tbname(stmt, name) != 0); + void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0); + if(taos == NULL) { + printf("Cannot connect to tdengine server\n"); + exit(EXIT_FAILURE); + } + execute_simple_sql(taos, "drop database if exists stmt_test"); + execute_simple_sql(taos, "create database stmt_test"); + execute_simple_sql(taos, "use stmt_test"); + execute_simple_sql(taos, "create stable super(ts timestamp, c1 int) tags (id int)"); + execute_simple_sql(taos, "create table tb using super tags (1)"); + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + char* stmt_sql = calloc(1, 1000); + sprintf(stmt_sql, "insert into ? values (?,?)"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + assert(taos_stmt_set_sub_tbname(stmt, name) != 0); + sprintf(name, "tb"); + assert(taos_stmt_set_sub_tbname(stmt, name) == 0); + // assert(taos_load_table_info(taos, "super, tb") == 0); + // assert(taos_stmt_set_sub_tbname(stmt, name) == 0); + free(name); + free(stmt_sql); + assert(taos_stmt_close(stmt) == 0); + printf("finish taos_stmt_set_sub_tbname test\n"); +} + +void taos_stmt_bind_param_test() { + printf("start taos_stmt_bind_param test\n"); + TAOS_STMT *stmt = NULL; + TAOS_BIND *binds = NULL; + assert(taos_stmt_bind_param(stmt, binds) != 0); + void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0); + if(taos == NULL) { + printf("Cannot connect to tdengine server\n"); + exit(EXIT_FAILURE); + } + execute_simple_sql(taos, "drop database if exists stmt_test"); + execute_simple_sql(taos, "create database stmt_test"); + execute_simple_sql(taos, "use stmt_test"); + execute_simple_sql(taos, "create table super(ts timestamp, c1 int)"); + stmt = taos_stmt_init(taos); + char* stmt_sql = calloc(1, 1000); + sprintf(stmt_sql, "insert into ? values (?,?)"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + assert(taos_stmt_bind_param(stmt, binds) != 0); + free(binds); + TAOS_BIND *params = calloc(2, sizeof(TAOS_BIND)); + int64_t ts = (int64_t)1591060628000; + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[0].buffer_length = sizeof(uint64_t); + params[0].buffer = &ts; + params[0].length = ¶ms[0].buffer_length; + params[0].is_null = NULL; + int32_t i = (int32_t)21474; + params[1].buffer_type = TSDB_DATA_TYPE_INT; + params[1].buffer_length = sizeof(int32_t); + params[1].buffer = &i; + params[1].length = ¶ms[1].buffer_length; + params[1].is_null = NULL; + assert(taos_stmt_bind_param(stmt, params) != 0); + assert(taos_stmt_set_tbname(stmt, "super") == 0); + assert(taos_stmt_bind_param(stmt, params) == 0); + free(params); + free(stmt_sql); + taos_stmt_close(stmt); + printf("finish taos_stmt_bind_param test\n"); +} + +void taos_stmt_bind_single_param_batch_test() { + printf("start taos_stmt_bind_single_param_batch test\n"); + TAOS_STMT *stmt = NULL; + TAOS_MULTI_BIND *bind = NULL; + assert(taos_stmt_bind_single_param_batch(stmt, bind, 0) != 0); + printf("finish taos_stmt_bind_single_param_batch test\n"); +} + +void taos_stmt_bind_param_batch_test() { + printf("start taos_stmt_bind_param_batch test\n"); + TAOS_STMT *stmt = NULL; + TAOS_MULTI_BIND *bind = NULL; + assert(taos_stmt_bind_param_batch(stmt, bind) != 0); + printf("finish taos_stmt_bind_param_batch test\n"); +} + +void taos_stmt_add_batch_test() { + printf("start taos_stmt_add_batch test\n"); + TAOS_STMT *stmt = NULL; + assert(taos_stmt_add_batch(stmt) != 0); + void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0); + if(taos == NULL) { + printf("Cannot connect to tdengine server\n"); + exit(EXIT_FAILURE); + } + execute_simple_sql(taos, "drop database if exists stmt_test"); + execute_simple_sql(taos, "create database stmt_test"); + execute_simple_sql(taos, "use stmt_test"); + execute_simple_sql(taos, "create table super(ts timestamp, c1 int)"); + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + char* stmt_sql = calloc(1, 1000); + sprintf(stmt_sql, "insert into ? values (?,?)"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + assert(taos_stmt_add_batch(stmt) != 0); + TAOS_BIND *params = calloc(2, sizeof(TAOS_BIND)); + int64_t ts = (int64_t)1591060628000; + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[0].buffer_length = sizeof(uint64_t); + params[0].buffer = &ts; + params[0].length = ¶ms[0].buffer_length; + params[0].is_null = NULL; + int32_t i = (int32_t)21474; + params[1].buffer_type = TSDB_DATA_TYPE_INT; + params[1].buffer_length = sizeof(int32_t); + params[1].buffer = &i; + params[1].length = ¶ms[1].buffer_length; + params[1].is_null = NULL; + assert(taos_stmt_set_tbname(stmt, "super") == 0); + assert(taos_stmt_bind_param(stmt, params) == 0); + assert(taos_stmt_add_batch(stmt) == 0); + free(params); + free(stmt_sql); + assert(taos_stmt_close(stmt) == 0); + printf("finish taos_stmt_add_batch test\n"); +} + +void taos_stmt_execute_test() { + printf("start taos_stmt_execute test\n"); + TAOS_STMT *stmt = NULL; + assert(taos_stmt_execute(stmt) != 0); + void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0); + if(taos == NULL) { + printf("Cannot connect to tdengine server\n"); + exit(EXIT_FAILURE); + } + execute_simple_sql(taos, "drop database if exists stmt_test"); + execute_simple_sql(taos, "create database stmt_test"); + execute_simple_sql(taos, "use stmt_test"); + execute_simple_sql(taos, "create table super(ts timestamp, c1 int)"); + stmt = taos_stmt_init(taos); + assert(stmt != NULL); + assert(taos_stmt_execute(stmt) != 0); + char* stmt_sql = calloc(1, 1000); + sprintf(stmt_sql, "insert into ? values (?,?)"); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + assert(taos_stmt_execute(stmt) != 0); + TAOS_BIND *params = calloc(2, sizeof(TAOS_BIND)); + int64_t ts = (int64_t)1591060628000; + params[0].buffer_type = TSDB_DATA_TYPE_TIMESTAMP; + params[0].buffer_length = sizeof(uint64_t); + params[0].buffer = &ts; + params[0].length = ¶ms[0].buffer_length; + params[0].is_null = NULL; + int32_t i = (int32_t)21474; + params[1].buffer_type = TSDB_DATA_TYPE_INT; + params[1].buffer_length = sizeof(int32_t); + params[1].buffer = &i; + params[1].length = ¶ms[1].buffer_length; + params[1].is_null = NULL; + assert(taos_stmt_set_tbname(stmt, "super") == 0); + assert(taos_stmt_execute(stmt) != 0); + assert(taos_stmt_bind_param(stmt, params) == 0); + assert(taos_stmt_execute(stmt) != 0); + assert(taos_stmt_add_batch(stmt) == 0); + assert(taos_stmt_execute(stmt) == 0); + free(params); + free(stmt_sql); + assert(taos_stmt_close(stmt) == 0); + printf("finish taos_stmt_execute test\n"); +} + +void taos_stmt_use_result_query(void *taos, char *col, int type) { + TAOS_STMT *stmt = taos_stmt_init(taos); + assert(stmt != NULL); + char *stmt_sql = calloc(1, 1024); + struct { + int64_t c1; + int32_t c2; + int64_t c3; + float c4; + double c5; + char c6[8]; + int16_t c7; + int8_t c8; + int8_t c9; + char c10[32]; + } v = {0}; + v.c1 = (int64_t)1591060628000; + v.c2 = (int32_t)1; + v.c3 = (int64_t)1; + v.c4 = (float)1; + v.c5 = (double)1; + strcpy(v.c6, "abcdefgh"); + v.c7 = 1; + v.c8 = 1; + v.c9 = 1; + strcpy(v.c10, "一二三四五六七八"); + uintptr_t c10len=strlen(v.c10); + sprintf(stmt_sql, "select * from stmt_test.t1 where %s = ?", col); + printf("stmt_sql: %s\n", stmt_sql); + assert(taos_stmt_prepare(stmt, stmt_sql, 0) == 0); + TAOS_BIND *params = calloc(1, sizeof(TAOS_BIND)); + params->buffer_type = type; + params->is_null = NULL; + switch(type){ + case TSDB_DATA_TYPE_TIMESTAMP: + params->buffer_length = sizeof(v.c1); + params->buffer = &v.c1; + params->length = ¶ms->buffer_length; + break; + case TSDB_DATA_TYPE_INT: + params->buffer_length = sizeof(v.c2); + params->buffer = &v.c2; + params->length = ¶ms->buffer_length; + case TSDB_DATA_TYPE_BIGINT: + params->buffer_length = sizeof(v.c3); + params->buffer = &v.c3; + params->length = ¶ms->buffer_length; + break; + case TSDB_DATA_TYPE_FLOAT: + params->buffer_length = sizeof(v.c4); + params->buffer = &v.c4; + params->length = ¶ms->buffer_length; + case TSDB_DATA_TYPE_DOUBLE: + params->buffer_length = sizeof(v.c5); + params->buffer = &v.c5; + params->length = ¶ms->buffer_length; + break; + case TSDB_DATA_TYPE_BINARY: + params->buffer_length = sizeof(v.c6); + params->buffer = &v.c6; + params->length = ¶ms->buffer_length; + break; + case TSDB_DATA_TYPE_SMALLINT: + params->buffer_length = sizeof(v.c7); + params->buffer = &v.c7; + params->length = ¶ms->buffer_length; + break; + case TSDB_DATA_TYPE_TINYINT: + params->buffer_length = sizeof(v.c8); + params->buffer = &v.c8; + params->length = ¶ms->buffer_length; + case TSDB_DATA_TYPE_BOOL: + params->buffer_length = sizeof(v.c9); + params->buffer = &v.c9; + params->length = ¶ms->buffer_length; + break; + case TSDB_DATA_TYPE_NCHAR: + params->buffer_length = sizeof(v.c10); + params->buffer = &v.c10; + params->length = &c10len; + break; + default: + printf("Cannnot find type: %d\n", type); + break; + + } + assert(taos_stmt_bind_param(stmt, params) == 0); + assert(taos_stmt_execute(stmt) == 0); + TAOS_RES* result = taos_stmt_use_result(stmt); + assert(result != NULL); + print_result(result); + assert(taos_stmt_close(stmt) == 0); + free(params); + free(stmt_sql); + taos_free_result(result); +} + +void taos_stmt_use_result_test() { + printf("start taos_stmt_use_result test\n"); + void *taos = taos_connect("127.0.0.1","root","taosdata",NULL,0); + if(taos == NULL) { + printf("Cannot connect to tdengine server\n"); + exit(EXIT_FAILURE); + } + execute_simple_sql(taos, "drop database if exists stmt_test"); + execute_simple_sql(taos, "create database stmt_test"); + execute_simple_sql(taos, "use stmt_test"); + execute_simple_sql(taos, "create table super(ts timestamp, c1 int, c2 bigint, c3 float, c4 double, c5 binary(8), c6 smallint, c7 tinyint, c8 bool, c9 nchar(8), c10 timestamp) tags (t1 int, t2 bigint, t3 float, t4 double, t5 binary(8), t6 smallint, t7 tinyint, t8 bool, t9 nchar(8))"); + execute_simple_sql(taos, "create table t1 using super tags (1, 1, 1, 1, 'abcdefgh',1,1,1,'一二三四五六七八')"); + execute_simple_sql(taos, "insert into t1 values (1591060628000, 1, 1, 1, 1, 'abcdefgh',1,1,1,'一二三四五六七八', now)"); + execute_simple_sql(taos, "insert into t1 values (1591060628001, 1, 1, 1, 1, 'abcdefgh',1,1,1,'一二三四五六七八', now)"); + + taos_stmt_use_result_query(taos, "c1", TSDB_DATA_TYPE_INT); + taos_stmt_use_result_query(taos, "c2", TSDB_DATA_TYPE_BIGINT); + taos_stmt_use_result_query(taos, "c3", TSDB_DATA_TYPE_FLOAT); + taos_stmt_use_result_query(taos, "c4", TSDB_DATA_TYPE_DOUBLE); + taos_stmt_use_result_query(taos, "c5", TSDB_DATA_TYPE_BINARY); + taos_stmt_use_result_query(taos, "c6", TSDB_DATA_TYPE_SMALLINT); + taos_stmt_use_result_query(taos, "c7", TSDB_DATA_TYPE_TINYINT); + taos_stmt_use_result_query(taos, "c8", TSDB_DATA_TYPE_BOOL); + taos_stmt_use_result_query(taos, "c9", TSDB_DATA_TYPE_NCHAR); + + printf("finish taos_stmt_use_result test\n"); +} + +void taos_stmt_close_test() { + printf("start taos_stmt_close test\n"); + // ASM ERROR + // TAOS_STMT *stmt = NULL; + // assert(taos_stmt_close(stmt) != 0); + printf("finish taos_stmt_close test\n"); +} + +void test_api_reliability() { + // ASM catch memory leak + taos_stmt_init_test(); + taos_stmt_preprare_test(); + taos_stmt_set_tbname_test(); + taos_stmt_set_tbname_tags_test(); + taos_stmt_set_sub_tbname_test(); + taos_stmt_bind_param_test(); + taos_stmt_bind_single_param_batch_test(); + taos_stmt_bind_param_batch_test(); + taos_stmt_add_batch_test(); + taos_stmt_execute_test(); + taos_stmt_close_test(); +} + +void test_query() { + taos_stmt_use_result_test(); +} + +int main(int argc, char *argv[]) { + test_api_reliability(); + test_query(); + return 0; +} \ No newline at end of file diff --git a/tests/script/fullGeneralSuite.sim b/tests/script/fullGeneralSuite.sim index 5b5a911558b5eb1d27f34fb10590a3b9ff52658c..188ce1405541cbbb230ceb186c44cfd4230925fc 100644 --- a/tests/script/fullGeneralSuite.sim +++ b/tests/script/fullGeneralSuite.sim @@ -221,3 +221,5 @@ run general/stream/table_replica1_vnoden.sim run general/stream/metrics_replica1_vnoden.sim run general/db/show_create_db.sim run general/db/show_create_table.sim +run general/parser/like.sim +run general/parser/regex.sim diff --git a/tests/script/general/http/restful_dbname.sim b/tests/script/general/http/restful_dbname.sim new file mode 100644 index 0000000000000000000000000000000000000000..75cd198507dda306c736cbcdeef4a044f66da9de --- /dev/null +++ b/tests/script/general/http/restful_dbname.sim @@ -0,0 +1,124 @@ +system sh/stop_dnodes.sh +sleep 2000 +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c walLevel -v 1 +system sh/cfg.sh -n dnode1 -c http -v 1 +system sh/cfg.sh -n dnode1 -c httpDbNameMandatory -v 1 +system sh/exec.sh -n dnode1 -s start + +sleep 2000 +sql connect +sql drop database if exists db + +print ============================ dnode1 start + +print =============== step1 - login + +system_content curl 127.0.0.1:7111/rest/login/root/taosdata +print curl 127.0.0.1:7111/rest/login/root/taosdata -----> $system_content + +if $system_content != @{"status":"succ","code":0,"desc":"/KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04"}@ then + return -1 +endi + +print =============== step2 - execute sql without db_name + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'show databases' 127.0.0.1:7111/rest/sql + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'show databases' 127.0.0.1:7111/rest/sql + +if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create database if not exists db' 127.0.0.1:7111/rest/sql + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create database if not exists db' 127.0.0.1:7111/rest/sql + +if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create table table_rest (ts timestamp, i int)' 127.0.0.1:7111/rest/sql + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create table table_rest (ts timestamp, i int)' 127.0.0.1:7111/rest/sql + +if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'insert into table_rest (now, 1)' 127.0.0.1:7111/rest/sql + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'insert into table_rest values (now, 1)' 127.0.0.1:7111/rest/sql + +if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from table_rest' 127.0.0.1:7111/rest/sql + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from table_rest' 127.0.0.1:7111/rest/sql + +if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'drop database if exists db' 127.0.0.1:7111/rest/sql + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'drop database if exists db' 127.0.0.1:7111/rest/sql + +if $system_content != @{"status":"error","code":4354,"desc":"invalid url format"}@ then + return -1 +endi + +print =============== step3 - execute sql with db_name + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'show databases' 127.0.0.1:7111/rest/sql/databases + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'show databases' 127.0.0.1:7111/rest/sql/databases + +if $system_content != @{"status":"succ","head":["name","created_time","ntables","vgroups","replica","quorum","days","keep","cache(MB)","blocks","minrows","maxrows","wallevel","fsync","comp","cachelast","precision","update","status"],"column_meta":[["name",8,32],["created_time",9,8],["ntables",4,4],["vgroups",4,4],["replica",3,2],["quorum",3,2],["days",3,2],["keep",8,24],["cache(MB)",4,4],["blocks",4,4],["minrows",4,4],["maxrows",4,4],["wallevel",2,1],["fsync",4,4],["comp",2,1],["cachelast",2,1],["precision",8,3],["update",2,1],["status",8,10]],"data":[],"rows":0}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create database if not exists db' 127.0.0.1:7111/rest/sql/db + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create database if not exists db' 127.0.0.1:7111/rest/sql/db + +if $system_content != @{"status":"succ","head":["affected_rows"],"column_meta":[["affected_rows",4,4]],"data":[[0]],"rows":1}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create table table_rest (ts timestamp, i int)' 127.0.0.1:7111/rest/sql/db + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'create table table_rest (ts timestamp, i int)' 127.0.0.1:7111/rest/sql/db + +if $system_content != @{"status":"succ","head":["affected_rows"],"column_meta":[["affected_rows",4,4]],"data":[[0]],"rows":1}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'insert into table_rest (now, 1)' 127.0.0.1:7111/rest/sql/db + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'insert into table_rest values (1629904789233, 1)' 127.0.0.1:7111/rest/sql/db + +if $system_content != @{"status":"succ","head":["affected_rows"],"column_meta":[["affected_rows",4,4]],"data":[[1]],"rows":1}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from table_rest' 127.0.0.1:7111/rest/sql/db + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from table_rest' 127.0.0.1:7111/rest/sql/db + +if $system_content != @{"status":"succ","head":["ts","i"],"column_meta":[["ts",9,8],["i",4,4]],"data":[["2021-08-25 23:19:49.233",1]],"rows":1}@ then + return -1 +endi + +print curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'drop database if exists db' 127.0.0.1:7111/rest/sql/db + +system_content curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'drop database if exists db' 127.0.0.1:7111/rest/sql/db + +if $system_content != @{"status":"succ","head":["affected_rows"],"column_meta":[["affected_rows",4,4]],"data":[[0]],"rows":1}@ then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/general/parser/columnValue_float.sim b/tests/script/general/parser/columnValue_float.sim index c7008d0b132e1d82b32a773555c638e71340b731..1832f7f84746bd8f0e94c463db04c38e2c01e273 100644 --- a/tests/script/general/parser/columnValue_float.sim +++ b/tests/script/general/parser/columnValue_float.sim @@ -150,13 +150,13 @@ if $data00 != 0.00150 then print expect 0.00150, actual: $data00 return -1 endi -sql create table st_float_15_0 using mt_float tags (3.40282347e+38) -sql select tagname from st_float_15_0 +#sql create table st_float_15_0 using mt_float tags (3.40282347e+38) +#sql select tagname from st_float_15_0 #if $data00 != 0.001500 then # return -1 #endi -sql create table st_float_16_0 using mt_float tags (-3.40282347e+38) -sql select tagname from st_float_16_0 +#sql create table st_float_16_0 using mt_float tags (-3.40282347e+38) +#sql select tagname from st_float_16_0 #if $data00 != 0.001500 then # return -1 #endi diff --git a/tests/script/general/parser/function.sim b/tests/script/general/parser/function.sim index 0c93fe919a8f8d934017135ecf1d3cff4515a3e1..556292b21b218f4df2aaa034d8babe35903a23b8 100644 --- a/tests/script/general/parser/function.sim +++ b/tests/script/general/parser/function.sim @@ -313,6 +313,12 @@ if $rows != 6 then return -1 endi +print =============================> TD-6086 +sql create stable td6086st(ts timestamp, d double) tags(t nchar(50)); +sql create table td6086ct1 using td6086st tags("ct1"); +sql create table td6086ct2 using td6086st tags("ct2"); +sql SELECT LAST(d),t FROM td6086st WHERE tbname in ('td6086ct1', 'td6086ct2') and ts>="2019-07-30 00:00:00" and ts<="2021-08-31 00:00:00" interval(1800s) fill(prev) GROUP BY tbname; + print ==================> td-2624 sql create table tm2(ts timestamp, k int, b binary(12)); sql insert into tm2 values('2011-01-02 18:42:45.326', -1,'abc'); @@ -1149,9 +1155,11 @@ endi sql select derivative(test_column_alias_name, 1s, 0) from (select avg(k) test_column_alias_name from t1 interval(1s)); -sql create table smeters (ts timestamp, current float, voltage int); -sql insert into smeters values ('2021-08-08 10:10:10', 10, 1); -sql insert into smeters values ('2021-08-08 10:10:12', 10, 2); +sql create table smeters (ts timestamp, current float, voltage int) tags (t1 int); +sql create table smeter1 using smeters tags (1); +sql insert into smeter1 values ('2021-08-08 10:10:10', 10, 2); +sql insert into smeter1 values ('2021-08-08 10:10:12', 10, 2); +sql insert into smeter1 values ('2021-08-08 10:10:14', 20, 1); sql select stddev(voltage) from smeters where ts>='2021-08-08 10:10:10.000' and ts < '2021-08-08 10:10:20.000' and current=10 interval(1000a); if $rows != 2 then @@ -1160,9 +1168,21 @@ endi if $data00 != @21-08-08 10:10:10.000@ then return -1 endi +if $data01 != 0.000000000 then + return -1 +endi if $data10 != @21-08-08 10:10:12.000@ then return -1 endi +if $data11 != 0.000000000 then + return -1 +endi - +sql select stddev(voltage) from smeters where ts>='2021-08-08 10:10:10.000' and ts < '2021-08-08 10:10:20.000' and current=10; +if $rows != 1 then + return -1 +endi +if $data00 != 0.000000000 then + return -1 +endi diff --git a/tests/script/general/parser/interp.sim b/tests/script/general/parser/interp.sim index 74febff0638826ddaa33960e546eb0a106d28eff..f192837bb7422046b0fbf05e66b2f2165d7e3c10 100644 --- a/tests/script/general/parser/interp.sim +++ b/tests/script/general/parser/interp.sim @@ -68,7 +68,6 @@ print ================== server restart completed run general/parser/interp_test.sim - print ================= TD-5931 sql create stable st5931(ts timestamp, f int) tags(t int) sql create table ct5931 using st5931 tags(1) @@ -76,6 +75,7 @@ sql create table nt5931(ts timestamp, f int) sql select interp(*) from nt5931 where ts=now sql select interp(*) from st5931 where ts=now sql select interp(*) from ct5931 where ts=now + if $rows != 0 then return -1 endi diff --git a/tests/script/general/parser/interp_test.sim b/tests/script/general/parser/interp_test.sim index 845afb0173685bf609897646eb188d689be6df10..8eac8a41d391508737232a3f068c477922bf77aa 100644 --- a/tests/script/general/parser/interp_test.sim +++ b/tests/script/general/parser/interp_test.sim @@ -23,562 +23,563 @@ sql use $db ##### select interp from table print ====== select intp from table $tb = $tbPrefix . 0 - ## interp(*) from tb - sql select interp(*) from $tb where ts = $ts0 - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:00.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != 0 then - return -1 - endi - - ## interp + limit offset - sql select interp(*) from $tb where ts = $ts0 limit 5 offset 1 - if $rows != 0 then - return -1 - endi - - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:00.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != 0 then - return -1 - endi - if $data03 != 0.00000 then - return -1 - endi - if $data04 != 0.000000000 then - return -1 - endi - if $data05 != 0 then - return -1 - endi - if $data06 != 0 then - return -1 - endi - if $data07 != 1 then - return -1 - endi - if $data08 != binary0 then - return -1 - endi - if $data09 != nchar0 then - return -1 - endi - - ## intp + aggregation functions - #$t = $ts0 + $delta - #$t = $t + $delta - #sql_error select interp(ts), max(c1), min(c2), count(c3), sum(c4), avg(c5), stddev(c6), first(c7), last(c8), interp(c9) from $tb where ts = $t - - ### illegal queries on a table - sql_error select interp(ts), c1 from $tb where ts = $ts0 - sql_error select interp(ts) from $tb where ts >= $ts0 - sql_error select interp(ts), max(c1), min(c2), count(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(NULL) - - ### interp from tb + fill - $t = $ts0 + 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t - if $rows != 0 then - return -1 - endi - - ## fill(none) - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(none) - if $rows != 0 then - return -1 - endi - $t = $tsu + 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(none) - if $rows != 0 then - return -1 - endi - - ## fill(NULL) - $t = $tsu - 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(value, NULL) order by ts asc - if $rows != 1 then - return -1 - endi - if $data00 != @18-11-25 19:29:59.000@ then - return -1 - endi - if $data01 != NULL then - print expect NULL, actual $data01 - return -1 - endi - if $data02 != NULL then - return -1 - endi - if $data03 != NULL then - return -1 - endi - if $data04 != NULL then - return -1 - endi - if $data05 != NULL then - return -1 - endi - if $data06 != NULL then - return -1 - endi - if $data07 != NULL then - return -1 - endi - if $data08 != NULL then - return -1 - endi - if $data09 != NULL then - return -1 - endi - - $t = $tsu + 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(none) - if $rows != 0 then - return -1 - endi - - ## fill(prev) - $t = $ts0 + 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(prev) - if $rows != 1 then - return -1 - endi - - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(prev) - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:00.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != 0 then - return -1 - endi - if $data03 != 0.00000 then - return -1 - endi - if $data04 != 0.000000000 then - return -1 - endi - if $data05 != 0 then - return -1 - endi - if $data06 != 0 then - return -1 - endi - if $data07 != 1 then - return -1 - endi - if $data08 != binary0 then - return -1 - endi - if $data09 != nchar0 then - return -1 - endi - - $t = $ts0 - 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(prev) - if $rows != 0 then - return -1 - endi - - $t = $ts0 + 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $t fill(prev) - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:01.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != NULL then - return -1 - endi - if $data03 != 0.00000 then - print expect 0.00000, actual:$data03 - return -1 - endi +## interp(*) from tb +sql select interp(*) from $tb where ts = $ts0 +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:00.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != 0 then + return -1 +endi + +## interp + limit offset +sql select interp(*) from $tb where ts = $ts0 limit 5 offset 1 +if $rows != 0 then + return -1 +endi + +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:00.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != 0 then + return -1 +endi +if $data03 != 0.00000 then + return -1 +endi +if $data04 != 0.000000000 then + return -1 +endi +if $data05 != 0 then + return -1 +endi +if $data06 != 0 then + return -1 +endi +if $data07 != 1 then + return -1 +endi +if $data08 != binary0 then + return -1 +endi +if $data09 != nchar0 then + return -1 +endi + +## intp + aggregation functions +$t = $ts0 + $delta +$t = $t + $delta +sql_error select interp(ts), max(c1), min(c2), count(c3), sum(c4), avg(c5), stddev(c6), first(c7), last(c8), interp(c9) from $tb where ts = $t +sql_error select interp(ts) from $tb where ts=$ts0 interval(1s) + +### illegal queries on a table +sql_error select interp(ts), c1 from $tb where ts = $ts0 +sql_error select interp(ts) from $tb where ts >= $ts0 +sql_error select interp(ts), max(c1), min(c2), count(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(NULL) + +### interp from tb + fill +$t = $ts0 + 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t +if $rows != 0 then + return -1 +endi + +## fill(none) +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(none) +if $rows != 0 then + return -1 +endi +$t = $tsu + 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(none) +if $rows != 0 then + return -1 +endi + +## fill(NULL) +$t = $tsu - 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(value, NULL) order by ts asc +if $rows != 1 then + return -1 +endi +if $data00 != @18-11-25 19:29:59.000@ then + return -1 +endi +if $data01 != NULL then + print expect NULL, actual $data01 + return -1 +endi +if $data02 != NULL then + return -1 +endi +if $data03 != NULL then + return -1 +endi +if $data04 != NULL then + return -1 +endi +if $data05 != NULL then + return -1 +endi +if $data06 != NULL then + return -1 +endi +if $data07 != NULL then + return -1 +endi +if $data08 != NULL then + return -1 +endi +if $data09 != NULL then + return -1 +endi + +$t = $tsu + 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(none) +if $rows != 0 then + return -1 +endi + +## fill(prev) +$t = $ts0 + 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(prev) +if $rows != 1 then + return -1 +endi + +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(prev) +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:00.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != 0 then + return -1 +endi +if $data03 != 0.00000 then + return -1 +endi +if $data04 != 0.000000000 then + return -1 +endi +if $data05 != 0 then + return -1 +endi +if $data06 != 0 then + return -1 +endi +if $data07 != 1 then + return -1 +endi +if $data08 != binary0 then + return -1 +endi +if $data09 != nchar0 then + return -1 +endi + +$t = $ts0 - 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(prev) +if $rows != 0 then + return -1 +endi + +$t = $ts0 + 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $t fill(prev) +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:01.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != NULL then + return -1 +endi +if $data03 != 0.00000 then + print expect 0.00000, actual:$data03 + return -1 +endi # if $data04 != NULL then # return -1 # endi - $t = $tsu + 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(prev) - if $rows != 0 then - return -1 - endi - - ## fill(linear) - $t = $ts0 + 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) - print ====== 0:$data00, 1:$data01, 2:$data02, 3:$data03, 4:$data04, 5:$data05, 6:$data06, 7:$data07, 8:$data08, 9:$data09 - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:01.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != 0 then - return -1 - endi - print $data03 - if $data03 != 0.00167 then - return -1 - endi - if $data04 != 0.001666667 then - return -1 - endi - if $data05 != 0 then - return -1 - endi - if $data06 != 0 then - return -1 - endi - if $data07 != NULL then - return -1 - endi - if $data08 != NULL then - return -1 - endi - if $data09 != NULL then - return -1 - endi - # columns contain NULL values - $t = $ts0 + 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $t fill(linear) - print ====== 0:$data00, 1:$data01, 2:$data02, 3:$data03, 4:$data04, 5:$data05, 6:$data06, 7:$data07, 8:$data08, 9:$data09 - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:01.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != NULL then - return -1 - endi - if $data03 != 0.00167 then - return -1 - endi - if $data04 != NULL then - return -1 - endi - if $data05 != 0 then - return -1 - endi - if $data06 != 0 then - return -1 - endi - if $data07 != NULL then - return -1 - endi - if $data08 != NULL then - return -1 - endi - if $data09 != NULL then - return -1 - endi - - print select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(linear) - - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(linear) - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:00.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != 0 then - return -1 - endi - if $data03 != 0.00000 then - return -1 - endi - if $data04 != 0.000000000 then - return -1 - endi - if $data05 != 0 then - return -1 - endi - if $data06 != 0 then - return -1 - endi - if $data07 != 1 then - return -1 - endi - if $data08 != binary0 then - return -1 - endi - if $data09 != nchar0 then - return -1 - endi - # columns contain NULL values - - print select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $ts0 fill(linear) - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $ts0 fill(linear) - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:00.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != NULL then - return -1 - endi - if $data03 != 0.00000 then - return -1 - endi - if $data04 != NULL then - return -1 - endi - if $data05 != 0 then - return -1 - endi - if $data06 != 0 then - return -1 - endi - if $data07 != 1 then - return -1 - endi - if $data08 != binary0 then - return -1 - endi - if $data09 != nchar0 then - return -1 - endi - - $t = $ts0 - 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) - if $rows != 0 then - return -1 - endi - - $t = $tsu + 1000 - print select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) - if $rows != 0 then - return -1 - endi +$t = $tsu + 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(prev) +if $rows != 0 then + return -1 +endi + +## fill(linear) +$t = $ts0 + 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) +print ====== 0:$data00, 1:$data01, 2:$data02, 3:$data03, 4:$data04, 5:$data05, 6:$data06, 7:$data07, 8:$data08, 9:$data09 +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:01.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != 0 then + return -1 +endi +print $data03 +if $data03 != 0.00167 then + return -1 +endi +if $data04 != 0.001666667 then + return -1 +endi +if $data05 != 0 then + return -1 +endi +if $data06 != 0 then + return -1 +endi +if $data07 != NULL then + return -1 +endi +if $data08 != NULL then + return -1 +endi +if $data09 != NULL then + return -1 +endi +# columns contain NULL values +$t = $ts0 + 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $t fill(linear) +print ====== 0:$data00, 1:$data01, 2:$data02, 3:$data03, 4:$data04, 5:$data05, 6:$data06, 7:$data07, 8:$data08, 9:$data09 +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:01.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != NULL then + return -1 +endi +if $data03 != 0.00167 then + return -1 +endi +if $data04 != NULL then + return -1 +endi +if $data05 != 0 then + return -1 +endi +if $data06 != 0 then + return -1 +endi +if $data07 != NULL then + return -1 +endi +if $data08 != NULL then + return -1 +endi +if $data09 != NULL then + return -1 +endi + +print select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(linear) + +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(linear) +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:00.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != 0 then + return -1 +endi +if $data03 != 0.00000 then + return -1 +endi +if $data04 != 0.000000000 then + return -1 +endi +if $data05 != 0 then + return -1 +endi +if $data06 != 0 then + return -1 +endi +if $data07 != 1 then + return -1 +endi +if $data08 != binary0 then + return -1 +endi +if $data09 != nchar0 then + return -1 +endi +# columns contain NULL values + +print select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $ts0 fill(linear) +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $ts0 fill(linear) +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:00.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != NULL then + return -1 +endi +if $data03 != 0.00000 then + return -1 +endi +if $data04 != NULL then + return -1 +endi +if $data05 != 0 then + return -1 +endi +if $data06 != 0 then + return -1 +endi +if $data07 != 1 then + return -1 +endi +if $data08 != binary0 then + return -1 +endi +if $data09 != nchar0 then + return -1 +endi + +$t = $ts0 - 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) +if $rows != 0 then + return -1 +endi + +$t = $tsu + 1000 +print select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(linear) +if $rows != 0 then + return -1 +endi + +## fill(value) +$t = $ts0 + 1000 +print 91 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(value, -1, -2) +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:01.000@ then + return -1 +endi +if $data01 != -2 then + return -1 +endi +if $data02 != -2 then + return -1 +endi +if $data03 != -2.00000 then + return -1 +endi +if $data04 != -2.000000000 then + return -1 +endi +if $data05 != -2 then + return -1 +endi +if $data06 != -2 then + return -1 +endi +if $data07 != 1 then + return -1 +endi +if $data08 != NULL then + return -1 +endi +if $data09 != NULL then + return -1 +endi + +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(value, -1, -2, -3) +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:00.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != 0 then + return -1 +endi +if $data03 != 0.00000 then + return -1 +endi +if $data04 != 0.000000000 then + return -1 +endi +if $data05 != 0 then + return -1 +endi +if $data06 != 0 then + return -1 +endi +if $data07 != 1 then + return -1 +endi +if $data08 != binary0 then + return -1 +endi +if $data09 != nchar0 then + return -1 +endi + +# table has NULL columns +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $ts0 fill(value, -1, -2, -3) +if $rows != 1 then + return -1 +endi +if $data00 != @18-09-17 09:00:00.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != NULL then + return -1 +endi +if $data03 != 0.00000 then + return -1 +endi +if $data04 != NULL then + return -1 +endi + +$t = $ts0 - 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(value, -1, -2) +if $rows != 0 then + return -1 +endi + +$t = $tsu + 1000 +sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(value, -1, -2) +if $rows != 0 then + return -1 +endi -## fill(value) - $t = $ts0 + 1000 - print 91 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(value, -1, -2) - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:01.000@ then - return -1 - endi - if $data01 != -2 then - return -1 - endi - if $data02 != -2 then - return -1 - endi - if $data03 != -2.00000 then - return -1 - endi - if $data04 != -2.000000000 then - return -1 - endi - if $data05 != -2 then - return -1 - endi - if $data06 != -2 then - return -1 - endi - if $data07 != 1 then - return -1 - endi - if $data08 != NULL then - return -1 - endi - if $data09 != NULL then - return -1 - endi - - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $ts0 fill(value, -1, -2, -3) - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:00.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != 0 then - return -1 - endi - if $data03 != 0.00000 then - return -1 - endi - if $data04 != 0.000000000 then - return -1 - endi - if $data05 != 0 then - return -1 - endi - if $data06 != 0 then - return -1 - endi - if $data07 != 1 then - return -1 - endi - if $data08 != binary0 then - return -1 - endi - if $data09 != nchar0 then - return -1 - endi - - # table has NULL columns - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from intp_tb3 where ts = $ts0 fill(value, -1, -2, -3) - if $rows != 1 then - return -1 - endi - if $data00 != @18-09-17 09:00:00.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != NULL then - return -1 - endi - if $data03 != 0.00000 then - return -1 - endi - if $data04 != NULL then - return -1 - endi - - $t = $ts0 - 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(value, -1, -2) - if $rows != 0 then - return -1 - endi - - $t = $tsu + 1000 - sql select interp(ts), interp(c1), interp(c2), interp(c3), interp(c4), interp(c5), interp(c6), interp(c7), interp(c8), interp(c9) from $tb where ts = $t fill(value, -1, -2) - if $rows != 0 then - return -1 - endi - -##### select interp from stable - ## interp(*) from stb - print select interp(*) from $stb where ts = $ts0 - sql select interp(*) from $stb where ts = $ts0 - if $rows != 1 then - return -1 - endi - $t = $ts0 + 1000 - print 92 - - sql select interp(*) from $stb where ts = $t - if $rows != 0 then - return -1 - endi - ## interp(*) from stb + group by - sql select interp(ts, c1, c2, c3, c4, c5, c7, c9) from $stb where ts = $ts0 group by tbname order by tbname asc - print ====== select interp(ts, c1, c2, c3, c4, c5, c7, c9) from $stb where ts = $ts0 group by tbname order by tbname asc - print ====== 0:$data00, 1:$data01, 2:$data02, 3:$data03, 4:$data04, 5:$data05, 6:$data06, 7:$data07, 8:$data08, 9:$data09 - print ====== 0:$data20, 1:$data21, 2:$data22, 3:$data23, 4:$data24, 5:$data25, 6:$data26, 7:$data27, 8:$data28, 9:$data29 - if $rows != $tbNum then - return -1 - endi - if $data00 != @18-09-17 09:00:00.000@ then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != 0 then - return -1 - endi - if $data04 != 0.000000000 then - return -1 - endi - if $data08 != intp_tb0 then - return -1 - endi - if $data22 != NULL then - return -1 - endi - if $data24 != NULL then - return -1 - endi - if $data28 != intp_tb2 then - return -1 - endi - - ## interp(*) from stb + group by + limit offset - sql select interp(*) from $stb where ts = $ts0 group by tbname limit 0 - if $rows != 0 then - return -1 - endi - sql select interp(*) from $stb where ts = $ts0 group by tbname limit 0 offset 1 - - ## interp(*) from stb + group by + fill(none) - $t = $ts0 + 1000 - sql select interp(*) from $stb where ts = $t fill(none) group by tbname - if $rows != 0 then - return -1 - endi - - sql select interp(*) from $stb where ts = $ts0 fill(none) group by tbname - if $rows != 4 then - return -1 - endi - if $data01 != 0 then - return -1 - endi - if $data02 != 0 then - return -1 - endi - if $data21 != 0 then - return -1 - endi - if $data22 != NULL then - return -1 - endi - if $data24 != NULL then - return -1 - endi - - ## interp(*) from stb + group by + fill(none) - $t = $ts0 + 1000 +### select interp from stable +## interp(*) from stb +print select interp(*) from $stb where ts = $ts0 +sql select interp(*) from $stb where ts = $ts0 +if $rows != 1 then + return -1 +endi +$t = $ts0 + 1000 +print 92 + +sql select interp(*) from $stb where ts = $t +if $rows != 0 then + return -1 +endi +## interp(*) from stb + group by +sql select interp(ts, c1, c2, c3, c4, c5, c7, c9) from $stb where ts = $ts0 group by tbname order by tbname asc +print ====== select interp(ts, c1, c2, c3, c4, c5, c7, c9) from $stb where ts = $ts0 group by tbname order by tbname asc +print ====== 0:$data00, 1:$data01, 2:$data02, 3:$data03, 4:$data04, 5:$data05, 6:$data06, 7:$data07, 8:$data08, 9:$data09 +print ====== 0:$data20, 1:$data21, 2:$data22, 3:$data23, 4:$data24, 5:$data25, 6:$data26, 7:$data27, 8:$data28, 9:$data29 +if $rows != $tbNum then + return -1 +endi +if $data00 != @18-09-17 09:00:00.000@ then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != 0 then + return -1 +endi +if $data04 != 0.000000000 then + return -1 +endi +if $data08 != intp_tb0 then + return -1 +endi +if $data22 != NULL then + return -1 +endi +if $data24 != NULL then + return -1 +endi +if $data28 != intp_tb2 then + return -1 +endi + +## interp(*) from stb + group by + limit offset +sql select interp(*) from $stb where ts = $ts0 group by tbname limit 0 +if $rows != 0 then + return -1 +endi +sql select interp(*) from $stb where ts = $ts0 group by tbname limit 0 offset 1 + +## interp(*) from stb + group by + fill(none) +$t = $ts0 + 1000 +sql select interp(*) from $stb where ts = $t fill(none) group by tbname +if $rows != 0 then + return -1 +endi + +sql select interp(*) from $stb where ts = $ts0 fill(none) group by tbname +if $rows != 4 then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data02 != 0 then + return -1 +endi +if $data21 != 0 then + return -1 +endi +if $data22 != NULL then + return -1 +endi +if $data24 != NULL then + return -1 +endi + +## interp(*) from stb + group by + fill(none) +$t = $ts0 + 1000 sql select interp(*) from $stb where ts = $t fill(NULL) group by tbname if $rows != $tbNum then return -1 @@ -846,12 +847,12 @@ if $data29 != NULL then endi sql_error select interp(ts,c1) from intp_tb0 where ts>'2018-11-25 19:19:00' and ts<'2018-11-25 19:19:12'; -sql select interp(ts,c1) from intp_tb0 where ts>'2018-11-25 19:19:00' and ts<'2018-11-25 19:19:12' interval(1s) fill(linear); +sql select interp(ts,c1) from intp_tb0 where ts>'2018-11-25 19:19:00' and ts<'2018-11-25 19:19:12' every(1s) fill(linear); if $rows != 0 then return -1 endi -sql select interp(c1) from intp_tb0 where ts>'2018-11-25 18:09:00' and ts<'2018-11-25 19:20:12' interval(18m); +sql select interp(c1) from intp_tb0 where ts>'2018-11-25 18:09:00' and ts<'2018-11-25 19:20:12' every(18m); if $rows != 1 then return -1 endi @@ -864,7 +865,7 @@ if $data01 != 3 then return -1 endi -sql select interp(c1,c3,c4,ts) from intp_tb0 where ts>'2018-11-25 18:09:00' and ts<'2018-11-25 19:20:12' interval(18m) fill(linear) +sql select interp(c1,c3,c4,ts) from intp_tb0 where ts>'2018-11-25 18:09:00' and ts<'2018-11-25 19:20:12' every(18m) fill(linear) if $rows != 5 then return -1 endi @@ -930,12 +931,258 @@ if $data44 != @18-11-25 19:06:00.000@ then endi +sql select interp(c1) from intp_stb0 where ts >= '2018-09-17 20:35:00.000' and ts <= '2018-09-17 20:42:00.000' every(1m) fill(linear); +if $rows != 8 then + return -1 +endi +if $data00 != @18-09-17 20:35:00.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data10 != @18-09-17 20:36:00.000@ then + return -1 +endi +if $data11 != NULL then + return -1 +endi +if $data20 != @18-09-17 20:37:00.000@ then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data30 != @18-09-17 20:38:00.000@ then + return -1 +endi +if $data31 != NULL then + return -1 +endi +if $data40 != @18-09-17 20:39:00.000@ then + return -1 +endi +if $data41 != NULL then + return -1 +endi +if $data50 != @18-09-17 20:40:00.000@ then + return -1 +endi +if $data51 != 0 then + return -1 +endi +if $data60 != @18-09-17 20:41:00.000@ then + return -1 +endi +if $data61 != NULL then + return -1 +endi +if $data70 != @18-09-17 20:42:00.000@ then + return -1 +endi +if $data71 != NULL then + return -1 +endi + + +sql select interp(c1) from intp_stb0 where ts >= '2018-09-17 20:35:00.000' and ts <= '2018-09-17 20:42:00.000' every(1m) fill(linear) order by ts desc; +if $rows != 8 then + return -1 +endi +if $data00 != @18-09-17 20:42:00.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data10 != @18-09-17 20:41:00.000@ then + return -1 +endi +if $data11 != NULL then + return -1 +endi +if $data20 != @18-09-17 20:40:00.000@ then + return -1 +endi +if $data21 != 0 then + return -1 +endi +if $data30 != @18-09-17 20:39:00.000@ then + return -1 +endi +if $data31 != NULL then + return -1 +endi +if $data40 != @18-09-17 20:38:00.000@ then + return -1 +endi +if $data41 != NULL then + return -1 +endi +if $data50 != @18-09-17 20:37:00.000@ then + return -1 +endi +if $data51 != NULL then + return -1 +endi +if $data60 != @18-09-17 20:36:00.000@ then + return -1 +endi +if $data61 != NULL then + return -1 +endi +if $data70 != @18-09-17 20:35:00.000@ then + return -1 +endi +if $data71 != NULL then + return -1 +endi + +sql select interp(c3) from intp_stb0 where ts >= '2018-09-17 20:35:00.000' and ts <= '2018-09-17 20:50:00.000' every(2m) fill(linear) order by ts; +if $rows != 9 then + return -1 +endi +if $data00 != @18-09-17 20:34:00.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data10 != @18-09-17 20:36:00.000@ then + return -1 +endi +if $data11 != NULL then + return -1 +endi +if $data20 != @18-09-17 20:38:00.000@ then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data30 != @18-09-17 20:40:00.000@ then + return -1 +endi +if $data31 != 0.00000 then + return -1 +endi +if $data40 != @18-09-17 20:42:00.000@ then + return -1 +endi +if $data41 != 0.20000 then + return -1 +endi +if $data50 != @18-09-17 20:44:00.000@ then + return -1 +endi +if $data51 != 0.40000 then + return -1 +endi +if $data60 != @18-09-17 20:46:00.000@ then + return -1 +endi +if $data61 != 0.60000 then + return -1 +endi +if $data70 != @18-09-17 20:48:00.000@ then + return -1 +endi +if $data71 != 0.80000 then + return -1 +endi +if $data80 != @18-09-17 20:50:00.000@ then + return -1 +endi +if $data81 != 1.00000 then + return -1 +endi + +sql select interp(c3) from intp_stb0 where ts >= '2018-09-17 20:35:00.000' and ts <= '2018-09-17 20:50:00.000' every(3m) fill(linear) order by ts; +if $rows != 6 then + return -1 +endi +if $data00 != @18-09-17 20:33:00.000@ then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data10 != @18-09-17 20:36:00.000@ then + return -1 +endi +if $data11 != NULL then + return -1 +endi +if $data20 != @18-09-17 20:39:00.000@ then + return -1 +endi +if $data21 != NULL then + return -1 +endi +if $data30 != @18-09-17 20:42:00.000@ then + return -1 +endi +if $data31 != 0.20000 then + return -1 +endi +if $data40 != @18-09-17 20:45:00.000@ then + return -1 +endi +if $data41 != 0.50000 then + return -1 +endi +if $data50 != @18-09-17 20:48:00.000@ then + return -1 +endi +if $data51 != 0.80000 then + return -1 +endi +sql select interp(c3) from intp_stb0 where ts >= '2018-09-17 20:35:00.000' and ts <= '2018-09-17 20:50:00.000' every(3m) fill(linear) order by ts desc; +if $rows != 6 then + return -1 +endi +if $data00 != @18-09-17 20:48:00.000@ then + return -1 +endi +if $data01 != 0.80000 then + return -1 +endi +if $data10 != @18-09-17 20:45:00.000@ then + return -1 +endi +if $data11 != 0.50000 then + return -1 +endi +if $data20 != @18-09-17 20:42:00.000@ then + return -1 +endi +if $data21 != 0.20000 then + return -1 +endi +if $data30 != @18-09-17 20:39:00.000@ then + return -1 +endi +if $data31 != NULL then + return -1 +endi +if $data40 != @18-09-17 20:36:00.000@ then + return -1 +endi +if $data41 != NULL then + return -1 +endi +if $data50 != @18-09-17 20:33:00.000@ then + return -1 +endi +if $data51 != NULL then + return -1 +endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' interval(1s) fill(linear); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1s) fill(linear); if $rows != 6 then return -1 endi @@ -976,7 +1223,7 @@ if $data51 != 9.87500 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' interval(1s) fill(value, 1); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1s) fill(value, 1); if $rows != 6 then return -1 endi @@ -1017,7 +1264,7 @@ if $data51 != 1.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' interval(1s) fill(NULL); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1s) fill(NULL); if $rows != 6 then return -1 endi @@ -1058,7 +1305,7 @@ if $data51 != NULL then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' interval(1s) fill(prev); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1s) fill(prev); if $rows != 6 then return -1 endi @@ -1099,7 +1346,7 @@ if $data51 != 9.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' interval(1s) fill(next); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:00' every(1s) fill(next); if $rows != 6 then return -1 endi @@ -1141,11 +1388,11 @@ if $data51 != 10.00000 then endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:56' interval(1s) fill(linear); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:56' every(1s) fill(linear); if $rows != 0 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:56' interval(1s) fill(prev); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:56' every(1s) fill(prev); if $rows != 2 then return -1 endi @@ -1162,7 +1409,7 @@ if $data11 != 3.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:56' interval(1s) fill(next); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:56' every(1s) fill(next); if $rows != 2 then return -1 endi @@ -1179,7 +1426,7 @@ if $data11 != NULL then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:57' interval(1s) fill(linear); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:57' every(1s) fill(linear); if $rows != 3 then return -1 endi @@ -1202,7 +1449,7 @@ if $data21 != 3.77273 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:57' interval(1s) fill(prev); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:57' every(1s) fill(prev); if $rows != 3 then return -1 endi @@ -1225,7 +1472,7 @@ if $data21 != 3.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:57' interval(1s) fill(next); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:19:57' every(1s) fill(next); if $rows != 3 then return -1 endi @@ -1248,7 +1495,7 @@ if $data21 != 4.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:03' interval(1s) fill(linear); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:03' every(1s) fill(linear); if $rows != 10 then return -1 endi @@ -1313,7 +1560,7 @@ if $data91 != NULL then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:03' interval(1s) fill(prev); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:03' every(1s) fill(prev); if $rows != 10 then return -1 endi @@ -1378,7 +1625,7 @@ if $data91 != 14.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:03' interval(1s) fill(next); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:03' every(1s) fill(next); if $rows != 10 then return -1 endi @@ -1443,7 +1690,7 @@ if $data91 != NULL then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:05' interval(1s) fill(linear); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:05' every(1s) fill(linear); if $rows != 12 then return -1 endi @@ -1496,7 +1743,7 @@ if $data71 != 15.29412 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:05' interval(1s) fill(prev); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:05' every(1s) fill(prev); if $rows != 12 then return -1 endi @@ -1561,7 +1808,7 @@ if $data91 != 14.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:05' interval(1s) fill(next); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:05' every(1s) fill(next); if $rows != 12 then return -1 endi @@ -1626,7 +1873,7 @@ if $data91 != 20.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:20:02' and ts<='2021-07-25 02:20:05' interval(1s) fill(value, 1); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:20:02' and ts<='2021-07-25 02:20:05' every(1s) fill(value, 1); if $rows != 4 then return -1 endi @@ -1655,7 +1902,7 @@ if $data31 != 20.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:20:02' and ts<='2021-07-25 02:20:05' interval(1s) fill(null); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:20:02' and ts<='2021-07-25 02:20:05' every(1s) fill(null); if $rows != 4 then return -1 endi @@ -1685,7 +1932,7 @@ if $data31 != 20.00000 then endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:25' interval(1s) fill(linear); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:25' every(1s) fill(linear); if $rows != 32 then return -1 endi @@ -1738,7 +1985,7 @@ if $data71 != 15.29412 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:25' interval(1s) fill(prev); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:25' every(1s) fill(prev); if $rows != 32 then return -1 endi @@ -1803,7 +2050,7 @@ if $data91 != 14.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:25' interval(1s) fill(next); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:20:25' every(1s) fill(next); if $rows != 32 then return -1 endi @@ -1869,7 +2116,7 @@ if $data91 != 20.00000 then endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:25:00' interval(1s) fill(linear); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:25:00' every(1s) fill(linear); if $rows != 307 then return -1 endi @@ -1922,7 +2169,7 @@ if $data71 != 15.29412 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:25:00' interval(1s) fill(prev); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:25:00' every(1s) fill(prev); if $rows != 307 then return -1 endi @@ -1987,7 +2234,7 @@ if $data91 != 14.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:25:00' interval(1s) fill(next); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 02:25:00' every(1s) fill(next); if $rows != 307 then return -1 endi @@ -2052,7 +2299,7 @@ if $data91 != 20.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 03:25:00' interval(1s) fill(linear); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 03:25:00' every(1s) fill(linear); if $rows != 3907 then return -1 endi @@ -2106,7 +2353,7 @@ if $data71 != 15.29412 then endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 03:25:00' interval(1s) fill(prev); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 03:25:00' every(1s) fill(prev); if $rows != 3907 then return -1 endi @@ -2171,7 +2418,7 @@ if $data91 != 14.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 03:25:00' interval(1s) fill(next); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<='2021-07-25 03:25:00' every(1s) fill(next); if $rows != 3907 then return -1 endi @@ -2236,7 +2483,7 @@ if $data91 != 20.00000 then return -1 endi -sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:07' interval(1s); +sql select interp(pav) from ap1 where ts> '2021-07-25 02:19:54' and ts<'2021-07-25 02:20:07' every(1s); if $rows != 1 then return -1 endi diff --git a/tests/script/general/parser/like.sim b/tests/script/general/parser/like.sim new file mode 100644 index 0000000000000000000000000000000000000000..fce996ebee37d887e2f86fc2a8566d844e8d04f5 --- /dev/null +++ b/tests/script/general/parser/like.sim @@ -0,0 +1,61 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c walLevel -v 1 +system sh/cfg.sh -n dnode1 -c maxtablesPerVnode -v 4 +system sh/exec.sh -n dnode1 -s start + +sleep 10 +sql connect +print ======================== dnode1 start + + +$db = testdb +sql drop database if exists $db +sql create database $db cachelast 2 +sql use $db + +$table1 = table_name +$table2 = tablexname + +sql create table $table1 (ts timestamp, b binary(20)) +sql create table $table2 (ts timestamp, b binary(20)) + +sql insert into $table1 values(now, "table_name") +sql insert into $table1 values(now-1m, "tablexname") +sql insert into $table1 values(now-2m, "tablexxx") +sql insert into $table1 values(now-2m, "table") + +sql select b from $table1 +if $rows != 4 then + return -1 +endi + +sql select b from $table1 where b like 'table_name' +if $rows != 2 then + return -1 +endi + + +sql select b from $table1 where b like 'table\_name' +if $rows != 1 then + return -1 +endi + +sql show tables; +if $rows != 2 then + return -1 +endi + +sql show tables like 'table_name' +if $rows != 2 then + return -1 +endi + +sql show tables like 'table\_name' +if $rows != 1 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT + + diff --git a/tests/script/general/parser/limit.sim b/tests/script/general/parser/limit.sim index 23b85095c54c9bb439c0766e379b8950778f8d90..3af2cb301854b27bc1b9c33bf8b06cbd17e87fd3 100644 --- a/tests/script/general/parser/limit.sim +++ b/tests/script/general/parser/limit.sim @@ -75,4 +75,9 @@ sleep 100 run general/parser/limit_tb.sim run general/parser/limit_stb.sim +print ========> TD-6017 +sql use $db +sql select * from (select ts, top(c1, 5) from $tb where ts >= $ts0 order by ts desc limit 3 offset 1) +sql select * from (select ts, top(c1, 5) from $stb where ts >= $ts0 order by ts desc limit 3 offset 1) + system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/general/parser/limit_tb.sim b/tests/script/general/parser/limit_tb.sim index 0c987d88c99c898ef57e19c2f9cabee4b712e12d..4a93797d40fb65a7df9ad8d18c60292bed83dfe4 100644 --- a/tests/script/general/parser/limit_tb.sim +++ b/tests/script/general/parser/limit_tb.sim @@ -355,6 +355,10 @@ sql select top(c1, 1) from $tb where ts >= $ts0 and ts <= $tsu limit 5 offset 1 if $rows != 0 then return -1 endi + +print ========> TD-6017 +sql select * from (select ts, top(c1, 5) from $tb where ts >= $ts0 and ts <= $tsu order by ts desc limit 3 offset 1) + sql select top(c1, 5) from $tb where ts >= $ts0 and ts <= $tsu order by ts desc limit 3 offset 1 print select top(c1, 5) from $tb where ts >= $ts0 and ts <= $tsu order by ts desc limit 3 offset 1 print $data00 $data01 diff --git a/tests/script/general/parser/regex.sim b/tests/script/general/parser/regex.sim new file mode 100644 index 0000000000000000000000000000000000000000..5351d914f34004b5bf198fb9e10792306f8ac32b --- /dev/null +++ b/tests/script/general/parser/regex.sim @@ -0,0 +1,62 @@ +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 + +$db = testdb +sql drop database if exists $db +sql create database $db +sql use $db + +print ======================== regular expression match test +$st_name = st +$ct1_name = ct1 +$ct2_name = ct2 + +sql create table $st_name (ts timestamp, c1b binary(20)) tags(t1b binary(20)); +sql create table $ct1_name using $st_name tags('taosdata1') +sql create table $ct2_name using $st_name tags('taosdata2') +sql create table not_match using $st_name tags('NOTMATCH') + +sql select tbname from $st_name where tbname match '.*' +if $rows != 3 then + return -1 +endi + + +sql select tbname from $st_name where tbname match '^ct[[:digit:]]' + +if $rows != 2 then + return -1 +endi + +sql select tbname from $st_name where tbname match '.*' +if $rows !=3 then + return -1 +endi + +sql select tbname from $st_name where t1b match '[[:lower:]]+' +if $rows != 2 then + return -1 +endi + +sql insert into $ct1_name values(now, 'this is engine') +sql insert into $ct2_name values(now, 'this is app egnine') + +sql select c1b from $st_name where c1b match 'engine' +if $data00 != @this is engine@ then + return -1 +endi + +if $rows != 1 then + return -1 +endi + + +system sh/exec.sh -n dnode1 -s stop -x SIGINT + + diff --git a/tests/script/general/parser/tbnameIn_query.sim b/tests/script/general/parser/tbnameIn_query.sim index 65bb89d549c32c8ae6d3054898ce26caf5482832..db27886bbfde744910068b702199e2079d24c7d2 100644 --- a/tests/script/general/parser/tbnameIn_query.sim +++ b/tests/script/general/parser/tbnameIn_query.sim @@ -101,6 +101,30 @@ if $data11 != 2 then return -1 endi +## tbname in can accpet Upper case table name +sql select count(*) from $stb where tbname in ('ti_tb0', 'TI_tb1', 'TI_TB2') group by t1 order by t1 +if $rows != 3 then + return -1 +endi +if $data00 != 10 then + return -1 +endi +if $data01 != 0 then + return -1 +endi +if $data10 != 10 then + return -1 +endi +if $data11 != 1 then + return -1 +endi +if $data20 != 10 then + return -1 +endi +if $data21 != 2 then + return -1 +endi + # multiple tbname in is not allowed NOW sql_error select count(*) from $stb where tbname in ('ti_tb1', 'ti_tb300') and tbname in ('ti_tb5', 'ti_tb1000') group by t1 order by t1 asc #if $rows != 4 then diff --git a/tests/script/http/httpTest.c b/tests/script/http/httpTest.c new file mode 100644 index 0000000000000000000000000000000000000000..36ce6b95ba7836893aeec0831d60a289ff658f66 --- /dev/null +++ b/tests/script/http/httpTest.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXLINE 1024 + +typedef struct { + pthread_t pid; + int threadId; + int rows; + int tables; +} ThreadObj; + +void post(char *ip,int port,char *page,char *msg) { + int sockfd,n; + char recvline[MAXLINE]; + struct sockaddr_in servaddr; + char content[4096]; + char content_page[50]; + sprintf(content_page,"POST /%s HTTP/1.1\r\n",page); + char content_host[50]; + sprintf(content_host,"HOST: %s:%d\r\n",ip,port); + char content_type[] = "Content-Type: text/plain\r\n"; + char Auth[] = "Authorization: Basic cm9vdDp0YW9zZGF0YQ==\r\n"; + char content_len[50]; + sprintf(content_len,"Content-Length: %ld\r\n\r\n",strlen(msg)); + sprintf(content,"%s%s%s%s%s%s",content_page,content_host,content_type,Auth,content_len,msg); + if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { + printf("socket error\n"); + } + bzero(&servaddr,sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + if(inet_pton(AF_INET,ip,&servaddr.sin_addr) <= 0) { + printf("inet_pton error\n"); + } + if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0) { + printf("connect error\n"); + } + write(sockfd,content,strlen(content)); + printf("%s\n", content); + while((n = read(sockfd,recvline,MAXLINE)) > 0) { + recvline[n] = 0; + if(fputs(recvline,stdout) == EOF) { + printf("fputs error\n"); + } + } + if(n < 0) { + printf("read error\n"); + } +} + +void singleThread() { + char ip[] = "127.0.0.1"; + int port = 6041; + char page[] = "rest/sql"; + char page1[] = "rest/sql/db1"; + char page2[] = "rest/sql/db2"; + char nonexit[] = "rest/sql/xxdb"; + + post(ip,port,page,"drop database if exists db1"); + post(ip,port,page,"create database if not exists db1"); + post(ip,port,page,"drop database if exists db2"); + post(ip,port,page,"create database if not exists db2"); + post(ip,port,page1,"create table t11 (ts timestamp, c1 int)"); + post(ip,port,page2,"create table t21 (ts timestamp, c1 int)"); + post(ip,port,page1,"insert into t11 values (now, 1)"); + post(ip,port,page2,"insert into t21 values (now, 2)"); + post(ip,port,nonexit,"create database if not exists db3"); +} + +void execute(void *params) { + char ip[] = "127.0.0.1"; + int port = 6041; + char page[] = "rest/sql"; + char *unique = calloc(1, 1024); + char *sql = calloc(1, 1024); + ThreadObj *pThread = (ThreadObj *)params; + printf("Thread %d started\n", pThread->threadId); + sprintf(unique, "rest/sql/db%d",pThread->threadId); + sprintf(sql, "drop database if exists db%d", pThread->threadId); + post(ip,port,page, sql); + sprintf(sql, "create database if not exists db%d", pThread->threadId); + post(ip,port,page, sql); + for (int i = 0; i < pThread->tables; i++) { + sprintf(sql, "create table t%d (ts timestamp, c1 int)", i); + post(ip,port,unique, sql); + } + for (int i = 0; i < pThread->rows; i++) { + sprintf(sql, "insert into t%d values (now + %ds, %d)", pThread->threadId, i, pThread->threadId); + post(ip,port,unique, sql); + } + free(unique); + free(sql); + return; +} + +void multiThread() { + int numOfThreads = 100; + int numOfTables = 100; + int numOfRows = 1; + ThreadObj *threads = calloc((size_t)numOfThreads, sizeof(ThreadObj)); + for (int i = 0; i < numOfThreads; i++) { + ThreadObj *pthread = threads + i; + pthread_attr_t thattr; + pthread->threadId = i + 1; + pthread->rows = numOfRows; + pthread->tables = numOfTables; + pthread_attr_init(&thattr); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); + pthread_create(&pthread->pid, &thattr, (void *(*)(void *))execute, pthread); + } + for (int i = 0; i < numOfThreads; i++) { + pthread_join(threads[i].pid, NULL); + } + free(threads); +} + +int main() { + singleThread(); + multiThread(); + exit(0); +} \ No newline at end of file diff --git a/tests/script/http/httpTestSqlUtc.c b/tests/script/http/httpTestSqlUtc.c new file mode 100644 index 0000000000000000000000000000000000000000..643c884a1a64d6eaaeb8984cd80d985408edf0e6 --- /dev/null +++ b/tests/script/http/httpTestSqlUtc.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXLINE 1024 + +typedef struct { + pthread_t pid; + int threadId; + int rows; + int tables; +} ThreadObj; + +void post(char *ip,int port,char *page,char *msg) { + int sockfd,n; + char recvline[MAXLINE]; + struct sockaddr_in servaddr; + char content[4096]; + char content_page[50]; + sprintf(content_page,"POST /%s HTTP/1.1\r\n",page); + char content_host[50]; + sprintf(content_host,"HOST: %s:%d\r\n",ip,port); + char content_type[] = "Content-Type: text/plain\r\n"; + char Auth[] = "Authorization: Basic cm9vdDp0YW9zZGF0YQ==\r\n"; + char content_len[50]; + sprintf(content_len,"Content-Length: %ld\r\n\r\n",strlen(msg)); + sprintf(content,"%s%s%s%s%s%s",content_page,content_host,content_type,Auth,content_len,msg); + if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { + printf("socket error\n"); + } + bzero(&servaddr,sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + if(inet_pton(AF_INET,ip,&servaddr.sin_addr) <= 0) { + printf("inet_pton error\n"); + } + if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0) { + printf("connect error\n"); + } + write(sockfd,content,strlen(content)); + printf("%s\n", content); + while((n = read(sockfd,recvline,MAXLINE)) > 0) { + recvline[n] = 0; + if(fputs(recvline,stdout) == EOF) { + printf("fputs error\n"); + } + } + if(n < 0) { + printf("read error\n"); + } +} + +void singleThread() { + char ip[] = "127.0.0.1"; + int port = 6041; + char page[] = "rest/sqlutc"; + char page1[] = "rest/sqlutc/db1"; + char page2[] = "rest/sqlutc/db2"; + char nonexit[] = "rest/sqlutc/xxdb"; + + post(ip,port,page,"drop database if exists db1"); + post(ip,port,page,"create database if not exists db1"); + post(ip,port,page,"drop database if exists db2"); + post(ip,port,page,"create database if not exists db2"); + post(ip,port,page1,"create table t11 (ts timestamp, c1 int)"); + post(ip,port,page2,"create table t21 (ts timestamp, c1 int)"); + post(ip,port,page1,"insert into t11 values (now, 1)"); + post(ip,port,page2,"insert into t21 values (now, 2)"); + post(ip,port,nonexit,"create database if not exists db3"); +} + +void execute(void *params) { + char ip[] = "127.0.0.1"; + int port = 6041; + char page[] = "rest/sqlutc"; + char *unique = calloc(1, 1024); + char *sql = calloc(1, 1024); + ThreadObj *pThread = (ThreadObj *)params; + printf("Thread %d started\n", pThread->threadId); + sprintf(unique, "rest/sqlutc/db%d",pThread->threadId); + sprintf(sql, "drop database if exists db%d", pThread->threadId); + post(ip,port,page, sql); + sprintf(sql, "create database if not exists db%d", pThread->threadId); + post(ip,port,page, sql); + for (int i = 0; i < pThread->tables; i++) { + sprintf(sql, "create table t%d (ts timestamp, c1 int)", i); + post(ip,port,unique, sql); + } + for (int i = 0; i < pThread->rows; i++) { + sprintf(sql, "insert into t%d values (now + %ds, %d)", pThread->threadId, i, pThread->threadId); + post(ip,port,unique, sql); + } + free(unique); + free(sql); + return; +} + +void multiThread() { + int numOfThreads = 100; + int numOfTables = 100; + int numOfRows = 1; + ThreadObj *threads = calloc((size_t)numOfThreads, sizeof(ThreadObj)); + for (int i = 0; i < numOfThreads; i++) { + ThreadObj *pthread = threads + i; + pthread_attr_t thattr; + pthread->threadId = i + 1; + pthread->rows = numOfRows; + pthread->tables = numOfTables; + pthread_attr_init(&thattr); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); + pthread_create(&pthread->pid, &thattr, (void *(*)(void *))execute, pthread); + } + for (int i = 0; i < numOfThreads; i++) { + pthread_join(threads[i].pid, NULL); + } + free(threads); +} + +int main() { + singleThread(); + multiThread(); + exit(0); +} \ No newline at end of file diff --git a/tests/script/http/httpTestSqlt.c b/tests/script/http/httpTestSqlt.c new file mode 100644 index 0000000000000000000000000000000000000000..2eaaee0f992d802d57b4fc4d684da4622ea3b763 --- /dev/null +++ b/tests/script/http/httpTestSqlt.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXLINE 1024 + +typedef struct { + pthread_t pid; + int threadId; + int rows; + int tables; +} ThreadObj; + +void post(char *ip,int port,char *page,char *msg) { + int sockfd,n; + char recvline[MAXLINE]; + struct sockaddr_in servaddr; + char content[4096]; + char content_page[50]; + sprintf(content_page,"POST /%s HTTP/1.1\r\n",page); + char content_host[50]; + sprintf(content_host,"HOST: %s:%d\r\n",ip,port); + char content_type[] = "Content-Type: text/plain\r\n"; + char Auth[] = "Authorization: Basic cm9vdDp0YW9zZGF0YQ==\r\n"; + char content_len[50]; + sprintf(content_len,"Content-Length: %ld\r\n\r\n",strlen(msg)); + sprintf(content,"%s%s%s%s%s%s",content_page,content_host,content_type,Auth,content_len,msg); + if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { + printf("socket error\n"); + } + bzero(&servaddr,sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + if(inet_pton(AF_INET,ip,&servaddr.sin_addr) <= 0) { + printf("inet_pton error\n"); + } + if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0) { + printf("connect error\n"); + } + write(sockfd,content,strlen(content)); + printf("%s\n", content); + while((n = read(sockfd,recvline,MAXLINE)) > 0) { + recvline[n] = 0; + if(fputs(recvline,stdout) == EOF) { + printf("fputs error\n"); + } + } + if(n < 0) { + printf("read error\n"); + } +} + +void singleThread() { + char ip[] = "127.0.0.1"; + int port = 6041; + char page[] = "rest/sqlt"; + char page1[] = "rest/sqlt/db1"; + char page2[] = "rest/sqlt/db2"; + char nonexit[] = "rest/sqlt/xxdb"; + + post(ip,port,page,"drop database if exists db1"); + post(ip,port,page,"create database if not exists db1"); + post(ip,port,page,"drop database if exists db2"); + post(ip,port,page,"create database if not exists db2"); + post(ip,port,page1,"create table t11 (ts timestamp, c1 int)"); + post(ip,port,page2,"create table t21 (ts timestamp, c1 int)"); + post(ip,port,page1,"insert into t11 values (now, 1)"); + post(ip,port,page2,"insert into t21 values (now, 2)"); + post(ip,port,nonexit,"create database if not exists db3"); +} + +void execute(void *params) { + char ip[] = "127.0.0.1"; + int port = 6041; + char page[] = "rest/sqlt"; + char *unique = calloc(1, 1024); + char *sql = calloc(1, 1024); + ThreadObj *pThread = (ThreadObj *)params; + printf("Thread %d started\n", pThread->threadId); + sprintf(unique, "rest/sqlt/db%d",pThread->threadId); + sprintf(sql, "drop database if exists db%d", pThread->threadId); + post(ip,port,page, sql); + sprintf(sql, "create database if not exists db%d", pThread->threadId); + post(ip,port,page, sql); + for (int i = 0; i < pThread->tables; i++) { + sprintf(sql, "create table t%d (ts timestamp, c1 int)", i); + post(ip,port,unique, sql); + } + for (int i = 0; i < pThread->rows; i++) { + sprintf(sql, "insert into t%d values (now + %ds, %d)", pThread->threadId, i, pThread->threadId); + post(ip,port,unique, sql); + } + free(unique); + free(sql); + return; +} + +void multiThread() { + int numOfThreads = 100; + int numOfTables = 100; + int numOfRows = 1; + ThreadObj *threads = calloc((size_t)numOfThreads, sizeof(ThreadObj)); + for (int i = 0; i < numOfThreads; i++) { + ThreadObj *pthread = threads + i; + pthread_attr_t thattr; + pthread->threadId = i + 1; + pthread->rows = numOfRows; + pthread->tables = numOfTables; + pthread_attr_init(&thattr); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); + pthread_create(&pthread->pid, &thattr, (void *(*)(void *))execute, pthread); + } + for (int i = 0; i < numOfThreads; i++) { + pthread_join(threads[i].pid, NULL); + } + free(threads); +} + +int main() { + singleThread(); + multiThread(); + exit(0); +} \ No newline at end of file diff --git a/tests/script/http/makefile b/tests/script/http/makefile new file mode 100644 index 0000000000000000000000000000000000000000..50886cf6b1c5f445263f05434839537ca8a5794e --- /dev/null +++ b/tests/script/http/makefile @@ -0,0 +1,9 @@ +all: + gcc -g httpTest.c -o httpTest -lpthread + gcc -g httpTestSqlt.c -o httpTestSqlt -lpthread + gcc -g httpTestSqlUtc.c -o httpTestSqlUtc -lpthread + +clean: + rm httpTest + rm httpTestSqlt + rm httpTestSqlUtc \ No newline at end of file diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index b087c734f349d76d1545c954f73ebafde0a5f227..4dff6393798fb0c103048e18ab23b4f34cbff048 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -90,6 +90,14 @@ cd ../../../debug; make ./test.sh -f general/parser/function.sim ./test.sh -f unique/cluster/vgroup100.sim +./test.sh -f unique/http/admin.sim +./test.sh -f unique/http/opentsdb.sim + +./test.sh -f unique/import/replica2.sim +./test.sh -f unique/import/replica3.sim + +./test.sh -f general/alter/cached_schema_after_alter.sim + #======================b1-end=============== #======================b2-start===============