diff --git a/.gitignore b/.gitignore index a69d2e44bd7eadf27d721ccf13c47ea91f6164ba..a6e222d2e9fba615319e7b03825e16c381313a13 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,4 @@ tools/COPYING tools/BUGS tools/taos-tools tools/taosws-rs +tags diff --git a/CMakeLists.txt b/CMakeLists.txt index 566d4ad29d7dff9c43ab61cac03da9a4dfdef63a..fb2b306f65467361dd5612f5bf1e6629a7a0c306 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ if (NOT DEFINED TD_SOURCE_DIR) set( TD_SOURCE_DIR ${PROJECT_SOURCE_DIR} ) endif() +SET(TD_COMMUNITY_DIR ${PROJECT_SOURCE_DIR}) + set(TD_SUPPORT_DIR "${TD_SOURCE_DIR}/cmake") set(TD_CONTRIB_DIR "${TD_SOURCE_DIR}/contrib") diff --git a/CODE_OF_CONDUCT-CN.md b/CODE_OF_CONDUCT-CN.md new file mode 100644 index 0000000000000000000000000000000000000000..cd14ea9c1c5c51aeaa93f7e6eccd4108a0ff9ec4 --- /dev/null +++ b/CODE_OF_CONDUCT-CN.md @@ -0,0 +1,47 @@ +# 贡献者契约行为准则 + +[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](code_of_conduct.md) + +## 我们的承诺 + +为了营造一个开放和热情的环境,作为贡献者和维护者,我们承诺让每个人参与我们的项目和社区成为一种无骚扰的体验,无论年龄、体型、残疾、种族、性别特征、性别认同和表达、经验水平、教育、社会经济地位、国籍、个人外表、种族、宗教或性认同和取向如何。 + +## 我们的标准 + +有助于创造积极环境的行为示例包括: + +- 使用热情和包容的语言 +- 尊重不同的观点和经历 +- 优雅地接受建设性的批评 +- 专注于对社区最有利的事情 +- 对其他社区成员表示同情 + +参与者不可接受的行为示例包括: + +- 使用性感的语言或图像以及不受欢迎的性关注或进步 +- 拖钓、侮辱/贬损评论以及人身或政治攻击 +- 公共或私人骚扰 +- 未经明确许可发布他人的私人信息,例如物理地址或电子地址 +- 在专业环境中可能被合理认为不适当的其他行为 + +## 我们的责任 + +项目维护人员负责阐明可接受行为的标准,并期望针对任何不可接受行为的情况采取适当和公平的纠正措施。 + +项目维护者有权利和责任删除、编辑或拒绝评论、提交、代码、wiki 编辑、问题和其他不符合本行为准则的贡献,或暂时或永久禁止任何贡献者从事他们认为不适当、威胁、冒犯或有害的其他行为。 + +## 范围 + +本行为准则适用于所有项目空间,也适用于个人在公共场所代表项目或其社区时。 代表项目或社区的示例包括使用官方项目电子邮件地址、通过官方社交媒体帐户发布信息或在在线或离线活动中担任指定代表。 项目的表示可以由项目维护者进一步定义和澄清。 + +## 执法 + +可以通过 support@taosdata.com 联系项目团队来报告辱骂、骚扰或其他不可接受的行为。 所有投诉都将被审查和调查,并将产生被认为必要且适合具体情况的回应。 项目团队有义务对事件的报告者保密。 具体执行政策的更多细节可能会单独发布。 + +不善意遵守或执行行为准则的项目维护者可能会面临由项目领导的其他成员确定的临时或永久影响。 + +## 来源 + +本行为准则改编自贡献者公约 1.4 版,可在 https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 获取 + +有关此行为准则的常见问题的答案,请参阅 https://www.contributor-covenant.org/faq \ No newline at end of file diff --git a/Jenkinsfile2 b/Jenkinsfile2 index 5a0e7972c6081a3ff1c5e01a932c24709bc153a9..55bd5466ed4abe40cfaedc634b75a59b43668759 100644 --- a/Jenkinsfile2 +++ b/Jenkinsfile2 @@ -40,7 +40,7 @@ def check_docs() { sh ''' cd ${WKC} git reset --hard - git clean -fxd + git clean -f rm -rf examples/rust/ git remote prune origin git fetch @@ -86,7 +86,7 @@ def pre_test(){ git fetch cd ${WKC} git reset --hard - git clean -fxd + git clean -f rm -rf examples/rust/ git remote prune origin git fetch @@ -173,7 +173,7 @@ def pre_test_build_mac() { ''' sh ''' cd ${WK}/debug - cmake .. -DBUILD_TEST=true -DBUILD_HTTPS=false + cmake .. -DBUILD_TEST=true -DBUILD_HTTPS=false -DCMAKE_BUILD_TYPE=Release make -j10 ctest -j10 || exit 7 ''' @@ -201,7 +201,7 @@ def pre_test_win(){ ''' bat ''' cd %WIN_COMMUNITY_ROOT% - git clean -fxd + git clean -f git reset --hard git remote prune origin git fetch @@ -313,7 +313,8 @@ def pre_test_build_win() { bat ''' cd %WIN_CONNECTOR_ROOT% python.exe -m pip install --upgrade pip - python -m pip install . + python -m pip uninstall taospy -y + python -m pip install taospy==2.7.6 xcopy /e/y/i/f %WIN_INTERNAL_ROOT%\\debug\\build\\lib\\taos.dll C:\\Windows\\System32 ''' return 1 @@ -331,8 +332,6 @@ def run_win_test() { bat ''' echo "windows test ..." cd %WIN_CONNECTOR_ROOT% - python.exe -m pip install --upgrade pip - python -m pip install . xcopy /e/y/i/f %WIN_INTERNAL_ROOT%\\debug\\build\\lib\\taos.dll C:\\Windows\\System32 ls -l C:\\Windows\\System32\\taos.dll time /t @@ -387,7 +386,7 @@ pipeline { } steps { catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { - timeout(time: 75, unit: 'MINUTES'){ + timeout(time: 126, unit: 'MINUTES'){ pre_test_win() pre_test_build_win() run_win_ctest() @@ -423,7 +422,7 @@ pipeline { echo "${WKDIR}/restore.sh -p ${BRANCH_NAME} -n ${BUILD_ID} -c {container name}" } catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { - timeout(time: 120, unit: 'MINUTES'){ + timeout(time: 130, unit: 'MINUTES'){ pre_test() script { sh ''' @@ -461,7 +460,7 @@ pipeline { cd ${WKC}/tests/parallel_test export DEFAULT_RETRY_TIME=2 date - ''' + timeout_cmd + ''' time ./run.sh -e -m /home/m.json -t cases.task -b ${BRANCH_NAME}_${BUILD_ID} -l ${WKDIR}/log -o 480 ''' + extra_param + ''' + ''' + timeout_cmd + ''' time ./run.sh -e -m /home/m.json -t cases.task -b ${BRANCH_NAME}_${BUILD_ID} -l ${WKDIR}/log -o 600 ''' + extra_param + ''' ''' } } diff --git a/README-CN.md b/README-CN.md index b5a2564f9101593335933b8ab2bdffd88e67014d..a6dfefc47ac98db6d222021923849be6ac2a8549 100644 --- a/README-CN.md +++ b/README-CN.md @@ -52,7 +52,7 @@ TDengine 还提供一组辅助工具软件 taosTools,目前它包含 taosBench ### Ubuntu 18.04 及以上版本 & Debian: ```bash -sudo apt-get install -y gcc cmake build-essential git libssl-dev +sudo apt-get install -y gcc cmake build-essential git libssl-dev libgflags2.2 libgflags-dev ``` #### 为 taos-tools 安装编译需要的软件 @@ -104,6 +104,16 @@ sudo yum install -y zlib-devel zlib-static xz-devel snappy-devel jansson jansson sudo yum config-manager --set-enabled Powertools ``` +#### CentOS + devtoolset + +除上述编译依赖包,需要执行以下命令: + +``` +sudo yum install centos-release-scl +sudo yum install devtoolset-9 devtoolset-9-libatomic-devel +scl enable devtoolset-9 -- bash +``` + ### macOS ``` @@ -342,4 +352,4 @@ TDengine 提供了丰富的应用程序开发接口,其中包括 C/C++、Java # 加入技术交流群 -TDengine 官方社群「物联网大数据群」对外开放,欢迎您加入讨论。搜索微信号 "tdengine",加小 T 为好友,即可入群。 +TDengine 官方社群「物联网大数据群」对外开放,欢迎您加入讨论。搜索微信号 "tdengine1",加小 T 为好友,即可入群。 diff --git a/README.md b/README.md index 3f7208dfb96d857c22f3b7fa83df6d25b4c46246..a088404c85c414e46a7b9a056c3d89aaa65e87a8 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ To build TDengine, use [CMake](https://cmake.org/) 3.0.2 or higher versions in t ### Ubuntu 18.04 and above or Debian ```bash -sudo apt-get install -y gcc cmake build-essential git libssl-dev +sudo apt-get install -y gcc cmake build-essential git libssl-dev libgflags2.2 libgflags-dev ``` #### Install build dependencies for taosTools @@ -111,6 +111,16 @@ If the PowerTools installation fails, you can try to use: sudo yum config-manager --set-enabled powertools ``` +#### For CentOS + devtoolset + +Besides above dependencies, please run following commands: + +``` +sudo yum install centos-release-scl +sudo yum install devtoolset-9 devtoolset-9-libatomic-devel +scl enable devtoolset-9 -- bash +``` + ### macOS ``` @@ -355,6 +365,6 @@ Please follow the [contribution guidelines](CONTRIBUTING.md) to contribute to th For more information about TDengine, you can follow us on social media and join our Discord server: - [Discord](https://discord.com/invite/VZdSuUg4pS) -- [Twitter](https://twitter.com/TaosData) +- [Twitter](https://twitter.com/TDengineDB) - [LinkedIn](https://www.linkedin.com/company/tdengine/) -- [YouTube](https://www.youtube.com/channel/UCmp-1U6GS_3V3hjir6Uq5DQ) +- [YouTube](https://www.youtube.com/@tdengine) diff --git a/cmake/cmake.define b/cmake/cmake.define index 1b9a06d9e4abe516c68b47e7d7dff20538f2fc13..8484355a910103b6b44c2c2bb4b3d0e8180919a9 100644 --- a/cmake/cmake.define +++ b/cmake/cmake.define @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.0) set(CMAKE_VERBOSE_MAKEFILE OFF) +set(TD_BUILD_TAOSA_INTERNAL FALSE) #set output directory SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/build/lib) @@ -118,9 +119,12 @@ ELSE () SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=shift-base -fno-sanitize=alignment -g3 -Wformat=0") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -fsanitize=address -fsanitize=undefined -fsanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=shift-base -fno-sanitize=alignment -g3 -Wformat=0") MESSAGE(STATUS "Compile with Address Sanitizer!") + ELSEIF (${BUILD_RELEASE}) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -O3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-reserved-user-defined-literal -Wno-literal-suffix -Werror=return-type -fPIC -O3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k") ELSE () SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wno-reserved-user-defined-literal -Wno-literal-suffix -Werror=return-type -fPIC -gdwarf-2 -g3 -Wformat=2 -Wno-format-nonliteral -Wno-format-truncation -Wno-format-y2k") ENDIF () # disable all assert diff --git a/cmake/cmake.install b/cmake/cmake.install index fd1e080ddab1478f73689e7cced405ae8404fbc2..67634625ce53c6ea48dc03746a39fdb03975c2af 100644 --- a/cmake/cmake.install +++ b/cmake/cmake.install @@ -21,7 +21,7 @@ IF (TD_LINUX) ELSEIF (TD_WINDOWS) SET(TD_MAKE_INSTALL_SH "${TD_SOURCE_DIR}/packaging/tools/make_install.bat") INSTALL(CODE "MESSAGE(\"make install script: ${TD_MAKE_INSTALL_SH}\")") - INSTALL(CODE "execute_process(COMMAND ${TD_MAKE_INSTALL_SH} :needAdmin ${TD_SOURCE_DIR} ${PROJECT_BINARY_DIR} Windows ${TD_VER_NUMBER})") + INSTALL(CODE "execute_process(COMMAND ${TD_MAKE_INSTALL_SH} :needAdmin ${TD_SOURCE_DIR} ${PROJECT_BINARY_DIR} Windows ${TD_VER_NUMBER} ${TD_BUILD_TAOSA_INTERNAL})") ELSEIF (TD_DARWIN) SET(TD_MAKE_INSTALL_SH "${TD_SOURCE_DIR}/packaging/tools/make_install.sh") INSTALL(CODE "MESSAGE(\"make install script: ${TD_MAKE_INSTALL_SH}\")") diff --git a/cmake/cmake.options b/cmake/cmake.options index 60ff00affc01408b084a8993441e4fe7052f4977..14939c1d309961e94a42bb7e7505782367178342 100644 --- a/cmake/cmake.options +++ b/cmake/cmake.options @@ -171,3 +171,8 @@ option( ON ) +option( + BUILD_RELEASE + "If build release version" + OFF +) diff --git a/cmake/cmake.platform b/cmake/cmake.platform index a4bfcaf609cc98f43094dabd993b8e310b9b220f..61eb66f675bd12840d025b5d0ed43192120506b4 100644 --- a/cmake/cmake.platform +++ b/cmake/cmake.platform @@ -37,6 +37,21 @@ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin SET(TD_LINUX_32 TRUE) ENDIF () + EXECUTE_PROCESS(COMMAND chmod 777 ${CMAKE_CURRENT_LIST_DIR}/../packaging/tools/get_os.sh) + EXECUTE_PROCESS(COMMAND readlink /bin/sh OUTPUT_VARIABLE SHELL_LINK) + MESSAGE(STATUS "The shell is: " ${SHELL_LINK}) + + IF (${SHELL_LINK} MATCHES "dash") + EXECUTE_PROCESS(COMMAND ${CMAKE_CURRENT_LIST_DIR}/../packaging/tools/get_os.sh "" OUTPUT_VARIABLE TD_OS_INFO) + ELSE () + EXECUTE_PROCESS(COMMAND sh ${CMAKE_CURRENT_LIST_DIR}/../packaging/tools/get_os.sh "" OUTPUT_VARIABLE TD_OS_INFO) + ENDIF () + MESSAGE(STATUS "The current OS is " ${TD_OS_INFO}) + IF (${TD_OS_INFO} MATCHES "Alpine") + SET(TD_ALPINE TRUE) + ADD_DEFINITIONS("-D_ALPINE") + ENDIF () + ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") SET(TD_DARWIN TRUE) diff --git a/cmake/cmake.version b/cmake/cmake.version index a30618157b94a8fb361aa20ae87af00f8a1c3852..3166a0695cea5132fdd509da130548079add2103 100644 --- a/cmake/cmake.version +++ b/cmake/cmake.version @@ -2,7 +2,7 @@ IF (DEFINED VERNUMBER) SET(TD_VER_NUMBER ${VERNUMBER}) ELSE () - SET(TD_VER_NUMBER "3.0.2.5") + SET(TD_VER_NUMBER "3.0.4.1") ENDIF () IF (DEFINED VERCOMPATIBLE) @@ -16,7 +16,7 @@ find_program(HAVE_GIT NAMES git) IF (DEFINED GITINFO) SET(TD_VER_GIT ${GITINFO}) ELSEIF (HAVE_GIT) - execute_process(COMMAND git log -1 --format=%H WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMITID) + execute_process(COMMAND git log -1 --format=%H WORKING_DIRECTORY ${TD_COMMUNITY_DIR} OUTPUT_VARIABLE GIT_COMMITID) #message(STATUS "git log result:${GIT_COMMITID}") IF (GIT_COMMITID) string (REGEX REPLACE "[\n\t\r]" "" GIT_COMMITID ${GIT_COMMITID}) @@ -30,6 +30,23 @@ ELSE () SET(TD_VER_GIT "no git commit id") ENDIF () +IF (DEFINED GITINFOI) + SET(TD_VER_GIT_INTERNAL ${GITINFOI}) +ELSEIF (HAVE_GIT) + execute_process(COMMAND git log -1 --format=%H WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMITID) + message(STATUS "git log result:${GIT_COMMITID}") + IF (GIT_COMMITID) + string (REGEX REPLACE "[\n\t\r]" "" GIT_COMMITID ${GIT_COMMITID}) + SET(TD_VER_GIT_INTERNAL ${GIT_COMMITID}) + ELSE () + message(STATUS "not a git repository") + SET(TD_VER_GIT "no git commit id") + ENDIF () +ELSE () + message(STATUS "no git cmd") + SET(TD_VER_GIT_INTERNAL "no git commit id") +ENDIF () + IF (DEFINED VERDATE) SET(TD_VER_DATE ${VERDATE}) ELSE () diff --git a/cmake/taosadapter_CMakeLists.txt.in b/cmake/taosadapter_CMakeLists.txt.in index 8df50af03c38eae13b143d6a5af7608d045860bb..c67918351de7b25d18403314886bd5227f8fa6c6 100644 --- a/cmake/taosadapter_CMakeLists.txt.in +++ b/cmake/taosadapter_CMakeLists.txt.in @@ -2,7 +2,7 @@ # taosadapter ExternalProject_Add(taosadapter GIT_REPOSITORY https://github.com/taosdata/taosadapter.git - GIT_TAG db6c843 + GIT_TAG 565ca21 SOURCE_DIR "${TD_SOURCE_DIR}/tools/taosadapter" BINARY_DIR "" #BUILD_IN_SOURCE TRUE diff --git a/cmake/taostools_CMakeLists.txt.in b/cmake/taostools_CMakeLists.txt.in index 5f9a44084c414c3f9dc2427b186d90f628de37b5..d9d2f120690e714122756a36821a6fe6398151c2 100644 --- a/cmake/taostools_CMakeLists.txt.in +++ b/cmake/taostools_CMakeLists.txt.in @@ -2,7 +2,7 @@ # taos-tools ExternalProject_Add(taos-tools GIT_REPOSITORY https://github.com/taosdata/taos-tools.git - GIT_TAG 7c641c5 + GIT_TAG 4378702 SOURCE_DIR "${TD_SOURCE_DIR}/tools/taos-tools" BINARY_DIR "" #BUILD_IN_SOURCE TRUE diff --git a/cmake/taosws_CMakeLists.txt.in b/cmake/taosws_CMakeLists.txt.in index e79c6b799f0bfdf98e73d33188c12d355eb32708..b013d45911988ce38cd752766e862da3d461b1cd 100644 --- a/cmake/taosws_CMakeLists.txt.in +++ b/cmake/taosws_CMakeLists.txt.in @@ -2,7 +2,7 @@ # taosws-rs ExternalProject_Add(taosws-rs GIT_REPOSITORY https://github.com/taosdata/taos-connector-rust.git - GIT_TAG f406d51 + GIT_TAG main SOURCE_DIR "${TD_SOURCE_DIR}/tools/taosws-rs" BINARY_DIR "" #BUILD_IN_SOURCE TRUE diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000000000000000000000000000000000000..c61f9701abb7750b5e36c10eac480f61886fd5ca --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,9 @@ +-DLINUX +-DWEBSOCKET +-I/usr/include +-Iinclude +-Iinclude/os +-Iinclude/common +-Iinclude/util +-Iinclude/libs/transport +-Itools/shell/inc diff --git a/docs/doxgen/vnode_write.md b/docs/doxgen/vnode_write.md index 7b8dbd6535587d9fdf204d92fa63c6298038df8a..0f1150a33113e26bbd60ef5462eb603074710c0f 100644 --- a/docs/doxgen/vnode_write.md +++ b/docs/doxgen/vnode_write.md @@ -204,7 +204,7 @@ group vnodeProcessReqs() s -> s: note right save the requests in log store - and wait for comfirmation or + and wait for confirmation or other cases end note @@ -236,7 +236,7 @@ s -> s: syncAppendReqToLogStore() s -> v: walWrite() alt has meta req - <- s: comfirmation + <- s: confirmation else s -> v: vnodeApplyReqs() end diff --git a/docs/en/01-index.md b/docs/en/01-index.md index 13552ea9dcfbae71a368cad9d55b4a0030ac266a..296cd968986d5dd7738d6c3b997901614f893763 100644 --- a/docs/en/01-index.md +++ b/docs/en/01-index.md @@ -1,6 +1,7 @@ --- title: TDengine Documentation sidebar_label: Documentation Home +description: This website contains the user manuals for TDengine, an open-source, cloud-native time-series database optimized for IoT, Connected Cars, and Industrial IoT. slug: / --- diff --git a/docs/en/02-intro/index.md b/docs/en/02-intro/index.md index a60bfab2ccd30fb585d72ee14054029b1c176a66..79d170eeb9abd42f13a5625fc807c11d03a7c598 100644 --- a/docs/en/02-intro/index.md +++ b/docs/en/02-intro/index.md @@ -1,5 +1,6 @@ --- title: Introduction +description: This document introduces the major features, competitive advantages, typical use cases, and benchmarks of TDengine. toc_max_heading_level: 2 --- @@ -122,11 +123,11 @@ As a high-performance, scalable and SQL supported time-series database, TDengine ## Comparison with other databases -- [Writing Performance Comparison of TDengine and InfluxDB ](https://tdengine.com/2022/02/23/4975.html) -- [Query Performance Comparison of TDengine and InfluxDB](https://tdengine.com/2022/02/24/5120.html) -- [TDengine vs OpenTSDB](https://tdengine.com/2019/09/12/710.html) -- [TDengine vs Cassandra](https://tdengine.com/2019/09/12/708.html) -- [TDengine vs InfluxDB](https://tdengine.com/2019/09/12/706.html) +- [Writing Performance Comparison of TDengine and InfluxDB ](https://tdengine.com/performance-comparison-of-tdengine-and-influxdb/) +- [Query Performance Comparison of TDengine and InfluxDB](https://tdengine.com/query-performance-comparison-test-report-tdengine-vs-influxdb/) +- [TDengine vs OpenTSDB](https://tdengine.com/performance-tdengine-vs-opentsdb/) +- [TDengine vs Cassandra](https://tdengine.com/performance-tdengine-vs-cassandra/) +- [TDengine vs InfluxDB](https://tdengine.com/performance-tdengine-vs-influxdb/) ## More readings - [Introduction to Time-Series Database](https://tdengine.com/tsdb/) diff --git a/docs/en/04-concept/index.md b/docs/en/04-concept/index.md index 0b1b226c17100d56313b5480e26f437841afe8c7..771a061c310bd53c485394fe3a8897567b12e48b 100644 --- a/docs/en/04-concept/index.md +++ b/docs/en/04-concept/index.md @@ -1,5 +1,6 @@ --- title: Concepts +description: This document describes the basic concepts of TDengine, including the supertable. --- In order to explain the basic concepts and provide some sample code, the TDengine documentation smart meters as a typical time series use case. We assume the following: 1. Each smart meter collects three metrics i.e. current, voltage, and phase; 2. There are multiple smart meters; 3. Each meter has static attributes like location and group ID. Based on this, collected data will look similar to the following table: diff --git a/docs/en/05-get-started/01-docker.md b/docs/en/05-get-started/01-docker.md index ac273daba48d39bd0777ffdb30f431c6521d13b3..42e6861674434ad9800f69dcf00fe80a140e9bf7 100644 --- a/docs/en/05-get-started/01-docker.md +++ b/docs/en/05-get-started/01-docker.md @@ -1,6 +1,7 @@ --- -sidebar_label: Docker title: Quick Install on Docker +sidebar_label: Docker +description: This document describes how to install TDengine in a Docker container and perform queries and inserts. --- This document describes how to install TDengine in a Docker container and perform queries and inserts. diff --git a/docs/en/05-get-started/03-package.md b/docs/en/05-get-started/03-package.md index 54d2e046c214f2df8ecd5ff03b7d5108c701938d..3282f600ac81fd6a4cc45fb8c09e3c036570cc18 100644 --- a/docs/en/05-get-started/03-package.md +++ b/docs/en/05-get-started/03-package.md @@ -1,6 +1,7 @@ --- -sidebar_label: Package title: Quick Install from Package +sidebar_label: Package +description: This document describes how to install TDengine on Linux, Windows, and macOS and perform queries and inserts. --- import Tabs from "@theme/Tabs"; @@ -187,7 +188,7 @@ You can use the TDengine CLI to monitor your TDengine deployment and execute ad -After the installation is complete, run `C:\TDengine\taosd.exe` to start TDengine Server. +After the installation is complete, please run `sc start taosd` or run `C:\TDengine\taosd.exe` with administrator privilege to start TDengine Server. ## Command Line Interface (CLI) @@ -201,16 +202,18 @@ After the installation is complete, double-click the /applications/TDengine to s The following `launchctl` commands can help you manage TDengine service: -- Start TDengine Server: `launchctl start com.tdengine.taosd` +- Start TDengine Server: `sudo launchctl start com.tdengine.taosd` -- Stop TDengine Server: `launchctl stop com.tdengine.taosd` +- Stop TDengine Server: `sudo launchctl stop com.tdengine.taosd` -- Check TDengine Server status: `launchctl list | grep taosd` +- Check TDengine Server status: `sudo launchctl list | grep taosd` :::info - -- The `launchctl` command does not require _root_ privileges. You don't need to use the `sudo` command. -- The first content returned by the `launchctl list | grep taosd` command is the PID of the program, if '-' indicates that the TDengine service is not running. +- Please use `sudo` to run `launchctl` to manage _com.tdengine.taosd_ with administrator privileges. +- The administrator privilege is required for service management to enhance security. +- Troubleshooting: +- The first column returned by the command `launchctl list | grep taosd` is the PID of the program. If it's `-`, that means the TDengine service is not running. +- If the service is abnormal, please check the `launchd.log` file from the system log or the `taosdlog` from the `/var/log/taos directory` for more information. ::: diff --git a/docs/en/05-get-started/index.md b/docs/en/05-get-started/index.md index 12cfa22c69b1db8e82de4cb251ca3d8c67fc4546..66573a89cd6e181192132cc0b304f415fa25b89c 100644 --- a/docs/en/05-get-started/index.md +++ b/docs/en/05-get-started/index.md @@ -1,6 +1,6 @@ --- title: Get Started -description: This article describes how to install TDengine and test its performance. +description: This document describes how to install TDengine on various platforms. --- import GitHubSVG from './github.svg' diff --git a/docs/en/07-develop/01-connect/index.md b/docs/en/07-develop/01-connect/index.md index 45bbaa2751a6ac6c04b4d6a7fcb00dd0fe03f638..913c24f1896e3c2af6614fc07e9319c6fb06783f 100644 --- a/docs/en/07-develop/01-connect/index.md +++ b/docs/en/07-develop/01-connect/index.md @@ -1,7 +1,7 @@ --- -sidebar_label: Connect title: Connect to TDengine -description: "How to establish connections to TDengine and how to install and use TDengine connectors." +sidebar_label: Connect +description: This document describes how to establish connections to TDengine and how to install and use TDengine connectors. --- import Tabs from "@theme/Tabs"; diff --git a/docs/en/07-develop/02-model/index.mdx b/docs/en/07-develop/02-model/index.mdx index 19a239805f1492eae0c463f5a942378b83ecf6b8..db5a259cfe6f8cc1fec6c588ec9b31888334ca06 100644 --- a/docs/en/07-develop/02-model/index.mdx +++ b/docs/en/07-develop/02-model/index.mdx @@ -1,5 +1,6 @@ --- title: Data Model +description: This document describes the data model of TDengine. --- The data model employed by TDengine is similar to that of a relational database. You have to create databases and tables. You must design the data model based on your own business and application requirements. You should design the [STable](/concept/#super-table-stable) (an abbreviation for super table) schema to fit your data. This chapter will explain the big picture without getting into syntactical details. diff --git a/docs/en/07-develop/03-insert-data/01-sql-writing.mdx b/docs/en/07-develop/03-insert-data/01-sql-writing.mdx index f2168645ff9e59d60e88c85f86e890945b9f336c..3731882fb23677588e72ba5e9d39049af2dfd97d 100644 --- a/docs/en/07-develop/03-insert-data/01-sql-writing.mdx +++ b/docs/en/07-develop/03-insert-data/01-sql-writing.mdx @@ -1,5 +1,6 @@ --- title: Insert Using SQL +description: This document describes how to insert data into TDengine using SQL. --- import Tabs from "@theme/Tabs"; @@ -29,25 +30,31 @@ Application programs can execute `INSERT` statement through connectors to insert The below SQL statement is used to insert one row into table "d1001". ```sql -INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31); +INSERT INTO d1001 VALUES (ts1, 10.3, 219, 0.31); ``` +`ts1` is Unix timestamp, the timestamps which is larger than the difference between current time and KEEP in config is only allowed. For further detial, refer to [TDengine SQL insert timestamp section](/taos-sql/insert). + ### Insert Multiple Rows Multiple rows can be inserted in a single SQL statement. The example below inserts 2 rows into table "d1001". ```sql -INSERT INTO d1001 VALUES (1538548684000, 10.2, 220, 0.23) (1538548696650, 10.3, 218, 0.25); +INSERT INTO d1001 VALUES (ts2, 10.2, 220, 0.23) (ts2, 10.3, 218, 0.25); ``` +`ts1` and `ts2` is Unix timestamp, the timestamps which is larger than the difference between current time and KEEP in config is only allowed. For further detial, refer to [TDengine SQL insert timestamp section](/taos-sql/insert). + ### Insert into Multiple Tables Data can be inserted into multiple tables in the same SQL statement. The example below inserts 2 rows into table "d1001" and 1 row into table "d1002". ```sql -INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6, 218, 0.33) d1002 VALUES (1538548696800, 12.3, 221, 0.31); +INSERT INTO d1001 VALUES (ts1, 10.3, 219, 0.31) (ts2, 12.6, 218, 0.33) d1002 VALUES (ts3, 12.3, 221, 0.31); ``` +`ts1`, `ts2` and `ts3` is Unix timestamp, the timestamps which is larger than the difference between current time and KEEP in config is only allowed. For further detial, refer to [TDengine SQL insert timestamp section](/taos-sql/insert). + For more details about `INSERT` please refer to [INSERT](/taos-sql/insert). :::info diff --git a/docs/en/07-develop/03-insert-data/20-kafka-writting.mdx b/docs/en/07-develop/03-insert-data/20-kafka-writting.mdx index ffb969a8a6d0bc61e23fee44f245a24236db5b1b..89ca10b669d094a156f55439429e329308e71935 100644 --- a/docs/en/07-develop/03-insert-data/20-kafka-writting.mdx +++ b/docs/en/07-develop/03-insert-data/20-kafka-writting.mdx @@ -1,5 +1,6 @@ --- title: Write from Kafka +description: This document describes how to insert data into TDengine using Kafka. --- import Tabs from "@theme/Tabs"; diff --git a/docs/en/07-develop/03-insert-data/30-influxdb-line.mdx b/docs/en/07-develop/03-insert-data/30-influxdb-line.mdx index 3c088602602301fafa824bc256f1f2caca128abd..c559883d26c7ef5750f3ee1f828912f8d800c3a4 100644 --- a/docs/en/07-develop/03-insert-data/30-influxdb-line.mdx +++ b/docs/en/07-develop/03-insert-data/30-influxdb-line.mdx @@ -1,6 +1,7 @@ --- -sidebar_label: InfluxDB Line Protocol title: InfluxDB Line Protocol +sidebar_label: InfluxDB Line Protocol +description: This document describes how to insert data into TDengine using the InfluxDB Line Protocol. --- import Tabs from "@theme/Tabs"; @@ -38,7 +39,7 @@ meters,location=California.LosAngeles,groupid=2 current=13.4,voltage=223,phase=0 - Each data in `field_set` must be self-descriptive for its data type. For example 1.2f32 means a value 1.2 of float type. Without the "f" type suffix, it will be treated as type double. - Multiple kinds of precision can be used for the `timestamp` field. Time precision can be from nanosecond (ns) to hour (h). - The child table name is created automatically in a rule to guarantee its uniqueness. But you can configure `smlChildTableName` in taos.cfg to specify a tag value as the table names if the tag value is unique globally. For example, if a tag is called `tname` and you set `smlChildTableName=tname` in taos.cfg, when you insert `st,tname=cpu1,t1=4 c1=3 1626006833639000000`, the child table `cpu1` will be created automatically. Note that if multiple rows have the same tname but different tag_set values, the tag_set of the first row is used to create the table and the others are ignored. -- It is assumed that the order of field_set in a supertable is consistent, meaning that the first record contains all fields and subsequent records store fields in the same order. If the order is not consistent, set smlDataFormat in taos.cfg to false. Otherwise, data will be written out of order and a database error will occur.(smlDataFormat in taos.cfg default to false after version of 3.0.1.3) +- It is assumed that the order of field_set in a supertable is consistent, meaning that the first record contains all fields and subsequent records store fields in the same order. If the order is not consistent, set smlDataFormat in taos.cfg to false. Otherwise, data will be written out of order and a database error will occur.(smlDataFormat in taos.cfg default to false after version of 3.0.1.3, smlDataFormat is discarded since 3.0.3.0) ::: For more details please refer to [InfluxDB Line Protocol](https://docs.influxdata.com/influxdb/v2.0/reference/syntax/line-protocol/) and [TDengine Schemaless](/reference/schemaless/#Schemaless-Line-Protocol) diff --git a/docs/en/07-develop/03-insert-data/40-opentsdb-telnet.mdx b/docs/en/07-develop/03-insert-data/40-opentsdb-telnet.mdx index 5d3f25dca96a0d41a4562aa067800607e8e04277..30bc3b87bf035f563e1a03508a90466e9288f89c 100644 --- a/docs/en/07-develop/03-insert-data/40-opentsdb-telnet.mdx +++ b/docs/en/07-develop/03-insert-data/40-opentsdb-telnet.mdx @@ -1,6 +1,7 @@ --- -sidebar_label: OpenTSDB Line Protocol title: OpenTSDB Line Protocol +sidebar_label: OpenTSDB Line Protocol +description: This document describes how to insert data into TDengine using the OpenTSDB Line Protocol. --- import Tabs from "@theme/Tabs"; diff --git a/docs/en/07-develop/03-insert-data/50-opentsdb-json.mdx b/docs/en/07-develop/03-insert-data/50-opentsdb-json.mdx index 7a3ac6bad3b203a9859e235e92d0865f7147d24c..e9db130241236e7224e5965c4c3c651ddab8cb00 100644 --- a/docs/en/07-develop/03-insert-data/50-opentsdb-json.mdx +++ b/docs/en/07-develop/03-insert-data/50-opentsdb-json.mdx @@ -1,6 +1,7 @@ --- -sidebar_label: OpenTSDB JSON Protocol title: OpenTSDB JSON Protocol +sidebar_label: OpenTSDB JSON Protocol +description: This document describes how to insert data into TDengine using the OpenTSDB JSON protocol. --- import Tabs from "@theme/Tabs"; @@ -47,7 +48,6 @@ Please refer to [OpenTSDB HTTP API](http://opentsdb.net/docs/build/html/api_http :::note - In JSON protocol, strings will be converted to NCHAR type and numeric values will be converted to double type. -- Only data in array format is accepted and so an array must be used even if there is only one row. - The child table name is created automatically in a rule to guarantee its uniqueness. But you can configure `smlChildTableName` in taos.cfg to specify a tag value as the table names if the tag value is unique globally. For example, if a tag is called `tname` and you set `smlChildTableName=tname` in taos.cfg, when you insert `st,tname=cpu1,t1=4 c1=3 1626006833639000000`, the child table `cpu1` will be automatically created. Note that if multiple rows have the same tname but different tag_set values, the tag_set of the first row is used to create the table and the others are ignored. ::: diff --git a/docs/en/07-develop/03-insert-data/60-high-volume.md b/docs/en/07-develop/03-insert-data/60-high-volume.md index 272a13881372b58a9a66c0d452cda54f9ee8c78c..d6a00481383035c0babc6fab94e8359b4806ff72 100644 --- a/docs/en/07-develop/03-insert-data/60-high-volume.md +++ b/docs/en/07-develop/03-insert-data/60-high-volume.md @@ -1,6 +1,7 @@ --- -sidebar_label: High Performance Writing title: High Performance Writing +sidebar_label: High Performance Writing +description: This document describes how to achieve high performance when writing data into TDengine. --- import Tabs from "@theme/Tabs"; @@ -27,7 +28,7 @@ From the perspective of application program, you need to consider: - Writing to known existing tables is more efficient than writing to uncertain tables in automatic creating mode because the later needs to check whether the table exists or not before actually writing data into it. - Writing in SQL is more efficient than writing in schemaless mode because schemaless writing creates table automatically and may alter table schema. -Application programs need to take care of the above factors and try to take advantage of them. The application progam should write to single table in each write batch. The batch size needs to be tuned to a proper value on a specific system. The number of concurrent connections needs to be tuned to a proper value too to achieve the best writing throughput. +Application programs need to take care of the above factors and try to take advantage of them. The application program should write to single table in each write batch. The batch size needs to be tuned to a proper value on a specific system. The number of concurrent connections needs to be tuned to a proper value too to achieve the best writing throughput. ### Data Source diff --git a/docs/en/07-develop/03-insert-data/_py_kafka.mdx b/docs/en/07-develop/03-insert-data/_py_kafka.mdx index dc43a0d415275189220287278547b015865e8d90..c71821dad129fe1a573e6f607eb591f81f928ae1 100644 --- a/docs/en/07-develop/03-insert-data/_py_kafka.mdx +++ b/docs/en/07-develop/03-insert-data/_py_kafka.mdx @@ -53,8 +53,69 @@ for p in ps: In addition to python's built-in multithreading and multiprocessing library, we can also use the third-party library gunicorn. -### Examples +### examples + +
+kafka_example_perform + +`kafka_example_perform` is the entry point of the examples. + +```py +{{#include docs/examples/python/kafka_example_perform.py}} +``` +
+ +
+kafka_example_common + +`kafka_example_common` is the common code of the examples. ```py -{{#include docs/examples/python/kafka_example.py}} +{{#include docs/examples/python/kafka_example_common.py}} ``` +
+ +
+kafka_example_producer + +`kafka_example_producer` is `producer`, which is responsible for generating test data and sending it to kafka. + +```py +{{#include docs/examples/python/kafka_example_producer.py}} +``` +
+ +
+kafka_example_consumer + +`kafka_example_consumer` is `consumer`,which is responsible for consuming data from kafka and writing it to TDengine. + +```py +{{#include docs/examples/python/kafka_example_consumer.py}} +``` +
+ +### execute Python examples + +
+ execute Python examples + + 1. install and start up `kafka` + 2. install python3 and pip + 3. install `taospy` by pip + 4. install `kafka-python` by pip + 5. execute this example + + The entry point of this example is `kafka_example_perform.py`. For more information about usage, please use `--help` command. + + ``` + python3 kafka_example_perform.py --help + ``` + + For example, the following command is creating 100 sub-table and inserting 20000 data for each table and the kafka max poll is 100 and 1 thread and 1 process per thread. + + ``` + python3 kafka_example_perform.py -table-count=100 -table-items=20000 -max-poll=100 -threads=1 -processes=1 + ``` + +
diff --git a/docs/en/07-develop/03-insert-data/index.md b/docs/en/07-develop/03-insert-data/index.md index 1a71e719a56448e4b535632e570ce8a04d2282bb..15f8f4ee9e9b24e6b511e6d29505c7b99fea3ae8 100644 --- a/docs/en/07-develop/03-insert-data/index.md +++ b/docs/en/07-develop/03-insert-data/index.md @@ -1,5 +1,6 @@ --- title: Insert Data +description: This document describes how to insert data into TDengine. --- TDengine supports multiple protocols of inserting data, including SQL, InfluxDB Line protocol, OpenTSDB Telnet protocol, and OpenTSDB JSON protocol. Data can be inserted row by row, or in batches. Data from one or more collection points can be inserted simultaneously. Data can be inserted with multiple threads, and out of order data and historical data can be inserted as well. InfluxDB Line protocol, OpenTSDB Telnet protocol and OpenTSDB JSON protocol are the 3 kinds of schemaless insert protocols supported by TDengine. It's not necessary to create STables and tables in advance if using schemaless protocols, and the schemas can be adjusted automatically based on the data being inserted. diff --git a/docs/en/07-develop/04-query-data/index.mdx b/docs/en/07-develop/04-query-data/index.mdx index 38dc98d1ff262c7f8ec4951297e6f42e436682c8..7e167bb4f342167c486403259985976357e44496 100644 --- a/docs/en/07-develop/04-query-data/index.mdx +++ b/docs/en/07-develop/04-query-data/index.mdx @@ -1,6 +1,6 @@ --- title: Query Data -description: "This chapter introduces major query functionalities and how to perform sync and async query using connectors." +description: This document describes how to query data in TDengine and how to perform synchronous and asynchronous queries using connectors. --- import Tabs from "@theme/Tabs"; diff --git a/docs/en/07-develop/06-stream.md b/docs/en/07-develop/06-stream.md index 36f903ee9a4f2d210e63d0b79e702bc199f790ed..125173e60bae77bbbe782363ebd2103cf7e4b703 100644 --- a/docs/en/07-develop/06-stream.md +++ b/docs/en/07-develop/06-stream.md @@ -1,7 +1,7 @@ --- -sidebar_label: Stream Processing -description: "The TDengine stream processing engine combines data inserts, preprocessing, analytics, real-time computation, and alerting into a single component." title: Stream Processing +sidebar_label: Stream Processing +description: This document describes the stream processing component of TDengine. --- Raw time-series data is often cleaned and preprocessed before being permanently stored in a database. In a traditional time-series solution, this generally requires the deployment of stream processing systems such as Kafka or Flink. However, the complexity of such systems increases the cost of development and maintenance. diff --git a/docs/en/07-develop/07-tmq.mdx b/docs/en/07-develop/07-tmq.mdx index 17b3f5caa062eaacb4216b7153e899040e702cc1..7465cc0a12ecc9c92a48a2308fe101d057f80492 100644 --- a/docs/en/07-develop/07-tmq.mdx +++ b/docs/en/07-develop/07-tmq.mdx @@ -7,6 +7,7 @@ title: Data Subscription import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; import Java from "./_sub_java.mdx"; +import JavaWS from "./_sub_java_ws.mdx" import Python from "./_sub_python.mdx"; import Go from "./_sub_go.mdx"; import Rust from "./_sub_rust.mdx"; @@ -22,7 +23,7 @@ By subscribing to a topic, a consumer can obtain the latest data in that topic i To implement these features, TDengine indexes its write-ahead log (WAL) file for fast random access and provides configurable methods for replacing and retaining this file. You can define a retention period and size for this file. For information, see the CREATE DATABASE statement. In this way, the WAL file is transformed into a persistent storage engine that remembers the order in which events occur. However, note that configuring an overly long retention period for your WAL files makes database compression inefficient. TDengine then uses the WAL file instead of the time-series database as its storage engine for queries in the form of topics. TDengine reads the data from the WAL file; uses a unified query engine instance to perform filtering, transformations, and other operations; and finally pushes the data to consumers. - +Tips:The default data subscription is to consume data from the wal. If the wal is deleted, the consumed data will be incomplete. At this time, you can set the parameter experimental.snapshot.enable to true to obtain all data from the tsdb, but in this way, the consumption order of the data cannot be guaranteed. Therefore, it is recommended to set a reasonable retention policy for WAL based on your consumption situation to ensure that you can subscribe all data from WAL. ## Data Schema and API @@ -94,22 +95,21 @@ void close() throws SQLException; ```python -class TaosConsumer(): - def __init__(self, *topics, **configs) - - def __iter__(self) +class Consumer: + def subscribe(self, topics): + pass - def __next__(self) + def unsubscribe(self): + pass - def sync_next(self) - - def subscription(self) + def poll(self, timeout: float = 1.0): + pass - def unsubscribe(self) + def close(self): + pass - def close(self) - - def __del__(self) + def commit(self, message): + pass ``` @@ -117,19 +117,22 @@ class TaosConsumer(): ```go -func NewConsumer(conf *Config) (*Consumer, error) +func NewConsumer(conf *tmq.ConfigMap) (*Consumer, error) -func (c *Consumer) Close() error +// rebalanceCb is reserved for compatibility purpose +func (c *Consumer) Subscribe(topic string, rebalanceCb RebalanceCb) error -func (c *Consumer) Commit(ctx context.Context, message unsafe.Pointer) error +// rebalanceCb is reserved for compatibility purpose +func (c *Consumer) SubscribeTopics(topics []string, rebalanceCb RebalanceCb) error -func (c *Consumer) FreeMessage(message unsafe.Pointer) +func (c *Consumer) Poll(timeoutMs int) tmq.Event -func (c *Consumer) Poll(timeout time.Duration) (*Result, error) - -func (c *Consumer) Subscribe(topics []string) error +// tmq.TopicPartition is reserved for compatibility purpose +func (c *Consumer) Commit() ([]tmq.TopicPartition, error) func (c *Consumer) Unsubscribe() error + +func (c *Consumer) Close() error ``` @@ -220,7 +223,7 @@ A database including one supertable and two subtables is created as follows: ```sql DROP DATABASE IF EXISTS tmqdb; CREATE DATABASE tmqdb; -CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16) TAGS(t1 INT, t3 VARCHAR(16)); +CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16)) TAGS(t1 INT, t3 VARCHAR(16)); CREATE TABLE tmqdb.ctb0 USING tmqdb.stb TAGS(0, "subtable0"); CREATE TABLE tmqdb.ctb1 USING tmqdb.stb TAGS(1, "subtable1"); INSERT INTO tmqdb.ctb0 VALUES(now, 0, 0, 'a0')(now+1s, 0, 0, 'a00'); @@ -282,18 +285,17 @@ You configure the following parameters when creating a consumer: | Parameter | Type | Description | Remarks | | :----------------------------: | :-----: | -------------------------------------------------------- | ------------------------------------------- | -| `td.connect.ip` | string | Used in establishing a connection; same as `taos_connect` | | -| `td.connect.user` | string | Used in establishing a connection; same as `taos_connect` | | -| `td.connect.pass` | string | Used in establishing a connection; same as `taos_connect` | | -| `td.connect.port` | string | Used in establishing a connection; same as `taos_connect` | | +| `td.connect.ip` | string | Used in establishing a connection; same as `taos_connect` | Only valid for establishing native connection | +| `td.connect.user` | string | Used in establishing a connection; same as `taos_connect` | Only valid for establishing native connection | +| `td.connect.pass` | string | Used in establishing a connection; same as `taos_connect` | Only valid for establishing native connection | +| `td.connect.port` | string | Used in establishing a connection; same as `taos_connect` | Only valid for establishing native connection | | `group.id` | string | Consumer group ID; consumers with the same ID are in the same group | **Required**. Maximum length: 192. | | `client.id` | string | Client ID | Maximum length: 192. | | `auto.offset.reset` | enum | Initial offset for the consumer group | Specify `earliest`, `latest`, or `none`(default) | -| `enable.auto.commit` | boolean | Commit automatically | Specify `true` or `false`. | +| `enable.auto.commit` | boolean | Commit automatically; true: user application doesn't need to explicitly commit; false: user application need to handle commit by itself | Default value is true | | `auto.commit.interval.ms` | integer | Interval for automatic commits, in milliseconds | -| `enable.heartbeat.background` | boolean | Backend heartbeat; if enabled, the consumer does not go offline even if it has not polled for a long time | | -| `experimental.snapshot.enable` | boolean | Specify whether to consume messages from the WAL or from TSBS | | -| `msg.with.table.name` | boolean | Specify whether to deserialize table names from messages | +| `experimental.snapshot.enable` | boolean | Specify whether to consume data in TSDB; true: both data in WAL and in TSDB can be consumed; false: only data in WAL can be consumed | default value: false | +| `msg.with.table.name` | boolean | Specify whether to deserialize table names from messages | default value: false The method of specifying these parameters depends on the language used: @@ -357,50 +359,19 @@ public class MetersDeserializer extends ReferenceDeserializer { ```go -config := tmq.NewConfig() -defer config.Destroy() -err = config.SetGroupID("test") -if err != nil { - panic(err) -} -err = config.SetAutoOffsetReset("earliest") -if err != nil { - panic(err) -} -err = config.SetConnectIP("127.0.0.1") -if err != nil { - panic(err) -} -err = config.SetConnectUser("root") -if err != nil { - panic(err) -} -err = config.SetConnectPass("taosdata") -if err != nil { - panic(err) -} -err = config.SetConnectPort("6030") -if err != nil { - panic(err) -} -err = config.SetMsgWithTableName(true) -if err != nil { - panic(err) -} -err = config.EnableHeartBeat() -if err != nil { - panic(err) -} -err = config.EnableAutoCommit(func(result *wrapper.TMQCommitCallbackResult) { - if result.ErrCode != 0 { - errStr := wrapper.TMQErr2Str(result.ErrCode) - err := errors.NewError(int(result.ErrCode), errStr) - panic(err) - } -}) -if err != nil { - panic(err) +conf := &tmq.ConfigMap{ + "group.id": "test", + "auto.offset.reset": "earliest", + "td.connect.ip": "127.0.0.1", + "td.connect.user": "root", + "td.connect.pass": "taosdata", + "td.connect.port": "6030", + "client.id": "test_tmq_c", + "enable.auto.commit": "false", + "experimental.snapshot.enable": "true", + "msg.with.table.name": "true", } +consumer, err := NewConsumer(conf) ``` @@ -422,23 +393,31 @@ let mut consumer = tmq.build()?; +```python +from taos.tmq import Consumer + +# Syntax: `consumer = Consumer(configs)` +# +# Example: +consumer = Consumer({"group.id": "local", "td.connect.ip": "127.0.0.1"}) +``` + Python programs use the following parameters: -| Parameter | Type | Description | Remarks | -| :----------------------------: | :----: | -------------------------------------------------------- | ------------------------------------------- | -| `td_connect_ip` | string | Used in establishing a connection; same as `taos_connect` | | -| `td_connect_user` | string | Used in establishing a connection; same as `taos_connect` | | -| `td_connect_pass` | string | Used in establishing a connection; same as `taos_connect` | | -| `td_connect_port` | string | Used in establishing a connection; same as `taos_connect` | | -| `group_id` | string | Consumer group ID; consumers with the same ID are in the same group | **Required**. Maximum length: 192. | -| `client_id` | string | Client ID | Maximum length: 192. | -| `auto_offset_reset` | string | Initial offset for the consumer group | Specify `earliest`, `latest`, or `none`(default) | -| `enable_auto_commit` | string | Commit automatically | Specify `true` or `false`. | -| `auto_commit_interval_ms` | string | Interval for automatic commits, in milliseconds | -| `enable_heartbeat_background` | string | Backend heartbeat; if enabled, the consumer does not go offline even if it has not polled for a long time | Specify `true` or `false`. | -| `experimental_snapshot_enable` | string | Specify whether to consume messages from the WAL or from TSBS | Specify `true` or `false`. | -| `msg_with_table_name` | string | Specify whether to deserialize table names from messages | Specify `true` or `false`. -| `timeout` | int | Consumer pull timeout | | +| Parameter | Type | Description | Remarks | +|:---------:|:----:|:-----------:|:-------:| +| `td.connect.ip` | string | Used in establishing a connection|| +| `td.connect.user` | string | Used in establishing a connection|| +| `td.connect.pass` | string | Used in establishing a connection|| +| `td.connect.port` | string | Used in establishing a connection|| +| `group.id` | string | Consumer group ID; consumers with the same ID are in the same group | **Required**. Maximum length: 192 | +| `client.id` | string | Client ID | Maximum length: 192 | +| `msg.with.table.name` | string | Specify whether to deserialize table names from messages | pecify `true` or `false` | +| `enable.auto.commit` | string | Commit automatically | pecify `true` or `false` | +| `auto.commit.interval.ms` | string | Interval for automatic commits, in milliseconds | | +| `auto.offset.reset` | string | Initial offset for the consumer group | Specify `earliest`, `latest`, or `none`(default) | +| `experimental.snapshot.enable` | string | Specify whether it's allowed to consume messages from the WAL or from TSDB | Specify `true` or `false` | +| `enable.heartbeat.background` | string | Backend heartbeat; if enabled, the consumer does not go offline even if it has not polled for a long time | Specify `true` or `false` | @@ -523,11 +502,7 @@ consumer.subscribe(topics); ```go -consumer, err := tmq.NewConsumer(config) -if err != nil { - panic(err) -} -err = consumer.Subscribe([]string{"example_tmq_topic"}) +err = consumer.Subscribe("example_tmq_topic", nil) if err != nil { panic(err) } @@ -545,7 +520,7 @@ consumer.subscribe(["tmq_meters"]).await?; ```python -consumer = TaosConsumer('topic_ctb_column', group_id='vg2') +consumer.subscribe(['topic1', 'topic2']) ``` @@ -611,13 +586,17 @@ while(running){ ```go for { - result, err := consumer.Poll(time.Second) - if err != nil { - panic(err) + ev := consumer.Poll(0) + if ev != nil { + switch e := ev.(type) { + case *tmqcommon.DataMessage: + fmt.Println(e.Value()) + case tmqcommon.Error: + fmt.Fprintf(os.Stderr, "%% Error: %v: %v\n", e.Code(), e) + panic(e) + } + consumer.Commit() } - fmt.Println(result) - consumer.Commit(context.Background(), result.Message) - consumer.FreeMessage(result.Message) } ``` @@ -660,9 +639,17 @@ for { ```python -for msg in consumer: - for row in msg: - print(row) +while True: + res = consumer.poll(100) + if not res: + continue + err = res.error() + if err is not None: + raise err + val = res.value() + + for block in val: + print(block.fetchall()) ``` @@ -729,7 +716,11 @@ consumer.close(); ```go -consumer.Close() +/* Unsubscribe */ +_ = consumer.Unsubscribe() + +/* Close consumer */ +_ = consumer.Close() ``` @@ -815,7 +806,14 @@ The following section shows sample code in various languages. - + + + + + + + + diff --git a/docs/en/07-develop/08-cache.md b/docs/en/07-develop/08-cache.md index 82a4787016f608f8e32e89b1747443b7cd164551..6a6ca3e5947b6a3233f90e5e0a01417e6be3b19d 100644 --- a/docs/en/07-develop/08-cache.md +++ b/docs/en/07-develop/08-cache.md @@ -1,7 +1,7 @@ --- -sidebar_label: Caching title: Caching -description: "This document describes the caching component of TDengine." +sidebar_label: Caching +description: This document describes the caching component of TDengine. --- TDengine uses various kinds of caching techniques to efficiently write and query data. This document describes the caching component of TDengine. diff --git a/docs/en/07-develop/09-udf.md b/docs/en/07-develop/09-udf.md index 699b3ebe5f7cddaa6f56cb8027c784a5821a7a0d..dc42743b51778593e40993e8da1dd1e6c3c8a122 100644 --- a/docs/en/07-develop/09-udf.md +++ b/docs/en/07-develop/09-udf.md @@ -1,7 +1,7 @@ --- -sidebar_label: UDF title: User-Defined Functions (UDF) -description: "You can define your own scalar and aggregate functions to expand the query capabilities of TDengine." +sidebar_label: UDF +description: This document describes how to create user-defined functions (UDF), your own scalar and aggregate functions that can expand the query capabilities of TDengine. --- The built-in functions of TDengine may not be sufficient for the use cases of every application. In this case, you can define custom functions for use in TDengine queries. These are known as user-defined functions (UDF). A user-defined function takes one column of data or the result of a subquery as its input. @@ -65,11 +65,11 @@ int32_t aggfn_init() { } // aggregate start function. The intermediate value or the state(@interBuf) is initialized in this function. The function name shall be concatenation of udf name and _start suffix -// @param interbuf intermediate value to intialize +// @param interbuf intermediate value to initialize // @return error number defined in taoserror.h int32_t aggfn_start(SUdfInterBuf* interBuf) { // initialize intermediate value in interBuf - return TSDB_CODE_SUCESS; + return TSDB_CODE_SUCCESS; } // aggregate reduce function. This function aggregate old state(@interbuf) and one data bock(inputBlock) and output a new state(@newInterBuf). diff --git a/docs/en/07-develop/_sub_java.mdx b/docs/en/07-develop/_sub_java.mdx index d14b5fd6095dd90f89dd2c2e828858585cfddff9..c0e9e6c9371123c737e40d7a5f9a6736e8edf44e 100644 --- a/docs/en/07-develop/_sub_java.mdx +++ b/docs/en/07-develop/_sub_java.mdx @@ -1,11 +1,9 @@ ```java {{#include docs/examples/java/src/main/java/com/taos/example/SubscribeDemo.java}} -{{#include docs/examples/java/src/main/java/com/taos/example/MetersDeserializer.java}} -{{#include docs/examples/java/src/main/java/com/taos/example/Meters.java}} ``` ```java {{#include docs/examples/java/src/main/java/com/taos/example/MetersDeserializer.java}} ``` ```java {{#include docs/examples/java/src/main/java/com/taos/example/Meters.java}} -``` \ No newline at end of file +``` diff --git a/docs/en/07-develop/_sub_java_ws.mdx b/docs/en/07-develop/_sub_java_ws.mdx new file mode 100644 index 0000000000000000000000000000000000000000..2a48713358fdb5d018e62bb17215521dbc5a491a --- /dev/null +++ b/docs/en/07-develop/_sub_java_ws.mdx @@ -0,0 +1,9 @@ +```java +{{#include docs/examples/java/src/main/java/com/taos/example/WebsocketSubscribeDemo.java}} +``` +```java +{{#include docs/examples/java/src/main/java/com/taos/example/MetersDeserializer.java}} +``` +```java +{{#include docs/examples/java/src/main/java/com/taos/example/Meters.java}} +``` diff --git a/docs/en/07-develop/index.md b/docs/en/07-develop/index.md index 34649d32a2f758fda2bd79afbbd8f3427b714353..8f80b82b970c576945eee6f972bd901d910614a9 100644 --- a/docs/en/07-develop/index.md +++ b/docs/en/07-develop/index.md @@ -1,5 +1,6 @@ --- title: Developer Guide +description: This document describes how to use the various components of TDengine from a developer's perspective. --- Before creating an application to process time-series data with TDengine, consider the following: diff --git a/docs/en/10-deployment/01-deploy.md b/docs/en/10-deployment/01-deploy.md index 5dfcd3108d8b10cf24cdd5c852c4225ced0f16b2..da00e21a7ec7c7a34c0a3ae60b2928bd3b036cc4 100644 --- a/docs/en/10-deployment/01-deploy.md +++ b/docs/en/10-deployment/01-deploy.md @@ -1,6 +1,7 @@ --- -sidebar_label: Manual Deployment title: Manual Deployment and Management +sidebar_label: Manual Deployment +description: This document describes how to deploy TDengine on a server. --- ## Prerequisites diff --git a/docs/en/10-deployment/03-k8s.md b/docs/en/10-deployment/03-k8s.md index b0aa6777130864404e97dc332cf0e5ce830bf8ed..49e61caafce6414a10c4bc1937ce13394a7da9eb 100644 --- a/docs/en/10-deployment/03-k8s.md +++ b/docs/en/10-deployment/03-k8s.md @@ -1,6 +1,7 @@ --- -sidebar_label: Kubernetes title: Deploying a TDengine Cluster in Kubernetes +sidebar_label: Kubernetes +description: This document describes how to deploy TDengine on Kubernetes. --- TDengine is a cloud-native time-series database that can be deployed on Kubernetes. This document gives a step-by-step description of how you can use YAML files to create a TDengine cluster and introduces common operations for TDengine in a Kubernetes environment. diff --git a/docs/en/10-deployment/05-helm.md b/docs/en/10-deployment/05-helm.md index a4fa68100078efe85fff5e1b078ebd07e5337d5a..aa617176693a576c8dbd37b83a70b1be3b983ef0 100644 --- a/docs/en/10-deployment/05-helm.md +++ b/docs/en/10-deployment/05-helm.md @@ -1,6 +1,7 @@ --- -sidebar_label: Helm title: Use Helm to deploy TDengine +sidebar_label: Helm +description: This document describes how to deploy TDengine on Kubernetes by using Helm. --- Helm is a package manager for Kubernetes that can provide more capabilities in deploying on Kubernetes. @@ -22,7 +23,7 @@ Helm uses the kubectl and kubeconfig configurations to perform Kubernetes operat To use TDengine Chart, download it from GitHub: ```bash -wget https://github.com/taosdata/TDengine-Operator/raw/3.0/helm/tdengine-3.0.0.tgz +wget https://github.com/taosdata/TDengine-Operator/raw/3.0/helm/tdengine-3.0.2.tgz ``` @@ -38,7 +39,7 @@ With minikube, the default value is standard. Use Helm commands to install TDengine: ```bash -helm install tdengine tdengine-3.0.0.tgz \ +helm install tdengine tdengine-3.0.2.tgz \ --set storage.className= ``` @@ -46,7 +47,7 @@ helm install tdengine tdengine-3.0.0.tgz \ You can configure a small storage size in minikube to ensure that your deployment does not exceed your available disk space. ```bash -helm install tdengine tdengine-3.0.0.tgz \ +helm install tdengine tdengine-3.0.2.tgz \ --set storage.className=standard \ --set storage.dataSize=2Gi \ --set storage.logSize=10Mi @@ -83,14 +84,14 @@ You can configure custom parameters in TDengine with the `values.yaml` file. Run the `helm show values` command to see all parameters supported by TDengine Chart. ```bash -helm show values tdengine-3.0.0.tgz +helm show values tdengine-3.0.2.tgz ``` Save the output of this command as `values.yaml`. Then you can modify this file with your desired values and use it to deploy a TDengine cluster: ```bash -helm install tdengine tdengine-3.0.0.tgz -f values.yaml +helm install tdengine tdengine-3.0.2.tgz -f values.yaml ``` @@ -107,7 +108,7 @@ image: prefix: tdengine/tdengine #pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. -# tag: "3.0.0.0" +# tag: "3.0.2.0" service: # ClusterIP is the default service type, use NodeIP only if you know what you are doing. @@ -155,15 +156,15 @@ clusterDomainSuffix: "" # See the [Configuration Variables](../../reference/config) # # Note: -# 1. firstEp/secondEp: should not be setted here, it's auto generated at scale-up. -# 2. serverPort: should not be setted, we'll use the default 6030 in many places. -# 3. fqdn: will be auto generated in kubenetes, user should not care about it. +# 1. firstEp/secondEp: should not be set here, it's auto generated at scale-up. +# 2. serverPort: should not be set, we'll use the default 6030 in many places. +# 3. fqdn: will be auto generated in kubernetes, user should not care about it. # 4. role: currently role is not supported - every node is able to be mnode and vnode. # # Btw, keep quotes "" around the value like below, even the value will be number or not. taoscfg: # Starts as cluster or not, must be 0 or 1. - # 0: all pods will start as a seperate TDengine server + # 0: all pods will start as a separate TDengine server # 1: pods will start as TDengine server cluster. [default] CLUSTER: "1" diff --git a/docs/en/10-deployment/index.md b/docs/en/10-deployment/index.md index 7054a33e4a40222ed5eb9a15837990e3e7a81cff..865fbc2da57bb985dabc03a743c5e0f7186b98be 100644 --- a/docs/en/10-deployment/index.md +++ b/docs/en/10-deployment/index.md @@ -1,5 +1,6 @@ --- title: Deployment +description: This document describes how to deploy a TDengine cluster on a server, on Kubernetes, and by using Helm. --- TDengine has a native distributed design and provides the ability to scale out. A few nodes can form a TDengine cluster. If you need higher processing power, you just need to add more nodes into the cluster. TDengine uses virtual node technology to virtualize a node into multiple virtual nodes to achieve load balancing. At the same time, TDengine can group virtual nodes on different nodes into virtual node groups, and use the replication mechanism to ensure the high availability of the system. The cluster feature of TDengine is completely open source. diff --git a/docs/en/12-taos-sql/01-data-type.md b/docs/en/12-taos-sql/01-data-type.md index 60046629a4c6f89ccfe9b20adcbb2fdba2ffb261..641fd3cbb7c4e2937cc1756a41a522f6eb4b51aa 100644 --- a/docs/en/12-taos-sql/01-data-type.md +++ b/docs/en/12-taos-sql/01-data-type.md @@ -1,7 +1,7 @@ --- -sidebar_label: Data Types title: Data Types -description: 'TDengine supports a variety of data types including timestamp, float, JSON and many others.' +sidebar_label: Data Types +description: This document describes the data types that TDengine supports. --- ## Timestamp diff --git a/docs/en/12-taos-sql/02-database.md b/docs/en/12-taos-sql/02-database.md index a12406fe4353d437c5df9755f8f8e68b0f24282f..ec007d68302f719ec09b1b13f58a1a6bddb2748c 100644 --- a/docs/en/12-taos-sql/02-database.md +++ b/docs/en/12-taos-sql/02-database.md @@ -1,7 +1,7 @@ --- -sidebar_label: Database title: Database -description: "create and drop database, show or change database parameters" +sidebar_label: Database +description: This document describes how to create and perform operations on databases. --- ## Create a Database @@ -27,13 +27,16 @@ database_option: { | PRECISION {'ms' | 'us' | 'ns'} | REPLICA value | RETENTIONS ingestion_duration:keep_duration ... - | STRICT {'off' | 'on'} | WAL_LEVEL {1 | 2} | VGROUPS value | SINGLE_STABLE {0 | 1} + | STT_TRIGGER value + | TABLE_PREFIX value + | TABLE_SUFFIX value + | TSDB_PAGESIZE value | WAL_RETENTION_PERIOD value - | WAL_ROLL_PERIOD value | WAL_RETENTION_SIZE value + | WAL_ROLL_PERIOD value | WAL_SEGMENT_SIZE value } ``` @@ -55,15 +58,12 @@ database_option: { - WAL_FSYNC_PERIOD: specifies the interval (in milliseconds) at which data is written from the WAL to disk. This parameter takes effect only when the WAL parameter is set to 2. The default value is 3000. Enter a value between 0 and 180000. The value 0 indicates that incoming data is immediately written to disk. - MAXROWS: specifies the maximum number of rows recorded in a block. The default value is 4096. - MINROWS: specifies the minimum number of rows recorded in a block. The default value is 100. -- KEEP: specifies the time for which data is retained. Enter a value between 1 and 365000. The default value is 3650. The value of the KEEP parameter must be greater than or equal to the value of the DURATION parameter. TDengine automatically deletes data that is older than the value of the KEEP parameter. You can use m (minutes), h (hours), and d (days) as the unit, for example KEEP 100h or KEEP 10d. If you do not include a unit, d is used by default. +- KEEP: specifies the time for which data is retained. Enter a value between 1 and 365000. The default value is 3650. The value of the KEEP parameter must be greater than or equal to the value of the DURATION parameter. TDengine automatically deletes data that is older than the value of the KEEP parameter. You can use m (minutes), h (hours), and d (days) as the unit, for example KEEP 100h or KEEP 10d. If you do not include a unit, d is used by default. The Enterprise Edition supports [Tiered Storage](https://docs.tdengine.com/tdinternal/arch/#tiered-storage) function, thus multiple KEEP values (comma separated and up to 3 values supported, and meet keep 0 <= keep 1 <= keep 2, e.g. KEEP 100h,100d,3650d) are supported; the Community Edition does not support Tiered Storage function (although multiple keep values are configured, they do not take effect, only the maximum keep value is used as KEEP). - PAGES: specifies the number of pages in the metadata storage engine cache on each vnode. Enter a value greater than or equal to 64. The default value is 256. The space occupied by metadata storage on each vnode is equal to the product of the values of the PAGESIZE and PAGES parameters. The space occupied by default is 1 MB. - PAGESIZE: specifies the size (in KB) of each page in the metadata storage engine cache on each vnode. The default value is 4. Enter a value between 1 and 16384. - PRECISION: specifies the precision at which a database records timestamps. Enter ms for milliseconds, us for microseconds, or ns for nanoseconds. The default value is ms. - REPLICA: specifies the number of replicas that are made of the database. Enter 1 or 3. The default value is 1. The value of the REPLICA parameter cannot exceed the number of dnodes in the cluster. - RETENTIONS: specifies the retention period for data aggregated at various intervals. For example, RETENTIONS 15s:7d,1m:21d,15m:50d indicates that data aggregated every 15 seconds is retained for 7 days, data aggregated every 1 minute is retained for 21 days, and data aggregated every 15 minutes is retained for 50 days. You must enter three aggregation intervals and corresponding retention periods. -- STRICT: specifies whether strong data consistency is enabled. The default value is off. - - on: Strong consistency is enabled and implemented through the Raft consensus algorithm. In this mode, an operation is considered successful once it is confirmed by half of the nodes in the cluster. - - off: Strong consistency is disabled. In this mode, an operation is considered successful when it is initiated by the local node. - WAL_LEVEL: specifies whether fsync is enabled. The default value is 1. - 1: WAL is enabled but fsync is disabled. - 2: WAL and fsync are both enabled. @@ -71,11 +71,14 @@ database_option: { - SINGLE_STABLE: specifies whether the database can contain more than one supertable. - 0: The database can contain multiple supertables. - 1: The database can contain only one supertable. -- WAL_RETENTION_PERIOD: specifies the time after which WAL files are deleted. This parameter is used for data subscription. Enter a time in seconds. The default value of single copy is 0. A value of 0 indicates that each WAL file is deleted immediately after its contents are written to disk. -1: WAL files are never deleted. The default value of multiple copy is 4 days. -- WAL_RETENTION_SIZE: specifies the size at which WAL files are deleted. This parameter is used for data subscription. Enter a size in KB. The default value of single copy is 0. A value of 0 indicates that each WAL file is deleted immediately after its contents are written to disk. -1: WAL files are never deleted. The default value of multiple copy is -1. -- WAL_ROLL_PERIOD: specifies the time after which WAL files are rotated. After this period elapses, a new WAL file is created. The default value of single copy is 0. A value of 0 indicates that a new WAL file is created only after the previous WAL file was written to disk. The default values of multiple copy is 1 day. -- WAL_SEGMENT_SIZE: specifies the maximum size of a WAL file. After the current WAL file reaches this size, a new WAL file is created. The default value is 0. A value of 0 indicates that a new WAL file is created only after the previous WAL file was written to disk. - +- STT_TRIGGER: specifies the number of file merges triggered by flushed files. The default is 8, ranging from 1 to 16. For high-frequency scenarios with few tables, it is recommended to use the default configuration or a smaller value for this parameter; For multi-table low-frequency scenarios, it is recommended to configure this parameter with a larger value. +- TABLE_PREFIX:The prefix length in the table name that is ignored when distributing table to vnode based on table name. +- TABLE_SUFFIX:The suffix length in the table name that is ignored when distributing table to vnode based on table name. +- TSDB_PAGESIZE: The page size of the data storage engine in a vnode. The unit is KB. The default is 4 KB. The range is 1 to 16384, that is, 1 KB to 16 MB. +- WAL_RETENTION_PERIOD: specifies the maximum time of which WAL files are to be kept for consumption. This parameter is used for data subscription. Enter a time in seconds. The default value 0. A value of 0 indicates that WAL files are not required to keep for consumption. Alter it with a proper value at first to create topics. +- WAL_RETENTION_SIZE: specifies the maximum total size of which WAL files are to be kept for consumption. This parameter is used for data subscription. Enter a size in KB. The default value is 0. A value of 0 indicates that the total size of WAL files to keep for consumption has no upper limit. +- WAL_ROLL_PERIOD: specifies the time after which WAL files are rotated. After this period elapses, a new WAL file is created. The default value is 0. A value of 0 indicates that a new WAL file is created only after TSDB data in memory are flushed to disk. +- WAL_SEGMENT_SIZE: specifies the maximum size of a WAL file. After the current WAL file reaches this size, a new WAL file is created. The default value is 0. A value of 0 indicates that a new WAL file is created only after TSDB data in memory are flushed to disk. ### Example Statement ```sql @@ -112,12 +115,34 @@ alter_database_options: alter_database_option: { CACHEMODEL {'none' | 'last_row' | 'last_value' | 'both'} | CACHESIZE value + | BUFFER value + | PAGES value + | REPLICA value + | STT_TRIGGER value | WAL_LEVEL value | WAL_FSYNC_PERIOD value | KEEP value + | WAL_RETENTION_PERIOD value + | WAL_RETENTION_SIZE value } ``` +### ALTER CACHESIZE + +The command of changing database configuration parameters is easy to use, but it's hard to determine whether a parameter is proper or not. In this section we will describe how to determine whether cachesize is big enough. + +1. How to check cachesize? + +You can use `select * from information_schema.ins_databases;` to get the value of cachesize. + +2. How to check cacheload? + +You can use `show .vgroups;` to check the value of cacheload. + +3. Determine whether cachesize is big engough + +If the value of `cacheload` is very close to the value of `cachesize`, then it's very probably that `cachesize` is too small. If the value of `cacheload` is much smaller than the value of `cachesize`, then `cachesize` is big enough. You can use this simple principle to determine. Depending on how much memory is available in your system, you can choose to double `cachesize` or incrase it by even 5 or more times. + :::note Other parameters cannot be modified after the database has been created. @@ -154,3 +179,27 @@ TRIM DATABASE db_name; ``` The preceding SQL statement deletes data that has expired and orders the remaining data in accordance with the storage configuration. + +## Flush Data + +```sql +FLUSH DATABASE db_name; +``` + +Flush data from memory onto disk. Before shutting down a node, executing this command can avoid data restore after restarting and speed up the startup process. + +## Redistribute Vgroup + +```sql +REDISTRIBUTE VGROUP vgroup_no DNODE dnode_id1 [DNODE dnode_id2] [DNODE dnode_id3] +``` + +Adjust the distribution of vnodes in the vgroup according to the given list of dnodes. + +## Balance Vgroup + +```sql +BALANCE VGROUP +``` + +Automatically adjusts the distribution of vnodes in all vgroups of the cluster, which is equivalent to load balancing the data of the cluster at the vnode level. diff --git a/docs/en/12-taos-sql/03-table.md b/docs/en/12-taos-sql/03-table.md index 6d12b8c73056d049997a244ed0ab788742094d65..f61d1f51471bf042aea79023bff4f74c43831eb8 100644 --- a/docs/en/12-taos-sql/03-table.md +++ b/docs/en/12-taos-sql/03-table.md @@ -1,5 +1,6 @@ --- title: Table +description: This document describes how to create and perform operations on standard tables and subtables. --- ## Create Table diff --git a/docs/en/12-taos-sql/04-stable.md b/docs/en/12-taos-sql/04-stable.md index 8a7c713f8cad6d61c8b098583cc4e282b00d48cf..a1d103eaf04a30214a8c1ef88e43a949710bcdbc 100644 --- a/docs/en/12-taos-sql/04-stable.md +++ b/docs/en/12-taos-sql/04-stable.md @@ -1,6 +1,7 @@ --- -sidebar_label: Supertable title: Supertable +sidebar_label: Supertable +description: This document describes how to create and perform operations on supertables. --- ## Create a Supertable @@ -12,12 +13,11 @@ create_definition: col_name column_definition column_definition: - type_name [COMMENT 'string_value'] + type_name ``` **More explanations** - Each supertable can have a maximum of 4096 columns, including tags. The minimum number of columns is 3: a timestamp column used as the key, one tag column, and one data column. -- When you create a supertable, you can add comments to columns and tags. - The TAGS keyword defines the tag columns for the supertable. The following restrictions apply to tag columns: - A tag column can use the TIMESTAMP data type, but the values in the column must be fixed numbers. Timestamps including formulae, such as "now + 10s", cannot be stored in a tag column. - The name of a tag column cannot be the same as the name of any other column. @@ -33,7 +33,7 @@ column_definition: SHOW STABLES [LIKE tb_name_wildcard]; ``` -The preceding SQL statement shows all supertables in the current TDengine database, including the name, creation time, number of columns, number of tags, and number of subtabels for each supertable. +The preceding SQL statement shows all supertables in the current TDengine database, including the name, creation time, number of columns, number of tags, and number of subtables for each supertable. ### View the CREATE Statement for a Supertable diff --git a/docs/en/12-taos-sql/05-insert.md b/docs/en/12-taos-sql/05-insert.md index 9141211db5239cb6a035f4a01a831adf9f50aa77..c22357abfa1c9e2a4dece880c407cb4bbfdaa055 100644 --- a/docs/en/12-taos-sql/05-insert.md +++ b/docs/en/12-taos-sql/05-insert.md @@ -1,6 +1,7 @@ --- -sidebar_label: Insert title: Insert +sidebar_label: Insert +description: This document describes how to insert data into TDengine. --- ## Syntax @@ -27,7 +28,7 @@ INSERT INTO tb_name [(field1_name, ...)] subquery 2. The precision of a timestamp depends on its format. The precision configured for the database affects only timestamps that are inserted as long integers (UNIX time). Timestamps inserted as date and time strings are not affected. As an example, the timestamp 2021-07-13 16:16:48 is equivalent to 1626164208 in UNIX time. This UNIX time is modified to 1626164208000 for databases with millisecond precision, 1626164208000000 for databases with microsecond precision, and 1626164208000000000 for databases with nanosecond precision. 3. If you want to insert multiple rows simultaneously, do not use the NOW function in the timestamp. Using the NOW function in this situation will cause multiple rows to have the same timestamp and prevent them from being stored correctly. This is because the NOW function obtains the current time on the client, and multiple instances of NOW in a single statement will return the same time. - The earliest timestamp that you can use when inserting data is equal to the current time on the server minus the value of the KEEP parameter. The latest timestamp that you can use when inserting data is equal to the current time on the server plus the value of the DURATION parameter. You can configure the KEEP and DURATION parameters when you create a database. The default values are 3650 days for the KEEP parameter and 10 days for the DURATION parameter. + The earliest timestamp that you can use when inserting data is equal to the current time on the server minus the value of the KEEP parameter (You can configure the KEEP parameter when you create a database and the default value is 3650 days). The latest timestamp you can use when inserting data depends on the PRECISION parameter (You can configure the PRECISION parameter when you create a database, ms means milliseconds, us means microseconds, ns means nanoseconds, and the default value is milliseconds). If the timestamp precision is milliseconds or microseconds, the latest timestamp is the Unix epoch (January 1st, 1970 at 00:00:00.000 UTC) plus 1000 years, that is, January 1st, 2970 at 00:00:00.000 UTC; If the timestamp precision is nanoseconds, the latest timestamp is the Unix epoch plus 292 years, that is, January 1st, 2262 at 00:00:00.000000000 UTC. **Syntax** diff --git a/docs/en/12-taos-sql/06-select.md b/docs/en/12-taos-sql/06-select.md index 485779f55f292f04ecebfc75dd82ddfa240d98bf..de7294f7a9dbc78b854dffa25ffd0e7edd7e7b66 100644 --- a/docs/en/12-taos-sql/06-select.md +++ b/docs/en/12-taos-sql/06-select.md @@ -1,6 +1,7 @@ --- -sidebar_label: Select title: Select +sidebar_label: Select +description: This document describes how to query data in TDengine. --- ## Syntax @@ -247,13 +248,13 @@ You can also use the NULLS keyword to specify the position of null values. Ascen The LIMIT keyword controls the number of results that are displayed. You can also use the OFFSET keyword to specify the result to display first. `LIMIT` and `OFFSET` are executed after `ORDER BY` in the query execution. You can include an offset in a LIMIT clause. For example, LIMIT 5 OFFSET 2 can also be written LIMIT 2, 5. Both of these clauses display the third through the seventh results. -In a statement that includes a PARTITON BY clause, the LIMIT keyword is performed on each partition, not on the entire set of results. +In a statement that includes a PARTITION BY/GROUP BY clause, the LIMIT keyword is performed on each partition/group, not on the entire set of results. ## SLIMIT -The SLIMIT keyword is used with a PARTITION BY clause to control the number of partitions that are displayed. You can include an offset in a SLIMIT clause. For example, SLIMIT 5 OFFSET 2 can also be written LIMIT 2, 5. Both of these clauses display the third through the seventh partitions. +The SLIMIT keyword is used with a PARTITION BY/GROUP BY clause to control the number of partitions/groups that are displayed. You can include an offset in a SLIMIT clause. For example, SLIMIT 5 OFFSET 2 can also be written LIMIT 2, 5. Both of these clauses display the third through the seventh partitions/groups. -Note: If you include an ORDER BY clause, only one partition can be displayed. +Note: If you include an ORDER BY clause, only one partition/group can be displayed. ## Special Query @@ -354,9 +355,9 @@ SELECT AVG(CASE WHEN voltage < 200 or voltage > 250 THEN 220 ELSE voltage END) F ## JOIN -TDengine supports natural joins between supertables, between standard tables, and between subqueries. The difference between natural joins and inner joins is that natural joins require that the fields being joined in the supertables or standard tables must have the same name. Data or tag columns must be joined with the equivalent column in another table. +TDengine supports the `INTER JOIN` based on the timestamp primary key, that is, the `JOIN` condition must contain the timestamp primary key. As long as the requirement of timestamp-based primary key is met, `INTER JOIN` can be made between normal tables, sub-tables, super tables and sub-queries at will, and there is no limit on the number of tables. -For standard tables, only the timestamp (primary key) can be used in join operations. For example: +For standard tables: ```sql SELECT * @@ -364,7 +365,7 @@ FROM temp_tb_1 t1, pressure_tb_1 t2 WHERE t1.ts = t2.ts ``` -For supertables, tags as well as timestamps can be used in join operations. For example: +For supertables: ```sql SELECT * @@ -372,20 +373,15 @@ FROM temp_stable t1, temp_stable t2 WHERE t1.ts = t2.ts AND t1.deviceid = t2.deviceid AND t1.status=0; ``` -Similarly, join operations can be performed on the result sets of multiple subqueries. - -:::note - -The following restriction apply to JOIN statements: +For sub-table and super table: -- The number of tables or supertables in a single join operation cannot exceed 10. -- `FILL` cannot be used in a JOIN statement. -- Arithmetic operations cannot be performed on the result sets of join operation. -- `GROUP BY` is not allowed on a segment of the tables that participate in a join operation. -- `OR` cannot be used in the conditions for join operation -- Join operation can be performed only on tags or timestamps. You cannot perform a join operation on data columns. +```sql +SELECT * +FROM temp_ctable t1, temp_stable t2 +WHERE t1.ts = t2.ts AND t1.deviceid = t2.deviceid AND t1.status=0; +``` -::: +Similarly, join operations can be performed on the result sets of multiple subqueries. ## Nested Query diff --git a/docs/en/12-taos-sql/07-tag-index.md b/docs/en/12-taos-sql/07-tag-index.md new file mode 100644 index 0000000000000000000000000000000000000000..cb2a61d3e813ad130476f8f3309d30b7e208a009 --- /dev/null +++ b/docs/en/12-taos-sql/07-tag-index.md @@ -0,0 +1,51 @@ +--- +sidebar_label: Tag Index +title: Tag Index +description: Use Tag Index to Improve Query Performance +--- + +## Introduction + +Prior to TDengine 3.0.3.0 (excluded),only one index is created by default on the first tag of each super talbe, but it's not allowed to dynamically create index on any other tags. From version 3.0.30, you can dynamically create index on any tag of any type. The index created automatically by TDengine is still valid. Query performance can benefit from indexes if you use properly. + +## Syntax + +1. The syntax of creating an index + +```sql +CREATE INDEX index_name ON tbl_name (tagColName) +``` + +In the above statement, `index_name` if the name of the index, `tbl_name` is the name of the super table,`tagColName` is the name of the tag on which the index is being created. `tagColName` can be any type supported by TDengine. + +2. The syntax of drop an index + +```sql +DROP INDEX index_name +``` + +In the above statement, `index_name` is the name of an existing index. If the index doesn't exist, the command would fail but doesn't generate any impact to the system. + +3. The syntax of show indexes in the system + +```sql +SELECT * FROM information_schema.INS_INDEXES +``` + +You can also add filter conditions to limit the results. + +## Detailed Specification + +1. Indexes can improve query performance significantly if they are used properly. The operators supported by tag index include `=`, `>`, `>=`, `<`, `<=`. If you use these operators with tags, indexes can improve query performance significantly. However, for operators not in this scope, indexes don't help. More and more operators will be added in future. + +2. Only one index can be created on each tag, error would be reported if you try to create more than one indexes on same tag. + +3. Each time you can create an index on a single tag, you are not allowed to create indexes on multiple tags together. + +4. The name of each index must be unique across the whole system, regardless of the type of the index, e.g. tag index or sma index. + +5. There is no limit on the number of indexes, but each index may add some burden on the metadata subsystem. So too many indexes may decrease the efficiency of reading or writing metadata and then decrease the system performance. So it's better not to add unnecessary indexes. + +6. You can' create index on a normal table or a child table. + +7. If the unique values of a tag column are too few, it's better not to create index on such tag columns, the benefit would be very small. \ No newline at end of file diff --git a/docs/en/12-taos-sql/08-delete-data.mdx b/docs/en/12-taos-sql/08-delete-data.mdx index 999c467ad05b6d3e349e322141acfb02a49de5ff..f91a89a7ebe86a7699f5c9a3fd6d3bca200c1445 100644 --- a/docs/en/12-taos-sql/08-delete-data.mdx +++ b/docs/en/12-taos-sql/08-delete-data.mdx @@ -1,7 +1,7 @@ --- -sidebar_label: Delete Data -description: "Delete data from table or Stable" title: Delete Data +sidebar_label: Delete Data +description: This document describes how to delete data from TDengine. --- TDengine provides the functionality of deleting data from a table or STable according to specified time range, it can be used to cleanup abnormal data generated due to device failure. diff --git a/docs/en/12-taos-sql/10-function.md b/docs/en/12-taos-sql/10-function.md index 8ab5176aab0a3cd9a2dc4395febbf6ddc8f595f3..8dfa9c2851c16ac16d43559555e492991b44dd15 100644 --- a/docs/en/12-taos-sql/10-function.md +++ b/docs/en/12-taos-sql/10-function.md @@ -1,6 +1,7 @@ --- -sidebar_label: Functions title: Functions +sidebar_label: Functions +description: This document describes the standard SQL functions available in TDengine. toc_max_heading_level: 4 --- @@ -665,13 +666,13 @@ If you input a specific column, the number of non-null values in the column is r ELAPSED(ts_primary_key [, time_unit]) ``` -**Description**:`elapsed` function can be used to calculate the continuous time length in which there is valid data. If it's used with `INTERVAL` clause, the returned result is the calcualted time length within each time window. If it's used without `INTERVAL` caluse, the returned result is the calculated time length within the specified time range. Please be noted that the return value of `elapsed` is the number of `time_unit` in the calculated time length. +**Description**:`elapsed` function can be used to calculate the continuous time length in which there is valid data. If it's used with `INTERVAL` clause, the returned result is the calculated time length within each time window. If it's used without `INTERVAL` caluse, the returned result is the calculated time length within the specified time range. Please be noted that the return value of `elapsed` is the number of `time_unit` in the calculated time length. **Return value type**: Double if the input value is not NULL; **Return value type**: TIMESTAMP -**Applicable tables**: table, STable, outter in nested query +**Applicable tables**: table, STable, outer in nested query **Explanations**: - `ts_primary_key` parameter can only be the first column of a table, i.e. timestamp primary key. @@ -753,7 +754,7 @@ HYPERLOGLOG(expr) **Description**: The cardinal number of a specific column is returned by using hyperloglog algorithm. The benefit of using hyperloglog algorithm is that the memory usage is under control when the data volume is huge. - However, when the data volume is very small, the result may be not accurate, it's recommented to use `select count(data) from (select unique(col) as data from table)` in this case. + However, when the data volume is very small, the result may be not accurate, it's recommended to use `select count(data) from (select unique(col) as data from table)` in this case. **Return value type**: Integer @@ -795,19 +796,23 @@ HISTOGRAM(expr,bin_type, bin_description, normalized) ### PERCENTILE ```sql -PERCENTILE(expr, p) +PERCENTILE(expr, p [, p1] ...) ``` **Description**: The value whose rank in a specific column matches the specified percentage. If such a value matching the specified percentage doesn't exist in the column, an interpolation value will be returned. -**Return value type**: DOUBLE +**Return value type**: This function takes 2 minimum and 11 maximum parameters, and it can simultaneously return 10 percentiles at most. If 2 parameters are given, a single percentile is returned and the value type is DOUBLE. + If more than 2 parameters are given, the return value type is a VARCHAR string, the format of which is a JSON ARRAY containing all return values. **Applicable column types**: Numeric **Applicable table types**: table only -**More explanations**: _p_ is in range [0,100], when _p_ is 0, the result is same as using function MIN; when _p_ is 100, the result is same as function MAX. +**More explanations**: +- _p_ is in range [0,100], when _p_ is 0, the result is same as using function MIN; when _p_ is 100, the result is same as function MAX. +- When calculating multiple percentiles of a specific column, a single PERCENTILE function with multiple parameters is advised, as this can largely reduce the query response time. + For example, using SELECT percentile(col, 90, 95, 99) FROM table will perform better than SELECT percentile(col, 90), percentile(col, 95), percentile(col, 99) from table. ## Selection Functions @@ -876,7 +881,17 @@ INTERP(expr) - The number of rows in the result set of `INTERP` is determined by the parameter `EVERY(time_unit)`. Starting from timestamp1, one interpolation is performed for every time interval specified `time_unit` parameter. The parameter `time_unit` must be an integer, with no quotes, with a time unit of: a(millisecond)), s(second), m(minute), h(hour), d(day), or w(week). For example, `EVERY(500a)` will interpolate every 500 milliseconds. - Interpolation is performed based on `FILL` parameter. For more information about FILL clause, see [FILL Clause](../distinguished/#fill-clause). - `INTERP` can only be used to interpolate in single timeline. So it must be used with `partition by tbname` when it's used on a STable. -- Pseudo column `_irowts` can be used along with `INTERP` to return the timestamps associated with interpolation points(support after version 3.0.1.4). +- Pseudocolumn `_irowts` can be used along with `INTERP` to return the timestamps associated with interpolation points(support after version 3.0.2.0). +- Pseudocolumn `_isfilled` can be used along with `INTERP` to indicate whether the results are original records or data points generated by interpolation algorithm(support after version 3.0.3.0). + +**Example** + +- We use the smart meters example used in this documentation to illustrate how to use the INTERP function. +- We want to downsample every 1 hour and use a linear fill for missing values. Note the order in which the "partition by" clause and the "range", "every" and "fill" parameters are used. + +```sql +SELECT _irowts,INTERP(current) FROM test.meters PARTITION BY TBNAME RANGE('2017-07-22 00:00:00','2017-07-24 12:25:00') EVERY(1h) FILL(LINEAR) +``` ### LAST diff --git a/docs/en/12-taos-sql/12-distinguished.md b/docs/en/12-taos-sql/12-distinguished.md index 0763e85a53bc6021a2fe28d7df20f627d1b3fbe7..01d7065905359dd312346f54293c5cf8d8f04afb 100644 --- a/docs/en/12-taos-sql/12-distinguished.md +++ b/docs/en/12-taos-sql/12-distinguished.md @@ -1,6 +1,7 @@ --- -sidebar_label: Time-Series Extensions title: Time-Series Extensions +sidebar_label: Time-Series Extensions +description: This document describes the extended functions specific to time-series data processing available in TDengine. --- As a purpose-built database for storing and processing time-series data, TDengine provides time-series-specific extensions to standard SQL. @@ -20,7 +21,7 @@ part_list can be any scalar expression, such as a column, constant, scalar funct A PARTITION BY clause is processed as follows: - The PARTITION BY clause must occur after the WHERE clause -- The PARTITION BY caluse partitions the data according to the specified dimentions, then perform computation on each partition. The performed computation is determined by the rest of the statement - a window clause, GROUP BY clause, or SELECT clause. +- The PARTITION BY caluse partitions the data according to the specified dimensions, then perform computation on each partition. The performed computation is determined by the rest of the statement - a window clause, GROUP BY clause, or SELECT clause. - The PARTITION BY clause can be used together with a window clause or GROUP BY clause. In this case, the window or GROUP BY clause takes effect on every partition. For example, the following statement partitions the table by the location tag, performs downsampling over a 10 minute window, and returns the maximum value: ```sql @@ -31,15 +32,15 @@ The most common usage of PARTITION BY is partitioning the data in subtables by t ## Windowed Queries -Aggregation by time window is supported in TDengine. For example, in the case where temperature sensors report the temperature every seconds, the average temperature for every 10 minutes can be retrieved by performing a query with a time window. Window related clauses are used to divide the data set to be queried into subsets and then aggregation is performed across the subsets. There are three kinds of windows: time window, status window, and session window. There are two kinds of time windows: sliding window and flip time/tumbling window. The query syntax is as follows: +Aggregation by time window is supported in TDengine. For example, in the case where temperature sensors report the temperature every seconds, the average temperature for every 10 minutes can be retrieved by performing a query with a time window. Window related clauses are used to divide the data set to be queried into subsets and then aggregation is performed across the subsets. There are four kinds of windows: time window, status window, session window, and event window. There are two kinds of time windows: sliding window and flip time/tumbling window. The syntax of window clause is as follows: ```sql -SELECT select_list FROM tb_name - [WHERE where_condition] - [SESSION(ts_col, tol_val)] - [STATE_WINDOW(col)] - [INTERVAL(interval [, offset]) [SLIDING sliding]] - [FILL({NONE | VALUE | PREV | NULL | LINEAR | NEXT})] +window_clause: { + SESSION(ts_col, tol_val) + | STATE_WINDOW(col) + | INTERVAL(interval [, offset]) [SLIDING sliding] [FILL({NONE | VALUE | PREV | NULL | LINEAR | NEXT})] + | EVENT_WINDOW START WITH start_trigger_condition END WITH end_trigger_condition +} ``` The following restrictions apply: @@ -74,6 +75,16 @@ These pseudocolumns occur after the aggregation clause. 5. LINEAR:Fill with the closest non-NULL value, `FILL(LINEAR)` 6. NEXT:Fill with the next non-NULL value, `FILL(NEXT)` +In the above filling modes, except for `NONE` mode, the `fill` clause will be ignored if there is no data in the defined time range, i.e. no data would be filled and the query result would be empty. This behavior is reasonable when the filling mode is `PREV`, `NEXT`, `LINEAR`, because filling can't be performed if there is not any data. For filling modes `NULL` and `VALUE`, however, filling can be performed even though there is not any data, filling or not depends on the choice of user's application. To accomplish the need of this force filling behavior and not break the behavior of existing filling modes, TDengine added two new filling modes since version 3.0.3.0. + +1. NULL_F: Fill `NULL` by force +2. VALUE_F: Fill `VALUE` by force + +The detailed beaviors of `NULL`, `NULL_F`, `VALUE`, and VALUE_F are described below: +- When used with `INTERVAL`: `NULL_F` and `VALUE_F` are filling by force;`NULL` and `VALUE` don't fill by force. The behavior of each filling mode is exactly same as what the name suggests. +- When used with `INTERVAL` in stream processing: `NULL_F` and `NULL` are same, i.e. don't fill by force; `VALUE_F` and `VALUE` and same, i.e. don't fill by force. It's suggested that there is no filling by force in stream processing. +- When used with `INTERP`: `NULL` and `NULL_F` and same, i.e. filling by force; `VALUE` and `VALUE_F` are same, i.e. filling by force. It's suggested that there is always filling by force when used with `INTERP`. + :::info 1. A huge volume of interpolation output may be returned using `FILL`, so it's recommended to specify the time range when using `FILL`. The maximum number of interpolation values that can be returned in a single query is 10,000,000. @@ -104,7 +115,7 @@ SELECT COUNT(*) FROM temp_tb_1 INTERVAL(1m) SLIDING(2m); When using time windows, note the following: -- The window length for aggregation depends on the value of INTERVAL. The minimum interval is 10 ms. You can configure a window as an offset from UTC 0:00. The offset cannot be smaler than the interval. You can use SLIDING to specify the length of time that the window moves forward. +- The window length for aggregation depends on the value of INTERVAL. The minimum interval is 10 ms. You can configure a window as an offset from UTC 0:00. The offset cannot be smaller than the interval. You can use SLIDING to specify the length of time that the window moves forward. Please note that the `timezone` parameter should be configured to be the same value in the `taos.cfg` configuration file on client side and server side. - The result set is in ascending order of timestamp when you aggregate by time window. @@ -145,6 +156,26 @@ If the time interval between two continuous rows are within the time interval sp SELECT COUNT(*), FIRST(ts) FROM temp_tb_1 SESSION(ts, tol_val); ``` +### Event Window + +Event window is determined according to the window start condition and the window close condition. The window is started when `start_trigger_condition` is evaluated to true, the window is closed when `end_trigger_condition` is evaluated to true. `start_trigger_condition` and `end_trigger_condition` can be any conditional expressions supported by TDengine and can include multiple columns. + +There may be only one row of data in an event window, when a row meets both the `start_trigger_condition` and the `end_trigger_condition`. + +The window is treated as invalid or non-existing if the `end_trigger_condition` can't be met. There will be no output in case that a window can't be closed. + +If the event window query is performed on a super table, TDengine consolidates all the data of all child tables into a single timeline then perform event window based query. + +If you want to perform event window based query on the result set of a sub-query, the result set of the sub-query should be arranged in the order of timestamp and include the column of timestamp. + +For example, the diagram below illustrates the event windows generated by the query below: + +```sql +select _wstart, _wend, count(*) from t event_window start with c1 > 0 end with c2 < 10 +``` + +![Event Window Illustration](./event_window.webp) + ### Examples A table of intelligent meters can be created by the SQL statement below: diff --git a/docs/en/12-taos-sql/13-tmq.md b/docs/en/12-taos-sql/13-tmq.md index befab4f4f01e595564e93ffcfbb0723e13294af0..1a805c76fb8e51ad22dd4e8b090860a6e1730a24 100644 --- a/docs/en/12-taos-sql/13-tmq.md +++ b/docs/en/12-taos-sql/13-tmq.md @@ -1,6 +1,7 @@ --- -sidebar_label: Data Subscription title: Data Subscription +sidebar_label: Data Subscription +description: This document describes the SQL statements related to the data subscription component of TDengine. --- The information in this document is related to the TDengine data subscription feature. diff --git a/docs/en/12-taos-sql/14-stream.md b/docs/en/12-taos-sql/14-stream.md index c47d2da0ebf8b8d3ecc2e51fad659ceb423ad46f..b8f6c3a163e1c2fa37e437725652eabb1a71dbe6 100644 --- a/docs/en/12-taos-sql/14-stream.md +++ b/docs/en/12-taos-sql/14-stream.md @@ -1,6 +1,7 @@ --- -sidebar_label: Stream Processing title: Stream Processing +sidebar_label: Stream Processing +description: This document describes the SQL statements related to the stream processing component of TDengine. --- Raw time-series data is often cleaned and preprocessed before being permanently stored in a database. Stream processing components like Kafka, Flink, and Spark are often deployed alongside a time-series database to handle these operations, increasing system complexity and maintenance costs. @@ -108,7 +109,7 @@ SHOW STREAMS; When you create a stream, you can use the TRIGGER parameter to specify triggering conditions for it. -For non-windowed processing, triggering occurs in real time. For windowed processing, there are three methods of triggering: +For non-windowed processing, triggering occurs in real time. For windowed processing, there are three methods of triggering,the default value is AT_ONCE: 1. AT_ONCE: triggers on write diff --git a/docs/en/12-taos-sql/16-operators.md b/docs/en/12-taos-sql/16-operators.md index c426e2879342e430c61c4f8133aa9f8186888941..32ad4e7075b6a510cb537016effb6064e6c51794 100644 --- a/docs/en/12-taos-sql/16-operators.md +++ b/docs/en/12-taos-sql/16-operators.md @@ -1,6 +1,7 @@ --- -sidebar_label: Operators title: Operators +sidebar_label: Operators +description: This document describes the SQL operators available in TDengine. --- ## Arithmetic Operators diff --git a/docs/en/12-taos-sql/17-json.md b/docs/en/12-taos-sql/17-json.md index 77f774303316b466a15226f548f84da69be8f92d..843858c0c76211346278fc078e7d04de5adecd7f 100644 --- a/docs/en/12-taos-sql/17-json.md +++ b/docs/en/12-taos-sql/17-json.md @@ -1,6 +1,7 @@ --- -sidebar_label: JSON Type title: JSON Type +sidebar_label: JSON Type +description: This document describes the JSON data type in TDengine. --- @@ -54,7 +55,7 @@ title: JSON Type 4. Tag Operations - The value of a JSON tag can be altered. Please note that the full JSON will be overriden when doing this. + The value of a JSON tag can be altered. Please note that the full JSON will be overridden when doing this. The name of a JSON tag can be altered. diff --git a/docs/en/12-taos-sql/18-escape.md b/docs/en/12-taos-sql/18-escape.md index a2ae40de98be677e599e83a634952a39faeaafbf..85e4610e44f1a6f93e9727c32f8333cddf07ecc7 100644 --- a/docs/en/12-taos-sql/18-escape.md +++ b/docs/en/12-taos-sql/18-escape.md @@ -1,5 +1,6 @@ --- title: Escape Characters +description: This document describes the usage of escape characters in TDengine. --- ## Escape Characters diff --git a/docs/en/12-taos-sql/19-limit.md b/docs/en/12-taos-sql/19-limit.md index f00ec90f5755d3d004a35b210f93560c6f719536..654fae7560d3c24df1353b87952a3868ca307418 100644 --- a/docs/en/12-taos-sql/19-limit.md +++ b/docs/en/12-taos-sql/19-limit.md @@ -1,6 +1,7 @@ --- -sidebar_label: Name and Size Limits title: Name and Size Limits +sidebar_label: Name and Size Limits +description: This document describes the name and size limits in TDengine. --- ## Naming Rules diff --git a/docs/en/12-taos-sql/20-keywords.md b/docs/en/12-taos-sql/20-keywords.md index 4b479b866b77e1e354d20376ccb869755af76d00..a2191c87ee17444d5341b8e97b33a954be84dc98 100644 --- a/docs/en/12-taos-sql/20-keywords.md +++ b/docs/en/12-taos-sql/20-keywords.md @@ -1,6 +1,7 @@ --- -sidebar_label: Reserved Keywords title: Reserved Keywords +sidebar_label: Reserved Keywords +description: This document describes the reserved keywords in TDengine that cannot be used in object names. --- ## Keyword List @@ -17,6 +18,7 @@ The following list shows all reserved keywords: - ADD - AFTER - AGGREGATE +- ALIVE - ALL - ALTER - ANALYZE diff --git a/docs/en/12-taos-sql/21-node.md b/docs/en/12-taos-sql/21-node.md index a0d49ab208448fa9dd90ef63deb235ef051b0e19..8a5069e66f5111c3c362829cfd654f16a80b60c7 100644 --- a/docs/en/12-taos-sql/21-node.md +++ b/docs/en/12-taos-sql/21-node.md @@ -1,6 +1,7 @@ --- -sidebar_label: Cluster title: Cluster +sidebar_label: Cluster +description: This document describes the SQL statements related to cluster management in TDengine. --- The physical entities that form TDengine clusters are known as data nodes (dnodes). Each dnode is a process running on the operating system of the physical machine. Dnodes can contain virtual nodes (vnodes), which store time-series data. Virtual nodes are formed into vgroups, which have 1 or 3 vnodes depending on the replica setting. If you want to enable replication on your cluster, it must contain at least three nodes. Dnodes can also contain management nodes (mnodes). Each cluster has up to three mnodes. Finally, dnodes can contain query nodes (qnodes), which compute time-series data, thus separating compute from storage. A single dnode can contain a vnode, qnode, and mnode. diff --git a/docs/en/12-taos-sql/22-meta.md b/docs/en/12-taos-sql/22-meta.md index 1cd759742a8714274712343a22cbf723cd9c3212..81284aeaedf89044a4a253e845d70e7fd67f4168 100644 --- a/docs/en/12-taos-sql/22-meta.md +++ b/docs/en/12-taos-sql/22-meta.md @@ -1,6 +1,7 @@ --- -sidebar_label: Metadata title: Information_Schema Database +sidebar_label: Metadata +description: This document describes how to use the INFORMATION_SCHEMA database in TDengine. --- TDengine includes a built-in database named `INFORMATION_SCHEMA` to provide access to database metadata, system information, and status information. This information includes database names, table names, and currently running SQL statements. All information related to TDengine maintenance is stored in this database. It contains several read-only tables. These tables are more accurately described as views, and they do not correspond to specific files. You can query these tables but cannot write data to them. The INFORMATION_SCHEMA database is intended to provide a unified method for SHOW commands to access data. However, using SELECT ... FROM INFORMATION_SCHEMA.tablename offers several advantages over SHOW commands: @@ -178,6 +179,20 @@ Provides information about standard tables and subtables. | 5 | tag_type | BINARY(64) | Tag type | | 6 | tag_value | BINARY(16384) | Tag value | +## INS_COLUMNS + +| # | **列名** | **数据类型** | **说明** | +| --- | :---------: | ------------- | ---------------------- | +| 1 | table_name | BINARY(192) | Table name | +| 2 | db_name | BINARY(64) | Database name | +| 3 | table_type | BINARY(21) | Table type | +| 4 | col_name | BINARY(64) | Column name | +| 5 | col_type | BINARY(32) | Column type | +| 6 | col_length | INT | Column length | +| 7 | col_precision | INT | Column precision | +| 8 | col_scale | INT | Column scale | +| 9 | col_nullable | INT | Column nullable | + ## INS_USERS Provides information about TDengine users. @@ -273,9 +288,9 @@ Provides dnode configuration information. | 1 | stream_name | BINARY(64) | Stream name | | 2 | create_time | TIMESTAMP | Creation time | | 3 | sql | BINARY(1024) | SQL statement used to create the stream | -| 4 | status | BIANRY(20) | Current status | +| 4 | status | BINARY(20) | Current status | | 5 | source_db | BINARY(64) | Source database | -| 6 | target_db | BIANRY(64) | Target database | +| 6 | target_db | BINARY(64) | Target database | | 7 | target_table | BINARY(192) | Target table | | 8 | watermark | BIGINT | Watermark (see stream processing documentation). It should be noted that `watermark` is a TDengine keyword and needs to be escaped with ` when used as a column name. | | 9 | trigger | INT | Method of triggering the result push (see stream processing documentation). It should be noted that `trigger` is a TDengine keyword and needs to be escaped with ` when used as a column name. | diff --git a/docs/en/12-taos-sql/23-perf.md b/docs/en/12-taos-sql/23-perf.md index 29cf3af6abfbbc06e42ae99c78f35f33a3c7c30a..fc369ec663cf9130bd7d1af650f1f47a1054fad6 100644 --- a/docs/en/12-taos-sql/23-perf.md +++ b/docs/en/12-taos-sql/23-perf.md @@ -1,6 +1,7 @@ --- -sidebar_label: Statistics title: Performance_Schema Database +sidebar_label: Statistics +description: This document describes how to use the PERFORMANCE_SCHEMA database in TDengine. --- TDengine includes a built-in database named `PERFORMANCE_SCHEMA` to provide access to database performance statistics. This document introduces the tables of PERFORMANCE_SCHEMA and their structure. diff --git a/docs/en/12-taos-sql/24-show.md b/docs/en/12-taos-sql/24-show.md index 1bda4a118d796765f2dab6f5fdeae27a58cdd232..1f340cab306e22312a940d830281d9f390648da4 100644 --- a/docs/en/12-taos-sql/24-show.md +++ b/docs/en/12-taos-sql/24-show.md @@ -1,9 +1,10 @@ --- -sidebar_label: SHOW Statement title: SHOW Statement for Metadata +sidebar_label: SHOW Statement +description: This document describes how to use the SHOW statement in TDengine. --- -`SHOW` command can be used to get brief system information. To get details about metatadata, information, and status in the system, please use `select` to query the tables in database `INFORMATION_SCHEMA`. +`SHOW` command can be used to get brief system information. To get details about metadata, information, and status in the system, please use `select` to query the tables in database `INFORMATION_SCHEMA`. ## SHOW APPS @@ -85,10 +86,10 @@ SHOW FUNCTIONS; Shows all user-defined functions in the system. -## SHOW LICENSE +## SHOW LICENCES ```sql -SHOW LICENSE; +SHOW LICENCES; SHOW GRANTS; ``` @@ -178,6 +179,141 @@ SHOW TABLE DISTRIBUTED table_name; Shows how table data is distributed. +Examples: Below is an example of this command to display the block distribution of table `d0` in detailed format. + +```sql +show table distributed d0\G; +``` + +
+ Show Example +

+*************************** 1.row ***************************
+_block_dist: Total_Blocks=[5] Total_Size=[93.65 KB] Average_size=[18.73 KB] Compression_Ratio=[23.98 %]
+
+Total_Blocks :  Table `d0` contains total 5 blocks
+
+Total_Size:  The total size of all the data blocks in table `d0` is 93.65 KB 
+
+Average_size:  The average size of each block is 18.73 KB
+
+Compression_Ratio: The data compression rate is 23.98%
+ 
+*************************** 2.row ***************************
+_block_dist: Total_Rows=[20000] Inmem_Rows=[0] MinRows=[3616] MaxRows=[4096] Average_Rows=[4000]
+
+Total_Rows: Table `d0` contains 20,000 rows
+
+Inmem_Rows: The rows still in memory, i.e. not committed in disk, is 0, i.e. none such rows
+
+MinRows:  The minimum number of rows in a block is 3,616 
+
+MaxRows: The maximum number of rows in a block is 4,096B
+
+Average_Rows: The average number of rows in a block is 4,000
+
+*************************** 3.row ***************************
+_block_dist: Total_Tables=[1] Total_Files=[2]
+
+Total_Tables:  The number of child tables, 1 in this example
+
+Total_Files:   The number of files storing the table's data, 2 in this example
+
+*************************** 4.row ***************************
+
+_block_dist: --------------------------------------------------------------------------------
+
+*************************** 5.row ***************************
+
+_block_dist: 0100 |
+
+*************************** 6.row ***************************
+
+_block_dist: 0299 |
+
+*************************** 7.row ***************************
+
+_block_dist: 0498 |
+
+*************************** 8.row ***************************
+
+_block_dist: 0697 |
+
+*************************** 9.row ***************************
+
+_block_dist: 0896 |
+
+*************************** 10.row ***************************
+
+_block_dist: 1095 |
+
+*************************** 11.row ***************************
+
+_block_dist: 1294 |
+
+*************************** 12.row ***************************
+
+_block_dist: 1493 |
+
+*************************** 13.row ***************************
+
+_block_dist: 1692 |
+
+*************************** 14.row ***************************
+
+_block_dist: 1891 |
+
+*************************** 15.row ***************************
+
+_block_dist: 2090 |
+
+*************************** 16.row ***************************
+
+_block_dist: 2289 |
+
+*************************** 17.row ***************************
+
+_block_dist: 2488 |
+
+*************************** 18.row ***************************
+
+_block_dist: 2687 |
+
+*************************** 19.row ***************************
+
+_block_dist: 2886 |
+
+*************************** 20.row ***************************
+
+_block_dist: 3085 |
+
+*************************** 21.row ***************************
+
+_block_dist: 3284 |
+
+*************************** 22.row ***************************
+
+_block_dist: 3483 |||||||||||||||||  1 (20.00%)
+
+*************************** 23.row ***************************
+
+_block_dist: 3682 |
+
+*************************** 24.row ***************************
+
+_block_dist: 3881 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||  4 (80.00%)
+
+Query OK, 24 row(s) in set (0.002444s)
+
+
+
+ +The above show the block distribution percentage according to the number of rows in each block. In the above example, we can get below information: +- `_block_dist: 3483 ||||||||||||||||| 1 (20.00%)` means there is one block whose rows is between 3,483 and 3,681. +- `_block_dist: 3881 ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 4 (80.00%)` means there are 4 blocks whose rows is between 3,881 and 4,096. - The number of blocks whose rows fall in other range is zero. + +Note that only the information about the data blocks in the data file will be displayed here, and the information about the data in the stt file will not be displayed. + ## SHOW TAGS ```sql @@ -225,12 +361,12 @@ Shows the working configuration of the parameters that must be the same on each SHOW [db_name.]VGROUPS; ``` -Shows information about all vgroups in the system or about the vgroups for a specified database. +Shows information about all vgroups in the current database. ## SHOW VNODES ```sql -SHOW VNODES [dnode_name]; +SHOW VNODES {dnode_id | dnode_endpoint}; ``` Shows information about all vnodes in the system or about the vnodes for a specified dnode. diff --git a/docs/en/12-taos-sql/25-grant.md b/docs/en/12-taos-sql/25-grant.md index f895567c621f123778c8a711a68357a889ca0098..8b4c4393523c90595c7dd5461fc2abc73fa44c93 100644 --- a/docs/en/12-taos-sql/25-grant.md +++ b/docs/en/12-taos-sql/25-grant.md @@ -1,7 +1,7 @@ --- -sidebar_label: Access Control title: User and Access Control -description: Manage user and user's permission +sidebar_label: Access Control +description: This document describes how to manage users and permissions in TDengine. --- This document describes how to manage permissions in TDengine. diff --git a/docs/en/12-taos-sql/26-udf.md b/docs/en/12-taos-sql/26-udf.md index 977f3bcc0844ad63e4d2fe0f28d9ca8f29c5cbd6..cb64873705c471fa23288b604df5c03fcade2ba0 100644 --- a/docs/en/12-taos-sql/26-udf.md +++ b/docs/en/12-taos-sql/26-udf.md @@ -1,6 +1,7 @@ --- -sidebar_label: User-Defined Functions title: User-Defined Functions (UDF) +sidebar_label: User-Defined Functions +description: This document describes the SQL statements related to user-defined functions (UDF) in TDengine. --- You can create user-defined functions and import them into TDengine. @@ -40,7 +41,7 @@ CREATE AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [ ```sql CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 8; ``` -For more information about user-defined functions, see [User-Defined Functions](../../develop/udf). +For more information about user-defined functions, see [User-Defined Functions](/develop/udf). ## Manage UDF diff --git a/docs/en/12-taos-sql/27-index.md b/docs/en/12-taos-sql/27-index.md index 7d09bc43ab06932b82019923d4a8fda48cd99c97..7586e4af76983e785b2c6b3f03870a8bcd6df4a3 100644 --- a/docs/en/12-taos-sql/27-index.md +++ b/docs/en/12-taos-sql/27-index.md @@ -1,6 +1,7 @@ --- -sidebar_label: Index -title: Using Indices +title: Indexing +sidebar_label: Indexing +description: This document describes the SQL statements related to indexing in TDengine. --- TDengine supports SMA and FULLTEXT indexing. diff --git a/docs/en/12-taos-sql/28-recovery.md b/docs/en/12-taos-sql/28-recovery.md index e869ffc45ff7420836d91a2536d32ce6b08a0d82..b4da25ea0c3b4f2758c981ee5bd03985ef3f2754 100644 --- a/docs/en/12-taos-sql/28-recovery.md +++ b/docs/en/12-taos-sql/28-recovery.md @@ -1,6 +1,7 @@ --- -sidebar_label: Error Recovery title: Error Recovery +sidebar_label: Error Recovery +description: This document describes the SQL statements related to error recovery in TDengine. --- In a complex environment, connections and query tasks may encounter errors or fail to return in a reasonable time. If this occurs, you can terminate the connection or task. diff --git a/docs/en/12-taos-sql/29-changes.md b/docs/en/12-taos-sql/29-changes.md index 78b6d5fc05b9b03e1e8b3af268bc357dfaa401bc..f4606f263fbda42e8e221d067912b884a3be4a40 100644 --- a/docs/en/12-taos-sql/29-changes.md +++ b/docs/en/12-taos-sql/29-changes.md @@ -1,7 +1,7 @@ --- -sidebar_label: Changes in TDengine 3.0 title: Changes in TDengine 3.0 -description: "This document explains how TDengine SQL has changed in version 3.0." +sidebar_label: Changes in TDengine 3.0 +description: This document describes how TDengine SQL has changed in version 3.0 compared with previous versions. --- ## Basic SQL Elements @@ -27,7 +27,7 @@ The following data types can be used in the schema for standard tables. | - | :------- | :-------- | :------- | | 1 | ALTER ACCOUNT | Deprecated| This Enterprise Edition-only statement has been removed. It returns the error "This statement is no longer supported." | 2 | ALTER ALL DNODES | Added | Modifies the configuration of all dnodes. -| 3 | ALTER DATABASE | Modified | Deprecated
  • QUORUM: Specified the required number of confirmations. STRICT is now used to specify strong or weak consistency. The STRICT parameter cannot be modified.
  • BLOCKS: Specified the memory blocks used by each vnode. BUFFER is now used to specify the size of the write cache pool for each vnode.
  • UPDATE: Specified whether update operations were supported. All databases now support updating data in certain columns.
  • CACHELAST: Specified how to cache the newest row of data. CACHEMODEL now replaces CACHELAST.
  • COMP: Cannot be modified.
    Added
  • CACHEMODEL: Specifies whether to cache the latest subtable data.
  • CACHESIZE: Specifies the size of the cache for the newest subtable data.
  • WAL_FSYNC_PERIOD: Replaces the FSYNC parameter.
  • WAL_LEVEL: Replaces the WAL parameter.
    Modified
  • REPLICA: Cannot be modified.
  • KEEP: Now supports units.
+| 3 | ALTER DATABASE | Modified | Deprecated
  • QUORUM: Specified the required number of confirmations. TDengine 3.0 provides strict consistency by default and doesn't allow to change to weak consitency.
  • BLOCKS: Specified the memory blocks used by each vnode. BUFFER is now used to specify the size of the write cache pool for each vnode.
  • UPDATE: Specified whether update operations were supported. All databases now support updating data in certain columns.
  • CACHELAST: Specified how to cache the newest row of data. CACHEMODEL now replaces CACHELAST.
  • COMP: Cannot be modified.
    Added
  • CACHEMODEL: Specifies whether to cache the latest subtable data.
  • CACHESIZE: Specifies the size of the cache for the newest subtable data.
  • WAL_FSYNC_PERIOD: Replaces the FSYNC parameter.
  • WAL_LEVEL: Replaces the WAL parameter.
  • WAL_RETENTION_PERIOD: specifies the time after which WAL files are deleted. This parameter is used for data subscription.
  • WAL_RETENTION_SIZE: specifies the size at which WAL files are deleted. This parameter is used for data subscription.
    Modified
  • REPLICA: Cannot be modified.
  • KEEP: Now supports units.
| 4 | ALTER STABLE | Modified | Deprecated
  • CHANGE TAG: Modified the name of a tag. Replaced by RENAME TAG.
    Added
  • RENAME TAG: Replaces CHANGE TAG.
  • COMMENT: Specifies comments for a supertable.
| 5 | ALTER TABLE | Modified | Deprecated
  • CHANGE TAG: Modified the name of a tag. Replaced by RENAME TAG.
    Added
  • RENAME TAG: Replaces CHANGE TAG.
  • COMMENT: Specifies comments for a standard table.
  • TTL: Specifies the time-to-live for a standard table.
| 6 | ALTER USER | Modified | Deprecated
  • PRIVILEGE: Specified user permissions. Replaced by GRANT and REVOKE.
    Added
  • ENABLE: Enables or disables a user.
  • SYSINFO: Specifies whether a user can query system information.
@@ -54,7 +54,6 @@ The following data types can be used in the schema for standard tables. | 27 | GRANT | Added | Grants permissions to a user. | 28 | KILL TRANSACTION | Added | Terminates an mnode transaction. | 29 | KILL STREAM | Deprecated | Terminated a continuous query. The continuous query feature has been replaced with the stream processing feature. -| 30 | MERGE VGROUP | Added | Merges vgroups. | 31 | REVOKE | Added | Revokes permissions from a user. | 32 | SELECT | Modified |
  • SELECT does not use the implicit results column. Output columns must be specified in the SELECT clause.
  • DISTINCT support is enhanced. In previous versions, DISTINCT only worked on the tag column and could not be used with JOIN or GROUP BY.
  • JOIN support is enhanced. The following are now supported after JOIN: a WHERE clause with OR, operations on multiple tables, and GROUP BY on multiple tables.
  • Subqueries after FROM are enhanced. Levels of nesting are no longer restricted. Subqueries can be used with UNION ALL. Other syntax restrictions are eliminated.
  • All scalar functions can be used after WHERE.
  • GROUP BY is enhanced. You can group by any scalar expression or combination thereof.
  • SESSION can be used on supertables. When PARTITION BY is not used, data in supertables is merged into a single timeline.
  • STATE_WINDOW can be used on supertables. When PARTITION BY is not used, data in supertables is merged into a single timeline.
  • ORDER BY is enhanced. It is no longer required to use ORDER BY and GROUP BY together. There is no longer a restriction on the number of order expressions. NULLS FIRST and NULLS LAST syntax has been added. Any expression that conforms to the ORDER BY semantics can be used.
  • Added PARTITION BY syntax. PARTITION BY replaces GROUP BY tags.
| 33 | SHOW ACCOUNTS | Deprecated | This Enterprise Edition-only statement has been removed. It returns the error "This statement is no longer supported." @@ -76,8 +75,9 @@ The following data types can be used in the schema for standard tables. | 49 | SHOW TRANSACTIONS | Added | Shows all running transactions in the system. | 50 | SHOW DNODE VARIABLES | Added | Shows the configuration of the specified dnode. | 51 | SHOW VNODES | Not supported | Shows information about vnodes in the system. Not supported. -| 52 | SPLIT VGROUP | Added | Splits a vgroup into two vgroups. -| 53 | TRIM DATABASE | Added | Deletes data that has expired and orders the remaining data in accordance with the storage configuration. +| 52 | TRIM DATABASE | Added | Deletes data that has expired and orders the remaining data in accordance with the storage configuration. +| 53 | REDISTRIBUTE VGROUP | Added | Adjust the distribution of VNODES in VGROUP. +| 54 | BALANCE VGROUP | Added | Auto adjust the distribution of VNODES in VGROUP. ## SQL Functions diff --git a/docs/en/12-taos-sql/event_window.webp b/docs/en/12-taos-sql/event_window.webp new file mode 100644 index 0000000000000000000000000000000000000000..0a3a344b03194f245aa879b801fa4edb38f85445 Binary files /dev/null and b/docs/en/12-taos-sql/event_window.webp differ diff --git a/docs/en/12-taos-sql/index.md b/docs/en/12-taos-sql/index.md index a5ffc9dc8dce158eccc0fa0519f09ba346710c31..276f84f21bc8ab92d13f1975b298dbdcf25db249 100644 --- a/docs/en/12-taos-sql/index.md +++ b/docs/en/12-taos-sql/index.md @@ -1,6 +1,6 @@ --- title: TDengine SQL -description: 'The syntax supported by TDengine SQL ' +description: This document describes the syntax and functions supported by TDengine SQL. --- This section explains the syntax of SQL to perform operations on databases, tables and STables, insert data, select data and use functions. We also provide some tips that can be used in TDengine SQL. If you have previous experience with SQL this section will be fairly easy to understand. If you do not have previous experience with SQL, you'll come to appreciate the simplicity and power of SQL. TDengine SQL has been enhanced in version 3.0, and the query engine has been rearchitected. For information about how TDengine SQL has changed, see [Changes in TDengine 3.0](../taos-sql/changes). diff --git a/docs/en/13-operation/01-pkg-install.md b/docs/en/13-operation/01-pkg-install.md index d7713b943f5fe8fbd5e685b8ba03ff8cc8ed4e53..561013947100a0c938154c37fa9e11b17fd428b6 100644 --- a/docs/en/13-operation/01-pkg-install.md +++ b/docs/en/13-operation/01-pkg-install.md @@ -1,6 +1,6 @@ --- title: Install and Uninstall -description: Install, Uninstall, Start, Stop and Upgrade +description: This document describes how to install, upgrade, and uninstall TDengine. --- import Tabs from "@theme/Tabs"; @@ -15,14 +15,14 @@ About details of installing TDenine, please refer to [Installation Guide](../../ ## Uninstall - + -Apt-get package of TDengine can be uninstalled as below: +Uninstall package of TDengine by apt-get can be uninstalled as below: ```bash $ sudo apt-get remove tdengine Reading package lists... Done -Building dependency tree +Building dependency tree Reading state information... Done The following packages will be REMOVED: tdengine @@ -35,7 +35,7 @@ TDengine is removed successfully! ``` -Apt-get package of taosTools can be uninstalled as below: +If you have installed taos-tools, please uninstall it first before uninstall TDengine. The command of uninstall is following: ``` $ sudo apt remove taostools @@ -111,8 +111,20 @@ taos tools is uninstalled successfully! ``` + Run C:\TDengine\unins000.exe to uninstall TDengine on a Windows system. + + + + +TDengine can be uninstalled as below: + +``` +$ rmtaos +TDengine is removed successfully! +``` + @@ -150,13 +162,13 @@ There are two aspects in upgrade operation: upgrade installation package and upg To upgrade a package, follow the steps mentioned previously to first uninstall the old version then install the new version. -Upgrading a running server is much more complex. First please check the version number of the old version and the new version. The version number of TDengine consists of 4 sections, only if the first 3 sections match can the old version be upgraded to the new version. The steps of upgrading a running server are as below: +Upgrading a running server is much more complex. First please check the version number of the old version and the new version. The version number of TDengine consists of 4 sections, only if the first 2 sections match can the old version be upgraded to the new version. The steps of upgrading a running server are as below: - Stop inserting data -- Make sure all data is persisted to disk +- Make sure all data is persisted to disk, please use command `flush database` - Stop the cluster of TDengine - Uninstall old version and install new version - Start the cluster of TDengine -- Execute simple queries, such as the ones executed prior to installing the new package, to make sure there is no data loss +- Execute simple queries, such as the ones executed prior to installing the new package, to make sure there is no data loss - Run some simple data insertion statements to make sure the cluster works well - Restore business services diff --git a/docs/en/13-operation/02-planning.mdx b/docs/en/13-operation/02-planning.mdx index 2dffa7bb8747e21e4754740208eafed65d341217..37ef6aae26ce55046ead09bcfbe37a14213bad46 100644 --- a/docs/en/13-operation/02-planning.mdx +++ b/docs/en/13-operation/02-planning.mdx @@ -1,6 +1,7 @@ --- -sidebar_label: Resource Planning title: Resource Planning +sidebar_label: Resource Planning +description: This document describes how to plan compute and storage resources for your TDengine cluster. --- It is important to plan computing and storage resources if using TDengine to build an IoT, time-series or Big Data platform. How to plan the CPU, memory and disk resources required, will be described in this chapter. diff --git a/docs/en/13-operation/03-tolerance.md b/docs/en/13-operation/03-tolerance.md index 21a5a902822d7b85f555114a112686d4e35c64aa..c8d2c3f3f62f3eeba950de335ef636d08d19f180 100644 --- a/docs/en/13-operation/03-tolerance.md +++ b/docs/en/13-operation/03-tolerance.md @@ -1,5 +1,6 @@ --- title: Fault Tolerance and Disaster Recovery +description: This document describes how TDengine provides fault tolerance and disaster recovery. --- ## Fault Tolerance @@ -17,14 +18,8 @@ To achieve absolutely no data loss, set wal_level to 2 and wal_fsync_period to 0 ## Disaster Recovery -TDengine uses replication to provide high availability. +TDengine provides disaster recovery by using taosX to replicate data between two TDengine clusters which are deployed in two distant data centers. Assume there are two TDengine clusters, A and B, A is the source and B is the target, and A takes the workload of writing and querying. You can deploy `taosX` in the data center where cluster A resides in, `taosX` consumes the data written into cluster A and writes into cluster B. If the data center of cluster A is disrupted because of disaster, you can switch to cluster B to take the workload of data writing and querying, and deploy a `taosX` in the data center of cluster B to replicate data from cluster B to cluster A if cluster A has been recovered, or another cluster C if cluster A has not been recovered. -A TDengine cluster is managed by mnodes. You can configure up to three mnodes to ensure high availability. The data replication between mnode replicas is performed in a synchronous way to guarantee metadata consistency. +You can use the data replication feature of `taosX` to build more complicated disaster recovery solution. -The number of replicas for time series data in TDengine is associated with each database. There can be many databases in a cluster and each database can be configured with a different number of replicas. When creating a database, the parameter `replica` is used to specify the number of replicas. To achieve high availability, set `replica` to 3. - -The number of dnodes in a TDengine cluster must NOT be lower than the number of replicas for any database, otherwise it would fail when trying to create a table. - -As long as the dnodes of a TDengine cluster are deployed on different physical machines and the replica number is higher than 1, high availability can be achieved without any other assistance. For disaster recovery, dnodes of a TDengine cluster should be deployed in geographically different data centers. - -Alternatively, you can use taosX to synchronize the data from one TDengine cluster to another cluster in a remote location. However, taosX is only available in TDengine enterprise version, for more information please contact tdengine.com. +taosX is only provided in TDengine enterprise edition, for more details please contact business@tdengine.com. diff --git a/docs/en/13-operation/07-import.md b/docs/en/13-operation/07-import.md index 8362cec1ab3072866018678b42a679d0c19b49de..e95824e927f4c65b427d0819d7bc968c52f5fbe5 100644 --- a/docs/en/13-operation/07-import.md +++ b/docs/en/13-operation/07-import.md @@ -1,5 +1,6 @@ --- title: Data Import +description: This document describes how to import data into TDengine. --- There are multiple ways of importing data provided by TDengine: import with script, import from data file, import using `taosdump`. diff --git a/docs/en/13-operation/08-export.md b/docs/en/13-operation/08-export.md index 5780de42faeaedbc1c985ad2aa2f52fe56c76971..bffda36e23741a7ff52394772c918fa7040ea047 100644 --- a/docs/en/13-operation/08-export.md +++ b/docs/en/13-operation/08-export.md @@ -1,5 +1,6 @@ --- title: Data Export +description: This document describes how to export data from TDengine. --- There are two ways of exporting data from a TDengine cluster: diff --git a/docs/en/13-operation/10-monitor.md b/docs/en/13-operation/10-monitor.md index 74a5564a2a7b82009e6b2406290a5c15afbf3c1d..346b874059a11c5608027b4ea6e2550765d64186 100644 --- a/docs/en/13-operation/10-monitor.md +++ b/docs/en/13-operation/10-monitor.md @@ -1,5 +1,6 @@ --- title: TDengine Monitoring +description: This document describes how to monitor your TDengine cluster. --- After TDengine is started, it automatically writes monitoring data including CPU, memory and disk usage, bandwidth, number of requests, disk I/O speed, slow queries, into a designated database at a predefined interval through taosKeeper. Additionally, some important system operations, like logon, create user, drop database, and alerts and warnings generated in TDengine are written into the `log` database too. A system operator can view the data in `log` database from TDengine CLI or from a web console. diff --git a/docs/en/13-operation/17-diagnose.md b/docs/en/13-operation/17-diagnose.md index fa202a23ea5b5d58eb0fc107045a9c27c7fa99ad..9d42b3ebbcfe0b87fa23bccaee12769d465fc24e 100644 --- a/docs/en/13-operation/17-diagnose.md +++ b/docs/en/13-operation/17-diagnose.md @@ -1,5 +1,6 @@ --- title: Problem Diagnostics +description: This document describes how to diagnose issues with your TDengine cluster. --- ## Network Connection Diagnostics diff --git a/docs/en/13-operation/index.md b/docs/en/13-operation/index.md index c64749c40e26f091e4a25e0238827ebceff4b069..8b386dc19a1113a84016bf3d03dd847216eed930 100644 --- a/docs/en/13-operation/index.md +++ b/docs/en/13-operation/index.md @@ -1,5 +1,6 @@ --- title: Administration +description: This document describes how to perform management operations on your TDengine cluster from an administrator's perspective. --- This chapter is mainly written for system administrators. It covers download, install/uninstall, data import/export, system monitoring, user management, connection management, capacity planning and system optimization. diff --git a/docs/en/14-reference/02-rest-api/02-rest-api.mdx b/docs/en/14-reference/02-rest-api/02-rest-api.mdx index 09e40b956f9a3b713335bec768fd1d5474f4bea1..409e079b92d5c8375ce6b3da60c0b2aa053ef662 100644 --- a/docs/en/14-reference/02-rest-api/02-rest-api.mdx +++ b/docs/en/14-reference/02-rest-api/02-rest-api.mdx @@ -1,5 +1,6 @@ --- title: REST API +description: This document describes the TDengine REST API. --- To support the development of various types of applications and platforms, TDengine provides an API that conforms to REST principles; namely REST API. To minimize the learning cost, unlike REST APIs for other database engines, TDengine allows insertion of SQL commands in the BODY of an HTTP POST request, to operate the database. @@ -67,7 +68,7 @@ The following return value results indicate that the verification passed. ## HTTP request URL format ```text -http://:/rest/sql/[db_name][?tz=timezone] +http://:/rest/sql/[db_name][?tz=timezone[&req_id=req_id]] ``` Parameter Description: @@ -76,6 +77,7 @@ Parameter Description: - port: httpPort configuration item in the configuration file, default is 6041. - db_name: Optional parameter that specifies the default database name for the executed SQL command. - tz: Optional parameter that specifies the timezone of the returned time, following the IANA Time Zone rules, e.g. `America/New_York`. +- req_id: Optional parameter that specifies the request id for tracing. For example, `http://h1.taos.com:6041/rest/sql/test` is a URL to `h1.taos.com:6041` and sets the default database name to `test`. @@ -98,13 +100,13 @@ The HTTP request's BODY is a complete SQL command, and the data table in the SQL Use `curl` to initiate an HTTP request with a custom authentication method, with the following syntax. ```bash -curl -L -H "Authorization: Basic " -d "" :/rest/sql/[db_name][?tz=timezone] +curl -L -H "Authorization: Basic " -d "" :/rest/sql/[db_name][?tz=timezone[&req_id=req_id]] ``` or ```bash -curl -L -u username:password -d "" :/rest/sql/[db_name][?tz=timezone] +curl -L -u username:password -d "" :/rest/sql/[db_name][?tz=timezone[&req_id=req_id]] ``` where `TOKEN` is the string after Base64 encoding of `{username}:{password}`, e.g. `root:taosdata` is encoded as `cm9vdDp0YW9zZGF0YQ==`.. @@ -113,14 +115,41 @@ where `TOKEN` is the string after Base64 encoding of `{username}:{password}`, e. ### HTTP Response Code -| **Response Code** | **Description** | -|-------------------|----------------| -| 200 | Success. (Also used for C interface errors.) | -| 400 | Parameter error | -| 401 | Authentication failure | -| 404 | Interface not found | -| 500 | Internal error | -| 503 | Insufficient system resources | +Starting from `TDengine 3.0.3.0`, `taosAdapter` provides a configuration parameter `httpCodeServerError` to set whether to return a non-200 http status code when the C interface returns an error + +| **Description** | **httpCodeServerError false** | **httpCodeServerError true** | +|--------------------|---------------------------- ------|---------------------------------------| +| taos_errno() returns 0 | 200 | 200 | +| taos_errno() returns non-0 | 200 (except authentication error) | 500 (except authentication error and 400/502 error) | +| Parameter error | 400 (only handle HTTP request URL parameter error) | 400 (handle HTTP request URL parameter error and taosd return error) | +| Authentication error | 401 | 401 | +| Interface does not exist | 404 | 404 | +| Cluster unavailable error | 502 | 502 | +| Insufficient system resources | 503 | 503 | + +The C error codes that return http code 400 are: + +- TSDB_CODE_TSC_SQL_SYNTAX_ERROR ( 0x0216 ) +- TSDB_CODE_TSC_LINE_SYNTAX_ERROR (0x021B) +- TSDB_CODE_PAR_SYNTAX_ERROR (0x2600) +- TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE (0x060B) +- TSDB_CODE_TSC_VALUE_OUT_OF_RANGE (0x0224) +- TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE (0x263B) + +The error code that returns http code 401 are: + +- TSDB_CODE_MND_USER_ALREADY_EXIST (0x0350) +- TSDB_CODE_MND_USER_NOT_EXIST (0x0351) +- TSDB_CODE_MND_INVALID_USER_FORMAT (0x0352) +- TSDB_CODE_MND_INVALID_PASS_FORMAT (0x0353) +- TSDB_CODE_MND_NO_USER_FROM_CONN (0x0354) +- TSDB_CODE_MND_TOO_MANY_USERS (0x0355) +- TSDB_CODE_MND_INVALID_ALTER_OPER (0x0356) +- TSDB_CODE_MND_AUTH_FAILURE (0x0357) + +The error code that returns http code 403 are: + +- TSDB_CODE_RPC_SOMENODE_NOT_CONNECTED (0x0020) ### HTTP body structure @@ -268,7 +297,6 @@ Response body: ```json { - "status": "succ", "code": 0, "desc": "/KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04" } @@ -354,6 +382,130 @@ Response body: } ``` +## REST API between TDengine 2.x and 3.0 + +### URI + +| URI | TDengine 2.x | TDengine 3.0 | +| :--------------------| :------------------: | :--------------------------------------------------: | +| /rest/sql | Supported | Supported (with different response code and body) | +| /rest/sqlt | Supported | No more supported | +| /rest/sqlutc | Supported | No more supported | + +### HTTP code + +| HTTP code | TDengine 2.x | TDengine 3.0 | note | +| :--------------------| :------------------: | :----------: | :-----------------------------------: | +| 200 | Supported | Supported | Success or taosc return error | +| 400 | Not supported | Supported | Parameter error | +| 401 | Not supported | Supported | Authentication failure | +| 404 | Supported | Supported | URI not exist | +| 500 | Not supported | Supported | Internal error | +| 503 | Supported | Supported | Insufficient system resources | + +### Response body + +#### REST response body return from TDengine 2.x + +```JSON +{ + "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": [ + [ + "log", + "2020-09-02 17:23:00.039", + 4, + 1, + 1, + 1, + 10, + "30,30,30", + 1, + 3, + 100, + 4096, + 1, + 3000, + 2, + "us", + "ready" + ] + ], + "rows": 1 +} +``` +``` + "data": [ + [ + "information_schema", + 16, + "ready" + ], + [ + "performance_schema", + 9, + "ready" + ] + ], +``` + +#### REST response body return from TDengine 3.0 + +```JSON +{ + "code": 0, + "column_meta": [ + [ + "name", + "VARCHAR", + 64 + ], + [ + "ntables", + "BIGINT", + 8 + ], + [ + "status", + "VARCHAR", + 10 + ] + ], + "data": [ + [ + "information_schema", + 16, + "ready" + ], + [ + "performance_schema", + 9, + "ready" + ] + ], + "rows": 2 +} +``` + ## Reference [taosAdapter](/reference/taosadapter/) diff --git a/docs/en/14-reference/03-connector/03-cpp.mdx b/docs/en/14-reference/03-connector/03-cpp.mdx index 906d56ab158e20db4bafa9eb8375434568555184..b543879b3cf8814d21d0a6f940762c67cc2519b0 100644 --- a/docs/en/14-reference/03-connector/03-cpp.mdx +++ b/docs/en/14-reference/03-connector/03-cpp.mdx @@ -1,6 +1,7 @@ --- -sidebar_label: C/C++ title: C/C++ Connector +sidebar_label: C/C++ +description: This document describes the TDengine C/C++ connector. --- C/C++ developers can use TDengine's client driver and the C/C++ connector, to develop their applications to connect to TDengine clusters for data writing, querying, and other functions. To use the C/C++ connector you must include the TDengine header file _taos.h_, which lists the function prototypes of the provided APIs. The application also needs to link to the corresponding dynamic libraries on the platform where it is located. @@ -175,6 +176,14 @@ The base API is used to do things like create database connections and provide a Set the current default database to `db`. +- `int taos_get_current_db(TAOS *taos, char *database, int len, int *required)` + + - The variables database and len are applied by the user outside and allocated space. The current database name and length will be assigned to database and len. + - As long as the db name is not assigned to the database normally (including truncation), an error will be returned with the return value of -1, and then the user can use taos_errstr(NULL) to get error message. + - If database==NULL or len<=0, returns an error, the space required to store the db (including the last '\0') in the variable required + - If len is less than the space required to store the db (including the last '\0'), an error is returned. The truncated data assigned in the database ends with '\0'. + - If len is greater than or equal to the space required to store the db (including the last '\0'), return normal 0, and assign the db name ending with '\0' in the database. + - `void taos_close(TAOS *taos)` Closes the connection, where `taos` is the handle returned by `taos_connect()`. @@ -403,5 +412,17 @@ In addition to writing data using the SQL method or the parameter binding API, w Note that the timestamp resolution parameter only takes effect when the protocol type is `SML_LINE_PROTOCOL`. For OpenTSDB's text protocol, timestamp resolution follows its official resolution rules - time precision is confirmed by the number of characters contained in the timestamp. - **Supported Versions** - This feature interface is supported from version 2.3.0.0. + schemaless 其他相关的接口 +- `TAOS_RES *taos_schemaless_insert_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, int precision, int64_t reqid)` +- `TAOS_RES *taos_schemaless_insert_raw(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision)` +- `TAOS_RES *taos_schemaless_insert_raw_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision, int64_t reqid)` +- `TAOS_RES *taos_schemaless_insert_ttl(TAOS *taos, char *lines[], int numLines, int protocol, int precision, int32_t ttl)` +- `TAOS_RES *taos_schemaless_insert_ttl_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, int precision, int32_t ttl, int64_t reqid)` +- `TAOS_RES *taos_schemaless_insert_raw_ttl(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision, int32_t ttl)` +- `TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision, int32_t ttl, int64_t reqid)` + + **Description** + - The above seven interfaces are extension interfaces, which are mainly used to pass ttl and reqid parameters, and can be used as needed. + - Withing _raw interfaces represent data through the passed parameters lines and len. In order to solve the problem that the original interface data contains '\0' and is truncated. The totalRows pointer returns the number of parsed data rows. + - Withing _ttl interfaces can pass the ttl parameter to control the ttl expiration time of the table. + - Withing _reqid interfaces can track the entire call chain by passing the reqid parameter. diff --git a/docs/en/14-reference/03-connector/04-java.mdx b/docs/en/14-reference/03-connector/04-java.mdx index 7b3440ebac2f630a2f6f39c3b270a2196d1d7739..fd4b4641d75e2116267b3f7f13a995079913f663 100644 --- a/docs/en/14-reference/03-connector/04-java.mdx +++ b/docs/en/14-reference/03-connector/04-java.mdx @@ -1,8 +1,8 @@ --- -toc_max_heading_level: 4 -sidebar_label: Java title: TDengine Java Connector -description: The TDengine Java Connector is implemented on the standard JDBC API and provides native and REST connectors. +sidebar_label: Java +description: This document describes the TDengine Java Connector. +toc_max_heading_level: 4 --- import Tabs from '@theme/Tabs'; @@ -300,7 +300,7 @@ stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int > **Note**: If you do not use `use db` to specify the database, all subsequent operations on the table need to add the database name as a prefix, such as db.tb. -### 插入数据 +### Insert data ```java // insert data @@ -696,6 +696,9 @@ TaosConsumer consumer = new TaosConsumer<>(config); - enable.auto.commit: Specifies whether to commit automatically. - group.id: consumer: Specifies the group that the consumer is in. - value.deserializer: To deserialize the results, you can inherit `com.taosdata.jdbc.tmq.ReferenceDeserializer` and specify the result set bean. You can also inherit `com.taosdata.jdbc.tmq.Deserializer` and perform custom deserialization based on the SQL result set. +- td.connect.type: Specifies the type connect with TDengine, `jni` or `WebSocket`. default is `jni` +- httpConnectTimeout:WebSocket connection timeout in milliseconds, the default value is 5000 ms. It only takes effect when using WebSocket type. +- messageWaitTimeout:socket timeout in milliseconds, the default value is 10000 ms. It only takes effect when using WebSocket type. - For more information, see [Consumer Parameters](../../../develop/tmq). #### Subscribe to consume data @@ -722,7 +725,12 @@ consumer.close() For more information, see [Data Subscription](../../../develop/tmq). -### Usage examples +#### Full Sample Code + + + + +In addition to the native connection, the Java Connector also supports subscribing via websocket. ```java public abstract class ConsumerLoop { @@ -795,6 +803,87 @@ public abstract class ConsumerLoop { } ``` + + + +```java +public abstract class ConsumerLoop { + private final TaosConsumer consumer; + private final List topics; + private final AtomicBoolean shutdown; + private final CountDownLatch shutdownLatch; + + public ConsumerLoop() throws SQLException { + Properties config = new Properties(); + config.setProperty("bootstrap.servers", "localhost:6041"); + config.setProperty("td.connect.type", "ws"); + config.setProperty("msg.with.table.name", "true"); + config.setProperty("enable.auto.commit", "true"); + config.setProperty("group.id", "group2"); + config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.ConsumerLoop$ResultDeserializer"); + + this.consumer = new TaosConsumer<>(config); + this.topics = Collections.singletonList("topic_speed"); + this.shutdown = new AtomicBoolean(false); + this.shutdownLatch = new CountDownLatch(1); + } + + public abstract void process(ResultBean result); + + public void pollData() throws SQLException { + try { + consumer.subscribe(topics); + + while (!shutdown.get()) { + ConsumerRecords records = consumer.poll(Duration.ofMillis(100)); + for (ResultBean record : records) { + process(record); + } + } + consumer.unsubscribe(); + } finally { + consumer.close(); + shutdownLatch.countDown(); + } + } + + public void shutdown() throws InterruptedException { + shutdown.set(true); + shutdownLatch.await(); + } + + public static class ResultDeserializer extends ReferenceDeserializer { + + } + + public static class ResultBean { + private Timestamp ts; + private int speed; + + public Timestamp getTs() { + return ts; + } + + public void setTs(Timestamp ts) { + this.ts = ts; + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + } +} +``` + + + + +> **Note**: The value of value.deserializer should be adjusted based on the package path of the test environment. + ### Use with connection pool #### HikariCP @@ -878,8 +967,10 @@ The source code of the sample application is under `TDengine/examples/JDBC`: | taos-jdbcdriver version | major changes | | :---------------------: | :--------------------------------------------: | -| 3.0.1 - 3.0.2 | fix the resultSet data is parsed incorrectly sometimes. 3.0.1 is compiled on JDK 11, you are advised to use 3.0.2 in the JDK 8 environment | +| 3.1.0 | JDBC REST connection supports subscription over WebSocket | +| 3.0.1 - 3.0.4 | fix the resultSet data is parsed incorrectly sometimes. 3.0.1 is compiled on JDK 11, you are advised to use other version in the JDK 8 environment | | 3.0.0 | Support for TDengine 3.0 | +| 2.0.42 | fix wasNull interface return value in WebSocket connection | | 2.0.41 | fix decode method of username and password in REST connection | | 2.0.39 - 2.0.40 | Add REST connection/request timeout parameters | | 2.0.38 | JDBC REST connections add bulk pull function | diff --git a/docs/en/14-reference/03-connector/05-go.mdx b/docs/en/14-reference/03-connector/05-go.mdx index df5b129cea552144d5833190d46e8a78f2fd2fa5..0088f230069b15f12e455b5b6d2d6fa261fc5a14 100644 --- a/docs/en/14-reference/03-connector/05-go.mdx +++ b/docs/en/14-reference/03-connector/05-go.mdx @@ -1,7 +1,8 @@ --- -toc_max_heading_level: 4 -sidebar_label: Go title: TDengine Go Connector +sidebar_label: Go +description: This document describes the TDengine Go connector. +toc_max_heading_level: 4 --- import Tabs from '@theme/Tabs'; @@ -119,7 +120,7 @@ _taosSql_ implements Go's `database/sql/driver` interface via cgo. You can use t Use `taosSql` as `driverName` and use a correct [DSN](#DSN) as `dataSourceName`, DSN supports the following parameters. -* configPath specifies the `taos.cfg` directory +* cfg specifies the `taos.cfg` directory For example: @@ -355,26 +356,29 @@ The `af` package encapsulates TDengine advanced functions such as connection man #### Subscribe -* `func NewConsumer(conf *Config) (*Consumer, error)` +* `func NewConsumer(conf *tmq.ConfigMap) (*Consumer, error)` Creates consumer group. -* `func (c *Consumer) Subscribe(topics []string) error` +* `func (c *Consumer) Subscribe(topic string, rebalanceCb RebalanceCb) error` +Note: `rebalanceCb` is reserved for compatibility purpose + +Subscribes a topic. + +* `func (c *Consumer) SubscribeTopics(topics []string, rebalanceCb RebalanceCb) error` +Note: `rebalanceCb` is reserved for compatibility purpose Subscribes to topics. -* `func (c *Consumer) Poll(timeout time.Duration) (*Result, error)` +* `func (c *Consumer) Poll(timeoutMs int) tmq.Event` Polling information. -* `func (c *Consumer) Commit(ctx context.Context, message unsafe.Pointer) error` +* `func (c *Consumer) Commit() ([]tmq.TopicPartition, error)` +Note: `tmq.TopicPartition` is reserved for compatibility purpose Commit information. -* `func (c *Consumer) FreeMessage(message unsafe.Pointer)` - -Free information. - * `func (c *Consumer) Unsubscribe() error` Unsubscribe. @@ -441,25 +445,36 @@ Close consumer. ### Subscribe via WebSocket -* `func NewConsumer(config *Config) (*Consumer, error)` +* `func NewConsumer(conf *tmq.ConfigMap) (*Consumer, error)` - Creates consumer group. +Creates consumer group. -* `func (c *Consumer) Subscribe(topic []string) error` +* `func (c *Consumer) Subscribe(topic string, rebalanceCb RebalanceCb) error` +Note: `rebalanceCb` is reserved for compatibility purpose - Subscribes to topics. +Subscribes a topic. -* `func (c *Consumer) Poll(timeout time.Duration) (*Result, error)` +* `func (c *Consumer) SubscribeTopics(topics []string, rebalanceCb RebalanceCb) error` +Note: `rebalanceCb` is reserved for compatibility purpose - Polling information. +Subscribes to topics. -* `func (c *Consumer) Commit(messageID uint64) error` +* `func (c *Consumer) Poll(timeoutMs int) tmq.Event` - Commit information. +Polling information. + +* `func (c *Consumer) Commit() ([]tmq.TopicPartition, error)` +Note: `tmq.TopicPartition` is reserved for compatibility purpose + +Commit information. + +* `func (c *Consumer) Unsubscribe() error` + +Unsubscribe. * `func (c *Consumer) Close() error` - Close consumer. +Close consumer. For a complete example see [GitHub sample file](https://github.com/taosdata/driver-go/blob/3.0/examples/tmqoverws/main.go) diff --git a/docs/en/14-reference/03-connector/06-rust.mdx b/docs/en/14-reference/03-connector/06-rust.mdx index 4e2a7848dc87ac0522b6d5aa5855b5a0998dc789..ad522e9d2b26ff02ee06bb7438acc12d315529c4 100644 --- a/docs/en/14-reference/03-connector/06-rust.mdx +++ b/docs/en/14-reference/03-connector/06-rust.mdx @@ -1,7 +1,8 @@ --- -toc_max_heading_level: 4 -sidebar_label: Rust title: TDengine Rust Connector +sidebar_label: Rust +description: This document describes the TDengine Rust connector. +toc_max_heading_level: 4 --- import Tabs from '@theme/Tabs'; @@ -38,7 +39,7 @@ The Rust Connector is still under rapid development and is not guaranteed to be * Install the Rust development toolchain * If using the native connection, please install the TDengine client driver. Please refer to [install client driver](/reference/connector#install-client-driver) -# Add taos dependency +### Add taos dependency Depending on the connection method, add the [taos][taos] dependency in your Rust project as follows: @@ -281,7 +282,7 @@ In the application code, use `pool.get()? ` to get a connection object [Taos]. let taos = pool.get()?; ``` -# Connectors +### Connectors The [Taos][struct.Taos] object provides an API to perform operations on multiple databases. diff --git a/docs/en/14-reference/03-connector/07-python.mdx b/docs/en/14-reference/03-connector/07-python.mdx index 25e6b2188a64928e35b8e8c45988a426802eb9f3..bfbdd929c263a59df42e1f310b267ba1521032c2 100644 --- a/docs/en/14-reference/03-connector/07-python.mdx +++ b/docs/en/14-reference/03-connector/07-python.mdx @@ -1,7 +1,7 @@ --- -sidebar_label: Python title: TDengine Python Connector -description: "taospy is the official Python connector for TDengine. taospy provides a rich API that makes it easy for Python applications to use TDengine. tasopy wraps both the native and REST interfaces of TDengine, corresponding to the two submodules of tasopy: taos and taosrest. In addition to wrapping the native and REST interfaces, taospy also provides a programming interface that conforms to the Python Data Access Specification (PEP 249), making it easy to integrate taospy with many third-party tools, such as SQLAlchemy and pandas." +sidebar_label: Python +description: This document describes taospy, the TDengine Python connector. --- import Tabs from "@theme/Tabs"; @@ -10,10 +10,11 @@ import TabItem from "@theme/TabItem"; `taospy` is the official Python connector for TDengine. taospy provides a rich API that makes it easy for Python applications to use TDengine. `taospy` wraps both the [native interface](/reference/connector/cpp) and [REST interface](/reference/rest-api) of TDengine, which correspond to the `taos` and `taosrest` modules of the `taospy` package, respectively. In addition to wrapping the native and REST interfaces, `taospy` also provides a set of programming interfaces that conforms to the [Python Data Access Specification (PEP 249)](https://peps.python.org/pep-0249/). It is easy to integrate `taospy` with many third-party tools, such as [SQLAlchemy](https://www.sqlalchemy.org/) and [pandas](https://pandas.pydata.org/). -The direct connection to the server using the native interface provided by the client driver is referred to hereinafter as a "native connection"; the connection to the server using the REST interface provided by taosAdapter is referred to hereinafter as a "REST connection". +`taos-ws-py` is an optional package to enable using WebSocket to connect TDengine. -The source code for the Python connector is hosted on [GitHub](https://github.com/taosdata/taos-connector-python). +The direct connection to the server using the native interface provided by the client driver is referred to hereinafter as a "native connection"; the connection to the server using the REST or WebSocket interface provided by taosAdapter is referred to hereinafter as a "REST connection" or "WebSocket connection". +The source code for the Python connector is hosted on [GitHub](https://github.com/taosdata/taos-connector-python). ## Supported platforms - The [supported platforms](/reference/connector/#supported-platforms) for the native connection are the same as the ones supported by the TDengine client. @@ -32,7 +33,7 @@ We recommend using the latest version of `taospy`, regardless of the version of ### Preparation -1. Install Python. Python >= 3.7 is recommended. If Python is not available on your system, refer to the [Python BeginnersGuide](https://wiki.python.org/moin/BeginnersGuide/Download) to install it. +1. Install Python. The recent taospy package requires Python 3.6.2+. The earlier versions of taospy require Python 3.7+. The taos-ws-py package requires Python 3.7+. If Python is not available on your system, refer to the [Python BeginnersGuide](https://wiki.python.org/moin/BeginnersGuide/Download) to install it. 2. Install [pip](https://pypi.org/project/pip/). In most cases, the Python installer comes with the pip utility. If not, please refer to [pip documentation](https://pip.pypa.io/en/stable/installation/) to install it. If you use a native connection, you will also need to [Install Client Driver](/reference/connector#Install-Client-Driver). The client install package includes the TDengine client dynamic link library (`libtaos.so` or `taos.dll`) and the TDengine CLI. @@ -78,6 +79,22 @@ pip3 install git+https://github.com/taosdata/taos-connector-python.git
+#### Install `taos-ws-py` (Optional) + +The taos-ws-py package provides the way to access TDengine via WebSocket. + +##### Install taos-ws-py with taospy + +```bash +pip3 install taospy[ws] +``` + +##### Install taos-ws-py only + +```bash +pip3 install taos-ws-py +``` + ### Verify @@ -98,6 +115,15 @@ For REST connections, verifying that the `taosrest` module can be imported succe import taosrest ``` +
+ + +For WebSocket connection, verifying that the `taosws` module can be imported successfully can be done in the Python Interactive Shell by typing. + +```python +import taosws +``` + @@ -166,6 +192,28 @@ If the test is successful, it will output the server version information, e.g. } ``` + + + +For WebSocket connection, make sure the cluster and taosAdapter component, are running. This can be testetd using the following `curl` command. + +``` +curl -i -N -d "show databases" -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: :" -H "Origin: http://:" http://:/rest/sql +``` + +The FQDN above is the FQDN of the machine running taosAdapter, PORT is the port taosAdapter listening, default is `6041`. + +If the test is successful, it will output the server version information, e.g. + +```json +HTTP/1.1 200 OK +Content-Type: application/json; charset=utf-8 +Date: Tue, 21 Mar 2023 09:29:17 GMT +Transfer-Encoding: chunked + +{"status":"succ","head":["server_version()"],"column_meta":[["server_version()",8,8]],"data":[["2.6.0.27"]],"rows":1} +``` + @@ -212,6 +260,16 @@ All arguments to the `connect()` function are optional keyword arguments. The fo - `password`: TDengine user password. The default is `taosdata`. - `timeout`: HTTP request timeout. Enter a value in seconds. The default is `socket._GLOBAL_DEFAULT_TIMEOUT`. Usually, no configuration is needed. + + + + +```python +{{#include docs/examples/python/connect_websocket_examples.py:connect}} +``` + +The parameter of `connect()` is the url of TDengine, and the protocol is `taosws` or `ws`. + @@ -282,7 +340,95 @@ The `RestClient` class is a direct wrapper for the [REST API](/reference/rest-ap For a more detailed description of the `sql()` method, please refer to [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html). + + + +```python +{{#include docs/examples/python/connect_websocket_examples.py:basic}} +``` + +- `conn.execute`: can use to execute arbitrary SQL statements, and return the number of rows affected. +- `conn.query`: can use to execute query SQL statements, and return the query results. + + + + +### Usage with req_id + +By using the optional req_id parameter, you can specify a request ID that can be used for tracing. + + + + +##### TaosConnection class + +The `TaosConnection` class contains both an implementation of the PEP249 Connection interface (e.g., the `cursor()` method and the `close()` method) and many extensions (e.g., the `execute()`, `query()`, `schemaless_insert()`, and `subscribe()` methods). + +```python title="execute method" +{{#include docs/examples/python/connection_usage_native_reference_with_req_id.py:insert}} +``` + +```python title="query method" +{{#include docs/examples/python/connection_usage_native_reference_with_req_id.py:query}} +``` + +:::tip +The queried results can only be fetched once. For example, only one of `fetch_all()` and `fetch_all_into_dict()` can be used in the example above. Repeated fetches will result in an empty list. +::: + +##### Use of TaosResult class + +In the above example of using the `TaosConnection` class, we have shown two ways to get the result of a query: `fetch_all()` and `fetch_all_into_dict()`. In addition, `TaosResult` also provides methods to iterate through the result set by rows (`rows_iter`) or by data blocks (`blocks_iter`). Using these two methods will be more efficient in scenarios where the query has a large amount of data. + +```python title="blocks_iter method" +{{#include docs/examples/python/result_set_with_req_id_examples.py}} +``` +##### Use of the TaosCursor class + +The `TaosConnection` class and the `TaosResult` class already implement all the functionality of the native interface. If you are familiar with the interfaces in the PEP249 specification, you can also use the methods provided by the `TaosCursor` class. + +```python title="Use of TaosCursor" +{{#include docs/examples/python/cursor_usage_native_reference_with_req_id.py}} +``` + +:::note +The TaosCursor class uses native connections for write and query operations. In a client-side multi-threaded scenario, this cursor instance must remain thread exclusive and cannot be shared across threads for use, otherwise, it will result in errors in the returned results. + +::: + + + + +##### Use of TaosRestCursor class + +The `TaosRestCursor` class is an implementation of the PEP249 Cursor interface. + +```python title="Use of TaosRestCursor" +{{#include docs/examples/python/connect_rest_with_req_id_examples.py:basic}} +``` +- `cursor.execute`: Used to execute arbitrary SQL statements. +- `cursor.rowcount` : For write operations, returns the number of successful rows written. For query operations, returns the number of rows in the result set. +- `cursor.description` : Returns the description of the field. Please refer to [TaosRestCursor](https://docs.taosdata.com/api/taospy/taosrest/cursor.html) for the specific format of the description information. + +##### Use of the RestClient class + +The `RestClient` class is a direct wrapper for the [REST API](/reference/rest-api). It contains only a `sql()` method for executing arbitrary SQL statements and returning the result. + +```python title="Use of RestClient" +{{#include docs/examples/python/rest_client_with_req_id_example.py}} +``` + +For a more detailed description of the `sql()` method, please refer to [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html). + + + + +```python +{{#include docs/examples/python/connect_websocket_with_req_id_examples.py:basic}} +``` +- `conn.execute`: can use to execute arbitrary SQL statements, and return the number of rows affected. +- `conn.query`: can use to execute query SQL statements, and return the query results. @@ -303,6 +449,13 @@ For a more detailed description of the `sql()` method, please refer to [RestClie {{#include docs/examples/python/conn_rest_pandas.py}} ``` + + + +```python +{{#include docs/examples/python/conn_websocket_pandas.py}} +``` + diff --git a/docs/en/14-reference/03-connector/08-node.mdx b/docs/en/14-reference/03-connector/08-node.mdx index a36cf0efc9432425ad16c4d8112cc813a8c528b9..b7c2e6b76537dc8b2a039684d2d712d91337cecd 100644 --- a/docs/en/14-reference/03-connector/08-node.mdx +++ b/docs/en/14-reference/03-connector/08-node.mdx @@ -1,7 +1,8 @@ --- -toc_max_heading_level: 4 -sidebar_label: Node.js title: TDengine Node.js Connector +sidebar_label: Node.js +description: This document describes the TDengine Node.js connector. +toc_max_heading_level: 4 --- import Tabs from "@theme/Tabs"; @@ -31,7 +32,9 @@ Please refer to [version support list](/reference/connector#version-support) ## Supported features -### Native connectors + + + 1. Connection Management 2. General Query @@ -40,12 +43,16 @@ Please refer to [version support list](/reference/connector#version-support) 5. Subscription 6. Schemaless -### REST Connector + + 1. Connection Management 2. General Query 3. Continuous Query + + + ## Installation Steps ### Pre-installation preparation @@ -59,9 +66,19 @@ Please refer to [version support list](/reference/connector#version-support) - `python` (recommended for `v2.7` , `v3.x.x` currently not supported) - `@tdengine/client` 3.0.0 supports Node.js LTS v10.9.0 or later and Node.js LTS v12.8.0 or later. Older versions may be incompatible. - `make` -- C compiler, [GCC](https://gcc.gnu.org) v4.8.5 or higher +- C compiler, [GCC](https://gcc.gnu.org) v4.8.5 or later. + + + +- `python` (recommended for `v2.7` , `v3.x.x` currently not supported) +- `@tdengine/client` 3.0.0 currently supports Node.js from v12.22.12, but only later versions of v12. Other versions may be incompatible. +- `make` +- C compiler, [GCC](https://gcc.gnu.org) v4.8.5 or later. + + + - Installation method 1 @@ -104,6 +121,9 @@ npm install @tdengine/rest ### Verify + + + After installing the TDengine client, use the `nodejsChecker.js` program to verify that the current environment supports Node.js access to TDengine. Verification in details: @@ -120,6 +140,28 @@ node nodejsChecker.js host=localhost - After executing the above steps, the command-line will output the result of `nodejsChecker.js` connecting to the TDengine instance and performing a simple insert and query. + + + +After installing the TDengine client, use the `restChecker.js` program to verify that the current environment supports Node.js access to TDengine. + +Verification in details: + +- Create an installation test folder such as `~/tdengine-test`. Download the [restChecker.js source code](https://github.com/taosdata/TDengine/tree/3.0/docs/examples/node/restexample/restChecker.js) to your local. + +- Execute the following command from the command-line. + +```bash +npm init -y +npm install @tdengine/rest +node restChecker.js +``` + +- After executing the above steps, the command-line will output the result of `restChecker.js` connecting to the TDengine instance and performing a simple insert and query. + + + + ## Establishing a connection Please choose to use one of the connectors. @@ -171,24 +213,69 @@ let cursor = conn.cursor(); #### SQL Write + + + + + + +```js +{{#include docs/examples/node/restexample/insert_example.js}} +``` + + + + #### InfluxDB line protocol write + + + + + + #### OpenTSDB Telnet line protocol write + + + + + + #### OpenTSDB JSON line protocol write + + + + + + ### Querying data + + + + + + + +```js +{{#include docs/examples/node/restexample/query_example.js}} +``` + + + + ## More sample programs @@ -249,4 +336,4 @@ let cursor = conn.cursor(); ## API Reference -[API Reference](https://docs.taosdata.com/api/td2.0-connector/) \ No newline at end of file +[API Reference](https://docs.taosdata.com/api/td2.0-connector/) diff --git a/docs/en/14-reference/03-connector/09-csharp.mdx b/docs/en/14-reference/03-connector/09-csharp.mdx index 85514f58ac1a19c7ae1a725e9b055f10280ebbb6..fdc0824973eb83d3d544be239ea954e29b5ba265 100644 --- a/docs/en/14-reference/03-connector/09-csharp.mdx +++ b/docs/en/14-reference/03-connector/09-csharp.mdx @@ -1,7 +1,8 @@ --- -toc_max_heading_level: 4 -sidebar_label: C# title: C# Connector +sidebar_label: C# +description: This document describes the TDengine C# connector. +toc_max_heading_level: 4 --- import Tabs from '@theme/Tabs'; @@ -17,7 +18,7 @@ import CSAsyncQuery from "../../07-develop/04-query-data/_cs_async.mdx" `TDengine.Connector` is a C# language connector provided by TDengine that allows C# developers to develop C# applications that access TDengine cluster data. -The `TDengine.Connector` connector supports connect to TDengine instances via the TDengine client driver (taosc), providing data writing, querying, subscription, schemaless writing, bind interface, etc.The `TDengine.Connector` also supports WebSocket and developers can build connection through DSN, which supports data writing, querying, and parameter binding, etc. +The `TDengine.Connector` connector supports connect to TDengine instances via the TDengine client driver (taosc), providing data writing, querying, subscription, schemaless writing, bind interface, etc.The `TDengine.Connector` also supports WebSocket from v3.0.1 and developers can build connection through DSN, which supports data writing, querying, and parameter binding, etc. This article describes how to install `TDengine.Connector` in a Linux or Windows environment and connect to TDengine clusters via `TDengine.Connector` to perform basic operations such as data writing and querying. @@ -66,31 +67,43 @@ Please refer to [version support list](/reference/connector#version-support) * [Nuget Client](https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools) (optional installation) * Install TDengine client driver, please refer to [Install client driver](/reference/connector/#install-client-driver) for details -### Install via dotnet CLI +### Install `TDengine.Connector` - + -You can reference the `TDengine.Connector` published in Nuget to the current project via the `dotnet` command under the path of the existing .NET project. +You can reference the `TDengine.Connector` published in Nuget to the current project via the `dotnet` CLI under the path of the existing .NET project. ``` bash dotnet add package TDengine.Connector ``` - - +You may also modify the current.NET project file. You can include the following 'ItemGroup' in your project file (.csproj). -You can [download the source code](https://github.com/taosdata/taos-connector-dotnet/tree/3.0) and directly reference the latest version of the TDengine.Connector library. - -```bash -git clone -b 3.0 https://github.com/taosdata/taos-connector-dotnet.git -cd taos-connector-dotnet -cp -r src/ myProject +``` XML + + + +``` -cd myProject -dotnet add exmaple.csproj reference src/TDengine.csproj + + + +In this scenario, modifying your project file is required in order to copy the WebSocket dependency dynamic library from the nuget package into your project. +```XML + + + + + + + + + ``` +Notice: `TDengine.Connector` only version>= 3.0.2 includes the dynamic library for WebSocket. + @@ -252,19 +265,20 @@ ws://localhost:6041/test |Sample program |Sample program description | |--------------------------------------------------------------------------------------------------------------------|--------------------------------------------| -| [CURD](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/Query/Query.cs) | Table creation, data insertion, and query examples with TDengine.Connector | -| [JSON Tag](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/JSONTag) | Writing and querying JSON tag data with TDengine Connector | -| [stmt](https://github.com/taosdata/taos-connector-dotnet/tree/3.0/examples/Stmt) | Parameter binding with TDengine Connector | -| [schemaless](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/schemaless) | Schemaless writes with TDengine Connector | -| [async query](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/AsyncQuery/QueryAsync.cs) | Asynchronous queries with TDengine Connector | -| [Subscription](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/TMQ/TMQ.cs) | Subscription example with TDengine Connector | -| [Basic WebSocket Usage](https://github.com/taosdata/taos-connector-dotnet/blob/5a4a7cd0dbcda114447cdc6d0c6dedd8e84a52da/examples/WS/WebSocketSample.cs) | WebSocket basic data in and out with TDengine connector | -| [WebSocket Parameter Binding](https://github.com/taosdata/taos-connector-dotnet/blob/5a4a7cd0dbcda114447cdc6d0c6dedd8e84a52da/examples/WS/WebSocketSTMT.cs) | WebSocket parameter binding example | +| [CURD](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/Query/Query.cs) | Table creation, data insertion, and query examples with TDengine.Connector | +| [JSON Tag](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/JSONTag) | Writing and querying JSON tag data with TDengine Connector | +| [stmt](https://github.com/taosdata/taos-connector-dotnet/tree/3.0/examples/NET6Examples/Stmt) | Parameter binding with TDengine Connector | +| [schemaless](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/schemaless) | Schemaless writes with TDengine Connector | +| [async query](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/AsyncQuery/QueryAsync.cs) | Asynchronous queries with TDengine Connector | +| [Subscription](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/TMQ/TMQ.cs) | Subscription example with TDengine Connector | +| [Basic WebSocket Usage](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/FrameWork45/WS/WebSocketSample.cs) | WebSocket basic data in and out with TDengine connector | +| [WebSocket Parameter Binding](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/FrameWork45/WS/WebSocketSTMT.cs) | WebSocket parameter binding example | ## Important update records | TDengine.Connector | Description | |--------------------|--------------------------------| +| 3.0.2 | Support .NET Framework 4.5 and above. Support .Net standard 2.0. Nuget package includes dynamic library for WebSocket.| | 3.0.1 | Support WebSocket and Cloud,With function query, insert, and parameter binding| | 3.0.0 | Supports TDengine 3.0.0.0. TDengine 2.x is not supported. Added `TDengine.Impl.GetData()` interface to deserialize query results. | | 1.0.7 | Fixed TDengine.Query() memory leak. | diff --git a/docs/en/14-reference/03-connector/10-php.mdx b/docs/en/14-reference/03-connector/10-php.mdx index 87f8616f9ebac598285406eb404b7c2544950ee3..6cc45ded49b90edbbea2d83ff91da7cf1ad89ce7 100644 --- a/docs/en/14-reference/03-connector/10-php.mdx +++ b/docs/en/14-reference/03-connector/10-php.mdx @@ -1,6 +1,7 @@ --- -sidebar_label: PHP title: PHP Connector +sidebar_label: PHP +description: This document describes the TDengine PHP connector. --- `php-tdengine` is the TDengine PHP connector provided by TDengine community. In particular, it supports Swoole coroutine. @@ -86,7 +87,7 @@ In this section a few sample programs which use TDengine PHP connector to access > Any error would throw exception: `TDengine\Exception\TDengineException` -### Establish Conection +### Establish Connection
Establish Connection diff --git a/docs/en/14-reference/03-connector/_category_.yml b/docs/en/14-reference/03-connector/_category_.yml index e470f64aa013b137f05f03db112641faf2956297..6a766e96574844db87a70ff7eb5f0005cb6acbfb 100644 --- a/docs/en/14-reference/03-connector/_category_.yml +++ b/docs/en/14-reference/03-connector/_category_.yml @@ -1 +1 @@ -label: "connector" \ No newline at end of file +label: "Connector" diff --git a/docs/en/14-reference/03-connector/_linux_install.mdx b/docs/en/14-reference/03-connector/_linux_install.mdx index 97f6cd333961d24bd015a2ebcf7223f89fecca2c..398593cfe6b23cbb3269182a68fb7563e2964484 100644 --- a/docs/en/14-reference/03-connector/_linux_install.mdx +++ b/docs/en/14-reference/03-connector/_linux_install.mdx @@ -14,7 +14,7 @@ import PkgListV3 from "/components/PkgListV3"; Once the package is unzipped, you will see the following files in the directory: - _ install_client.sh_: install script - - _ taos.tar.gz_: client driver package + - _ package.tar.gz_: client driver package - _ driver_: TDengine client driver - _examples_: some example programs of different programming languages (C/C#/go/JDBC/MATLAB/python/R) You can run `install_client.sh` to install it. diff --git a/docs/en/14-reference/03-connector/_windows_install.mdx b/docs/en/14-reference/03-connector/_windows_install.mdx index a96e02feeafe6c0f0937a407d7d8d3a882a5e2d3..723f685b5deb066c81c50601f2a436f8e0c6f300 100644 --- a/docs/en/14-reference/03-connector/_windows_install.mdx +++ b/docs/en/14-reference/03-connector/_windows_install.mdx @@ -11,7 +11,7 @@ import PkgListV3 from "/components/PkgListV3"; The default installation path is C:\TDengine, including the following files (directories). - _taos.exe_: TDengine CLI command-line program - - _taosadapter.exe_: server-side executable that provides RESTful services and accepts writing requests from a variety of other softwares + - _taosadapter.exe_: server-side executable that provides RESTful services and accepts writing requests from a variety of other software - _taosBenchmark.exe_: TDengine testing tool - _cfg_: configuration file directory - _driver_: client driver dynamic link library diff --git a/docs/en/14-reference/03-connector/index.mdx b/docs/en/14-reference/03-connector/index.mdx index ba8dbb85d4982c5d6c89f5dbe6157bd88a8c00a4..a35d5bc2d1ed4a69f9750a1153d15efe815f674d 100644 --- a/docs/en/14-reference/03-connector/index.mdx +++ b/docs/en/14-reference/03-connector/index.mdx @@ -1,5 +1,6 @@ --- title: Connector +description: This document describes the connectors that TDengine provides to interface with various programming languages. --- TDengine provides a rich set of APIs (application development interface). To facilitate users to develop their applications quickly, TDengine supports connectors for multiple programming languages, including official connectors for C/C++, Java, Python, Go, Node.js, C#, and Rust. These connectors support connecting to TDengine clusters using both native interfaces (taosc) and REST interfaces (not supported in a few languages yet). Community developers have also contributed several unofficial connectors, such as the ADO.NET connector, the Lua connector, and the PHP connector. @@ -59,11 +60,11 @@ The different database framework specifications for various programming language | -------------------------------------- | ------------- | --------------- | ------------- | ------------- | ------------- | ------------- | | **Connection Management** | Support | Support | Support | Support | Support | Support | | **Regular Query** | Support | Support | Support | Support | Support | Support | -| **Parameter Binding** | Not supported | Not supported | support | Support | Not supported | Support | -| **Subscription (TMQ) ** | Not supported | Not supported | support | Not supported | Not supported | Support | -| **Schemaless** | Not supported | Not supported | Not supported | Not supported | Not supported | Not supported | -| **Bulk Pulling (based on WebSocket) ** | Support | Support | Support | support | Support | Support | -| **DataFrame** | Not supported | Support | Not supported | Not supported | Not supported | Not supported | +| **Parameter Binding** | Not Supported | Not Supported | Support | Support | Not Supported | Support | +| **Subscription (TMQ) ** | Supported | Support | Support | Not Supported | Not Supported | Support | +| **Schemaless** | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported | +| **Bulk Pulling (based on WebSocket) ** | Support | Support | Support | Support | Support | Support | +| **DataFrame** | Not Supported | Support | Not Supported | Not Supported | Not Supported | Not Supported | :::warning diff --git a/docs/en/14-reference/04-taosadapter.md b/docs/en/14-reference/04-taosadapter.md index ad00584360acc18dca46998948fd96790965e5b1..7ab894a1c72651e3568f3effa351b044c397b2dd 100644 --- a/docs/en/14-reference/04-taosadapter.md +++ b/docs/en/14-reference/04-taosadapter.md @@ -1,7 +1,7 @@ --- -title: "taosAdapter" -description: "taosAdapter is a TDengine companion tool that acts as a bridge and adapter between TDengine clusters and applications. It provides an easy-to-use and efficient way to ingest data directly from data collection agent software such as Telegraf, StatsD, collectd, etc. It also provides an InfluxDB/OpenTSDB compatible data ingestion interface, allowing InfluxDB/OpenTSDB applications to be seamlessly ported to TDengine." -sidebar_label: "taosAdapter" +title: taosAdapter +sidebar_label: taosAdapter +description: This document describes how to use taosAdapter, a TDengine companion tool that acts as a bridge and adapter between TDengine clusters and applications. --- import Prometheus from "./_prometheus.mdx" @@ -21,6 +21,7 @@ taosAdapter provides the following features. - Seamless connection to collectd - Seamless connection to StatsD - Supports Prometheus remote_read and remote_write +- Get table's VGroup ID ## taosAdapter architecture diagram @@ -57,6 +58,7 @@ Usage of taosAdapter: --collectd.enable enable collectd. Env "TAOS_ADAPTER_COLLECTD_ENABLE" (default true) --collectd.password string collectd password. Env "TAOS_ADAPTER_COLLECTD_PASSWORD" (default "taosdata") --collectd.port int collectd server port. Env "TAOS_ADAPTER_COLLECTD_PORT" (default 6045) + --collectd.ttl int collectd data ttl. Env "TAOS_ADAPTER_COLLECTD_TTL" --collectd.user string collectd user. Env "TAOS_ADAPTER_COLLECTD_USER" (default "root") --collectd.worker int collectd write worker. Env "TAOS_ADAPTER_COLLECTD_WORKER" (default 10) -c, --config string config path default /etc/taos/taosadapter.toml @@ -66,8 +68,9 @@ Usage of taosAdapter: --cors.allowOrigins stringArray cors allow origins. Env "TAOS_ADAPTER_ALLOW_ORIGINS" --cors.allowWebSockets cors allow WebSockets. Env "TAOS_ADAPTER_CORS_ALLOW_WebSockets" --cors.exposeHeaders stringArray cors expose headers. Env "TAOS_ADAPTER_Expose_Headers" - --debug enable debug mode. Env "TAOS_ADAPTER_DEBUG" + --debug enable debug mode. Env "TAOS_ADAPTER_DEBUG" (default true) --help Print this help message and exit + --httpCodeServerError Use a non-200 http status code when taosd returns an error. Env "TAOS_ADAPTER_HTTP_CODE_SERVER_ERROR" --influxdb.enable enable influxdb. Env "TAOS_ADAPTER_INFLUXDB_ENABLE" (default true) --log.enableRecordHttpSql whether to record http sql. Env "TAOS_ADAPTER_LOG_ENABLE_RECORD_HTTP_SQL" --log.path string log path. Env "TAOS_ADAPTER_LOG_PATH" (default "/var/log/taos") @@ -78,14 +81,17 @@ Usage of taosAdapter: --log.sqlRotationSize string record sql log rotation size(KB MB GB), must be a positive integer. Env "TAOS_ADAPTER_LOG_SQL_ROTATION_SIZE" (default "1GB") --log.sqlRotationTime duration record sql log rotation time. Env "TAOS_ADAPTER_LOG_SQL_ROTATION_TIME" (default 24h0m0s) --logLevel string log level (panic fatal error warn warning info debug trace). Env "TAOS_ADAPTER_LOG_LEVEL" (default "info") - --monitor.collectDuration duration Set monitor duration. Env "TAOS_MONITOR_COLLECT_DURATION" (default 3s) - --monitor.identity string The identity of the current instance, or 'hostname:port' if it is empty. Env "TAOS_MONITOR_IDENTITY" - --monitor.incgroup Whether running in cgroup. Env "TAOS_MONITOR_INCGROUP" - --monitor.password string TDengine password. Env "TAOS_MONITOR_PASSWORD" (default "taosdata") --monitor.pauseAllMemoryThreshold float Memory percentage threshold for pause all. Env "TAOS_MONITOR_PAUSE_ALL_MEMORY_THRESHOLD" (default 80) - --monitor.pauseQueryMemoryThreshold float Memory percentage threshold for pause query. Env "TAOS_MONITOR_PAUSE_QUERY_MEMORY_THRESHOLD" (default 70) - --monitor.user string TDengine user. Env "TAOS_MONITOR_USER" (default "root") - --monitor.writeInterval duration Set write to TDengine interval. Env "TAOS_MONITOR_WRITE_INTERVAL" (default 30s) - --monitor.writeToTD Whether write metrics to TDengine. Env "TAOS_MONITOR_WRITE_TO_TD" + --monitor.collectDuration duration Set monitor duration. Env "TAOS_ADAPTER_MONITOR_COLLECT_DURATION" (default 3s) + --monitor.disable Whether to disable monitoring. Env "TAOS_ADAPTER_MONITOR_DISABLE" + --monitor.disableCollectClientIP Whether to disable collecting clientIP. Env "TAOS_ADAPTER_MONITOR_DISABLE_COLLECT_CLIENT_IP" + --monitor.identity string The identity of the current instance, or 'hostname:port' if it is empty. Env "TAOS_ADAPTER_MONITOR_IDENTITY" + --monitor.incgroup Whether running in cgroup. Env "TAOS_ADAPTER_MONITOR_INCGROUP" + --monitor.password string TDengine password. Env "TAOS_ADAPTER_MONITOR_PASSWORD" (default "taosdata") + --monitor.pauseAllMemoryThreshold float Memory percentage threshold for pause all. Env "TAOS_ADAPTER_MONITOR_PAUSE_ALL_MEMORY_THRESHOLD" (default 80) + --monitor.pauseQueryMemoryThreshold float Memory percentage threshold for pause query. Env "TAOS_ADAPTER_MONITOR_PAUSE_QUERY_MEMORY_THRESHOLD" (default 70) + --monitor.user string TDengine user. Env "TAOS_ADAPTER_MONITOR_USER" (default "root") + --monitor.writeInterval duration Set write to TDengine interval. Env "TAOS_ADAPTER_MONITOR_WRITE_INTERVAL" (default 30s) + --monitor.writeToTD Whether write metrics to TDengine. Env "TAOS_ADAPTER_MONITOR_WRITE_TO_TD" --node_exporter.caCertFile string node_exporter ca cert file path. Env "TAOS_ADAPTER_NODE_EXPORTER_CA_CERT_FILE" --node_exporter.certFile string node_exporter cert file path. Env "TAOS_ADAPTER_NODE_EXPORTER_CERT_FILE" --node_exporter.db string node_exporter db name. Env "TAOS_ADAPTER_NODE_EXPORTER_DB" (default "node_exporter") @@ -98,6 +104,7 @@ Usage of taosAdapter: --node_exporter.keyFile string node_exporter cert key file path. Env "TAOS_ADAPTER_NODE_EXPORTER_KEY_FILE" --node_exporter.password string node_exporter password. Env "TAOS_ADAPTER_NODE_EXPORTER_PASSWORD" (default "taosdata") --node_exporter.responseTimeout duration node_exporter response timeout. Env "TAOS_ADAPTER_NODE_EXPORTER_RESPONSE_TIMEOUT" (default 5s) + --node_exporter.ttl int node_exporter data ttl. Env "TAOS_ADAPTER_NODE_EXPORTER_TTL" --node_exporter.urls strings node_exporter urls. Env "TAOS_ADAPTER_NODE_EXPORTER_URLS" (default [http://localhost:9100]) --node_exporter.user string node_exporter user. Env "TAOS_ADAPTER_NODE_EXPORTER_USER" (default "root") --opentsdb.enable enable opentsdb. Env "TAOS_ADAPTER_OPENTSDB_ENABLE" (default true) @@ -109,10 +116,11 @@ Usage of taosAdapter: --opentsdb_telnet.password string opentsdb_telnet password. Env "TAOS_ADAPTER_OPENTSDB_TELNET_PASSWORD" (default "taosdata") --opentsdb_telnet.ports ints opentsdb telnet tcp port. Env "TAOS_ADAPTER_OPENTSDB_TELNET_PORTS" (default [6046,6047,6048,6049]) --opentsdb_telnet.tcpKeepAlive enable tcp keep alive. Env "TAOS_ADAPTER_OPENTSDB_TELNET_TCP_KEEP_ALIVE" + --opentsdb_telnet.ttl int opentsdb_telnet data ttl. Env "TAOS_ADAPTER_OPENTSDB_TELNET_TTL" --opentsdb_telnet.user string opentsdb_telnet user. Env "TAOS_ADAPTER_OPENTSDB_TELNET_USER" (default "root") - --pool.idleTimeout duration Set idle connection timeout. Env "TAOS_ADAPTER_POOL_IDLE_TIMEOUT" (default 1h0m0s) - --pool.maxConnect int max connections to taosd. Env "TAOS_ADAPTER_POOL_MAX_CONNECT" (default 4000) - --pool.maxIdle int max idle connections to taosd. Env "TAOS_ADAPTER_POOL_MAX_IDLE" (default 4000) + --pool.idleTimeout duration Set idle connection timeout. Env "TAOS_ADAPTER_POOL_IDLE_TIMEOUT" + --pool.maxConnect int max connections to taosd. Env "TAOS_ADAPTER_POOL_MAX_CONNECT" + --pool.maxIdle int max idle connections to taosd. Env "TAOS_ADAPTER_POOL_MAX_IDLE" -P, --port int http port. Env "TAOS_ADAPTER_PORT" (default 6041) --prometheus.enable enable prometheus. Env "TAOS_ADAPTER_PROMETHEUS_ENABLE" (default true) --restfulRowLimit int restful returns the maximum number of rows (-1 means no limit). Env "TAOS_ADAPTER_RESTFUL_ROW_LIMIT" (default -1) @@ -129,6 +137,7 @@ Usage of taosAdapter: --statsd.port int statsd server port. Env "TAOS_ADAPTER_STATSD_PORT" (default 6044) --statsd.protocol string statsd protocol [tcp or udp]. Env "TAOS_ADAPTER_STATSD_PROTOCOL" (default "udp") --statsd.tcpKeepAlive enable tcp keep alive. Env "TAOS_ADAPTER_STATSD_TCP_KEEP_ALIVE" + --statsd.ttl int statsd data ttl. Env "TAOS_ADAPTER_STATSD_TTL" --statsd.user string statsd user. Env "TAOS_ADAPTER_STATSD_USER" (default "root") --statsd.worker int statsd write worker. Env "TAOS_ADAPTER_STATSD_WORKER" (default 10) --taosConfigDir string load taos client config path. Env "TAOS_ADAPTER_TAOS_CONFIG_FILE" @@ -174,6 +183,7 @@ See [example/config/taosadapter.toml](https://github.com/taosdata/taosadapter/bl node_export is an exporter for machine metrics. Please visit [https://github.com/prometheus/node_exporter](https://github.com/prometheus/node_exporter) for more information. - Support for Prometheus remote_read and remote_write remote_read and remote_write are interfaces for Prometheus data read and write from/to other data storage solution. Please visit [https://prometheus.io/blog/2019/10/10/remote-read-meets-streaming/#remote-apis](https://prometheus.io/blog/2019/10/10/remote-read-meets-streaming/#remote-apis) for more information. +- Get table's VGroup ID. For more information about VGroup, please refer to [primary-logic-unit](/tdinternal/arch/#primary-logic-unit). ## Interfaces @@ -195,6 +205,7 @@ Support InfluxDB query parameters as follows. - `precision` The time precision used by TDengine - `u` TDengine user name - `p` TDengine password +- `ttl` The time to live of automatically created sub-table. This value cannot be updated. TDengine will use the ttl value of the first data of sub-table to create sub-table. For more information, please refer [Create Table](/taos-sql/table/#create-table) Note: InfluxDB token authorization is not supported at present. Only Basic authorization and query parameter validation are supported. Example: curl --request POST http://127.0.0.1:6041/influxdb/v1/write?db=test --user "root:taosdata" --data-binary "measurement,host=host1 field1=2i,field2=2.0 1577836800000000000" @@ -236,6 +247,10 @@ node_export is an exporter of hardware and OS metrics exposed by the \*NIX kerne +### Get table's VGroup ID + +You can call `http://:6041/rest/vgid?db=&table=` to get table's VGroup ID. For more information about VGroup, please refer to [primary-logic-unit](/tdinternal/arch/#primary-logic-unit). + ## Memory usage optimization methods taosAdapter will monitor its memory usage during operation and adjust it with two thresholds. Valid values are integers between 1 to 100, and represent a percentage of the system's physical memory. @@ -313,6 +328,10 @@ This parameter controls the number of results returned by the following interfac - `http://:6041/rest/sql` - `http://:6041/prometheus/v1/remote_read/:db` +## Configure http return code + +taosAdapter uses the parameter `httpCodeServerError` to set whether to return a non-200 http status code http status code other than when the C interface returns an error. When set to true, different http status codes will be returned according to the error code returned by C. For details, see [RESTful API](https://docs.tdengine.com/reference/rest-api/) HTTP Response Code chapter. + ## Troubleshooting You can check the taosAdapter running status with the `systemctl status taosadapter` command. diff --git a/docs/en/14-reference/05-taosbenchmark.md b/docs/en/14-reference/05-taosbenchmark.md index 6e08671e344100aa3dcfeba5a10c0d0e304a1a91..f49424d3ba817be1d338ab78fb5738f859a5a235 100644 --- a/docs/en/14-reference/05-taosbenchmark.md +++ b/docs/en/14-reference/05-taosbenchmark.md @@ -1,8 +1,8 @@ --- title: taosBenchmark sidebar_label: taosBenchmark +description: This document describes how to use taosBenchmark, a tool for testing the performance of TDengine. toc_max_heading_level: 4 -description: "taosBenchmark (once called taosdemo ) is a tool for testing the performance of TDengine." --- # Introduction @@ -92,7 +92,7 @@ taosBenchmark -f -## Command-line argument in detailed +## Command-line argument in detail - **-f/--file ** : specify the configuration file to use. This file includes All parameters. Users should not use this parameter with other parameters on the command-line. There is no default value. @@ -198,19 +198,28 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\) - **-R/--disorder-range ** : Specify the timestamp range for the disordered data. It leads the resulting disorder timestamp as the ordered timestamp minus a random value in this range. Valid only if the percentage of disordered data specified by `-O/--disorder` is greater than 0. -- **-F/--prepare_rand ** : +- **-F/--prepared_rand ** : Specify the number of unique values in the generated random data. A value of 1 means that all data are equal. The default value is 10000. - **-a/--replica ** : Specify the number of replicas when creating the database. The default value is 1. +- **-k/--keep-trying ** : + Keep trying if failed to insert, default is no. Available with v3.0.9+. + +- **-z/--trying-interval ** : + Specify interval between keep trying insert. Valid value is a positive number. Only valid when keep trying be enabled. Available with v3.0.9+. + +- **-v/--vgroups ** : + Specify vgroups number for creating a database, only valid with daemon version 3.0+ + - **-V/--version** : Show version information only. Users should not use it with other parameters. - **-? /--help** : Show help information and exit. Users should not use it with other parameters. -## Configuration file parameters in detailed +## Configuration file parameters in detail ### General configuration parameters @@ -231,6 +240,18 @@ The parameters listed in this section apply to all function modes. `filetype` must be set to `insert` in the insertion scenario. See [General Configuration Parameters](#General Configuration Parameters) +- ** keep_trying ** : Keep trying if failed to insert, default is no. Available with v3.0.9+. + +- ** trying_interval ** : Specify interval between keep trying insert. Valid value is a positive number. Only valid when keep trying be enabled. Available with v3.0.9+. + +- ** childtable_from and childtable_to ** : specify the child table range to create. The range is [childtable_from, childtable_to). +  +- ** continue_if_fail ** : allow the user to specify the reaction if the insertion failed. + + - "continue_if_fail" : "no" // means taosBenchmark will exit if it fails to insert as default reaction behavior. + - "continue_if_fail" : "yes" // means taosBenchmark will warn the user if it fails to insert but continue to insert the next record. + - "continue_if_fail": "smart" // means taosBenchmark will try to create the non-existent child table if it fails to insert. + #### Database related configuration parameters The parameters related to database creation are configured in `dbinfo` in the json configuration file, as follows. The other parameters correspond to the database parameters specified when `create database` in [../../taos-sql/database]. @@ -342,7 +363,7 @@ The configuration parameters for specifying super table tag columns and data col - **min**: The minimum value of the column/label of the data type. The generated value will equal or large than the minimum value. -- **max**: The maximum value of the column/label of the data type. The generated value will less than the maxium value. +- **max**: The maximum value of the column/label of the data type. The generated value will less than the maximum value. - **values**: The value field of the nchar/binary column/label, which will be chosen randomly from the values. @@ -370,7 +391,7 @@ The configuration parameters for specifying super table tag columns and data col - **num_of_records_per_req** : Writing the number of rows of records per request to TDengine, the default value is 30000. When it is set too large, the TDengine client driver will return the corresponding error message, so you need to lower the setting of this parameter to meet the writing requirements. -- **prepare_rand**: The number of unique values in the generated random data. A value of 1 means that all data are equal. The default value is 10000. +- **prepared_rand**: The number of unique values in the generated random data. A value of 1 means that all data are equal. The default value is 10000. ### Query scenario configuration parameters @@ -382,11 +403,11 @@ See [General Configuration Parameters](#General Configuration Parameters) for de #### Configuration parameters for executing the specified query statement -The configuration parameters for querying the sub-tables or the normal tables are set in `specified_table_query`. +The configuration parameters for querying the specified table (it can be a super table, a sub-table or a normal table) are set in `specified_table_query`. - **query_interval** : The query interval in seconds, the default value is 0. -- **threads**: The number of threads to execute the query SQL, the default value is 1. +- **threads/concurrent**: The number of threads to execute the query SQL, the default value is 1. - **sqls**. - **sql**: the SQL command to be executed. @@ -413,9 +434,9 @@ The configuration parameters of the super table query are set in `super_table_qu #### Configuration parameters for executing the specified subscription statement -The configuration parameters for subscribing to a sub-table or a generic table are set in `specified_table_query`. +The configuration parameters for subscribing to a specified table (it can be a super table, a sub-table or a generic table) are set in `specified_table_query`. -- **threads**: The number of threads to execute SQL, default is 1. +- **threads/concurrent**: The number of threads to execute SQL, default is 1. - **interval**: The time interval to execute the subscription, in seconds, default is 0. diff --git a/docs/en/14-reference/06-taosdump.md b/docs/en/14-reference/06-taosdump.md index e73441a96b087062b2e3912ed73010fc3e761bb9..dcfc068a3d64eb9f755f498b2b80d0a2b228842f 100644 --- a/docs/en/14-reference/06-taosdump.md +++ b/docs/en/14-reference/06-taosdump.md @@ -1,6 +1,6 @@ --- title: taosdump -description: "taosdump is a tool that supports backing up data from a running TDengine cluster and restoring the backed up data to the same, or another running TDengine cluster." +description: This document describes how to use taosdump, a tool for backing up and restoring the data in a TDengine cluster. --- ## Introduction @@ -19,7 +19,7 @@ Users should not use taosdump to back up raw data, environment settings, hardwar There are two ways to install taosdump: -- Install the taosTools official installer. Please find taosTools from [All download links](https://www.tdengine.com/all-downloads) page and download and install it. +- Install the taosTools official installer. Please find taosTools from [Release History](https://docs.taosdata.com/releases/tools/) page and download and install it. - Compile taos-tools separately and install it. Please refer to the [taos-tools](https://github.com/taosdata/taos-tools) repository for details. diff --git a/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json b/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json index f651983528ca824b4e6b14586aac5a5bfb4ecab8..43f29bda4445d0559b60d51a6d421442e9d38d4d 100644 --- a/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json +++ b/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json @@ -1590,7 +1590,7 @@ }, { "datasource": "${DS_TDENGINE}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -1919,7 +1919,7 @@ }, { "datasource": "${DS_TDENGINE}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -1977,7 +1977,7 @@ }, { "datasource": "${DS_TDENGINE}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -2825,7 +2825,7 @@ "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "Requets Count per Minutes $fqdn", + "title": "Requests Count per Minutes $fqdn", "tooltip": { "shared": true, "sort": 0, diff --git a/docs/en/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp b/docs/en/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp index 942130d4fabf7944c7add10acb3bb42ca7f51e0f..a90477880ff3a2cb2068540b55b69e4bbdbd8d4c 100644 Binary files a/docs/en/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp and b/docs/en/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp differ diff --git a/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json b/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json index b4254c428b28a0084e54b5e3c509dd2e0ec651b9..660875262edfe4b4211075839b60dfcdcb26d198 100644 --- a/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json +++ b/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json @@ -1566,7 +1566,7 @@ }, { "datasource": "${ds}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -1933,7 +1933,7 @@ }, { "datasource": "${ds}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -2000,7 +2000,7 @@ }, { "datasource": "${ds}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -2961,7 +2961,7 @@ "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "Requets Count per Minutes $fqdn", + "title": "Requests Count per Minutes $fqdn", "tooltip": { "shared": true, "sort": 0, @@ -3355,4 +3355,4 @@ "title": "TDengine", "uid": "tdengine", "version": 8 -} \ No newline at end of file +} diff --git a/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana.json b/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana.json index 7696cfce3fcca3dd5f9278c91d3df2c1b32b9c97..e3bad31fab4e9110da505621d8ea7444584b33cb 100644 --- a/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana.json +++ b/docs/en/14-reference/07-tdinsight/assets/tdengine-grafana.json @@ -186,7 +186,7 @@ }, { "datasource": "TDengine", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "gridPos": { "h": 6, "w": 8, @@ -253,7 +253,7 @@ ], "timeFrom": null, "timeShift": null, - "title": "taosd memery", + "title": "taosd memory", "type": "gauge" }, { diff --git a/docs/en/14-reference/07-tdinsight/index.md b/docs/en/14-reference/07-tdinsight/index.md index d03c16a8bc25a39fb751ded4b5c12df4b69a8e4e..652d5ded0b3fed28961e92d4894fa090be393873 100644 --- a/docs/en/14-reference/07-tdinsight/index.md +++ b/docs/en/14-reference/07-tdinsight/index.md @@ -1,6 +1,7 @@ --- title: TDinsight - Grafana-based Zero-Dependency Monitoring Solution for TDengine sidebar_label: TDinsight +description: This document describes TDinsight, a monitoring solution for TDengine. --- TDinsight is a solution for monitoring TDengine using the builtin native monitoring database and [Grafana]. @@ -325,11 +326,12 @@ Currently, only the number of logins per minute is reported. Support monitoring taosAdapter request statistics and status details. Includes. -1. **http_request_inflight**: number of real-time requests. -2. **http_request_total**: number of total requests. -3. **http_request_fail**: number of failed requets. -4. **CPU Used**: CPU usage of taosAdapter. -5. **Memory Used**: Memory usage of taosAdapter. +1. **Http Request Total**: number of total requests. +2. **Http Request Fail**: number of failed requests. +3. **CPU Used**: CPU usage of taosAdapter. +4. **Memory Used**: Memory usage of taosAdapter. +5. **Http Request Inflight**: number of real-time requests. +6. **Http Status Code**: taosAdapter http status code. ## Upgrade diff --git a/docs/en/14-reference/08-taos-shell.md b/docs/en/14-reference/08-taos-shell.md index 68e2f087658305ec408c50e27f4a87ef43b2c870..e66da7ec1768227d5ec50ce039bd8f794cf90c48 100644 --- a/docs/en/14-reference/08-taos-shell.md +++ b/docs/en/14-reference/08-taos-shell.md @@ -1,7 +1,7 @@ --- title: TDengine Command Line Interface (CLI) sidebar_label: Command Line Interface -description: Instructions and tips for using the TDengine CLI +description: This document describes how to use the TDengine CLI. --- The TDengine command-line interface (hereafter referred to as `TDengine CLI`) is the simplest way for users to manipulate and interact with TDengine instances. @@ -61,12 +61,14 @@ And many more parameters. - -c CONFIGDIR: Specify the directory where configuration file exists. The default is `/etc/taos`, and the default name of the configuration file in this directory is `taos.cfg` - -C: Print the configuration parameters of `taos.cfg` in the default directory or specified by -c - -d DATABASE: Specify the database to use when connecting to the server +- -E dsn: connect to the TDengine Cloud or a server which provides WebSocket connection - -f FILE: Execute the SQL script file in non-interactive mode Note that each SQL statement in the script file must be only one line. - -k: Test the operational status of the server. 0: unavailable; 1: network ok; 2: service ok; 3: service degraded; 4: exiting - -l PKTLEN: Test package size to be used for network testing - -n NETROLE: test scope for network connection test, default is `client`. The value can be `client` or `server`. - -N PKTNUM: Number of packets used for network testing - -r: output the timestamp format as unsigned 64-bits integer (uint64_t in C language) +- -R: Use RESTful mode when connecting - -s COMMAND: execute SQL commands in non-interactive mode - -t: Test the boot status of the server. The statuses of -k apply. - -w DISPLAYWIDTH: Specify the number of columns of the server display. diff --git a/docs/en/14-reference/09-support-platform/index.md b/docs/en/14-reference/09-support-platform/index.md index 061294f0160f5f07c7c032b4a7475f6b12c2efca..7dfa8ac93a9e91eb9238f7b56033a592c241079f 100644 --- a/docs/en/14-reference/09-support-platform/index.md +++ b/docs/en/14-reference/09-support-platform/index.md @@ -1,6 +1,6 @@ --- title: List of supported platforms -description: "List of platforms supported by TDengine server, client, and connector" +description: This document describes the supported platforms for the TDengine server, client, and connectors. --- ## List of supported platforms for TDengine server diff --git a/docs/en/14-reference/11-docker/index.md b/docs/en/14-reference/11-docker/index.md index 89987c456f14d243a4b59af5b15ae754225bbaf9..5a48f2e4b1e58132c728dadfba2afbe39ae8bef3 100644 --- a/docs/en/14-reference/11-docker/index.md +++ b/docs/en/14-reference/11-docker/index.md @@ -1,6 +1,6 @@ --- title: Deploying TDengine with Docker -description: "This chapter focuses on starting the TDengine service in a container and accessing it." +description: This chapter describes how to start and access TDengine in a Docker container. --- This chapter describes how to start the TDengine service in a container and access it. Users can control the behavior of the service in the container by using environment variables on the docker run command-line or in the docker-compose file. @@ -273,49 +273,48 @@ password: taosdata ## Start the TDengine cluster with docker-compose -1. The following docker-compose file starts a TDengine cluster with two replicas, two management nodes, two data nodes, and one arbitrator. - - ```docker - version: "3" - services: - arbitrator: - image: tdengine/tdengine:$VERSION - command: tarbitrator - td-1: - image: tdengine/tdengine:$VERSION - environment: - TAOS_FQDN: "td-1" - TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 - volumes: - - taosdata-td1:/var/lib/taos/ - - taoslog-td1:/var/log/taos/ - td-2: - image: tdengine/tdengine:$VERSION - environment: - TAOS_FQDN: "td-2" - TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 - volumes: - - taosdata-td2:/var/lib/taos/ - - taoslog-td2:/var/log/taos/ - volumes: - taosdata-td1: - taoslog-td1: - taosdata-td2: - taoslog-td2: - ``` +1. The following docker-compose file starts a TDengine cluster with three nodes. + +```yml +version: "3" +services: + td-1: + image: tdengine/tdengine:$VERSION + environment: + TAOS_FQDN: "td-1" + TAOS_FIRST_EP: "td-1" + volumes: + - taosdata-td1:/var/lib/taos/ + - taoslog-td1:/var/log/taos/ + td-2: + image: tdengine/tdengine:$VERSION + environment: + TAOS_FQDN: "td-2" + TAOS_FIRST_EP: "td-1" + volumes: + - taosdata-td2:/var/lib/taos/ + - taoslog-td2:/var/log/taos/ + td-3: + image: tdengine/tdengine:$VERSION + environment: + TAOS_FQDN: "td-3" + TAOS_FIRST_EP: "td-1" + volumes: + - taosdata-td3:/var/lib/taos/ + - taoslog-td3:/var/log/taos/ +volumes: + taosdata-td1: + taoslog-td1: + taosdata-td2: + taoslog-td2: + taosdata-td3: + taoslog-td3: +``` :::note - The `VERSION` environment variable is used to set the tdengine image tag - `TAOS_FIRST_EP` must be set on the newly created instance so that it can join the TDengine cluster; if there is a high availability requirement, `TAOS_SECOND_EP` needs to be used at the same time -- `TAOS_REPLICA` is used to set the default number of database replicas. Its value range is [1,3] - We recommend setting it with `TAOS_ARBITRATOR` to use arbitrator in a two-nodes environment. ::: 2. Start the cluster @@ -345,17 +344,18 @@ password: taosdata 4. Show dnodes via TDengine CLI - ```shell - $ docker-compose exec td-1 taos -s "show dnodes" - - taos> show dnodes - id | end_point | vnodes | cores | status | role | create_time | offline reason | - ====================================================================================================================================== - 1 | td-1:6030 | 1 | 8 | ready | any | 2022-01-18 02:47:42.871 | | - 2 | td-2:6030 | 0 | 8 | ready | any | 2022-01-18 02:47:43.518 | | - 0 | arbitrator:6042 | 0 | 0 | ready | arb | 2022-01-18 02:47:43.633 | - | - Query OK, 3 row(s) in set (0.000811s) - ``` +```shell +$ docker-compose exec td-1 taos -s "show dnodes" + +taos> show dnodes + id | endpoint | vnodes | support_vnodes | status | create_time | note | +====================================================================================================================================== + 1 | td-1:6030 | 0 | 32 | ready | 2022-08-19 07:57:29.971 | | + 2 | td-2:6030 | 0 | 32 | ready | 2022-08-19 07:57:31.415 | | + 3 | td-3:6030 | 0 | 32 | ready | 2022-08-19 07:57:31.417 | | +Query OK, 3 rows in database (0.021262s) + +``` ## taosAdapter @@ -373,83 +373,70 @@ password: taosdata Suppose you want to deploy multiple taosAdapters to improve throughput and provide high availability. In that case, the recommended configuration method uses a reverse proxy such as Nginx to offer a unified access entry. For specific configuration methods, please refer to the official documentation of Nginx. Here is an example: - ```docker - version: "3" - - networks: - inter: - api: - - services: - arbitrator: - image: tdengine/tdengine:$VERSION - command: tarbitrator - networks: - - inter - td-1: - image: tdengine/tdengine:$VERSION - networks: - - inter - environment: - TAOS_FQDN: "td-1" - TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 - volumes: - - taosdata-td1:/var/lib/taos/ - - taoslog-td1:/var/log/taos/ - td-2: - image: tdengine/tdengine:$VERSION - networks: - - inter - environment: - TAOS_FQDN: "td-2" - TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 - volumes: - - taosdata-td2:/var/lib/taos/ - - taoslog-td2:/var/log/taos/ - adapter: - image: tdengine/tdengine:$VERSION - command: taosadapter - networks: - - inter - environment: - TAOS_FIRST_EP: "td-1" - TAOS_SECOND_EP: "td-2" - deploy: - replicas: 4 - nginx: - image: nginx - depends_on: - - adapter - networks: - - inter - - api - ports: - - 6041:6041 - - 6044:6044/udp - command: [ - "sh", - "-c", - "while true; - do curl -s http://adapter:6041/-/ping >/dev/null && break; - done; - printf 'server{listen 6041;location /{proxy_pass http://adapter:6041;}}' - > /etc/nginx/conf.d/rest.conf; - printf 'stream{server{listen 6044 udp;proxy_pass adapter:6044;}}' - >> /etc/nginx/nginx.conf;cat /etc/nginx/nginx.conf; - nginx -g 'daemon off;'", - ] - volumes: - taosdata-td1: - taoslog-td1: - taosdata-td2: - taoslog-td2: - ``` +```yml +version: "3" + +networks: + inter: + +services: + td-1: + image: tdengine/tdengine:$VERSION + networks: + - inter + environment: + TAOS_FQDN: "td-1" + TAOS_FIRST_EP: "td-1" + volumes: + - taosdata-td1:/var/lib/taos/ + - taoslog-td1:/var/log/taos/ + td-2: + image: tdengine/tdengine:$VERSION + networks: + - inter + environment: + TAOS_FQDN: "td-2" + TAOS_FIRST_EP: "td-1" + volumes: + - taosdata-td2:/var/lib/taos/ + - taoslog-td2:/var/log/taos/ + adapter: + image: tdengine/tdengine:$VERSION + entrypoint: "taosadapter" + networks: + - inter + environment: + TAOS_FIRST_EP: "td-1" + TAOS_SECOND_EP: "td-2" + deploy: + replicas: 4 + nginx: + image: nginx + depends_on: + - adapter + networks: + - inter + ports: + - 6041:6041 + - 6044:6044/udp + command: [ + "sh", + "-c", + "while true; + do curl -s http://adapter:6041/-/ping >/dev/null && break; + done; + printf 'server{listen 6041;location /{proxy_pass http://adapter:6041;}}' + > /etc/nginx/conf.d/rest.conf; + printf 'stream{server{listen 6044 udp;proxy_pass adapter:6044;}}' + >> /etc/nginx/nginx.conf;cat /etc/nginx/nginx.conf; + nginx -g 'daemon off;'", + ] +volumes: + taosdata-td1: + taoslog-td1: + taosdata-td2: + taoslog-td2: +``` ## Deploy with docker swarm diff --git a/docs/en/14-reference/12-config/index.md b/docs/en/14-reference/12-config/index.md index 274c99509836702dc067ca7f3357acc96be4132c..430487a3af9f8729e199251b9cb6c913ee059769 100644 --- a/docs/en/14-reference/12-config/index.md +++ b/docs/en/14-reference/12-config/index.md @@ -1,6 +1,6 @@ --- title: Configuration Parameters -description: "Configuration parameters for client and server in TDengine" +description: This document describes the configuration parameters for the TDengine server and client. --- ## Configuration File on Server Side @@ -29,7 +29,7 @@ taos -C taos --dump-config ``` -# Configuration Parameters +## Configuration Parameters :::note The parameters described in this document by the effect that they have on the system. @@ -83,7 +83,7 @@ The parameters described in this document by the effect that they have on the sy | :------- | :----------- | :----------------------------------------------- | :--------------------------------------------------------------------------------------------- | | TCP | 6030 | Communication between client and server. In a multi-node cluster, communication between nodes. serverPort | | TCP | 6041 | REST connection between client and server | Prior to 2.4.0.0: serverPort+11; After 2.4.0.0 refer to [taosAdapter](/reference/taosadapter/) | -| TCP | 6043 | Service Port of TaosKeeper | The parameter of TaosKeeper | +| TCP | 6043 | Service Port of taosKeeper | The parameter of taosKeeper | | TCP | 6044 | Data access port for StatsD | Configurable through taosAdapter parameters. | UDP | 6045 | Data access for statsd | Configurable through taosAdapter parameters. | TCP | 6060 | Port of Monitoring Service in Enterprise version | | @@ -99,6 +99,9 @@ The parameters described in this document by the effect that they have on the sy ## Monitoring Parameters +:::note +Please note the `taoskeeper` needs to be installed and running to create the `log` database and receiving metrics sent by `taosd` as the full monitoring solution. + ### monitor | Attribute | Description | @@ -106,7 +109,7 @@ The parameters described in this document by the effect that they have on the sy | Applicable | Server only | | Meaning | The switch for monitoring inside server. The main object of monitoring is to collect information about load on physical nodes, including CPU usage, memory usage, disk usage, and network bandwidth. Monitoring information is sent over HTTP to the taosKeeper service specified by `monitorFqdn` and `monitorProt`. | Value Range | 0: monitoring disabled, 1: monitoring enabled | -| Default | 1 | +| Default | 0 | ### monitorFqdn @@ -142,6 +145,15 @@ The parameters described in this document by the effect that they have on the sy | Meaning | Switch for allowing TDengine to collect and report service usage information | | Value Range | 0: Not allowed; 1: Allowed | | Default Value | 1 | +### crashReporting + +| Attribute | Description | +| -------- | -------------------------------------------- | +| Applicable | Server Only | +| Meaning |Switch for allowing TDengine to collect and report crash related information | +| Value Range | 0,1 0: Not allowed;1:allowed | +| Default Value | 1 | + ## Query Parameters @@ -153,11 +165,7 @@ The parameters described in this document by the effect that they have on the sy | Meaning | Execution policy for query statements | | Unit | None | | Default | 1 | -| Notes | 1: Run queries on vnodes and not on qnodes | - -2: Run subtasks without scan operators on qnodes and subtasks with scan operators on vnodes. - -3: Only run scan operators on vnodes; run all other operators on qnodes. +| Value Range | 1: Run queries on vnodes and not on qnodes; 2: Run subtasks without scan operators on qnodes and subtasks with scan operators on vnodes; 3: Only run scan operators on vnodes, and run all other operators on qnodes. | ### querySmaOptimize @@ -167,12 +175,17 @@ The parameters described in this document by the effect that they have on the sy | Meaning | SMA index optimization policy | | Unit | None | | Default Value | 0 | -| Notes | +| Notes |0: Disable SMA indexing and perform all queries on non-indexed data; 1: Enable SMA indexing and perform queries from suitable statements on precomputation results.| -0: Disable SMA indexing and perform all queries on non-indexed data. - -1: Enable SMA indexing and perform queries from suitable statements on precomputation results.| +### countAlwaysReturnValue +| Attribute | Description | +| -------- | -------------------------------- | +| Applicable | Server only | +| Meaning | count()/hyperloglog() return value or not if the input data is empty or NULL | +| Vlue Range | 0:Return empty line,1:Return 0 | +| Default | 1 | +| Notes | When this parameter is setting to 1, for queries containing GROUP BY, PARTITION BY and INTERVAL clause, and input data in certain groups or windows is empty or NULL, the corresponding groups or windows have no return values | ### maxNumOfDistinctRes @@ -306,6 +319,15 @@ The charset that takes effect is UTF-8. | Applicable | Server Only | | Meaning | All data files are stored in this directory | | Default Value | /var/lib/taos | +| Note | The [Tiered Storage](https://docs.tdengine.com/tdinternal/arch/#tiered-storage) function needs to be used in conjunction with the [KEEP](https://docs.tdengine.com/taos-sql/database/#parameters) parameter | + +### tempDir + +| Attribute | Description | +| -------- | ------------------------------------------ | +| Applicable | Server only | +| Meaning | The directory where to put all the temporary files generated during system running | +| Default | /tmp | ### minimalTmpDirGB @@ -336,89 +358,6 @@ The charset that takes effect is UTF-8. | Value Range | 0-4096 | | Default Value | 2x the CPU cores | -## Time Parameters - -### statusInterval - -| Attribute | Description | -| -------- | --------------------------- | -| Applicable | Server Only | -| Meaning | the interval of dnode reporting status to mnode | -| Unit | second | -| Value Range | 1-10 | -| Default Value | 1 | - -### shellActivityTimer - -| Attribute | Description | -| -------- | --------------------------------- | -| Applicable | Server and Client | -| Meaning | The interval for TDengine CLI to send heartbeat to mnode | -| Unit | second | -| Value Range | 1-120 | -| Default Value | 3 | - -## Performance Optimization Parameters - -### numOfCommitThreads - -| Attribute | Description | -| -------- | ---------------------- | -| Applicable | Server Only | -| Meaning | Maximum of threads for committing to disk | -| Default Value | | - -## Compression Parameters - -### compressMsgSize - -| Attribute | Description | -| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Applicable | Server Only | -| Meaning | The threshold for message size to compress the message. | Set the value to 64330 bytes for good message compression. | -| Unit | bytes | -| Value Range | 0: already compress; >0: compress when message exceeds it; -1: always uncompress | -| Default Value | -1 | - -### compressColData - -| Attribute | Description | -| -------- | --------------------------------------------------------------------------------------- | -| Applicable | Server Only | -| Meaning | The threshold for size of column data to trigger compression for the query result | -| Unit | bytes | -| Value Range | 0: always compress; >0: only compress when the size of any column data exceeds the threshold; -1: always uncompress | -| Default Value | -1 | -| Default Value | -1 | -| Note | available from version 2.3.0.0 | | - -## Continuous Query Parameters | - -### minSlidingTime - -| Attribute | Description | -| ------------- | -------------------------------------------------------- | -| Applicable | Server Only | -| Meaning | Minimum sliding time of time window | -| Unit | millisecond or microsecond , depending on time precision | -| Value Range | 10-1000000 | -| Default Value | 10 | - -### minIntervalTime - -| Attribute | Description | -| ------------- | --------------------------- | -| Applicable | Server Only | -| Meaning | Minimum size of time window | -| Unit | millisecond | -| Value Range | 1-1000000 | -| Default Value | 10 | - -:::info -To prevent system resource from being exhausted by multiple concurrent streams, a random delay is applied on each stream automatically. `maxFirstStreamCompDelay` is the maximum delay time before a continuous query is started the first time. `streamCompDelayRatio` is the ratio for calculating delay time, with the size of the time window as base. `maxStreamCompDelay` is the maximum delay time. The actual delay time is a random time not bigger than `maxStreamCompDelay`. If a continuous query fails, `retryStreamComDelay` is the delay time before retrying it, also not bigger than `maxStreamCompDelay`. - -::: - ## Log Parameters ### logDir @@ -661,9 +600,21 @@ To prevent system resource from being exhausted by multiple concurrent streams, | Attribute | Description | | -------- | ----------------------------- | | Applicable | Client only | -| Meaning | Whether schemaless columns are consistently ordered | +| Meaning | Whether schemaless columns are consistently ordered, depat, discarded since 3.0.3.0| | Value Range | 0: not consistent; 1: consistent. | -| Default | 1 | +| Default | 0 | + +## Compress Parameters + +### compressMsgSize + +| Attribute | Description | +| -------- | ----------------------------- | +| Applicable | Both Client and Server side | +| Meaning | Whether RPC message is compressed | +| Value Range | -1: none message is compressed; 0: all messages are compressed; N (N>0): messages exceeding N bytes are compressed | +| Default | -1 | + ## Other Parameters @@ -686,172 +637,60 @@ To prevent system resource from being exhausted by multiple concurrent streams, | Value Range | 0: disable UDF; 1: enabled UDF | | Default Value | 1 | -## Parameter Comparison of TDengine 2.x and 3.0 -| # | **Parameter** | **In 2.x** | **In 3.0** | -| --- | :-----------------: | --------------- | --------------- | -| 1 | firstEp | Yes | Yes | -| 2 | secondEp | Yes | Yes | -| 3 | fqdn | Yes | Yes | -| 4 | serverPort | Yes | Yes | -| 5 | maxShellConns | Yes | Yes | -| 6 | monitor | Yes | Yes | -| 7 | monitorFqdn | No | Yes | -| 8 | monitorPort | No | Yes | -| 9 | monitorInterval | Yes | Yes | -| 10 | monitorMaxLogs | No | Yes | -| 11 | monitorComp | No | Yes | -| 12 | telemetryReporting | Yes | Yes | -| 13 | telemetryInterval | No | Yes | -| 14 | telemetryServer | No | Yes | -| 15 | telemetryPort | No | Yes | -| 16 | queryPolicy | No | Yes | -| 17 | querySmaOptimize | No | Yes | -| 18 | queryRsmaTolerance | No | Yes | -| 19 | queryBufferSize | Yes | Yes | -| 20 | maxNumOfDistinctRes | Yes | Yes | -| 21 | minSlidingTime | Yes | Yes | -| 22 | minIntervalTime | Yes | Yes | -| 23 | countAlwaysReturnValue | Yes | Yes | -| 24 | dataDir | Yes | Yes | -| 25 | minimalDataDirGB | Yes | Yes | -| 26 | supportVnodes | No | Yes | -| 27 | tempDir | Yes | Yes | -| 28 | minimalTmpDirGB | Yes | Yes | -| 29 | compressMsgSize | Yes | Yes | -| 30 | compressColData | Yes | Yes | -| 31 | smlChildTableName | Yes | Yes | -| 32 | smlTagName | Yes | Yes | -| 33 | smlDataFormat | No | Yes | -| 34 | statusInterval | Yes | Yes | -| 35 | shellActivityTimer | Yes | Yes | -| 36 | transPullupInterval | No | Yes | -| 37 | mqRebalanceInterval | No | Yes | -| 38 | ttlUnit | No | Yes | -| 39 | ttlPushInterval | No | Yes | -| 40 | numOfTaskQueueThreads | No | Yes | -| 41 | numOfRpcThreads | No | Yes | -| 42 | numOfCommitThreads | Yes | Yes | -| 43 | numOfMnodeReadThreads | No | Yes | -| 44 | numOfVnodeQueryThreads | No | Yes | -| 45 | ratioOfVnodeStreamThreads | No | Yes | -| 46 | numOfVnodeFetchThreads | No | Yes | -| 47 | numOfVnodeRsmaThreads | No | Yes | -| 48 | numOfQnodeQueryThreads | No | Yes | -| 49 | numOfQnodeFetchThreads | No | Yes | -| 50 | numOfSnodeSharedThreads | No | Yes | -| 51 | numOfSnodeUniqueThreads | No | Yes | -| 52 | rpcQueueMemoryAllowed | No | Yes | -| 53 | logDir | Yes | Yes | -| 54 | minimalLogDirGB | Yes | Yes | -| 55 | numOfLogLines | Yes | Yes | -| 56 | asyncLog | Yes | Yes | -| 57 | logKeepDays | Yes | Yes | -| 60 | debugFlag | Yes | Yes | -| 61 | tmrDebugFlag | Yes | Yes | -| 62 | uDebugFlag | Yes | Yes | -| 63 | rpcDebugFlag | Yes | Yes | -| 64 | jniDebugFlag | Yes | Yes | -| 65 | qDebugFlag | Yes | Yes | -| 66 | cDebugFlag | Yes | Yes | -| 67 | dDebugFlag | Yes | Yes | -| 68 | vDebugFlag | Yes | Yes | -| 69 | mDebugFlag | Yes | Yes | -| 70 | wDebugFlag | Yes | Yes | -| 71 | sDebugFlag | Yes | Yes | -| 72 | tsdbDebugFlag | Yes | Yes | -| 73 | tqDebugFlag | No | Yes | -| 74 | fsDebugFlag | Yes | Yes | -| 75 | udfDebugFlag | No | Yes | -| 76 | smaDebugFlag | No | Yes | -| 77 | idxDebugFlag | No | Yes | -| 78 | tdbDebugFlag | No | Yes | -| 79 | metaDebugFlag | No | Yes | -| 80 | timezone | Yes | Yes | -| 81 | locale | Yes | Yes | -| 82 | charset | Yes | Yes | -| 83 | udf | Yes | Yes | -| 84 | enableCoreFile | Yes | Yes | -| 85 | arbitrator | Yes | No | -| 86 | numOfThreadsPerCore | Yes | No | -| 87 | numOfMnodes | Yes | No | -| 88 | vnodeBak | Yes | No | -| 89 | balance | Yes | No | -| 90 | balanceInterval | Yes | No | -| 91 | offlineThreshold | Yes | No | -| 92 | role | Yes | No | -| 93 | dnodeNopLoop | Yes | No | -| 94 | keepTimeOffset | Yes | No | -| 95 | rpcTimer | Yes | No | -| 96 | rpcMaxTime | Yes | No | -| 97 | rpcForceTcp | Yes | No | -| 98 | tcpConnTimeout | Yes | No | -| 99 | syncCheckInterval | Yes | No | -| 100 | maxTmrCtrl | Yes | No | -| 101 | monitorReplica | Yes | No | -| 102 | smlTagNullName | Yes | No | -| 103 | keepColumnName | Yes | No | -| 104 | ratioOfQueryCores | Yes | No | -| 105 | maxStreamCompDelay | Yes | No | -| 106 | maxFirstStreamCompDelay | Yes | No | -| 107 | retryStreamCompDelay | Yes | No | -| 108 | streamCompDelayRatio | Yes | No | -| 109 | maxVgroupsPerDb | Yes | No | -| 110 | maxTablesPerVnode | Yes | No | -| 111 | minTablesPerVnode | Yes | No | -| 112 | tableIncStepPerVnode | Yes | No | -| 113 | cache | Yes | No | -| 114 | blocks | Yes | No | -| 115 | days | Yes | No | -| 116 | keep | Yes | No | -| 117 | minRows | Yes | No | -| 118 | maxRows | Yes | No | -| 119 | quorum | Yes | No | -| 120 | comp | Yes | No | -| 121 | walLevel | Yes | No | -| 122 | fsync | Yes | No | -| 123 | replica | Yes | No | -| 124 | partitions | Yes | No | -| 125 | quorum | Yes | No | -| 126 | update | Yes | No | -| 127 | cachelast | Yes | No | -| 128 | maxSQLLength | Yes | No | -| 129 | maxWildCardsLength | Yes | No | -| 130 | maxRegexStringLen | Yes | No | -| 131 | maxNumOfOrderedRes | Yes | No | -| 132 | maxConnections | Yes | No | -| 133 | mnodeEqualVnodeNum | Yes | No | -| 134 | http | Yes | No | -| 135 | httpEnableRecordSql | Yes | No | -| 136 | httpMaxThreads | Yes | No | -| 137 | restfulRowLimit | Yes | No | -| 138 | httpDbNameMandatory | Yes | No | -| 139 | httpKeepAlive | Yes | No | -| 140 | enableRecordSql | Yes | No | -| 141 | maxBinaryDisplayWidth | Yes | No | -| 142 | stream | Yes | No | -| 143 | retrieveBlockingModel | Yes | No | -| 144 | tsdbMetaCompactRatio | Yes | No | -| 145 | defaultJSONStrType | Yes | No | -| 146 | walFlushSize | Yes | No | -| 147 | keepTimeOffset | Yes | No | -| 148 | flowctrl | Yes | No | -| 149 | slaveQuery | Yes | No | -| 150 | adjustMaster | Yes | No | -| 151 | topicBinaryLen | Yes | No | -| 152 | telegrafUseFieldNum | Yes | No | -| 153 | deadLockKillQuery | Yes | No | -| 154 | clientMerge | Yes | No | -| 155 | sdbDebugFlag | Yes | No | -| 156 | odbcDebugFlag | Yes | No | -| 157 | httpDebugFlag | Yes | No | -| 158 | monDebugFlag | Yes | No | -| 159 | cqDebugFlag | Yes | No | -| 160 | shortcutFlag | Yes | No | -| 161 | probeSeconds | Yes | No | -| 162 | probeKillSeconds | Yes | No | -| 163 | probeInterval | Yes | No | -| 164 | lossyColumns | Yes | No | -| 165 | fPrecision | Yes | No | -| 166 | dPrecision | Yes | No | -| 167 | maxRange | Yes | No | -| 168 | range | Yes | No | + +## 3.0 Parameters + +| # | **参数** | **Applicable to 2.x ** | **Applicable to 3.0 ** | Current behavior in 3.0 | +| --- | :---------------------: | --------------- | --------------- | ------------------------------------------------- | +| 1 | firstEp | Yes | Yes | | +| 2 | secondEp | Yes | Yes | | +| 3 | fqdn | Yes | Yes | | +| 4 | serverPort | Yes | Yes | | +| 5 | maxShellConns | Yes | Yes | | +| 6 | monitor | Yes | Yes | | +| 7 | monitorFqdn | No | Yes | | +| 8 | monitorPort | No | Yes | | +| 9 | monitorInterval | Yes | Yes | | +| 10 | queryPolicy | No | Yes | | +| 11 | querySmaOptimize | No | Yes | | +| 12 | maxNumOfDistinctRes | Yes | Yes | | +| 15 | countAlwaysReturnValue | Yes | Yes | | +| 16 | dataDir | Yes | Yes | | +| 17 | minimalDataDirGB | Yes | Yes | | +| 18 | supportVnodes | No | Yes | | +| 19 | tempDir | Yes | Yes | | +| 20 | minimalTmpDirGB | Yes | Yes | | +| 21 | smlChildTableName | Yes | Yes | | +| 22 | smlTagName | Yes | Yes | | +| 23 | smlDataFormat | No | Yes(discarded since 3.0.3.0) | | +| 24 | statusInterval | Yes | Yes | | +| 25 | logDir | Yes | Yes | | +| 26 | minimalLogDirGB | Yes | Yes | | +| 27 | numOfLogLines | Yes | Yes | | +| 28 | asyncLog | Yes | Yes | | +| 29 | logKeepDays | Yes | Yes | | +| 30 | debugFlag | Yes | Yes | | +| 31 | tmrDebugFlag | Yes | Yes | | +| 32 | uDebugFlag | Yes | Yes | | +| 33 | rpcDebugFlag | Yes | Yes | | +| 34 | jniDebugFlag | Yes | Yes | | +| 35 | qDebugFlag | Yes | Yes | | +| 36 | cDebugFlag | Yes | Yes | | +| 37 | dDebugFlag | Yes | Yes | | +| 38 | vDebugFlag | Yes | Yes | | +| 39 | mDebugFlag | Yes | Yes | | +| 40 | wDebugFlag | Yes | Yes | | +| 41 | sDebugFlag | Yes | Yes | | +| 42 | tsdbDebugFlag | Yes | Yes | | +| 43 | tqDebugFlag | No | Yes | | +| 44 | fsDebugFlag | Yes | Yes | | +| 45 | udfDebugFlag | No | Yes | | +| 46 | smaDebugFlag | No | Yes | | +| 47 | idxDebugFlag | No | Yes | | +| 48 | tdbDebugFlag | No | Yes | | +| 49 | metaDebugFlag | No | Yes | | +| 50 | timezone | Yes | Yes | | +| 51 | locale | Yes | Yes | | +| 52 | charset | Yes | Yes | | +| 53 | udf | Yes | Yes | | +| 54 | enableCoreFile | Yes | Yes | | diff --git a/docs/en/14-reference/12-directory.md b/docs/en/14-reference/12-directory.md index 19b036418f18637bfd21fa286f24528c649d146d..439fcf37f683d33c85f0c469f62379a6a38f3938 100644 --- a/docs/en/14-reference/12-directory.md +++ b/docs/en/14-reference/12-directory.md @@ -1,6 +1,6 @@ --- title: File directory structure -description: "TDengine installation directory description" +description: This document describes the structure of the TDengine directory after installation. --- After TDengine is installed, the following directories or files will be created in the system by default. @@ -24,7 +24,7 @@ All executable files of TDengine are in the _/usr/local/taos/bin_ directory by d - _taosdump_: data import and export tool - _taosBenchmark_: TDengine testing tool - _remove.sh_: script to uninstall TDengine, please execute it carefully, link to the **rmtaos** command in the /usr/bin directory. Will remove the TDengine installation directory `/usr/local/taos`, but will keep `/etc/taos`, `/var/lib/taos`, `/var/log/taos` -- _taosadapter_: server-side executable that provides RESTful services and accepts writing requests from a variety of other softwares +- _taosadapter_: server-side executable that provides RESTful services and accepts writing requests from a variety of other software - _TDinsight.sh_: script to download TDinsight and install it - _set_core.sh_: script for setting up the system to generate core dump files for easy debugging - _taosd-dump-cfg.gdb_: script to facilitate debugging of taosd's gdb execution. diff --git a/docs/en/14-reference/13-schemaless/13-schemaless.md b/docs/en/14-reference/13-schemaless/13-schemaless.md index 10321ab083e6e654e66cb73f1bc21f9fbd678fda..aad0e63a4228ca303302d4a3970182355f750d53 100644 --- a/docs/en/14-reference/13-schemaless/13-schemaless.md +++ b/docs/en/14-reference/13-schemaless/13-schemaless.md @@ -1,15 +1,13 @@ --- title: Schemaless Writing -description: 'The Schemaless write method eliminates the need to create super tables/sub tables in advance and automatically creates the storage structure corresponding to the data, as it is written to the interface.' +description: This document describes how to use the schemaless write component of TDengine. --- -In IoT applications, data is collected for many purposes such as intelligent control, business analysis, device monitoring and so on. Due to changes in business or functional requirements or changes in device hardware, the application logic and even the data collected may change. Schemaless writing automatically creates storage structures for your data as it is being written to TDengine, so that you do not need to create supertables in advance. When necessary, schemaless writing -will automatically add the required columns to ensure that the data written by the user is stored correctly. +In IoT applications, data is collected for many purposes such as intelligent control, business analysis, device monitoring and so on. Due to changes in business or functional requirements or changes in device hardware, the application logic and even the data collected may change. Schemaless writing automatically creates storage structures for your data as it is being written to TDengine, so that you do not need to create supertables in advance. When necessary, schemaless writing will automatically add the required columns to ensure that the data written by the user is stored correctly. The schemaless writing method creates super tables and their corresponding subtables. These are completely indistinguishable from the super tables and subtables created directly via SQL. You can write data directly to them via SQL statements. Note that the names of tables created by schemaless writing are based on fixed mapping rules for tag values, so they are not explicitly ideographic and they lack readability. -Tips: -The schemaless write will automatically create a table. You do not need to create a table manually, or an unknown error may occur. +Note: Schemaless writing creates tables automatically. Creating tables manually is not supported with schemaless writing. ## Schemaless Writing Line Protocol @@ -50,8 +48,7 @@ In the schemaless writing data line protocol, each data item in the field_set ne - `t`, `T`, `true`, `True`, `TRUE`, `f`, `F`, `false`, and `False` will be handled directly as BOOL types. -For example, the following data rows write c1 column as 3 (BIGINT), c2 column as false (BOOL), c3 column -as "passit" (BINARY), c4 column as 4 (DOUBLE), and the primary key timestamp as 1626006833639000000 to child table with the t1 label as "3" (NCHAR), the t2 label as "4" (NCHAR), and the t3 label as "t3" (NCHAR) and the super table named `st`. +For example, the following string indicates that the one row of data is written to the st supertable with the t1 tag as "3" (NCHAR), the t2 tag as "4" (NCHAR), and the t3 tag as "t3" (NCHAR); the c1 column is 3 (BIGINT), the c2 column is false (BOOL), the c3 column is "passit" (BINARY), the c4 column is 4 (DOUBLE), and the primary key timestamp is 1626006833639000000. ```json st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4f64 1626006833639000000 @@ -69,23 +66,31 @@ Schemaless writes process row data according to the following principles. "measurement,tag_key1=tag_value1,tag_key2=tag_value2" ``` +:::tip Note that tag_key1, tag_key2 are not the original order of the tags entered by the user but the result of using the tag names in ascending order of the strings. Therefore, tag_key1 is not the first tag entered in the line protocol. -The string's MD5 hash value "md5_val" is calculated after the ranking is completed. The calculation result is then combined with the string to generate the table name: "t_md5_val". "t_" is a fixed prefix that every table generated by this mapping relationship has. +The string's MD5 hash value "md5_val" is calculated after the ranking is completed. The calculation result is then combined with the string to generate the table name: "t_md5_val". "t\_" is a fixed prefix that every table generated by this mapping relationship has. +::: + You can configure smlChildTableName in taos.cfg to specify table names, for example, `smlChildTableName=tname`. You can insert `st,tname=cpul,t1=4 c1=3 1626006833639000000` and the cpu1 table will be automatically created. Note that if multiple rows have the same tname but different tag_set values, the tag_set of the first row is used to create the table and the others are ignored. 2. If the super table obtained by parsing the line protocol does not exist, this super table is created. + **Important:** Manually creating supertables for schemaless writing is not supported. Schemaless writing creates appropriate supertables automatically. + 3. If the subtable obtained by the parse line protocol does not exist, Schemaless creates the sub-table according to the subtable name determined in steps 1 or 2. + 4. If the specified tag or regular column in the data row does not exist, the corresponding tag or regular column is added to the super table (only incremental). -5. If there are some tag columns or regular columns in the super table that are not specified to take values in a data row, then the values of these columns are set to - NULL. + +5. If there are some tag columns or regular columns in the super table that are not specified to take values in a data row, then the values of these columns are set to NULL. + 6. For BINARY or NCHAR columns, if the length of the value provided in a data row exceeds the column type limit, the maximum length of characters allowed to be stored in the column is automatically increased (only incremented and not decremented) to ensure complete preservation of the data. + 7. Errors encountered throughout the processing will interrupt the writing process and return an error code. -8. It is assumed that the order of field_set in a supertable is consistent, meaning that the first record contains all fields and subsequent records store fields in the same order. If the order is not consistent, set smlDataFormat in taos.cfg to false. Otherwise, data will be written out of order and a database error will occur.(smlDataFormat in taos.cfg default to false after version of 3.0.1.3) -:::tip -All processing logic of schemaless will still follow TDengine's underlying restrictions on data structures, such as the total length of each row of data cannot exceed -16KB. See [TDengine SQL Boundary Limits](/taos-sql/limit) for specific constraints in this area. +8. It is assumed that the order of field_set in a supertable is consistent, meaning that the first record contains all fields and subsequent records store fields in the same order. If the order is not consistent, set smlDataFormat in taos.cfg to false. Otherwise, data will be written out of order and a database error will occur. + Note: TDengine 3.0.3.0 and later automatically detect whether order is consistent. This parameter is no longer used. +:::tip +All processing logic of schemaless will still follow TDengine's underlying restrictions on data structures, such as the total length of each row of data cannot exceed 48 KB and the total length of a tag value cannot exceed 16 KB. See [TDengine SQL Boundary Limits](/taos-sql/limit) for specific constraints in this area. ::: ## Time resolution recognition @@ -114,8 +119,7 @@ In OpenTSDB file and JSON protocol modes, the precision of the timestamp is dete ## Data Model Mapping -This section describes how data in line protocol is mapped to a schema. The data measurement in each line is mapped to a -supertable name. The tag name in tag_set is the tag name in the schema, and the name in field_set is the column name in the schema. The following example shows how data is mapped: +This section describes how data in InfluxDB line protocol is mapped to a schema. The data measurement in each line is mapped to a supertable name. The tag name in tag_set is the tag name in the schema, and the name in field_set is the column name in the schema. The following example shows how data is mapped: ```json st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4f64 1626006833639000000 @@ -131,7 +135,7 @@ create stable st (_ts timestamp, c1 bigint, c2 bool, c3 binary(6), c4 bigint) ta This section describes the impact on the schema caused by different data being written. -If you use line protocol to write to a specific tag field and then later change the field type, a schema error will ocur. This triggers an error on the write API. This is shown as follows: +If you use line protocol to write to a specific tag field and then later change the field type, a schema error will occur. This triggers an error on the write API. This is shown as follows: ```json st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4 1626006833639000000 @@ -160,7 +164,7 @@ The preceding data includes a new entry, c6, with type binary(6). When this occu TDengine guarantees the idempotency of data writes. This means that you can repeatedly call the API to perform write operations with bad data. However, TDengine does not guarantee the atomicity of multi-row writes. In a multi-row write, some data may be written successfully and other data unsuccessfully. -##: Error Codes +## Error Codes The TSDB_CODE_TSC_LINE_SYNTAX_ERROR indicates an error in the schemaless writing component. This error occurs when writing text. For other errors, schemaless writing uses the standard TDengine error codes diff --git a/docs/en/14-reference/14-taosKeeper.md b/docs/en/14-reference/14-taosKeeper.md index 665bc75380d4f59666d792d074fb37c65c810264..895bd82e1924a59227bc8193c277b96eccd6cd66 100644 --- a/docs/en/14-reference/14-taosKeeper.md +++ b/docs/en/14-reference/14-taosKeeper.md @@ -1,53 +1,114 @@ --- sidebar_label: taosKeeper title: taosKeeper -description: exports TDengine monitoring metrics. +description: This document describes how to use taosKeeper, a tool for exporting TDengine monitoring metrics. --- +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + ## Introduction taosKeeper is a tool for TDengine that exports monitoring metrics. With taosKeeper, you can easily monitor the operational status of your TDengine deployment. taosKeeper uses the TDengine REST API. It is not necessary to install TDengine Client to use taosKeeper. ## Installation - +There are two ways to install taosKeeper: Methods of installing taosKeeper: - - -- You can compile taosKeeper separately and install it. Please refer to the [taosKeeper](https://github.com/taosdata/taoskeeper) repository for details. --> -You can compile taosKeeper separately and install it. Please refer to the [taosKeeper](https://github.com/taosdata/taoskeeper) repository for details. +- Installing the official TDengine installer will automatically install taosKeeper. Please refer to [TDengine installation](/operation/pkg-install) for details. -## Run +- You can compile taosKeeper separately and install it. Please refer to the [taosKeeper](https://github.com/taosdata/taoskeeper) repository for details. +## Configuration and Launch -### Configuration and running methods +### Configuration taosKeeper needs to be executed on the terminal of the operating system, it supports three configuration methods: [Command-line arguments](#command-line-arguments-in-detail), [environment variable](#environment-variable-in-detail) and [configuration file](#configuration-file-parameters-in-detail). The precedence of those is Command-line, environment variable and configuration file. -**Make sure that the TDengine cluster is running correctly before running taosKeeper. ** Ensure that the monitoring service in TDengine has been started. For more information, see [TDengine Monitoring Configuration](../config/#monitoring). +**Make sure that the TDengine cluster is running correctly before running taosKeeper.** Ensure that the monitoring service in TDengine has been started. At least the values of `monitor` and `monitorFqdn` need to be set in `taos.cfg`. + +```shell +monitor 1 +monitorFqdn localhost # taoskeeper's FQDN +``` -### Command-Line Parameters +For more information, see [TDengine Monitoring Configuration](../config/#monitoring). -You can use command-line parameters to run taosKeeper and control its behavior: +### Quick Launch -```shell -$ taosKeeper + + + +After the installation is complete, run the following command to start the taoskeeper service: + +```bash +systemctl start taoskeeper ``` -### Environment variable -You can use Environment variable to run taosKeeper and control its behavior: +Run the following command to confirm that taoskeeper is running normally: -```shell -$ export TAOS_KEEPER_TDENGINE_HOST=192.168.64.3 - -$ taoskeeper +```bash +systemctl status taoskeeper +``` + +Output similar to the following indicates that taoskeeper is running normally: + +``` +Active: active (running) +``` + +Output similar to the following indicates that taoskeeper has not started successfully: + +``` +Active: inactive (dead) ``` -you can run `taoskeeper -h` for more detail. +The following `systemctl` commands can help you manage taoskeeper service: + +- Start taoskeeper Server: `systemctl start taoskeeper` + +- Stop taoskeeper Server: `systemctl stop taoskeeper` + +- Restart taoskeeper Server: `systemctl restart taoskeeper` + +- Check taoskeeper Server status: `systemctl status taoskeeper` + +:::info -### Configuration File +- The `systemctl` command requires _root_ privileges. If you are not logged in as the _root_ user, use the `sudo` command. +- The `systemctl stop taoskeeper` command will instantly stop taoskeeper Server. +- If your system does not include `systemd`, you can run `/usr/local/taos/bin/taoskeeper` to start taoskeeper manually. -You can quickly launch taosKeeper with the following commands. If you do not specify a configuration file, `/etc/taos/keeper.toml` is used by default. If this file does not specify configurations, the default values are used. +::: + + + + +After the installation is complete, run `launchctl start com.tdengine.taoskeeper` to start taoskeeper Server. + +The following `launchctl` commands can help you manage taoskeeper service: + +- Start taoskeeper Server: `sudo launchctl start com.tdengine.taoskeeper` + +- Stop taoskeeper Server: `sudo launchctl stop com.tdengine.taoskeeper` + +- Check taoskeeper Server status: `sudo launchctl list | grep taoskeeper` + +:::info +- Please use `sudo` to run `launchctl` to manage _com.tdengine.taoskeeper_ with administrator privileges. +- The administrator privilege is required for service management to enhance security. +- Troubleshooting: +- The first column returned by the command `launchctl list | grep taoskeeper` is the PID of the program. If it's `-`, that means the taoskeeper service is not running. +- If the service is abnormal, please check the `launchd.log` file from the system log. + +::: + + + + +#### Launch With Configuration File + +You can quickly launch taosKeeper with the following commands. If you do not specify a configuration file, `/etc/taos/keeper.toml` is used by default. If this file does not specify configurations, the default values are used. ```shell $ taoskeeper -c @@ -125,19 +186,36 @@ $ curl http://127.0.0.1:6043/metrics Sample result set (excerpt): ```shell -# HELP taos_cluster_info_connections_total +# HELP taos_cluster_info_connections_total # TYPE taos_cluster_info_connections_total counter taos_cluster_info_connections_total{cluster_id="5981392874047724755"} 16 -# HELP taos_cluster_info_dbs_total +# HELP taos_cluster_info_dbs_total # TYPE taos_cluster_info_dbs_total counter taos_cluster_info_dbs_total{cluster_id="5981392874047724755"} 2 -# HELP taos_cluster_info_dnodes_alive +# HELP taos_cluster_info_dnodes_alive # TYPE taos_cluster_info_dnodes_alive counter taos_cluster_info_dnodes_alive{cluster_id="5981392874047724755"} 1 -# HELP taos_cluster_info_dnodes_total +# HELP taos_cluster_info_dnodes_total # TYPE taos_cluster_info_dnodes_total counter taos_cluster_info_dnodes_total{cluster_id="5981392874047724755"} 1 -# HELP taos_cluster_info_first_ep +# HELP taos_cluster_info_first_ep # TYPE taos_cluster_info_first_ep gauge taos_cluster_info_first_ep{cluster_id="5981392874047724755",value="hlb:6030"} 1 -``` \ No newline at end of file +``` + +### check_health + +``` +$ curl -i http://127.0.0.1:6043/check_health +``` + +Response: + +``` +HTTP/1.1 200 OK +Content-Type: application/json; charset=utf-8 +Date: Mon, 03 Apr 2023 07:20:38 GMT +Content-Length: 19 + +{"version":"1.0.0"} +``` diff --git a/docs/en/14-reference/_statsd.mdx b/docs/en/14-reference/_statsd.mdx index d068304a1dce52da9e89a1c19a5cca3956b7f0ce..b15c9640db210ca9f42295327430373e2fc6b8fc 100644 --- a/docs/en/14-reference/_statsd.mdx +++ b/docs/en/14-reference/_statsd.mdx @@ -31,7 +31,7 @@ The default database name written by taosAdapter is `statsd`. To specify a diffe ### Configuring StatsD -To use StatsD, you need to download its [source code](https://github.com/statsd/statsd). Please refer to the example file `exampleConfig.js` in the root directory of the source download to modify the configuration file. In , please fill in the domain name or IP address of the server running taosAdapter, and , please fill in the port where taosAdapter receives StatsD data (default is 6044). +To use StatsD, you need to download its [source code](https://github.com/statsd/statsd). Please refer to the example file `exampleConfig.js` in the root directory of the source download to modify the configuration file. In , please fill in the domain name or IP address of the server running taosAdapter, and , please fill in the port where taosAdapter receives StatsD data (default is 6044). ``` backends section add ". /backends/repeater" diff --git a/docs/en/14-reference/index.md b/docs/en/14-reference/index.md index f3a64913d065d1d8e321ce7433c9d605ef70bd13..bc8ec6996538bf15bf4cb4d52aaa126ed11b5b72 100644 --- a/docs/en/14-reference/index.md +++ b/docs/en/14-reference/index.md @@ -1,5 +1,6 @@ --- title: Reference +description: This document describes TDengine connectors and utilities. --- This section describes the TDengine connectors and utilities. diff --git a/docs/en/20-third-party/01-grafana.mdx b/docs/en/20-third-party/01-grafana.mdx index ca32ce8afce30eaa6756f7b403685b989d824bbf..b0e9dea707fb2fb326329895921850cd6d721b6d 100644 --- a/docs/en/20-third-party/01-grafana.mdx +++ b/docs/en/20-third-party/01-grafana.mdx @@ -1,6 +1,7 @@ --- -sidebar_label: Grafana title: Grafana +sidebar_label: Grafana +description: This document describes how to integrate TDengine with Grafana. --- import Tabs from "@theme/Tabs"; @@ -76,7 +77,7 @@ sudo -u grafana grafana-cli plugins install tdengine-datasource You can also download zip files from [GitHub](https://github.com/taosdata/grafanaplugin/releases/tag/latest) or [Grafana](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation) and install manually. The commands are as follows: ```bash -GF_VERSION=3.2.7 +GF_VERSION=3.3.1 # from GitHub wget https://github.com/taosdata/grafanaplugin/releases/download/v$GF_VERSION/tdengine-datasource-$GF_VERSION.zip # from Grafana @@ -155,13 +156,13 @@ You can setup a zero-configuration stack for TDengine + Grafana by [docker-compo services: tdengine: - image: tdengine/tdengine:2.6.0.2 + image: tdengine/tdengine:3.0.2.4 environment: TAOS_FQDN: tdengine volumes: - tdengine-data:/var/lib/taos/ grafana: - image: grafana/grafana:8.5.6 + image: grafana/grafana:9.3.6 volumes: - ./tdengine.yml/:/etc/grafana/provisioning/tdengine.yml - grafana-data:/var/lib/grafana @@ -196,11 +197,18 @@ As shown above, select the `TDengine` data source in the `Query` and enter the c - INPUT SQL: Enter the desired query (the results being two columns and multiple rows), such as `select _wstart, avg(mem_system) from log.dnodes_info where ts >= $from and ts < $to interval($interval)`. In this statement, $from, $to, and $interval are variables that Grafana replaces with the query time range and interval. In addition to the built-in variables, custom template variables are also supported. - ALIAS BY: This allows you to set the current query alias. - GENERATE SQL: Clicking this button will automatically replace the corresponding variables and generate the final executed statement. +- Group by column name(s): `group by` or `partition by` columns name split by comma. By setting `Group by column name(s)`, it can show multi-dimension data if Sql is `group by` or `partition by`. Such as, it can show data by `dnode_ep` if sql is `select _wstart as ts, avg(mem_system), dnode_ep from log.dnodes_info where ts>=$from and ts<=$to partition by dnode_ep interval($interval)` and `Group by column name(s)` is `dnode_ep`. +- Format to: format legend for `group by` or `partition by`. Such as it can display series data by `dnode_ep` if sql is `select _wstart as ts, avg(mem_system), dnode_ep from log.dnodes_info where ts>=$from and ts<=$to partition by dnode_ep interval($interval)` and `Group by column name(s)` is `dnode_ep` and `Format to` is `mem_system_{{dnode_ep}}`. Follow the default prompt to query the average system memory usage for the specified interval on the server where the current TDengine deployment is located as follows. ![TDengine Database TDinsight plugin create dashboard 2](./grafana/create_dashboard2.webp) +查询每台 TDengine 服务器指定间隔系统内存平均使用量如下. +The example to query the average system memory usage for the specified interval on each server as follows. + +![TDengine Database TDinsight plugin create dashboard 2](./grafana/create_dashboard3.webp) + > For more information on how to use Grafana to create the appropriate monitoring interface and for more details on using Grafana, refer to the official Grafana [documentation](https://grafana.com/docs/). ### Importing the Dashboard diff --git a/docs/en/20-third-party/02-prometheus.md b/docs/en/20-third-party/02-prometheus.md index ef9b9cb637ffc8da2de6acdd853fa097cfbc0193..bfdd3d015e6fcfa484fdceea6f0bebc43049ed17 100644 --- a/docs/en/20-third-party/02-prometheus.md +++ b/docs/en/20-third-party/02-prometheus.md @@ -1,6 +1,7 @@ --- -sidebar_label: Prometheus title: Prometheus writing and reading +sidebar_label: Prometheus +description: This document describes how to integrate TDengine with Prometheus. --- import Prometheus from "../14-reference/_prometheus.mdx" diff --git a/docs/en/20-third-party/03-telegraf.md b/docs/en/20-third-party/03-telegraf.md index 8f3cab0e57094a1d2fac5f54601489382ac3f9a1..7e99b84eab88614bf82da92a2db11ddf1be753bf 100644 --- a/docs/en/20-third-party/03-telegraf.md +++ b/docs/en/20-third-party/03-telegraf.md @@ -1,6 +1,7 @@ --- -sidebar_label: Telegraf title: Telegraf writing +sidebar_label: Telegraf +description: This document describes how to integrate TDengine with Telegraf. --- import Telegraf from "../14-reference/_telegraf.mdx" diff --git a/docs/en/20-third-party/05-collectd.md b/docs/en/20-third-party/05-collectd.md index 5b52e3b7bc75c2d21ab5a6c08331030fe4e423f7..d8c8e7f81def389418d28d62486ef32afb5d996c 100644 --- a/docs/en/20-third-party/05-collectd.md +++ b/docs/en/20-third-party/05-collectd.md @@ -1,6 +1,7 @@ --- -sidebar_label: collectd title: collectd writing +sidebar_label: collectd +description: This document describes how to integrate TDengine with collectd. --- import CollectD from "../14-reference/_collectd.mdx" diff --git a/docs/en/20-third-party/06-statsd.md b/docs/en/20-third-party/06-statsd.md index b861a48ecd59fa1f2036c6c323d3fdee8a3ee44b..ea428e9cdb45992cdebd6be4713583b88990a67f 100644 --- a/docs/en/20-third-party/06-statsd.md +++ b/docs/en/20-third-party/06-statsd.md @@ -1,6 +1,7 @@ --- -sidebar_label: StatsD title: StatsD Writing +sidebar_label: StatsD +description: This document describes how to integrate TDengine with StatsD. --- import StatsD from "../14-reference/_statsd.mdx" diff --git a/docs/en/20-third-party/07-icinga2.md b/docs/en/20-third-party/07-icinga2.md index 167b6a4303f838c8c9945a95dac802a54bad3525..540aae8689bc0885ab4649be8fd07fec04dad829 100644 --- a/docs/en/20-third-party/07-icinga2.md +++ b/docs/en/20-third-party/07-icinga2.md @@ -1,6 +1,7 @@ --- -sidebar_label: icinga2 title: icinga2 writing +sidebar_label: icinga2 +description: This document describes how to integrate TDengine with icinga2. --- import Icinga2 from "../14-reference/_icinga2.mdx" diff --git a/docs/en/20-third-party/08-tcollector.md b/docs/en/20-third-party/08-tcollector.md index b604a2d7125851a8f2ec4965f755f5400d0613bf..f1c0ecd44deaea6172d8d9b1d4e6c2e5ee8ccabb 100644 --- a/docs/en/20-third-party/08-tcollector.md +++ b/docs/en/20-third-party/08-tcollector.md @@ -1,6 +1,7 @@ --- -sidebar_label: TCollector title: TCollector writing +sidebar_label: TCollector +description: This document describes how to integrate TDengine with TCollector. --- import TCollector from "../14-reference/_tcollector.mdx" diff --git a/docs/en/20-third-party/09-emq-broker.md b/docs/en/20-third-party/09-emq-broker.md index 2ead1bbaf40f06fec2a5cbf85e46fdfdcc5216df..10ce0174ed5d362a113acd7ade59741a10155657 100644 --- a/docs/en/20-third-party/09-emq-broker.md +++ b/docs/en/20-third-party/09-emq-broker.md @@ -1,6 +1,7 @@ --- -sidebar_label: EMQX Broker title: EMQX Broker writing +sidebar_label: EMQX Broker +description: This document describes how to integrate TDengine with the EMQX broker. --- MQTT is a popular IoT data transfer protocol. [EMQX](https://github.com/emqx/emqx) is an open-source MQTT Broker software. You can write MQTT data directly to TDengine without any code. You only need to setup "rules" in EMQX Dashboard to create a simple configuration. EMQX supports saving data to TDengine by sending data to a web service and provides a native TDengine driver for direct saving in the Enterprise Edition. Please refer to the [EMQX official documentation](https://www.emqx.io/docs/en/v4.4/rule/rule-engine.html) for details on how to use it.). diff --git a/docs/en/20-third-party/10-hive-mq-broker.md b/docs/en/20-third-party/10-hive-mq-broker.md index 828a62ac5b336766d5c3770cc42cd3a61cfd8d5d..6c5165596e04678db1dd32d16756133719fdb4b9 100644 --- a/docs/en/20-third-party/10-hive-mq-broker.md +++ b/docs/en/20-third-party/10-hive-mq-broker.md @@ -1,6 +1,7 @@ --- -sidebar_label: HiveMQ Broker title: HiveMQ Broker Writing +sidebar_label: HiveMQ Broker +description: This document describes how to integrate TDengine with the HiveMQ broker. --- [HiveMQ](https://www.hivemq.com/) is an MQTT broker that provides community and enterprise editions. HiveMQ is mainly for enterprise emerging machine-to-machine M2M communication and internal transport, meeting scalability, ease of management, and security features. HiveMQ provides an open-source plug-in development kit. MQTT data can be saved to TDengine via TDengine extension for HiveMQ. For more information, see [HiveMQ TDengine Extension](https://github.com/huskar-t/hivemq-tdengine-extension/blob/b62a26ecc164a310104df57691691b237e091c89/README_EN.md). diff --git a/docs/en/20-third-party/11-kafka.md b/docs/en/20-third-party/11-kafka.md index 3e8f7c295d7b6ab81ecb678865ed3e4eff81b2c5..9e322d2a5b0234a24c880a5656a25d35933af845 100644 --- a/docs/en/20-third-party/11-kafka.md +++ b/docs/en/20-third-party/11-kafka.md @@ -1,6 +1,7 @@ --- -sidebar_label: Kafka title: TDengine Kafka Connector Tutorial +sidebar_label: Kafka +description: This document describes how to integrate TDengine with Kafka. --- TDengine Kafka Connector contains two plugins: TDengine Source Connector and TDengine Sink Connector. Users only need to provide a simple configuration file to synchronize the data of the specified topic in Kafka (batch or real-time) to TDengine or synchronize the data (batch or real-time) of the specified database in TDengine to Kafka. @@ -76,7 +77,7 @@ Development: false ### Install from source code ``` -git clone https://github.com/taosdata/kafka-connect-tdengine.git +git clone --branch 3.0 https://github.com/taosdata/kafka-connect-tdengine.git cd kafka-connect-tdengine mvn clean package unzip -d $CONFLUENT_HOME/share/java/ target/components/packages/taosdata-kafka-connect-tdengine-*.zip diff --git a/docs/en/20-third-party/12-google-data-studio.md b/docs/en/20-third-party/12-google-data-studio.md index fc94f98056bbeeeec88ca7ea12a4a6a7e6f15dc5..ea6431fa5a81b3b9e51fe04e8e404cf52e9c0ad9 100644 --- a/docs/en/20-third-party/12-google-data-studio.md +++ b/docs/en/20-third-party/12-google-data-studio.md @@ -1,6 +1,7 @@ --- -sidebar_label: Google Data Studio title: Use Google Data Studio to access TDengine +sidebar_label: Google Data Studio +description: This document describes how to integrate TDengine with Google Data Studio. --- Data Studio is a powerful tool for reporting and visualization, offering a wide variety of charts and connectors and making it easy to generate reports based on predefined templates. Its ease of use and robust ecosystem have made it one of the first choices for people working in data analysis. diff --git a/docs/en/20-third-party/13-Jupyter.md b/docs/en/20-third-party/13-Jupyter.md index fbd7e530f0959740c53e48ce1d73d92ce0d6c5c5..1ac9df1da4c7756c4f186d456948ae65262e9d54 100644 --- a/docs/en/20-third-party/13-Jupyter.md +++ b/docs/en/20-third-party/13-Jupyter.md @@ -1,6 +1,7 @@ --- -sidebar_label: JupyterLab title: Connect JupyterLab to TDengine +sidebar_label: JupyterLab +description: This document describes how to integrate TDengine with JupyterLab. --- JupyterLab is the next generation of the ubiquitous Jupyter Notebook. In this note we show you how to install the TDengine Python connector to connect to TDengine in JupyterLab. You can then insert data and perform queries against the TDengine instance within JupyterLab. diff --git a/docs/en/20-third-party/grafana/create_dashboard1.webp b/docs/en/20-third-party/grafana/create_dashboard1.webp index 55eb388833e4df2a46f4d1cf6d346aa11429385d..df41d66d50e888555792ef34188a966c2e106a86 100644 Binary files a/docs/en/20-third-party/grafana/create_dashboard1.webp and b/docs/en/20-third-party/grafana/create_dashboard1.webp differ diff --git a/docs/en/20-third-party/grafana/create_dashboard2.webp b/docs/en/20-third-party/grafana/create_dashboard2.webp index bb40e407187718c52e9f617d8ebd3d25fd14b56b..ba50f5299605bd72ebfe1f3f5d1d62bdbc8939c9 100644 Binary files a/docs/en/20-third-party/grafana/create_dashboard2.webp and b/docs/en/20-third-party/grafana/create_dashboard2.webp differ diff --git a/docs/en/20-third-party/grafana/create_dashboard3.webp b/docs/en/20-third-party/grafana/create_dashboard3.webp new file mode 100644 index 0000000000000000000000000000000000000000..84f387f87bcc8e06fca90deabebd1d601c528ef1 Binary files /dev/null and b/docs/en/20-third-party/grafana/create_dashboard3.webp differ diff --git a/docs/en/20-third-party/index.md b/docs/en/20-third-party/index.md index 87bd9e075133d1182ee93d1c1c43617c766755b9..6fc8043eefef62d476e289195c8f38e385e020c4 100644 --- a/docs/en/20-third-party/index.md +++ b/docs/en/20-third-party/index.md @@ -1,5 +1,6 @@ --- title: Third Party Tools +description: This document describes how to integrate TDengine with various third-party tools. --- Since TDengine supports standard SQL commands, common database connector standards (e.g., JDBC), ORM, and other popular time-series database writing protocols (e.g., InfluxDB Line Protocol, OpenTSDB JSON, OpenTSDB Telnet, etc.), it is very easy to integrate TDengine with other third party tools. You only need to provide simple configuration, the integration can be done without a line of code. diff --git a/docs/en/21-tdinternal/01-arch.md b/docs/en/21-tdinternal/01-arch.md index 697ecb98a1c212dbdfef47a916fe1e288ea5508c..cef05dcc56793846fd36515121f6688f74999bbf 100644 --- a/docs/en/21-tdinternal/01-arch.md +++ b/docs/en/21-tdinternal/01-arch.md @@ -1,6 +1,7 @@ --- -sidebar_label: Architecture title: Architecture +sidebar_label: Architecture +description: This document describes the architecture of TDengine. --- ## Cluster and Primary Logic Unit diff --git a/docs/en/21-tdinternal/03-high-availability.md b/docs/en/21-tdinternal/03-high-availability.md index e2e1c6521efd59078e7dc9c9a1e5d8df3377d266..e2a1e358b0ceddd995216e2c86bedc8982385df3 100644 --- a/docs/en/21-tdinternal/03-high-availability.md +++ b/docs/en/21-tdinternal/03-high-availability.md @@ -1,6 +1,7 @@ --- -sidebar_label: High Availability title: High Availability +sidebar_label: High Availability +description: This document describes how TDengine implements high availability. --- ## High Availability of Vnode @@ -27,4 +28,4 @@ SHOW MNODES; The end point and role/status (leader, follower, candidate, offline) of all mnodes can be shown by the above command. When the first dnode is started in a cluster, there must be one mnode in this dnode. Without at least one mnode, the cluster cannot work. -From TDengine 3.0.0, RAFT procotol is used to guarantee the high availability, so the number of mnodes is should be 1 or 3. +From TDengine 3.0.0, RAFT protocol is used to guarantee the high availability, so the number of mnodes is should be 1 or 3. diff --git a/docs/en/21-tdinternal/04-load-balance.md b/docs/en/21-tdinternal/04-load-balance.md index 7648398059a2a422533d6d687336988d207c79a4..474272c46d216dafb84f6d89cf25784eefe7331e 100644 --- a/docs/en/21-tdinternal/04-load-balance.md +++ b/docs/en/21-tdinternal/04-load-balance.md @@ -1,6 +1,7 @@ --- -sidebar_label: Load Balance title: Load Balance +sidebar_label: Load Balance +description: This document describes how TDengine implements load balancing. --- The load balance in TDengine is mainly about processing data series data. TDengine employes builtin hash algorithm to distribute all the tables, sub-tables and their data of a database across all the vgroups that belongs to the database. Each table or sub-table can only be handled by a single vgroup, while each vgroup can process multiple table or sub-table. @@ -13,8 +14,8 @@ create database db0 vgroups 100; The proper value of `vgroups` depends on available system resources. Assuming there is only one database to be created in the system, then the number of `vgroups` is determined by the available resources from all dnodes. In principle more vgroups can be created if you have more CPU and memory. Disk I/O is another important factor to consider. Once the bottleneck shows on disk I/O, more vgroups may downgrad the system performance significantly. If multiple databases are to be created in the system, then the total number of `vroups` of all the databases are dependent on the available system resources. It needs to be careful to distribute vgroups among these databases, you need to consider the number of tables, data writing frequency, size of each data row for all these databases. A recommended practice is to firstly choose a starting number for `vgroups`, for example double of the number of CPU cores, then try to adjust and optimize system configurations to find the best setting for `vgroups`, then distribute these vgroups among databases. -Furthermode, TDengine distributes the vgroups of each database equally among all dnodes. In case of replica 3, the distrubtion is even more complex, TDengine tries its best to prevent any dnode from becoming a bottleneck. +Furthermode, TDengine distributes the vgroups of each database equally among all dnodes. In case of replica 3, the distribution is even more complex, TDengine tries its best to prevent any dnode from becoming a bottleneck. TDegnine utilizes the above ways to achieve load balance in a cluster, and finally achieve higher throughput. -Once the load balance is achieved, after some operations like deleting tables or droping databases, the load across all dnodes may become inbalanced, the method of rebalance will be provided in later versions. However, even without explicit rebalancing, TDengine will try its best to achieve new balance without manual interfering when a new database is created. \ No newline at end of file +Once the load balance is achieved, after some operations like deleting tables or dropping databases, the load across all dnodes may become imbalanced, the method of rebalance will be provided in later versions. However, even without explicit rebalancing, TDengine will try its best to achieve new balance without manual interfering when a new database is created. diff --git a/docs/en/21-tdinternal/index.md b/docs/en/21-tdinternal/index.md index 999d6f89ff57164d6e0372620504c8ecc9de7c9b..4f0846754382767b4694ab1c54f8ae2d3340948c 100644 --- a/docs/en/21-tdinternal/index.md +++ b/docs/en/21-tdinternal/index.md @@ -1,5 +1,6 @@ --- title: TDengine Inside +description: This document describes the internals of TDengine from an architectural perspective. --- ```mdx-code-block diff --git a/docs/en/25-application/01-telegraf.md b/docs/en/25-application/01-telegraf.md index 65fb08ee674cc9c952bbcfda57f0366fa129fdf2..b84b30bb71fe2231228007f95154a181000ac566 100644 --- a/docs/en/25-application/01-telegraf.md +++ b/docs/en/25-application/01-telegraf.md @@ -1,6 +1,7 @@ --- -sidebar_label: TDengine + Telegraf + Grafana title: Quickly Build IT DevOps Visualization System with TDengine + Telegraf + Grafana +sidebar_label: TDengine + Telegraf + Grafana +description: This document describes how to create an IT visualization system by integrating TDengine with Telegraf and Grafana. --- ## Background @@ -66,7 +67,7 @@ sudo systemctl start telegraf Log in to the Grafana interface using a web browser at `IP:3000`, with the system's initial username and password being `admin/admin`. Click on the gear icon on the left and select `Plugins`, you should find the TDengine data source plugin icon. -Click on the plus icon on the left and select `Import` to get the data from `https://github.com/taosdata/grafanaplugin/blob/master/examples/telegraf/grafana/dashboards/telegraf-dashboard-v0.1.0.json`, download the dashboard JSON file and import it. You will then see the dashboard in the following screen. +Click on the plus icon on the left and select `Import` to get the data from `https://github.com/taosdata/grafanaplugin/blob/master/examples/telegraf/grafana/dashboards/telegraf-dashboard-v3.json` (for TDengine 3.0. for TDengine 2.x, please use `telegraf-dashboard-v2.json`), download the dashboard JSON file and import it. You will then see the dashboard in the following screen. ![TDengine Database IT-DevOps-Solutions-telegraf-dashboard](./IT-DevOps-Solutions-telegraf-dashboard.webp) diff --git a/docs/en/25-application/02-collectd.md b/docs/en/25-application/02-collectd.md index 97412b230941435a08df12c859d63bca68b79ec9..6ac7253fc46c50d3efe698d508de8669c65bf5d9 100644 --- a/docs/en/25-application/02-collectd.md +++ b/docs/en/25-application/02-collectd.md @@ -1,6 +1,7 @@ --- -sidebar_label: TDengine + collectd/StatsD + Grafana title: Quickly build an IT DevOps visualization system using TDengine + collectd/StatsD + Grafana +sidebar_label: TDengine + collectd/StatsD + Grafana +description: This document describes how to build an IT visualization system by integrating TDengine with Grafana and collectd or StatsD. --- ## Background diff --git a/docs/en/25-application/03-immigrate.md b/docs/en/25-application/_03-immigrate.md similarity index 99% rename from docs/en/25-application/03-immigrate.md rename to docs/en/25-application/_03-immigrate.md index 1aabaa43e77660d72bca00d7d59cdee69b1a7c92..5f4a86937e305c517bca36f6fcf3be6ae791dd20 100644 --- a/docs/en/25-application/03-immigrate.md +++ b/docs/en/25-application/_03-immigrate.md @@ -1,6 +1,7 @@ --- -sidebar_label: OpenTSDB Migration to TDengine title: Best Practices for Migrating OpenTSDB Applications to TDengine +sidebar_label: OpenTSDB Migration to TDengine +description: This document describes the best practices for migrating an OpenTSDB application to TDengine. --- As a distributed, scalable, distributed time-series database platform based on HBase, and thanks to its first-mover advantage, OpenTSDB is widely used for monitoring in DevOps. However, as new technologies like cloud computing, microservices, and containerization technology has developed rapidly, Enterprise-level services are becoming more and more diverse and the architecture is becoming more complex. @@ -183,7 +184,7 @@ TDengine supports the standard JDBC 3.0 interface for manipulating databases, bu To facilitate historical data migration, we provide a plug-in for the data synchronization tool DataX, which can automatically write data into TDengine.The automatic data migration of DataX can only support the data migration process of a single value model. -For the specific usage of DataX and how to use DataX to write data to TDengine, please refer to [DataX-based TDengine Data Migration Tool](https://www.taosdata.com/blog/2021/10/26/3156.html). +For the specific usage of DataX and how to use DataX to write data to TDengine, please refer to [DataX-based TDengine Data Migration Tool](https://www.taosdata.com/engineering/16401.html). After migrating via DataX, we found that we can significantly improve the efficiency of migrating historical data by starting multiple processes and migrating numerous metrics simultaneously. The following are some records of the migration process. We provide these as a reference for application migration. diff --git a/docs/en/25-application/index.md b/docs/en/25-application/index.md index 5383a00c67c515dc65fd2ed1cac4b218710288b5..178fef47b64285efe732e53b316581ae4876a218 100644 --- a/docs/en/25-application/index.md +++ b/docs/en/25-application/index.md @@ -1,5 +1,6 @@ --- title: Application Practice +description: This document describes some examples of building systems around TDengine. --- ```mdx-code-block diff --git a/docs/en/27-train-faq/01-faq.md b/docs/en/27-train-faq/01-faq.md index 82e98b0d980c16acad0783abd62525cc6bde06ec..9e7f4f8e0d3d94f0016c0dcc6701c670fd7d32c8 100644 --- a/docs/en/27-train-faq/01-faq.md +++ b/docs/en/27-train-faq/01-faq.md @@ -1,5 +1,6 @@ --- title: Frequently Asked Questions +description: This document describes the frequently asked questions about TDengine. --- ## Submit an Issue @@ -33,7 +34,7 @@ TDengine 3.0 is not compatible with the configuration and data files from previo 4. Install TDengine 3.0. 5. For assistance in migrating data to TDengine 3.0, contact [TDengine Support](https://tdengine.com/support). -### 4. How can I resolve the "Unable to establish connection" error? +### 2. How can I resolve the "Unable to establish connection" error? This error indicates that the client could not connect to the server. Perform the following troubleshooting steps: @@ -68,7 +69,7 @@ This error indicates that the client could not connect to the server. Perform th 11. You can also use the TDengine CLI to diagnose network issues. For more information, see [Problem Diagnostics](https://docs.tdengine.com/operation/diagnose/). -### 5. How can I resolve the "Unable to resolve FQDN" error? +### 3. How can I resolve the "Unable to resolve FQDN" error? Clients and dnodes must be able to resolve the FQDN of each required node. You can confirm your configuration as follows: @@ -79,15 +80,15 @@ Clients and dnodes must be able to resolve the FQDN of each required node. You c 5. If TDengine has been previously installed and the `hostname` was modified, open `dnode.json` in the `data` folder and verify that the endpoint configuration is correct. The default location of the dnode file is `/var/lib/taos/dnode`. Ensure that you clean up previous installations before reinstalling TDengine. 6. Confirm whether FQDNs are preconfigured in `/etc/hosts` and `/etc/hostname`. -### 6. What is the most effective way to write data to TDengine? +### 4. What is the most effective way to write data to TDengine? Writing data in batches provides higher efficiency in most situations. You can insert one or more data records into one or more tables in a single SQL statement. -### 9. Why are table names not fully displayed? +### 5. Why are table names not fully displayed? The number of columns in the TDengine CLI terminal display is limited. This can cause table names to be cut off, and if you use an incomplete name in a statement, the "Table does not exist" error will occur. You can increase the display size with the `maxBinaryDisplayWidth` parameter or the SQL statement `set max_binary_display_width`. You can also append `\G` to your SQL statement to bypass this limitation. -### 10. How can I migrate data? +### 6. How can I migrate data? In TDengine, the `hostname` uniquely identifies a machine. When you move data files to a new machine, you must configure the new machine to have the same `host name` as the original machine. @@ -97,7 +98,7 @@ The data structure of previous versions of TDengine is not compatible with versi ::: -### 11. How can I temporary change the log level from the TDengine Client? +### 7. How can I temporary change the log level from the TDengine Client? To change the log level for debugging purposes, you can use the following command: @@ -118,14 +119,14 @@ Use `resetlog` to remove all logs generated on the local client. Use the other p For each parameter, you can set the value to `131` (error and warning), `135` (error, warning, and debug), or `143` (error, warning, debug, and trace). -### Why do TDengine components written in Go fail to compile? +### 8. Why do TDengine components written in Go fail to compile? TDengine includes taosAdapter, an independent component written in Go. This component provides the REST API as well as data access for other products such as Prometheus and Telegraf. When using the develop branch, you must run `git submodule update --init --recursive` to download the taosAdapter repository and then compile it. TDengine Go components require Go version 1.14 or later. -### 13. How can I query the storage space being used by my data? +### 9. How can I query the storage space being used by my data? The TDengine data files are stored in `/var/lib/taos` by default. Log files are stored in `/var/log/taos`. @@ -133,7 +134,7 @@ To see how much space your data files occupy, run `du -sh /var/lib/taos/vnode -- If you want to see how much space is occupied by a single database, first determine which vgroup is storing the database by running `show vgroups`. Then check `/var/lib/taos/vnode` for the files associated with the vgroup ID. -### 15. How is timezone information processed for timestamps? +### 10. How is timezone information processed for timestamps? TDengine uses the timezone of the client for timestamps. The server timezone does not affect timestamps. The client converts Unix timestamps in SQL statements to UTC before sending them to the server. When you query data on the server, it provides timestamps in UTC to the client, which converts them to its local time. @@ -144,13 +145,13 @@ Timestamps are processed as follows: 3. A timezone explicitly specified when establishing a connection to TDengine through a connector takes precedence over `taos.cfg` and the system timezone. For example, the Java connector allows you to specify a timezone in the JDBC URL. 4. If you use an RFC 3339 timestamp (2013-04-12T15:52:01.123+08:00), or an ISO 8601 timestamp (2013-04-12T15:52:01.123+0800), the timezone specified in the timestamp is used instead of the timestamps configured using any other method. -### 16. Which network ports are required by TDengine? +### 11. Which network ports are required by TDengine? See [serverPort](https://docs.tdengine.com/reference/config/#serverport) in Configuration Parameters. Note that ports are specified using 6030 as the default first port. If you change this port, all other ports change as well. -### 17. Why do applications such as Grafana fail to connect to TDengine over the REST API? +### 12. Why do applications such as Grafana fail to connect to TDengine over the REST API? In TDengine, the REST API is provided by taosAdapter. Ensure that taosAdapter is running before you connect an application to TDengine over the REST API. You can run `systemctl start taosadapter` to start the service. @@ -158,7 +159,7 @@ Note that the log path for taosAdapter must be configured separately. The defaul For more information, see [taosAdapter](https://docs.tdengine.com/reference/taosadapter/). -### 18. How can I resolve out-of-memory (OOM) errors? +### 13. How can I resolve out-of-memory (OOM) errors? OOM errors are thrown by the operating system when its memory, including swap, becomes insufficient and it needs to terminate processes to remain operational. Most OOM errors in TDengine occur for one of the following reasons: free memory is less than the value of `vm.min_free_kbytes` or free memory is less than the size of the request. If TDengine occupies reserved memory, an OOM error can occur even when free memory is sufficient. diff --git a/docs/en/27-train-faq/index.md b/docs/en/27-train-faq/index.md index 2cb87aab005b0ecc9275b6fe10e267487d38c336..cc55a41559a32fcb89b28a99705b59e07c22a81d 100644 --- a/docs/en/27-train-faq/index.md +++ b/docs/en/27-train-faq/index.md @@ -1,5 +1,6 @@ --- title: FAQ & Others +description: This document describes common issues related with TDengine. --- ```mdx-code-block diff --git a/docs/en/28-releases/01-tdengine.md b/docs/en/28-releases/01-tdengine.md index 32bdc21e7c0552f5f891b38f806e48efb6c419ac..b160058d02c22dc824b0e960ad61cbe596999a70 100644 --- a/docs/en/28-releases/01-tdengine.md +++ b/docs/en/28-releases/01-tdengine.md @@ -1,7 +1,7 @@ --- -sidebar_label: TDengine title: TDengine Release History and Download Links -description: TDengine release history, Release Notes and download links. +sidebar_label: TDengine +description: This document provides download links for all released versions of TDengine 3.0. --- TDengine 3.x installation packages can be downloaded at the following links: @@ -10,6 +10,50 @@ For TDengine 2.x installation packages by version, please visit [here](https://w import Release from "/components/ReleaseV3"; +## 3.0.3.2 + + + +## 3.0.3.1 + + + +## 3.0.3.1 + + + +## 3.0.3.0 + + + +## 3.0.2.6 + + + +## 3.0.2.5 + + + +## 3.0.2.4 + + + +## 3.0.2.3 + + + +## 3.0.2.2 + + + +## 3.0.2.1 + + + +## 3.0.2.0 + + + ## 3.0.1.8 diff --git a/docs/en/28-releases/02-tools.md b/docs/en/28-releases/02-tools.md index 7126b5a997043231d1cf93d633b8cd71e5f6275e..17581b780a8cba5e0e73ef7d0ff8da8e54f0de56 100644 --- a/docs/en/28-releases/02-tools.md +++ b/docs/en/28-releases/02-tools.md @@ -1,7 +1,7 @@ --- -sidebar_label: taosTools title: taosTools Release History and Download Links -description: taosTools release history, Release Notes, download links. +sidebar_label: taosTools +description: This document provides download links for all released versions of taosTools compatible with TDengine 3.0. --- taosTools installation packages can be downloaded at the following links: @@ -10,6 +10,50 @@ For other historical version installers, please visit [here](https://www.taosdat import Release from "/components/ReleaseV3"; +## 2.4.11 + + + +## 2.4.10 + + + +## 2.4.9 + + + +## 2.4.8 + + + +## 2.4.6 + + + +## 2.4.3 + + + +## 2.4.2 + + + +## 2.4.1 + + + +## 2.4.0 + + + +## 2.3.3 + + + +## 2.3.2 + + + ## 2.3.0 diff --git a/docs/en/28-releases/index.md b/docs/en/28-releases/index.md index c01c99cdce0190fb04f88d55a09e8cc406d4d8b0..d1f93c3b9b2cf297578953d9c262b60f3ad2a214 100644 --- a/docs/en/28-releases/index.md +++ b/docs/en/28-releases/index.md @@ -1,5 +1,6 @@ --- title: Releases +description: This document describes TDengine products that have been released. --- ```mdx-code-block diff --git a/docs/examples/c/tmq_example.c b/docs/examples/c/tmq_example.c index a3bade308a4ce41f556878d90861e299893315c4..d958428b8ffec9064166ddfd502cc0e2dbd9a200 100644 --- a/docs/examples/c/tmq_example.c +++ b/docs/examples/c/tmq_example.c @@ -70,7 +70,7 @@ static int32_t init_env() { taos_free_result(pRes); // create database - pRes = taos_query(pConn, "create database tmqdb"); + pRes = taos_query(pConn, "create database tmqdb wal_retention_period 3600"); if (taos_errno(pRes) != 0) { printf("error in create tmqdb, reason:%s\n", taos_errstr(pRes)); return -1; diff --git a/docs/examples/csharp/asyncQuery/asyncquery.csproj b/docs/examples/csharp/asyncQuery/asyncquery.csproj index 23e590cd25aa88e58cabf81717a6baf320f447bc..7c5b693f28dfa8832ae08bbaae9aa8a367951c70 100644 --- a/docs/examples/csharp/asyncQuery/asyncquery.csproj +++ b/docs/examples/csharp/asyncQuery/asyncquery.csproj @@ -9,7 +9,7 @@ - + diff --git a/docs/examples/csharp/connect/connect.csproj b/docs/examples/csharp/connect/connect.csproj index 3a912f8987ace6ae540726886d901c8d32a7b81b..a08e86d4b42199be44a6551e37da11efb6e06a34 100644 --- a/docs/examples/csharp/connect/connect.csproj +++ b/docs/examples/csharp/connect/connect.csproj @@ -9,7 +9,7 @@ - + diff --git a/docs/examples/csharp/influxdbLine/Program.cs b/docs/examples/csharp/influxdbLine/Program.cs index fa3cb21fe04977b5081c922d623dee5514056770..a620c016090c9177966f8361eac0e65d23192bd8 100644 --- a/docs/examples/csharp/influxdbLine/Program.cs +++ b/docs/examples/csharp/influxdbLine/Program.cs @@ -48,7 +48,7 @@ namespace TDengineExample static void PrepareDatabase(IntPtr conn) { - IntPtr res = TDengine.Query(conn, "CREATE DATABASE test"); + IntPtr res = TDengine.Query(conn, "CREATE DATABASE test WAL_RETENTION_PERIOD 3600"); if (TDengine.ErrorNo(res) != 0) { throw new Exception("failed to create database, reason: " + TDengine.Error(res)); diff --git a/docs/examples/csharp/influxdbLine/influxdbline.csproj b/docs/examples/csharp/influxdbLine/influxdbline.csproj index 58bca485088e409fe1d387c6020418bbc2bf871b..4889f8fde9dc0eb75c0547e32355929d1cceb138 100644 --- a/docs/examples/csharp/influxdbLine/influxdbline.csproj +++ b/docs/examples/csharp/influxdbLine/influxdbline.csproj @@ -9,7 +9,7 @@ - + diff --git a/docs/examples/csharp/optsJSON/Program.cs b/docs/examples/csharp/optsJSON/Program.cs index b67b5af62bf0a1fd9028125da0b665f723f2e4ec..8dcc1dce92be2f134ce68910c916896c07fc4003 100644 --- a/docs/examples/csharp/optsJSON/Program.cs +++ b/docs/examples/csharp/optsJSON/Program.cs @@ -54,7 +54,7 @@ namespace TDengineExample static void PrepareDatabase(IntPtr conn) { - IntPtr res = TDengine.Query(conn, "CREATE DATABASE test"); + IntPtr res = TDengine.Query(conn, "CREATE DATABASE test WAL_RETENTION_PERIOD 3600"); if (TDengine.ErrorNo(res) != 0) { throw new Exception("failed to create database, reason: " + TDengine.Error(res)); diff --git a/docs/examples/csharp/optsJSON/optsJSON.csproj b/docs/examples/csharp/optsJSON/optsJSON.csproj index da16025dcd45f8e5c4ba6e242524c2e56191e93c..208f04c82d19f83f2746871b64a6dfdf0dcf3eae 100644 --- a/docs/examples/csharp/optsJSON/optsJSON.csproj +++ b/docs/examples/csharp/optsJSON/optsJSON.csproj @@ -9,7 +9,7 @@ - + diff --git a/docs/examples/csharp/optsTelnet/Program.cs b/docs/examples/csharp/optsTelnet/Program.cs index e73ceb041accf88222176342d46fe1a669584211..ccd29d0cfc62ac1a59bea8465630595c2e65b5c0 100644 --- a/docs/examples/csharp/optsTelnet/Program.cs +++ b/docs/examples/csharp/optsTelnet/Program.cs @@ -58,7 +58,7 @@ namespace TDengineExample static void PrepareDatabase(IntPtr conn) { - IntPtr res = TDengine.Query(conn, "CREATE DATABASE test"); + IntPtr res = TDengine.Query(conn, "CREATE DATABASE test WAL_RETENTION_PERIOD 3600"); if (TDengine.ErrorNo(res) != 0) { throw new Exception("failed to create database, reason: " + TDengine.Error(res)); diff --git a/docs/examples/csharp/optsTelnet/optstelnet.csproj b/docs/examples/csharp/optsTelnet/optstelnet.csproj index 194de21bcc74653a2267b29681ece6243fd401fc..32c76ec4184b82e943897a36bc3bcbbd9ec85149 100644 --- a/docs/examples/csharp/optsTelnet/optstelnet.csproj +++ b/docs/examples/csharp/optsTelnet/optstelnet.csproj @@ -9,7 +9,7 @@ - + diff --git a/docs/examples/csharp/query/query.csproj b/docs/examples/csharp/query/query.csproj index c97dbd3051e1a415b192e73d6753266b0b41b07d..360d73b2c096ef86df59876d0629fd0c4b6a239b 100644 --- a/docs/examples/csharp/query/query.csproj +++ b/docs/examples/csharp/query/query.csproj @@ -9,7 +9,7 @@ - + diff --git a/docs/examples/csharp/sqlInsert/Program.cs b/docs/examples/csharp/sqlInsert/Program.cs index f23a6e1663023d1d2fafb3e92e0b605f8ac55e52..25a945a45952d596153707bb4ea8d6c6e327b098 100644 --- a/docs/examples/csharp/sqlInsert/Program.cs +++ b/docs/examples/csharp/sqlInsert/Program.cs @@ -11,7 +11,7 @@ namespace TDengineExample IntPtr conn = GetConnection(); try { - IntPtr res = TDengine.Query(conn, "CREATE DATABASE power"); + IntPtr res = TDengine.Query(conn, "CREATE DATABASE power WAL_RETENTION_PERIOD 3600"); CheckRes(conn, res, "failed to create database"); res = TDengine.Query(conn, "USE power"); CheckRes(conn, res, "failed to change database"); diff --git a/docs/examples/csharp/sqlInsert/sqlinsert.csproj b/docs/examples/csharp/sqlInsert/sqlinsert.csproj index ab0e5e717a78faad07c949b434b0d0b8a26c7211..1b6f745c82437e9796da4c48fc720600dbe99cb5 100644 --- a/docs/examples/csharp/sqlInsert/sqlinsert.csproj +++ b/docs/examples/csharp/sqlInsert/sqlinsert.csproj @@ -9,7 +9,7 @@ - + diff --git a/docs/examples/csharp/stmtInsert/Program.cs b/docs/examples/csharp/stmtInsert/Program.cs index 87e1971feb8499c515206f05a1e916070ac57f4c..2e856a49bbbbae5424a517363e3ae1360ba6a0c7 100644 --- a/docs/examples/csharp/stmtInsert/Program.cs +++ b/docs/examples/csharp/stmtInsert/Program.cs @@ -42,7 +42,7 @@ namespace TDengineExample // 5. execute res = TDengine.StmtExecute(stmt); - CheckStmtRes(res, "faild to execute"); + CheckStmtRes(res, "failed to execute"); // 6. free TaosMultiBind.FreeTaosBind(tags); @@ -76,7 +76,7 @@ namespace TDengineExample static void PrepareSTable() { - IntPtr res = TDengine.Query(conn, "CREATE DATABASE power"); + IntPtr res = TDengine.Query(conn, "CREATE DATABASE power WAL_RETENTION_PERIOD 3600"); CheckResPtr(res, "failed to create database"); res = TDengine.Query(conn, "USE power"); CheckResPtr(res, "failed to change database"); @@ -92,7 +92,7 @@ namespace TDengineExample int code = TDengine.StmtClose(stmt); if (code != 0) { - throw new Exception($"falied to close stmt, {code} reason: {TDengine.StmtErrorStr(stmt)} "); + throw new Exception($"failed to close stmt, {code} reason: {TDengine.StmtErrorStr(stmt)} "); } } } diff --git a/docs/examples/csharp/stmtInsert/stmtinsert.csproj b/docs/examples/csharp/stmtInsert/stmtinsert.csproj index 3d459fbeda02ab03dc40dac2ecae290724cccbcc..f5b2b673971c3822e6f6c9b65b8f02bc9d4dc80e 100644 --- a/docs/examples/csharp/stmtInsert/stmtinsert.csproj +++ b/docs/examples/csharp/stmtInsert/stmtinsert.csproj @@ -9,7 +9,7 @@ - + diff --git a/docs/examples/csharp/subscribe/subscribe.csproj b/docs/examples/csharp/subscribe/subscribe.csproj index 8ae1cf6bc6023558c28797a0d9fcccb2f2e87653..191b3f9e9bb07dc72c9bb452ad19e30e42af922a 100644 --- a/docs/examples/csharp/subscribe/subscribe.csproj +++ b/docs/examples/csharp/subscribe/subscribe.csproj @@ -9,7 +9,7 @@ - + diff --git a/docs/examples/csharp/wsConnect/wsConnect.csproj b/docs/examples/csharp/wsConnect/wsConnect.csproj index 34951dc761903e5a4b7a4bec5dfe55a965ab88be..c7988b6e9c955f21d53a312e10b513403363936e 100644 --- a/docs/examples/csharp/wsConnect/wsConnect.csproj +++ b/docs/examples/csharp/wsConnect/wsConnect.csproj @@ -2,12 +2,17 @@ Exe - net5.0 - enable + net6.0 - + + + + + + + diff --git a/docs/examples/csharp/wsInsert/wsInsert.csproj b/docs/examples/csharp/wsInsert/wsInsert.csproj index 34951dc761903e5a4b7a4bec5dfe55a965ab88be..5aa419b2c80bf303e84ff3f1a30a839ce9220663 100644 --- a/docs/examples/csharp/wsInsert/wsInsert.csproj +++ b/docs/examples/csharp/wsInsert/wsInsert.csproj @@ -2,12 +2,16 @@ Exe - net5.0 + net6.0 enable - - + - + + + + + + diff --git a/docs/examples/csharp/wsQuery/wsQuery.csproj b/docs/examples/csharp/wsQuery/wsQuery.csproj index 34951dc761903e5a4b7a4bec5dfe55a965ab88be..bcc7c19a59fdab1c8ad9d3098824239d645743e6 100644 --- a/docs/examples/csharp/wsQuery/wsQuery.csproj +++ b/docs/examples/csharp/wsQuery/wsQuery.csproj @@ -2,12 +2,18 @@ Exe - net5.0 + net6.0 enable - + + + + + + + diff --git a/docs/examples/csharp/wsStmt/wsStmt.csproj b/docs/examples/csharp/wsStmt/wsStmt.csproj index 34951dc761903e5a4b7a4bec5dfe55a965ab88be..bcc7c19a59fdab1c8ad9d3098824239d645743e6 100644 --- a/docs/examples/csharp/wsStmt/wsStmt.csproj +++ b/docs/examples/csharp/wsStmt/wsStmt.csproj @@ -2,12 +2,18 @@ Exe - net5.0 + net6.0 enable - + + + + + + + diff --git a/docs/examples/go/go.sum b/docs/examples/go/go.sum new file mode 100644 index 0000000000000000000000000000000000000000..13e13adaa189053696320a6eb9740daa319a98b7 --- /dev/null +++ b/docs/examples/go/go.sum @@ -0,0 +1,15 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/taosdata/driver-go/v3 v3.1.0/go.mod h1:H2vo/At+rOPY1aMzUV9P49SVX7NlXb3LAbKw+MCLrmU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/docs/examples/go/sub/main.go b/docs/examples/go/sub/main.go index 7721eed1346f254e104bb41a2135171ebd518e2c..cb24e351ab8cc5265cefbed9565d9a404aadf08d 100644 --- a/docs/examples/go/sub/main.go +++ b/docs/examples/go/sub/main.go @@ -1,17 +1,12 @@ package main import ( - "context" - "encoding/json" "fmt" - "strconv" - "time" + "os" "github.com/taosdata/driver-go/v3/af" "github.com/taosdata/driver-go/v3/af/tmq" - "github.com/taosdata/driver-go/v3/common" - "github.com/taosdata/driver-go/v3/errors" - "github.com/taosdata/driver-go/v3/wrapper" + tmqcommon "github.com/taosdata/driver-go/v3/common/tmq" ) func main() { @@ -20,101 +15,63 @@ func main() { panic(err) } defer db.Close() - _, err = db.Exec("create database if not exists example_tmq") + _, err = db.Exec("create database if not exists example_tmq wal_retention_period 3600") if err != nil { panic(err) } - _, err = db.Exec("create topic if not exists example_tmq_topic with meta as DATABASE example_tmq") + _, err = db.Exec("create topic if not exists example_tmq_topic as DATABASE example_tmq") if err != nil { panic(err) } - config := tmq.NewConfig() - defer config.Destroy() - err = config.SetGroupID("test") if err != nil { panic(err) } - err = config.SetAutoOffsetReset("earliest") - if err != nil { - panic(err) - } - err = config.SetConnectIP("127.0.0.1") - if err != nil { - panic(err) - } - err = config.SetConnectUser("root") - if err != nil { - panic(err) - } - err = config.SetConnectPass("taosdata") + consumer, err := tmq.NewConsumer(&tmqcommon.ConfigMap{ + "group.id": "test", + "auto.offset.reset": "earliest", + "td.connect.ip": "127.0.0.1", + "td.connect.user": "root", + "td.connect.pass": "taosdata", + "td.connect.port": "6030", + "client.id": "test_tmq_client", + "enable.auto.commit": "false", + "experimental.snapshot.enable": "true", + "msg.with.table.name": "true", + }) if err != nil { panic(err) } - err = config.SetConnectPort("6030") + err = consumer.Subscribe("example_tmq_topic", nil) if err != nil { panic(err) } - err = config.SetMsgWithTableName(true) + _, err = db.Exec("create table example_tmq.t1 (ts timestamp,v int)") if err != nil { panic(err) } - err = config.EnableHeartBeat() + _, err = db.Exec("insert into example_tmq.t1 values(now,1)") if err != nil { panic(err) } - err = config.EnableAutoCommit(func(result *wrapper.TMQCommitCallbackResult) { - if result.ErrCode != 0 { - errStr := wrapper.TMQErr2Str(result.ErrCode) - err := errors.NewError(int(result.ErrCode), errStr) - panic(err) + for i := 0; i < 5; i++ { + ev := consumer.Poll(0) + if ev != nil { + switch e := ev.(type) { + case *tmqcommon.DataMessage: + fmt.Println(e.String()) + case tmqcommon.Error: + fmt.Fprintf(os.Stderr, "%% Error: %v: %v\n", e.Code(), e) + panic(e) + } + consumer.Commit() } - }) - if err != nil { - panic(err) } - consumer, err := tmq.NewConsumer(config) + err = consumer.Unsubscribe() if err != nil { panic(err) } - err = consumer.Subscribe([]string{"example_tmq_topic"}) + err = consumer.Close() if err != nil { panic(err) } - _, err = db.Exec("create table example_tmq.t1 (ts timestamp,v int)") - if err != nil { - panic(err) - } - for { - result, err := consumer.Poll(time.Second) - if err != nil { - panic(err) - } - if result.Type != common.TMQ_RES_TABLE_META { - panic("want message type 2 got " + strconv.Itoa(int(result.Type))) - } - data, _ := json.Marshal(result.Meta) - fmt.Println(string(data)) - consumer.Commit(context.Background(), result.Message) - consumer.FreeMessage(result.Message) - break - } - _, err = db.Exec("insert into example_tmq.t1 values(now,1)") - if err != nil { - panic(err) - } - for { - result, err := consumer.Poll(time.Second) - if err != nil { - panic(err) - } - if result.Type != common.TMQ_RES_DATA { - panic("want message type 1 got " + strconv.Itoa(int(result.Type))) - } - data, _ := json.Marshal(result.Data) - fmt.Println(string(data)) - consumer.Commit(context.Background(), result.Message) - consumer.FreeMessage(result.Message) - break - } - consumer.Close() } diff --git a/docs/examples/java/pom.xml b/docs/examples/java/pom.xml index 634c3f75a8386db4caab5c1d598f89dc93926c54..01d0ce936c20df1f8567869c1307606ab949cd32 100644 --- a/docs/examples/java/pom.xml +++ b/docs/examples/java/pom.xml @@ -1,6 +1,7 @@ - 4.0.0 @@ -17,13 +18,13 @@ - + com.taosdata.jdbc taos-jdbcdriver - 3.0.0 + 3.1.0 - + junit junit @@ -32,4 +33,4 @@ - + \ No newline at end of file diff --git a/docs/examples/java/src/main/java/com/taos/example/SubscribeDemo.java b/docs/examples/java/src/main/java/com/taos/example/SubscribeDemo.java index e9af5e9ce0c0473f4513cbb949dcbd9f433c0c92..8da6f77bae432dee987d4567229c2fbebd657be8 100644 --- a/docs/examples/java/src/main/java/com/taos/example/SubscribeDemo.java +++ b/docs/examples/java/src/main/java/com/taos/example/SubscribeDemo.java @@ -35,7 +35,7 @@ public class SubscribeDemo { try (Statement statement = connection.createStatement()) { statement.executeUpdate("drop topic if exists " + TOPIC); statement.executeUpdate("drop database if exists " + DB_NAME); - statement.executeUpdate("create database " + DB_NAME); + statement.executeUpdate("create database " + DB_NAME + " wal_retention_period 3600"); statement.executeUpdate("use " + DB_NAME); statement.executeUpdate( "CREATE TABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT) TAGS (`groupid` INT, `location` BINARY(24))"); diff --git a/docs/examples/java/src/main/java/com/taos/example/WebsocketSubscribeDemo.java b/docs/examples/java/src/main/java/com/taos/example/WebsocketSubscribeDemo.java new file mode 100644 index 0000000000000000000000000000000000000000..83cb04f55244aacf860573a42ddc952e1e522803 --- /dev/null +++ b/docs/examples/java/src/main/java/com/taos/example/WebsocketSubscribeDemo.java @@ -0,0 +1,79 @@ +package com.taos.example; + +import com.taosdata.jdbc.tmq.ConsumerRecords; +import com.taosdata.jdbc.tmq.TMQConstants; +import com.taosdata.jdbc.tmq.TaosConsumer; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.Duration; +import java.util.Collections; +import java.util.Properties; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicBoolean; + +public class WebsocketSubscribeDemo { + private static final String TOPIC = "tmq_topic_ws"; + private static final String DB_NAME = "meters_ws"; + private static final AtomicBoolean shutdown = new AtomicBoolean(false); + + public static void main(String[] args) { + Timer timer = new Timer(); + timer.schedule(new TimerTask() { + public void run() { + shutdown.set(true); + } + }, 3_000); + try { + // prepare + Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); + String jdbcUrl = "jdbc:TAOS-RS://127.0.0.1:6041/?user=root&password=taosdata&batchfetch=true"; + try (Connection connection = DriverManager.getConnection(jdbcUrl); + Statement statement = connection.createStatement()) { + statement.executeUpdate("drop topic if exists " + TOPIC); + statement.executeUpdate("drop database if exists " + DB_NAME); + statement.executeUpdate("create database " + DB_NAME + " wal_retention_period 3600"); + statement.executeUpdate("use " + DB_NAME); + statement.executeUpdate( + "CREATE TABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT) TAGS (`groupid` INT, `location` BINARY(24))"); + statement.executeUpdate("CREATE TABLE `d0` USING `meters` TAGS(0, 'California.LosAngles')"); + statement.executeUpdate("INSERT INTO `d0` values(now - 10s, 0.32, 116)"); + statement.executeUpdate("INSERT INTO `d0` values(now - 8s, NULL, NULL)"); + statement.executeUpdate( + "INSERT INTO `d1` USING `meters` TAGS(1, 'California.SanFrancisco') values(now - 9s, 10.1, 119)"); + statement.executeUpdate( + "INSERT INTO `d1` values (now-8s, 10, 120) (now - 6s, 10, 119) (now - 4s, 11.2, 118)"); + // create topic + statement.executeUpdate("create topic " + TOPIC + " as select * from meters"); + } + + // create consumer + Properties properties = new Properties(); + properties.setProperty(TMQConstants.BOOTSTRAP_SERVERS, "127.0.0.1:6041"); + properties.setProperty(TMQConstants.CONNECT_TYPE, "ws"); + properties.setProperty(TMQConstants.MSG_WITH_TABLE_NAME, "true"); + properties.setProperty(TMQConstants.ENABLE_AUTO_COMMIT, "true"); + properties.setProperty(TMQConstants.GROUP_ID, "test"); + properties.setProperty(TMQConstants.VALUE_DESERIALIZER, + "com.taos.example.MetersDeserializer"); + + // poll data + try (TaosConsumer consumer = new TaosConsumer<>(properties)) { + consumer.subscribe(Collections.singletonList(TOPIC)); + while (!shutdown.get()) { + ConsumerRecords meters = consumer.poll(Duration.ofMillis(100)); + for (Meters meter : meters) { + System.out.println(meter); + } + } + consumer.unsubscribe(); + } + } catch (ClassNotFoundException | SQLException e) { + e.printStackTrace(); + } + timer.cancel(); + } +} diff --git a/docs/examples/java/src/main/java/com/taos/example/highvolume/DataBaseMonitor.java b/docs/examples/java/src/main/java/com/taos/example/highvolume/DataBaseMonitor.java index 04b149a4b96441ecfd1b0bdde54c9ed71349cab2..8678f65231153b1e05fb0141cd63272ee6941f9a 100644 --- a/docs/examples/java/src/main/java/com/taos/example/highvolume/DataBaseMonitor.java +++ b/docs/examples/java/src/main/java/com/taos/example/highvolume/DataBaseMonitor.java @@ -36,28 +36,17 @@ public class DataBaseMonitor { stmt.execute("CREATE STABLE test.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)"); } - public Long count() throws SQLException { - if (!stmt.isClosed()) { - ResultSet result = stmt.executeQuery("SELECT count(*) from test.meters"); + public long count() throws SQLException { + try (ResultSet result = stmt.executeQuery("SELECT count(*) from test.meters")) { result.next(); return result.getLong(1); } - return null; } - /** - * show test.stables; - * - * name | created_time | columns | tags | tables | - * ============================================================================================ - * meters | 2022-07-20 08:39:30.902 | 4 | 2 | 620000 | - */ - public Long getTableCount() throws SQLException { - if (!stmt.isClosed()) { - ResultSet result = stmt.executeQuery("show test.stables"); + public long getTableCount() throws SQLException { + try (ResultSet result = stmt.executeQuery("select count(*) from information_schema.ins_tables where db_name = 'test';")) { result.next(); - return result.getLong(5); + return result.getLong(1); } - return null; } } \ No newline at end of file diff --git a/docs/examples/java/src/main/java/com/taos/example/highvolume/SQLWriter.java b/docs/examples/java/src/main/java/com/taos/example/highvolume/SQLWriter.java index c2989acdbe3d0f56d7451ac86051a55955ce14de..dc820f161c8ae3a49f692b97ba6eaebbda304f90 100644 --- a/docs/examples/java/src/main/java/com/taos/example/highvolume/SQLWriter.java +++ b/docs/examples/java/src/main/java/com/taos/example/highvolume/SQLWriter.java @@ -42,7 +42,7 @@ public class SQLWriter { /** * Maximum SQL length. */ - private int maxSQLLength; + private int maxSQLLength = 800_000; /** * Map from table name to column values. For example: @@ -81,14 +81,6 @@ public class SQLWriter { conn = getConnection(); stmt = conn.createStatement(); stmt.execute("use test"); - ResultSet rs = stmt.executeQuery("show variables"); - while (rs.next()) { - String configName = rs.getString(1); - if ("maxSQLLength".equals(configName)) { - maxSQLLength = Integer.parseInt(rs.getString(2)); - logger.info("maxSQLLength={}", maxSQLLength); - } - } } /** @@ -149,7 +141,7 @@ public class SQLWriter { } catch (SQLException e) { // convert to error code defined in taoserror.h int errorCode = e.getErrorCode() & 0xffff; - if (errorCode == 0x362 || errorCode == 0x218) { + if (errorCode == 0x2603) { // Table does not exist createTables(); executeSQL(sql); diff --git a/docs/examples/java/src/test/java/com/taos/test/TestAll.java b/docs/examples/java/src/test/java/com/taos/test/TestAll.java index 8d201da0745e1d2d36220c9d78383fc37d4a813a..f24156d8b13fc8f0dfb6eac52b8b68815e8e3483 100644 --- a/docs/examples/java/src/test/java/com/taos/test/TestAll.java +++ b/docs/examples/java/src/test/java/com/taos/test/TestAll.java @@ -64,21 +64,15 @@ public class TestAll { @Test public void testSubscribe() { - - Thread thread = new Thread(() -> { - try { - Thread.sleep(1000); - insertData(); - } catch (SQLException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }); - thread.start(); SubscribeDemo.main(args); } + + @Test + public void testSubscribeOverWebsocket() { + WebsocketSubscribeDemo.main(args); + } + @Test public void testSchemaless() throws SQLException { LineProtocolExample.main(args); diff --git a/docs/examples/node/restexample/connect.js b/docs/examples/node/restexample/connect.js index bb027d4fe85f35e5a7047b1517caee00314e2153..f36472b4c09a952cffe4b8ab24d1d9aa9f15b3fe 100644 --- a/docs/examples/node/restexample/connect.js +++ b/docs/examples/node/restexample/connect.js @@ -3,18 +3,14 @@ const { options, connect } = require("@tdengine/rest"); async function test() { options.path = "/rest/sql"; options.host = "localhost"; + options.port = 6041; let conn = connect(options); let cursor = conn.cursor(); try { let res = await cursor.query("SELECT server_version()"); - res.toString(); + console.log("res.getResult()",res.getResult()); } catch (err) { console.log(err); } } test(); - -// output: -// server_version() | -// =================== -// 3.0.0.0 | diff --git a/docs/examples/node/restexample/insert_example.js b/docs/examples/node/restexample/insert_example.js new file mode 100644 index 0000000000000000000000000000000000000000..d9fddf9f2888a878f369e7a2ee20c5ce49d0cc99 --- /dev/null +++ b/docs/examples/node/restexample/insert_example.js @@ -0,0 +1,19 @@ +const { options, connect } = require("@tdengine/rest"); + +async function sqlInsert() { + options.path = "/rest/sql"; + options.host = "localhost"; + options.port = 6041; + let conn = connect(options); + let cursor = conn.cursor(); + try { + let res = await cursor.query('CREATE DATABASE power'); + res = await cursor.query('CREATE STABLE power.meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int)'); + res = await cursor.query('INSERT INTO power.d1001 USING power.meters TAGS ("California.SanFrancisco", 2) VALUES (NOW, 10.2, 219, 0.32)'); + console.log("res.getResult()", res.getResult()); + } catch (err) { + console.log(err); + } +} +sqlInsert(); + diff --git a/docs/examples/node/restexample/query_example.js b/docs/examples/node/restexample/query_example.js new file mode 100644 index 0000000000000000000000000000000000000000..0edce64a24edddaf48b207d676f6d704d832ed68 --- /dev/null +++ b/docs/examples/node/restexample/query_example.js @@ -0,0 +1,16 @@ +const { options, connect } = require("@tdengine/rest"); + +async function query() { + options.path = "/rest/sql"; + options.host = "localhost"; + options.port = 6041; + let conn = connect(options); + let cursor = conn.cursor(); + try { + let res = await cursor.query('select * from power.meters'); + console.log("res.getResult()", res.getResult()); + } catch (err) { + console.log(err); + } +} +query(); diff --git a/docs/examples/node/restexample/restChecker.js b/docs/examples/node/restexample/restChecker.js new file mode 100644 index 0000000000000000000000000000000000000000..a999684e575d4271e5a62895a5b1678a37d16a65 --- /dev/null +++ b/docs/examples/node/restexample/restChecker.js @@ -0,0 +1,78 @@ +const { options, connect } = require("@tdengine/rest"); +options.path = '/rest/sql/' +options.host = 'localhost'; +options.port = 6041; +options.user = "root"; +options.passwd = "taosdata"; + +//optional +// options.url = "http://127.0.0.1:6041"; + +const db = 'rest_ts_db'; +const table = 'rest' +const createDB = `create database if not exists ${db} keep 3650`; +const dropDB = `drop database if exists ${db}`; +const createTB = `create table if not exists ${db}.${table}(ts timestamp,i8 tinyint,i16 smallint,i32 int,i64 bigint,bnr binary(40),nchr nchar(40))`; +const addColumn = `alter table ${db}.${table} add column new_column nchar(40) `; +const dropColumn = `alter table ${db}.${table} drop column new_column`; +const insertSql = `insert into ${db}.${table} values('2022-03-30 18:30:51.567',1,2,3,4,'binary1','nchar1')` + + `('2022-03-30 18:30:51.568',5,6,7,8,'binary2','nchar2')` + + `('2022-03-30 18:30:51.569',9,0,1,2,'binary3','nchar3')`; +const querySql = `select * from ${db}.${table}`; +const errorSql = 'show database'; + +let conn = connect(options); +let cursor = conn.cursor(); + +async function execute(sql, pure = true) { + let result = await cursor.query(sql, pure); + // print query result as taos shell + // Get Result object, return Result object. + console.log("result.getResult()",result.getResult()); + // Get Meta data, return Meta[]|undefined(when execute failed this is undefined). + console.log("result.getMeta()",result.getMeta()); + // Get data,return Array>|undefined(when execute failed this is undefined). + console.log("result.getData()",result.getData()); + // Get affect rows,return number|undefined(when execute failed this is undefined). + console.log("result.getAffectRows()",result.getAffectRows()); + // Get command,return SQL send to server(need to `query(sql,false)`,set 'pure=false',default true). + console.log("result.getCommand()",result.getCommand()); + // Get error code ,return number|undefined(when execute failed this is undefined). + console.log("result.getErrCode()",result.getErrCode()); + // Get error string,return string|undefined(when execute failed this is undefined). + console.log("result.getErrStr()",result.getErrStr()); +} + +(async () => { + // start execute time + let start = new Date().getTime(); + await execute(createDB); + console.log("-----------------------------------") + + await execute(createTB); + console.log("-----------------------------------") + + await execute(addColumn); + console.log("----------------------------------") + + await execute(dropColumn); + console.log("-----------------------------------") + + await execute(insertSql); + console.log("-----------------------------------") + + await execute(querySql); + console.log("-----------------------------------") + + await execute(errorSql); + console.log("-----------------------------------") + + await execute(dropDB); + // finish time + let end = new Date().getTime(); + console.log("total spend time:%d ms",end - start); +})() + + + + diff --git a/docs/examples/python/conn_websocket_pandas.py b/docs/examples/python/conn_websocket_pandas.py new file mode 100644 index 0000000000000000000000000000000000000000..5cad5384b251b7016f895d4d0e8792e42bfc395f --- /dev/null +++ b/docs/examples/python/conn_websocket_pandas.py @@ -0,0 +1,39 @@ +import pandas +from sqlalchemy import create_engine, text +import taos + +taos_conn = taos.connect() +taos_conn.execute('drop database if exists power') +taos_conn.execute('create database if not exists power wal_retention_period 3600') +taos_conn.execute("use power") +taos_conn.execute( + "CREATE STABLE power.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)") +# insert data +taos_conn.execute("""INSERT INTO power.d1001 USING power.meters TAGS('California.SanFrancisco', 2) +VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) +('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000) + power.d1002 USING power.meters TAGS('California.SanFrancisco', 3) + VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000) + power.d1003 USING power.meters TAGS('California.LosAngeles', 2) + VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000) ('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000) + power.d1004 USING power.meters TAGS('California.LosAngeles', 3) + VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)""") + +engine = create_engine("taosws://root:taosdata@localhost:6041") +conn = engine.connect() +df: pandas.DataFrame = pandas.read_sql(text("SELECT * FROM power.meters"), conn) +conn.close() + +# print index +print(df.index) +# print data type of element in ts column +print(type(df.ts[0])) +print(df.head(3)) + +# output: +# RangeIndex(start=0, stop=8, step=1) +# +# ts current ... location groupid +# 0 2018-10-03 14:38:05.000 10.3 ... California.SanFrancisco 2 +# 1 2018-10-03 14:38:15.000 12.6 ... California.SanFrancisco 2 +# 2 2018-10-03 14:38:16.800 12.3 ... California.SanFrancisco 2 diff --git a/docs/examples/python/connect_rest_with_req_id_examples.py b/docs/examples/python/connect_rest_with_req_id_examples.py new file mode 100644 index 0000000000000000000000000000000000000000..3feb574fa60d5701aa040b606846cb6cf7a28aaa --- /dev/null +++ b/docs/examples/python/connect_rest_with_req_id_examples.py @@ -0,0 +1,44 @@ +# ANCHOR: connect +from taosrest import connect, TaosRestConnection, TaosRestCursor + +conn = connect(url="http://localhost:6041", + user="root", + password="taosdata", + timeout=30) + +# ANCHOR_END: connect +# ANCHOR: basic +# create STable +cursor = conn.cursor() +cursor.execute("DROP DATABASE IF EXISTS power", req_id=1) +cursor.execute("CREATE DATABASE power", req_id=2) +cursor.execute( + "CREATE STABLE power.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)", req_id=3) + +# insert data +cursor.execute("""INSERT INTO power.d1001 USING power.meters TAGS('California.SanFrancisco', 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000) + power.d1002 USING power.meters TAGS('California.SanFrancisco', 3) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000) + power.d1003 USING power.meters TAGS('California.LosAngeles', 2) VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000) ('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000) + power.d1004 USING power.meters TAGS('California.LosAngeles', 3) VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000)""", req_id=4) +print("inserted row count:", cursor.rowcount) + +# query data +cursor.execute("SELECT * FROM power.meters LIMIT 3", req_id=5) +# get total rows +print("queried row count:", cursor.rowcount) +# get column names from cursor +column_names = [meta[0] for meta in cursor.description] +# get rows +data = cursor.fetchall() +print(column_names) +for row in data: + print(row) + +# output: +# inserted row count: 8 +# queried row count: 3 +# ['ts', 'current', 'voltage', 'phase', 'location', 'groupid'] +# [datetime.datetime(2018, 10, 3, 14, 38, 5, 500000, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), '+08:00')), 11.8, 221, 0.28, 'california.losangeles', 2] +# [datetime.datetime(2018, 10, 3, 14, 38, 16, 600000, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), '+08:00')), 13.4, 223, 0.29, 'california.losangeles', 2] +# [datetime.datetime(2018, 10, 3, 14, 38, 5, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), '+08:00')), 10.8, 223, 0.29, 'california.losangeles', 3] +# ANCHOR_END: basic diff --git a/docs/examples/python/connect_websocket_examples.py b/docs/examples/python/connect_websocket_examples.py new file mode 100644 index 0000000000000000000000000000000000000000..29452bbf9d32b2e630575ef4f51fd2d10b59495a --- /dev/null +++ b/docs/examples/python/connect_websocket_examples.py @@ -0,0 +1,29 @@ +# ANCHOR: connect +import taosws + +conn = taosws.connect("taosws://root:taosdata@localhost:6041") +# ANCHOR_END: connect + +# ANCHOR: basic +conn.execute("drop database if exists connwspy") +conn.execute("create database if not exists connwspy wal_retention_period 3600") +conn.execute("use connwspy") +conn.execute("create table if not exists stb (ts timestamp, c1 int) tags (t1 int)") +conn.execute("create table if not exists tb1 using stb tags (1)") +conn.execute("insert into tb1 values (now, 1)") +conn.execute("insert into tb1 values (now, 2)") +conn.execute("insert into tb1 values (now, 3)") + +r = conn.execute("select * from stb") +result = conn.query("select * from stb") +num_of_fields = result.field_count +print(num_of_fields) + +for row in result: + print(row) + +# output: +# 3 +# ('2023-02-28 15:56:13.329 +08:00', 1, 1) +# ('2023-02-28 15:56:13.333 +08:00', 2, 1) +# ('2023-02-28 15:56:13.337 +08:00', 3, 1) diff --git a/docs/examples/python/connect_websocket_with_req_id_examples.py b/docs/examples/python/connect_websocket_with_req_id_examples.py new file mode 100644 index 0000000000000000000000000000000000000000..f5f76c8446649e8b9b77b754d45eca0cb5d5a210 --- /dev/null +++ b/docs/examples/python/connect_websocket_with_req_id_examples.py @@ -0,0 +1,29 @@ +# ANCHOR: connect +import taosws + +conn = taosws.connect("taosws://root:taosdata@localhost:6041") +# ANCHOR_END: connect + +# ANCHOR: basic +conn.execute("drop database if exists connwspy", req_id=1) +conn.execute("create database if not exists connwspy", req_id=2) +conn.execute("use connwspy", req_id=3) +conn.execute("create table if not exists stb (ts timestamp, c1 int) tags (t1 int)", req_id=4) +conn.execute("create table if not exists tb1 using stb tags (1)", req_id=5) +conn.execute("insert into tb1 values (now, 1)", req_id=6) +conn.execute("insert into tb1 values (now, 2)", req_id=7) +conn.execute("insert into tb1 values (now, 3)", req_id=8) + +r = conn.execute("select * from stb", req_id=9) +result = conn.query("select * from stb", req_id=10) +num_of_fields = result.field_count +print(num_of_fields) + +for row in result: + print(row) + +# output: +# 3 +# ('2023-02-28 15:56:13.329 +08:00', 1, 1) +# ('2023-02-28 15:56:13.333 +08:00', 2, 1) +# ('2023-02-28 15:56:13.337 +08:00', 3, 1) diff --git a/docs/examples/python/connection_usage_native_reference_with_req_id.py b/docs/examples/python/connection_usage_native_reference_with_req_id.py new file mode 100644 index 0000000000000000000000000000000000000000..24d0914ad54eb9545ab56468230201f3e2bd3484 --- /dev/null +++ b/docs/examples/python/connection_usage_native_reference_with_req_id.py @@ -0,0 +1,45 @@ +import taos + +# ANCHOR: insert +conn = taos.connect() +# Execute a sql, ignore the result set, just get affected rows. It's useful for DDL and DML statement. +conn.execute("DROP DATABASE IF EXISTS test", req_id=1) +conn.execute("CREATE DATABASE test", req_id=2) +# change database. same as execute "USE db" +conn.select_db("test") +conn.execute("CREATE STABLE weather(ts TIMESTAMP, temperature FLOAT) TAGS (location INT)", req_id=3) +affected_row = conn.execute("INSERT INTO t1 USING weather TAGS(1) VALUES (now, 23.5) (now+1m, 23.5) (now+2m, 24.4)", req_id=4) +print("affected_row", affected_row) +# output: +# affected_row 3 +# ANCHOR_END: insert + +# ANCHOR: query +# Execute a sql and get its result set. It's useful for SELECT statement +result = conn.query("SELECT * from weather", req_id=5) + +# Get fields from result +fields = result.fields +for field in fields: + print(field) # {name: ts, type: 9, bytes: 8} + +# output: +# {name: ts, type: 9, bytes: 8} +# {name: temperature, type: 6, bytes: 4} +# {name: location, type: 4, bytes: 4} + +# Get data from result as list of tuple +data = result.fetch_all() +print(data) +# output: +# [(datetime.datetime(2022, 4, 27, 9, 4, 25, 367000), 23.5, 1), (datetime.datetime(2022, 4, 27, 9, 5, 25, 367000), 23.5, 1), (datetime.datetime(2022, 4, 27, 9, 6, 25, 367000), 24.399999618530273, 1)] + +# Or get data from result as a list of dict +# map_data = result.fetch_all_into_dict() +# print(map_data) +# output: +# [{'ts': datetime.datetime(2022, 4, 27, 9, 1, 15, 343000), 'temperature': 23.5, 'location': 1}, {'ts': datetime.datetime(2022, 4, 27, 9, 2, 15, 343000), 'temperature': 23.5, 'location': 1}, {'ts': datetime.datetime(2022, 4, 27, 9, 3, 15, 343000), 'temperature': 24.399999618530273, 'location': 1}] +# ANCHOR_END: query + + +conn.close() \ No newline at end of file diff --git a/docs/examples/python/cursor_usage_native_reference_with_req_id.py b/docs/examples/python/cursor_usage_native_reference_with_req_id.py new file mode 100644 index 0000000000000000000000000000000000000000..15207ee6bc97fdb00918b98439fff785770f1334 --- /dev/null +++ b/docs/examples/python/cursor_usage_native_reference_with_req_id.py @@ -0,0 +1,32 @@ +import taos + +conn = taos.connect() +cursor = conn.cursor() + +cursor.execute("DROP DATABASE IF EXISTS test", req_id=1) +cursor.execute("CREATE DATABASE test", req_id=2) +cursor.execute("USE test", req_id=3) +cursor.execute("CREATE STABLE weather(ts TIMESTAMP, temperature FLOAT) TAGS (location INT)", req_id=4) + +for i in range(1000): + location = str(i % 10) + tb = "t" + location + cursor.execute(f"INSERT INTO {tb} USING weather TAGS({location}) VALUES (now+{i}a, 23.5) (now+{i + 1}a, 23.5)", req_id=5+i) + +cursor.execute("SELECT count(*) FROM weather", req_id=1005) +data = cursor.fetchall() +print("count:", data[0][0]) +cursor.execute("SELECT tbname, * FROM weather LIMIT 2", req_id=1006) +col_names = [meta[0] for meta in cursor.description] +print(col_names) +rows = cursor.fetchall() +print(rows) + +cursor.close() +conn.close() + +# output: +# count: 2000 +# ['tbname', 'ts', 'temperature', 'location'] +# row_count: -1 +# [('t0', datetime.datetime(2022, 4, 27, 14, 54, 24, 392000), 23.5, 0), ('t0', datetime.datetime(2022, 4, 27, 14, 54, 24, 393000), 23.5, 0)] diff --git a/docs/examples/python/kafka_example.py b/docs/examples/python/kafka_example.py deleted file mode 100644 index a89287d372d505225e2d679e7f205a3857014533..0000000000000000000000000000000000000000 --- a/docs/examples/python/kafka_example.py +++ /dev/null @@ -1,242 +0,0 @@ -#! encoding = utf-8 -import json -import time -from json import JSONDecodeError -from typing import Callable -import logging -from concurrent.futures import ThreadPoolExecutor, Future - -import taos -from kafka import KafkaConsumer -from kafka.consumer.fetcher import ConsumerRecord - - -class Consumer(object): - DEFAULT_CONFIGS = { - 'kafka_brokers': 'localhost:9092', - 'kafka_topic': 'python_kafka', - 'kafka_group_id': 'taos', - 'taos_host': 'localhost', - 'taos_user': 'root', - 'taos_password': 'taosdata', - 'taos_database': 'power', - 'taos_port': 6030, - 'timezone': None, - 'clean_after_testing': False, - 'bath_consume': True, - 'batch_size': 1000, - 'async_model': True, - 'workers': 10, - 'testing': False - } - - LOCATIONS = ['California.SanFrancisco', 'California.LosAngles', 'California.SanDiego', 'California.SanJose', - 'California.PaloAlto', 'California.Campbell', 'California.MountainView', 'California.Sunnyvale', - 'California.SantaClara', 'California.Cupertino'] - - CREATE_DATABASE_SQL = 'create database if not exists {} keep 365 duration 10 buffer 16 wal_level 1' - USE_DATABASE_SQL = 'use {}' - DROP_TABLE_SQL = 'drop table if exists meters' - DROP_DATABASE_SQL = 'drop database if exists {}' - CREATE_STABLE_SQL = 'create stable meters (ts timestamp, current float, voltage int, phase float) ' \ - 'tags (location binary(64), groupId int)' - CREATE_TABLE_SQL = 'create table if not exists {} using meters tags (\'{}\', {})' - INSERT_SQL_HEADER = "insert into " - INSERT_PART_SQL = 'power.{} values (\'{}\', {}, {}, {})' - - def __init__(self, **configs): - self.config: dict = self.DEFAULT_CONFIGS - self.config.update(configs) - if not self.config.get('testing'): - self.consumer = KafkaConsumer( - self.config.get('kafka_topic'), # topic - bootstrap_servers=self.config.get('kafka_brokers'), - group_id=self.config.get('kafka_group_id'), - ) - self.taos = taos.connect( - host=self.config.get('taos_host'), - user=self.config.get('taos_user'), - password=self.config.get('taos_password'), - port=self.config.get('taos_port'), - timezone=self.config.get('timezone'), - ) - if self.config.get('async_model'): - self.pool = ThreadPoolExecutor(max_workers=self.config.get('workers')) - self.tasks = [] - # tags and table mapping # key: {location}_{groupId} value: - self.tag_table_mapping = {} - i = 0 - for location in self.LOCATIONS: - for j in range(1, 11): - table_name = 'd{}'.format(i) - self._cache_table(location=location, group_id=j, table_name=table_name) - i += 1 - - def init_env(self): - # create database and table - self.taos.execute(self.DROP_DATABASE_SQL.format(self.config.get('taos_database'))) - self.taos.execute(self.CREATE_DATABASE_SQL.format(self.config.get('taos_database'))) - self.taos.execute(self.USE_DATABASE_SQL.format(self.config.get('taos_database'))) - self.taos.execute(self.DROP_TABLE_SQL) - self.taos.execute(self.CREATE_STABLE_SQL) - for tags, table_name in self.tag_table_mapping.items(): - location, group_id = _get_location_and_group(tags) - self.taos.execute(self.CREATE_TABLE_SQL.format(table_name, location, group_id)) - - def consume(self): - logging.warning('## start consumer topic-[%s]', self.config.get('kafka_topic')) - try: - if self.config.get('bath_consume'): - self._run_batch(self._to_taos_batch) - else: - self._run(self._to_taos) - except KeyboardInterrupt: - logging.warning("## caught keyboard interrupt, stopping") - finally: - self.stop() - - def stop(self): - # close consumer - if self.consumer is not None: - self.consumer.commit() - self.consumer.close() - - # multi thread - if self.config.get('async_model'): - for task in self.tasks: - while not task.done(): - pass - if self.pool is not None: - self.pool.shutdown() - - # clean data - if self.config.get('clean_after_testing'): - self.taos.execute(self.DROP_TABLE_SQL) - self.taos.execute(self.DROP_DATABASE_SQL.format(self.config.get('taos_database'))) - # close taos - if self.taos is not None: - self.taos.close() - - def _run(self, f): - for message in self.consumer: - if self.config.get('async_model'): - self.pool.submit(f(message)) - else: - f(message) - - def _run_batch(self, f): - while True: - messages = self.consumer.poll(timeout_ms=500, max_records=self.config.get('batch_size')) - if messages: - if self.config.get('async_model'): - self.pool.submit(f, messages.values()) - else: - f(list(messages.values())) - if not messages: - time.sleep(0.1) - - def _to_taos(self, message: ConsumerRecord) -> bool: - sql = self.INSERT_SQL_HEADER + self._build_sql(message.value) - if len(sql) == 0: # decode error, skip - return True - logging.info('## insert sql %s', sql) - return self.taos.execute(sql=sql) == 1 - - def _to_taos_batch(self, messages): - sql = self._build_sql_batch(messages=messages) - if len(sql) == 0: # decode error, skip - return - self.taos.execute(sql=sql) - - def _build_sql(self, msg_value: str) -> str: - try: - data = json.loads(msg_value) - except JSONDecodeError as e: - logging.error('## decode message [%s] error ', msg_value, e) - return '' - location = data.get('location') - group_id = data.get('groupId') - ts = data.get('ts') - current = data.get('current') - voltage = data.get('voltage') - phase = data.get('phase') - - table_name = self._get_table_name(location=location, group_id=group_id) - return self.INSERT_PART_SQL.format(table_name, ts, current, voltage, phase) - - def _build_sql_batch(self, messages) -> str: - sql_list = [] - for partition_messages in messages: - for message in partition_messages: - sql_list.append(self._build_sql(message.value)) - - return self.INSERT_SQL_HEADER + ' '.join(sql_list) - - def _cache_table(self, location: str, group_id: int, table_name: str): - self.tag_table_mapping[_tag_table_mapping_key(location=location, group_id=group_id)] = table_name - - def _get_table_name(self, location: str, group_id: int) -> str: - return self.tag_table_mapping.get(_tag_table_mapping_key(location=location, group_id=group_id)) - - -def _tag_table_mapping_key(location: str, group_id: int): - return '{}_{}'.format(location, group_id) - - -def _get_location_and_group(key: str) -> (str, int): - fields = key.split('_') - return fields[0], fields[1] - - -def test_to_taos(consumer: Consumer): - msg = { - 'location': 'California.SanFrancisco', - 'groupId': 1, - 'ts': '2022-12-06 15:13:38.643', - 'current': 3.41, - 'voltage': 105, - 'phase': 0.02027, - } - record = ConsumerRecord(checksum=None, headers=None, offset=1, key=None, value=json.dumps(msg), partition=1, - topic='test', serialized_key_size=None, serialized_header_size=None, - serialized_value_size=None, timestamp=time.time(), timestamp_type=None) - assert consumer._to_taos(message=record) - - -def test_to_taos_batch(consumer: Consumer): - records = [ - [ - ConsumerRecord(checksum=None, headers=None, offset=1, key=None, - value=json.dumps({'location': 'California.SanFrancisco', - 'groupId': 1, - 'ts': '2022-12-06 15:13:38.643', - 'current': 3.41, - 'voltage': 105, - 'phase': 0.02027, }), - partition=1, topic='test', serialized_key_size=None, serialized_header_size=None, - serialized_value_size=None, timestamp=time.time(), timestamp_type=None), - ConsumerRecord(checksum=None, headers=None, offset=1, key=None, - value=json.dumps({'location': 'California.LosAngles', - 'groupId': 2, - 'ts': '2022-12-06 15:13:39.643', - 'current': 3.41, - 'voltage': 102, - 'phase': 0.02027, }), - partition=1, topic='test', serialized_key_size=None, serialized_header_size=None, - serialized_value_size=None, timestamp=time.time(), timestamp_type=None), - ] - ] - - consumer._to_taos_batch(messages=records) - - -if __name__ == '__main__': - consumer = Consumer(async_model=True, testing=True) - # init env - consumer.init_env() - # consumer.consume() - # test build sql - # test build sql batch - test_to_taos(consumer) - test_to_taos_batch(consumer) - \ No newline at end of file diff --git a/docs/examples/python/kafka_example_common.py b/docs/examples/python/kafka_example_common.py new file mode 100644 index 0000000000000000000000000000000000000000..1c735abfc080f63f5bc4126a7f44474dbf5d157c --- /dev/null +++ b/docs/examples/python/kafka_example_common.py @@ -0,0 +1,65 @@ +#! encoding = utf-8 +import taos + +LOCATIONS = ['California.SanFrancisco', 'California.LosAngles', 'California.SanDiego', 'California.SanJose', + 'California.PaloAlto', 'California.Campbell', 'California.MountainView', 'California.Sunnyvale', + 'California.SantaClara', 'California.Cupertino'] + +CREATE_DATABASE_SQL = 'create database if not exists {} keep 365 duration 10 buffer 16 wal_level 1 wal_retention_period 3600' +USE_DATABASE_SQL = 'use {}' +DROP_TABLE_SQL = 'drop table if exists meters' +DROP_DATABASE_SQL = 'drop database if exists {}' +CREATE_STABLE_SQL = 'create stable meters (ts timestamp, current float, voltage int, phase float) tags ' \ + '(location binary(64), groupId int)' +CREATE_TABLE_SQL = 'create table if not exists {} using meters tags (\'{}\', {})' + + +def create_database_and_tables(host, port, user, password, db, table_count): + tags_tables = _init_tags_table_names(table_count=table_count) + conn = taos.connect(host=host, port=port, user=user, password=password) + + conn.execute(DROP_DATABASE_SQL.format(db)) + conn.execute(CREATE_DATABASE_SQL.format(db)) + conn.execute(USE_DATABASE_SQL.format(db)) + conn.execute(DROP_TABLE_SQL) + conn.execute(CREATE_STABLE_SQL) + for tags in tags_tables: + location, group_id = _get_location_and_group(tags) + tables = tags_tables[tags] + for table_name in tables: + conn.execute(CREATE_TABLE_SQL.format(table_name, location, group_id)) + conn.close() + + +def clean(host, port, user, password, db): + conn = taos.connect(host=host, port=port, user=user, password=password) + conn.execute(DROP_DATABASE_SQL.format(db)) + conn.close() + + +def _init_tags_table_names(table_count): + tags_table_names = {} + group_id = 0 + for i in range(table_count): + table_name = 'd{}'.format(i) + location_idx = i % len(LOCATIONS) + location = LOCATIONS[location_idx] + if location_idx == 0: + group_id += 1 + if group_id > 10: + group_id -= 10 + key = _tag_table_mapping_key(location=location, group_id=group_id) + if key not in tags_table_names: + tags_table_names[key] = [] + tags_table_names[key].append(table_name) + + return tags_table_names + + +def _tag_table_mapping_key(location, group_id): + return '{}_{}'.format(location, group_id) + + +def _get_location_and_group(key): + fields = key.split('_') + return fields[0], fields[1] diff --git a/docs/examples/python/kafka_example_consumer.py b/docs/examples/python/kafka_example_consumer.py new file mode 100644 index 0000000000000000000000000000000000000000..e2d5cf535b3953a3c0ecec9e25cc615948162633 --- /dev/null +++ b/docs/examples/python/kafka_example_consumer.py @@ -0,0 +1,231 @@ +#! encoding = utf-8 +import json +import logging +import time +from concurrent.futures import ThreadPoolExecutor, Future +from json import JSONDecodeError +from typing import Callable + +import taos +from kafka import KafkaConsumer +from kafka.consumer.fetcher import ConsumerRecord + +import kafka_example_common as common + + +class Consumer(object): + DEFAULT_CONFIGS = { + 'kafka_brokers': 'localhost:9092', # kafka broker + 'kafka_topic': 'tdengine_kafka_practices', + 'kafka_group_id': 'taos', + 'taos_host': 'localhost', # TDengine host + 'taos_port': 6030, # TDengine port + 'taos_user': 'root', # TDengine user name + 'taos_password': 'taosdata', # TDengine password + 'taos_database': 'power', # TDengine database + 'message_type': 'json', # message format, 'json' or 'line' + 'clean_after_testing': False, # if drop database after testing + 'max_poll': 1000, # poll size for batch mode + 'workers': 10, # thread count for multi-threading + 'testing': False + } + + INSERT_SQL_HEADER = "insert into " + INSERT_PART_SQL = '{} values (\'{}\', {}, {}, {})' + + def __init__(self, **configs): + self.config = self.DEFAULT_CONFIGS + self.config.update(configs) + + self.consumer = None + if not self.config.get('testing'): + self.consumer = KafkaConsumer( + self.config.get('kafka_topic'), + bootstrap_servers=self.config.get('kafka_brokers'), + group_id=self.config.get('kafka_group_id'), + ) + + self.conns = taos.connect( + host=self.config.get('taos_host'), + port=self.config.get('taos_port'), + user=self.config.get('taos_user'), + password=self.config.get('taos_password'), + db=self.config.get('taos_database'), + ) + if self.config.get('workers') > 1: + self.pool = ThreadPoolExecutor(max_workers=self.config.get('workers')) + self.tasks = [] + # tags and table mapping # key: {location}_{groupId} value: + + def consume(self): + """ + + consume data from kafka and deal. Base on `message_type`, `bath_consume`, `insert_by_table`, + there are several deal function. + :return: + """ + self.conns.execute(common.USE_DATABASE_SQL.format(self.config.get('taos_database'))) + try: + if self.config.get('message_type') == 'line': # line + self._run(self._line_to_taos) + if self.config.get('message_type') == 'json': # json + self._run(self._json_to_taos) + except KeyboardInterrupt: + logging.warning("## caught keyboard interrupt, stopping") + finally: + self.stop() + + def stop(self): + """ + + stop consuming + :return: + """ + # close consumer + if self.consumer is not None: + self.consumer.commit() + self.consumer.close() + + # multi thread + if self.config.get('workers') > 1: + if self.pool is not None: + self.pool.shutdown() + for task in self.tasks: + while not task.done(): + time.sleep(0.01) + + # clean data + if self.config.get('clean_after_testing'): + self.conns.execute(common.DROP_TABLE_SQL) + self.conns.execute(common.DROP_DATABASE_SQL.format(self.config.get('taos_database'))) + # close taos + if self.conns is not None: + self.conns.close() + + def _run(self, f): + """ + + run in batch consuming mode + :param f: + :return: + """ + i = 0 # just for test. + while True: + messages = self.consumer.poll(timeout_ms=100, max_records=self.config.get('max_poll')) + if messages: + if self.config.get('workers') > 1: + self.pool.submit(f, messages.values()) + else: + f(list(messages.values())) + if not messages: + i += 1 # just for test. + time.sleep(0.1) + if i > 3: # just for test. + logging.warning('## test over.') # just for test. + return # just for test. + + def _json_to_taos(self, messages): + """ + + convert a batch of json data to sql, and insert into TDengine + :param messages: + :return: + """ + sql = self._build_sql_from_json(messages=messages) + self.conns.execute(sql=sql) + + def _line_to_taos(self, messages): + """ + + convert a batch of lines data to sql, and insert into TDengine + :param messages: + :return: + """ + lines = [] + for partition_messages in messages: + for message in partition_messages: + lines.append(message.value.decode()) + sql = self.INSERT_SQL_HEADER + ' '.join(lines) + self.conns.execute(sql=sql) + + def _build_single_sql_from_json(self, msg_value): + try: + data = json.loads(msg_value) + except JSONDecodeError as e: + logging.error('## decode message [%s] error ', msg_value, e) + return '' + # location = data.get('location') + # group_id = data.get('groupId') + ts = data.get('ts') + current = data.get('current') + voltage = data.get('voltage') + phase = data.get('phase') + table_name = data.get('table_name') + + return self.INSERT_PART_SQL.format(table_name, ts, current, voltage, phase) + + def _build_sql_from_json(self, messages): + sql_list = [] + for partition_messages in messages: + for message in partition_messages: + sql_list.append(self._build_single_sql_from_json(message.value)) + return self.INSERT_SQL_HEADER + ' '.join(sql_list) + + +def test_json_to_taos(consumer: Consumer): + records = [ + [ + ConsumerRecord(checksum=None, headers=None, offset=1, key=None, + value=json.dumps({'table_name': 'd0', + 'ts': '2022-12-06 15:13:38.643', + 'current': 3.41, + 'voltage': 105, + 'phase': 0.02027, }), + partition=1, topic='test', serialized_key_size=None, serialized_header_size=None, + serialized_value_size=None, timestamp=time.time(), timestamp_type=None), + ConsumerRecord(checksum=None, headers=None, offset=1, key=None, + value=json.dumps({'table_name': 'd1', + 'ts': '2022-12-06 15:13:39.643', + 'current': 3.41, + 'voltage': 102, + 'phase': 0.02027, }), + partition=1, topic='test', serialized_key_size=None, serialized_header_size=None, + serialized_value_size=None, timestamp=time.time(), timestamp_type=None), + ] + ] + + consumer._json_to_taos(messages=records) + + +def test_line_to_taos(consumer: Consumer): + records = [ + [ + ConsumerRecord(checksum=None, headers=None, offset=1, key=None, + value="d0 values('2023-01-01 00:00:00.001', 3.49, 109, 0.02737)".encode('utf-8'), + partition=1, topic='test', serialized_key_size=None, serialized_header_size=None, + serialized_value_size=None, timestamp=time.time(), timestamp_type=None), + ConsumerRecord(checksum=None, headers=None, offset=1, key=None, + value="d1 values('2023-01-01 00:00:00.002', 6.19, 112, 0.09171)".encode('utf-8'), + partition=1, topic='test', serialized_key_size=None, serialized_header_size=None, + serialized_value_size=None, timestamp=time.time(), timestamp_type=None), + ] + ] + consumer._line_to_taos(messages=records) + + +def consume(kafka_brokers, kafka_topic, kafka_group_id, taos_host, taos_port, taos_user, + taos_password, taos_database, message_type, max_poll, workers): + c = Consumer(kafka_brokers=kafka_brokers, kafka_topic=kafka_topic, kafka_group_id=kafka_group_id, + taos_host=taos_host, taos_port=taos_port, taos_user=taos_user, taos_password=taos_password, + taos_database=taos_database, message_type=message_type, max_poll=max_poll, workers=workers) + c.consume() + + +if __name__ == '__main__': + consumer = Consumer(testing=True) + common.create_database_and_tables(host='localhost', port=6030, user='root', password='taosdata', db='py_kafka_test', + table_count=10) + consumer.conns.execute(common.USE_DATABASE_SQL.format('py_kafka_test')) + test_json_to_taos(consumer) + test_line_to_taos(consumer) + common.clean(host='localhost', port=6030, user='root', password='taosdata', db='py_kafka_test') diff --git a/docs/examples/python/kafka_example_perform.py b/docs/examples/python/kafka_example_perform.py new file mode 100644 index 0000000000000000000000000000000000000000..23ae4b48c8fc8139b85cd41b041953e8f55f12b4 --- /dev/null +++ b/docs/examples/python/kafka_example_perform.py @@ -0,0 +1,103 @@ +#! encoding=utf-8 + +import argparse +import logging +import multiprocessing +import time +from multiprocessing import pool + +import kafka_example_common as common +import kafka_example_consumer as consumer +import kafka_example_producer as producer + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-kafka-broker', type=str, default='localhost:9092', + help='kafka borker host. default is `localhost:9200`') + parser.add_argument('-kafka-topic', type=str, default='tdengine-kafka-practices', + help='kafka topic. default is `tdengine-kafka-practices`') + parser.add_argument('-kafka-group', type=str, default='kafka_practices', + help='kafka consumer group. default is `kafka_practices`') + parser.add_argument('-taos-host', type=str, default='localhost', + help='TDengine host. default is `localhost`') + parser.add_argument('-taos-port', type=int, default=6030, help='TDengine port. default is 6030') + parser.add_argument('-taos-user', type=str, default='root', help='TDengine username, default is `root`') + parser.add_argument('-taos-password', type=str, default='taosdata', help='TDengine password, default is `taosdata`') + parser.add_argument('-taos-db', type=str, default='tdengine_kafka_practices', + help='TDengine db name, default is `tdengine_kafka_practices`') + parser.add_argument('-table-count', type=int, default=100, help='TDengine sub-table count, default is 100') + parser.add_argument('-table-items', type=int, default=1000, help='items in per sub-tables, default is 1000') + parser.add_argument('-message-type', type=str, default='line', + help='kafka message type. `line` or `json`. default is `line`') + parser.add_argument('-max-poll', type=int, default=1000, help='max poll for kafka consumer') + parser.add_argument('-threads', type=int, default=10, help='thread count for deal message') + parser.add_argument('-processes', type=int, default=1, help='process count') + + args = parser.parse_args() + total = args.table_count * args.table_items + + logging.warning("## start to prepare testing data...") + prepare_data_start = time.time() + producer.produce_total(100, args.kafka_broker, args.kafka_topic, args.message_type, total, args.table_count) + prepare_data_end = time.time() + logging.warning("## prepare testing data finished! spend-[%s]", prepare_data_end - prepare_data_start) + + logging.warning("## start to create database and tables ...") + create_db_start = time.time() + # create database and table + common.create_database_and_tables(host=args.taos_host, port=args.taos_port, user=args.taos_user, + password=args.taos_password, db=args.taos_db, table_count=args.table_count) + create_db_end = time.time() + logging.warning("## create database and tables finished! spend [%s]", create_db_end - create_db_start) + + processes = args.processes + + logging.warning("## start to consume data and insert into TDengine...") + consume_start = time.time() + if processes > 1: # multiprocess + multiprocessing.set_start_method("spawn") + pool = pool.Pool(processes) + + consume_start = time.time() + for _ in range(processes): + pool.apply_async(func=consumer.consume, args=( + args.kafka_broker, args.kafka_topic, args.kafka_group, args.taos_host, args.taos_port, args.taos_user, + args.taos_password, args.taos_db, args.message_type, args.max_poll, args.threads)) + pool.close() + pool.join() + else: + consume_start = time.time() + consumer.consume(kafka_brokers=args.kafka_broker, kafka_topic=args.kafka_topic, kafka_group_id=args.kafka_group, + taos_host=args.taos_host, taos_port=args.taos_port, taos_user=args.taos_user, + taos_password=args.taos_password, taos_database=args.taos_db, message_type=args.message_type, + max_poll=args.max_poll, workers=args.threads) + consume_end = time.time() + logging.warning("## consume data and insert into TDengine over! spend-[%s]", consume_end - consume_start) + + # print report + logging.warning( + "\n#######################\n" + " Prepare data \n" + "#######################\n" + "# data_type # %s \n" + "# total # %s \n" + "# spend # %s s\n" + "#######################\n" + " Create database \n" + "#######################\n" + "# stable # 1 \n" + "# sub-table # 100 \n" + "# spend # %s s \n" + "#######################\n" + " Consume \n" + "#######################\n" + "# data_type # %s \n" + "# threads # %s \n" + "# processes # %s \n" + "# total_count # %s \n" + "# spend # %s s\n" + "# per_second # %s \n" + "#######################\n", + args.message_type, total, prepare_data_end - prepare_data_start, create_db_end - create_db_start, + args.message_type, args.threads, processes, total, consume_end - consume_start, + total / (consume_end - consume_start)) diff --git a/docs/examples/python/kafka_example_producer.py b/docs/examples/python/kafka_example_producer.py new file mode 100644 index 0000000000000000000000000000000000000000..51468c7e37ab3400bece69fa58e126a789ef9860 --- /dev/null +++ b/docs/examples/python/kafka_example_producer.py @@ -0,0 +1,97 @@ +#! encoding = utf-8 +import json +import random +import threading +from concurrent.futures import ThreadPoolExecutor, Future +from datetime import datetime + +from kafka import KafkaProducer + +locations = ['California.SanFrancisco', 'California.LosAngles', 'California.SanDiego', 'California.SanJose', + 'California.PaloAlto', 'California.Campbell', 'California.MountainView', 'California.Sunnyvale', + 'California.SantaClara', 'California.Cupertino'] + +producers: list[KafkaProducer] = [] + +lock = threading.Lock() +start = 1640966400 + + +def produce_total(workers, broker, topic, message_type, total, table_count): + if len(producers) == 0: + lock.acquire() + if len(producers) == 0: + _init_kafka_producers(broker=broker, count=10) + lock.release() + pool = ThreadPoolExecutor(max_workers=workers) + futures = [] + for _ in range(0, workers): + futures.append(pool.submit(_produce_total, topic, message_type, int(total / workers), table_count)) + pool.shutdown() + for f in futures: + f.result() + _close_kafka_producers() + + +def _produce_total(topic, message_type, total, table_count): + producer = _get_kafka_producer() + for _ in range(total): + message = _get_fake_date(message_type=message_type, table_count=table_count) + producer.send(topic=topic, value=message.encode(encoding='utf-8')) + + +def _init_kafka_producers(broker, count): + for _ in range(count): + p = KafkaProducer(bootstrap_servers=broker, batch_size=64 * 1024, linger_ms=300, acks=0) + producers.append(p) + + +def _close_kafka_producers(): + for p in producers: + p.close() + + +def _get_kafka_producer(): + return producers[random.randint(0, len(producers) - 1)] + + +def _get_fake_date(table_count, message_type='json'): + if message_type == 'json': + return _get_json_message(table_count=table_count) + if message_type == 'line': + return _get_line_message(table_count=table_count) + return '' + + +def _get_json_message(table_count): + return json.dumps({ + 'ts': _get_timestamp(), + 'current': random.randint(0, 1000) / 100, + 'voltage': random.randint(105, 115), + 'phase': random.randint(0, 32000) / 100000, + 'location': random.choice(locations), + 'groupId': random.randint(1, 10), + 'table_name': _random_table_name(table_count) + }) + + +def _get_line_message(table_count): + return "{} values('{}', {}, {}, {})".format( + _random_table_name(table_count), # table + _get_timestamp(), # ts + random.randint(0, 1000) / 100, # current + random.randint(105, 115), # voltage + random.randint(0, 32000) / 100000, # phase + ) + + +def _random_table_name(table_count): + return 'd{}'.format(random.randint(0, table_count - 1)) + + +def _get_timestamp(): + global start + lock.acquire(blocking=True) + start += 0.001 + lock.release() + return datetime.fromtimestamp(start).strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] diff --git a/docs/examples/python/mockdatasource.py b/docs/examples/python/mockdatasource.py index 15a7d2ff8c5b1febefcf4f81f481220947257b50..9c702936ea6f1bdff3f604d376fd1925b4dc118e 100644 --- a/docs/examples/python/mockdatasource.py +++ b/docs/examples/python/mockdatasource.py @@ -59,4 +59,3 @@ if __name__ == '__main__': datasource = MockDataSource('t', 10, False) for data in datasource: print(data) - \ No newline at end of file diff --git a/docs/examples/python/native_insert_example.py b/docs/examples/python/native_insert_example.py index 94fd00a6e9d1dcd2119693c4b5c862d36c219a3d..cdde7d23d24d12e11c67b6c6acc0e0b089fb5335 100644 --- a/docs/examples/python/native_insert_example.py +++ b/docs/examples/python/native_insert_example.py @@ -25,10 +25,10 @@ def create_stable(conn: taos.TaosConnection): # The generated SQL is: -# INSERT INTO d1001 USING meters TAGS(California.SanFrancisco, 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000) -# d1002 USING meters TAGS(California.SanFrancisco, 3) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000) -# d1003 USING meters TAGS(California.LosAngeles, 2) VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000) ('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000) -# d1004 USING meters TAGS(California.LosAngeles, 3) VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000) +# INSERT INTO d1001 USING meters TAGS('California.SanFrancisco', 2) VALUES ('2018-10-03 14:38:05.000', 10.30000, 219, 0.31000) ('2018-10-03 14:38:15.000', 12.60000, 218, 0.33000) ('2018-10-03 14:38:16.800', 12.30000, 221, 0.31000) +# d1002 USING meters TAGS('California.SanFrancisco', 3) VALUES ('2018-10-03 14:38:16.650', 10.30000, 218, 0.25000) +# d1003 USING meters TAGS('California.LosAngeles', 2) VALUES ('2018-10-03 14:38:05.500', 11.80000, 221, 0.28000) ('2018-10-03 14:38:16.600', 13.40000, 223, 0.29000) +# d1004 USING meters TAGS('California.LosAngeles', 3) VALUES ('2018-10-03 14:38:05.000', 10.80000, 223, 0.29000) ('2018-10-03 14:38:06.500', 11.50000, 221, 0.35000) def get_sql(): global lines diff --git a/docs/examples/python/rest_client_with_req_id_example.py b/docs/examples/python/rest_client_with_req_id_example.py new file mode 100644 index 0000000000000000000000000000000000000000..918398e51eb8c5e33c6fed3b7e05afdbd1c66878 --- /dev/null +++ b/docs/examples/python/rest_client_with_req_id_example.py @@ -0,0 +1,9 @@ +from taosrest import RestClient + +client = RestClient("http://localhost:6041", user="root", password="taosdata") +res: dict = client.sql("SELECT ts, current FROM power.meters LIMIT 1", req_id=1) +print(res) + +# output: +# {'status': 'succ', 'head': ['ts', 'current'], 'column_meta': [['ts', 9, 8], ['current', 6, 4]], 'data': [[datetime.datetime(2018, 10, 3, 14, 38, 5, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), '+08:00')), 10.3]], 'rows': 1} + diff --git a/docs/examples/python/result_set_with_req_id_examples.py b/docs/examples/python/result_set_with_req_id_examples.py new file mode 100644 index 0000000000000000000000000000000000000000..90ae2f4f2671bf00669adc69270dc943a02c16aa --- /dev/null +++ b/docs/examples/python/result_set_with_req_id_examples.py @@ -0,0 +1,33 @@ +import taos + +conn = taos.connect() +conn.execute("DROP DATABASE IF EXISTS test", req_id=1) +conn.execute("CREATE DATABASE test", req_id=2) +conn.select_db("test") +conn.execute("CREATE STABLE weather(ts TIMESTAMP, temperature FLOAT) TAGS (location INT)", req_id=3) +# prepare data +for i in range(2000): + location = str(i % 10) + tb = "t" + location + conn.execute(f"INSERT INTO {tb} USING weather TAGS({location}) VALUES (now+{i}a, 23.5) (now+{i + 1}a, 23.5)", req_id=4+i) + +result: taos.TaosResult = conn.query("SELECT * FROM weather", req_id=2004) + +block_index = 0 +blocks: taos.TaosBlocks = result.blocks_iter() +for rows, length in blocks: + print("block ", block_index, " length", length) + print("first row in this block:", rows[0]) + block_index += 1 + +conn.close() + +# possible output: +# block 0 length 1200 +# first row in this block: (datetime.datetime(2022, 4, 27, 15, 14, 52, 46000), 23.5, 0) +# block 1 length 1200 +# first row in this block: (datetime.datetime(2022, 4, 27, 15, 14, 52, 76000), 23.5, 3) +# block 2 length 1200 +# first row in this block: (datetime.datetime(2022, 4, 27, 15, 14, 52, 99000), 23.5, 6) +# block 3 length 400 +# first row in this block: (datetime.datetime(2022, 4, 27, 15, 14, 52, 122000), 23.5, 9) diff --git a/docs/examples/python/sql_writer.py b/docs/examples/python/sql_writer.py index db51bb71744c89ed130370f611f655086de0ef74..3456981a7b9a174e38f8795ff7251ab3c675174b 100644 --- a/docs/examples/python/sql_writer.py +++ b/docs/examples/python/sql_writer.py @@ -109,4 +109,3 @@ if __name__ == '__main__': writer.execute_sql( "INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) " "VALUES ('2021-07-13 14:06:32.272', 10.2, 219, 0.32)") - \ No newline at end of file diff --git a/docs/examples/python/tmq_example.py b/docs/examples/python/tmq_example.py index 32778e9f25f4a8b58007f39d4aeac53c30fe6895..5b462fa1536d34a11824eed09310f1068735a7dc 100644 --- a/docs/examples/python/tmq_example.py +++ b/docs/examples/python/tmq_example.py @@ -6,7 +6,7 @@ def init_tmq_env(db, topic): conn = taos.connect() conn.execute("drop topic if exists {}".format(topic)) conn.execute("drop database if exists {}".format(db)) - conn.execute("create database if not exists {}".format(db)) + conn.execute("create database if not exists {} wal_retention_period 3600".format(db)) conn.select_db(db) conn.execute( "create stable if not exists stb1 (ts timestamp, c1 int, c2 float, c3 varchar(16)) tags(t1 int, t3 varchar(16))") @@ -52,4 +52,4 @@ if __name__ == '__main__': finally: consumer.unsubscribe() consumer.close() - cleanup("tmq_test", "tmq_test_topic") \ No newline at end of file + cleanup("tmq_test", "tmq_test_topic") diff --git a/docs/examples/python/tmq_websocket_example.py b/docs/examples/python/tmq_websocket_example.py new file mode 100644 index 0000000000000000000000000000000000000000..e1dcb0086a995c0c20a5d079ed6d8f4d18ea0356 --- /dev/null +++ b/docs/examples/python/tmq_websocket_example.py @@ -0,0 +1,31 @@ +#!/usr/bin/python3 +from taosws import Consumer + +conf = { + "td.connect.websocket.scheme": "ws", + "group.id": "0", +} +consumer = Consumer(conf) + +consumer.subscribe(["test"]) + +while True: + message = consumer.poll(timeout=1.0) + if message: + id = message.vgroup() + topic = message.topic() + database = message.database() + + for block in message: + nrows = block.nrows() + ncols = block.ncols() + for row in block: + print(row) + values = block.fetchall() + print(nrows, ncols) + + # consumer.commit(message) + else: + break + +consumer.close() diff --git a/docs/examples/rust/nativeexample/examples/subscribe_demo.rs b/docs/examples/rust/nativeexample/examples/subscribe_demo.rs index 7551ad46b139f70c3e966fc3bfaf8e6cb58b17f8..d54bb60e937d8a9756dafb00a754260f432c6777 100644 --- a/docs/examples/rust/nativeexample/examples/subscribe_demo.rs +++ b/docs/examples/rust/nativeexample/examples/subscribe_demo.rs @@ -45,7 +45,7 @@ async fn main() -> anyhow::Result<()> { taos.exec_many([ format!("DROP TOPIC IF EXISTS tmq_meters"), format!("DROP DATABASE IF EXISTS `{db}`"), - format!("CREATE DATABASE `{db}`"), + format!("CREATE DATABASE `{db}` WAL_RETENTION_PERIOD 3600"), format!("USE `{db}`"), // create super table format!("CREATE TABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) TAGS (`groupid` INT, `location` BINARY(24))"), diff --git a/docs/zh/04-concept/index.md b/docs/zh/04-concept/index.md index 2cba68edcd152f5059845b9e25342b3f335f3b8b..b389b8d1ce2597c44f8164c0edc0dedc53d79efe 100644 --- a/docs/zh/04-concept/index.md +++ b/docs/zh/04-concept/index.md @@ -149,7 +149,7 @@ TDengine 建议用数据采集点的名字(如上表中的 d1001)来做表 3. 子表一定属于一张超级表,但普通表不属于任何超级表 4. 普通表无法转为子表,子表也无法转为普通表。 -超级表与与基于超级表建立的子表之间的关系表现在: +超级表与基于超级表建立的子表之间的关系表现在: 1. 一张超级表包含有多张子表,这些子表具有相同的采集量 Schema,但带有不同的标签值。 2. 不能通过子表调整数据或标签的模式,对于超级表的数据模式修改立即对所有的子表生效。 diff --git a/docs/zh/05-get-started/03-package.md b/docs/zh/05-get-started/03-package.md index 781a65402c24d368b8f62bda825875f3cd5a6aac..bdf6a730d0b4b456ef1e689966935af173871394 100644 --- a/docs/zh/05-get-started/03-package.md +++ b/docs/zh/05-get-started/03-package.md @@ -10,7 +10,7 @@ import PkgListV3 from "/components/PkgListV3"; 您可以[用 Docker 立即体验](../../get-started/docker/) TDengine。如果您希望对 TDengine 贡献代码或对内部实现感兴趣,请参考我们的 [TDengine GitHub 主页](https://github.com/taosdata/TDengine) 下载源码构建和安装. -TDengine 完整的软件包包括服务端(taosd)、应用驱动(taosc)、用于与第三方系统对接并提供 RESTful 接口的 taosAdapter、命令行程序(CLI,taos)和一些工具软件。目前 taosdump、TDinsight 仅在 Linux 系统上安装和运行,后续将支持 Windows、macOS 等系统。TDengine 除了提供多种语言的连接器之外,还通过 [taosAdapter](../../reference/taosadapter/) 提供 [RESTful 接口](../../connector/rest-api/)。 +TDengine 完整的软件包包括服务端(taosd)、应用驱动(taosc)、用于与第三方系统对接并提供 RESTful 接口的 taosAdapter、命令行程序(CLI,taos)和一些工具软件。目前 TDinsight 仅在 Linux 系统上安装和运行,后续将支持 Windows、macOS 等系统。TDengine 除了提供多种语言的连接器之外,还通过 [taosAdapter](../../reference/taosadapter/) 提供 [RESTful 接口](../../connector/rest-api/)。 为方便使用,标准的服务端安装包包含了 taosd、taosAdapter、taosc、taos、taosdump、taosBenchmark、TDinsight 安装脚本和示例代码;如果您只需要用到服务端程序和客户端连接的 C/C++ 语言支持,也可以仅下载 Lite 版本的安装包。 @@ -178,7 +178,7 @@ Active: inactive (dead) ::: -## TDengine 命令行(CLI) +**TDengine 命令行(CLI)** 为便于检查 TDengine 的状态,执行数据库(Database)的各种即席(Ad Hoc)查询,TDengine 提供一命令行应用程序(以下简称为 TDengine CLI)taos。要进入 TDengine 命令行,您只要在终端执行 `taos` 即可。 @@ -186,9 +186,9 @@ Active: inactive (dead) -安装后,在 `C:\TDengine` 目录下,运行 `taosd.exe` 来启动 TDengine 服务进程。 +安装后,可以在拥有管理员权限的 cmd 窗口执行 `sc start taosd` 或在 `C:\TDengine` 目录下,运行 `taosd.exe` 来启动 TDengine 服务进程。 -## TDengine 命令行(CLI) +**TDengine 命令行(CLI)** 为便于检查 TDengine 的状态,执行数据库(Database)的各种即席(Ad Hoc)查询,TDengine 提供一命令行应用程序(以下简称为 TDengine CLI)taos。要进入 TDengine 命令行,您只要在终端执行 `taos` 即可。 @@ -196,24 +196,26 @@ Active: inactive (dead) -安装后,在应用程序目录下,双击 TDengine 图标来启动程序,也可以运行 `launchctl start com.tdengine.taosd` 来启动 TDengine 服务进程。 +安装后,在应用程序目录下,双击 TDengine 图标来启动程序,也可以运行 `sudo launchctl start com.tdengine.taosd` 来启动 TDengine 服务进程。 -如下 `launchctl` 命令可以帮助你管理 TDengine 服务: +如下 `launchctl` 命令用于管理 TDengine 服务: -- 启动服务进程:`launchctl start com.tdengine.taosd` +- 启动服务进程:`sudo launchctl start com.tdengine.taosd` -- 停止服务进程:`launchctl stop com.tdengine.taosd` +- 停止服务进程:`sudo launchctl stop com.tdengine.taosd` -- 查看服务状态:`launchctl list | grep taosd` +- 查看服务状态:`sudo launchctl list | grep taosd` :::info -- `launchctl` 命令不需要管理员权限,请不要在前面加 `sudo`。 -- `launchctl list | grep taosd` 指令返回的第一个内容是程序的 PID,若为 `-` 则说明 TDengine 服务未运行。 +- `launchctl` 命令管理`com.tdengine.taosd`需要管理员权限,务必在前面加 `sudo` 来增强安全性。 +- `sudo launchctl list | grep taosd` 指令返回的第一列是 `taosd` 程序的 PID,若为 `-` 则说明 TDengine 服务未运行。 +- 故障排查: +- 如果服务异常请查看系统日志 `launchd.log` 或者 `/var/log/taos` 目录下 `taosdlog` 日志获取更多信息。 ::: -## TDengine 命令行(CLI) +**TDengine 命令行(CLI)** 为便于检查 TDengine 的状态,执行数据库(Database)的各种即席(Ad Hoc)查询,TDengine 提供一命令行应用程序(以下简称为 TDengine CLI)taos。要进入 TDengine 命令行,您只要在 Windows 终端的 C:\TDengine 目录下,运行 taos.exe 来启动 TDengine 命令行。 diff --git a/docs/zh/05-get-started/index.md b/docs/zh/05-get-started/index.md index 832310aa7c677940c7e4ca13be5f31c2d98a64dc..16172277b5accef4e0e5c707d1bb7f09ace23446 100644 --- a/docs/zh/05-get-started/index.md +++ b/docs/zh/05-get-started/index.md @@ -4,6 +4,7 @@ description: '快速设置 TDengine 环境并体验其高效写入和查询' --- import xiaot from './xiaot.webp' +import xiaot_new from './xiaot-03.webp' import channel from './channel.webp' import official_account from './official-account.webp' @@ -18,30 +19,19 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ``` -## 学习 TDengine 知识地图 - -TDengine 知识地图中涵盖了 TDengine 的各种知识点,揭示了各概念实体之间的调用关系和数据流向。学习和了解 TDengine 知识地图有助于你快速掌握 TDengine 的知识体系。 - -
-
- -
图 1. TDengine 知识地图
-
-
- ## 加入 TDengine 官方社区 微信扫描以下二维码,学习了解 TDengine 的最新技术,与大家共同交流物联网大数据技术应用、TDengine 使用问题和技巧等话题。
- + - - - + + +
小 T 的二维码小 T 的二维码 TDengine 微信视频号 TDengine 微信公众号
加入“物联网大数据技术前沿群”
与大家进行技术交流
关注 TDengine 微信视频号
收看技术直播与教学视频
关注 TDengine 微信公众号
阅读核心技术与行业案例文章
加入 TDengine 微信群
了解学习最新物联网技术
关注 TDengine 视频号
收看技术直播与教学视频
关注 TDengine 公众号
阅读技术文章与行业案例
diff --git a/docs/zh/05-get-started/xiaot-03.webp b/docs/zh/05-get-started/xiaot-03.webp new file mode 100644 index 0000000000000000000000000000000000000000..c115346e9e84ffb990aec5947b2107b5daf6e19b Binary files /dev/null and b/docs/zh/05-get-started/xiaot-03.webp differ diff --git a/docs/zh/05-get-started/xiaot-new.webp b/docs/zh/05-get-started/xiaot-new.webp new file mode 100644 index 0000000000000000000000000000000000000000..483b54d2ef3d8894527aa154a42cf6cd2463c579 Binary files /dev/null and b/docs/zh/05-get-started/xiaot-new.webp differ diff --git a/docs/zh/07-develop/03-insert-data/01-sql-writing.mdx b/docs/zh/07-develop/03-insert-data/01-sql-writing.mdx index 47024171562bb7dc2d4e2063bc2fb0d44faad45b..89974ceb7b77627c70c4ec468b9716c4f2b204fc 100644 --- a/docs/zh/07-develop/03-insert-data/01-sql-writing.mdx +++ b/docs/zh/07-develop/03-insert-data/01-sql-writing.mdx @@ -30,25 +30,31 @@ import PhpStmt from "./_php_stmt.mdx"; 下面这条 INSERT 就将一条记录写入到表 d1001 中: ```sql -INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31); +INSERT INTO d1001 VALUES (ts1, 10.3, 219, 0.31); ``` +这里的`ts1`为Unix时间戳(Unix timestamp),允许插入的最老记录的时间戳,是相对于当前服务器时间,减去配置的 KEEP 值。时间戳详情规则参考 [TDengine SQL数据写入 关于时间戳一节](/taos-sql/insert) + ### 一次写入多条 TDengine 支持一次写入多条记录,比如下面这条命令就将两条记录写入到表 d1001 中: ```sql -INSERT INTO d1001 VALUES (1538548684000, 10.2, 220, 0.23) (1538548696650, 10.3, 218, 0.25); +INSERT INTO d1001 VALUES (ts1, 10.2, 220, 0.23) (ts2, 10.3, 218, 0.25); ``` +这里的`ts1`和`ts2`为Unix时间戳(Unix timestamp),允许插入的最老记录的时间戳,是相对于当前服务器时间,减去配置的 KEEP 值。时间戳详情规则参考 [TDengine SQL数据写入 关于时间戳一节](/taos-sql/insert) + ### 一次写入多表 TDengine 也支持一次向多个表写入数据,比如下面这条命令就向 d1001 写入两条记录,向 d1002 写入一条记录: ```sql -INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6, 218, 0.33) d1002 VALUES (1538548696800, 12.3, 221, 0.31); +INSERT INTO d1001 VALUES (ts1, 10.3, 219, 0.31) (ts2, 12.6, 218, 0.33) d1002 VALUES (ts3, 12.3, 221, 0.31); ``` +这里的`ts1`、`ts2`和`ts3`为Unix时间戳(Unix timestamp),允许插入的最老记录的时间戳,是相对于当前服务器时间,减去配置的 KEEP 值。时间戳详情规则参考 [TDengine SQL数据写入 关于时间戳一节](/taos-sql/insert) + 详细的 SQL INSERT 语法规则参考 [TDengine SQL 的数据写入](/taos-sql/insert)。 :::info diff --git a/docs/zh/07-develop/03-insert-data/30-influxdb-line.mdx b/docs/zh/07-develop/03-insert-data/30-influxdb-line.mdx index afe73af8dbc3a768a3e7640a9de5f11dbe18653c..876f123fe13776b5ccb045fc390182e8bc8ecf8e 100644 --- a/docs/zh/07-develop/03-insert-data/30-influxdb-line.mdx +++ b/docs/zh/07-develop/03-insert-data/30-influxdb-line.mdx @@ -37,7 +37,7 @@ meters,location=California.LosAngeles,groupid=2 current=13.4,voltage=223,phase=0 - tag_set 中的所有的数据自动转化为 NCHAR 数据类型; - field_set 中的每个数据项都需要对自身的数据类型进行描述, 比如 1.2f32 代表 FLOAT 类型的数值 1.2, 如果不带类型后缀会被当作 DOUBLE 处理; - timestamp 支持多种时间精度。写入数据的时候需要用参数指定时间精度,支持从小时到纳秒的 6 种时间精度。 -- 为了提高写入的效率,默认假设同一个超级表中 field_set 的顺序是一样的(第一条数据包含所有的 field,后面的数据按照这个顺序),如果顺序不一样,需要配置参数 smlDataFormat 为 false,否则,数据写入按照相同顺序写入,库中数据会异常。(3.0.1.3 之后的版本 smlDataFormat 默认为 false) [TDengine 无模式写入参考指南](/reference/schemaless/#无模式写入行协议) +- 为了提高写入的效率,默认假设同一个超级表中 field_set 的顺序是一样的(第一条数据包含所有的 field,后面的数据按照这个顺序),如果顺序不一样,需要配置参数 smlDataFormat 为 false,否则,数据写入按照相同顺序写入,库中数据会异常。(3.0.1.3 之后的版本 smlDataFormat 默认为 false,从3.0.3.0开始,该配置废弃) [TDengine 无模式写入参考指南](/reference/schemaless/#无模式写入行协议) - 默认产生的子表名是根据规则生成的唯一 ID 值。用户也可以通过在 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 st,tname=cpu1,t1=4 c1=3 1626006833639000000 则创建的子表名为 cpu1。注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。[TDengine 无模式写入参考指南](/reference/schemaless/#无模式写入行协议) ::: diff --git a/docs/zh/07-develop/03-insert-data/50-opentsdb-json.mdx b/docs/zh/07-develop/03-insert-data/50-opentsdb-json.mdx index 89818409c5032166e77a50f07ea1b54bd66617cb..e1fd3dacc8d91ea4ce3efde6f71a645cc65140ea 100644 --- a/docs/zh/07-develop/03-insert-data/50-opentsdb-json.mdx +++ b/docs/zh/07-develop/03-insert-data/50-opentsdb-json.mdx @@ -47,7 +47,6 @@ OpenTSDB JSON 格式协议采用一个 JSON 字符串表示一行或多行数据 :::note - 对于 JSON 格式协议,TDengine 并不会自动把所有标签转成 NCHAR 类型, 字符串将将转为 NCHAR 类型, 数值将同样转换为 DOUBLE 类型。 -- TDengine 只接收 JSON **数组格式**的字符串,即使一行数据也需要转换成数组形式。 - 默认生成的子表名是根据规则生成的唯一 ID 值。用户也可以通过在 taos.cfg 里配置 smlChildTableName 参数来指定某个标签值作为子表名。该标签值应该具有全局唯一性。举例如下:假设有个标签名为tname, 配置 smlChildTableName=tname, 插入数据为 `"tags": { "host": "web02","dc": "lga","tname":"cpu1"}` 则创建的子表名为 cpu1。注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略)。 ::: diff --git a/docs/zh/07-develop/03-insert-data/_py_kafka.mdx b/docs/zh/07-develop/03-insert-data/_py_kafka.mdx index cd7edf557d4ae41df0f55f4456fe405515132e51..d656325674aae33c3bd222fddeb5efb776593d59 100644 --- a/docs/zh/07-develop/03-insert-data/_py_kafka.mdx +++ b/docs/zh/07-develop/03-insert-data/_py_kafka.mdx @@ -55,6 +55,70 @@ for p in ps: ### 完整示例 +
+kafka_example_perform + +`kafka_example_perform` 是示例程序的入口 + +```py +{{#include docs/examples/python/kafka_example_perform.py}} +``` +
+ +
+kafka_example_common + +`kafka_example_common` 是示例程序的公共代码 + ```py -{{#include docs/examples/python/kafka_example.py}} +{{#include docs/examples/python/kafka_example_common.py}} ``` +
+ +
+kafka_example_producer + +`kafka_example_producer` 是示例程序的 producer 代码,负责生成并发送测试数据到 kafka + +```py +{{#include docs/examples/python/kafka_example_producer.py}} +``` +
+ +
+kafka_example_consumer + +`kafka_example_consumer` 是示例程序的 consumer 代码,负责从 kafka 消费数据,并写入到 TDengine + +```py +{{#include docs/examples/python/kafka_example_consumer.py}} +``` +
+ +### 执行步骤 + +
+ 执行 Python 示例程序 + + 1. 安装并启动 kafka + + 2. python 环境准备 + - 安装 python3 + - 安装 taospy + - 安装 kafka-python + + 3. 执行示例程序 + + 程序的执行入口是 `kafka_example_perform.py`,获取程序完整的执行参数,请执行 help 命令。 + + ``` + python3 kafka_example_perform.py --help + ``` + + 以下为创建 100 个子表,每个子表 20000 条数据,kafka max poll 为 100,一个进程,每个进程一个处理线程的程序执行命令 + + ``` + python3 kafka_example_perform.py -table-count=100 -table-items=20000 -max-poll=100 -threads=1 -processes=1 + ``` + +
diff --git a/docs/zh/07-develop/06-stream.md b/docs/zh/07-develop/06-stream.md index a2e1d1a1dac5af44e053aa314ede45005e2de587..4a5ebb96e8add2a8756b3e21d29f4ba40d5b927f 100644 --- a/docs/zh/07-develop/06-stream.md +++ b/docs/zh/07-develop/06-stream.md @@ -52,7 +52,7 @@ CREATE TABLE d1004 USING meters TAGS ("California.LosAngeles", 3); ### 创建流 ```sql -create stream current_stream into current_stream_output_stb as select _wstart as start, _wend as wend, max(current) as max_current from meters where voltage <= 220 interval (5s); +create stream current_stream trigger at_once into current_stream_output_stb as select _wstart as wstart, _wend as wend, max(current) as max_current from meters where voltage <= 220 interval (5s); ``` ### 写入数据 @@ -70,8 +70,8 @@ insert into d1004 values("2018-10-03 14:38:06.500", 11.50000, 221, 0.35000); ### 查询以观察结果 ```sql -taos> select start, wend, max_current from current_stream_output_stb; - start | wend | max_current | +taos> select wstart, wend, max_current from current_stream_output_stb; + wstart | wend | max_current | =========================================================================== 2018-10-03 14:38:05.000 | 2018-10-03 14:38:10.000 | 10.30000 | 2018-10-03 14:38:15.000 | 2018-10-03 14:38:20.000 | 12.60000 | @@ -89,7 +89,7 @@ Query OK, 2 rows in database (0.018762s) ### 创建流 ```sql -create stream power_stream into power_stream_output_stb as select ts, concat_ws(".", location, tbname) as meter_location, current*voltage*cos(phase) as active_power, current*voltage*sin(phase) as reactive_power from meters partition by tbname; +create stream power_stream trigger at_once into power_stream_output_stb as select ts, concat_ws(".", location, tbname) as meter_location, current*voltage*cos(phase) as active_power, current*voltage*sin(phase) as reactive_power from meters partition by tbname; ``` ### 写入数据 diff --git a/docs/zh/07-develop/07-tmq.mdx b/docs/zh/07-develop/07-tmq.mdx index 1f5a089aaa2a051e238eedc0315c37cad643b33f..036c9aa86e5c91903a74bffd1f9c59a13a97c116 100644 --- a/docs/zh/07-develop/07-tmq.mdx +++ b/docs/zh/07-develop/07-tmq.mdx @@ -7,6 +7,7 @@ title: 数据订阅 import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; import Java from "./_sub_java.mdx"; +import JavaWS from "./_sub_java_ws.mdx"; import Python from "./_sub_python.mdx"; import Go from "./_sub_go.mdx"; import Rust from "./_sub_rust.mdx"; @@ -24,6 +25,7 @@ import CDemo from "./_sub_c.mdx"; 本文档不对消息队列本身的基础知识做介绍,如果需要了解,请自行搜索。 +注意:默认是从wal消费数据,如果wal被删除,消费到的数据会不全,此时可以将参数 experimental.snapshot.enable 设置为true,从tsdb获取全部数据,但是这样的话就不能保证数据的消费顺序。所以建议根据自己的消费情况合理的设置wal的保留策略,保证可以从wal里订阅到全部数据。 ## 主要数据结构和 API 不同语言下, TMQ 订阅相关的 API 及数据结构如下: @@ -92,22 +94,21 @@ void close() throws SQLException; ```python -class TaosConsumer(): - def __init__(self, *topics, **configs) +class Consumer: + def subscribe(self, topics): + pass - def __iter__(self) + def unsubscribe(self): + pass - def __next__(self) + def poll(self, timeout: float = 1.0): + pass - def sync_next(self) - - def subscription(self) + def close(self): + pass - def unsubscribe(self) - - def close(self) - - def __del__(self) + def commit(self, message): + pass ``` @@ -115,19 +116,22 @@ class TaosConsumer(): ```go -func NewConsumer(conf *Config) (*Consumer, error) - -func (c *Consumer) Close() error +func NewConsumer(conf *tmq.ConfigMap) (*Consumer, error) -func (c *Consumer) Commit(ctx context.Context, message unsafe.Pointer) error +// 出于兼容目的保留 rebalanceCb 参数,当前未使用 +func (c *Consumer) Subscribe(topic string, rebalanceCb RebalanceCb) error -func (c *Consumer) FreeMessage(message unsafe.Pointer) +// 出于兼容目的保留 rebalanceCb 参数,当前未使用 +func (c *Consumer) SubscribeTopics(topics []string, rebalanceCb RebalanceCb) error -func (c *Consumer) Poll(timeout time.Duration) (*Result, error) +func (c *Consumer) Poll(timeoutMs int) tmq.Event -func (c *Consumer) Subscribe(topics []string) error +// 出于兼容目的保留 tmq.TopicPartition 参数,当前未使用 +func (c *Consumer) Commit() ([]tmq.TopicPartition, error) func (c *Consumer) Unsubscribe() error + +func (c *Consumer) Close() error ``` @@ -280,18 +284,17 @@ CREATE TOPIC topic_name AS DATABASE db_name; | 参数名称 | 类型 | 参数说明 | 备注 | | :----------------------------: | :-----: | -------------------------------------------------------- | ------------------------------------------- | -| `td.connect.ip` | string | 用于创建连接,同 `taos_connect` | | -| `td.connect.user` | string | 用于创建连接,同 `taos_connect` | | -| `td.connect.pass` | string | 用于创建连接,同 `taos_connect` | | -| `td.connect.port` | integer | 用于创建连接,同 `taos_connect` | | +| `td.connect.ip` | string | 用于创建连接,同 `taos_connect` | 仅用于建立原生连接 | +| `td.connect.user` | string | 用于创建连接,同 `taos_connect` | 仅用于建立原生连接 | +| `td.connect.pass` | string | 用于创建连接,同 `taos_connect` | 仅用于建立原生连接 | +| `td.connect.port` | integer | 用于创建连接,同 `taos_connect` | 仅用于建立原生连接 | | `group.id` | string | 消费组 ID,同一消费组共享消费进度 | **必填项**。最大长度:192。 | | `client.id` | string | 客户端 ID | 最大长度:192。 | -| `auto.offset.reset` | enum | 消费组订阅的初始位置 | 可选:`earliest`(default), `latest`, `none` | -| `enable.auto.commit` | boolean | 是否启用消费位点自动提交 | 合法值:`true`, `false`。 | -| `auto.commit.interval.ms` | integer | 以毫秒为单位的消费记录自动提交消费位点时间间 | 默认 5000 m | -| `enable.heartbeat.background` | boolean | 启用后台心跳,启用后即使长时间不 poll 消息也不会造成离线 | 默认开启 | -| `experimental.snapshot.enable` | boolean | 是否允许从 TSDB 消费数据 | 实验功能,默认关闭 | -| `msg.with.table.name` | boolean | 是否允许从消息中解析表名, 不适用于列订阅(列订阅时可将 tbname 作为列写入 subquery 语句) | | +| `auto.offset.reset` | enum | 消费组订阅的初始位置 |
`earliest`: default;从头开始订阅;
`latest`: 仅从最新数据开始订阅;
`none`: 没有提交的 offset 无法订阅 | +| `enable.auto.commit` | boolean | 是否启用消费位点自动提交,true: 自动提交,客户端应用无需commit;false:客户端应用需要自行commit | 默认值为 true | +| `auto.commit.interval.ms` | integer | 消费记录自动提交消费位点时间间隔,单位为毫秒 | 默认值为 5000 | +| `experimental.snapshot.enable` | boolean | 是否允许从 TSDB 消费数据。当其关闭时,只能消费依据 WAL 保留策略仍然在WAL中的数据;当其打开时,除WAL中的数据以外,也能够消费已经从WAL中删除但落盘到TSDB中的数据 | 实验功能,默认关闭 | +| `msg.with.table.name` | boolean | 是否允许从消息中解析表名, 不适用于列订阅(列订阅时可将 tbname 作为列写入 subquery 语句) |默认关闭 | 对于不同编程语言,其设置方式如下: @@ -355,50 +358,19 @@ public class MetersDeserializer extends ReferenceDeserializer { ```go -config := tmq.NewConfig() -defer config.Destroy() -err = config.SetGroupID("test") -if err != nil { - panic(err) -} -err = config.SetAutoOffsetReset("earliest") -if err != nil { - panic(err) -} -err = config.SetConnectIP("127.0.0.1") -if err != nil { - panic(err) -} -err = config.SetConnectUser("root") -if err != nil { - panic(err) -} -err = config.SetConnectPass("taosdata") -if err != nil { - panic(err) -} -err = config.SetConnectPort("6030") -if err != nil { - panic(err) -} -err = config.SetMsgWithTableName(true) -if err != nil { - panic(err) -} -err = config.EnableHeartBeat() -if err != nil { - panic(err) -} -err = config.EnableAutoCommit(func(result *wrapper.TMQCommitCallbackResult) { - if result.ErrCode != 0 { - errStr := wrapper.TMQErr2Str(result.ErrCode) - err := errors.NewError(int(result.ErrCode), errStr) - panic(err) - } -}) -if err != nil { - panic(err) +conf := &tmq.ConfigMap{ + "group.id": "test", + "auto.offset.reset": "earliest", + "td.connect.ip": "127.0.0.1", + "td.connect.user": "root", + "td.connect.pass": "taosdata", + "td.connect.port": "6030", + "client.id": "test_tmq_c", + "enable.auto.commit": "false", + "experimental.snapshot.enable": "true", + "msg.with.table.name": "true", } +consumer, err := NewConsumer(conf) ``` @@ -420,34 +392,32 @@ let mut consumer = tmq.build()?; -Python 语言下引入 `taos` 库的 `TaosConsumer` 类,创建一个 Consumer 示例: +Python 语言下引入 `taos` 库的 `Consumer` 类,创建一个 Consumer 示例: ```python -from taos.tmq import TaosConsumer +from taos.tmq import Consumer -# Syntax: `consumer = TaosConsumer(*topics, **args)` +# Syntax: `consumer = Consumer(configs)` # # Example: -consumer = TaosConsumer('topic1', 'topic2', td_connect_ip = "127.0.0.1", group_id = "local") +consumer = Consumer({"group.id": "local", "td.connect.ip": "127.0.0.1"}) ``` -其中,元组类型参数被视为 *Topics*,字典类型参数用于以下订阅配置设置: +其中,`configs` 为 dict 类型,传递创建 Consumer 的参数。可以配置的参数有: -| 参数名称 | 类型 | 参数说明 | 备注 | -| :----------------------------: | :----: | -------------------------------------------------------- | ------------------------------------------- | -| `td_connect_ip` | string | 用于创建连接,同 `taos_connect` | | -| `td_connect_user` | string | 用于创建连接,同 `taos_connect` | | -| `td_connect_pass` | string | 用于创建连接,同 `taos_connect` | | -| `td_connect_port` | string | 用于创建连接,同 `taos_connect` | | -| `group_id` | string | 消费组 ID,同一消费组共享消费进度 | **必填项**。最大长度:192。 | -| `client_id` | string | 客户端 ID | 最大长度:192。 | -| `auto_offset_reset` | string | 消费组订阅的初始位置 | 可选:`earliest`(default), `latest`, `none` | -| `enable_auto_commit` | string | 启用自动提交 | 合法值:`true`, `false`,默认为 true | -| `auto_commit_interval_ms` | string | 以毫秒为单位的自动提交时间间隔 | 默认值:5000 ms | -| `enable_heartbeat_background` | string | 启用后台心跳,启用后即使长时间不 poll 消息也不会造成离线 | 合法值:`true`, `false` | -| `experimental_snapshot_enable` | string | 是否允许从 TSDB 消费数据 | 合法值:`true`, `false` | -| `msg_with_table_name` | string | 是否允许从消息中解析表名,不适用于列订阅 | 合法值:`true`, `false` | -| `timeout` | int | 消费者拉取数据的超时时间 | | +| 参数名称 | 类型 | 参数说明 | 备注 | +|:------:|:----:|:-------:|:---:| +| `td.connect.ip` | string | 用于创建连接|| +| `td.connect.user` | string | 用于创建连接|| +| `td.connect.pass` | string | 用于创建连接|| +| `td.connect.port` | string | 用于创建连接|| +| `group.id` | string | 消费组 ID,同一消费组共享消费进度 | **必填项**。最大长度:192 | +| `client.id` | string | 客户端 ID | 最大长度:192 | +| `msg.with.table.name` | string | 是否允许从消息中解析表名,不适用于列订阅 | 合法值:`true`, `false` | +| `enable.auto.commit` | string | 启用自动提交 | 合法值:`true`, `false` | +| `auto.commit.interval.ms` | string | 以毫秒为单位的自动提交时间间隔 | 默认值:5000 ms | +| `auto.offset.reset` | string | 消费组订阅的初始位置 | 可选:`earliest`(default), `latest`, `none` | +| `experimental.snapshot.enable` | string | 是否允许从 TSDB 消费数据 | 合法值:`true`, `false` | @@ -532,11 +502,7 @@ consumer.subscribe(topics); ```go -consumer, err := tmq.NewConsumer(config) -if err != nil { - panic(err) -} -err = consumer.Subscribe([]string{"example_tmq_topic"}) +err = consumer.Subscribe("example_tmq_topic", nil) if err != nil { panic(err) } @@ -554,7 +520,7 @@ consumer.subscribe(["tmq_meters"]).await?; ```python -consumer = TaosConsumer('topic_ctb_column', group_id='vg2') +consumer.subscribe(['topic1', 'topic2']) ``` @@ -620,13 +586,17 @@ while(running){ ```go for { - result, err := consumer.Poll(time.Second) - if err != nil { - panic(err) + ev := consumer.Poll(0) + if ev != nil { + switch e := ev.(type) { + case *tmqcommon.DataMessage: + fmt.Println(e.Value()) + case tmqcommon.Error: + fmt.Fprintf(os.Stderr, "%% Error: %v: %v\n", e.Code(), e) + panic(e) + } + consumer.Commit() } - fmt.Println(result) - consumer.Commit(context.Background(), result.Message) - consumer.FreeMessage(result.Message) } ``` @@ -669,9 +639,17 @@ for { ```python -for msg in consumer: - for row in msg: - print(row) +while True: + res = consumer.poll(100) + if not res: + continue + err = res.error() + if err is not None: + raise err + val = res.value() + + for block in val: + print(block.fetchall()) ``` @@ -738,7 +716,11 @@ consumer.close(); ```go -consumer.Close() +/* Unsubscribe */ +_ = consumer.Unsubscribe() + +/* Close consumer */ +_ = consumer.Close() ``` @@ -824,7 +806,14 @@ SHOW SUBSCRIPTIONS; - + + + + + + + + diff --git a/docs/zh/07-develop/09-udf.md b/docs/zh/07-develop/09-udf.md index 7a3a3822d5f619337dc0c81482903b51f26a5e96..8a8ef82009c512b550cd514f3d52716f79d8e0a1 100644 --- a/docs/zh/07-develop/09-udf.md +++ b/docs/zh/07-develop/09-udf.md @@ -65,11 +65,11 @@ int32_t aggfn_init() { } // aggregate start function. The intermediate value or the state(@interBuf) is initialized in this function. The function name shall be concatenation of udf name and _start suffix -// @param interbuf intermediate value to intialize +// @param interbuf intermediate value to initialize // @return error number defined in taoserror.h int32_t aggfn_start(SUdfInterBuf* interBuf) { // initialize intermediate value in interBuf - return TSDB_CODE_SUCESS; + return TSDB_CODE_SUCCESS; } // aggregate reduce function. This function aggregate old state(@interbuf) and one data bock(inputBlock) and output a new state(@newInterBuf). @@ -231,7 +231,7 @@ bit_add 实现多列的按位与功能。如果只有一列,返回这一列。
-### 聚合函数示例 [l2norm](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/l2norm.c) +### 聚合函数示例1 返回值为数值类型 [l2norm](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/l2norm.c) l2norm 实现了输入列的所有数据的二阶范数,即对每个数据先平方,再累加求和,最后开方。 @@ -243,3 +243,29 @@ l2norm 实现了输入列的所有数据的二阶范数,即对每个数据先 ``` + +### 聚合函数示例2 返回值为字符串类型 [max_vol](https://github.com/taosdata/TDengine/blob/develop/tests/script/sh/max_vol.c) + +max_vol 实现了从多个输入的电压列中找到最大电压,返回由设备ID + 最大电压所在(行,列)+ 最大电压值 组成的组合字符串值 + +创建表: +```bash +create table battery(ts timestamp, vol1 float, vol2 float, vol3 float, deviceId varchar(16)); +``` +创建自定义函数: +```bash +create aggregate function max_vol as '/root/udf/libmaxvol.so' outputtype binary(64) bufsize 10240 language 'C'; +``` +使用自定义函数: +```bash +select max_vol(vol1,vol2,vol3,deviceid) from battery; +``` + +
+max_vol.c + +```c +{{#include tests/script/sh/max_vol.c}} +``` + +
\ No newline at end of file diff --git a/docs/zh/07-develop/_sub_java.mdx b/docs/zh/07-develop/_sub_java.mdx index e7de158cc8d2b0b686b25bbe96e7a092c2a68e51..60810ec27513b4ffd6142f6a58f09a31b65a878e 100644 --- a/docs/zh/07-develop/_sub_java.mdx +++ b/docs/zh/07-develop/_sub_java.mdx @@ -6,4 +6,3 @@ ``` ```java {{#include docs/examples/java/src/main/java/com/taos/example/Meters.java}} -``` \ No newline at end of file diff --git a/docs/zh/07-develop/_sub_java_ws.mdx b/docs/zh/07-develop/_sub_java_ws.mdx new file mode 100644 index 0000000000000000000000000000000000000000..5a4211d05901c572cf7e3f7afd48f955395a159d --- /dev/null +++ b/docs/zh/07-develop/_sub_java_ws.mdx @@ -0,0 +1,9 @@ +```java +{{#include docs/examples/java/src/main/java/com/taos/example/WebsocketSubscribeDemo.java}} +``` +```java +{{#include docs/examples/java/src/main/java/com/taos/example/MetersDeserializer.java}} +``` +```java +{{#include docs/examples/java/src/main/java/com/taos/example/Meters.java}} +``` \ No newline at end of file diff --git a/docs/zh/08-connector/02-rest-api.mdx b/docs/zh/08-connector/02-rest-api.mdx index af2ec1b1c2f2c677efa3e0a5c5ca2e16fa3c9b27..f3f1e087d809b7ce98d27721ada13b7a5fdf7159 100644 --- a/docs/zh/08-connector/02-rest-api.mdx +++ b/docs/zh/08-connector/02-rest-api.mdx @@ -69,7 +69,7 @@ curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" \ ## HTTP 请求格式 ```text -http://:/rest/sql/[db_name][?tz=timezone] +http://:/rest/sql/[db_name][?tz=timezone[&req_id=req_id]] ``` 参数说明: @@ -78,6 +78,7 @@ http://:/rest/sql/[db_name][?tz=timezone] - port: 配置文件中 httpPort 配置项,缺省为 6041。 - db_name: 可选参数,指定本次所执行的 SQL 语句的默认数据库库名。 - tz: 可选参数,指定返回时间的时区,遵照 IANA Time Zone 规则,如 `America/New_York`。 +- req_id: 可选参数,指定请求 id,可以用于 tracing。 例如:`http://h1.taos.com:6041/rest/sql/test` 是指向地址为 `h1.taos.com:6041` 的 URL,并将默认使用的数据库库名设置为 `test`。 @@ -100,13 +101,13 @@ HTTP 请求的 BODY 里就是一个完整的 SQL 语句,SQL 语句中的数据 使用 `curl` 通过自定义身份认证方式来发起一个 HTTP Request,语法如下: ```bash -curl -L -H "Authorization: Basic " -d "" :/rest/sql/[db_name][?tz=timezone] +curl -L -H "Authorization: Basic " -d "" :/rest/sql/[db_name][?tz=timezone[&req_id=req_id]] ``` 或者, ```bash -curl -L -u username:password -d "" :/rest/sql/[db_name][?tz=timezone] +curl -L -u username:password -d "" :/rest/sql/[db_name][?tz=timezone[&req_id=req_id]] ``` 其中,`TOKEN` 为 `{username}:{password}` 经过 Base64 编码之后的字符串,例如 `root:taosdata` 编码后为 `cm9vdDp0YW9zZGF0YQ==`。 @@ -115,14 +116,41 @@ curl -L -u username:password -d "" :/rest/sql/[db_name][?tz=timez ### HTTP 响应码 -| **response code** | **说明** | -|-------------------|----------------| -| 200 | 正确返回和 C 接口错误返回 | -| 400 | 参数错误返回 | -| 401 | 鉴权失败 | -| 404 | 接口不存在 | -| 500 | 内部错误 | -| 503 | 系统资源不足 | +从 `TDengine 3.0.3.0` 开始 `taosAdapter` 提供配置参数 `httpCodeServerError` 用来设置当 C 接口返回错误时是否返回非 200 的http状态码 + +| **说明** | **httpCodeServerError false** | **httpCodeServerError true** | +|--------------------|-------------------------------|---------------------------------------| +| taos_errno() 返回 0 | 200 | 200 | +| taos_errno() 返回 非0 | 200(除鉴权错误) | 500 (除鉴权错误和 400/502 错误) | +| 参数错误 | 400 (仅处理 HTTP 请求 URL 参数错误) | 400 (处理 HTTP 请求 URL 参数错误和 taosd 返回错误) | +| 鉴权错误 | 401 | 401 | +| 接口不存在 | 404 | 404 | +| 集群不可用错误 | 502 | 502 | +| 系统资源不足 | 503 | 503 | + +返回 400 的 C 错误码为: + +- TSDB_CODE_TSC_SQL_SYNTAX_ERROR ( 0x0216) +- TSDB_CODE_TSC_LINE_SYNTAX_ERROR (0x021B) +- TSDB_CODE_PAR_SYNTAX_ERROR (0x2600) +- TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE (0x060B) +- TSDB_CODE_TSC_VALUE_OUT_OF_RANGE (0x0224) +- TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE (0x263B) + +返回 401 的错误码为: + +- TSDB_CODE_MND_USER_ALREADY_EXIST (0x0350) +- TSDB_CODE_MND_USER_NOT_EXIST ( 0x0351) +- TSDB_CODE_MND_INVALID_USER_FORMAT (0x0352) +- TSDB_CODE_MND_INVALID_PASS_FORMAT (0x0353) +- TSDB_CODE_MND_NO_USER_FROM_CONN (0x0354) +- TSDB_CODE_MND_TOO_MANY_USERS (0x0355) +- TSDB_CODE_MND_INVALID_ALTER_OPER (0x0356) +- TSDB_CODE_MND_AUTH_FAILURE (0x0357) + +返回 403 的错误码为: + +- TSDB_CODE_RPC_SOMENODE_NOT_CONNECTED (0x0020) ### HTTP body 结构 @@ -270,7 +298,6 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata ```json { - "status": "succ", "code": 0, "desc": "/KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04" } @@ -356,6 +383,133 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata } ``` +## TDengine 2.x 和 3.0 之间 REST API 的差异 + +### URI + +| URI | TDengine 2.x | TDengine 3.0 | +| :--------------------| :------------------: | :--------------------------------------------------: | +| /rest/sql | 支持 | 支持 (响应代码和消息体不同) | +| /rest/sqlt | 支持 | 不再支持 | +| /rest/sqlutc | 支持 | 不再支持 | + + +### HTTP code + +| HTTP code | TDengine 2.x | TDengine 3.0 | 备注 | +| :--------------------| :------------------: | :----------: | :-----------------------------------: | +| 200 | 支持 | 支持 | 正确返回和 taosc 接口错误返回 | +| 400 | 不支持 | 支持 | 参数错误返回 | +| 401 | 不支持 | 支持 | 鉴权失败 | +| 404 | 支持 | 支持 | 接口不存在 | +| 500 | 不支持 | 支持 | 内部错误 | +| 503 | 支持 | 支持 | 系统资源不足 | + + +### 响应代码和消息体 + +#### TDengine 2.x 响应代码和消息体 + +```JSON +{ + "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": [ + [ + "log", + "2020-09-02 17:23:00.039", + 4, + 1, + 1, + 1, + 10, + "30,30,30", + 1, + 3, + 100, + 4096, + 1, + 3000, + 2, + "us", + "ready" + ] + ], + "rows": 1 +} +``` +``` + "data": [ + [ + "information_schema", + 16, + "ready" + ], + [ + "performance_schema", + 9, + "ready" + ] + ], +``` + +#### TDengine 3.0 响应代码和消息体 + + +```JSON +{ + "code": 0, + "column_meta": [ + [ + "name", + "VARCHAR", + 64 + ], + [ + "ntables", + "BIGINT", + 8 + ], + [ + "status", + "VARCHAR", + 10 + ] + ], + "data": [ + [ + "information_schema", + 16, + "ready" + ], + [ + "performance_schema", + 9, + "ready" + ] + ], + "rows": 2 +} +``` + ## 参考 [taosAdapter](/reference/taosadapter/) diff --git a/docs/zh/08-connector/05-schemaless-api.mdx b/docs/zh/08-connector/05-schemaless-api.mdx index f6d7e09212c71ed7b142eeabf2a2d69c5f79d439..8f0a9273b9988c191681063adfb67ebfd03615d3 100644 --- a/docs/zh/08-connector/05-schemaless-api.mdx +++ b/docs/zh/08-connector/05-schemaless-api.mdx @@ -19,6 +19,7 @@ TDengine 提供了兼容 InfluxDB (v1) 和 OpenTSDB 行协议的 Schemaless API - `precision` TDengine 使用的时间精度 - `u` TDengine 用户名 - `p` TDengine 密码 +- `ttl` 自动创建的子表生命周期,以子表的第一条数据的 TTL 参数为准,不可更新。更多信息请参考[创建表文档](taos-sql/table/#创建表)的 TTL 参数 注意: 目前不支持 InfluxDB 的 token 验证方式,仅支持 Basic 验证和查询参数验证。 diff --git a/docs/zh/08-connector/10-cpp.mdx b/docs/zh/08-connector/10-cpp.mdx index ad83aee734e03b5bea807959c36ee90be4e1731d..9c5095f09cce0a833757da377e8c19be7a7e310d 100644 --- a/docs/zh/08-connector/10-cpp.mdx +++ b/docs/zh/08-connector/10-cpp.mdx @@ -263,6 +263,14 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) - `int taos_select_db(TAOS *taos, const char *db)` 将当前的缺省数据库设置为 `db`。 + +- `int taos_get_current_db(TAOS *taos, char *database, int len, int *required)` + + - database,len为用户在外面申请的空间,内部会把当前db赋值到database里。 + - 只要是没有正常把db名赋值到database中(包括截断),返回错误,返回值为-1,然后用户可以通过 taos_errstr(NULL) 来获取错误提示。 + - 如果,database == NULL 或者 len<=0 返回错误,required里保存存储db需要的空间(包含最后的'\0') + - 如果,len 小于 存储db需要的空间(包含最后的'\0'),返回错误,database里赋值截断的数据,以'\0'结尾。 + - 如果,len 大于等于 存储db需要的空间(包含最后的'\0'),返回正常0,database里赋值以'\0‘结尾的db名。 - `void taos_close(TAOS *taos)` @@ -302,7 +310,7 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) - `TAOS_FIELD *taos_fetch_fields(TAOS_RES *res)` - 获取查询结果集每列数据的属性(列的名称、列的数据类型、列的长度),与 `taos_num_fileds()` 配合使用,可用来解析 `taos_fetch_row()` 返回的一个元组(一行)的数据。 `TAOS_FIELD` 的结构如下: + 获取查询结果集每列数据的属性(列的名称、列的数据类型、列的长度),与 `taos_num_fields()` 配合使用,可用来解析 `taos_fetch_row()` 返回的一个元组(一行)的数据。 `TAOS_FIELD` 的结构如下: ```c typedef struct taosField { @@ -330,6 +338,7 @@ typedef struct taosField { :::note 2.0 及以上版本 TDengine 推荐数据库应用的每个线程都建立一个独立的连接,或基于线程建立连接池。而不推荐在应用中将该连接 (TAOS\*) 结构体传递到不同的线程共享使用。基于 TAOS 结构体发出的查询、写入等操作具有多线程安全性,但 “USE statement” 等状态量有可能在线程之间相互干扰。此外,C 语言的连接器可以按照需求动态建立面向数据库的新连接(该过程对用户不可见),同时建议只有在程序最后退出的时候才调用 `taos_close()` 关闭连接。 +另一个需要注意的是,在上述同步 API 执行过程中,不能调用类似 pthread_cancel 之类的 API 来强制结束线程,因为涉及一些模块的同步操作,如果强制结束线程有可能造成包括但不限于死锁等异常状况。 ::: @@ -492,5 +501,17 @@ TDengine 的异步 API 均采用非阻塞调用模式。应用程序可以用多 需要注意的是,时间戳分辨率参数只在协议类型为 `SML_LINE_PROTOCOL` 的时候生效。 对于 OpenTSDB 的文本协议,时间戳的解析遵循其官方解析规则 — 按照时间戳包含的字符的数量来确认时间精度。 - **支持版本** - 该功能接口从 2.3.0.0 版本开始支持。 + **schemaless 其他相关的接口** +- `TAOS_RES *taos_schemaless_insert_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, int precision, int64_t reqid)` +- `TAOS_RES *taos_schemaless_insert_raw(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision)` +- `TAOS_RES *taos_schemaless_insert_raw_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision, int64_t reqid)` +- `TAOS_RES *taos_schemaless_insert_ttl(TAOS *taos, char *lines[], int numLines, int protocol, int precision, int32_t ttl)` +- `TAOS_RES *taos_schemaless_insert_ttl_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, int precision, int32_t ttl, int64_t reqid)` +- `TAOS_RES *taos_schemaless_insert_raw_ttl(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision, int32_t ttl)` +- `TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision, int32_t ttl, int64_t reqid)` + + **说明** + - 上面这7个接口是扩展接口,主要用于在schemaless写入时传递ttl、reqid参数,可以根据需要使用。 + - 带_raw的接口通过传递的参数lines指针和长度len来表示数据,为了解决原始接口数据包含'\0'而被截断的问题。totalRows指针返回解析出来的数据行数。 + - 带_ttl的接口可以传递ttl参数来控制建表的ttl到期时间。 + - 带_reqid的接口可以通过传递reqid参数来追踪整个的调用链。 diff --git a/docs/zh/08-connector/14-java.mdx b/docs/zh/08-connector/14-java.mdx index 1ee59d2df429f2bd64b1dfdcc2ef81f12b1272d0..d1c12583659e2f6dd2a63357669b92c3b1ff29b1 100644 --- a/docs/zh/08-connector/14-java.mdx +++ b/docs/zh/08-connector/14-java.mdx @@ -17,7 +17,7 @@ import TabItem from '@theme/TabItem'; - JDBC 原生连接:Java 应用在物理节点 1(pnode1)上使用 TSDBDriver 直接调用客户端驱动(libtaos.so 或 taos.dll)的 API 将写入和查询请求发送到位于物理节点 2(pnode2)上的 taosd 实例。 - JDBC REST 连接:Java 应用通过 RestfulDriver 将 SQL 封装成一个 REST 请求,发送给物理节点 2 的 REST 服务器(taosAdapter),通过 REST 服务器请求 taosd 并返回结果。 -使用 REST 连接,不依赖 TDengine 客户端驱动,可以跨平台,更加方便灵活,但性能比原生连接器低约 30%。 +使用 REST 连接,不依赖 TDengine 客户端驱动,可以跨平台,更加方便灵活。 :::info TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致,但 TDengine 与关系对象型数据库的使用场景和技术特征存在差异,所以`taos-jdbcdriver` 与传统的 JDBC driver 也存在一定差异。在使用时需要注意以下几点: @@ -68,39 +68,38 @@ TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对 ### 安装连接器 - + - 目前 taos-jdbcdriver 已经发布到 [Sonatype Repository](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) - 仓库,且各大仓库都已同步。 +目前 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) +- [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 中添加以下依赖: +Maven 项目中,在 pom.xml 中添加以下依赖: - ```xml-dtd - - com.taosdata.jdbc - taos-jdbcdriver - 3.0.0 - - ``` +```xml-dtd + + com.taosdata.jdbc + taos-jdbcdriver + 3.0.0 + +``` - - + + - 可以通过下载 TDengine 的源码,自己编译最新版本的 Java connector +可以通过下载 TDengine 的源码,自己编译最新版本的 Java connector - ```shell - git clone https://github.com/taosdata/taos-connector-jdbc.git - cd taos-connector-jdbc - mvn clean install -Dmaven.test.skip=true - ``` +```shell +git clone https://github.com/taosdata/taos-connector-jdbc.git +cd taos-connector-jdbc +mvn clean install -Dmaven.test.skip=true +``` - 编译后,在 target 目录下会产生 taos-jdbcdriver-3.0.*-dist.jar 的 jar 包,并自动将编译的 jar 文件放在本地的 Maven 仓库中。 +编译后,在 target 目录下会产生 taos-jdbcdriver-3.0.*-dist.jar 的 jar 包,并自动将编译的 jar 文件放在本地的 Maven 仓库中。 - + ## 建立连接 @@ -111,125 +110,117 @@ TDengine 的 JDBC URL 规范格式为: 对于建立连接,原生连接与 REST 连接有细微不同。 - + - ```java - Class.forName("com.taosdata.jdbc.TSDBDriver"); - String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata"; - Connection conn = DriverManager.getConnection(jdbcUrl); - ``` +```java +Class.forName("com.taosdata.jdbc.TSDBDriver"); +String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata"; +Connection conn = DriverManager.getConnection(jdbcUrl); +``` - 以上示例,使用了 JDBC 原生连接的 TSDBDriver,建立了到 hostname 为 taosdemo.com,端口为 6030(TDengine 的默认端口),数据库名为 test 的连接。这个 URL - 中指定用户名(user)为 root,密码(password)为 taosdata。 +以上示例,使用了 JDBC 原生连接的 TSDBDriver,建立了到 hostname 为 taosdemo.com,端口为 6030(TDengine 的默认端口),数据库名为 test 的连接。这个 URL +中指定用户名(user)为 root,密码(password)为 taosdata。 - **注意**:使用 JDBC 原生连接,taos-jdbcdriver 需要依赖客户端驱动(Linux 下是 libtaos.so;Windows 下是 taos.dll;macOS 下是 libtaos.dylib)。 +**注意**:使用 JDBC 原生连接,taos-jdbcdriver 需要依赖客户端驱动(Linux 下是 libtaos.so;Windows 下是 taos.dll;macOS 下是 libtaos.dylib)。 - url 中的配置参数如下: +url 中的配置参数如下: - - user:登录 TDengine 用户名,默认值 'root'。 - - password:用户登录密码,默认值 'taosdata'。 - - cfgdir:客户端配置文件目录路径,Linux OS 上默认值 `/etc/taos`,Windows OS 上默认值 `C:/TDengine/cfg`。 - - charset:客户端使用的字符集,默认值为系统字符集。 - - locale:客户端语言环境,默认值系统当前 locale。 - - timezone:客户端使用的时区,默认值为系统当前时区。 - - batchfetch: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:true。开启批量拉取同时获取一批数据在查询数据量较大时批量拉取可以有效的提升查询性能。 - - batchErrorIgnore:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败将继续执行下面的 SQL。false:不再执行失败 SQL - 后的任何语句。默认值为:false。 +- user:登录 TDengine 用户名,默认值 'root'。 +- password:用户登录密码,默认值 'taosdata'。 +- cfgdir:客户端配置文件目录路径,Linux OS 上默认值 `/etc/taos`,Windows OS 上默认值 `C:/TDengine/cfg`。 +- charset:客户端使用的字符集,默认值为系统字符集。 +- locale:客户端语言环境,默认值系统当前 locale。 +- timezone:客户端使用的时区,默认值为系统当前时区。 +- batchfetch: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:true。开启批量拉取同时获取一批数据在查询数据量较大时批量拉取可以有效的提升查询性能。 +- batchErrorIgnore:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败将继续执行下面的 SQL。false:不再执行失败 SQL 后的任何语句。默认值为:false。 - JDBC 原生连接的使用请参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1955.html)。 +JDBC 原生连接的使用请参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1955.html)。 - **使用 TDengine 客户端驱动配置文件建立连接 ** +**使用 TDengine 客户端驱动配置文件建立连接 ** - 当使用 JDBC 原生连接连接 TDengine 集群时,可以使用 TDengine 客户端驱动配置文件,在配置文件中指定集群的 firstEp、secondEp 等参数。如下所示: +当使用 JDBC 原生连接连接 TDengine 集群时,可以使用 TDengine 客户端驱动配置文件,在配置文件中指定集群的 firstEp、secondEp 等参数。如下所示: - 1. 在 Java 应用中不指定 hostname 和 port +1. 在 Java 应用中不指定 hostname 和 port - ```java - public Connection getConn() throws Exception{ - Class.forName("com.taosdata.jdbc.TSDBDriver"); - 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; - } - ``` +```java +public Connection getConn() throws Exception{ + Class.forName("com.taosdata.jdbc.TSDBDriver"); + 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. 在配置文件中指定 firstEp 和 secondEp +2. 在配置文件中指定 firstEp 和 secondEp - ```shell - # first fully qualified domain name (FQDN) for TDengine system - firstEp cluster_node1:6030 +```shell +# 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 +# second fully qualified domain name (FQDN) for TDengine system, for cluster only +secondEp cluster_node2:6030 - # default system charset - # charset UTF-8 +# default system charset +# charset UTF-8 - # system locale - # locale en_US.UTF-8 - ``` +# system locale +# locale en_US.UTF-8 +``` - 以上示例,jdbc 会使用客户端的配置文件,建立到 hostname 为 cluster_node1、端口为 6030、数据库名为 test 的连接。当集群中 firstEp 节点失效时,JDBC 会尝试使用 secondEp - 连接集群。 +以上示例,jdbc 会使用客户端的配置文件,建立到 hostname 为 cluster_node1、端口为 6030、数据库名为 test 的连接。当集群中 firstEp 节点失效时,JDBC 会尝试使用 secondEp 连接集群。 - TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可以正常建立到集群的连接。 +TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可以正常建立到集群的连接。 - > **注意**:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件,Linux OS 上默认值 /etc/taos/taos.cfg ,Windows OS 上默认值 - C://TDengine/cfg/taos.cfg。 +> **注意**:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件,Linux OS 上默认值 /etc/taos/taos.cfg ,Windows OS 上默认值 C://TDengine/cfg/taos.cfg。 - - + + - ```java - Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); - String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata"; - Connection conn = DriverManager.getConnection(jdbcUrl); - ``` +```java +Class.forName("com.taosdata.jdbc.rs.RestfulDriver"); +String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata"; +Connection conn = DriverManager.getConnection(jdbcUrl); +``` - 以上示例,使用了 JDBC REST 连接的 RestfulDriver,建立了到 hostname 为 taosdemo.com,端口为 6041,数据库名为 test 的连接。这个 URL 中指定用户名(user)为 - root,密码(password)为 taosdata。 +以上示例,使用了 JDBC REST 连接的 RestfulDriver,建立了到 hostname 为 taosdemo.com,端口为 6041,数据库名为 test 的连接。这个 URL 中指定用户名(user)为 root,密码(password)为 taosdata。 - 使用 JDBC REST 连接,不需要依赖客户端驱动。与 JDBC 原生连接相比,仅需要: +使用 JDBC REST 连接,不需要依赖客户端驱动。与 JDBC 原生连接相比,仅需要: - 1. driverClass 指定为“com.taosdata.jdbc.rs.RestfulDriver”; - 2. jdbcUrl 以“jdbc:TAOS-RS://”开头; - 3. 使用 6041 作为连接端口。 +1. driverClass 指定为“com.taosdata.jdbc.rs.RestfulDriver”; +2. jdbcUrl 以“jdbc:TAOS-RS://”开头; +3. 使用 6041 作为连接端口。 - url 中的配置参数如下: +url 中的配置参数如下: - - user:登录 TDengine 用户名,默认值 'root'。 - - password:用户登录密码,默认值 'taosdata'。 - - batchfetch: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:false。逐行拉取结果集使用 HTTP 方式进行数据传输。JDBC REST - 连接支持批量拉取数据功能。taos-jdbcdriver 与 TDengine 之间通过 WebSocket 连接进行数据传输。相较于 HTTP,WebSocket 可以使 JDBC REST 连接支持大数据量查询,并提升查询性能。 - - charset: 当开启批量拉取数据时,指定解析字符串数据的字符集。 - - batchErrorIgnore:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败,继续执行下面的 SQL 了。false:不再执行失败 SQL - 后的任何语句。默认值为:false。 - - httpConnectTimeout: 连接超时时间,单位 ms, 默认值为 5000。 - - httpSocketTimeout: socket 超时时间,单位 ms,默认值为 5000。仅在 batchfetch 设置为 false 时生效。 - - messageWaitTimeout: 消息超时时间, 单位 ms, 默认值为 3000。 仅在 batchfetch 设置为 true 时生效。 - - useSSL: 连接中是否使用 SSL。 +- user:登录 TDengine 用户名,默认值 'root'。 +- password:用户登录密码,默认值 'taosdata'。 +- batchfetch: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:false。逐行拉取结果集使用 HTTP 方式进行数据传输。JDBC REST 连接支持批量拉取数据功能。taos-jdbcdriver 与 TDengine 之间通过 WebSocket 连接进行数据传输。相较于 HTTP,WebSocket 可以使 JDBC REST 连接支持大数据量查询,并提升查询性能。 +- charset: 当开启批量拉取数据时,指定解析字符串数据的字符集。 +- batchErrorIgnore:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败,继续执行下面的 SQL 了。false:不再执行失败 SQL 后的任何语句。默认值为:false。 +- httpConnectTimeout: 连接超时时间,单位 ms, 默认值为 5000。 +- httpSocketTimeout: socket 超时时间,单位 ms,默认值为 5000。仅在 batchfetch 设置为 false 时生效。 +- messageWaitTimeout: 消息超时时间, 单位 ms, 默认值为 3000。 仅在 batchfetch 设置为 true 时生效。 +- useSSL: 连接中是否使用 SSL。 - **注意**:部分配置项(比如:locale、timezone)在 REST 连接中不生效。 +**注意**:部分配置项(比如:locale、timezone)在 REST 连接中不生效。 - :::note +:::note - - 与原生连接方式不同,REST 接口是无状态的。在使用 JDBC REST 连接时,需要在 SQL 中指定表、超级表的数据库名称。例如: +- 与原生连接方式不同,REST 接口是无状态的。在使用 JDBC REST 连接时,需要在 SQL 中指定表、超级表的数据库名称。例如: - ```sql - INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('California.SanFrancisco') VALUES(now, 24.6); - ``` +```sql +INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('California.SanFrancisco') VALUES(now, 24.6); +``` - - 如果在 url 中指定了 dbname,那么,JDBC REST 连接会默认使用/rest/sql/dbname 作为 restful 请求的 url,在 SQL 中不需要指定 dbname。例如:url 为 - jdbc:TAOS-RS://127.0.0.1:6041/test,那么,可以执行 sql:insert into t1 using weather(ts, temperature) - tags('California.SanFrancisco') values(now, 24.6); +- 如果在 url 中指定了 dbname,那么,JDBC REST 连接会默认使用/rest/sql/dbname 作为 restful 请求的 url,在 SQL 中不需要指定 dbname。例如:url 为 jdbc:TAOS-RS://127.0.0.1:6041/test,那么,可以执行 sql:insert into t1 using weather(ts, temperature) tags('California.SanFrancisco') values(now, 24.6); - ::: +::: - + ### 指定 URL 和 Properties 获取连接 @@ -708,7 +699,10 @@ TaosConsumer consumer = new TaosConsumer<>(config); - enable.auto.commit: 是否允许自动提交。 - group.id: consumer: 所在的 group。 - value.deserializer: 结果集反序列化方法,可以继承 `com.taosdata.jdbc.tmq.ReferenceDeserializer`,并指定结果集 bean,实现反序列化。也可以继承 `com.taosdata.jdbc.tmq.Deserializer`,根据 SQL 的 resultSet 自定义反序列化方式。 -- 其他参数请参考:[Consumer 参数列表](../../../develop/tmq#创建-consumer-以及consumer-group) +- td.connect.type: 连接方式。jni:表示使用动态库连接的方式,ws/WebSocket:表示使用 WebSocket 进行数据通信。默认为 jni 方式。 +- httpConnectTimeout:创建连接超时参数,单位 ms,默认为 5000 ms。仅在 WebSocket 连接下有效。 +- messageWaitTimeout:数据传输超时参数,单位 ms,默认为 10000 ms。仅在 WebSocket 连接下有效。 +其他参数请参考:[Consumer 参数列表](../../../develop/tmq#创建-consumer-以及consumer-group) #### 订阅消费数据 @@ -734,7 +728,10 @@ consumer.close() 详情请参考:[数据订阅](../../../develop/tmq) -### 使用示例如下: +#### 完整示例 + + + ```java public abstract class ConsumerLoop { @@ -807,6 +804,89 @@ public abstract class ConsumerLoop { } ``` + + + +除了原生的连接方式,Java 连接器还支持通过 WebSocket 订阅数据。 + +```java +public abstract class ConsumerLoop { + private final TaosConsumer consumer; + private final List topics; + private final AtomicBoolean shutdown; + private final CountDownLatch shutdownLatch; + + public ConsumerLoop() throws SQLException { + Properties config = new Properties(); + config.setProperty("bootstrap.servers", "localhost:6041"); + config.setProperty("td.connect.type", "ws"); + config.setProperty("msg.with.table.name", "true"); + config.setProperty("enable.auto.commit", "true"); + config.setProperty("group.id", "group2"); + config.setProperty("value.deserializer", "com.taosdata.jdbc.tmq.ConsumerTest.ConsumerLoop$ResultDeserializer"); + + this.consumer = new TaosConsumer<>(config); + this.topics = Collections.singletonList("topic_speed"); + this.shutdown = new AtomicBoolean(false); + this.shutdownLatch = new CountDownLatch(1); + } + + public abstract void process(ResultBean result); + + public void pollData() throws SQLException { + try { + consumer.subscribe(topics); + + while (!shutdown.get()) { + ConsumerRecords records = consumer.poll(Duration.ofMillis(100)); + for (ResultBean record : records) { + process(record); + } + } + consumer.unsubscribe(); + } finally { + consumer.close(); + shutdownLatch.countDown(); + } + } + + public void shutdown() throws InterruptedException { + shutdown.set(true); + shutdownLatch.await(); + } + + public static class ResultDeserializer extends ReferenceDeserializer { + + } + + public static class ResultBean { + private Timestamp ts; + private int speed; + + public Timestamp getTs() { + return ts; + } + + public void setTs(Timestamp ts) { + this.ts = ts; + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + } +} +``` + + + + +> **注意**:这里的 value.deserializer 配置参数值应该根据测试环境的包路径做相应的调整。 + ### 与连接池使用 #### HikariCP @@ -890,8 +970,10 @@ public static void main(String[] args) throws Exception { | taos-jdbcdriver 版本 | 主要变化 | | :------------------: | :----------------------------: | -| 3.0.1 - 3.0.2 | 修复一些情况下结果集数据解析错误的问题。3.0.1 在 JDK 11 环境编译,JDK 8 环境下建议使用 3.0.2 版本 | +| 3.1.0 | WebSocket 连接支持订阅功能 | +| 3.0.1 - 3.0.4 | 修复一些情况下结果集数据解析错误的问题。3.0.1 在 JDK 11 环境编译,JDK 8 环境下建议使用其他版本 | | 3.0.0 | 支持 TDengine 3.0 | +| 2.0.42 | 修在 WebSocket 连接中 wasNull 接口返回值 | | 2.0.41 | 修正 REST 连接中用户名和密码转码方式 | | 2.0.39 - 2.0.40 | 增加 REST 连接/请求 超时设置 | | 2.0.38 | JDBC REST 连接增加批量拉取功能 | @@ -928,7 +1010,7 @@ public static void main(String[] args) throws Exception { **原因**:taos-jdbcdriver 3.0.1 版本需要在 JDK 11+ 环境使用。 -**解决方法**: 更换 taos-jdbcdriver 3.0.2 版本。 +**解决方法**: 更换 taos-jdbcdriver 3.0.2+ 版本。 其它问题请参考 [FAQ](../../../train-faq/faq) diff --git a/docs/zh/08-connector/20-go.mdx b/docs/zh/08-connector/20-go.mdx index 0fc4007f6362697222b425c8c2c803b911b9ac8a..fd6df992b530fdce4427e34ef8bc227f449eaac7 100644 --- a/docs/zh/08-connector/20-go.mdx +++ b/docs/zh/08-connector/20-go.mdx @@ -15,7 +15,7 @@ import GoOpenTSDBTelnet from "../07-develop/03-insert-data/_go_opts_telnet.mdx" import GoOpenTSDBJson from "../07-develop/03-insert-data/_go_opts_json.mdx" import GoQuery from "../07-develop/04-query-data/_go.mdx" -`driver-go` 是 TDengine 的官方 Go 语言连接器,实现了 Go 语言[ database/sql ](https://golang.org/pkg/database/sql/) 包的接口。Go 开发人员可以通过它开发存取 TDengine 集群数据的应用软件。 +`driver-go` 是 TDengine 的官方 Go 语言连接器,实现了 Go 语言 [database/sql](https://golang.org/pkg/database/sql/) 包的接口。Go 开发人员可以通过它开发存取 TDengine 集群数据的应用软件。 `driver-go` 提供两种建立连接的方式。一种是**原生连接**,它通过 TDengine 客户端驱动程序(taosc)原生连接 TDengine 运行实例,支持数据写入、查询、订阅、schemaless 接口和参数绑定接口等功能。另外一种是 **REST 连接**,它通过 taosAdapter 提供的 REST 接口连接 TDengine 运行实例。REST 连接实现的功能特性集合和原生连接有少量不同。 @@ -112,6 +112,7 @@ REST 连接支持所有能运行 Go 的平台。 ```text username:password@protocol(address)/dbname?param=value ``` + ### 使用连接器进行连接 @@ -121,7 +122,7 @@ _taosSql_ 通过 cgo 实现了 Go 的 `database/sql/driver` 接口。只需要 使用 `taosSql` 作为 `driverName` 并且使用一个正确的 [DSN](#DSN) 作为 `dataSourceName`,DSN 支持的参数: -* configPath 指定 taos.cfg 目录 +* cfg 指定 taos.cfg 目录 示例: @@ -176,6 +177,7 @@ func main() { } } ``` +
@@ -207,6 +209,7 @@ func main() { } } ``` + @@ -357,33 +360,32 @@ func main() { #### 订阅 -* `func NewConsumer(conf *Config) (*Consumer, error)` - -创建消费者。 +* `func NewConsumer(conf *tmq.ConfigMap) (*Consumer, error)` -* `func (c *Consumer) Subscribe(topics []string) error` + 创建消费者。 -订阅主题。 +* `func (c *Consumer) Subscribe(topic string, rebalanceCb RebalanceCb) error` +注意:出于兼容目的保留 `rebalanceCb` 参数,当前未使用 -* `func (c *Consumer) Poll(timeout time.Duration) (*Result, error)` + 订阅单个主题。 -轮询消息。 +* `func (c *Consumer) SubscribeTopics(topics []string, rebalanceCb RebalanceCb) error` +注意:出于兼容目的保留 `rebalanceCb` 参数,当前未使用 -* `func (c *Consumer) Commit(ctx context.Context, message unsafe.Pointer) error` + 订阅主题。 -提交消息。 +* `func (c *Consumer) Poll(timeoutMs int) tmq.Event` -* `func (c *Consumer) FreeMessage(message unsafe.Pointer)` + 轮询消息。 -释放消息。 +* `func (c *Consumer) Commit() ([]tmq.TopicPartition, error)` +注意:出于兼容目的保留 `tmq.TopicPartition` 参数,当前未使用 -* `func (c *Consumer) Unsubscribe() error` - -取消订阅。 + 提交消息。 * `func (c *Consumer) Close() error` -关闭消费者。 + 关闭连接。 #### schemaless @@ -443,25 +445,32 @@ func main() { ### 通过 WebSocket 订阅 -* `func NewConsumer(config *Config) (*Consumer, error)` +* `func NewConsumer(conf *tmq.ConfigMap) (*Consumer, error)` + + 创建消费者。 + +* `func (c *Consumer) Subscribe(topic string, rebalanceCb RebalanceCb) error` +注意:出于兼容目的保留 `rebalanceCb` 参数,当前未使用 - 创建消费者。 + 订阅单个主题。 -* `func (c *Consumer) Subscribe(topic []string) error` +* `func (c *Consumer) SubscribeTopics(topics []string, rebalanceCb RebalanceCb) error` +注意:出于兼容目的保留 `rebalanceCb` 参数,当前未使用 - 订阅主题。 + 订阅主题。 -* `func (c *Consumer) Poll(timeout time.Duration) (*Result, error)` +* `func (c *Consumer) Poll(timeoutMs int) tmq.Event` - 轮询消息。 + 轮询消息。 -* `func (c *Consumer) Commit(messageID uint64) error` +* `func (c *Consumer) Commit() ([]tmq.TopicPartition, error)` +注意:出于兼容目的保留 `tmq.TopicPartition` 参数,当前未使用 - 提交消息。 + 提交消息。 * `func (c *Consumer) Close() error` - 关闭消费者。 + 关闭连接。 完整订阅示例参见 [GitHub 示例文件](https://github.com/taosdata/driver-go/blob/3.0/examples/tmqoverws/main.go) diff --git a/docs/zh/08-connector/26-rust.mdx b/docs/zh/08-connector/26-rust.mdx index eeb93a6558b755a6c179ecea86aae8b594fd16fe..5cf37f79468db8153f7ceeb70567ec0c5f09e5e7 100644 --- a/docs/zh/08-connector/26-rust.mdx +++ b/docs/zh/08-connector/26-rust.mdx @@ -64,6 +64,13 @@ taos = "*" taos = { version = "*", default-features = false, features = ["ws"] } ``` +当仅启用 `ws` 特性时,可同时指定 `r2d2` 使得在同步(blocking/sync)模式下使用 [r2d2] 作为连接池: + +```toml +[dependencies] +taos = { version = "*", default-features = false, features = ["r2d2", "ws"] } +``` + @@ -252,26 +259,24 @@ let conn: Taos = cfg.build(); ### 连接池 -在复杂应用中,建议启用连接池。[taos] 的连接池使用 [r2d2] 实现。 +在复杂应用中,建议启用连接池。[taos] 的连接池默认(异步模式)使用 [deadpool] 实现。 如下,可以生成一个默认参数的连接池。 ```rust -let pool = TaosBuilder::from_dsn(dsn)?.pool()?; +let pool: Pool = TaosBuilder::from_dsn("taos:///") + .unwrap() + .pool() + .unwrap(); ``` 同样可以使用连接池的构造器,对连接池参数进行设置: ```rust -let dsn = "taos://localhost:6030"; - -let opts = PoolBuilder::new() - .max_size(5000) // max connections - .max_lifetime(Some(Duration::from_secs(60 * 60))) // lifetime of each connection - .min_idle(Some(1000)) // minimal idle connections - .connection_timeout(Duration::from_secs(2)); - -let pool = TaosBuilder::from_dsn(dsn)?.with_pool_builder(opts)?; +let pool: Pool = Pool::builder(Manager::from_dsn(self.dsn.clone()).unwrap().0) + .max_size(88) // 最大连接数 + .build() + .unwrap(); ``` 在应用代码中,使用 `pool.get()?` 来获取一个连接对象 [Taos]。 @@ -511,6 +516,7 @@ consumer.unsubscribe().await; 其他相关结构体 API 使用说明请移步 Rust 文档托管网页:。 [taos]: https://github.com/taosdata/rust-connector-taos +[deadpool]: https://crates.io/crates/deadpool [r2d2]: https://crates.io/crates/r2d2 [TaosBuilder]: https://docs.rs/taos/latest/taos/struct.TaosBuilder.html [TaosCfg]: https://docs.rs/taos/latest/taos/struct.TaosCfg.html diff --git a/docs/zh/08-connector/30-python.mdx b/docs/zh/08-connector/30-python.mdx index 2ca11800c8b34dd8fe815cad8e81fe7b6faf79ad..5395610df3ce5535293f8017f5e14c403e9a8279 100644 --- a/docs/zh/08-connector/30-python.mdx +++ b/docs/zh/08-connector/30-python.mdx @@ -10,7 +10,9 @@ import TabItem from "@theme/TabItem"; `taospy` 是 TDengine 的官方 Python 连接器。`taospy` 提供了丰富的 API, 使得 Python 应用可以很方便地使用 TDengine。`taospy` 对 TDengine 的[原生接口](../cpp)和 [REST 接口](../rest-api)都进行了封装, 分别对应 `taospy` 包的 `taos` 模块 和 `taosrest` 模块。 除了对原生接口和 REST 接口的封装,`taospy` 还提供了符合 [Python 数据访问规范(PEP 249)](https://peps.python.org/pep-0249/) 的编程接口。这使得 `taospy` 和很多第三方工具集成变得简单,比如 [SQLAlchemy](https://www.sqlalchemy.org/) 和 [pandas](https://pandas.pydata.org/)。 -使用客户端驱动提供的原生接口直接与服务端建立的连接的方式下文中称为“原生连接”;使用 taosAdapter 提供的 REST 接口与服务端建立的连接的方式下文中称为“REST 连接”。 +`taos-ws-py` 是使用 WebSocket 方式连接 TDengine 的 Python 连接器包。可以选装。 + +使用客户端驱动提供的原生接口直接与服务端建立的连接的方式下文中称为“原生连接”;使用 taosAdapter 提供的 REST 接口或 WebSocket 接口与服务端建立的连接的方式下文中称为“REST 连接”或“WebSocket 连接”。 Python 连接器的源码托管在 [GitHub](https://github.com/taosdata/taos-connector-python)。 @@ -32,7 +34,7 @@ Python 连接器的源码托管在 [GitHub](https://github.com/taosdata/taos-con ### 准备 -1. 安装 Python。建议使用 Python >= 3.7。如果系统上还没有 Python 可参考 [Python BeginnersGuide](https://wiki.python.org/moin/BeginnersGuide/Download) 安装。 +1. 安装 Python。新近版本 taospy 包要求 Python 3.6.2+。早期版本 taospy 包要求 Python 3.7+。taos-ws-py 包要求 Python 3.7+。如果系统上还没有 Python 可参考 [Python BeginnersGuide](https://wiki.python.org/moin/BeginnersGuide/Download) 安装。 2. 安装 [pip](https://pypi.org/project/pip/)。大部分情况下 Python 的安装包都自带了 pip 工具, 如果没有请参考 [pip documentation](https://pip.pypa.io/en/stable/installation/) 安装。 3. 如果使用原生连接,还需[安装客户端驱动](../#安装客户端驱动)。客户端软件包含了 TDengine 客户端动态链接库(libtaos.so 或 taos.dll) 和 TDengine CLI。 @@ -78,6 +80,23 @@ pip3 install git+https://github.com/taosdata/taos-connector-python.git +#### 安装 `taos-ws-py`(可选) + +taos-ws-py 包提供了通过 WebSocket 连接 TDengine 的能力,可选安装 taos-ws-py 以获得 WebSocket 连接 TDengine 的能力。 + + +##### 和 taospy 同时安装 + +```bash +pip3 install taospy[ws] +``` + +##### 单独安装 + +```bash +pip3 install taos-ws-py +``` + ### 安装验证 @@ -98,6 +117,15 @@ import taos import taosrest ``` + + + +对于 WebSocket 连接,只需验证是否能成功导入 `taosws` 模块。可在 Python 交互式 Shell 中输入: + +```python +import taosws +``` + @@ -166,6 +194,27 @@ curl -u root:taosdata http://:/rest/sql -d "select server_version()" } ``` + + + +对于 WebSocket 连接, 除了确保集群已经启动,还要确保 taosAdapter 组件已经启动。可以使用如下 curl 命令测试: + +``` +curl -i -N -d "show databases" -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: :" -H "Origin: http://:" http://:/rest/sql +``` + +上面的 FQDN 为运行 taosAdapter 的机器的 FQDN, PORT 为 taosAdapter 配置的监听端口, 默认为 6041。 +如果测试成功,会输出服务器版本信息,比如: + +```json +HTTP/1.1 200 OK +Content-Type: application/json; charset=utf-8 +Date: Tue, 21 Mar 2023 09:29:17 GMT +Transfer-Encoding: chunked + +{"status":"succ","head":["server_version()"],"column_meta":[["server_version()",8,8]],"data":[["2.6.0.27"]],"rows":1} +``` + @@ -212,6 +261,16 @@ curl -u root:taosdata http://:/rest/sql -d "select server_version()" - `password`: TDengine 用户密码。默认是 taosdata。 - `timeout`: HTTP 请求超时时间。单位为秒。默认为 `socket._GLOBAL_DEFAULT_TIMEOUT`。 一般无需配置。 + + + + +```python +{{#include docs/examples/python/connect_websocket_examples.py:connect}} +``` + +`connect()` 函数参数为连接 url,协议为 `taosws` 或 `ws` + @@ -281,8 +340,94 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线 ``` 对于 `sql()` 方法更详细的介绍, 请参考 [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html)。 + + + +```python +{{#include docs/examples/python/connect_websocket_examples.py:basic}} +``` + +- `conn.execute`: 用来执行任意 SQL 语句,返回影响的行数 +- `conn.query`: 用来执行查询 SQL 语句,返回查询结果 + + + + +### 与 req_id 一起使用 + +使用可选的 req_id 参数,指定请求 id,可以用于 tracing + + + + +##### TaosConnection 类的使用 + +`TaosConnection` 类既包含对 PEP249 Connection 接口的实现(如:`cursor`方法和 `close` 方法),也包含很多扩展功能(如: `execute`、 `query`、`schemaless_insert` 和 `subscribe` 方法。 + +```python title="execute 方法" +{{#include docs/examples/python/connection_usage_native_reference_with_req_id.py:insert}} +``` + +```python title="query 方法" +{{#include docs/examples/python/connection_usage_native_reference_with_req_id.py:query}} +``` + +:::tip +查询结果只能获取一次。比如上面的示例中 `fetch_all()` 和 `fetch_all_into_dict()` 只能用一个。重复获取得到的结果为空列表。 +::: + +##### TaosResult 类的使用 + +上面 `TaosConnection` 类的使用示例中,我们已经展示了两种获取查询结果的方法: `fetch_all()` 和 `fetch_all_into_dict()`。除此之外 `TaosResult` 还提供了按行迭代(`rows_iter`)或按数据块迭代(`blocks_iter`)结果集的方法。在查询数据量较大的场景,使用这两个方法会更高效。 + +```python title="blocks_iter 方法" +{{#include docs/examples/python/result_set_with_req_id_examples.py}} +``` +##### TaosCursor 类的使用 + +`TaosConnection` 类和 `TaosResult` 类已经实现了原生接口的所有功能。如果你对 PEP249 规范中的接口比较熟悉也可以使用 `TaosCursor` 类提供的方法。 + +```python title="TaosCursor 的使用" +{{#include docs/examples/python/cursor_usage_native_reference_with_req_id.py}} +``` + +:::note +TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线程的场景下,这个游标实例必须保持线程独享,不能跨线程共享使用,否则会导致返回结果出现错误。 + +::: + + + + +##### TaosRestCursor 类的使用 + +`TaosRestCursor` 类是对 PEP249 Cursor 接口的实现。 + +```python title="TaosRestCursor 的使用" +{{#include docs/examples/python/connect_rest_with_req_id_examples.py:basic}} +``` +- `cursor.execute` : 用来执行任意 SQL 语句。 +- `cursor.rowcount`: 对于写入操作返回写入成功记录数。对于查询操作,返回结果集行数。 +- `cursor.description` : 返回字段的描述信息。关于描述信息的具体格式请参考[TaosRestCursor](https://docs.taosdata.com/api/taospy/taosrest/cursor.html)。 + +##### RestClient 类的使用 + +`RestClient` 类是对于 [REST API](../rest-api) 的直接封装。它只包含一个 `sql()` 方法用于执行任意 SQL 语句, 并返回执行结果。 + +```python title="RestClient 的使用" +{{#include docs/examples/python/rest_client_with_req_id_example.py}} +``` + +对于 `sql()` 方法更详细的介绍, 请参考 [RestClient](https://docs.taosdata.com/api/taospy/taosrest/restclient.html)。 + + +```python +{{#include docs/examples/python/connect_websocket_with_req_id_examples.py:basic}} +``` +- `conn.execute`: 用来执行任意 SQL 语句,返回影响的行数 +- `conn.query`: 用来执行查询 SQL 语句,返回查询结果 @@ -303,6 +448,39 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线 {{#include docs/examples/python/conn_rest_pandas.py}} ``` + + + +```python +{{#include docs/examples/python/conn_websocket_pandas.py}} +``` + + + + +### 数据订阅 + +连接器支持数据订阅功能,数据订阅功能请参考 [数据订阅](../../develop/tmq/)。 + + + + +`Consumer` 提供了 Python 连接器订阅 TMQ 数据的 API,相关 API 定义请参考 [数据订阅文档](../../develop/tmq/#%E4%B8%BB%E8%A6%81%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C-api)。 + +```python +{{#include docs/examples/python/tmq_example.py}} +``` + + + + + +除了原生的连接方式,Python 连接器还支持通过 websocket 订阅 TMQ 数据。 + +```python +{{#include docs/examples/python/tmq_websocket_example.py}} +``` + @@ -314,7 +492,7 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线 | [bind_row.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/bind-row.py) | 参数绑定,一次绑定一行 | | [insert_lines.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/insert-lines.py) | InfluxDB 行协议写入 | | [json_tag.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/json-tag.py) | 使用 JSON 类型的标签 | -| [tmq.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/tmq.py) | tmq 订阅 | +| [tmq_consumer.py](https://github.com/taosdata/taos-connector-python/blob/main/examples/tmq_consumer.py) | tmq 订阅 | ## 其它说明 @@ -325,7 +503,7 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线 ```python {{#include docs/examples/python/handle_exception.py}} ``` - +`` ### 关于纳秒 (nanosecond) 由于目前 Python 对 nanosecond 支持的不完善(见下面的链接),目前的实现方式是在 nanosecond 精度时返回整数,而不是 ms 和 us 返回的 datetime 类型,应用开发者需要自行处理,建议使用 pandas 的 to_datetime()。未来如果 Python 正式完整支持了纳秒,Python 连接器可能会修改相关接口。 diff --git a/docs/zh/08-connector/35-node.mdx b/docs/zh/08-connector/35-node.mdx index 35c28e3b9fc52698b813e65191732d3dd84c336e..25f8bdf1775357f4c81d11e37bfeb4f6f13a3d09 100644 --- a/docs/zh/08-connector/35-node.mdx +++ b/docs/zh/08-connector/35-node.mdx @@ -31,7 +31,8 @@ REST 连接器支持所有能运行 Node.js 的平台。 ## 支持的功能特性 -### 原生连接器 + + 1. 连接管理 2. 普通查询 @@ -40,12 +41,17 @@ REST 连接器支持所有能运行 Node.js 的平台。 5. 订阅功能 6. Schemaless -### REST 连接器 + + 1. 连接管理 2. 普通查询 3. 连续查询 + + + + ## 安装步骤 ### 安装前准备 @@ -62,6 +68,16 @@ REST 连接器支持所有能运行 Node.js 的平台。 - C 语言编译器,[GCC](https://gcc.gnu.org) v4.8.5 或更高版本 + + + +- `python` (建议`v2.7` , `v3.x.x` 目前还不支持) +- `@tdengine/client` 3.0.0 目前是只支持 Node.js v12.22.12 或 v12 的更高版本;其他版本可能存在包兼容性的问题 +- `make` +- C 语言编译器,[GCC](https://gcc.gnu.org) v4.8.5 或更高版本 + + + - 安装方法 1 @@ -104,6 +120,9 @@ npm install @tdengine/rest ### 安装验证 + + + 在安装好 TDengine 客户端后,使用 nodejsChecker.js 程序能够验证当前环境是否支持 Node.js 方式访问 TDengine。 验证方法: @@ -120,11 +139,35 @@ node nodejsChecker.js host=localhost - 执行以上步骤后,在命令行会输出 nodejsChecker.js 连接 TDengine 实例,并执行简单插入和查询的结果。 + + + +在安装好 TDengine 客户端后,使用 nodejsChecker.js 程序能够验证当前环境是否支持 Node.js 方式访问 TDengine。 + +验证方法: + +- 新建安装验证目录,例如:`~/tdengine-test`,下载 GitHub 上 [restChecker.js 源代码](https://github.com/taosdata/TDengine/tree/3.0/docs/examples/node/restexample/restChecker.js)到本地。 + +- 在命令行中执行以下命令。 + +```bash +npm init -y +npm install @tdengine/rest +node restChecker.js +``` + +- 执行以上步骤后,在命令行会输出 restChecker.js 连接 TDengine 实例,并执行简单插入和查询的结果。 + + + + + + ## 建立连接 请选择使用一种连接器。 - + 安装并引用 `@tdengine/client` 包。 @@ -171,24 +214,71 @@ let cursor = conn.cursor(); #### SQL 写入 + + + + + + +```js +{{#include docs/examples/node/restexample/insert_example.js}} +``` + + + + + + #### InfluxDB 行协议写入 + + + + + + #### OpenTSDB Telnet 行协议写入 + + + + + + #### OpenTSDB JSON 行协议写入 + + + + + + ### 查询数据 + + + + + + + +```js +{{#include docs/examples/node/restexample/query_example.js}} +``` + + + + ## 更多示例程序 diff --git a/docs/zh/08-connector/40-csharp.mdx b/docs/zh/08-connector/40-csharp.mdx index a1a161d4eea9e2534ebb3a573211dcfae5dbb21f..3a945e77fd3295061847063e7c2d0de4a67790a5 100644 --- a/docs/zh/08-connector/40-csharp.mdx +++ b/docs/zh/08-connector/40-csharp.mdx @@ -17,7 +17,7 @@ import CSAsyncQuery from "../07-develop/04-query-data/_cs_async.mdx" `TDengine.Connector` 是 TDengine 提供的 C# 语言连接器。C# 开发人员可以通过它开发存取 TDengine 集群数据的 C# 应用软件。 -`TDengine.Connector` 连接器支持通过 TDengine 客户端驱动(taosc)建立与 TDengine 运行实例的连接,提供数据写入、查询、数据订阅、schemaless 数据写入、参数绑定接口数据写入等功能。 `TDengine.Connector` 还支持 WebSocket,通过 DSN 建立 WebSocket 连接,提供数据写入、查询、参数绑定接口数据写入等功能。 +`TDengine.Connector` 连接器支持通过 TDengine 客户端驱动(taosc)建立与 TDengine 运行实例的连接,提供数据写入、查询、数据订阅、schemaless 数据写入、参数绑定接口数据写入等功能。 `TDengine.Connector` 自 v3.0.1 起还支持 WebSocket,通过 DSN 建立 WebSocket 连接,提供数据写入、查询、参数绑定接口数据写入等功能。 本文介绍如何在 Linux 或 Windows 环境中安装 `TDengine.Connector`,并通过 `TDengine.Connector` 连接 TDengine 集群,进行数据写入、查询等基本操作。 @@ -67,30 +67,45 @@ import CSAsyncQuery from "../07-develop/04-query-data/_cs_async.mdx" * [Nuget 客户端](https://docs.microsoft.com/en-us/nuget/install-nuget-client-tools) (可选安装) * 安装 TDengine 客户端驱动,具体步骤请参考[安装客户端驱动](../#安装客户端驱动) -### 使用 dotnet CLI 安装 +### 安装 TDengine.Connector - + -可以在当前 .NET 项目的路径下,通过 dotnet 命令引用 Nuget 中发布的 `TDengine.Connector` 到当前项目。 +可以在当前 .NET 项目的路径下,通过 dotnet CLI 添加 Nuget package `TDengine.Connector` 到当前项目。 ``` bash dotnet add package TDengine.Connector ``` +也可以修改当前项目的 `.csproj` 文件,添加如下 ItemGroup。 + +``` XML + + + +``` + - -也可以[下载源码](https://github.com/taosdata/taos-connector-dotnet/tree/3.0),直接引用 TDengine.Connector 库 + -```bash -git clone -b 3.0 https://github.com/taosdata/taos-connector-dotnet.git -cd taos-connector-dotnet -cp -r src/ myProject +需要修改目标项目的 `.csproj` 项目文件,将 `.nupkg` 中的 `runtimes` 目录中的动态库复制到当前项目的 `$(OutDir)` 目录下。 -cd myProject -dotnet add exmaple.csproj reference src/TDengine.csproj +```XML + + + + + + + + + ``` + +注意:`TDengine.Connector` 自 version>= 3.0.2 的 nuget package 中才会有动态库( taosws.dll,libtaows.so )。 + @@ -148,9 +163,9 @@ namespace TDengineExample 各部分意义见下表: -* **protocol**: 显示指定以何种方式建立连接,例如:`ws://localhost:6041` 指定以 Websocket 方式建立连接(支持http/ws)。 +* **protocol**: 显示指定以何种方式建立连接,例如:`ws://localhost:6041` 指定以 Websocket 方式建立连接(支持 http/ws )。 -* **username/password**: 用于创建连接的用户名及密码(默认`root/taosdata`)。 +* **username/password**: 用于创建连接的用户名及密码(默认 `root/taosdata` )。 * **host/port**: 指定创建连接的服务器及端口,WebSocket 连接默认为 `localhost:6041` 。 @@ -253,19 +268,20 @@ namespace TDengineExample |示例程序 | 示例程序描述 | |--------------------------------------------------------------------------------------------------------------------|--------------------------------------------| -| [CURD](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/Query/Query.cs) | 使用 TDengine.Connector 实现的建表、插入、查询示例 | -| [JSON Tag](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/JSONTag) | 使用 TDengine.Connector 实现的写入和查询 JSON tag 类型数据的示例 | -| [stmt](https://github.com/taosdata/taos-connector-dotnet/tree/3.0/examples/Stmt) | 使用 TDengine.Connector 实现的参数绑定插入和查询的示例 | -| [schemaless](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/schemaless) | 使用 TDengine.Connector 实现的使用 schemaless 写入的示例 | -| [async query](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/AsyncQuery/QueryAsync.cs) | 使用 TDengine.Connector 实现的异步查询的示例 | -| [数据订阅(TMQ)](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/TMQ/TMQ.cs) | 使用 TDengine.Connector 实现的订阅数据的示例 | -| [Basic WebSocket Usage](https://github.com/taosdata/taos-connector-dotnet/blob/5a4a7cd0dbcda114447cdc6d0c6dedd8e84a52da/examples/WS/WebSocketSample.cs) | 使用 TDengine.Connector 的 WebSocket 基本的示例 | -| [Basic WebSocket STMT](https://github.com/taosdata/taos-connector-dotnet/blob/5a4a7cd0dbcda114447cdc6d0c6dedd8e84a52da/examples/WS/WebSocketSTMT.cs) | 使用 TDengine.Connector 的 WebSocket STMT 基本的示例 | +| [CURD](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/Query/Query.cs) | 使用 TDengine.Connector 实现的建表、插入、查询示例 | +| [JSON Tag](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/JSONTag) | 使用 TDengine.Connector 实现的写入和查询 JSON tag 类型数据的示例 | +| [stmt](https://github.com/taosdata/taos-connector-dotnet/tree/3.0/examples/NET6Examples/Stmt) | 使用 TDengine.Connector 实现的参数绑定插入和查询的示例 | +| [schemaless](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/schemaless) | 使用 TDengine.Connector 实现的使用 schemaless 写入的示例 | +| [async query](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/AsyncQuery/QueryAsync.cs) | 使用 TDengine.Connector 实现的异步查询的示例 | +| [数据订阅(TMQ)](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/NET6Examples/TMQ/TMQ.cs) | 使用 TDengine.Connector 实现的订阅数据的示例 | +| [Basic WebSocket Usage](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/FrameWork45/WS/WebSocketSample.cs) | 使用 TDengine.Connector 的 WebSocket 基本的示例 | +| [Basic WebSocket STMT](https://github.com/taosdata/taos-connector-dotnet/blob/3.0/examples/FrameWork45/WS/WebSocketSTMT.cs) | 使用 TDengine.Connector 的 WebSocket STMT 基本的示例 | ## 重要更新记录 | TDengine.Connector | 说明 | |--------------------|--------------------------------| +| 3.0.2 | 支持 .NET Framework 4.5 及以上,支持 .NET standard 2.0。Nuget Package 包含 WebSocket 动态库。 | | 3.0.1 | 支持 WebSocket 和 Cloud,查询,插入,参数绑定。 | | 3.0.0 | 支持 TDengine 3.0.0.0,不兼容 2.x。新增接口TDengine.Impl.GetData(),解析查询结果。 | | 1.0.7 | 修复 TDengine.Query()内存泄露。 | diff --git a/docs/zh/08-connector/_linux_install.mdx b/docs/zh/08-connector/_linux_install.mdx index 0b1f415f54d28e65a519d35ab94a84b3aa8338ba..b16ab2ac5b0696ee8e4077706e80f6e4267faf1b 100644 --- a/docs/zh/08-connector/_linux_install.mdx +++ b/docs/zh/08-connector/_linux_install.mdx @@ -14,7 +14,7 @@ import PkgListV3 from "/components/PkgListV3"; 解压软件包之后,会在解压目录下看到以下文件(目录): - _ install_client.sh_:安装脚本,用于应用驱动程序 - - _ taos.tar.gz_:应用驱动安装包 + - _ package.tar.gz_:应用驱动安装包 - _ driver_:TDengine 应用驱动 driver - _examples_: 各种编程语言的示例程序(c/C#/go/JDBC/MATLAB/python/R) 运行 install_client.sh 进行安装。 diff --git a/docs/zh/08-connector/index.md b/docs/zh/08-connector/index.md index a28a7cd66c1cc7598d473903eb95df5192d933d2..eb1f3a9a9a728f666f9964ef51795b76991d1fcc 100644 --- a/docs/zh/08-connector/index.md +++ b/docs/zh/08-connector/index.md @@ -60,7 +60,7 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器 | **连接管理** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | | **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | | **参数绑定** | 暂不支持 | 暂不支持 | 支持 | 支持 | 暂不支持 | 支持 | -| **数据订阅(TMQ)** | 暂不支持 | 暂不支持 | 支持 | 暂不支持 | 暂不支持 | 支持 | +| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 暂不支持 | 暂不支持 | 支持 | | **Schemaless** | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 | | **批量拉取(基于 WebSocket)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | | **DataFrame** | 不支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 | diff --git a/docs/zh/10-deployment/03-k8s.md b/docs/zh/10-deployment/03-k8s.md index 0cae59657c2a0199d3452bc37d36f2c537944d21..39ca56f3d978062f175ef8196ad1affe4bcd562b 100644 --- a/docs/zh/10-deployment/03-k8s.md +++ b/docs/zh/10-deployment/03-k8s.md @@ -102,7 +102,7 @@ spec: # Must set if you want a cluster. - name: TAOS_FIRST_EP value: "$(STS_NAME)-0.$(SERVICE_NAME).$(STS_NAMESPACE).svc.cluster.local:$(TAOS_SERVER_PORT)" - # TAOS_FQND should always be setted in k8s env. + # TAOS_FQND should always be set in k8s env. - name: TAOS_FQDN value: "$(POD_NAME).$(SERVICE_NAME).$(STS_NAMESPACE).svc.cluster.local" volumeMounts: diff --git a/docs/zh/10-deployment/05-helm.md b/docs/zh/10-deployment/05-helm.md index 9a3b21f09296e6f5a8dbd089225b6580b9567586..b2c405033f2814e3be5bcb298675e3bfb628babd 100644 --- a/docs/zh/10-deployment/05-helm.md +++ b/docs/zh/10-deployment/05-helm.md @@ -4,7 +4,7 @@ title: 使用 Helm 部署 TDengine 集群 description: 使用 Helm 部署 TDengine 集群的详细指南 --- -Helm 是 Kubernetes 的包管理器,上一节使用 Kubernets 部署 TDengine 集群的操作已经足够简单,但 Helm 依然可以提供更强大的能力。 +Helm 是 Kubernetes 的包管理器,上一节使用 Kubernetes 部署 TDengine 集群的操作已经足够简单,但 Helm 依然可以提供更强大的能力。 ## 安装 Helm @@ -23,7 +23,7 @@ Helm 会使用 kubectl 和 kubeconfig 的配置来操作 Kubernetes,可以参 TDengine Chart 尚未发布到 Helm 仓库,当前可以从 GitHub 直接下载: ```bash -wget https://github.com/taosdata/TDengine-Operator/raw/3.0/helm/tdengine-3.0.0.tgz +wget https://github.com/taosdata/TDengine-Operator/raw/3.0/helm/tdengine-3.0.2.tgz ``` @@ -39,7 +39,7 @@ kubectl get storageclass 之后,使用 helm 命令安装: ```bash -helm install tdengine tdengine-3.0.0.tgz \ +helm install tdengine tdengine-3.0.2.tgz \ --set storage.className= ``` @@ -47,7 +47,7 @@ helm install tdengine tdengine-3.0.0.tgz \ 在 minikube 环境下,可以设置一个较小的容量避免超出磁盘可用空间: ```bash -helm install tdengine tdengine-3.0.0.tgz \ +helm install tdengine tdengine-3.0.2.tgz \ --set storage.className=standard \ --set storage.dataSize=2Gi \ --set storage.logSize=10Mi @@ -84,14 +84,14 @@ TDengine 支持 `values.yaml` 自定义。 通过 helm show values 可以获取 TDengine Chart 支持的全部 values 列表: ```bash -helm show values tdengine-3.0.0.tgz +helm show values tdengine-3.0.2.tgz ``` 你可以将结果保存为 values.yaml,之后可以修改其中的各项参数,如 replica 数量,存储类名称,容量大小,TDengine 配置等,然后使用如下命令安装 TDengine 集群: ```bash -helm install tdengine tdengine-3.0.0.tgz -f values.yaml +helm install tdengine tdengine-3.0.2.tgz -f values.yaml ``` @@ -108,7 +108,7 @@ image: prefix: tdengine/tdengine #pullPolicy: Always # Overrides the image tag whose default is the chart appVersion. -# tag: "3.0.0.0" +# tag: "3.0.2.0" service: # ClusterIP is the default service type, use NodeIP only if you know what you are doing. @@ -156,15 +156,15 @@ clusterDomainSuffix: "" # See the variable list at https://www.taosdata.com/cn/documentation/administrator . # # Note: -# 1. firstEp/secondEp: should not be setted here, it's auto generated at scale-up. -# 2. serverPort: should not be setted, we'll use the default 6030 in many places. -# 3. fqdn: will be auto generated in kubenetes, user should not care about it. +# 1. firstEp/secondEp: should not be set here, it's auto generated at scale-up. +# 2. serverPort: should not be set, we'll use the default 6030 in many places. +# 3. fqdn: will be auto generated in kubernetes, user should not care about it. # 4. role: currently role is not supported - every node is able to be mnode and vnode. # # Btw, keep quotes "" around the value like below, even the value will be number or not. taoscfg: # Starts as cluster or not, must be 0 or 1. - # 0: all pods will start as a seperate TDengine server + # 0: all pods will start as a separate TDengine server # 1: pods will start as TDengine server cluster. [default] CLUSTER: "1" diff --git a/docs/zh/12-taos-sql/02-database.md b/docs/zh/12-taos-sql/02-database.md index 3918f240b4f9037db92af80df26dd471868b29de..b54998e08d33869d113ae883b14f929e5381f168 100644 --- a/docs/zh/12-taos-sql/02-database.md +++ b/docs/zh/12-taos-sql/02-database.md @@ -27,13 +27,16 @@ database_option: { | PRECISION {'ms' | 'us' | 'ns'} | REPLICA value | RETENTIONS ingestion_duration:keep_duration ... - | STRICT {'off' | 'on'} | WAL_LEVEL {1 | 2} | VGROUPS value | SINGLE_STABLE {0 | 1} + | STT_TRIGGER value + | TABLE_PREFIX value + | TABLE_SUFFIX value + | TSDB_PAGESIZE value | WAL_RETENTION_PERIOD value - | WAL_ROLL_PERIOD value | WAL_RETENTION_SIZE value + | WAL_ROLL_PERIOD value | WAL_SEGMENT_SIZE value } ``` @@ -55,15 +58,12 @@ database_option: { - WAL_FSYNC_PERIOD:当 WAL 参数设置为 2 时,落盘的周期。默认为 3000,单位毫秒。最小为 0,表示每次写入立即落盘;最大为 180000,即三分钟。 - MAXROWS:文件块中记录的最大条数,默认为 4096 条。 - MINROWS:文件块中记录的最小条数,默认为 100 条。 -- KEEP:表示数据文件保存的天数,缺省值为 3650,取值范围 [1, 365000],且必须大于或等于 DURATION 参数值。数据库会自动删除保存时间超过 KEEP 值的数据。KEEP 可以使用加单位的表示形式,如 KEEP 100h、KEEP 10d 等,支持 m(分钟)、h(小时)和 d(天)三个单位。也可以不写单位,如 KEEP 50,此时默认单位为天。 +- KEEP:表示数据文件保存的天数,缺省值为 3650,取值范围 [1, 365000],且必须大于或等于 DURATION 参数值。数据库会自动删除保存时间超过 KEEP 值的数据。KEEP 可以使用加单位的表示形式,如 KEEP 100h、KEEP 10d 等,支持 m(分钟)、h(小时)和 d(天)三个单位。也可以不写单位,如 KEEP 50,此时默认单位为天。企业版支持[多级存储](https://docs.taosdata.com/tdinternal/arch/#%E5%A4%9A%E7%BA%A7%E5%AD%98%E5%82%A8)功能, 因此, 可以设置多个保存时间(多个以英文逗号分隔,最多 3 个,满足 keep 0 <= keep 1 <= keep 2,如 KEEP 100h,100d,3650d); 社区版不支持多级存储功能(即使配置了多个保存时间, 也不会生效, KEEP 会取最大的保存时间)。 - PAGES:一个 VNODE 中元数据存储引擎的缓存页个数,默认为 256,最小 64。一个 VNODE 元数据存储占用 PAGESIZE \* PAGES,默认情况下为 1MB 内存。 - PAGESIZE:一个 VNODE 中元数据存储引擎的页大小,单位为 KB,默认为 4 KB。范围为 1 到 16384,即 1 KB 到 16 MB。 - PRECISION:数据库的时间戳精度。ms 表示毫秒,us 表示微秒,ns 表示纳秒,默认 ms 毫秒。 - REPLICA:表示数据库副本数,取值为 1 或 3,默认为 1。在集群中使用,副本数必须小于或等于 DNODE 的数目。 - RETENTIONS:表示数据的聚合周期和保存时长,如 RETENTIONS 15s:7d,1m:21d,15m:50d 表示数据原始采集周期为 15 秒,原始数据保存 7 天;按 1 分钟聚合的数据保存 21 天;按 15 分钟聚合的数据保存 50 天。目前支持且只支持三级存储周期。 -- STRICT:表示数据同步的一致性要求,默认为 off。 - - on 表示强一致,即运行标准的 raft 协议,半数提交返回成功。 - - off 表示弱一致,本地提交即返回成功。 - WAL_LEVEL:WAL 级别,默认为 1。 - 1:写 WAL,但不执行 fsync。 - 2:写 WAL,而且执行 fsync。 @@ -71,11 +71,14 @@ database_option: { - SINGLE_STABLE:表示此数据库中是否只可以创建一个超级表,用于超级表列非常多的情况。 - 0:表示可以创建多张超级表。 - 1:表示只可以创建一张超级表。 -- WAL_RETENTION_PERIOD:wal 文件的额外保留策略,用于数据订阅。wal 的保存时长,单位为 s。单副本默认为 0,即落盘后立即删除。-1 表示不删除。多副本默认为 4 天。 -- WAL_RETENTION_SIZE:wal 文件的额外保留策略,用于数据订阅。wal 的保存的最大上限,单位为 KB。单副本默认为 0,即落盘后立即删除。多副本默认为-1,表示不删除。 -- WAL_ROLL_PERIOD:wal 文件切换时长,单位为 s。当 wal 文件创建并写入后,经过该时间,会自动创建一个新的 wal 文件。单副本默认为 0,即仅在落盘时创建新文件。多副本默认为 1 天。 -- WAL_SEGMENT_SIZE:wal 单个文件大小,单位为 KB。当前写入文件大小超过上限后会自动创建一个新的 wal 文件。默认为 0,即仅在落盘时创建新文件。 - +- STT_TRIGGER:表示落盘文件触发文件合并的个数。默认为 1,范围 1 到 16。对于少表高频场景,此参数建议使用默认配置,或较小的值;而对于多表低频场景,此参数建议配置较大的值。 +- TABLE_PREFIX:内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的前缀的长度。 +- TABLE_SUFFIX:内部存储引擎根据表名分配存储该表数据的 VNODE 时要忽略的后缀的长度。 +- TSDB_PAGESIZE:一个 VNODE 中时序数据存储引擎的页大小,单位为 KB,默认为 4 KB。范围为 1 到 16384,即 1 KB到 16 MB。 +- WAL_RETENTION_PERIOD: 为了数据订阅消费,需要WAL日志文件额外保留的最大时长策略。WAL日志清理,不受订阅客户端消费状态影响。单位为 s。默认为 0,表示无需为订阅保留。新建订阅,应先设置恰当的时长策略。 +- WAL_RETENTION_SIZE:为了数据订阅消费,需要WAL日志文件额外保留的最大累计大小策略。单位为 KB。默认为 0,表示累计大小无上限。 +- WAL_ROLL_PERIOD:wal 文件切换时长,单位为 s。当WAL文件创建并写入后,经过该时间,会自动创建一个新的WAL文件。默认为 0,即仅在TSDB落盘时创建新文件。 +- WAL_SEGMENT_SIZE:wal 单个文件大小,单位为 KB。当前写入文件大小超过上限后会自动创建一个新的WAL文件。默认为 0,即仅在TSDB落盘时创建新文件。 ### 创建数据库示例 ```sql @@ -112,12 +115,32 @@ alter_database_options: alter_database_option: { CACHEMODEL {'none' | 'last_row' | 'last_value' | 'both'} | CACHESIZE value + | BUFFER value + | PAGES value + | REPLICA value + | STT_TRIGGER value | WAL_LEVEL value | WAL_FSYNC_PERIOD value | KEEP value } ``` +### 修改 CACHESIZE + +修改数据库参数的命令使用简单,难的是如何确定是否需要修改以及如何修改。本小节描述如何判断数据库的 cachesize 是否够用。 + +1. 如何查看 cachesize? + +通过 select * from information_schema.ins_databases; 可以查看这些 cachesize 的具体值。 + +2. 如何查看 cacheload? + +通过 show .vgroups; 可以查看 cacheload + +3. 判断 cachesize 是否够用 + +如果 cacheload 非常接近 cachesize,则 cachesize 可能过小。 如果 cacheload 明显小于 cachesize 则 cachesize 是够用的。可以根据这个原则判断是否需要修改 cachesize 。具体修改值可以根据系统可用内存情况来决定是加倍或者是提高几倍。 + :::note 其它参数在 3.0.0.0 中暂不支持修改 @@ -134,7 +157,7 @@ SHOW DATABASES; ### 显示一个数据库的创建语句 ``` -SHOW CREATE DATABASE db_name; +SHOW CREATE DATABASE db_name \G; ``` 常用于数据库迁移。对一个已经存在的数据库,返回其创建语句;在另一个集群中执行该语句,就能得到一个设置完全相同的 Database。 @@ -142,7 +165,7 @@ SHOW CREATE DATABASE db_name; ### 查看数据库参数 ```sql -SELECT * FROM INFORMATION_SCHEMA.INS_DATABASES WHERE NAME='DBNAME' \G; +SELECT * FROM INFORMATION_SCHEMA.INS_DATABASES WHERE NAME='db_name' \G; ``` 会列出指定数据库的配置参数,并且每行只显示一个参数。 @@ -154,3 +177,35 @@ TRIM DATABASE db_name; ``` 删除过期数据,并根据多级存储的配置归整数据。 + +## 落盘内存数据 + +```sql +FLUSH DATABASE db_name; +``` + +落盘内存中的数据。在关闭节点之前,执行这条命令可以避免重启后的数据回放,加速启动过程。 + +## 调整VGROUP中VNODE的分布 + +```sql +REDISTRIBUTE VGROUP vgroup_no DNODE dnode_id1 [DNODE dnode_id2] [DNODE dnode_id3] +``` + +按照给定的dnode列表,调整vgroup中的vnode分布。因为副本数目最大为3,所以最多输入3个dnode。 + +## 自动调整VGROUP中VNODE的分布 + +```sql +BALANCE VGROUP +``` + +自动调整集群所有vgroup中的vnode分布,相当于在vnode级别对集群进行数据的负载均衡操作。 + +## 查看数据库工作状态 + +```sql +SHOW db_name.ALIVE; +``` + +查询数据库 db_name 的可用状态,返回值 0:不可用 1:完全可用 2:部分可用(即数据库包含的 VNODE 部分节点可用,部分节点不可用) diff --git a/docs/zh/12-taos-sql/03-table.md b/docs/zh/12-taos-sql/03-table.md index 045abcde95e04cb4009dea9de597339c25fe36b0..5687c7e740766ad7a3fbea03ff42ce3137bb140e 100644 --- a/docs/zh/12-taos-sql/03-table.md +++ b/docs/zh/12-taos-sql/03-table.md @@ -57,7 +57,7 @@ table_option: { 3. MAX_DELAY:用于控制推送计算结果的最大延迟,默认值为 interval 的值(但不能超过最大值),最小单位毫秒,范围为 1 毫秒到 15 分钟,多个以逗号分隔。注:不建议 MAX_DELAY 设置太小,否则会过于频繁的推送结果,影响存储和查询性能,如无特殊需求,取默认值即可。只可用于超级表,且只有当数据库使用了 RETENTIONS 参数时,才可以使用此表参数。 4. ROLLUP:Rollup 指定的聚合函数,提供基于多层级的降采样聚合结果。只可用于超级表。只有当数据库使用了 RETENTIONS 参数时,才可以使用此表参数。作用于超级表除 TS 列外的其它所有列,但是只能定义一个聚合函数。 聚合函数支持 avg, sum, min, max, last, first。 5. SMA:Small Materialized Aggregates,提供基于数据块的自定义预计算功能。预计算类型包括 MAX、MIN 和 SUM。可用于超级表/普通表。 -6. TTL:Time to Live,是用户用来指定表的生命周期的参数。如果创建表时指定了这个参数,当该表的存在时间超过 TTL 指定的时间后,TDengine 自动删除该表。这个 TTL 的时间只是一个大概时间,系统不保证到了时间一定会将其删除,而只保证存在这样一个机制且最终一定会删除。TTL 单位是天,默认为 0,表示不限制,到期时间为表创建时间加上 TTL 时间。 +6. TTL:Time to Live,是用户用来指定表的生命周期的参数。如果创建表时指定了这个参数,当该表的存在时间超过 TTL 指定的时间后,TDengine 自动删除该表。这个 TTL 的时间只是一个大概时间,系统不保证到了时间一定会将其删除,而只保证存在这样一个机制且最终一定会删除。TTL 单位是天,默认为 0,表示不限制,到期时间为表创建时间加上 TTL 时间。TTL 与数据库 KEEP 参数没有关联,如果 KEEP 比 TTL 小,在表被删除之前数据也可能已经被删除。 ## 创建子表 diff --git a/docs/zh/12-taos-sql/04-stable.md b/docs/zh/12-taos-sql/04-stable.md index bd32da68aecc4c42be110e7716c1b2b4ebdab37c..74ef52ee7c53d6c619a47d7e6453b56f152104a2 100644 --- a/docs/zh/12-taos-sql/04-stable.md +++ b/docs/zh/12-taos-sql/04-stable.md @@ -13,12 +13,11 @@ create_definition: col_name column_definition column_definition: - type_name [COMMENT 'string_value'] + type_name ``` **使用说明** - 超级表中列的最大个数为 4096,需要注意,这里的 4096 是包含 TAG 列在内的,最小个数为 3,包含一个时间戳主键、一个 TAG 列和一个数据列。 -- 建表时可以给列或标签附加注释。 - TAGS语法指定超级表的标签列,标签列需要遵循以下约定: - TAGS 中的 TIMESTAMP 列写入数据时需要提供给定值,而暂不支持四则运算,例如 NOW + 10s 这类表达式。 - TAGS 列名不能与其他列名相同。 @@ -139,10 +138,10 @@ alter_table_option: { - ADD COLUMN:添加列。 - DROP COLUMN:删除列。 -- MODIFY COLUMN:修改列定义,如果数据列的类型是可变长类型,那么可以使用此指令修改其宽度,只能改大,不能改小。 +- MODIFY COLUMN:修改列的宽度,数据列的类型必须是 nchar 和 binary,使用此指令可以修改其宽度,只能改大,不能改小。 - ADD TAG:给超级表添加一个标签。 - DROP TAG:删除超级表的一个标签。从超级表删除某个标签后,该超级表下的所有子表也会自动删除该标签。 -- MODIFY TAG:修改超级表的一个标签的定义。如果标签的类型是可变长类型,那么可以使用此指令修改其宽度,只能改大,不能改小。 +- MODIFY TAG:修改超级表的一个标签的列宽度。标签的类型只能是 nchar 和 binary,使用此指令可以修改其宽度,只能改大,不能改小。 - RENAME TAG:修改超级表的一个标签的名称。从超级表修改某个标签名后,该超级表下的所有子表也会自动更新该标签名。 ### 增加列 diff --git a/docs/zh/12-taos-sql/05-insert.md b/docs/zh/12-taos-sql/05-insert.md index ccb8f40b21f7f0082f7bf420643e88a618d83f0e..b72754b15437a081b89056fca3a76030cac62363 100644 --- a/docs/zh/12-taos-sql/05-insert.md +++ b/docs/zh/12-taos-sql/05-insert.md @@ -28,7 +28,7 @@ INSERT INTO tb_name [(field1_name, ...)] subquery 2. 时间戳不同的格式语法会有不同的精度影响。字符串格式的时间戳写法不受所在 DATABASE 的时间精度设置影响;而长整形格式的时间戳写法会受到所在 DATABASE 的时间精度设置影响。例如,时间戳"2021-07-13 16:16:48"的 UNIX 秒数为 1626164208。则其在毫秒精度下需要写作 1626164208000,在微秒精度设置下就需要写为 1626164208000000,纳秒精度设置下需要写为 1626164208000000000。 3. 一次插入多行数据时,不要把首列的时间戳的值都写 NOW。否则会导致语句中的多条记录使用相同的时间戳,于是就可能出现相互覆盖以致这些数据行无法全部被正确保存。其原因在于,NOW 函数在执行中会被解析为所在 SQL 语句的客户端执行时间,出现在同一语句中的多个 NOW 标记也就会被替换为完全相同的时间戳取值。 - 允许插入的最老记录的时间戳,是相对于当前服务器时间,减去配置的 KEEP 值(数据保留的天数)。允许插入的最新记录的时间戳,是相对于当前服务器时间,加上配置的 DURATION 值(数据文件存储数据的时间跨度,单位为天)。KEEP 和 DURATION 都是可以在创建数据库时指定的,缺省值分别是 3650 天和 10 天。 + 允许插入的最老记录的时间戳,是相对于当前服务器时间,减去配置的 KEEP 值(数据保留的天数, 可以在创建数据库时指定,缺省值是 3650 天)。允许插入的最新记录的时间戳,取决于数据库的 PRECISION 值(时间戳精度, 可以在创建数据库时指定, ms 表示毫秒,us 表示微秒,ns 表示纳秒,默认毫秒):如果是毫秒或微秒, 取值为 1970 年 1 月 1 日 00:00:00.000 UTC 加上 1000 年, 即 2970 年 1 月 1 日 00:00:00.000 UTC; 如果是纳秒, 取值为 1970 年 1 月 1 日 00:00:00.000000000 UTC 加上 292 年, 即 2262 年 1 月 1 日 00:00:00.000000000 UTC。 **语法说明** diff --git a/docs/zh/12-taos-sql/06-select.md b/docs/zh/12-taos-sql/06-select.md index b9b26279e623f2f9f167c3c7f305f5921501f7b4..e4ba5b76e487e2ac739d0797a32f2a6a04d849e3 100644 --- a/docs/zh/12-taos-sql/06-select.md +++ b/docs/zh/12-taos-sql/06-select.md @@ -248,11 +248,11 @@ NULLS 语法用来指定 NULL 值在排序中输出的位置。NULLS LAST 是升 LIMIT 控制输出条数,OFFSET 指定从第几条之后开始输出。LIMIT/OFFSET 对结果集的执行顺序在 ORDER BY 之后。LIMIT 5 OFFSET 2 可以简写为 LIMIT 2, 5,都输出第 3 行到第 7 行数据。 -在有 PARTITION BY 子句时,LIMIT 控制的是每个切分的分片中的输出,而不是总的结果集输出。 +在有 PARTITION BY/GROUP BY 子句时,LIMIT 控制的是每个切分的分片中的输出,而不是总的结果集输出。 ## SLIMIT -SLIMIT 和 PARTITION BY 子句一起使用,用来控制输出的分片的数量。SLIMIT 5 SOFFSET 2 可以简写为 SLIMIT 2, 5,都表示输出第 3 个到第 7 个分片。 +SLIMIT 和 PARTITION BY/GROUP BY 子句一起使用,用来控制输出的分片的数量。SLIMIT 5 SOFFSET 2 可以简写为 SLIMIT 2, 5,都表示输出第 3 个到第 7 个分片。 需要注意,如果有 ORDER BY 子句,则输出只有一个分片。 @@ -354,9 +354,9 @@ SELECT AVG(CASE WHEN voltage < 200 or voltage > 250 THEN 220 ELSE voltage END) F ## JOIN 子句 -TDengine 支持“普通表与普通表之间”、“超级表与超级表之间”、“子查询与子查询之间” 进行自然连接。自然连接与内连接的主要区别是,自然连接要求参与连接的字段在不同的表/超级表中必须是同名字段。也即,TDengine 在连接关系的表达中,要求必须使用同名数据列/标签列的相等关系。 +TDengine 支持基于时间戳主键的内连接,即 JOIN 条件必须包含时间戳主键。只要满足基于时间戳主键这个要求,普通表、子表、超级表和子查询之间可以随意的进行内连接,且对表个数没有限制。 -在普通表与普通表之间的 JOIN 操作中,只能使用主键时间戳之间的相等关系。例如: +普通表与普通表之间的 JOIN 操作: ```sql SELECT * @@ -364,7 +364,7 @@ FROM temp_tb_1 t1, pressure_tb_1 t2 WHERE t1.ts = t2.ts ``` -在超级表与超级表之间的 JOIN 操作中,除了主键时间戳一致的条件外,还要求引入能实现一一对应的标签列的相等关系。例如: +超级表与超级表之间的 JOIN 操作: ```sql SELECT * @@ -372,20 +372,15 @@ FROM temp_stable t1, temp_stable t2 WHERE t1.ts = t2.ts AND t1.deviceid = t2.deviceid AND t1.status=0; ``` -类似地,也可以对多个子查询的查询结果进行 JOIN 操作。 - -:::note - -JOIN 语句存在如下限制要求: +子表与超级表之间的 JOIN 操作: -- 参与一条语句中 JOIN 操作的表/超级表最多可以有 10 个。 -- 在包含 JOIN 操作的查询语句中不支持 FILL。 -- 暂不支持参与 JOIN 操作的表之间聚合后的四则运算。 -- 不支持只对其中一部分表做 GROUP BY。 -- JOIN 查询的不同表的过滤条件之间不能为 OR。 -- JOIN 查询要求连接条件不能是普通列,只能针对标签和主时间字段列(第一列)。 +```sql +SELECT * +FROM temp_ctable t1, temp_stable t2 +WHERE t1.ts = t2.ts AND t1.deviceid = t2.deviceid AND t1.status=0; +``` -::: +类似地,也可以对多个子查询的查询结果进行 JOIN 操作。 ## 嵌套查询 diff --git a/docs/zh/12-taos-sql/07-tag-index.md b/docs/zh/12-taos-sql/07-tag-index.md new file mode 100644 index 0000000000000000000000000000000000000000..ae16b0b2ec4db26361c4b241fd6188bfe0df9b5e --- /dev/null +++ b/docs/zh/12-taos-sql/07-tag-index.md @@ -0,0 +1,51 @@ +--- +sidebar_label: 标签索引 +title: 标签索引 +description: 使用标签索引提升查询性能 +--- + +## 简介 + +在 TDengine 3.0.3.0 版本之前(不含),默认在第一列 TAG 上建立索引,但不支持给其它列动态添加索引。从 3.0.3.0 版本开始,可以动态地为其它 TAG 列添加索引。对于第一个 TAG 列上自动建立的索引,其在查询中默认生效,且用户无法对其进行任何干预。适当地使用索引能够有效地提升查询性能。 + +## 语法 + +创建索引的语法如下 + +```sql +CREATE INDEX index_name ON tbl_name (tagColName) +``` + +其中 `index_name` 为索引名称, `tbl_name` 为超级表名称,`tagColName` 为要在其上建立索引的 tag 列的名称。`tagColName` 的类型不受限制,即任何类型的 tag 列都可以建立索引。 + +删除索引的语法如下 + +```sql +DROP INDEX index_name +``` + +其中 `index_name` 为已经建立的某个索引的名称,如果该索引不存在则该命令执行失败,但不会对系统产生任何其它影响。 + +查看系统中已经存在的索引 + +```sql +SELECT * FROM information_schema.INS_INDEXES +``` + +也可以为上面的查询语句加上过滤条件以缩小查询范围。 + +## 使用说明 + +1. 索引使用得当能够提升数据过滤的效率,目前支持的过滤算子有 `=`, `>`, `>=`, `<`, `<=`。如果查询过滤条件中使用了这些算子,则索引能够明显提升查询效率。但如果查询过滤条件中使用的是其它算子,则索引起不到作用,查询效率没有变化。未来会逐步添加更多的算子。 + +2. 针对一个 tag 列只能建立一个索引,如果重复创建索引则会报错。 + +3. 每次只能针对一个 tag 列建立一个索引,不能同时对多个 tag 建立索引。 + +4. 整个系统中不管是哪种类型的索引,其名称必须唯一。 + +5. 对索引个数没有限制,但每增加一个索引都会导致系统中的元数据增加,过多的索引会降低元数据存取的效率从而降低整个系统的性能。所以请尽量避免添加不必要的索引。 + +6. 不支持对普通和子表建立索引。 + +7. 如果某个 tag 列的唯一值较少时,不建议对其建立索引,这种情况下收效甚微。 \ No newline at end of file diff --git a/docs/zh/12-taos-sql/10-function.md b/docs/zh/12-taos-sql/10-function.md index c44c09d10c115a41efd22048d4fdafdc85370ac2..94f805205183aca6a7a08d9a836b0df33c7ed1f0 100644 --- a/docs/zh/12-taos-sql/10-function.md +++ b/docs/zh/12-taos-sql/10-function.md @@ -798,18 +798,22 @@ HISTOGRAM(expr,bin_type, bin_description, normalized) ### PERCENTILE ```sql -PERCENTILE(expr, p) +PERCENTILE(expr, p [, p1] ... ) ``` **功能说明**:统计表中某列的值百分比分位数。 -**返回数据类型**: DOUBLE。 +**返回数据类型**: 该函数最小参数个数为 2 个,最大参数个数为 11 个。可以最多同时返回 10 个百分比分位数。当参数个数为 2 时, 返回一个分位数, 类型为DOUBLE,当参数个数大于 2 时,返回类型为VARCHAR, 格式为包含多个返回值的JSON数组。 **应用字段**:数值类型。 **适用于**:表。 -**使用说明**:*P*值取值范围 0≤*P*≤100,为 0 的时候等同于 MIN,为 100 的时候等同于 MAX。 +**使用说明**: + +- *P*值取值范围 0≤*P*≤100,为 0 的时候等同于 MIN,为 100 的时候等同于 MAX; +- 同时计算针对同一列的多个分位数时,建议使用一个PERCENTILE函数和多个参数的方式,能很大程度上降低查询的响应时间。 + 比如,使用查询SELECT percentile(col, 90, 95, 99) FROM table, 性能会优于SELECT percentile(col, 90), percentile(col, 95), percentile(col, 99) from table。 ## 选择函数 @@ -879,7 +883,8 @@ INTERP(expr) - INTERP 根据 EVERY(time_unit) 字段来确定输出时间范围内的结果条数,即从 timestamp1 开始每隔固定长度的时间(time_unit 值)进行插值,time_unit 可取值时间单位:1a(毫秒),1s(秒),1m(分),1h(小时),1d(天),1w(周)。例如 EVERY(500a) 将对于指定数据每500毫秒间隔进行一次插值. - INTERP 根据 FILL 字段来决定在每个符合输出条件的时刻如何进行插值。关于 FILL 子句如何使用请参考 [FILL 子句](../distinguished/#fill-子句) - INTERP 只能在一个时间序列内进行插值,因此当作用于超级表时必须跟 partition by tbname 一起使用。 -- INTERP 可以与伪列 _irowts 一起使用,返回插值点所对应的时间戳(3.0.1.4版本以后支持)。 +- INTERP 可以与伪列 _irowts 一起使用,返回插值点所对应的时间戳(3.0.2.0版本以后支持)。 +- INTERP 可以与伪列 _isfilled 一起使用,显示返回结果是否为原始记录或插值算法产生的数据(3.0.3.0版本以后支持)。 ### LAST diff --git a/docs/zh/12-taos-sql/12-distinguished.md b/docs/zh/12-taos-sql/12-distinguished.md index d36c852e7975dbe602166d8c7d12027043c2e302..f750124049c5b0dabecb359fe8c1b9d28ca1f431 100644 --- a/docs/zh/12-taos-sql/12-distinguished.md +++ b/docs/zh/12-taos-sql/12-distinguished.md @@ -31,15 +31,17 @@ select max(current) from meters partition by location interval(10m) ## 窗口切分查询 -TDengine 支持按时间窗口切分方式进行聚合结果查询,比如温度传感器每秒采集一次数据,但需查询每隔 10 分钟的温度平均值。这种场景下可以使用窗口子句来获得需要的查询结果。窗口子句用于针对查询的数据集合按照窗口切分成为查询子集并进行聚合,窗口包含时间窗口(time window)、状态窗口(status window)、会话窗口(session window)三种窗口。其中时间窗口又可划分为滑动时间窗口和翻转时间窗口。窗口切分查询语法如下: +TDengine 支持按时间窗口切分方式进行聚合结果查询,比如温度传感器每秒采集一次数据,但需查询每隔 10 分钟的温度平均值。这种场景下可以使用窗口子句来获得需要的查询结果。窗口子句用于针对查询的数据集合按照窗口切分成为查询子集并进行聚合,窗口包含时间窗口(time window)、状态窗口(status window)、会话窗口(session window)、条件窗口(event window)四种窗口。其中时间窗口又可划分为滑动时间窗口和翻转时间窗口。 + +窗口子句语法如下: ```sql -SELECT select_list FROM tb_name - [WHERE where_condition] - [SESSION(ts_col, tol_val)] - [STATE_WINDOW(col)] - [INTERVAL(interval [, offset]) [SLIDING sliding]] - [FILL({NONE | VALUE | PREV | NULL | LINEAR | NEXT})] +window_clause: { + SESSION(ts_col, tol_val) + | STATE_WINDOW(col) + | INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [FILL(fill_mod_and_val)] + | EVENT_WINDOW START WITH start_trigger_condition END WITH end_trigger_condition +} ``` 在上述语法中的具体限制如下 @@ -67,6 +69,16 @@ FILL 语句指定某一窗口区间数据缺失的情况下的填充模式。填 5. LINEAR 填充:根据前后距离最近的非 NULL 值做线性插值填充。例如:FILL(LINEAR)。 6. NEXT 填充:使用下一个非 NULL 值填充数据。例如:FILL(NEXT)。 +以上填充模式中,除了 NONE 模式默认不填充值之外,其他模式在查询的整个时间范围内如果没有数据 FILL 子句将被忽略,即不产生填充数据,查询结果为空。这种行为在部分模式(PREV、NEXT、LINEAR)下具有合理性,因为在这些模式下没有数据意味着无法产生填充数值。而对另外一些模式(NULL、VALUE)来说,理论上是可以产生填充数值的,至于需不需要输出填充数值,取决于应用的需求。所以为了满足这类需要强制填充数据或 NULL 的应用的需求,同时不破坏现有填充模式的行为兼容性,从 3.0.3.0 版本开始,增加了两种新的填充模式: + +7. NULL_F: 强制填充 NULL 值 +8. VALUE_F: 强制填充 VALUE 值 + +NULL, NULL_F, VALUE, VALUE_F 这几种填充模式针对不同场景区别如下: +- INTERVAL 子句: NULL_F, VALUE_F 为强制填充模式;NULL, VALUE 为非强制模式。在这种模式下下各自的语义与名称相符 +- 流计算中的 INTERVAL 子句:NULL_F 与 NULL 行为相同,均为非强制模式;VALUE_F 与 VALUE 行为相同,均为非强制模式。即流计算中的 INTERVAL 没有强制模式 +- INTERP 子句:NULL 与 NULL_F 行为相同,均为强制模式;VALUE 与 VALUE_F 行为相同,均为强制模式。即 INTERP 中没有非强制模式。 + :::info 1. 使用 FILL 语句的时候可能生成大量的填充输出,务必指定查询的时间区间。针对每次查询,系统可返回不超过 1 千万条具有插值的结果。 @@ -138,6 +150,24 @@ SELECT tbname, _wstart, CASE WHEN voltage >= 205 and voltage <= 235 THEN 1 ELSE SELECT COUNT(*), FIRST(ts) FROM temp_tb_1 SESSION(ts, tol_val); ``` +### 事件窗口 + +事件窗口根据开始条件和结束条件来划定窗口,当start_trigger_condition满足时则窗口开始,直到end_trigger_condition满足时窗口关闭。start_trigger_condition和end_trigger_condition可以是任意 TDengine 支持的条件表达式,且可以包含不同的列。 + +事件窗口可以仅包含一条数据。即当一条数据同时满足start_trigger_condition和end_trigger_condition,且当前不在一个窗口内时,这条数据自己构成了一个窗口。 + +事件窗口无法关闭时,不构成一个窗口,不会被输出。即有数据满足start_trigger_condition,此时窗口打开,但后续数据都不能满足end_trigger_condition,这个窗口无法被关闭,这部分数据不够成一个窗口,不会被输出。 + +如果直接在超级表上进行事件窗口查询,TDengine 会将超级表的数据汇总成一条时间线,然后进行事件窗口的计算。 +如果需要对子查询的结果集进行事件窗口查询,那么子查询的结果集需要满足按时间线输出的要求,且可以输出有效的时间戳列。 + +以下面的 SQL 语句为例,事件窗口切分如图所示: +```sql +select _wstart, _wend, count(*) from t event_window start with c1 > 0 end with c2 < 10 +``` + +![TDengine Database 事件窗口示意图](./event_window.webp) + ### 时间戳伪列 窗口聚合查询结果中,如果 SQL 语句中没有指定输出查询结果中的时间戳列,那么最终结果中不会自动包含窗口的时间列信息。如果需要在结果中输出聚合结果所对应的时间窗口信息,需要在 SELECT 子句中使用时间戳相关的伪列: 时间窗口起始时间 (\_WSTART), 时间窗口结束时间 (\_WEND), 时间窗口持续时间 (\_WDURATION), 以及查询整体窗口相关的伪列: 查询窗口起始时间(\_QSTART) 和查询窗口结束时间(\_QEND)。需要注意的是时间窗口起始时间和结束时间均是闭区间,时间窗口持续时间是数据当前时间分辨率下的数值。例如,如果当前数据库的时间分辨率是毫秒,那么结果中 500 就表示当前时间窗口的持续时间是 500毫秒 (500 ms)。 diff --git a/docs/zh/12-taos-sql/14-stream.md b/docs/zh/12-taos-sql/14-stream.md index a70d559a860c4e6ec44cbd13c34f7f306ab452cb..12e466f3491b779275d29bcfa79c3203aee01056 100644 --- a/docs/zh/12-taos-sql/14-stream.md +++ b/docs/zh/12-taos-sql/14-stream.md @@ -8,10 +8,13 @@ description: 流式计算的相关 SQL 的详细语法 ## 创建流式计算 ```sql -CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] INTO stb_name SUBTABLE(expression) AS subquery +CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] INTO stb_name[(field1_name, ...)] [TAGS (create_definition [, create_definition] ...)] SUBTABLE(expression) AS subquery stream_options: { - TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time] - WATERMARK time + TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time] + WATERMARK time + IGNORE EXPIRED [0|1] + DELETE_MARK time + FILL_HISTORY [0|1] } ``` @@ -28,6 +31,15 @@ subquery: SELECT select_list 支持会话窗口、状态窗口与滑动窗口,其中,会话窗口与状态窗口搭配超级表时必须与partition by tbname一起使用 +stb_name 是保存计算结果的超级表的表名,如果该超级表不存在,会自动创建;如果已存在,则检查列的schema信息。详见 写入已存在的超级表 + +TAGS 字句定义了流计算中创建TAG的规则,可以为每个partition对应的子表生成自定义的TAG值,详见 自定义TAG +```sql +create_definition: + col_name column_definition +column_definition: + type_name [COMMENT 'string_value'] +``` subtable 子句定义了流式计算中创建的子表的命名规则,详见 流式计算的 partition 部分。 @@ -114,7 +126,7 @@ SELECT * from information_schema.`ins_streams`; 在创建流时,可以通过 TRIGGER 指令指定流式计算的触发模式。 -对于非窗口计算,流式计算的触发是实时的;对于窗口计算,目前提供 3 种触发模式: +对于非窗口计算,流式计算的触发是实时的;对于窗口计算,目前提供 3 种触发模式,默认为 WINDOW_CLOSE: 1. AT_ONCE:写入立即触发 @@ -163,9 +175,41 @@ T3 时刻,最新事件到达,T 向后推移超过了第二个窗口关闭的 TDengine 对于过期数据提供两种处理方式,由 IGNORE EXPIRED 选项指定: -1. 重新计算,即 IGNORE EXPIRED 0:默认配置,从 TSDB 中重新查找对应窗口的所有数据并重新计算得到最新结果 +1. 重新计算,即 IGNORE EXPIRED 0:从 TSDB 中重新查找对应窗口的所有数据并重新计算得到最新结果 -2. 直接丢弃, 即 IGNORE EXPIRED 1:忽略过期数据 +2. 直接丢弃, 即 IGNORE EXPIRED 1:默认配置,忽略过期数据 无论在哪种模式下,watermark 都应该被妥善设置,来得到正确结果(直接丢弃模式)或避免频繁触发重算带来的性能开销(重新计算模式)。 + +## 写入已存在的超级表 +```sql +[field1_name,...] +``` +用来指定stb_name的列与subquery输出结果的对应关系。如果stb_name的列与subquery输出结果的位置、数量全部匹配,则不需要显示指定对应关系。如果stb_name的列与subquery输出结果的数据类型不匹配,会把subquery输出结果的类型转换成对应的stb_name的列的类型。 + +对于已经存在的超级表,检查列的schema信息 +1. 检查列的schema信息是否匹配,对于不匹配的,则自动进行类型转换,当前只有数据长度大于4096byte时才报错,其余场景都能进行类型转换。 +2. 检查列的个数是否相同,如果不同,需要显示的指定超级表与subquery的列的对应关系,否则报错;如果相同,可以指定对应关系,也可以不指定,不指定则按位置顺序对应。 +3. 至少自定义一个tag,否则报错。详见 自定义TAG + +## 自定义TAG + +用户可以为每个 partition 对应的子表生成自定义的TAG值。 +```sql +CREATE STREAM streams2 trigger at_once INTO st1 TAGS(cc varchar(100)) as select _wstart, count(*) c1 from st partition by concat("tag-", tbname) as cc interval(10s)); +``` + +PARTITION 子句中,为 concat("tag-", tbname)定义了一个别名cc, 对应超级表st1的自定义TAG的名字。在上述示例中,流新创建的子表的TAG将以前缀 'new-' 连接原表名作为TAG的值。 + +会对TAG信息进行如下检查 +1.检查tag的schema信息是否匹配,对于不匹配的,则自动进行数据类型转换,当前只有数据长度大于4096byte时才报错,其余场景都能进行类型转换。 +2.检查tag的个数是否相同,如果不同,需要显示的指定超级表与subquery的tag的对应关系,否则报错;如果相同,可以指定对应关系,也可以不指定,不指定则按位置顺序对应。 + +## 清理中间状态 + +``` +DELETE_MARK time +``` +DELETE_MARK用于删除缓存的窗口状态,也就是删除流计算的中间结果。如果不设置,默认值是10年 +T = 最新事件时间 - DELETE_MARK diff --git a/docs/zh/12-taos-sql/20-keywords.md b/docs/zh/12-taos-sql/20-keywords.md index 8013698fced2f31ca21dfa220066b027e71cb856..d416febd55521853812fbe6952d403f4d265ac4e 100644 --- a/docs/zh/12-taos-sql/20-keywords.md +++ b/docs/zh/12-taos-sql/20-keywords.md @@ -18,6 +18,7 @@ description: TDengine 保留关键字的详细列表 - ADD - AFTER - AGGREGATE +- ALIVE - ALL - ALTER - ANALYZE @@ -268,7 +269,7 @@ description: TDengine 保留关键字的详细列表 - SPLIT - STABLE - STABLES -- STAR +- START - STATE - STATE_WINDOW - STATEMENT diff --git a/docs/zh/12-taos-sql/21-node.md b/docs/zh/12-taos-sql/21-node.md index 4116343730eee014047de99291c868b792153cd7..778d699099b3a564d57cbe0d0374dbdcb0fde0dc 100644 --- a/docs/zh/12-taos-sql/21-node.md +++ b/docs/zh/12-taos-sql/21-node.md @@ -119,6 +119,14 @@ DROP QNODE ON DNODE dnode_id; 删除 ID 为 dnode_id 的 DNODE 上的 QNODE,但并不会影响该 dnode 的状态。 +## 查询集群状态 + +```sql +SHOW CLUSTER ALIVE; +``` + +查询当前集群的状态是否可用,返回值: 0:不可用 1:完全可用 2:部分可用(集群中部分节点下线,但其它节点仍可以正常使用) + ## 修改客户端配置 如果将客户端也看作广义的集群的一部分,可以通过如下命令动态修改客户端配置参数。 diff --git a/docs/zh/12-taos-sql/22-meta.md b/docs/zh/12-taos-sql/22-meta.md index c05dbf9c2afa0e477cff3029146b87482fbb6c36..1f2e3fb7d5742a01abae8fb9caf13ef090312cdc 100644 --- a/docs/zh/12-taos-sql/22-meta.md +++ b/docs/zh/12-taos-sql/22-meta.md @@ -166,7 +166,7 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数 | 7 | vgroup_id | INT | vgroup id | | 8 | ttl | INT | 表的生命周期。需要注意,`ttl` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 9 | table_comment | BINARY(1024) | 表注释 | -| 10 | type | BINARY(20) | 表类型 | +| 10 | type | BINARY(21) | 表类型 | ## INS_TAGS @@ -179,6 +179,20 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数 | 5 | tag_type | BINARY(64) | tag 的类型 | | 6 | tag_value | BINARY(16384) | tag 的值 | +## INS_COLUMNS + +| # | **列名** | **数据类型** | **说明** | +| --- | :---------: | ------------- | ---------------------- | +| 1 | table_name | BINARY(192) | 表名 | +| 2 | db_name | BINARY(64) | 该表所在的数据库的名称 | +| 3 | table_type | BINARY(21) | 表类型 | +| 4 | col_name | BINARY(64) | 列 的名称 | +| 5 | col_type | BINARY(32) | 列 的类型 | +| 6 | col_length | INT | 列 的长度 | +| 7 | col_precision | INT | 列 的精度 | +| 8 | col_scale | INT | 列 的比例 | +| 9 | col_nullable | INT | 列 是否可以为空 | + ## INS_USERS 提供系统中创建的用户的相关信息。 @@ -274,9 +288,9 @@ TDengine 内置了一个名为 `INFORMATION_SCHEMA` 的数据库,提供对数 | 1 | stream_name | BINARY(64) | 流计算名称 | | 2 | create_time | TIMESTAMP | 创建时间 | | 3 | sql | BINARY(1024) | 创建流计算时提供的 SQL 语句 | -| 4 | status | BIANRY(20) | 流当前状态 | +| 4 | status | BINARY(20) | 流当前状态 | | 5 | source_db | BINARY(64) | 源数据库 | -| 6 | target_db | BIANRY(64) | 目的数据库 | +| 6 | target_db | BINARY(64) | 目的数据库 | | 7 | target_table | BINARY(192) | 流计算写入的目标表 | | 8 | watermark | BIGINT | watermark,详见 SQL 手册流式计算。需要注意,`watermark` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | | 9 | trigger | INT | 计算结果推送模式,详见 SQL 手册流式计算。需要注意,`trigger` 为 TDengine 关键字,作为列名使用时需要使用 ` 进行转义。 | diff --git a/docs/zh/12-taos-sql/24-show.md b/docs/zh/12-taos-sql/24-show.md index 4bd1e52284f46d94cfd892c82a7fbe119b685532..ab29a1ee503da11c43dd2e3c2f6483eda8cfa233 100644 --- a/docs/zh/12-taos-sql/24-show.md +++ b/docs/zh/12-taos-sql/24-show.md @@ -86,10 +86,10 @@ SHOW FUNCTIONS; 显示用户定义的自定义函数。 -## SHOW LICENSE +## SHOW LICENCES ```sql -SHOW LICENSE; +SHOW LICENCES; SHOW GRANTS; ``` @@ -179,6 +179,84 @@ SHOW TABLE DISTRIBUTED table_name; 显示表的数据分布信息。 +示例说明: + +语句: show table distributed d0\G; 竖行显示表 d0 的 BLOCK 分布情况 + +
+ 显示示例 +

+
+*************************** 1.row ***************************
+
+_block_dist: Total_Blocks=[5] Total_Size=[93.65 KB] Average_size=[18.73 KB] Compression_Ratio=[23.98 %]
+
+Total_Blocks:  表 d0 占用的 block 个数为 5 个
+
+Total_Size:    表 d0 所有 block 在文件中占用的大小为 93.65 KB 
+
+Average_size:  平均每个 block 在文件中占用的空间大小为 18.73 KB
+
+Compression_Ratio: 数据压缩率 23.98%
+
+ 
+*************************** 2.row ***************************
+
+_block_dist: Total_Rows=[20000] Inmem_Rows=[0] MinRows=[3616] MaxRows=[4096] Average_Rows=[4000]
+
+Total_Rows:  统计表 d0 的存储在磁盘上行数 20000 行(该数值仅供参考,不是精确的行数。获得精确的行数需要使用 count 函数)
+
+Inmem_Rows: 存储在写缓存中的数据行数(没有落盘),0 行表示内存缓存中没有数据
+
+MinRows:    BLOCK 中最小的行数,为 3616 行
+
+MaxRows:    BLOCK 中最大的行数,为 4096 行
+
+Average_Rows: 每个 BLOCK 中的平均行数,此时为 4000 行
+
+
+*************************** 3.row ***************************
+
+_block_dist: Total_Tables=[1] Total_Files=[2] Total_Vgroups=[1]
+
+Total_Tables:   子表的个数,这里为 1
+
+Total_Files:   表数据被分别保存的数据文件数量,这里是 2 个文件
+
+Total_Vgroups: 表数据分布的虚拟节点(vnode)数量
+
+
+*************************** 5.row ***************************
+
+_block_dist: 0100 |
+
+*************************** 6.row ***************************
+
+_block_dist: 0299 |
+
+......
+
+*************************** 22.row ***************************
+
+_block_dist: 3483 |||||||||||||||||  1 (20.00%)
+
+*************************** 23.row ***************************
+
+_block_dist: 3682 |
+
+*************************** 24.row ***************************
+
+_block_dist: 3881 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||  4 (80.00%)
+
+Query OK, 24 row(s) in set (0.002444s)
+
+
+
+ +上面是块中包含数据行数的块儿分布情况图,这里的 0100 0299 0498 … 表示的是每个块中包含的数据行数,上面的意思就是这个表的 5 个块,分布在 3483 ~3681 行的块有 1 个,占整个块的 20%,分布在 3881 ~ 4096(最大行数)的块数为 4 个,占整个块的 80%, 其它区域内分布块数为 0。 + +需要注意,这里只会显示 data 文件中数据块的信息,stt 文件中的数据的信息不会被显示。 + ## SHOW TAGS ```sql @@ -226,12 +304,12 @@ SHOW DNODE dnode_id VARIABLES; SHOW [db_name.]VGROUPS; ``` -显示当前系统中所有 VGROUP 或某个 db 的 VGROUPS 的信息。 +显示当前数据库中所有 VGROUP 的信息。 ## SHOW VNODES ```sql -SHOW VNODES [dnode_name]; +SHOW VNODES {dnode_id | dnode_endpoint}; ``` 显示当前系统中所有 VNODE 或某个 DNODE 的 VNODE 的信息。 diff --git a/docs/zh/12-taos-sql/26-udf.md b/docs/zh/12-taos-sql/26-udf.md index cb349109a7d8758e336ec33ef9d70ece39be61f0..7697944f9a266279d1a13c6d392d8f6f3c16160d 100644 --- a/docs/zh/12-taos-sql/26-udf.md +++ b/docs/zh/12-taos-sql/26-udf.md @@ -41,7 +41,7 @@ CREATE AGGREGATE FUNCTION function_name AS library_path OUTPUTTYPE output_type [ ```sql CREATE AGGREGATE FUNCTION l2norm AS "/home/taos/udf_example/libl2norm.so" OUTPUTTYPE DOUBLE bufsize 8; ``` -关于如何开发自定义函数,请参考 [UDF使用说明](../../develop/udf)。 +关于如何开发自定义函数,请参考 [UDF使用说明](/develop/udf)。 ## 管理 UDF diff --git a/docs/zh/12-taos-sql/29-changes.md b/docs/zh/12-taos-sql/29-changes.md index 1ab7f4f0169932576edf9087a825367573713b03..a797966f57a5d9c8c942de1cce3dd3209c067de6 100644 --- a/docs/zh/12-taos-sql/29-changes.md +++ b/docs/zh/12-taos-sql/29-changes.md @@ -27,7 +27,7 @@ description: "TDengine 3.0 版本的语法变更说明" | - | :------- | :-------- | :------- | | 1 | ALTER ACCOUNT | 废除 | 2.x中为企业版功能,3.0不再支持。语法暂时保留了,执行报“This statement is no longer supported”错误。 | 2 | ALTER ALL DNODES | 新增 | 修改所有DNODE的参数。 -| 3 | ALTER DATABASE | 调整 | 废除
  • QUORUM:写入需要的副本确认数。3.0版本使用STRICT来指定强一致还是弱一致。3.0.0版本STRICT暂不支持修改。
  • BLOCKS:VNODE使用的内存块数。3.0版本使用BUFFER来表示VNODE写入内存池的大小。
  • UPDATE:更新操作的支持模式。3.0版本所有数据库都支持部分列更新。
  • CACHELAST:缓存最新一行数据的模式。3.0版本用CACHEMODEL代替。
  • COMP:3.0版本暂不支持修改。
    新增
  • CACHEMODEL:表示是否在内存中缓存子表的最近数据。
  • CACHESIZE:表示缓存子表最近数据的内存大小。
  • WAL_FSYNC_PERIOD:代替原FSYNC参数。
  • WAL_LEVEL:代替原WAL参数。
    调整
  • REPLICA:3.0.0版本暂不支持修改。
  • KEEP:3.0版本新增支持带单位的设置方式。
+| 3 | ALTER DATABASE | 调整 | 废除
  • QUORUM:写入需要的副本确认数。3.0 版本默认行为是强一致性,且不支持修改为弱一致性。
  • BLOCKS:VNODE使用的内存块数。3.0版本使用BUFFER来表示VNODE写入内存池的大小。
  • UPDATE:更新操作的支持模式。3.0版本所有数据库都支持部分列更新。
  • CACHELAST:缓存最新一行数据的模式。3.0版本用CACHEMODEL代替。
  • COMP:3.0版本暂不支持修改。

  • 新增
  • CACHEMODEL:表示是否在内存中缓存子表的最近数据。
  • CACHESIZE:表示缓存子表最近数据的内存大小。
  • WAL_FSYNC_PERIOD:代替原FSYNC参数。
  • WAL_LEVEL:代替原WAL参数。
  • WAL_RETENTION_PERIOD:3.0.4.0版本新增,wal文件的额外保留策略,用于数据订阅。
  • WAL_RETENTION_SIZE:3.0.4.0版本新增,wal文件的额外保留策略,用于数据订阅。
    调整
  • REPLICA:3.0.0版本暂不支持修改。
  • KEEP:3.0版本新增支持带单位的设置方式。
| 4 | ALTER STABLE | 调整 | 废除
  • CHANGE TAG:修改标签列的名称。3.0版本使用RENAME TAG代替。
    新增
  • RENAME TAG:代替原CHANGE TAG子句。
  • COMMENT:修改超级表的注释。
| 5 | ALTER TABLE | 调整 | 废除
  • CHANGE TAG:修改标签列的名称。3.0版本使用RENAME TAG代替。
    新增
  • RENAME TAG:代替原CHANGE TAG子句。
  • COMMENT:修改表的注释。
  • TTL:修改表的生命周期。
| 6 | ALTER USER | 调整 | 废除
  • PRIVILEGE:修改用户权限。3.0版本使用GRANT和REVOKE来授予和回收权限。
    新增
  • ENABLE:启用或停用此用户。
  • SYSINFO:修改用户是否可查看系统信息。
@@ -54,7 +54,6 @@ description: "TDengine 3.0 版本的语法变更说明" | 27 | GRANT | 新增 | 授予用户权限。 | 28 | KILL TRANSACTION | 新增 | 终止管理节点的事务。 | 29 | KILL STREAM | 废除 | 终止连续查询。3.0版本不再支持连续查询,而是用更通用的流计算来代替。 -| 30 | MERGE VGROUP | 新增 | 合并VGROUP。 | 31 | REVOKE | 新增 | 回收用户权限。 | 32 | SELECT | 调整 |
  • SELECT关闭隐式结果列,输出列均需要由SELECT子句来指定。
  • DISTINCT功能全面支持。2.x版本只支持对标签列去重,并且不可以和JOIN、GROUP BY等子句混用。
  • JOIN功能增强。增加支持:JOIN后WHERE条件中有OR条件;JOIN后的多表运算;JOIN后的多表GROUP BY。
  • FROM后子查询功能大幅增强。不限制子查询嵌套层数;支持子查询和UNION ALL混合使用;移除其他一些之前版本的语法限制。
  • WHERE后可以使用任意的标量表达式。
  • GROUP BY功能增强。支持任意标量表达式及其组合的分组。
  • SESSION可以用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。
  • STATE_WINDOW可以用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。
  • ORDER BY功能大幅增强。不再必须和GROUP BY子句一起使用;不再有排序表达式个数的限制;增加支持NULLS FIRST/LAST语法功能;支持符合语法语义的任意表达式。
  • 新增PARTITION BY语法。替代原来的GROUP BY tags。
| 33 | SHOW ACCOUNTS | 废除 | 2.x中为企业版功能,3.0不再支持。语法暂时保留了,执行报“This statement is no longer supported”错误。 @@ -76,8 +75,9 @@ description: "TDengine 3.0 版本的语法变更说明" | 49 | SHOW TRANSACTIONS | 新增 | 显示当前系统中正在执行的事务的信息。 | 50 | SHOW DNODE VARIABLES | 新增 |显示指定DNODE的配置参数。 | 51 | SHOW VNODES | 暂不支持 | 显示当前系统中VNODE的信息。3.0.0版本暂不支持。 -| 52 | SPLIT VGROUP | 新增 | 拆分VGROUP。 -| 53 | TRIM DATABASE | 新增 | 删除过期数据,并根据多级存储的配置归整数据。 +| 52 | TRIM DATABASE | 新增 | 删除过期数据,并根据多级存储的配置归整数据。 +| 53 | REDISTRIBUTE VGROUP | 新增 | 调整VGROUP中VNODE的分布。 +| 54 | BALANCE VGROUP | 新增 | 自动调整VGROUP中VNODE的分布。 ## SQL 函数变更 @@ -94,6 +94,7 @@ description: "TDengine 3.0 版本的语法变更说明" | 9 | SAMPLE | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 10 | STATECOUNT | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 | 11 | STATEDURATION | 增强 | 可以直接用于超级表了。没有PARTITION BY时,超级表的数据会被合并成一条时间线。 +| 12 | TIMETRUNCATE | 增强 | 增加ignore_timezone参数,可选是否使用,默认值为1. ## SCHEMALESS 变更 diff --git a/docs/zh/12-taos-sql/event_window.webp b/docs/zh/12-taos-sql/event_window.webp new file mode 100644 index 0000000000000000000000000000000000000000..6d2ac0820433ecb89f3e22f7070b94aa0635c885 Binary files /dev/null and b/docs/zh/12-taos-sql/event_window.webp differ diff --git a/docs/zh/14-reference/04-taosadapter.md b/docs/zh/14-reference/04-taosadapter.md index 4e1e7b7ace09f7cb43e5049ebefe21a24525b595..b8c5f9d647fcf920e454fabbf4da9c527b038a76 100644 --- a/docs/zh/14-reference/04-taosadapter.md +++ b/docs/zh/14-reference/04-taosadapter.md @@ -21,6 +21,7 @@ taosAdapter 提供以下功能: - 无缝连接到 collectd - 无缝连接到 StatsD - 支持 Prometheus remote_read 和 remote_write +- 获取 table 所在的虚拟节点组(VGroup)的 VGroup ID ## taosAdapter 架构图 @@ -57,6 +58,7 @@ Usage of taosAdapter: --collectd.enable enable collectd. Env "TAOS_ADAPTER_COLLECTD_ENABLE" (default true) --collectd.password string collectd password. Env "TAOS_ADAPTER_COLLECTD_PASSWORD" (default "taosdata") --collectd.port int collectd server port. Env "TAOS_ADAPTER_COLLECTD_PORT" (default 6045) + --collectd.ttl int collectd data ttl. Env "TAOS_ADAPTER_COLLECTD_TTL" --collectd.user string collectd user. Env "TAOS_ADAPTER_COLLECTD_USER" (default "root") --collectd.worker int collectd write worker. Env "TAOS_ADAPTER_COLLECTD_WORKER" (default 10) -c, --config string config path default /etc/taos/taosadapter.toml @@ -66,8 +68,9 @@ Usage of taosAdapter: --cors.allowOrigins stringArray cors allow origins. Env "TAOS_ADAPTER_ALLOW_ORIGINS" --cors.allowWebSockets cors allow WebSockets. Env "TAOS_ADAPTER_CORS_ALLOW_WebSockets" --cors.exposeHeaders stringArray cors expose headers. Env "TAOS_ADAPTER_Expose_Headers" - --debug enable debug mode. Env "TAOS_ADAPTER_DEBUG" + --debug enable debug mode. Env "TAOS_ADAPTER_DEBUG" (default true) --help Print this help message and exit + --httpCodeServerError Use a non-200 http status code when taosd returns an error. Env "TAOS_ADAPTER_HTTP_CODE_SERVER_ERROR" --influxdb.enable enable influxdb. Env "TAOS_ADAPTER_INFLUXDB_ENABLE" (default true) --log.enableRecordHttpSql whether to record http sql. Env "TAOS_ADAPTER_LOG_ENABLE_RECORD_HTTP_SQL" --log.path string log path. Env "TAOS_ADAPTER_LOG_PATH" (default "/var/log/taos") @@ -78,14 +81,17 @@ Usage of taosAdapter: --log.sqlRotationSize string record sql log rotation size(KB MB GB), must be a positive integer. Env "TAOS_ADAPTER_LOG_SQL_ROTATION_SIZE" (default "1GB") --log.sqlRotationTime duration record sql log rotation time. Env "TAOS_ADAPTER_LOG_SQL_ROTATION_TIME" (default 24h0m0s) --logLevel string log level (panic fatal error warn warning info debug trace). Env "TAOS_ADAPTER_LOG_LEVEL" (default "info") - --monitor.collectDuration duration Set monitor duration. Env "TAOS_MONITOR_COLLECT_DURATION" (default 3s) - --monitor.identity string The identity of the current instance, or 'hostname:port' if it is empty. Env "TAOS_MONITOR_IDENTITY" - --monitor.incgroup Whether running in cgroup. Env "TAOS_MONITOR_INCGROUP" - --monitor.password string TDengine password. Env "TAOS_MONITOR_PASSWORD" (default "taosdata") --monitor.pauseAllMemoryThreshold float Memory percentage threshold for pause all. Env "TAOS_MONITOR_PAUSE_ALL_MEMORY_THRESHOLD" (default 80) - --monitor.pauseQueryMemoryThreshold float Memory percentage threshold for pause query. Env "TAOS_MONITOR_PAUSE_QUERY_MEMORY_THRESHOLD" (default 70) - --monitor.user string TDengine user. Env "TAOS_MONITOR_USER" (default "root") - --monitor.writeInterval duration Set write to TDengine interval. Env "TAOS_MONITOR_WRITE_INTERVAL" (default 30s) - --monitor.writeToTD Whether write metrics to TDengine. Env "TAOS_MONITOR_WRITE_TO_TD" + --monitor.collectDuration duration Set monitor duration. Env "TAOS_ADAPTER_MONITOR_COLLECT_DURATION" (default 3s) + --monitor.disable Whether to disable monitoring. Env "TAOS_ADAPTER_MONITOR_DISABLE" + --monitor.disableCollectClientIP Whether to disable collecting clientIP. Env "TAOS_ADAPTER_MONITOR_DISABLE_COLLECT_CLIENT_IP" + --monitor.identity string The identity of the current instance, or 'hostname:port' if it is empty. Env "TAOS_ADAPTER_MONITOR_IDENTITY" + --monitor.incgroup Whether running in cgroup. Env "TAOS_ADAPTER_MONITOR_INCGROUP" + --monitor.password string TDengine password. Env "TAOS_ADAPTER_MONITOR_PASSWORD" (default "taosdata") + --monitor.pauseAllMemoryThreshold float Memory percentage threshold for pause all. Env "TAOS_ADAPTER_MONITOR_PAUSE_ALL_MEMORY_THRESHOLD" (default 80) + --monitor.pauseQueryMemoryThreshold float Memory percentage threshold for pause query. Env "TAOS_ADAPTER_MONITOR_PAUSE_QUERY_MEMORY_THRESHOLD" (default 70) + --monitor.user string TDengine user. Env "TAOS_ADAPTER_MONITOR_USER" (default "root") + --monitor.writeInterval duration Set write to TDengine interval. Env "TAOS_ADAPTER_MONITOR_WRITE_INTERVAL" (default 30s) + --monitor.writeToTD Whether write metrics to TDengine. Env "TAOS_ADAPTER_MONITOR_WRITE_TO_TD" --node_exporter.caCertFile string node_exporter ca cert file path. Env "TAOS_ADAPTER_NODE_EXPORTER_CA_CERT_FILE" --node_exporter.certFile string node_exporter cert file path. Env "TAOS_ADAPTER_NODE_EXPORTER_CERT_FILE" --node_exporter.db string node_exporter db name. Env "TAOS_ADAPTER_NODE_EXPORTER_DB" (default "node_exporter") @@ -98,6 +104,7 @@ Usage of taosAdapter: --node_exporter.keyFile string node_exporter cert key file path. Env "TAOS_ADAPTER_NODE_EXPORTER_KEY_FILE" --node_exporter.password string node_exporter password. Env "TAOS_ADAPTER_NODE_EXPORTER_PASSWORD" (default "taosdata") --node_exporter.responseTimeout duration node_exporter response timeout. Env "TAOS_ADAPTER_NODE_EXPORTER_RESPONSE_TIMEOUT" (default 5s) + --node_exporter.ttl int node_exporter data ttl. Env "TAOS_ADAPTER_NODE_EXPORTER_TTL" --node_exporter.urls strings node_exporter urls. Env "TAOS_ADAPTER_NODE_EXPORTER_URLS" (default [http://localhost:9100]) --node_exporter.user string node_exporter user. Env "TAOS_ADAPTER_NODE_EXPORTER_USER" (default "root") --opentsdb.enable enable opentsdb. Env "TAOS_ADAPTER_OPENTSDB_ENABLE" (default true) @@ -109,10 +116,11 @@ Usage of taosAdapter: --opentsdb_telnet.password string opentsdb_telnet password. Env "TAOS_ADAPTER_OPENTSDB_TELNET_PASSWORD" (default "taosdata") --opentsdb_telnet.ports ints opentsdb telnet tcp port. Env "TAOS_ADAPTER_OPENTSDB_TELNET_PORTS" (default [6046,6047,6048,6049]) --opentsdb_telnet.tcpKeepAlive enable tcp keep alive. Env "TAOS_ADAPTER_OPENTSDB_TELNET_TCP_KEEP_ALIVE" + --opentsdb_telnet.ttl int opentsdb_telnet data ttl. Env "TAOS_ADAPTER_OPENTSDB_TELNET_TTL" --opentsdb_telnet.user string opentsdb_telnet user. Env "TAOS_ADAPTER_OPENTSDB_TELNET_USER" (default "root") - --pool.idleTimeout duration Set idle connection timeout. Env "TAOS_ADAPTER_POOL_IDLE_TIMEOUT" (default 1h0m0s) - --pool.maxConnect int max connections to taosd. Env "TAOS_ADAPTER_POOL_MAX_CONNECT" (default 4000) - --pool.maxIdle int max idle connections to taosd. Env "TAOS_ADAPTER_POOL_MAX_IDLE" (default 4000) + --pool.idleTimeout duration Set idle connection timeout. Env "TAOS_ADAPTER_POOL_IDLE_TIMEOUT" + --pool.maxConnect int max connections to taosd. Env "TAOS_ADAPTER_POOL_MAX_CONNECT" + --pool.maxIdle int max idle connections to taosd. Env "TAOS_ADAPTER_POOL_MAX_IDLE" -P, --port int http port. Env "TAOS_ADAPTER_PORT" (default 6041) --prometheus.enable enable prometheus. Env "TAOS_ADAPTER_PROMETHEUS_ENABLE" (default true) --restfulRowLimit int restful returns the maximum number of rows (-1 means no limit). Env "TAOS_ADAPTER_RESTFUL_ROW_LIMIT" (default -1) @@ -129,6 +137,7 @@ Usage of taosAdapter: --statsd.port int statsd server port. Env "TAOS_ADAPTER_STATSD_PORT" (default 6044) --statsd.protocol string statsd protocol [tcp or udp]. Env "TAOS_ADAPTER_STATSD_PROTOCOL" (default "udp") --statsd.tcpKeepAlive enable tcp keep alive. Env "TAOS_ADAPTER_STATSD_TCP_KEEP_ALIVE" + --statsd.ttl int statsd data ttl. Env "TAOS_ADAPTER_STATSD_TTL" --statsd.user string statsd user. Env "TAOS_ADAPTER_STATSD_USER" (default "root") --statsd.worker int statsd write worker. Env "TAOS_ADAPTER_STATSD_WORKER" (default 10) --taosConfigDir string load taos client config path. Env "TAOS_ADAPTER_TAOS_CONFIG_FILE" @@ -174,6 +183,7 @@ AllowWebSockets node_export 是一个机器指标的导出器。请访问 [https://github.com/prometheus/node_exporter](https://github.com/prometheus/node_exporter) 了解更多信息。 - 支持 Prometheus remote_read 和 remote_write remote_read 和 remote_write 是 Prometheus 数据读写分离的集群方案。请访问[https://prometheus.io/blog/2019/10/10/remote-read-meets-streaming/#remote-apis](https://prometheus.io/blog/2019/10/10/remote-read-meets-streaming/#remote-apis) 了解更多信息。 +- 获取 table 所在的虚拟节点组(VGroup)的 VGroup ID。关于虚拟节点组(VGroup)的更多信息,请访问[整体架构文档](/tdinternal/arch/#主要逻辑单元) 。 ## 接口 @@ -195,6 +205,7 @@ AllowWebSockets - `precision` TDengine 使用的时间精度 - `u` TDengine 用户名 - `p` TDengine 密码 +- `ttl` 自动创建的子表生命周期,以子表的第一条数据的 TTL 参数为准,不可更新。更多信息请参考[创建表文档](taos-sql/table/#创建表)的 TTL 参数。 注意: 目前不支持 InfluxDB 的 token 验证方式,仅支持 Basic 验证和查询参数验证。 示例: curl --request POST http://127.0.0.1:6041/influxdb/v1/write?db=test --user "root:taosdata" --data-binary "measurement,host=host1 field1=2i,field2=2.0 1577836800000000000" @@ -235,6 +246,10 @@ Prometheus 使用的由 \*NIX 内核暴露的硬件和操作系统指标的输 +### 获取 table 的 VGroup ID + +可以访问 http 接口 `http://:6041/rest/vgid?db=&table=` 获取 table 的 VGroup ID。关于虚拟节点组(VGroup)的更多信息,请访问[整体架构文档](/tdinternal/arch/#主要逻辑单元) 。 + ## 内存使用优化方法 taosAdapter 将监测自身运行过程中内存使用率并通过两个阈值进行调节。有效值范围为 -1 到 100 的整数,单位为系统物理内存的百分比。 @@ -277,7 +292,7 @@ http 返回内容: ## taosAdapter 监控指标 -taosAdapter 采集 http 相关指标、cpu 百分比和内存百分比。 +taosAdapter 采集 http 相关指标、CPU 百分比和内存百分比。 ### http 接口 @@ -289,13 +304,13 @@ http://:6041/metrics ### 写入 TDengine -taosAdapter 支持将 http 监控、cpu 百分比和内存百分比写入 TDengine。 +taosAdapter 支持将 http 监控、CPU 百分比和内存百分比写入 TDengine。 有关配置参数 | **配置项** | **描述** | **默认值** | |-------------------------|--------------------------------------------|----------| -| monitor.collectDuration | cpu 和内存采集间隔 | 3s | +| monitor.collectDuration | CPU 和内存采集间隔 | 3s | | monitor.identity | 当前taosadapter 的标识符如果不设置将使用 'hostname:port' | | | monitor.incgroup | 是否是 cgroup 中运行(容器中运行设置为 true) | false | | monitor.writeToTD | 是否写入到 TDengine | false | @@ -312,6 +327,10 @@ taosAdapter 通过参数 `restfulRowLimit` 来控制结果的返回条数,-1 - `http://:6041/rest/sql` - `http://:6041/prometheus/v1/remote_read/:db` +## 配置 http 返回码 + +taosAdapter 通过参数 `httpCodeServerError` 来设置当 C 接口返回错误时是否返回非 200 的 http 状态码。当设置为 true 时将根据 C 返回的错误码返回不同 http 状态码。具体见 [HTTP 响应码](../../connector/rest-api/#http-响应码)。 + ## 故障解决 您可以通过命令 `systemctl status taosadapter` 来检查 taosAdapter 运行状态。 diff --git a/docs/zh/14-reference/05-taosbenchmark.md b/docs/zh/14-reference/05-taosbenchmark.md index 76dd5f12d89b223292a8c868fd66135ec204319b..c5d98767f9134c8eeb9bbc1ee2fb887370d9da54 100644 --- a/docs/zh/14-reference/05-taosbenchmark.md +++ b/docs/zh/14-reference/05-taosbenchmark.md @@ -204,6 +204,13 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\) - **-a/--replica ** : 创建数据库时指定其副本数,默认值为 1 。 +- ** -k/--keep-trying ** : 失败后进行重试的次数,默认不重试。需使用 v3.0.9 以上版本。 + +- ** -z/--trying-interval ** : 失败重试间隔时间,单位为毫秒,仅在 -k 指定重试后有效。需使用 v3.0.9 以上版本。 + +- **-v/--vgroups ** : + 创建数据库时指定 vgroups 数,仅对 TDengine v3.0+ 有效。 + - **-V/--version** : 显示版本信息并退出。不能与其它参数混用。 @@ -231,6 +238,17 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\) 插入场景下 `filetype` 必须设置为 `insert`,该参数及其它通用参数详见[通用配置参数](#通用配置参数) +- ** keep_trying ** : 失败后进行重试的次数,默认不重试。需使用 v3.0.9 以上版本。 + +- ** trying_interval ** : 失败重试间隔时间,单位为毫秒,仅在 keep_trying 指定重试后有效。需使用 v3.0.9 以上版本。 +- ** childtable_from 和 childtable_to ** : 指定写入子表范围,开闭区间为 [childtable_from, childtable_to). +  +- ** continue_if_fail ** : 允许用户定义失败后行为 + + “continue_if_fail”:  “no”, 失败 taosBenchmark 自动退出,默认行为 + “continue_if_fail”: “yes”, 失败 taosBenchmark 警告用户,并继续写入 + “continue_if_fail”: “smart”, 如果子表不存在失败,taosBenchmark 会建立子表并继续写入 + #### 数据库相关配置参数 创建数据库时的相关参数在 json 配置文件中的 `dbinfo` 中配置,个别具体参数如下。其余参数均与 TDengine 中 `create database` 时所指定的数据库参数相对应,详见[../../taos-sql/database] @@ -382,11 +400,11 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\) #### 执行指定查询语句的配置参数 -查询子表或者普通表的配置参数在 `specified_table_query` 中设置。 +查询指定表(可以指定超级表、子表或普通表)的配置参数在 `specified_table_query` 中设置。 - **query_interval** : 查询时间间隔,单位是秒,默认值为 0。 -- **threads** : 执行查询 SQL 的线程数,默认值为 1。 +- **threads/concurrent** : 执行查询 SQL 的线程数,默认值为 1。 - **sqls**: - **sql**: 执行的 SQL 命令,必填。 @@ -413,7 +431,7 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\) #### 执行指定订阅语句的配置参数 -订阅子表或者普通表的配置参数在 `specified_table_query` 中设置。 +订阅指定表(可以指定超级表、子表或者普通表)的配置参数在 `specified_table_query` 中设置。 - **threads/concurrent** : 执行 SQL 的线程数,默认为 1。 diff --git a/docs/zh/14-reference/06-taosdump.md b/docs/zh/14-reference/06-taosdump.md index 625499a94926ac3f86e4d34976c70a0bfe7b0954..8a031d147377713d0478d419798240f6f1194377 100644 --- a/docs/zh/14-reference/06-taosdump.md +++ b/docs/zh/14-reference/06-taosdump.md @@ -22,7 +22,7 @@ taosdump 是一个逻辑备份工具,它不应被用于备份任何原始数 taosdump 有两种安装方式: -- 安装 taosTools 官方安装包, 请从[所有下载链接](https://www.taosdata.com/all-downloads)页面找到 taosTools 并下载安装。 +- 安装 taosTools 官方安装包, 请从[发布历史页面](https://docs.taosdata.com/releases/tools/)页面找到 taosTools 并下载安装。 - 单独编译 taos-tools 并安装, 详情请参考 [taos-tools](https://github.com/taosdata/taos-tools) 仓库。 diff --git a/docs/zh/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json b/docs/zh/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json index f651983528ca824b4e6b14586aac5a5bfb4ecab8..43f29bda4445d0559b60d51a6d421442e9d38d4d 100644 --- a/docs/zh/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json +++ b/docs/zh/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json @@ -1590,7 +1590,7 @@ }, { "datasource": "${DS_TDENGINE}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -1919,7 +1919,7 @@ }, { "datasource": "${DS_TDENGINE}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -1977,7 +1977,7 @@ }, { "datasource": "${DS_TDENGINE}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -2825,7 +2825,7 @@ "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "Requets Count per Minutes $fqdn", + "title": "Requests Count per Minutes $fqdn", "tooltip": { "shared": true, "sort": 0, diff --git a/docs/zh/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp b/docs/zh/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp index 942130d4fabf7944c7add10acb3bb42ca7f51e0f..a90477880ff3a2cb2068540b55b69e4bbdbd8d4c 100644 Binary files a/docs/zh/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp and b/docs/zh/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp differ diff --git a/docs/zh/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json b/docs/zh/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json index b4254c428b28a0084e54b5e3c509dd2e0ec651b9..660875262edfe4b4211075839b60dfcdcb26d198 100644 --- a/docs/zh/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json +++ b/docs/zh/14-reference/07-tdinsight/assets/tdengine-grafana-7.x.json @@ -1566,7 +1566,7 @@ }, { "datasource": "${ds}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -1933,7 +1933,7 @@ }, { "datasource": "${ds}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -2000,7 +2000,7 @@ }, { "datasource": "${ds}", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "fieldConfig": { "defaults": { "color": { @@ -2961,7 +2961,7 @@ "timeFrom": null, "timeRegions": [], "timeShift": null, - "title": "Requets Count per Minutes $fqdn", + "title": "Requests Count per Minutes $fqdn", "tooltip": { "shared": true, "sort": 0, @@ -3355,4 +3355,4 @@ "title": "TDengine", "uid": "tdengine", "version": 8 -} \ No newline at end of file +} diff --git a/docs/zh/14-reference/07-tdinsight/assets/tdengine-grafana.json b/docs/zh/14-reference/07-tdinsight/assets/tdengine-grafana.json index 7696cfce3fcca3dd5f9278c91d3df2c1b32b9c97..e3bad31fab4e9110da505621d8ea7444584b33cb 100644 --- a/docs/zh/14-reference/07-tdinsight/assets/tdengine-grafana.json +++ b/docs/zh/14-reference/07-tdinsight/assets/tdengine-grafana.json @@ -186,7 +186,7 @@ }, { "datasource": "TDengine", - "description": "taosd max memery last 10 minutes", + "description": "taosd max memory last 10 minutes", "gridPos": { "h": 6, "w": 8, @@ -253,7 +253,7 @@ ], "timeFrom": null, "timeShift": null, - "title": "taosd memery", + "title": "taosd memory", "type": "gauge" }, { diff --git a/docs/zh/14-reference/07-tdinsight/index.mdx b/docs/zh/14-reference/07-tdinsight/index.mdx index 7f4c46a636ace97c6b04849d1b9805fcfc92da82..b4eda61ebdb4f6ab9b8b650571a35196c76eda56 100644 --- a/docs/zh/14-reference/07-tdinsight/index.mdx +++ b/docs/zh/14-reference/07-tdinsight/index.mdx @@ -43,10 +43,8 @@ sudo apt-get update sudo apt-get install grafana ``` -### 在 CentOS / RHEL 上安装 Grafana - - + 您可以从官方 YUM 镜像仓库安装。 @@ -79,7 +77,37 @@ sudo yum install \ - +### 安装 TDengine 数据源插件 + + + + +从 GitHub 安装 TDengine 最新版数据源插件。 + +```bash +get_latest_release() { + curl --silent "https://api.github.com/repos/taosdata/grafanaplugin/releases/latest" | + grep '"tag_name":' | + sed -E 's/.*"v([^"]+)".*/\1/' +} +TDENGINE_PLUGIN_VERSION=$(get_latest_release) +sudo grafana-cli \ + --pluginUrl https://github.com/taosdata/grafanaplugin/releases/download/v$TDENGINE_PLUGIN_VERSION/tdengine-datasource-$TDENGINE_PLUGIN_VERSION.zip \ + plugins install tdengine-datasource +``` + +:::note +3.1.6 和更早版本插件需要在配置文件 `/etc/grafana/grafana.ini` 中添加如下设置,以启用未签名插件。 + +```ini +[plugins] +allow_loading_unsigned_plugins = tdengine-datasource +``` + +::: + + + 我们提供了一个自动化安装脚本 [`TDinsight.sh`](https://github.com/taosdata/grafanaplugin/releases/latest/download/TDinsight.sh) 脚本以便用户快速进行安装配置。 @@ -140,10 +168,10 @@ Install and configure TDinsight dashboard in Grafana on Ubuntu 18.04/20.04 syste | -n | --tdengine-ds-name | TDENGINE_DS_NAME | TDengine 数据源名称,默认为 TDengine。 | | -a | --tdengine-api | TDENGINE_API | TDengine REST API 端点。默认为`http://127.0.0.1:6041`。 | | -u | --tdengine-user | TDENGINE_USER | TDengine 用户名。 [默认值:root] | -| -p | --tdengine-密码 | TDENGINE_PASSWORD | TDengine 密码。 [默认:taosdata] | +| -p | --tdengine-password | TDENGINE_PASSWORD | TDengine 密码。 [默认:taosdata] | | -i | --tdinsight-uid | TDINSIGHT_DASHBOARD_UID | TDinsight 仪表盘`uid`。 [默认值:tdinsight] | | -t | --tdinsight-title | TDINSIGHT_DASHBOARD_TITLE | TDinsight 仪表盘标题。 [默认:TDinsight] | -| -e | --tdinsight-可编辑 | TDINSIGHT_DASHBOARD_EDITABLE | 如果配置仪表盘可以编辑。 [默认值:false] | +| -e | --tdinsight-editable | TDINSIGHT_DASHBOARD_EDITABLE | 如果配置仪表盘可以编辑。 [默认值:false] | | -E | --external-notifier | EXTERNAL_NOTIFIER | 将外部通知程序 uid 应用于 TDinsight 仪表盘。 | 假设您在主机 `tdengine` 上启动 TDengine 数据库,HTTP API 端口为 `6041`,用户为 `root1`,密码为 `pass5ord`。执行脚本: @@ -175,33 +203,7 @@ sudo ./TDengine.sh -n TDengine-Env1 -a http://another:6041 -u root -p taosdata - 特别地,当您使用 Grafana Cloud 或其他组织时,`-O` 可用于设置组织 ID。 `-G` 可指定 Grafana 插件安装目录。 `-e` 参数将仪表盘设置为可编辑。 - - -### 安装 TDengine 数据源插件 - -从 GitHub 安装 TDengine 最新版数据源插件。 - -```bash -get_latest_release() { - curl --silent "https://api.github.com/repos/taosdata/grafanaplugin/releases/latest" | - grep '"tag_name":' | - sed -E 's/.*"v([^"]+)".*/\1/' -} -TDENGINE_PLUGIN_VERSION=$(get_latest_release) -sudo grafana-cli \ - --pluginUrl https://github.com/taosdata/grafanaplugin/releases/download/v$TDENGINE_PLUGIN_VERSION/tdengine-datasource-$TDENGINE_PLUGIN_VERSION.zip \ - plugins install tdengine-datasource -``` - -:::note -3.1.6 和更早版本插件需要在配置文件 `/etc/grafana/grafana.ini` 中添加如下设置,以启用未签名插件。 - -```ini -[plugins] -allow_loading_unsigned_plugins = tdengine-datasource -``` - -::: + ### 启动 Grafana 服务 @@ -233,8 +235,7 @@ sudo systemctl enable grafana-server ![TDengine Database TDinsight 数据源测试](./assets/howto-add-datasource-test.webp) - - + ### 导入仪表盘 @@ -345,11 +346,12 @@ TDinsight 仪表盘旨在提供 TDengine 相关资源的使用情况和状态, 支持监控 taosAdapter 请求统计和状态详情。包括: -1. **http_request_inflight**: 即时处理请求数 -2. **http_request_total**: 请求总数。 -3. **http_request_fail**: 请求总数。 -4. **CPU Used**: taosAdapter CPU 使用情况。 -5. **Memory Used**: taosAdapter 内存使用情况。 +1. **Http Request Total**: 请求总数。 +2. **Http Request Fail**: 请求总数。 +3. **CPU Used**: taosAdapter CPU 使用情况。 +4. **Memory Used**: taosAdapter 内存使用情况。 +5. **Http Request Inflight**: 即时处理请求数。 +6. **Http Status Code**: taosAdapter http 状态码。 ## 升级 diff --git a/docs/zh/14-reference/08-taos-shell.md b/docs/zh/14-reference/08-taos-shell.md index 5ac5f6f479e52aa7dd9a606a8eeb19e8c11a8a3c..3423cf35bbeb54c526e2bbad7ec3eae230cce07b 100644 --- a/docs/zh/14-reference/08-taos-shell.md +++ b/docs/zh/14-reference/08-taos-shell.md @@ -61,12 +61,14 @@ taos> SET MAX_BINARY_DISPLAY_WIDTH ; - -c CONFIGDIR: 指定配置文件目录,Linux 环境下默认为 `/etc/taos`,该目录下的配置文件默认名称为 `taos.cfg` - -C: 打印 -c 指定的目录中 `taos.cfg` 的配置参数 - -d DATABASE: 指定连接到服务端时使用的数据库 +- -E dsn: 使用 WebSocket DSN 连接云服务或者提供 WebSocket 连接的服务端 - -f FILE: 以非交互模式执行 SQL 脚本文件。文件中一个 SQL 语句只能占一行 - -k: 测试服务端运行状态,0: unavailable,1: network ok,2: service ok,3: service degraded,4: exiting - -l PKTLEN: 网络测试时使用的测试包大小 - -n NETROLE: 网络连接测试时的测试范围,默认为 `client`, 可选值为 `client`、`server` - -N PKTNUM: 网络测试时使用的测试包数量 - -r: 将时间输出出无符号 64 位整数类型(即 C 语音中 uint64_t) +- -R: 使用 RESTful 模式连接服务端 - -s COMMAND: 以非交互模式执行的 SQL 命令 - -t: 测试服务端启动状态,状态同-k - -w DISPLAYWIDTH: 客户端列显示宽度 diff --git a/docs/zh/14-reference/11-docker/index.md b/docs/zh/14-reference/11-docker/index.md index 086d72940c88adfe0e0c4c30cf16cc9cb2701630..a6696977f9cb08da2eb8ff68c42c54d388e74980 100644 --- a/docs/zh/14-reference/11-docker/index.md +++ b/docs/zh/14-reference/11-docker/index.md @@ -309,7 +309,7 @@ services: TAOS_FIRST_EP: "td-1" volumes: - taosdata-td3:/var/lib/taos/ - - taoslog-td3:/var/log/taos/ + - taoslog-td3:/var/log/taos/ volumes: taosdata-td1: taoslog-td1: @@ -473,18 +473,18 @@ Creating service taos_adapter ```shell $ docker stack ps taos ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS -7m3sbf532bqp taos_adapter.1 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago -pj403n6ofmmh taos_adapter.2 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago -rxqfwsyk5q1h taos_adapter.3 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago -qj40lpxr40oc taos_adapter.4 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago -oe3455ulxpze taos_nginx.1 nginx:latest vm98 Running Running about a minute ago -o0tsg70nrrc6 taos_td-1.1 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago +7m3sbf532bqp taos_adapter.1 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago +pj403n6ofmmh taos_adapter.2 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago +rxqfwsyk5q1h taos_adapter.3 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago +qj40lpxr40oc taos_adapter.4 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago +oe3455ulxpze taos_nginx.1 nginx:latest vm98 Running Running about a minute ago +o0tsg70nrrc6 taos_td-1.1 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago q5m1oxs589cp taos_td-2.1 tdengine/tdengine:3.0.0.0 vm98 Running Running about a minute ago $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS -ozuklorgl8bs taos_adapter replicated 4/4 tdengine/tdengine:3.0.0.0 +ozuklorgl8bs taos_adapter replicated 4/4 tdengine/tdengine:3.0.0.0 crmhdjw6vxw0 taos_nginx replicated 1/1 nginx:latest *:6041->6041/tcp, *:6044->6044/udp -o86ngy7csv5n taos_td-1 replicated 1/1 tdengine/tdengine:3.0.0.0 +o86ngy7csv5n taos_td-1 replicated 1/1 tdengine/tdengine:3.0.0.0 rma040ny4tb0 taos_td-2 replicated 1/1 tdengine/tdengine:3.0.0.0 ``` @@ -495,11 +495,11 @@ rma040ny4tb0 taos_td-2 replicated 1/1 tdengine/tdengine:3.0.0.0 ```shell $ docker service scale taos_adapter=1 taos_adapter scaled to 1 -overall progress: 1 out of 1 tasks -1/1: running [==================================================>] +overall progress: 1 out of 1 tasks +1/1: running [==================================================>] verify: Service converged $ docker service ls -f name=taos_adapter ID NAME MODE REPLICAS IMAGE PORTS -ozuklorgl8bs taos_adapter replicated 1/1 tdengine/tdengine:3.0.0.0 +ozuklorgl8bs taos_adapter replicated 1/1 tdengine/tdengine:3.0.0.0 ``` diff --git a/docs/zh/14-reference/12-config/index.md b/docs/zh/14-reference/12-config/index.md index 959438f48c288769186d22a9013fe10b738fd48f..e5efd77f8050ae2305a02a5bd70367d259cb971c 100644 --- a/docs/zh/14-reference/12-config/index.md +++ b/docs/zh/14-reference/12-config/index.md @@ -29,7 +29,7 @@ taos -C taos --dump-config ``` -# 配置参数详细列表 +## 配置参数详细列表 :::note 本节内容覆盖产品的配置参数,适用于服务端的参数按其对产品行为的影响进行分类,这其中有部分参数也同时适用于客户端;但有少量参数仅适用于客户端,这部分参数进行了单独归类。 @@ -83,7 +83,7 @@ taos --dump-config | :--- | :-------- | :---------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- | | TCP | 6030 | 客户端与服务端之间通讯,多节点集群的节点间通讯。 | 由配置文件设置 serverPort 决定。 | | TCP | 6041 | 客户端与服务端之间的 RESTful 通讯。 | 随 serverPort 端口变化。注意 taosAdapter 配置或有不同,请参考相应[文档](/reference/taosadapter/)。 | -| TCP | 6043 | TaosKeeper 监控服务端口。 | 随 TaosKeeper 启动参数设置变化。 | +| TCP | 6043 | taosKeeper 监控服务端口。 | 随 taosKeeper 启动参数设置变化。 | | TCP | 6044 | 支持 StatsD 的数据接入端口。 | 随 taosAdapter 启动参数设置变化| | UDP | 6045 | 支持 collectd 数据接入端口。 | 随 taosAdapter 启动参数设置变化 | | TCP | 6060 | 企业版内 Monitor 服务的网络端口。 | | @@ -99,21 +99,24 @@ taos --dump-config ## 监控相关 +:::note +请注意,完整的监控功能需要安装并运行 `taoskeeper` 服务。taoskeeper 负责接收监控指标数据并创建 `log` 库。 + ### monitor | 属性 | 说明 | | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 适用范围 | 仅服务端适用 | -| 含义 | 服务器内部的系统监控开关。监控主要负责收集物理节点的负载状况,包括 CPU、内存、硬盘、网络带宽的监控记录,监控信息将通过 HTTP 协议发送给由 `monitorFqdn` 和 `monitorProt` 指定的 TaosKeeper 监控服务 | +| 含义 | 服务器内部的系统监控开关。监控主要负责收集物理节点的负载状况,包括 CPU、内存、硬盘、网络带宽的监控记录,监控信息将通过 HTTP 协议发送给由 `monitorFqdn` 和 `monitorProt` 指定的 taosKeeper 监控服务 | | 取值范围 | 0:关闭监控服务, 1:激活监控服务。 | -| 缺省值 | 1 | +| 缺省值 | 0 | ### monitorFqdn | 属性 | 说明 | | -------- | -------------------------- | | 适用范围 | 仅服务端适用 | -| 含义 | TaosKeeper 监控服务的 FQDN | +| 含义 | taosKeeper 监控服务的 FQDN | | 缺省值 | 无 | ### monitorPort @@ -121,7 +124,7 @@ taos --dump-config | 属性 | 说明 | | -------- | --------------------------- | | 适用范围 | 仅服务端适用 | -| 含义 | TaosKeeper 监控服务的端口号 | +| 含义 | taosKeeper 监控服务的端口号 | | 缺省值 | 6043 | ### monitorInterval @@ -136,12 +139,21 @@ taos --dump-config ### telemetryReporting -| 属性 | 说明 | -| -------- | ---------------------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 是否允许 TDengine 采集和上报基本使用信息 | -| 取值范围 | 0:不允许 1:允许 | -| 缺省值 | 1 | +| 属性 | 说明 | +| -------- | -------------------------------------------- | +| 适用范围 | 仅服务端适用 | +| 含义 |是否上传 telemetry | +| 取值范围 | 0,1 0: 不上传;1:上传 | +| 缺省值 | 1 | + +### crashReporting + +| 属性 | 说明 | +| -------- | -------------------------------------------- | +| 适用范围 | 仅服务端适用 | +| 含义 |是否上传 crash 信息 | +| 取值范围 | 0,1 0: 不上传;1:上传 | +| 缺省值 | 1 | ## 查询相关 @@ -153,11 +165,7 @@ taos --dump-config | 含义 | 查询语句的执行策略 | | 单位 | 无 | | 缺省值 | 1 | -| 补充说明 | 1: 只使用 vnode,不使用 qnode | - -2: 没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行 - -3: vnode 只运行扫描算子,其余算子均在 qnode 执行 | +| 补充说明 | 1: 只使用 vnode,不使用 qnode; 2: 没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行; 3: vnode 只运行扫描算子,其余算子均在 qnode 执行 | ### querySmaOptimize @@ -167,11 +175,7 @@ taos --dump-config | 含义 | sma index 的优化策略 | | 单位 | 无 | | 缺省值 | 0 | -| 补充说明 | - -0: 表示不使用 sma index,永远从原始数据进行查询 - -1: 表示使用 sma index,对符合的语句,直接从预计算的结果进行查询 | +| 补充说明 |0: 表示不使用 sma index,永远从原始数据进行查询; 1: 表示使用 sma index,对符合的语句,直接从预计算的结果进行查询 | ### maxNumOfDistinctRes @@ -191,6 +195,16 @@ taos --dump-config | 取值范围 | 0 表示包含函数名,1 表示不包含函数名。 | | 缺省值 | 0 | +### countAlwaysReturnValue + +| 属性 | 说明 | +| -------- | -------------------------------- | +| 适用范围 | 仅服务端适用 | +| 含义 | count/hyperloglog函数在输入数据为空或者NULL的情况下是否返回值 | +| 取值范围 | 0:返回空行,1:返回 0 | +| 缺省值 | 1 | +| 补充说明 | 该参数设置为 1 时,如果查询中含有 GROUP BY,PARTITION BY 以及 INTERVAL 子句且相应的组或窗口内数据为空或者NULL, 对应的组或窗口将不返回查询结果 | + ## 区域相关 ### timezone @@ -305,13 +319,22 @@ charset 的有效值是 UTF-8。 | 适用范围 | 仅服务端适用 | | 含义 | 数据文件目录,所有的数据文件都将写入该目录 | | 缺省值 | /var/lib/taos | +| 补充说明 | [多级存储](https://docs.taosdata.com/tdinternal/arch/#%E5%A4%9A%E7%BA%A7%E5%AD%98%E5%82%A8) 功能需要与 [KEEP](https://docs.taosdata.com/taos-sql/database/#%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E) 参数配合使用 | + +### tempDir + +| 属性 | 说明 | +| -------- | ------------------------------------------ | +| 适用范围 | 仅服务端适用 | +| 含义 | 该参数指定所有系统运行过程中的临时文件生成的目录 | +| 缺省值 | /tmp | ### minimalTmpDirGB | 属性 | 说明 | | -------- | ------------------------------------------------ | | 适用范围 | 服务端和客户端均适用 | -| 含义 | 当日志文件夹的磁盘大小小于该值时,停止写临时文件 | +| 含义 | tempDir 所指定的临时文件目录所需要保留的最小空间 | | 单位 | GB | | 缺省值 | 1.0 | @@ -320,7 +343,7 @@ charset 的有效值是 UTF-8。 | 属性 | 说明 | | -------- | ------------------------------------------------ | | 适用范围 | 仅服务端适用 | -| 含义 | 当日志文件夹的磁盘大小小于该值时,停止写时序数据 | +| 含义 | dataDir 指定的时序数据存储目录所需要保留的最小 | | 单位 | GB | | 缺省值 | 2.0 | @@ -335,28 +358,6 @@ charset 的有效值是 UTF-8。 | 取值范围 | 0-4096 | | 缺省值 | CPU 核数的 2 倍 | -## 时间相关 - -### statusInterval - -| 属性 | 说明 | -| -------- | --------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | dnode 向 mnode 报告状态间隔 | -| 单位 | 秒 | -| 取值范围 | 1-10 | -| 缺省值 | 1 | - -### shellActivityTimer - -| 属性 | 说明 | -| -------- | --------------------------------- | -| 适用范围 | 服务端和客户端均适用 | -| 含义 | shell 客户端向 mnode 发送心跳间隔 | -| 单位 | 秒 | -| 取值范围 | 1-120 | -| 缺省值 | 3 | - ## 性能调优 ### numOfCommitThreads @@ -367,28 +368,6 @@ charset 的有效值是 UTF-8。 | 含义 | 设置写入线程的最大数量 | | 缺省值 | | -## 压缩相关 - -### compressMsgSize - -| 属性 | 说明 | -| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 客户端与服务器之间进行消息通讯过程中,对通讯的消息进行压缩的阈值。如果要压缩消息,建议设置为 64330 字节,即大于 64330 字节的消息体才进行压缩。 | -| 单位 | bytes | -| 取值范围 | `0 `表示对所有的消息均进行压缩 >0: 超过该值的消息才进行压缩 -1: 不压缩 | -| 缺省值 | -1 | - -### compressColData - -| 属性 | 说明 | -| -------- | --------------------------------------------------------------------------------------- | -| 适用范围 | 仅服务端适用 | -| 含义 | 客户端与服务器之间进行消息通讯过程中,对服务器端查询结果进行列压缩的阈值。 | -| 单位 | bytes | -| 取值范围 | 0: 对所有查询结果均进行压缩 >0: 查询结果中任意列大小超过该值的消息才进行压缩 -1: 不压缩 | -| 缺省值 | -1 | - ## 日志相关 ### logDir @@ -404,7 +383,7 @@ charset 的有效值是 UTF-8。 | 属性 | 说明 | | -------- | -------------------------------------------- | | 适用范围 | 服务端和客户端均适用 | -| 含义 | 当日志文件夹的磁盘大小小于该值时,停止写日志 | +| 含义 | 当日志文件夹所在磁盘可用空间大小小于该值时,停止写日志 | | 单位 | GB | | 缺省值 | 1.0 | @@ -613,7 +592,7 @@ charset 的有效值是 UTF-8。 | 属性 | 说明 | | -------- | ------------------------- | | 适用范围 | 仅客户端适用 | -| 含义 | schemaless 自定义的子表名 | +| 含义 | schemaless 自定义的子表名的 key | | 类型 | 字符串 | | 缺省值 | 无 | @@ -631,9 +610,9 @@ charset 的有效值是 UTF-8。 | 属性 | 说明 | | -------- | ----------------------------- | | 适用范围 | 仅客户端适用 | -| 含义 | schemaless 列数据是否顺序一致 | +| 含义 | schemaless 列数据是否顺序一致,从3.0.3.0开始,该配置废弃 | | 值域 | 0:不一致;1: 一致 | -| 缺省值 | 1 | +| 缺省值 | 0 | ## 其他 @@ -656,12 +635,18 @@ charset 的有效值是 UTF-8。 | 取值范围 | 0: 不启动;1:启动 | | 缺省值 | 1 | -## 2.X 与 3.0 配置参数对比 +## 压缩参数 -:::note -对于 2.x 版本中适用但在 3.0 版本中废弃的参数,其当前行为会有特别说明 +### compressMsgSize -::: +| 属性 | 说明 | +| -------- | ----------------------------- | +| 适用于 | 服务端和客户端均适用 | +| 含义 | 是否对 RPC 消息进行压缩 | +| 取值范围 | -1: 所有消息都不压缩; 0: 所有消息都压缩; N (N>0): 只有大于 N 个字节的消息才压缩 | +| 缺省值 | -1 | + +## 3.0 中有效的配置参数列表 | # | **参数** | **适用于 2.X ** | **适用于 3.0 ** | 3.0 版本的当前行为 | | --- | :---------------------: | --------------- | --------------- | ------------------------------------------------- | @@ -674,159 +659,134 @@ charset 的有效值是 UTF-8。 | 7 | monitorFqdn | 否 | 是 | | | 8 | monitorPort | 否 | 是 | | | 9 | monitorInterval | 是 | 是 | | -| 10 | monitorMaxLogs | 否 | 是 | | -| 11 | monitorComp | 否 | 是 | | -| 12 | telemetryReporting | 是 | 是 | | -| 13 | telemetryInterval | 否 | 是 | | -| 14 | telemetryServer | 否 | 是 | | -| 15 | telemetryPort | 否 | 是 | | -| 16 | queryPolicy | 否 | 是 | | -| 17 | querySmaOptimize | 否 | 是 | | -| 18 | queryRsmaTolerance | 否 | 是 | | -| 19 | queryBufferSize | 是 | 是 | | -| 20 | maxNumOfDistinctRes | 是 | 是 | | -| 21 | minSlidingTime | 是 | 是 | | -| 22 | minIntervalTime | 是 | 是 | | -| 23 | countAlwaysReturnValue | 是 | 是 | | -| 24 | dataDir | 是 | 是 | | -| 25 | minimalDataDirGB | 是 | 是 | | -| 26 | supportVnodes | 否 | 是 | | -| 27 | tempDir | 是 | 是 | | -| 28 | minimalTmpDirGB | 是 | 是 | | -| 29 | compressMsgSize | 是 | 是 | | -| 30 | compressColData | 是 | 是 | | -| 31 | smlChildTableName | 是 | 是 | | -| 32 | smlTagName | 是 | 是 | | -| 33 | smlDataFormat | 否 | 是 | | -| 34 | statusInterval | 是 | 是 | | -| 35 | shellActivityTimer | 是 | 是 | | -| 36 | transPullupInterval | 否 | 是 | | -| 37 | mqRebalanceInterval | 否 | 是 | | -| 38 | ttlUnit | 否 | 是 | | -| 39 | ttlPushInterval | 否 | 是 | | -| 40 | numOfTaskQueueThreads | 否 | 是 | | -| 41 | numOfRpcThreads | 否 | 是 | | -| 42 | numOfCommitThreads | 是 | 是 | | -| 43 | numOfMnodeReadThreads | 否 | 是 | | -| 44 | numOfVnodeQueryThreads | 否 | 是 | | -| 45 | ratioOfVnodeStreamThreads | 否 | 是 | | -| 46 | numOfVnodeFetchThreads | 否 | 是 | | -| 47 | numOfVnodeRsmaThreads | 否 | 是 | | -| 48 | numOfQnodeQueryThreads | 否 | 是 | | -| 49 | numOfQnodeFetchThreads | 否 | 是 | | -| 50 | numOfSnodeSharedThreads | 否 | 是 | | -| 51 | numOfSnodeUniqueThreads | 否 | 是 | | -| 52 | rpcQueueMemoryAllowed | 否 | 是 | | -| 53 | logDir | 是 | 是 | | -| 54 | minimalLogDirGB | 是 | 是 | | -| 55 | numOfLogLines | 是 | 是 | | -| 56 | asyncLog | 是 | 是 | | -| 57 | logKeepDays | 是 | 是 | | -| 60 | debugFlag | 是 | 是 | | -| 61 | tmrDebugFlag | 是 | 是 | | -| 62 | uDebugFlag | 是 | 是 | | -| 63 | rpcDebugFlag | 是 | 是 | | -| 64 | jniDebugFlag | 是 | 是 | | -| 65 | qDebugFlag | 是 | 是 | | -| 66 | cDebugFlag | 是 | 是 | | -| 67 | dDebugFlag | 是 | 是 | | -| 68 | vDebugFlag | 是 | 是 | | -| 69 | mDebugFlag | 是 | 是 | | -| 70 | wDebugFlag | 是 | 是 | | -| 71 | sDebugFlag | 是 | 是 | | -| 72 | tsdbDebugFlag | 是 | 是 | | -| 73 | tqDebugFlag | 否 | 是 | | -| 74 | fsDebugFlag | 是 | 是 | | -| 75 | udfDebugFlag | 否 | 是 | | -| 76 | smaDebugFlag | 否 | 是 | | -| 77 | idxDebugFlag | 否 | 是 | | -| 78 | tdbDebugFlag | 否 | 是 | | -| 79 | metaDebugFlag | 否 | 是 | | -| 80 | timezone | 是 | 是 | | -| 81 | locale | 是 | 是 | | -| 82 | charset | 是 | 是 | | -| 83 | udf | 是 | 是 | | -| 84 | enableCoreFile | 是 | 是 | | -| 85 | arbitrator | 是 | 否 | 通过 RAFT 协议选主 | -| 86 | numOfThreadsPerCore | 是 | 否 | 有其它参数设置多种线程池的大小 | -| 87 | numOfMnodes | 是 | 否 | 通过 create mnode 命令动态创建 mnode | -| 88 | vnodeBak | 是 | 否 | 3.0 行为未知 | -| 89 | balance | 是 | 否 | 负载均衡功能由 split/merge vgroups 实现 | -| 90 | balanceInterval | 是 | 否 | 随着 balance 参数失效 | -| 91 | offlineThreshold | 是 | 否 | 3.0 行为未知 | -| 92 | role | 是 | 否 | 由 supportVnode 决定是否能够创建 | -| 93 | dnodeNopLoop | 是 | 否 | 2.6 文档中未找到此参数 | -| 94 | keepTimeOffset | 是 | 否 | 2.6 文档中未找到此参数 | -| 95 | rpcTimer | 是 | 否 | 3.0 行为未知 | -| 96 | rpcMaxTime | 是 | 否 | 3.0 行为未知 | -| 97 | rpcForceTcp | 是 | 否 | 默认为 TCP | -| 98 | tcpConnTimeout | 是 | 否 | 3.0 行为未知 | -| 99 | syncCheckInterval | 是 | 否 | 3.0 行为未知 | -| 100 | maxTmrCtrl | 是 | 否 | 3.0 行为未知 | -| 101 | monitorReplica | 是 | 否 | 由 RAFT 协议管理多副本 | -| 102 | smlTagNullName | 是 | 否 | 3.0 行为未知 | -| 103 | keepColumnName | 是 | 否 | 3.0 行为未知 | -| 104 | ratioOfQueryCores | 是 | 否 | 由 线程池 相关配置参数决定 | -| 105 | maxStreamCompDelay | 是 | 否 | 3.0 行为未知 | -| 106 | maxFirstStreamCompDelay | 是 | 否 | 3.0 行为未知 | -| 107 | retryStreamCompDelay | 是 | 否 | 3.0 行为未知 | -| 108 | streamCompDelayRatio | 是 | 否 | 3.0 行为未知 | -| 109 | maxVgroupsPerDb | 是 | 否 | 由 create db 的参数 vgroups 指定实际 vgroups 数量 | -| 110 | maxTablesPerVnode | 是 | 否 | DB 中的所有表近似平均分配到各个 vgroup | -| 111 | minTablesPerVnode | 是 | 否 | DB 中的所有表近似平均分配到各个 vgroup | -| 112 | tableIncStepPerVnode | 是 | 否 | DB 中的所有表近似平均分配到各个 vgroup | -| 113 | cache | 是 | 否 | 由 buffer 代替 cache\*blocks | -| 114 | blocks | 是 | 否 | 由 buffer 代替 cache\*blocks | -| 115 | days | 是 | 否 | 由 create db 的参数 duration 取代 | -| 116 | keep | 是 | 否 | 由 create db 的参数 keep 取代 | -| 117 | minRows | 是 | 否 | 由 create db 的参数 minRows 取代 | -| 118 | maxRows | 是 | 否 | 由 create db 的参数 maxRows 取代 | -| 119 | quorum | 是 | 否 | 由 RAFT 协议决定 | -| 120 | comp | 是 | 否 | 由 create db 的参数 comp 取代 | -| 121 | walLevel | 是 | 否 | 由 create db 的参数 wal_level 取代 | -| 122 | fsync | 是 | 否 | 由 create db 的参数 wal_fsync_period 取代 | -| 123 | replica | 是 | 否 | 由 create db 的参数 replica 取代 | -| 124 | partitions | 是 | 否 | 3.0 行为未知 | -| 125 | update | 是 | 否 | 允许更新部分列 | -| 126 | cachelast | 是 | 否 | 由 create db 的参数 cacheModel 取代 | -| 127 | maxSQLLength | 是 | 否 | SQL 上限为 1MB,无需参数控制 | -| 128 | maxWildCardsLength | 是 | 否 | 3.0 行为未知 | -| 129 | maxRegexStringLen | 是 | 否 | 3.0 行为未知 | -| 130 | maxNumOfOrderedRes | 是 | 否 | 3.0 行为未知 | -| 131 | maxConnections | 是 | 否 | 取决于系统配置和系统处理能力,详见后面的 Note | -| 132 | mnodeEqualVnodeNum | 是 | 否 | 3.0 行为未知 | -| 133 | http | 是 | 否 | http 服务由 taosAdapter 提供 | -| 134 | httpEnableRecordSql | 是 | 否 | taosd 不提供 http 服务 | -| 135 | httpMaxThreads | 是 | 否 | taosd 不提供 http 服务 | -| 136 | restfulRowLimit | 是 | 否 | taosd 不提供 http 服务 | -| 137 | httpDbNameMandatory | 是 | 否 | taosd 不提供 http 服务 | -| 138 | httpKeepAlive | 是 | 否 | taosd 不提供 http 服务 | -| 139 | enableRecordSql | 是 | 否 | 3.0 行为未知 | -| 140 | maxBinaryDisplayWidth | 是 | 否 | 3.0 行为未知 | -| 141 | stream | 是 | 否 | 默认启用连续查询 | -| 142 | retrieveBlockingModel | 是 | 否 | 3.0 行为未知 | -| 143 | tsdbMetaCompactRatio | 是 | 否 | 3.0 行为未知 | -| 144 | defaultJSONStrType | 是 | 否 | 3.0 行为未知 | -| 145 | walFlushSize | 是 | 否 | 3.0 行为未知 | -| 146 | keepTimeOffset | 是 | 否 | 3.0 行为未知 | -| 147 | flowctrl | 是 | 否 | 3.0 行为未知 | -| 148 | slaveQuery | 是 | 否 | 3.0 行为未知: slave vnode 是否能够处理查询? | -| 149 | adjustMaster | 是 | 否 | 3.0 行为未知 | -| 150 | topicBinaryLen | 是 | 否 | 3.0 行为未知 | -| 151 | telegrafUseFieldNum | 是 | 否 | 3.0 行为未知 | -| 152 | deadLockKillQuery | 是 | 否 | 3.0 行为未知 | -| 153 | clientMerge | 是 | 否 | 3.0 行为未知 | -| 154 | sdbDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 155 | odbcDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 156 | httpDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 157 | monDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 158 | cqDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 159 | shortcutFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | -| 160 | probeSeconds | 是 | 否 | 3.0 行为未知 | -| 161 | probeKillSeconds | 是 | 否 | 3.0 行为未知 | -| 162 | probeInterval | 是 | 否 | 3.0 行为未知 | -| 163 | lossyColumns | 是 | 否 | 3.0 行为未知 | -| 164 | fPrecision | 是 | 否 | 3.0 行为未知 | -| 165 | dPrecision | 是 | 否 | 3.0 行为未知 | -| 166 | maxRange | 是 | 否 | 3.0 行为未知 | -| 167 | range | 是 | 否 | 3.0 行为未知 | +| 10 | queryPolicy | 否 | 是 | | +| 11 | querySmaOptimize | 否 | 是 | | +| 12 | maxNumOfDistinctRes | 是 | 是 | | +| 15 | countAlwaysReturnValue | 是 | 是 | | +| 16 | dataDir | 是 | 是 | | +| 17 | minimalDataDirGB | 是 | 是 | | +| 18 | supportVnodes | 否 | 是 | | +| 19 | tempDir | 是 | 是 | | +| 20 | minimalTmpDirGB | 是 | 是 | | +| 21 | smlChildTableName | 是 | 是 | | +| 22 | smlTagName | 是 | 是 | | +| 23 | smlDataFormat | 否 | 是(从3.0.3.0开始,该配置废弃) | | +| 24 | statusInterval | 是 | 是 | | +| 25 | logDir | 是 | 是 | | +| 26 | minimalLogDirGB | 是 | 是 | | +| 27 | numOfLogLines | 是 | 是 | | +| 28 | asyncLog | 是 | 是 | | +| 29 | logKeepDays | 是 | 是 | | +| 30 | debugFlag | 是 | 是 | | +| 31 | tmrDebugFlag | 是 | 是 | | +| 32 | uDebugFlag | 是 | 是 | | +| 33 | rpcDebugFlag | 是 | 是 | | +| 34 | jniDebugFlag | 是 | 是 | | +| 35 | qDebugFlag | 是 | 是 | | +| 36 | cDebugFlag | 是 | 是 | | +| 37 | dDebugFlag | 是 | 是 | | +| 38 | vDebugFlag | 是 | 是 | | +| 39 | mDebugFlag | 是 | 是 | | +| 40 | wDebugFlag | 是 | 是 | | +| 41 | sDebugFlag | 是 | 是 | | +| 42 | tsdbDebugFlag | 是 | 是 | | +| 43 | tqDebugFlag | 否 | 是 | | +| 44 | fsDebugFlag | 是 | 是 | | +| 45 | udfDebugFlag | 否 | 是 | | +| 46 | smaDebugFlag | 否 | 是 | | +| 47 | idxDebugFlag | 否 | 是 | | +| 48 | tdbDebugFlag | 否 | 是 | | +| 49 | metaDebugFlag | 否 | 是 | | +| 50 | timezone | 是 | 是 | | +| 51 | locale | 是 | 是 | | +| 52 | charset | 是 | 是 | | +| 53 | udf | 是 | 是 | | +| 54 | enableCoreFile | 是 | 是 | | + +## 2.x->3.0 的废弃参数 + +| # | **参数** | **适用于 2.X ** | **适用于 3.0 ** | 3.0 版本的当前行为 | +| --- | :---------------------: | --------------- | --------------- | ------------------------------------------------- | +| 1 | arbitrator | 是 | 否 | 通过 RAFT 协议选主 | +| 2 | numOfThreadsPerCore | 是 | 否 | 有其它参数设置多种线程池的大小 | +| 3 | numOfMnodes | 是 | 否 | 通过 create mnode 命令动态创建 mnode | +| 4 | vnodeBak | 是 | 否 | 3.0 行为未知 | +| 5 | balance | 是 | 否 | 负载均衡功能由 split/merge vgroups 实现 (暂不支持) | +| 6 | balanceInterval | 是 | 否 | 随着 balance 参数失效 | +| 7 | offlineThreshold | 是 | 否 | 3.0 行为未知 | +| 8 | role | 是 | 否 | 由 supportVnode 决定是否能够创建 | +| 9 | dnodeNopLoop | 是 | 否 | 2.6 文档中未找到此参数 | +| 10 | keepTimeOffset | 是 | 否 | 2.6 文档中未找到此参数 | +| 11 | rpcTimer | 是 | 否 | 3.0 行为未知 | +| 12 | rpcMaxTime | 是 | 否 | 3.0 行为未知 | +| 13 | rpcForceTcp | 是 | 否 | 默认为 TCP | +| 14 | tcpConnTimeout | 是 | 否 | 3.0 行为未知 | +| 15 | syncCheckInterval | 是 | 否 | 3.0 行为未知 | +| 16 | maxTmrCtrl | 是 | 否 | 3.0 行为未知 | +| 17 | monitorReplica | 是 | 否 | 由 RAFT 协议管理多副本 | +| 18 | smlTagNullName | 是 | 否 | 3.0 行为未知 | +| 19 | keepColumnName | 是 | 否 | 3.0 行为未知 | +| 20 | ratioOfQueryCores | 是 | 否 | 由 线程池 相关配置参数决定 | +| 21 | maxStreamCompDelay | 是 | 否 | 3.0 行为未知 | +| 22 | maxFirstStreamCompDelay | 是 | 否 | 3.0 行为未知 | +| 23 | retryStreamCompDelay | 是 | 否 | 3.0 行为未知 | +| 24 | streamCompDelayRatio | 是 | 否 | 3.0 行为未知 | +| 25 | maxVgroupsPerDb | 是 | 否 | 由 create db 的参数 vgroups 指定实际 vgroups 数量 | +| 26 | maxTablesPerVnode | 是 | 否 | DB 中的所有表近似平均分配到各个 vgroup | +| 27 | minTablesPerVnode | 是 | 否 | DB 中的所有表近似平均分配到各个 vgroup | +| 28 | tableIncStepPerVnode | 是 | 否 | DB 中的所有表近似平均分配到各个 vgroup | +| 29 | cache | 是 | 否 | 由 buffer 代替 cache\*blocks | +| 30 | blocks | 是 | 否 | 由 buffer 代替 cache\*blocks | +| 31 | days | 是 | 否 | 由 create db 的参数 duration 取代 | +| 32 | keep | 是 | 否 | 由 create db 的参数 keep 取代 | +| 33 | minRows | 是 | 否 | 由 create db 的参数 minRows 取代 | +| 34 | maxRows | 是 | 否 | 由 create db 的参数 maxRows 取代 | +| 35 | quorum | 是 | 否 | 由 RAFT 协议决定 | +| 36 | comp | 是 | 否 | 由 create db 的参数 comp 取代 | +| 37 | walLevel | 是 | 否 | 由 create db 的参数 wal_level 取代 | +| 38 | fsync | 是 | 否 | 由 create db 的参数 wal_fsync_period 取代 | +| 39 | replica | 是 | 否 | 由 create db 的参数 replica 取代 | +| 40 | partitions | 是 | 否 | 3.0 行为未知 | +| 41 | update | 是 | 否 | 允许更新部分列 | +| 42 | cachelast | 是 | 否 | 由 create db 的参数 cacheModel 取代 | +| 43 | maxSQLLength | 是 | 否 | SQL 上限为 1MB,无需参数控制 | +| 44 | maxWildCardsLength | 是 | 否 | 3.0 行为未知 | +| 45 | maxRegexStringLen | 是 | 否 | 3.0 行为未知 | +| 46 | maxNumOfOrderedRes | 是 | 否 | 3.0 行为未知 | +| 47 | maxConnections | 是 | 否 | 取决于系统配置和系统处理能力,详见后面的 Note | +| 48 | mnodeEqualVnodeNum | 是 | 否 | 3.0 行为未知 | +| 49 | http | 是 | 否 | http 服务由 taosAdapter 提供 | +| 50 | httpEnableRecordSql | 是 | 否 | taosd 不提供 http 服务 | +| 51 | httpMaxThreads | 是 | 否 | taosd 不提供 http 服务 | +| 52 | restfulRowLimit | 是 | 否 | taosd 不提供 http 服务 | +| 53 | httpDbNameMandatory | 是 | 否 | taosd 不提供 http 服务 | +| 54 | httpKeepAlive | 是 | 否 | taosd 不提供 http 服务 | +| 55 | enableRecordSql | 是 | 否 | 3.0 行为未知 | +| 56 | maxBinaryDisplayWidth | 是 | 否 | 3.0 行为未知 | +| 57 | stream | 是 | 否 | 默认启用连续查询 | +| 58 | retrieveBlockingModel | 是 | 否 | 3.0 行为未知 | +| 59 | tsdbMetaCompactRatio | 是 | 否 | 3.0 行为未知 | +| 60 | defaultJSONStrType | 是 | 否 | 3.0 行为未知 | +| 61 | walFlushSize | 是 | 否 | 3.0 行为未知 | +| 62 | keepTimeOffset | 是 | 否 | 3.0 行为未知 | +| 63 | flowctrl | 是 | 否 | 3.0 行为未知 | +| 64 | slaveQuery | 是 | 否 | 3.0 行为未知: slave vnode 是否能够处理查询? | +| 65 | adjustMaster | 是 | 否 | 3.0 行为未知 | +| 66 | topicBinaryLen | 是 | 否 | 3.0 行为未知 | +| 67 | telegrafUseFieldNum | 是 | 否 | 3.0 行为未知 | +| 68 | deadLockKillQuery | 是 | 否 | 3.0 行为未知 | +| 69 | clientMerge | 是 | 否 | 3.0 行为未知 | +| 70 | sdbDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | +| 71 | odbcDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | +| 72 | httpDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | +| 73 | monDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | +| 74 | cqDebugFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | +| 75 | shortcutFlag | 是 | 否 | 参考 3.0 的 DebugFlag 系列参数 | +| 76 | probeSeconds | 是 | 否 | 3.0 行为未知 | +| 77 | probeKillSeconds | 是 | 否 | 3.0 行为未知 | +| 78 | probeInterval | 是 | 否 | 3.0 行为未知 | +| 79 | lossyColumns | 是 | 否 | 3.0 行为未知 | +| 80 | fPrecision | 是 | 否 | 3.0 行为未知 | +| 81 | dPrecision | 是 | 否 | 3.0 行为未知 | +| 82 | maxRange | 是 | 否 | 3.0 行为未知 | +| 83 | range | 是 | 否 | 3.0 行为未知 | diff --git a/docs/zh/14-reference/13-schemaless/13-schemaless.md b/docs/zh/14-reference/13-schemaless/13-schemaless.md index 3aebd616a075394dbeddc9e608cd2a57bb8cf844..e5f232c1fc506a6e37cb128cab129a7fe539d60a 100644 --- a/docs/zh/14-reference/13-schemaless/13-schemaless.md +++ b/docs/zh/14-reference/13-schemaless/13-schemaless.md @@ -83,11 +83,11 @@ st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4f64 1626006833639000000 NULL。 6. 对 BINARY 或 NCHAR 列,如果数据行中所提供值的长度超出了列类型的限制,自动增加该列允许存储的字符长度上限(只增不减),以保证数据的完整保存。 7. 整个处理过程中遇到的错误会中断写入过程,并返回错误代码。 -8. 为了提高写入的效率,默认假设同一个超级表中 field_set 的顺序是一样的(第一条数据包含所有的 field,后面的数据按照这个顺序),如果顺序不一样,需要配置参数 smlDataFormat 为 false,否则,数据写入按照相同顺序写入,库中数据会异常。 +8. 为了提高写入的效率,默认假设同一个超级表中 field_set 的顺序是一样的(第一条数据包含所有的 field,后面的数据按照这个顺序),如果顺序不一样,需要配置参数 smlDataFormat 为 false,否则,数据写入按照相同顺序写入,库中数据会异常,从3.0.3.0开始,自动检测顺序是否一致,该配置废弃。 :::tip 无模式所有的处理逻辑,仍会遵循 TDengine 对数据结构的底层限制,例如每行数据的总长度不能超过 -16KB。这方面的具体限制约束请参见 [TDengine SQL 边界限制](/taos-sql/limit) +48KB,标签值的总长度不超过16KB。这方面的具体限制约束请参见 [TDengine SQL 边界限制](/taos-sql/limit) ::: diff --git a/docs/zh/14-reference/14-taosKeeper.md b/docs/zh/14-reference/14-taosKeeper.md index 7780dc2fe9a5742ce9d6855599ca080804a493b5..12b609584a65d729c93e256b3918bd04d03e2010 100644 --- a/docs/zh/14-reference/14-taosKeeper.md +++ b/docs/zh/14-reference/14-taosKeeper.md @@ -4,51 +4,114 @@ title: taosKeeper description: TDengine 3.0 版本监控指标的导出工具 --- +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + ## 简介 -TaosKeeper 是 TDengine 3.0 版本监控指标的导出工具,通过简单的几项配置即可获取 TDengine 的运行状态。taosKeeper 使用 TDengine RESTful 接口,所以不需要安装 TDengine 客户端即可使用。 +taosKeeper 是 TDengine 3.0 版本监控指标的导出工具,通过简单的几项配置即可获取 TDengine 的运行状态。taosKeeper 使用 TDengine RESTful 接口,所以不需要安装 TDengine 客户端即可使用。 ## 安装 - +taosKeeper 有两种安装方式: taosKeeper 安装方式: - +- 安装 TDengine 官方安装包的同时会自动安装 taosKeeper, 详情请参考[ TDengine 安装](/operation/pkg-install)。 - - 单独编译 taosKeeper 并安装,详情请参考 [taosKeeper](https://github.com/taosdata/taoskeeper) 仓库。 -## 运行 +## 配置和运行方式 -### 配置和运行方式 +### 配置 taosKeeper 需要在操作系统终端执行,该工具支持三种配置方式:[命令行参数](#命令行参数启动)、[环境变量](#环境变量启动) 和 [配置文件](#配置文件启动)。优先级为:命令行参数、环境变量、配置文件参数。 -**在运行 taosKeeper 之前要确保 TDengine 集群与 taosAdapter 已经在正确运行。** 并且 TDengine 已经开启监控服务,具体请参考:[TDengine 监控配置](../config/#监控相关)。 +**在运行 taosKeeper 之前要确保 TDengine 集群与 taosAdapter 已经在正确运行。** 并且 TDengine 已经开启监控服务,TDengine 配置文件 `taos.cfg` 中至少需要配置 `monitor` 和 `monitorFqdn`。 + +```shell +monitor 1 +monitorFqdn localhost # taoskeeper 服务的 FQDN +``` + +TDengine 监控配置相关,具体请参考:[TDengine 监控配置](../config/#监控相关)。 -### 命令行参数启动 -在使用命令行参数运行 taosKeeper 并控制其行为。 +### 启动 -```shell -$ taosKeeper + + + +安装后,请使用 `systemctl` 命令来启动 taoskeeper 的服务进程。 + +```bash +systemctl start taoskeeper ``` -### 环境变量启动 +检查服务是否正常工作: -通过设置环境变量达到控制启动参数的目的,通常在容器中运行时使用。 +```bash +systemctl status taoskeeper +``` + +如果服务进程处于活动状态,则 status 指令会显示如下的相关信息: -```shell -$ export TAOS_KEEPER_TDENGINE_HOST=192.168.64.3 - -$ taoskeeper ``` +Active: active (running) +``` + +如果后台服务进程处于停止状态,则 status 指令会显示如下的相关信息: + +``` +Active: inactive (dead) +``` + +如下 `systemctl` 命令可以帮助你管理 taoskeeper 服务: + +- 启动服务进程:`systemctl start taoskeeper` + +- 停止服务进程:`systemctl stop taoskeeper` + +- 重启服务进程:`systemctl restart taoskeeper` + +- 查看服务状态:`systemctl status taoskeeper` -具体参数列表请参照 `taoskeeper -h` 输入结果。 +:::info -### 配置文件启动 +- `systemctl` 命令需要 _root_ 权限来运行,如果您非 _root_ 用户,请在命令前添加 `sudo`。 +- 如果系统中不支持 `systemd`,也可以用手动运行 `/usr/local/taos/bin/taoskeeper` 方式启动 taoskeeper 服务。 +- 故障排查: +- 如果服务异常请查看系统日志获取更多信息。 +::: + -执行以下命令即可快速体验 taosKeeper。当不指定 taosKeeper 配置文件时,优先使用 `/etc/taos/keeper.toml` 配置,否则将使用默认配置。 + + +安装后,可以运行 `sudo launchctl start com.tdengine.taoskeeper` 来启动 taoskeeper 服务进程。 + +如下 `launchctl` 命令用于管理 taoskeeper 服务: + +- 启动服务进程:`sudo launchctl start com.tdengine.taoskeeper` + +- 停止服务进程:`sudo launchctl stop com.tdengine.taoskeeper` + +- 查看服务状态:`sudo launchctl list | grep taoskeeper` + +:::info + +- `launchctl` 命令管理`com.tdengine.taoskeeper`需要管理员权限,务必在前面加 `sudo` 来增强安全性。 +- `sudo launchctl list | grep taoskeeper` 指令返回的第一列是 `taoskeeper` 程序的 PID,若为 `-` 则说明 taoskeeper 服务未运行。 +- 故障排查: +- 如果服务异常请查看系统日志获取更多信息。 + +::: + + + + + +#### 配置文件启动 + +执行以下命令即可快速体验 taosKeeper。当不指定 taosKeeper 配置文件时,优先使用 `/etc/taos/keeper.toml` 配置,否则将使用默认配置。 ```shell $ taoskeeper -c @@ -126,19 +189,36 @@ $ curl http://127.0.0.1:6043/metrics 部分结果集: ```shell -# HELP taos_cluster_info_connections_total +# HELP taos_cluster_info_connections_total # TYPE taos_cluster_info_connections_total counter taos_cluster_info_connections_total{cluster_id="5981392874047724755"} 16 -# HELP taos_cluster_info_dbs_total +# HELP taos_cluster_info_dbs_total # TYPE taos_cluster_info_dbs_total counter taos_cluster_info_dbs_total{cluster_id="5981392874047724755"} 2 -# HELP taos_cluster_info_dnodes_alive +# HELP taos_cluster_info_dnodes_alive # TYPE taos_cluster_info_dnodes_alive counter taos_cluster_info_dnodes_alive{cluster_id="5981392874047724755"} 1 -# HELP taos_cluster_info_dnodes_total +# HELP taos_cluster_info_dnodes_total # TYPE taos_cluster_info_dnodes_total counter taos_cluster_info_dnodes_total{cluster_id="5981392874047724755"} 1 -# HELP taos_cluster_info_first_ep +# HELP taos_cluster_info_first_ep # TYPE taos_cluster_info_first_ep gauge taos_cluster_info_first_ep{cluster_id="5981392874047724755",value="hlb:6030"} 1 ``` + +### check_health + +``` +$ curl -i http://127.0.0.1:6043/check_health +``` + +返回结果: + +``` +HTTP/1.1 200 OK +Content-Type: application/json; charset=utf-8 +Date: Mon, 03 Apr 2023 07:20:38 GMT +Content-Length: 19 + +{"version":"1.0.0"} +``` diff --git a/docs/zh/14-reference/_statsd.mdx b/docs/zh/14-reference/_statsd.mdx index dc4f19b37c6111b394f183fb57ca487828b66e70..21c2e29f64865df9ad421a8219ca7b5cef86380e 100644 --- a/docs/zh/14-reference/_statsd.mdx +++ b/docs/zh/14-reference/_statsd.mdx @@ -31,7 +31,7 @@ deleteTimings = true ### 配置 StatsD -使用 StatsD 需要下载其[源代码](https://github.com/statsd/statsd)。其配置文件请参考其源代码下载到本地的根目录下的示例文件 `exampleConfig.js` 进行修改。其中 填写运行 taosAdapter 的服务器域名或 IP 地址,请填写 taosAdapter 接收 StatsD 数据的端口(默认为 6044)。 +使用 StatsD 需要下载其[源代码](https://github.com/statsd/statsd)。其配置文件请参考其源代码下载到本地的根目录下的示例文件 `exampleConfig.js` 进行修改。其中 填写运行 taosAdapter 的服务器域名或 IP 地址,请填写 taosAdapter 接收 StatsD 数据的端口(默认为 6044)。 ``` backends 部分添加 "./backends/repeater" diff --git a/docs/zh/17-operation/01-pkg-install.md b/docs/zh/17-operation/01-pkg-install.md index 6d93c1697b1e0936b3f6539d3b1fb95db0baa956..6272c14db79537dd65c93e424097b9c31e88ddb9 100644 --- a/docs/zh/17-operation/01-pkg-install.md +++ b/docs/zh/17-operation/01-pkg-install.md @@ -141,8 +141,20 @@ taos tools is uninstalled successfully! ``` + 在 C:\TDengine 目录下,通过运行 unins000.exe 卸载程序来卸载 TDengine。 + + + + +卸载 TDengine 命令如下: + +``` +$ rmtaos +TDengine is removed successfully! +``` + diff --git a/docs/zh/17-operation/03-tolerance.md b/docs/zh/17-operation/03-tolerance.md index 79cf10c39a7028e04e7c1ebbea54738dcdc528af..bf2a651c1a9a68411a2348eccda7e0e44db75214 100644 --- a/docs/zh/17-operation/03-tolerance.md +++ b/docs/zh/17-operation/03-tolerance.md @@ -19,12 +19,8 @@ TDengine 接收到应用的请求数据包时,先将请求的原始数据包 ## 灾备 -TDengine 的集群通过多个副本的机制,来提供系统的高可用性,同时具备一定的灾备能力。 +TDengine 灾备是通过在异地的两个数据中心中设置两个 TDengine 集群并利用 taosX 的数据复制能力来实现的。假定两个集群为集群 A 和集群 B,其中集群 A 为源集群,承担写入请求并提供查询服务。则在集群 A 所在数据中心中可以配置 taosX 利用 TDengine 提供的数据订阅能力,实时消费集群 A 中新写入的数据,并同步到集群 B。如果发生了灾难导致集群 A 所在数据中心不可用,则可以启用集群 B 作为数据写入和查询的主节点,并在集群 B 所处数据中心中配置 taosX 将数据复制到已经恢复的集群 A 或者新建的集群 C。 -TDengine 集群是由 mnode 负责管理的,为保证 mnode 的高可靠,可以配置 三个 mnode 副本。为保证元数据的强一致性,mnode 副本之间通过同步方式进行数据复制,保证了元数据的强一致性。 +利用 taosX 的数据复制能力也可以构造出更复杂的灾备方案。 -TDengine 集群中的时序数据的副本数是与数据库关联的,一个集群里可以有多个数据库,每个数据库可以配置不同的副本数。创建数据库时,通过参数 replica 指定副本数。为了支持高可靠,需要设置副本数为 3。 - -TDengine 集群的节点数必须大于等于副本数,否则创建表时将报错。 - -当 TDengine 集群中的节点部署在不同的物理机上,并设置多个副本数时,就实现了系统的高可靠性,无需再使用其他软件或工具。TDengine 企业版还可以将副本部署在不同机房,从而实现异地容灾。 +taosX 只在 TDengine 企业版中提供,关于其具体细节,请联系 business@taosdata.com diff --git a/docs/zh/20-third-party/01-grafana.mdx b/docs/zh/20-third-party/01-grafana.mdx index d5cfe847cada26a102b634573e7f4e2492adf60b..7980736a1c62150df1c2742c788aabde9b1dbc3b 100644 --- a/docs/zh/20-third-party/01-grafana.mdx +++ b/docs/zh/20-third-party/01-grafana.mdx @@ -77,7 +77,7 @@ sudo -u grafana grafana-cli plugins install tdengine-datasource 或者从 [GitHub](https://github.com/taosdata/grafanaplugin/releases/tag/latest) 或 [Grafana](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation) 下载 .zip 文件到本地并解压到 Grafana 插件目录。命令行下载示例如下: ```bash -GF_VERSION=3.2.7 +GF_VERSION=3.3.1 # from GitHub wget https://github.com/taosdata/grafanaplugin/releases/download/v$GF_VERSION/tdengine-datasource-$GF_VERSION.zip # from Grafana @@ -156,13 +156,13 @@ docker run -d \ services: tdengine: - image: tdengine/tdengine:2.6.0.2 + image: tdengine/tdengine:3.0.2.4 environment: TAOS_FQDN: tdengine volumes: - tdengine-data:/var/lib/taos/ grafana: - image: grafana/grafana:8.5.6 + image: grafana/grafana:9.3.6 volumes: - ./tdengine.yml/:/etc/grafana/provisioning/tdengine.yml - grafana-data:/var/lib/grafana @@ -197,11 +197,17 @@ docker run -d \ - INPUT SQL:输入要查询的语句(该 SQL 语句的结果集应为两列多行),例如:`select _wstart, avg(mem_system) from log.dnodes_info where ts >= $from and ts < $to interval($interval)` ,其中,from、to 和 interval 为 TDengine 插件的内置变量,表示从 Grafana 插件面板获取的查询范围和时间间隔。除了内置变量外,`也支持可以使用自定义模板变量`。 - ALIAS BY:可设置当前查询别名。 - GENERATE SQL: 点击该按钮会自动替换相应变量,并生成最终执行的语句。 +- Group by column name(s): **半角**逗号分隔的 `group by` 或 `partition by` 列名。如果是 `group by` or `partition by` 查询语句,设置 `Group by` 列,可以展示多维数据。例如:INPUT SQL 为 `select _wstart as ts, avg(mem_system), dnode_ep from log.dnodes_info where ts>=$from and ts<=$to partition by dnode_ep interval($interval)`,设置 Group by 列名为 `dnode_ep`,可以按 `dnode_ep` 展示数据。 +- Format to: Group by 或 Partition by 场景下多维数据 legend 格式化格式。例如上述 INPUT SQL,将 Format to 设置为 `mem_system_{{dnode_ep}}`,展示的 legend 名字为格式化的列名。 按照默认提示查询当前 TDengine 部署所在服务器指定间隔系统内存平均使用量如下: ![TDengine Database Grafana plugin create dashboard](./create_dashboard2.webp) +查询每台 TDengine 服务器指定间隔系统内存平均使用量如下: + +![TDengine Database Grafana plugin create dashboard](./create_dashboard3.webp) + > 关于如何使用 Grafana 创建相应的监测界面以及更多有关使用 Grafana 的信息,请参考 Grafana 官方的[文档](https://grafana.com/docs/)。 ### 导入 Dashboard diff --git a/docs/zh/20-third-party/11-kafka.md b/docs/zh/20-third-party/11-kafka.md index cc2247f25ebacbc8f5290c2442860f264fad39f1..7fb7738a4f629ccda5dd2aca3c65bf7cb5a90efe 100644 --- a/docs/zh/20-third-party/11-kafka.md +++ b/docs/zh/20-third-party/11-kafka.md @@ -79,7 +79,7 @@ Development: false ### 从源码安装 ``` -git clone https://github.com/taosdata/kafka-connect-tdengine.git +git clone --branch 3.0 https://github.com/taosdata/kafka-connect-tdengine.git cd kafka-connect-tdengine mvn clean package unzip -d $CONFLUENT_HOME/share/java/ target/components/packages/taosdata-kafka-connect-tdengine-*.zip diff --git a/docs/zh/20-third-party/create_dashboard1.webp b/docs/zh/20-third-party/create_dashboard1.webp index 55eb388833e4df2a46f4d1cf6d346aa11429385d..df41d66d50e888555792ef34188a966c2e106a86 100644 Binary files a/docs/zh/20-third-party/create_dashboard1.webp and b/docs/zh/20-third-party/create_dashboard1.webp differ diff --git a/docs/zh/20-third-party/create_dashboard2.webp b/docs/zh/20-third-party/create_dashboard2.webp index bb40e407187718c52e9f617d8ebd3d25fd14b56b..ba50f5299605bd72ebfe1f3f5d1d62bdbc8939c9 100644 Binary files a/docs/zh/20-third-party/create_dashboard2.webp and b/docs/zh/20-third-party/create_dashboard2.webp differ diff --git a/docs/zh/20-third-party/create_dashboard3.webp b/docs/zh/20-third-party/create_dashboard3.webp new file mode 100644 index 0000000000000000000000000000000000000000..84f387f87bcc8e06fca90deabebd1d601c528ef1 Binary files /dev/null and b/docs/zh/20-third-party/create_dashboard3.webp differ diff --git a/docs/zh/25-application/01-telegraf.md b/docs/zh/25-application/01-telegraf.md index ec263d77927d2960ef684d9d94c9cad4073429b9..07a3067a4f25d6a47d44603afb9929f967d490b5 100644 --- a/docs/zh/25-application/01-telegraf.md +++ b/docs/zh/25-application/01-telegraf.md @@ -67,7 +67,7 @@ sudo systemctl start telegraf 使用 Web 浏览器访问 `IP:3000` 登录 Grafana 界面,系统初始用户名密码为 admin/admin。 点击左侧齿轮图标并选择 `Plugins`,应该可以找到 TDengine data source 插件图标。 -点击左侧加号图标并选择 `Import`,从 `https://github.com/taosdata/grafanaplugin/blob/master/examples/telegraf/grafana/dashboards/telegraf-dashboard-v0.1.0.json` 下载 dashboard JSON 文件后导入。之后可以看到如下界面的仪表盘: +点击左侧加号图标并选择 `Import`,从 `https://github.com/taosdata/grafanaplugin/blob/master/examples/telegraf/grafana/dashboards/telegraf-dashboard-v3.json` (适配 TDengine 3.0, 如果使用 TDengine 2.x, 请下载 `telegraf-dashboard-v2.json`) 下载 dashboard JSON 文件后导入。之后可以看到如下界面的仪表盘: ![TDengine Database IT-DevOps-Solutions-telegraf-dashboard](./IT-DevOps-Solutions-telegraf-dashboard.webp) diff --git a/docs/zh/25-application/_03-immigrate.md b/docs/zh/25-application/03-immigrate.md similarity index 70% rename from docs/zh/25-application/_03-immigrate.md rename to docs/zh/25-application/03-immigrate.md index d1c9caea099b79494784aa1122e89d7b4d412464..75788c0cc7d6e0e84402ba77c4a1aa875d772d8b 100644 --- a/docs/zh/25-application/_03-immigrate.md +++ b/docs/zh/25-application/03-immigrate.md @@ -18,82 +18,15 @@ title: OpenTSDB 应用迁移到 TDengine 的最佳实践 如果我们将原本运行在 OpenTSDB 上的应用迁移到 TDengine 上,不仅可以有效地降低计算和存储资源的占用、减少部署服务器的规模,还能够极大减少运行维护的成本的输出,让运维管理工作更简单、更轻松,大幅降低总拥有成本。与 OpenTSDB 一样,TDengine 也已经进行了开源,不同的是,除了单机版,后者还实现了集群版开源,被厂商绑定的顾虑一扫而空。 -在下文中我们将就“使用最典型并广泛应用的运维监控(DevOps)场景”来说明,如何在不编码的情况下将 OpenTSDB 的应用快速、安全、可靠地迁移到 TDengine 之上。后续的章节会做更深度的介绍,以便于进行非 DevOps 场景的迁移。 +在下文中我们将说明如何在不编码的情况下将 OpenTSDB 的应用快速、安全、可靠地迁移到 TDengine 之上。 -## DevOps 应用快速迁移 +## TDengine 与 OpenTSDB 的差异 -### 1、典型应用场景 - -一个典型的 DevOps 应用场景的系统整体的架构如下图(图 1) 所示。 - -**图 1. DevOps 场景中典型架构** -![TDengine Database IT-DevOps-Solutions-Immigrate-OpenTSDB-Arch](./IT-DevOps-Solutions-Immigrate-OpenTSDB-Arch.webp "图1. DevOps 场景中典型架构") - -在该应用场景中,包含了部署在应用环境中负责收集机器度量(Metrics)、网络度量(Metrics)以及应用度量(Metrics)的 Agent 工具、汇聚 Agent 收集信息的数据收集器,数据持久化存储和管理的系统以及监控数据可视化工具(例如:Grafana 等)。 - -其中,部署在应用节点的 Agents 负责向 collectd/Statsd 提供不同来源的运行指标,collectd/StatsD 则负责将汇聚的数据推送到 OpenTSDB 集群系统,然后使用可视化看板 Grafana 将数据可视化呈现出来。 - -### 2、迁移服务 - -- **TDengine 安装部署** - -首先是 TDengine 的安装,从官网上下载 TDengine 最新稳定版进行安装。各种安装包的使用帮助请参见博客[《TDengine 多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html)。 - -注意,安装完成以后,不要立即启动 `taosd` 服务,在正确配置完成参数以后再启动。 - -- **调整数据收集器配置** - -在 TDengine 2.4 版本中,包含一个组件 taosAdapter。taosAdapter 是一个无状态、可快速弹性伸缩的组件,它可以兼容 Influxdb 的 Line Protocol 和 OpenTSDB 的 telnet/JSON 写入协议规范,提供了丰富的数据接入能力,有效的节省用户迁移成本,降低用户应用迁移的难度。 - -用户可以根据需求弹性部署 taosAdapter 实例,结合场景的需要,快速提升数据写入的吞吐量,为不同应用场景下的数据写入提供保障。 - -通过 taosAdapter,用户可以将 collectd 或 StatsD 收集的数据直接推送到 TDengine ,实现应用场景的无缝迁移,非常的轻松便捷。taosAdapter 还支持 Telegraf、Icinga、TCollector 、node_exporter 的数据接入,使用详情参考[taosAdapter](/reference/taosadapter/)。 - -如果使用 collectd,修改其默认位置 `/etc/collectd/collectd.conf` 的配置文件为指向 taosAdapter 部署的节点 IP 地址和端口。假设 taosAdapter 的 IP 地址为 192.168.1.130,端口为 6046,配置如下: - -```html -LoadPlugin write_tsdb - - - Host "192.168.1.130" Port "6046" HostTags "status=production" StoreRates - false AlwaysAppendDS false - - -``` - -即可让 collectd 将数据使用推送到 OpenTSDB 的插件方式推送到 taosAdapter, taosAdapter 将调用 API 将数据写入到 TDengine 中,从而完成数据的写入工作。如果你使用的是 StatsD 相应地调整配置文件信息。 - -- **调整看板(Dashboard)系统** - -在数据能够正常写入 TDengine 后,可以调整适配 Grafana 将写入 TDengine 的数据可视化呈现出来。获取和使用 TDengine 提供的 Grafana 插件请参考[与其他工具的连接](/third-party/grafana)。 - -TDengine 提供了默认的两套 Dashboard 模板,用户只需要将 Grafana 目录下的模板导入到 Grafana 中即可激活使用。 - -**图 2. 导入 Grafana 模板** -![TDengine Database IT-DevOps-Solutions-Immigrate-OpenTSDB-Dashboard](./IT-DevOps-Solutions-Immigrate-OpenTSDB-Dashboard.webp "图2. 导入 Grafana 模板") - -操作完以上步骤后,就完成了将 OpenTSDB 替换成为 TDengine 的迁移工作。可以看到整个流程非常简单,不需要写代码,只需要对某些配置文件进行调整即可完成全部的迁移工作。 - -### 3、迁移后架构 - -完成迁移以后,此时的系统整体的架构如下图(图 3)所示,而整个过程中采集端、数据写入端、以及监控呈现端均保持了稳定,除了极少的配置调整外,不涉及任何重要的更改和变动。OpenTSDB 大量的应用场景均为 DevOps ,这种场景下,简单的参数设置即可完成 OpenTSDB 到 TDengine 迁移动作,使用上 TDengine 更加强大的处理能力和查询性能。 - -在绝大多数的 DevOps 场景中,如果你拥有一个小规模的 OpenTSDB 集群(3 台及以下的节点)作为 DevOps 的存储端,依赖于 OpenTSDB 为系统持久化层提供数据存储和查询功能,那么你可以安全地将其替换为 TDengine,并节约更多的计算和存储资源。在同等计算资源配置情况下,单台 TDengine 即可满足 3 ~ 5 台 OpenTSDB 节点提供的服务能力。如果规模比较大,那便需要采用 TDengine 集群。 - -如果你的应用特别复杂,或者应用领域并不是 DevOps 场景,你可以继续阅读后续的章节,更加全面深入地了解将 OpenTSDB 的应用迁移到 TDengine 的高级话题。 - -**图 3. 迁移完成后的系统架构** -![TDengine Database IT-DevOps-Solutions-Immigrate-TDengine-Arch](./IT-DevOps-Solutions-Immigrate-TDengine-Arch.webp "图 3. 迁移完成后的系统架构") - -## 其他场景的迁移评估与策略 - -### 1、TDengine 与 OpenTSDB 的差异 - -本章将详细介绍 OpenTSDB 与 TDengine 在系统功能层面上存在的差异。阅读完本章的内容,你可以全面地评估是否能够将某些基于 OpenTSDB 的复杂应用迁移到 TDengine 上,以及迁移之后应该注意的问题。 +本节将详细介绍 OpenTSDB 与 TDengine 在系统功能层面上存在的差异。阅读完本节的内容,你可以全面地评估是否能够将某些基于 OpenTSDB 的复杂应用迁移到 TDengine 上,以及迁移之后应该注意的问题。 TDengine 当前只支持 Grafana 的可视化看板呈现,所以如果你的应用中使用了 Grafana 以外的前端看板(例如[TSDash](https://github.com/facebook/tsdash)、[Status Wolf](https://github.com/box/StatusWolf)等),那么前端看板将无法直接迁移到 TDengine,需要将前端看板重新适配到 Grafana 才可以正常运行。 -在 2.3.0.x 版本中,TDengine 只能够支持 collectd 和 StatsD 作为数据收集汇聚软件,当然后面会陆续提供更多的数据收集聚合软件的接入支持。如果您的收集端使用了其他类型的数据汇聚器,您的应用需要适配到这两个数据汇聚端系统,才能够将数据正常写入。除了上述两个数据汇聚端软件协议以外,TDengine 还支持通过 InfluxDB 的行协议和 OpenTSDB 的数据写入协议、JSON 格式将数据直接写入,您可以重写数据推送端的逻辑,使用 TDengine 支持的行协议来写入数据。 +如果您的收集端使用了像 collectd 和 StatsD 这样的数据采集工具,要重新配置这些数据采集工具将数据写入到 TDengine。TDengine 还支持通过 InfluxDB 的行协议和 OpenTSDB 的数据写入协议、JSON 格式将数据直接写入,您可以重写数据推送端的逻辑,使用 TDengine 支持的行协议来写入数据。 此外,如果你的应用中使用了 OpenTSDB 以下特性,在将应用迁移到 TDengine 之前你还需要了解以下注意事项: @@ -104,11 +37,11 @@ TDengine 当前只支持 Grafana 的可视化看板呈现,所以如果你的 通过上面的介绍,相信你应该能够了解 OpenTSDB 迁移到 TDengine 带来的变化,这些信息也有助于你正确地判断是否可以接受将应用 迁移到 TDengine 之上,体验 TDengine 提供的强大的时序数据处理能力和便捷的使用体验。 -### 2、迁移策略 +## 迁移策略 首先将基于 OpenTSDB 的系统进行迁移涉及到的数据模式设计、系统规模估算、数据写入端改造,进行数据分流、应用适配工作;之后将两个系统并行运行一段时间,再将历史数据迁移到 TDengine 中。当然如果你的应用中有部分功能强依赖于上述 OpenTSDB 特性,同时又不希望停止使用,可以考虑保持原有的 OpenTSDB 系统运行,同时启动 TDengine 来提供主要的服务。 -## 数据模型设计 +### 数据模型设计 一方面,TDengine 要求其入库的数据具有严格的模式定义。另一方面,TDengine 的数据模型相对于 OpenTSDB 来说又更加丰富,多值模型能够兼容全部的单值模型的建立需求。 @@ -150,7 +83,7 @@ insert into memory_vm130_memory_buffered_collectd using memory tags(‘vm130’ 如果你想要利用 TDengine 的多值模型能力,需要首先满足以下要求:不同的采集量具有相同的采集频率,且能够通过消息队列**同时到达**数据写入端,从而确保使用 SQL 语句将多个指标一次性写入。将度量的名称作为超级表的名称,建立具有相同采集频率且能够同时到达的数据多列模型。子表的表名采用具有固定规则的方式进行命名。上述每个度量均只包含一个测量值,因此无法将其转化为多值模型。 -## 数据分流与应用适配 +### 数据分流与应用适配 从消息队列中订阅数据,并启动调整后的写入程序写入数据。 @@ -166,15 +99,128 @@ TDengine 不支持采用 OpenTSDB 的查询语法进行查询或数据获取处 TDengine 支持标准的 JDBC 3.0 接口操纵数据库,你也可以使用其他类型的高级语言的连接器来查询读取数据,以适配你的应用。具体的操作和使用帮助也请参阅用户手册。 -## 历史数据迁移 - -### 1、使用工具自动迁移数据 - -为了方便历史数据的迁移工作,我们为数据同步工具 DataX 提供了插件,能够将数据自动写入到 TDengine 中,需要注意的是 DataX 的自动化数据迁移只能够支持单值模型的数据迁移过程。 - -DataX 具体的使用方式及如何使用 DataX 将数据写入 TDengine 请参见[基于 DataX 的 TDengine 数据迁移工具](https://www.taosdata.com/blog/2021/10/26/3156.html)。 -在对 DataX 进行迁移实践后,我们发现通过启动多个进程,同时迁移多个 metric 的方式,可以大幅度的提高迁移历史数据的效率,下面是迁移过程中的部分记录,希望这些能为应用迁移工作带来参考。 +## 使用 DataX 迁移数据 + +为了方便历史数据的迁移工作,我们为数据同步工具 DataX 提供了适配 TDengine 3.0 的插件,能够将数据自动写入到 TDengine 中,需要注意的是 DataX 的自动化数据迁移只能够支持单值模型的数据迁移过程。 + +### 安装和部署 TDengine + +在进行数据迁移之前,要有一个正确运行的 TDengine 集群。首先是 TDengine 的安装,从官网上下载 TDengine 最新稳定版进行安装。各种安装包的使用帮助请参考 [安装指南](../../get-started/package) + +安装完成后,请根据 [部署指南](../../deployment/deploy) 配置集群。 + +### 插件功能介绍 + +1. TDengine30Reader 提供的功能: + 1. 支持通过 SQL 进行数据筛选; + 2. 根据时间间隔进行任务切分; + 3. 支持 TDengine 的全部数据类型; + 4. 支持批量读取,通过 batchSize 参数控制批量拉取结果集的大小,提高读取性能。 +2. TDengine30Writer 支持的功能: + 1. 支持 OpenTSDB 的 json 格式的行协议,使用 TDengine 的 schemaless 方式写入 TDengine。 + 2. 支持批量写入,通过 batchSize 参数控制批量写入的数量,提高写入性能。 + +### DataX 安装环境准备 + +1. 需要安装 TDengine 客户端 +2. 需要安装 JDK 1.8 环境(运行 DataX) +3. 需要安装 Python 环境(运行 DataX) +4. 需要 maven 编译环境(如果不编译 DataX 则可以不安装 maven) + +### 安装 + +1. 下载源码 +~~~ +git clone https://github.com/taosdata/DataX.git +~~~ +2. 编译打包 +~~~ +cd DataX +mvn -U clean package assembly:assembly -Dmaven.test.skip=true +~~~ +3. 安装 +~~~ +cp target/datax.tar.gz your_install_dir +cd your_install_dir +tar -zxvf dataX.tar.gz +~~~ + +### 数据迁移 Job 的配置 + +以一个从 OpenTSDB 到 TDengine 3.0 版本的数据迁移任务为例,配置文件 opentsdb2tdengine.json 如下: +~~~ +{ + "job":{ + "content":[{ + "reader": { + "name": "opentsdbreader", + "parameter": { + "endpoint": "http://192.168.1.180:4242", + "column": ["weather_temperature"], + "beginDateTime": "2021-01-01 00:00:00", + "endDateTime": "2021-01-01 01:00:00" + } + }, + "writer": { + "name": "tdengine30writer", + "parameter": { + "username": "root", + "password": "taosdata", + "connection": [ + { + "table": [ + "matric1" + ], + "jdbcUrl": "jdbc:TAOS://192.168.1.101:6030/test?timestampFormat=TIMESTAMP" + } + ], + "batchSize": 1000, + "ignoreTagsUnmatched": true + } + } + }], + "setting": { + "speed": { + "channel": 1 + } + } + } + } +~~~ +配置说明: +1. 上面的配置表示,从 192.168.1.180 的 OpenTSDB,到 192.168.1.101 的 TDengine 的迁移。迁移 metric 为 weather_temperature,时间从 2021-01-01 00:00:00 开始,到 2021-01-01 01:00:00 结束的数据。 +2. reader 使用 datax 的 opentsdbreader,parameter 的配置请参考:[opentsdbreader.md#配置参数](https://github.com/taosdata/DataX/blob/master/opentsdbreader/doc/opentsdbreader.md) +3. tdengine30writer 的 parameter 中,user,password 为必须项,没有默认值。batchSize 不是必须项,默认值为 1。详细参考:[tdengine30writer.md#配置参数](https://github.com/taosdata/DataX/blob/master/tdengine30writer/doc/tdengine30writer-CN.md) +4. TDengine 中,如果 dbname 指定的 database 不存在,则需要在迁移前创建数据库。 + +### 执行迁移任务 + +~~~ +python bin/datax.py job/opentsdb2tdengine.json +~~~ + +### 限制条件 + +1. 目前,DataX 自带的 opentsdbreader 仅支持 OpenTSDB-2.3.X 版本。详细参考:[opentsdbreader#约束限制](https://github.com/alibaba/DataX/blob/master/opentsdbreader/doc/opentsdbreader.md#5-%E7%BA%A6%E6%9D%9F%E9%99%90%E5%88%B6) +2. 数据迁移工具依赖 TDengine 客户端中的 `libtaos.so/taos.dll/libtaos.dylib`,需要与服务端对应版本的 TDengine-client。 + +### FAQ + +1. 如何估算一个数据迁移任务所需要的资源 + DataX 的每个 reader 按照自己的 task 切分策略进行任务划分,具体请参考 DataX 的任务调度规则。在估算资源是,需要按照数据迁移的数据量,任务切分规则和网络带宽限制等综合考虑,最好以实际数据迁移测试结果为准。 +2. TDengine30Writer 的 batchSize 设置多大效率最高? + batchSize 是控制批量写入的参数,在获取 batchSize 行纪录后,TDengineWriter 会向 TDengine 发送一次写入请求,这减少了与 TDengine 交互次数,从而提高了性能。从测试结果来看,batchSize 在 500-1000 范围内效率最高。 +3. job 的配置中 channel 数为多少合适? + job 中的 channel 数为流量控制的参数,每个 channel 都需要开辟一块内存,用来缓存数据。如果 channel 设置过大,会引起 OOM,所以 channel 数并不是越大越好。增加 channel 数后,需要提高 JVM 内存大小。从测试结果来看,channel 在 1~6 的范围内都是合适,能够保证 DataX 的流量最大化即可。 +4. java.sql.SQLException: TDengine ERROR (8000060b): Invalid client value + 配置文件中 column 中没有配置 tbname,此时会触发行协议数据写入(行协议写入只会自动创建子表名,但需要提前创建好超级表),行协议写入的情况下不支持 TAG 数据类型为非 NCHAR,所以此种情况有两种解决方案:1.将 TAG 全部修改为 NCHAR 类型;2.在 Column 中配置好表名称这样不会触发行协议写入。 +5. java.sql.SQLException: TDengine ERROR (8000060b): Timestamp data out of range + 配置文件中 column 中没有配置 tbname,此时会触发行协议数据写入,且 TAG 全部为 NCHAR 类型,此时需要保证时间戳的一列名称为 _ts,而不能是其他名称(行协议写入下,默认将最后的时间戳写入到 _ts 一列,且不能随意命名)。若想避免请使用 tbname 指定表名以避免触发行协议写入。 + +### 提升性能 + + 在对 DataX 进行迁移实践后,我们发现通过启动多个进程,同时迁移多个 metric 的方式,可以大幅度的提高迁移历史数据的效率,下面是迁移过程中的部分记录,希望这些能为应用迁移工作带来参考。 | DataX 实例个数 (并发进程个数) | 迁移记录速度 (条/秒) | | ----------------------------- | --------------------- | @@ -184,9 +230,9 @@ DataX 具体的使用方式及如何使用 DataX 将数据写入 TDengine 请参 | 5 | 约 29.5 万 | | 10 | 约 33 万 | -
(注:测试数据源自 单节点 Intel(R) Core(TM) i7-10700 CPU@2.90GHz 16 核 64G 硬件设备,channel 和 batchSize 分别为 8 和 1000,每条记录包含 10 个 tag) +(注:测试数据源自 单节点 Intel(R) Core(TM) i7-10700 CPU@2.90GHz 16 核 64G 硬件设备,channel 和 batchSize 分别为 8 和 1000,每条记录包含 10 个 tag) -### 2、手动迁移数据 +## 手动迁移数据 如果你需要使用多值模型进行数据写入,就需要自行开发一个将数据从 OpenTSDB 导出的工具,然后确认哪些时间线能够合并导入到同一个时间线,再将可以同时导入的时间通过 SQL 语句的写入到数据库中。 @@ -393,31 +439,11 @@ WHERE ts>=1510560000 AND ts<=1515000009 综上所述,可使用单台 16 核 32GB 的机器,或者使用 2 台 8 核 16GB 机器构成的集群。 -## 附录 3: 集群部署及启动 - -TDengine 提供了丰富的帮助文档说明集群安装、部署的诸多方面的内容,这里提供相应的文档列表,供你参考。 - -### 集群部署 - -首先是安装 TDengine,从官网上下载 TDengine 最新稳定版,解压缩后运行 install.sh 进行安装。各种安装包的使用帮助请参见博客[《TDengine 多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html)。 - -注意安装完成以后,不要立即启动 `taosd` 服务,在正确配置完成参数以后才启动 `taosd` 服务。 - -### 设置运行参数并启动服务 - -为确保系统能够正常获取运行的必要信息。请在服务端正确设置以下关键参数: - -FQDN、firstEp、secondEP、dataDir、logDir、tmpDir、serverPort。各参数的具体含义及设置的要求,可参见文档《[TDengine 集群安装、管理](/cluster/)》 - -按照相同的步骤,在需要运行的节点上设置参数,并启动 `taosd` 服务,然后添加 Dnode 到集群中。 - -最后启动 `taos` 命令行程序,执行命令 `show dnodes`,如果能看到所有的加入集群的节点,那么集群顺利搭建完成。具体的操作流程及注意事项,请参阅文档《[TDengine 集群安装、管理](/cluster/)》 - -## 附录 4: 超级表名称 +## 附录 3: 超级表名称 由于 OpenTSDB 的 metric 名称中带有点号(“.”),例如“cpu.usage_user”这种名称的 metric。但是点号在 TDengine 中具有特殊含义,是用来分隔数据库和表名称的分隔符。TDengine 也提供转义符,以允许用户在(超级)表名称中使用关键词或特殊分隔符(如:点号)。为了使用特殊字符,需要采用转义字符将表的名称括起来,例如:`cpu.usage_user`这样就是合法的(超级)表名称。 -## 附录 5:参考文章 +## 附录 4:参考文章 -1. [使用 TDengine + collectd/StatsD + Grafana 快速搭建 IT 运维监控系统](/application/collectd/) -2. [通过 collectd 将采集数据直接写入 TDengine](/third-party/collectd/) +1. [使用 TDengine + collectd/StatsD + Grafana 快速搭建 IT 运维监控系统](../collectd/) +2. [通过 collectd 将采集数据直接写入 TDengine](../../third-party/collectd/) diff --git a/docs/zh/27-train-faq/01-faq.md b/docs/zh/27-train-faq/01-faq.md index 595b69b08b87ee33e27937fb89b84adc41c89d08..b0006196301c8a5dfa06842f9f49f77ece7f7507 100644 --- a/docs/zh/27-train-faq/01-faq.md +++ b/docs/zh/27-train-faq/01-faq.md @@ -243,3 +243,8 @@ sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist ``` launchctl limit maxfiles ``` +### 20 建库时提示 Out of dnodes +该提示是创建 db 的 vnode 数量不够了,需要的 vnode 不能超过了 dnode 中 vnode 的上限。因为系统默认是一个 dnode 中有 CPU 核数两倍的 vnode,也可以通过配置文件中的参数 supportVnodes 控制。 +正常调大 taos.cfg 中 supportVnodes 参数即可。 + + diff --git a/docs/zh/28-releases/01-tdengine.md b/docs/zh/28-releases/01-tdengine.md index 7ed9e0c5a018401e2028a1e0786459d4e26f27b6..b4441ad078059f51d8632e0db9c8007db9eb804e 100644 --- a/docs/zh/28-releases/01-tdengine.md +++ b/docs/zh/28-releases/01-tdengine.md @@ -10,11 +10,51 @@ TDengine 2.x 各版本安装包请访问[这里](https://www.taosdata.com/all-do import Release from "/components/ReleaseV3"; +## 3.0.3.2 + + + +## 3.0.3.1 + + + +## 3.0.3.0 + + + + +## 3.0.2.6 + + + +## 3.0.2.5 + + + +## 3.0.2.4 + + + +## 3.0.2.3 + + + +## 3.0.2.2 + + + +## 3.0.2.1 + + + +## 3.0.2.0 + + + ## 3.0.1.8 - ## 3.0.1.7 diff --git a/docs/zh/28-releases/02-tools.md b/docs/zh/28-releases/02-tools.md index 67ca3fae67b36e5f08c57440bbaa64ec4f80bf4e..cce6834f12af02568632949bde044b81ea718808 100644 --- a/docs/zh/28-releases/02-tools.md +++ b/docs/zh/28-releases/02-tools.md @@ -10,6 +10,50 @@ taosTools 各版本安装包下载链接如下: import Release from "/components/ReleaseV3"; +## 2.4.11 + + + +## 2.4.10 + + + +## 2.4.9 + + + +## 2.4.8 + + + +## 2.4.6 + + + +## 2.4.3 + + + +## 2.4.2 + + + +## 2.4.1 + + + +## 2.4.0 + + + +## 2.3.3 + + + +## 2.3.2 + + + ## 2.3.0 diff --git a/examples/JDBC/springbootdemo/readme.md b/examples/JDBC/springbootdemo/readme.md index a3942a6a512501b7dee1f4f4ff5ccc93da0babbb..a89e21c009d2455dc8c5bf922fdfdcf5015ad21e 100644 --- a/examples/JDBC/springbootdemo/readme.md +++ b/examples/JDBC/springbootdemo/readme.md @@ -1,6 +1,13 @@ ## TDengine SpringBoot + Mybatis Demo ## 需要提前创建 test 数据库 + +``` +$ taos -s 'create database if not exists test' + +$ curl http://localhost:8080/weather/init +``` + ### 配置 application.properties ```properties # datasource config diff --git a/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.xml b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.xml index 99d5893ec198535d9e8ef1cc6c443625d0a64ec1..4899ec46547561bd0b820b22dcb5c8a2098c4d8d 100644 --- a/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.xml +++ b/examples/JDBC/springbootdemo/src/main/java/com/taosdata/example/springbootdemo/dao/WeatherMapper.xml @@ -7,6 +7,7 @@ + - insert into test.t#{groupId} (ts, temperature, humidity, note) - values (#{ts}, ${temperature}, ${humidity}, #{note}) + insert into test.t#{groupId} (ts, temperature, humidity, note, bytes) + values (#{ts}, ${temperature}, ${humidity}, #{note}, #{bytes})
table_prefix, Table prefix name. Default is 't'." + ) print( - '\t-m, --tbname
table_prefix, Table prefix name. Default is \'t\'.') + "\t-M, --stable flag, Use super table. Default is no" + ) print( - '\t-M, --stable flag, Use super table. Default is no') + "\t-s, --stbname stable_prefix, STable prefix name. Default is 'st'" + ) print( - '\t-s, --stbname stable_prefix, STable prefix name. Default is \'st\'') - print('\t-Q, --query [NO|EACHTB|command] query, Execute query command. set \'EACHTB\' means select * from each table') + "\t-Q, --query [NO|EACHTB|command] query, Execute query command. set 'EACHTB' means select * from each table" + ) print( - '\t-T, --threads num_of_threads, The number of threads. Default is 1.') + "\t-T, --threads num_of_threads, The number of threads. Default is 1." + ) print( - '\t-C, --processes num_of_processes, The number of threads. Default is 1.') - print('\t-r, --batch num_of_records_per_req, The number of records per request. Default is 1000.') + "\t-C, --processes num_of_processes, The number of threads. Default is 1." + ) + print( + "\t-r, --batch num_of_records_per_req, The number of records per request. Default is 1000." + ) print( - '\t-t, --numOfTb num_of_tables, The number of tables. Default is 1.') - print('\t-n, --numOfRec num_of_records_per_table, The number of records per table. Default is 1.') - print('\t-c, --config config_directory, Configuration directory. Default is \'/etc/taos/\'.') - print('\t-x, --inserOnly flag, Insert only flag.') - print('\t-O, --outOfOrder out of order data insert, 0: In order, 1: Out of order. Default is in order.') - print('\t-R, --rateOOOO rate, Out of order data\'s rate--if order=1 Default 10, min: 0, max: 50.') - print('\t-D, --deleteMethod Delete data methods 0: don\'t delete, 1: delete by table, 2: delete by stable, 3: delete by database.') - print('\t-v, --verbose Print verbose output') - print('\t-g, --debug Print debug output') + "\t-t, --numOfTb num_of_tables, The number of tables. Default is 1." + ) print( - '\t-y, --skipPrompt Skip read key for continous test, default is not skip') - print('') + "\t-n, --numOfRec num_of_records_per_table, The number of records per table. Default is 1." + ) + print( + "\t-c, --config config_directory, Configuration directory. Default is '/etc/taos/'." + ) + print("\t-x, --inserOnly flag, Insert only flag.") + print( + "\t-O, --outOfOrder out of order data insert, 0: In order, 1: Out of order. Default is in order." + ) + print( + "\t-R, --rateOOOO rate, Out of order data's rate--if order=1 Default 10, min: 0, max: 50." + ) + print( + "\t-D, --deleteMethod Delete data methods 0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database." + ) + print("\t-v, --verbose Print verbose output") + print("\t-g, --debug Print debug output") + print( + "\t-y, --skipPrompt Skip read key for continous test, default is not skip" + ) + print("") sys.exit(0) - if key in ['-N', '--native']: + if key in ["-N", "--native"]: try: import taos except Exception as e: @@ -571,104 +592,104 @@ if __name__ == "__main__": sys.exit(1) native = True - if key in ['-h', '--host']: + if key in ["-h", "--host"]: host = value - if key in ['-p', '--port']: + if key in ["-p", "--port"]: port = int(value) - if key in ['-u', '--user']: + if key in ["-u", "--user"]: user = value - if key in ['-P', '--password']: + if key in ["-P", "--password"]: password = value else: password = defaultPass - if key in ['-d', '--dbname']: + if key in ["-d", "--dbname"]: dbName = value - if key in ['-a', '--replica']: + if key in ["-a", "--replica"]: replica = int(value) if replica < 1: print("FATAL: number of replica need > 0") sys.exit(1) - if key in ['-m', '--tbname']: + if key in ["-m", "--tbname"]: tbName = value - if key in ['-M', '--stable']: + if key in ["-M", "--stable"]: useStable = True numOfStb = 1 - if key in ['-s', '--stbname']: + if key in ["-s", "--stbname"]: stbName = value - if key in ['-Q', '--query']: + if key in ["-Q", "--query"]: queryCmd = str(value) - if key in ['-T', '--threads']: + if key in ["-T", "--threads"]: threads = int(value) if threads < 1: print("FATAL: number of threads must be larger than 0") sys.exit(1) - if key in ['-C', '--processes']: + if key in ["-C", "--processes"]: processes = int(value) if processes < 1: print("FATAL: number of processes must be larger than 0") sys.exit(1) - if key in ['-r', '--batch']: + if key in ["-r", "--batch"]: batch = int(value) - if key in ['-l', '--colsPerRec']: + if key in ["-l", "--colsPerRec"]: colsPerRec = int(value) - if key in ['-t', '--numOfTb']: + if key in ["-t", "--numOfTb"]: numOfTb = int(value) v_print("numOfTb is %d", numOfTb) - if key in ['-n', '--numOfRec']: + if key in ["-n", "--numOfRec"]: numOfRec = int(value) v_print("numOfRec is %d", numOfRec) if numOfRec < 1: print("FATAL: number of records must be larger than 0") sys.exit(1) - - if key in ['-c', '--config']: + if key in ["-c", "--config"]: configDir = value v_print("config dir: %s", configDir) - if key in ['-x', '--insertOnly']: + if key in ["-x", "--insertOnly"]: insertOnly = True v_print("insert only: %d", insertOnly) - if key in ['-O', '--outOfOrder']: + if key in ["-O", "--outOfOrder"]: outOfOrder = int(value) v_print("out of order is %d", outOfOrder) - if key in ['-R', '--rateOOOO']: + if key in ["-R", "--rateOOOO"]: rateOOOO = int(value) v_print("the rate of out of order is %d", rateOOOO) - if key in ['-D', '--deleteMethod']: + if key in ["-D", "--deleteMethod"]: deleteMethod = int(value) if (deleteMethod < 0) or (deleteMethod > 3): print( - "inputed delete method is %d, valid value is 0~3, set to default 0" % - deleteMethod) + "inputed delete method is %d, valid value is 0~3, set to default 0" + % deleteMethod + ) deleteMethod = 0 v_print("the delete method is %d", deleteMethod) - if key in ['-v', '--verbose']: + if key in ["-v", "--verbose"]: verbose = True - if key in ['-g', '--debug']: + if key in ["-g", "--debug"]: debug = True - if key in ['-y', '--skipPrompt']: + if key in ["-y", "--skipPrompt"]: skipPrompt = True if verbose: @@ -679,13 +700,11 @@ if __name__ == "__main__": # establish connection first if native if native: - v_print("host:%s, user:%s passwd:%s configDir:%s ", host, user, password, configDir) + v_print("host:%s, user:%s passwd:xxxxxx configDir:%s ", host, user, configDir) try: conn = taos.connect( - host=host, - user=user, - password=password, - config=configDir) + host=host, user=user, password=password, config=configDir + ) v_print("conn: %s", str(conn.__class__)) except Exception as e: print("Error: %s" % e.args[0]) @@ -705,7 +724,7 @@ if __name__ == "__main__": drop_tables() print("Drop tables done.") elif deleteMethod == 2: - drop_stables() + drop_stable() print("Drop super tables done.") elif deleteMethod == 3: drop_databases() @@ -725,7 +744,7 @@ if __name__ == "__main__": if numOfStb > 0: create_stb() - if (autosubtable == False): + if autosubtable is False: create_tb_using_stb() else: create_tb() @@ -734,7 +753,9 @@ if __name__ == "__main__": end_time = time.time() print( "Total time consumed {} seconds for create table.".format( - (end_time - start_time_begin))) + (end_time - start_time_begin) + ) + ) if native: cursor.close() @@ -758,10 +779,8 @@ if __name__ == "__main__": remainder = numOfTb % processes v_print( - "num of tables: %d, quotient: %d, remainder: %d", - numOfTb, - quotient, - remainder) + "num of tables: %d, quotient: %d, remainder: %d", numOfTb, quotient, remainder + ) for i in range(processes): begin = end @@ -770,7 +789,15 @@ if __name__ == "__main__": end = begin + quotient + 1 else: end = begin + quotient - pool.apply_async(insert_data_process, args=(lock, i, begin, end,)) + pool.apply_async( + insert_data_process, + args=( + lock, + i, + begin, + end, + ), + ) pool.close() pool.join() @@ -780,8 +807,9 @@ if __name__ == "__main__": end_time = time.time() print( "Total time consumed {} seconds for insert data.".format( - (end_time - start_time))) - + (end_time - start_time) + ) + ) # query data if queryCmd != "NO": @@ -790,8 +818,6 @@ if __name__ == "__main__": if measure: end_time = time.time() - print( - "Total time consumed {} seconds.".format( - (end_time - start_time_begin))) + print("Total time consumed {} seconds.".format((end_time - start_time_begin))) print("done") diff --git a/examples/rust/wrapper.h b/examples/rust/wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..78857597a9dc0c9a0f35194339a0d132f788d592 --- /dev/null +++ b/examples/rust/wrapper.h @@ -0,0 +1 @@ +#include diff --git a/include/client/taos.h b/include/client/taos.h index 838d0e826662abe5d2fbd6253601a12f06978c75..a59e203644afe66fe166cdcc4c04afb539a1a289 100644 --- a/include/client/taos.h +++ b/include/client/taos.h @@ -208,6 +208,7 @@ DLL_EXPORT TAOS_ROW *taos_result_block(TAOS_RES *res); DLL_EXPORT const char *taos_get_server_info(TAOS *taos); DLL_EXPORT const char *taos_get_client_info(); +DLL_EXPORT int taos_get_current_db(TAOS *taos, char *database, int len, int *required); DLL_EXPORT const char *taos_errstr(TAOS_RES *res); DLL_EXPORT int taos_errno(TAOS_RES *res); @@ -224,6 +225,9 @@ DLL_EXPORT int taos_get_tables_vgId(TAOS *taos, const char *db, const char *tabl DLL_EXPORT int taos_load_table_info(TAOS *taos, const char *tableNameList); +// set heart beat thread quit mode , if quicByKill 1 then kill thread else quit from inner +DLL_EXPORT void taos_set_hb_quit(int8_t quitByKill); + /* --------------------------schemaless INTERFACE------------------------------- */ DLL_EXPORT TAOS_RES *taos_schemaless_insert(TAOS *taos, char *lines[], int numLines, int protocol, int precision); diff --git a/include/common/systable.h b/include/common/systable.h index 6f65c1e8b870d4a42427173bf3ea17ae7ade0ce1..ea18338e9e8dcf6d9b7d92152b99efafd201309a 100644 --- a/include/common/systable.h +++ b/include/common/systable.h @@ -13,15 +13,15 @@ * along with this program. If not, see . */ +#ifndef TDENGINE_SYSTABLE_H +#define TDENGINE_SYSTABLE_H + #ifdef __cplusplus extern "C" { #endif #include "os.h" -#ifndef TDENGINE_SYSTABLE_H -#define TDENGINE_SYSTABLE_H - #define TSDB_INFORMATION_SCHEMA_DB "information_schema" #define TSDB_INS_TABLE_DNODES "ins_dnodes" #define TSDB_INS_TABLE_MNODES "ins_mnodes" @@ -36,6 +36,7 @@ extern "C" { #define TSDB_INS_TABLE_STABLES "ins_stables" #define TSDB_INS_TABLE_TABLES "ins_tables" #define TSDB_INS_TABLE_TAGS "ins_tags" +#define TSDB_INS_TABLE_COLS "ins_columns" #define TSDB_INS_TABLE_TABLE_DISTRIBUTED "ins_table_distributed" #define TSDB_INS_TABLE_USERS "ins_users" #define TSDB_INS_TABLE_LICENCES "ins_grants" diff --git a/include/common/taosdef.h b/include/common/taosdef.h index bf4de9d4ded1d0955bef05b1e3000be0bf34d8aa..d1ca446904594fa57d54031d5b39e529795d70da 100644 --- a/include/common/taosdef.h +++ b/include/common/taosdef.h @@ -30,6 +30,11 @@ typedef int64_t tb_uid_t; #define IS_TSWINDOW_SPECIFIED(win) (((win).skey != INT64_MIN) || ((win).ekey != INT64_MAX)) #define TSWINDOW_IS_EQUAL(t1, t2) (((t1).skey == (t2).skey) && ((t1).ekey == (t2).ekey)) +//define show cluster alive and show db.alive +#define SHOW_STATUS_NOT_AVAILABLE 0 +#define SHOW_STATUS_AVAILABLE 1 +#define SHOW_STATUS_HALF_AVAILABLE 2 + typedef enum { TSDB_SUPER_TABLE = 1, // super table TSDB_CHILD_TABLE = 2, // table created from super table diff --git a/include/common/tcommon.h b/include/common/tcommon.h index d88747eb928986ab0e242901bb354b7fd9e77493..2bc67e439f5da6d9873730acaf2a108eeb4fce8b 100644 --- a/include/common/tcommon.h +++ b/include/common/tcommon.h @@ -25,13 +25,6 @@ extern "C" { #endif -// TODO remove it -enum { - TMQ_CONF__RESET_OFFSET__NONE = -3, - TMQ_CONF__RESET_OFFSET__EARLIEAST = -2, - TMQ_CONF__RESET_OFFSET__LATEST = -1, -}; - // clang-format off #define IS_META_MSG(x) ( \ x == TDMT_VND_CREATE_STB \ @@ -162,6 +155,7 @@ typedef enum EStreamType { STREAM_PULL_DATA, STREAM_PULL_OVER, STREAM_FILL_OVER, + STREAM_CREATE_CHILD_TABLE, } EStreamType; #pragma pack(push, 1) @@ -191,11 +185,11 @@ typedef struct SBlockID { typedef struct SDataBlockInfo { STimeWindow window; int32_t rowSize; - int32_t rows; // todo hide this attribute + int64_t rows; // todo hide this attribute uint32_t capacity; SBlockID id; int16_t hasVarCol; - int16_t dataLoad; // denote if the data is loaded or not + int16_t dataLoad; // denote if the data is loaded or not // TODO: optimize and remove following int64_t version; // used for stream, and need serialization @@ -204,8 +198,7 @@ typedef struct SDataBlockInfo { STimeWindow calWin; // used for stream, do not serialize TSKEY watermark; // used for stream - char parTbName[TSDB_TABLE_NAME_LEN]; // used for stream partition - STag* pTag; // used for stream partition + char parTbName[TSDB_TABLE_NAME_LEN]; // used for stream partition } SDataBlockInfo; typedef struct SSDataBlock { @@ -215,21 +208,10 @@ typedef struct SSDataBlock { } SSDataBlock; enum { - FETCH_TYPE__DATA = 1, - FETCH_TYPE__META, - FETCH_TYPE__SEP, + FETCH_TYPE__DATA = 0, FETCH_TYPE__NONE, }; -typedef struct { - int8_t fetchType; - STqOffsetVal offset; - union { - SSDataBlock data; - void* meta; - }; -} SFetchRet; - typedef struct SVarColAttr { int32_t* offset; // start position for each entry in the list uint32_t length; // used buffer size that contain the valid data @@ -239,22 +221,22 @@ typedef struct SVarColAttr { // pBlockAgg->numOfNull == info.rows, all data are null // pBlockAgg->numOfNull == 0, no data are null. typedef struct SColumnInfoData { - char* pData; // the corresponding block data in memory + char* pData; // the corresponding block data in memory union { char* nullbitmap; // bitmap, one bit for each item in the list SVarColAttr varmeta; }; - SColumnInfo info; // column info - bool hasNull; // if current column data has null value. + SColumnInfo info; // column info + bool hasNull; // if current column data has null value. } SColumnInfoData; typedef struct SQueryTableDataCond { uint64_t suid; - int32_t order; // desc|asc order to iterate the data block + int32_t order; // desc|asc order to iterate the data block int32_t numOfCols; SColumnInfo* colList; - int32_t* pSlotList; // the column output destation slot, and it may be null - int32_t type; // data block load type: + int32_t* pSlotList; // the column output destation slot, and it may be null + int32_t type; // data block load type: STimeWindow twindows; int64_t startVersion; int64_t endVersion; @@ -300,6 +282,7 @@ typedef struct STableBlockDistInfo { int32_t firstSeekTimeUs; uint32_t numOfInmemRows; uint32_t numOfSmallBlocks; + uint32_t numOfVgroups; int32_t blockRowsHisto[20]; } STableBlockDistInfo; @@ -340,7 +323,7 @@ typedef struct SExprInfo { typedef struct { const char* key; - int32_t keyLen; + size_t keyLen; uint8_t type; union { const char* value; @@ -349,7 +332,9 @@ typedef struct { double d; float f; }; - int32_t length; + size_t length; + bool keyEscaped; + bool valueEscaped; } SSmlKv; #define QUERY_ASC_FORWARD_STEP 1 @@ -383,6 +368,13 @@ typedef struct STUidTagInfo { #define CALCULATE_END_TS_COLUMN_INDEX 5 #define TABLE_NAME_COLUMN_INDEX 6 +// stream create table block column +#define UD_TABLE_NAME_COLUMN_INDEX 0 +#define UD_GROUPID_COLUMN_INDEX 1 +#define UD_TAG_COLUMN_INDEX 2 + +int32_t taosGenCrashJsonMsg(int signum, char **pMsg, int64_t clusterId, int64_t startTime); + #ifdef __cplusplus } #endif diff --git a/include/common/tdatablock.h b/include/common/tdatablock.h index 9c5b712db6c5daaaa3303c73a73b24ab33e8a9ff..99fffa2cf1d6f28697fea0a96562707aeb3e3a71 100644 --- a/include/common/tdatablock.h +++ b/include/common/tdatablock.h @@ -58,7 +58,6 @@ typedef struct SBlockOrderInfo { #define BitmapLen(_n) (((_n) + ((1 << NBIT) - 1)) >> NBIT) #define colDataGetVarData(p1_, r_) ((p1_)->pData + (p1_)->varmeta.offset[(r_)]) - #define colDataGetNumData(p1_, r_) ((p1_)->pData + ((r_) * (p1_)->info.bytes)) // SColumnInfoData, rowNumber #define colDataGetData(p1_, r_) \ @@ -83,33 +82,6 @@ static FORCE_INLINE bool colDataIsNull_s(const SColumnInfoData* pColumnInfoData, } } -static FORCE_INLINE bool colDataIsNNull_s(const SColumnInfoData* pColumnInfoData, int32_t startIndex, - uint32_t nRows) { - if (!pColumnInfoData->hasNull) { - return false; - } - - if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) { - for (int32_t i = startIndex; i < nRows; ++i) { - if (!colDataIsNull_var(pColumnInfoData, i)) { - return false; - } - } - } else { - if (pColumnInfoData->nullbitmap == NULL) { - return false; - } - - for (int32_t i = startIndex; i < nRows; ++i) { - if (!colDataIsNull_f(pColumnInfoData->nullbitmap, i)) { - return false; - } - } - } - - return true; -} - static FORCE_INLINE bool colDataIsNull(const SColumnInfoData* pColumnInfoData, uint32_t totalRows, uint32_t row, SColumnDataAgg* pColAgg) { if (!pColumnInfoData->hasNull) { @@ -137,18 +109,18 @@ static FORCE_INLINE bool colDataIsNull(const SColumnInfoData* pColumnInfoData, u } } -static FORCE_INLINE void colDataAppendNULL(SColumnInfoData* pColumnInfoData, uint32_t currentRow) { +static FORCE_INLINE void colDataSetNULL(SColumnInfoData* pColumnInfoData, uint32_t rowIndex) { // There is a placehold for each NULL value of binary or nchar type. if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) { - colDataSetNull_var(pColumnInfoData, currentRow); // it is a null value of VAR type. + colDataSetNull_var(pColumnInfoData, rowIndex); // it is a null value of VAR type. } else { - colDataSetNull_f_s(pColumnInfoData, currentRow); + colDataSetNull_f_s(pColumnInfoData, rowIndex); } pColumnInfoData->hasNull = true; } -static FORCE_INLINE void colDataAppendNNULL(SColumnInfoData* pColumnInfoData, uint32_t start, size_t nRows) { +static FORCE_INLINE void colDataSetNNULL(SColumnInfoData* pColumnInfoData, uint32_t start, size_t nRows) { if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) { for (int32_t i = start; i < start + nRows; ++i) { colDataSetNull_var(pColumnInfoData, i); // it is a null value of VAR type. @@ -163,50 +135,50 @@ static FORCE_INLINE void colDataAppendNNULL(SColumnInfoData* pColumnInfoData, ui pColumnInfoData->hasNull = true; } -static FORCE_INLINE void colDataAppendInt8(SColumnInfoData* pColumnInfoData, uint32_t currentRow, int8_t* v) { +static FORCE_INLINE void colDataSetInt8(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, int8_t* v) { ASSERT(pColumnInfoData->info.type == TSDB_DATA_TYPE_TINYINT || pColumnInfoData->info.type == TSDB_DATA_TYPE_UTINYINT || pColumnInfoData->info.type == TSDB_DATA_TYPE_BOOL); - char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * currentRow; + char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * rowIndex; *(int8_t*)p = *(int8_t*)v; } -static FORCE_INLINE void colDataAppendInt16(SColumnInfoData* pColumnInfoData, uint32_t currentRow, int16_t* v) { +static FORCE_INLINE void colDataSetInt16(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, int16_t* v) { ASSERT(pColumnInfoData->info.type == TSDB_DATA_TYPE_SMALLINT || pColumnInfoData->info.type == TSDB_DATA_TYPE_USMALLINT); - char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * currentRow; + char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * rowIndex; *(int16_t*)p = *(int16_t*)v; } -static FORCE_INLINE void colDataAppendInt32(SColumnInfoData* pColumnInfoData, uint32_t currentRow, int32_t* v) { +static FORCE_INLINE void colDataSetInt32(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, int32_t* v) { ASSERT(pColumnInfoData->info.type == TSDB_DATA_TYPE_INT || pColumnInfoData->info.type == TSDB_DATA_TYPE_UINT); - char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * currentRow; + char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * rowIndex; *(int32_t*)p = *(int32_t*)v; } -static FORCE_INLINE void colDataAppendInt64(SColumnInfoData* pColumnInfoData, uint32_t currentRow, int64_t* v) { +static FORCE_INLINE void colDataSetInt64(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, int64_t* v) { int32_t type = pColumnInfoData->info.type; ASSERT(type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_UBIGINT || type == TSDB_DATA_TYPE_TIMESTAMP); - char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * currentRow; + char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * rowIndex; *(int64_t*)p = *(int64_t*)v; } -static FORCE_INLINE void colDataAppendFloat(SColumnInfoData* pColumnInfoData, uint32_t currentRow, float* v) { +static FORCE_INLINE void colDataSetFloat(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, float* v) { ASSERT(pColumnInfoData->info.type == TSDB_DATA_TYPE_FLOAT); - char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * currentRow; + char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * rowIndex; *(float*)p = *(float*)v; } -static FORCE_INLINE void colDataAppendDouble(SColumnInfoData* pColumnInfoData, uint32_t currentRow, double* v) { +static FORCE_INLINE void colDataSetDouble(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, double* v) { ASSERT(pColumnInfoData->info.type == TSDB_DATA_TYPE_DOUBLE); - char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * currentRow; + char* p = pColumnInfoData->pData + pColumnInfoData->info.bytes * rowIndex; *(double*)p = *(double*)v; } int32_t getJsonValueLen(const char* data); -int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, bool isNull); -int32_t colDataAppendNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, - uint32_t numOfRows); +int32_t colDataSetVal(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull); +int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull); +int32_t colDataSetNItems(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, uint32_t numOfRows, bool trimValue); int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, int32_t* capacity, const SColumnInfoData* pSource, int32_t numOfRow2); int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* pSource, int32_t numOfRows, @@ -245,7 +217,7 @@ void blockDataEmpty(SSDataBlock* pDataBlock); size_t blockDataGetCapacityInRow(const SSDataBlock* pBlock, size_t pageSize); -int32_t blockDataTrimFirstNRows(SSDataBlock* pBlock, size_t n); +int32_t blockDataTrimFirstRows(SSDataBlock* pBlock, size_t n); int32_t blockDataKeepFirstNRows(SSDataBlock* pBlock, size_t n); int32_t assignOneDataBlock(SSDataBlock* dst, const SSDataBlock* src); @@ -271,7 +243,7 @@ void blockDebugShowDataBlocks(const SArray* dataBlocks, const char* flag); // for debug char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** dumpBuf); -int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SSDataBlock* pDataBlocks, STSchema* pTSchema, int32_t vgId, +int32_t buildSubmitReqFromDataBlock(SSubmitReq2** pReq, const SSDataBlock* pDataBlocks, const STSchema* pTSchema, int64_t uid, int32_t vgId, tb_uid_t suid); char* buildCtbNameByGroupId(const char* stbName, uint64_t groupId); @@ -280,13 +252,6 @@ static FORCE_INLINE int32_t blockGetEncodeSize(const SSDataBlock* pBlock) { return blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)) + blockDataGetSize(pBlock); } -static FORCE_INLINE int32_t blockCompressColData(SColumnInfoData* pColRes, int32_t numOfRows, char* data, - int8_t compressed) { - int32_t colSize = colDataGetLength(pColRes, numOfRows); - return (*(tDataTypes[pColRes->info.type].compFunc))(pColRes->pData, colSize, numOfRows, data, - colSize + COMP_OVERFLOW_BYTES, compressed, NULL, 0); -} - #ifdef __cplusplus } #endif diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index 6855287fb2d354f52998342d368c46b3a852bf89..8be5cb4d413b9392702c628d72f27cb0662687a3 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -29,6 +29,7 @@ extern "C" { typedef struct SBuffer SBuffer; typedef struct SSchema SSchema; +typedef struct SSchema2 SSchema2; typedef struct STColumn STColumn; typedef struct STSchema STSchema; typedef struct SValue SValue; @@ -44,18 +45,38 @@ typedef struct SColData SColData; #define HAS_VALUE ((uint8_t)0x4) // bitmap ================================ -const static uint8_t BIT2_MAP[4][4] = {{0b00000000, 0b00000001, 0b00000010, 0}, - {0b00000000, 0b00000100, 0b00001000, 2}, - {0b00000000, 0b00010000, 0b00100000, 4}, - {0b00000000, 0b01000000, 0b10000000, 6}}; - -#define N1(n) ((((uint8_t)1) << (n)) - 1) -#define BIT1_SIZE(n) ((((n)-1) >> 3) + 1) -#define BIT2_SIZE(n) ((((n)-1) >> 2) + 1) -#define SET_BIT1(p, i, v) ((p)[(i) >> 3] = (p)[(i) >> 3] & N1((i)&7) | (((uint8_t)(v)) << ((i)&7))) -#define GET_BIT1(p, i) (((p)[(i) >> 3] >> ((i)&7)) & ((uint8_t)1)) -#define SET_BIT2(p, i, v) ((p)[(i) >> 2] = (p)[(i) >> 2] & N1(BIT2_MAP[(i)&3][3]) | BIT2_MAP[(i)&3][(v)]) -#define GET_BIT2(p, i) (((p)[(i) >> 2] >> BIT2_MAP[(i)&3][3]) & ((uint8_t)3)) +const static uint8_t BIT1_MAP[8] = {0b11111110, 0b11111101, 0b11111011, 0b11110111, + 0b11101111, 0b11011111, 0b10111111, 0b01111111}; + +const static uint8_t BIT2_MAP[4] = {0b11111100, 0b11110011, 0b11001111, 0b00111111}; + +#define ONE ((uint8_t)1) +#define THREE ((uint8_t)3) +#define DIV_8(i) ((i) >> 3) +#define MOD_8(i) ((i)&7) +#define DIV_4(i) ((i) >> 2) +#define MOD_4(i) ((i)&3) +#define MOD_4_TIME_2(i) (MOD_4(i) << 1) +#define BIT1_SIZE(n) (DIV_8((n)-1) + 1) +#define BIT2_SIZE(n) (DIV_4((n)-1) + 1) +#define SET_BIT1(p, i, v) ((p)[DIV_8(i)] = (p)[DIV_8(i)] & BIT1_MAP[MOD_8(i)] | ((v) << MOD_8(i))) +#define SET_BIT1_EX(p, i, v) \ + do { \ + if (MOD_8(i) == 0) { \ + (p)[DIV_8(i)] = 0; \ + } \ + SET_BIT1(p, i, v); \ + } while (0) +#define GET_BIT1(p, i) (((p)[DIV_8(i)] >> MOD_8(i)) & ONE) +#define SET_BIT2(p, i, v) ((p)[DIV_4(i)] = (p)[DIV_4(i)] & BIT2_MAP[MOD_4(i)] | ((v) << MOD_4_TIME_2(i))) +#define SET_BIT2_EX(p, i, v) \ + do { \ + if (MOD_4(i) == 0) { \ + (p)[DIV_4(i)] = 0; \ + } \ + SET_BIT2(p, i, v); \ + } while (0) +#define GET_BIT2(p, i) (((p)[DIV_4(i)] >> MOD_4_TIME_2(i)) & THREE) // SBuffer ================================ struct SBuffer { @@ -70,9 +91,6 @@ int32_t tBufferInit(SBuffer *pBuffer, int64_t size); int32_t tBufferPut(SBuffer *pBuffer, const void *pData, int64_t nData); int32_t tBufferReserve(SBuffer *pBuffer, int64_t nData, void **ppData); -// STSchema ================================ -void tDestroyTSchema(STSchema *pTSchema); - // SColVal ================================ #define CV_FLAG_VALUE ((int8_t)0x0) #define CV_FLAG_NONE ((int8_t)0x1) @@ -87,8 +105,12 @@ void tDestroyTSchema(STSchema *pTSchema); #define COL_VAL_IS_VALUE(CV) ((CV)->flag == CV_FLAG_VALUE) // SRow ================================ -int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer); -void tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal); +int32_t tRowBuild(SArray *aColVal, const STSchema *pTSchema, SRow **ppRow); +int32_t tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal); +void tRowDestroy(SRow *pRow); +void tRowSort(SArray *aRowP); +int32_t tRowMerge(SArray *aRowP, STSchema *pTSchema, int8_t flag); +int32_t tRowUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *aColData, int32_t nColData, int32_t flag); // SRowIter ================================ int32_t tRowIterOpen(SRow *pRow, STSchema *pTSchema, SRowIter **ppIter); @@ -110,15 +132,29 @@ void debugPrintSTag(STag *pTag, const char *tag, int32_t ln); // TODO: remov int32_t parseJsontoTagData(const char *json, SArray *pTagVals, STag **ppTag, void *pMsgBuf); // SColData ================================ +typedef void *(*xMallocFn)(void *, int32_t); void tColDataDestroy(void *ph); void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn); void tColDataClear(SColData *pColData); +void tColDataDeepClear(SColData *pColData); int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal); +int32_t tColDataUpdateValue(SColData *pColData, SColVal *pColVal, bool forward); void tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal); uint8_t tColDataGetBitValue(const SColData *pColData, int32_t iVal); -int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest); +int32_t tColDataCopy(SColData *pColDataFrom, SColData *pColData, xMallocFn xMalloc, void *arg); extern void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, int16_t *numOfNull); +// for stmt bind +int32_t tColDataAddValueByBind(SColData *pColData, TAOS_MULTI_BIND *pBind); +void tColDataSortMerge(SArray *colDataArr); + +// for raw block +int32_t tColDataAddValueByDataBlock(SColData *pColData, int8_t type, int32_t bytes, int32_t nRows, char *lengthOrbitmap, + char *data); +// for encode/decode +int32_t tPutColData(uint8_t *pBuf, SColData *pColData); +int32_t tGetColData(uint8_t *pBuf, SColData *pColData); + // STRUCT ================================ struct STColumn { col_id_t colId; @@ -166,8 +202,11 @@ struct SColData { int16_t cid; int8_t type; int8_t smaOn; + int32_t numOfNone; // # of none + int32_t numOfNull; // # of null + int32_t numOfValue; // # of vale int32_t nVal; - uint8_t flag; + int8_t flag; uint8_t *pBitMap; int32_t *aOffset; int32_t nData; @@ -225,23 +264,15 @@ struct STag { memcpy(varDataVal(x), (str), (_size)); \ } while (0); -// ----------------- SCHEMA BUILDER DEFINITION -typedef struct { - int32_t tCols; - int32_t nCols; - schema_ver_t version; - uint16_t flen; - int32_t tlen; - STColumn *columns; -} STSchemaBuilder; - -int32_t tdInitTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version); -void tdDestroyTSchemaBuilder(STSchemaBuilder *pBuilder); -void tdResetTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version); -int32_t tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int8_t flags, col_id_t colId, col_bytes_t bytes); -STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder); - +// STSchema ================================ STSchema *tBuildTSchema(SSchema *aSchema, int32_t numOfCols, int32_t version); +#define tDestroyTSchema(pTSchema) \ + do { \ + if (pTSchema) { \ + taosMemoryFree(pTSchema); \ + pTSchema = NULL; \ + } \ + } while (0) #endif diff --git a/include/common/tglobal.h b/include/common/tglobal.h index 2331f0b23c52d6b826796549a1964d4eb970a9fd..6fde7b48a29779b2a0c26fb58d360bbfc7ff221f 100644 --- a/include/common/tglobal.h +++ b/include/common/tglobal.h @@ -49,6 +49,8 @@ extern int32_t tsTagFilterResCacheSize; // queue & threads extern int32_t tsNumOfRpcThreads; +extern int32_t tsNumOfRpcSessions; +extern int32_t tsTimeToGetAvailableConn; extern int32_t tsNumOfCommitThreads; extern int32_t tsNumOfTaskQueueThreads; extern int32_t tsNumOfMnodeQueryThreads; @@ -72,6 +74,10 @@ extern int32_t tsHeartbeatTimeout; // vnode extern int64_t tsVndCommitMaxIntervalMs; +// mnode +extern int64_t tsMndSdbWriteDelta; +extern int64_t tsMndLogRetention; + // monitor extern bool tsEnableMonitor; extern int32_t tsMonitorInterval; @@ -86,17 +92,19 @@ extern int32_t tsTelemInterval; extern char tsTelemServer[]; extern uint16_t tsTelemPort; extern bool tsEnableCrashReport; -extern char* tsTelemUri; -extern char* tsClientCrashReportUri; -extern char* tsSvrCrashReportUri; +extern char *tsTelemUri; +extern char *tsClientCrashReportUri; +extern char *tsSvrCrashReportUri; // query buffer management extern int32_t tsQueryBufferSize; // maximum allowed usage buffer size in MB for each data node during query processing -extern int64_t tsQueryBufferSizeBytes; // maximum allowed usage buffer size in byte for each data node +extern int64_t tsQueryBufferSizeBytes; // maximum allowed usage buffer size in byte for each data node +extern int32_t tsCacheLazyLoadThreshold; // cost threshold for last/last_row loading cache as much as possible // query client extern int32_t tsQueryPolicy; extern int32_t tsQueryRspPolicy; +extern int64_t tsQueryMaxConcurrentTables; extern int32_t tsQuerySmaOptimize; extern int32_t tsQueryRsmaTolerance; extern bool tsQueryPlannerTrace; @@ -104,6 +112,7 @@ extern int32_t tsQueryNodeChunkSize; extern bool tsQueryUseNodeAllocator; extern bool tsKeepColumnName; extern bool tsEnableQueryHb; +extern bool tsEnableScience; extern int32_t tsRedirectPeriod; extern int32_t tsRedirectFactor; extern int32_t tsRedirectMaxPeriod; @@ -139,10 +148,10 @@ extern char tsUdfdResFuncs[]; extern char tsUdfdLdLibPath[]; // schemaless -extern char tsSmlChildTableName[]; -extern char tsSmlTagName[]; -extern bool tsSmlDataFormat; -extern int32_t tsSmlBatchSize; +extern char tsSmlChildTableName[]; +extern char tsSmlTagName[]; +// extern bool tsSmlDataFormat; +// extern int32_t tsSmlBatchSize; // wal extern int64_t tsWalFsyncDataSizeLimit; @@ -159,6 +168,8 @@ extern int32_t tsUptimeInterval; extern int32_t tsRpcRetryLimit; extern int32_t tsRpcRetryInterval; +extern bool tsDisableStream; + // #define NEEDTO_COMPRESSS_MSG(size) (tsCompressMsgSize != -1 && (size) > tsCompressMsgSize) int32_t taosCreateLog(const char *logname, int32_t logFileNum, const char *cfgDir, const char **envCmd, diff --git a/include/common/tmisce.h b/include/common/tmisce.h index b9f5cf5b91f55a8f9ca14194b41673c8506bb3fa..bc6558900c2f370c1e29ed09d430587c7bcf531d 100644 --- a/include/common/tmisce.h +++ b/include/common/tmisce.h @@ -27,13 +27,14 @@ typedef struct SCorEpSet { SEpSet epSet; } SCorEpSet; +#define GET_ACTIVE_EP(_eps) (&((_eps)->eps[(_eps)->inUse])) int32_t taosGetFqdnPortFromEp(const char* ep, SEp* pEp); void addEpIntoEpSet(SEpSet* pEpSet, const char* fqdn, uint16_t port); -bool isEpsetEqual(const SEpSet* s1, const SEpSet* s2); - -void updateEpSet_s(SCorEpSet* pEpSet, SEpSet* pNewEpSet); -SEpSet getEpSet_s(SCorEpSet* pEpSet); +bool isEpsetEqual(const SEpSet* s1, const SEpSet* s2); +void epsetAssign(SEpSet* dst, const SEpSet* pSrc); +void updateEpSet_s(SCorEpSet* pEpSet, SEpSet* pNewEpSet); +SEpSet getEpSet_s(SCorEpSet* pEpSet); #ifdef __cplusplus } diff --git a/include/common/tmsg.h b/include/common/tmsg.h index 8dcadf47b686f7cba102dc68988f06a005753cee..9b01532839d16032bb38b3c91b90c608d5b072c9 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -66,6 +66,15 @@ extern int32_t tMsgDict[]; typedef uint16_t tmsg_t; +static inline bool tmsgIsValid(tmsg_t type) { + if (type < TDMT_DND_MAX_MSG || type < TDMT_MND_MAX_MSG || type < TDMT_VND_MAX_MSG || type < TDMT_SCH_MAX_MSG || + type < TDMT_STREAM_MAX_MSG || type < TDMT_MON_MAX_MSG || type < TDMT_SYNC_MAX_MSG || type < TDMT_VND_STREAM_MSG || + type < TDMT_VND_TMQ_MSG || type < TDMT_VND_TMQ_MAX_MSG) { + return true; + } else { + return false; + } +} static inline bool vnodeIsMsgBlock(tmsg_t type) { return (type == TDMT_VND_CREATE_TABLE) || (type == TDMT_VND_ALTER_TABLE) || (type == TDMT_VND_DROP_TABLE) || (type == TDMT_VND_UPDATE_TAG_VAL) || (type == TDMT_VND_ALTER_CONFIRM); @@ -115,6 +124,7 @@ typedef enum _mgmt_table { TSDB_MGMT_TABLE_STREAMS, TSDB_MGMT_TABLE_TABLE, TSDB_MGMT_TABLE_TAG, + TSDB_MGMT_TABLE_COL, TSDB_MGMT_TABLE_USER, TSDB_MGMT_TABLE_GRANTS, TSDB_MGMT_TABLE_VGROUP, @@ -143,6 +153,8 @@ typedef enum _mgmt_table { #define TSDB_ALTER_TABLE_UPDATE_TAG_BYTES 8 #define TSDB_ALTER_TABLE_UPDATE_OPTIONS 9 #define TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME 10 +#define TSDB_ALTER_TABLE_ADD_TAG_INDEX 11 +#define TSDB_ALTER_TABLE_DROP_TAG_INDEX 12 #define TSDB_FILL_NONE 0 #define TSDB_FILL_NULL 1 @@ -165,6 +177,12 @@ typedef enum _mgmt_table { #define TSDB_ALTER_USER_SYSINFO 0xA #define TSDB_ALTER_USER_ADD_SUBSCRIBE_TOPIC 0xB #define TSDB_ALTER_USER_REMOVE_SUBSCRIBE_TOPIC 0xC +#define TSDB_ALTER_USER_ADD_READ_TABLE 0xD +#define TSDB_ALTER_USER_REMOVE_READ_TABLE 0xE +#define TSDB_ALTER_USER_ADD_WRITE_TABLE 0xF +#define TSDB_ALTER_USER_REMOVE_WRITE_TABLE 0x10 +#define TSDB_ALTER_USER_ADD_ALL_TABLE 0x11 +#define TSDB_ALTER_USER_REMOVE_ALL_TABLE 0x12 #define TSDB_ALTER_USER_PRIVILEGES 0x2 @@ -293,6 +311,15 @@ struct SSchema { char name[TSDB_COL_NAME_LEN]; }; +struct SSchema2 { + int8_t type; + int8_t flags; + col_id_t colId; + int32_t bytes; + char name[TSDB_COL_NAME_LEN]; + char alias[TSDB_COL_NAME_LEN]; +}; + typedef struct { char tbName[TSDB_TABLE_NAME_LEN]; char stbName[TSDB_TABLE_NAME_LEN]; @@ -345,7 +372,19 @@ void tFreeSSubmitRsp(SSubmitRsp* pRsp); #define COL_IS_SET(FLG) (((FLG) & (COL_SET_VAL | COL_SET_NULL)) != 0) #define COL_CLR_SET(FLG) ((FLG) &= (~(COL_SET_VAL | COL_SET_NULL))) -#define IS_BSMA_ON(s) (((s)->flags & 0x01) == COL_SMA_ON) +#define IS_BSMA_ON(s) (((s)->flags & 0x01) == COL_SMA_ON) +#define IS_IDX_ON(s) (((s)->flags & 0x02) == COL_IDX_ON) +#define IS_SET_NULL(s) (((s)->flags & COL_SET_NULL) == COL_SET_NULL) + +#define SSCHMEA_SET_IDX_ON(s) \ + do { \ + (s)->flags |= COL_IDX_ON; \ + } while (0) + +#define SSCHMEA_SET_IDX_OFF(s) \ + do { \ + (s)->flags &= (~COL_IDX_ON); \ + } while (0) #define SSCHMEA_TYPE(s) ((s)->type) #define SSCHMEA_FLAGS(s) ((s)->flags) @@ -376,13 +415,20 @@ static FORCE_INLINE SSchemaWrapper* tCloneSSchemaWrapper(const SSchemaWrapper* p return pSW; } -static FORCE_INLINE void tDeleteSSchemaWrapper(SSchemaWrapper* pSchemaWrapper) { +static FORCE_INLINE void tDeleteSchemaWrapper(SSchemaWrapper* pSchemaWrapper) { if (pSchemaWrapper) { taosMemoryFree(pSchemaWrapper->pSchema); taosMemoryFree(pSchemaWrapper); } } +static FORCE_INLINE void tDeleteSSchemaWrapperForHash(void* pSchemaWrapper) { + if (pSchemaWrapper != NULL && *(SSchemaWrapper**)pSchemaWrapper != NULL) { + taosMemoryFree((*(SSchemaWrapper**)pSchemaWrapper)->pSchema); + taosMemoryFree(*(SSchemaWrapper**)pSchemaWrapper); + } +} + static FORCE_INLINE int32_t taosEncodeSSchema(void** buf, const SSchema* pSchema) { int32_t tlen = 0; tlen += taosEncodeFixedI8(buf, pSchema->type); @@ -484,8 +530,6 @@ static FORCE_INLINE int32_t tDecodeSSchemaWrapperEx(SDecoder* pDecoder, SSchemaW return 0; } -STSchema* tdGetSTSChemaFromSSChema(SSchema* pSchema, int32_t nCols, int32_t sver); - typedef struct { char name[TSDB_TABLE_FNAME_LEN]; int8_t igExists; @@ -574,6 +618,7 @@ typedef struct { char user[TSDB_USER_LEN]; char passwd[TSDB_PASSWORD_LEN]; int64_t startTime; + char sVer[TSDB_VERSION_LEN]; } SConnectReq; int32_t tSerializeSConnectReq(void* buf, int32_t bufLen, SConnectReq* pReq); @@ -630,17 +675,21 @@ int32_t tSerializeSCreateUserReq(void* buf, int32_t bufLen, SCreateUserReq* pReq int32_t tDeserializeSCreateUserReq(void* buf, int32_t bufLen, SCreateUserReq* pReq); typedef struct { - int8_t alterType; - int8_t superUser; - int8_t sysInfo; - int8_t enable; - char user[TSDB_USER_LEN]; - char pass[TSDB_USET_PASSWORD_LEN]; - char objname[TSDB_DB_FNAME_LEN]; // db or topic + int8_t alterType; + int8_t superUser; + int8_t sysInfo; + int8_t enable; + char user[TSDB_USER_LEN]; + char pass[TSDB_USET_PASSWORD_LEN]; + char objname[TSDB_DB_FNAME_LEN]; // db or topic + char tabName[TSDB_TABLE_NAME_LEN]; + char* tagCond; + int32_t tagCondLen; } SAlterUserReq; int32_t tSerializeSAlterUserReq(void* buf, int32_t bufLen, SAlterUserReq* pReq); int32_t tDeserializeSAlterUserReq(void* buf, int32_t bufLen, SAlterUserReq* pReq); +void tFreeSAlterUserReq(SAlterUserReq* pReq); typedef struct { char user[TSDB_USER_LEN]; @@ -659,6 +708,9 @@ typedef struct { SHashObj* createdDbs; SHashObj* readDbs; SHashObj* writeDbs; + SHashObj* readTbs; + SHashObj* writeTbs; + SHashObj* useDbs; } SGetUserAuthRsp; int32_t tSerializeSGetUserAuthRsp(void* buf, int32_t bufLen, SGetUserAuthRsp* pRsp); @@ -806,6 +858,9 @@ typedef struct { int8_t cacheLast; int8_t replications; int32_t sstTrigger; + int32_t minRows; + int32_t walRetentionPeriod; + int32_t walRetentionSize; } SAlterDbReq; int32_t tSerializeSAlterDbReq(void* buf, int32_t bufLen, SAlterDbReq* pReq); @@ -887,6 +942,9 @@ int32_t tSerializeSVDropTtlTableReq(void* buf, int32_t bufLen, SVDropTtlTableReq int32_t tDeserializeSVDropTtlTableReq(void* buf, int32_t bufLen, SVDropTtlTableReq* pReq); typedef struct { + char db[TSDB_DB_FNAME_LEN]; + int64_t dbId; + int32_t cfgVersion; int32_t numOfVgroups; int32_t numOfStables; int32_t buffer; @@ -900,20 +958,32 @@ typedef struct { int32_t minRows; int32_t maxRows; int32_t walFsyncPeriod; + int16_t hashPrefix; + int16_t hashSuffix; int8_t walLevel; int8_t precision; int8_t compression; int8_t replications; int8_t strict; int8_t cacheLast; + int32_t tsdbPageSize; + int32_t walRetentionPeriod; + int32_t walRollPeriod; + int64_t walRetentionSize; + int64_t walSegmentSize; int32_t numOfRetensions; SArray* pRetensions; int8_t schemaless; int16_t sstTrigger; } SDbCfgRsp; +typedef SDbCfgRsp SDbCfgInfo; + +int32_t tSerializeSDbCfgRspImpl(SEncoder *encoder, const SDbCfgRsp *pRsp); int32_t tSerializeSDbCfgRsp(void* buf, int32_t bufLen, const SDbCfgRsp* pRsp); int32_t tDeserializeSDbCfgRsp(void* buf, int32_t bufLen, SDbCfgRsp* pRsp); +int32_t tDeserializeSDbCfgRspImpl(SDecoder* decoder, SDbCfgRsp *pRsp); +void tFreeSDbCfgRsp(SDbCfgRsp *pRsp); typedef struct { int32_t rowNum; @@ -970,12 +1040,17 @@ int32_t tDeserializeSDnodeListRsp(void* buf, int32_t bufLen, SDnodeListRsp* pRsp void tFreeSDnodeListRsp(SDnodeListRsp* pRsp); typedef struct { - SArray* pArray; // Array of SUseDbRsp -} SUseDbBatchRsp; + SUseDbRsp *useDbRsp; + SDbCfgRsp *cfgRsp; +} SDbHbRsp; -int32_t tSerializeSUseDbBatchRsp(void* buf, int32_t bufLen, SUseDbBatchRsp* pRsp); -int32_t tDeserializeSUseDbBatchRsp(void* buf, int32_t bufLen, SUseDbBatchRsp* pRsp); -void tFreeSUseDbBatchRsp(SUseDbBatchRsp* pRsp); +typedef struct { + SArray* pArray; // Array of SDbHbRsp +} SDbHbBatchRsp; + +int32_t tSerializeSDbHbBatchRsp(void* buf, int32_t bufLen, SDbHbBatchRsp* pRsp); +int32_t tDeserializeSDbHbBatchRsp(void* buf, int32_t bufLen, SDbHbBatchRsp* pRsp); +void tFreeSDbHbBatchRsp(SDbHbBatchRsp* pRsp); typedef struct { SArray* pArray; // Array of SGetUserAuthRsp @@ -986,7 +1061,8 @@ int32_t tDeserializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchR void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp* pRsp); typedef struct { - char db[TSDB_DB_FNAME_LEN]; + char db[TSDB_DB_FNAME_LEN]; + STimeWindow timeRange; } SCompactDbReq; int32_t tSerializeSCompactDbReq(void* buf, int32_t bufLen, SCompactDbReq* pReq); @@ -1004,6 +1080,7 @@ typedef struct { int64_t signature; char* pComment; char* pCode; + int8_t orReplace; } SCreateFuncReq; int32_t tSerializeSCreateFuncReq(void* buf, int32_t bufLen, SCreateFuncReq* pReq); @@ -1042,9 +1119,15 @@ typedef struct { char* pCode; } SFuncInfo; +typedef struct { + int32_t funcVersion; + int64_t funcCreatedTime; +} SFuncExtraInfo; + typedef struct { int32_t numOfFuncs; SArray* pFuncInfos; + SArray* pFuncExtraInfos; } SRetrieveFuncRsp; int32_t tSerializeSRetrieveFuncRsp(void* buf, int32_t bufLen, SRetrieveFuncRsp* pRsp); @@ -1088,6 +1171,7 @@ typedef struct { int64_t numOfInsertSuccessReqs; int64_t numOfBatchInsertReqs; int64_t numOfBatchInsertSuccessReqs; + int32_t numOfCachedTables; } SVnodeLoad; typedef struct { @@ -1234,9 +1318,21 @@ int32_t tSerializeSDropVnodeReq(void* buf, int32_t bufLen, SDropVnodeReq* pReq); int32_t tDeserializeSDropVnodeReq(void* buf, int32_t bufLen, SDropVnodeReq* pReq); typedef struct { + char colName[TSDB_COL_NAME_LEN]; + char stb[TSDB_TABLE_FNAME_LEN]; + int64_t stbUid; int64_t dbUid; - char db[TSDB_DB_FNAME_LEN]; int64_t reserved[8]; +} SDropIndexReq; + +int32_t tSerializeSDropIdxReq(void* buf, int32_t bufLen, SDropIndexReq* pReq); +int32_t tDeserializeSDropIdxReq(void* buf, int32_t bufLen, SDropIndexReq* pReq); + +typedef struct { + int64_t dbUid; + char db[TSDB_DB_FNAME_LEN]; + int64_t compactStartTime; + STimeWindow tw; } SCompactVnodeReq; int32_t tSerializeSCompactVnodeReq(void* buf, int32_t bufLen, SCompactVnodeReq* pReq); @@ -1257,6 +1353,12 @@ typedef struct { int8_t strict; int8_t cacheLast; int64_t reserved[8]; + // 1st modification + int16_t sttTrigger; + int32_t minRows; + // 2nd modification + int32_t walRetentionPeriod; + int32_t walRetentionSize; } SAlterVnodeConfigReq; int32_t tSerializeSAlterVnodeConfigReq(void* buf, int32_t bufLen, SAlterVnodeConfigReq* pReq); @@ -1274,6 +1376,25 @@ typedef struct { int32_t tSerializeSAlterVnodeReplicaReq(void* buf, int32_t bufLen, SAlterVnodeReplicaReq* pReq); int32_t tDeserializeSAlterVnodeReplicaReq(void* buf, int32_t bufLen, SAlterVnodeReplicaReq* pReq); +typedef struct { + int32_t vgId; + int8_t disable; +} SDisableVnodeWriteReq; + +int32_t tSerializeSDisableVnodeWriteReq(void* buf, int32_t bufLen, SDisableVnodeWriteReq* pReq); +int32_t tDeserializeSDisableVnodeWriteReq(void* buf, int32_t bufLen, SDisableVnodeWriteReq* pReq); + +typedef struct { + int32_t srcVgId; + int32_t dstVgId; + uint32_t hashBegin; + uint32_t hashEnd; + int64_t reserved; +} SAlterVnodeHashRangeReq; + +int32_t tSerializeSAlterVnodeHashRangeReq(void* buf, int32_t bufLen, SAlterVnodeHashRangeReq* pReq); +int32_t tDeserializeSAlterVnodeHashRangeReq(void* buf, int32_t bufLen, SAlterVnodeHashRangeReq* pReq); + typedef struct { SMsgHead header; char dbFName[TSDB_DB_FNAME_LEN]; @@ -1397,6 +1518,7 @@ typedef struct { char db[TSDB_DB_FNAME_LEN]; char tb[TSDB_TABLE_NAME_LEN]; char user[TSDB_USER_LEN]; + char filterTb[TSDB_TABLE_NAME_LEN]; int64_t showId; } SRetrieveTableReq; @@ -1572,6 +1694,20 @@ typedef struct { int32_t tSerializeSRedistributeVgroupReq(void* buf, int32_t bufLen, SRedistributeVgroupReq* pReq); int32_t tDeserializeSRedistributeVgroupReq(void* buf, int32_t bufLen, SRedistributeVgroupReq* pReq); +typedef struct { + int32_t useless; +} SBalanceVgroupLeaderReq; + +int32_t tSerializeSBalanceVgroupLeaderReq(void* buf, int32_t bufLen, SBalanceVgroupLeaderReq* pReq); +int32_t tDeserializeSBalanceVgroupLeaderReq(void* buf, int32_t bufLen, SBalanceVgroupLeaderReq* pReq); + +typedef struct { + int32_t vgId; +} SForceBecomeFollowerReq; + +int32_t tSerializeSForceBecomeFollowerReq(void* buf, int32_t bufLen, SForceBecomeFollowerReq* pReq); +int32_t tDeserializeSForceBecomeFollowerReq(void* buf, int32_t bufLen, SForceBecomeFollowerReq* pReq); + typedef struct { int32_t vgId; } SSplitVgroupReq; @@ -1737,6 +1873,8 @@ typedef struct { int32_t execId; } STaskDropReq; +int32_t tSerializeSTaskDropReq(void* buf, int32_t bufLen, STaskDropReq* pReq); +int32_t tDeserializeSTaskDropReq(void* buf, int32_t bufLen, STaskDropReq* pReq); int32_t tSerializeSTaskDropReq(void* buf, int32_t bufLen, STaskDropReq* pReq); int32_t tDeserializeSTaskDropReq(void* buf, int32_t bufLen, STaskDropReq* pReq); @@ -1750,11 +1888,19 @@ typedef struct { #define STREAM_TRIGGER_AT_ONCE 1 #define STREAM_TRIGGER_WINDOW_CLOSE 2 #define STREAM_TRIGGER_MAX_DELAY 3 -#define STREAM_DEFAULT_IGNORE_EXPIRED 0 +#define STREAM_DEFAULT_IGNORE_EXPIRED 1 #define STREAM_FILL_HISTORY_ON 1 #define STREAM_FILL_HISTORY_OFF 0 #define STREAM_DEFAULT_FILL_HISTORY STREAM_FILL_HISTORY_OFF #define STREAM_DEFAULT_IGNORE_UPDATE 0 +#define STREAM_CREATE_STABLE_TRUE 1 +#define STREAM_CREATE_STABLE_FALSE 0 + +typedef struct SColLocation { + int16_t slotId; + col_id_t colId; + int8_t type; +} SColLocation; typedef struct { char name[TSDB_STREAM_FNAME_LEN]; @@ -1772,8 +1918,12 @@ typedef struct { SArray* pTags; // array of SField // 3.0.20 int64_t checkpointFreq; // ms - int64_t deleteMark; - int8_t igUpdate; + // 3.0.2.3 + int8_t createStb; + uint64_t targetStbUid; + SArray* fillNullCols; // array of SColLocation + int64_t deleteMark; + int8_t igUpdate; } SCMCreateStreamReq; typedef struct { @@ -1935,7 +2085,6 @@ static FORCE_INLINE void* tDeserializeSMVSubscribeReq(void* buf, SMVSubscribeReq typedef struct { char key[TSDB_SUBSCRIBE_KEY_LEN]; - SArray* lostConsumers; // SArray SArray* removedConsumers; // SArray SArray* newConsumers; // SArray } SMqRebInfo; @@ -1946,10 +2095,6 @@ static FORCE_INLINE SMqRebInfo* tNewSMqRebSubscribe(const char* key) { return NULL; } tstrncpy(pRebInfo->key, key, TSDB_SUBSCRIBE_KEY_LEN); - pRebInfo->lostConsumers = taosArrayInit(0, sizeof(int64_t)); - if (pRebInfo->lostConsumers == NULL) { - goto _err; - } pRebInfo->removedConsumers = taosArrayInit(0, sizeof(int64_t)); if (pRebInfo->removedConsumers == NULL) { goto _err; @@ -1960,7 +2105,6 @@ static FORCE_INLINE SMqRebInfo* tNewSMqRebSubscribe(const char* key) { } return pRebInfo; _err: - taosArrayDestroy(pRebInfo->lostConsumers); taosArrayDestroy(pRebInfo->removedConsumers); taosArrayDestroy(pRebInfo->newConsumers); taosMemoryFreeClear(pRebInfo); @@ -2087,10 +2231,15 @@ typedef struct SVCreateTbReq { }; } SVCreateTbReq; -int tEncodeSVCreateTbReq(SEncoder* pCoder, const SVCreateTbReq* pReq); -int tDecodeSVCreateTbReq(SDecoder* pCoder, SVCreateTbReq* pReq); +int tEncodeSVCreateTbReq(SEncoder* pCoder, const SVCreateTbReq* pReq); +int tDecodeSVCreateTbReq(SDecoder* pCoder, SVCreateTbReq* pReq); +void tDestroySVCreateTbReq(SVCreateTbReq* pReq, int32_t flags); static FORCE_INLINE void tdDestroySVCreateTbReq(SVCreateTbReq* req) { + if (NULL == req) { + return; + } + taosMemoryFreeClear(req->name); taosMemoryFreeClear(req->comment); if (req->type == TSDB_CHILD_TABLE) { @@ -2605,7 +2754,7 @@ typedef struct { char subKey[TSDB_SUBSCRIBE_KEY_LEN]; int8_t subType; int8_t withMeta; - char* qmsg; + char* qmsg; // SubPlanToString int64_t suid; } SMqRebVgReq; @@ -2767,6 +2916,22 @@ typedef struct { int32_t tSerializeSMDropSmaReq(void* buf, int32_t bufLen, SMDropSmaReq* pReq); int32_t tDeserializeSMDropSmaReq(void* buf, int32_t bufLen, SMDropSmaReq* pReq); +typedef struct { + char dbFName[TSDB_DB_FNAME_LEN]; + char stbName[TSDB_TABLE_NAME_LEN]; + char colName[TSDB_COL_NAME_LEN]; + char idxName[TSDB_INDEX_FNAME_LEN]; + int8_t idxType; +} SCreateTagIndexReq; + +int32_t tSerializeSCreateTagIdxReq(void* buf, int32_t bufLen, SCreateTagIndexReq* pReq); +int32_t tDeserializeSCreateTagIdxReq(void* buf, int32_t bufLen, SCreateTagIndexReq* pReq); + +typedef SMDropSmaReq SDropTagIndexReq; + +int32_t tSerializeSDropTagIdxReq(void* buf, int32_t bufLen, SDropTagIndexReq* pReq); +int32_t tDeserializeSDropTagIdxReq(void* buf, int32_t bufLen, SDropTagIndexReq* pReq); + typedef struct { int8_t version; // for compatibility(default 0) int8_t intervalUnit; // MACRO: TIME_UNIT_XXX @@ -3067,9 +3232,10 @@ typedef struct { SArray* blockData; SArray* blockTbName; SArray* blockSchema; - int32_t createTableNum; - SArray* createTableLen; - SArray* createTableReq; + // the following attributes are extended from SMqDataRsp + int32_t createTableNum; + SArray* createTableLen; + SArray* createTableReq; } STaosxRsp; int32_t tEncodeSTaosxRsp(SEncoder* pEncoder, const STaosxRsp* pRsp); @@ -3238,6 +3404,64 @@ int32_t tSerializeSMqAskEpReq(void* buf, int32_t bufLen, SMqAskEpReq* pReq); int32_t tDeserializeSMqAskEpReq(void* buf, int32_t bufLen, SMqAskEpReq* pReq); int32_t tSerializeSMqHbReq(void* buf, int32_t bufLen, SMqHbReq* pReq); int32_t tDeserializeSMqHbReq(void* buf, int32_t bufLen, SMqHbReq* pReq); +int32_t tSerializeSMqAskEpReq(void* buf, int32_t bufLen, SMqAskEpReq* pReq); +int32_t tDeserializeSMqAskEpReq(void* buf, int32_t bufLen, SMqAskEpReq* pReq); +int32_t tSerializeSMqHbReq(void* buf, int32_t bufLen, SMqHbReq* pReq); +int32_t tDeserializeSMqHbReq(void* buf, int32_t bufLen, SMqHbReq* pReq); + +#define SUBMIT_REQ_AUTO_CREATE_TABLE 0x1 +#define SUBMIT_REQ_COLUMN_DATA_FORMAT 0x2 + +typedef struct { + int32_t flags; + SVCreateTbReq* pCreateTbReq; + int64_t suid; + int64_t uid; + int32_t sver; + union { + SArray* aRowP; + SArray* aCol; + }; +} SSubmitTbData; + +typedef struct { + SArray* aSubmitTbData; // SArray +} SSubmitReq2; + +typedef struct { + SMsgHead header; + int64_t version; + char data[]; // SSubmitReq2 +} SSubmitReq2Msg; + +int32_t tEncodeSubmitReq(SEncoder* pCoder, const SSubmitReq2* pReq); +int32_t tDecodeSubmitReq(SDecoder* pCoder, SSubmitReq2* pReq); +void tDestroySubmitTbData(SSubmitTbData* pTbData, int32_t flag); +void tDestroySubmitReq(SSubmitReq2* pReq, int32_t flag); + +typedef struct { + int32_t affectedRows; + SArray* aCreateTbRsp; // SArray +} SSubmitRsp2; + +int32_t tEncodeSSubmitRsp2(SEncoder* pCoder, const SSubmitRsp2* pRsp); +int32_t tDecodeSSubmitRsp2(SDecoder* pCoder, SSubmitRsp2* pRsp); +void tDestroySSubmitRsp2(SSubmitRsp2* pRsp, int32_t flag); + +#define TSDB_MSG_FLG_ENCODE 0x1 +#define TSDB_MSG_FLG_DECODE 0x2 +#define TSDB_MSG_FLG_CMPT 0x3 + +typedef struct { + union { + struct { + void* msgStr; + int32_t msgLen; + int64_t ver; + }; + void* pDataBlock; + }; +} SPackedData; #pragma pack(pop) diff --git a/include/common/tmsgcb.h b/include/common/tmsgcb.h index eaac319141521a7e80f2f64a02e5580f7375bd74..9b709272b2f5473828eee762a0834b999c2ec4bd 100644 --- a/include/common/tmsgcb.h +++ b/include/common/tmsgcb.h @@ -34,12 +34,12 @@ typedef enum { WRITE_QUEUE, APPLY_QUEUE, SYNC_QUEUE, - SYNC_CTRL_QUEUE, + SYNC_RD_QUEUE, STREAM_QUEUE, QUEUE_MAX, } EQueueType; -typedef void (*UpdateDnodeInfoFp)(void* pData, int32_t* dnodeId, int64_t* clusterId, char* fqdn, uint16_t* port); +typedef bool (*UpdateDnodeInfoFp)(void* pData, int32_t* dnodeId, int64_t* clusterId, char* fqdn, uint16_t* port); typedef int32_t (*PutToQueueFp)(void* pMgmt, EQueueType qtype, SRpcMsg* pMsg); typedef int32_t (*GetQueueSizeFp)(void* pMgmt, int32_t vgId, EQueueType qtype); typedef int32_t (*SendReqFp)(const SEpSet* pEpSet, SRpcMsg* pMsg); @@ -70,7 +70,7 @@ void tmsgSendRsp(SRpcMsg* pMsg); void tmsgRegisterBrokenLinkArg(SRpcMsg* pMsg); void tmsgReleaseHandle(SRpcHandleInfo* pHandle, int8_t type); void tmsgReportStartup(const char* name, const char* desc); -void tmsgUpdateDnodeInfo(int32_t* dnodeId, int64_t* clusterId, char* fqdn, uint16_t* port); +bool tmsgUpdateDnodeInfo(int32_t* dnodeId, int64_t* clusterId, char* fqdn, uint16_t* port); void tmsgUpdateDnodeEpSet(SEpSet* epset); #ifdef __cplusplus diff --git a/include/common/tmsgdef.h b/include/common/tmsgdef.h index 7833bdf1393c72b988b1553d691e7d8936b14603..6cf6140815cf1663392950b0ee119b0ae65db126 100644 --- a/include/common/tmsgdef.h +++ b/include/common/tmsgdef.h @@ -172,9 +172,10 @@ enum { TD_DEF_MSG_TYPE(TDMT_MND_SERVER_VERSION, "server-version", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_UPTIME_TIMER, "uptime-timer", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_TMQ_LOST_CONSUMER_CLEAR, "lost-consumer-clear", NULL, NULL) - TD_DEF_MSG_TYPE(TDMT_MND_STREAM_CHECKPOINT_TIMER, "stream-checkpoint-tmr", NULL, NULL) - TD_DEF_MSG_TYPE(TDMT_MND_STREAM_BEGIN_CHECKPOINT, "stream-begin-checkpoint", NULL, NULL) + // TD_DEF_MSG_TYPE(TDMT_MND_STREAM_CHECKPOINT_TIMER, "stream-checkpoint-tmr", NULL, NULL) + // TD_DEF_MSG_TYPE(TDMT_MND_STREAM_BEGIN_CHECKPOINT, "stream-begin-checkpoint", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_MND_MAX_MSG, "mnd-max", NULL, NULL) + TD_DEF_MSG_TYPE(TDMT_MND_BALANCE_VGROUP_LEADER, "balance-vgroup-leader", NULL, NULL) TD_NEW_MSG_SEG(TDMT_VND_MSG) TD_DEF_MSG_TYPE(TDMT_VND_SUBMIT, "submit", SSubmitReq, SSubmitRsp) @@ -220,6 +221,10 @@ enum { TD_DEF_MSG_TYPE(TDMT_VND_DROP_TTL_TABLE, "vnode-drop-ttl-stb", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_TRIM, "vnode-trim", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_COMMIT, "vnode-commit", NULL, NULL) + TD_DEF_MSG_TYPE(TDMT_VND_CREATE_INDEX, "vnode-create-index", NULL, NULL) + TD_DEF_MSG_TYPE(TDMT_VND_DROP_INDEX, "vnode-drop-index", NULL, NULL) + + TD_DEF_MSG_TYPE(TDMT_VND_DISABLE_WRITE, "vnode-disable-write", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_VND_MAX_MSG, "vnd-max", NULL, NULL) TD_NEW_MSG_SEG(TDMT_SCH_MSG) @@ -255,7 +260,7 @@ enum { TD_NEW_MSG_SEG(TDMT_SYNC_MSG) TD_DEF_MSG_TYPE(TDMT_SYNC_TIMEOUT, "sync-timer", NULL, NULL) - TD_DEF_MSG_TYPE(TDMT_SYNC_PING, "sync-ping", NULL, NULL) // no longer used + TD_DEF_MSG_TYPE(TDMT_SYNC_TIMEOUT_ELECTION, "sync-elect", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_SYNC_PING_REPLY, "sync-ping-reply", NULL, NULL) // no longer used TD_DEF_MSG_TYPE(TDMT_SYNC_CLIENT_REQUEST, "sync-client-request", NULL, NULL) TD_DEF_MSG_TYPE(TDMT_SYNC_CLIENT_REQUEST_BATCH, "sync-client-request-batch", NULL, NULL) @@ -282,6 +287,7 @@ enum { TD_DEF_MSG_TYPE(TDMT_SYNC_PRE_SNAPSHOT, "sync-pre-snapshot", NULL, NULL) // no longer used TD_DEF_MSG_TYPE(TDMT_SYNC_PRE_SNAPSHOT_REPLY, "sync-pre-snapshot-reply", NULL, NULL) // no longer used TD_DEF_MSG_TYPE(TDMT_SYNC_MAX_MSG, "sync-max", NULL, NULL) + TD_DEF_MSG_TYPE(TDMT_SYNC_FORCE_FOLLOWER, "sync-force-become-follower", NULL, NULL) TD_NEW_MSG_SEG(TDMT_VND_STREAM_MSG) TD_DEF_MSG_TYPE(TDMT_VND_STREAM_TRIGGER, "vnode-stream-trigger", NULL, NULL) diff --git a/include/common/ttime.h b/include/common/ttime.h index 7bbc6a8e5655f1470424fcc9757bbbd7584799ea..de74e48100e337a516d6fa3848317074be56ec1f 100644 --- a/include/common/ttime.h +++ b/include/common/ttime.h @@ -64,7 +64,7 @@ static FORCE_INLINE int64_t taosGetTimestampToday(int32_t precision) { : 1000000000; time_t t = taosTime(NULL); struct tm tm; - taosLocalTime(&t, &tm); + taosLocalTime(&t, &tm, NULL); tm.tm_hour = 0; tm.tm_min = 0; tm.tm_sec = 0; @@ -80,15 +80,15 @@ int32_t taosTimeCountInterval(int64_t skey, int64_t ekey, int64_t interval, char int32_t parseAbsoluteDuration(const char* token, int32_t tokenlen, int64_t* ts, char* unit, int32_t timePrecision); int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit, int32_t timePrecision); -int32_t taosParseTime(const char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t dayligth); +int32_t taosParseTime(const char* timestr, int64_t* pTime, int32_t len, int32_t timePrec, int8_t dayligth); void deltaToUtcInitOnce(); char getPrecisionUnit(int32_t precision); -int64_t convertTimePrecision(int64_t time, int32_t fromPrecision, int32_t toPrecision); -int64_t convertTimeFromPrecisionToUnit(int64_t time, int32_t fromPrecision, char toUnit); +int64_t convertTimePrecision(int64_t ts, int32_t fromPrecision, int32_t toPrecision); +int64_t convertTimeFromPrecisionToUnit(int64_t ts, int32_t fromPrecision, char toUnit); int32_t convertStringToTimestamp(int16_t type, char* inputData, int64_t timePrec, int64_t* timeVal); -void taosFormatUtcTime(char* buf, int32_t bufLen, int64_t time, int32_t precision); +void taosFormatUtcTime(char* buf, int32_t bufLen, int64_t ts, int32_t precision); #ifdef __cplusplus } diff --git a/include/common/ttokendef.h b/include/common/ttokendef.h index 1d69e129f4110d4f461ed1b0d65cce578551b2e4..10b5328e6d7fe83df5476817eb4e3991ac45895e 100644 --- a/include/common/ttokendef.h +++ b/include/common/ttokendef.h @@ -16,329 +16,336 @@ #ifndef _TD_COMMON_TOKEN_H_ #define _TD_COMMON_TOKEN_H_ -#define TK_OR 1 -#define TK_AND 2 -#define TK_UNION 3 -#define TK_ALL 4 -#define TK_MINUS 5 -#define TK_EXCEPT 6 -#define TK_INTERSECT 7 -#define TK_NK_BITAND 8 -#define TK_NK_BITOR 9 -#define TK_NK_LSHIFT 10 -#define TK_NK_RSHIFT 11 -#define TK_NK_PLUS 12 -#define TK_NK_MINUS 13 -#define TK_NK_STAR 14 -#define TK_NK_SLASH 15 -#define TK_NK_REM 16 -#define TK_NK_CONCAT 17 -#define TK_CREATE 18 -#define TK_ACCOUNT 19 -#define TK_NK_ID 20 -#define TK_PASS 21 -#define TK_NK_STRING 22 -#define TK_ALTER 23 -#define TK_PPS 24 -#define TK_TSERIES 25 -#define TK_STORAGE 26 -#define TK_STREAMS 27 -#define TK_QTIME 28 -#define TK_DBS 29 -#define TK_USERS 30 -#define TK_CONNS 31 -#define TK_STATE 32 -#define TK_USER 33 -#define TK_ENABLE 34 -#define TK_NK_INTEGER 35 -#define TK_SYSINFO 36 -#define TK_DROP 37 -#define TK_GRANT 38 -#define TK_ON 39 -#define TK_TO 40 -#define TK_REVOKE 41 -#define TK_FROM 42 -#define TK_SUBSCRIBE 43 -#define TK_NK_COMMA 44 -#define TK_READ 45 -#define TK_WRITE 46 -#define TK_NK_DOT 47 -#define TK_DNODE 48 -#define TK_PORT 49 -#define TK_DNODES 50 -#define TK_NK_IPTOKEN 51 -#define TK_FORCE 52 -#define TK_LOCAL 53 -#define TK_QNODE 54 -#define TK_BNODE 55 -#define TK_SNODE 56 -#define TK_MNODE 57 -#define TK_DATABASE 58 -#define TK_USE 59 -#define TK_FLUSH 60 -#define TK_TRIM 61 -#define TK_IF 62 -#define TK_NOT 63 -#define TK_EXISTS 64 -#define TK_BUFFER 65 -#define TK_CACHEMODEL 66 -#define TK_CACHESIZE 67 -#define TK_COMP 68 -#define TK_DURATION 69 -#define TK_NK_VARIABLE 70 -#define TK_MAXROWS 71 -#define TK_MINROWS 72 -#define TK_KEEP 73 -#define TK_PAGES 74 -#define TK_PAGESIZE 75 -#define TK_TSDB_PAGESIZE 76 -#define TK_PRECISION 77 -#define TK_REPLICA 78 -#define TK_VGROUPS 79 -#define TK_SINGLE_STABLE 80 -#define TK_RETENTIONS 81 -#define TK_SCHEMALESS 82 -#define TK_WAL_LEVEL 83 -#define TK_WAL_FSYNC_PERIOD 84 -#define TK_WAL_RETENTION_PERIOD 85 -#define TK_WAL_RETENTION_SIZE 86 -#define TK_WAL_ROLL_PERIOD 87 -#define TK_WAL_SEGMENT_SIZE 88 -#define TK_STT_TRIGGER 89 -#define TK_TABLE_PREFIX 90 -#define TK_TABLE_SUFFIX 91 -#define TK_NK_COLON 92 -#define TK_MAX_SPEED 93 -#define TK_TABLE 94 -#define TK_NK_LP 95 -#define TK_NK_RP 96 -#define TK_STABLE 97 -#define TK_ADD 98 -#define TK_COLUMN 99 -#define TK_MODIFY 100 -#define TK_RENAME 101 -#define TK_TAG 102 -#define TK_SET 103 -#define TK_NK_EQ 104 -#define TK_USING 105 -#define TK_TAGS 106 -#define TK_COMMENT 107 -#define TK_BOOL 108 -#define TK_TINYINT 109 -#define TK_SMALLINT 110 -#define TK_INT 111 -#define TK_INTEGER 112 -#define TK_BIGINT 113 -#define TK_FLOAT 114 -#define TK_DOUBLE 115 -#define TK_BINARY 116 -#define TK_TIMESTAMP 117 -#define TK_NCHAR 118 -#define TK_UNSIGNED 119 -#define TK_JSON 120 -#define TK_VARCHAR 121 -#define TK_MEDIUMBLOB 122 -#define TK_BLOB 123 -#define TK_VARBINARY 124 -#define TK_DECIMAL 125 -#define TK_MAX_DELAY 126 -#define TK_WATERMARK 127 -#define TK_ROLLUP 128 -#define TK_TTL 129 -#define TK_SMA 130 -#define TK_DELETE_MARK 131 -#define TK_FIRST 132 -#define TK_LAST 133 -#define TK_SHOW 134 -#define TK_PRIVILEGES 135 -#define TK_DATABASES 136 -#define TK_TABLES 137 -#define TK_STABLES 138 -#define TK_MNODES 139 -#define TK_QNODES 140 -#define TK_FUNCTIONS 141 -#define TK_INDEXES 142 -#define TK_ACCOUNTS 143 -#define TK_APPS 144 -#define TK_CONNECTIONS 145 -#define TK_LICENCES 146 -#define TK_GRANTS 147 -#define TK_QUERIES 148 -#define TK_SCORES 149 -#define TK_TOPICS 150 -#define TK_VARIABLES 151 -#define TK_CLUSTER 152 -#define TK_BNODES 153 -#define TK_SNODES 154 -#define TK_TRANSACTIONS 155 -#define TK_DISTRIBUTED 156 -#define TK_CONSUMERS 157 -#define TK_SUBSCRIPTIONS 158 -#define TK_VNODES 159 -#define TK_LIKE 160 -#define TK_TBNAME 161 -#define TK_QTAGS 162 -#define TK_AS 163 -#define TK_INDEX 164 -#define TK_FUNCTION 165 -#define TK_INTERVAL 166 -#define TK_TOPIC 167 -#define TK_WITH 168 -#define TK_META 169 -#define TK_CONSUMER 170 -#define TK_GROUP 171 -#define TK_DESC 172 -#define TK_DESCRIBE 173 -#define TK_RESET 174 -#define TK_QUERY 175 -#define TK_CACHE 176 -#define TK_EXPLAIN 177 -#define TK_ANALYZE 178 -#define TK_VERBOSE 179 -#define TK_NK_BOOL 180 -#define TK_RATIO 181 -#define TK_NK_FLOAT 182 -#define TK_OUTPUTTYPE 183 -#define TK_AGGREGATE 184 -#define TK_BUFSIZE 185 -#define TK_STREAM 186 -#define TK_INTO 187 -#define TK_TRIGGER 188 -#define TK_AT_ONCE 189 -#define TK_WINDOW_CLOSE 190 -#define TK_IGNORE 191 -#define TK_EXPIRED 192 -#define TK_FILL_HISTORY 193 -#define TK_UPDATE 194 -#define TK_SUBTABLE 195 -#define TK_KILL 196 -#define TK_CONNECTION 197 -#define TK_TRANSACTION 198 -#define TK_BALANCE 199 -#define TK_VGROUP 200 -#define TK_MERGE 201 -#define TK_REDISTRIBUTE 202 -#define TK_SPLIT 203 -#define TK_DELETE 204 -#define TK_INSERT 205 -#define TK_NULL 206 -#define TK_NK_QUESTION 207 -#define TK_NK_ARROW 208 -#define TK_ROWTS 209 -#define TK_QSTART 210 -#define TK_QEND 211 -#define TK_QDURATION 212 -#define TK_WSTART 213 -#define TK_WEND 214 -#define TK_WDURATION 215 -#define TK_IROWTS 216 -#define TK_CAST 217 -#define TK_NOW 218 -#define TK_TODAY 219 -#define TK_TIMEZONE 220 -#define TK_CLIENT_VERSION 221 -#define TK_SERVER_VERSION 222 -#define TK_SERVER_STATUS 223 -#define TK_CURRENT_USER 224 -#define TK_COUNT 225 -#define TK_LAST_ROW 226 -#define TK_CASE 227 -#define TK_END 228 -#define TK_WHEN 229 -#define TK_THEN 230 -#define TK_ELSE 231 -#define TK_BETWEEN 232 -#define TK_IS 233 -#define TK_NK_LT 234 -#define TK_NK_GT 235 -#define TK_NK_LE 236 -#define TK_NK_GE 237 -#define TK_NK_NE 238 -#define TK_MATCH 239 -#define TK_NMATCH 240 -#define TK_CONTAINS 241 -#define TK_IN 242 -#define TK_JOIN 243 -#define TK_INNER 244 -#define TK_SELECT 245 -#define TK_DISTINCT 246 -#define TK_WHERE 247 -#define TK_PARTITION 248 -#define TK_BY 249 -#define TK_SESSION 250 -#define TK_STATE_WINDOW 251 -#define TK_SLIDING 252 -#define TK_FILL 253 -#define TK_VALUE 254 -#define TK_VALUE_F 255 -#define TK_NONE 256 -#define TK_PREV 257 -#define TK_NULL_F 258 -#define TK_LINEAR 259 -#define TK_NEXT 260 -#define TK_HAVING 261 -#define TK_RANGE 262 -#define TK_EVERY 263 -#define TK_ORDER 264 -#define TK_SLIMIT 265 -#define TK_SOFFSET 266 -#define TK_LIMIT 267 -#define TK_OFFSET 268 -#define TK_ASC 269 -#define TK_NULLS 270 -#define TK_ABORT 271 -#define TK_AFTER 272 -#define TK_ATTACH 273 -#define TK_BEFORE 274 -#define TK_BEGIN 275 -#define TK_BITAND 276 -#define TK_BITNOT 277 -#define TK_BITOR 278 -#define TK_BLOCKS 279 -#define TK_CHANGE 280 -#define TK_COMMA 281 -#define TK_COMPACT 282 -#define TK_CONCAT 283 -#define TK_CONFLICT 284 -#define TK_COPY 285 -#define TK_DEFERRED 286 -#define TK_DELIMITERS 287 -#define TK_DETACH 288 -#define TK_DIVIDE 289 -#define TK_DOT 290 -#define TK_EACH 291 -#define TK_FAIL 292 -#define TK_FILE 293 -#define TK_FOR 294 -#define TK_GLOB 295 -#define TK_ID 296 -#define TK_IMMEDIATE 297 -#define TK_IMPORT 298 -#define TK_INITIALLY 299 -#define TK_INSTEAD 300 -#define TK_ISNULL 301 -#define TK_KEY 302 -#define TK_MODULES 303 -#define TK_NK_BITNOT 304 -#define TK_NK_SEMI 305 -#define TK_NOTNULL 306 -#define TK_OF 307 -#define TK_PLUS 308 -#define TK_PRIVILEGE 309 -#define TK_RAISE 310 -#define TK_REPLACE 311 -#define TK_RESTRICT 312 -#define TK_ROW 313 -#define TK_SEMI 314 -#define TK_STAR 315 -#define TK_STATEMENT 316 -#define TK_STRICT 317 -#define TK_STRING 318 -#define TK_TIMES 319 -#define TK_VALUES 320 -#define TK_VARIABLE 321 -#define TK_VIEW 322 -#define TK_WAL 323 +#define TK_OR 1 +#define TK_AND 2 +#define TK_UNION 3 +#define TK_ALL 4 +#define TK_MINUS 5 +#define TK_EXCEPT 6 +#define TK_INTERSECT 7 +#define TK_NK_BITAND 8 +#define TK_NK_BITOR 9 +#define TK_NK_LSHIFT 10 +#define TK_NK_RSHIFT 11 +#define TK_NK_PLUS 12 +#define TK_NK_MINUS 13 +#define TK_NK_STAR 14 +#define TK_NK_SLASH 15 +#define TK_NK_REM 16 +#define TK_NK_CONCAT 17 +#define TK_CREATE 18 +#define TK_ACCOUNT 19 +#define TK_NK_ID 20 +#define TK_PASS 21 +#define TK_NK_STRING 22 +#define TK_ALTER 23 +#define TK_PPS 24 +#define TK_TSERIES 25 +#define TK_STORAGE 26 +#define TK_STREAMS 27 +#define TK_QTIME 28 +#define TK_DBS 29 +#define TK_USERS 30 +#define TK_CONNS 31 +#define TK_STATE 32 +#define TK_USER 33 +#define TK_ENABLE 34 +#define TK_NK_INTEGER 35 +#define TK_SYSINFO 36 +#define TK_DROP 37 +#define TK_GRANT 38 +#define TK_ON 39 +#define TK_TO 40 +#define TK_REVOKE 41 +#define TK_FROM 42 +#define TK_SUBSCRIBE 43 +#define TK_NK_COMMA 44 +#define TK_READ 45 +#define TK_WRITE 46 +#define TK_NK_DOT 47 +#define TK_WITH 48 +#define TK_DNODE 49 +#define TK_PORT 50 +#define TK_DNODES 51 +#define TK_NK_IPTOKEN 52 +#define TK_FORCE 53 +#define TK_LOCAL 54 +#define TK_QNODE 55 +#define TK_BNODE 56 +#define TK_SNODE 57 +#define TK_MNODE 58 +#define TK_DATABASE 59 +#define TK_USE 60 +#define TK_FLUSH 61 +#define TK_TRIM 62 +#define TK_COMPACT 63 +#define TK_IF 64 +#define TK_NOT 65 +#define TK_EXISTS 66 +#define TK_BUFFER 67 +#define TK_CACHEMODEL 68 +#define TK_CACHESIZE 69 +#define TK_COMP 70 +#define TK_DURATION 71 +#define TK_NK_VARIABLE 72 +#define TK_MAXROWS 73 +#define TK_MINROWS 74 +#define TK_KEEP 75 +#define TK_PAGES 76 +#define TK_PAGESIZE 77 +#define TK_TSDB_PAGESIZE 78 +#define TK_PRECISION 79 +#define TK_REPLICA 80 +#define TK_VGROUPS 81 +#define TK_SINGLE_STABLE 82 +#define TK_RETENTIONS 83 +#define TK_SCHEMALESS 84 +#define TK_WAL_LEVEL 85 +#define TK_WAL_FSYNC_PERIOD 86 +#define TK_WAL_RETENTION_PERIOD 87 +#define TK_WAL_RETENTION_SIZE 88 +#define TK_WAL_ROLL_PERIOD 89 +#define TK_WAL_SEGMENT_SIZE 90 +#define TK_STT_TRIGGER 91 +#define TK_TABLE_PREFIX 92 +#define TK_TABLE_SUFFIX 93 +#define TK_NK_COLON 94 +#define TK_MAX_SPEED 95 +#define TK_START 96 +#define TK_TIMESTAMP 97 +#define TK_END 98 +#define TK_TABLE 99 +#define TK_NK_LP 100 +#define TK_NK_RP 101 +#define TK_STABLE 102 +#define TK_ADD 103 +#define TK_COLUMN 104 +#define TK_MODIFY 105 +#define TK_RENAME 106 +#define TK_TAG 107 +#define TK_SET 108 +#define TK_NK_EQ 109 +#define TK_USING 110 +#define TK_TAGS 111 +#define TK_BOOL 112 +#define TK_TINYINT 113 +#define TK_SMALLINT 114 +#define TK_INT 115 +#define TK_INTEGER 116 +#define TK_BIGINT 117 +#define TK_FLOAT 118 +#define TK_DOUBLE 119 +#define TK_BINARY 120 +#define TK_NCHAR 121 +#define TK_UNSIGNED 122 +#define TK_JSON 123 +#define TK_VARCHAR 124 +#define TK_MEDIUMBLOB 125 +#define TK_BLOB 126 +#define TK_VARBINARY 127 +#define TK_DECIMAL 128 +#define TK_COMMENT 129 +#define TK_MAX_DELAY 130 +#define TK_WATERMARK 131 +#define TK_ROLLUP 132 +#define TK_TTL 133 +#define TK_SMA 134 +#define TK_DELETE_MARK 135 +#define TK_FIRST 136 +#define TK_LAST 137 +#define TK_SHOW 138 +#define TK_PRIVILEGES 139 +#define TK_DATABASES 140 +#define TK_TABLES 141 +#define TK_STABLES 142 +#define TK_MNODES 143 +#define TK_QNODES 144 +#define TK_FUNCTIONS 145 +#define TK_INDEXES 146 +#define TK_ACCOUNTS 147 +#define TK_APPS 148 +#define TK_CONNECTIONS 149 +#define TK_LICENCES 150 +#define TK_GRANTS 151 +#define TK_QUERIES 152 +#define TK_SCORES 153 +#define TK_TOPICS 154 +#define TK_VARIABLES 155 +#define TK_CLUSTER 156 +#define TK_BNODES 157 +#define TK_SNODES 158 +#define TK_TRANSACTIONS 159 +#define TK_DISTRIBUTED 160 +#define TK_CONSUMERS 161 +#define TK_SUBSCRIPTIONS 162 +#define TK_VNODES 163 +#define TK_ALIVE 164 +#define TK_LIKE 165 +#define TK_TBNAME 166 +#define TK_QTAGS 167 +#define TK_AS 168 +#define TK_INDEX 169 +#define TK_FUNCTION 170 +#define TK_INTERVAL 171 +#define TK_COUNT 172 +#define TK_LAST_ROW 173 +#define TK_TOPIC 174 +#define TK_META 175 +#define TK_CONSUMER 176 +#define TK_GROUP 177 +#define TK_DESC 178 +#define TK_DESCRIBE 179 +#define TK_RESET 180 +#define TK_QUERY 181 +#define TK_CACHE 182 +#define TK_EXPLAIN 183 +#define TK_ANALYZE 184 +#define TK_VERBOSE 185 +#define TK_NK_BOOL 186 +#define TK_RATIO 187 +#define TK_NK_FLOAT 188 +#define TK_OUTPUTTYPE 189 +#define TK_AGGREGATE 190 +#define TK_BUFSIZE 191 +#define TK_LANGUAGE 192 +#define TK_REPLACE 193 +#define TK_STREAM 194 +#define TK_INTO 195 +#define TK_TRIGGER 196 +#define TK_AT_ONCE 197 +#define TK_WINDOW_CLOSE 198 +#define TK_IGNORE 199 +#define TK_EXPIRED 200 +#define TK_FILL_HISTORY 201 +#define TK_UPDATE 202 +#define TK_SUBTABLE 203 +#define TK_KILL 204 +#define TK_CONNECTION 205 +#define TK_TRANSACTION 206 +#define TK_BALANCE 207 +#define TK_VGROUP 208 +#define TK_LEADER 209 +#define TK_MERGE 210 +#define TK_REDISTRIBUTE 211 +#define TK_SPLIT 212 +#define TK_DELETE 213 +#define TK_INSERT 214 +#define TK_NULL 215 +#define TK_NK_QUESTION 216 +#define TK_NK_ARROW 217 +#define TK_ROWTS 218 +#define TK_QSTART 219 +#define TK_QEND 220 +#define TK_QDURATION 221 +#define TK_WSTART 222 +#define TK_WEND 223 +#define TK_WDURATION 224 +#define TK_IROWTS 225 +#define TK_ISFILLED 226 +#define TK_CAST 227 +#define TK_NOW 228 +#define TK_TODAY 229 +#define TK_TIMEZONE 230 +#define TK_CLIENT_VERSION 231 +#define TK_SERVER_VERSION 232 +#define TK_SERVER_STATUS 233 +#define TK_CURRENT_USER 234 +#define TK_CASE 235 +#define TK_WHEN 236 +#define TK_THEN 237 +#define TK_ELSE 238 +#define TK_BETWEEN 239 +#define TK_IS 240 +#define TK_NK_LT 241 +#define TK_NK_GT 242 +#define TK_NK_LE 243 +#define TK_NK_GE 244 +#define TK_NK_NE 245 +#define TK_MATCH 246 +#define TK_NMATCH 247 +#define TK_CONTAINS 248 +#define TK_IN 249 +#define TK_JOIN 250 +#define TK_INNER 251 +#define TK_SELECT 252 +#define TK_DISTINCT 253 +#define TK_WHERE 254 +#define TK_PARTITION 255 +#define TK_BY 256 +#define TK_SESSION 257 +#define TK_STATE_WINDOW 258 +#define TK_EVENT_WINDOW 259 +#define TK_SLIDING 260 +#define TK_FILL 261 +#define TK_VALUE 262 +#define TK_VALUE_F 263 +#define TK_NONE 264 +#define TK_PREV 265 +#define TK_NULL_F 266 +#define TK_LINEAR 267 +#define TK_NEXT 268 +#define TK_HAVING 269 +#define TK_RANGE 270 +#define TK_EVERY 271 +#define TK_ORDER 272 +#define TK_SLIMIT 273 +#define TK_SOFFSET 274 +#define TK_LIMIT 275 +#define TK_OFFSET 276 +#define TK_ASC 277 +#define TK_NULLS 278 +#define TK_ABORT 279 +#define TK_AFTER 280 +#define TK_ATTACH 281 +#define TK_BEFORE 282 +#define TK_BEGIN 283 +#define TK_BITAND 284 +#define TK_BITNOT 285 +#define TK_BITOR 286 +#define TK_BLOCKS 287 +#define TK_CHANGE 288 +#define TK_COMMA 289 +#define TK_CONCAT 290 +#define TK_CONFLICT 291 +#define TK_COPY 292 +#define TK_DEFERRED 293 +#define TK_DELIMITERS 294 +#define TK_DETACH 295 +#define TK_DIVIDE 296 +#define TK_DOT 297 +#define TK_EACH 298 +#define TK_FAIL 299 +#define TK_FILE 300 +#define TK_FOR 301 +#define TK_GLOB 302 +#define TK_ID 303 +#define TK_IMMEDIATE 304 +#define TK_IMPORT 305 +#define TK_INITIALLY 306 +#define TK_INSTEAD 307 +#define TK_ISNULL 308 +#define TK_KEY 309 +#define TK_MODULES 310 +#define TK_NK_BITNOT 311 +#define TK_NK_SEMI 312 +#define TK_NOTNULL 313 +#define TK_OF 314 +#define TK_PLUS 315 +#define TK_PRIVILEGE 316 +#define TK_RAISE 317 +#define TK_RESTRICT 318 +#define TK_ROW 319 +#define TK_SEMI 320 +#define TK_STAR 321 +#define TK_STATEMENT 322 +#define TK_STRICT 323 +#define TK_STRING 324 +#define TK_TIMES 325 +#define TK_VALUES 326 +#define TK_VARIABLE 327 +#define TK_VIEW 328 +#define TK_WAL 329 + #define TK_NK_SPACE 600 #define TK_NK_COMMENT 601 diff --git a/include/common/ttypes.h b/include/common/ttypes.h index b7061300c1760c0b557562924caa329080779bda..f8a85ee1b0a86e268046f813ccb1721d97c3c029 100644 --- a/include/common/ttypes.h +++ b/include/common/ttypes.h @@ -53,10 +53,6 @@ typedef struct { #define varDataNetLen(v) (htons(((VarDataLenT *)(v))[0])) #define varDataNetTLen(v) (sizeof(VarDataLenT) + varDataNetLen(v)) -// this data type is internally used only in 'in' query to hold the values -#define TSDB_DATA_TYPE_POINTER_ARRAY (1000) -#define TSDB_DATA_TYPE_VALUE_ARRAY (1001) - #define GET_TYPED_DATA(_v, _finalType, _type, _data) \ do { \ switch (_type) { \ @@ -266,6 +262,7 @@ typedef struct { #define IS_FLOAT_TYPE(_t) ((_t) == TSDB_DATA_TYPE_FLOAT || (_t) == TSDB_DATA_TYPE_DOUBLE) #define IS_INTEGER_TYPE(_t) ((IS_SIGNED_NUMERIC_TYPE(_t)) || (IS_UNSIGNED_NUMERIC_TYPE(_t))) #define IS_TIMESTAMP_TYPE(_t) ((_t) == TSDB_DATA_TYPE_TIMESTAMP) +#define IS_BOOLEAN_TYPE(_t) ((_t) == TSDB_DATA_TYPE_BOOL) #define IS_NUMERIC_TYPE(_t) ((IS_SIGNED_NUMERIC_TYPE(_t)) || (IS_UNSIGNED_NUMERIC_TYPE(_t)) || (IS_FLOAT_TYPE(_t))) #define IS_MATHABLE_TYPE(_t) \ diff --git a/include/libs/catalog/catalog.h b/include/libs/catalog/catalog.h index fbb24d28623d99932966e625d6499ebbc836ac0a..9250bda592599d387b2041de2dd448ffd6750bc9 100644 --- a/include/libs/catalog/catalog.h +++ b/include/libs/catalog/catalog.h @@ -29,6 +29,7 @@ extern "C" { #include "tmsg.h" #include "tname.h" #include "transport.h" +#include "nodes.h" typedef struct SCatalog SCatalog; @@ -49,10 +50,15 @@ typedef enum { typedef struct SUserAuthInfo { char user[TSDB_USER_LEN]; - char dbFName[TSDB_DB_FNAME_LEN]; + SName tbName; AUTH_TYPE type; } SUserAuthInfo; +typedef struct SUserAuthRes { + bool pass; + SNode* pCond; +} SUserAuthRes; + typedef struct SDbInfo { int32_t vgVer; int32_t tbNum; @@ -76,6 +82,7 @@ typedef struct SCatalogReq { SArray* pUser; // element is SUserAuthInfo SArray* pTableIndex; // element is SNAME SArray* pTableCfg; // element is SNAME + SArray* pTableTag; // element is SNAME bool qNodeRequired; // valid qnode bool dNodeRequired; // valid dnode bool svrVerRequired; @@ -96,9 +103,10 @@ typedef struct SMetaData { SArray* pTableIndex; // pRes = SArray* SArray* pUdfList; // pRes = SFuncInfo* SArray* pIndex; // pRes = SIndexInfo* - SArray* pUser; // pRes = bool* + SArray* pUser; // pRes = SUserAuthRes* SArray* pQnodeList; // pRes = SArray* SArray* pTableCfg; // pRes = STableCfg* + SArray* pTableTag; // pRes = SArray* SArray* pDnodeList; // pRes = SArray* SMetaRes* pSvrVer; // pRes = char* } SMetaData; @@ -116,18 +124,19 @@ typedef struct SSTableVersion { char stbName[TSDB_TABLE_NAME_LEN]; uint64_t dbId; uint64_t suid; - int16_t sversion; - int16_t tversion; + int32_t sversion; + int32_t tversion; int32_t smaVer; } SSTableVersion; -typedef struct SDbVgVersion { +typedef struct SDbCacheInfo { char dbFName[TSDB_DB_FNAME_LEN]; int64_t dbId; int32_t vgVersion; + int32_t cfgVersion; int32_t numOfTable; // unit is TSDB_TABLE_NUM_UNIT int64_t stateTs; -} SDbVgVersion; +} SDbCacheInfo; typedef struct STbSVersion { char* tbFName; @@ -140,7 +149,6 @@ typedef struct SUserAuthVersion { int32_t version; } SUserAuthVersion; -typedef SDbCfgRsp SDbCfgInfo; typedef SUserIndexRsp SIndexInfo; typedef void (*catalogCallback)(SMetaData* pResult, void* param, int32_t code); @@ -172,6 +180,8 @@ int32_t catalogGetDBVgInfo(SCatalog* pCtg, SRequestConnInfo* pConn, const char* int32_t catalogUpdateDBVgInfo(SCatalog* pCatalog, const char* dbName, uint64_t dbId, SDBVgInfo* dbInfo); +int32_t catalogUpdateDbCfg(SCatalog* pCtg, const char* dbFName, uint64_t dbId, SDbCfgInfo* cfgInfo); + int32_t catalogRemoveDB(SCatalog* pCatalog, const char* dbName, uint64_t dbId); int32_t catalogRemoveTableMeta(SCatalog* pCtg, SName* pTableName); @@ -296,7 +306,7 @@ int32_t catalogGetDnodeList(SCatalog* pCatalog, SRequestConnInfo* pConn, SArray* int32_t catalogGetExpiredSTables(SCatalog* pCatalog, SSTableVersion** stables, uint32_t* num); -int32_t catalogGetExpiredDBs(SCatalog* pCatalog, SDbVgVersion** dbs, uint32_t* num); +int32_t catalogGetExpiredDBs(SCatalog* pCatalog, SDbCacheInfo** dbs, uint32_t* num); int32_t catalogGetExpiredUsers(SCatalog* pCtg, SUserAuthVersion** users, uint32_t* num); @@ -306,17 +316,17 @@ int32_t catalogGetIndexMeta(SCatalog* pCtg, SRequestConnInfo* pConn, const char* int32_t catalogGetTableIndex(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName, SArray** pRes); +int32_t catalogGetTableTag(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName, SArray** pRes); + int32_t catalogRefreshGetTableCfg(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName, STableCfg** pCfg); int32_t catalogUpdateTableIndex(SCatalog* pCtg, STableIndexRsp* pRsp); int32_t catalogGetUdfInfo(SCatalog* pCtg, SRequestConnInfo* pConn, const char* funcName, SFuncInfo* pInfo); -int32_t catalogChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, const char* user, const char* dbFName, AUTH_TYPE type, - bool* pass); +int32_t catalogChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, SUserAuthInfo *pAuth, SUserAuthRes* pRes); -int32_t catalogChkAuthFromCache(SCatalog* pCtg, const char* user, const char* dbFName, AUTH_TYPE type, bool* pass, - bool* exists); +int32_t catalogChkAuthFromCache(SCatalog* pCtg, SUserAuthInfo *pAuth, SUserAuthRes* pRes, bool* exists); int32_t catalogUpdateUserAuthInfo(SCatalog* pCtg, SGetUserAuthRsp* pAuth); diff --git a/include/libs/command/command.h b/include/libs/command/command.h index b3339a417ba463212c3abc163b57519194953c10..a8b1a0902acac276080d905554a3773f68e66b1c 100644 --- a/include/libs/command/command.h +++ b/include/libs/command/command.h @@ -22,7 +22,7 @@ typedef struct SExplainCtx SExplainCtx; -int32_t qExecCommand(bool sysInfoUser, SNode *pStmt, SRetrieveTableRsp **pRsp); +int32_t qExecCommand(int64_t* pConnId, bool sysInfoUser, SNode *pStmt, SRetrieveTableRsp **pRsp); int32_t qExecStaticExplain(SQueryPlan *pDag, SRetrieveTableRsp **pRsp); int32_t qExecExplainBegin(SQueryPlan *pDag, SExplainCtx **pCtx, int64_t startTs); diff --git a/include/libs/executor/dataSinkMgt.h b/include/libs/executor/dataSinkMgt.h index ed7cbc812504ae09099abd79020c6b9d761d6674..ce7d038d42c8f37bec730111d6d26d946c47a168 100644 --- a/include/libs/executor/dataSinkMgt.h +++ b/include/libs/executor/dataSinkMgt.h @@ -29,7 +29,6 @@ extern "C" { #define DS_BUF_FULL 2 #define DS_BUF_EMPTY 3 -struct SDataSink; struct SSDataBlock; typedef struct SDeleterRes { diff --git a/include/libs/executor/executor.h b/include/libs/executor/executor.h index 382837951a3bf4df736f167667e6592a57e8c4c0..5fa39b6bb1145fed6d1316b1692dc901f0b5d698 100644 --- a/include/libs/executor/executor.h +++ b/include/libs/executor/executor.h @@ -26,6 +26,7 @@ extern "C" { typedef void* qTaskInfo_t; typedef void* DataSinkHandle; + struct SRpcMsg; struct SSubplan; @@ -67,9 +68,10 @@ typedef enum { * Create the exec task for stream mode * @param pMsg * @param SReadHandle + * @param vgId * @return */ -qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, SReadHandle* readers); +qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, SReadHandle* readers, int32_t vgId); /** * Create the exec task for queue mode @@ -77,9 +79,22 @@ qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, SReadHandle* readers); * @param SReadHandle * @return */ -qTaskInfo_t qCreateQueueExecTaskInfo(void* msg, SReadHandle* readers, int32_t* numOfCols, SSchemaWrapper** pSchema); +qTaskInfo_t qCreateQueueExecTaskInfo(void* msg, SReadHandle* pReaderHandle, int32_t vgId, int32_t* numOfCols, + uint64_t id); + +/** + * set the task Id, usually used by message queue process + * @param tinfo + * @param taskId + * @param queryId + */ +void qSetTaskId(qTaskInfo_t tinfo, uint64_t taskId, uint64_t queryId); int32_t qSetStreamOpOpen(qTaskInfo_t tinfo); + +// todo refactor +void qGetCheckpointVersion(qTaskInfo_t tinfo, int64_t* dataVer, int64_t* ckId); + /** * Set multiple input data blocks for the stream scan. * @param tinfo @@ -108,7 +123,7 @@ int32_t qSetSMAInput(qTaskInfo_t tinfo, const void* pBlocks, size_t numOfBlocks, * @param isAdd * @return */ -int32_t qUpdateQualifiedTableId(qTaskInfo_t tinfo, const SArray* tableIdList, bool isAdd); +int32_t qUpdateTableListForStreamScanner(qTaskInfo_t tinfo, const SArray* tableIdList, bool isAdd); /** * Create the exec task object according to task json @@ -140,7 +155,6 @@ int32_t qGetQueryTableSchemaVersion(qTaskInfo_t tinfo, char* dbName, char* table * @param handle * @return */ - int32_t qExecTaskOpt(qTaskInfo_t tinfo, SArray* pResList, uint64_t* useconds, bool* hasMore, SLocalFetch* pLocal); int32_t qExecTask(qTaskInfo_t tinfo, SSDataBlock** pBlock, uint64_t* useconds); @@ -154,6 +168,8 @@ void qCleanExecTaskBlockBuf(qTaskInfo_t tinfo); */ int32_t qAsyncKillTask(qTaskInfo_t tinfo, int32_t rspCode); +int32_t qKillTask(qTaskInfo_t tinfo, int32_t rspCode); + bool qTaskIsExecuting(qTaskInfo_t qinfo); /** @@ -162,14 +178,6 @@ bool qTaskIsExecuting(qTaskInfo_t qinfo); */ void qDestroyTask(qTaskInfo_t tinfo); -/** - * Extract the qualified table id list, and than pass them to the TSDB driver to load the required table data blocks. - * - * @param iter the table iterator to traverse all tables belongs to a super table, or an invert index - * @return - */ -int32_t qGetQualifiedTableIdList(void* pTableList, const char* tagCond, int32_t tagCondLen, SArray* pTableIdList); - void qProcessRspMsg(void* parent, struct SRpcMsg* pMsg, struct SEpSet* pEpSet); int32_t qGetExplainExecInfo(qTaskInfo_t tinfo, SArray* pExecInfoList /*,int32_t* resNum, SExplainExecInfo** pRes*/); @@ -190,18 +198,18 @@ STimeWindow getAlignQueryTimeWindow(const SInterval* pInterval, int64_t key); */ int32_t qGetStreamScanStatus(qTaskInfo_t tinfo, uint64_t* uid, int64_t* ts); -int32_t qStreamPrepareTsdbScan(qTaskInfo_t tinfo, uint64_t uid, int64_t ts); +SArray* qGetQueriedTableListInfo(qTaskInfo_t tinfo); + +void verifyOffset(void *pWalReader, STqOffsetVal* pOffset); int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subType); -int32_t qStreamScanMemData(qTaskInfo_t tinfo, const SSubmitReq* pReq); +void qStreamSetOpen(qTaskInfo_t tinfo); -int32_t qStreamExtractOffset(qTaskInfo_t tinfo, STqOffsetVal* pOffset); +void qStreamExtractOffset(qTaskInfo_t tinfo, STqOffsetVal* pOffset); SMqMetaRsp* qStreamExtractMetaMsg(qTaskInfo_t tinfo); -int64_t qStreamExtractPrepareUid(qTaskInfo_t tinfo); - const SSchemaWrapper* qExtractSchemaFromTask(qTaskInfo_t tinfo); const char* qExtractTbnameFromTask(qTaskInfo_t tinfo); @@ -210,14 +218,14 @@ void* qExtractReaderFromStreamScanner(void* scanner); int32_t qExtractStreamScanner(qTaskInfo_t tinfo, void** scanner); -int32_t qStreamInput(qTaskInfo_t tinfo, void* pItem); - int32_t qStreamSetParamForRecover(qTaskInfo_t tinfo); int32_t qStreamSourceRecoverStep1(qTaskInfo_t tinfo, int64_t ver); int32_t qStreamSourceRecoverStep2(qTaskInfo_t tinfo, int64_t ver); int32_t qStreamRecoverFinish(qTaskInfo_t tinfo); int32_t qStreamRestoreParam(qTaskInfo_t tinfo); bool qStreamRecoverScanFinished(qTaskInfo_t tinfo); +void qStreamCloseTsdbReader(void* task); +void resetTaskInfo(qTaskInfo_t tinfo); #ifdef __cplusplus } diff --git a/include/libs/function/function.h b/include/libs/function/function.h index c44ad12759aa636260a46befaeaa43ce0ed13872..aa5c78195aff3bcb2b685921228cf843a7ea1e9a 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -76,7 +76,7 @@ enum { enum { MAIN_SCAN = 0x0u, REVERSE_SCAN = 0x1u, // todo remove it - REPEAT_SCAN = 0x2u, // repeat scan belongs to the master scan + PRE_SCAN = 0x2u, // pre-scan belongs to the main scan and occurs before main scan }; typedef struct SPoint1 { @@ -112,7 +112,7 @@ typedef struct SResultDataInfo { typedef struct SInputColumnInfoData { int32_t totalRows; // total rows in current columnar data int32_t startRowIndex; // handle started row index - int32_t numOfRows; // the number of rows needs to be handled + int64_t numOfRows; // the number of rows needs to be handled int32_t numOfInputCols; // PTS is not included bool colDataSMAIsSet; // if agg is set or not SColumnInfoData *pPTS; // primary timestamp column diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h index 411c7d5e8b22640f4fd67651b3de8f7a86bb171e..f097a2b2df7765f9f9f3af69c53c00beafb9f49e 100644 --- a/include/libs/function/functionMgt.h +++ b/include/libs/function/functionMgt.h @@ -120,6 +120,7 @@ typedef enum EFunctionType { FUNCTION_TYPE_WEND, FUNCTION_TYPE_WDURATION, FUNCTION_TYPE_IROWTS, + FUNCTION_TYPE_ISFILLED, FUNCTION_TYPE_TAGS, // internal function @@ -188,7 +189,7 @@ bool fmIsScalarFunc(int32_t funcId); bool fmIsVectorFunc(int32_t funcId); bool fmIsIndefiniteRowsFunc(int32_t funcId); bool fmIsStringFunc(int32_t funcId); -bool fmIsDatetimeFunc(int32_t funcId); +bool fmIsDateTimeFunc(int32_t funcId); bool fmIsSelectFunc(int32_t funcId); bool fmIsTimelineFunc(int32_t funcId); bool fmIsTimeorderFunc(int32_t funcId); @@ -229,6 +230,7 @@ typedef enum EFuncDataRequired { FUNC_DATA_REQUIRED_SMA_LOAD, FUNC_DATA_REQUIRED_NOT_LOAD, FUNC_DATA_REQUIRED_FILTEROUT, + FUNC_DATA_REQUIRED_ALL_FILTEROUT, } EFuncDataRequired; EFuncDataRequired fmFuncDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow); @@ -240,6 +242,7 @@ int32_t fmGetUdafExecFuncs(int32_t funcId, SFuncExecFuncs* pFpSet); int32_t fmSetInvertFunc(int32_t funcId, SFuncExecFuncs* pFpSet); int32_t fmSetNormalFunc(int32_t funcId, SFuncExecFuncs* pFpSet); bool fmIsInvertible(int32_t funcId); +char* fmGetFuncName(int32_t funcId); #ifdef __cplusplus } diff --git a/include/libs/function/taosudf.h b/include/libs/function/taosudf.h index 1b1339340b1dc13d85740e953400ac6c0ee85f40..c825574fa6e3aea8936a3a9e5cd16224956a94a6 100644 --- a/include/libs/function/taosudf.h +++ b/include/libs/function/taosudf.h @@ -80,10 +80,6 @@ typedef struct SUdfInterBuf { } SUdfInterBuf; typedef void *UdfcFuncHandle; -// dynamic lib init and destroy -typedef int32_t (*TUdfInitFunc)(); -typedef int32_t (*TUdfDestroyFunc)(); - #define UDF_MEMORY_EXP_GROWTH 1.5 #define NBIT (3u) #define BitPos(_n) ((_n) & ((1 << NBIT) - 1)) @@ -153,6 +149,8 @@ static FORCE_INLINE int32_t udfColEnsureCapacity(SUdfColumn *pColumn, int32_t ne allocCapacity *= UDF_MEMORY_EXP_GROWTH; } + int32_t existedRows = data->numOfRows; + if (IS_VAR_DATA_TYPE(meta->type)) { char *tmp = (char *)realloc(data->varLenCol.varOffsets, sizeof(int32_t) * allocCapacity); if (tmp == NULL) { @@ -160,14 +158,20 @@ static FORCE_INLINE int32_t udfColEnsureCapacity(SUdfColumn *pColumn, int32_t ne } data->varLenCol.varOffsets = (int32_t *)tmp; data->varLenCol.varOffsetsLen = sizeof(int32_t) * allocCapacity; + memset(&data->varLenCol.varOffsets[existedRows], 0, sizeof(int32_t) * (allocCapacity - existedRows)); // for payload, add data in udfColDataAppend } else { char *tmp = (char *)realloc(data->fixLenCol.nullBitmap, BitmapLen(allocCapacity)); if (tmp == NULL) { return TSDB_CODE_OUT_OF_MEMORY; } + uint32_t extend = BitmapLen(allocCapacity) - BitmapLen(data->rowsAlloc); + memset(tmp + BitmapLen(data->rowsAlloc), 0, extend); data->fixLenCol.nullBitmap = tmp; data->fixLenCol.nullBitmapLen = BitmapLen(allocCapacity); + int32_t oldLen = BitmapLen(existedRows); + memset(&data->fixLenCol.nullBitmap[oldLen], 0, BitmapLen(allocCapacity) - oldLen); + if (meta->type == TSDB_DATA_TYPE_NULL) { return TSDB_CODE_SUCCESS; } @@ -194,6 +198,7 @@ static FORCE_INLINE void udfColDataSetNull(SUdfColumn *pColumn, int32_t row) { udfColDataSetNull_f(pColumn, row); } pColumn->hasNull = true; + pColumn->colData.numOfRows = ((int32_t)(row + 1) > pColumn->colData.numOfRows) ? (int32_t)(row + 1) : pColumn->colData.numOfRows; } static FORCE_INLINE int32_t udfColDataSet(SUdfColumn *pColumn, uint32_t currentRow, const char *pData, bool isNull) { @@ -252,6 +257,10 @@ static FORCE_INLINE int32_t udfColDataSet(SUdfColumn *pColumn, uint32_t currentR return 0; } +// dynamic lib init and destroy for C UDF +typedef int32_t (*TUdfInitFunc)(); +typedef int32_t (*TUdfDestroyFunc)(); + typedef int32_t (*TUdfScalarProcFunc)(SUdfDataBlock *block, SUdfColumn *resultCol); typedef int32_t (*TUdfAggStartFunc)(SUdfInterBuf *buf); @@ -259,6 +268,43 @@ typedef int32_t (*TUdfAggProcessFunc)(SUdfDataBlock *block, SUdfInterBuf *interB typedef int32_t (*TUdfAggMergeFunc)(SUdfInterBuf *inputBuf1, SUdfInterBuf *inputBuf2, SUdfInterBuf *outputBuf); typedef int32_t (*TUdfAggFinishFunc)(SUdfInterBuf *buf, SUdfInterBuf *resultData); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct SScriptUdfEnvItem { + const char *name; + const char *value; +} SScriptUdfEnvItem; + +typedef enum EUdfFuncType { UDF_FUNC_TYPE_SCALAR = 1, UDF_FUNC_TYPE_AGG = 2 } EUdfFuncType; + +typedef struct SScriptUdfInfo { + const char *name; + int32_t version; + int64_t createdTime; + + EUdfFuncType funcType; + int8_t scriptType; + int8_t outputType; + int32_t outputLen; + int32_t bufSize; + + const char *path; +} SScriptUdfInfo; + +typedef int32_t (*TScriptUdfScalarProcFunc)(SUdfDataBlock *block, SUdfColumn *resultCol, void *udfCtx); + +typedef int32_t (*TScriptUdfAggStartFunc)(SUdfInterBuf *buf, void *udfCtx); +typedef int32_t (*TScriptUdfAggProcessFunc)(SUdfDataBlock *block, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf, + void *udfCtx); +typedef int32_t (*TScriptUdfAggMergeFunc)(SUdfInterBuf *inputBuf1, SUdfInterBuf *inputBuf2, SUdfInterBuf *outputBuf, + void *udfCtx); +typedef int32_t (*TScriptUdfAggFinishFunc)(SUdfInterBuf *buf, SUdfInterBuf *resultData, void *udfCtx); +typedef int32_t (*TScriptUdfInitFunc)(SScriptUdfInfo *info, void **pUdfCtx); +typedef int32_t (*TScriptUdfDestoryFunc)(void *udfCtx); + +// the following function is for open/close script plugin. +typedef int32_t (*TScriptOpenFunc)(SScriptUdfEnvItem *items, int numItems); +typedef int32_t (*TScriptCloseFunc)(); + #ifdef __cplusplus } #endif diff --git a/include/libs/monitor/monitor.h b/include/libs/monitor/monitor.h index 3dee59ab14a0ac780f18f731a5abb6dbe559b6fd..607179c4464f157aca7d757403775b634b694d8b 100644 --- a/include/libs/monitor/monitor.h +++ b/include/libs/monitor/monitor.h @@ -116,6 +116,8 @@ typedef struct { int32_t vnodes_total; int32_t vnodes_alive; int32_t connections_total; + int32_t topics_toal; + int32_t streams_total; SArray *dnodes; // array of SMonDnodeDesc SArray *mnodes; // array of SMonMnodeDesc } SMonClusterInfo; @@ -147,9 +149,9 @@ typedef struct { } SMonStbInfo; typedef struct { - int32_t expire_time; - int64_t timeseries_used; - int64_t timeseries_total; + uint32_t expire_time; + int64_t timeseries_used; + int64_t timeseries_total; } SMonGrantInfo; typedef struct { diff --git a/include/libs/nodes/cmdnodes.h b/include/libs/nodes/cmdnodes.h index de2780691291fb2028e8f8a684f71195140a7d26..2323d044ec4d2c79dad571682026f62f09631588 100644 --- a/include/libs/nodes/cmdnodes.h +++ b/include/libs/nodes/cmdnodes.h @@ -40,14 +40,16 @@ extern "C" { #define SHOW_LOCAL_VARIABLES_RESULT_FIELD1_LEN (TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE) #define SHOW_LOCAL_VARIABLES_RESULT_FIELD2_LEN (TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE) -#define PRIVILEGE_TYPE_MASK(n) (1 << n) +#define SHOW_ALIVE_RESULT_COLS 1 -#define PRIVILEGE_TYPE_ALL PRIVILEGE_TYPE_MASK(0) -#define PRIVILEGE_TYPE_READ PRIVILEGE_TYPE_MASK(1) -#define PRIVILEGE_TYPE_WRITE PRIVILEGE_TYPE_MASK(2) -#define PRIVILEGE_TYPE_SUBSCRIBE PRIVILEGE_TYPE_MASK(3) +#define BIT_FLAG_MASK(n) (1 << n) +#define BIT_FLAG_SET_MASK(val, mask) ((val) |= (mask)) +#define BIT_FLAG_TEST_MASK(val, mask) (((val) & (mask)) != 0) -#define PRIVILEGE_TYPE_TEST_MASK(val, mask) (((val) & (mask)) != 0) +#define PRIVILEGE_TYPE_ALL BIT_FLAG_MASK(0) +#define PRIVILEGE_TYPE_READ BIT_FLAG_MASK(1) +#define PRIVILEGE_TYPE_WRITE BIT_FLAG_MASK(2) +#define PRIVILEGE_TYPE_SUBSCRIBE BIT_FLAG_MASK(3) typedef struct SDatabaseOptions { ENodeType type; @@ -123,6 +125,13 @@ typedef struct STrimDatabaseStmt { int32_t maxSpeed; } STrimDatabaseStmt; +typedef struct SCompactDatabaseStmt { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; + SNode* pStart; + SNode* pEnd; +} SCompactDatabaseStmt; + typedef struct STableOptions { ENodeType type; bool commentNull; @@ -171,10 +180,10 @@ typedef struct SCreateSubTableClause { STableOptions* pOptions; } SCreateSubTableClause; -typedef struct SCreateMultiTableStmt { +typedef struct SCreateMultiTablesStmt { ENodeType type; SNodeList* pSubTables; -} SCreateMultiTableStmt; +} SCreateMultiTablesStmt; typedef struct SDropTableClause { ENodeType type; @@ -209,14 +218,14 @@ typedef struct SAlterTableStmt { typedef struct SCreateUserStmt { ENodeType type; - char useName[TSDB_USER_LEN]; + char userName[TSDB_USER_LEN]; char password[TSDB_USET_PASSWORD_LEN]; int8_t sysinfo; } SCreateUserStmt; typedef struct SAlterUserStmt { ENodeType type; - char useName[TSDB_USER_LEN]; + char userName[TSDB_USER_LEN]; int8_t alterType; char password[TSDB_USET_PASSWORD_LEN]; int8_t enable; @@ -225,7 +234,7 @@ typedef struct SAlterUserStmt { typedef struct SDropUserStmt { ENodeType type; - char useName[TSDB_USER_LEN]; + char userName[TSDB_USER_LEN]; } SDropUserStmt; typedef struct SCreateDnodeStmt { @@ -259,9 +268,15 @@ typedef struct SShowStmt { typedef struct SShowCreateDatabaseStmt { ENodeType type; char dbName[TSDB_DB_NAME_LEN]; + char dbFName[TSDB_DB_FNAME_LEN]; void* pCfg; // SDbCfgInfo } SShowCreateDatabaseStmt; +typedef struct SShowAliveStmt { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; +} SShowAliveStmt; + typedef struct SShowCreateTableStmt { ENodeType type; char dbName[TSDB_DB_NAME_LEN]; @@ -295,7 +310,7 @@ typedef struct SShowTableTagsStmt { SNodeList* pTags; } SShowTableTagsStmt; -typedef enum EIndexType { INDEX_TYPE_SMA = 1, INDEX_TYPE_FULLTEXT } EIndexType; +typedef enum EIndexType { INDEX_TYPE_SMA = 1, INDEX_TYPE_FULLTEXT, INDEX_TYPE_NORMAL } EIndexType; typedef struct SIndexOptions { ENodeType type; @@ -381,6 +396,15 @@ typedef struct SKillQueryStmt { char queryId[TSDB_QUERY_ID_LEN]; } SKillQueryStmt; +typedef enum EStreamOptionsSetFlag { + SOPT_TRIGGER_TYPE_SET = BIT_FLAG_MASK(0), + SOPT_WATERMARK_SET = BIT_FLAG_MASK(1), + SOPT_DELETE_MARK_SET = BIT_FLAG_MASK(2), + SOPT_FILL_HISTORY_SET = BIT_FLAG_MASK(3), + SOPT_IGNORE_EXPIRED_SET = BIT_FLAG_MASK(4), + SOPT_IGNORE_UPDATE_SET = BIT_FLAG_MASK(5), +} EStreamOptionsSetFlag; + typedef struct SStreamOptions { ENodeType type; int8_t triggerType; @@ -390,6 +414,7 @@ typedef struct SStreamOptions { int8_t fillHistory; int8_t ignoreExpired; int8_t ignoreUpdate; + int64_t setFlag; } SStreamOptions; typedef struct SCreateStreamStmt { @@ -402,6 +427,7 @@ typedef struct SCreateStreamStmt { SNode* pQuery; SNodeList* pTags; SNode* pSubtable; + SNodeList* pCols; } SCreateStreamStmt; typedef struct SDropStreamStmt { @@ -412,12 +438,14 @@ typedef struct SDropStreamStmt { typedef struct SCreateFunctionStmt { ENodeType type; + bool orReplace; bool ignoreExists; char funcName[TSDB_FUNC_NAME_LEN]; bool isAgg; char libraryPath[PATH_MAX]; SDataType outputDt; int32_t bufSize; + int8_t language; } SCreateFunctionStmt; typedef struct SDropFunctionStmt { @@ -430,7 +458,9 @@ typedef struct SGrantStmt { ENodeType type; char userName[TSDB_USER_LEN]; char objName[TSDB_DB_NAME_LEN]; // db or topic + char tabName[TSDB_TABLE_NAME_LEN]; int64_t privileges; + SNode* pTagCond; } SGrantStmt; typedef SGrantStmt SRevokeStmt; @@ -439,6 +469,10 @@ typedef struct SBalanceVgroupStmt { ENodeType type; } SBalanceVgroupStmt; +typedef struct SBalanceVgroupLeaderStmt { + ENodeType type; +} SBalanceVgroupLeaderStmt; + typedef struct SMergeVgroupStmt { ENodeType type; int32_t vgId1; diff --git a/include/libs/nodes/nodes.h b/include/libs/nodes/nodes.h index 412054b13e3bdceec6234919040c4b99a43d6102..fd601bc3ba5c8415ac479c1d3c07c25c538ee905 100644 --- a/include/libs/nodes/nodes.h +++ b/include/libs/nodes/nodes.h @@ -112,11 +112,12 @@ typedef enum ENodeType { QUERY_NODE_COLUMN_REF, QUERY_NODE_WHEN_THEN, QUERY_NODE_CASE_WHEN, + QUERY_NODE_EVENT_WINDOW, // Statement nodes are used in parser and planner module. QUERY_NODE_SET_OPERATOR = 100, QUERY_NODE_SELECT_STMT, - QUERY_NODE_VNODE_MODIF_STMT, + QUERY_NODE_VNODE_MODIFY_STMT, QUERY_NODE_CREATE_DATABASE_STMT, QUERY_NODE_DROP_DATABASE_STMT, QUERY_NODE_ALTER_DATABASE_STMT, @@ -124,7 +125,7 @@ typedef enum ENodeType { QUERY_NODE_TRIM_DATABASE_STMT, QUERY_NODE_CREATE_TABLE_STMT, QUERY_NODE_CREATE_SUBTABLE_CLAUSE, - QUERY_NODE_CREATE_MULTI_TABLE_STMT, + QUERY_NODE_CREATE_MULTI_TABLES_STMT, QUERY_NODE_DROP_TABLE_CLAUSE, QUERY_NODE_DROP_TABLE_STMT, QUERY_NODE_DROP_SUPER_TABLE_STMT, @@ -154,7 +155,7 @@ typedef enum ENodeType { QUERY_NODE_EXPLAIN_STMT, QUERY_NODE_DESCRIBE_STMT, QUERY_NODE_RESET_QUERY_CACHE_STMT, - QUERY_NODE_COMPACT_STMT, + QUERY_NODE_COMPACT_DATABASE_STMT, QUERY_NODE_CREATE_FUNCTION_STMT, QUERY_NODE_DROP_FUNCTION_STMT, QUERY_NODE_CREATE_STREAM_STMT, @@ -207,6 +208,9 @@ typedef enum ENodeType { QUERY_NODE_DELETE_STMT, QUERY_NODE_INSERT_STMT, QUERY_NODE_QUERY, + QUERY_NODE_SHOW_DB_ALIVE_STMT, + QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT, + QUERY_NODE_BALANCE_VGROUP_LEADER_STMT, // logic plan node QUERY_NODE_LOGIC_PLAN_SCAN = 1000, @@ -265,7 +269,9 @@ typedef enum ENodeType { QUERY_NODE_PHYSICAL_PLAN_DELETE, QUERY_NODE_PHYSICAL_SUBPLAN, QUERY_NODE_PHYSICAL_PLAN, - QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN + QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN, + QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT, + QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT } ENodeType; /** @@ -301,6 +307,7 @@ void nodesDestroyAllocator(int64_t allocatorId); SNode* nodesMakeNode(ENodeType type); void nodesDestroyNode(SNode* pNode); +void nodesFree(void* p); SNodeList* nodesMakeList(); int32_t nodesListAppend(SNodeList* pList, SNode* pNode); diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index 80fa0d3e78211464b4a327a32c8c374ba66c4953..0e235191b136f6b374664c8cbfc546a45e6f838d 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -112,6 +112,7 @@ typedef struct SJoinLogicNode { SNode* pOnConditions; bool isSingleTableJoin; EOrder inputTsOrder; + SNode* pTagEqualConditions; } SJoinLogicNode; typedef struct SAggLogicNode { @@ -187,7 +188,12 @@ typedef struct SMergeLogicNode { bool groupSort; } SMergeLogicNode; -typedef enum EWindowType { WINDOW_TYPE_INTERVAL = 1, WINDOW_TYPE_SESSION, WINDOW_TYPE_STATE } EWindowType; +typedef enum EWindowType { + WINDOW_TYPE_INTERVAL = 1, + WINDOW_TYPE_SESSION, + WINDOW_TYPE_STATE, + WINDOW_TYPE_EVENT +} EWindowType; typedef enum EWindowAlgorithm { INTERVAL_ALGO_HASH = 1, @@ -214,6 +220,8 @@ typedef struct SWindowLogicNode { SNode* pTspk; SNode* pTsEnd; SNode* pStateExpr; + SNode* pStartCond; + SNode* pEndCond; int8_t triggerType; int64_t watermark; int64_t deleteMark; @@ -398,6 +406,7 @@ typedef struct SSortMergeJoinPhysiNode { SNode* pOnConditions; SNodeList* pTargets; EOrder inputTsOrder; + SNode* pTagEqualCondtions; } SSortMergeJoinPhysiNode; typedef struct SAggPhysiNode { @@ -503,6 +512,14 @@ typedef struct SStateWinodwPhysiNode { typedef SStateWinodwPhysiNode SStreamStateWinodwPhysiNode; +typedef struct SEventWinodwPhysiNode { + SWinodwPhysiNode window; + SNode* pStartCond; + SNode* pEndCond; +} SEventWinodwPhysiNode; + +typedef SEventWinodwPhysiNode SStreamEventWinodwPhysiNode; + typedef struct SSortPhysiNode { SPhysiNode node; SNodeList* pExprs; // these are expression list of order_by_clause and parameter expression of aggregate function @@ -550,6 +567,7 @@ typedef struct SQueryInserterNode { char tableName[TSDB_TABLE_NAME_LEN]; int32_t vgId; SEpSet epSet; + bool explain; } SQueryInserterNode; typedef struct SDataDeleterNode { diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index e291051351b433e92ee0271166a581f08fb4abfe..9569cfe055fee6c715b3dc921518cc15feb439ad 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -223,6 +223,13 @@ typedef struct SIntervalWindowNode { SNode* pFill; } SIntervalWindowNode; +typedef struct SEventWindowNode { + ENodeType type; // QUERY_NODE_EVENT_WINDOW + SNode* pCol; // timestamp primary key + SNode* pStartCond; + SNode* pEndCond; +} SEventWindowNode; + typedef enum EFillMode { FILL_MODE_NONE = 1, FILL_MODE_VALUE, @@ -291,6 +298,7 @@ typedef struct SSelectStmt { bool hasUniqueFunc; bool hasTailFunc; bool hasInterpFunc; + bool hasInterpPseudoColFunc; bool hasLastRowFunc; bool hasLastFunc; bool hasTimeLineFunc; @@ -356,34 +364,36 @@ typedef struct SVgDataBlocks { void* pData; // SSubmitReq + SSubmitBlk + ... } SVgDataBlocks; -typedef void (*FFreeDataBlockHash)(SHashObj*); -typedef void (*FFreeDataBlockArray)(SArray*); - -typedef struct SVnodeModifOpStmt { - ENodeType nodeType; - ENodeType sqlNodeType; - SArray* pDataBlocks; // data block for each vgroup, SArray. - uint32_t insertType; // insert data from [file|sql statement| bound statement] - const char* pSql; // current sql statement position - int32_t totalRowsNum; - int32_t totalTbNum; - SName targetTableName; - SName usingTableName; - const char* pBoundCols; - struct STableMeta* pTableMeta; - SHashObj* pVgroupsHashObj; - SHashObj* pTableBlockHashObj; - SHashObj* pSubTableHashObj; - SHashObj* pTableNameHashObj; - SHashObj* pDbFNameHashObj; - SArray* pVgDataBlocks; - SVCreateTbReq createTblReq; - TdFilePtr fp; - FFreeDataBlockHash freeHashFunc; - FFreeDataBlockArray freeArrayFunc; - bool usingTableProcessing; - bool fileProcessing; -} SVnodeModifOpStmt; +typedef void (*FFreeTableBlockHash)(SHashObj*); +typedef void (*FFreeVgourpBlockArray)(SArray*); + +typedef struct SVnodeModifyOpStmt { + ENodeType nodeType; + ENodeType sqlNodeType; + SArray* pDataBlocks; // data block for each vgroup, SArray. + uint32_t insertType; // insert data from [file|sql statement| bound statement] + const char* pSql; // current sql statement position + int32_t totalRowsNum; + int32_t totalTbNum; + SName targetTableName; + SName usingTableName; + const char* pBoundCols; + struct STableMeta* pTableMeta; + SNode* pTagCond; + SArray* pTableTag; + SHashObj* pVgroupsHashObj; + SHashObj* pTableBlockHashObj; // SHashObj + SHashObj* pSubTableHashObj; + SHashObj* pTableNameHashObj; + SHashObj* pDbFNameHashObj; + SArray* pVgDataBlocks; // SArray + SVCreateTbReq* pCreateTblReq; + TdFilePtr fp; + FFreeTableBlockHash freeHashFunc; + FFreeVgourpBlockArray freeArrayFunc; + bool usingTableProcessing; + bool fileProcessing; +} SVnodeModifyOpStmt; typedef struct SExplainOptions { ENodeType type; diff --git a/include/libs/parser/parser.h b/include/libs/parser/parser.h index 52edd9708ca505e0bdb9be177da3f2f60b2a03a8..558203052f1e7241f1b315bb87e8710b5526db63 100644 --- a/include/libs/parser/parser.h +++ b/include/libs/parser/parser.h @@ -58,7 +58,6 @@ typedef struct SParseContext { bool isSuperUser; bool enableSysInfo; bool async; - int8_t schemalessType; const char* svrVer; bool nodeOffline; SArray* pTableMetaPos; // sql table pos => catalog data pos @@ -85,12 +84,13 @@ int32_t qSetSTableIdForRsma(SNode* pStmt, int64_t uid); void qCleanupKeywordsTable(); int32_t qBuildStmtOutput(SQuery* pQuery, SHashObj* pVgHash, SHashObj* pBlockHash); -int32_t qResetStmtDataBlock(void* block, bool keepBuf); -int32_t qCloneStmtDataBlock(void** pDst, void* pSrc); -void qFreeStmtDataBlock(void* pDataBlock); -int32_t qRebuildStmtDataBlock(void** pDst, void* pSrc, uint64_t uid, int32_t vgId); -void qDestroyStmtDataBlock(void* pBlock); -STableMeta* qGetTableMetaInDataBlock(void* pDataBlock); +int32_t qResetStmtDataBlock(STableDataCxt* block, bool keepBuf); +int32_t qCloneStmtDataBlock(STableDataCxt** pDst, STableDataCxt* pSrc, bool reset); +int32_t qRebuildStmtDataBlock(STableDataCxt** pDst, STableDataCxt* pSrc, uint64_t uid, uint64_t suid, int32_t vgId, + bool rebuildCreateTb); +void qDestroyStmtDataBlock(STableDataCxt* pBlock); +STableMeta* qGetTableMetaInDataBlock(STableDataCxt* pDataBlock); +int32_t qCloneCurrentTbData(STableDataCxt* pDataBlock, SSubmitTbData** pData); int32_t qStmtBindParams(SQuery* pQuery, TAOS_MULTI_BIND* pParams, int32_t colIdx); int32_t qStmtParseQuerySql(SParseContext* pCxt, SQuery* pQuery); @@ -105,12 +105,18 @@ void destroyBoundColumnInfo(void* pBoundInfo); int32_t qCreateSName(SName* pName, const char* pTableName, int32_t acctId, char* dbName, char* msgBuf, int32_t msgBufLen); -void* smlInitHandle(SQuery* pQuery); -void smlDestroyHandle(void* pHandle); -int32_t smlBindData(void* handle, SArray* tags, SArray* colsSchema, SArray* cols, bool format, STableMeta* pTableMeta, - char* tableName, const char* sTableName, int32_t sTableNameLen, int32_t ttl, char* msgBuf, - int16_t msgBufLen); -int32_t smlBuildOutput(void* handle, SHashObj* pVgHash); +void qDestroyBoundColInfo(void* pInfo); + +SQuery* smlInitHandle(); +int32_t smlBuildRow(STableDataCxt* pTableCxt); +int32_t smlBuildCol(STableDataCxt* pTableCxt, SSchema* schema, void* kv, int32_t index); +STableDataCxt* smlInitTableDataCtx(SQuery* query, STableMeta* pTableMeta); + +int32_t smlBindData(SQuery* handle, bool dataFormat, SArray* tags, SArray* colsSchema, SArray* cols, + STableMeta* pTableMeta, char* tableName, const char* sTableName, int32_t sTableNameLen, int32_t ttl, + char* msgBuf, int16_t msgBufLen); +int32_t smlBuildOutput(SQuery* handle, SHashObj* pVgHash); +int rawBlockBindData(SQuery *query, STableMeta* pTableMeta, void* data, SVCreateTbReq* pCreateTb, TAOS_FIELD *fields, int numFields, bool needChangeLength); int32_t rewriteToVnodeModifyOpStmt(SQuery* pQuery, SArray* pBufArray); SArray* serializeVgroupsCreateTableBatch(SHashObj* pVgroupHashmap); diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h index 5b640dce92052f1aef246f599c3f686a089c2ec7..69aa315ec2f8ece539231f64fcdb0cd62ea6da6d 100644 --- a/include/libs/qcom/query.h +++ b/include/libs/qcom/query.h @@ -26,12 +26,14 @@ extern "C" { #include "tlog.h" #include "tmsg.h" #include "tmsgcb.h" +#include "systable.h" typedef enum { JOB_TASK_STATUS_NULL = 0, JOB_TASK_STATUS_INIT, JOB_TASK_STATUS_EXEC, JOB_TASK_STATUS_PART_SUCC, + JOB_TASK_STATUS_FETCH, JOB_TASK_STATUS_SUCC, JOB_TASK_STATUS_FAIL, JOB_TASK_STATUS_DROP, @@ -114,8 +116,8 @@ typedef struct STableMeta { // if the table is TSDB_CHILD_TABLE, the following information is acquired from the corresponding super table meta // info - int16_t sversion; - int16_t tversion; + int32_t sversion; + int32_t tversion; STableComInfo tableInfo; SSchema schema[]; } STableMeta; @@ -163,6 +165,23 @@ typedef struct STargetInfo { int32_t vgId; } STargetInfo; +typedef struct SBoundColInfo { + int16_t* pColIndex; // bound index => schema index + int32_t numOfCols; + int32_t numOfBound; +} SBoundColInfo; + +typedef struct STableDataCxt { + STableMeta* pMeta; + STSchema* pSchema; + SBoundColInfo boundColsInfo; + SArray* pValues; + SSubmitTbData* pData; + TSKEY lastTs; + bool ordered; + bool duplicateTs; +} STableDataCxt; + typedef int32_t (*__async_send_cb_fn_t)(void* param, SDataBuf* pMsg, int32_t code); typedef int32_t (*__async_exec_fn_t)(void* param); @@ -175,6 +194,7 @@ typedef struct SRequestConnInfo { typedef void (*__freeFunc)(void* param); +// todo add creator/destroyer function typedef struct SMsgSendInfo { __async_send_cb_fn_t fp; // async callback function STargetInfo target; // for update epset @@ -238,7 +258,9 @@ int32_t dataConverToStr(char* str, int type, void* buf, int32_t bufSize, int32_t char* parseTagDatatoJson(void* p); int32_t cloneTableMeta(STableMeta* pSrc, STableMeta** pDst); int32_t cloneDbVgInfo(SDBVgInfo* pSrc, SDBVgInfo** pDst); +int32_t cloneSVreateTbReq(SVCreateTbReq* pSrc, SVCreateTbReq** pDst); void freeVgInfo(SDBVgInfo* vgInfo); +void freeDbCfgInfo(SDbCfgInfo *pInfo); extern int32_t (*queryBuildMsg[TDMT_MAX])(void* input, char** msg, int32_t msgSize, int32_t* msgLen, void* (*mallocFp)(int64_t)); @@ -284,9 +306,10 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t #define REQUEST_TOTAL_EXEC_TIMES 2 -#define IS_SYS_DBNAME(_dbname) \ - (((*(_dbname) == 'i') && (0 == strcmp(_dbname, TSDB_INFORMATION_SCHEMA_DB))) || \ - ((*(_dbname) == 'p') && (0 == strcmp(_dbname, TSDB_PERFORMANCE_SCHEMA_DB)))) +#define IS_INFORMATION_SCHEMA_DB(_name) ((*(_name) == 'i') && (0 == strcmp(_name, TSDB_INFORMATION_SCHEMA_DB))) +#define IS_PERFORMANCE_SCHEMA_DB(_name) ((*(_name) == 'p') && (0 == strcmp(_name, TSDB_PERFORMANCE_SCHEMA_DB))) + +#define IS_SYS_DBNAME(_dbname) (IS_INFORMATION_SCHEMA_DB(_dbname) || IS_PERFORMANCE_SCHEMA_DB(_dbname)) #define qFatal(...) \ do { \ diff --git a/include/libs/qworker/qworker.h b/include/libs/qworker/qworker.h index 2be0561ce7940e2c17dd49d71f62486d80538fc0..60ed94d4de5a9c43dc64ba2041073eb67889608e 100644 --- a/include/libs/qworker/qworker.h +++ b/include/libs/qworker/qworker.h @@ -106,6 +106,8 @@ int32_t qWorkerProcessLocalQuery(void *pMgmt, uint64_t sId, uint64_t qId, uint64 int32_t qWorkerProcessLocalFetch(void *pMgmt, uint64_t sId, uint64_t qId, uint64_t tId, int64_t rId, int32_t eId, void **pRsp, SArray *explainRes); +int32_t qWorkerDbgEnableDebug(char *option); + #ifdef __cplusplus } #endif diff --git a/include/libs/stream/streamState.h b/include/libs/stream/streamState.h index 912c09a0fb53f1c9075adaa2a57a1f5c72361965..42a7261f3889f41befa4545471bbffd40d355f4e 100644 --- a/include/libs/stream/streamState.h +++ b/include/libs/stream/streamState.h @@ -23,28 +23,29 @@ extern "C" { #ifndef _STREAM_STATE_H_ #define _STREAM_STATE_H_ -typedef struct SStreamTask SStreamTask; - typedef bool (*state_key_cmpr_fn)(void* pKey1, void* pKey2); typedef struct STdbState { - SStreamTask* pOwner; - TDB* db; - TTB* pStateDb; - TTB* pFuncStateDb; - TTB* pFillStateDb; // todo refactor - TTB* pSessionStateDb; - TTB* pParNameDb; - TXN* txn; + struct SStreamTask* pOwner; + + TDB* db; + TTB* pStateDb; + TTB* pFuncStateDb; + TTB* pFillStateDb; // todo refactor + TTB* pSessionStateDb; + TTB* pParNameDb; + TTB* pParTagDb; + TXN* txn; } STdbState; // incremental state storage typedef struct { STdbState* pTdbState; int32_t number; + int64_t checkPointId; } SStreamState; -SStreamState* streamStateOpen(char* path, SStreamTask* pTask, bool specPath, int32_t szPage, int32_t pages); +SStreamState* streamStateOpen(char* path, struct SStreamTask* pTask, bool specPath, int32_t szPage, int32_t pages); void streamStateClose(SStreamState* pState); int32_t streamStateBegin(SStreamState* pState); int32_t streamStateCommit(SStreamState* pState); @@ -108,6 +109,9 @@ int32_t streamStateCurPrev(SStreamState* pState, SStreamStateCur* pCur); int32_t streamStatePutParName(SStreamState* pState, int64_t groupId, const char* tbname); int32_t streamStateGetParName(SStreamState* pState, int64_t groupId, void** pVal); +int32_t streamStatePutParTag(SStreamState* pState, int64_t groupId, const void* tag, int32_t tagLen); +int32_t streamStateGetParTag(SStreamState* pState, int64_t groupId, void** tagVal, int32_t* tagLen); + #if 0 char* streamStateSessionDump(SStreamState* pState); char* streamStateIntervalDump(SStreamState* pState); diff --git a/include/libs/stream/tstream.h b/include/libs/stream/tstream.h index c5352eee468bfd41af16c6e93707b525203677e2..0d021e2fa223b29308fb6894f5c743e7de7bad36 100644 --- a/include/libs/stream/tstream.h +++ b/include/libs/stream/tstream.h @@ -13,8 +13,8 @@ * along with this program. If not, see . */ -#include "executor.h" #include "os.h" +#include "executor.h" #include "query.h" #include "streamState.h" #include "tdatablock.h" @@ -103,19 +103,22 @@ typedef struct { int8_t type; } SStreamQueueItem; +typedef void FTbSink(SStreamTask* pTask, void* vnode, int64_t ver, void* data); +typedef int32_t FTaskExpand(void* ahandle, SStreamTask* pTask, int64_t ver); + typedef struct { int8_t type; int64_t ver; int32_t* dataRef; - SSubmitReq* data; -} SStreamDataSubmit; + SPackedData submit; +} SStreamDataSubmit2; typedef struct { int8_t type; int64_t ver; SArray* dataRefs; // SArray - SArray* reqs; // SArray -} SStreamMergedSubmit; + SArray* submits; // SArray +} SStreamMergedSubmit2; typedef struct { int8_t type; @@ -132,7 +135,6 @@ typedef struct { typedef struct { int8_t type; int64_t ver; - int32_t* dataRef; SSDataBlock* pBlock; } SStreamRefDataBlock; @@ -159,20 +161,24 @@ typedef struct { void streamFreeQitem(SStreamQueueItem* data); +#if 0 bool streamQueueResEmpty(const SStreamQueueRes* pRes); int64_t streamQueueResSize(const SStreamQueueRes* pRes); SStreamQueueNode* streamQueueResFront(SStreamQueueRes* pRes); SStreamQueueNode* streamQueueResPop(SStreamQueueRes* pRes); void streamQueueResClear(SStreamQueueRes* pRes); SStreamQueueRes streamQueueBuildRes(SStreamQueueNode* pNode); +#endif typedef struct { SStreamQueueNode* pHead; } SStreamQueue1; +#if 0 bool streamQueueHasTask(const SStreamQueue1* pQueue); int32_t streamQueuePush(SStreamQueue1* pQueue, SStreamQueueItem* pItem); SStreamQueueRes streamQueueGetRes(SStreamQueue1* pQueue); +#endif typedef struct { STaosQueue* queue; @@ -199,36 +205,20 @@ static FORCE_INLINE void streamQueueProcessFail(SStreamQueue* queue) { } static FORCE_INLINE void* streamQueueCurItem(SStreamQueue* queue) { - // return queue->qItem; } -static FORCE_INLINE void* streamQueueNextItem(SStreamQueue* queue) { - int8_t dequeueFlag = atomic_exchange_8(&queue->status, STREAM_QUEUE__PROCESSING); - if (dequeueFlag == STREAM_QUEUE__FAILED) { - ASSERT(queue->qItem != NULL); - return streamQueueCurItem(queue); - } else { - queue->qItem = NULL; - taosGetQitem(queue->qall, &queue->qItem); - if (queue->qItem == NULL) { - taosReadAllQitems(queue->queue, queue->qall); - taosGetQitem(queue->qall, &queue->qItem); - } - return streamQueueCurItem(queue); - } -} - -SStreamDataSubmit* streamDataSubmitNew(SSubmitReq* pReq); +void* streamQueueNextItem(SStreamQueue* queue); -void streamDataSubmitRefDec(SStreamDataSubmit* pDataSubmit); +SStreamDataSubmit2* streamDataSubmitNew(SPackedData submit, int32_t type); +void streamDataSubmitDestroy(SStreamDataSubmit2* pDataSubmit); -SStreamDataSubmit* streamSubmitRefClone(SStreamDataSubmit* pSubmit); +SStreamDataSubmit2* streamSubmitBlockClone(SStreamDataSubmit2* pSubmit); typedef struct { - char* qmsg; - // followings are not applicable to encoder and decoder - void* executor; + char* qmsg; + void* pExecutor; // not applicable to encoder and decoder + struct SWalReader* pWalReader; // not applicable to encoder and decoder } STaskExec; typedef struct { @@ -243,16 +233,13 @@ typedef struct { SUseDbRsp dbInfo; } STaskDispatcherShuffle; -typedef void FTbSink(SStreamTask* pTask, void* vnode, int64_t ver, void* data); - typedef struct { int64_t stbUid; char stbFullName[TSDB_TABLE_FNAME_LEN]; SSchemaWrapper* pSchemaWrapper; - // not applicable to encoder and decoder - void* vnode; - FTbSink* tbSinkFunc; - STSchema* pTSchema; + void* vnode; // not available to encoder and decoder + FTbSink* tbSinkFunc; + STSchema* pTSchema; } STaskSinkTb; typedef void FSmaSink(void* vnode, int64_t smaId, const SArray* data); @@ -275,24 +262,35 @@ typedef struct { SEpSet epSet; } SStreamChildEpInfo; -typedef struct SStreamTask { - int64_t streamId; - int32_t taskId; - int32_t totalLevel; - int8_t taskLevel; - int8_t outputType; - int16_t dispatchMsgType; +typedef struct SStreamId { + int64_t streamId; + int32_t taskId; + const char* idStr; +} SStreamId; +typedef struct SCheckpointInfo { + int64_t id; + int64_t version; // offset in WAL + int64_t currentVer;// current offset in WAL, not serialize it +} SCheckpointInfo; + +typedef struct SStreamStatus { int8_t taskStatus; int8_t schedStatus; - - // node info - int32_t selfChildId; - int32_t nodeId; - SEpSet epSet; - - int64_t recoverSnapVer; - int64_t startVer; +} SStreamStatus; + +struct SStreamTask { + SStreamId id; + int32_t totalLevel; + int8_t taskLevel; + int8_t outputType; + int16_t dispatchMsgType; + SStreamStatus status; + int32_t selfChildId; + int32_t nodeId; + SEpSet epSet; + SCheckpointInfo chkInfo; + STaskExec exec; // fill history int8_t fillHistory; @@ -302,9 +300,6 @@ typedef struct SStreamTask { int32_t nextCheckId; SArray* checkpointInfo; // SArray - // exec - STaskExec exec; - // output union { STaskDispatcherFixedEp fixedEpDispatcher; @@ -314,84 +309,54 @@ typedef struct SStreamTask { STaskSinkFetch fetchSink; }; - int8_t inputStatus; - int8_t outputStatus; - - // STaosQueue* inputQueue1; - // STaosQall* inputQall; + int8_t inputStatus; + int8_t outputStatus; SStreamQueue* inputQueue; SStreamQueue* outputQueue; // trigger - int8_t triggerStatus; - int64_t triggerParam; - void* timer; - - // msg handle - SMsgCb* pMsgCb; - - // state backend - SStreamState* pState; - - // do not serialize - int32_t recoverTryingDownstream; - int32_t recoverWaitingUpstream; - int64_t checkReqId; - SArray* checkReqIds; // shuffle - int32_t refCnt; - - int64_t checkpointingId; - int32_t checkpointAlignCnt; + int8_t triggerStatus; + int64_t triggerParam; + void* timer; + SMsgCb* pMsgCb; // msg handle + SStreamState* pState; // state backend + + // the followings attributes don't be serialized + int32_t recoverTryingDownstream; + int32_t recoverWaitingUpstream; + int64_t checkReqId; + SArray* checkReqIds; // shuffle + int32_t refCnt; + int64_t checkpointingId; + int32_t checkpointAlignCnt; + struct SStreamMeta* pMeta; +}; -} SStreamTask; +// meta +typedef struct SStreamMeta { + char* path; + TDB* db; + TTB* pTaskDb; + TTB* pCheckpointDb; + SHashObj* pTasks; + SArray* pTaskList; // SArray + void* ahandle; + TXN* txn; + FTaskExpand* expandFunc; + int32_t vgId; + SRWLatch lock; + int32_t walScanCounter; +} SStreamMeta; int32_t tEncodeStreamEpInfo(SEncoder* pEncoder, const SStreamChildEpInfo* pInfo); int32_t tDecodeStreamEpInfo(SDecoder* pDecoder, SStreamChildEpInfo* pInfo); -SStreamTask* tNewSStreamTask(int64_t streamId); -int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask); -int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask); -void tFreeSStreamTask(SStreamTask* pTask); - -static FORCE_INLINE int32_t streamTaskInput(SStreamTask* pTask, SStreamQueueItem* pItem) { - int8_t type = pItem->type; - if (type == STREAM_INPUT__DATA_SUBMIT) { - SStreamDataSubmit* pSubmitClone = streamSubmitRefClone((SStreamDataSubmit*)pItem); - if (pSubmitClone == NULL) { - qDebug("task %d %p submit enqueue failed since out of memory", pTask->taskId, pTask); - terrno = TSDB_CODE_OUT_OF_MEMORY; - atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED); - return -1; - } - qDebug("task %d %p submit enqueue %p %p %p", pTask->taskId, pTask, pItem, pSubmitClone, pSubmitClone->data); - taosWriteQitem(pTask->inputQueue->queue, pSubmitClone); - // qStreamInput(pTask->exec.executor, pSubmitClone); - } else if (type == STREAM_INPUT__DATA_BLOCK || type == STREAM_INPUT__DATA_RETRIEVE || - type == STREAM_INPUT__REF_DATA_BLOCK) { - taosWriteQitem(pTask->inputQueue->queue, pItem); - // qStreamInput(pTask->exec.executor, pItem); - } else if (type == STREAM_INPUT__CHECKPOINT) { - taosWriteQitem(pTask->inputQueue->queue, pItem); - // qStreamInput(pTask->exec.executor, pItem); - } else if (type == STREAM_INPUT__GET_RES) { - taosWriteQitem(pTask->inputQueue->queue, pItem); - // qStreamInput(pTask->exec.executor, pItem); - } - - if (type != STREAM_INPUT__GET_RES && type != STREAM_INPUT__CHECKPOINT && pTask->triggerParam != 0) { - atomic_val_compare_exchange_8(&pTask->triggerStatus, TASK_TRIGGER_STATUS__INACTIVE, TASK_TRIGGER_STATUS__ACTIVE); - } - -#if 0 - // TODO: back pressure - atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__NORMAL); -#endif - return 0; -} - -static FORCE_INLINE void streamTaskInputFail(SStreamTask* pTask) { - atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED); -} +SStreamTask* tNewStreamTask(int64_t streamId); +int32_t tEncodeStreamTask(SEncoder* pEncoder, const SStreamTask* pTask); +int32_t tDecodeStreamTask(SDecoder* pDecoder, SStreamTask* pTask); +void tFreeStreamTask(SStreamTask* pTask); +int32_t tAppendDataToInputQueue(SStreamTask* pTask, SStreamQueueItem* pItem); +bool tInputQueueIsFull(const SStreamTask* pTask); typedef struct { SMsgHead head; @@ -566,19 +531,22 @@ int32_t streamProcessDispatchReq(SStreamTask* pTask, SStreamDispatchReq* pReq, S int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp, int32_t code); int32_t streamProcessRetrieveReq(SStreamTask* pTask, SStreamRetrieveReq* pReq, SRpcMsg* pMsg); -int32_t streamProcessRetrieveRsp(SStreamTask* pTask, SStreamRetrieveRsp* pRsp); +// int32_t streamProcessRetrieveRsp(SStreamTask* pTask, SStreamRetrieveRsp* pRsp); +void streamTaskInputFail(SStreamTask* pTask); int32_t streamTryExec(SStreamTask* pTask); int32_t streamSchedExec(SStreamTask* pTask); int32_t streamTaskOutput(SStreamTask* pTask, SStreamDataBlock* pBlock); +bool streamTaskShouldStop(const SStreamStatus* pStatus); int32_t streamScanExec(SStreamTask* pTask, int32_t batchSz); // recover and fill history int32_t streamTaskCheckDownstream(SStreamTask* pTask, int64_t version); int32_t streamTaskLaunchRecover(SStreamTask* pTask, int64_t version); -int32_t streamProcessTaskCheckReq(SStreamTask* pTask, const SStreamTaskCheckReq* pReq); +int32_t streamTaskCheckStatus(SStreamTask* pTask); int32_t streamProcessTaskCheckRsp(SStreamTask* pTask, const SStreamTaskCheckRsp* pRsp, int64_t version); + // common int32_t streamSetParamForRecover(SStreamTask* pTask); int32_t streamRestoreParam(SStreamTask* pTask); @@ -595,39 +563,22 @@ int32_t streamAggRecoverPrepare(SStreamTask* pTask); // int32_t streamAggChildrenRecoverFinish(SStreamTask* pTask); int32_t streamProcessRecoverFinishReq(SStreamTask* pTask, int32_t childId); -// expand and deploy -typedef int32_t FTaskExpand(void* ahandle, SStreamTask* pTask, int64_t ver); - -// meta -typedef struct SStreamMeta { - char* path; - TDB* db; - TTB* pTaskDb; - TTB* pCheckpointDb; - SHashObj* pTasks; - SHashObj* pRecoverStatus; - void* ahandle; - TXN* txn; - FTaskExpand* expandFunc; - int32_t vgId; - SRWLatch lock; -} SStreamMeta; - SStreamMeta* streamMetaOpen(const char* path, void* ahandle, FTaskExpand expandFunc, int32_t vgId); void streamMetaClose(SStreamMeta* streamMeta); -int32_t streamMetaAddTask(SStreamMeta* pMeta, int64_t ver, SStreamTask* pTask); -int32_t streamMetaAddSerializedTask(SStreamMeta* pMeta, int64_t startVer, char* msg, int32_t msgLen); -SStreamTask* streamMetaGetTask(SStreamMeta* pMeta, int32_t taskId); +int32_t streamMetaSaveTask(SStreamMeta* pMeta, SStreamTask* pTask); +int32_t streamMetaAddDeployedTask(SStreamMeta* pMeta, int64_t ver, SStreamTask* pTask); +int32_t streamMetaAddSerializedTask(SStreamMeta* pMeta, int64_t checkpointVer, char* msg, int32_t msgLen); +int32_t streamMetaGetNumOfTasks(const SStreamMeta* pMeta); SStreamTask* streamMetaAcquireTask(SStreamMeta* pMeta, int32_t taskId); void streamMetaReleaseTask(SStreamMeta* pMeta, SStreamTask* pTask); void streamMetaRemoveTask(SStreamMeta* pMeta, int32_t taskId); -int32_t streamMetaBegin(SStreamMeta* pMeta); -int32_t streamMetaCommit(SStreamMeta* pMeta); -int32_t streamMetaRollBack(SStreamMeta* pMeta); -int32_t streamLoadTasks(SStreamMeta* pMeta); +int32_t streamMetaBegin(SStreamMeta* pMeta); +int32_t streamMetaCommit(SStreamMeta* pMeta); +int32_t streamMetaRollBack(SStreamMeta* pMeta); +int32_t streamLoadTasks(SStreamMeta* pMeta, int64_t ver); // checkpoint int32_t streamProcessCheckpointSourceReq(SStreamMeta* pMeta, SStreamTask* pTask, SStreamCheckpointSourceReq* pReq); diff --git a/include/libs/sync/sync.h b/include/libs/sync/sync.h index 5e37da4f3f57a57c8ebab0fb7537786ea6a642b9..fdb4506cf3c00d04b6f5981601eb6915d3cd381b 100644 --- a/include/libs/sync/sync.h +++ b/include/libs/sync/sync.h @@ -35,7 +35,6 @@ extern "C" { #define SYNC_MAX_RECV_TIME_RANGE_MS 1200 #define SYNC_DEL_WAL_MS (1000 * 60) #define SYNC_ADD_QUORUM_COUNT 3 -#define SYNC_MNODE_LOG_RETENTION 10000 #define SYNC_VNODE_LOG_RETENTION (TSDB_SYNC_LOG_BUFFER_RETENTION + 1) #define SNAPSHOT_MAX_CLOCK_SKEW_MS 1000 * 10 #define SNAPSHOT_WAIT_MS 1000 * 30 @@ -49,7 +48,7 @@ extern "C" { #define SYNC_HEARTBEAT_REPLY_SLOW_MS 1500 #define SYNC_SNAP_RESEND_MS 1000 * 60 -#define SYNC_VND_COMMIT_MIN_MS 1000 +#define SYNC_VND_COMMIT_MIN_MS 3000 #define SYNC_MAX_BATCH_SIZE 1 #define SYNC_INDEX_BEGIN 0 @@ -144,10 +143,11 @@ typedef struct SSyncFSM { void* data; int32_t (*FpCommitCb)(const struct SSyncFSM* pFsm, SRpcMsg* pMsg, const SFsmCbMeta* pMeta); + SyncIndex (*FpAppliedIndexCb)(const struct SSyncFSM* pFsm); int32_t (*FpPreCommitCb)(const struct SSyncFSM* pFsm, SRpcMsg* pMsg, const SFsmCbMeta* pMeta); void (*FpRollBackCb)(const struct SSyncFSM* pFsm, SRpcMsg* pMsg, const SFsmCbMeta* pMeta); - void (*FpRestoreFinishCb)(const struct SSyncFSM* pFsm); + void (*FpRestoreFinishCb)(const struct SSyncFSM* pFsm, const SyncIndex commitIdx); void (*FpReConfigCb)(const struct SSyncFSM* pFsm, SRpcMsg* pMsg, const SReConfigCbMeta* pMeta); void (*FpLeaderTransferCb)(const struct SSyncFSM* pFsm, SRpcMsg* pMsg, const SFsmCbMeta* pMeta); bool (*FpApplyQueueEmptyCb)(const struct SSyncFSM* pFsm); @@ -246,6 +246,7 @@ bool syncIsReadyForRead(int64_t rid); bool syncSnapshotSending(int64_t rid); bool syncSnapshotRecving(int64_t rid); int32_t syncSendTimeoutRsp(int64_t rid, int64_t seq); +int32_t syncForceBecomeFollower(SSyncNode* ths, const SRpcMsg* pRpcMsg); SSyncState syncGetState(int64_t rid); void syncGetRetryEpSet(int64_t rid, SEpSet* pEpSet); diff --git a/include/libs/tfs/tfs.h b/include/libs/tfs/tfs.h index 3af75e0eaf443e7887dacd6a3056be4241ec5c9b..cbf1d60e35ac1c4187ddb0a5d8cc366714cbaec3 100644 --- a/include/libs/tfs/tfs.h +++ b/include/libs/tfs/tfs.h @@ -150,7 +150,7 @@ int32_t tfsRmdir(STfs *pTfs, const char *rname); * @param nrname The rel name of new file. * @return int32_t 0 for success, -1 for failure. */ -int32_t tfsRename(STfs *pTfs, char *orname, char *nrname); +int32_t tfsRename(STfs *pTfs, const char *orname, const char *nrname); /** * @brief Init file object in tfs. diff --git a/include/libs/transport/thttp.h b/include/libs/transport/thttp.h index 9a6aee418794b61abd88e132b42964c56c69451c..f6f1f7f02771b6a3cefbd85864d01e9b46b39b29 100644 --- a/include/libs/transport/thttp.h +++ b/include/libs/transport/thttp.h @@ -17,6 +17,7 @@ #define _TD_UTIL_HTTP_H_ #include "os.h" +#include "tref.h" #ifdef __cplusplus extern "C" { @@ -24,7 +25,8 @@ extern "C" { typedef enum { HTTP_GZIP, HTTP_FLAT } EHttpCompFlag; -int32_t taosSendHttpReport(const char* server, const char* uri, uint16_t port, char* pCont, int32_t contLen, EHttpCompFlag flag); +int32_t taosSendHttpReport(const char* server, const char* uri, uint16_t port, char* pCont, int32_t contLen, + EHttpCompFlag flag); #ifdef __cplusplus } diff --git a/include/libs/transport/trpc.h b/include/libs/transport/trpc.h index de3c2a9f52f7f7743ae58f57c0bc53d1cc0d2991..c73e5c127af03cdc07e47c1ca95dd775a38599f2 100644 --- a/include/libs/transport/trpc.h +++ b/include/libs/transport/trpc.h @@ -112,7 +112,12 @@ typedef struct SRpcInit { // fail fast fp RpcFFfp ffp; - void *parent; + int32_t connLimitNum; + int32_t connLimitLock; + int32_t timeToGetConn; + int8_t supportBatch; // 0: no batch, 1. batch + int32_t batchSize; + void *parent; } SRpcInit; typedef struct { diff --git a/include/libs/wal/wal.h b/include/libs/wal/wal.h index 1eed342f8ca496006fc5fa00150cad4cc5dea9a6..7e106eefdeca155bc8c8d4ce139cdd8b50ce1460 100644 --- a/include/libs/wal/wal.h +++ b/include/libs/wal/wal.h @@ -66,6 +66,7 @@ typedef struct { int64_t commitVer; int64_t appliedVer; int64_t lastVer; + int64_t logRetention; } SWalVer; #pragma pack(push, 1) @@ -126,18 +127,20 @@ typedef struct SWal { typedef struct { int64_t refId; int64_t refVer; - int64_t refFile; +// int64_t refFile; SWal *pWal; } SWalRef; typedef struct { - int8_t scanUncommited; +// int8_t scanUncommited; int8_t scanNotApplied; int8_t scanMeta; + int8_t deleteMsg; int8_t enableRef; } SWalFilterCond; -typedef struct { +// todo hide this struct +typedef struct SWalReader { SWal *pWal; int64_t readerId; TdFilePtr pLogFile; @@ -145,8 +148,6 @@ typedef struct { int64_t curFileFirstVer; int64_t curVersion; int64_t capacity; - int8_t curInvalid; - int8_t curStopped; TdThreadMutex mutex; SWalFilterCond cond; // TODO remove it @@ -180,7 +181,7 @@ void walFsync(SWal *, bool force); int32_t walCommit(SWal *, int64_t ver); int32_t walRollback(SWal *, int64_t ver); // notify that previous logs can be pruned safely -int32_t walBeginSnapshot(SWal *, int64_t ver); +int32_t walBeginSnapshot(SWal *, int64_t ver, int64_t logRetention); int32_t walEndSnapshot(SWal *); int32_t walRestoreFromSnapshot(SWal *, int64_t ver); // for tq @@ -193,8 +194,10 @@ SWalReader *walOpenReader(SWal *, SWalFilterCond *pCond); void walCloseReader(SWalReader *pRead); void walReadReset(SWalReader *pReader); int32_t walReadVer(SWalReader *pRead, int64_t ver); -int32_t walReadSeekVer(SWalReader *pRead, int64_t ver); +int32_t walReaderSeekVer(SWalReader *pRead, int64_t ver); int32_t walNextValidMsg(SWalReader *pRead); +int64_t walReaderGetCurrentVer(const SWalReader* pReader); +int64_t walReaderGetValidFirstVer(const SWalReader* pReader); // only for tq usage void walSetReaderCapacity(SWalReader *pRead, int32_t capacity); @@ -207,8 +210,7 @@ SWalRef *walRefCommittedVer(SWal *); SWalRef *walOpenRef(SWal *); void walCloseRef(SWal *pWal, int64_t refId); -int32_t walRefVer(SWalRef *, int64_t ver); -void walUnrefVer(SWalRef *); +int32_t walSetRefVer(SWalRef *, int64_t ver); // helper function for raft bool walLogExist(SWal *, int64_t ver); diff --git a/include/os/os.h b/include/os/os.h index b27fa84406b843f15ba99d52f7d9fde8580a0899..309a977ff6b7e6d500d93cba0ee487cc7befbd9e 100644 --- a/include/os/os.h +++ b/include/os/os.h @@ -27,7 +27,11 @@ extern "C" { #if !defined(WINDOWS) #include + +#if !defined(_ALPINE) #include +#endif + #include #include #include @@ -116,6 +120,7 @@ extern "C" { #include "osTimer.h" #include "osTimezone.h" #include "taoserror.h" +#include "tlog.h" #ifdef __cplusplus } diff --git a/include/os/osDir.h b/include/os/osDir.h index 73871602c5e7818f0d9b050280d7326ee39678ef..55c7a15764cf68a15e37602d1182a56d859091b1 100644 --- a/include/os/osDir.h +++ b/include/os/osDir.h @@ -31,21 +31,49 @@ extern "C" { #endif +#if defined(CUS_NAME) || defined(CUS_PROMPT) || defined(CUS_EMAIL) +#include "cus_name.h" +#endif + #ifdef WINDOWS + #define TD_TMP_DIR_PATH "C:\\Windows\\Temp\\" +#ifdef CUS_NAME +#define TD_CFG_DIR_PATH "C:\\"CUS_NAME"\\cfg\\" +#define TD_DATA_DIR_PATH "C:\\"CUS_NAME"\\data\\" +#define TD_LOG_DIR_PATH "C:\\"CUS_NAME"\\log\\" +#else #define TD_CFG_DIR_PATH "C:\\TDengine\\cfg\\" #define TD_DATA_DIR_PATH "C:\\TDengine\\data\\" #define TD_LOG_DIR_PATH "C:\\TDengine\\log\\" +#endif // CUS_NAME + #elif defined(_TD_DARWIN_64) + +#ifdef CUS_PROMPT +#define TD_TMP_DIR_PATH "/tmp/"CUS_PROMPT"d/" +#define TD_CFG_DIR_PATH "/etc/"CUS_PROMPT"/" +#define TD_DATA_DIR_PATH "/var/lib/"CUS_PROMPT"/" +#define TD_LOG_DIR_PATH "/var/log/"CUS_PROMPT"/" +#else #define TD_TMP_DIR_PATH "/tmp/taosd/" #define TD_CFG_DIR_PATH "/etc/taos/" #define TD_DATA_DIR_PATH "/var/lib/taos/" #define TD_LOG_DIR_PATH "/var/log/taos/" +#endif // CUS_PROMPT + #else + #define TD_TMP_DIR_PATH "/tmp/" +#ifdef CUS_PROMPT +#define TD_CFG_DIR_PATH "/etc/"CUS_PROMPT"/" +#define TD_DATA_DIR_PATH "/var/lib/"CUS_PROMPT"/" +#define TD_LOG_DIR_PATH "/var/log/"CUS_PROMPT"/" +#else #define TD_CFG_DIR_PATH "/etc/taos/" #define TD_DATA_DIR_PATH "/var/lib/taos/" #define TD_LOG_DIR_PATH "/var/log/taos/" +#endif // CUS_PROMPT #endif typedef struct TdDir *TdDirPtr; diff --git a/include/os/osMemory.h b/include/os/osMemory.h index e6a4488287816f21ca9eeee76a3208ff6e6ff12d..44a97bf05517241cf32d48fcfe940dcbb216859a 100644 --- a/include/os/osMemory.h +++ b/include/os/osMemory.h @@ -29,14 +29,19 @@ extern "C" { #define calloc CALLOC_FUNC_TAOS_FORBID #define realloc REALLOC_FUNC_TAOS_FORBID #define free FREE_FUNC_TAOS_FORBID +#ifdef strdup +#undef strdup +#define strdup STRDUP_FUNC_TAOS_FORBID +#endif #endif // ifndef ALLOW_FORBID_FUNC - #endif // if !defined(WINDOWS) +int32_t taosMemoryDbgInit(); +int32_t taosMemoryDbgInitRestore(); void *taosMemoryMalloc(int64_t size); void *taosMemoryCalloc(int64_t num, int64_t size); void *taosMemoryRealloc(void *ptr, int64_t size); -void *taosMemoryStrDup(const char *ptr); +char *taosStrdup(const char *ptr); void taosMemoryFree(void *ptr); int64_t taosMemorySize(void *ptr); void taosPrintBackTrace(); diff --git a/include/os/osSysinfo.h b/include/os/osSysinfo.h index dbe4d6801e42fa04a9b9da0f2d3f864d0b75f94d..a8ccb67bfb1bb345150a2d7ee90d776e7b251aa3 100644 --- a/include/os/osSysinfo.h +++ b/include/os/osSysinfo.h @@ -60,6 +60,13 @@ void taosSetCoreDump(bool enable); #endif // WINDOWS +#if defined(_ALPINE) + +#define _UTSNAME_LENGTH 65 +#define _UTSNAME_MACHINE_LENGTH _UTSNAME_LENGTH + +#endif + typedef struct { char sysname[_UTSNAME_MACHINE_LENGTH]; char nodename[_UTSNAME_MACHINE_LENGTH]; diff --git a/include/os/osSystem.h b/include/os/osSystem.h index 5154c56e4b5b48fb1a85e2dd620b3b3338902478..ba9f137b40edb2b4eacd2369004e1bd74bdd7361 100644 --- a/include/os/osSystem.h +++ b/include/os/osSystem.h @@ -16,6 +16,11 @@ #ifndef _TD_OS_SYSTEM_H_ #define _TD_OS_SYSTEM_H_ +#ifdef _ALPINE +#define UNW_LOCAL_ONLY +#include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -29,46 +34,124 @@ extern "C" { #define tcgetattr TCGETATTR_FUNC_TAOS_FORBID #endif -typedef struct TdCmd* TdCmdPtr; +typedef struct TdCmd *TdCmdPtr; + +TdCmdPtr taosOpenCmd(const char *cmd); + +int64_t taosGetsCmd(TdCmdPtr pCmd, int32_t maxSize, char *__restrict buf); + +int64_t taosGetLineCmd(TdCmdPtr pCmd, char **__restrict ptrBuf); + +int32_t taosEOFCmd(TdCmdPtr pCmd); -TdCmdPtr taosOpenCmd(const char* cmd); -int64_t taosGetsCmd(TdCmdPtr pCmd, int32_t maxSize, char* __restrict buf); -int64_t taosGetLineCmd(TdCmdPtr pCmd, char** __restrict ptrBuf); -int32_t taosEOFCmd(TdCmdPtr pCmd); -int64_t taosCloseCmd(TdCmdPtr* ppCmd); +int64_t taosCloseCmd(TdCmdPtr *ppCmd); -void* taosLoadDll(const char* filename); -void* taosLoadSym(void* handle, char* name); -void taosCloseDll(void* handle); +void *taosLoadDll(const char *filename); + +void *taosLoadSym(void *handle, char *name); + +void taosCloseDll(void *handle); int32_t taosSetConsoleEcho(bool on); -void taosSetTerminalMode(); + +void taosSetTerminalMode(); + int32_t taosGetOldTerminalMode(); -void taosResetTerminalMode(); + +void taosResetTerminalMode(); #define STACKSIZE 100 -#if !defined(WINDOWS) -#define taosLogTraceToBuf(buf, bufSize, ignoreNum) { \ - void* array[STACKSIZE]; \ - int32_t size = backtrace(array, STACKSIZE); \ - char** strings = backtrace_symbols(array, size); \ - int32_t offset = 0; \ - if (strings != NULL) { \ - offset = snprintf(buf, bufSize - 1, "obtained %d stack frames\n", (ignoreNum > 0) ? size - ignoreNum : size); \ - for (int32_t i = (ignoreNum > 0) ? ignoreNum : 0; i < size; i++) { \ - offset += snprintf(buf + offset, bufSize - 1 - offset, "frame:%d, %s\n", (ignoreNum > 0) ? i - ignoreNum : i, strings[i]); \ - } \ - } \ - \ - taosMemoryFree(strings); \ -} +#if defined(_ALPINE) +#define taosLogTraceToBuf(buf, bufSize, ignoreNum) \ + { \ + unw_cursor_t cursor; \ + unw_context_t context; \ + \ + unw_getcontext(&context); \ + unw_init_local(&cursor, &context); \ + \ + char *array[STACKSIZE]; \ + int32_t size = 0; \ + int32_t ignores = ignoreNum; \ + int32_t offset = 0; \ + while (unw_step(&cursor) > 0 && size < STACKSIZE) { \ + unw_word_t offset, pc; \ + char fname[64]; \ + unw_get_reg(&cursor, UNW_REG_IP, &pc); \ + fname[0] = '\0'; \ + (void)unw_get_proc_name(&cursor, fname, sizeof(fname), &offset); \ + size += 1; \ + array[size] = (char *)taosMemoryMalloc(sizeof(char) * STACKSIZE + 1); \ + snprintf(array[size], STACKSIZE, "0x%lx : (%s+0x%lx) [0x%lx]\n", (long)pc, fname, (long)offset, (long)pc); \ + } \ + if (ignoreNum < size && size > 0) { \ + offset = snprintf(buf, bufSize - 1, "obtained %d stack frames\n", (ignoreNum > 0) ? size - ignoreNum : size); \ + for (int32_t i = (ignoreNum > 0) ? ignoreNum : 0; i < size; i++) { \ + offset += snprintf(buf + offset, bufSize - 1 - offset, "frame:%d, %s\n", (ignoreNum > 0) ? i - ignoreNum : i, \ + array[i]); \ + } \ + } \ + for (int i = 0; i < size; i++) { \ + taosMemoryFree(array[i]); \ + } \ + } + +#define taosPrintTrace(flags, level, dflag, ignoreNum) \ + { \ + unw_cursor_t cursor; \ + unw_context_t context; \ + \ + unw_getcontext(&context); \ + unw_init_local(&cursor, &context); \ + \ + char *array[STACKSIZE]; \ + int32_t size = 0; \ + while (unw_step(&cursor) > 0 && size < STACKSIZE) { \ + unw_word_t offset, pc; \ + char fname[64]; \ + unw_get_reg(&cursor, UNW_REG_IP, &pc); \ + fname[0] = '\0'; \ + (void)unw_get_proc_name(&cursor, fname, sizeof(fname), &offset); \ + size += 1; \ + array[size] = (char *)taosMemoryMalloc(sizeof(char) * STACKSIZE + 1); \ + snprintf(array[size], STACKSIZE, "frame:%d, 0x%lx : (%s+0x%lx) [0x%lx]\n", size, (long)pc, fname, (long)offset, \ + (long)pc); \ + } \ + if (ignoreNum < size && size > 0) { \ + taosPrintLog(flags, level, dflag, "obtained %d stack frames", (ignoreNum > 0) ? size - ignoreNum : size); \ + for (int32_t i = (ignoreNum > 0) ? ignoreNum : 0; i < size; i++) { \ + taosPrintLog(flags, level, dflag, "frame:%d, %s", (ignoreNum > 0) ? i - ignoreNum : i, array[i]); \ + } \ + } \ + for (int i = 0; i < size; i++) { \ + taosMemoryFree(array[i]); \ + } \ + } + +#elif !defined(WINDOWS) +#define taosLogTraceToBuf(buf, bufSize, ignoreNum) \ + { \ + void *array[STACKSIZE]; \ + int32_t size = backtrace(array, STACKSIZE); \ + char **strings = backtrace_symbols(array, size); \ + int32_t offset = 0; \ + if (strings != NULL) { \ + offset = snprintf(buf, bufSize - 1, "obtained %d stack frames\n", (ignoreNum > 0) ? size - ignoreNum : size); \ + for (int32_t i = (ignoreNum > 0) ? ignoreNum : 0; i < size; i++) { \ + offset += snprintf(buf + offset, bufSize - 1 - offset, "frame:%d, %s\n", (ignoreNum > 0) ? i - ignoreNum : i, \ + strings[i]); \ + } \ + } \ + \ + taosMemoryFree(strings); \ + } #define taosPrintTrace(flags, level, dflag, ignoreNum) \ { \ - void* array[STACKSIZE]; \ - int32_t size = backtrace(array, STACKSIZE); \ - char** strings = backtrace_symbols(array, size); \ + void *array[STACKSIZE]; \ + int32_t size = backtrace(array, STACKSIZE); \ + char **strings = backtrace_symbols(array, size); \ if (strings != NULL) { \ taosPrintLog(flags, level, dflag, "obtained %d stack frames", (ignoreNum > 0) ? size - ignoreNum : size); \ for (int32_t i = (ignoreNum > 0) ? ignoreNum : 0; i < size; i++) { \ @@ -80,65 +163,70 @@ void taosResetTerminalMode(); } #else -#include #include +#include -#define taosLogTraceToBuf(buf, bufSize, ignoreNum) { \ - unsigned int i; \ - void* stack[STACKSIZE]; \ - unsigned short frames; \ - SYMBOL_INFO* symbol; \ - HANDLE process; \ - int32_t offset = 0; \ - \ - process = GetCurrentProcess(); \ - \ - SymInitialize(process, NULL, TRUE); \ - \ - frames = CaptureStackBackTrace(0, STACKSIZE, stack, NULL); \ - symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); \ - if (symbol != NULL) { \ - symbol->MaxNameLen = 255; \ - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); \ - \ - if (frames > 0) { \ - offset = snprintf(buf, bufSize - 1, "obtained %d stack frames\n", (ignoreNum > 0) ? frames - ignoreNum : frames); \ - for (i = (ignoreNum > 0) ? ignoreNum : 0; i < frames; i++) { \ - SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); \ - offset += snprintf(buf + offset, bufSize - 1 - offset, "frame:%i, %s - 0x%0X\n", (ignoreNum > 0) ? i - ignoreNum : i, symbol->Name, symbol->Address); \ - } \ - } \ - free(symbol); \ - } \ +#define taosLogTraceToBuf(buf, bufSize, ignoreNum) \ + { \ + unsigned int i; \ + void *stack[STACKSIZE]; \ + unsigned short frames; \ + SYMBOL_INFO *symbol; \ + HANDLE process; \ + int32_t offset = 0; \ + \ + process = GetCurrentProcess(); \ + \ + SymInitialize(process, NULL, TRUE); \ + \ + frames = CaptureStackBackTrace(0, STACKSIZE, stack, NULL); \ + symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); \ + if (symbol != NULL) { \ + symbol->MaxNameLen = 255; \ + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); \ + \ + if (frames > 0) { \ + offset = \ + snprintf(buf, bufSize - 1, "obtained %d stack frames\n", (ignoreNum > 0) ? frames - ignoreNum : frames); \ + for (i = (ignoreNum > 0) ? ignoreNum : 0; i < frames; i++) { \ + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); \ + offset += snprintf(buf + offset, bufSize - 1 - offset, "frame:%i, %s - 0x%0X\n", \ + (ignoreNum > 0) ? i - ignoreNum : i, symbol->Name, symbol->Address); \ + } \ + } \ + free(symbol); \ + } \ } -#define taosPrintTrace(flags, level, dflag, ignoreNum) \ +#define taosPrintTrace(flags, level, dflag, ignoreNum) \ { \ - unsigned int i; \ - void* stack[STACKSIZE]; \ - unsigned short frames; \ - SYMBOL_INFO* symbol; \ - HANDLE process; \ - \ - process = GetCurrentProcess(); \ - \ - SymInitialize(process, NULL, TRUE); \ - \ - frames = CaptureStackBackTrace(0, STACKSIZE, stack, NULL); \ - symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); \ - if (symbol != NULL) { \ - symbol->MaxNameLen = 255; \ - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); \ - \ - if (frames > 0) { \ - taosPrintLog(flags, level, dflag, "obtained %d stack frames\n", (ignoreNum > 0) ? frames - ignoreNum : frames); \ - for (i = (ignoreNum > 0) ? ignoreNum : 0; i < frames; i++) { \ - SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); \ - taosPrintLog(flags, level, dflag, "frame:%i, %s - 0x%0X\n", (ignoreNum > 0) ? i - ignoreNum : i, symbol->Name, symbol->Address); \ - } \ - } \ - free(symbol); \ - } \ + unsigned int i; \ + void *stack[STACKSIZE]; \ + unsigned short frames; \ + SYMBOL_INFO *symbol; \ + HANDLE process; \ + \ + process = GetCurrentProcess(); \ + \ + SymInitialize(process, NULL, TRUE); \ + \ + frames = CaptureStackBackTrace(0, STACKSIZE, stack, NULL); \ + symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); \ + if (symbol != NULL) { \ + symbol->MaxNameLen = 255; \ + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); \ + \ + if (frames > 0) { \ + taosPrintLog(flags, level, dflag, "obtained %d stack frames\n", \ + (ignoreNum > 0) ? frames - ignoreNum : frames); \ + for (i = (ignoreNum > 0) ? ignoreNum : 0; i < frames; i++) { \ + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); \ + taosPrintLog(flags, level, dflag, "frame:%i, %s - 0x%0X\n", (ignoreNum > 0) ? i - ignoreNum : i, \ + symbol->Name, symbol->Address); \ + } \ + } \ + free(symbol); \ + } \ } #endif diff --git a/include/os/osThread.h b/include/os/osThread.h index 916d463733373c2512ab77a7e6931cede98966af..aa0dc066c60bb7e218f249bb06505c43c7d2845c 100644 --- a/include/os/osThread.h +++ b/include/os/osThread.h @@ -22,7 +22,7 @@ extern "C" { #endif -#ifndef WINDOWS +#if !defined(WINDOWS) && !defined(_ALPINE) #ifndef __USE_XOPEN2K #define TD_USE_SPINLOCK_AS_MUTEX typedef pthread_mutex_t pthread_spinlock_t; @@ -100,7 +100,11 @@ typedef pthread_key_t TdThreadKey; #define pthread_condattr_init PTHREAD_CONDATTR_INIT_FUNC_TAOS_FORBID #define pthread_condattr_setpshared PTHREAD_CONDATTR_SETPSHARED_FUNC_TAOS_FORBID #define pthread_detach PTHREAD_DETACH_FUNC_TAOS_FORBID + +#if !defined(_ALPINE) #define pthread_equal PTHREAD_EQUAL_FUNC_TAOS_FORBID +#endif + #define pthread_exit PTHREAD_EXIT_FUNC_TAOS_FORBID #define pthread_getschedparam PTHREAD_GETSCHEDPARAM_FUNC_TAOS_FORBID #define pthread_getspecific PTHREAD_GETSPECIFIC_FUNC_TAOS_FORBID diff --git a/include/os/osTime.h b/include/os/osTime.h index 0a0a54119b4a40b79e54b7183b0cdc57cac03ca7..51a285a1393171ea59940498a4c8134afa270366 100644 --- a/include/os/osTime.h +++ b/include/os/osTime.h @@ -91,7 +91,7 @@ static FORCE_INLINE int64_t taosGetMonoTimestampMs() { } char *taosStrpTime(const char *buf, const char *fmt, struct tm *tm); -struct tm *taosLocalTime(const time_t *timep, struct tm *result); +struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf); struct tm *taosLocalTimeNolock(struct tm *result, const time_t *timep, int dst); time_t taosTime(time_t *t); time_t taosMktime(struct tm *timep); diff --git a/include/libs/cache/cache.h b/include/util/cus_name.h similarity index 73% rename from include/libs/cache/cache.h rename to include/util/cus_name.h index 6a2587ee9674668861d050ee734987125674e643..16f677f855ba07403d292e4e64dd6060fb2ccf31 100644 --- a/include/libs/cache/cache.h +++ b/include/util/cus_name.h @@ -13,15 +13,19 @@ * along with this program. If not, see . */ -#ifndef _TD_CACHE_H_ -#define _TD_CACHE_H_ +#ifndef _CUS_NAME_H_ +#define _CUS_NAME_H_ -#ifdef __cplusplus -extern "C" { +#ifndef CUS_NAME +#define CUS_NAME "TDengine" #endif -#ifdef __cplusplus -} +#ifndef CUS_PROMPT +#define CUS_PROMPT "taos" #endif -#endif /*_TD_CACHE_H_*/ \ No newline at end of file +#ifndef CUS_EMAIL +#define CUS_EMAIL "" +#endif + +#endif // _CUS_NAME_H_ diff --git a/include/util/tRealloc.h b/include/util/tRealloc.h index f3593d5818cd626c7268ec1b721bd961fba3a845..3229c53039f6dc857dd7e0b2d4774e6875ef8c16 100644 --- a/include/util/tRealloc.h +++ b/include/util/tRealloc.h @@ -52,11 +52,13 @@ _exit: return code; } -static FORCE_INLINE void tFree(uint8_t *pBuf) { - if (pBuf) { - taosMemoryFree(pBuf - sizeof(int64_t)); - } -} +#define tFree(BUF) \ + do { \ + if (BUF) { \ + taosMemoryFree((uint8_t *)(BUF) - sizeof(int64_t)); \ + (BUF) = NULL; \ + } \ + } while (0) #ifdef __cplusplus } diff --git a/include/util/taoserror.h b/include/util/taoserror.h index d8eecdfc64a7ca348111872edc9ba9f9ee5e4913..80630c135871e5a947db4aebc1df25887eee1dba 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -67,6 +67,10 @@ int32_t* taosGetErrno(); #define TSDB_CODE_RPC_TIMEOUT TAOS_DEF_ERROR_CODE(0, 0x0019) // #define TSDB_CODE_RPC_SOMENODE_NOT_CONNECTED TAOS_DEF_ERROR_CODE(0, 0x0020) // "Vgroup could not be connected" #define TSDB_CODE_RPC_SOMENODE_BROKEN_LINK TAOS_DEF_ERROR_CODE(0, 0x0021) // +#define TSDB_CODE_RPC_MAX_SESSIONS TAOS_DEF_ERROR_CODE(0, 0x0022) // + + + //common & util #define TSDB_CODE_OPS_NOT_SUPPORT TAOS_DEF_ERROR_CODE(0, 0x0100) // @@ -112,9 +116,11 @@ int32_t* taosGetErrno(); #define TSDB_CODE_NO_DISKSPACE TAOS_DEF_ERROR_CODE(0, 0x012B) #define TSDB_CODE_TIMEOUT_ERROR TAOS_DEF_ERROR_CODE(0, 0x012C) #define TSDB_CODE_MSG_ENCODE_ERROR TAOS_DEF_ERROR_CODE(0, 0x012D) +#define TSDB_CODE_NO_ENOUGH_DISKSPACE TAOS_DEF_ERROR_CODE(0, 0x012E) #define TSDB_CODE_APP_IS_STARTING TAOS_DEF_ERROR_CODE(0, 0x0130) // #define TSDB_CODE_APP_IS_STOPPING TAOS_DEF_ERROR_CODE(0, 0x0131) // +#define TSDB_CODE_IVLD_DATA_FMT TAOS_DEF_ERROR_CODE(0, 0x0132) // //client #define TSDB_CODE_TSC_INVALID_OPERATION TAOS_DEF_ERROR_CODE(0, 0x0200) @@ -140,7 +146,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_TSC_CONN_KILLED TAOS_DEF_ERROR_CODE(0, 0x0215) #define TSDB_CODE_TSC_SQL_SYNTAX_ERROR TAOS_DEF_ERROR_CODE(0, 0x0216) #define TSDB_CODE_TSC_DB_NOT_SELECTED TAOS_DEF_ERROR_CODE(0, 0x0217) -#define TSDB_CODE_TSC_INVALID_TABLE_NAME TAOS_DEF_ERROR_CODE(0, 0x0218) +//#define TSDB_CODE_TSC_INVALID_TABLE_NAME TAOS_DEF_ERROR_CODE(0, 0x0218) #define TSDB_CODE_TSC_EXCEED_SQL_LIMIT TAOS_DEF_ERROR_CODE(0, 0x0219) #define TSDB_CODE_TSC_FILE_EMPTY TAOS_DEF_ERROR_CODE(0, 0x021A) #define TSDB_CODE_TSC_LINE_SYNTAX_ERROR TAOS_DEF_ERROR_CODE(0, 0x021B) @@ -159,6 +165,8 @@ int32_t* taosGetErrno(); #define TSDB_CODE_TSC_QUERY_KILLED TAOS_DEF_ERROR_CODE(0, 0X022D) #define TSDB_CODE_TSC_NO_EXEC_NODE TAOS_DEF_ERROR_CODE(0, 0X022E) #define TSDB_CODE_TSC_NOT_STABLE_ERROR TAOS_DEF_ERROR_CODE(0, 0X022F) +#define TSDB_CODE_TSC_STMT_CACHE_ERROR TAOS_DEF_ERROR_CODE(0, 0X0230) +#define TSDB_CODE_TSC_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0X0231) // mnode-common // #define TSDB_CODE_MND_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0300) // 2.x @@ -215,6 +223,7 @@ int32_t* taosGetErrno(); // #define TSDB_CODE_MND_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x033C) // 2.x // #define TSDB_CODE_MND_DNODE_ID_NOT_CONFIGUREDTAOS_DEF_ERROR_CODE(0, 0x033D) // 2.x // #define TSDB_CODE_MND_DNODE_EP_NOT_CONFIGUREDTAOS_DEF_ERROR_CODE(0, 0x033E) // 2.x +#define TSDB_CODE_MND_DNODE_DIFF_CLUSTER TAOS_DEF_ERROR_CODE(0, 0x033F) // internal // mnode-acct #define TSDB_CODE_MND_ACCT_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0340) @@ -232,6 +241,8 @@ int32_t* taosGetErrno(); #define TSDB_CODE_MND_TOO_MANY_USERS TAOS_DEF_ERROR_CODE(0, 0x0355) #define TSDB_CODE_MND_INVALID_ALTER_OPER TAOS_DEF_ERROR_CODE(0, 0x0356) #define TSDB_CODE_MND_AUTH_FAILURE TAOS_DEF_ERROR_CODE(0, 0x0357) +#define TSDB_CODE_MND_USER_NOT_AVAILABLE TAOS_DEF_ERROR_CODE(0, 0x0358) +#define TSDB_CODE_MND_PRIVILEDGE_EXIST TAOS_DEF_ERROR_CODE(0, 0x0359) // mnode-stable-part1 #define TSDB_CODE_MND_STB_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0360) @@ -250,6 +261,8 @@ int32_t* taosGetErrno(); // #define TSDB_CODE_MND_INVALID_STABLE_NAME TAOS_DEF_ERROR_CODE(0, 0x036D) // 2.x #define TSDB_CODE_MND_INVALID_STB_OPTION TAOS_DEF_ERROR_CODE(0, 0x036E) #define TSDB_CODE_MND_INVALID_ROW_BYTES TAOS_DEF_ERROR_CODE(0, 0x036F) +#define TSDB_CODE_MND_FIELD_VALUE_OVERFLOW TAOS_DEF_ERROR_CODE(0, 0x0370) + // mnode-func #define TSDB_CODE_MND_INVALID_FUNC_NAME TAOS_DEF_ERROR_CODE(0, 0x0370) @@ -263,6 +276,8 @@ int32_t* taosGetErrno(); #define TSDB_CODE_MND_INVALID_FUNC_COMMENT TAOS_DEF_ERROR_CODE(0, 0x0378) #define TSDB_CODE_MND_INVALID_FUNC_RETRIEVE TAOS_DEF_ERROR_CODE(0, 0x0379) + + // mnode-db #define TSDB_CODE_MND_DB_NOT_SELECTED TAOS_DEF_ERROR_CODE(0, 0x0380) #define TSDB_CODE_MND_DB_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0381) // @@ -276,6 +291,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_MND_INVALID_DB_ACCT TAOS_DEF_ERROR_CODE(0, 0x0389) // internal #define TSDB_CODE_MND_DB_OPTION_UNCHANGED TAOS_DEF_ERROR_CODE(0, 0x038A) // #define TSDB_CODE_MND_DB_INDEX_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x038B) +#define TSDB_CODE_MND_DB_RETENTION_PERIOD_ZERO TAOS_DEF_ERROR_CODE(0, 0x038C) // #define TSDB_CODE_MND_INVALID_DB_OPTION_DAYS TAOS_DEF_ERROR_CODE(0, 0x0390) // 2.x // #define TSDB_CODE_MND_INVALID_DB_OPTION_KEEP TAOS_DEF_ERROR_CODE(0, 0x0391) // 2.x // #define TSDB_CODE_MND_INVALID_TOPIC TAOS_DEF_ERROR_CODE(0, 0x0392) // 2.x @@ -357,12 +373,18 @@ int32_t* taosGetErrno(); #define TSDB_CODE_MND_STREAM_TASK_DROPPED TAOS_DEF_ERROR_CODE(0, 0x03F4) #define TSDB_CODE_MND_MULTI_REPLICA_SOURCE_DB TAOS_DEF_ERROR_CODE(0, 0x03F5) #define TSDB_CODE_MND_TOO_MANY_STREAMS TAOS_DEF_ERROR_CODE(0, 0x03F6) +#define TSDB_CODE_MND_INVALID_TARGET_TABLE TAOS_DEF_ERROR_CODE(0, 0x03F7) // mnode-sma #define TSDB_CODE_MND_SMA_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0480) #define TSDB_CODE_MND_SMA_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0481) #define TSDB_CODE_MND_INVALID_SMA_OPTION TAOS_DEF_ERROR_CODE(0, 0x0482) +// mnode-tag-indxe + +#define TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x0483) +#define TSDB_CODE_MND_TAG_INDEX_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x0484) + // dnode // #define TSDB_CODE_DND_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0400) // 2.x // #define TSDB_CODE_DND_OUT_OF_MEMORY TAOS_DEF_ERROR_CODE(0, 0x0401) // 2.x @@ -415,6 +437,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_VND_NO_AVAIL_BUFPOOL TAOS_DEF_ERROR_CODE(0, 0x0528) #define TSDB_CODE_VND_STOPPED TAOS_DEF_ERROR_CODE(0, 0x0529) #define TSDB_CODE_VND_DUP_REQUEST TAOS_DEF_ERROR_CODE(0, 0x0530) +#define TSDB_CODE_VND_QUERY_BUSY TAOS_DEF_ERROR_CODE(0, 0x0531) // tsdb #define TSDB_CODE_TDB_INVALID_TABLE_ID TAOS_DEF_ERROR_CODE(0, 0x0600) @@ -523,7 +546,8 @@ int32_t* taosGetErrno(); #define TSDB_CODE_SYN_BATCH_ERROR TAOS_DEF_ERROR_CODE(0, 0x0913) #define TSDB_CODE_SYN_RESTORING TAOS_DEF_ERROR_CODE(0, 0x0914) #define TSDB_CODE_SYN_INVALID_SNAPSHOT_MSG TAOS_DEF_ERROR_CODE(0, 0x0915) // internal -#define TSDB_CODE_SYN_BUFFER_FULL TAOS_DEF_ERROR_CODE(0, 0x0916) // +#define TSDB_CODE_SYN_BUFFER_FULL TAOS_DEF_ERROR_CODE(0, 0x0916) +#define TSDB_CODE_SYN_WRITE_STALL TAOS_DEF_ERROR_CODE(0, 0x0917) #define TSDB_CODE_SYN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x09FF) // tq @@ -623,7 +647,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_PAR_INCORRECT_NUM_OF_COL TAOS_DEF_ERROR_CODE(0, 0x2634) #define TSDB_CODE_PAR_INCORRECT_TIMESTAMP_VAL TAOS_DEF_ERROR_CODE(0, 0x2635) #define TSDB_CODE_PAR_OFFSET_LESS_ZERO TAOS_DEF_ERROR_CODE(0, 0x2637) -#define TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_BY TAOS_DEF_ERROR_CODE(0, 0x2638) +#define TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_GROUP_BY TAOS_DEF_ERROR_CODE(0, 0x2638) #define TSDB_CODE_PAR_INVALID_TOPIC_QUERY TAOS_DEF_ERROR_CODE(0, 0x2639) #define TSDB_CODE_PAR_INVALID_DROP_STABLE TAOS_DEF_ERROR_CODE(0, 0x263A) #define TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE TAOS_DEF_ERROR_CODE(0, 0x263B) @@ -668,6 +692,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_PAR_NOT_SUPPORT_JOIN TAOS_DEF_ERROR_CODE(0, 0x2664) #define TSDB_CODE_PAR_INVALID_TAGS_PC TAOS_DEF_ERROR_CODE(0, 0x2665) #define TSDB_CODE_PAR_INVALID_TIMELINE_QUERY TAOS_DEF_ERROR_CODE(0, 0x2666) +#define TSDB_CODE_PAR_INVALID_OPTR_USAGE TAOS_DEF_ERROR_CODE(0, 0x2667) #define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x26FF) //planner @@ -694,6 +719,8 @@ int32_t* taosGetErrno(); #define TSDB_CODE_UDF_NO_FUNC_HANDLE TAOS_DEF_ERROR_CODE(0, 0x2908) #define TSDB_CODE_UDF_INVALID_BUFSIZE TAOS_DEF_ERROR_CODE(0, 0x2909) #define TSDB_CODE_UDF_INVALID_OUTPUT_TYPE TAOS_DEF_ERROR_CODE(0, 0x290A) +#define TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED TAOS_DEF_ERROR_CODE(0, 0x290B) +#define TSDB_CODE_UDF_FUNC_EXEC_FAILURE TAOS_DEF_ERROR_CODE(0, 0x290C) // sml #define TSDB_CODE_SML_INVALID_PROTOCOL_TYPE TAOS_DEF_ERROR_CODE(0, 0x3000) @@ -701,6 +728,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_SML_INVALID_DATA TAOS_DEF_ERROR_CODE(0, 0x3002) #define TSDB_CODE_SML_INVALID_DB_CONF TAOS_DEF_ERROR_CODE(0, 0x3003) #define TSDB_CODE_SML_NOT_SAME_TYPE TAOS_DEF_ERROR_CODE(0, 0x3004) +#define TSDB_CODE_SML_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x3005) //tsma #define TSDB_CODE_TSMA_INIT_FAILED TAOS_DEF_ERROR_CODE(0, 0x3100) @@ -716,7 +744,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_RSMA_INVALID_ENV TAOS_DEF_ERROR_CODE(0, 0x3150) #define TSDB_CODE_RSMA_INVALID_STAT TAOS_DEF_ERROR_CODE(0, 0x3151) #define TSDB_CODE_RSMA_QTASKINFO_CREATE TAOS_DEF_ERROR_CODE(0, 0x3152) -// #define TSDB_CODE_RSMA_FILE_CORRUPTED TAOS_DEF_ERROR_CODE(0, 0x3153) +#define TSDB_CODE_RSMA_FS_COMMIT TAOS_DEF_ERROR_CODE(0, 0x3153) #define TSDB_CODE_RSMA_REMOVE_EXISTS TAOS_DEF_ERROR_CODE(0, 0x3154) #define TSDB_CODE_RSMA_FETCH_MSG_MSSED_UP TAOS_DEF_ERROR_CODE(0, 0x3155) #define TSDB_CODE_RSMA_EMPTY_INFO TAOS_DEF_ERROR_CODE(0, 0x3156) @@ -724,6 +752,9 @@ int32_t* taosGetErrno(); #define TSDB_CODE_RSMA_REGEX_MATCH TAOS_DEF_ERROR_CODE(0, 0x3158) #define TSDB_CODE_RSMA_STREAM_STATE_OPEN TAOS_DEF_ERROR_CODE(0, 0x3159) #define TSDB_CODE_RSMA_STREAM_STATE_COMMIT TAOS_DEF_ERROR_CODE(0, 0x3160) +#define TSDB_CODE_RSMA_FS_REF TAOS_DEF_ERROR_CODE(0, 0x3161) +#define TSDB_CODE_RSMA_FS_SYNC TAOS_DEF_ERROR_CODE(0, 0x3162) +#define TSDB_CODE_RSMA_FS_UPDATE TAOS_DEF_ERROR_CODE(0, 0x3163) //index #define TSDB_CODE_INDEX_REBUILDING TAOS_DEF_ERROR_CODE(0, 0x3200) @@ -733,6 +764,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_TMQ_INVALID_MSG TAOS_DEF_ERROR_CODE(0, 0x4000) #define TSDB_CODE_TMQ_CONSUMER_MISMATCH TAOS_DEF_ERROR_CODE(0, 0x4001) #define TSDB_CODE_TMQ_CONSUMER_CLOSED TAOS_DEF_ERROR_CODE(0, 0x4002) +#define TSDB_CODE_TMQ_CONSUMER_ERROR TAOS_DEF_ERROR_CODE(0, 0x4003) // stream #define TSDB_CODE_STREAM_TASK_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x4100) diff --git a/include/util/tarray.h b/include/util/tarray.h index af9cf5fde1a4b17bcc628854f97011e2a1b893c7..4bf24b46b9d913c00d11b5ef53f8630f3ad4dbf5 100644 --- a/include/util/tarray.h +++ b/include/util/tarray.h @@ -22,19 +22,6 @@ extern "C" { #endif -#if 0 -#define TARRAY(TYPE) \ - struct { \ - int32_t tarray_size_; \ - int32_t tarray_neles_; \ - struct TYPE* td_array_data_; \ - } - -#define TARRAY_SIZE(ARRAY) (ARRAY)->tarray_size_ -#define TARRAY_NELES(ARRAY) (ARRAY)->tarray_neles_ -#define TARRAY_ELE_AT(ARRAY, IDX) ((ARRAY)->td_array_data_ + idx) -#endif - #define TARRAY_MIN_SIZE 8 #define TARRAY_GET_ELEM(array, index) ((void*)((char*)((array)->pData) + (index) * (array)->elemSize)) #define TARRAY_ELEM_IDX(array, ele) (POINTER_DISTANCE(ele, (array)->pData) / (array)->elemSize) @@ -46,6 +33,9 @@ typedef struct SArray { void* pData; } SArray; +#define TARRAY_SIZE(array) ((array)->size) +#define TARRAY_DATA(array) ((array)->pData) + /** * * @param size @@ -53,7 +43,7 @@ typedef struct SArray { * @return */ SArray* taosArrayInit(size_t size, size_t elemSize); -SArray* taosArrayInit_s(size_t size, size_t elemSize, size_t initialSize); +SArray* taosArrayInit_s(size_t elemSize, size_t initialSize); /** * @@ -79,14 +69,6 @@ void* taosArrayAddBatch(SArray* pArray, const void* pData, int32_t nEles); */ void taosArrayRemoveDuplicate(SArray* pArray, __compar_fn_t comparFn, void (*fp)(void*)); -/** - * - * @param pArray - * @param comparFn - * @param fp - */ -void taosArrayRemoveDuplicateP(SArray* pArray, __compar_fn_t comparFn, void (*fp)(void*)); - /** * add all element from the source array list into the destination * @param pArray @@ -187,6 +169,13 @@ void taosArrayPopTailBatch(SArray* pArray, size_t cnt); */ void taosArrayRemove(SArray* pArray, size_t index); +/** + * remove batch entry from the given index + * @param pArray + * @param index + */ +void taosArrayRemoveBatch(SArray* pArray, size_t index, size_t num, FDelete fp); + /** * copy the whole array from source to destination * @param pDst @@ -219,6 +208,8 @@ void taosArrayDestroyP(SArray* pArray, FDelete fp); void taosArrayDestroyEx(SArray* pArray, FDelete fp); +void taosArraySwap(SArray* a, SArray* b); + /** * sort the array * @param pArray @@ -255,14 +246,6 @@ void taosArraySortPWithExt(SArray* pArray, __ext_compar_fn_t fn, const void* par int32_t taosEncodeArray(void** buf, const SArray* pArray, FEncode encode); void* taosDecodeArray(const void* buf, SArray** pArray, FDecode decode, int32_t dataSz); -/** - * swap array - * @param a - * @param b - * @return - */ -void taosArraySwap(SArray* a, SArray* b); - #ifdef __cplusplus } #endif diff --git a/include/util/tdef.h b/include/util/tdef.h index e03352d98b455c449e0b05c7da553b249111e074..680620a094342b5bab9d50c8a4962c79e0de29f2 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -104,6 +104,7 @@ extern const int32_t TYPE_BYTES[16]; #define TSDB_INDEX_TYPE_SMA "SMA" #define TSDB_INDEX_TYPE_FULLTEXT "FULLTEXT" +#define TSDB_INDEX_TYPE_NORMAL "NORMAL" #define TSDB_INS_USER_STABLES_DBNAME_COLID 2 @@ -190,21 +191,23 @@ typedef enum ELogicConditionType { #define TSDB_MIN_COLUMNS 2 // PRIMARY COLUMN(timestamp) + other columns #define TSDB_NODE_NAME_LEN 64 -#define TSDB_TABLE_NAME_LEN 193 // it is a null-terminated string -#define TSDB_TOPIC_NAME_LEN 193 // it is a null-terminated string -#define TSDB_CGROUP_LEN 193 // it is a null-terminated string -#define TSDB_STREAM_NAME_LEN 193 // it is a null-terminated string +#define TSDB_TABLE_NAME_LEN 193 // it is a null-terminated string +#define TSDB_TOPIC_NAME_LEN 193 // it is a null-terminated string +#define TSDB_CGROUP_LEN 193 // it is a null-terminated string +#define TSDB_USER_CGROUP_LEN (TSDB_USER_LEN + TSDB_CGROUP_LEN) // it is a null-terminated string +#define TSDB_STREAM_NAME_LEN 193 // it is a null-terminated string #define TSDB_DB_NAME_LEN 65 #define TSDB_DB_FNAME_LEN (TSDB_ACCT_ID_LEN + TSDB_DB_NAME_LEN + TSDB_NAME_DELIMITER_LEN) +#define TSDB_PRIVILEDGE_CONDITION_LEN 200 #define TSDB_FUNC_NAME_LEN 65 #define TSDB_FUNC_COMMENT_LEN 1024 * 1024 #define TSDB_FUNC_CODE_LEN 10 * 1024 * 1024 -#define TSDB_FUNC_BUF_SIZE 512 +#define TSDB_FUNC_BUF_SIZE 4096 * 64 #define TSDB_FUNC_TYPE_SCALAR 1 #define TSDB_FUNC_TYPE_AGGREGATE 2 #define TSDB_FUNC_SCRIPT_BIN_LIB 0 -#define TSDB_FUNC_SCRIPT_LUA 1 +#define TSDB_FUNC_SCRIPT_PYTHON 1 #define TSDB_FUNC_MAX_RETRIEVE 1024 #define TSDB_INDEX_NAME_LEN 65 // 64 + 1 '\0' @@ -246,7 +249,7 @@ typedef enum ELogicConditionType { #define TSDB_AUTH_LEN 16 #define TSDB_PASSWORD_LEN 32 #define TSDB_USET_PASSWORD_LEN 129 -#define TSDB_VERSION_LEN 12 +#define TSDB_VERSION_LEN 32 #define TSDB_LABEL_LEN 8 #define TSDB_JOB_STATUS_LEN 32 @@ -281,8 +284,8 @@ typedef enum ELogicConditionType { #define TSDB_DNODE_ROLE_MGMT 1 #define TSDB_DNODE_ROLE_VNODE 2 -#define TSDB_MAX_REPLICA 5 -#define TSDB_SYNC_LOG_BUFFER_SIZE 4096 +#define TSDB_MAX_REPLICA 5 +#define TSDB_SYNC_LOG_BUFFER_SIZE 4096 #define TSDB_SYNC_LOG_BUFFER_RETENTION (TSDB_SYNC_LOG_BUFFER_SIZE >> 4) #define TSDB_TBNAME_COLUMN_INDEX (-1) @@ -314,10 +317,10 @@ typedef enum ELogicConditionType { #define TSDB_MAX_KEEP_NS (365 * 292 * 1440) // data in db to be reserved. #define TSDB_DEFAULT_KEEP (3650 * 1440) // ten years #define TSDB_MIN_MINROWS_FBLOCK 10 -#define TSDB_MAX_MINROWS_FBLOCK 1000 +#define TSDB_MAX_MINROWS_FBLOCK 1000000 #define TSDB_DEFAULT_MINROWS_FBLOCK 100 #define TSDB_MIN_MAXROWS_FBLOCK 200 -#define TSDB_MAX_MAXROWS_FBLOCK 10000 +#define TSDB_MAX_MAXROWS_FBLOCK 10000000 #define TSDB_DEFAULT_MAXROWS_FBLOCK 4096 #define TSDB_MIN_FSYNC_PERIOD 0 #define TSDB_MAX_FSYNC_PERIOD 180000 // millisecond @@ -365,11 +368,11 @@ typedef enum ELogicConditionType { #define TSDB_MIN_STT_TRIGGER 1 #define TSDB_MAX_STT_TRIGGER 16 #define TSDB_DEFAULT_SST_TRIGGER 1 -#define TSDB_MIN_HASH_PREFIX 0 -#define TSDB_MAX_HASH_PREFIX 128 +#define TSDB_MIN_HASH_PREFIX (2 - TSDB_TABLE_NAME_LEN) +#define TSDB_MAX_HASH_PREFIX (TSDB_TABLE_NAME_LEN - 2) #define TSDB_DEFAULT_HASH_PREFIX 0 -#define TSDB_MIN_HASH_SUFFIX 0 -#define TSDB_MAX_HASH_SUFFIX 128 +#define TSDB_MIN_HASH_SUFFIX (2 - TSDB_TABLE_NAME_LEN) +#define TSDB_MAX_HASH_SUFFIX (TSDB_TABLE_NAME_LEN - 2) #define TSDB_DEFAULT_HASH_SUFFIX 0 #define TSDB_DB_MIN_WAL_RETENTION_PERIOD -1 @@ -413,7 +416,7 @@ typedef enum ELogicConditionType { #ifdef WINDOWS #define TSDB_MAX_RPC_THREADS 4 // windows pipe only support 4 connections. #else -#define TSDB_MAX_RPC_THREADS 20 +#define TSDB_MAX_RPC_THREADS 10 #endif #define TSDB_QUERY_TYPE_NON_TYPE 0x00u // none type diff --git a/include/util/tencode.h b/include/util/tencode.h index a6dd58297e8c1dba644d86eb5145b273406fbf9e..ff97a205073822be2c98e39469066a0470794a51 100644 --- a/include/util/tencode.h +++ b/include/util/tencode.h @@ -116,6 +116,7 @@ static int32_t tEncodeI64v(SEncoder* pCoder, int64_t val); static int32_t tEncodeFloat(SEncoder* pCoder, float val); static int32_t tEncodeDouble(SEncoder* pCoder, double val); static int32_t tEncodeBinary(SEncoder* pCoder, const uint8_t* val, uint32_t len); +static int32_t tEncodeBinaryEx(SEncoder* pCoder, const uint8_t* val, uint32_t len); static int32_t tEncodeCStrWithLen(SEncoder* pCoder, const char* val, uint32_t len); static int32_t tEncodeCStr(SEncoder* pCoder, const char* val); diff --git a/include/util/tlog.h b/include/util/tlog.h index 4311719ca575e2ccc69d3281d8f49d1e006d24aa..541b7589b799f4c1821430b692c31aa179e669b6 100644 --- a/include/util/tlog.h +++ b/include/util/tlog.h @@ -89,20 +89,19 @@ bool taosAssertRelease(bool condition); // Disable all asserts that may compromise the performance. #if defined DISABLE_ASSERT #define ASSERT(condition) -#define ASSERTS(condition, ...) (0) +#define ASSERTS(condition, ...) (0) #else -#define ASSERTS(condition, ...) taosAssertDebug(condition, __FILE__, __LINE__, __VA_ARGS__) +#define ASSERTS(condition, ...) ((condition) ? false : taosAssertDebug(condition, __FILE__, __LINE__, __VA_ARGS__)) #ifdef NDEBUG #define ASSERT(condition) taosAssertRelease(condition) #else -#define ASSERT(condition) taosAssertDebug(condition, __FILE__, __LINE__, "assert info not provided") +#define ASSERT(condition) ASSERTS(condition, "assert info not provided") #endif #endif -void taosLogCrashInfo(char* nodeType, char* pMsg, int64_t msgLen, int signum, void *sigInfo); -void taosReadCrashInfo(char* filepath, char** pMsg, int64_t* pMsgLen, TdFilePtr* pFd); -void taosReleaseCrashLogFile(TdFilePtr pFile, bool truncateFile); -int32_t taosGenCrashJsonMsg(int signum, char** pMsg, int64_t clusterId, int64_t startTime); +void taosLogCrashInfo(char *nodeType, char *pMsg, int64_t msgLen, int signum, void *sigInfo); +void taosReadCrashInfo(char *filepath, char **pMsg, int64_t *pMsgLen, TdFilePtr *pFd); +void taosReleaseCrashLogFile(TdFilePtr pFile, bool truncateFile); // clang-format off #define uFatal(...) { if (uDebugFlag & DEBUG_FATAL) { taosPrintLog("UTL FATAL", DEBUG_FATAL, tsLogEmbedded ? 255 : uDebugFlag, __VA_ARGS__); }} @@ -116,7 +115,7 @@ int32_t taosGenCrashJsonMsg(int signum, char** pMsg, int64_t clusterId, int64_t #define pError(...) { taosPrintLog("APP ERROR ", DEBUG_ERROR, 255, __VA_ARGS__); } #define pPrint(...) { taosPrintLog("APP ", DEBUG_INFO, 255, __VA_ARGS__); } // clang-format on -//#define BUF_PAGE_DEBUG +// #define BUF_PAGE_DEBUG #ifdef __cplusplus } #endif diff --git a/include/util/tlrucache.h b/include/util/tlrucache.h index 19009342484bce74c5173e7bf61ab52d6ddae767..c9cf71c2fd99398bd3f5e55bd08127f4278ed1f4 100644 --- a/include/util/tlrucache.h +++ b/include/util/tlrucache.h @@ -55,6 +55,8 @@ void *taosLRUCacheValue(SLRUCache *cache, LRUHandle *handle); size_t taosLRUCacheGetUsage(SLRUCache *cache); size_t taosLRUCacheGetPinnedUsage(SLRUCache *cache); +int32_t taosLRUCacheGetElems(SLRUCache *cache); + void taosLRUCacheSetCapacity(SLRUCache *cache, size_t capacity); size_t taosLRUCacheGetCapacity(SLRUCache *cache); diff --git a/include/util/tqueue.h b/include/util/tqueue.h index 1f6b205cdf8a2faa045a7a08b9008cb271a741a1..d05b5418b37d1506d52f7b211c3c92db53dabc85 100644 --- a/include/util/tqueue.h +++ b/include/util/tqueue.h @@ -61,7 +61,7 @@ typedef void (*FItems)(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfItems); typedef struct STaosQnode STaosQnode; -typedef struct STaosQnode { +struct STaosQnode { STaosQnode *next; STaosQueue *queue; int64_t timestamp; @@ -70,9 +70,9 @@ typedef struct STaosQnode { int8_t itype; int8_t reserved[3]; char item[]; -} STaosQnode; +}; -typedef struct STaosQueue { +struct STaosQueue { STaosQnode *head; STaosQnode *tail; STaosQueue *next; // for queue set @@ -84,22 +84,22 @@ typedef struct STaosQueue { int64_t memOfItems; int32_t numOfItems; int64_t threadId; -} STaosQueue; +}; -typedef struct STaosQset { +struct STaosQset { STaosQueue *head; STaosQueue *current; TdThreadMutex mutex; tsem_t sem; int32_t numOfQueues; int32_t numOfItems; -} STaosQset; +}; -typedef struct STaosQall { +struct STaosQall { STaosQnode *current; STaosQnode *start; int32_t numOfItems; -} STaosQall; +}; STaosQueue *taosOpenQueue(); void taosCloseQueue(STaosQueue *queue); diff --git a/include/util/trbtree.h b/include/util/trbtree.h index 7c93c8dd8d65f2c4947019f370c0933e6ad81ee0..e2264194401bee65a22f0301f0339cb76a8d7356 100644 --- a/include/util/trbtree.h +++ b/include/util/trbtree.h @@ -33,9 +33,12 @@ typedef int32_t (*tRBTreeCmprFn)(const SRBTreeNode *, const SRBTreeNode *); #define tRBTreeMax(T) ((T)->max == ((T)->NIL) ? NULL : (T)->max) void tRBTreeCreate(SRBTree *pTree, tRBTreeCmprFn cmprFn); +void tRBTreeClear(SRBTree *pTree); SRBTreeNode *tRBTreePut(SRBTree *pTree, SRBTreeNode *z); void tRBTreeDrop(SRBTree *pTree, SRBTreeNode *z); SRBTreeNode *tRBTreeDropByKey(SRBTree *pTree, void *pKey); +SRBTreeNode *tRBTreeDropMin(SRBTree *pTree); +SRBTreeNode *tRBTreeDropMax(SRBTree *pTree); SRBTreeNode *tRBTreeGet(SRBTree *pTree, const SRBTreeNode *pKeyNode); // SRBTreeIter ============================================= diff --git a/include/util/tsimplehash.h b/include/util/tsimplehash.h index c9df9114763549da1b88c551f9efcc421e0e5c14..987a9fe2a847549bd9eb645fc33b880ed9773186 100644 --- a/include/util/tsimplehash.h +++ b/include/util/tsimplehash.h @@ -48,6 +48,13 @@ SSHashObj *tSimpleHashInit(size_t capacity, _hash_fn_t fn); */ int32_t tSimpleHashGetSize(const SSHashObj *pHashObj); +/** + * set the free function pointer + * @param pHashObj + * @param freeFp + */ +void tSimpleHashSetFreeFp(SSHashObj* pHashObj, _hash_free_fn_t freeFp); + int32_t tSimpleHashPrint(const SSHashObj *pHashObj); /** diff --git a/include/util/ttrace.h b/include/util/ttrace.h index 5cdb1eecaaa249f27bccd108072e803f771d2517..e672882f57960cef28d4deb700637b3027c1e0c4 100644 --- a/include/util/ttrace.h +++ b/include/util/ttrace.h @@ -59,11 +59,13 @@ typedef struct STraceId { char* _t = _buf; \ _t[0] = '0'; \ _t[1] = 'x'; \ - _t += titoa(rootId, 16, &_t[2]); \ + _t += 2; \ + _t += titoa(rootId, 16, &_t[0]); \ _t[0] = ':'; \ _t[1] = '0'; \ _t[2] = 'x'; \ - _t += titoa(msgId, 16, &_t[3]); \ + _t += 3; \ + _t += titoa(msgId, 16, &_t[0]); \ } while (0) #ifdef __cplusplus diff --git a/include/util/tutil.h b/include/util/tutil.h index e0801e529507bd3152037e646895f66c6eefa35c..7a59aa170aa0f0011ec55cbb5507047c6c5d2a21 100644 --- a/include/util/tutil.h +++ b/include/util/tutil.h @@ -81,14 +81,22 @@ static FORCE_INLINE void taosEncryptPass_c(uint8_t *inBuf, size_t len, char *tar static FORCE_INLINE int32_t taosGetTbHashVal(const char *tbname, int32_t tblen, int32_t method, int32_t prefix, int32_t suffix) { - if (prefix == 0 && suffix == 0) { + if ((prefix == 0 && suffix == 0) || (tblen <= (prefix + suffix)) || (tblen <= -1 * (prefix + suffix)) || prefix * suffix < 0) { return MurmurHash3_32(tbname, tblen); + } else if (prefix > 0 || suffix > 0) { + return MurmurHash3_32(tbname + prefix, tblen - prefix - suffix); } else { - if (tblen <= (prefix + suffix)) { - return MurmurHash3_32(tbname, tblen); - } else { - return MurmurHash3_32(tbname + prefix, tblen - prefix - suffix); + char tbName[TSDB_TABLE_FNAME_LEN]; + int32_t offset = 0; + if (prefix < 0) { + offset = -1 * prefix; + strncpy(tbName, tbname, offset); } + if (suffix < 0) { + strncpy(tbName + offset, tbname + tblen + suffix, -1 * suffix); + offset += -1 *suffix; + } + return MurmurHash3_32(tbName, offset); } } @@ -98,6 +106,8 @@ static FORCE_INLINE int32_t taosGetTbHashVal(const char *tbname, int32_t tblen, goto LABEL; \ } +#define VND_CHECK_CODE(CODE, LINO, LABEL) TSDB_CHECK_CODE(CODE, LINO, LABEL) + #ifdef __cplusplus } #endif diff --git a/include/util/tversion.h b/include/util/tversion.h index c924752a01f52f01f2cb40dbc6e16770f23d1ea2..f5c42b2a224d24d2dc2a951ec981de9c878ef0df 100644 --- a/include/util/tversion.h +++ b/include/util/tversion.h @@ -13,8 +13,8 @@ * along with this program. If not, see . */ -#ifndef _TD_UTIL_VERSION_H_ -#define _TD_UTIL_VERSION_H_ +#ifndef _TD_UTIL_TVERSION_H_ +#define _TD_UTIL_TVERSION_H_ #include "os.h" @@ -25,9 +25,11 @@ extern "C" { int32_t taosVersionStrToInt(const char *vstr, int32_t *vint); int32_t taosVersionIntToStr(int32_t vint, char *vstr, int32_t len); int32_t taosCheckVersionCompatible(int32_t clientVer, int32_t serverVer, int32_t comparedSegments); +int32_t taosCheckVersionCompatibleFromStr(const char *pClientVersion, const char *pServerVersion, + int32_t comparedSegments); #ifdef __cplusplus } #endif -#endif /*_TD_UTIL_VERSION_H_*/ +#endif /*_TD_UTIL_TVERSION_H_*/ diff --git a/include/util/tworker.h b/include/util/tworker.h index 0636f16dbbd50b709de18ce556d8a9dcbdcfba8d..8508adf052bf8eb368dd9846d0a5e1ada1bb6e6e 100644 --- a/include/util/tworker.h +++ b/include/util/tworker.h @@ -26,12 +26,12 @@ extern "C" { typedef struct SQWorkerPool SQWorkerPool; typedef struct SWWorkerPool SWWorkerPool; -typedef struct SQWorker { +typedef struct SQueueWorker { int32_t id; // worker id int64_t pid; // thread pid TdThread thread; // thread id void *pool; -} SQWorker; +} SQueueWorker; typedef struct SQWorkerPool { int32_t max; // max number of workers @@ -39,7 +39,7 @@ typedef struct SQWorkerPool { int32_t num; // current number of workers STaosQset *qset; const char *name; - SQWorker *workers; + SQueueWorker *workers; TdThreadMutex mutex; } SQWorkerPool; diff --git a/include/util/version.h b/include/util/version.h index bac29e5baf6f7a754aa6d1b0bcfd2a06b841b0da..b241dd248b9a673591bbc94e1a71a78ad721919e 100644 --- a/include/util/version.h +++ b/include/util/version.h @@ -23,6 +23,7 @@ extern "C" { extern char version[]; extern char compatible_version[]; extern char gitinfo[]; +extern char gitinfoOfInternal[]; extern char buildinfo[]; #ifdef __cplusplus diff --git a/include/util/xxhash.h b/include/util/xxhash.h deleted file mode 100644 index d6bad943358d37e01471681e4c2b25d0c2275e87..0000000000000000000000000000000000000000 --- a/include/util/xxhash.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - xxHash - Extremely Fast Hash algorithm - Header File - Copyright (C) 2012-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - xxHash source repository : https://github.com/Cyan4973/xxHash -*/ - -/* Notice extracted from xxHash homepage : - -xxHash is an extremely fast Hash algorithm, running at RAM speed limits. -It also successfully passes all tests from the SMHasher suite. - -Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) - -Name Speed Q.Score Author -xxHash 5.4 GB/s 10 -CrapWow 3.2 GB/s 2 Andrew -MumurHash 3a 2.7 GB/s 10 Austin Appleby -SpookyHash 2.0 GB/s 10 Bob Jenkins -SBox 1.4 GB/s 9 Bret Mulvey -Lookup3 1.2 GB/s 9 Bob Jenkins -SuperFastHash 1.2 GB/s 1 Paul Hsieh -CityHash64 1.05 GB/s 10 Pike & Alakuijala -FNV 0.55 GB/s 5 Fowler, Noll, Vo -CRC32 0.43 GB/s 9 -MD5-32 0.33 GB/s 10 Ronald L. Rivest -SHA1-32 0.28 GB/s 10 - -Q.Score is a measure of quality of the hash function. -It depends on successfully passing SMHasher test set. -10 is a perfect score. - -A 64-bit version, named XXH64, is available since r35. -It offers much better speed, but for 64-bit applications only. -Name Speed on 64 bits Speed on 32 bits -XXH64 13.8 GB/s 1.9 GB/s -XXH32 6.8 GB/s 6.0 GB/s -*/ - -#ifndef XXHASH_H_5627135585666179 -#define XXHASH_H_5627135585666179 1 - -#if defined (__cplusplus) -extern "C" { -#endif - - -/* **************************** -* Definitions -******************************/ -#include /* size_t */ -typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; - - -/* **************************** - * API modifier - ******************************/ -/** XXH_INLINE_ALL (and XXH_PRIVATE_API) - * This is useful to include xxhash functions in `static` mode - * in order to inline them, and remove their symbol from the public list. - * Inlining can offer dramatic performance improvement on small keys. - * Methodology : - * #define XXH_INLINE_ALL - * #include "xxhash.h" - * `xxhash.c` is automatically included. - * It's not useful to compile and link it as a separate module. - */ -#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) -# ifndef XXH_STATIC_LINKING_ONLY -# define XXH_STATIC_LINKING_ONLY -# endif -# if defined(__GNUC__) -# define XXH_PUBLIC_API static __inline __attribute__((unused)) -# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) -# define XXH_PUBLIC_API static inline -# elif defined(_MSC_VER) -# define XXH_PUBLIC_API static __inline -# else - /* this version may generate warnings for unused static functions */ -# define XXH_PUBLIC_API static -# endif -#else -# define XXH_PUBLIC_API /* do nothing */ -#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ - -/*! XXH_NAMESPACE, aka Namespace Emulation : - * - * If you want to include _and expose_ xxHash functions from within your own library, - * but also want to avoid symbol collisions with other libraries which may also include xxHash, - * - * you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library - * with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values). - * - * Note that no change is required within the calling program as long as it includes `xxhash.h` : - * regular symbol name will be automatically translated by this header. - */ -#ifdef XXH_NAMESPACE -# define XXH_CAT(A,B) A##B -# define XXH_NAME2(A,B) XXH_CAT(A,B) -# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) -# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) -# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) -# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) -# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) -# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) -# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) -# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) -# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) -# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) -# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) -# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) -# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) -# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) -# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) -# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) -# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) -# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) -# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) -#endif - - -/* ************************************* -* Version -***************************************/ -#define XXH_VERSION_MAJOR 0 -#define XXH_VERSION_MINOR 6 -#define XXH_VERSION_RELEASE 5 -#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) -XXH_PUBLIC_API unsigned XXH_versionNumber (void); - - -/*-********************************************************************** -* 32-bit hash -************************************************************************/ -typedef unsigned int XXH32_hash_t; - -/*! XXH32() : - Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input". - The memory between input & input+length must be valid (allocated and read-accessible). - "seed" can be used to alter the result predictably. - Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */ -XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed); - -/*====== Streaming ======*/ -typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ -XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); -XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); - -XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed); -XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); - -/* - * Streaming functions generate the xxHash of an input provided in multiple segments. - * Note that, for small input, they are slower than single-call functions, due to state management. - * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. - * - * XXH state must first be allocated, using XXH*_createState() . - * - * Start a new hash by initializing state with a seed, using XXH*_reset(). - * - * Then, feed the hash state by calling XXH*_update() as many times as necessary. - * The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. - * - * Finally, a hash value can be produced anytime, by using XXH*_digest(). - * This function returns the nn-bits hash as an int or long long. - * - * It's still possible to continue inserting input into the hash state after a digest, - * and generate some new hashes later on, by calling again XXH*_digest(). - * - * When done, free XXH state space if it was allocated dynamically. - */ - -/*====== Canonical representation ======*/ - -typedef struct { unsigned char digest[4]; } XXH32_canonical_t; -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); - -/* Default result type for XXH functions are primitive unsigned 32 and 64 bits. - * The canonical representation uses human-readable write convention, aka big-endian (large digits first). - * These functions allow transformation of hash result into and from its canonical format. - * This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. - */ - - -#ifndef XXH_NO_LONG_LONG -/*-********************************************************************** -* 64-bit hash -************************************************************************/ -typedef unsigned long long XXH64_hash_t; - -/*! XXH64() : - Calculate the 64-bit hash of sequence of length "len" stored at memory address "input". - "seed" can be used to alter the result predictably. - This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark). -*/ -XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed); - -/*====== Streaming ======*/ -typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ -XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); -XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); - -XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); - -/*====== Canonical representation ======*/ -typedef struct { unsigned char digest[8]; } XXH64_canonical_t; -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); -#endif /* XXH_NO_LONG_LONG */ - - - -#ifdef XXH_STATIC_LINKING_ONLY - -/* ================================================================================================ - This section contains declarations which are not guaranteed to remain stable. - They may change in future versions, becoming incompatible with a different version of the library. - These declarations should only be used with static linking. - Never use them in association with dynamic linking ! -=================================================================================================== */ - -/* These definitions are only present to allow - * static allocation of XXH state, on stack or in a struct for example. - * Never **ever** use members directly. */ - -#if !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - -struct XXH32_state_s { - uint32_t total_len_32; - uint32_t large_len; - uint32_t v1; - uint32_t v2; - uint32_t v3; - uint32_t v4; - uint32_t mem32[4]; - uint32_t memsize; - uint32_t reserved; /* never read nor write, might be removed in a future version */ -}; /* typedef'd to XXH32_state_t */ - -struct XXH64_state_s { - uint64_t total_len; - uint64_t v1; - uint64_t v2; - uint64_t v3; - uint64_t v4; - uint64_t mem64[4]; - uint32_t memsize; - uint32_t reserved[2]; /* never read nor write, might be removed in a future version */ -}; /* typedef'd to XXH64_state_t */ - -# else - -struct XXH32_state_s { - unsigned total_len_32; - unsigned large_len; - unsigned v1; - unsigned v2; - unsigned v3; - unsigned v4; - unsigned mem32[4]; - unsigned memsize; - unsigned reserved; /* never read nor write, might be removed in a future version */ -}; /* typedef'd to XXH32_state_t */ - -# ifndef XXH_NO_LONG_LONG /* remove 64-bit support */ -struct XXH64_state_s { - unsigned long long total_len; - unsigned long long v1; - unsigned long long v2; - unsigned long long v3; - unsigned long long v4; - unsigned long long mem64[4]; - unsigned memsize; - unsigned reserved[2]; /* never read nor write, might be removed in a future version */ -}; /* typedef'd to XXH64_state_t */ -# endif - -# endif - - -#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) -# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */ -#endif - -#endif /* XXH_STATIC_LINKING_ONLY */ - - -#if defined (__cplusplus) -} -#endif - -#endif /* XXHASH_H_5627135585666179 */ diff --git a/packaging/cfg/taos.cfg b/packaging/cfg/taos.cfg index 3d3dfc8e7322ac11ca7bc30b95127c2d4590271d..2159899aa277f550adf76eb7c107bf3da17c9ab1 100644 --- a/packaging/cfg/taos.cfg +++ b/packaging/cfg/taos.cfg @@ -1,19 +1,18 @@ ######################################################## # # -# TDengine Configuration # -# Any questions, please email support@taosdata.com # +# Configuration # # # ######################################################## ######### 0. Client only configurations ############# -# The interval for TDengine CLI to send heartbeat to mnode +# The interval for CLI to send heartbeat to mnode # shellActivityTimer 3 ############### 1. Cluster End point ############################ -# The end point of the first dnode in the cluster to be connected to when this dnode or a TDengine CLI `taos` is started +# The end point of the first dnode in the cluster to be connected to when this dnode or the CLI utility is started # firstEp hostname:6030 # The end point of the second dnode to be connected to if the firstEp is not available @@ -25,7 +24,7 @@ # The FQDN of the host on which this dnode will be started. It can be IP address # fqdn hostname -# The port for external access after this dnode is started +# The port for external access after this dnode is started # serverPort 6030 # The maximum number of connections a dnode can accept @@ -40,10 +39,10 @@ # temporary file's directory, if you are using Windows platform please change to Windows path # tempDir /tmp/ -# Switch for allowing TDengine to collect and report service usage information +# Switch for allowing to collect and report service usage information # telemetryReporting 1 -# Switch for allowing TDengine to collect and report crash information +# Switch for allowing to collect and report crash information # crashReporting 1 # The maximum number of vnodes supported by this dnode @@ -96,7 +95,7 @@ # if free disk space is less than this value, this dnode will fail to start # minimalDataDirGB 2.0 -# enable/disable system monitor +# enable/disable system monitor # monitor 1 # The following parameter is used to limit the maximum number of lines in log files. @@ -114,8 +113,8 @@ # The following parameters are used for debug purpose only by this dnode. # debugFlag is a 8 bits mask: FILE-SCREEN-UNUSED-HeartBeat-DUMP-TRACE_WARN-ERROR -# Available debug levels are: -# 131: output warning and error +# Available debug levels are: +# 131: output warning and error # 135: output debug, warning and error # 143: output trace, debug, warning and error to log # 199: output debug, warning and error to both screen and file @@ -130,7 +129,7 @@ # debug flag for util # uDebugFlag 131 -# debug flag for rpc +# debug flag for rpc # rpcDebugFlag 131 # debug flag for jni @@ -139,7 +138,7 @@ # debug flag for query # qDebugFlag 131 -# debug flag for taosc driver +# debug flag for client driver # cDebugFlag 131 # debug flag for dnode messages diff --git a/packaging/cfg/taosd.service b/packaging/cfg/taosd.service index fff4b74e62a6da8f2bda9a6306a79132d7585e42..52c4b1d1e2d7aeb3447633353f48b2363c16efaa 100644 --- a/packaging/cfg/taosd.service +++ b/packaging/cfg/taosd.service @@ -1,5 +1,5 @@ [Unit] -Description=TDengine server service +Description=server service After=network-online.target Wants=network-online.target diff --git a/packaging/deb/DEBIAN/preinst b/packaging/deb/DEBIAN/preinst index 8a1a7d4d8160c0680d2492699e3d8c4a5709b096..904a946e2092fdef4325cab27fd759291896348d 100644 --- a/packaging/deb/DEBIAN/preinst +++ b/packaging/deb/DEBIAN/preinst @@ -26,6 +26,38 @@ if pidof taosd &> /dev/null; then sleep 1 fi +# Stop adapter service if running +if pidof taosadapter &> /dev/null; then + if pidof systemd &> /dev/null; then + ${csudo}systemctl stop taosadapter || : + elif $(which service &> /dev/null); then + ${csudo}service taosadapter stop || : + else + pid=$(ps -ef | grep "taosadapter" | grep -v "grep" | awk '{print $2}') + if [ -n "$pid" ]; then + ${csudo}kill -9 $pid || : + fi + fi + echo "Stop taosadapter service success!" + sleep 1 +fi + +# Stop keeper service if running +if pidof taoskeeper &> /dev/null; then + if pidof systemd &> /dev/null; then + ${csudo}systemctl stop taoskeeper || : + elif $(which service &> /dev/null); then + ${csudo}service taoskeeper stop || : + else + pid=$(ps -ef | grep "taoskeeper" | grep -v "grep" | awk '{print $2}') + if [ -n "$pid" ]; then + ${csudo}kill -9 $pid || : + fi + fi + echo "Stop taoskeeper service success!" + sleep 1 +fi + # if taos.cfg already softlink, remove it cfg_install_dir="/etc/taos" install_main_dir="/usr/local/taos" @@ -41,6 +73,11 @@ if [ -f "${install_main_dir}/taosadapter.service" ]; then ${csudo}rm -f ${install_main_dir}/cfg/taosadapter.service || : fi +if [ -f "${install_main_dir}/taoskeeper.toml" ]; then + ${csudo}rm -f ${install_main_dir}/cfg/taoskeeper.toml || : +fi + + # there can not libtaos.so*, otherwise ln -s error ${csudo}rm -f ${install_main_dir}/driver/libtaos.* || : [ -f ${install_main_dir}/driver/libtaosws.so ] && ${csudo}rm -f ${install_main_dir}/driver/libtaosws.so || : diff --git a/packaging/deb/DEBIAN/prerm b/packaging/deb/DEBIAN/prerm index 65f261db2c6c1ac70b761312af68a5188acea541..0d63115a0411e1edbd3a1474f56b865697040ccf 100644 --- a/packaging/deb/DEBIAN/prerm +++ b/packaging/deb/DEBIAN/prerm @@ -32,6 +32,7 @@ else ${csudo}rm -f ${bin_link_dir}/udfd || : ${csudo}rm -f ${bin_link_dir}/taosadapter || : ${csudo}rm -f ${bin_link_dir}/taosdemo || : + ${csudo}rm -f ${bin_link_dir}/taoskeeper || : ${csudo}rm -f ${cfg_link_dir}/* || : ${csudo}rm -f ${inc_link_dir}/taos.h || : ${csudo}rm -f ${inc_link_dir}/taosdef.h || : diff --git a/packaging/deb/makedeb.sh b/packaging/deb/makedeb.sh index 94a24a41487e8d7b82571bcc524392e4335d7fae..9f49cf345a4dd9e36f048f03bd49a28539baec66 100755 --- a/packaging/deb/makedeb.sh +++ b/packaging/deb/makedeb.sh @@ -44,8 +44,31 @@ mkdir -p ${pkg_dir}${install_home_path}/include #mkdir -p ${pkg_dir}${install_home_path}/init.d mkdir -p ${pkg_dir}${install_home_path}/script +# download taoskeeper and build +if [ "$cpuType" = "x64" ] || [ "$cpuType" = "x86_64" ] || [ "$cpuType" = "amd64" ]; then + arch=amd64 +elif [ "$cpuType" = "x32" ] || [ "$cpuType" = "i386" ] || [ "$cpuType" = "i686" ]; then + arch=386 +elif [ "$cpuType" = "arm" ] || [ "$cpuType" = "aarch32" ]; then + arch=arm +elif [ "$cpuType" = "arm64" ] || [ "$cpuType" = "aarch64" ]; then + arch=arm64 +else + arch=$cpuType +fi + +echo "${top_dir}/../enterprise/packaging/build_taoskeeper.sh -r ${arch} -e taoskeeper" +echo "$top_dir=${top_dir}" +taoskeeper_binary=`${top_dir}/../enterprise/packaging/build_taoskeeper.sh -r $arch -e taoskeeper` +echo "taoskeeper_binary: ${taoskeeper_binary}" + +# copy config files +cp $(dirname ${taoskeeper_binary})/config/taoskeeper.toml ${pkg_dir}${install_home_path}/cfg +cp $(dirname ${taoskeeper_binary})/taoskeeper.service ${pkg_dir}${install_home_path}/cfg + cp ${compile_dir}/../packaging/cfg/taos.cfg ${pkg_dir}${install_home_path}/cfg cp ${compile_dir}/../packaging/cfg/taosd.service ${pkg_dir}${install_home_path}/cfg + if [ -f "${compile_dir}/test/cfg/taosadapter.toml" ]; then cp ${compile_dir}/test/cfg/taosadapter.toml ${pkg_dir}${install_home_path}/cfg || : fi @@ -53,6 +76,7 @@ if [ -f "${compile_dir}/test/cfg/taosadapter.service" ]; then cp ${compile_dir}/test/cfg/taosadapter.service ${pkg_dir}${install_home_path}/cfg || : fi +cp ${taoskeeper_binary} ${pkg_dir}${install_home_path}/bin #cp ${compile_dir}/../packaging/deb/taosd ${pkg_dir}${install_home_path}/init.d cp ${compile_dir}/../packaging/tools/post.sh ${pkg_dir}${install_home_path}/script cp ${compile_dir}/../packaging/tools/preun.sh ${pkg_dir}${install_home_path}/script @@ -143,6 +167,7 @@ else exit 1 fi +rm -rf ${pkg_dir}/build-taoskeeper # make deb package dpkg -b ${pkg_dir} $debname echo "make deb package success!" @@ -150,4 +175,5 @@ echo "make deb package success!" cp ${pkg_dir}/*.deb ${output_dir} # clean temp dir + rm -rf ${pkg_dir} diff --git a/packaging/debRpmAutoInstall.sh b/packaging/debRpmAutoInstall.sh index 3579f813e5b6ce91f0daa1fd230af14a4bf3d4b9..8fadffe4c68d05f9bb0e6f3ed160ead7d8bdb00d 100755 --- a/packaging/debRpmAutoInstall.sh +++ b/packaging/debRpmAutoInstall.sh @@ -1,15 +1,15 @@ #!/usr/bin/expect -set packgeName [lindex $argv 0] +set packageName [lindex $argv 0] set packageSuffix [lindex $argv 1] -set timeout 3 +set timeout 30 if { ${packageSuffix} == "deb" } { - spawn dpkg -i ${packgeName} + spawn dpkg -i ${packageName} } elseif { ${packageSuffix} == "rpm"} { - spawn rpm -ivh ${packgeName} + spawn rpm -ivh ${packageName} } expect "*one:" send "\r" expect "*skip:" send "\r" -expect eof \ No newline at end of file +expect eof diff --git a/packaging/docker/Dockerfile b/packaging/docker/Dockerfile index 35bea0e65ccc5070fe9d4e82adadc7132ae7cc81..7d90beac1c9e12792a4d9a1de76c06b91157049f 100644 --- a/packaging/docker/Dockerfile +++ b/packaging/docker/Dockerfile @@ -12,7 +12,7 @@ ENV TINI_VERSION v0.19.0 ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${cpuType} /tini ENV DEBIAN_FRONTEND=noninteractive WORKDIR /root/ -RUN tar -zxf ${pkgFile} && cd /root/${dirName}/ && /bin/bash install.sh -e no && cd /root && rm /root/${pkgFile} && rm -rf /root/${dirName} && apt-get update && apt-get install -y locales tzdata netcat && locale-gen en_US.UTF-8 && apt-get clean && rm -rf /var/lib/apt/lists/ && chmod +x /tini +RUN tar -zxf ${pkgFile} && cd /root/${dirName}/ && /bin/bash install.sh -e no && cd /root && rm /root/${pkgFile} && rm -rf /root/${dirName} && apt-get update && apt-get install -y locales tzdata netcat curl gdb vim tmux less net-tools valgrind && locale-gen en_US.UTF-8 && apt-get clean && rm -rf /var/lib/apt/lists/ && chmod +x /tini ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib" \ LC_CTYPE=en_US.UTF-8 \ diff --git a/packaging/docker/DockerfileCloud b/packaging/docker/DockerfileCloud deleted file mode 100644 index fa8fcabf344f60f73d80c776cc3e46e5b08feecc..0000000000000000000000000000000000000000 --- a/packaging/docker/DockerfileCloud +++ /dev/null @@ -1,30 +0,0 @@ -FROM ubuntu:18.04 - -WORKDIR /root - -ARG pkgFile -ARG dirName -ARG cpuType -RUN echo ${pkgFile} && echo ${dirName} - -RUN apt update -RUN apt install -y curl - -COPY ${pkgFile} /root/ -ENV TINI_VERSION v0.19.0 -ENV TAOS_DISABLE_ADAPTER 1 -ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${cpuType} /tini -ENV DEBIAN_FRONTEND=noninteractive -WORKDIR /root/ -RUN tar -zxf ${pkgFile} && cd /root/${dirName}/ && /bin/bash install.sh -e no && cd /root && rm /root/${pkgFile} && rm -rf /root/${dirName} && apt-get update && apt-get install -y locales tzdata netcat && locale-gen en_US.UTF-8 && apt-get clean && rm -rf /var/lib/apt/lists/ && chmod +x /tini - -ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib" \ - LC_CTYPE=en_US.UTF-8 \ - LANG=en_US.UTF-8 \ - LC_ALL=en_US.UTF-8 -COPY ./run.sh /usr/bin/ -COPY ./bin/* /usr/bin/ - -ENTRYPOINT ["/tini", "--", "/usr/bin/entrypoint.sh"] -CMD ["bash", "-c", "/usr/bin/run.sh"] -VOLUME [ "/var/lib/taos", "/var/log/taos" ] diff --git a/packaging/docker/README.md b/packaging/docker/README.md index 763ab73724587eb4dc231eb399a60937eaba6dca..4509a7a1a9ae521906e19e018a3f2037a7bb5a5f 100644 --- a/packaging/docker/README.md +++ b/packaging/docker/README.md @@ -18,65 +18,58 @@ TDengine is an open-sourced big data platform under [GNU AGPL v3.0](http://www.g ## How to use this image -### Start a TDengine instance with RESTful API exposed +### Starting TDengine -Simply, you can use `docker run` to start a TDengine instance and connect it with restful connectors(eg. [JDBC-RESTful](https://www.taosdata.com/cn/documentation/connector/java)). +The TDengine image starts with the HTTP service activated by default, using the following command: -```bash +```shell docker run -d --name tdengine -p 6041:6041 tdengine/tdengine ``` -This command starts a docker container by name `tdengine` with TDengine server running, and maps the container's HTTP port 6041 to the host's port 6041. If you have `curl` in your host, you can list the databases by the command: +The above command starts a container named "tdengine" and maps the HTTP service port 6041 to the host port 6041. You can verify that the HTTP service provided in this container is available using the following command. -```bash +```shell curl -u root:taosdata -d "show databases" localhost:6041/rest/sql ``` -You can execute the `taos` shell command in the container: +The TDengine client taos can be executed in this container to access TDengine using the following command. -```bash +```shell $ docker exec -it tdengine taos -Welcome to the TDengine shell from Linux, Client Version:2.4.0.0 -Copyright (c) 2020 by TAOS Data, Inc. All rights reserved. - taos> show databases; - name | created_time | ntables | vgroups | replica | quorum | days | keep | cache(MB) | blocks | minrows | maxrows | wallevel | fsync | comp | cachelast | precision | update | status | -==================================================================================================================================================================================================================================================================================== - log | 2022-01-17 13:57:22.270 | 10 | 1 | 1 | 1 | 10 | 30 | 1 | 3 | 100 | 4096 | 1 | 3000 | 2 | 0 | us | 0 | ready | -Query OK, 1 row(s) in set (0.002843s) + name | +================================= + information_schema | + performance_schema | +Query OK, 2 row(s) in set (0.002843s) ``` -Since TDengine use container hostname to establish connections, it's a bit more complex to use TDengine CLI and native connectors(such as JDBC-JNI) with TDengine container instance. This is the recommended way to expose ports and use TDengine with docker in simple cases. If you want to use TDengine CLI or taosc/connectors smoothly outside the `tdengine` container, see next use cases that match you need. +The TDengine server running in the container uses the container's hostname to establish a connection. Using TDengine CLI or various connectors (such as JDBC-JNI) to access the TDengine inside the container from outside the container is more complicated. So the above is the simplest way to access the TDengine service in the container and is suitable for some simple scenarios. Please refer to the next section if you want to access the TDengine service in the container from outside the container using TDengine CLI or various connectors for complex scenarios. -### Start with host network +### Start TDengine on the host network -```bash +```shell docker run -d --name tdengine --network host tdengine/tdengine ``` -Starts container with `host` network will use host's hostname as fqdn instead of container id. It's much like starting natively with `systemd` in host. After installing the client, you can use `taos` shell as normal in host path. +The above command starts TDengine on the host network and uses the host's FQDN to establish a connection instead of the container's hostname. It is the equivalent of using `systemctl` to start TDengine on the host. If the TDengine client is already installed on the host, you can access it directly with the following command. -```bash +```shell $ taos -Welcome to the TDengine shell from Linux, Client Version:2.4.0.0 -Copyright (c) 2020 by TAOS Data, Inc. All rights reserved. - taos> show dnodes; id | end_point | vnodes | cores | status | role | create_time | offline reason | ====================================================================================================================================== - 1 | host:6030 | 1 | 8 | ready | any | 2022-01-17 22:10:32.619 | | + 1 | myhost:6030 | 1 | 8 | ready | any | 2022-01-17 22:10:32.619 | | Query OK, 1 row(s) in set (0.003233s) ``` -### Start with exposed ports and specified hostname - -Set the fqdn explicitly will help you to use in other environment or applications. We provide environment variable `TAOS_FQDN` or `fqdn` config option to explicitly set the hostname used by TDengine container instance(s). +### Start TDengine with the specified hostname and port -Use `TAOS_FQDN` variable within `docker run` command: +The `TAOS_FQDN` environment variable or the `fqdn` configuration item in `taos.cfg` allows TDengine to establish a connection at the specified hostname. This approach provides greater flexibility for deployment. -```bash +```shell docker run -d \ --name tdengine \ -e TAOS_FQDN=tdengine \ @@ -85,79 +78,58 @@ docker run -d \ tdengine/tdengine ``` -This command starts a docker container with TDengine server running and maps the container's TCP ports from 6030 to 6049 to the host's ports from 6030 to 6049 with TCP protocol and UDP ports range 6030-6039 to the host's UDP ports 6030-6039. If the host is already running TDengine server and occupying the same port(s), you need to map the container's port to a different unused port segment. (Please see TDengine 2.0 Port Description for details). In order to support TDengine clients accessing TDengine server services, both TCP and UDP ports need to be exposed by default(unless `rpcForceTcp` is set to `1`). +The above command starts a TDengine service in the container, which listens to the hostname tdengine, and maps the container's port segment 6030 to 6049 to the host's port segment 6030 to 6049 (both TCP and UDP ports need to be mapped). If the port segment is already occupied on the host, you can modify the above command to specify a free port segment on the host. If `rpcForceTcp` is set to `1`, you can map only the TCP protocol. -If you want to use TDengine CLI or native connectors([JDBC-JNI](https://www.taosdata.com/cn/documentation/connector/java), or [driver-go](https://github.com/taosdata/driver-go)), you need to make sure the `TAOS_FQDN` is resolvable at `/etc/hosts` or with custom DNS service. +Next, ensure the hostname "tdengine" is resolvable in `/etc/hosts`. -If you set the `TAOS_FQDN` to host's hostname, it will works as using `hosts` network like previous use case. Otherwise, like in `-e TAOS_FQDN=tdengine`, you can add the hostname record `tdengine` into `/etc/hosts` (use `127.0.0.1` here in host path, if use TDengine client/application in other hosts, you should set the right ip to the host eg. `192.168.10.1`(check the real ip in host with `hostname -i` or `ip route list default`) to make the TDengine endpoint resolvable): - -```bash +```shell echo 127.0.0.1 tdengine |sudo tee -a /etc/hosts ``` -Then you can use `taos` with the host `tdengine`: +Finally, the TDengine service can be accessed from the TDengine CLI or any connector with "tdengine" as the server address. -```bash -taos -h tdengine +```shell +taos -h tdengine -P 6030 ``` -Or develop/test applications with native connectors. As in python: +If set `TAOS_FQDN` to the same hostname, the effect is the same as "Start TDengine on host network". -```python -import taos; -conn = taos.connect(host = "tdengine") -res = conn.query("show databases") -for row in res.fetch_all_into_dict(): - print(row) -``` +### Start TDengine on the specified network -See the results: - -```bash -Python 3.8.10 (default, Nov 26 2021, 20:14:08) -[GCC 9.3.0] on linux -Type "help", "copyright", "credits" or "license" for more information. ->>> import taos; ->>> conn = taos.connect(host = "tdengine") ->>> res = conn.query("show databases") ->>> for row in res.fetch_all_into_dict(): -... print(row) -... -{'name': 'log', 'created_time': datetime.datetime(2022, 1, 17, 22, 56, 2, 490000), 'ntables': 11, 'vgroups': 1, 'replica': 1, 'quorum': 1, 'days': 10, 'keep': '30', 'cache(MB)': 1, 'blocks': 3, 'minrows': 100, 'maxrows': 4096, 'wallevel': 1, 'fsync': 3000, 'comp': 2, 'cachelast': 0, 'precision': 'us', 'update': 0, 'status': 'ready'} -``` +You can also start TDengine on a specific network. Perform the following steps: -### Start with specific network +1. First, create a docker network named `td-net` -Alternatively, you can use TDengine natively by using specific network. + ```shell + docker network create td-net + ``` -First, create network for TDengine server and client/application. +2. Start TDengine -```bash -docker network create td-net -``` + Start the TDengine service on the `td-net` network with the following command: -Start TDengine instance with service name as fqdn (explicitly set with `TAOS_FQDN`): + ```shell + docker run -d --name tdengine --network td-net \ + -e TAOS_FQDN=tdengine \ + tdengine/tdengine + ``` -```bash -docker run -d --name tdengine --network td-net \ - -e TAOS_FQDN=tdengine \ - tdengine/tdengine -``` +3. Start the TDengine client in another container on the same network -Start TDengine client in another container with the specific network: + ```shell + docker run --rm -it --network td-net -e TAOS_FIRST_EP=tdengine tdengine/tdengine taos + # or + #docker run --rm -it --network td-net -e tdengine/tdengine taos -h tdengine + ``` -```bash -docker run --rm -it --network td-net -e TAOS_FIRST_EP=tdengine tdengine/tdengine taos -# or -docker run --rm -it --network td-net -e tdengine/tdengine taos -h tdengine -``` +### Launching a client application in a container -When you build your application with docker, you should add the TDengine client in the dockerfile, as based on `ubuntu:20.04` image, install the client like this: +If you want to start your application in a container, you need to add the corresponding dependencies on TDengine to the image as well, e.g. -```dockerfile +```docker FROM ubuntu:20.04 RUN apt-get update && apt-get install -y wget -ENV TDENGINE_VERSION=2.4.0.0 +ENV TDENGINE_VERSION=3.0.0.0 RUN wget -c https://www.taosdata.com/assets-download/3.0/TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \ && tar xvf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \ && cd TDengine-client-${TDENGINE_VERSION} \ @@ -169,10 +141,7 @@ RUN wget -c https://www.taosdata.com/assets-download/3.0/TDengine-client-${TDENG #CMD ["app"] ``` -Here is an Go example app: - - - +Here is an example GO program: ```go /* @@ -181,19 +150,19 @@ Here is an Go example app: package main import ( - "database/sql" - "flag" - "fmt" - "time" + "database/sql" + "flag" + "fmt" + "time" - _ "github.com/taosdata/driver-go/v2/taosSql" + _ "github.com/taosdata/driver-go/v3/taosSql" ) type config struct { - hostName string - serverPort string - user string - password string + hostName string + serverPort string + user string + password string } var configPara config @@ -201,70 +170,67 @@ var taosDriverName = "taosSql" var url string func init() { - flag.StringVar(&configPara.hostName, "h", "", "The host to connect to TDengine server.") - flag.StringVar(&configPara.serverPort, "p", "", "The TCP/IP port number to use for the connection to TDengine server.") - flag.StringVar(&configPara.user, "u", "root", "The TDengine user name to use when connecting to the server.") - flag.StringVar(&configPara.password, "P", "taosdata", "The password to use when connecting to the server.") - flag.Parse() + flag.StringVar(&configPara.hostName, "h", "", "The host to connect to TDengine server.") + flag.StringVar(&configPara.serverPort, "p", "", "The TCP/IP port number to use for the connection to TDengine server.") + flag.StringVar(&configPara.user, "u", "root", "The TDengine user name to use when connecting to the server.") + flag.StringVar(&configPara.password, "P", "taosdata", "The password to use when connecting to the server.") + flag.Parse() } func printAllArgs() { - fmt.Printf("============= args parse result: =============\n") - fmt.Printf("hostName: %v\n", configPara.hostName) - fmt.Printf("serverPort: %v\n", configPara.serverPort) - fmt.Printf("usr: %v\n", configPara.user) - fmt.Printf("password: %v\n", configPara.password) - fmt.Printf("================================================\n") + fmt.Printf("============= args parse result: =============\n") + fmt.Printf("hostName: %v\n", configPara.hostName) + fmt.Printf("serverPort: %v\n", configPara.serverPort) + fmt.Printf("usr: %v\n", configPara.user) + fmt.Printf("password: %v\n", configPara.password) + fmt.Printf("================================================\n") } func main() { - printAllArgs() - - url = "root:taosdata@/tcp(" + configPara.hostName + ":" + configPara.serverPort + ")/" - - taos, err := sql.Open(taosDriverName, url) - checkErr(err, "open database error") - defer taos.Close() - - taos.Exec("create database if not exists test") - taos.Exec("use test") - taos.Exec("create table if not exists tb1 (ts timestamp, a int)") - _, err = taos.Exec("insert into tb1 values(now, 0)(now+1s,1)(now+2s,2)(now+3s,3)") - checkErr(err, "failed to insert") - rows, err := taos.Query("select * from tb1") - checkErr(err, "failed to select") - - defer rows.Close() - for rows.Next() { - var r struct { - ts time.Time - a int - } - err := rows.Scan(&r.ts, &r.a) - if err != nil { - fmt.Println("scan error:\n", err) - return - } - fmt.Println(r.ts, r.a) - } + printAllArgs() + + url = "root:taosdata@/tcp(" + configPara.hostName + ":" + configPara.serverPort + ")/" + + taos, err := sql.Open(taosDriverName, url) + checkErr(err, "open database error") + defer taos.Close() + + taos.Exec("create database if not exists test") + taos.Exec("use test") + taos.Exec("create table if not exists tb1 (ts timestamp, a int)") + _, err = taos.Exec("insert into tb1 values(now, 0)(now+1s,1)(now+2s,2)(now+3s,3)") + checkErr(err, "failed to insert") + rows, err := taos.Query("select * from tb1") + checkErr(err, "failed to select") + + defer rows.Close() + for rows.Next() { + var r struct { + ts time.Time + a int + } + err := rows.Scan(&r.ts, &r.a) + if err != nil { + fmt.Println("scan error:\n", err) + return + } + fmt.Println(r.ts, r.a) + } } func checkErr(err error, prompt string) { - if err != nil { - fmt.Println("ERROR: %s\n", prompt) - panic(err) - } + if err != nil { + fmt.Println("ERROR: %s\n", prompt) + panic(err) + } } ``` - - - -Full version of dockerfile could be: +Here is the full Dockerfile: -```dockerfile +```docker FROM golang:1.17.6-buster as builder -ENV TDENGINE_VERSION=2.4.0.0 +ENV TDENGINE_VERSION=3.0.0.0 RUN wget -c https://www.taosdata.com/assets-download/3.0/TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \ && tar xvf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \ && cd TDengine-client-${TDENGINE_VERSION} \ @@ -274,11 +240,13 @@ RUN wget -c https://www.taosdata.com/assets-download/3.0/TDengine-client-${TDENG WORKDIR /usr/src/app/ ENV GOPROXY="https://goproxy.io,direct" COPY ./main.go ./go.mod ./go.sum /usr/src/app/ -RUN go env && go mod tidy && go build +RUN go env +RUN go mod tidy +RUN go build FROM ubuntu:20.04 RUN apt-get update && apt-get install -y wget -ENV TDENGINE_VERSION=2.4.0.0 +ENV TDENGINE_VERSION=3.0.0.0 RUN wget -c https://www.taosdata.com/assets-download/3.0/TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \ && tar xvf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \ && cd TDengine-client-${TDENGINE_VERSION} \ @@ -291,9 +259,9 @@ COPY --from=builder /usr/src/app/app /usr/bin/ CMD ["app"] ``` -Suppose you have `main.go`, `go.mod` `go.sum`, `app.dockerfile`, build the app and run it with network `td-net`: +Now that we have `main.go`, `go.mod`, `go.sum`, `app.dockerfile`, we can build the application and start it on the `td-net` network. -```bash +```shell $ docker build -t app -f app.dockerfile $ docker run --rm --network td-net app -h tdengine -p 6030 ============= args parse result: ============= @@ -316,26 +284,18 @@ password: taosdata 2022-01-18 01:43:51.029 +0000 UTC 3 ``` -Now you must be much familiar with developing and testing with TDengine, let's see some more complex cases. +### Start the TDengine cluster with docker-compose -### Start with docker-compose with multiple nodes(instances) +1. The following docker-compose file starts a TDengine cluster with three nodes. -Start a 2-replicas-2-mnodes-2-dnodes-1-arbitrator TDengine cluster with `docker-compose` is quite simple. Save the file as `docker-compose.yml`: - -```yaml +```yml version: "3" services: - arbitrator: - image: tdengine/tdengine:$VERSION - command: tarbitrator td-1: image: tdengine/tdengine:$VERSION environment: TAOS_FQDN: "td-1" TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 volumes: - taosdata-td1:/var/lib/taos/ - taoslog-td1:/var/log/taos/ @@ -344,101 +304,95 @@ services: environment: TAOS_FQDN: "td-2" TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 volumes: - taosdata-td2:/var/lib/taos/ - taoslog-td2:/var/log/taos/ + td-3: + image: tdengine/tdengine:$VERSION + environment: + TAOS_FQDN: "td-3" + TAOS_FIRST_EP: "td-1" + volumes: + - taosdata-td3:/var/lib/taos/ + - taoslog-td3:/var/log/taos/ volumes: taosdata-td1: taoslog-td1: taosdata-td2: taoslog-td2: + taosdata-td3: + taoslog-td3: ``` -You may notice that: - -- We use `VERSION` environment variable to set `tdengine` image tag version once. -- **`TAOS_FIRST_EP`** **MUST** be set to join the newly created instances into an existing TDengine cluster. If you want more instances, use `TAOS_SECOND_EP` in case of HA(High Availability) concerns. -- `TAOS_NUM_OF_MNODES` is for setting number of mnodes for the cluster. -- `TAOS_REPLICA` set the default database replicas, `2` means there're one master and one slave copy of data. The `replica` option should be `1 <= replica <= 3`, and not greater than dnodes number. -- `TAOS_ARBITRATOR` set the arbitrator entrypoint of the cluster for failover/election stuff. It's better to use arbitrator in a two nodes cluster. -- The way to start an arbitrator service is as easy as abc: just add command name `tarbitrator`(which is the binary name of arbitrator daemon) in docker-compose service option: `command: tarbitrator`, and everything is ok now. - -Now run `docker-compose up -d` with version specified: - -```bash -$ VERSION=2.4.0.0 docker-compose up -d -Creating network "test_default" with the default driver -Creating volume "test_taosdata-td1" with default driver -Creating volume "test_taoslog-td1" with default driver -Creating volume "test_taosdata-td2" with default driver -Creating volume "test_taoslog-td2" with default driver -Creating test_td-1_1 ... done -Creating test_arbitrator_1 ... done -Creating test_td-2_1 ... done -``` +:::note -Check the status: +- The `VERSION` environment variable is used to set the tdengine image tag +- `TAOS_FIRST_EP` must be set on the newly created instance so that it can join the TDengine cluster; if there is a high availability requirement, `TAOS_SECOND_EP` needs to be used at the same time + ::: -```bash -$ docker-compose ps - Name Command State Ports ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -test_arbitrator_1 /usr/bin/entrypoint.sh tar ... Up 6030/tcp, 6031/tcp, 6032/tcp, 6033/tcp, 6034/tcp, 6035/tcp, 6036/tcp, 6037/tcp, 6038/tcp, 6039/tcp, 6040/tcp, 6041/tcp, 6042/tcp -test_td-1_1 /usr/bin/entrypoint.sh taosd Up 6030/tcp, 6031/tcp, 6032/tcp, 6033/tcp, 6034/tcp, 6035/tcp, 6036/tcp, 6037/tcp, 6038/tcp, 6039/tcp, 6040/tcp, 6041/tcp, 6042/tcp -test_td-2_1 /usr/bin/entrypoint.sh taosd Up 6030/tcp, 6031/tcp, 6032/tcp, 6033/tcp, 6034/tcp, 6035/tcp, 6036/tcp, 6037/tcp, 6038/tcp, 6039/tcp, 6040/tcp, 6041/tcp, 6042/tcp -``` +2. Start the cluster -Check dnodes with TDengine CLI: + ```shell + $ VERSION=3.0.0.0 docker-compose up -d + Creating network "test_default" with the default driver + Creating volume "test_taosdata-td1" with default driver + Creating volume "test_taoslog-td1" with default driver + Creating volume "test_taosdata-td2" with default driver + Creating volume "test_taoslog-td2" with default driver + Creating test_td-1_1 ... done + Creating test_arbitrator_1 ... done + Creating test_td-2_1 ... done + ``` -```bash -$ docker-compose exec td-1 taos -s "show dnodes" +3. Check the status of each node + + ```shell + $ docker-compose ps + Name Command State Ports + --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + test_arbitrator_1 /usr/bin/entrypoint.sh tar ... Up 6030/tcp, 6031/tcp, 6032/tcp, 6033/tcp, 6034/tcp, 6035/tcp, 6036/tcp, 6037/tcp, 6038/tcp, 6039/tcp, 6040/tcp, 6041/tcp, 6042/tcp + test_td-1_1 /usr/bin/entrypoint.sh taosd Up 6030/tcp, 6031/tcp, 6032/tcp, 6033/tcp, 6034/tcp, 6035/tcp, 6036/tcp, 6037/tcp, 6038/tcp, 6039/tcp, 6040/tcp, 6041/tcp, 6042/tcp + test_td-2_1 /usr/bin/entrypoint.sh taosd Up 6030/tcp, 6031/tcp, 6032/tcp, 6033/tcp, 6034/tcp, 6035/tcp, 6036/tcp, 6037/tcp, 6038/tcp, 6039/tcp, 6040/tcp, 6041/tcp, 6042/tcp + ``` -Welcome to the TDengine shell from Linux, Client Version:2.4.0.0 -Copyright (c) 2020 by TAOS Data, Inc. All rights reserved. +4. Show dnodes via TDengine CLI + +```shell +$ docker-compose exec td-1 taos -s "show dnodes" taos> show dnodes - id | end_point | vnodes | cores | status | role | create_time | offline reason | + id | endpoint | vnodes | support_vnodes | status | create_time | note | ====================================================================================================================================== - 1 | td-1:6030 | 1 | 8 | ready | any | 2022-01-18 02:47:42.871 | | - 2 | td-2:6030 | 0 | 8 | ready | any | 2022-01-18 02:47:43.518 | | - 0 | arbitrator:6042 | 0 | 0 | ready | arb | 2022-01-18 02:47:43.633 | - | -Query OK, 3 row(s) in set (0.000811s) -``` + 1 | td-1:6030 | 0 | 32 | ready | 2022-08-19 07:57:29.971 | | + 2 | td-2:6030 | 0 | 32 | ready | 2022-08-19 07:57:31.415 | | + 3 | td-3:6030 | 0 | 32 | ready | 2022-08-19 07:57:31.417 | | +Query OK, 3 rows in database (0.021262s) -### Start a TDengine cluster with scaled taosadapter service +``` -In previous use case, you could see the way to start other services built with TDengine(`taosd` as the default command). There's another important service you should know: +## taosAdapter -> **taosAdapter** is a TDengine’s companion tool and is a bridge/adapter between TDengine cluster and application. It provides an easy-to-use and efficient way to ingest data from data collections agents(like Telegraf, StatsD, CollectD) directly. It also provides InfluxDB/OpenTSDB compatible data ingestion interface to allow InfluxDB/OpenTSDB applications to immigrate to TDengine seamlessly. +1. taosAdapter is enabled by default in the TDengine container. If you want to disable it, specify the environment variable `TAOS_DISABLE_ADAPTER=true` at startup -`taosadapter` is running inside `tdengine` image by default, you can disable it by `TAOS_DISABLE_ADAPTER=true`. Running `taosadapter` in a separate container is like how `arbitrator` does: +2. At the same time, for flexible deployment, taosAdapter can be started in a separate container -```yaml -services: - # ... - adapter: - image: tdengine/tdengine:$VERSION - command: taosadapter -``` + ```docker + services: + # ... + adapter: + image: tdengine/tdengine:$VERSION + command: taosadapter + ``` -`taosadapter` could be scaled with docker-compose, so that you can manage the `taosadapter` nodes easily. Here is an example shows 4-`taosadapter` instances in a TDengine cluster(much like previous use cases): + Suppose you want to deploy multiple taosAdapters to improve throughput and provide high availability. In that case, the recommended configuration method uses a reverse proxy such as Nginx to offer a unified access entry. For specific configuration methods, please refer to the official documentation of Nginx. Here is an example: -```yaml +```yml version: "3" networks: inter: - api: services: - arbitrator: - image: tdengine/tdengine:$VERSION - command: tarbitrator - networks: - - inter td-1: image: tdengine/tdengine:$VERSION networks: @@ -446,9 +400,6 @@ services: environment: TAOS_FQDN: "td-1" TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 volumes: - taosdata-td1:/var/lib/taos/ - taoslog-td1:/var/log/taos/ @@ -459,15 +410,12 @@ services: environment: TAOS_FQDN: "td-2" TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 volumes: - taosdata-td2:/var/lib/taos/ - taoslog-td2:/var/log/taos/ adapter: image: tdengine/tdengine:$VERSION - command: taosadapter + entrypoint: "taosadapter" networks: - inter environment: @@ -481,7 +429,6 @@ services: - adapter networks: - inter - - api ports: - 6041:6041 - 6044:6044/udp @@ -504,100 +451,14 @@ volumes: taoslog-td2: ``` -Start the cluster: - -```bash -$ VERSION=2.4.0.0 docker-compose up -d -Creating network "docker_inter" with the default driver -Creating network "docker_api" with the default driver -Creating volume "docker_taosdata-td1" with default driver -Creating volume "docker_taoslog-td1" with default driver -Creating volume "docker_taosdata-td2" with default driver -Creating volume "docker_taoslog-td2" with default driver -Creating docker_td-2_1 ... done -Creating docker_arbitrator_1 ... done -Creating docker_td-1_1 ... done -Creating docker_adapter_1 ... done -Creating docker_adapter_2 ... done -Creating docker_adapter_3 ... done -``` - -It will start a TDengine cluster with two dnodes and four taosadapter instances, expose ports 6041/tcp and 6044/udp to host. - -`6041` is the RESTful API endpoint port, you can verify that the RESTful interface taosAdapter provides working using the `curl` command. - -```bash -$ curl -H 'Authorization: Basic cm9vdDp0YW9zZGF0YQ==' -d 'show databases;' 127.0.0.1:6041/rest/sql -{"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":[["log","2022-01-18 04:37:42.902",16,1,1,1,10,"30",1,3,100,4096,1,3000,2,0,"us",0,"ready"]],"rows":1} -``` - -If you run curl in batch(here we use [hyperfine](https://github.com/sharkdp/hyperfine) - a command-line benchmarking tool), the requests are balanced into 4 adapter instances. - -```bash -hyperfine -m10 'curl -u root:taosdata localhost:6041/rest/sql -d "describe log.log"' -``` - -View the logs with `docker-compose logs`: - -```bash -$ docker-compose logs adapter -# some logs skipped -adapter_2 | 01/18 04:57:44.616529 00000039 TAOS_ADAPTER info "| 200 | 162.185µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=18 -adapter_1 | 01/18 04:57:44.627695 00000039 TAOS_ADAPTER info "| 200 | 145.485µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=17 -adapter_3 | 01/18 04:57:44.639165 00000040 TAOS_ADAPTER info "| 200 | 146.913µs | 172.21.0.9 | POST | /rest/sql " sessionID=17 model=web -adapter_4 | 01/18 04:57:44.650829 00000039 TAOS_ADAPTER info "| 200 | 153.201µs | 172.21.0.9 | POST | /rest/sql " sessionID=17 model=web -adapter_2 | 01/18 04:57:44.662422 00000039 TAOS_ADAPTER info "| 200 | 211.393µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=19 -adapter_1 | 01/18 04:57:44.673426 00000039 TAOS_ADAPTER info "| 200 | 154.714µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=18 -adapter_3 | 01/18 04:57:44.684788 00000040 TAOS_ADAPTER info "| 200 | 131.876µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=18 -adapter_4 | 01/18 04:57:44.696261 00000039 TAOS_ADAPTER info "| 200 | 162.173µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=18 -adapter_2 | 01/18 04:57:44.707414 00000039 TAOS_ADAPTER info "| 200 | 164.419µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=20 -adapter_1 | 01/18 04:57:44.720842 00000039 TAOS_ADAPTER info "| 200 | 179.374µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=19 -adapter_3 | 01/18 04:57:44.732184 00000040 TAOS_ADAPTER info "| 200 | 141.174µs | 172.21.0.9 | POST | /rest/sql " sessionID=19 model=web -adapter_4 | 01/18 04:57:44.744024 00000039 TAOS_ADAPTER info "| 200 | 159.774µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=19 -adapter_2 | 01/18 04:57:44.773732 00000039 TAOS_ADAPTER info "| 200 | 178.993µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=21 -adapter_1 | 01/18 04:57:44.796518 00000039 TAOS_ADAPTER info "| 200 | 238.24µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=20 -adapter_3 | 01/18 04:57:44.810744 00000040 TAOS_ADAPTER info "| 200 | 176.133µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=20 -adapter_4 | 01/18 04:57:44.826395 00000039 TAOS_ADAPTER info "| 200 | 149.215µs | 172.21.0.9 | POST | /rest/sql " model=web sessionID=20 -``` - -`6044/udp` is the [StatsD](https://github.com/statsd/statsd)-compatible port, you can verify this feature with `nc` command(usually provided by `netcat` package). - -```bash -echo "foo:1|c" | nc -u -w0 127.0.0.1 6044 -``` - -Check the result in `taos` shell with `docker-compose exec`: +## Deploy with docker swarm -```bash -$ dc exec td-1 taos +If you want to deploy a container-based TDengine cluster on multiple hosts, you can use docker swarm. First, to establish a docker swarm cluster on these hosts, please refer to the official docker documentation. -Welcome to the TDengine shell from Linux, Client Version:2.4.0.0 -Copyright (c) 2020 by TAOS Data, Inc. All rights reserved. +The docker-compose file can refer to the previous section. Here is the command to start TDengine with docker swarm: -taos> show databases; - name | created_time | ntables | vgroups | replica | quorum | days | keep | cache(MB) | blocks | minrows | maxrows | wallevel | fsync | comp | cachelast | precision | update | status | -==================================================================================================================================================================================================================================================================================== - log | 2022-01-18 04:37:42.902 | 17 | 1 | 1 | 1 | 10 | 30 | 1 | 3 | 100 | 4096 | 1 | 3000 | 2 | 0 | us | 0 | ready | - statsd | 2022-01-18 04:45:02.563 | 1 | 1 | 2 | 1 | 10 | 3650 | 16 | 6 | 100 | 4096 | 1 | 3000 | 2 | 0 | ns | 2 | ready | -Query OK, 2 row(s) in set (0.001838s) - -taos> select * from statsd.foo; - ts | value | metric_type | -======================================================================================= - 2022-01-18 04:45:02.563422822 | 1 | counter | -Query OK, 1 row(s) in set (0.003854s) -``` - -Use `docker-compose up -d adapter=1 to reduce the instances to 1 - -### Deploy TDengine cluster in Docker Swarm with `docker-compose.yml` - -If you use docker swarm mode, it will schedule arbitrator/taosd/taosadapter services into different hosts automatically. If you've no experience with k8s/kubernetes, this is the most convenient way to scale out the TDengine cluster with multiple hosts/servers. - -Use the `docker-compose.yml` file in previous use case, and deploy with `docker stack` or `docker deploy`: - -```bash -$ VERSION=2.4.0 docker stack deploy -c docker-compose.yml taos +```shell +$ VERSION=3.0.0.0 docker stack deploy -c docker-compose.yml taos Creating network taos_inter Creating network taos_api Creating service taos_arbitrator @@ -607,58 +468,40 @@ Creating service taos_adapter Creating service taos_nginx ``` -Now you've created a TDengine cluster with multiple host servers. - -Use `docker service` or `docker stack` to manage the cluster: +Checking status: - - -```bash +```shell $ docker stack ps taos ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS -79ni8temw59n taos_nginx.1 nginx:latest TM1701 Running Running about a minute ago -3e94u72msiyg taos_adapter.1 tdengine/tdengine:2.4.0 TM1702 Running Running 56 seconds ago -100amjkwzsc6 taos_td-2.1 tdengine/tdengine:2.4.0 TM1703 Running Running about a minute ago -pkjehr2vvaaa taos_td-1.1 tdengine/tdengine:2.4.0 TM1704 Running Running 2 minutes ago -tpzvgpsr1qkt taos_arbitrator.1 tdengine/tdengine:2.4.0 TM1705 Running Running 2 minutes ago -rvss3g5yg6fa taos_adapter.2 tdengine/tdengine:2.4.0 TM1706 Running Running 56 seconds ago -i2augxamfllf taos_adapter.3 tdengine/tdengine:2.4.0 TM1707 Running Running 56 seconds ago -lmjyhzccpvpg taos_adapter.4 tdengine/tdengine:2.4.0 TM1708 Running Running 56 seconds ago +79ni8temw59n taos_nginx.1 nginx:latest TM1701 Running Running about a minute ago +3e94u72msiyg taos_adapter.1 tdengine/tdengine:3.0.0.0 TM1702 Running Running 56 seconds ago +100amjkwzsc6 taos_td-2.1 tdengine/tdengine:3.0.0.0 TM1703 Running Running about a minute ago +pkjehr2vvaaa taos_td-1.1 tdengine/tdengine:3.0.0.0 TM1704 Running Running 2 minutes ago +tpzvgpsr1qkt taos_arbitrator.1 tdengine/tdengine:3.0.0.0 TM1705 Running Running 2 minutes ago +rvss3g5yg6fa taos_adapter.2 tdengine/tdengine:3.0.0.0 TM1706 Running Running 56 seconds ago +i2augxamfllf taos_adapter.3 tdengine/tdengine:3.0.0.0 TM1707 Running Running 56 seconds ago +lmjyhzccpvpg taos_adapter.4 tdengine/tdengine:3.0.0.0 TM1708 Running Running 56 seconds ago $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS -561t4lu6nfw6 taos_adapter replicated 4/4 tdengine/tdengine:2.4.0 -3hk5ct3q90sm taos_arbitrator replicated 1/1 tdengine/tdengine:2.4.0 +561t4lu6nfw6 taos_adapter replicated 4/4 tdengine/tdengine:3.0.0.0 +3hk5ct3q90sm taos_arbitrator replicated 1/1 tdengine/tdengine:3.0.0.0 d8qr52envqzu taos_nginx replicated 1/1 nginx:latest *:6041->6041/tcp, *:6044->6044/udp -2isssfvjk747 taos_td-1 replicated 1/1 tdengine/tdengine:2.4.0 -9pzw7u02ichv taos_td-2 replicated 1/1 tdengine/tdengine:2.4.0 +2isssfvjk747 taos_td-1 replicated 1/1 tdengine/tdengine:3.0.0.0 +9pzw7u02ichv taos_td-2 replicated 1/1 tdengine/tdengine:3.0.0.0 ``` - - -It shows that there are two dnodes, one arbitrator, four taosadapter and one nginx reverse-forward service in this cluster. +From the above output, you can see two dnodes, two taosAdapters, and one Nginx reverse proxy service. -You can scale down the taosadapter replicas to `1` by `docker service`: +Next, we can reduce the number of taosAdapter services. -```bash +```shell $ docker service scale taos_adapter=1 taos_adapter scaled to 1 -overall progress: 1 out of 1 tasks -1/1: running [==================================================>] +overall progress: 1 out of 1 tasks +1/1: running [==================================================>] verify: Service converged $ docker service ls -f name=taos_adapter ID NAME MODE REPLICAS IMAGE PORTS -561t4lu6nfw6 taos_adapter replicated 1/1 tdengine/tdengine:2.4.0 -``` - -Now it remains only 1 taosadapter instance in the cluster. - -When you want to remove the cluster, just type: - -```bash -docker stack rm taos +561t4lu6nfw6 taos_adapter replicated 1/1 tdengine/tdengine:3.0.0.0 ``` - -### Environment Variables - -When you start `tdengine` image, you can adjust the configuration of TDengine by passing environment variables on the `docker run` command line or in the docker compose file. You can use all of the environment variables that passed to taosd or taosadapter. diff --git a/packaging/docker/bin/entrypoint.sh b/packaging/docker/bin/entrypoint.sh index f4be349c0de0ea0df382fc6fee033120c5c48007..a60254d7ef370aa1404f864df24125eebc4cad08 100755 --- a/packaging/docker/bin/entrypoint.sh +++ b/packaging/docker/bin/entrypoint.sh @@ -42,8 +42,9 @@ if [ "$DISABLE_ADAPTER" = "0" ]; then done fi -# if has mnode ep set or the host is first ep or not for cluster, just start. -if [ -f "$DATA_DIR/dnode/mnodeEpSet.json" ] || +# if dnode has been created or has mnode ep set or the host is first ep or not for cluster, just start. +if [ -f "$DATA_DIR/dnode/dnode.json" ] || + [ -f "$DATA_DIR/dnode/mnodeEpSet.json" ] || [ "$TAOS_FQDN" = "$FIRST_EP_HOST" ]; then $@ # others will first wait the first ep ready. @@ -54,7 +55,7 @@ else exit $? fi while true; do - es=$(taos -h $FIRST_EP_HOST -P $FIRST_EP_PORT --check) + es=$(taos -h $FIRST_EP_HOST -P $FIRST_EP_PORT --check | grep "^[0-9]*:") echo ${es} if [ "${es%%:*}" -eq 2 ]; then echo "execute create dnode" diff --git a/packaging/docker/bin/taos-check b/packaging/docker/bin/taos-check index 5dc06b6018b93b627610b446ca6363773fd0fd72..349187da9bb0e5b3b7d15f1bfed5afdb7f4c20c9 100755 --- a/packaging/docker/bin/taos-check +++ b/packaging/docker/bin/taos-check @@ -1,5 +1,5 @@ #!/bin/sh -es=$(taos --check) +es=$(taos --check | grep "^[0-9]*:") code=${es%%:*} if [ "$code" -ne "0" ] && [ "$code" -ne "4" ]; then exit 0 diff --git a/packaging/docker/docker-compose.yml b/packaging/docker/docker-compose.yml deleted file mode 100644 index 301b41e7d43c2a894d866c1f0d45cf8d13328585..0000000000000000000000000000000000000000 --- a/packaging/docker/docker-compose.yml +++ /dev/null @@ -1,77 +0,0 @@ -version: "3" - -networks: - inter: - api: - -services: - arbitrator: - image: tdengine/tdengine:$VERSION - command: tarbitrator - networks: - - inter - td-1: - image: tdengine/tdengine:$VERSION - networks: - - inter - environment: - TAOS_FQDN: "td-1" - TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 - volumes: - - taosdata-td1:/var/lib/taos/ - - taoslog-td1:/var/log/taos/ - td-2: - image: tdengine/tdengine:$VERSION - networks: - - inter - environment: - TAOS_FQDN: "td-2" - TAOS_FIRST_EP: "td-1" - TAOS_NUM_OF_MNODES: "2" - TAOS_REPLICA: "2" - TAOS_ARBITRATOR: arbitrator:6042 - volumes: - - taosdata-td2:/var/lib/taos/ - - taoslog-td2:/var/log/taos/ - adapter: - image: tdengine/tdengine:$VERSION - command: taosadapter - networks: - - inter - environment: - TAOS_FIRST_EP: "td-1" - TOAS_SECOND_EP: "td-2" - deploy: - replicas: 4 - update_config: - parallelism: 4 - nginx: - image: nginx - depends_on: - - adapter - networks: - - inter - - api - ports: - - 6041:6041 - - 6044:6044/udp - command: [ - "sh", - "-c", - "while true; - do curl -s http://adapter:6041/-/ping >/dev/null && break; - done; - printf 'server{listen 6041;location /{proxy_pass http://adapter:6041;}}' - > /etc/nginx/conf.d/rest.conf; - printf 'stream{server{listen 6044 udp;proxy_pass adapter:6044;}}' - >> /etc/nginx/nginx.conf;cat /etc/nginx/nginx.conf; - nginx -g 'daemon off;'", - ] -volumes: - taosdata-td1: - taoslog-td1: - taosdata-td2: - taoslog-td2: diff --git a/packaging/docker/dockerManifest.sh b/packaging/docker/dockerManifest.sh index 8f71e30fbdca1cc9adf8e9b46c652475822e4b08..db71bf8833d3fce82a461e7021da3eaa66b0bf60 100755 --- a/packaging/docker/dockerManifest.sh +++ b/packaging/docker/dockerManifest.sh @@ -1,9 +1,9 @@ #!/bin/bash set -e #set -x -set -v +set -v -# dockerbuild.sh +# dockerbuild.sh # -n [version number] # -p [xxxx] # -V [stable | beta] @@ -28,7 +28,7 @@ do V) #echo "verType=$OPTARG" verType=$(echo $OPTARG) - ;; + ;; h) echo "Usage: `basename $0` -n [version number] " echo " -p [password for docker hub] " @@ -39,8 +39,8 @@ do a) #echo "dockerLatest=$OPTARG" dockerLatest=$(echo $OPTARG) - ;; - ?) #unknow option + ;; + ?) #unknow option echo "unkonw argument" exit 1 ;; @@ -60,7 +60,7 @@ if [ "$verType" == "stable" ]; then elif [ "$verType" == "beta" ];then verType=beta tagVal=ver-${version}-beta - dockerinput=TDengine-server-${version}-${verType}-Linux-$cpuType.tar.gz + dockerinput=TDengine-server-${version}-${verType}-Linux-$cpuType.tar.gz dockerinput_x64=TDengine-server-${version}-${verType}-Linux-amd64.tar.gz dockerim=tdengine/tdengine-beta dockeramd64=tdengine/tdengine-amd64-beta @@ -73,30 +73,30 @@ fi username="tdengine" -# generate docker verison +# generate docker version echo "generate ${dockerim}:${version}" docker manifest create -a ${dockerim}:${version} ${dockeramd64}:${version} ${dockeraarch64}:${version} docker manifest inspect ${dockerim}:${version} docker manifest rm ${dockerim}:${version} docker manifest create -a ${dockerim}:${version} ${dockeramd64}:${version} ${dockeraarch64}:${version} docker manifest inspect ${dockerim}:${version} -docker login -u ${username} -p ${passWord} +docker login -u ${username} -p ${passWord} docker manifest push ${dockerim}:${version} -# generate docker latest +# generate docker latest echo "generate ${dockerim}:latest " if [ ${dockerLatest} == 'y' ] ;then echo "docker manifest create -a ${dockerim}:latest ${dockeramd64}:latest ${dockeraarch64}:latest" docker manifest create -a ${dockerim}:latest ${dockeramd64}:latest ${dockeraarch64}:latest - docker manifest inspect ${dockerim}:latest - docker manifest rm ${dockerim}:latest + docker manifest inspect ${dockerim}:latest + docker manifest rm ${dockerim}:latest docker manifest create -a ${dockerim}:latest ${dockeramd64}:latest ${dockeraarch64}:latest docker manifest inspect ${dockerim}:latest docker login -u tdengine -p ${passWord} #replace the docker registry username and password docker manifest push ${dockerim}:latest - docker pull tdengine/tdengine:latest + docker pull tdengine/tdengine:latest fi diff --git a/packaging/docker/dockerbuild.sh b/packaging/docker/dockerbuild.sh index b02387a3d1191c09dadfa1ce21ab33183a52a7da..4b6fc8576b233192a6835d455d73baf14abc1758 100755 --- a/packaging/docker/dockerbuild.sh +++ b/packaging/docker/dockerbuild.sh @@ -74,7 +74,7 @@ do done -# Check_verison() +# Check_version() # { # } @@ -102,14 +102,14 @@ scriptDir=$(dirname $(readlink -f $0)) communityDir=${scriptDir}/../../../community DockerfilePath=${communityDir}/packaging/docker/ if [ "$cloudBuild" == "y" ]; then - comunityArchiveDir=/nas/TDengine/v$version/cloud + communityArchiveDir=/nas/TDengine/v$version/cloud Dockerfile=${communityDir}/packaging/docker/DockerfileCloud else - comunityArchiveDir=/nas/TDengine/v$version/community + communityArchiveDir=/nas/TDengine/v$version/community Dockerfile=${communityDir}/packaging/docker/Dockerfile fi cd ${scriptDir} -cp -f ${comunityArchiveDir}/${pkgFile} . +cp -f ${communityArchiveDir}/${pkgFile} . echo "dirName=${dirName}" diff --git a/packaging/release.bat b/packaging/release.bat index 4c82c5ead538c2152b1047fabb608f096a6e48b0..4b49f364d05a2c49b2bde31c20792bba728cd718 100644 --- a/packaging/release.bat +++ b/packaging/release.bat @@ -46,9 +46,9 @@ rd /s /Q C:\TDengine cmake --install . if not %errorlevel% == 0 ( call :RUNFAILED build x64 failed & exit /b 1) cd %package_dir% -iscc /DMyAppInstallName="%packagServerName_x64%" /DMyAppVersion="%2" /DMyAppExcludeSource="" tools\tdengine.iss /O..\release +iscc /DMyAppInstallName="%packagServerName_x64%" /DMyAppVersion="%2" /DCusName="TDengine" /DCusPrompt="taos" /DMyAppExcludeSource="" tools\tdengine.iss /O..\release if not %errorlevel% == 0 ( call :RUNFAILED package %packagServerName_x64% failed & exit /b 1) -iscc /DMyAppInstallName="%packagClientName_x64%" /DMyAppVersion="%2" /DMyAppExcludeSource="taosd.exe" tools\tdengine.iss /O..\release +iscc /DMyAppInstallName="%packagClientName_x64%" /DMyAppVersion="%2" /DCusName="TDengine" /DCusPrompt="taos" /DMyAppExcludeSource="taosd.exe" tools\tdengine.iss /O..\release if not %errorlevel% == 0 ( call :RUNFAILED package %packagClientName_x64% failed & exit /b 1) goto EXIT0 diff --git a/packaging/release.sh b/packaging/release.sh deleted file mode 100755 index 1dfbf2b1124b0ebdeb1d9062c5d9d659eabe8a78..0000000000000000000000000000000000000000 --- a/packaging/release.sh +++ /dev/null @@ -1,319 +0,0 @@ -#!/bin/bash -# -# Generate the deb package for ubuntu, or rpm package for centos, or tar.gz package for other linux os - -set -e -# set -x - -# release.sh -v [cluster | edge] -# -c [aarch32 | aarch64 | x64 | x86 | mips64 | loongarch64...] -# -o [Linux | Kylin | Alpine | Raspberrypi | Darwin | Windows | Ningsi60 | Ningsi80 |...] -# -V [stable | beta] -# -l [full | lite] -# -s [static | dynamic] -# -d [taos | ...] -# -n [2.0.0.3] -# -m [2.0.0.0] -# -H [ false | true] - -# set parameters by default value -verMode=edge # [cluster, edge, cloud] -verType=stable # [stable, beta] -cpuType=x64 # [aarch32 | aarch64 | x64 | x86 | mips64 loongarch64...] -osType=Linux # [Linux | Kylin | Alpine | Raspberrypi | Darwin | Windows | Ningsi60 | Ningsi80 |...] -pagMode=full # [full | lite] -soMode=dynamic # [static | dynamic] -dbName=taos # [taos | ...] -allocator=glibc # [glibc | jemalloc] -verNumber="" -verNumberComp="3.0.0.0" -httpdBuild=false - -while getopts "hv:V:c:o:l:s:d:a:n:m:H:" arg; do - case $arg in - v) - #echo "verMode=$OPTARG" - verMode=$(echo $OPTARG) - ;; - V) - #echo "verType=$OPTARG" - verType=$(echo $OPTARG) - ;; - c) - #echo "cpuType=$OPTARG" - cpuType=$(echo $OPTARG) - ;; - l) - #echo "pagMode=$OPTARG" - pagMode=$(echo $OPTARG) - ;; - s) - #echo "soMode=$OPTARG" - soMode=$(echo $OPTARG) - ;; - d) - #echo "dbName=$OPTARG" - dbName=$(echo $OPTARG) - ;; - a) - #echo "allocator=$OPTARG" - allocator=$(echo $OPTARG) - ;; - n) - #echo "verNumber=$OPTARG" - verNumber=$(echo $OPTARG) - ;; - m) - #echo "verNumberComp=$OPTARG" - verNumberComp=$(echo $OPTARG) - ;; - o) - #echo "osType=$OPTARG" - osType=$(echo $OPTARG) - ;; - H) - #echo "httpdBuild=$OPTARG" - httpdBuild=$(echo $OPTARG) - ;; - h) - echo "Usage: $(basename $0) -v [cluster | edge] " - echo " -c [aarch32 | aarch64 | x64 | x86 | mips64 | loongarch64 ...] " - echo " -o [Linux | Kylin | Alpine | Raspberrypi | Darwin | Windows | Ningsi60 | Ningsi80 |...] " - echo " -V [stable | beta] " - echo " -l [full | lite] " - echo " -a [glibc | jemalloc] " - echo " -s [static | dynamic] " - echo " -d [taos | ...] " - echo " -n [version number] " - echo " -m [compatible version number] " - echo " -H [false | true] " - exit 0 - ;; - ?) #unknow option - echo "unkonw argument" - exit 1 - ;; - esac -done - -osType=$(uname) - -echo "verMode=${verMode} verType=${verType} cpuType=${cpuType} osType=${osType} pagMode=${pagMode} soMode=${soMode} dbName=${dbName} allocator=${allocator} verNumber=${verNumber} verNumberComp=${verNumberComp} httpdBuild=${httpdBuild}" - -curr_dir=$(pwd) - -if [ "$osType" == "Darwin" ]; then - script_dir=$(dirname $0) - cd ${script_dir} - script_dir="$(pwd)" - top_dir=${script_dir}/.. -else - script_dir="$(dirname $(readlink -f $0))" - top_dir="$(readlink -f ${script_dir}/..)" -fi - -csudo="" -#if command -v sudo > /dev/null; then -# csudo="sudo " -#fi - -function is_valid_version() { - [ -z $1 ] && return 1 || : - - rx='^([0-9]+\.){3}(\*|[0-9]+)$' - if [[ $1 =~ $rx ]]; then - return 0 - fi - return 1 -} - -function vercomp() { - if [[ $1 == $2 ]]; then - echo 0 - exit 0 - fi - - local IFS=. - local i ver1=($1) ver2=($2) - - # fill empty fields in ver1 with zeros - for ((i = ${#ver1[@]}; i < ${#ver2[@]}; i++)); do - ver1[i]=0 - done - - for ((i = 0; i < ${#ver1[@]}; i++)); do - if [[ -z ${ver2[i]} ]]; then - # fill empty fields in ver2 with zeros - ver2[i]=0 - fi - if ((10#${ver1[i]} > 10#${ver2[i]})); then - echo 1 - exit 0 - fi - if ((10#${ver1[i]} < 10#${ver2[i]})); then - echo 2 - exit 0 - fi - done - echo 0 -} - -# 1. check version information -if ( (! is_valid_version $verNumber) || (! is_valid_version $verNumberComp) || [[ "$(vercomp $verNumber $verNumberComp)" == '2' ]]); then - echo "please enter correct version" - exit 0 -fi - -echo "=======================new version number: ${verNumber}, compatible version: ${verNumberComp}======================================" - -build_time=$(date +"%F %R") - -# get commint id from git -gitinfo=$(git rev-parse --verify HEAD) - -if [[ "$verMode" == "cluster" ]] || [[ "$verMode" == "cloud" ]]; then - enterprise_dir="${top_dir}/../enterprise" - cd ${enterprise_dir} - gitinfoOfInternal=$(git rev-parse --verify HEAD) -else - gitinfoOfInternal=NULL -fi - -cd "${curr_dir}" - -# 2. cmake executable file -compile_dir="${top_dir}/debug" -if [ -d ${compile_dir} ]; then - rm -rf ${compile_dir} -fi - -mkdir -p ${compile_dir} -cd ${compile_dir} - -if [[ "$allocator" == "jemalloc" ]]; then - allocator_macro="-DJEMALLOC_ENABLED=true" -else - allocator_macro="" -fi - -if [[ "$dbName" != "taos" ]]; then - source ${enterprise_dir}/packaging/oem/sed_$dbName.sh - replace_community_$dbName -fi - -if [[ "$httpdBuild" == "true" ]]; then - BUILD_HTTP=true -else - BUILD_HTTP=false -fi - -if [[ "$verMode" == "cluster" ]] || [[ "$verMode" == "cloud" ]]; then - BUILD_HTTP=internal -fi - -if [[ "$pagMode" == "full" ]]; then - BUILD_TOOLS=true -else - BUILD_TOOLS=false -fi - -# check support cpu type -if [[ "$cpuType" == "x64" ]] || [[ "$cpuType" == "aarch64" ]] || [[ "$cpuType" == "aarch32" ]] || [[ "$cpuType" == "arm64" ]] || [[ "$cpuType" == "arm32" ]] || [[ "$cpuType" == "mips64" ]] || [[ "$cpuType" == "loongarch64" ]] ; then - if [ "$verMode" == "edge" ]; then - # community-version compile - cmake ../ -DCPUTYPE=${cpuType} -DWEBSOCKET=true -DOSTYPE=${osType} -DSOMODE=${soMode} -DDBNAME=${dbName} -DVERTYPE=${verType} -DVERDATE="${build_time}" -DGITINFO=${gitinfo} -DGITINFOI=${gitinfoOfInternal} -DVERNUMBER=${verNumber} -DVERCOMPATIBLE=${verNumberComp} -DPAGMODE=${pagMode} -DBUILD_HTTP=${BUILD_HTTP} -DBUILD_TOOLS=${BUILD_TOOLS} ${allocator_macro} - elif [ "$verMode" == "cloud" ]; then - cmake ../../ -DCPUTYPE=${cpuType} -DWEBSOCKET=true -DBUILD_TAOSX=true -DBUILD_CLOUD=true -DOSTYPE=${osType} -DSOMODE=${soMode} -DDBNAME=${dbName} -DVERTYPE=${verType} -DVERDATE="${build_time}" -DGITINFO=${gitinfo} -DGITINFOI=${gitinfoOfInternal} -DVERNUMBER=${verNumber} -DVERCOMPATIBLE=${verNumberComp} -DBUILD_HTTP=${BUILD_HTTP} -DBUILD_TOOLS=${BUILD_TOOLS} ${allocator_macro} - elif [ "$verMode" == "cluster" ]; then - if [[ "$dbName" != "taos" ]]; then - replace_enterprise_$dbName - fi - cmake ../../ -DCPUTYPE=${cpuType} -DWEBSOCKET=true -DBUILD_TAOSX=true -DOSTYPE=${osType} -DSOMODE=${soMode} -DDBNAME=${dbName} -DVERTYPE=${verType} -DVERDATE="${build_time}" -DGITINFO=${gitinfo} -DGITINFOI=${gitinfoOfInternal} -DVERNUMBER=${verNumber} -DVERCOMPATIBLE=${verNumberComp} -DBUILD_HTTP=${BUILD_HTTP} -DBUILD_TOOLS=${BUILD_TOOLS} ${allocator_macro} - fi -else - echo "input cpuType=${cpuType} error!!!" - exit 1 -fi - -ostype=`uname` -if [ "${ostype}" == "Darwin" ]; then - CORES=$(sysctl -n hw.ncpu) -else - CORES=$(grep -c ^processor /proc/cpuinfo) -fi - -if [[ "$allocator" == "jemalloc" ]]; then - # jemalloc need compile first, so disable parallel build - make -j ${CORES} && ${csudo}make install -else - make -j ${CORES} && ${csudo}make install -fi - -cd ${curr_dir} - -# 3. Call the corresponding script for packaging -if [ "$osType" != "Darwin" ]; then - if [[ "$verMode" != "cluster" ]] && [[ "$verMode" != "cloud" ]] && [[ "$pagMode" == "full" ]] && [[ "$cpuType" == "x64" ]] && [[ "$dbName" == "taos" ]]; then - ret='0' - command -v dpkg >/dev/null 2>&1 || { ret='1'; } - if [ "$ret" -eq 0 ]; then - echo "====do deb package for the ubuntu system====" - output_dir="${top_dir}/debs" - if [ -d ${output_dir} ]; then - rm -rf ${output_dir} - fi - mkdir -p ${output_dir} - cd ${script_dir}/deb - ${csudo}./makedeb.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType} - - if [[ "$pagMode" == "full" ]]; then - if [ -d ${top_dir}/tools/taos-tools/packaging/deb ]; then - cd ${top_dir}/tools/taos-tools/packaging/deb - taos_tools_ver=$(git tag |grep -v taos | sort | tail -1) - [ -z "$taos_tools_ver" ] && taos_tools_ver="0.1.0" - - ${csudo}./make-taos-tools-deb.sh ${top_dir} \ - ${compile_dir} ${output_dir} ${taos_tools_ver} ${cpuType} ${osType} ${verMode} ${verType} ${verNumberComp} - fi - fi - else - echo "==========dpkg command not exist, so not release deb package!!!" - fi - ret='0' - command -v rpmbuild >/dev/null 2>&1 || { ret='1'; } - if [ "$ret" -eq 0 ]; then - echo "====do rpm package for the centos system====" - output_dir="${top_dir}/rpms" - if [ -d ${output_dir} ]; then - rm -rf ${output_dir} - fi - mkdir -p ${output_dir} - cd ${script_dir}/rpm - ${csudo}./makerpm.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType} - - if [[ "$pagMode" == "full" ]]; then - if [ -d ${top_dir}/tools/taos-tools/packaging/rpm ]; then - cd ${top_dir}/tools/taos-tools/packaging/rpm - taos_tools_ver=$(git tag |grep -v taos | sort | tail -1) - [ -z "$taos_tools_ver" ] && taos_tools_ver="0.1.0" - - ${csudo}./make-taos-tools-rpm.sh ${top_dir} \ - ${compile_dir} ${output_dir} ${taos_tools_ver} ${cpuType} ${osType} ${verMode} ${verType} ${verNumberComp} - fi - fi - else - echo "==========rpmbuild command not exist, so not release rpm package!!!" - fi - fi - - echo "====do tar.gz package for all systems====" - cd ${script_dir}/tools - - ${csudo}./makepkg.sh ${compile_dir} ${verNumber} "${build_time}" ${cpuType} ${osType} ${verMode} ${verType} ${pagMode} ${verNumberComp} ${dbName} - ${csudo}./makeclient.sh ${compile_dir} ${verNumber} "${build_time}" ${cpuType} ${osType} ${verMode} ${verType} ${pagMode} ${dbName} - -else - cd ${script_dir}/tools - ./makepkg.sh ${compile_dir} ${verNumber} "${build_time}" ${cpuType} ${osType} ${verMode} ${verType} ${pagMode} ${verNumberComp} ${dbName} - ./makeclient.sh ${compile_dir} ${verNumber} "${build_time}" ${cpuType} ${osType} ${verMode} ${verType} ${pagMode} ${dbName} -fi diff --git a/packaging/rpm/makerpm.sh b/packaging/rpm/makerpm.sh index 4ac67ec754ce230f9a777570c42a9300c757978d..9cf00364aa249580d4241fc0ad923454d488a526 100755 --- a/packaging/rpm/makerpm.sh +++ b/packaging/rpm/makerpm.sh @@ -35,14 +35,16 @@ function cp_rpm_package() { local cur_dir cd $1 cur_dir=$(pwd) - + echo "cp_rpm_package cd: ${cur_dir}" for dirlist in "$(ls ${cur_dir})"; do if test -d ${dirlist}; then cd ${dirlist} + echo 'cp_rpm_package ${cur_dir}/${dirlist}' cp_rpm_package ${cur_dir}/${dirlist} cd .. fi if test -e ${dirlist}; then + echo "${cur_dir}/${dirlist} ${output_dir}/TDengine-${tdengine_ver}.rpm" cp ${cur_dir}/${dirlist} ${output_dir}/TDengine-${tdengine_ver}.rpm fi done @@ -54,6 +56,25 @@ fi ${csudo}mkdir -p ${pkg_dir} cd ${pkg_dir} +# download taoskeeper and build +if [ "$cpuType" = "x64" ] || [ "$cpuType" = "x86_64" ] || [ "$cpuType" = "amd64" ]; then + arch=amd64 +elif [ "$cpuType" = "x32" ] || [ "$cpuType" = "i386" ] || [ "$cpuType" = "i686" ]; then + arch=386 +elif [ "$cpuType" = "arm" ] || [ "$cpuType" = "aarch32" ]; then + arch=arm +elif [ "$cpuType" = "arm64" ] || [ "$cpuType" = "aarch64" ]; then + arch=arm64 +else + arch=$cpuType +fi + +cd ${top_dir} +echo "${top_dir}/../enterprise/packaging/build_taoskeeper.sh -r ${arch} -e taoskeeper" +taoskeeper_binary=`${top_dir}/../enterprise/packaging/build_taoskeeper.sh -r $arch -e taoskeeper` +echo "taoskeeper_binary: ${taoskeeper_binary}" +cd ${package_dir} + ${csudo}mkdir -p BUILD BUILDROOT RPMS SOURCES SPECS SRPMS ${csudo}rpmbuild --define="_version ${tdengine_ver}" --define="_topdir ${pkg_dir}" --define="_compiledir ${compile_dir}" -bb ${spec_file} @@ -85,3 +106,4 @@ mv ${output_dir}/TDengine-${tdengine_ver}.rpm ${output_dir}/${rpmname} cd .. ${csudo}rm -rf ${pkg_dir} +rm -rf ${top_dir}/build-taoskeeper \ No newline at end of file diff --git a/packaging/rpm/tdengine.spec b/packaging/rpm/tdengine.spec index e9d86219cb635d29cfc360314d122362d3285c0c..52d5335003097787a9d607ed4f020eb9153ceb31 100644 --- a/packaging/rpm/tdengine.spec +++ b/packaging/rpm/tdengine.spec @@ -3,6 +3,7 @@ %define cfg_install_dir /etc/taos %define __strip /bin/true %global __python /usr/bin/python3 +%global _build_id_links none Name: tdengine Version: %{_version} @@ -62,6 +63,15 @@ fi if [ -f %{_compiledir}/test/cfg/taosadapter.service ]; then cp %{_compiledir}/test/cfg/taosadapter.service %{buildroot}%{homepath}/cfg fi + +if [ -f %{_compiledir}/../build-taoskeeper/config/taoskeeper.toml ]; then + cp %{_compiledir}/../build-taoskeeper/config/taoskeeper.toml %{buildroot}%{homepath}/cfg ||: +fi + +if [ -f %{_compiledir}/../build-taoskeeper/taoskeeper.service ]; then + cp %{_compiledir}/../build-taoskeeper/taoskeeper.service %{buildroot}%{homepath}/cfg ||: +fi + #cp %{_compiledir}/../packaging/rpm/taosd %{buildroot}%{homepath}/init.d cp %{_compiledir}/../packaging/tools/post.sh %{buildroot}%{homepath}/script cp %{_compiledir}/../packaging/tools/preun.sh %{buildroot}%{homepath}/script @@ -73,8 +83,12 @@ cp %{_compiledir}/build/bin/taosd %{buildroot}%{homepath}/bin cp %{_compiledir}/build/bin/udfd %{buildroot}%{homepath}/bin cp %{_compiledir}/build/bin/taosBenchmark %{buildroot}%{homepath}/bin +if [ -f %{_compiledir}/../build-taoskeeper/taoskeeper ]; then + cp %{_compiledir}/../build-taoskeeper/taoskeeper %{buildroot}%{homepath}/bin +fi + if [ -f %{_compiledir}/build/bin/taosadapter ]; then - cp %{_compiledir}/build/bin/taosadapter %{buildroot}%{homepath}/bin ||: + cp %{_compiledir}/build/bin/taosadapter %{buildroot}%{homepath}/bin fi cp %{_compiledir}/build/lib/${libfile} %{buildroot}%{homepath}/driver [ -f %{_compiledir}/build/lib/${wslibfile} ] && cp %{_compiledir}/build/lib/${wslibfile} %{buildroot}%{homepath}/driver ||: @@ -90,48 +104,38 @@ cp %{_compiledir}/../include/libs/function/taosudf.h %{buildroot}%{homepat cp -r %{_compiledir}/../examples/* %{buildroot}%{homepath}/examples if [ -f %{_compiledir}/build/bin/jemalloc-config ]; then - mkdir -p %{buildroot}%{userlocalpath}/bin - mkdir -p %{buildroot}%{userlocalpath}/lib - mkdir -p %{buildroot}%{userlocalpath}/lib/pkgconfig - mkdir -p %{buildroot}%{userlocalpath}/include - mkdir -p %{buildroot}%{userlocalpath}/include/jemalloc - mkdir -p %{buildroot}%{userlocalpath}/share - mkdir -p %{buildroot}%{userlocalpath}/share/doc - mkdir -p %{buildroot}%{userlocalpath}/share/doc/jemalloc - mkdir -p %{buildroot}%{userlocalpath}/share/man - mkdir -p %{buildroot}%{userlocalpath}/share/man/man3 - - cp %{_compiledir}/build/bin/jemalloc-config %{buildroot}%{userlocalpath}/bin/ + mkdir -p %{buildroot}%{homepath}/jemalloc/ ||: + mkdir -p %{buildroot}%{homepath}/jemalloc/include/jemalloc/ ||: + mkdir -p %{buildroot}%{homepath}/jemalloc/lib/ ||: + mkdir -p %{buildroot}%{homepath}/jemalloc/lib/pkgconfig ||: + + cp %{_compiledir}/build/bin/jemalloc-config %{buildroot}%{homepath}/jemalloc/bin if [ -f %{_compiledir}/build/bin/jemalloc.sh ]; then - cp %{_compiledir}/build/bin/jemalloc.sh %{buildroot}%{userlocalpath}/bin/ + cp %{_compiledir}/build/bin/jemalloc.sh %{buildroot}%{homepath}/jemalloc/bin fi if [ -f %{_compiledir}/build/bin/jeprof ]; then - cp %{_compiledir}/build/bin/jeprof %{buildroot}%{userlocalpath}/bin/ + cp %{_compiledir}/build/bin/jeprof %{buildroot}%{homepath}/jemalloc/bin fi if [ -f %{_compiledir}/build/include/jemalloc/jemalloc.h ]; then - cp %{_compiledir}/build/include/jemalloc/jemalloc.h %{buildroot}%{userlocalpath}/include/jemalloc/ + cp %{_compiledir}/build/include/jemalloc/jemalloc.h %{buildroot}%{homepath}/jemalloc/include/jemalloc/ fi if [ -f %{_compiledir}/build/lib/libjemalloc.so.2 ]; then - cp %{_compiledir}/build/lib/libjemalloc.so.2 %{buildroot}%{userlocalpath}/lib/ - ln -sf libjemalloc.so.2 %{buildroot}%{userlocalpath}/lib/libjemalloc.so + cp %{_compiledir}/build/lib/libjemalloc.so.2 %{buildroot}%{homepath}/jemalloc/lib + ln -sf libjemalloc.so.2 %{buildroot}%{homepath}/jemalloc/lib/libjemalloc.so fi if [ -f %{_compiledir}/build/lib/libjemalloc.a ]; then - cp %{_compiledir}/build/lib/libjemalloc.a %{buildroot}%{userlocalpath}/lib/ + cp %{_compiledir}/build/lib/libjemalloc.a %{buildroot}%{homepath}/jemalloc/lib fi if [ -f %{_compiledir}/build/lib/libjemalloc_pic.a ]; then - cp %{_compiledir}/build/lib/libjemalloc_pic.a %{buildroot}%{userlocalpath}/lib/ + cp %{_compiledir}/build/lib/libjemalloc_pic.a %{buildroot}%{homepath}/jemalloc/lib fi if [ -f %{_compiledir}/build/lib/pkgconfig/jemalloc.pc ]; then - cp %{_compiledir}/build/lib/pkgconfig/jemalloc.pc %{buildroot}%{userlocalpath}/lib/pkgconfig/ - fi - if [ -f %{_compiledir}/build/share/doc/jemalloc/jemalloc.html ]; then - cp %{_compiledir}/build/share/doc/jemalloc/jemalloc.html %{buildroot}%{userlocalpath}/share/doc/jemalloc/ - fi - if [ -f %{_compiledir}/build/share/man/man3/jemalloc.3 ]; then - cp %{_compiledir}/build/share/man/man3/jemalloc.3 %{buildroot}%{userlocalpath}/share/man/man3/ + cp %{_compiledir}/build/lib/pkgconfig/jemalloc.pc %{buildroot}%{homepath}/jemalloc/lib/pkgconfig fi fi - +ls -al %{buildroot}%{homepath}/bin +tree -L 5 +echo "==============================copying files done" #Scripts executed before installation %pre if [ -f /var/lib/taos/dnode/dnodeCfg.json ]; then @@ -208,6 +212,7 @@ if [ $1 -eq 0 ];then ${csudo}rm -f ${bin_link_dir}/taosd || : ${csudo}rm -f ${bin_link_dir}/udfd || : ${csudo}rm -f ${bin_link_dir}/taosadapter || : + ${csudo}rm -f ${bin_link_dir}/taoskeeper || : ${csudo}rm -f ${cfg_link_dir}/* || : ${csudo}rm -f ${inc_link_dir}/taos.h || : ${csudo}rm -f ${inc_link_dir}/taosdef.h || : diff --git a/packaging/testpackage.sh b/packaging/testpackage.sh index 78d5043b0cf664e02d840fe307b93dc9cc8d9a68..081383f89b358325f55cc1a7641015efcb0a4eed 100755 --- a/packaging/testpackage.sh +++ b/packaging/testpackage.sh @@ -25,7 +25,7 @@ sourcePath="nas" cpuType="x64" lite="true" packageType="tar" -subFile="taos.tar.gz" +subFile="package.tar.gz" while getopts "m:c:f:l:s:o:t:v:h" opt; do case $opt in m) @@ -79,9 +79,9 @@ GREEN_UNDERLINE='\033[4;32m' NC='\033[0m' if [[ ${verMode} = "enterprise" ]];then - prePackag="TDengine-enterprise-${testFile}" + prePackage="TDengine-enterprise-${testFile}" elif [ ${verMode} = "community" ];then - prePackag="TDengine-${testFile}" + prePackage="TDengine-${testFile}" fi if [ ${lite} = "true" ];then packageLite="-Lite" @@ -92,10 +92,10 @@ if [[ "$packageType" = "tar" ]] ;then packageType="tar.gz" fi -tdPath="${prePackag}-${version}" -originTdpPath="${prePackag}-${originversion}" +tdPath="${prePackage}-${version}" +originTdpPath="${prePackage}-${originversion}" -packgeName="${tdPath}-Linux-${cpuType}${packageLite}.${packageType}" +packageName="${tdPath}-Linux-${cpuType}${packageLite}.${packageType}" originPackageName="${originTdpPath}-Linux-${cpuType}${packageLite}.${packageType}" if [ "$testFile" == "server" ] ;then @@ -105,13 +105,13 @@ elif [ ${testFile} = "client" ];then elif [ ${testFile} = "tools" ];then tdPath="taosTools-${version}" originTdpPath="taosTools-${originversion}" - packgeName="${tdPath}-Linux-${cpuType}${packageLite}.${packageType}" + packageName="${tdPath}-Linux-${cpuType}${packageLite}.${packageType}" originPackageName="${originTdpPath}-Linux-${cpuType}${packageLite}.${packageType}" installCmd="install-taostools.sh" fi -echo "tdPath:${tdPath},originTdpPath:${originTdpPath},packgeName:${packgeName},originPackageName:${originPackageName}" +echo "tdPath:${tdPath},originTdpPath:${originTdpPath},packageName:${packageName},originPackageName:${originPackageName}" function cmdInstall { command=$1 if command -v ${command} ;then @@ -206,7 +206,7 @@ else fi -if [[ ${packgeName} =~ "server" ]] ;then +if [[ ${packageName} =~ "server" ]] ;then echoColor BD " pkill -9 taosd " pkill -9 taosd fi @@ -232,25 +232,25 @@ if [ -d ${installPath}/${tdPath} ] ;then fi echoColor G "===== download installPackage =====" -cd ${installPath} && wgetFile ${packgeName} ${version} ${sourcePath} +cd ${installPath} && wgetFile ${packageName} ${version} ${sourcePath} cd ${oriInstallPath} && wgetFile ${originPackageName} ${originversion} ${sourcePath} cd ${installPath} cp -r ${scriptDir}/debRpmAutoInstall.sh . -packageSuffix=$(echo ${packgeName} | awk -F '.' '{print $NF}') +packageSuffix=$(echo ${packageName} | awk -F '.' '{print $NF}') if [ ! -f debRpmAutoInstall.sh ];then echo '#!/usr/bin/expect ' > debRpmAutoInstall.sh - echo 'set packgeName [lindex $argv 0]' >> debRpmAutoInstall.sh + echo 'set packageName [lindex $argv 0]' >> debRpmAutoInstall.sh echo 'set packageSuffix [lindex $argv 1]' >> debRpmAutoInstall.sh - echo 'set timeout 3 ' >> debRpmAutoInstall.sh + echo 'set timeout 30 ' >> debRpmAutoInstall.sh echo 'if { ${packageSuffix} == "deb" } {' >> debRpmAutoInstall.sh - echo ' spawn dpkg -i ${packgeName} ' >> debRpmAutoInstall.sh + echo ' spawn dpkg -i ${packageName} ' >> debRpmAutoInstall.sh echo '} elseif { ${packageSuffix} == "rpm"} {' >> debRpmAutoInstall.sh - echo ' spawn rpm -ivh ${packgeName}' >> debRpmAutoInstall.sh + echo ' spawn rpm -ivh ${packageName}' >> debRpmAutoInstall.sh echo '}' >> debRpmAutoInstall.sh echo 'expect "*one:"' >> debRpmAutoInstall.sh echo 'send "\r"' >> debRpmAutoInstall.sh @@ -261,25 +261,25 @@ fi echoColor G "===== instal Package =====" -if [[ ${packgeName} =~ "deb" ]];then +if [[ ${packageName} =~ "deb" ]];then cd ${installPath} dpkg -r taostools dpkg -r tdengine - if [[ ${packgeName} =~ "TDengine" ]];then - echoColor BD "./debRpmAutoInstall.sh ${packgeName} ${packageSuffix}" && chmod 755 debRpmAutoInstall.sh && ./debRpmAutoInstall.sh ${packgeName} ${packageSuffix} + if [[ ${packageName} =~ "TDengine" ]];then + echoColor BD "./debRpmAutoInstall.sh ${packageName} ${packageSuffix}" && chmod 755 debRpmAutoInstall.sh && ./debRpmAutoInstall.sh ${packageName} ${packageSuffix} else - echoColor BD "dpkg -i ${packgeName}" && dpkg -i ${packgeName} + echoColor BD "dpkg -i ${packageName}" && dpkg -i ${packageName} fi -elif [[ ${packgeName} =~ "rpm" ]];then +elif [[ ${packageName} =~ "rpm" ]];then cd ${installPath} sudo rpm -e tdengine sudo rpm -e taostools - if [[ ${packgeName} =~ "TDengine" ]];then - echoColor BD "./debRpmAutoInstall.sh ${packgeName} ${packageSuffix}" && chmod 755 debRpmAutoInstall.sh && ./debRpmAutoInstall.sh ${packgeName} ${packageSuffix} + if [[ ${packageName} =~ "TDengine" ]];then + echoColor BD "./debRpmAutoInstall.sh ${packageName} ${packageSuffix}" && chmod 755 debRpmAutoInstall.sh && ./debRpmAutoInstall.sh ${packageName} ${packageSuffix} else - echoColor BD "rpm -ivh ${packgeName}" && rpm -ivh ${packgeName} + echoColor BD "rpm -ivh ${packageName}" && rpm -ivh ${packageName} fi -elif [[ ${packgeName} =~ "tar" ]];then +elif [[ ${packageName} =~ "tar" ]];then echoColor G "===== check installPackage File of tar =====" cd ${oriInstallPath} if [ ! -f {originPackageName} ];then @@ -290,7 +290,7 @@ elif [[ ${packgeName} =~ "tar" ]];then echoColor BD "tar -xf ${originPackageName}" && tar -xf ${originPackageName} cd ${installPath} echoColor YD "unzip the new installation package" - echoColor BD "tar -xf ${packgeName}" && tar -xf ${packgeName} + echoColor BD "tar -xf ${packageName}" && tar -xf ${packageName} if [ ${testFile} != "tools" ] ;then cd ${installPath}/${tdPath} && tar xf ${subFile} @@ -326,7 +326,7 @@ fi cd ${installPath} -if [[ ${packgeName} =~ "Lite" ]] || ([[ ${packgeName} =~ "x64" ]] && [[ ${packgeName} =~ "client" ]]) || ([[ ${packgeName} =~ "deb" ]] && [[ ${packgeName} =~ "server" ]]) || ([[ ${packgeName} =~ "rpm" ]] && [[ ${packgeName} =~ "server" ]]) ;then +if [[ ${packageName} =~ "Lite" ]] || ([[ ${packageName} =~ "x64" ]] && [[ ${packageName} =~ "client" ]]) || ([[ ${packageName} =~ "deb" ]] && [[ ${packageName} =~ "server" ]]) || ([[ ${packageName} =~ "rpm" ]] && [[ ${packageName} =~ "server" ]]) ;then echoColor G "===== install taos-tools when package is lite or client =====" cd ${installPath} if [ ! -f "taosTools-2.1.3-Linux-x64.tar.gz " ];then @@ -334,7 +334,7 @@ if [[ ${packgeName} =~ "Lite" ]] || ([[ ${packgeName} =~ "x64" ]] && [[ ${pac tar xf taosTools-2.1.3-Linux-x64.tar.gz fi cd taosTools-2.1.3 && bash install-taostools.sh -elif ([[ ${packgeName} =~ "arm64" ]] && [[ ${packgeName} =~ "client" ]]);then +elif ([[ ${packageName} =~ "arm64" ]] && [[ ${packageName} =~ "client" ]]);then echoColor G "===== install taos-tools arm when package is arm64-client =====" cd ${installPath} if [ ! -f "taosTools-2.1.3-Linux-x64.tar.gz " ];then @@ -347,28 +347,28 @@ fi echoColor G "===== start TDengine =====" -if [[ ${packgeName} =~ "server" ]] ;then +if [[ ${packageName} =~ "server" ]] ;then echoColor BD " rm -rf /var/lib/taos/* && systemctl restart taosd " rm -rf /var/lib/taos/* systemctl restart taosd fi -rm -rf ${installPath}/${packgeName} +rm -rf ${installPath}/${packageName} rm -rf ${installPath}/${tdPath}/ -# if ([[ ${packgeName} =~ "Lite" ]] && [[ ${packgeName} =~ "tar" ]]) || [[ ${packgeName} =~ "client" ]] ;then +# if ([[ ${packageName} =~ "Lite" ]] && [[ ${packageName} =~ "tar" ]]) || [[ ${packageName} =~ "client" ]] ;then # echoColor G "===== install taos-tools when package is lite or client =====" # cd ${installPath} # wgetFile taosTools-2.1.2-Linux-x64.tar.gz . # tar xf taosTools-2.1.2-Linux-x64.tar.gz # cd taosTools-2.1.2 && bash install-taostools.sh -# elif [[ ${packgeName} =~ "Lite" ]] && [[ ${packgeName} =~ "deb" ]] ;then +# elif [[ ${packageName} =~ "Lite" ]] && [[ ${packageName} =~ "deb" ]] ;then # echoColor G "===== install taos-tools when package is lite or client =====" # cd ${installPath} # wgetFile taosTools-2.1.2-Linux-x64.tar.gz . # tar xf taosTools-2.1.2-Linux-x64.tar.gz # cd taosTools-2.1.2 && bash install-taostools.sh -# elif [[ ${packgeName} =~ "Lite" ]] && [[ ${packgeName} =~ "rpm" ]] ;then +# elif [[ ${packageName} =~ "Lite" ]] && [[ ${packageName} =~ "rpm" ]] ;then # echoColor G "===== install taos-tools when package is lite or client =====" # cd ${installPath} # wgetFile taosTools-2.1.2-Linux-x64.tar.gz . diff --git a/packaging/tools/com.taosdata.taoskeeper.plist b/packaging/tools/com.taosdata.taoskeeper.plist new file mode 100644 index 0000000000000000000000000000000000000000..338b5d8e79c4a6f529f70e85bdd2d8b64d67264f --- /dev/null +++ b/packaging/tools/com.taosdata.taoskeeper.plist @@ -0,0 +1,33 @@ + + + + + Label + com.tdengine.taoskeeper + ProgramArguments + + /usr/local/bin/taoskeeper + + ProcessType + Interactive + Disabled + + RunAtLoad + + LaunchOnlyOnce + + SessionCreate + + ExitTimeOut + 600 + KeepAlive + + SuccessfulExit + + AfterInitialDemand + + + Program + /usr/local/bin/taoskeeper + + \ No newline at end of file diff --git a/packaging/tools/install.sh b/packaging/tools/install.sh index dfdbaa6fdd634679d45b1fa3eeaa5aabdea36a23..1b47b10520147664a3c2f3a558fed1208f84a2ca 100755 --- a/packaging/tools/install.sh +++ b/packaging/tools/install.sh @@ -4,7 +4,7 @@ # is required to use systemd to manage services at boot set -e -#set -x +# set -x verMode=edge pagMode=full @@ -24,7 +24,7 @@ productName="TDengine" emailName="taosdata.com" uninstallScript="rmtaos" historyFile="taos_history" -tarName="taos.tar.gz" +tarName="package.tar.gz" dataDir="/var/lib/taos" logDir="/var/log/taos" configDir="/etc/taos" @@ -35,6 +35,25 @@ dumpName="taosdump" demoName="taosdemo" xname="taosx" +clientName2="taos" +serverName2="${clientName2}d" +configFile2="${clientName2}.cfg" +productName2="TDengine" +emailName2="taosdata.com" +xname2="${clientName2}x" +adapterName2="${clientName2}adapter" + +explorerName="${clientName2}-explorer" +benchmarkName2="${clientName2}Benchmark" +demoName2="${clientName2}demo" +dumpName2="${clientName2}dump" +uninstallScript2="rm${clientName2}" + +historyFile="${clientName2}_history" +logDir="/var/log/${clientName2}" +configDir="/etc/${clientName2}" +installDir="/usr/local/${clientName2}" + data_dir=${dataDir} log_dir=${logDir} cfg_install_dir=${configDir} @@ -191,32 +210,40 @@ function install_main_path() { function install_bin() { # Remove links - ${csudo}rm -f ${bin_link_dir}/${clientName} || : - ${csudo}rm -f ${bin_link_dir}/${serverName} || : + ${csudo}rm -f ${bin_link_dir}/${clientName2} || : + ${csudo}rm -f ${bin_link_dir}/${serverName2} || : ${csudo}rm -f ${bin_link_dir}/${udfdName} || : ${csudo}rm -f ${bin_link_dir}/${adapterName} || : - ${csudo}rm -f ${bin_link_dir}/${uninstallScript} || : - ${csudo}rm -f ${bin_link_dir}/${demoName} || : - ${csudo}rm -f ${bin_link_dir}/${benchmarkName} || : - ${csudo}rm -f ${bin_link_dir}/${dumpName} || : - ${csudo}rm -f ${bin_link_dir}/${xname} || : + ${csudo}rm -f ${bin_link_dir}/${uninstallScript2} || : + ${csudo}rm -f ${bin_link_dir}/${demoName2} || : + ${csudo}rm -f ${bin_link_dir}/${benchmarkName2} || : + ${csudo}rm -f ${bin_link_dir}/${dumpName2} || : + ${csudo}rm -f ${bin_link_dir}/${xname2} || : + ${csudo}rm -f ${bin_link_dir}/${explorerName} || : ${csudo}rm -f ${bin_link_dir}/set_core || : ${csudo}rm -f ${bin_link_dir}/TDinsight.sh || : ${csudo}cp -r ${script_dir}/bin/* ${install_main_dir}/bin && ${csudo}chmod 0555 ${install_main_dir}/bin/* #Make link - [ -x ${install_main_dir}/bin/${clientName} ] && ${csudo}ln -s ${install_main_dir}/bin/${clientName} ${bin_link_dir}/${clientName} || : - [ -x ${install_main_dir}/bin/${serverName} ] && ${csudo}ln -s ${install_main_dir}/bin/${serverName} ${bin_link_dir}/${serverName} || : - [ -x ${install_main_dir}/bin/${udfdName} ] && ${csudo}ln -s ${install_main_dir}/bin/${udfdName} ${bin_link_dir}/${udfdName} || : - [ -x ${install_main_dir}/bin/${adapterName} ] && ${csudo}ln -s ${install_main_dir}/bin/${adapterName} ${bin_link_dir}/${adapterName} || : - [ -x ${install_main_dir}/bin/${benchmarkName} ] && ${csudo}ln -sf ${install_main_dir}/bin/${benchmarkName} ${bin_link_dir}/${demoName} || : - [ -x ${install_main_dir}/bin/${benchmarkName} ] && ${csudo}ln -sf ${install_main_dir}/bin/${benchmarkName} ${bin_link_dir}/${benchmarkName} || : - [ -x ${install_main_dir}/bin/${dumpName} ] && ${csudo}ln -s ${install_main_dir}/bin/${dumpName} ${bin_link_dir}/${dumpName} || : - [ -x ${install_main_dir}/bin/${xname} ] && ${csudo}ln -s ${install_main_dir}/bin/${xname} ${bin_link_dir}/${xname} || : - [ -x ${install_main_dir}/bin/TDinsight.sh ] && ${csudo}ln -s ${install_main_dir}/bin/TDinsight.sh ${bin_link_dir}/TDinsight.sh || : - [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/${uninstallScript} || : + [ -x ${install_main_dir}/bin/${clientName2} ] && ${csudo}ln -sf ${install_main_dir}/bin/${clientName2} ${bin_link_dir}/${clientName2} || : + [ -x ${install_main_dir}/bin/${serverName2} ] && ${csudo}ln -sf ${install_main_dir}/bin/${serverName2} ${bin_link_dir}/${serverName2} || : + [ -x ${install_main_dir}/bin/${udfdName} ] && ${csudo}ln -sf ${install_main_dir}/bin/${udfdName} ${bin_link_dir}/${udfdName} || : + [ -x ${install_main_dir}/bin/${adapterName2} ] && ${csudo}ln -sf ${install_main_dir}/bin/${adapterName2} ${bin_link_dir}/${adapterName2} || : + [ -x ${install_main_dir}/bin/${benchmarkName2} ] && ${csudo}ln -sf ${install_main_dir}/bin/${benchmarkName2} ${bin_link_dir}/${demoName2} || : + [ -x ${install_main_dir}/bin/${benchmarkName2} ] && ${csudo}ln -sf ${install_main_dir}/bin/${benchmarkName2} ${bin_link_dir}/${benchmarkName2} || : + [ -x ${install_main_dir}/bin/${dumpName2} ] && ${csudo}ln -sf ${install_main_dir}/bin/${dumpName2} ${bin_link_dir}/${dumpName2} || : + [ -x ${install_main_dir}/bin/${xname2} ] && ${csudo}ln -sf ${install_main_dir}/bin/${xname2} ${bin_link_dir}/${xname2} || : + [ -x ${install_main_dir}/bin/${explorerName} ] && ${csudo}ln -sf ${install_main_dir}/bin/${explorerName} ${bin_link_dir}/${explorerName} || : + [ -x ${install_main_dir}/bin/TDinsight.sh ] && ${csudo}ln -sf ${install_main_dir}/bin/TDinsight.sh ${bin_link_dir}/TDinsight.sh || : + if [ "$clientName2" == "${clientName}" ]; then + [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/${uninstallScript} || : + fi [ -x ${install_main_dir}/bin/set_core.sh ] && ${csudo}ln -s ${install_main_dir}/bin/set_core.sh ${bin_link_dir}/set_core || : + + if [ "$verMode" == "cluster" ] && [ "$clientName" != "$clientName2" ]; then + [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/${uninstallScript2} || : + fi } function install_lib() { @@ -226,14 +253,14 @@ function install_lib() { #${csudo}rm -rf ${v15_java_app_dir} || : ${csudo}cp -rf ${script_dir}/driver/* ${install_main_dir}/driver && ${csudo}chmod 777 ${install_main_dir}/driver/* - ${csudo}ln -s ${install_main_dir}/driver/libtaos.* ${lib_link_dir}/libtaos.so.1 - ${csudo}ln -s ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so + ${csudo}ln -sf ${install_main_dir}/driver/libtaos.* ${lib_link_dir}/libtaos.so.1 + ${csudo}ln -sf ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so [ -f ${install_main_dir}/driver/libtaosws.so ] && ${csudo}ln -sf ${install_main_dir}/driver/libtaosws.so ${lib_link_dir}/libtaosws.so || : if [[ -d ${lib64_link_dir} && ! -e ${lib64_link_dir}/libtaos.so ]]; then - ${csudo}ln -s ${install_main_dir}/driver/libtaos.* ${lib64_link_dir}/libtaos.so.1 || : - ${csudo}ln -s ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so || : + ${csudo}ln -sf ${install_main_dir}/driver/libtaos.* ${lib64_link_dir}/libtaos.so.1 || : + ${csudo}ln -sf ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so || : [ -f ${install_main_dir}/libtaosws.so ] && ${csudo}ln -sf ${install_main_dir}/libtaosws.so ${lib64_link_dir}/libtaosws.so || : fi @@ -323,10 +350,10 @@ function install_header() { [ -f ${inc_link_dir}/taosws.h ] && ${csudo}rm -f ${inc_link_dir}/taosws.h || : ${csudo}cp -f ${script_dir}/inc/* ${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/taosdef.h ${inc_link_dir}/taosdef.h - ${csudo}ln -s ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h - ${csudo}ln -s ${install_main_dir}/include/taosudf.h ${inc_link_dir}/taosudf.h + ${csudo}ln -sf ${install_main_dir}/include/taos.h ${inc_link_dir}/taos.h + ${csudo}ln -sf ${install_main_dir}/include/taosdef.h ${inc_link_dir}/taosdef.h + ${csudo}ln -sf ${install_main_dir}/include/taoserror.h ${inc_link_dir}/taoserror.h + ${csudo}ln -sf ${install_main_dir}/include/taosudf.h ${inc_link_dir}/taosudf.h [ -f ${install_main_dir}/include/taosws.h ] && ${csudo}ln -sf ${install_main_dir}/include/taosws.h ${inc_link_dir}/taosws.h || : } @@ -375,7 +402,7 @@ function set_hostname() { ${csudo}sed -i -r "s/#*\s*(HOSTNAME=\s*).*/\1$newHostname/" /etc/sysconfig/network || : fi - ${csudo}sed -i -r "s/#*\s*(fqdn\s*).*/\1$newHostname/" ${cfg_install_dir}/${configFile} + ${csudo}sed -i -r "s/#*\s*(fqdn\s*).*/\1$newHostname/" ${cfg_install_dir}/${configFile2} serverFqdn=$newHostname if [[ -e /etc/hosts ]]; then @@ -409,7 +436,7 @@ function set_ipAsFqdn() { echo -e -n "${GREEN}Unable to get local ip, use 127.0.0.1${NC}" localFqdn="127.0.0.1" # Write the local FQDN to configuration file - ${csudo}sed -i -r "s/#*\s*(fqdn\s*).*/\1$localFqdn/" ${cfg_install_dir}/${configFile} + ${csudo}sed -i -r "s/#*\s*(fqdn\s*).*/\1$localFqdn/" ${cfg_install_dir}/${configFile2} serverFqdn=$localFqdn echo return @@ -431,7 +458,7 @@ function set_ipAsFqdn() { read -p "Please choose an IP from local IP list:" localFqdn else # Write the local FQDN to configuration file - ${csudo}sed -i -r "s/#*\s*(fqdn\s*).*/\1$localFqdn/" ${cfg_install_dir}/${configFile} + ${csudo}sed -i -r "s/#*\s*(fqdn\s*).*/\1$localFqdn/" ${cfg_install_dir}/${configFile2} serverFqdn=$localFqdn break fi @@ -487,7 +514,7 @@ function install_adapter_config() { fi [ -f ${cfg_install_dir}/${adapterName}.toml ] && - ${csudo}ln -s ${cfg_install_dir}/${adapterName}.toml ${install_main_dir}/cfg/${adapterName}.toml + ${csudo}ln -sf ${cfg_install_dir}/${adapterName}.toml ${install_main_dir}/cfg/${adapterName}.toml [ ! -z $1 ] && return 0 || : # only install client @@ -495,15 +522,15 @@ function install_adapter_config() { function install_config() { - if [ ! -f "${cfg_install_dir}/${configFile}" ]; then + if [ ! -f "${cfg_install_dir}/${configFile2}" ]; then ${csudo}mkdir -p ${cfg_install_dir} - [ -f ${script_dir}/cfg/${configFile} ] && ${csudo}cp ${script_dir}/cfg/${configFile} ${cfg_install_dir} + [ -f ${script_dir}/cfg/${configFile2} ] && ${csudo}cp ${script_dir}/cfg/${configFile2} ${cfg_install_dir} ${csudo}chmod 644 ${cfg_install_dir}/* else - ${csudo}cp -f ${script_dir}/cfg/${configFile} ${cfg_install_dir}/${configFile}.new + ${csudo}cp -f ${script_dir}/cfg/${configFile2} ${cfg_install_dir}/${configFile2}.new fi - ${csudo}ln -s ${cfg_install_dir}/${configFile} ${install_main_dir}/cfg + ${csudo}ln -sf ${cfg_install_dir}/${configFile2} ${install_main_dir}/cfg [ ! -z $1 ] && return 0 || : # only install client @@ -518,13 +545,13 @@ function install_config() { local_fqdn_check echo - echo -e -n "${GREEN}Enter FQDN:port (like h1.${emailName}:6030) of an existing ${productName} cluster node to join${NC}" + echo -e -n "${GREEN}Enter FQDN:port (like h1.${emailName2}:6030) of an existing ${productName2} cluster node to join${NC}" echo echo -e -n "${GREEN}OR leave it blank to build one${NC}:" read firstEp while true; do if [ ! -z "$firstEp" ]; then - ${csudo}sed -i -r "s/#*\s*(firstEp\s*).*/\1$firstEp/" ${cfg_install_dir}/${configFile} + ${csudo}sed -i -r "s/#*\s*(firstEp\s*).*/\1$firstEp/" ${cfg_install_dir}/${configFile2} break else break @@ -545,39 +572,57 @@ function install_config() { done } +function install_share_etc() { + [ ! -d ${script_dir}/share/etc ] && return + for c in `ls ${script_dir}/share/etc/`; do + if [ -e /etc/${clientName2}/$c ]; then + out=/etc/${clientName2}/$c.new.`date +%F` + ${csudo}cp -f ${script_dir}/share/etc/$c $out ||: + else + ${csudo}mkdir -p /etc/${clientName2} >/dev/null 2>/dev/null ||: + ${csudo}cp -f ${script_dir}/share/etc/$c /etc/${clientName2}/$c ||: + fi + done + + [ ! -d ${script_dir}/share/srv ] && return + ${csudo} cp ${script_dir}/share/srv/* ${service_config_dir} ||: +} + function install_log() { ${csudo}rm -rf ${log_dir} || : ${csudo}mkdir -p ${log_dir} && ${csudo}chmod 777 ${log_dir} - ${csudo}ln -s ${log_dir} ${install_main_dir}/log + ${csudo}ln -sf ${log_dir} ${install_main_dir}/log } function install_data() { ${csudo}mkdir -p ${data_dir} - ${csudo}ln -s ${data_dir} ${install_main_dir}/data + ${csudo}ln -sf ${data_dir} ${install_main_dir}/data } function install_connector() { - [ -d "${script_dir}/connector/" ] && ${csudo}cp -rf ${script_dir}/connector/ ${install_main_dir}/ + if [ -d "${script_dir}/connector/" ]; then + ${csudo}cp -rf ${script_dir}/connector/ ${install_main_dir}/ || echo "failed to copy connector" + fi } function install_examples() { if [ -d ${script_dir}/examples ]; then - ${csudo}cp -rf ${script_dir}/examples/* ${install_main_dir}/examples + ${csudo}cp -rf ${script_dir}/examples/* ${install_main_dir}/examples || echo "failed to copy examples" fi } function install_web() { if [ -d "${script_dir}/share" ]; then - ${csudo}cp -rf ${script_dir}/share/* ${install_main_dir}/share + ${csudo}cp -rf ${script_dir}/share/* ${install_main_dir}/share > /dev/null 2>&1 ||: fi } function clean_service_on_sysvinit() { - if ps aux | grep -v grep | grep ${serverName} &>/dev/null; then - ${csudo}service ${serverName} stop || : + if ps aux | grep -v grep | grep ${serverName2} &>/dev/null; then + ${csudo}service ${serverName2} stop || : fi if ps aux | grep -v grep | grep tarbitrator &>/dev/null; then @@ -585,30 +630,30 @@ function clean_service_on_sysvinit() { fi if ((${initd_mod} == 1)); then - if [ -e ${service_config_dir}/${serverName} ]; then - ${csudo}chkconfig --del ${serverName} || : + if [ -e ${service_config_dir}/${serverName2} ]; then + ${csudo}chkconfig --del ${serverName2} || : fi if [ -e ${service_config_dir}/tarbitratord ]; then ${csudo}chkconfig --del tarbitratord || : fi elif ((${initd_mod} == 2)); then - if [ -e ${service_config_dir}/${serverName} ]; then - ${csudo}insserv -r ${serverName} || : + if [ -e ${service_config_dir}/${serverName2} ]; then + ${csudo}insserv -r ${serverName2} || : fi if [ -e ${service_config_dir}/tarbitratord ]; then ${csudo}insserv -r tarbitratord || : fi elif ((${initd_mod} == 3)); then - if [ -e ${service_config_dir}/${serverName} ]; then - ${csudo}update-rc.d -f ${serverName} remove || : + if [ -e ${service_config_dir}/${serverName2} ]; then + ${csudo}update-rc.d -f ${serverName2} remove || : fi if [ -e ${service_config_dir}/tarbitratord ]; then ${csudo}update-rc.d -f tarbitratord remove || : fi fi - ${csudo}rm -f ${service_config_dir}/${serverName} || : + ${csudo}rm -f ${service_config_dir}/${serverName2} || : ${csudo}rm -f ${service_config_dir}/tarbitratord || : if $(which init &>/dev/null); then @@ -629,24 +674,24 @@ function install_service_on_sysvinit() { fi if ((${initd_mod} == 1)); then - ${csudo}chkconfig --add ${serverName} || : - ${csudo}chkconfig --level 2345 ${serverName} on || : + ${csudo}chkconfig --add ${serverName2} || : + ${csudo}chkconfig --level 2345 ${serverName2} on || : elif ((${initd_mod} == 2)); then - ${csudo}insserv ${serverName} || : - ${csudo}insserv -d ${serverName} || : + ${csudo}insserv ${serverName2} || : + ${csudo}insserv -d ${serverName2} || : elif ((${initd_mod} == 3)); then - ${csudo}update-rc.d ${serverName} defaults || : + ${csudo}update-rc.d ${serverName2} defaults || : fi } function clean_service_on_systemd() { - taosd_service_config="${service_config_dir}/${serverName}.service" - if systemctl is-active --quiet ${serverName}; then + service_config="${service_config_dir}/${serverName2}.service" + if systemctl is-active --quiet ${serverName2}; then echo "${productName} is running, stopping it..." - ${csudo}systemctl stop ${serverName} &>/dev/null || echo &>/dev/null + ${csudo}systemctl stop ${serverName2} &>/dev/null || echo &>/dev/null fi - ${csudo}systemctl disable ${serverName} &>/dev/null || echo &>/dev/null - ${csudo}rm -f ${taosd_service_config} + ${csudo}systemctl disable ${serverName2} &>/dev/null || echo &>/dev/null + ${csudo}rm -f ${service_config} tarbitratord_service_config="${service_config_dir}/tarbitratord.service" if systemctl is-active --quiet tarbitratord; then @@ -655,17 +700,49 @@ function clean_service_on_systemd() { fi ${csudo}systemctl disable tarbitratord &>/dev/null || echo &>/dev/null ${csudo}rm -f ${tarbitratord_service_config} + # if [ "$verMode" == "cluster" ] && [ "$clientName" != "$clientName2" ]; then + # ${csudo}rm -f ${service_config_dir}/${serverName2}.service + # fi + x_service_config="${service_config_dir}/${xName2}.service" + if [ -e "$x_service_config" ]; then + if systemctl is-active --quiet ${xName2}; then + echo "${productName2} ${xName2} is running, stopping it..." + ${csudo}systemctl stop ${xName2} &>/dev/null || echo &>/dev/null + fi + ${csudo}systemctl disable ${xName2} &>/dev/null || echo &>/dev/null + ${csudo}rm -f ${x_service_config} + fi + + explorer_service_config="${service_config_dir}/${explorerName2}.service" + if [ -e "$explorer_service_config" ]; then + if systemctl is-active --quiet ${explorerName2}; then + echo "${productName2} ${explorerName2} is running, stopping it..." + ${csudo}systemctl stop ${explorerName2} &>/dev/null || echo &>/dev/null + fi + ${csudo}systemctl disable ${explorerName2} &>/dev/null || echo &>/dev/null + ${csudo}rm -f ${explorer_service_config} + ${csudo}rm -f /etc/${clientName2}/explorer.toml + fi } function install_service_on_systemd() { clean_service_on_systemd - [ -f ${script_dir}/cfg/${serverName}.service ] && - ${csudo}cp ${script_dir}/cfg/${serverName}.service \ + install_share_etc + + [ -f ${script_dir}/cfg/${serverName2}.service ] && + ${csudo}cp ${script_dir}/cfg/${serverName2}.service \ ${service_config_dir}/ || : + + # if [ "$verMode" == "cluster" ] && [ "$clientName" != "$clientName2" ]; then + # [ -f ${script_dir}/cfg/${serverName2}.service ] && + # ${csudo}cp ${script_dir}/cfg/${serverName2}.service \ + # ${service_config_dir}/${serverName2}.service || : + # fi + ${csudo}systemctl daemon-reload - ${csudo}systemctl enable ${serverName} + ${csudo}systemctl enable ${serverName2} ${csudo}systemctl daemon-reload } @@ -685,7 +762,7 @@ function install_service() { elif ((${service_mod} == 1)); then install_service_on_sysvinit else - kill_process ${serverName} + kill_process ${serverName2} fi } @@ -722,10 +799,10 @@ function is_version_compatible() { if [ -f ${script_dir}/driver/vercomp.txt ]; then min_compatible_version=$(cat ${script_dir}/driver/vercomp.txt) else - min_compatible_version=$(${script_dir}/bin/${serverName} -V | head -1 | cut -d ' ' -f 5) + min_compatible_version=$(${script_dir}/bin/${serverName2} -V | head -1 | cut -d ' ' -f 5) fi - exist_version=$(${installDir}/bin/${serverName} -V | head -1 | cut -d ' ' -f 3) + exist_version=$(${installDir}/bin/${serverName2} -V | head -1 | cut -d ' ' -f 3) vercomp $exist_version "3.0.0.0" case $? in 2) @@ -793,15 +870,15 @@ function updateProduct() { tar -zxf ${tarName} install_jemalloc - echo -e "${GREEN}Start to update ${productName}...${NC}" + echo -e "${GREEN}Start to update ${productName2}...${NC}" # Stop the service if running - if ps aux | grep -v grep | grep ${serverName} &>/dev/null; then + if ps aux | grep -v grep | grep ${serverName2} &>/dev/null; then if ((${service_mod} == 0)); then - ${csudo}systemctl stop ${serverName} || : + ${csudo}systemctl stop ${serverName2} || : elif ((${service_mod} == 1)); then - ${csudo}service ${serverName} stop || : + ${csudo}service ${serverName2} stop || : else - kill_process ${serverName} + kill_process ${serverName2} fi sleep 1 fi @@ -828,44 +905,44 @@ function updateProduct() { openresty_work=false echo - echo -e "${GREEN_DARK}To configure ${productName} ${NC}: edit ${cfg_install_dir}/${configFile}" - [ -f ${configDir}/taosadapter.toml ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To configure Taos Adapter ${NC}: edit ${configDir}/taosadapter.toml" + echo -e "${GREEN_DARK}To configure ${productName2} ${NC}: edit ${cfg_install_dir}/${configFile2}" + [ -f ${configDir}/${clientName2}adapter.toml ] && [ -f ${installDir}/bin/${clientName2}adapter ] && \ + echo -e "${GREEN_DARK}To configure ${clientName2} Adapter ${NC}: edit ${configDir}/${clientName2}adapter.toml" if ((${service_mod} == 0)); then - echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}systemctl start ${serverName}${NC}" - [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adatper ${NC}: ${csudo}systemctl start taosadapter ${NC}" + echo -e "${GREEN_DARK}To start ${productName2} ${NC}: ${csudo}systemctl start ${serverName2}${NC}" + [ -f ${service_config_dir}/${clientName2}adapter.service ] && [ -f ${installDir}/bin/${clientName2}adapter ] && \ + echo -e "${GREEN_DARK}To start ${clientName2} Adapter ${NC}: ${csudo}systemctl start ${clientName2}adapter ${NC}" elif ((${service_mod} == 1)); then - echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}service ${serverName} start${NC}" - [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" + echo -e "${GREEN_DARK}To start ${productName2} ${NC}: ${csudo}service ${serverName2} start${NC}" + [ -f ${service_config_dir}/${clientName2}adapter.service ] && [ -f ${installDir}/bin/${clientName2}adapter ] && \ + echo -e "${GREEN_DARK}To start ${clientName2} Adapter ${NC}: ${csudo}service ${clientName2}adapter start${NC}" else - echo -e "${GREEN_DARK}To start ${productName} ${NC}: ./${serverName}${NC}" - [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" + echo -e "${GREEN_DARK}To start ${productName2} ${NC}: ./${serverName2}${NC}" + [ -f ${installDir}/bin/${clientName2}adapter ] && \ + echo -e "${GREEN_DARK}To start ${clientName2} Adapter ${NC}: ${clientName2}adapter &${NC}" fi if [ ${openresty_work} = 'true' ]; then - echo -e "${GREEN_DARK}To access ${productName} ${NC}: use ${GREEN_UNDERLINE}${clientName} -h $serverFqdn${NC} in shell OR from ${GREEN_UNDERLINE}http://127.0.0.1:${web_port}${NC}" + echo -e "${GREEN_DARK}To access ${productName2} ${NC}: use ${GREEN_UNDERLINE}${clientName2} -h $serverFqdn${NC} in shell OR from ${GREEN_UNDERLINE}http://127.0.0.1:${web_port}${NC}" else - echo -e "${GREEN_DARK}To access ${productName} ${NC}: use ${GREEN_UNDERLINE}${clientName} -h $serverFqdn${NC} in shell${NC}" + echo -e "${GREEN_DARK}To access ${productName2} ${NC}: use ${GREEN_UNDERLINE}${clientName2} -h $serverFqdn${NC} in shell${NC}" fi if ((${prompt_force} == 1)); then echo "" - echo -e "${RED}Please run '${serverName} --force-keep-file' at first time for the exist ${productName} $exist_version!${NC}" + echo -e "${RED}Please run '${serverName2} --force-keep-file' at first time for the exist ${productName2} $exist_version!${NC}" fi echo - echo -e "\033[44;32;1m${productName} is updated successfully!${NC}" + echo -e "\033[44;32;1m${productName2} is updated successfully!${NC}" else install_bin install_config echo - echo -e "\033[44;32;1m${productName} client is updated successfully!${NC}" + echo -e "\033[44;32;1m${productName2} client is updated successfully!${NC}" fi - rm -rf $(tar -tf ${tarName} | grep -v "^\./$") + rm -rf $(tar -tf ${tarName} | grep -Ev "^\./$|^\/") } function installProduct() { @@ -876,7 +953,7 @@ function installProduct() { fi tar -zxf ${tarName} - echo -e "${GREEN}Start to install ${productName}...${NC}" + echo -e "${GREEN}Start to install ${productName2}...${NC}" install_main_path @@ -910,21 +987,21 @@ function installProduct() { # Ask if to start the service echo - echo -e "${GREEN_DARK}To configure ${productName} ${NC}: edit ${cfg_install_dir}/${configFile}" - [ -f ${configDir}/taosadapter.toml ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To configure Taos Adapter ${NC}: edit ${configDir}/taosadapter.toml" + echo -e "${GREEN_DARK}To configure ${productName2} ${NC}: edit ${cfg_install_dir}/${configFile2}" + [ -f ${configDir}/${clientName2}adapter.toml ] && [ -f ${installDir}/bin/${clientName2}adapter ] && \ + echo -e "${GREEN_DARK}To configure ${clientName2} Adapter ${NC}: edit ${configDir}/${clientName2}adapter.toml" if ((${service_mod} == 0)); then - echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}systemctl start ${serverName}${NC}" - [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adatper ${NC}: ${csudo}systemctl start taosadapter ${NC}" + echo -e "${GREEN_DARK}To start ${productName2} ${NC}: ${csudo}systemctl start ${serverName2}${NC}" + [ -f ${service_config_dir}/${clientName2}adapter.service ] && [ -f ${installDir}/bin/${clientName2}adapter ] && \ + echo -e "${GREEN_DARK}To start ${clientName2} Adapter ${NC}: ${csudo}systemctl start ${clientName2}adapter ${NC}" elif ((${service_mod} == 1)); then - echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}service ${serverName} start${NC}" - [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" + echo -e "${GREEN_DARK}To start ${productName2} ${NC}: ${csudo}service ${serverName2} start${NC}" + [ -f ${service_config_dir}/${clientName2}adapter.service ] && [ -f ${installDir}/bin/${clientName2}adapter ] && \ + echo -e "${GREEN_DARK}To start ${clientName2} Adapter ${NC}: ${csudo}service ${clientName2}adapter start${NC}" else - echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${serverName}${NC}" - [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" + echo -e "${GREEN_DARK}To start ${productName2} ${NC}: ${serverName2}${NC}" + [ -f ${installDir}/bin/${clientName2}adapter ] && \ + echo -e "${GREEN_DARK}To start ${clientName2} Adapter ${NC}: ${clientName2}adapter &${NC}" fi if [ ! -z "$firstEp" ]; then @@ -936,28 +1013,28 @@ function installProduct() { tmpPort="" fi if [[ "$tmpPort" != "" ]]; then - echo -e "${GREEN_DARK}To access ${productName} ${NC}: ${clientName} -h $tmpFqdn -P $tmpPort${GREEN_DARK} to login into cluster, then${NC}" + echo -e "${GREEN_DARK}To access ${productName2} ${NC}: ${clientName2} -h $tmpFqdn -P $tmpPort${GREEN_DARK} to login into cluster, then${NC}" else - echo -e "${GREEN_DARK}To access ${productName} ${NC}: ${clientName} -h $tmpFqdn${GREEN_DARK} to login into cluster, then${NC}" + echo -e "${GREEN_DARK}To access ${productName2} ${NC}: ${clientName2} -h $tmpFqdn${GREEN_DARK} to login into cluster, then${NC}" fi echo -e "${GREEN_DARK}execute ${NC}: create dnode 'newDnodeFQDN:port'; ${GREEN_DARK}to add this new node${NC}" echo elif [ ! -z "$serverFqdn" ]; then - echo -e "${GREEN_DARK}To access ${productName} ${NC}: ${clientName} -h $serverFqdn${GREEN_DARK} to login into ${productName} server${NC}" + echo -e "${GREEN_DARK}To access ${productName2} ${NC}: ${clientName2} -h $serverFqdn${GREEN_DARK} to login into ${productName2} server${NC}" echo fi - echo -e "\033[44;32;1m${productName} is installed successfully!${NC}" + echo -e "\033[44;32;1m${productName2} is installed successfully!${NC}" echo else # Only install client install_bin install_config echo - echo -e "\033[44;32;1m${productName} client is installed successfully!${NC}" + echo -e "\033[44;32;1m${productName2} client is installed successfully!${NC}" fi touch ~/.${historyFile} - rm -rf $(tar -tf ${tarName} | grep -v "^\./$") + rm -rf $(tar -tf ${tarName} | grep -Ev "^\./$|^\/") } ## ==============================Main program starts from here============================ @@ -965,10 +1042,10 @@ serverFqdn=$(hostname) if [ "$verType" == "server" ]; then # Check default 2.x data file. if [ -x ${data_dir}/dnode/dnodeCfg.json ]; then - echo -e "\033[44;31;5mThe default data directory ${data_dir} contains old data of tdengine 2.x, please clear it before installing!\033[0m" + echo -e "\033[44;31;5mThe default data directory ${data_dir} contains old data of ${productName2} 2.x, please clear it before installing!\033[0m" else # Install server and client - if [ -x ${bin_dir}/${serverName} ]; then + if [ -x ${bin_dir}/${serverName2} ]; then update_flag=1 updateProduct else @@ -978,7 +1055,7 @@ if [ "$verType" == "server" ]; then elif [ "$verType" == "client" ]; then interactiveFqdn=no # Only install client - if [ -x ${bin_dir}/${clientName} ]; then + if [ -x ${bin_dir}/${clientName2} ]; then update_flag=1 updateProduct client else diff --git a/packaging/tools/install_client.sh b/packaging/tools/install_client.sh index f7d677c9821ed685750dcd50e2823f9abda4ef42..53b9c80f10082a1aa70dc6aec54ea54b25be66f1 100755 --- a/packaging/tools/install_client.sh +++ b/packaging/tools/install_client.sh @@ -17,12 +17,22 @@ serverName="taosd" clientName="taos" uninstallScript="rmtaos" configFile="taos.cfg" -tarName="taos.tar.gz" +tarName="package.tar.gz" osType=Linux pagMode=full verMode=edge +clientName2="taos" +serverName2="taosd" +productName2="TDengine" +emailName2="taosdata.com" + +benchmarkName2="${clientName2}Benchmark" +dumpName2="${clientName2}dump" +demoName2="${clientName2}demo" +uninstallScript2="rm${clientName2}" + if [ "$osType" != "Darwin" ]; then script_dir=$(dirname $(readlink -f "$0")) # Dynamic directory @@ -85,7 +95,7 @@ function install_main_path() { ${csudo}mkdir -p ${install_main_dir}/cfg ${csudo}mkdir -p ${install_main_dir}/bin ${csudo}mkdir -p ${install_main_dir}/driver - if [ $productName == "TDengine" ]; then + if [ "$productName2" == "TDengine" ]; then ${csudo}mkdir -p ${install_main_dir}/examples fi ${csudo}mkdir -p ${install_main_dir}/include @@ -108,10 +118,20 @@ function install_bin() { #Make link [ -x ${install_main_dir}/bin/${clientName} ] && ${csudo}ln -s ${install_main_dir}/bin/${clientName} ${bin_link_dir}/${clientName} || : if [ "$osType" != "Darwin" ]; then - [ -x ${install_main_dir}/bin/taosdemo ] && ${csudo}ln -s ${install_main_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || : + [ -x ${install_main_dir}/bin/${demoName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${demoName2} ${bin_link_dir}/${demoName2} || : fi [ -x ${install_main_dir}/bin/remove_client.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove_client.sh ${bin_link_dir}/${uninstallScript} || : [ -x ${install_main_dir}/bin/set_core.sh ] && ${csudo}ln -s ${install_main_dir}/bin/set_core.sh ${bin_link_dir}/set_core || : + + if [ "$verMode" == "cluster" ] && [ "$clientName" != "$clientName2" ]; then + #Make link + [ -x ${install_main_dir}/bin/${clientName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${clientName2} ${bin_link_dir}/${clientName2} || : + if [ "$osType" != "Darwin" ]; then + [ -x ${install_main_dir}/bin/${demoName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${demoName2} ${bin_link_dir}/${demoName2} || : + [ -x ${install_main_dir}/bin/${benchmarkName2} ] && ${csudo}ln -s ${install_main_dir}/bin/${benchmarkName2} ${bin_link_dir}/${benchmarkName2} || : + fi + [ -x ${install_main_dir}/bin/remove_client.sh ] && ${csudo}ln -sf ${install_main_dir}/bin/remove_client.sh ${bin_link_dir}/${uninstallScript2} || : + fi } function clean_lib() { @@ -263,9 +283,9 @@ function update_TDengine() { exit 1 fi tar -zxf ${tarName} - echo -e "${GREEN}Start to update ${productName} client...${NC}" + echo -e "${GREEN}Start to update ${productName2} client...${NC}" # Stop the client shell if running - if ps aux | grep -v grep | grep ${clientName} &> /dev/null; then + if ps aux | grep -v grep | grep ${clientName2} &> /dev/null; then kill_client sleep 1 fi @@ -284,9 +304,9 @@ function update_TDengine() { install_config echo - echo -e "\033[44;32;1m${productName} client is updated successfully!${NC}" + echo -e "\033[44;32;1m${productName2} client is updated successfully!${NC}" - rm -rf $(tar -tf ${tarName}) + rm -rf $(tar -tf ${tarName} | grep -Ev "^\./$|^\/") } function install_TDengine() { @@ -296,7 +316,7 @@ function install_TDengine() { exit 1 fi tar -zxf ${tarName} - echo -e "${GREEN}Start to install ${productName} client...${NC}" + echo -e "${GREEN}Start to install ${productName2} client...${NC}" install_main_path install_log @@ -311,9 +331,9 @@ function install_TDengine() { install_config echo - echo -e "\033[44;32;1m${productName} client is installed successfully!${NC}" + echo -e "\033[44;32;1m${productName2} client is installed successfully!${NC}" - rm -rf $(tar -tf ${tarName}) + rm -rf $(tar -tf ${tarName} | grep -Ev "^\./$|^\/") } @@ -321,7 +341,7 @@ function install_TDengine() { # Install or updata client and client # if server is already install, don't install client if [ -e ${bin_dir}/${serverName} ]; then - echo -e "\033[44;32;1mThere are already installed ${productName} server, so don't need install client!${NC}" + echo -e "\033[44;32;1mThere are already installed ${productName2} server, so don't need install client!${NC}" exit 0 fi diff --git a/packaging/tools/mac_before_install.txt b/packaging/tools/mac_before_install.txt index 3b6d610e882e9d2b6d9d8986f23fd1a5b8f9cb0a..4ce2374b7fed8e9cdaf50c62231df8ae6a2032e4 100644 --- a/packaging/tools/mac_before_install.txt +++ b/packaging/tools/mac_before_install.txt @@ -1,6 +1,9 @@ -TDengine is a high-efficient, scalable, high-available distributed time-series database, which makes a lot of optimizations on inserting and querying data, which is far more efficient than normal regular databases. So TDengine can meet the high requirements of IOT and other areas on storing and querying a large amount of data. +TDengine is an open-source, cloud-native time-series database optimized for Internet of Things (IoT), Connected Cars, and Industrial IoT. With its built-in caching, stream processing, and data subscription capabilities, TDengine offers a simplified solution for time-series data processing. + +• To configure TDengine, edit /etc/taos/taos.cfg +• To start service, run launchctl start com.tdengine.taosd +• To start Taos Adapter, run launchctl start com.tdengine.taosadapter +• To access TDengine from your local machine, run taos + +If you're experiencing problems installing TDengine, check the file /var/log/taos/tdengine_install.log to help troubleshoot the installation. -To configure TDengine : edit /etc/taos/taos.cfg -To start service : launchctl start com.tdengine.taosd -To start Taos Adapter : launchctl start com.tdengine.taosadapter -To access TDengine : use taos in shell \ No newline at end of file diff --git a/packaging/tools/mac_before_install_client.txt b/packaging/tools/mac_before_install_client.txt new file mode 100644 index 0000000000000000000000000000000000000000..cce8191667f7570591612944f611729e9e399c31 --- /dev/null +++ b/packaging/tools/mac_before_install_client.txt @@ -0,0 +1,9 @@ +TDengine is an open-source, cloud-native time-series database optimized for Internet of Things (IoT), Connected Cars, and Industrial IoT. With its built-in caching, stream processing, and data subscription capabilities, TDengine offers a simplified solution for time-series data processing. + +After the installation process is complete, perform the following steps to start using TDengine: +1: Open Terminal on your Mac. +2: To connect to a TDengine server using the default settings and credentials, run the taos command. +3: To connect to a TDengine server using custom settings or credentials, run taos --help for more information. +4: To connect to TDengine Cloud, follow the instructions on the Tools - TDengine CLI page in your TDengine Cloud account. + +If any issues occur during installation, check the /var/log/taos/tdengine_install.log file to troubleshoot. \ No newline at end of file diff --git a/packaging/tools/make_install.bat b/packaging/tools/make_install.bat index 993a8a19ee2862addc68304ff36359062846145b..41113c9ae45ca73c9623bffff9b921fdf4525f3f 100644 --- a/packaging/tools/make_install.bat +++ b/packaging/tools/make_install.bat @@ -22,6 +22,7 @@ set binary_dir=%3 set binary_dir=%binary_dir:/=\\% set osType=%4 set verNumber=%5 +set Enterprise=%6 set target_dir=C:\\TDengine if not exist %target_dir% ( @@ -65,7 +66,39 @@ if exist %binary_dir%\\build\\lib\\taosws.dll ( if exist %binary_dir%\\build\\bin\\taosdump.exe ( copy %binary_dir%\\build\\bin\\taosdump.exe %target_dir% > nul ) - +if %Enterprise% == TRUE ( + if exist %binary_dir%\\build\\bin\\taosx.exe ( + copy %binary_dir%\\build\\bin\\taosx.exe %target_dir% > nul + ) + if exist %binary_dir%\\build\\bin\\taos-explorer.exe ( + copy %binary_dir%\\build\\bin\\taos-explorer.exe %target_dir% > nul + ) + if exist %binary_dir%\\build\\bin\\tmq_sim.exe ( + copy %binary_dir%\\build\\bin\\tmq_sim.exe %target_dir% > nul + ) + if exist %binary_dir%\\build\\bin\\tsim.exe ( + copy %binary_dir%\\build\\bin\\tsim.exe %target_dir% > nul + ) + if exist %binary_dir%\\build\\bin\\tmq_taosx_ci.exe ( + copy %binary_dir%\\build\\bin\\tmq_taosx_ci.exe %target_dir% > nul + ) + if exist %binary_dir%\\build\\bin\\tmq_demo.exe ( + copy %binary_dir%\\build\\bin\\tmq_demo.exe %target_dir% > nul + ) + if exist %binary_dir%\\build\\bin\\dumper.exe ( + copy %binary_dir%\\build\\bin\\dumper.exe %target_dir% > nul + ) + if exist %binary_dir%\\build\\bin\\runUdf.exe ( + copy %binary_dir%\\build\\bin\\runUdf.exe %target_dir% > nul + ) + if exist %binary_dir%\\build\\bin\\create_table.exe ( + copy %binary_dir%\\build\\bin\\create_table.exe %target_dir% > nul + ) + if exist %binary_dir%\\build\\bin\\*explorer.exe ( + copy %binary_dir%\\build\\bin\\*explorer.exe %target_dir% > nul + ) +) + copy %binary_dir%\\build\\bin\\taosd.exe %target_dir% > nul copy %binary_dir%\\build\\bin\\udfd.exe %target_dir% > nul if exist %binary_dir%\\build\\bin\\taosadapter.exe ( @@ -91,9 +124,18 @@ call :stop_delete call :check_svc taosd call :check_svc taosadapter -copy /y C:\\TDengine\\driver\\taos.dll C:\\Windows\\System32 > nul -if exist C:\\TDengine\\driver\\taosws.dll ( - copy /y C:\\TDengine\\driver\\taosws.dll C:\\Windows\\System32 > nul +if exist c:\\windows\\sysnative ( + echo x86 + copy /y C:\\TDengine\\driver\\taos.dll %windir%\\sysnative > nul + if exist C:\\TDengine\\driver\\taosws.dll ( + copy /y C:\\TDengine\\driver\\taosws.dll %windir%\\sysnative > nul + ) +) else ( + echo x64 + copy /y C:\\TDengine\\driver\\taos.dll C:\\Windows\\System32 > nul + if exist C:\\TDengine\\driver\\taosws.dll ( + copy /y C:\\TDengine\\driver\\taosws.dll C:\\Windows\\System32 > nul + ) ) rem // create services diff --git a/packaging/tools/make_install.sh b/packaging/tools/make_install.sh index aae3c3b593ba9281929f793145b4598b15f46c95..98c5245cd39367203d7a8d8387b56846d1e19083 100755 --- a/packaging/tools/make_install.sh +++ b/packaging/tools/make_install.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # # This file is used to install TAOS time-series database on linux systems. The operating system # is required to use systemd to manage services at boot @@ -200,6 +200,7 @@ function install_bin() { [ -f ${binary_dir}/build/bin/taosadapter ] && ${csudo}cp -r ${binary_dir}/build/bin/taosadapter ${install_main_dir}/bin || : [ -f ${binary_dir}/build/bin/udfd ] && ${csudo}cp -r ${binary_dir}/build/bin/udfd ${install_main_dir}/bin || : [ -f ${binary_dir}/build/bin/taosx ] && ${csudo}cp -r ${binary_dir}/build/bin/taosx ${install_main_dir}/bin || : + [ -f ${binary_dir}/build/bin/*explorer ] && ${csudo}cp -r ${binary_dir}/build/bin/*explorer ${install_main_dir}/bin || : ${csudo}cp -r ${binary_dir}/build/bin/${serverName} ${install_main_dir}/bin || : ${csudo}cp -r ${script_dir}/remove.sh ${install_main_dir}/bin || : @@ -212,6 +213,7 @@ function install_bin() { [ -x ${install_main_dir}/bin/taosdump ] && ${csudo}ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump > /dev/null 2>&1 || : [ -f ${install_main_dir}/bin/taosBenchmark ] && ${csudo}ln -sf ${install_main_dir}/bin/taosBenchmark ${install_main_dir}/bin/taosdemo > /dev/null 2>&1 || : [ -x ${install_main_dir}/bin/taosx ] && ${csudo}ln -s ${install_main_dir}/bin/taosx ${bin_link_dir}/taosx > /dev/null 2>&1 || : + [ -x ${install_main_dir}/bin/*explorer ] && ${csudo}ln -s ${install_main_dir}/bin/*explorer ${bin_link_dir}/*explorer > /dev/null 2>&1 || : [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/${uninstallScript} > /dev/null 2>&1 || : fi } @@ -340,7 +342,7 @@ function install_lib() { #install_avro lib64 if [ "$osType" != "Darwin" ]; then - ${csudo}ldconfig + ${csudo}ldconfig /etc/ld.so.conf.d fi } @@ -606,23 +608,23 @@ function update_TDengine() { echo -e "${GREEN_DARK}To configure ${productName} ${NC}: edit ${configDir}/${configFile}" [ -f ${configDir}/taosadapter.toml ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To configure Taos Adapter ${NC}: edit ${configDir}/taosadapter.toml" + echo -e "${GREEN_DARK}To configure Adapter ${NC}: edit ${configDir}/taosadapter.toml" if ((${service_mod} == 0)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}systemctl start ${serverName}${NC}" [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adatper ${NC}: ${csudo}systemctl start taosadapter ${NC}" + echo -e "${GREEN_DARK}To start Adapter ${NC}: ${csudo}systemctl start taosadapter ${NC}" elif ((${service_mod} == 1)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}service ${serverName} start${NC}" [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" + echo -e "${GREEN_DARK}To start Adapter ${NC}: ${csudo}service taosadapter start${NC}" else if [ "$osType" != "Darwin" ]; then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${serverName}${NC}" [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" + echo -e "${GREEN_DARK}To start Adapter ${NC}: taosadapter &${NC}" else echo -e "${GREEN_DARK}To start service ${NC}: launchctl start com.tdengine.taosd${NC}" - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: launchctl start com.tdengine.taosadapter${NC}" + echo -e "${GREEN_DARK}To start Adapter ${NC}: launchctl start com.tdengine.taosadapter${NC}" fi fi @@ -658,23 +660,23 @@ function install_TDengine() { echo echo -e "${GREEN_DARK}To configure ${productName} ${NC}: edit ${configDir}/${configFile}" [ -f ${configDir}/taosadapter.toml ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To configure Taos Adapter ${NC}: edit ${configDir}/taosadapter.toml" + echo -e "${GREEN_DARK}To configure Adapter ${NC}: edit ${configDir}/taosadapter.toml" if ((${service_mod} == 0)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}systemctl start ${serverName}${NC}" [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}systemctl start taosadapter ${NC}" + echo -e "${GREEN_DARK}To start Adapter ${NC}: ${csudo}systemctl start taosadapter ${NC}" elif ((${service_mod} == 1)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}service ${serverName} start${NC}" [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" + echo -e "${GREEN_DARK}To start Adapter ${NC}: ${csudo}service taosadapter start${NC}" else if [ "$osType" != "Darwin" ]; then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${serverName}${NC}" [ -f ${installDir}/bin/taosadapter ] && \ - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" + echo -e "${GREEN_DARK}To start Adapter ${NC}: taosadapter &${NC}" else echo -e "${GREEN_DARK}To start service ${NC}: launchctl start com.tdengine.taosd${NC}" - echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: launchctl start com.tdengine.taosadapter${NC}" + echo -e "${GREEN_DARK}To start Adapter ${NC}: launchctl start com.tdengine.taosadapter${NC}" fi fi diff --git a/packaging/tools/makeclient.sh b/packaging/tools/makeclient.sh index db28de8decada6593abf5600bd8cf86cfe7d0984..28dc770755a9af46bff1f429a7107194e41ae75d 100755 --- a/packaging/tools/makeclient.sh +++ b/packaging/tools/makeclient.sh @@ -2,7 +2,7 @@ # # Generate tar.gz package for linux client in all os system set -e -# set -x +set -x curr_dir=$(pwd) compile_dir=$1 @@ -13,12 +13,21 @@ osType=$5 verMode=$6 verType=$7 pagMode=$8 -dbName=$9 +#comVersion=$9 +dbName=$10 + +productName2="${11}" +#serverName2="${12}d" +clientName2="${12}" +# cusEmail2=${13} productName="TDengine" clientName="taos" +benchmarkName="taosBenchmark" configFile="taos.cfg" -tarName="taos.tar.gz" +tarName="package.tar.gz" + +benchmarkName2="${clientName2}Benchmark" if [ "$osType" != "Darwin" ]; then script_dir="$(dirname $(readlink -f $0))" @@ -38,15 +47,22 @@ release_dir="${top_dir}/release" #package_name='linux' if [ "$verMode" == "cluster" ]; then - install_dir="${release_dir}/${productName}-enterprise-client-${version}" + install_dir="${release_dir}/${productName2}-enterprise-client-${version}" elif [ "$verMode" == "cloud" ]; then - install_dir="${release_dir}/${productName}-cloud-client-${version}" + install_dir="${release_dir}/${productName2}-cloud-client-${version}" else - install_dir="${release_dir}/${productName}-client-${version}" + install_dir="${release_dir}/${productName2}-client-${version}" fi # Directories and files. +#if [ "$verMode" == "cluster" ]; then +# sed -i 's/verMode=edge/verMode=cluster/g' ${script_dir}/remove_client.sh +# sed -i "s/clientName2=\"taos\"/clientName2=\"${clientName2}\"/g" ${script_dir}/remove_client.sh +# sed -i "s/configFile2=\"taos\"/configFile2=\"${clientName2}\"/g" ${script_dir}/remove_client.sh +# sed -i "s/productName2=\"TDengine\"/productName2=\"${productName2}\"/g" ${script_dir}/remove_client.sh +#fi + if [ "$osType" != "Darwin" ]; then if [ "$pagMode" == "lite" ]; then strip ${build_dir}/bin/${clientName} @@ -54,6 +70,7 @@ if [ "$osType" != "Darwin" ]; then ${script_dir}/remove_client.sh" else bin_files="${build_dir}/bin/${clientName} \ + ${build_dir}/bin/${benchmarkName} \ ${script_dir}/remove_client.sh \ ${script_dir}/set_core.sh \ ${script_dir}/get_client.sh" @@ -131,22 +148,29 @@ fi cd ${curr_dir} cp ${install_files} ${install_dir} +cp ${install_dir}/install_client.sh install_client_temp.sh if [ "$osType" == "Darwin" ]; then - sed 's/osType=Linux/osType=Darwin/g' ${install_dir}/install_client.sh >>install_client_temp.sh + sed -i 's/osType=Linux/osType=Darwin/g' install_client_temp.sh mv install_client_temp.sh ${install_dir}/install_client.sh fi if [ "$verMode" == "cluster" ]; then - sed 's/verMode=edge/verMode=cluster/g' ${install_dir}/install_client.sh >>install_client_temp.sh + sed -i 's/verMode=edge/verMode=cluster/g' install_client_temp.sh + sed -i "s/serverName2=\"taosd\"/serverName2=\"${serverName2}\"/g" install_client_temp.sh + sed -i "s/clientName2=\"taos\"/clientName2=\"${clientName2}\"/g" install_client_temp.sh + sed -i "s/configFile2=\"taos.cfg\"/configFile2=\"${clientName2}.cfg\"/g" install_client_temp.sh + sed -i "s/productName2=\"TDengine\"/productName2=\"${productName2}\"/g" install_client_temp.sh + sed -i "s/emailName2=\"taosdata.com\"/emailName2=\"${cusEmail2}\"/g" install_client_temp.sh + mv install_client_temp.sh ${install_dir}/install_client.sh fi if [ "$verMode" == "cloud" ]; then - sed 's/verMode=edge/verMode=cloud/g' ${install_dir}/install_client.sh >>install_client_temp.sh + sed -i 's/verMode=edge/verMode=cloud/g' install_client_temp.sh mv install_client_temp.sh ${install_dir}/install_client.sh fi if [ "$pagMode" == "lite" ]; then - sed 's/pagMode=full/pagMode=lite/g' ${install_dir}/install_client.sh >>install_client_temp.sh + sed -i 's/pagMode=full/pagMode=lite/g' install_client_temp.sh mv install_client_temp.sh ${install_dir}/install_client.sh fi chmod a+x ${install_dir}/install_client.sh @@ -173,7 +197,8 @@ if [[ $productName == "TDengine" ]]; then mkdir -p ${install_dir}/connector if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then if [ "$osType" != "Darwin" ]; then - [ -f ${build_dir}/lib/*.jar ] && cp ${build_dir}/lib/*.jar ${install_dir}/connector || : + jars=$(ls ${build_dir}/lib/*.jar 2>/dev/null|wc -l) + [ "${jars}" != "0" ] && cp ${build_dir}/lib/*.jar ${install_dir}/connector || : fi git clone --depth 1 https://github.com/taosdata/driver-go ${install_dir}/connector/go rm -rf ${install_dir}/connector/go/.git ||: diff --git a/packaging/tools/makepkg.sh b/packaging/tools/makepkg.sh index 0ee548242f2a69b025dddb46381d8d8c1d30d799..3da005c405cd61aa77ebf89240497ffa485b989f 100755 --- a/packaging/tools/makepkg.sh +++ b/packaging/tools/makepkg.sh @@ -16,6 +16,10 @@ verType=$7 pagMode=$8 versionComp=$9 dbName=${10} +productName2="${11}" +serverName2="${12}d" +clientName2="${12}" +cusEmail2="${13}" script_dir="$(dirname $(readlink -f $0))" top_dir="$(readlink -f ${script_dir}/../..)" @@ -24,7 +28,7 @@ productName="TDengine" serverName="taosd" clientName="taos" configFile="taos.cfg" -tarName="taos.tar.gz" +tarName="package.tar.gz" dumpName="taosdump" benchmarkName="taosBenchmark" toolsName="taostools" @@ -38,23 +42,23 @@ release_dir="${top_dir}/release" #package_name='linux' if [ "$verMode" == "cluster" ]; then - install_dir="${release_dir}/${productName}-enterprise-server-${version}" + install_dir="${release_dir}/${productName2}-enterprise-server-${version}" elif [ "$verMode" == "cloud" ]; then - install_dir="${release_dir}/${productName}-cloud-server-${version}" + install_dir="${release_dir}/${productName2}-cloud-server-${version}" else - install_dir="${release_dir}/${productName}-server-${version}" + install_dir="${release_dir}/${productName2}-server-${version}" fi if [ -d ${top_dir}/tools/taos-tools/packaging/deb ]; then cd ${top_dir}/tools/taos-tools/packaging/deb - [ -z "$taos_tools_ver" ] && taos_tools_ver="0.1.0" - taostools_ver=$(git tag |grep -v taos | sort | tail -1) - taostools_install_dir="${release_dir}/${clientName}Tools-${taostools_ver}" + taostools_ver=$(git for-each-ref --sort=taggerdate --format '%(tag)' refs/tags|grep -v taos | tail -1) + [ -z "$taostools_ver" ] && taostools_ver="0.1.0" + taostools_install_dir="${release_dir}/${clientName2}Tools-${taostools_ver}" cd ${curr_dir} else - taostools_install_dir="${release_dir}/${clientName}Tools-${version}" + taostools_install_dir="${release_dir}/${clientName2}Tools-${version}" fi # Directories and files @@ -85,12 +89,14 @@ else ${build_dir}/bin/tdengine-datasource.zip \ ${build_dir}/bin/tdengine-datasource.zip.md5sum" [ -f ${build_dir}/bin/taosx ] && taosx_bin="${build_dir}/bin/taosx" + explorer_bin_files=$(find ${build_dir}/bin/ -name '*-explorer') bin_files="${build_dir}/bin/${serverName} \ ${build_dir}/bin/${clientName} \ ${taostools_bin_files} \ ${taosx_bin} \ - ${build_dir}/bin/taosadapter \ + ${explorer_bin_files} \ + ${build_dir}/bin/${clientName}adapter \ ${build_dir}/bin/udfd \ ${script_dir}/remove.sh \ ${script_dir}/set_core.sh \ @@ -129,12 +135,12 @@ mkdir -p ${install_dir}/inc && cp ${header_files} ${install_dir}/inc mkdir -p ${install_dir}/cfg && cp ${cfg_dir}/${configFile} ${install_dir}/cfg/${configFile} -if [ -f "${compile_dir}/test/cfg/taosadapter.toml" ]; then - cp ${compile_dir}/test/cfg/taosadapter.toml ${install_dir}/cfg || : +if [ -f "${compile_dir}/test/cfg/${clientName}adapter.toml" ]; then + cp ${compile_dir}/test/cfg/${clientName}adapter.toml ${install_dir}/cfg || : fi -if [ -f "${compile_dir}/test/cfg/taosadapter.service" ]; then - cp ${compile_dir}/test/cfg/taosadapter.service ${install_dir}/cfg || : +if [ -f "${compile_dir}/test/cfg/${clientName}adapter.service" ]; then + cp ${compile_dir}/test/cfg/${clientName}adapter.service ${install_dir}/cfg || : fi if [ -f "${cfg_dir}/${serverName}.service" ]; then @@ -144,18 +150,19 @@ fi mkdir -p ${install_dir}/bin && cp ${bin_files} ${install_dir}/bin && chmod a+x ${install_dir}/bin/* || : mkdir -p ${install_dir}/init.d && cp ${init_file_deb} ${install_dir}/init.d/${serverName}.deb mkdir -p ${install_dir}/init.d && cp ${init_file_rpm} ${install_dir}/init.d/${serverName}.rpm +# mkdir -p ${install_dir}/share && cp -rf ${build_dir}/share/{etc,srv} ${install_dir}/share ||: if [ $adapterName != "taosadapter" ]; then - mv ${install_dir}/cfg/taosadapter.toml ${install_dir}/cfg/$adapterName.toml + mv ${install_dir}/cfg/${clientName2}adapter.toml ${install_dir}/cfg/$adapterName.toml sed -i "s/path = \"\/var\/log\/taos\"/path = \"\/var\/log\/${productName}\"/g" ${install_dir}/cfg/$adapterName.toml sed -i "s/password = \"taosdata\"/password = \"${defaultPasswd}\"/g" ${install_dir}/cfg/$adapterName.toml - mv ${install_dir}/cfg/taosadapter.service ${install_dir}/cfg/$adapterName.service + mv ${install_dir}/cfg/${clientName2}adapter.service ${install_dir}/cfg/$adapterName.service sed -i "s/TDengine/${productName}/g" ${install_dir}/cfg/$adapterName.service sed -i "s/taosAdapter/${adapterName}/g" ${install_dir}/cfg/$adapterName.service sed -i "s/taosadapter/${adapterName}/g" ${install_dir}/cfg/$adapterName.service - mv ${install_dir}/bin/taosadapter ${install_dir}/bin/${adapterName} + mv ${install_dir}/bin/${clientName2}adapter ${install_dir}/bin/${adapterName} mv ${install_dir}/bin/taosd-dump-cfg.gdb ${install_dir}/bin/${serverName}-dump-cfg.gdb fi @@ -165,22 +172,22 @@ if [ -n "${taostools_bin_files}" ]; then && cp ${taostools_bin_files} ${taostools_install_dir}/bin \ && chmod a+x ${taostools_install_dir}/bin/* || : - if [ -f ${top_dir}/tools/taos-tools/packaging/tools/install-taostools.sh ]; then - cp ${top_dir}/tools/taos-tools/packaging/tools/install-taostools.sh \ + if [ -f ${top_dir}/tools/taos-tools/packaging/tools/install-tools.sh ]; then + cp ${top_dir}/tools/taos-tools/packaging/tools/install-tools.sh \ ${taostools_install_dir}/ > /dev/null \ - && chmod a+x ${taostools_install_dir}/install-taostools.sh \ - || echo -e "failed to copy install-taostools.sh" + && chmod a+x ${taostools_install_dir}/install-tools.sh \ + || echo -e "failed to copy install-tools.sh" else - echo -e "install-taostools.sh not found" + echo -e "install-tools.sh not found" fi - if [ -f ${top_dir}/tools/taos-tools/packaging/tools/uninstall-taostools.sh ]; then - cp ${top_dir}/tools/taos-tools/packaging/tools/uninstall-taostools.sh \ + if [ -f ${top_dir}/tools/taos-tools/packaging/tools/uninstall-tools.sh ]; then + cp ${top_dir}/tools/taos-tools/packaging/tools/uninstall-tools.sh \ ${taostools_install_dir}/ > /dev/null \ - && chmod a+x ${taostools_install_dir}/uninstall-taostools.sh \ - || echo -e "failed to copy uninstall-taostools.sh" + && chmod a+x ${taostools_install_dir}/uninstall-tools.sh \ + || echo -e "failed to copy uninstall-tools.sh" else - echo -e "uninstall-taostools.sh not found" + echo -e "uninstall-tools.sh not found" fi if [ -f ${build_dir}/lib/libavro.so.23.0.0 ]; then @@ -225,6 +232,12 @@ fi if [ "$verMode" == "cluster" ]; then sed 's/verMode=edge/verMode=cluster/g' ${install_dir}/bin/remove.sh >>remove_temp.sh + sed -i "s/serverName2=\"taosd\"/serverName2=\"${serverName2}\"/g" remove_temp.sh + sed -i "s/clientName2=\"taos\"/clientName2=\"${clientName2}\"/g" remove_temp.sh + sed -i "s/configFile2=\"taos.cfg\"/configFile2=\"${clientName2}.cfg\"/g" remove_temp.sh + sed -i "s/productName2=\"TDengine\"/productName2=\"${productName2}\"/g" remove_temp.sh + cusDomain=`echo "${cusEmail2}" | sed 's/^[^@]*@//'` + sed -i "s/emailName2=\"taosdata.com\"/emailName2=\"${cusDomain}\"/g" remove_temp.sh mv remove_temp.sh ${install_dir}/bin/remove.sh fi if [ "$verMode" == "cloud" ]; then @@ -247,16 +260,23 @@ fi cd ${curr_dir} cp ${install_files} ${install_dir} +cp ${install_dir}/install.sh install_temp.sh if [ "$verMode" == "cluster" ]; then - sed 's/verMode=edge/verMode=cluster/g' ${install_dir}/install.sh >>install_temp.sh + sed -i 's/verMode=edge/verMode=cluster/g' install_temp.sh + sed -i "s/serverName2=\"taosd\"/serverName2=\"${serverName2}\"/g" install_temp.sh + sed -i "s/clientName2=\"taos\"/clientName2=\"${clientName2}\"/g" install_temp.sh + sed -i "s/configFile2=\"taos.cfg\"/configFile2=\"${clientName2}.cfg\"/g" install_temp.sh + sed -i "s/productName2=\"TDengine\"/productName2=\"${productName2}\"/g" install_temp.sh + cusDomain=`echo "${cusEmail2}" | sed 's/^[^@]*@//'` + sed -i "s/emailName2=\"taosdata.com\"/emailName2=\"${cusDomain}\"/g" install_temp.sh mv install_temp.sh ${install_dir}/install.sh fi if [ "$verMode" == "cloud" ]; then - sed 's/verMode=edge/verMode=cloud/g' ${install_dir}/install.sh >>install_temp.sh + sed -i 's/verMode=edge/verMode=cloud/g' install_temp.sh mv install_temp.sh ${install_dir}/install.sh fi if [ "$pagMode" == "lite" ]; then - sed 's/pagMode=full/pagMode=lite/g' ${install_dir}/install.sh >>install_temp.sh + sed -i 's/pagMode=full/pagMode=lite/g' install_temp.sh mv install_temp.sh ${install_dir}/install.sh fi chmod a+x ${install_dir}/install.sh @@ -302,6 +322,7 @@ if [[ $dbName == "taos" ]]; then mkdir -p ${install_dir}/share/ cp -Rfap ${web_dir}/admin ${install_dir}/share/ cp ${web_dir}/png/taos.png ${install_dir}/share/admin/images/taos.png + cp -rf ${build_dir}/share/{etc,srv} ${install_dir}/share ||: else echo "directory not found for enterprise release: ${web_dir}/admin" fi @@ -317,7 +338,20 @@ if [ "$verMode" == "cluster" ] || [ "$verMode" == "cloud" ]; then connector_dir="${code_dir}/connector" mkdir -p ${install_dir}/connector if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then - [ -f ${build_dir}/lib/*.jar ] && cp ${build_dir}/lib/*.jar ${install_dir}/connector || : + tmp_pwd=`pwd` + cd ${install_dir}/connector + if [ ! -d taos-connector-jdbc ];then + git clone -b 3.1.0 --depth=1 https://github.com/taosdata/taos-connector-jdbc.git ||: + fi + cd taos-connector-jdbc + mvn clean package -Dmaven.test.skip=true + echo ${build_dir}/lib/ + cp target/*.jar ${build_dir}/lib/ + cd ${install_dir}/connector + rm -rf taos-connector-jdbc + cd ${tmp_pwd} + jars=$(ls ${build_dir}/lib/*.jar 2>/dev/null|wc -l) + [ "${jars}" != "0" ] && cp ${build_dir}/lib/*.jar ${install_dir}/connector || : git clone --depth 1 https://github.com/taosdata/driver-go ${install_dir}/connector/go rm -rf ${install_dir}/connector/go/.git ||: diff --git a/packaging/tools/post.sh b/packaging/tools/post.sh index 4441e0ba1f54e61ab4a276eed33a7001c0845a22..fc392c9684c04ed6ce587d977ec4628df59cbe6f 100755 --- a/packaging/tools/post.sh +++ b/packaging/tools/post.sh @@ -48,6 +48,7 @@ fi data_link_dir="${install_main_dir}/data" log_link_dir="${install_main_dir}/log" +install_log_path="${log_dir}/tdengine_install.log" # static directory cfg_dir="${install_main_dir}/cfg" @@ -101,6 +102,11 @@ if [ "$osType" = "Darwin" ]; then ${csudo}cp -rf tdengine ${install_main_dir} fi +function log_print(){ + now=$(date +"%D %T") + echo "$now $1" >> ${install_log_path} +} + function kill_taosadapter() { # ${csudo}pkill -f taosadapter || : pid=$(ps -ef | grep "taosadapter" | grep -v "grep" | awk '{print $2}') @@ -109,6 +115,13 @@ function kill_taosadapter() { fi } +function kill_taoskeeper() { + pid=$(ps -ef | grep "taoskeeper" | grep -v "grep" | awk '{print $2}') + if [ -n "$pid" ]; then + ${csudo}kill -9 $pid || : + fi +} + function kill_taosd() { # ${csudo}pkill -f taosd || : pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}') @@ -118,6 +131,7 @@ function kill_taosd() { } function install_include() { + log_print "start install include from ${inc_dir} to ${inc_link_dir}" ${csudo}mkdir -p ${inc_link_dir} ${csudo}rm -f ${inc_link_dir}/taos.h ${inc_link_dir}/taosdef.h ${inc_link_dir}/taoserror.h ${inc_link_dir}/taosudf.h || : [ -f ${inc_link_dir}/taosws.h ] && ${csudo}rm -f ${inc_link_dir}/taosws.h ||: @@ -128,57 +142,142 @@ function install_include() { ${csudo}ln -s ${inc_dir}/taosudf.h ${inc_link_dir}/taosudf.h [ -f ${inc_dir}/taosws.h ] && ${csudo}ln -sf ${inc_dir}/taosws.h ${inc_link_dir}/taosws.h ||: + log_print "install include success" +} + +function install_jemalloc() { + jemalloc_dir=${script_dir}/../jemalloc + + if [ -d ${jemalloc_dir} ]; then + ${csudo}/usr/bin/install -c -d /usr/local/bin + + if [ -f ${jemalloc_dir}/bin/jemalloc-config ]; then + ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/bin/jemalloc-config /usr/local/bin + fi + if [ -f ${jemalloc_dir}/bin/jemalloc.sh ]; then + ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/bin/jemalloc.sh /usr/local/bin + fi + if [ -f ${jemalloc_dir}/bin/jeprof ]; then + ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/bin/jeprof /usr/local/bin + fi + if [ -f ${jemalloc_dir}/include/jemalloc/jemalloc.h ]; then + ${csudo}/usr/bin/install -c -d /usr/local/include/jemalloc + ${csudo}/usr/bin/install -c -m 644 ${jemalloc_dir}/include/jemalloc/jemalloc.h /usr/local/include/jemalloc + fi + if [ -f ${jemalloc_dir}/lib/libjemalloc.so.2 ]; then + ${csudo}/usr/bin/install -c -d /usr/local/lib + ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/lib/libjemalloc.so.2 /usr/local/lib + ${csudo}ln -sf libjemalloc.so.2 /usr/local/lib/libjemalloc.so + ${csudo}/usr/bin/install -c -d /usr/local/lib + if [ -f ${jemalloc_dir}/lib/libjemalloc.a ]; then + ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/lib/libjemalloc.a /usr/local/lib + fi + if [ -f ${jemalloc_dir}/lib/libjemalloc_pic.a ]; then + ${csudo}/usr/bin/install -c -m 755 ${jemalloc_dir}/lib/libjemalloc_pic.a /usr/local/lib + fi + if [ -f ${jemalloc_dir}/lib/libjemalloc_pic.a ]; then + ${csudo}/usr/bin/install -c -d /usr/local/lib/pkgconfig + ${csudo}/usr/bin/install -c -m 644 ${jemalloc_dir}/lib/pkgconfig/jemalloc.pc /usr/local/lib/pkgconfig + fi + fi + if [ -f ${jemalloc_dir}/share/doc/jemalloc/jemalloc.html ]; then + ${csudo}/usr/bin/install -c -d /usr/local/share/doc/jemalloc + ${csudo}/usr/bin/install -c -m 644 ${jemalloc_dir}/share/doc/jemalloc/jemalloc.html /usr/local/share/doc/jemalloc + fi + if [ -f ${jemalloc_dir}/share/man/man3/jemalloc.3 ]; then + ${csudo}/usr/bin/install -c -d /usr/local/share/man/man3 + ${csudo}/usr/bin/install -c -m 644 ${jemalloc_dir}/share/man/man3/jemalloc.3 /usr/local/share/man/man3 + fi + + if [ -d /etc/ld.so.conf.d ]; then + echo "/usr/local/lib" | ${csudo}tee /etc/ld.so.conf.d/jemalloc.conf >/dev/null || echo -e "failed to write /etc/ld.so.conf.d/jemalloc.conf" + ${csudo}ldconfig + else + echo "/etc/ld.so.conf.d not found!" + fi + fi } function install_lib() { + log_print "start install lib from ${lib_dir} to ${lib_link_dir}" ${csudo}rm -f ${lib_link_dir}/libtaos* || : ${csudo}rm -f ${lib64_link_dir}/libtaos* || : [ -f ${lib_link_dir}/libtaosws.${lib_file_ext} ] && ${csudo}rm -f ${lib_link_dir}/libtaosws.${lib_file_ext} || : [ -f ${lib64_link_dir}/libtaosws.${lib_file_ext} ] && ${csudo}rm -f ${lib64_link_dir}/libtaosws.${lib_file_ext} || : - ${csudo}ln -s ${lib_dir}/libtaos.* ${lib_link_dir}/libtaos.${lib_file_ext_1} - ${csudo}ln -s ${lib_link_dir}/libtaos.${lib_file_ext_1} ${lib_link_dir}/libtaos.${lib_file_ext} + ${csudo}ln -s ${lib_dir}/libtaos.* ${lib_link_dir}/libtaos.${lib_file_ext_1} 2>>${install_log_path} || return 1 + ${csudo}ln -s ${lib_link_dir}/libtaos.${lib_file_ext_1} ${lib_link_dir}/libtaos.${lib_file_ext} 2>>${install_log_path} || return 1 [ -f ${lib_dir}/libtaosws.${lib_file_ext} ] && ${csudo}ln -sf ${lib_dir}/libtaosws.${lib_file_ext} ${lib_link_dir}/libtaosws.${lib_file_ext} ||: if [[ -d ${lib64_link_dir} && ! -e ${lib64_link_dir}/libtaos.${lib_file_ext} ]]; then - ${csudo}ln -s ${lib_dir}/libtaos.* ${lib64_link_dir}/libtaos.${lib_file_ext_1} || : - ${csudo}ln -s ${lib64_link_dir}/libtaos.${lib_file_ext_1} ${lib64_link_dir}/libtaos.${lib_file_ext} || : + ${csudo}ln -s ${lib_dir}/libtaos.* ${lib64_link_dir}/libtaos.${lib_file_ext_1} 2>>${install_log_path} || return 1 + ${csudo}ln -s ${lib64_link_dir}/libtaos.${lib_file_ext_1} ${lib64_link_dir}/libtaos.${lib_file_ext} 2>>${install_log_path} || return 1 - [ -f ${lib_dir}/libtaosws.${lib_file_ext} ] && ${csudo}ln -sf ${lib_dir}/libtaosws.${lib_file_ext} ${lib64_link_dir}/libtaosws.${lib_file_ext} || : + [ -f ${lib_dir}/libtaosws.${lib_file_ext} ] && ${csudo}ln -sf ${lib_dir}/libtaosws.${lib_file_ext} ${lib64_link_dir}/libtaosws.${lib_file_ext} 2>>${install_log_path} fi if [ "$osType" != "Darwin" ]; then ${csudo}ldconfig fi + + log_print "install lib success" } function install_bin() { # Remove links + log_print "start install bin from ${bin_dir} to ${bin_link_dir}" ${csudo}rm -f ${bin_link_dir}/taos || : ${csudo}rm -f ${bin_link_dir}/taosd || : ${csudo}rm -f ${bin_link_dir}/udfd || : ${csudo}rm -f ${bin_link_dir}/taosadapter || : ${csudo}rm -f ${bin_link_dir}/taosBenchmark || : + ${csudo}rm -f ${bin_link_dir}/taoskeeper || : ${csudo}rm -f ${bin_link_dir}/taosdemo || : ${csudo}rm -f ${bin_link_dir}/taosdump || : ${csudo}rm -f ${bin_link_dir}/rmtaos || : ${csudo}rm -f ${bin_link_dir}/set_core || : + ${csudo}rm -f ${bin_link_dir}/*explorer || : ${csudo}chmod 0555 ${bin_dir}/* #Make link - [ -x ${bin_dir}/taos ] && ${csudo}ln -s ${bin_dir}/taos ${bin_link_dir}/taos || : - [ -x ${bin_dir}/taosd ] && ${csudo}ln -s ${bin_dir}/taosd ${bin_link_dir}/taosd || : - [ -x ${bin_dir}/udfd ] && ${csudo}ln -s ${bin_dir}/udfd ${bin_link_dir}/udfd || : - [ -x ${bin_dir}/taosadapter ] && ${csudo}ln -s ${bin_dir}/taosadapter ${bin_link_dir}/taosadapter || : - [ -x ${bin_dir}/taosBenchmark ] && ${csudo}ln -sf ${bin_dir}/taosBenchmark ${bin_link_dir}/taosdemo || : - [ -x ${bin_dir}/taosBenchmark ] && ${csudo}ln -sf ${bin_dir}/taosBenchmark ${bin_link_dir}/taosBenchmark || : - [ -x ${bin_dir}/TDinsight.sh ] && ${csudo}ln -sf ${bin_dir}/TDinsight.sh ${bin_link_dir}/TDinsight.sh || : - [ -x ${bin_dir}/taosdump ] && ${csudo}ln -s ${bin_dir}/taosdump ${bin_link_dir}/taosdump || : - [ -x ${bin_dir}/set_core.sh ] && ${csudo}ln -s ${bin_dir}/set_core.sh ${bin_link_dir}/set_core || : - [ -x ${bin_dir}/remove.sh ] && ${csudo}ln -s ${bin_dir}/remove.sh ${bin_link_dir}/rmtaos || : + if [ -x ${bin_dir}/taos ]; then + ${csudo}ln -s ${bin_dir}/taos ${bin_link_dir}/taos 2>>${install_log_path} || return 1 + fi + if [ -x ${bin_dir}/taosd ]; then + ${csudo}ln -s ${bin_dir}/taosd ${bin_link_dir}/taosd 2>>${install_log_path} || return 1 + fi + if [ -x ${bin_dir}/udfd ]; then + ${csudo}ln -s ${bin_dir}/udfd ${bin_link_dir}/udfd 2>>${install_log_path} || return 1 + fi + if [ -x ${bin_dir}/taosadapter ]; then + ${csudo}ln -s ${bin_dir}/taosadapter ${bin_link_dir}/taosadapter 2>>${install_log_path} || return 1 + fi + if [ -x ${bin_dir}/taosBenchmark ]; then + ${csudo}ln -sf ${bin_dir}/taosBenchmark ${bin_link_dir}/taosdemo 2>>${install_log_path} + ${csudo}ln -sf ${bin_dir}/taosBenchmark ${bin_link_dir}/taosBenchmark 2>>${install_log_path} + fi + if [ -x ${bin_dir}/TDinsight.sh ]; then + ${csudo}ln -sf ${bin_dir}/TDinsight.sh ${bin_link_dir}/TDinsight.sh 2>>${install_log_path} || return 1 + fi + if [ -x ${bin_dir}/taosdump ]; then + ${csudo}ln -s ${bin_dir}/taosdump ${bin_link_dir}/taosdump 2>>${install_log_path} || return 1 + fi + if [ -x ${bin_dir}/set_core.sh ]; then + ${csudo}ln -s ${bin_dir}/set_core.sh ${bin_link_dir}/set_core 2>>${install_log_path} || return 1 + fi + if [ -x ${bin_dir}/remove.sh ]; then + ${csudo}ln -s ${bin_dir}/remove.sh ${bin_link_dir}/rmtaos 2>>${install_log_path} || return 1 + fi + if [ -x ${bin_dir}/taoskeeper ]; then + ${csudo}ln -sf ${bin_dir}/taoskeeper ${bin_link_dir}/taoskeeper 2>>${install_log_path} || return 1 + fi + if [ -x ${bin_dir}/*explorer ]; then + ${csudo}ln -s ${bin_dir}/*explorer ${bin_link_dir}/*explorer 2>>${install_log_path} || return 1 + fi + log_print "install bin success" } function add_newHostname_to_hosts() { @@ -337,7 +436,7 @@ function local_fqdn_check() { function install_taosadapter_config() { if [ ! -f "${cfg_install_dir}/taosadapter.toml" ]; then - [ ! -d %{cfg_install_dir} ] && + [ ! -d ${cfg_install_dir} ] && ${csudo}${csudo}mkdir -p ${cfg_install_dir} [ -f ${cfg_dir}/taosadapter.toml ] && ${csudo}cp ${cfg_dir}/taosadapter.toml ${cfg_install_dir} [ -f ${cfg_install_dir}/taosadapter.toml ] && @@ -351,7 +450,31 @@ function install_taosadapter_config() { ${csudo}ln -s ${cfg_install_dir}/taosadapter.toml ${cfg_dir} } +function install_taoskeeper_config() { + # if new environment without taoskeeper + if [[ ! -f "${cfg_install_dir}/keeper.toml" ]] && [[ ! -f "${cfg_install_dir}/taoskeeper.toml" ]]; then + [ ! -d ${cfg_install_dir} ] && ${csudo}${csudo}mkdir -p ${cfg_install_dir} + [ -f ${cfg_dir}/taoskeeper.toml ] && ${csudo}cp ${cfg_dir}/taoskeeper.toml ${cfg_install_dir} + [ -f ${cfg_install_dir}/taoskeeper.toml ] && + ${csudo}chmod 644 ${cfg_install_dir}/taoskeeper.toml + fi + # if old machine with taoskeeper.toml file + if [ -f ${cfg_install_dir}/taoskeeper.toml ]; then + ${csudo}mv ${cfg_dir}/taoskeeper.toml ${cfg_dir}/taoskeeper.toml.new + fi + + if [ -f ${cfg_install_dir}/keeper.toml ]; then + echo "The file keeper.toml will be renamed to taoskeeper.toml" + ${csudo}mv ${cfg_install_dir}/keeper.toml ${cfg_install_dir}/taoskeeper.toml + ${csudo}mv ${cfg_dir}/taoskeeper.toml ${cfg_dir}/taoskeeper.toml.new + fi + + [ -f ${cfg_install_dir}/taoskeeper.toml ] && + ${csudo}ln -s ${cfg_install_dir}/taoskeeper.toml ${cfg_dir} +} + function install_config() { + log_print "start install config from ${cfg_dir} to ${cfg_install_dir}" if [ ! -f "${cfg_install_dir}/taos.cfg" ]; then ${csudo}${csudo}mkdir -p ${cfg_install_dir} [ -f ${cfg_dir}/taos.cfg ] && ${csudo}cp ${cfg_dir}/taos.cfg ${cfg_install_dir} @@ -419,6 +542,8 @@ function install_config() { break fi done + + log_print "install config success" } function clean_service_on_sysvinit() { @@ -469,7 +594,7 @@ function install_service_on_sysvinit() { function clean_service_on_systemd() { taosd_service_config="${service_config_dir}/taosd.service" - # taosd service already is stoped before install in preinst script + # taosd service already is stopped before install in preinst script #if systemctl is-active --quiet taosd; then # echo "TDengine is running, stopping it..." # ${csudo}systemctl stop taosd &> /dev/null || echo &> /dev/null @@ -521,6 +646,11 @@ function install_service_on_launchctl() { ${csudo}cp ${install_main_dir}/service/com.taosdata.taosadapter.plist /Library/LaunchDaemons/com.taosdata.taosadapter.plist || : ${csudo}launchctl load -w /Library/LaunchDaemons/com.taosdata.taosadapter.plist || : fi + if [ -f ${install_main_dir}/service/com.taosdata.taoskeeper.plist ]; then + ${csudo}launchctl unload -w /Library/LaunchDaemons/com.taosdata.taoskeeper.plist > /dev/null 2>&1 || : + ${csudo}cp ${install_main_dir}/service/com.taosdata.taoskeeper.plist /Library/LaunchDaemons/com.taosdata.taoskeeper.plist || : + ${csudo}launchctl load -w /Library/LaunchDaemons/com.taosdata.taoskeeper.plist || : + fi } function install_taosadapter_service() { @@ -532,7 +662,17 @@ function install_taosadapter_service() { fi } +function install_taoskeeper_service() { + if ((${service_mod}==0)); then + [ -f ${script_dir}/../cfg/taoskeeper.service ] &&\ + ${csudo}cp ${script_dir}/../cfg/taoskeeper.service \ + ${service_config_dir}/ || : + ${csudo}systemctl daemon-reload + fi +} + function install_service() { + log_print "start install service" if [ "$osType" != "Darwin" ]; then if ((${service_mod}==0)); then install_service_on_systemd @@ -546,6 +686,7 @@ function install_service() { else install_service_on_launchctl fi + log_print "install service success" } function install_app() { @@ -564,8 +705,16 @@ function install_app() { fi } -function install_TDengine() { - echo -e "${GREEN}Start to install TDengine...${NC}" +function checkDirectory() { + if [ ! -d "${bin_link_dir}" ]; then + ${csudo}mkdir -p ${bin_link_dir} + log_print "${bin_link_dir} directory created" + fi + + if [ ! -d "${lib_link_dir}" ]; then + ${csudo}mkdir -p ${lib_link_dir} + log_print "${lib_link_dir} directory created" + fi #install log and data dir , then ln to /usr/local/taos ${csudo}mkdir -p ${log_dir} && ${csudo}chmod 777 ${log_dir} @@ -576,14 +725,30 @@ function install_TDengine() { ${csudo}ln -s ${log_dir} ${log_link_dir} || : ${csudo}ln -s ${data_dir} ${data_link_dir} || : +} + +function install_TDengine() { + echo -e "${GREEN}Start to install TDengine...${NC}" + log_print "start to install TDengine" + + checkDirectory # Install include, lib, binary and service - install_include - install_lib + install_include && + install_lib && + install_jemalloc install_bin + + if [[ "$?" != 0 ]];then + log_print "install TDengine failed!" + return 1 + fi + install_config install_taosadapter_config + install_taoskeeper_config install_taosadapter_service + install_taoskeeper_service install_service install_app @@ -622,11 +787,14 @@ function install_TDengine() { echo -e "${GREEN_DARK}To access TDengine ${NC}: taos -h $serverFqdn${GREEN_DARK} to login into TDengine server${NC}" echo fi + log_print "install TDengine successfully!" echo echo -e "\033[44;32;1mTDengine is installed successfully!${NC}" } ## ==============================Main program starts from here============================ +${csudo}rm -rf ${install_log_path} +log_print "installer start..." serverFqdn=$(hostname) install_TDengine diff --git a/packaging/tools/preun.sh b/packaging/tools/preun.sh index 0e96c71d5d4e3e27911b7f7537345e38a6195c6d..68f6b53c45cc13169e36971174dafd66c0259411 100755 --- a/packaging/tools/preun.sh +++ b/packaging/tools/preun.sh @@ -17,7 +17,7 @@ cfg_link_dir="/usr/local/taos/cfg" service_config_dir="/etc/systemd/system" taos_service_name="taosd" - +taoskeeper_service_name="taoskeeper" csudo="" if command -v sudo > /dev/null; then csudo="sudo " @@ -57,6 +57,13 @@ function kill_taosd() { fi } +function kill_taoskeeper() { + pid=$(ps -ef | grep "taoskeeper" | grep -v "grep" | awk '{print $2}') + if [ -n "$pid" ]; then + ${csudo}kill -9 $pid || : + fi +} + function clean_service_on_systemd() { taosadapter_service_config="${service_config_dir}/taosadapter.service" if systemctl is-active --quiet taosadapter; then @@ -76,6 +83,12 @@ function clean_service_on_systemd() { [ -f ${taosadapter_service_config} ] && ${csudo}rm -f ${taosadapter_service_config} + taoskeeper_service_config="${service_config_dir}/${taoskeeper_service_name}.service" + if systemctl is-active --quiet ${taoskeeper_service_name}; then + echo "TDengine taoskeeper is running, stopping it..." + ${csudo}systemctl stop ${taoskeeper_service_name} &> /dev/null || echo &> /dev/null + fi + [ -f ${taoskeeper_service_config} ] && ${csudo}rm -f ${taoskeeper_service_config} } function clean_service_on_sysvinit() { @@ -111,6 +124,7 @@ function clean_service() { # must manual stop taosd kill_taosadapter kill_taosd + kill_taoskeeper fi } @@ -124,6 +138,7 @@ ${csudo}rm -f ${bin_link_dir}/taosadapter || : ${csudo}rm -f ${bin_link_dir}/taosBenchmark || : ${csudo}rm -f ${bin_link_dir}/taosdemo || : ${csudo}rm -f ${bin_link_dir}/set_core || : +${csudo}rm -f ${bin_link_dir}/taoskeeper || : ${csudo}rm -f ${cfg_link_dir}/*.new || : ${csudo}rm -f ${inc_link_dir}/taos.h || : ${csudo}rm -f ${inc_link_dir}/taosdef.h || : diff --git a/packaging/tools/release_note b/packaging/tools/release_note index 4578a4523c50f3b0764ce05add5920cf0be72172..81b09ba69c1485804e194a760e4aedde10014388 100644 --- a/packaging/tools/release_note +++ b/packaging/tools/release_note @@ -72,7 +72,7 @@ New Features: taos-1.4.13 (Released on 2018-12-14) Bugs Fixed: - - Clients failed to connect to server due to unexpected and invalid packets recieved by the server. + - Clients failed to connect to server due to unexpected and invalid packets received by the server. Features Added: - Add support to HikariCP in TSDB JDBC driver. diff --git a/packaging/tools/remove.sh b/packaging/tools/remove.sh index 8e5630ec2f7bc89d739486efdec7fc55acb2b046..6c671473bfb5046ac18e7b813088ec6d6d3843d2 100755 --- a/packaging/tools/remove.sh +++ b/packaging/tools/remove.sh @@ -36,6 +36,21 @@ clientName="taos" uninstallScript="rmtaos" productName="TDengine" +serverName2="taosd" +clientName2="taos" +productName2="TDengine" + +adapterName2="${clientName2}adapter" +demoName2="${clientName2}demo" +benchmarkName2="${clientName2}Benchmark" +dumpName2="${clientName2}dump" +keeperName2="${clientName2}keeper" +xName2="${clientName2}x" +explorerName2="${clientName2}-explorer" +uninstallScript2="rm${clientName2}" + +installDir="/usr/local/${clientName2}" + #install main path install_main_dir=${installDir} data_link_dir=${installDir}/data @@ -45,8 +60,8 @@ local_bin_link_dir="/usr/local/bin" service_config_dir="/etc/systemd/system" -taos_service_name=${serverName} -taosadapter_service_name="taosadapter" +taos_service_name=${serverName2} +taosadapter_service_name="${clientName2}adapter" tarbitrator_service_name="tarbitratord" csudo="" if command -v sudo >/dev/null; then @@ -74,14 +89,14 @@ else fi function kill_taosadapter() { - pid=$(ps -ef | grep "taosadapter" | grep -v "grep" | awk '{print $2}') + pid=$(ps -ef | grep "${adapterName2}" | grep -v "grep" | awk '{print $2}') if [ -n "$pid" ]; then ${csudo}kill -9 $pid || : fi } function kill_taosd() { - pid=$(ps -ef | grep ${serverName} | grep -v "grep" | awk '{print $2}') + pid=$(ps -ef | grep ${serverName2} | grep -v "grep" | awk '{print $2}') if [ -n "$pid" ]; then ${csudo}kill -9 $pid || : fi @@ -99,19 +114,29 @@ function clean_bin() { ${csudo}rm -f ${bin_link_dir}/${clientName} || : ${csudo}rm -f ${bin_link_dir}/${serverName} || : ${csudo}rm -f ${bin_link_dir}/udfd || : - ${csudo}rm -f ${bin_link_dir}/taosadapter || : - ${csudo}rm -f ${bin_link_dir}/taosBenchmark || : - ${csudo}rm -f ${bin_link_dir}/taosdemo || : - ${csudo}rm -f ${bin_link_dir}/taosdump || : - ${csudo}rm -f ${bin_link_dir}/${uninstallScript} || : + ${csudo}rm -f ${bin_link_dir}/${adapterName2} || : + ${csudo}rm -f ${bin_link_dir}/${benchmarkName2} || : + ${csudo}rm -f ${bin_link_dir}/${demoName2} || : + ${csudo}rm -f ${bin_link_dir}/${dumpName2} || : + ${csudo}rm -f ${bin_link_dir}/${uninstallScript} || : ${csudo}rm -f ${bin_link_dir}/tarbitrator || : ${csudo}rm -f ${bin_link_dir}/set_core || : ${csudo}rm -f ${bin_link_dir}/TDinsight.sh || : + ${csudo}rm -f ${bin_link_dir}/${keeperName2} || : + ${csudo}rm -f ${bin_link_dir}/${xName2} || : + ${csudo}rm -f ${bin_link_dir}/${explorerName2} || : + + if [ "$verMode" == "cluster" ] && [ "$clientName" != "$clientName2" ]; then + ${csudo}rm -f ${bin_link_dir}/${clientName2} || : + ${csudo}rm -f ${bin_link_dir}/${benchmarkName2} || : + ${csudo}rm -f ${bin_link_dir}/${dumpName2} || : + ${csudo}rm -f ${bin_link_dir}/${uninstallScript2} || : + fi } function clean_local_bin() { - ${csudo}rm -f ${local_bin_link_dir}/taosBenchmark || : - ${csudo}rm -f ${local_bin_link_dir}/taosdemo || : + ${csudo}rm -f ${local_bin_link_dir}/${benchmarkName2} || : + ${csudo}rm -f ${local_bin_link_dir}/${demoName2} || : } function clean_lib() { @@ -147,15 +172,15 @@ function clean_log() { function clean_service_on_systemd() { taosd_service_config="${service_config_dir}/${taos_service_name}.service" if systemctl is-active --quiet ${taos_service_name}; then - echo "${productName} ${serverName} is running, stopping it..." + echo "${productName2} ${serverName2} is running, stopping it..." ${csudo}systemctl stop ${taos_service_name} &>/dev/null || echo &>/dev/null fi ${csudo}systemctl disable ${taos_service_name} &>/dev/null || echo &>/dev/null ${csudo}rm -f ${taosd_service_config} - taosadapter_service_config="${service_config_dir}/taosadapter.service" + taosadapter_service_config="${service_config_dir}/${clientName2}adapter.service" if systemctl is-active --quiet ${taosadapter_service_name}; then - echo "${productName} taosAdapter is running, stopping it..." + echo "${productName2} ${clientName2}Adapter is running, stopping it..." ${csudo}systemctl stop ${taosadapter_service_name} &>/dev/null || echo &>/dev/null fi ${csudo}systemctl disable ${taosadapter_service_name} &>/dev/null || echo &>/dev/null @@ -163,21 +188,41 @@ function clean_service_on_systemd() { tarbitratord_service_config="${service_config_dir}/${tarbitrator_service_name}.service" if systemctl is-active --quiet ${tarbitrator_service_name}; then - echo "${productName} tarbitrator is running, stopping it..." + echo "${productName2} tarbitrator is running, stopping it..." ${csudo}systemctl stop ${tarbitrator_service_name} &>/dev/null || echo &>/dev/null fi ${csudo}systemctl disable ${tarbitrator_service_name} &>/dev/null || echo &>/dev/null - ${csudo}rm -f ${tarbitratord_service_config} + + x_service_config="${service_config_dir}/${xName2}.service" + if [ -e "$x_service_config" ]; then + if systemctl is-active --quiet ${xName2}; then + echo "${productName2} ${xName2} is running, stopping it..." + ${csudo}systemctl stop ${xName2} &>/dev/null || echo &>/dev/null + fi + ${csudo}systemctl disable ${xName2} &>/dev/null || echo &>/dev/null + ${csudo}rm -f ${x_service_config} + fi + + explorer_service_config="${service_config_dir}/${explorerName2}.service" + if [ -e "$explorer_service_config" ]; then + if systemctl is-active --quiet ${explorerName2}; then + echo "${productName2} ${explorerName2} is running, stopping it..." + ${csudo}systemctl stop ${explorerName2} &>/dev/null || echo &>/dev/null + fi + ${csudo}systemctl disable ${explorerName2} &>/dev/null || echo &>/dev/null + ${csudo}rm -f ${explorer_service_config} + ${csudo}rm -f /etc/${clientName2}/explorer.toml + fi } function clean_service_on_sysvinit() { if ps aux | grep -v grep | grep ${serverName} &>/dev/null; then - echo "${productName} ${serverName} is running, stopping it..." + echo "${productName2} ${serverName2} is running, stopping it..." ${csudo}service ${serverName} stop || : fi if ps aux | grep -v grep | grep tarbitrator &>/dev/null; then - echo "${productName} tarbitrator is running, stopping it..." + echo "${productName2} tarbitrator is running, stopping it..." ${csudo}service tarbitratord stop || : fi @@ -215,8 +260,8 @@ function clean_service_on_sysvinit() { function clean_service_on_launchctl() { ${csudouser}launchctl unload -w /Library/LaunchDaemons/com.taosdata.taosd.plist > /dev/null 2>&1 || : ${csudo}rm /Library/LaunchDaemons/com.taosdata.taosd.plist > /dev/null 2>&1 || : - ${csudouser}launchctl unload -w /Library/LaunchDaemons/com.taosdata.taosadapter.plist > /dev/null 2>&1 || : - ${csudo}rm /Library/LaunchDaemons/com.taosdata.taosadapter.plist > /dev/null 2>&1 || : + ${csudouser}launchctl unload -w /Library/LaunchDaemons/com.taosdata.${clientName2}adapter.plist > /dev/null 2>&1 || : + ${csudo}rm /Library/LaunchDaemons/com.taosdata.${clientName2}adapter.plist > /dev/null 2>&1 || : } function clean_service() { @@ -272,5 +317,5 @@ if [ "$osType" = "Darwin" ]; then ${csudo}rm -rf /Applications/TDengine.app fi -echo -e "${GREEN}${productName} is removed successfully!${NC}" +echo -e "${GREEN}${productName2} is removed successfully!${NC}" echo diff --git a/packaging/tools/remove_client.sh b/packaging/tools/remove_client.sh index 7ab7fa85998284e0dcb4cd158eb8599806fd7470..2bdb56fac210982048d630469fbb10942bc15f69 100755 --- a/packaging/tools/remove_client.sh +++ b/packaging/tools/remove_client.sh @@ -12,6 +12,16 @@ installDir="/usr/local/taos" clientName="taos" uninstallScript="rmtaos" +clientName2="taos" +productName2="TDengine" + +benchmarkName2="${clientName2}Benchmark" +demoName2="${clientName2}demo" +dumpName2="${clientName2}dump" +uninstallScript2="rm${clientName2}" + +installDir="/usr/local/${clientName2}" + #install main path install_main_dir=${installDir} @@ -35,11 +45,20 @@ function kill_client() { function clean_bin() { # Remove link - ${csudo}rm -f ${bin_link_dir}/${clientName} || : - ${csudo}rm -f ${bin_link_dir}/taosdemo || : - ${csudo}rm -f ${bin_link_dir}/taosdump || : + ${csudo}rm -f ${bin_link_dir}/${clientName2} || : + ${csudo}rm -f ${bin_link_dir}/${demoName2} || : + ${csudo}rm -f ${bin_link_dir}/${benchmarkName2} || : + ${csudo}rm -f ${bin_link_dir}/${dumpName2} || : ${csudo}rm -f ${bin_link_dir}/${uninstallScript} || : ${csudo}rm -f ${bin_link_dir}/set_core || : + + if [ "$verMode" == "cluster" ] && [ "$clientName" != "$clientName2" ]; then + ${csudo}rm -f ${bin_link_dir}/${clientName2} || : + ${csudo}rm -f ${bin_link_dir}/${demoName2} || : + ${csudo}rm -f ${bin_link_dir}/${benchmarkName2} || : + ${csudo}rm -f ${bin_link_dir}/${dumpName2} || : + ${csudo}rm -f ${bin_link_dir}/${uninstallScript2} || : + fi } function clean_lib() { @@ -82,5 +101,5 @@ clean_config ${csudo}rm -rf ${install_main_dir} -echo -e "${GREEN}TDengine client is removed successfully!${NC}" +echo -e "${GREEN}${productName2} client is removed successfully!${NC}" echo diff --git a/packaging/tools/repair_link.sh b/packaging/tools/repair_link.sh index 7fd503f27013a9fce7208ece4335a1f427e05c9d..d71a16023eaabb3248283ed54a786a7cf0caf728 100755 --- a/packaging/tools/repair_link.sh +++ b/packaging/tools/repair_link.sh @@ -8,7 +8,7 @@ read -p "Please enter link directory such as /var/lib/taos/tsdb: " linkDir while true; do if [ ! -d $linkDir ]; then - read -p "Paht not exists, please enter the correct link path:" linkDir + read -p "Path not exists, please enter the correct link path:" linkDir continue fi break @@ -28,12 +28,12 @@ for linkFile in $(find -L $linkDir -xtype l); do if [ -z "${dirHash["$dirName"]}" ]; then read -p "Please enter the directory to replace ${dirName}:" newDir - read -p "Do you want to replcace all[y/N]?" replcaceAll - if [[ ( "${replcaceAll}" == "y") || ( "${replcaceAll}" == "Y") ]]; then + read -p "Do you want to replace all[y/N]?" replaceAll + if [[ ( "${replaceAll}" == "y") || ( "${replaceAll}" == "Y") ]]; then dirHash["$dirName"]="$newDir" fi fi - # Replcace the file + # Replace the file ln -sf "${newDir}/${baseName}" "${linkFile}" done diff --git a/packaging/tools/tdengine.iss b/packaging/tools/tdengine.iss index 3a22c737743872528887616b83b3ec58329e8795..8676fa2c51e891edc4077dfd2b6f9e5888af5f05 100644 --- a/packaging/tools/tdengine.iss +++ b/packaging/tools/tdengine.iss @@ -18,11 +18,10 @@ #define MyAppDLLName "\driver\*.dll" ;#define MyAppVersion "3.0" ;#define MyAppInstallName "TDengine" -;#define MyAppInstallName "TDengine" [Setup] VersionInfoVersion={#MyAppVersion} AppId={{A0F7A93C-79C4-485D-B2B8-F0D03DF42FAB} -AppName={#MyAppName} +AppName={#CusName} AppVersion={#MyAppVersion} ;AppVerName={#MyAppName} {#MyAppVersion} AppPublisher={#MyAppPublisher} @@ -59,6 +58,9 @@ Source: {#MyAppSourceDir}{#MyAppDriverName}; DestDir: "{app}\driver"; Flags: igN Source: {#MyAppSourceDir}{#MyAppIncludeName}; DestDir: "{app}\include"; Flags: igNoreversion recursesubdirs createallsubdirs Source: {#MyAppSourceDir}{#MyAppExeName}; DestDir: "{app}"; Excludes: {#MyAppExcludeSource} ; Flags: igNoreversion recursesubdirs createallsubdirs Source: {#MyAppSourceDir}{#MyAppTaosdemoExeName}; DestDir: "{app}"; Flags: igNoreversion recursesubdirs createallsubdirs +Source: {#MyAppSourceDir}\taos.exe; DestDir: "{app}"; DestName: "{#CusPrompt}.exe"; Flags: igNoreversion recursesubdirs createallsubdirs +Source: {#MyAppSourceDir}\taosBenchmark.exe; DestDir: "{app}"; DestName: "{#CusPrompt}Benchmark.exe"; Flags: igNoreversion recursesubdirs createallsubdirs +Source: {#MyAppSourceDir}\taosdump.exe; DestDir: "{app}"; DestName: "{#CusPrompt}dump.exe"; Flags: igNoreversion recursesubdirs createallsubdirs [run] @@ -73,8 +75,8 @@ RunOnceId: "deltaosadapter"; Filename: {sys}\sc.exe; Parameters: "delete taosada [Registry] Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \ - ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\TDengine"; \ - Check: NeedsAddPath('C:\TDengine') + ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};C:\{#CusName}"; \ + Check: NeedsAddPath('C:\{#CusName}') [Code] function NeedsAddPath(Param: string): boolean; @@ -104,11 +106,11 @@ Name: "desktopicon";Description: "{cm:CreateDesktopIcon}"; GroupDescription:"{cm [Icons] Name:"{group}\Taos Shell"; Filename: "{app}\include\{#MyAppTaosExeName}" ; Parameters: "taos.exe" ; IconFilename: "{app}\include\{#MyAppIco}" -Name:"{group}\Open TDengine Directory"; Filename: "{app}\" +Name:"{group}\Open {#CusName} Directory"; Filename: "{app}\" Name:"{group}\Taosdemo"; Filename: "{app}\include\{#MyAppTaosExeName}" ; Parameters: "taosdemo.exe" ; IconFilename: "{app}\include\{#MyAppIco}" Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" ; IconFilename: "{app}\include\{#MyAppIco}" Name:"{commondesktop}\Taos Shell"; Filename: "{app}\include\{#MyAppTaosExeName}" ; Parameters: "taos.exe" ; Tasks: desktopicon; WorkingDir: "{app}" ; IconFilename: "{app}\include\{#MyAppIco}" [Messages] -ConfirmUninstall=Do you really want to uninstall TDengine from your computer?%n%nPress [Y] to completely delete %1 and all its components;%nPress [N] to keep the software on your computer. +ConfirmUninstall=Do you really want to uninstall {#CusName} from your computer?%n%nPress [Y] to completely delete %1 and all its components;%nPress [N] to keep the software on your computer. diff --git a/packaging/tools/windows_before_install.txt b/packaging/tools/windows_before_install.txt index ef783bf10badedc733e87946a323d499b60fc5ac..91cb35d77e788d0705624da14d9e36c75403be3e 100644 --- a/packaging/tools/windows_before_install.txt +++ b/packaging/tools/windows_before_install.txt @@ -1,4 +1,4 @@ -TDengine is a high-efficient, scalable, high-available distributed time-series database, which makes a lot of optimizations on inserting and querying data, which is far more efficient than normal regular databases. So TDengine can meet the high requirements of IOT and other areas on storing and querying a large amount of data. +TDengine is an open-source, cloud-native time-series database optimized for Internet of Things (IoT), Connected Cars, and Industrial IoT. With its built-in caching, stream processing, and data subscription capabilities, TDengine offers a simplified solution for time-series data processing. TDengine will be installed under C:\TDengine, users can modify configuration file C:\TDengine\cfg\taos.cfg, set the log file path or other parameters. To start/stop TDengine with administrator privileges: sc start/stop taosd diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index 903a6a22cac05c7c921ed6287ae38b2498b064fe..46d44d744327d16d77bd4055644d4c797550e40e 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -36,14 +36,6 @@ extern "C" { #include "tconfig.h" -#define CHECK_CODE_GOTO(expr, label) \ - do { \ - code = expr; \ - if (TSDB_CODE_SUCCESS != code) { \ - goto label; \ - } \ - } while (0) - #define ERROR_MSG_BUF_DEFAULT_SIZE 512 #define HEARTBEAT_INTERVAL 1500 // ms @@ -66,7 +58,8 @@ enum { typedef struct SAppInstInfo SAppInstInfo; typedef struct { - char* key; + char* key; + int32_t idx; // statistics int32_t reportCnt; int32_t connKeyCnt; @@ -87,6 +80,7 @@ typedef struct { int64_t appId; // ctl int8_t threadStop; + int8_t quitByKill; TdThread thread; TdThreadMutex lock; // used when app init and cleanup SHashObj* appSummary; @@ -97,16 +91,14 @@ typedef struct { typedef struct SQueryExecMetric { int64_t start; // start timestamp, us - int64_t syntaxStart; // start to parse, us - int64_t syntaxEnd; // end to parse, us int64_t ctgStart; // start to parse, us - int64_t ctgEnd; // end to parse, us - int64_t semanticEnd; - int64_t planEnd; - int64_t resultReady; - int64_t execEnd; - int64_t send; // start to send to server, us - int64_t rsp; // receive response from server, us + int64_t execStart; // start to parse, us + + int64_t parseCostUs; + int64_t ctgCostUs; + int64_t analyseCostUs; + int64_t planCostUs; + int64_t execCostUs; } SQueryExecMetric; struct SAppInstInfo { @@ -149,9 +141,12 @@ typedef struct STscObj { int32_t numOfReqs; // number of sqlObj bound to this connection SAppInstInfo* pAppInfo; SHashObj* pRequests; - int8_t schemalessType; // todo remove it, this attribute should be move to request } STscObj; +typedef struct STscDbg { + bool memEnable; +} STscDbg; + typedef struct SResultColumn { union { char* nullbitmap; // bitmap, one bit for each item in the list @@ -284,25 +279,7 @@ static FORCE_INLINE SReqResultInfo* tmqGetCurResInfo(TAOS_RES* res) { return (SReqResultInfo*)&msg->resInfo; } -static FORCE_INLINE SReqResultInfo* tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4) { - SMqRspObj* msg = (SMqRspObj*)res; - msg->resIter++; - if (msg->resIter < msg->rsp.blockNum) { - SRetrieveTableRsp* pRetrieve = (SRetrieveTableRsp*)taosArrayGetP(msg->rsp.blockData, msg->resIter); - if (msg->rsp.withSchema) { - SSchemaWrapper* pSW = (SSchemaWrapper*)taosArrayGetP(msg->rsp.blockSchema, msg->resIter); - setResSchemaInfo(&msg->resInfo, pSW->pSchema, pSW->nCols); - taosMemoryFreeClear(msg->resInfo.row); - taosMemoryFreeClear(msg->resInfo.pCol); - taosMemoryFreeClear(msg->resInfo.length); - taosMemoryFreeClear(msg->resInfo.convertBuf); - taosMemoryFreeClear(msg->resInfo.convertJson); - } - setQueryResultFromRsp(&msg->resInfo, pRetrieve, convertUcs4, false); - return &msg->resInfo; - } - return NULL; -} +SReqResultInfo* tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4); static FORCE_INLINE SReqResultInfo* tscGetCurResInfo(TAOS_RES* res) { if (TD_RES_QUERY(res)) return &(((SRequestObj*)res)->body.resInfo); @@ -315,7 +292,6 @@ extern int32_t clientConnRefPool; extern int32_t timestampDeltaLimit; extern int64_t lastClusterId; - __async_send_cb_fn_t getMsgRspHandle(int32_t msgType); SMsgSendInfo* buildMsgInfoImpl(SRequestObj* pReqObj); @@ -368,7 +344,6 @@ void taos_close_internal(void* taos); // global, called by mgmt int hbMgrInit(); void hbMgrCleanUp(); -int hbHandleRsp(SClientHbBatchRsp* hbRsp); // cluster level SAppHbMgr* appHbMgrInit(SAppInstInfo* pAppInstInfo, char* key); @@ -381,9 +356,6 @@ void stopAllRequests(SHashObj* pRequests); int hbRegisterConn(SAppHbMgr* pAppHbMgr, int64_t tscRefId, int64_t clusterId, int8_t connType); void hbDeregisterConn(SAppHbMgr* pAppHbMgr, SClientHbKey connKey); -// --- mq -void hbMgrInitMqHbRspHandle(); - typedef struct SSqlCallbackWrapper { SParseContext* pParseCtx; SCatalogReq* pCatalogReq; diff --git a/source/client/inc/clientLog.h b/source/client/inc/clientLog.h index 0cb36ff61db570f2c6fb488d2964fc38c2cfd7f4..1a6d47d4f991d85ba48f319993712b7b8d057f07 100644 --- a/source/client/inc/clientLog.h +++ b/source/client/inc/clientLog.h @@ -25,12 +25,16 @@ extern "C" { // clang-format off #define tscFatal(...) do { if (cDebugFlag & DEBUG_FATAL) { taosPrintLog("TSC FATAL ", DEBUG_FATAL, cDebugFlag, __VA_ARGS__); }} while(0) #define tscError(...) do { if (cDebugFlag & DEBUG_ERROR) { taosPrintLog("TSC ERROR ", DEBUG_ERROR, cDebugFlag, __VA_ARGS__); }} while(0) +#define tscErrorL(...) do { if (cDebugFlag & DEBUG_ERROR) { taosPrintLongString("TSC ERROR ", DEBUG_ERROR, cDebugFlag, __VA_ARGS__); }} while(0) #define tscWarn(...) do { if (cDebugFlag & DEBUG_WARN) { taosPrintLog("TSC WARN ", DEBUG_WARN, cDebugFlag, __VA_ARGS__); }} while(0) +#define tscWarnL(...) do { if (cDebugFlag & DEBUG_WARN) { taosPrintLongString("TSC WARN ", DEBUG_WARN, cDebugFlag, __VA_ARGS__); }} while(0) #define tscInfo(...) do { if (cDebugFlag & DEBUG_INFO) { taosPrintLog("TSC ", DEBUG_INFO, cDebugFlag, __VA_ARGS__); }} while(0) #define tscDebug(...) do { if (cDebugFlag & DEBUG_DEBUG) { taosPrintLog("TSC ", DEBUG_DEBUG, cDebugFlag, __VA_ARGS__); }} while(0) #define tscTrace(...) do { if (cDebugFlag & DEBUG_TRACE) { taosPrintLog("TSC ", DEBUG_TRACE, cDebugFlag, __VA_ARGS__); }} while(0) #define tscDebugL(...) do { if (cDebugFlag & DEBUG_DEBUG) { taosPrintLongString("TSC ", DEBUG_DEBUG, cDebugFlag, __VA_ARGS__); }} while(0) -//#define tscPerf(...) do { if (cDebugFlag & DEBUG_INFO) { taosPrintLog("TSC ", DEBUG_INFO, cDebugFlag, __VA_ARGS__); }} while(0) +#define tscPerf(...) do { if (cDebugFlag & DEBUG_INFO) { taosPrintLog("TSC ", 0, cDebugFlag, __VA_ARGS__); }} while(0) +#define tscLog(...) do { taosPrintLog("TSC ", 0, DEBUG_FILE, __VA_ARGS__); } while(0) +#define tscLogL(...) do { taosPrintLongString("TSC ", 0, DEBUG_FILE, __VA_ARGS__); } while(0) // clang-format on #ifdef __cplusplus diff --git a/source/client/inc/clientSml.h b/source/client/inc/clientSml.h new file mode 100644 index 0000000000000000000000000000000000000000..b20fc6f57a4256f07f55150711d82a6bf05175f7 --- /dev/null +++ b/source/client/inc/clientSml.h @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef TDENGINE_CLIENTSML_H +#define TDENGINE_CLIENTSML_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "catalog.h" +#include "clientInt.h" +#include "osThread.h" +#include "query.h" +#include "taos.h" +#include "taoserror.h" +#include "tcommon.h" +#include "tdef.h" +#include "tglobal.h" +#include "tlog.h" +#include "tmsg.h" +#include "tname.h" +#include "ttime.h" +#include "ttypes.h" +#include "cJSON.h" + +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) +# define expect(expr,value) (__builtin_expect ((expr),(value)) ) +#else +# define expect(expr,value) (expr) +#endif + +#ifndef likely +#define likely(expr) expect((expr) != 0, 1) +#endif +#ifndef unlikely +#define unlikely(expr) expect((expr) != 0, 0) +#endif + +#define SPACE ' ' +#define COMMA ',' +#define EQUAL '=' +#define QUOTE '"' +#define SLASH '\\' + +#define JUMP_SPACE(sql, sqlEnd) \ + while (sql < sqlEnd) { \ + if (unlikely(*sql == SPACE)) \ + sql++; \ + else \ + break; \ + } + +#define IS_INVALID_COL_LEN(len) ((len) <= 0 || (len) >= TSDB_COL_NAME_LEN) +#define IS_INVALID_TABLE_LEN(len) ((len) <= 0 || (len) >= TSDB_TABLE_NAME_LEN) + +#define TS "_ts" +#define TS_LEN 3 +#define VALUE "_value" +#define VALUE_LEN 6 + +#define OTD_JSON_FIELDS_NUM 4 +#define MAX_RETRY_TIMES 10 +typedef TSDB_SML_PROTOCOL_TYPE SMLProtocolType; + +typedef enum { + SCHEMA_ACTION_NULL, + SCHEMA_ACTION_CREATE_STABLE, + SCHEMA_ACTION_ADD_COLUMN, + SCHEMA_ACTION_ADD_TAG, + SCHEMA_ACTION_CHANGE_COLUMN_SIZE, + SCHEMA_ACTION_CHANGE_TAG_SIZE, +} ESchemaAction; + +typedef struct { + const void *key; + int32_t keyLen; + void *value; + bool used; +}Node; + +typedef struct NodeList{ + Node data; + struct NodeList* next; +}NodeList; + +typedef struct { + char *measure; + char *tags; + char *cols; + char *timestamp; + char *measureTag; + + int32_t measureLen; + int32_t measureTagsLen; + int32_t tagsLen; + int32_t colsLen; + int32_t timestampLen; + + bool measureEscaped; + SArray *colArray; +} SSmlLineInfo; + +typedef struct { + const char *sTableName; // super table name + int32_t sTableNameLen; + char childTableName[TSDB_TABLE_NAME_LEN]; + uint64_t uid; +// void *key; // for openTsdb + + SArray *tags; + + // elements are SHashObj for find by key quickly + SArray *cols; + STableDataCxt *tableDataCtx; +} SSmlTableInfo; + +typedef struct { + SArray *tags; // save the origin order to create table + SHashObj *tagHash; // elements are + + SArray *cols; + SHashObj *colHash; + + STableMeta *tableMeta; +} SSmlSTableMeta; + +typedef struct { + int32_t len; + char *buf; +} SSmlMsgBuf; + +typedef struct { + int32_t code; + int32_t lineNum; + + int32_t numOfSTables; + int32_t numOfCTables; + int32_t numOfCreateSTables; + int32_t numOfAlterColSTables; + int32_t numOfAlterTagSTables; + + int64_t parseTime; + int64_t schemaTime; + int64_t insertBindTime; + int64_t insertRpcTime; + int64_t endTime; +} SSmlCostInfo; + +typedef struct { + int64_t id; + + SMLProtocolType protocol; + int8_t precision; + bool reRun; + bool dataFormat; // true means that the name and order of keys in each line are the same(only for influx protocol) + bool isRawLine; + int32_t ttl; + int32_t uid; // used for automatic create child table + + SHashObj *childTables; + SHashObj *tableUids; + SHashObj *superTables; + SHashObj *pVgHash; + + STscObj *taos; + SCatalog *pCatalog; + SRequestObj *pRequest; + SQuery *pQuery; + + SSmlCostInfo cost; + int32_t lineNum; + SSmlMsgBuf msgBuf; + + cJSON *root; // for parse json + int8_t offset[OTD_JSON_FIELDS_NUM]; + SSmlLineInfo *lines; // element is SSmlLineInfo + bool parseJsonByLib; + SArray *tagJsonArray; + SArray *valueJsonArray; + + // + SArray *preLineTagKV; + SArray *maxTagKVs; + SArray *masColKVs; + + SSmlLineInfo preLine; + STableMeta *currSTableMeta; + STableDataCxt *currTableDataCtx; + bool needModifySchema; +} SSmlHandle; + +#define IS_SAME_CHILD_TABLE (elements->measureTagsLen == info->preLine.measureTagsLen \ +&& memcmp(elements->measure, info->preLine.measure, elements->measureTagsLen) == 0) + +#define IS_SAME_SUPER_TABLE (elements->measureLen == info->preLine.measureLen \ +&& memcmp(elements->measure, info->preLine.measure, elements->measureLen) == 0) + +#define IS_SAME_KEY (maxKV->keyLen == kv.keyLen && memcmp(maxKV->key, kv.key, kv.keyLen) == 0) + +#define IS_SLASH_LETTER_IN_MEASUREMENT(sql) \ + (*((sql)-1) == SLASH && (*(sql) == COMMA || *(sql) == SPACE)) + +#define MOVE_FORWARD_ONE(sql, len) (memmove((void *)((sql)-1), (sql), len)) + +#define PROCESS_SLASH_IN_MEASUREMENT(key, keyLen) \ + for (int i = 1; i < keyLen; ++i) { \ + if (IS_SLASH_LETTER_IN_MEASUREMENT(key + i)) { \ + MOVE_FORWARD_ONE(key + i, keyLen - i); \ + keyLen--; \ + } \ + } + +extern int64_t smlFactorNS[3]; +extern int64_t smlFactorS[3]; + +typedef int32_t (*_equal_fn_sml)(const void *, const void *); + +SSmlHandle *smlBuildSmlInfo(TAOS *taos); +void smlDestroyInfo(SSmlHandle *info); +int smlJsonParseObjFirst(char **start, SSmlLineInfo *element, int8_t *offset); +int smlJsonParseObj(char **start, SSmlLineInfo *element, int8_t *offset); +//SArray *smlJsonParseTags(char *start, char *end); +bool smlParseNumberOld(SSmlKv *kvVal, SSmlMsgBuf *msg); +void* nodeListGet(NodeList* list, const void *key, int32_t len, _equal_fn_sml fn); +int nodeListSet(NodeList** list, const void *key, int32_t len, void* value, _equal_fn_sml fn); +int nodeListSize(NodeList* list); +bool smlDoubleToInt64OverFlow(double num); +int32_t smlBuildInvalidDataMsg(SSmlMsgBuf *pBuf, const char *msg1, const char *msg2); +bool smlParseNumber(SSmlKv *kvVal, SSmlMsgBuf *msg); +int64_t smlGetTimeValue(const char *value, int32_t len, uint8_t fromPrecision, uint8_t toPrecision); +int8_t smlGetTsTypeByLen(int32_t len); +SSmlTableInfo* smlBuildTableInfo(int numRows, const char* measure, int32_t measureLen); +SSmlSTableMeta* smlBuildSTableMeta(bool isDataFormat); +int32_t smlSetCTableName(SSmlTableInfo *oneTable); +void getTableUid(SSmlHandle *info, SSmlLineInfo *currElement, SSmlTableInfo *tinfo); +STableMeta* smlGetMeta(SSmlHandle *info, const void* measure, int32_t measureLen); +int32_t is_same_child_table_telnet(const void *a, const void *b); +int64_t smlParseOpenTsdbTime(SSmlHandle *info, const char *data, int32_t len); +int32_t smlClearForRerun(SSmlHandle *info); +int32_t smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg); +uint8_t smlGetTimestampLen(int64_t num); +void clearColValArray(SArray* pCols); +void smlDestroyTableInfo(SSmlHandle *info, SSmlTableInfo *tag); + +void freeSSmlKv(void* data); +int32_t smlParseInfluxString(SSmlHandle *info, char *sql, char *sqlEnd, SSmlLineInfo *elements); +int32_t smlParseTelnetString(SSmlHandle *info, char *sql, char *sqlEnd, SSmlLineInfo *elements); +int32_t smlParseJSON(SSmlHandle *info, char *payload); + +#ifdef __cplusplus +} +#endif + +#endif // TDENGINE_CLIENTSML_H diff --git a/source/client/inc/clientStmt.h b/source/client/inc/clientStmt.h index e5507ccf816b9fd591e6e27ee2974badcb5734ed..cbef80b6daa63fd3192aae98cfb6170893381894 100644 --- a/source/client/inc/clientStmt.h +++ b/source/client/inc/clientStmt.h @@ -21,8 +21,6 @@ extern "C" { #endif #include "catalog.h" -typedef void STableDataBlocks; - typedef enum { STMT_TYPE_INSERT = 1, STMT_TYPE_MULTI_INSERT, @@ -43,8 +41,8 @@ typedef enum { } STMT_STATUS; typedef struct SStmtTableCache { - STableDataBlocks *pDataBlock; - void *boundTags; + STableDataCxt *pDataCtx; + void *boundTags; } SStmtTableCache; typedef struct SStmtQueryResInfo { @@ -71,10 +69,11 @@ typedef struct SStmtBindInfo { } SStmtBindInfo; typedef struct SStmtExecInfo { - int32_t affectedRows; - SRequestObj *pRequest; - SHashObj *pBlockHash; - bool autoCreateTbl; + int32_t affectedRows; + SRequestObj *pRequest; + SHashObj *pBlockHash; + STableDataCxt *pCurrBlock; + SSubmitTbData *pCurrTbData; } SStmtExecInfo; typedef struct SStmtSQLInfo { @@ -103,6 +102,7 @@ typedef struct STscStmt { SStmtBindInfo bInfo; int64_t reqid; + int32_t errCode; } STscStmt; extern char *gStmtStatusStr[]; @@ -122,6 +122,7 @@ extern char *gStmtStatusStr[]; int32_t _code = c; \ if (_code != TSDB_CODE_SUCCESS) { \ terrno = _code; \ + pStmt->errCode = _code; \ return _code; \ } \ } while (0) @@ -130,6 +131,7 @@ extern char *gStmtStatusStr[]; int32_t _code = c; \ if (_code != TSDB_CODE_SUCCESS) { \ terrno = _code; \ + pStmt->errCode = _code; \ } \ return _code; \ } while (0) @@ -138,9 +140,19 @@ extern char *gStmtStatusStr[]; code = c; \ if (code != TSDB_CODE_SUCCESS) { \ terrno = code; \ + pStmt->errCode = code; \ goto _return; \ } \ } while (0) +#define STMT_ERRI_JRET(c) \ + do { \ + code = c; \ + if (code != TSDB_CODE_SUCCESS) { \ + terrno = code; \ + goto _return; \ + } \ + } while (0) + #define STMT_ELOG(param, ...) qError("stmt:%p " param, pStmt, __VA_ARGS__) #define STMT_DLOG(param, ...) qDebug("stmt:%p " param, pStmt, __VA_ARGS__) diff --git a/source/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h b/source/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h index a88bf0f7a6bfd74bc92a82e57a44c5fc2957f6a8..2921afc3f827d233b2b4a6fd0d2886e97dfaf325 100644 --- a/source/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h +++ b/source/client/jni/com_taosdata_jdbc_TSDBJNIConnector.h @@ -75,6 +75,14 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEn */ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp(JNIEnv *, jobject, jbyteArray, jlong); +/* + * Class: com_taosdata_jdbc_TSDBJNIConnector + * Method: executeQueryWithReqId + * Signature: ([BJJ)I + */ +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryWithReqId(JNIEnv *, jobject, jbyteArray, + jlong, jlong); + /* * Class: com_taosdata_jdbc_TSDBJNIConnector * Method: getErrCodeImp @@ -186,6 +194,14 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTab */ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp(JNIEnv *, jobject, jbyteArray, jlong); +/* + * Class: com_taosdata_jdbc_TSDBJNIConnector + * Method: prepareStmtWithReqId + * Signature: ([BJJ)I + */ +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtWithReqId(JNIEnv *, jobject, jbyteArray, + jlong, jlong); + /* * Class: com_taosdata_jdbc_TSDBJNIConnector * Method: setBindTableNameImp @@ -260,6 +276,32 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JN JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertImp(JNIEnv *, jobject, jobjectArray, jlong, jint, jint); +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertWithReqId(JNIEnv *, jobject, jlong, + jobjectArray, jint, jint, + jlong); + +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertWithTtl(JNIEnv *, jobject, jlong, + jobjectArray, jint, jint, jint); + +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertWithTtlAndReqId(JNIEnv *, jobject, + jlong, jobjectArray, + jint, jint, jint, + jlong); + +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertRaw(JNIEnv *, jobject, jlong, jstring, + jint, jint); + +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertRawWithReqId(JNIEnv *, jobject, jlong, + jstring, jint, jint, + jlong); + +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertRawWithTtl(JNIEnv *, jobject, jlong, + jstring, jint, jint, jint); + +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertRawWithTtlAndReqId(JNIEnv *, jobject, + jlong, jstring, + jint, jint, jint, + jlong); /** * Class: com_taosdata_jdbc_TSDBJNIConnector * Method: getTableVgID diff --git a/source/client/jni/com_taosdata_jdbc_tmq_TMQConnector.h b/source/client/jni/com_taosdata_jdbc_tmq_TMQConnector.h index 197cd78006e211180e21a4c0be1596d4940ba170..c035b6598c8b6290997e65a30f40cd28a11279b1 100644 --- a/source/client/jni/com_taosdata_jdbc_tmq_TMQConnector.h +++ b/source/client/jni/com_taosdata_jdbc_tmq_TMQConnector.h @@ -99,6 +99,9 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitSync(JNI */ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitAsync(JNIEnv *, jobject, jlong, jlong, jobject); +JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_consumerCommitAsync(JNIEnv *, jobject, jlong, jlong, + jobject); + /* * Class: com_taosdata_jdbc_tmq_TMQConnector * Method: tmqUnsubscribeImp diff --git a/source/client/src/clientEnv.c b/source/client/src/clientEnv.c index 593a8fd20a88591255a3b0a5aba4507f91a56569..1d639550608211439c50d7596c9aa08620cb8197 100644 --- a/source/client/src/clientEnv.c +++ b/source/client/src/clientEnv.c @@ -23,16 +23,21 @@ #include "scheduler.h" #include "tcache.h" #include "tglobal.h" +#include "thttp.h" #include "tmsg.h" #include "tref.h" #include "trpc.h" #include "tsched.h" #include "ttime.h" -#include "thttp.h" + +#if defined(CUS_NAME) || defined(CUS_PROMPT) || defined(CUS_EMAIL) +#include "cus_name.h" +#endif #define TSC_VAR_NOT_RELEASE 1 #define TSC_VAR_RELEASED 0 +STscDbg tscDbg = {0}; SAppInfo appInfo; int64_t lastClusterId = 0; int32_t clientReqRefPool = -1; @@ -65,7 +70,10 @@ static int32_t registerRequest(SRequestObj *pRequest, STscObj *pTscObj) { static void deregisterRequest(SRequestObj *pRequest) { const static int64_t SLOW_QUERY_INTERVAL = 3000000L; // todo configurable - assert(pRequest != NULL); + if (pRequest == NULL) { + tscError("pRequest == NULL"); + return; + } STscObj *pTscObj = pRequest->pTscObj; SAppClusterSummary *pActivity = &pTscObj->pAppInfo->summary; @@ -79,26 +87,27 @@ static void deregisterRequest(SRequestObj *pRequest) { "current:%d, app current:%d", pRequest->self, pTscObj->id, pRequest->requestId, duration / 1000.0, num, currentInst); - if (QUERY_NODE_VNODE_MODIF_STMT == pRequest->stmtType) { - // tscPerf("insert duration %" PRId64 "us: syntax:%" PRId64 "us, ctg:%" PRId64 "us, semantic:%" PRId64 - // "us, exec:%" PRId64 "us", - // duration, pRequest->metric.syntaxEnd - pRequest->metric.syntaxStart, - // pRequest->metric.ctgEnd - pRequest->metric.ctgStart, pRequest->metric.semanticEnd - - // pRequest->metric.ctgEnd, pRequest->metric.execEnd - pRequest->metric.semanticEnd); - atomic_add_fetch_64((int64_t *)&pActivity->insertElapsedTime, duration); - } else if (QUERY_NODE_SELECT_STMT == pRequest->stmtType) { - // tscPerf("select duration %" PRId64 "us: syntax:%" PRId64 "us, ctg:%" PRId64 "us, semantic:%" PRId64 - // "us, planner:%" PRId64 "us, exec:%" PRId64 "us, reqId:0x%" PRIx64, - // duration, pRequest->metric.syntaxEnd - pRequest->metric.syntaxStart, - // pRequest->metric.ctgEnd - pRequest->metric.ctgStart, pRequest->metric.semanticEnd - - // pRequest->metric.ctgEnd, pRequest->metric.planEnd - pRequest->metric.semanticEnd, - // pRequest->metric.resultReady - pRequest->metric.planEnd, pRequest->requestId); - - atomic_add_fetch_64((int64_t *)&pActivity->queryElapsedTime, duration); + if (pRequest->pQuery && pRequest->pQuery->pRoot) { + if (QUERY_NODE_VNODE_MODIFY_STMT == pRequest->pQuery->pRoot->type && + (0 == ((SVnodeModifyOpStmt *)pRequest->pQuery->pRoot)->sqlNodeType)) { + tscDebug("insert duration %" PRId64 "us: parseCost:%" PRId64 "us, ctgCost:%" PRId64 "us, analyseCost:%" PRId64 + "us, planCost:%" PRId64 "us, exec:%" PRId64 "us", + duration, pRequest->metric.parseCostUs, pRequest->metric.ctgCostUs, pRequest->metric.analyseCostUs, + pRequest->metric.planCostUs, pRequest->metric.execCostUs); + atomic_add_fetch_64((int64_t *)&pActivity->insertElapsedTime, duration); + } else if (QUERY_NODE_SELECT_STMT == pRequest->stmtType) { + tscDebug("query duration %" PRId64 "us: parseCost:%" PRId64 "us, ctgCost:%" PRId64 "us, analyseCost:%" PRId64 + "us, planCost:%" PRId64 "us, exec:%" PRId64 "us", + duration, pRequest->metric.parseCostUs, pRequest->metric.ctgCostUs, pRequest->metric.analyseCostUs, + pRequest->metric.planCostUs, pRequest->metric.execCostUs); + + atomic_add_fetch_64((int64_t *)&pActivity->queryElapsedTime, duration); + } } if (duration >= SLOW_QUERY_INTERVAL) { atomic_add_fetch_64((int64_t *)&pActivity->numOfSlowQueries, 1); + tscLogL("slow query: %s, duration:%" PRId64, pRequest->sqlstr, duration); } releaseTscObj(pTscObj->id); @@ -140,7 +149,7 @@ void *openTransporter(const char *user, const char *auth, int32_t numOfThread) { memset(&rpcInit, 0, sizeof(rpcInit)); rpcInit.localPort = 0; rpcInit.label = "TSC"; - rpcInit.numOfThreads = numOfThread; + rpcInit.numOfThreads = tsNumOfRpcThreads; rpcInit.cfp = processMsgFromServer; rpcInit.rfp = clientRpcRfp; rpcInit.sessions = 1024; @@ -155,6 +164,12 @@ void *openTransporter(const char *user, const char *auth, int32_t numOfThread) { rpcInit.retryMaxInterval = tsRedirectMaxPeriod; rpcInit.retryMaxTimouet = tsMaxRetryWaitTime; + int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3); + connLimitNum = TMAX(connLimitNum, 10); + connLimitNum = TMIN(connLimitNum, 1000); + rpcInit.connLimitNum = connLimitNum; + rpcInit.timeToGetConn = tsTimeToGetAvailableConn; + void *pDnodeConn = rpcOpen(&rpcInit); if (pDnodeConn == NULL) { tscError("failed to init connection to server"); @@ -267,7 +282,6 @@ void *createTscObj(const char *user, const char *auth, const char *db, int32_t c taosThreadMutexInit(&pObj->mutex, NULL); pObj->id = taosAddRef(clientConnRefPool, pObj); - pObj->schemalessType = 1; atomic_add_fetch_64(&pObj->pAppInfo->numOfConns, 1); @@ -362,8 +376,6 @@ void doDestroyRequest(void *p) { taosArrayDestroy(pRequest->tableList); taosArrayDestroy(pRequest->dbList); taosArrayDestroy(pRequest->targetTableList); - qDestroyQuery(pRequest->pQuery); - nodesDestroyAllocator(pRequest->allocatorRefId); destroyQueryExecRes(&pRequest->body.resInfo.execRes); @@ -372,12 +384,15 @@ void doDestroyRequest(void *p) { } if (pRequest->syncQuery) { - if (pRequest->body.param){ - tsem_destroy(&((SSyncQueryParam*)pRequest->body.param)->sem); - } + if (pRequest->body.param) { + tsem_destroy(&((SSyncQueryParam *)pRequest->body.param)->sem); + } taosMemoryFree(pRequest->body.param); } + qDestroyQuery(pRequest->pQuery); + nodesDestroyAllocator(pRequest->allocatorRefId); + taosMemoryFreeClear(pRequest->sqlstr); taosMemoryFree(pRequest); tscTrace("end to destroy request %" PRIx64 " p:%p", reqId, pRequest); @@ -398,20 +413,20 @@ static void *tscCrashReportThreadFp(void *param) { setThreadName("client-crashReport"); char filepath[PATH_MAX] = {0}; snprintf(filepath, sizeof(filepath), "%s%s.taosCrashLog", tsLogDir, TD_DIRSEP); - char *pMsg = NULL; - int64_t msgLen = 0; + char *pMsg = NULL; + int64_t msgLen = 0; TdFilePtr pFile = NULL; - bool truncateFile = false; - int32_t sleepTime = 200; - int32_t reportPeriodNum = 3600 * 1000 / sleepTime; - int32_t loopTimes = reportPeriodNum; + bool truncateFile = false; + int32_t sleepTime = 200; + int32_t reportPeriodNum = 3600 * 1000 / sleepTime; + int32_t loopTimes = reportPeriodNum; #ifdef WINDOWS if (taosCheckCurrentInDll()) { atexit(crashReportThreadFuncUnexpectedStopped); } #endif - + while (1) { if (clientStop) break; if (loopTimes++ < reportPeriodNum) { @@ -441,12 +456,12 @@ static void *tscCrashReportThreadFp(void *param) { pMsg = NULL; continue; } - + if (pFile) { taosReleaseCrashLogFile(pFile, truncateFile); truncateFile = false; } - + taosMsleep(sleepTime); loopTimes = 0; } @@ -459,11 +474,11 @@ int32_t tscCrashReportInit() { if (!tsEnableCrashReport) { return 0; } - + TdThreadAttr thAttr; taosThreadAttrInit(&thAttr); taosThreadAttrSetDetachState(&thAttr, PTHREAD_CREATE_JOINABLE); - TdThread crashReportThread; + TdThread crashReportThread; if (taosThreadCreate(&crashReportThread, &thAttr, tscCrashReportThreadFp, NULL) != 0) { tscError("failed to create crashReport thread since %s", strerror(errno)); return -1; @@ -488,27 +503,37 @@ void tscStopCrashReport() { } } - void tscWriteCrashInfo(int signum, void *sigInfo, void *context) { - char *pMsg = NULL; + char *pMsg = NULL; const char *flags = "UTL FATAL "; ELogLevel level = DEBUG_FATAL; int32_t dflag = 255; - int64_t msgLen= -1; + int64_t msgLen = -1; if (tsEnableCrashReport) { if (taosGenCrashJsonMsg(signum, &pMsg, lastClusterId, appInfo.startTime)) { taosPrintLog(flags, level, dflag, "failed to generate crash json msg"); } else { - msgLen = strlen(pMsg); + msgLen = strlen(pMsg); } } taosLogCrashInfo("taos", pMsg, msgLen, signum, sigInfo); } - void taos_init_imp(void) { +#if defined(LINUX) + if (tscDbg.memEnable) { + int32_t code = taosMemoryDbgInit(); + if (code) { + printf("failed to init memory dbg, error:%s\n", tstrerror(code)); + } else { + tsAsyncLog = false; + printf("memory dbg enabled\n"); + } + } +#endif + // 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); @@ -521,9 +546,15 @@ void taos_init_imp(void) { deltaToUtcInitOnce(); - if (taosCreateLog("taoslog", 10, configDir, NULL, NULL, NULL, NULL, 1) != 0) { + char logDirName[64] = {0}; +#ifdef CUS_PROMPT + snprintf(logDirName, 64, "%slog", CUS_PROMPT); +#else + snprintf(logDirName, 64, "taoslog"); +#endif + if (taosCreateLog(logDirName, 10, configDir, NULL, NULL, NULL, NULL, 1) != 0) { // ignore create log failed, only print - printf(" WARING: Create taoslog failed. configDir=%s\n", configDir); + printf(" WARING: Create %s failed:%s. configDir=%s\n", logDirName, strerror(errno), configDir); } if (taosInitCfg(configDir, NULL, NULL, NULL, NULL, 1) != 0) { @@ -534,7 +565,8 @@ void taos_init_imp(void) { initQueryModuleMsgHandle(); if (taosConvInit() != 0) { - ASSERTS(0, "failed to init conv"); + tscError("failed to init conv"); + return; } rpcInit(); @@ -561,7 +593,7 @@ void taos_init_imp(void) { taosThreadMutexInit(&appInfo.mutex, NULL); tscCrashReportInit(); - + tscDebug("client is initialized successfully"); } @@ -612,6 +644,9 @@ int taos_options_imp(TSDB_OPTION option, const char *str) { tscError("failed to set cfg:%s to %s since %s", pItem->name, str, terrstr()); } else { tscInfo("set cfg:%s to %s", pItem->name, str); + if (TSDB_OPTION_SHELL_ACTIVITY_TIMER == option || TSDB_OPTION_USE_ADAPTER == option) { + code = taosSetCfg(pCfg, pItem->name); + } } return code; diff --git a/source/client/src/clientHb.c b/source/client/src/clientHb.c index 47ed2cf035a13314b81f2208718d2c466efb5c68..0cf993091172d3445d92405e4e99b1c48498a3f9 100644 --- a/source/client/src/clientHb.c +++ b/source/client/src/clientHb.c @@ -49,65 +49,97 @@ static int32_t hbProcessUserAuthInfoRsp(void *value, int32_t valueLen, struct SC return TSDB_CODE_SUCCESS; } -static int32_t hbProcessDBInfoRsp(void *value, int32_t valueLen, struct SCatalog *pCatalog) { +static int32_t hbGenerateVgInfoFromRsp(SDBVgInfo **pInfo, SUseDbRsp *rsp) { int32_t code = 0; + SDBVgInfo *vgInfo = taosMemoryCalloc(1, sizeof(SDBVgInfo)); + if (NULL == vgInfo) { + code = TSDB_CODE_OUT_OF_MEMORY; + return code; + } + + vgInfo->vgVersion = rsp->vgVersion; + vgInfo->stateTs = rsp->stateTs; + vgInfo->hashMethod = rsp->hashMethod; + vgInfo->hashPrefix = rsp->hashPrefix; + vgInfo->hashSuffix = rsp->hashSuffix; + vgInfo->vgHash = taosHashInit(rsp->vgNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK); + if (NULL == vgInfo->vgHash) { + taosMemoryFree(vgInfo); + tscError("hash init[%d] failed", rsp->vgNum); + code = TSDB_CODE_OUT_OF_MEMORY; + goto _return; + } + + for (int32_t j = 0; j < rsp->vgNum; ++j) { + SVgroupInfo *pInfo = taosArrayGet(rsp->pVgroupInfos, j); + if (taosHashPut(vgInfo->vgHash, &pInfo->vgId, sizeof(int32_t), pInfo, sizeof(SVgroupInfo)) != 0) { + tscError("hash push failed, errno:%d", errno); + taosHashCleanup(vgInfo->vgHash); + taosMemoryFree(vgInfo); + code = TSDB_CODE_OUT_OF_MEMORY; + goto _return; + } + } - SUseDbBatchRsp batchUseRsp = {0}; - if (tDeserializeSUseDbBatchRsp(value, valueLen, &batchUseRsp) != 0) { - terrno = TSDB_CODE_INVALID_MSG; - return -1; +_return: + if (code) { + taosHashCleanup(vgInfo->vgHash); + taosMemoryFreeClear(vgInfo); } - int32_t numOfBatchs = taosArrayGetSize(batchUseRsp.pArray); - for (int32_t i = 0; i < numOfBatchs; ++i) { - SUseDbRsp *rsp = taosArrayGet(batchUseRsp.pArray, i); - tscDebug("hb db rsp, db:%s, vgVersion:%d, stateTs:%" PRId64 ", uid:%" PRIx64, rsp->db, rsp->vgVersion, rsp->stateTs, - rsp->uid); + *pInfo = vgInfo; + return code; +} - if (rsp->vgVersion < 0) { - code = catalogRemoveDB(pCatalog, rsp->db, rsp->uid); - } else { - SDBVgInfo *vgInfo = taosMemoryCalloc(1, sizeof(SDBVgInfo)); - if (NULL == vgInfo) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _return; - } +static int32_t hbProcessDBInfoRsp(void *value, int32_t valueLen, struct SCatalog *pCatalog) { + int32_t code = 0; - vgInfo->vgVersion = rsp->vgVersion; - vgInfo->stateTs = rsp->stateTs; - vgInfo->hashMethod = rsp->hashMethod; - vgInfo->hashPrefix = rsp->hashPrefix; - vgInfo->hashSuffix = rsp->hashSuffix; - vgInfo->vgHash = taosHashInit(rsp->vgNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK); - if (NULL == vgInfo->vgHash) { - taosMemoryFree(vgInfo); - tscError("hash init[%d] failed", rsp->vgNum); - code = TSDB_CODE_OUT_OF_MEMORY; - goto _return; - } + SDbHbBatchRsp batchRsp = {0}; + if (tDeserializeSDbHbBatchRsp(value, valueLen, &batchRsp) != 0) { + terrno = TSDB_CODE_INVALID_MSG; + code = terrno; + goto _return; + } - for (int32_t j = 0; j < rsp->vgNum; ++j) { - SVgroupInfo *pInfo = taosArrayGet(rsp->pVgroupInfos, j); - if (taosHashPut(vgInfo->vgHash, &pInfo->vgId, sizeof(int32_t), pInfo, sizeof(SVgroupInfo)) != 0) { - tscError("hash push failed, errno:%d", errno); - taosHashCleanup(vgInfo->vgHash); - taosMemoryFree(vgInfo); - code = TSDB_CODE_OUT_OF_MEMORY; + int32_t numOfBatchs = taosArrayGetSize(batchRsp.pArray); + for (int32_t i = 0; i < numOfBatchs; ++i) { + SDbHbRsp *rsp = taosArrayGet(batchRsp.pArray, i); + if (rsp->useDbRsp) { + tscDebug("hb use db rsp, db:%s, vgVersion:%d, stateTs:%" PRId64 ", uid:%" PRIx64, + rsp->useDbRsp->db, rsp->useDbRsp->vgVersion, rsp->useDbRsp->stateTs, rsp->useDbRsp->uid); + + if (rsp->useDbRsp->vgVersion < 0) { + code = catalogRemoveDB(pCatalog, rsp->useDbRsp->db, rsp->useDbRsp->uid); + } else { + SDBVgInfo *vgInfo = NULL; + code = hbGenerateVgInfoFromRsp(&vgInfo, rsp->useDbRsp); + if (TSDB_CODE_SUCCESS != code) { goto _return; } + + catalogUpdateDBVgInfo(pCatalog, rsp->useDbRsp->db, rsp->useDbRsp->uid, vgInfo); + + if (IS_SYS_DBNAME(rsp->useDbRsp->db)) { + code = hbGenerateVgInfoFromRsp(&vgInfo, rsp->useDbRsp); + if (TSDB_CODE_SUCCESS != code) { + goto _return; + } + + catalogUpdateDBVgInfo(pCatalog, (rsp->useDbRsp->db[0] == 'i') ? TSDB_PERFORMANCE_SCHEMA_DB : TSDB_INFORMATION_SCHEMA_DB, rsp->useDbRsp->uid, vgInfo); + } } - - catalogUpdateDBVgInfo(pCatalog, rsp->db, rsp->uid, vgInfo); } - if (code) { - goto _return; + if (rsp->cfgRsp) { + tscDebug("hb db cfg rsp, db:%s, cfgVersion:%d", rsp->cfgRsp->db, rsp->cfgRsp->cfgVersion); + catalogUpdateDbCfg(pCatalog, rsp->cfgRsp->db, rsp->cfgRsp->dbId, rsp->cfgRsp); + rsp->cfgRsp = NULL; } } _return: - tFreeSUseDbBatchRsp(&batchUseRsp); + tFreeSDbHbBatchRsp(&batchRsp); return code; } @@ -276,8 +308,12 @@ static int32_t hbQueryHbRspHandle(SAppHbMgr *pAppHbMgr, SClientHbRsp *pRsp) { } static int32_t hbAsyncCallBack(void *param, SDataBuf *pMsg, int32_t code) { + if (0 == atomic_load_8(&clientHbMgr.inited)) { + goto _return; + } + static int32_t emptyRspNum = 0; - char *key = (char *)param; + int32_t idx = *(int32_t *)param; SClientHbBatchRsp pRsp = {0}; if (TSDB_CODE_SUCCESS == code) { tDeserializeSClientHbBatchRsp(pMsg->pData, pMsg->len, &pRsp); @@ -292,22 +328,24 @@ static int32_t hbAsyncCallBack(void *param, SDataBuf *pMsg, int32_t code) { int32_t rspNum = taosArrayGetSize(pRsp.rsps); - taosThreadMutexLock(&appInfo.mutex); + taosThreadMutexLock(&clientHbMgr.lock); - SAppInstInfo **pInst = taosHashGet(appInfo.pInstMap, key, strlen(key)); - if (pInst == NULL || NULL == *pInst) { - taosThreadMutexUnlock(&appInfo.mutex); - tscError("cluster not exist, key:%s", key); + SAppHbMgr *pAppHbMgr = taosArrayGetP(clientHbMgr.appHbMgrs, idx); + if (pAppHbMgr == NULL) { + taosThreadMutexUnlock(&clientHbMgr.lock); + tscError("appHbMgr not exist, idx:%d", idx); taosMemoryFree(pMsg->pData); taosMemoryFree(pMsg->pEpSet); tFreeClientHbBatchRsp(&pRsp); return -1; } + SAppInstInfo *pInst = pAppHbMgr->pAppInstInfo; + if (code != 0) { - (*pInst)->onlineDnodes = ((*pInst)->totalDnodes ? 0 : -1); - tscDebug("hb rsp error %s, update server status %d/%d", tstrerror(code), (*pInst)->onlineDnodes, - (*pInst)->totalDnodes); + pInst->onlineDnodes = pInst->totalDnodes ? 0 : -1; + tscDebug("hb rsp error %s, update server status %d/%d", tstrerror(code), pInst->onlineDnodes, + pInst->totalDnodes); } if (rspNum) { @@ -319,15 +357,17 @@ static int32_t hbAsyncCallBack(void *param, SDataBuf *pMsg, int32_t code) { for (int32_t i = 0; i < rspNum; ++i) { SClientHbRsp *rsp = taosArrayGet(pRsp.rsps, i); - code = (*clientHbMgr.rspHandle[rsp->connKey.connType])((*pInst)->pAppHbMgr, rsp); + code = (*clientHbMgr.rspHandle[rsp->connKey.connType])(pAppHbMgr, rsp); if (code) { break; } } - taosThreadMutexUnlock(&appInfo.mutex); + taosThreadMutexUnlock(&clientHbMgr.lock); tFreeClientHbBatchRsp(&pRsp); + +_return: taosMemoryFree(pMsg->pData); taosMemoryFree(pMsg->pEpSet); return code; @@ -347,7 +387,7 @@ int32_t hbBuildQueryDesc(SQueryHbReqBasic *hbBasic, STscObj *pObj) { continue; } - if (pRequest->killed) { + if (pRequest->killed || 0 == pRequest->body.queryJob) { releaseRequest(*rid); pIter = taosHashIterate(pObj->pRequests, pIter); continue; @@ -376,7 +416,6 @@ int32_t hbBuildQueryDesc(SQueryHbReqBasic *hbBasic, STscObj *pObj) { desc.subPlanNum = 0; } desc.subPlanNum = taosArrayGetSize(desc.subDesc); - ASSERT(desc.subPlanNum == taosArrayGetSize(desc.subDesc)); } else { desc.subDesc = NULL; } @@ -476,7 +515,7 @@ int32_t hbGetExpiredUserInfo(SClientHbKey *connKey, struct SCatalog *pCatalog, S } int32_t hbGetExpiredDBInfo(SClientHbKey *connKey, struct SCatalog *pCatalog, SClientHbReq *req) { - SDbVgVersion *dbs = NULL; + SDbCacheInfo *dbs = NULL; uint32_t dbNum = 0; int32_t code = 0; @@ -491,16 +530,20 @@ int32_t hbGetExpiredDBInfo(SClientHbKey *connKey, struct SCatalog *pCatalog, SCl } for (int32_t i = 0; i < dbNum; ++i) { - SDbVgVersion *db = &dbs[i]; + SDbCacheInfo *db = &dbs[i]; + tscDebug("the %dth expired dbFName:%s, dbId:%" PRId64 ", vgVersion:%d, cfgVersion:%d, numOfTable:%d, startTs:%" PRId64, + i, db->dbFName, db->dbId, db->vgVersion, db->cfgVersion, db->numOfTable, db->stateTs); + db->dbId = htobe64(db->dbId); db->vgVersion = htonl(db->vgVersion); + db->cfgVersion = htonl(db->cfgVersion); db->numOfTable = htonl(db->numOfTable); db->stateTs = htobe64(db->stateTs); } SKv kv = { .key = HEARTBEAT_KEY_DBINFO, - .valueLen = sizeof(SDbVgVersion) * dbNum, + .valueLen = sizeof(SDbCacheInfo) * dbNum, .value = dbs, }; @@ -759,7 +802,8 @@ static void *hbThreadFunc(void *param) { pInfo->msgInfo.pData = buf; pInfo->msgInfo.len = tlen; pInfo->msgType = TDMT_MND_HEARTBEAT; - pInfo->param = strdup(pAppHbMgr->key); + pInfo->param = taosMemoryMalloc(sizeof(int32_t)); + *(int32_t *)pInfo->param = i; pInfo->paramFreeFp = taosMemoryFree; pInfo->requestId = generateRequestId(); pInfo->requestObjRefId = 0; @@ -807,13 +851,21 @@ static void hbStopThread() { return; } - taosThreadJoin(clientHbMgr.thread, NULL); + // thread quit mode kill or inner exit from self-thread + if (clientHbMgr.quitByKill) { + taosThreadKill(clientHbMgr.thread, 0); + } else { + taosThreadJoin(clientHbMgr.thread, NULL); + } tscDebug("hb thread stopped"); } SAppHbMgr *appHbMgrInit(SAppInstInfo *pAppInstInfo, char *key) { - hbMgrInit(); + if(hbMgrInit() != 0){ + terrno = TSDB_CODE_TSC_INTERNAL_ERROR; + return NULL; + } SAppHbMgr *pAppHbMgr = taosMemoryMalloc(sizeof(SAppHbMgr)); if (pAppHbMgr == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -824,7 +876,7 @@ SAppHbMgr *appHbMgrInit(SAppInstInfo *pAppInstInfo, char *key) { pAppHbMgr->connKeyCnt = 0; pAppHbMgr->reportCnt = 0; pAppHbMgr->reportBytes = 0; - pAppHbMgr->key = strdup(key); + pAppHbMgr->key = taosStrdup(key); // init app info pAppHbMgr->pAppInstInfo = pAppInstInfo; @@ -842,6 +894,7 @@ SAppHbMgr *appHbMgrInit(SAppInstInfo *pAppInstInfo, char *key) { taosThreadMutexLock(&clientHbMgr.lock); taosArrayPush(clientHbMgr.appHbMgrs, &pAppHbMgr); + pAppHbMgr->idx = taosArrayGetSize(clientHbMgr.appHbMgrs) - 1; taosThreadMutexUnlock(&clientHbMgr.lock); return pAppHbMgr; @@ -899,16 +952,28 @@ int hbMgrInit() { TdThreadMutexAttr attr = {0}; int ret = taosThreadMutexAttrInit(&attr); - assert(ret == 0); + if(ret != 0){ + uError("hbMgrInit:taosThreadMutexAttrInit error") + return ret; + } ret = taosThreadMutexAttrSetType(&attr, PTHREAD_MUTEX_RECURSIVE); - assert(ret == 0); + if(ret != 0){ + uError("hbMgrInit:taosThreadMutexAttrSetType error") + return ret; + } ret = taosThreadMutexInit(&clientHbMgr.lock, &attr); - assert(ret == 0); + if(ret != 0){ + uError("hbMgrInit:taosThreadMutexInit error") + return ret; + } ret = taosThreadMutexAttrDestroy(&attr); - assert(ret == 0); + if(ret != 0){ + uError("hbMgrInit:taosThreadMutexAttrDestroy error") + return ret; + } // init handle funcs hbMgrInitHandle(); @@ -983,3 +1048,8 @@ void hbDeregisterConn(SAppHbMgr *pAppHbMgr, SClientHbKey connKey) { atomic_sub_fetch_32(&pAppHbMgr->connKeyCnt, 1); } + +// set heart beat thread quit mode , if quicByKill 1 then kill thread else quit from inner +void taos_set_hb_quit(int8_t quitByKill) { + clientHbMgr.quitByKill = quitByKill; +} diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 67fa1e77812b7a4f6b060b0d71c679729b48335f..ce174744ef740e13dffb4ab4a44cdf5a601b0f29 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -52,7 +52,7 @@ static bool validateDbName(const char* db) { return stringLengthCheck(db, TSDB_D static char* getClusterKey(const char* user, const char* auth, const char* ip, int32_t port) { char key[512] = {0}; snprintf(key, sizeof(key), "%s:%s:%s:%d", user, auth, ip, port); - return strdup(key); + return taosStrdup(key); } bool chkRequestKilled(void* param) { @@ -192,7 +192,7 @@ int32_t buildRequest(uint64_t connId, const char* sql, int sqlLen, void* param, (*pRequest)->sqlLen = sqlLen; (*pRequest)->validateOnly = validateSql; - SSyncQueryParam* newpParam; + SSyncQueryParam* newpParam = NULL; if (param == NULL) { newpParam = taosMemoryCalloc(1, sizeof(SSyncQueryParam)); if (newpParam == NULL) { @@ -252,7 +252,6 @@ int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtC .pTransporter = pTscObj->pAppInfo->pTransporter, .pStmtCb = pStmtCb, .pUser = pTscObj->user, - .schemalessType = pTscObj->schemalessType, .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)), .enableSysInfo = pTscObj->sysInfo, .svrVer = pTscObj->sVer, @@ -286,7 +285,7 @@ int32_t parseSql(SRequestObj* pRequest, bool topicQuery, SQuery** pQuery, SStmtC int32_t execLocalCmd(SRequestObj* pRequest, SQuery* pQuery) { SRetrieveTableRsp* pRsp = NULL; - int32_t code = qExecCommand(pRequest->pTscObj->sysInfo, pQuery->pRoot, &pRsp); + int32_t code = qExecCommand(&pRequest->pTscObj->id, pRequest->pTscObj->sysInfo, pQuery->pRoot, &pRsp); if (TSDB_CODE_SUCCESS == code && NULL != pRsp) { code = setQueryResultFromRsp(&pRequest->body.resInfo, pRsp, false, true); } @@ -324,7 +323,7 @@ void asyncExecLocalCmd(SRequestObj* pRequest, SQuery* pQuery) { return; } - int32_t code = qExecCommand(pRequest->pTscObj->sysInfo, pQuery->pRoot, &pRsp); + int32_t code = qExecCommand(&pRequest->pTscObj->id, pRequest->pTscObj->sysInfo, pQuery->pRoot, &pRsp); if (TSDB_CODE_SUCCESS == code && NULL != pRsp) { code = setQueryResultFromRsp(&pRequest->body.resInfo, pRsp, false, true); } @@ -466,7 +465,10 @@ int32_t getPlan(SRequestObj* pRequest, SQuery* pQuery, SQueryPlan** pPlan, SArra } void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t numOfCols) { - ASSERT(pSchema != NULL && numOfCols > 0); + if (pResInfo == NULL || pSchema == NULL || numOfCols <= 0) { + tscError("invalid paras, pResInfo == NULL || pSchema == NULL || numOfCols <= 0"); + return; + } pResInfo->numOfCols = numOfCols; if (pResInfo->fields != NULL) { @@ -477,7 +479,10 @@ void setResSchemaInfo(SReqResultInfo* pResInfo, const SSchema* pSchema, int32_t } pResInfo->fields = taosMemoryCalloc(numOfCols, sizeof(TAOS_FIELD)); pResInfo->userFields = taosMemoryCalloc(numOfCols, sizeof(TAOS_FIELD)); - ASSERT(numOfCols == pResInfo->numOfCols); + if (numOfCols != pResInfo->numOfCols) { + tscError("numOfCols:%d != pResInfo->numOfCols:%d", numOfCols, pResInfo->numOfCols); + return; + } for (int32_t i = 0; i < pResInfo->numOfCols; ++i) { pResInfo->fields[i].bytes = pSchema[i].bytes; @@ -754,47 +759,21 @@ int32_t scheduleQuery(SRequestObj* pRequest, SQueryPlan* pDag, SArray* pNodeList } int32_t handleSubmitExecRes(SRequestObj* pRequest, void* res, SCatalog* pCatalog, SEpSet* epset) { - int32_t code = 0; - SArray* pArray = NULL; - SSubmitRsp* pRsp = (SSubmitRsp*)res; - if (pRsp->nBlocks <= 0) { - taosMemoryFreeClear(pRsp->pBlocks); + SArray* pArray = NULL; + SSubmitRsp2* pRsp = (SSubmitRsp2*)res; + if (NULL == pRsp->aCreateTbRsp) { return TSDB_CODE_SUCCESS; } - pArray = taosArrayInit(pRsp->nBlocks, sizeof(STbSVersion)); - if (NULL == pArray) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return TSDB_CODE_OUT_OF_MEMORY; - } - - for (int32_t i = 0; i < pRsp->nBlocks; ++i) { - SSubmitBlkRsp* blk = pRsp->pBlocks + i; - if (blk->pMeta) { - handleCreateTbExecRes(blk->pMeta, pCatalog); - tFreeSTableMetaRsp(blk->pMeta); - taosMemoryFreeClear(blk->pMeta); - } - - if (NULL == blk->tblFName || 0 == blk->tblFName[0]) { - continue; + int32_t tbNum = taosArrayGetSize(pRsp->aCreateTbRsp); + for (int32_t i = 0; i < tbNum; ++i) { + SVCreateTbRsp* pTbRsp = (SVCreateTbRsp*)taosArrayGet(pRsp->aCreateTbRsp, i); + if (pTbRsp->pMeta) { + handleCreateTbExecRes(pTbRsp->pMeta, pCatalog); } - - STbSVersion tbSver = {.tbFName = blk->tblFName, .sver = blk->sver}; - taosArrayPush(pArray, &tbSver); } - SRequestConnInfo conn = {.pTrans = pRequest->pTscObj->pAppInfo->pTransporter, - .requestId = pRequest->requestId, - .requestObjRefId = pRequest->self, - .mgmtEps = *epset}; - - code = catalogChkTbMetaVersion(pCatalog, &conn, pArray); - -_return: - - taosArrayDestroy(pArray); - return code; + return TSDB_CODE_SUCCESS; } int32_t handleQueryExecRes(SRequestObj* pRequest, void* res, SCatalog* pCatalog, SEpSet* epset) { @@ -895,7 +874,7 @@ int32_t handleQueryExecRsp(SRequestObj* pRequest) { } static bool incompletaFileParsing(SNode* pStmt) { - return QUERY_NODE_VNODE_MODIF_STMT != nodeType(pStmt) ? false : ((SVnodeModifOpStmt*)pStmt)->fileProcessing; + return QUERY_NODE_VNODE_MODIFY_STMT != nodeType(pStmt) ? false : ((SVnodeModifyOpStmt*)pStmt)->fileProcessing; } // todo refacto the error code mgmt @@ -946,7 +925,7 @@ void schedulerExecCb(SExecResult* pResult, void* param, int32_t code) { removeMeta(pTscObj, pRequest->targetTableList); } - pRequest->metric.execEnd = taosGetTimestampUs(); + pRequest->metric.execCostUs = taosGetTimestampUs() - pRequest->metric.execStart; int32_t code1 = handleQueryExecRsp(pRequest); if (pRequest->code == TSDB_CODE_SUCCESS && pRequest->code != code1) { pRequest->code = code1; @@ -974,7 +953,7 @@ SRequestObj* launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQue if (pQuery->pRoot && !pRequest->inRetry) { STscObj* pTscObj = pRequest->pTscObj; SAppClusterSummary* pActivity = &pTscObj->pAppInfo->summary; - if (QUERY_NODE_VNODE_MODIF_STMT == pQuery->pRoot->type) { + if (QUERY_NODE_VNODE_MODIFY_STMT == pQuery->pRoot->type) { atomic_add_fetch_64((int64_t*)&pActivity->numOfInsertsReq, 1); } else if (QUERY_NODE_SELECT_STMT == pQuery->pRoot->type) { atomic_add_fetch_64((int64_t*)&pActivity->numOfQueryReq, 1); @@ -1060,8 +1039,7 @@ static int32_t asyncExecSchQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaDat .sysInfo = pRequest->pTscObj->sysInfo, .allocatorId = pRequest->allocatorRefId}; - SAppInstInfo* pAppInfo = getAppInfo(pRequest); - SQueryPlan* pDag = NULL; + SQueryPlan* pDag = NULL; int64_t st = taosGetTimestampUs(); int32_t code = qCreateQueryPlan(&cxt, &pDag, pMnodeList); @@ -1072,14 +1050,12 @@ static int32_t asyncExecSchQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaDat pRequest->body.subplanNum = pDag->numOfSubplans; } - pRequest->metric.planEnd = taosGetTimestampUs(); - if (code == TSDB_CODE_SUCCESS) { - tscDebug("0x%" PRIx64 " create query plan success, elapsed time:%.2f ms, 0x%" PRIx64, pRequest->self, - (pRequest->metric.planEnd - st) / 1000.0, pRequest->requestId); - } + pRequest->metric.execStart = taosGetTimestampUs(); + pRequest->metric.planCostUs = pRequest->metric.execStart - st; + if (TSDB_CODE_SUCCESS == code && !pRequest->validateOnly) { SArray* pNodeList = NULL; - if (QUERY_NODE_VNODE_MODIF_STMT != nodeType(pQuery->pRoot)) { + if (QUERY_NODE_VNODE_MODIFY_STMT != nodeType(pQuery->pRoot)) { buildAsyncExecNodeList(pRequest, &pNodeList, pMnodeList, pResultMeta); } @@ -1107,6 +1083,10 @@ static int32_t asyncExecSchQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaDat tscDebug("0x%" PRIx64 " plan not executed, code:%s 0x%" PRIx64, pRequest->self, tstrerror(code), pRequest->requestId); destorySqlCallbackWrapper(pWrapper); + if (TSDB_CODE_SUCCESS != code) { + pRequest->code = terrno; + } + pRequest->body.queryFp(pRequest->body.param, pRequest, code); } @@ -1124,6 +1104,17 @@ void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultM destorySqlCallbackWrapper(pWrapper); } + if (pQuery->pRoot && !pRequest->inRetry) { + STscObj* pTscObj = pRequest->pTscObj; + SAppClusterSummary* pActivity = &pTscObj->pAppInfo->summary; + if (QUERY_NODE_VNODE_MODIFY_STMT == pQuery->pRoot->type && + (0 == ((SVnodeModifyOpStmt*)pQuery->pRoot)->sqlNodeType)) { + atomic_add_fetch_64((int64_t*)&pActivity->numOfInsertsReq, 1); + } else if (QUERY_NODE_SELECT_STMT == pQuery->pRoot->type) { + atomic_add_fetch_64((int64_t*)&pActivity->numOfQueryReq, 1); + } + } + switch (pQuery->execMode) { case QUERY_EXEC_MODE_LOCAL: asyncExecLocalCmd(pRequest, pQuery); @@ -1143,11 +1134,6 @@ void launchAsyncQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaData* pResultM pRequest->body.queryFp(pRequest->body.param, pRequest, -1); break; } - - // TODO weired responding code? - if (TSDB_CODE_SUCCESS != code) { - pRequest->code = terrno; - } } int32_t refreshMeta(STscObj* pTscObj, SRequestObj* pRequest) { @@ -1318,6 +1304,7 @@ static SMsgSendInfo* buildConnectMsg(SRequestObj* pRequest) { tstrncpy(connectReq.app, appInfo.appName, sizeof(connectReq.app)); tstrncpy(connectReq.user, pObj->user, sizeof(connectReq.user)); tstrncpy(connectReq.passwd, pObj->pass, sizeof(connectReq.passwd)); + tstrncpy(connectReq.sVer, version, sizeof(connectReq.sVer)); int32_t contLen = tSerializeSConnectReq(NULL, 0, &connectReq); void* pReq = taosMemoryMalloc(contLen); @@ -1379,7 +1366,10 @@ int32_t doProcessMsgFromServer(void* param) { SEpSet* pEpSet = arg->pEpset; SMsgSendInfo* pSendInfo = (SMsgSendInfo*)pMsg->info.ahandle; - assert(pMsg->info.ahandle != NULL); + if (pMsg->info.ahandle == NULL) { + tscError("doProcessMsgFromServer pMsg->info.ahandle == NULL"); + return TSDB_CODE_TSC_INTERNAL_ERROR; + } STscObj* pTscObj = NULL; STraceId* trace = &pMsg->info.traceId; @@ -1392,22 +1382,12 @@ int32_t doProcessMsgFromServer(void* param) { if (pSendInfo->requestObjRefId != 0) { SRequestObj* pRequest = (SRequestObj*)taosAcquireRef(clientReqRefPool, pSendInfo->requestObjRefId); if (pRequest) { - assert(pRequest->self == pSendInfo->requestObjRefId); - - pRequest->metric.rsp = taosGetTimestampUs(); - pTscObj = pRequest->pTscObj; - /* - * There is not response callback function for submit response. - * The actual inserted number of points is the first number. - */ - int32_t elapsed = pRequest->metric.rsp - pRequest->metric.start; - if (pMsg->code == TSDB_CODE_SUCCESS) { - tscDebug("0x%" PRIx64 " rsp msg:%s, code:%s rspLen:%d, elapsed:%d ms, reqId:0x%" PRIx64, pRequest->self, - TMSG_INFO(pMsg->msgType), tstrerror(pMsg->code), pMsg->contLen, elapsed / 1000, pRequest->requestId); - } else { - tscError("0x%" PRIx64 " rsp msg:%s, code:%s rspLen:%d, elapsed time:%d ms, reqId:0x%" PRIx64, pRequest->self, - TMSG_INFO(pMsg->msgType), tstrerror(pMsg->code), pMsg->contLen, elapsed / 1000, pRequest->requestId); + if (pRequest->self != pSendInfo->requestObjRefId) { + tscError("doProcessMsgFromServer pRequest->self:%" PRId64 " != pSendInfo->requestObjRefId:%" PRId64, + pRequest->self, pSendInfo->requestObjRefId); + return TSDB_CODE_TSC_INTERNAL_ERROR; } + pTscObj = pRequest->pTscObj; } } @@ -1539,7 +1519,9 @@ void doSetOneRowPtr(SReqResultInfo* pResultInfo) { } void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4) { - assert(pRequest != NULL); + if (pRequest == NULL) { + return NULL; + } SReqResultInfo* pResultInfo = &pRequest->body.resInfo; if (pResultInfo->pData == NULL || pResultInfo->current >= pResultInfo->numOfRows) { @@ -1561,7 +1543,7 @@ void* doFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4) } pRequest->code = - setQueryResultFromRsp(&pRequest->body.resInfo, (SRetrieveTableRsp*)pResInfo->pData, convertUcs4, true); + setQueryResultFromRsp(&pRequest->body.resInfo, (const SRetrieveTableRsp*)pResInfo->pData, convertUcs4, true); if (pRequest->code != TSDB_CODE_SUCCESS) { pResultInfo->numOfRows = 0; return NULL; @@ -1593,7 +1575,9 @@ static void syncFetchFn(void* param, TAOS_RES* res, int32_t numOfRows) { } void* doAsyncFetchRows(SRequestObj* pRequest, bool setupOneRowPtr, bool convertUcs4) { - assert(pRequest != NULL); + if (pRequest == NULL) { + return NULL; + } SReqResultInfo* pResultInfo = &pRequest->body.resInfo; if (pResultInfo->pData == NULL || pResultInfo->current >= pResultInfo->numOfRows) { @@ -1657,8 +1641,13 @@ static int32_t doConvertUCS4(SReqResultInfo* pResultInfo, int32_t numOfRows, int char* pStart = pCol->offset[j] + pCol->pData; int32_t len = taosUcs4ToMbs((TdUcs4*)varDataVal(pStart), varDataLen(pStart), varDataVal(p)); - ASSERT(len <= bytes); - ASSERT((p + len) < (pResultInfo->convertBuf[i] + colLength[i])); + if (len > bytes || (p + len) >= (pResultInfo->convertBuf[i] + colLength[i])) { + tscError( + "doConvertUCS4 error, invalid data. len:%d, bytes:%d, (p + len):%p, (pResultInfo->convertBuf[i] + " + "colLength[i]):%p", + len, bytes, (p + len), (pResultInfo->convertBuf[i] + colLength[i])); + return TSDB_CODE_TSC_INTERNAL_ERROR; + } varDataSetLen(p, len); pCol->offset[j] = (p - pResultInfo->convertBuf[i]); @@ -1675,9 +1664,6 @@ static int32_t doConvertUCS4(SReqResultInfo* pResultInfo, int32_t numOfRows, int } int32_t getVersion1BlockMetaSize(const char* p, int32_t numOfCols) { - int32_t cols = *(int32_t*)(p + sizeof(int32_t) * 3); - ASSERT(numOfCols == cols); - return sizeof(int32_t) + sizeof(int32_t) + sizeof(int32_t) * 3 + sizeof(uint64_t) + numOfCols * (sizeof(int8_t) + sizeof(int32_t)); } @@ -1687,6 +1673,12 @@ static int32_t estimateJsonLen(SReqResultInfo* pResultInfo, int32_t numOfCols, i // | version | total length | total rows | total columns | flag seg| block group id | column schema | each column // length | + int32_t cols = *(int32_t*)(p + sizeof(int32_t) * 3); + if (ASSERT(numOfCols == cols)) { + tscError("estimateJsonLen error: numOfCols:%d != cols:%d", numOfCols, cols); + return -1; + } + int32_t len = getVersion1BlockMetaSize(p, numOfCols); int32_t* colLength = (int32_t*)(p + len); len += sizeof(int32_t) * numOfCols; @@ -1720,7 +1712,8 @@ static int32_t estimateJsonLen(SReqResultInfo* pResultInfo, int32_t numOfCols, i } else if (jsonInnerType == TSDB_DATA_TYPE_BOOL) { len += (VARSTR_HEADER_SIZE + 5); } else { - ASSERT(0); + tscError("estimateJsonLen error: invalid type:%d", jsonInnerType); + return -1; } } } else if (IS_VAR_DATA_TYPE(pResultInfo->fields[i].type)) { @@ -1754,12 +1747,21 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo, int32_t numOfCols, int char* p = (char*)pResultInfo->pData; int32_t dataLen = estimateJsonLen(pResultInfo, numOfCols, numOfRows); + if (dataLen <= 0) { + return TSDB_CODE_TSC_INTERNAL_ERROR; + } pResultInfo->convertJson = taosMemoryCalloc(1, dataLen); if (pResultInfo->convertJson == NULL) return TSDB_CODE_OUT_OF_MEMORY; char* p1 = pResultInfo->convertJson; int32_t totalLen = 0; + int32_t cols = *(int32_t*)(p + sizeof(int32_t) * 3); + if (ASSERT(numOfCols == cols)) { + tscError("doConvertJson error: numOfCols:%d != cols:%d", numOfCols, cols); + return TSDB_CODE_TSC_INTERNAL_ERROR; + } + int32_t len = getVersion1BlockMetaSize(p, numOfCols); memcpy(p1, p, len); @@ -1780,8 +1782,10 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo, int32_t numOfCols, int for (int32_t i = 0; i < numOfCols; ++i) { int32_t colLen = htonl(colLength[i]); int32_t colLen1 = htonl(colLength1[i]); - ASSERT(colLen < dataLen); - + if (ASSERT(colLen < dataLen)) { + tscError("doConvertJson error: colLen:%d >= dataLen:%d", colLen, dataLen); + return TSDB_CODE_TSC_INTERNAL_ERROR; + } if (pResultInfo->fields[i].type == TSDB_DATA_TYPE_JSON) { int32_t* offset = (int32_t*)pStart; int32_t* offset1 = (int32_t*)pStart1; @@ -1826,7 +1830,8 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo, int32_t numOfCols, int sprintf(varDataVal(dst), "%s", (*((char*)jsonInnerData) == 1) ? "true" : "false"); varDataSetLen(dst, strlen(varDataVal(dst))); } else { - ASSERT(0); + tscError("doConvertJson error: invalid type:%d", jsonInnerType); + return TSDB_CODE_TSC_INTERNAL_ERROR; } offset1[j] = len; @@ -1864,7 +1869,10 @@ static int32_t doConvertJson(SReqResultInfo* pResultInfo, int32_t numOfCols, int int32_t setResultDataPtr(SReqResultInfo* pResultInfo, TAOS_FIELD* pFields, int32_t numOfCols, int32_t numOfRows, bool convertUcs4) { - assert(numOfCols > 0 && pFields != NULL && pResultInfo != NULL); + if (ASSERT(numOfCols > 0 && pFields != NULL && pResultInfo != NULL)) { + tscError("setResultDataPtr paras error"); + return TSDB_CODE_TSC_INTERNAL_ERROR; + } if (numOfRows == 0) { return TSDB_CODE_SUCCESS; } @@ -1893,7 +1901,11 @@ int32_t setResultDataPtr(SReqResultInfo* pResultInfo, TAOS_FIELD* pFields, int32 int32_t cols = *(int32_t*)p; p += sizeof(int32_t); - ASSERT(rows == numOfRows && cols == numOfCols); + if (ASSERT(rows == numOfRows && cols == numOfCols)) { + tscError("setResultDataPtr paras error:rows;%d numOfRows:%d cols:%d numOfCols:%d", rows, numOfRows, cols, + numOfCols); + return TSDB_CODE_TSC_INTERNAL_ERROR; + } int32_t hasColumnSeg = *(int32_t*)p; p += sizeof(int32_t); @@ -1920,7 +1932,7 @@ int32_t setResultDataPtr(SReqResultInfo* pResultInfo, TAOS_FIELD* pFields, int32 colLength[i] = htonl(colLength[i]); if (colLength[i] >= dataLen) { tscError("invalid colLength %d, dataLen %d", colLength[i], dataLen); - ASSERT(0); + return TSDB_CODE_TSC_INTERNAL_ERROR; } if (IS_VAR_DATA_TYPE(pResultInfo->fields[i].type)) { @@ -1958,7 +1970,11 @@ char* getDbOfConnection(STscObj* pObj) { } void setConnectionDB(STscObj* pTscObj, const char* db) { - assert(db != NULL && pTscObj != NULL); + if (db == NULL || pTscObj == NULL) { + tscError("setConnectionDB para is NULL"); + return; + } + taosThreadMutexLock(&pTscObj->mutex); tstrncpy(pTscObj->db, db, tListLen(pTscObj->db)); taosThreadMutexUnlock(&pTscObj->mutex); @@ -1976,7 +1992,10 @@ void resetConnectDB(STscObj* pTscObj) { int32_t setQueryResultFromRsp(SReqResultInfo* pResultInfo, const SRetrieveTableRsp* pRsp, bool convertUcs4, bool freeAfterUse) { - assert(pResultInfo != NULL && pRsp != NULL); + if (pResultInfo == NULL || pRsp == NULL) { + tscError("setQueryResultFromRsp paras is null"); + return TSDB_CODE_TSC_INTERNAL_ERROR; + } if (freeAfterUse) taosMemoryFreeClear(pResultInfo->pRspMsg); @@ -2013,6 +2032,12 @@ TSDB_SERVER_STATUS taos_check_server_status(const char* fqdn, int port, char* de rpcInit.compressSize = tsCompressMsgSize; rpcInit.user = "_dnd"; + int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3); + connLimitNum = TMAX(connLimitNum, 10); + connLimitNum = TMIN(connLimitNum, 500); + rpcInit.connLimitNum = connLimitNum; + rpcInit.timeToGetConn = tsTimeToGetAvailableConn; + clientRpc = rpcOpen(&rpcInit); if (clientRpc == NULL) { tscError("failed to init server status client"); @@ -2327,6 +2352,8 @@ TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly) { return NULL; } + tscDebug("taos_query start with sql:%s", sql); + SSyncQueryParam* param = taosMemoryCalloc(1, sizeof(SSyncQueryParam)); tsem_init(¶m->sem, 0, 0); @@ -2341,6 +2368,8 @@ TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly) { taosMemoryFree(param); } + tscDebug("taos_query end with sql:%s", sql); + return pRequest; } diff --git a/source/client/src/clientJniConnector.c b/source/client/src/clientJniConnector.c index 859d4ec80ff6e954259415dabaf1761eb3e7129e..b61335475125955b801b5b697992e79c98010431 100644 --- a/source/client/src/clientJniConnector.c +++ b/source/client/src/clientJniConnector.c @@ -55,7 +55,8 @@ jclass g_tmqClass; jmethodID g_createConsumerErrorCallback; jmethodID g_topicListCallback; -jclass g_consumerClass; +jclass g_consumerClass; +// deprecated jmethodID g_commitCallback; void jniGetGlobalMethod(JNIEnv *env) { @@ -330,13 +331,58 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryImp( int32_t code = taos_errno(tres); if (code != TSDB_CODE_SUCCESS) { - jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, tscon, tstrerror(code), taos_errstr(tres)); + jniError("jobj:%p, conn:%p, code:0x%x, msg:%s", jobj, tscon, code, taos_errstr(tres)); } else { if (taos_is_update_query(tres)) { int32_t affectRows = taos_affected_rows(tres); - jniDebug("jobj:%p, conn:%p, code:%s, affect rows:%d", jobj, tscon, tstrerror(code), affectRows); + jniDebug("jobj:%p, conn:%p, code:0x%x, affect rows:%d", jobj, tscon, code, affectRows); } else { - jniDebug("jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); + jniDebug("jobj:%p, conn:%p, code:0x%x", jobj, tscon, code); + } + } + + taosMemoryFreeClear(str); + return (jlong)tres; +} + +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeQueryWithReqId(JNIEnv *env, jobject jobj, + jbyteArray jsql, jlong con, + jlong reqId) { + TAOS *tscon = (TAOS *)con; + if (tscon == NULL) { + jniError("jobj:%p, connection already closed", jobj); + return JNI_CONNECTION_NULL; + } + + if (jsql == NULL) { + jniError("jobj:%p, conn:%p, empty sql string", jobj, tscon); + return JNI_SQL_NULL; + } + + jsize len = (*env)->GetArrayLength(env, jsql); + + char *str = (char *)taosMemoryCalloc(1, sizeof(char) * (len + 1)); + if (str == NULL) { + jniError("jobj:%p, conn:%p, alloc memory failed", jobj, tscon); + return JNI_OUT_OF_MEMORY; + } + + (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str); + if ((*env)->ExceptionCheck(env)) { + // todo handle error + } + + TAOS_RES *tres = taos_query_with_reqid(tscon, str, reqId); + int32_t code = taos_errno(tres); + + if (code != TSDB_CODE_SUCCESS) { + jniError("jobj:%p, conn:%p, code:0x%x, msg:%s", jobj, tscon, code, taos_errstr(tres)); + } else { + if (taos_is_update_query(tres)) { + int32_t affectRows = taos_affected_rows(tres); + jniDebug("jobj:%p, conn:%p, code:0x%x, affect rows:%d", jobj, tscon, code, affectRows); + } else { + jniDebug("jobj:%p, conn:%p, code:0x%x", jobj, tscon, code); } } @@ -488,7 +534,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn numOfFields); return JNI_FETCH_END; } else { - jniDebug("jobj:%p, conn:%p, interrupted query. fetch row error code: %d, msg:%s", jobj, tscon, code, + jniDebug("jobj:%p, conn:%p, interrupted query. fetch row error code: 0x%x, msg:%s", jobj, tscon, code, taos_errstr(result)); return JNI_RESULT_SET_NULL; } @@ -574,17 +620,21 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchBlockImp(JNI TAOS_RES *tres = (TAOS_RES *)res; int32_t numOfFields = taos_num_fields(tres); - assert(numOfFields > 0); + if (numOfFields <= 0) { + jniError("jobj:%p, conn:%p, query interrupted. taos_num_fields error code: 0x%x, msg:%s", jobj, tscon, + taos_errno(tres), taos_errstr(tres)); + return JNI_RESULT_SET_NULL; + } - void *data; - int32_t numOfRows; + void *data = NULL; + int32_t numOfRows = 0; int error_code = taos_fetch_raw_block(tres, &numOfRows, &data); if (numOfRows == 0) { if (error_code == JNI_SUCCESS) { jniDebug("jobj:%p, conn:%p, resultset:%p, no data to retrieve", jobj, tscon, (void *)res); return JNI_FETCH_END; } else { - jniError("jobj:%p, conn:%p, query interrupted. fetch block error code:%d, msg:%s", jobj, tscon, error_code, + jniError("jobj:%p, conn:%p, query interrupted. fetch block error code: 0x%x, msg:%s", jobj, tscon, error_code, taos_errstr(tres)); return JNI_RESULT_SET_NULL; } @@ -634,7 +684,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_validateCreateTab } int code = taos_validate_sql(tscon, str); - jniDebug("jobj:%p, conn:%p, code is %d", jobj, tscon, code); + jniDebug("jobj:%p, conn:%p, code: 0x%x", jobj, tscon, code); taosMemoryFreeClear(str); return code; @@ -699,7 +749,45 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtImp(J int32_t code = taos_stmt_prepare(pStmt, str, len); taosMemoryFreeClear(str); if (code != TSDB_CODE_SUCCESS) { - jniError("prepareStmt jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); + jniError("prepareStmt jobj:%p, conn:%p, code: 0x%x", jobj, tscon, code); + return JNI_TDENGINE_ERROR; + } + + return (jlong)pStmt; +} + +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_prepareStmtWithReqId(JNIEnv *env, jobject jobj, + jbyteArray jsql, jlong con, + jlong reqId) { + TAOS *tscon = (TAOS *)con; + if (tscon == NULL) { + jniError("jobj:%p, connection already closed", jobj); + return JNI_CONNECTION_NULL; + } + + if (jsql == NULL) { + jniError("jobj:%p, conn:%p, empty sql string", jobj, tscon); + return JNI_SQL_NULL; + } + + jsize len = (*env)->GetArrayLength(env, jsql); + + char *str = (char *)taosMemoryCalloc(1, sizeof(char) * (len + 1)); + if (str == NULL) { + jniError("jobj:%p, conn:%p, alloc memory failed", jobj, tscon); + return JNI_OUT_OF_MEMORY; + } + + (*env)->GetByteArrayRegion(env, jsql, 0, len, (jbyte *)str); + if ((*env)->ExceptionCheck(env)) { + // todo handle error + } + + TAOS_STMT *pStmt = taos_stmt_init_with_reqid(tscon, reqId); + int32_t code = taos_stmt_prepare(pStmt, str, len); + taosMemoryFreeClear(str); + if (code != TSDB_CODE_SUCCESS) { + jniError("prepareStmtWithReqId jobj:%p, conn:%p, code: 0x%x", jobj, tscon, code); return JNI_TDENGINE_ERROR; } @@ -727,8 +815,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setBindTableNameI if (code != TSDB_CODE_SUCCESS) { (*env)->ReleaseStringUTFChars(env, jname, name); - jniError("bindTableName jobj:%p, conn:%p, code:%s", jobj, tsconn, tstrerror(code)); - return JNI_TDENGINE_ERROR; + jniError("bindTableName jobj:%p, conn:%p, code: 0x%x", jobj, tsconn, code); + return code; } jniDebug("jobj:%p, conn:%p, set stmt bind table name:%s", jobj, tsconn, name); @@ -802,8 +890,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setTableNameTagsI (*env)->ReleaseStringUTFChars(env, tableName, name); if (code != TSDB_CODE_SUCCESS) { - jniError("tableNameTags jobj:%p, conn:%p, code:%s", jobj, tsconn, tstrerror(code)); - return JNI_TDENGINE_ERROR; + jniError("tableNameTags jobj:%p, conn:%p, code: 0x%x", jobj, tsconn, code); + return code; } return JNI_SUCCESS; } @@ -868,8 +956,8 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_bindColDataImp( taosMemoryFreeClear(b); if (code != TSDB_CODE_SUCCESS) { - jniError("bindColData jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); - return JNI_TDENGINE_ERROR; + jniError("bindColData jobj:%p, conn:%p, code: 0x%x", jobj, tscon, code); + return code; } return JNI_SUCCESS; @@ -891,8 +979,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_addBatchImp(JNIEn int32_t code = taos_stmt_add_batch(pStmt); if (code != TSDB_CODE_SUCCESS) { - jniError("add batch jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); - return JNI_TDENGINE_ERROR; + jniError("add batch jobj:%p, conn:%p, code: 0x%x", jobj, tscon, code); + return code; } jniDebug("jobj:%p, conn:%p, stmt closed", jobj, tscon); @@ -915,8 +1003,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_executeBatchImp(J int32_t code = taos_stmt_execute(pStmt); if (code != TSDB_CODE_SUCCESS) { - jniError("excute batch jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); - return JNI_TDENGINE_ERROR; + jniError("excute batch jobj:%p, conn:%p, code: 0x%x", jobj, tscon, code); + return code; } jniDebug("jobj:%p, conn:%p, batch execute", jobj, tscon); @@ -939,8 +1027,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_closeStmt(JNIEnv int32_t code = taos_stmt_close(pStmt); if (code != TSDB_CODE_SUCCESS) { - jniError("close stmt jobj:%p, conn:%p, code:%s", jobj, tscon, tstrerror(code)); - return JNI_TDENGINE_ERROR; + jniError("close stmt jobj:%p, conn:%p, code: 0x%x", jobj, tscon, code); + return code; } jniDebug("jobj:%p, conn:%p, stmt closed", jobj, tscon); @@ -1001,12 +1089,9 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_insertLinesImp(JN TAOS_RES *tres = schemalessInsert(env, jobj, lines, taos, protocol, precision); - if (tres == NULL) { - return JNI_OUT_OF_MEMORY; - } int code = taos_errno(tres); if (code != TSDB_CODE_SUCCESS) { - jniError("jobj:%p, conn:%p, code:%s, msg:%s", jobj, taos, tstrerror(code), taos_errstr(tres)); + jniError("jobj:%p, conn:%p, code: 0x%x, msg:%s", jobj, taos, code, taos_errstr(tres)); taos_free_result(tres); return JNI_TDENGINE_ERROR; } @@ -1025,12 +1110,251 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsert } TAOS_RES *tres = schemalessInsert(env, jobj, lines, taos, protocol, precision); - if (tres == NULL) { + + return (jlong)tres; +} + +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertWithReqId( + JNIEnv *env, jobject jobj, jlong conn, jobjectArray lines, jint protocol, jint precision, jlong reqId) { + 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 = taosMemoryCalloc(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); + } + + TAOS_RES *tres = taos_schemaless_insert_with_reqid(taos, c_lines, numLines, protocol, precision, reqId); + + for (int i = 0; i < numLines; ++i) { + jstring line = (jstring)((*env)->GetObjectArrayElement(env, lines, i)); + (*env)->ReleaseStringUTFChars(env, line, c_lines[i]); + } + + taosMemoryFreeClear(c_lines); + + return (jlong)tres; +} + +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertWithTtl(JNIEnv *env, jobject jobj, + jlong conn, jobjectArray lines, + jint protocol, jint precision, + jint ttl) { + 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 = taosMemoryCalloc(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); + } + + TAOS_RES *tres = taos_schemaless_insert_ttl(taos, c_lines, numLines, protocol, precision, ttl); + + for (int i = 0; i < numLines; ++i) { + jstring line = (jstring)((*env)->GetObjectArrayElement(env, lines, i)); + (*env)->ReleaseStringUTFChars(env, line, c_lines[i]); + } + + taosMemoryFreeClear(c_lines); + return (jlong)tres; } +JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertWithTtlAndReqId( + JNIEnv *env, jobject jobj, jlong conn, jobjectArray lines, jint protocol, jint precision, jint ttl, jlong reqId) { + 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 = taosMemoryCalloc(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); + } + + TAOS_RES *tres = taos_schemaless_insert_ttl_with_reqid(taos, c_lines, numLines, protocol, precision, ttl, reqId); + + for (int i = 0; i < numLines; ++i) { + jstring line = (jstring)((*env)->GetObjectArrayElement(env, lines, i)); + (*env)->ReleaseStringUTFChars(env, line, c_lines[i]); + } + + taosMemoryFreeClear(c_lines); + + return (jlong)tres; +} + +JNIEXPORT jobject createSchemalessResp(JNIEnv *env, int totalRows, int code, const char *msg) { + // find class + jclass schemaless_clazz = (*env)->FindClass(env, "com/taosdata/jdbc/SchemalessResp"); + // find methods + jmethodID init_method = (*env)->GetMethodID(env, schemaless_clazz, "", "()V"); + jmethodID setCode_method = (*env)->GetMethodID(env, schemaless_clazz, "setCode", "(I)V"); + jmethodID setMsg_method = (*env)->GetMethodID(env, schemaless_clazz, "setMsg", "(Ljava/lang/String;)V"); + jmethodID setTotalRows_method = (*env)->GetMethodID(env, schemaless_clazz, "setTotalRows", "(I)V"); + // new schemaless + jobject schemaless_obj = (*env)->NewObject(env, schemaless_clazz, init_method); + // set code + (*env)->CallVoidMethod(env, schemaless_obj, setCode_method, code); + // set totalRows + (*env)->CallVoidMethod(env, schemaless_obj, setTotalRows_method, totalRows); + // set message + jstring message = (*env)->NewStringUTF(env, msg); + (*env)->CallVoidMethod(env, schemaless_obj, setMsg_method, message); + + return schemaless_obj; +} + +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertRaw(JNIEnv *env, jobject jobj, + jlong conn, jstring data, + jint protocol, jint precision) { + TAOS *taos = (TAOS *)conn; + if (taos == NULL) { + jniError("jobj:%p, connection already closed", jobj); + char *msg = "JNI connection is NULL"; + return createSchemalessResp(env, 0, JNI_CONNECTION_NULL, msg); + } + + char *line = (char *)(*env)->GetStringUTFChars(env, data, NULL); + jint len = (*env)->GetStringUTFLength(env, data); + int32_t totalRows; + TAOS_RES *tres = taos_schemaless_insert_raw(taos, line, len, &totalRows, protocol, precision); + + (*env)->ReleaseStringUTFChars(env, data, line); + + // if (tres == NULL) { + // jniError("jobj:%p, schemaless raw insert failed", jobj); + // char *msg = "JNI schemaless raw insert return null"; + // return createSchemalessResp(env, 0, JNI_TDENGINE_ERROR, msg); + // } + + int code = taos_errno(tres); + if (code != TSDB_CODE_SUCCESS) { + jniError("jobj:%p, conn:%p, code: 0x%x, msg:%s", jobj, taos, code, taos_errstr(tres)); + jobject jobject = createSchemalessResp(env, 0, code, taos_errstr(tres)); + taos_free_result(tres); + return jobject; + } + taos_free_result(tres); + + return createSchemalessResp(env, totalRows, JNI_SUCCESS, NULL); +} + +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertRawWithReqId( + JNIEnv *env, jobject jobj, jlong conn, jstring data, jint protocol, jint precision, jlong reqId) { + TAOS *taos = (TAOS *)conn; + if (taos == NULL) { + jniError("jobj:%p, connection already closed", jobj); + char *msg = "JNI connection is NULL"; + return createSchemalessResp(env, 0, JNI_CONNECTION_NULL, msg); + } + + char *line = (char *)(*env)->GetStringUTFChars(env, data, NULL); + jint len = (*env)->GetStringUTFLength(env, data); + int32_t totalRows; + TAOS_RES *tres = taos_schemaless_insert_raw_with_reqid(taos, line, len, &totalRows, protocol, precision, reqId); + + (*env)->ReleaseStringUTFChars(env, data, line); + + int code = taos_errno(tres); + if (code != TSDB_CODE_SUCCESS) { + jniError("jobj:%p, conn:%p, code: 0x%x, msg:%s", jobj, taos, code, taos_errstr(tres)); + jobject jobject = createSchemalessResp(env, 0, code, taos_errstr(tres)); + taos_free_result(tres); + return jobject; + } + taos_free_result(tres); + + return createSchemalessResp(env, totalRows, JNI_SUCCESS, NULL); +} + +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertRawWithTtl(JNIEnv *env, jobject jobj, + jlong conn, jstring data, + jint protocol, + jint precision, jint ttl) { + TAOS *taos = (TAOS *)conn; + if (taos == NULL) { + jniError("jobj:%p, connection already closed", jobj); + char *msg = "JNI connection is NULL"; + return createSchemalessResp(env, 0, JNI_CONNECTION_NULL, msg); + } + + char *line = (char *)(*env)->GetStringUTFChars(env, data, NULL); + jint len = (*env)->GetStringUTFLength(env, data); + int32_t totalRows; + TAOS_RES *tres = taos_schemaless_insert_raw_ttl(taos, line, len, &totalRows, protocol, precision, ttl); + + (*env)->ReleaseStringUTFChars(env, data, line); + + int code = taos_errno(tres); + if (code != TSDB_CODE_SUCCESS) { + jniError("jobj:%p, conn:%p, code: 0x%x, msg:%s", jobj, taos, code, taos_errstr(tres)); + jobject jobject = createSchemalessResp(env, 0, code, taos_errstr(tres)); + taos_free_result(tres); + return jobject; + } + taos_free_result(tres); + + return createSchemalessResp(env, totalRows, JNI_SUCCESS, NULL); +} + +JNIEXPORT jobject JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertRawWithTtlAndReqId( + JNIEnv *env, jobject jobj, jlong conn, jstring data, jint protocol, jint precision, jint ttl, jlong reqId) { + TAOS *taos = (TAOS *)conn; + if (taos == NULL) { + jniError("jobj:%p, connection already closed", jobj); + char *msg = "JNI connection is NULL"; + return createSchemalessResp(env, 0, JNI_CONNECTION_NULL, msg); + } + + char *line = (char *)(*env)->GetStringUTFChars(env, data, NULL); + jint len = (*env)->GetStringUTFLength(env, data); + int32_t totalRows; + TAOS_RES *tres = + taos_schemaless_insert_raw_ttl_with_reqid(taos, line, len, &totalRows, protocol, precision, ttl, reqId); + + (*env)->ReleaseStringUTFChars(env, data, line); + + int code = taos_errno(tres); + if (code != TSDB_CODE_SUCCESS) { + jniError("jobj:%p, conn:%p, code: 0x%x, msg:%s", jobj, taos, code, taos_errstr(tres)); + jobject jobject = createSchemalessResp(env, 0, code, taos_errstr(tres)); + taos_free_result(tres); + return jobject; + } + taos_free_result(tres); + + return createSchemalessResp(env, totalRows, JNI_SUCCESS, NULL); +} + // TABLE_VG_ID_FID_CACHE cache resp object for getTableVgID typedef struct TABLE_VG_ID_FIELD_CACHE { int cached; diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 2042ff141cbe98f2147cea925ce4913e0935793b..fd70598efb32afa332ca604a645b786de35ca962 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -108,7 +108,7 @@ TAOS *taos_connect(const char *ip, const char *user, const char *pass, const cha if (pass == NULL) { pass = TSDB_DEFAULT_PASS; } - + STscObj *pObj = taos_connect_internal(ip, user, pass, NULL, db, port, CONN_TYPE__QUERY); if (pObj) { int64_t *rid = taosMemoryCalloc(1, sizeof(int64_t)); @@ -191,7 +191,7 @@ void taos_free_result(TAOS_RES *res) { taosArrayDestroyP(pRsp->rsp.blockData, taosMemoryFree); taosArrayDestroy(pRsp->rsp.blockDataLen); taosArrayDestroyP(pRsp->rsp.blockTbName, taosMemoryFree); - taosArrayDestroyP(pRsp->rsp.blockSchema, (FDelete)tDeleteSSchemaWrapper); + taosArrayDestroyP(pRsp->rsp.blockSchema, (FDelete)tDeleteSchemaWrapper); // taosx taosArrayDestroy(pRsp->rsp.createTableLen); taosArrayDestroyP(pRsp->rsp.createTableReq, taosMemoryFree); @@ -204,7 +204,7 @@ void taos_free_result(TAOS_RES *res) { taosArrayDestroyP(pRsp->rsp.blockData, taosMemoryFree); taosArrayDestroy(pRsp->rsp.blockDataLen); taosArrayDestroyP(pRsp->rsp.blockTbName, taosMemoryFree); - taosArrayDestroyP(pRsp->rsp.blockSchema, (FDelete)tDeleteSSchemaWrapper); + taosArrayDestroyP(pRsp->rsp.blockSchema, (FDelete)tDeleteSchemaWrapper); pRsp->resInfo.pRspMsg = NULL; doFreeReqResultInfo(&pRsp->resInfo); taosMemoryFree(pRsp); @@ -281,7 +281,10 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) { return pResultInfo->row; } else { pResultInfo = tmqGetNextResInfo(res, true); - if (pResultInfo == NULL) return NULL; + if (pResultInfo == NULL) { + return NULL; + } + doSetOneRowPtr(pResultInfo); pResultInfo->current += 1; return pResultInfo->row; @@ -293,7 +296,6 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) { tscError("invalid result passed to taos_fetch_row"); return NULL; } - return NULL; } int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) { @@ -357,9 +359,13 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) case TSDB_DATA_TYPE_NCHAR: { int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE); if (fields[i].type == TSDB_DATA_TYPE_BINARY) { - assert(charLen <= fields[i].bytes && charLen >= 0); + if (ASSERT(charLen <= fields[i].bytes && charLen >= 0)) { + tscError("taos_print_row error binary. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes); + } } else { - assert(charLen <= fields[i].bytes * TSDB_NCHAR_SIZE && charLen >= 0); + if (ASSERT(charLen <= fields[i].bytes * TSDB_NCHAR_SIZE && charLen >= 0)) { + tscError("taos_print_row error. charLen:%d, fields[i].bytes:%d", charLen, fields[i].bytes); + } } memcpy(str + len, row[i], charLen); @@ -432,6 +438,22 @@ const char *taos_data_type(int type) { return "TSDB_DATA_TYPE_NCHAR"; case TSDB_DATA_TYPE_JSON: return "TSDB_DATA_TYPE_JSON"; + case TSDB_DATA_TYPE_UTINYINT: + return "TSDB_DATA_TYPE_UTINYINT"; + case TSDB_DATA_TYPE_USMALLINT: + return "TSDB_DATA_TYPE_USMALLINT"; + case TSDB_DATA_TYPE_UINT: + return "TSDB_DATA_TYPE_UINT"; + case TSDB_DATA_TYPE_UBIGINT: + return "TSDB_DATA_TYPE_UBIGINT"; + case TSDB_DATA_TYPE_VARBINARY: + return "TSDB_DATA_TYPE_VARBINARY"; + case TSDB_DATA_TYPE_DECIMAL: + return "TSDB_DATA_TYPE_DECIMAL"; + case TSDB_DATA_TYPE_BLOB: + return "TSDB_DATA_TYPE_BLOB"; + case TSDB_DATA_TYPE_MEDIUMBLOB: + return "TSDB_DATA_TYPE_MEDIUMBLOB"; default: return "UNKNOWN"; } @@ -578,12 +600,15 @@ int taos_fetch_block_s(TAOS_RES *res, int *numOfRows, TAOS_ROW *rows) { (*numOfRows) = pResultInfo->numOfRows; return 0; } else { - ASSERT(0); + tscError("taos_fetch_block_s invalid res type"); return -1; } } int taos_fetch_raw_block(TAOS_RES *res, int *numOfRows, void **pData) { + *numOfRows = 0; + *pData = NULL; + if (res == NULL || TD_RES_TMQ_META(res)) { return 0; } @@ -671,6 +696,32 @@ const char *taos_get_server_info(TAOS *taos) { return pTscObj->sDetailVer; } +int taos_get_current_db(TAOS *taos, char *database, int len, int *required) { + STscObj *pTscObj = acquireTscObj(*(int64_t *)taos); + if (pTscObj == NULL) { + terrno = TSDB_CODE_TSC_DISCONNECTED; + return -1; + } + + int code = TSDB_CODE_SUCCESS; + taosThreadMutexLock(&pTscObj->mutex); + if (database == NULL || len <= 0) { + if (required != NULL) *required = strlen(pTscObj->db) + 1; + terrno = TSDB_CODE_INVALID_PARA; + code = -1; + } else if (len < strlen(pTscObj->db) + 1) { + tstrncpy(database, pTscObj->db, len); + if (required) *required = strlen(pTscObj->db) + 1; + terrno = TSDB_CODE_INVALID_PARA; + code = -1; + } else { + strcpy(database, pTscObj->db); + code = 0; + } + taosThreadMutexUnlock(&pTscObj->mutex); + return code; +} + static void destoryTablesReq(void *p) { STablesReq *pRes = (STablesReq *)p; taosArrayDestroy(pRes->pTables); @@ -690,6 +741,7 @@ static void destoryCatalogReq(SCatalogReq *pCatalogReq) { taosArrayDestroy(pCatalogReq->pUser); taosArrayDestroy(pCatalogReq->pTableIndex); taosArrayDestroy(pCatalogReq->pTableCfg); + taosArrayDestroy(pCatalogReq->pTableTag); taosMemoryFree(pCatalogReq); } @@ -707,7 +759,8 @@ static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t SRequestObj *pRequest = pWrapper->pRequest; SQuery *pQuery = pRequest->pQuery; - pRequest->metric.ctgEnd = taosGetTimestampUs(); + int64_t analyseStart = taosGetTimestampUs(); + pRequest->metric.ctgCostUs = analyseStart - pRequest->metric.ctgStart; qDebug("0x%" PRIx64 " start to semantic analysis, reqId:0x%" PRIx64, pRequest->self, pRequest->requestId); if (code == TSDB_CODE_SUCCESS) { @@ -718,7 +771,7 @@ static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t } } - pRequest->metric.semanticEnd = taosGetTimestampUs(); + pRequest->metric.analyseCostUs = taosGetTimestampUs() - analyseStart; if (code == TSDB_CODE_SUCCESS) { if (pQuery->haveResultSet) { @@ -730,10 +783,6 @@ static void doAsyncQueryFromAnalyse(SMetaData *pResultMeta, void *param, int32_t TSWAP(pRequest->tableList, (pQuery)->pTableList); TSWAP(pRequest->targetTableList, (pQuery)->pTargetTableList); - double el = (pRequest->metric.semanticEnd - pRequest->metric.ctgEnd) / 1000.0; - tscDebug("0x%" PRIx64 " analysis semantics completed, start async query, elapsed time:%.2f ms, reqId:0x%" PRIx64, - pRequest->self, el, pRequest->requestId); - launchAsyncQuery(pRequest, pQuery, pResultMeta, pWrapper); } else { destorySqlCallbackWrapper(pWrapper); @@ -798,12 +847,12 @@ static void doAsyncQueryFromParse(SMetaData *pResultMeta, void *param, int32_t c SRequestObj *pRequest = pWrapper->pRequest; SQuery *pQuery = pRequest->pQuery; - pRequest->metric.ctgEnd = taosGetTimestampUs(); + pRequest->metric.ctgCostUs += taosGetTimestampUs() - pRequest->metric.ctgStart; qDebug("0x%" PRIx64 " start to continue parse, reqId:0x%" PRIx64 ", code:%s", pRequest->self, pRequest->requestId, tstrerror(code)); if (code == TSDB_CODE_SUCCESS) { - //pWrapper->pCatalogReq->forceUpdate = false; + // pWrapper->pCatalogReq->forceUpdate = false; code = qContinueParseSql(pWrapper->pParseCtx, pWrapper->pCatalogReq, pResultMeta, pQuery); } @@ -832,14 +881,16 @@ void continueInsertFromCsv(SSqlCallbackWrapper *pWrapper, SRequestObj *pRequest) tstrerror(code), pWrapper->pRequest->requestId); destorySqlCallbackWrapper(pWrapper); terrno = code; - pWrapper->pRequest->code = code; - pWrapper->pRequest->body.queryFp(pWrapper->pRequest->body.param, pWrapper->pRequest, code); + pRequest->code = code; + pRequest->body.queryFp(pRequest->body.param, pRequest, code); } } void taos_query_a(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param) { int64_t connId = *(int64_t *)taos; + tscDebug("taos_query_a start with sql:%s", sql); taosAsyncQueryImpl(connId, sql, fp, param, false); + tscDebug("taos_query_a end with sql:%s", sql); } void taos_query_a_with_reqid(TAOS *taos, const char *sql, __taos_async_fn_t fp, void *param, int64_t reqid) { @@ -867,7 +918,6 @@ int32_t createParseContext(const SRequestObj *pRequest, SParseContext **pCxt) { .pTransporter = pTscObj->pAppInfo->pTransporter, .pStmtCb = NULL, .pUser = pTscObj->user, - .schemalessType = pTscObj->schemalessType, .isSuperUser = (0 == strcmp(pTscObj->user, TSDB_DEFAULT_USER)), .enableSysInfo = pTscObj->sysInfo, .async = true, @@ -910,7 +960,7 @@ void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) { } if (TSDB_CODE_SUCCESS == code) { - pRequest->metric.syntaxStart = taosGetTimestampUs(); + int64_t syntaxStart = taosGetTimestampUs(); pWrapper->pCatalogReq = taosMemoryCalloc(1, sizeof(SCatalogReq)); if (pWrapper->pCatalogReq == NULL) { @@ -921,22 +971,15 @@ void doAsyncQuery(SRequestObj *pRequest, bool updateMetaForce) { code = qParseSqlSyntax(pWrapper->pParseCtx, &pRequest->pQuery, pWrapper->pCatalogReq); } - pRequest->metric.syntaxEnd = taosGetTimestampUs(); - } - - if (TSDB_CODE_SUCCESS == code && !updateMetaForce) { - SAppClusterSummary *pActivity = &pTscObj->pAppInfo->summary; - if (QUERY_NODE_INSERT_STMT == nodeType(pRequest->pQuery->pRoot)) { - atomic_add_fetch_64((int64_t *)&pActivity->numOfInsertsReq, 1); - } else if (QUERY_NODE_SELECT_STMT == nodeType(pRequest->pQuery->pRoot)) { - atomic_add_fetch_64((int64_t *)&pActivity->numOfQueryReq, 1); - } + pRequest->metric.parseCostUs += taosGetTimestampUs() - syntaxStart; } if (TSDB_CODE_SUCCESS == code) { pRequest->stmtType = pRequest->pQuery->pRoot->type; - phaseAsyncQuery(pWrapper); - } else { + code = phaseAsyncQuery(pWrapper); + } + + if (TSDB_CODE_SUCCESS != code) { tscError("0x%" PRIx64 " error happens, code:%d - %s, reqId:0x%" PRIx64, pRequest->self, code, tstrerror(code), pRequest->requestId); destorySqlCallbackWrapper(pWrapper); @@ -961,7 +1004,6 @@ static void fetchCallback(void *pResult, void *param, int32_t code) { SRequestObj *pRequest = (SRequestObj *)param; SReqResultInfo *pResultInfo = &pRequest->body.resInfo; - pRequest->metric.resultReady = taosGetTimestampUs(); tscDebug("0x%" PRIx64 " enter scheduler fetch cb, code:%d - %s, reqId:0x%" PRIx64, pRequest->self, code, tstrerror(code), pRequest->requestId); @@ -983,7 +1025,7 @@ static void fetchCallback(void *pResult, void *param, int32_t code) { } pRequest->code = - setQueryResultFromRsp(pResultInfo, (SRetrieveTableRsp *)pResultInfo->pData, pResultInfo->convertUcs4, true); + setQueryResultFromRsp(pResultInfo, (const SRetrieveTableRsp *)pResultInfo->pData, pResultInfo->convertUcs4, true); if (pRequest->code != TSDB_CODE_SUCCESS) { pResultInfo->numOfRows = 0; pRequest->code = code; @@ -1003,8 +1045,14 @@ static void fetchCallback(void *pResult, void *param, int32_t code) { } void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { - ASSERT(res != NULL && fp != NULL); - ASSERT(TD_RES_QUERY(res)); + if (ASSERT(res != NULL && fp != NULL)) { + tscError("taos_fetch_rows_a invalid paras"); + return; + } + if (ASSERT(TD_RES_QUERY(res))) { + tscError("taos_fetch_rows_a res is NULL"); + return; + } SRequestObj *pRequest = res; pRequest->body.fetchFp = fp; @@ -1047,9 +1095,14 @@ void taos_fetch_rows_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { } void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { - ASSERT(res != NULL && fp != NULL); - ASSERT(TD_RES_QUERY(res)); - + if (ASSERT(res != NULL && fp != NULL)) { + tscError("taos_fetch_rows_a invalid paras"); + return; + } + if (ASSERT(TD_RES_QUERY(res))) { + tscError("taos_fetch_rows_a res is NULL"); + return; + } SRequestObj *pRequest = res; SReqResultInfo *pResultInfo = &pRequest->body.resInfo; @@ -1061,8 +1114,14 @@ void taos_fetch_raw_block_a(TAOS_RES *res, __taos_async_fn_t fp, void *param) { } const void *taos_get_raw_block(TAOS_RES *res) { - ASSERT(res != NULL); - ASSERT(TD_RES_QUERY(res)); + if (ASSERT(res != NULL)) { + tscError("taos_fetch_rows_a invalid paras"); + return NULL; + } + if (ASSERT(TD_RES_QUERY(res))) { + tscError("taos_fetch_rows_a res is NULL"); + return NULL; + } SRequestObj *pRequest = res; return pRequest->body.resInfo.pData; @@ -1217,7 +1276,6 @@ _return: return code; } - int taos_load_table_info(TAOS *taos, const char *tableNameList) { if (NULL == taos) { terrno = TSDB_CODE_TSC_DISCONNECTED; @@ -1382,8 +1440,7 @@ int taos_stmt_get_col_fields(TAOS_STMT *stmt, int *fieldNum, TAOS_FIELD_E **fiel } // let stmt to reclaim TAOS_FIELD_E that was allocated by `taos_stmt_get_tag_fields`/`taos_stmt_get_col_fields` -void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields) -{ +void taos_stmt_reclaim_fields(TAOS_STMT *stmt, TAOS_FIELD_E *fields) { (void)stmt; if (!fields) return; taosMemoryFree(fields); diff --git a/source/client/src/clientMsgHandler.c b/source/client/src/clientMsgHandler.c index f414c7e92f8e208a5559dd8bdcf03642b4b7f7ed..032517cafc5d7d7726d387d6c9d9636474ce7742 100644 --- a/source/client/src/clientMsgHandler.c +++ b/source/client/src/clientMsgHandler.c @@ -18,10 +18,12 @@ #include "clientLog.h" #include "os.h" #include "query.h" +#include "systable.h" +#include "tdatablock.h" #include "tdef.h" +#include "tglobal.h" #include "tname.h" -#include "tdatablock.h" -#include "systable.h" +#include "tversion.h" static void setErrno(SRequestObj* pRequest, int32_t code) { pRequest->code = code; @@ -47,11 +49,11 @@ int32_t genericRspCallback(void* param, SDataBuf* pMsg, int32_t code) { } int32_t processConnectRsp(void* param, SDataBuf* pMsg, int32_t code) { - SRequestObj *pRequest = acquireRequest(*(int64_t*)param); + SRequestObj* pRequest = acquireRequest(*(int64_t*)param); if (NULL == pRequest) { goto End; } - + if (code != TSDB_CODE_SUCCESS) { setErrno(pRequest, code); tsem_post(&pRequest->body.rspSem); @@ -65,7 +67,7 @@ int32_t processConnectRsp(void* param, SDataBuf* pMsg, int32_t code) { tsem_post(&pRequest->body.rspSem); goto End; } - + SConnectRsp connectRsp = {0}; if (tDeserializeSConnectRsp(pMsg->pData, pMsg->len, &connectRsp) != 0) { code = TSDB_CODE_TSC_INVALID_VERSION; @@ -74,6 +76,12 @@ int32_t processConnectRsp(void* param, SDataBuf* pMsg, int32_t code) { goto End; } + if ((code = taosCheckVersionCompatibleFromStr(version, connectRsp.sVer, 3)) != 0) { + setErrno(pRequest, code); + tsem_post(&pRequest->body.rspSem); + goto End; + } + int32_t now = taosGetTimestampSec(); int32_t delta = abs(now - connectRsp.svrTimestamp); if (delta > timestampDeltaLimit) { @@ -84,7 +92,6 @@ int32_t processConnectRsp(void* param, SDataBuf* pMsg, int32_t code) { goto End; } - /*assert(connectRsp.epSet.numOfEps > 0);*/ if (connectRsp.epSet.numOfEps == 0) { setErrno(pRequest, TSDB_CODE_APP_ERROR); tsem_post(&pRequest->body.rspSem); @@ -127,14 +134,14 @@ int32_t processConnectRsp(void* param, SDataBuf* pMsg, int32_t code) { tscDebug("0x%" PRIx64 " clusterId:%" PRId64 ", totalConn:%" PRId64, pRequest->requestId, connectRsp.clusterId, pTscObj->pAppInfo->numOfConns); - + tsem_post(&pRequest->body.rspSem); End: if (pRequest) { releaseRequest(pRequest->self); } - + taosMemoryFree(param); taosMemoryFree(pMsg->pEpSet); taosMemoryFree(pMsg->pData); @@ -150,7 +157,6 @@ SMsgSendInfo* buildMsgInfoImpl(SRequestObj* pRequest) { pMsgSendInfo->msgType = pRequest->type; pMsgSendInfo->target.type = TARGET_TYPE_MNODE; - assert(pRequest != NULL); pMsgSendInfo->msgInfo = pRequest->body.requestMsg; pMsgSendInfo->fp = getMsgRspHandle(pRequest->type); return pMsgSendInfo; @@ -163,6 +169,22 @@ int32_t processCreateDbRsp(void* param, SDataBuf* pMsg, int32_t code) { taosMemoryFree(pMsg->pEpSet); if (code != TSDB_CODE_SUCCESS) { setErrno(pRequest, code); + } else { + struct SCatalog* pCatalog = NULL; + int32_t code = catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &pCatalog); + if (TSDB_CODE_SUCCESS == code) { + STscObj* pTscObj = pRequest->pTscObj; + + SRequestConnInfo conn = {.pTrans = pTscObj->pAppInfo->pTransporter, + .requestId = pRequest->requestId, + .requestObjRefId = pRequest->self, + .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)}; + char dbFName[TSDB_DB_FNAME_LEN]; + snprintf(dbFName, sizeof(dbFName) - 1, "%d.%s", pTscObj->acctId, TSDB_INFORMATION_SCHEMA_DB); + catalogRefreshDBVgInfo(pCatalog, &conn, dbFName); + snprintf(dbFName, sizeof(dbFName) - 1, "%d.%s", pTscObj->acctId, TSDB_PERFORMANCE_SCHEMA_DB); + catalogRefreshDBVgInfo(pCatalog, &conn, dbFName); + } } if (pRequest->body.queryFp) { @@ -182,7 +204,7 @@ int32_t processUseDbRsp(void* param, SDataBuf* pMsg, int32_t code) { tDeserializeSUseDbRsp(pMsg->pData, pMsg->len, &usedbRsp); struct SCatalog* pCatalog = NULL; - if (usedbRsp.vgVersion >= 0) { // cached in local + if (usedbRsp.vgVersion >= 0) { // cached in local uint64_t clusterId = pRequest->pTscObj->pAppInfo->clusterId; int32_t code1 = catalogGetHandle(clusterId, &pCatalog); if (code1 != TSDB_CODE_SUCCESS) { @@ -274,7 +296,9 @@ int32_t processUseDbRsp(void* param, SDataBuf* pMsg, int32_t code) { } int32_t processCreateSTableRsp(void* param, SDataBuf* pMsg, int32_t code) { - assert(pMsg != NULL && param != NULL); + if (pMsg == NULL || param == NULL) { + return TSDB_CODE_TSC_INVALID_INPUT; + } SRequestObj* pRequest = param; if (code != TSDB_CODE_SUCCESS) { @@ -327,13 +351,13 @@ int32_t processDropDbRsp(void* param, SDataBuf* pMsg, int32_t code) { int32_t code = catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &pCatalog); if (TSDB_CODE_SUCCESS == code) { catalogRemoveDB(pCatalog, dropdbRsp.db, dropdbRsp.uid); - STscObj* pTscObj = pRequest->pTscObj; + STscObj* pTscObj = pRequest->pTscObj; SRequestConnInfo conn = {.pTrans = pTscObj->pAppInfo->pTransporter, .requestId = pRequest->requestId, .requestObjRefId = pRequest->self, .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)}; - char dbFName[TSDB_DB_FNAME_LEN]; + char dbFName[TSDB_DB_FNAME_LEN]; snprintf(dbFName, sizeof(dbFName) - 1, "%d.%s", pTscObj->acctId, TSDB_INFORMATION_SCHEMA_DB); catalogRefreshDBVgInfo(pCatalog, &conn, dbFName); snprintf(dbFName, sizeof(dbFName) - 1, "%d.%s", pTscObj->acctId, TSDB_PERFORMANCE_SCHEMA_DB); @@ -417,12 +441,12 @@ static int32_t buildShowVariablesBlock(SArray* pVars, SSDataBlock** block) { char name[TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(name, pInfo->name, TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE); SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, c++); - colDataAppend(pColInfo, i, name, false); + colDataSetVal(pColInfo, i, name, false); char value[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(value, pInfo->value, TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE); pColInfo = taosArrayGet(pBlock->pDataBlock, c++); - colDataAppend(pColInfo, i, value, false); + colDataSetVal(pColInfo, i, value, false); } pBlock->info.rows = numOfCfg; @@ -455,9 +479,14 @@ static int32_t buildShowVariablesRsp(SArray* pVars, SRetrieveTableRsp** pRsp) { (*pRsp)->numOfCols = htonl(SHOW_VARIABLES_RESULT_COLS); int32_t len = blockEncode(pBlock, (*pRsp)->data, SHOW_VARIABLES_RESULT_COLS); - ASSERT(len == rspSize - sizeof(SRetrieveTableRsp)); - blockDataDestroy(pBlock); + + if (len != rspSize - sizeof(SRetrieveTableRsp)) { + uError("buildShowVariablesRsp error, len:%d != rspSize - sizeof(SRetrieveTableRsp):%" PRIu64, len, + (uint64_t)(rspSize - sizeof(SRetrieveTableRsp))); + return TSDB_CODE_TSC_INVALID_INPUT; + } + return TSDB_CODE_SUCCESS; } @@ -476,6 +505,9 @@ int32_t processShowVariablesRsp(void* param, SDataBuf* pMsg, int32_t code) { code = setQueryResultFromRsp(&pRequest->body.resInfo, pRes, false, true); } + if (code != 0) { + taosMemoryFree(pRes); + } tFreeSShowVariablesRsp(&rsp); } diff --git a/source/client/src/clientRawBlockWrite.c b/source/client/src/clientRawBlockWrite.c index 8c91eacf1eefcdbfffb9ce72a7dec80a86e92e3e..a09780dc153db0512d3c2678646397a68cafb53e 100644 --- a/source/client/src/clientRawBlockWrite.c +++ b/source/client/src/clientRawBlockWrite.c @@ -25,9 +25,7 @@ #include "tref.h" #include "ttimer.h" -static tb_uid_t processSuid(tb_uid_t suid, char* db){ - return suid + MurmurHash3_32(db, strlen(db)); -} +static tb_uid_t processSuid(tb_uid_t suid, char* db) { return suid + MurmurHash3_32(db, strlen(db)); } static char* buildCreateTableJson(SSchemaWrapper* schemaRow, SSchemaWrapper* schemaTag, char* name, int64_t id, int8_t t) { @@ -183,7 +181,7 @@ static char* buildAlterSTableJson(void* alterData, int32_t alterDataLen) { } string = cJSON_PrintUnformatted(json); - end: +end: cJSON_Delete(json); tFreeSMAltertbReq(&req); return string; @@ -194,6 +192,7 @@ static char* processCreateStb(SMqMetaRsp* metaRsp) { SDecoder coder; char* string = NULL; + uDebug("processCreateStb called"); // decode and process req void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead); @@ -203,8 +202,8 @@ static char* processCreateStb(SMqMetaRsp* metaRsp) { goto _err; } string = buildCreateTableJson(&req.schemaRow, &req.schemaTag, req.name, req.suid, TSDB_SUPER_TABLE); - - _err: + uDebug("processCreateStb %s", string); +_err: tDecoderClear(&coder); return string; } @@ -213,6 +212,7 @@ static char* processAlterStb(SMqMetaRsp* metaRsp) { SVCreateStbReq req = {0}; SDecoder coder; char* string = NULL; + uDebug("processAlterStb called"); // decode and process req void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); @@ -223,8 +223,9 @@ static char* processAlterStb(SMqMetaRsp* metaRsp) { goto _err; } string = buildAlterSTableJson(req.alterOriData, req.alterOriDataLen); + uDebug("processAlterStb %s", string); - _err: +_err: tDecoderClear(&coder); return string; } @@ -306,7 +307,7 @@ static void buildChildElement(cJSON* json, SVCreateTbReq* pCreateReq) { cJSON_AddItemToArray(tags, tag); } - end: +end: cJSON_AddItemToObject(json, "tags", tags); taosArrayDestroy(pTagVals); } @@ -346,6 +347,7 @@ static char* processCreateTable(SMqMetaRsp* metaRsp) { SVCreateTbReq* pCreateReq; char* string = NULL; // decode + uDebug("processCreateTable called"); void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead); tDecoderInit(&decoder, data, len); @@ -362,9 +364,10 @@ static char* processCreateTable(SMqMetaRsp* metaRsp) { string = buildCreateTableJson(&pCreateReq->ntb.schemaRow, NULL, pCreateReq->name, pCreateReq->uid, TSDB_NORMAL_TABLE); } + uDebug("processCreateTable :%s", string); } - _exit: +_exit: for (int32_t iReq = 0; iReq < req.nReqs; iReq++) { pCreateReq = req.pReqs + iReq; taosMemoryFreeClear(pCreateReq->comment); @@ -377,7 +380,11 @@ static char* processCreateTable(SMqMetaRsp* metaRsp) { } static char* processAutoCreateTable(STaosxRsp* rsp) { - ASSERT(rsp->createTableNum != 0); + uDebug("processAutoCreateTable called"); + if (rsp->createTableNum <= 0) { + uError("WriteRaw:processAutoCreateTable rsp->createTableNum <= 0"); + goto _exit; + } SDecoder* decoder = taosMemoryCalloc(rsp->createTableNum, sizeof(SDecoder)); SVCreateTbReq* pCreateReq = taosMemoryCalloc(rsp->createTableNum, sizeof(SVCreateTbReq)); @@ -393,11 +400,14 @@ static char* processAutoCreateTable(STaosxRsp* rsp) { goto _exit; } - ASSERT(pCreateReq[iReq].type == TSDB_CHILD_TABLE); + if (pCreateReq[iReq].type != TSDB_CHILD_TABLE) { + uError("WriteRaw:processAutoCreateTable pCreateReq[iReq].type != TSDB_CHILD_TABLE"); + goto _exit; + } } string = buildCreateCTableJson(pCreateReq, rsp->createTableNum); - - _exit: + uDebug("processAutoCreateTable :%s", string); +_exit: for (int i = 0; i < rsp->createTableNum; i++) { tDecoderClear(&decoder[i]); taosMemoryFreeClear(pCreateReq[i].comment); @@ -416,6 +426,7 @@ static char* processAlterTable(SMqMetaRsp* metaRsp) { char* string = NULL; cJSON* json = NULL; + uDebug("processAlterTable called"); // decode void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead); @@ -498,7 +509,10 @@ static char* processAlterTable(SMqMetaRsp* metaRsp) { char* buf = NULL; if (vAlterTbReq.tagType == TSDB_DATA_TYPE_JSON) { - ASSERT(tTagIsJson(vAlterTbReq.pTagVal) == true); + if (!tTagIsJson(vAlterTbReq.pTagVal)) { + uError("processAlterTable isJson false"); + goto _exit; + } buf = parseTagDatatoJson(vAlterTbReq.pTagVal); } else { buf = taosMemoryCalloc(vAlterTbReq.nTagVal + 1, 1); @@ -518,8 +532,9 @@ static char* processAlterTable(SMqMetaRsp* metaRsp) { break; } string = cJSON_PrintUnformatted(json); + uDebug("processAlterTable :%s", string); - _exit: +_exit: cJSON_Delete(json); tDecoderClear(&decoder); return string; @@ -530,6 +545,7 @@ static char* processDropSTable(SMqMetaRsp* metaRsp) { SVDropStbReq req = {0}; char* string = NULL; cJSON* json = NULL; + uDebug("processDropSTable called"); // decode void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); @@ -551,19 +567,20 @@ static char* processDropSTable(SMqMetaRsp* metaRsp) { cJSON_AddItemToObject(json, "tableName", tableName); string = cJSON_PrintUnformatted(json); - - _exit: + uDebug("processDropSTable :%s", string); +_exit: cJSON_Delete(json); tDecoderClear(&decoder); return string; } -static char* processDeleteTable(SMqMetaRsp* metaRsp){ +static char* processDeleteTable(SMqMetaRsp* metaRsp) { SDeleteRes req = {0}; SDecoder coder = {0}; int32_t code = TSDB_CODE_SUCCESS; cJSON* json = NULL; char* string = NULL; + uDebug("processDeleteTable called"); // decode and process req void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead); @@ -590,8 +607,8 @@ static char* processDeleteTable(SMqMetaRsp* metaRsp){ cJSON_AddItemToObject(json, "sql", sqlJson); string = cJSON_PrintUnformatted(json); - - _exit: + uDebug("processDeleteTable :%s", string); +_exit: cJSON_Delete(json); tDecoderClear(&coder); return string; @@ -603,6 +620,7 @@ static char* processDropTable(SMqMetaRsp* metaRsp) { char* string = NULL; cJSON* json = NULL; + uDebug("processDropTable called"); // decode void* data = POINTER_SHIFT(metaRsp->metaRsp, sizeof(SMsgHead)); int32_t len = metaRsp->metaRspLen - sizeof(SMsgHead); @@ -632,8 +650,8 @@ static char* processDropTable(SMqMetaRsp* metaRsp) { cJSON_AddItemToObject(json, "tableNameList", tableNameList); string = cJSON_PrintUnformatted(json); - - _exit: + uDebug("processDropTable :%s", string); +_exit: cJSON_Delete(json); tDecoderClear(&decoder); return string; @@ -646,6 +664,7 @@ static int32_t taosCreateStb(TAOS* taos, void* meta, int32_t metaLen) { int32_t code = TSDB_CODE_SUCCESS; SRequestObj* pRequest = NULL; + uDebug("taosCreateStb called"); code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; @@ -689,6 +708,7 @@ static int32_t taosCreateStb(TAOS* taos, void* meta, int32_t metaLen) { pReq.source = TD_REQ_FROM_TAOX; pReq.igExists = true; + uDebug("taosCreateStb name:%s suid:%" PRId64 " processSuid:%" PRId64, req.name, req.suid, pReq.suid); STscObj* pTscObj = pRequest->pTscObj; SName tableName; tNameExtractFullName(toName(pTscObj->acctId, pRequest->pDb, req.name, &tableName), pReq.name); @@ -721,7 +741,7 @@ static int32_t taosCreateStb(TAOS* taos, void* meta, int32_t metaLen) { code = pRequest->code; taosMemoryFree(pCmdMsg.pMsg); - end: +end: destroyRequest(pRequest); tFreeSMCreateStbReq(&pReq); tDecoderClear(&coder); @@ -735,6 +755,7 @@ static int32_t taosDropStb(TAOS* taos, void* meta, int32_t metaLen) { int32_t code = TSDB_CODE_SUCCESS; SRequestObj* pRequest = NULL; + uDebug("taosDropStb called"); code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; @@ -754,11 +775,37 @@ static int32_t taosDropStb(TAOS* taos, void* meta, int32_t metaLen) { goto end; } + SCatalog* pCatalog = NULL; + code = catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &pCatalog); + if (code != TSDB_CODE_SUCCESS) { + goto end; + } + SRequestConnInfo conn = {.pTrans = pRequest->pTscObj->pAppInfo->pTransporter, + .requestId = pRequest->requestId, + .requestObjRefId = pRequest->self, + .mgmtEps = getEpSet_s(&pRequest->pTscObj->pAppInfo->mgmtEp)}; + SName pName = {0}; + toName(pRequest->pTscObj->acctId, pRequest->pDb, req.name, &pName); + STableMeta* pTableMeta = NULL; + code = catalogGetTableMeta(pCatalog, &conn, &pName, &pTableMeta); + if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) { + code = TSDB_CODE_SUCCESS; + taosMemoryFreeClear(pTableMeta); + goto end; + } + if (code != TSDB_CODE_SUCCESS) { + uError("taosCreateTable:catalogGetTableMeta failed. table name: %s", req.name); + goto end; + } + pReq.suid = pTableMeta->uid; + taosMemoryFreeClear(pTableMeta); + // build drop stable pReq.igNotExists = true; pReq.source = TD_REQ_FROM_TAOX; - pReq.suid = processSuid(req.suid, pRequest->pDb); + // pReq.suid = processSuid(req.suid, pRequest->pDb); + uDebug("taosDropStb name:%s suid:%" PRId64 " new suid:%" PRId64, req.name, req.suid, pReq.suid); STscObj* pTscObj = pRequest->pTscObj; SName tableName = {0}; tNameExtractFullName(toName(pTscObj->acctId, pRequest->pDb, req.name, &tableName), pReq.name); @@ -783,7 +830,7 @@ static int32_t taosDropStb(TAOS* taos, void* meta, int32_t metaLen) { launchQueryImpl(pRequest, &pQuery, true, NULL); if (pRequest->code == TSDB_CODE_SUCCESS) { - SCatalog* pCatalog = NULL; + // SCatalog* pCatalog = NULL; catalogGetHandle(pTscObj->pAppInfo->clusterId, &pCatalog); catalogRemoveTableMeta(pCatalog, &tableName); } @@ -791,7 +838,7 @@ static int32_t taosDropStb(TAOS* taos, void* meta, int32_t metaLen) { code = pRequest->code; taosMemoryFree(pCmdMsg.pMsg); - end: +end: destroyRequest(pRequest); tDecoderClear(&coder); return code; @@ -816,6 +863,7 @@ static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) { SQuery* pQuery = NULL; SHashObj* pVgroupHashmap = NULL; + uDebug("taosCreateTable called"); code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; @@ -852,9 +900,9 @@ static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) { taosHashSetFreeFp(pVgroupHashmap, destroyCreateTbReqBatch); SRequestConnInfo conn = {.pTrans = pTscObj->pAppInfo->pTransporter, - .requestId = pRequest->requestId, - .requestObjRefId = pRequest->self, - .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)}; + .requestId = pRequest->requestId, + .requestObjRefId = pRequest->self, + .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)}; pRequest->tableList = taosArrayInit(req.nReqs, sizeof(SName)); // loop to create table @@ -875,13 +923,17 @@ static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) { if (pCreateReq->type == TSDB_CHILD_TABLE) { STableMeta* pTableMeta = NULL; SName sName = {0}; - pCreateReq->ctb.suid = processSuid(pCreateReq->ctb.suid, pRequest->pDb); + tb_uid_t oldSuid = pCreateReq->ctb.suid; + // pCreateReq->ctb.suid = processSuid(pCreateReq->ctb.suid, pRequest->pDb); toName(pTscObj->acctId, pRequest->pDb, pCreateReq->ctb.stbName, &sName); code = catalogGetTableMeta(pCatalog, &conn, &sName, &pTableMeta); if (code != TSDB_CODE_SUCCESS) { uError("taosCreateTable:catalogGetTableMeta failed. table name: %s", pCreateReq->ctb.stbName); goto end; } + pCreateReq->ctb.suid = pTableMeta->uid; + uDebug("taosCreateTable name:%s sname:%s suid:%" PRId64 " new suid:%" PRId64, pCreateReq->name, + pCreateReq->ctb.stbName, oldSuid, pCreateReq->ctb.suid); for (int32_t i = 0; i < taosArrayGetSize(pCreateReq->ctb.tagName); i++) { char* tName = taosArrayGet(pCreateReq->ctb.tagName, i); @@ -935,7 +987,7 @@ static int32_t taosCreateTable(TAOS* taos, void* meta, int32_t metaLen) { code = pRequest->code; - end: +end: for (int32_t iReq = 0; iReq < req.nReqs; iReq++) { pCreateReq = req.pReqs + iReq; taosMemoryFreeClear(pCreateReq->comment); @@ -970,6 +1022,7 @@ static int32_t taosDropTable(TAOS* taos, void* meta, int32_t metaLen) { SQuery* pQuery = NULL; SHashObj* pVgroupHashmap = NULL; + uDebug("taosDropTable called"); code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { goto end; @@ -1005,15 +1058,15 @@ static int32_t taosDropTable(TAOS* taos, void* meta, int32_t metaLen) { taosHashSetFreeFp(pVgroupHashmap, destroyDropTbReqBatch); SRequestConnInfo conn = {.pTrans = pTscObj->pAppInfo->pTransporter, - .requestId = pRequest->requestId, - .requestObjRefId = pRequest->self, - .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)}; + .requestId = pRequest->requestId, + .requestObjRefId = pRequest->self, + .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)}; pRequest->tableList = taosArrayInit(req.nReqs, sizeof(SName)); // loop to create table for (int32_t iReq = 0; iReq < req.nReqs; iReq++) { pDropReq = req.pReqs + iReq; pDropReq->igNotExists = true; - pDropReq->suid = processSuid(pDropReq->suid, pRequest->pDb); + // pDropReq->suid = processSuid(pDropReq->suid, pRequest->pDb); SVgroupInfo pInfo = {0}; SName pName = {0}; @@ -1023,6 +1076,22 @@ static int32_t taosDropTable(TAOS* taos, void* meta, int32_t metaLen) { goto end; } + STableMeta* pTableMeta = NULL; + code = catalogGetTableMeta(pCatalog, &conn, &pName, &pTableMeta); + if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) { + code = TSDB_CODE_SUCCESS; + taosMemoryFreeClear(pTableMeta); + continue; + } + if (code != TSDB_CODE_SUCCESS) { + uError("taosDropTable:catalogGetTableMeta failed. table name: %s", pDropReq->name); + goto end; + } + tb_uid_t oldSuid = pDropReq->suid; + pDropReq->suid = pTableMeta->suid; + taosMemoryFreeClear(pTableMeta); + uDebug("taosDropTable name:%s suid:%" PRId64 " new suid:%" PRId64, pDropReq->name, oldSuid, pDropReq->suid); + taosArrayPush(pRequest->tableList, &pName); SVgroupDropTableBatch* pTableBatch = taosHashGet(pVgroupHashmap, &pInfo.vgId, sizeof(pInfo.vgId)); if (pTableBatch == NULL) { @@ -1037,6 +1106,9 @@ static int32_t taosDropTable(TAOS* taos, void* meta, int32_t metaLen) { } } + if (taosHashGetSize(pVgroupHashmap) == 0) { + goto end; + } SArray* pBufArray = serializeVgroupsDropTableBatch(pVgroupHashmap); if (NULL == pBufArray) { code = TSDB_CODE_OUT_OF_MEMORY; @@ -1060,7 +1132,7 @@ static int32_t taosDropTable(TAOS* taos, void* meta, int32_t metaLen) { } code = pRequest->code; - end: +end: taosHashCleanup(pVgroupHashmap); destroyRequest(pRequest); tDecoderClear(&coder); @@ -1105,6 +1177,7 @@ static int32_t taosDeleteData(TAOS* taos, void* meta, int32_t metaLen) { SDecoder coder = {0}; int32_t code = TSDB_CODE_SUCCESS; + uDebug("taosDeleteData called"); // decode and process req void* data = POINTER_SHIFT(meta, sizeof(SMsgHead)); int32_t len = metaLen - sizeof(SMsgHead); @@ -1123,12 +1196,12 @@ static int32_t taosDeleteData(TAOS* taos, void* meta, int32_t metaLen) { TAOS_RES* res = taos_query(taos, sql); SRequestObj* pRequest = (SRequestObj*)res; code = pRequest->code; - if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) { + if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST || code == TSDB_CODE_PAR_GET_META_ERROR) { code = TSDB_CODE_SUCCESS; } taos_free_result(res); - end: +end: tDecoderClear(&coder); return code; } @@ -1142,6 +1215,7 @@ static int32_t taosAlterTable(TAOS* taos, void* meta, int32_t metaLen) { SArray* pArray = NULL; SVgDataBlocks* pVgData = NULL; + uDebug("taosAlterTable called"); code = buildRequest(*(int64_t*)taos, "", 0, NULL, false, &pRequest, 0); if (code != TSDB_CODE_SUCCESS) { @@ -1175,9 +1249,9 @@ static int32_t taosAlterTable(TAOS* taos, void* meta, int32_t metaLen) { } SRequestConnInfo conn = {.pTrans = pTscObj->pAppInfo->pTransporter, - .requestId = pRequest->requestId, - .requestObjRefId = pRequest->self, - .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)}; + .requestId = pRequest->requestId, + .requestObjRefId = pRequest->self, + .mgmtEps = getEpSet_s(&pTscObj->pAppInfo->mgmtEp)}; SVgroupInfo pInfo = {0}; SName pName = {0}; @@ -1187,6 +1261,7 @@ static int32_t taosAlterTable(TAOS* taos, void* meta, int32_t metaLen) { goto end; } + uDebug("taosAlterTable name:%s", req.tbName); pArray = taosArrayInit(1, sizeof(void*)); if (NULL == pArray) { code = TSDB_CODE_OUT_OF_MEMORY; @@ -1236,7 +1311,7 @@ static int32_t taosAlterTable(TAOS* taos, void* meta, int32_t metaLen) { code = handleAlterTbExecRes(pRes->res, pCatalog); } } - end: +end: taosArrayDestroy(pArray); if (pVgData) taosMemoryFreeClear(pVgData->pData); taosMemoryFreeClear(pVgData); @@ -1246,21 +1321,13 @@ static int32_t taosAlterTable(TAOS* taos, void* meta, int32_t metaLen) { return code; } -typedef struct { - SVgroupInfo vg; - void* data; -} VgData; - -static void destroyVgHash(void* data) { - VgData* vgData = (VgData*)data; - taosMemoryFreeClear(vgData->data); -} - -int taos_write_raw_block_with_fields(TAOS* taos, int rows, char* pData, const char* tbname, TAOS_FIELD *fields, int numFields){ +int taos_write_raw_block_with_fields(TAOS* taos, int rows, char* pData, const char* tbname, TAOS_FIELD* fields, + int numFields) { int32_t code = TSDB_CODE_SUCCESS; STableMeta* pTableMeta = NULL; SQuery* pQuery = NULL; - SSubmitReq* subReq = NULL; + SHashObj* pVgHash = NULL; + uDebug("taos_write_raw_block_with_fields called"); SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT, 0); if (!pRequest) { @@ -1280,6 +1347,7 @@ int taos_write_raw_block_with_fields(TAOS* taos, int rows, char* pData, const ch tstrncpy(pName.dbname, pRequest->pDb, sizeof(pName.dbname)); tstrncpy(pName.tname, tbname, sizeof(pName.tname)); + uDebug("taos_write_raw_block_with_fields name:%s", tbname); struct SCatalog* pCatalog = NULL; code = catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &pCatalog); if (code != TSDB_CODE_SUCCESS) { @@ -1305,157 +1373,38 @@ int taos_write_raw_block_with_fields(TAOS* taos, int rows, char* pData, const ch uError("WriteRaw:catalogGetTableMeta failed. table name: %s", tbname); goto end; } - uint64_t suid = (TSDB_NORMAL_TABLE == pTableMeta->tableType ? 0 : pTableMeta->suid); - uint64_t uid = pTableMeta->uid; - int32_t numOfCols = pTableMeta->tableInfo.numOfColumns; + // uError("td23101 0vgId:%d, vgId:%d, name:%s, uid:%"PRIu64, vgData.vgId, pTableMeta->vgId, tbname, pTableMeta->uid); - uint16_t fLen = 0; - int32_t rowSize = 0; - int16_t nVar = 0; - for (int i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) { - SSchema* schema = pTableMeta->schema + i; - fLen += TYPE_BYTES[schema->type]; - rowSize += schema->bytes; - if (IS_VAR_DATA_TYPE(schema->type)) { - nVar++; - } - } - - fLen -= sizeof(TSKEY); - - int32_t extendedRowSize = rowSize + TD_ROW_HEAD_LEN - sizeof(TSKEY) + nVar * sizeof(VarDataOffsetT) + - (int32_t)TD_BITMAP_BYTES(numOfCols - 1); - int32_t schemaLen = 0; - int32_t submitLen = sizeof(SSubmitBlk) + schemaLen + rows * extendedRowSize; - - int32_t totalLen = sizeof(SSubmitReq) + submitLen; - subReq = taosMemoryCalloc(1, totalLen); - SSubmitBlk* blk = POINTER_SHIFT(subReq, sizeof(SSubmitReq)); - void* blkSchema = POINTER_SHIFT(blk, sizeof(SSubmitBlk)); - STSRow* rowData = POINTER_SHIFT(blkSchema, schemaLen); - - SRowBuilder rb = {0}; - tdSRowInit(&rb, pTableMeta->sversion); - tdSRowSetTpInfo(&rb, numOfCols, fLen); - int32_t dataLen = 0; - - // | version | total length | total rows | total columns | flag seg| block group id | column schema | each column length | - char* pStart = pData + getVersion1BlockMetaSize(pData, numFields); - int32_t* colLength = (int32_t*)pStart; - pStart += sizeof(int32_t) * numFields; - - SResultColumn* pCol = taosMemoryCalloc(numFields, sizeof(SResultColumn)); - - for (int32_t i = 0; i < numFields; ++i) { - if (IS_VAR_DATA_TYPE(fields[i].type)) { - pCol[i].offset = (int32_t*)pStart; - pStart += rows * sizeof(int32_t); - } else { - pCol[i].nullbitmap = pStart; - pStart += BitmapLen(rows); - } - - pCol[i].pData = pStart; - pStart += colLength[i]; - } - - SHashObj* schemaHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); - for (int i = 0; i < numFields; i++) { - TAOS_FIELD* schema = &fields[i]; - taosHashPut(schemaHash, schema->name, strlen(schema->name), &i, sizeof(int32_t)); - } - - for (int32_t j = 0; j < rows; j++) { - tdSRowResetBuf(&rb, rowData); - int32_t offset = 0; - for (int32_t k = 0; k < numOfCols; k++) { - const SSchema* pColumn = &pTableMeta->schema[k]; - int32_t* index = taosHashGet(schemaHash, pColumn->name, strlen(pColumn->name)); - if (!index) { // add none - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NONE, NULL, false, offset, k); - }else{ - if (IS_VAR_DATA_TYPE(pColumn->type)) { - if (pCol[*index].offset[j] != -1) { - char* data = pCol[*index].pData + pCol[*index].offset[j]; - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, data, true, offset, k); - } else { - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NULL, NULL, false, offset, k); - } - } else { - if (!colDataIsNull_f(pCol[*index].nullbitmap, j)) { - char* data = pCol[*index].pData + pColumn->bytes * j; - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, data, true, offset, k); - } else { - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NULL, NULL, false, offset, k); - } - } - } - - if (pColumn->colId != PRIMARYKEY_TIMESTAMP_COL_ID) { - offset += TYPE_BYTES[pColumn->type]; - } - } - tdSRowEnd(&rb); - int32_t rowLen = TD_ROW_LEN(rowData); - rowData = POINTER_SHIFT(rowData, rowLen); - dataLen += rowLen; - } - - taosHashCleanup(schemaHash); - taosMemoryFree(pCol); - - blk->uid = htobe64(uid); - blk->suid = htobe64(suid); - blk->sversion = htonl(pTableMeta->sversion); - blk->schemaLen = htonl(schemaLen); - blk->numOfRows = htonl(rows); - blk->dataLen = htonl(dataLen); - subReq->length = sizeof(SSubmitReq) + sizeof(SSubmitBlk) + schemaLen + dataLen; - subReq->numOfBlocks = 1; - - pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY); - if (NULL == pQuery) { - uError("create SQuery error"); + pQuery = smlInitHandle(); + if (pQuery == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; goto end; } - pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; - pQuery->haveResultSet = false; - pQuery->msgType = TDMT_VND_SUBMIT; - pQuery->pRoot = (SNode*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); - if (NULL == pQuery->pRoot) { - uError("create pQuery->pRoot error"); - code = TSDB_CODE_OUT_OF_MEMORY; + pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); + taosHashPut(pVgHash, (const char*)&vgData.vgId, sizeof(vgData.vgId), (char*)&vgData, sizeof(vgData)); + // uError("td23101 1vgId:%d, numEps:%d, name:%s, uid:%"PRIu64, vgData.vgId, vgData.epSet.numOfEps, tbname, + // pTableMeta->uid); + + code = rawBlockBindData(pQuery, pTableMeta, pData, NULL, fields, numFields, false); + if (code != TSDB_CODE_SUCCESS) { + uError("WriteRaw:rawBlockBindData failed"); goto end; } - SVnodeModifOpStmt* nodeStmt = (SVnodeModifOpStmt*)(pQuery->pRoot); - nodeStmt->pDataBlocks = taosArrayInit(1, POINTER_BYTES); - SVgDataBlocks* dst = taosMemoryCalloc(1, sizeof(SVgDataBlocks)); - if (NULL == dst) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; + code = smlBuildOutput(pQuery, pVgHash); + if (code != TSDB_CODE_SUCCESS) { + uError("smlBuildOutput failed"); + return code; } - dst->vg = vgData; - dst->numOfTables = subReq->numOfBlocks; - dst->size = subReq->length; - dst->pData = (char*)subReq; - subReq->header.vgId = htonl(dst->vg.vgId); - subReq->version = htonl(1); - subReq->header.contLen = htonl(subReq->length); - subReq->length = htonl(subReq->length); - subReq->numOfBlocks = htonl(subReq->numOfBlocks); - subReq = NULL; // no need free - taosArrayPush(nodeStmt->pDataBlocks, &dst); launchQueryImpl(pRequest, pQuery, true, NULL); code = pRequest->code; - end: +end: taosMemoryFreeClear(pTableMeta); qDestroyQuery(pQuery); destroyRequest(pRequest); - taosMemoryFree(subReq); + taosHashCleanup(pVgHash); return code; } @@ -1463,8 +1412,9 @@ int taos_write_raw_block(TAOS* taos, int rows, char* pData, const char* tbname) int32_t code = TSDB_CODE_SUCCESS; STableMeta* pTableMeta = NULL; SQuery* pQuery = NULL; - SSubmitReq* subReq = NULL; + SHashObj* pVgHash = NULL; + uDebug("taos_write_raw_block called"); SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT, 0); if (!pRequest) { uError("WriteRaw:createRequest error request is null"); @@ -1483,6 +1433,7 @@ int taos_write_raw_block(TAOS* taos, int rows, char* pData, const char* tbname) tstrncpy(pName.dbname, pRequest->pDb, sizeof(pName.dbname)); tstrncpy(pName.tname, tbname, sizeof(pName.tname)); + uDebug("taos_write_raw_block name:%s", tbname); struct SCatalog* pCatalog = NULL; code = catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &pCatalog); if (code != TSDB_CODE_SUCCESS) { @@ -1508,146 +1459,34 @@ int taos_write_raw_block(TAOS* taos, int rows, char* pData, const char* tbname) uError("WriteRaw:catalogGetTableMeta failed. table name: %s", tbname); goto end; } - uint64_t suid = (TSDB_NORMAL_TABLE == pTableMeta->tableType ? 0 : pTableMeta->suid); - uint64_t uid = pTableMeta->uid; - int32_t numOfCols = pTableMeta->tableInfo.numOfColumns; - - uint16_t fLen = 0; - int32_t rowSize = 0; - int16_t nVar = 0; - for (int i = 0; i < numOfCols; i++) { - SSchema* schema = pTableMeta->schema + i; - fLen += TYPE_BYTES[schema->type]; - rowSize += schema->bytes; - if (IS_VAR_DATA_TYPE(schema->type)) { - nVar++; - } - } - fLen -= sizeof(TSKEY); - - int32_t extendedRowSize = rowSize + TD_ROW_HEAD_LEN - sizeof(TSKEY) + nVar * sizeof(VarDataOffsetT) + - (int32_t)TD_BITMAP_BYTES(numOfCols - 1); - int32_t schemaLen = 0; - int32_t submitLen = sizeof(SSubmitBlk) + schemaLen + rows * extendedRowSize; - - int32_t totalLen = sizeof(SSubmitReq) + submitLen; - subReq = taosMemoryCalloc(1, totalLen); - SSubmitBlk* blk = POINTER_SHIFT(subReq, sizeof(SSubmitReq)); - void* blkSchema = POINTER_SHIFT(blk, sizeof(SSubmitBlk)); - STSRow* rowData = POINTER_SHIFT(blkSchema, schemaLen); - - SRowBuilder rb = {0}; - tdSRowInit(&rb, pTableMeta->sversion); - tdSRowSetTpInfo(&rb, numOfCols, fLen); - int32_t dataLen = 0; - - // | version | total length | total rows | total columns | flag seg| block group id | column schema | each column length | - char* pStart = pData + getVersion1BlockMetaSize(pData, numOfCols); - int32_t* colLength = (int32_t*)pStart; - pStart += sizeof(int32_t) * numOfCols; - - SResultColumn* pCol = taosMemoryCalloc(numOfCols, sizeof(SResultColumn)); - - for (int32_t i = 0; i < numOfCols; ++i) { - if (IS_VAR_DATA_TYPE(pTableMeta->schema[i].type)) { - pCol[i].offset = (int32_t*)pStart; - pStart += rows * sizeof(int32_t); - } else { - pCol[i].nullbitmap = pStart; - pStart += BitmapLen(rows); - } - - pCol[i].pData = pStart; - pStart += colLength[i]; - } - - for (int32_t j = 0; j < rows; j++) { - tdSRowResetBuf(&rb, rowData); - int32_t offset = 0; - for (int32_t k = 0; k < numOfCols; k++) { - const SSchema* pColumn = &pTableMeta->schema[k]; - - if (IS_VAR_DATA_TYPE(pColumn->type)) { - if (pCol[k].offset[j] != -1) { - char* data = pCol[k].pData + pCol[k].offset[j]; - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, data, true, offset, k); - } else { - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NULL, NULL, false, offset, k); - } - } else { - if (!colDataIsNull_f(pCol[k].nullbitmap, j)) { - char* data = pCol[k].pData + pColumn->bytes * j; - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, data, true, offset, k); - } else { - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NULL, NULL, false, offset, k); - } - } - - if (pColumn->colId != PRIMARYKEY_TIMESTAMP_COL_ID) { - offset += TYPE_BYTES[pColumn->type]; - } - } - tdSRowEnd(&rb); - int32_t rowLen = TD_ROW_LEN(rowData); - rowData = POINTER_SHIFT(rowData, rowLen); - dataLen += rowLen; - } - - taosMemoryFree(pCol); - - blk->uid = htobe64(uid); - blk->suid = htobe64(suid); - blk->sversion = htonl(pTableMeta->sversion); - blk->schemaLen = htonl(schemaLen); - blk->numOfRows = htonl(rows); - blk->dataLen = htonl(dataLen); - subReq->length = sizeof(SSubmitReq) + sizeof(SSubmitBlk) + schemaLen + dataLen; - subReq->numOfBlocks = 1; - - pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY); - if (NULL == pQuery) { - uError("create SQuery error"); + pQuery = smlInitHandle(); + if (pQuery == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; - taosMemoryFree(subReq); goto end; } - pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; - pQuery->haveResultSet = false; - pQuery->msgType = TDMT_VND_SUBMIT; - pQuery->pRoot = (SNode*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); - if (NULL == pQuery->pRoot) { - uError("create pQuery->pRoot error"); - code = TSDB_CODE_OUT_OF_MEMORY; + pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); + taosHashPut(pVgHash, (const char*)&vgData.vgId, sizeof(vgData.vgId), (char*)&vgData, sizeof(vgData)); + + code = rawBlockBindData(pQuery, pTableMeta, pData, NULL, NULL, 0, false); + if (code != TSDB_CODE_SUCCESS) { + uError("WriteRaw:rawBlockBindData failed"); goto end; } - SVnodeModifOpStmt* nodeStmt = (SVnodeModifOpStmt*)(pQuery->pRoot); - nodeStmt->pDataBlocks = taosArrayInit(1, POINTER_BYTES); - SVgDataBlocks* dst = taosMemoryCalloc(1, sizeof(SVgDataBlocks)); - if (NULL == dst) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; + code = smlBuildOutput(pQuery, pVgHash); + if (code != TSDB_CODE_SUCCESS) { + uError("smlBuildOutput failed"); + return code; } - dst->vg = vgData; - dst->numOfTables = subReq->numOfBlocks; - dst->size = subReq->length; - dst->pData = (char*)subReq; - subReq->header.vgId = htonl(dst->vg.vgId); - subReq->version = htonl(1); - subReq->header.contLen = htonl(subReq->length); - subReq->length = htonl(subReq->length); - subReq->numOfBlocks = htonl(subReq->numOfBlocks); - subReq = NULL; // no need free - taosArrayPush(nodeStmt->pDataBlocks, &dst); launchQueryImpl(pRequest, pQuery, true, NULL); code = pRequest->code; - end: +end: taosMemoryFreeClear(pTableMeta); qDestroyQuery(pQuery); destroyRequest(pRequest); - taosMemoryFree(subReq); + taosHashCleanup(pVgHash); return code; } @@ -1658,6 +1497,7 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) { SMqRspObj rspObj = {0}; SDecoder decoder = {0}; STableMeta* pTableMeta = NULL; + uDebug("tmqWriteRawDataImpl called"); terrno = TSDB_CODE_SUCCESS; SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT, 0); @@ -1684,8 +1524,6 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) { goto end; } - pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); - taosHashSetFreeFp(pVgHash, destroyVgHash); struct SCatalog* pCatalog = NULL; code = catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &pCatalog); if (code != TSDB_CODE_SUCCESS) { @@ -1699,21 +1537,19 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) { conn.requestObjRefId = pRequest->self; conn.mgmtEps = getEpSet_s(&pRequest->pTscObj->pAppInfo->mgmtEp); - uDebug("raw data block num:%d\n", rspObj.rsp.blockNum); + pQuery = smlInitHandle(); + if (pQuery == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto end; + } + pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); + uDebug("tmqWriteRawDataImpl raw data block num:%d", rspObj.rsp.blockNum); while (++rspObj.resIter < rspObj.rsp.blockNum) { SRetrieveTableRsp* pRetrieve = (SRetrieveTableRsp*)taosArrayGetP(rspObj.rsp.blockData, rspObj.resIter); if (!rspObj.rsp.withSchema) { uError("WriteRaw:no schema, iter:%d", rspObj.resIter); goto end; } - SSchemaWrapper* pSW = (SSchemaWrapper*)taosArrayGetP(rspObj.rsp.blockSchema, rspObj.resIter); - setResSchemaInfo(&rspObj.resInfo, pSW->pSchema, pSW->nCols); - - code = setQueryResultFromRsp(&rspObj.resInfo, pRetrieve, false, false); - if (code != TSDB_CODE_SUCCESS) { - uError("WriteRaw: setQueryResultFromRsp error"); - goto end; - } const char* tbName = (const char*)taosArrayGetP(rspObj.rsp.blockTbName, rspObj.resIter); if (!tbName) { @@ -1722,18 +1558,11 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) { goto end; } - uDebug("raw data tbname:%s\n", tbName); + uDebug("tmqWriteRawDataImpl raw data tbname:%s", tbName); SName pName = {TSDB_TABLE_NAME_T, pRequest->pTscObj->acctId, {0}, {0}}; strcpy(pName.dbname, pRequest->pDb); strcpy(pName.tname, tbName); - VgData vgData = {0}; - code = catalogGetTableHashVgroup(pCatalog, &conn, &pName, &(vgData.vg)); - if (code != TSDB_CODE_SUCCESS) { - uError("WriteRaw:catalogGetTableHashVgroup failed. table name: %s", tbName); - goto end; - } - code = catalogGetTableMeta(pCatalog, &conn, &pName, &pTableMeta); if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) { uError("WriteRaw:catalogGetTableMeta table not exist. table name: %s", tbName); @@ -1745,173 +1574,48 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) { goto end; } - uint16_t fLen = 0; - int32_t rowSize = 0; - int16_t nVar = 0; - for (int i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) { - SSchema* schema = &pTableMeta->schema[i]; - fLen += TYPE_BYTES[schema->type]; - rowSize += schema->bytes; - if (IS_VAR_DATA_TYPE(schema->type)) { - nVar++; - } + SVgroupInfo vg; + code = catalogGetTableHashVgroup(pCatalog, &conn, &pName, &vg); + if (code != TSDB_CODE_SUCCESS) { + uError("WriteRaw:catalogGetTableHashVgroup failed. table name: %s", tbName); + goto end; } - fLen -= sizeof(TSKEY); - - int32_t rows = rspObj.resInfo.numOfRows; - int32_t extendedRowSize = rowSize + TD_ROW_HEAD_LEN - sizeof(TSKEY) + nVar * sizeof(VarDataOffsetT) + - (int32_t)TD_BITMAP_BYTES(pTableMeta->tableInfo.numOfColumns - 1); - int32_t schemaLen = 0; - int32_t submitLen = sizeof(SSubmitBlk) + schemaLen + rows * extendedRowSize; - - SSubmitReq* subReq = NULL; - SSubmitBlk* blk = NULL; - void* hData = taosHashGet(pVgHash, &vgData.vg.vgId, sizeof(vgData.vg.vgId)); - if (hData) { - vgData = *(VgData*)hData; - - int32_t totalLen = ((SSubmitReq*)(vgData.data))->length + submitLen; - void* tmp = taosMemoryRealloc(vgData.data, totalLen); - if (tmp == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; - } - vgData.data = tmp; - ((VgData*)hData)->data = tmp; - subReq = (SSubmitReq*)(vgData.data); - blk = POINTER_SHIFT(vgData.data, subReq->length); - } else { - int32_t totalLen = sizeof(SSubmitReq) + submitLen; - void* tmp = taosMemoryCalloc(1, totalLen); - if (tmp == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; - } - vgData.data = tmp; - taosHashPut(pVgHash, (const char*)&vgData.vg.vgId, sizeof(vgData.vg.vgId), (char*)&vgData, sizeof(vgData)); - subReq = (SSubmitReq*)(vgData.data); - subReq->length = sizeof(SSubmitReq); - subReq->numOfBlocks = 0; - blk = POINTER_SHIFT(vgData.data, sizeof(SSubmitReq)); + void* hData = taosHashGet(pVgHash, &vg.vgId, sizeof(vg.vgId)); + if (hData == NULL) { + taosHashPut(pVgHash, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg)); } - // pSW->pSchema should be same as pTableMeta->schema - // ASSERT(pSW->nCols == pTableMeta->tableInfo.numOfColumns); - uint64_t suid = (TSDB_NORMAL_TABLE == pTableMeta->tableType ? 0 : pTableMeta->suid); - uint64_t uid = pTableMeta->uid; - int16_t sver = pTableMeta->sversion; - - void* blkSchema = POINTER_SHIFT(blk, sizeof(SSubmitBlk)); - STSRow* rowData = POINTER_SHIFT(blkSchema, schemaLen); - - SRowBuilder rb = {0}; - tdSRowInit(&rb, sver); - tdSRowSetTpInfo(&rb, pTableMeta->tableInfo.numOfColumns, fLen); - int32_t totalLen = 0; - - SHashObj* schemaHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + SSchemaWrapper* pSW = (SSchemaWrapper*)taosArrayGetP(rspObj.rsp.blockSchema, rspObj.resIter); + TAOS_FIELD* fields = taosMemoryCalloc(pSW->nCols, sizeof(TAOS_FIELD)); + if (fields == NULL) { + goto end; + } for (int i = 0; i < pSW->nCols; i++) { - SSchema* schema = &pSW->pSchema[i]; - taosHashPut(schemaHash, schema->name, strlen(schema->name), &i, sizeof(int32_t)); + fields[i].type = pSW->pSchema[i].type; + fields[i].bytes = pSW->pSchema[i].bytes; + tstrncpy(fields[i].name, pSW->pSchema[i].name, tListLen(pSW->pSchema[i].name)); } - - for (int32_t j = 0; j < rows; j++) { - tdSRowResetBuf(&rb, rowData); - - doSetOneRowPtr(&rspObj.resInfo); - rspObj.resInfo.current += 1; - - int32_t offset = 0; - for (int32_t k = 0; k < pTableMeta->tableInfo.numOfColumns; k++) { - const SSchema* pColumn = &pTableMeta->schema[k]; - int32_t* index = taosHashGet(schemaHash, pColumn->name, strlen(pColumn->name)); - if (!index) { - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NONE, NULL, false, offset, k); - } else { - char* colData = rspObj.resInfo.row[*index]; - if (!colData) { - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NULL, NULL, false, offset, k); - } else { - if (IS_VAR_DATA_TYPE(pColumn->type)) { - colData -= VARSTR_HEADER_SIZE; - } - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, colData, true, offset, k); - } - } - if (pColumn->colId != PRIMARYKEY_TIMESTAMP_COL_ID) { - offset += TYPE_BYTES[pColumn->type]; - } - } - tdSRowEnd(&rb); - int32_t rowLen = TD_ROW_LEN(rowData); - rowData = POINTER_SHIFT(rowData, rowLen); - totalLen += rowLen; + code = rawBlockBindData(pQuery, pTableMeta, pRetrieve->data, NULL, fields, pSW->nCols, true); + taosMemoryFree(fields); + if (code != TSDB_CODE_SUCCESS) { + uError("WriteRaw:rawBlockBindData failed"); + goto end; } - - taosHashCleanup(schemaHash); - blk->uid = htobe64(uid); - blk->suid = htobe64(suid); - blk->sversion = htonl(sver); - blk->schemaLen = htonl(schemaLen); - blk->numOfRows = htonl(rows); - blk->dataLen = htonl(totalLen); - subReq->length += sizeof(SSubmitBlk) + schemaLen + totalLen; - subReq->numOfBlocks++; taosMemoryFreeClear(pTableMeta); - rspObj.resInfo.pRspMsg = NULL; - doFreeReqResultInfo(&rspObj.resInfo); } - pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY); - if (NULL == pQuery) { - uError("create SQuery error"); - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; - } - pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; - pQuery->haveResultSet = false; - pQuery->msgType = TDMT_VND_SUBMIT; - pQuery->pRoot = (SNode*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); - if (NULL == pQuery->pRoot) { - uError("create pQuery->pRoot error"); - code = TSDB_CODE_OUT_OF_MEMORY; + code = smlBuildOutput(pQuery, pVgHash); + if (code != TSDB_CODE_SUCCESS) { + uError("smlBuildOutput failed"); goto end; } - SVnodeModifOpStmt* nodeStmt = (SVnodeModifOpStmt*)(pQuery->pRoot); - - int32_t numOfVg = taosHashGetSize(pVgHash); - nodeStmt->pDataBlocks = taosArrayInit(numOfVg, POINTER_BYTES); - - VgData* vData = (VgData*)taosHashIterate(pVgHash, NULL); - while (vData) { - SVgDataBlocks* dst = taosMemoryCalloc(1, sizeof(SVgDataBlocks)); - if (NULL == dst) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; - } - dst->vg = vData->vg; - SSubmitReq* subReq = (SSubmitReq*)(vData->data); - dst->numOfTables = subReq->numOfBlocks; - dst->size = subReq->length; - dst->pData = (char*)subReq; - vData->data = NULL; // no need free - subReq->header.vgId = htonl(dst->vg.vgId); - subReq->version = htonl(1); - subReq->header.contLen = htonl(subReq->length); - subReq->length = htonl(subReq->length); - subReq->numOfBlocks = htonl(subReq->numOfBlocks); - taosArrayPush(nodeStmt->pDataBlocks, &dst); - vData = (VgData*)taosHashIterate(pVgHash, vData); - } launchQueryImpl(pRequest, pQuery, true, NULL); code = pRequest->code; - end: +end: tDeleteSMqDataRsp(&rspObj.rsp); - rspObj.resInfo.pRspMsg = NULL; - doFreeReqResultInfo(&rspObj.resInfo); tDecoderClear(&decoder); qDestroyQuery(pQuery); destroyRequest(pRequest); @@ -1920,7 +1624,6 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) { return code; } - static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen) { int32_t code = TSDB_CODE_SUCCESS; SHashObj* pVgHash = NULL; @@ -1928,7 +1631,8 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen) SMqTaosxRspObj rspObj = {0}; SDecoder decoder = {0}; STableMeta* pTableMeta = NULL; - void* schemaContent = NULL; + SVCreateTbReq* pCreateReqDst = NULL; + uDebug("tmqWriteRawMetaDataImpl called"); terrno = TSDB_CODE_SUCCESS; SRequestObj* pRequest = (SRequestObj*)createRequest(*(int64_t*)taos, TSDB_SQL_INSERT, 0); @@ -1955,8 +1659,6 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen) goto end; } - pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); - taosHashSetFreeFp(pVgHash, destroyVgHash); struct SCatalog* pCatalog = NULL; code = catalogGetHandle(pRequest->pTscObj->pAppInfo->clusterId, &pCatalog); if (code != TSDB_CODE_SUCCESS) { @@ -1970,21 +1672,20 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen) conn.requestObjRefId = pRequest->self; conn.mgmtEps = getEpSet_s(&pRequest->pTscObj->pAppInfo->mgmtEp); - uDebug("raw data block num:%d\n", rspObj.rsp.blockNum); + pQuery = smlInitHandle(); + if (pQuery == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto end; + } + pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); + + uDebug("tmqWriteRawMetaDataImpl raw data block num:%d", rspObj.rsp.blockNum); while (++rspObj.resIter < rspObj.rsp.blockNum) { SRetrieveTableRsp* pRetrieve = (SRetrieveTableRsp*)taosArrayGetP(rspObj.rsp.blockData, rspObj.resIter); if (!rspObj.rsp.withSchema) { uError("WriteRaw:no schema, iter:%d", rspObj.resIter); goto end; } - SSchemaWrapper* pSW = (SSchemaWrapper*)taosArrayGetP(rspObj.rsp.blockSchema, rspObj.resIter); - setResSchemaInfo(&rspObj.resInfo, pSW->pSchema, pSW->nCols); - - code = setQueryResultFromRsp(&rspObj.resInfo, pRetrieve, false, false); - if (code != TSDB_CODE_SUCCESS) { - uError("WriteRaw: setQueryResultFromRsp error"); - goto end; - } const char* tbName = (const char*)taosArrayGetP(rspObj.rsp.blockTbName, rspObj.resIter); if (!tbName) { @@ -1993,73 +1694,55 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen) goto end; } - uDebug("raw data tbname:%s\n", tbName); + uDebug("tmqWriteRawMetaDataImpl raw data tbname:%s\n", tbName); SName pName = {TSDB_TABLE_NAME_T, pRequest->pTscObj->acctId, {0}, {0}}; strcpy(pName.dbname, pRequest->pDb); strcpy(pName.tname, tbName); - VgData vgData = {0}; - code = catalogGetTableHashVgroup(pCatalog, &conn, &pName, &(vgData.vg)); - if (code != TSDB_CODE_SUCCESS) { - uError("WriteRaw:catalogGetTableHashVgroup failed. table name: %s", tbName); - goto end; - } - // find schema data info - int32_t schemaLen = 0; - void* schemaData = NULL; for (int j = 0; j < rspObj.rsp.createTableNum; j++) { void** dataTmp = taosArrayGet(rspObj.rsp.createTableReq, j); int32_t* lenTmp = taosArrayGet(rspObj.rsp.createTableLen, j); SDecoder decoderTmp = {0}; SVCreateTbReq pCreateReq = {0}; + tDecoderInit(&decoderTmp, *dataTmp, *lenTmp); + if (tDecodeSVCreateTbReq(&decoderTmp, &pCreateReq) < 0) { + tDecoderClear(&decoderTmp); + tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE); + uError("WriteRaw: tDecodeSVCreateTbReq error"); + code = TSDB_CODE_TMQ_INVALID_MSG; + goto end; + } - do{ - tDecoderInit(&decoderTmp, *dataTmp, *lenTmp); - if (tDecodeSVCreateTbReq(&decoderTmp, &pCreateReq) < 0) { - code = TSDB_CODE_MSG_DECODE_ERROR; - break; - } - - if (strcmp(tbName, pCreateReq.name) != 0) { - break; - } - - pCreateReq.ctb.suid = processSuid(pCreateReq.ctb.suid, pRequest->pDb); - - int32_t len = 0; - tEncodeSize(tEncodeSVCreateTbReq, &pCreateReq, len, code); - if(code != 0) { - code = TSDB_CODE_MSG_ENCODE_ERROR; - break; - } - taosMemoryFree(schemaContent); - schemaContent = taosMemoryMalloc(len); - if(!schemaContent) { - code = TSDB_CODE_OUT_OF_MEMORY; - break; - } - SEncoder encoder = {0}; - tEncoderInit(&encoder, schemaContent, len); - code = tEncodeSVCreateTbReq(&encoder, &pCreateReq); - if (code != 0) { - tEncoderClear(&encoder); - code = TSDB_CODE_MSG_ENCODE_ERROR; - break; - } - schemaLen = len; - schemaData = schemaContent; - strcpy(pName.tname, pCreateReq.ctb.stbName); - tEncoderClear(&encoder); - }while(0); + if (pCreateReq.type != TSDB_CHILD_TABLE) { + uError("WriteRaw:pCreateReq.type != TSDB_CHILD_TABLE. table name: %s", tbName); + code = TSDB_CODE_TSC_INVALID_VALUE; + tDecoderClear(&decoderTmp); + tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE); + goto end; + } + if (strcmp(tbName, pCreateReq.name) == 0) { + cloneSVreateTbReq(&pCreateReq, &pCreateReqDst); + // pCreateReqDst->ctb.suid = processSuid(pCreateReqDst->ctb.suid, pRequest->pDb); + tDecoderClear(&decoderTmp); + tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE); + break; + } tDecoderClear(&decoderTmp); - taosMemoryFreeClear(pCreateReq.comment); - taosArrayDestroy(pCreateReq.ctb.tagName); - if(code != 0) goto end; - if(schemaLen != 0) break; + tDestroySVCreateTbReq(&pCreateReq, TSDB_MSG_FLG_DECODE); } + SVgroupInfo vg; + code = catalogGetTableHashVgroup(pCatalog, &conn, &pName, &vg); + if (code != TSDB_CODE_SUCCESS) { + uError("WriteRaw:catalogGetTableHashVgroup failed. table name: %s", tbName); + goto end; + } + + if (pCreateReqDst) { // change stable name to get meta + strcpy(pName.tname, pCreateReqDst->ctb.stbName); + } code = catalogGetTableMeta(pCatalog, &conn, &pName, &pTableMeta); if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST) { uError("WriteRaw:catalogGetTableMeta table not exist. table name: %s", tbName); @@ -2071,186 +1754,61 @@ static int32_t tmqWriteRawMetaDataImpl(TAOS* taos, void* data, int32_t dataLen) goto end; } - uint16_t fLen = 0; - int32_t rowSize = 0; - int16_t nVar = 0; - for (int i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) { - SSchema* schema = &pTableMeta->schema[i]; - fLen += TYPE_BYTES[schema->type]; - rowSize += schema->bytes; - if (IS_VAR_DATA_TYPE(schema->type)) { - nVar++; - } + if (pCreateReqDst) { + pTableMeta->vgId = vg.vgId; + pTableMeta->uid = pCreateReqDst->uid; + pCreateReqDst->ctb.suid = pTableMeta->suid; } - fLen -= sizeof(TSKEY); - - int32_t rows = rspObj.resInfo.numOfRows; - int32_t extendedRowSize = rowSize + TD_ROW_HEAD_LEN - sizeof(TSKEY) + nVar * sizeof(VarDataOffsetT) + - (int32_t)TD_BITMAP_BYTES(pTableMeta->tableInfo.numOfColumns - 1); - - int32_t submitLen = sizeof(SSubmitBlk) + schemaLen + rows * extendedRowSize; - - SSubmitReq* subReq = NULL; - SSubmitBlk* blk = NULL; - void* hData = taosHashGet(pVgHash, &vgData.vg.vgId, sizeof(vgData.vg.vgId)); - if (hData) { - vgData = *(VgData*)hData; - - int32_t totalLen = ((SSubmitReq*)(vgData.data))->length + submitLen; - void* tmp = taosMemoryRealloc(vgData.data, totalLen); - if (tmp == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; - } - vgData.data = tmp; - ((VgData*)hData)->data = tmp; - subReq = (SSubmitReq*)(vgData.data); - blk = POINTER_SHIFT(vgData.data, subReq->length); - } else { - int32_t totalLen = sizeof(SSubmitReq) + submitLen; - void* tmp = taosMemoryCalloc(1, totalLen); - if (tmp == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; - } - vgData.data = tmp; - taosHashPut(pVgHash, (const char*)&vgData.vg.vgId, sizeof(vgData.vg.vgId), (char*)&vgData, sizeof(vgData)); - subReq = (SSubmitReq*)(vgData.data); - subReq->length = sizeof(SSubmitReq); - subReq->numOfBlocks = 0; - - blk = POINTER_SHIFT(vgData.data, sizeof(SSubmitReq)); + void* hData = taosHashGet(pVgHash, &vg.vgId, sizeof(vg.vgId)); + if (hData == NULL) { + taosHashPut(pVgHash, (const char*)&vg.vgId, sizeof(vg.vgId), (char*)&vg, sizeof(vg)); } - // pSW->pSchema should be same as pTableMeta->schema - // ASSERT(pSW->nCols == pTableMeta->tableInfo.numOfColumns); - uint64_t suid = (TSDB_NORMAL_TABLE == pTableMeta->tableType ? 0 : pTableMeta->suid); - uint64_t uid = pTableMeta->uid; - int16_t sver = pTableMeta->sversion; - - void* blkSchema = POINTER_SHIFT(blk, sizeof(SSubmitBlk)); - if (schemaData) { - memcpy(blkSchema, schemaData, schemaLen); + SSchemaWrapper* pSW = (SSchemaWrapper*)taosArrayGetP(rspObj.rsp.blockSchema, rspObj.resIter); + TAOS_FIELD* fields = taosMemoryCalloc(pSW->nCols, sizeof(TAOS_FIELD)); + if (fields == NULL) { + goto end; } - STSRow* rowData = POINTER_SHIFT(blkSchema, schemaLen); - - SRowBuilder rb = {0}; - tdSRowInit(&rb, sver); - tdSRowSetTpInfo(&rb, pTableMeta->tableInfo.numOfColumns, fLen); - int32_t totalLen = 0; - - SHashObj* schemaHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); for (int i = 0; i < pSW->nCols; i++) { - SSchema* schema = &pSW->pSchema[i]; - taosHashPut(schemaHash, schema->name, strlen(schema->name), &i, sizeof(int32_t)); + fields[i].type = pSW->pSchema[i].type; + fields[i].bytes = pSW->pSchema[i].bytes; + tstrncpy(fields[i].name, pSW->pSchema[i].name, tListLen(pSW->pSchema[i].name)); } - - for (int32_t j = 0; j < rows; j++) { - tdSRowResetBuf(&rb, rowData); - - doSetOneRowPtr(&rspObj.resInfo); - rspObj.resInfo.current += 1; - - int32_t offset = 0; - for (int32_t k = 0; k < pTableMeta->tableInfo.numOfColumns; k++) { - const SSchema* pColumn = &pTableMeta->schema[k]; - int32_t* index = taosHashGet(schemaHash, pColumn->name, strlen(pColumn->name)); - if (!index) { - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NONE, NULL, false, offset, k); - } else { - char* colData = rspObj.resInfo.row[*index]; - if (!colData) { - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NULL, NULL, false, offset, k); - } else { - if (IS_VAR_DATA_TYPE(pColumn->type)) { - colData -= VARSTR_HEADER_SIZE; - } - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, colData, true, offset, k); - } - } - if (pColumn->colId != PRIMARYKEY_TIMESTAMP_COL_ID) { - offset += TYPE_BYTES[pColumn->type]; - } - } - tdSRowEnd(&rb); - int32_t rowLen = TD_ROW_LEN(rowData); - rowData = POINTER_SHIFT(rowData, rowLen); - totalLen += rowLen; + code = rawBlockBindData(pQuery, pTableMeta, pRetrieve->data, pCreateReqDst, fields, pSW->nCols, true); + taosMemoryFree(fields); + if (code != TSDB_CODE_SUCCESS) { + uError("WriteRaw:rawBlockBindData failed"); + goto end; } - - taosHashCleanup(schemaHash); - blk->uid = htobe64(uid); - blk->suid = htobe64(suid); - blk->sversion = htonl(sver); - blk->schemaLen = htonl(schemaLen); - blk->numOfRows = htonl(rows); - blk->dataLen = htonl(totalLen); - subReq->length += sizeof(SSubmitBlk) + schemaLen + totalLen; - subReq->numOfBlocks++; + pCreateReqDst = NULL; taosMemoryFreeClear(pTableMeta); - rspObj.resInfo.pRspMsg = NULL; - doFreeReqResultInfo(&rspObj.resInfo); } - pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY); - if (NULL == pQuery) { - uError("create SQuery error"); - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; - } - pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; - pQuery->haveResultSet = false; - pQuery->msgType = TDMT_VND_SUBMIT; - pQuery->pRoot = (SNode*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); - if (NULL == pQuery->pRoot) { - uError("create pQuery->pRoot error"); - code = TSDB_CODE_OUT_OF_MEMORY; + code = smlBuildOutput(pQuery, pVgHash); + if (code != TSDB_CODE_SUCCESS) { + uError("smlBuildOutput failed"); goto end; } - SVnodeModifOpStmt* nodeStmt = (SVnodeModifOpStmt*)(pQuery->pRoot); - - int32_t numOfVg = taosHashGetSize(pVgHash); - nodeStmt->pDataBlocks = taosArrayInit(numOfVg, POINTER_BYTES); - - VgData* vData = (VgData*)taosHashIterate(pVgHash, NULL); - while (vData) { - SVgDataBlocks* dst = taosMemoryCalloc(1, sizeof(SVgDataBlocks)); - if (NULL == dst) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; - } - dst->vg = vData->vg; - SSubmitReq* subReq = (SSubmitReq*)(vData->data); - dst->numOfTables = subReq->numOfBlocks; - dst->size = subReq->length; - dst->pData = (char*)subReq; - vData->data = NULL; // no need free - subReq->header.vgId = htonl(dst->vg.vgId); - subReq->version = htonl(1); - subReq->header.contLen = htonl(subReq->length); - subReq->length = htonl(subReq->length); - subReq->numOfBlocks = htonl(subReq->numOfBlocks); - taosArrayPush(nodeStmt->pDataBlocks, &dst); - vData = (VgData*)taosHashIterate(pVgHash, vData); - } launchQueryImpl(pRequest, pQuery, true, NULL); code = pRequest->code; - end: +end: tDeleteSTaosxRsp(&rspObj.rsp); - rspObj.resInfo.pRspMsg = NULL; - doFreeReqResultInfo(&rspObj.resInfo); tDecoderClear(&decoder); qDestroyQuery(pQuery); destroyRequest(pRequest); taosHashCleanup(pVgHash); taosMemoryFreeClear(pTableMeta); - taosMemoryFree(schemaContent); + if (pCreateReqDst) { + tdDestroySVCreateTbReq(pCreateReqDst); + taosMemoryFree(pCreateReqDst); + } return code; } char* tmq_get_json_meta(TAOS_RES* res) { + uDebug("tmq_get_json_meta called"); if (!TD_RES_TMQ_META(res) && !TD_RES_TMQ_METADATA(res)) { return NULL; } @@ -2285,6 +1843,7 @@ char* tmq_get_json_meta(TAOS_RES* res) { void tmq_free_json_meta(char* jsonMeta) { taosMemoryFreeClear(jsonMeta); } int32_t tmq_get_raw(TAOS_RES* res, tmq_raw_data* raw) { + uDebug("tmq_get_raw called"); if (!raw || !res) { return TSDB_CODE_INVALID_PARA; } @@ -2293,6 +1852,7 @@ int32_t tmq_get_raw(TAOS_RES* res, tmq_raw_data* raw) { raw->raw = pMetaRspObj->metaRsp.metaRsp; raw->raw_len = pMetaRspObj->metaRsp.metaRspLen; raw->raw_type = pMetaRspObj->metaRsp.resMsgType; + uDebug("tmq_get_raw meta"); } else if (TD_RES_TMQ(res)) { SMqRspObj* rspObj = ((SMqRspObj*)res); @@ -2312,6 +1872,7 @@ int32_t tmq_get_raw(TAOS_RES* res, tmq_raw_data* raw) { raw->raw = buf; raw->raw_len = len; raw->raw_type = RES_TYPE__TMQ; + uDebug("tmq_get_raw data"); } else if (TD_RES_TMQ_METADATA(res)) { SMqTaosxRspObj* rspObj = ((SMqTaosxRspObj*)res); @@ -2331,19 +1892,23 @@ int32_t tmq_get_raw(TAOS_RES* res, tmq_raw_data* raw) { raw->raw = buf; raw->raw_len = len; raw->raw_type = RES_TYPE__TMQ_METADATA; + uDebug("tmq_get_raw meta data"); } else { + uError("tmq_get_raw error:%d", *(int8_t*)res); return TSDB_CODE_TMQ_INVALID_MSG; } return TSDB_CODE_SUCCESS; } void tmq_free_raw(tmq_raw_data raw) { + uDebug("tmq_free_raw raw_type:%d", raw.raw_type); if (raw.raw_type == RES_TYPE__TMQ || raw.raw_type == RES_TYPE__TMQ_METADATA) { taosMemoryFree(raw.raw); } } int32_t tmq_write_raw(TAOS* taos, tmq_raw_data raw) { + uDebug("tmq_write_raw called"); if (!taos) { return TSDB_CODE_INVALID_PARA; } diff --git a/source/client/src/clientSml.c b/source/client/src/clientSml.c index 0694f4c457294ad66028184e7e685d8fab7f517c..30c0008f3d8b227327bff4e7bcf1bd0bd4f147b6 100644 --- a/source/client/src/clientSml.c +++ b/source/client/src/clientSml.c @@ -1,210 +1,101 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + #include #include #include #include -#include "cJSON.h" -#include "catalog.h" -#include "clientInt.h" -#include "osSemaphore.h" -#include "osThread.h" -#include "query.h" -#include "taos.h" -#include "taoserror.h" -#include "tcommon.h" -#include "tdef.h" -#include "tglobal.h" -#include "tlog.h" -#include "tmsg.h" -#include "tname.h" -#include "ttime.h" -#include "ttypes.h" - -//================================================================================================= - -#define SPACE ' ' -#define COMMA ',' -#define EQUAL '=' -#define QUOTE '"' -#define SLASH '\\' - -#define JUMP_SPACE(sql, sqlEnd) \ - while (sql < sqlEnd) { \ - if (*sql == SPACE) \ - sql++; \ - else \ - break; \ - } -// comma , -#define IS_SLASH_COMMA(sql) (*(sql) == COMMA && *((sql)-1) == SLASH) -#define IS_COMMA(sql) (*(sql) == COMMA && *((sql)-1) != SLASH) -// space -#define IS_SLASH_SPACE(sql) (*(sql) == SPACE && *((sql)-1) == SLASH) -#define IS_SPACE(sql) (*(sql) == SPACE && *((sql)-1) != SLASH) -// equal = -#define IS_SLASH_EQUAL(sql) (*(sql) == EQUAL && *((sql)-1) == SLASH) -#define IS_EQUAL(sql) (*(sql) == EQUAL && *((sql)-1) != SLASH) -// quote " -#define IS_SLASH_QUOTE(sql) (*(sql) == QUOTE && *((sql)-1) == SLASH) -#define IS_QUOTE(sql) (*(sql) == QUOTE && *((sql)-1) != SLASH) -// SLASH -#define IS_SLASH_SLASH(sql) (*(sql) == SLASH && *((sql)-1) == SLASH) - -#define IS_SLASH_LETTER(sql) \ - (IS_SLASH_COMMA(sql) || IS_SLASH_SPACE(sql) || IS_SLASH_EQUAL(sql) || IS_SLASH_QUOTE(sql) || IS_SLASH_SLASH(sql)) - -#define MOVE_FORWARD_ONE(sql, len) (memmove((void *)((sql)-1), (sql), len)) - -#define PROCESS_SLASH(key, keyLen) \ - for (int i = 1; i < keyLen; ++i) { \ - if (IS_SLASH_LETTER(key + i)) { \ - MOVE_FORWARD_ONE(key + i, keyLen - i); \ - i--; \ - keyLen--; \ - } \ - } - -#define IS_INVALID_COL_LEN(len) ((len) <= 0 || (len) >= TSDB_COL_NAME_LEN) -#define IS_INVALID_TABLE_LEN(len) ((len) <= 0 || (len) >= TSDB_TABLE_NAME_LEN) - -#define OTD_JSON_SUB_FIELDS_NUM 2 -#define OTD_JSON_FIELDS_NUM 4 - -#define TS "_ts" -#define TS_LEN 3 -#define VALUE "_value" -#define VALUE_LEN 6 - -#define BINARY_ADD_LEN 2 // "binary" 2 means " " -#define NCHAR_ADD_LEN 3 // L"nchar" 3 means L" " - -#define MAX_RETRY_TIMES 5 -//================================================================================================= -typedef TSDB_SML_PROTOCOL_TYPE SMLProtocolType; - -typedef enum { - SCHEMA_ACTION_NULL, - SCHEMA_ACTION_CREATE_STABLE, - SCHEMA_ACTION_ADD_COLUMN, - SCHEMA_ACTION_ADD_TAG, - SCHEMA_ACTION_CHANGE_COLUMN_SIZE, - SCHEMA_ACTION_CHANGE_TAG_SIZE, -} ESchemaAction; - -typedef struct { - const char *measure; - const char *tags; - const char *cols; - const char *timestamp; - - int32_t measureLen; - int32_t measureTagsLen; - int32_t tagsLen; - int32_t colsLen; - int32_t timestampLen; -} SSmlLineInfo; - -typedef struct { - const char *sTableName; // super table name - int32_t sTableNameLen; - char childTableName[TSDB_TABLE_NAME_LEN]; - uint64_t uid; - - SArray *tags; - - // if info->formatData is true, elements are SArray. - // if info->formatData is false, elements are SHashObj for find by key quickly - SArray *cols; -} SSmlTableInfo; - -typedef struct { - SArray *tags; // save the origin order to create table - SHashObj *tagHash; // elements are - - SArray *cols; - SHashObj *colHash; - - STableMeta *tableMeta; -} SSmlSTableMeta; - -typedef struct { - int32_t len; - char *buf; -} SSmlMsgBuf; - -typedef struct { - int32_t code; - int32_t lineNum; - - int32_t numOfSTables; - int32_t numOfCTables; - int32_t numOfCreateSTables; - int32_t numOfAlterColSTables; - int32_t numOfAlterTagSTables; - - int64_t parseTime; - int64_t schemaTime; - int64_t insertBindTime; - int64_t insertRpcTime; - int64_t endTime; -} SSmlCostInfo; - -typedef struct { - int64_t id; - - SMLProtocolType protocol; - int8_t precision; - bool dataFormat; // true means that the name and order of keys in each line are the same(only for influx protocol) - bool isRawLine; - int32_t ttl; - - SHashObj *childTables; - SHashObj *superTables; - SHashObj *pVgHash; - void *exec; - - STscObj *taos; - SCatalog *pCatalog; - SRequestObj *pRequest; - SQuery *pQuery; - - SSmlCostInfo cost; - SSmlMsgBuf msgBuf; - SHashObj *dumplicateKey; // for dumplicate key - SArray *colsContainer; // for cols parse, if dataFormat == false - int32_t uid; // used for automatic create child table - - cJSON *root; // for parse json -} SSmlHandle; -//================================================================================================= - -//================================================================================================= -static volatile int64_t linesSmlHandleId = 0; -static int64_t smlGenId() { - int64_t id; - - do { - id = atomic_add_fetch_64(&linesSmlHandleId, 1); - } while (id == 0); +#include "clientSml.h" + +int64_t smlToMilli[3] = {3600000LL, 60000LL, 1000LL}; +int64_t smlFactorNS[3] = {NANOSECOND_PER_MSEC, NANOSECOND_PER_USEC, 1}; +int64_t smlFactorS[3] = {1000LL, 1000000LL, 1000000000LL}; + +void *nodeListGet(NodeList *list, const void *key, int32_t len, _equal_fn_sml fn) { + NodeList *tmp = list; + while (tmp) { + if (fn == NULL) { + if (tmp->data.used && tmp->data.keyLen == len && memcmp(tmp->data.key, key, len) == 0) { + return tmp->data.value; + } + } else { + if (tmp->data.used && fn(tmp->data.key, key) == 0) { + return tmp->data.value; + } + } - return id; + tmp = tmp->next; + } + return NULL; } -static inline bool smlDoubleToInt64OverFlow(double num) { - if (num >= (double)INT64_MAX || num <= (double)INT64_MIN) return true; - return false; +int nodeListSet(NodeList **list, const void *key, int32_t len, void *value, _equal_fn_sml fn) { + NodeList *tmp = *list; + while (tmp) { + if (!tmp->data.used) break; + if (fn == NULL) { + if (tmp->data.keyLen == len && memcmp(tmp->data.key, key, len) == 0) { + return -1; + } + } else { + if (tmp->data.keyLen == len && fn(tmp->data.key, key) == 0) { + return -1; + } + } + + tmp = tmp->next; + } + if (tmp) { + tmp->data.key = key; + tmp->data.keyLen = len; + tmp->data.value = value; + tmp->data.used = true; + } else { + NodeList *newNode = (NodeList *)taosMemoryCalloc(1, sizeof(NodeList)); + if (newNode == NULL) { + return -1; + } + newNode->data.key = key; + newNode->data.keyLen = len; + newNode->data.value = value; + newNode->data.used = true; + newNode->next = *list; + *list = newNode; + } + return 0; } -static inline bool smlCheckDuplicateKey(const char *key, int32_t keyLen, SHashObj *pHash) { - void *val = taosHashGet(pHash, key, keyLen); - if (val) { - return true; +int nodeListSize(NodeList *list) { + int cnt = 0; + while (list) { + if (list->data.used) + cnt++; + else + break; + list = list->next; } - taosHashPut(pHash, key, keyLen, key, 1); + return cnt; +} + +inline bool smlDoubleToInt64OverFlow(double num) { + if (num >= (double)INT64_MAX || num <= (double)INT64_MIN) return true; return false; } -static int32_t smlBuildInvalidDataMsg(SSmlMsgBuf *pBuf, const char *msg1, const char *msg2) { +int32_t smlBuildInvalidDataMsg(SSmlMsgBuf *pBuf, const char *msg1, const char *msg2) { if (pBuf->buf) { memset(pBuf->buf, 0, pBuf->len); if (msg1) strncat(pBuf->buf, msg1, pBuf->len); @@ -217,391 +108,312 @@ static int32_t smlBuildInvalidDataMsg(SSmlMsgBuf *pBuf, const char *msg1, const return TSDB_CODE_SML_INVALID_DATA; } -static int32_t smlGenerateSchemaAction(SSchema *colField, SHashObj *colHash, SSmlKv *kv, bool isTag, - ESchemaAction *action, SSmlHandle *info) { - uint16_t *index = colHash ? (uint16_t *)taosHashGet(colHash, kv->key, kv->keyLen) : NULL; - if (index) { - if (colField[*index].type != kv->type) { - uError("SML:0x%" PRIx64 " point type and db type mismatch. key: %s. point type: %d, db type: %d", info->id, - kv->key, colField[*index].type, kv->type); - return TSDB_CODE_TSC_INVALID_VALUE; - } - - if ((colField[*index].type == TSDB_DATA_TYPE_VARCHAR && - (colField[*index].bytes - VARSTR_HEADER_SIZE) < kv->length) || - (colField[*index].type == TSDB_DATA_TYPE_NCHAR && - ((colField[*index].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE < kv->length))) { - if (isTag) { - *action = SCHEMA_ACTION_CHANGE_TAG_SIZE; - } else { - *action = SCHEMA_ACTION_CHANGE_COLUMN_SIZE; - } - } - } else { - if (isTag) { - *action = SCHEMA_ACTION_ADD_TAG; - } else { - *action = SCHEMA_ACTION_ADD_COLUMN; - } +int64_t smlGetTimeValue(const char *value, int32_t len, uint8_t fromPrecision, uint8_t toPrecision) { + char *endPtr = NULL; + int64_t tsInt64 = taosStr2Int64(value, &endPtr, 10); + if (unlikely(value + len != endPtr)) { + return -1; } - return 0; -} -static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) { - int32_t result = 1; - while (result <= length) { - result *= 2; - } - if (type == TSDB_DATA_TYPE_BINARY && result > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) { - result = TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE; - } else if (type == TSDB_DATA_TYPE_NCHAR && result > (TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { - result = (TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE; + if (unlikely(fromPrecision >= TSDB_TIME_PRECISION_HOURS)) { + int64_t unit = smlToMilli[fromPrecision - TSDB_TIME_PRECISION_HOURS]; + if (tsInt64 != 0 && unit > INT64_MAX / tsInt64) { + return -1; + } + tsInt64 *= unit; + fromPrecision = TSDB_TIME_PRECISION_MILLI; } - if (type == TSDB_DATA_TYPE_NCHAR) { - result = result * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE; - } else if (type == TSDB_DATA_TYPE_BINARY) { - result = result + VARSTR_HEADER_SIZE; - } - return result; + return convertTimePrecision(tsInt64, fromPrecision, toPrecision); } -static int32_t smlProcessSchemaAction(SSmlHandle *info, SSchema *schemaField, SHashObj *schemaHash, SArray *cols, - ESchemaAction *action, bool isTag) { - int32_t code = TSDB_CODE_SUCCESS; - for (int j = 0; j < taosArrayGetSize(cols); ++j) { - if (j == 0 && !isTag) continue; - SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, j); - code = smlGenerateSchemaAction(schemaField, schemaHash, kv, isTag, action, info); - if (code != TSDB_CODE_SUCCESS) { - return code; - } +int8_t smlGetTsTypeByLen(int32_t len) { + if (len == TSDB_TIME_PRECISION_SEC_DIGITS) { + return TSDB_TIME_PRECISION_SECONDS; + } else if (len == TSDB_TIME_PRECISION_MILLI_DIGITS) { + return TSDB_TIME_PRECISION_MILLI; + } else { + return -1; } - return TSDB_CODE_SUCCESS; } -static int32_t smlCheckMeta(SSchema *schema, int32_t length, SArray *cols, bool isTag) { - SHashObj *hashTmp = taosHashInit(length, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); - int32_t i = 0; - for (; i < length; i++) { - taosHashPut(hashTmp, schema[i].name, strlen(schema[i].name), &i, SHORT_BYTES); +SSmlTableInfo *smlBuildTableInfo(int numRows, const char *measure, int32_t measureLen) { + SSmlTableInfo *tag = (SSmlTableInfo *)taosMemoryCalloc(sizeof(SSmlTableInfo), 1); + if (!tag) { + return NULL; } - if (isTag) { - i = 0; - } else { - i = 1; - } - for (; i < taosArrayGetSize(cols); i++) { - SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, i); - if (taosHashGet(hashTmp, kv->key, kv->keyLen) == NULL) { - taosHashCleanup(hashTmp); - return -1; - } - } - taosHashCleanup(hashTmp); - return 0; -} + tag->sTableName = measure; + tag->sTableNameLen = measureLen; -static int32_t getBytes(uint8_t type, int32_t length) { - if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { - return smlFindNearestPowerOf2(length, type); - } else { - return tDataTypes[type].bytes; + tag->cols = taosArrayInit(numRows, POINTER_BYTES); + if (tag->cols == NULL) { + uError("SML:smlBuildTableInfo failed to allocate memory"); + goto cleanup; } + + // tag->tags = taosArrayInit(16, sizeof(SSmlKv)); + // if (tag->tags == NULL) { + // uError("SML:smlBuildTableInfo failed to allocate memory"); + // goto cleanup; + // } + return tag; + +cleanup: + taosMemoryFree(tag); + return NULL; } -static int32_t smlBuildFieldsList(SSmlHandle *info, SSchema *schemaField, SHashObj *schemaHash, SArray *cols, - SArray *results, int32_t numOfCols, bool isTag) { - for (int j = 0; j < taosArrayGetSize(cols); ++j) { - SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, j); - ESchemaAction action = SCHEMA_ACTION_NULL; - smlGenerateSchemaAction(schemaField, schemaHash, kv, isTag, &action, info); - if (action == SCHEMA_ACTION_ADD_COLUMN || action == SCHEMA_ACTION_ADD_TAG) { - SField field = {0}; - field.type = kv->type; - field.bytes = getBytes(kv->type, kv->length); - memcpy(field.name, kv->key, kv->keyLen); - taosArrayPush(results, &field); - } else if (action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) { - uint16_t *index = (uint16_t *)taosHashGet(schemaHash, kv->key, kv->keyLen); - uint16_t newIndex = *index; - if (isTag) newIndex -= numOfCols; - SField *field = (SField *)taosArrayGet(results, newIndex); - field->bytes = getBytes(kv->type, kv->length); +static int32_t smlParseTableName(SArray *tags, char *childTableName) { + size_t childTableNameLen = strlen(tsSmlChildTableName); + if (childTableNameLen <= 0) return TSDB_CODE_SUCCESS; + + for (int i = 0; i < taosArrayGetSize(tags); i++) { + SSmlKv *tag = (SSmlKv *)taosArrayGet(tags, i); + // handle child table name + if (childTableNameLen == tag->keyLen && strncmp(tag->key, tsSmlChildTableName, tag->keyLen) == 0) { + memset(childTableName, 0, TSDB_TABLE_NAME_LEN); + strncpy(childTableName, tag->value, (tag->length < TSDB_TABLE_NAME_LEN ? tag->length : TSDB_TABLE_NAME_LEN)); + taosArrayRemove(tags, i); + break; } } + return TSDB_CODE_SUCCESS; } -// static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SSmlSTableMeta *sTableData, -// int32_t colVer, int32_t tagVer, int8_t source, uint64_t suid){ -static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns, SArray *pTags, STableMeta *pTableMeta, - ESchemaAction action) { - SRequestObj *pRequest = NULL; - SMCreateStbReq pReq = {0}; - int32_t code = TSDB_CODE_SUCCESS; - SCmdMsgInfo pCmdMsg = {0}; - - // put front for free - pReq.numOfColumns = taosArrayGetSize(pColumns); - pReq.pColumns = pColumns; - pReq.numOfTags = taosArrayGetSize(pTags); - pReq.pTags = pTags; +int32_t smlSetCTableName(SSmlTableInfo *oneTable) { + smlParseTableName(oneTable->tags, oneTable->childTableName); - code = buildRequest(info->taos->id, "", 0, NULL, false, &pRequest, 0); - if (code != TSDB_CODE_SUCCESS) { - goto end; - } + if (strlen(oneTable->childTableName) == 0) { + SArray *dst = taosArrayDup(oneTable->tags, NULL); + RandTableName rName = {dst, oneTable->sTableName, (uint8_t)oneTable->sTableNameLen, oneTable->childTableName}; - pRequest->syncQuery = true; - if (!pRequest->pDb) { - code = TSDB_CODE_PAR_DB_NOT_SPECIFIED; - goto end; + buildChildTableName(&rName); + taosArrayDestroy(dst); } + return TSDB_CODE_SUCCESS; +} - if (action == SCHEMA_ACTION_CREATE_STABLE) { - pReq.colVer = 1; - pReq.tagVer = 1; - pReq.suid = 0; - pReq.source = TD_REQ_FROM_APP; - } else if (action == SCHEMA_ACTION_ADD_TAG || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) { - pReq.colVer = pTableMeta->sversion; - pReq.tagVer = pTableMeta->tversion + 1; - pReq.suid = pTableMeta->uid; - pReq.source = TD_REQ_FROM_TAOX; - } else if (action == SCHEMA_ACTION_ADD_COLUMN || action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE) { - pReq.colVer = pTableMeta->sversion + 1; - pReq.tagVer = pTableMeta->tversion; - pReq.suid = pTableMeta->uid; - pReq.source = TD_REQ_FROM_TAOX; +void getTableUid(SSmlHandle *info, SSmlLineInfo *currElement, SSmlTableInfo *tinfo){ + char key[TSDB_TABLE_NAME_LEN * 2 + 1] = {0}; + size_t nLen = strlen(tinfo->childTableName); + memcpy(key, currElement->measure, currElement->measureLen); + memcpy(key + currElement->measureLen + 1, tinfo->childTableName, nLen); + void *uid = taosHashGet(info->tableUids, key, currElement->measureLen + 1 + nLen); // use \0 as separator for stable name and child table name + if (uid == NULL) { + tinfo->uid = info->uid++; + taosHashPut(info->tableUids, key, currElement->measureLen + 1 + nLen, &tinfo->uid, sizeof(uint64_t)); + }else{ + tinfo->uid = *(uint64_t*)uid; } +} - if (pReq.numOfTags == 0) { - pReq.numOfTags = 1; - SField field = {0}; - field.type = TSDB_DATA_TYPE_NCHAR; - field.bytes = 1; - strcpy(field.name, tsSmlTagName); - taosArrayPush(pReq.pTags, &field); +SSmlSTableMeta *smlBuildSTableMeta(bool isDataFormat) { + SSmlSTableMeta *meta = (SSmlSTableMeta *)taosMemoryCalloc(sizeof(SSmlSTableMeta), 1); + if (!meta) { + return NULL; } - pReq.commentLen = -1; - pReq.igExists = true; - tNameExtractFullName(pName, pReq.name); + if (unlikely(!isDataFormat)) { + meta->tagHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + if (meta->tagHash == NULL) { + uError("SML:smlBuildSTableMeta failed to allocate memory"); + goto cleanup; + } - pCmdMsg.epSet = getEpSet_s(&info->taos->pAppInfo->mgmtEp); - pCmdMsg.msgType = TDMT_MND_CREATE_STB; - pCmdMsg.msgLen = tSerializeSMCreateStbReq(NULL, 0, &pReq); - pCmdMsg.pMsg = taosMemoryMalloc(pCmdMsg.msgLen); - if (NULL == pCmdMsg.pMsg) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto end; + meta->colHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + if (meta->colHash == NULL) { + uError("SML:smlBuildSTableMeta failed to allocate memory"); + goto cleanup; + } } - tSerializeSMCreateStbReq(pCmdMsg.pMsg, pCmdMsg.msgLen, &pReq); - - SQuery pQuery; - memset(&pQuery, 0, sizeof(pQuery)); - pQuery.execMode = QUERY_EXEC_MODE_RPC; - pQuery.pCmdMsg = &pCmdMsg; - pQuery.msgType = pQuery.pCmdMsg->msgType; - pQuery.stableQuery = true; - launchQueryImpl(pRequest, &pQuery, true, NULL); + meta->tags = taosArrayInit(32, sizeof(SSmlKv)); + if (meta->tags == NULL) { + uError("SML:smlBuildSTableMeta failed to allocate memory"); + goto cleanup; + } - if (pRequest->code == TSDB_CODE_SUCCESS) { - catalogRemoveTableMeta(info->pCatalog, pName); + meta->cols = taosArrayInit(32, sizeof(SSmlKv)); + if (meta->cols == NULL) { + uError("SML:smlBuildSTableMeta failed to allocate memory"); + goto cleanup; } - code = pRequest->code; - taosMemoryFree(pCmdMsg.pMsg); + return meta; -end: - destroyRequest(pRequest); - tFreeSMCreateStbReq(&pReq); - return code; +cleanup: + taosMemoryFree(meta); + return NULL; } -static int32_t smlModifyDBSchemas(SSmlHandle *info) { - int32_t code = 0; - SHashObj *hashTmp = NULL; - STableMeta *pTableMeta = NULL; - - SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}}; - tstrncpy(pName.dbname, info->pRequest->pDb, sizeof(pName.dbname)); - - SRequestConnInfo conn = {0}; - conn.pTrans = info->taos->pAppInfo->pTransporter; - conn.requestId = info->pRequest->requestId; - conn.requestObjRefId = info->pRequest->self; - conn.mgmtEps = getEpSet_s(&info->taos->pAppInfo->mgmtEp); +// uint16_t smlCalTypeSum(char* endptr, int32_t left){ +// uint16_t sum = 0; +// for(int i = 0; i < left; i++){ +// sum += endptr[i]; +// } +// return sum; +// } - SSmlSTableMeta **tableMetaSml = (SSmlSTableMeta **)taosHashIterate(info->superTables, NULL); - while (tableMetaSml) { - SSmlSTableMeta *sTableData = *tableMetaSml; - bool needCheckMeta = false; // for multi thread +#define RETURN_FALSE \ + smlBuildInvalidDataMsg(msg, "invalid data", pVal); \ + return false; - size_t superTableLen = 0; - void *superTable = taosHashGetKey(tableMetaSml, &superTableLen); - memset(pName.tname, 0, TSDB_TABLE_NAME_LEN); - memcpy(pName.tname, superTable, superTableLen); - - code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta); - - if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST || code == TSDB_CODE_MND_STB_NOT_EXIST) { - SArray *pColumns = taosArrayInit(taosArrayGetSize(sTableData->cols), sizeof(SField)); - SArray *pTags = taosArrayInit(taosArrayGetSize(sTableData->tags), sizeof(SField)); - smlBuildFieldsList(info, NULL, NULL, sTableData->tags, pTags, 0, true); - smlBuildFieldsList(info, NULL, NULL, sTableData->cols, pColumns, 0, false); - - code = smlSendMetaMsg(info, &pName, pColumns, pTags, NULL, SCHEMA_ACTION_CREATE_STABLE); - if (code != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlSendMetaMsg failed. can not create %s", info->id, pName.tname); - goto end; - } - info->cost.numOfCreateSTables++; - taosMemoryFreeClear(pTableMeta); - - code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta); - if (code != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " catalogGetSTableMeta failed. super table name %s", info->id, pName.tname); - goto end; - } - } else if (code == TSDB_CODE_SUCCESS) { - hashTmp = taosHashInit(pTableMeta->tableInfo.numOfTags, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, - HASH_NO_LOCK); - for (uint16_t i = pTableMeta->tableInfo.numOfColumns; - i < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; i++) { - taosHashPut(hashTmp, pTableMeta->schema[i].name, strlen(pTableMeta->schema[i].name), &i, SHORT_BYTES); - } - - ESchemaAction action = SCHEMA_ACTION_NULL; - code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->tags, &action, true); - if (code != TSDB_CODE_SUCCESS) { - goto end; - } - if (action != SCHEMA_ACTION_NULL) { - SArray *pColumns = - taosArrayInit(taosArrayGetSize(sTableData->cols) + pTableMeta->tableInfo.numOfColumns, sizeof(SField)); - SArray *pTags = - taosArrayInit(taosArrayGetSize(sTableData->tags) + pTableMeta->tableInfo.numOfTags, sizeof(SField)); - - for (uint16_t i = 0; i < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; i++) { - SField field = {0}; - field.type = pTableMeta->schema[i].type; - field.bytes = pTableMeta->schema[i].bytes; - strcpy(field.name, pTableMeta->schema[i].name); - if (i < pTableMeta->tableInfo.numOfColumns) { - taosArrayPush(pColumns, &field); - } else { - taosArrayPush(pTags, &field); - } - } - smlBuildFieldsList(info, pTableMeta->schema, hashTmp, sTableData->tags, pTags, - pTableMeta->tableInfo.numOfColumns, true); - - code = smlSendMetaMsg(info, &pName, pColumns, pTags, pTableMeta, action); - if (code != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlSendMetaMsg failed. can not create %s", info->id, pName.tname); - goto end; - } - - info->cost.numOfAlterTagSTables++; - taosMemoryFreeClear(pTableMeta); - code = catalogRefreshTableMeta(info->pCatalog, &conn, &pName, -1); - if (code != TSDB_CODE_SUCCESS) { - goto end; - } - code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta); - if (code != TSDB_CODE_SUCCESS) { - goto end; - } - } +#define SET_DOUBLE \ + kvVal->type = TSDB_DATA_TYPE_DOUBLE; \ + kvVal->d = result; + +#define SET_FLOAT \ + if (!IS_VALID_FLOAT(result)) { \ + smlBuildInvalidDataMsg(msg, "float out of range[-3.402823466e+38,3.402823466e+38]", pVal); \ + return false; \ + } \ + kvVal->type = TSDB_DATA_TYPE_FLOAT; \ + kvVal->f = (float)result; + +#define SET_BIGINT \ + errno = 0; \ + int64_t tmp = taosStr2Int64(pVal, &endptr, 10); \ + if (errno == ERANGE) { \ + smlBuildInvalidDataMsg(msg, "big int out of range[-9223372036854775808,9223372036854775807]", pVal); \ + return false; \ + } \ + kvVal->type = TSDB_DATA_TYPE_BIGINT; \ + kvVal->i = tmp; + +#define SET_INT \ + if (!IS_VALID_INT(result)) { \ + smlBuildInvalidDataMsg(msg, "int out of range[-2147483648,2147483647]", pVal); \ + return false; \ + } \ + kvVal->type = TSDB_DATA_TYPE_INT; \ + kvVal->i = result; + +#define SET_SMALL_INT \ + if (!IS_VALID_SMALLINT(result)) { \ + smlBuildInvalidDataMsg(msg, "small int our of range[-32768,32767]", pVal); \ + return false; \ + } \ + kvVal->type = TSDB_DATA_TYPE_SMALLINT; \ + kvVal->i = result; + +#define SET_UBIGINT \ + errno = 0; \ + uint64_t tmp = taosStr2UInt64(pVal, &endptr, 10); \ + if (errno == ERANGE || result < 0) { \ + smlBuildInvalidDataMsg(msg, "unsigned big int out of range[0,18446744073709551615]", pVal); \ + return false; \ + } \ + kvVal->type = TSDB_DATA_TYPE_UBIGINT; \ + kvVal->u = tmp; + +#define SET_UINT \ + if (!IS_VALID_UINT(result)) { \ + smlBuildInvalidDataMsg(msg, "unsigned int out of range[0,4294967295]", pVal); \ + return false; \ + } \ + kvVal->type = TSDB_DATA_TYPE_UINT; \ + kvVal->u = result; + +#define SET_USMALL_INT \ + if (!IS_VALID_USMALLINT(result)) { \ + smlBuildInvalidDataMsg(msg, "unsigned small int out of rang[0,65535]", pVal); \ + return false; \ + } \ + kvVal->type = TSDB_DATA_TYPE_USMALLINT; \ + kvVal->u = result; + +#define SET_TINYINT \ + if (!IS_VALID_TINYINT(result)) { \ + smlBuildInvalidDataMsg(msg, "tiny int out of range[-128,127]", pVal); \ + return false; \ + } \ + kvVal->type = TSDB_DATA_TYPE_TINYINT; \ + kvVal->i = result; + +#define SET_UTINYINT \ + if (!IS_VALID_UTINYINT(result)) { \ + smlBuildInvalidDataMsg(msg, "unsigned tiny int out of range[0,255]", pVal); \ + return false; \ + } \ + kvVal->type = TSDB_DATA_TYPE_UTINYINT; \ + kvVal->u = result; + +bool smlParseNumber(SSmlKv *kvVal, SSmlMsgBuf *msg) { + const char *pVal = kvVal->value; + int32_t len = kvVal->length; + char *endptr = NULL; + double result = taosStr2Double(pVal, &endptr); + if (pVal == endptr) { + RETURN_FALSE + } - taosHashClear(hashTmp); - for (uint16_t i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) { - taosHashPut(hashTmp, pTableMeta->schema[i].name, strlen(pTableMeta->schema[i].name), &i, SHORT_BYTES); + int32_t left = len - (endptr - pVal); + if (left == 0) { + SET_DOUBLE + } else if (left == 3) { + if (endptr[0] == 'f' || endptr[0] == 'F') { + if (endptr[1] == '6' && endptr[2] == '4') { + SET_DOUBLE + } else if (endptr[1] == '3' && endptr[2] == '2') { + SET_FLOAT + } else { + RETURN_FALSE } - action = SCHEMA_ACTION_NULL; - code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->cols, &action, false); - if (code != TSDB_CODE_SUCCESS) { - goto end; + } else if (endptr[0] == 'i' || endptr[0] == 'I') { + if (endptr[1] == '6' && endptr[2] == '4') { + SET_BIGINT + } else if (endptr[1] == '3' && endptr[2] == '2') { + SET_INT + } else if (endptr[1] == '1' && endptr[2] == '6') { + SET_SMALL_INT + } else { + RETURN_FALSE } - if (action != SCHEMA_ACTION_NULL) { - SArray *pColumns = - taosArrayInit(taosArrayGetSize(sTableData->cols) + pTableMeta->tableInfo.numOfColumns, sizeof(SField)); - SArray *pTags = - taosArrayInit(taosArrayGetSize(sTableData->tags) + pTableMeta->tableInfo.numOfTags, sizeof(SField)); - - for (uint16_t i = 0; i < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; i++) { - SField field = {0}; - field.type = pTableMeta->schema[i].type; - field.bytes = pTableMeta->schema[i].bytes; - strcpy(field.name, pTableMeta->schema[i].name); - if (i < pTableMeta->tableInfo.numOfColumns) { - taosArrayPush(pColumns, &field); - } else { - taosArrayPush(pTags, &field); - } - } - - smlBuildFieldsList(info, pTableMeta->schema, hashTmp, sTableData->cols, pColumns, - pTableMeta->tableInfo.numOfColumns, false); - - code = smlSendMetaMsg(info, &pName, pColumns, pTags, pTableMeta, action); - if (code != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlSendMetaMsg failed. can not create %s", info->id, pName.tname); - goto end; - } - - info->cost.numOfAlterColSTables++; - taosMemoryFreeClear(pTableMeta); - code = catalogRefreshTableMeta(info->pCatalog, &conn, &pName, -1); - if (code != TSDB_CODE_SUCCESS) { - goto end; - } - code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta); - if (code != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " catalogGetSTableMeta failed. super table name %s", info->id, pName.tname); - goto end; - } + } else if (endptr[0] == 'u' || endptr[0] == 'U') { + if (endptr[1] == '6' && endptr[2] == '4') { + SET_UBIGINT + } else if (endptr[1] == '3' && endptr[2] == '2') { + SET_UINT + } else if (endptr[1] == '1' && endptr[2] == '6') { + SET_USMALL_INT + } else { + RETURN_FALSE } - - needCheckMeta = true; - taosHashCleanup(hashTmp); - hashTmp = NULL; } else { - uError("SML:0x%" PRIx64 " load table meta error: %s", info->id, tstrerror(code)); - goto end; + RETURN_FALSE } - - if (needCheckMeta) { - code = smlCheckMeta(&(pTableMeta->schema[pTableMeta->tableInfo.numOfColumns]), pTableMeta->tableInfo.numOfTags, - sTableData->tags, true); - if (code != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " check tag failed. super table name %s", info->id, pName.tname); - goto end; + } else if (left == 2) { + if (endptr[0] == 'i' || endptr[0] == 'I') { + if (endptr[1] == '8') { + SET_TINYINT + } else { + RETURN_FALSE } - code = smlCheckMeta(&(pTableMeta->schema[0]), pTableMeta->tableInfo.numOfColumns, sTableData->cols, false); - if (code != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " check cols failed. super table name %s", info->id, pName.tname); - goto end; + } else if (endptr[0] == 'u' || endptr[0] == 'U') { + if (endptr[1] == '8') { + SET_UTINYINT + } else { + RETURN_FALSE } + } else { + RETURN_FALSE } - - sTableData->tableMeta = pTableMeta; - - tableMetaSml = (SSmlSTableMeta **)taosHashIterate(info->superTables, tableMetaSml); + } else if (left == 1) { + if (endptr[0] == 'i' || endptr[0] == 'I') { + SET_BIGINT + } else if (endptr[0] == 'u' || endptr[0] == 'U') { + SET_UBIGINT + } else { + RETURN_FALSE + } + } else { + RETURN_FALSE; } - return 0; - -end: - taosHashCleanup(hashTmp); - taosMemoryFreeClear(pTableMeta); -// catalogRefreshTableMeta(info->pCatalog, &conn, &pName, 1); - return code; + return true; } -static bool smlParseNumber(SSmlKv *kvVal, SSmlMsgBuf *msg) { +bool smlParseNumberOld(SSmlKv *kvVal, SSmlMsgBuf *msg) { const char *pVal = kvVal->value; int32_t len = kvVal->length; char *endptr = NULL; @@ -699,764 +511,547 @@ static bool smlParseNumber(SSmlKv *kvVal, SSmlMsgBuf *msg) { return true; } -static bool smlParseBool(SSmlKv *kvVal) { - const char *pVal = kvVal->value; - int32_t len = kvVal->length; - if ((len == 1) && (pVal[0] == 't' || pVal[0] == 'T')) { - kvVal->i = true; - return true; - } +STableMeta *smlGetMeta(SSmlHandle *info, const void *measure, int32_t measureLen) { + STableMeta *pTableMeta = NULL; - if ((len == 1) && (pVal[0] == 'f' || pVal[0] == 'F')) { - kvVal->i = false; - return true; - } + SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}}; + tstrncpy(pName.dbname, info->pRequest->pDb, sizeof(pName.dbname)); - if ((len == 4) && !strncasecmp(pVal, "true", len)) { - kvVal->i = true; - return true; - } - if ((len == 5) && !strncasecmp(pVal, "false", len)) { - kvVal->i = false; - return true; - } - return false; -} + SRequestConnInfo conn = {0}; + conn.pTrans = info->taos->pAppInfo->pTransporter; + conn.requestId = info->pRequest->requestId; + conn.requestObjRefId = info->pRequest->self; + conn.mgmtEps = getEpSet_s(&info->taos->pAppInfo->mgmtEp); + memset(pName.tname, 0, TSDB_TABLE_NAME_LEN); + memcpy(pName.tname, measure, measureLen); -static bool smlIsBinary(const char *pVal, uint16_t len) { - // binary: "abc" - if (len < 2) { - return false; - } - if (pVal[0] == '"' && pVal[len - 1] == '"') { - return true; + int32_t code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta); + if (code != TSDB_CODE_SUCCESS) { + return NULL; } - return false; + return pTableMeta; } -static bool smlIsNchar(const char *pVal, uint16_t len) { - // nchar: L"abc" - if (len < 3) { - return false; - } - if ((pVal[0] == 'l' || pVal[0] == 'L') && pVal[1] == '"' && pVal[len - 1] == '"') { - return true; - } - return false; -} +static int64_t smlGenId() { + static volatile int64_t linesSmlHandleId = 0; -static int64_t smlGetTimeValue(const char *value, int32_t len, int8_t type) { - char *endPtr = NULL; - int64_t tsInt64 = taosStr2Int64(value, &endPtr, 10); - if (value + len != endPtr) { - return -1; - } - double ts = tsInt64; - switch (type) { - case TSDB_TIME_PRECISION_HOURS: - ts *= NANOSECOND_PER_HOUR; - tsInt64 *= NANOSECOND_PER_HOUR; - break; - case TSDB_TIME_PRECISION_MINUTES: - ts *= NANOSECOND_PER_MINUTE; - tsInt64 *= NANOSECOND_PER_MINUTE; - break; - case TSDB_TIME_PRECISION_SECONDS: - ts *= NANOSECOND_PER_SEC; - tsInt64 *= NANOSECOND_PER_SEC; - break; - case TSDB_TIME_PRECISION_MILLI: - ts *= NANOSECOND_PER_MSEC; - tsInt64 *= NANOSECOND_PER_MSEC; - break; - case TSDB_TIME_PRECISION_MICRO: - ts *= NANOSECOND_PER_USEC; - tsInt64 *= NANOSECOND_PER_USEC; - break; - case TSDB_TIME_PRECISION_NANO: - break; - default: - ASSERT(0); - } - if (ts >= (double)INT64_MAX || ts < 0) { - return -1; - } + int64_t id = 0; + do { + id = atomic_add_fetch_64(&linesSmlHandleId, 1); + } while (id == 0); - return tsInt64; + return id; } -static int8_t smlGetTsTypeByLen(int32_t len) { - if (len == TSDB_TIME_PRECISION_SEC_DIGITS) { - return TSDB_TIME_PRECISION_SECONDS; - } else if (len == TSDB_TIME_PRECISION_MILLI_DIGITS) { - return TSDB_TIME_PRECISION_MILLI; +static int32_t smlGenerateSchemaAction(SSchema *colField, SHashObj *colHash, SSmlKv *kv, bool isTag, + ESchemaAction *action, SSmlHandle *info) { + uint16_t *index = colHash ? (uint16_t *)taosHashGet(colHash, kv->key, kv->keyLen) : NULL; + if (index) { + if (colField[*index].type != kv->type) { + uError("SML:0x%" PRIx64 " point type and db type mismatch. db type: %d, point type: %d, key: %s", info->id, colField[*index].type, kv->type, kv->key); + return TSDB_CODE_SML_INVALID_DATA; + } + + if ((colField[*index].type == TSDB_DATA_TYPE_VARCHAR && + (colField[*index].bytes - VARSTR_HEADER_SIZE) < kv->length) || + (colField[*index].type == TSDB_DATA_TYPE_NCHAR && + ((colField[*index].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE < kv->length))) { + if (isTag) { + *action = SCHEMA_ACTION_CHANGE_TAG_SIZE; + } else { + *action = SCHEMA_ACTION_CHANGE_COLUMN_SIZE; + } + } } else { - return -1; + if (isTag) { + *action = SCHEMA_ACTION_ADD_TAG; + } else { + *action = SCHEMA_ACTION_ADD_COLUMN; + } } + return 0; } -static int8_t smlGetTsTypeByPrecision(int8_t precision) { - switch (precision) { - case TSDB_SML_TIMESTAMP_HOURS: - return TSDB_TIME_PRECISION_HOURS; - case TSDB_SML_TIMESTAMP_MILLI_SECONDS: - return TSDB_TIME_PRECISION_MILLI; - case TSDB_SML_TIMESTAMP_NANO_SECONDS: - case TSDB_SML_TIMESTAMP_NOT_CONFIGURED: - return TSDB_TIME_PRECISION_NANO; - case TSDB_SML_TIMESTAMP_MICRO_SECONDS: - return TSDB_TIME_PRECISION_MICRO; - case TSDB_SML_TIMESTAMP_SECONDS: - return TSDB_TIME_PRECISION_SECONDS; - case TSDB_SML_TIMESTAMP_MINUTES: - return TSDB_TIME_PRECISION_MINUTES; - default: - return -1; +#define BOUNDARY 1024 +static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) { + int32_t result = 1; + if (length >= BOUNDARY){ + result = length; + }else{ + while (result <= length) { + result *= 2; + } } -} - -static int64_t smlParseInfluxTime(SSmlHandle *info, const char *data, int32_t len) { - if (len == 0 || (len == 1 && data[0] == '0')) { - return taosGetTimestampNs(); + if (type == TSDB_DATA_TYPE_BINARY && result > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) { + result = TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE; + } else if (type == TSDB_DATA_TYPE_NCHAR && result > (TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { + result = (TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE; } - int8_t tsType = smlGetTsTypeByPrecision(info->precision); - if (tsType == -1) { - smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp precision", NULL); - return -1; + if (type == TSDB_DATA_TYPE_NCHAR) { + result = result * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE; + } else if (type == TSDB_DATA_TYPE_BINARY) { + result = result + VARSTR_HEADER_SIZE; } + return result; +} - int64_t ts = smlGetTimeValue(data, len, tsType); - if (ts == -1) { - smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", data); - return -1; +static int32_t smlProcessSchemaAction(SSmlHandle *info, SSchema *schemaField, SHashObj *schemaHash, SArray *cols, + ESchemaAction *action, bool isTag) { + int32_t code = TSDB_CODE_SUCCESS; + for (int j = 0; j < taosArrayGetSize(cols); ++j) { + if (j == 0 && !isTag) continue; + SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, j); + code = smlGenerateSchemaAction(schemaField, schemaHash, kv, isTag, action, info); + if (code != TSDB_CODE_SUCCESS) { + return code; + } } - return ts; + return TSDB_CODE_SUCCESS; } -static int64_t smlParseOpenTsdbTime(SSmlHandle *info, const char *data, int32_t len) { - if (!data) { - smlBuildInvalidDataMsg(&info->msgBuf, "timestamp can not be null", NULL); - return -1; - } - if (len == 1 && data[0] == '0') { - return taosGetTimestampNs(); - } - int8_t tsType = smlGetTsTypeByLen(len); - if (tsType == -1) { - smlBuildInvalidDataMsg(&info->msgBuf, - "timestamp precision can only be seconds(10 digits) or milli seconds(13 digits)", data); - return -1; - } - int64_t ts = smlGetTimeValue(data, len, tsType); - if (ts == -1) { - smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", data); - return -1; +static int32_t smlCheckMeta(SSchema *schema, int32_t length, SArray *cols, bool isTag) { + SHashObj *hashTmp = taosHashInit(length, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); + int32_t i = 0; + for (; i < length; i++) { + taosHashPut(hashTmp, schema[i].name, strlen(schema[i].name), &i, SHORT_BYTES); } - return ts; -} -static int32_t smlParseTS(SSmlHandle *info, const char *data, int32_t len, SArray *cols) { - int64_t ts = 0; - if (info->protocol == TSDB_SML_LINE_PROTOCOL) { - // uError("SML:data:%s,len:%d", data, len); - ts = smlParseInfluxTime(info, data, len); - } else if (info->protocol == TSDB_SML_TELNET_PROTOCOL) { - ts = smlParseOpenTsdbTime(info, data, len); + if (isTag) { + i = 0; } else { - ASSERT(0); - } - uDebug("SML:0x%" PRIx64 " smlParseTS:%" PRId64, info->id, ts); - - if (ts <= 0) { - uError("SML:0x%" PRIx64 " smlParseTS error:%" PRId64, info->id, ts); - return TSDB_CODE_INVALID_TIMESTAMP; - } - - // add ts to - SSmlKv *kv = (SSmlKv *)taosMemoryCalloc(sizeof(SSmlKv), 1); - if (!kv) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - kv->key = TS; - kv->keyLen = TS_LEN; - kv->i = ts; - kv->type = TSDB_DATA_TYPE_TIMESTAMP; - kv->length = (int16_t)tDataTypes[kv->type].bytes; - taosArrayPush(cols, &kv); - - return TSDB_CODE_SUCCESS; -} - -static int32_t smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg) { - // binary - if (smlIsBinary(pVal->value, pVal->length)) { - pVal->type = TSDB_DATA_TYPE_BINARY; - pVal->length -= BINARY_ADD_LEN; - if (pVal->length > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) { - return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; - } - pVal->value += (BINARY_ADD_LEN - 1); - return TSDB_CODE_SUCCESS; + i = 1; } - // nchar - if (smlIsNchar(pVal->value, pVal->length)) { - pVal->type = TSDB_DATA_TYPE_NCHAR; - pVal->length -= NCHAR_ADD_LEN; - if (pVal->length > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { - return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + for (; i < taosArrayGetSize(cols); i++) { + SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i); + if (taosHashGet(hashTmp, kv->key, kv->keyLen) == NULL) { + taosHashCleanup(hashTmp); + return -1; } - pVal->value += (NCHAR_ADD_LEN - 1); - return TSDB_CODE_SUCCESS; } + taosHashCleanup(hashTmp); + return 0; +} - // bool - if (smlParseBool(pVal)) { - pVal->type = TSDB_DATA_TYPE_BOOL; - pVal->length = (int16_t)tDataTypes[pVal->type].bytes; - return TSDB_CODE_SUCCESS; - } - // number - if (smlParseNumber(pVal, msg)) { - pVal->length = (int16_t)tDataTypes[pVal->type].bytes; - return TSDB_CODE_SUCCESS; +static int32_t getBytes(uint8_t type, int32_t length) { + if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) { + return smlFindNearestPowerOf2(length, type); + } else { + return tDataTypes[type].bytes; } - - return TSDB_CODE_TSC_INVALID_VALUE; } -static int32_t smlParseInfluxString(const char *sql, const char *sqlEnd, SSmlLineInfo *elements, SSmlMsgBuf *msg) { - if (!sql) return TSDB_CODE_SML_INVALID_DATA; - JUMP_SPACE(sql, sqlEnd) - if (*sql == COMMA) return TSDB_CODE_SML_INVALID_DATA; - elements->measure = sql; - - // parse measure - while (sql < sqlEnd) { - if ((sql != elements->measure) && IS_SLASH_LETTER(sql)) { - MOVE_FORWARD_ONE(sql, sqlEnd - sql); - sqlEnd--; - continue; - } - if (IS_COMMA(sql)) { - break; - } - - if (IS_SPACE(sql)) { - break; +static int32_t smlBuildFieldsList(SSmlHandle *info, SSchema *schemaField, SHashObj *schemaHash, SArray *cols, + SArray *results, int32_t numOfCols, bool isTag) { + for (int j = 0; j < taosArrayGetSize(cols); ++j) { + SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, j); + ESchemaAction action = SCHEMA_ACTION_NULL; + int code = smlGenerateSchemaAction(schemaField, schemaHash, kv, isTag, &action, info); + if (code != 0) { + return code; } - sql++; - } - elements->measureLen = sql - elements->measure; - if (IS_INVALID_TABLE_LEN(elements->measureLen)) { - smlBuildInvalidDataMsg(msg, "measure is empty or too large than 192", NULL); - return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; - } - - // parse tag - if (*sql == SPACE) { - elements->tagsLen = 0; - } else { - if (*sql == COMMA) sql++; - elements->tags = sql; - while (sql < sqlEnd) { - if (IS_SPACE(sql)) { - break; + if (action == SCHEMA_ACTION_ADD_COLUMN || action == SCHEMA_ACTION_ADD_TAG) { + SField field = {0}; + field.type = kv->type; + field.bytes = getBytes(kv->type, kv->length); + memcpy(field.name, kv->key, kv->keyLen); + taosArrayPush(results, &field); + } else if (action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) { + uint16_t *index = (uint16_t *)taosHashGet(schemaHash, kv->key, kv->keyLen); + if (index == NULL) { + uError("smlBuildFieldsList get error, key:%s", kv->key); + return TSDB_CODE_SML_INVALID_DATA; } - sql++; + uint16_t newIndex = *index; + if (isTag) newIndex -= numOfCols; + SField *field = (SField *)taosArrayGet(results, newIndex); + field->bytes = getBytes(kv->type, kv->length); } - elements->tagsLen = sql - elements->tags; } - elements->measureTagsLen = sql - elements->measure; - // parse cols - JUMP_SPACE(sql, sqlEnd) - elements->cols = sql; - bool isInQuote = false; - while (sql < sqlEnd) { - if (IS_QUOTE(sql)) { - isInQuote = !isInQuote; - } - if (!isInQuote && IS_SPACE(sql)) { - break; - } - sql++; - } - if (isInQuote) { - smlBuildInvalidDataMsg(msg, "only one quote", elements->cols); - return TSDB_CODE_SML_INVALID_DATA; + int32_t maxLen = isTag ? TSDB_MAX_TAGS_LEN : TSDB_MAX_BYTES_PER_ROW; + int32_t len = 0; + for (int j = 0; j < taosArrayGetSize(results); ++j) { + SField *field = taosArrayGet(results, j); + len += field->bytes; } - elements->colsLen = sql - elements->cols; - if (elements->colsLen == 0) { - smlBuildInvalidDataMsg(msg, "cols is empty", NULL); - return TSDB_CODE_SML_INVALID_DATA; - } - - // parse timestamp - JUMP_SPACE(sql, sqlEnd) - elements->timestamp = sql; - while (sql < sqlEnd) { - if (isspace(*sql)) { - break; - } - sql++; + if(len > maxLen){ + return isTag ? TSDB_CODE_PAR_INVALID_TAGS_LENGTH : TSDB_CODE_PAR_INVALID_ROW_LENGTH; } - elements->timestampLen = sql - elements->timestamp; return TSDB_CODE_SUCCESS; } -static void smlParseTelnetElement(const char **sql, const char *sqlEnd, const char **data, int32_t *len) { - while (*sql < sqlEnd) { - if (**sql != SPACE && !(*data)) { - *data = *sql; - } else if (**sql == SPACE && *data) { - *len = *sql - *data; - break; - } - (*sql)++; - } -} - -static int32_t smlParseTelnetTags(const char *data, const char *sqlEnd, SArray *cols, char *childTableName, - SHashObj *dumplicateKey, SSmlMsgBuf *msg) { - if (!cols) return TSDB_CODE_OUT_OF_MEMORY; - const char *sql = data; - size_t childTableNameLen = strlen(tsSmlChildTableName); - while (sql < sqlEnd) { - JUMP_SPACE(sql, sqlEnd) - if (*sql == '\0') break; - - const char *key = sql; - int32_t keyLen = 0; - - // parse key - while (sql < sqlEnd) { - if (*sql == SPACE) { - smlBuildInvalidDataMsg(msg, "invalid data", sql); - return TSDB_CODE_SML_INVALID_DATA; - } - if (*sql == EQUAL) { - keyLen = sql - key; - sql++; - break; - } - sql++; - } - - if (IS_INVALID_COL_LEN(keyLen)) { - smlBuildInvalidDataMsg(msg, "invalid key or key is too long than 64", key); - return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; - } - if (smlCheckDuplicateKey(key, keyLen, dumplicateKey)) { - smlBuildInvalidDataMsg(msg, "dumplicate key", key); - return TSDB_CODE_TSC_DUP_NAMES; - } - - // parse value - const char *value = sql; - int32_t valueLen = 0; - while (sql < sqlEnd) { - // parse value - if (*sql == SPACE) { - break; - } - if (*sql == EQUAL) { - smlBuildInvalidDataMsg(msg, "invalid data", sql); - return TSDB_CODE_SML_INVALID_DATA; - } - sql++; - } - valueLen = sql - value; - - if (valueLen == 0) { - smlBuildInvalidDataMsg(msg, "invalid value", value); - return TSDB_CODE_TSC_INVALID_VALUE; - } - - // handle child table name - if (childTableNameLen != 0 && strncmp(key, tsSmlChildTableName, keyLen) == 0) { - memset(childTableName, 0, TSDB_TABLE_NAME_LEN); - strncpy(childTableName, value, (valueLen < TSDB_TABLE_NAME_LEN ? valueLen : TSDB_TABLE_NAME_LEN)); - continue; - } - - if (valueLen > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { - return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; - } +// static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SSmlSTableMeta *sTableData, +// int32_t colVer, int32_t tagVer, int8_t source, uint64_t suid){ +static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns, SArray *pTags, STableMeta *pTableMeta, + ESchemaAction action) { + SRequestObj *pRequest = NULL; + SMCreateStbReq pReq = {0}; + int32_t code = TSDB_CODE_SUCCESS; + SCmdMsgInfo pCmdMsg = {0}; - // add kv to SSmlKv - SSmlKv *kv = (SSmlKv *)taosMemoryCalloc(sizeof(SSmlKv), 1); - if (!kv) return TSDB_CODE_OUT_OF_MEMORY; - kv->key = key; - kv->keyLen = keyLen; - kv->value = value; - kv->length = valueLen; - kv->type = TSDB_DATA_TYPE_NCHAR; + // put front for free + pReq.numOfColumns = taosArrayGetSize(pColumns); + pReq.pColumns = pColumns; + pReq.numOfTags = taosArrayGetSize(pTags); + pReq.pTags = pTags; - taosArrayPush(cols, &kv); + code = buildRequest(info->taos->id, "", 0, NULL, false, &pRequest, 0); + if (code != TSDB_CODE_SUCCESS) { + goto end; } - return TSDB_CODE_SUCCESS; -} - -// format: =[ =] -static int32_t smlParseTelnetString(SSmlHandle *info, const char *sql, const char *sqlEnd, SSmlTableInfo *tinfo, - SArray *cols) { - if (!sql) return TSDB_CODE_SML_INVALID_DATA; - - // parse metric - smlParseTelnetElement(&sql, sqlEnd, &tinfo->sTableName, &tinfo->sTableNameLen); - if (!(tinfo->sTableName) || IS_INVALID_TABLE_LEN(tinfo->sTableNameLen)) { - smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", sql); - return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; + pRequest->syncQuery = true; + if (!pRequest->pDb) { + code = TSDB_CODE_PAR_DB_NOT_SPECIFIED; + goto end; } - // parse timestamp - const char *timestamp = NULL; - int32_t tLen = 0; - smlParseTelnetElement(&sql, sqlEnd, ×tamp, &tLen); - if (!timestamp || tLen == 0) { - smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", sql); - return TSDB_CODE_SML_INVALID_DATA; + if (action == SCHEMA_ACTION_CREATE_STABLE) { + pReq.colVer = 1; + pReq.tagVer = 1; + pReq.suid = 0; + pReq.source = TD_REQ_FROM_APP; + } else if (action == SCHEMA_ACTION_ADD_TAG || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) { + pReq.colVer = pTableMeta->sversion; + pReq.tagVer = pTableMeta->tversion + 1; + pReq.suid = pTableMeta->uid; + pReq.source = TD_REQ_FROM_TAOX; + } else if (action == SCHEMA_ACTION_ADD_COLUMN || action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE) { + pReq.colVer = pTableMeta->sversion + 1; + pReq.tagVer = pTableMeta->tversion; + pReq.suid = pTableMeta->uid; + pReq.source = TD_REQ_FROM_TAOX; } - int32_t ret = smlParseTS(info, timestamp, tLen, cols); - if (ret != TSDB_CODE_SUCCESS) { - smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", sql); - return ret; + if (pReq.numOfTags == 0) { + pReq.numOfTags = 1; + SField field = {0}; + field.type = TSDB_DATA_TYPE_NCHAR; + field.bytes = TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE; + strcpy(field.name, tsSmlTagName); + taosArrayPush(pReq.pTags, &field); } - // parse value - const char *value = NULL; - int32_t valueLen = 0; - smlParseTelnetElement(&sql, sqlEnd, &value, &valueLen); - if (!value || valueLen == 0) { - smlBuildInvalidDataMsg(&info->msgBuf, "invalid value", sql); - return TSDB_CODE_TSC_INVALID_VALUE; - } + pReq.commentLen = -1; + pReq.igExists = true; + tNameExtractFullName(pName, pReq.name); - SSmlKv *kv = (SSmlKv *)taosMemoryCalloc(sizeof(SSmlKv), 1); - if (!kv) return TSDB_CODE_OUT_OF_MEMORY; - taosArrayPush(cols, &kv); - kv->key = VALUE; - kv->keyLen = VALUE_LEN; - kv->value = value; - kv->length = valueLen; - if ((ret = smlParseValue(kv, &info->msgBuf)) != TSDB_CODE_SUCCESS) { - return ret; + pCmdMsg.epSet = getEpSet_s(&info->taos->pAppInfo->mgmtEp); + pCmdMsg.msgType = TDMT_MND_CREATE_STB; + pCmdMsg.msgLen = tSerializeSMCreateStbReq(NULL, 0, &pReq); + pCmdMsg.pMsg = taosMemoryMalloc(pCmdMsg.msgLen); + if (NULL == pCmdMsg.pMsg) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto end; } + tSerializeSMCreateStbReq(pCmdMsg.pMsg, pCmdMsg.msgLen, &pReq); + + SQuery pQuery; + memset(&pQuery, 0, sizeof(pQuery)); + pQuery.execMode = QUERY_EXEC_MODE_RPC; + pQuery.pCmdMsg = &pCmdMsg; + pQuery.msgType = pQuery.pCmdMsg->msgType; + pQuery.stableQuery = true; + + launchQueryImpl(pRequest, &pQuery, true, NULL); - // parse tags - ret = smlParseTelnetTags(sql, sqlEnd, tinfo->tags, tinfo->childTableName, info->dumplicateKey, &info->msgBuf); - if (ret != TSDB_CODE_SUCCESS) { - smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", sql); - return ret; + if (pRequest->code == TSDB_CODE_SUCCESS) { + catalogRemoveTableMeta(info->pCatalog, pName); } + code = pRequest->code; + taosMemoryFree(pCmdMsg.pMsg); - return TSDB_CODE_SUCCESS; +end: + destroyRequest(pRequest); + tFreeSMCreateStbReq(&pReq); + return code; } -static int32_t smlParseCols(const char *data, int32_t len, SArray *cols, char *childTableName, bool isTag, - SHashObj *dumplicateKey, SSmlMsgBuf *msg) { - if (len == 0) { +static int32_t smlModifyDBSchemas(SSmlHandle *info) { + uDebug("SML:0x%" PRIx64 " smlModifyDBSchemas start, format:%d, needModifySchema:%d", info->id, info->dataFormat, + info->needModifySchema); + if (info->dataFormat && !info->needModifySchema) { return TSDB_CODE_SUCCESS; } + int32_t code = 0; + SHashObj *hashTmp = NULL; + STableMeta *pTableMeta = NULL; - size_t childTableNameLen = strlen(tsSmlChildTableName); - const char *sql = data; - while (sql < data + len) { - const char *key = sql; - int32_t keyLen = 0; + SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}}; + tstrncpy(pName.dbname, info->pRequest->pDb, sizeof(pName.dbname)); - while (sql < data + len) { - // parse key - if (IS_COMMA(sql)) { - smlBuildInvalidDataMsg(msg, "invalid data", sql); - return TSDB_CODE_SML_INVALID_DATA; - } - if (IS_EQUAL(sql)) { - keyLen = sql - key; - sql++; - break; - } - sql++; - } + SRequestConnInfo conn = {0}; + conn.pTrans = info->taos->pAppInfo->pTransporter; + conn.requestId = info->pRequest->requestId; + conn.requestObjRefId = info->pRequest->self; + conn.mgmtEps = getEpSet_s(&info->taos->pAppInfo->mgmtEp); - if (IS_INVALID_COL_LEN(keyLen)) { - smlBuildInvalidDataMsg(msg, "invalid key or key is too long than 64", key); - return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; - } - if (smlCheckDuplicateKey(key, keyLen, dumplicateKey)) { - smlBuildInvalidDataMsg(msg, "dumplicate key", key); - return TSDB_CODE_TSC_DUP_NAMES; - } + SSmlSTableMeta **tmp = (SSmlSTableMeta **)taosHashIterate(info->superTables, NULL); + while (tmp) { + SSmlSTableMeta *sTableData = *tmp; + bool needCheckMeta = false; // for multi thread - // parse value - const char *value = sql; - int32_t valueLen = 0; - bool isInQuote = false; - while (sql < data + len) { - // parse value - if (!isTag && IS_QUOTE(sql)) { - isInQuote = !isInQuote; - sql++; - continue; + size_t superTableLen = 0; + void *superTable = taosHashGetKey(tmp, &superTableLen); + char* measure = taosMemoryMalloc(superTableLen); + memcpy(measure, superTable, superTableLen); + PROCESS_SLASH_IN_MEASUREMENT(measure, superTableLen); + memset(pName.tname, 0, TSDB_TABLE_NAME_LEN); + memcpy(pName.tname, measure, superTableLen); + taosMemoryFree(measure); + + code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta); + + if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST || code == TSDB_CODE_MND_STB_NOT_EXIST) { + uDebug("SML:0x%" PRIx64 " smlModifyDBSchemas create table:%s", info->id, pName.tname); + SArray *pColumns = taosArrayInit(taosArrayGetSize(sTableData->cols), sizeof(SField)); + SArray *pTags = taosArrayInit(taosArrayGetSize(sTableData->tags), sizeof(SField)); + code = smlBuildFieldsList(info, NULL, NULL, sTableData->tags, pTags, 0, true); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " smlBuildFieldsList tag1 failed. %s", info->id, pName.tname); + taosArrayDestroy(pColumns); + taosArrayDestroy(pTags); + goto end; } - if (!isInQuote && IS_COMMA(sql)) { - break; + code = smlBuildFieldsList(info, NULL, NULL, sTableData->cols, pColumns, 0, false); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " smlBuildFieldsList col1 failed. %s", info->id, pName.tname); + taosArrayDestroy(pColumns); + taosArrayDestroy(pTags); + goto end; } - if (!isInQuote && IS_EQUAL(sql)) { - smlBuildInvalidDataMsg(msg, "invalid data", sql); - return TSDB_CODE_SML_INVALID_DATA; + code = smlSendMetaMsg(info, &pName, pColumns, pTags, NULL, SCHEMA_ACTION_CREATE_STABLE); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " smlSendMetaMsg failed. can not create %s", info->id, pName.tname); + goto end; } - sql++; - } - valueLen = sql - value; - sql++; - - if (isInQuote) { - smlBuildInvalidDataMsg(msg, "only one quote", value); - return TSDB_CODE_SML_INVALID_DATA; - } - if (valueLen == 0) { - smlBuildInvalidDataMsg(msg, "invalid value", value); - return TSDB_CODE_SML_INVALID_DATA; - } - PROCESS_SLASH(key, keyLen) - PROCESS_SLASH(value, valueLen) - - // handle child table name - if (childTableName && childTableNameLen != 0 && strncmp(key, tsSmlChildTableName, keyLen) == 0) { - memset(childTableName, 0, TSDB_TABLE_NAME_LEN); - strncpy(childTableName, value, (valueLen < TSDB_TABLE_NAME_LEN ? valueLen : TSDB_TABLE_NAME_LEN)); - continue; - } - - // add kv to SSmlKv - SSmlKv *kv = (SSmlKv *)taosMemoryCalloc(sizeof(SSmlKv), 1); - if (!kv) return TSDB_CODE_OUT_OF_MEMORY; - if (cols) taosArrayPush(cols, &kv); + info->cost.numOfCreateSTables++; + taosMemoryFreeClear(pTableMeta); - kv->key = key; - kv->keyLen = keyLen; - kv->value = value; - kv->length = valueLen; - if (isTag) { - if (valueLen > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { - return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " catalogGetSTableMeta failed. super table name %s", info->id, pName.tname); + goto end; } - kv->type = TSDB_DATA_TYPE_NCHAR; - } else { - int32_t ret = smlParseValue(kv, msg); - if (ret != TSDB_CODE_SUCCESS) { - return ret; + } else if (code == TSDB_CODE_SUCCESS) { + hashTmp = taosHashInit(pTableMeta->tableInfo.numOfTags, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, + HASH_NO_LOCK); + for (uint16_t i = pTableMeta->tableInfo.numOfColumns; + i < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; i++) { + taosHashPut(hashTmp, pTableMeta->schema[i].name, strlen(pTableMeta->schema[i].name), &i, SHORT_BYTES); } - } - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols, SSmlMsgBuf *msg) { - for (int i = 0; i < taosArrayGetSize(cols); ++i) { - SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, i); - int16_t *index = (int16_t *)taosHashGet(metaHash, kv->key, kv->keyLen); - if (index) { - SSmlKv **value = (SSmlKv **)taosArrayGet(metaArray, *index); - if (kv->type != (*value)->type) { - smlBuildInvalidDataMsg(msg, "the type is not the same like before", kv->key); - return TSDB_CODE_SML_NOT_SAME_TYPE; - } else { - if (IS_VAR_DATA_TYPE(kv->type)) { // update string len, if bigger - if (kv->length > (*value)->length) { - *value = kv; + ESchemaAction action = SCHEMA_ACTION_NULL; + code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->tags, &action, true); + if (code != TSDB_CODE_SUCCESS) { + goto end; + } + if (action != SCHEMA_ACTION_NULL) { + uDebug("SML:0x%" PRIx64 " smlModifyDBSchemas change table tag, table:%s, action:%d", info->id, pName.tname, + action); + SArray *pColumns = + taosArrayInit(taosArrayGetSize(sTableData->cols) + pTableMeta->tableInfo.numOfColumns, sizeof(SField)); + SArray *pTags = + taosArrayInit(taosArrayGetSize(sTableData->tags) + pTableMeta->tableInfo.numOfTags, sizeof(SField)); + + for (uint16_t i = 0; i < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; i++) { + SField field = {0}; + field.type = pTableMeta->schema[i].type; + field.bytes = pTableMeta->schema[i].bytes; + strcpy(field.name, pTableMeta->schema[i].name); + if (i < pTableMeta->tableInfo.numOfColumns) { + taosArrayPush(pColumns, &field); + } else { + taosArrayPush(pTags, &field); } } - } - } else { - size_t tmp = taosArrayGetSize(metaArray); - ASSERT(tmp <= INT16_MAX); - int16_t size = tmp; - taosArrayPush(metaArray, &kv); - taosHashPut(metaHash, kv->key, kv->keyLen, &size, SHORT_BYTES); - } - } + code = smlBuildFieldsList(info, pTableMeta->schema, hashTmp, sTableData->tags, pTags, + pTableMeta->tableInfo.numOfColumns, true); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " smlBuildFieldsList tag2 failed. %s", info->id, pName.tname); + taosArrayDestroy(pColumns); + taosArrayDestroy(pTags); + goto end; + } - return TSDB_CODE_SUCCESS; -} + if (taosArrayGetSize(pTags) + pTableMeta->tableInfo.numOfColumns > TSDB_MAX_COLUMNS) { + uError("SML:0x%" PRIx64 " too many columns than 4096", info->id); + code = TSDB_CODE_PAR_TOO_MANY_COLUMNS; + taosArrayDestroy(pColumns); + taosArrayDestroy(pTags); + goto end; + } + if (taosArrayGetSize(pTags) > TSDB_MAX_TAGS) { + uError("SML:0x%" PRIx64 " too many tags than 128", info->id); + code = TSDB_CODE_PAR_INVALID_TAGS_NUM; + taosArrayDestroy(pColumns); + taosArrayDestroy(pTags); + goto end; + } -static void smlInsertMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols) { - for (int16_t i = 0; i < taosArrayGetSize(cols); ++i) { - SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, i); - taosArrayPush(metaArray, &kv); - taosHashPut(metaHash, kv->key, kv->keyLen, &i, SHORT_BYTES); - } -} + code = smlSendMetaMsg(info, &pName, pColumns, pTags, pTableMeta, action); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " smlSendMetaMsg failed. can not create %s", info->id, pName.tname); + goto end; + } -static SSmlTableInfo *smlBuildTableInfo() { - SSmlTableInfo *tag = (SSmlTableInfo *)taosMemoryCalloc(sizeof(SSmlTableInfo), 1); - if (!tag) { - return NULL; - } + info->cost.numOfAlterTagSTables++; + taosMemoryFreeClear(pTableMeta); + code = catalogRefreshTableMeta(info->pCatalog, &conn, &pName, -1); + if (code != TSDB_CODE_SUCCESS) { + goto end; + } + code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta); + if (code != TSDB_CODE_SUCCESS) { + goto end; + } + } - tag->cols = taosArrayInit(16, POINTER_BYTES); - if (tag->cols == NULL) { - uError("SML:smlBuildTableInfo failed to allocate memory"); - goto cleanup; - } + taosHashClear(hashTmp); + for (uint16_t i = 0; i < pTableMeta->tableInfo.numOfColumns; i++) { + taosHashPut(hashTmp, pTableMeta->schema[i].name, strlen(pTableMeta->schema[i].name), &i, SHORT_BYTES); + } + action = SCHEMA_ACTION_NULL; + code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->cols, &action, false); + if (code != TSDB_CODE_SUCCESS) { + goto end; + } + if (action != SCHEMA_ACTION_NULL) { + uDebug("SML:0x%" PRIx64 " smlModifyDBSchemas change table col, table:%s, action:%d", info->id, pName.tname, + action); + SArray *pColumns = + taosArrayInit(taosArrayGetSize(sTableData->cols) + pTableMeta->tableInfo.numOfColumns, sizeof(SField)); + SArray *pTags = + taosArrayInit(taosArrayGetSize(sTableData->tags) + pTableMeta->tableInfo.numOfTags, sizeof(SField)); - tag->tags = taosArrayInit(16, POINTER_BYTES); - if (tag->tags == NULL) { - uError("SML:smlBuildTableInfo failed to allocate memory"); - goto cleanup; - } - return tag; + for (uint16_t i = 0; i < pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags; i++) { + SField field = {0}; + field.type = pTableMeta->schema[i].type; + field.bytes = pTableMeta->schema[i].bytes; + strcpy(field.name, pTableMeta->schema[i].name); + if (i < pTableMeta->tableInfo.numOfColumns) { + taosArrayPush(pColumns, &field); + } else { + taosArrayPush(pTags, &field); + } + } -cleanup: - taosMemoryFree(tag); - return NULL; -} + code = smlBuildFieldsList(info, pTableMeta->schema, hashTmp, sTableData->cols, pColumns, + pTableMeta->tableInfo.numOfColumns, false); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " smlBuildFieldsList col2 failed. %s", info->id, pName.tname); + taosArrayDestroy(pColumns); + taosArrayDestroy(pTags); + goto end; + } -static void smlDestroyTableInfo(SSmlHandle *info, SSmlTableInfo *tag) { - if (info->dataFormat) { - for (size_t i = 0; i < taosArrayGetSize(tag->cols); i++) { - SArray *kvArray = (SArray *)taosArrayGetP(tag->cols, i); - for (int j = 0; j < taosArrayGetSize(kvArray); ++j) { - SSmlKv *p = (SSmlKv *)taosArrayGetP(kvArray, j); - taosMemoryFree(p); + if (taosArrayGetSize(pColumns) + pTableMeta->tableInfo.numOfTags > TSDB_MAX_COLUMNS) { + uError("SML:0x%" PRIx64 " too many columns than 4096", info->id); + code = TSDB_CODE_PAR_TOO_MANY_COLUMNS; + taosArrayDestroy(pColumns); + taosArrayDestroy(pTags); + goto end; + } + + code = smlSendMetaMsg(info, &pName, pColumns, pTags, pTableMeta, action); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " smlSendMetaMsg failed. can not create %s", info->id, pName.tname); + goto end; + } + + info->cost.numOfAlterColSTables++; + taosMemoryFreeClear(pTableMeta); + code = catalogRefreshTableMeta(info->pCatalog, &conn, &pName, -1); + if (code != TSDB_CODE_SUCCESS) { + goto end; + } + code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " catalogGetSTableMeta failed. super table name %s", info->id, pName.tname); + goto end; + } } - taosArrayDestroy(kvArray); + + needCheckMeta = true; + taosHashCleanup(hashTmp); + hashTmp = NULL; + } else { + uError("SML:0x%" PRIx64 " load table meta error: %s", info->id, tstrerror(code)); + goto end; } - } else { - for (size_t i = 0; i < taosArrayGetSize(tag->cols); i++) { - SHashObj *kvHash = (SHashObj *)taosArrayGetP(tag->cols, i); - void **p1 = (void **)taosHashIterate(kvHash, NULL); - while (p1) { - taosMemoryFree(*p1); - p1 = (void **)taosHashIterate(kvHash, p1); + + if (needCheckMeta) { + code = smlCheckMeta(&(pTableMeta->schema[pTableMeta->tableInfo.numOfColumns]), pTableMeta->tableInfo.numOfTags, + sTableData->tags, true); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " check tag failed. super table name %s", info->id, pName.tname); + goto end; + } + code = smlCheckMeta(&(pTableMeta->schema[0]), pTableMeta->tableInfo.numOfColumns, sTableData->cols, false); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " check cols failed. super table name %s", info->id, pName.tname); + goto end; } - taosHashCleanup(kvHash); } - } - for (size_t i = 0; i < taosArrayGetSize(tag->tags); i++) { - SSmlKv *p = (SSmlKv *)taosArrayGetP(tag->tags, i); - taosMemoryFree(p); - } - taosArrayDestroy(tag->cols); - taosArrayDestroy(tag->tags); - taosMemoryFree(tag); -} -static int32_t smlKvTimeArrayCompare(const void *key1, const void *key2) { - SArray *s1 = *(SArray **)key1; - SArray *s2 = *(SArray **)key2; - SSmlKv *kv1 = (SSmlKv *)taosArrayGetP(s1, 0); - SSmlKv *kv2 = (SSmlKv *)taosArrayGetP(s2, 0); - ASSERT(kv1->type == TSDB_DATA_TYPE_TIMESTAMP); - ASSERT(kv2->type == TSDB_DATA_TYPE_TIMESTAMP); - if (kv1->i < kv2->i) { - return -1; - } else if (kv1->i > kv2->i) { - return 1; - } else { - return 0; + sTableData->tableMeta = pTableMeta; + uDebug("SML:0x%" PRIx64 "modify schema uid:%" PRIu64 ", sversion:%d, tversion:%d", info->id, pTableMeta->uid, + pTableMeta->sversion, pTableMeta->tversion) tmp = (SSmlSTableMeta **)taosHashIterate(info->superTables, tmp); } -} + uDebug("SML:0x%" PRIx64 " smlModifyDBSchemas end success, format:%d, needModifySchema:%d", info->id, info->dataFormat, + info->needModifySchema); -static int32_t smlKvTimeHashCompare(const void *key1, const void *key2) { - SHashObj *s1 = *(SHashObj **)key1; - SHashObj *s2 = *(SHashObj **)key2; - SSmlKv **kv1pp = (SSmlKv **)taosHashGet(s1, TS, TS_LEN); - SSmlKv **kv2pp = (SSmlKv **)taosHashGet(s2, TS, TS_LEN); - if (!kv1pp || !kv2pp) { - uError("smlKvTimeHashCompare kv is null"); - return -1; - } - SSmlKv *kv1 = *kv1pp; - SSmlKv *kv2 = *kv2pp; - if (!kv1 || kv1->type != TSDB_DATA_TYPE_TIMESTAMP) { - uError("smlKvTimeHashCompare kv1"); - return -1; - } - if (!kv2 || kv2->type != TSDB_DATA_TYPE_TIMESTAMP) { - uError("smlKvTimeHashCompare kv2"); - return -1; - } - if (kv1->i < kv2->i) { - return -1; - } else if (kv1->i > kv2->i) { - return 1; - } else { - return 0; - } -} + return 0; -static int32_t smlDealCols(SSmlTableInfo *oneTable, bool dataFormat, SArray *cols) { - if (dataFormat) { - void *p = taosArraySearch(oneTable->cols, &cols, smlKvTimeArrayCompare, TD_GT); - if (p == NULL) { - taosArrayPush(oneTable->cols, &cols); - } else { - taosArrayInsert(oneTable->cols, TARRAY_ELEM_IDX(oneTable->cols, p), &cols); - } - return TSDB_CODE_SUCCESS; - } +end: + taosHashCleanup(hashTmp); + taosMemoryFreeClear(pTableMeta); + catalogRefreshTableMeta(info->pCatalog, &conn, &pName, 1); + uError("SML:0x%" PRIx64 " smlModifyDBSchemas end failed:%d:%s, format:%d, needModifySchema:%d", info->id, code, + tstrerror(code), info->dataFormat, info->needModifySchema); - SHashObj *kvHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); - if (!kvHash) { - uError("SML:smlDealCols failed to allocate memory"); - return TSDB_CODE_OUT_OF_MEMORY; - } - for (size_t i = 0; i < taosArrayGetSize(cols); i++) { - SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, i); - taosHashPut(kvHash, kv->key, kv->keyLen, &kv, POINTER_BYTES); - } + return code; +} - void *p = taosArraySearch(oneTable->cols, &kvHash, smlKvTimeHashCompare, TD_GT); - if (p == NULL) { - taosArrayPush(oneTable->cols, &kvHash); - } else { - taosArrayInsert(oneTable->cols, TARRAY_ELEM_IDX(oneTable->cols, p), &kvHash); +/* +static int32_t smlCheckDupUnit(SHashObj *dumplicateKey, SArray *tags, SSmlMsgBuf *msg){ + for(int i = 0; i < taosArrayGetSize(tags); i++) { + SSmlKv *tag = taosArrayGet(tags, i); + if (smlCheckDuplicateKey(tag->key, tag->keyLen, dumplicateKey)) { + smlBuildInvalidDataMsg(msg, "dumplicate key", tag->key); + return TSDB_CODE_TSC_DUP_NAMES; + } } return TSDB_CODE_SUCCESS; } -static SSmlSTableMeta *smlBuildSTableMeta() { - SSmlSTableMeta *meta = (SSmlSTableMeta *)taosMemoryCalloc(sizeof(SSmlSTableMeta), 1); - if (!meta) { - return NULL; - } - meta->tagHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); - if (meta->tagHash == NULL) { - uError("SML:smlBuildSTableMeta failed to allocate memory"); - goto cleanup; +static int32_t smlJudgeDupColName(SArray *cols, SArray *tags, SSmlMsgBuf *msg) { + SHashObj *dumplicateKey = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + int ret = smlCheckDupUnit(dumplicateKey, cols, msg); + if(ret != TSDB_CODE_SUCCESS){ + goto end; } - - meta->colHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); - if (meta->colHash == NULL) { - uError("SML:smlBuildSTableMeta failed to allocate memory"); - goto cleanup; + ret = smlCheckDupUnit(dumplicateKey, tags, msg); + if(ret != TSDB_CODE_SUCCESS){ + goto end; } - meta->tags = taosArrayInit(32, POINTER_BYTES); - if (meta->tags == NULL) { - uError("SML:smlBuildSTableMeta failed to allocate memory"); - goto cleanup; - } + end: + taosHashCleanup(dumplicateKey); + return ret; +} +*/ - meta->cols = taosArrayInit(32, POINTER_BYTES); - if (meta->cols == NULL) { - uError("SML:smlBuildSTableMeta failed to allocate memory"); - goto cleanup; +static void smlInsertMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols) { + for (int16_t i = 0; i < taosArrayGetSize(cols); ++i) { + SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i); + int ret = taosHashPut(metaHash, kv->key, kv->keyLen, &i, SHORT_BYTES); + if (ret == 0) { + taosArrayPush(metaArray, kv); + } } - return meta; - -cleanup: - taosMemoryFree(meta); - return NULL; } static void smlDestroySTableMeta(SSmlSTableMeta *meta) { @@ -1468,838 +1063,295 @@ static void smlDestroySTableMeta(SSmlSTableMeta *meta) { taosMemoryFree(meta); } -static void smlDestroyCols(SArray *cols) { - if (!cols) return; +static int32_t smlUpdateMeta(SHashObj *metaHash, SArray *metaArray, SArray *cols, bool isTag, SSmlMsgBuf *msg) { for (int i = 0; i < taosArrayGetSize(cols); ++i) { - void *kv = taosArrayGetP(cols, i); - taosMemoryFree(kv); - } -} - -static void smlDestroyInfo(SSmlHandle *info) { - if (!info) return; - qDestroyQuery(info->pQuery); - smlDestroyHandle(info->exec); - - // destroy info->childTables - void **p1 = (void **)taosHashIterate(info->childTables, NULL); - while (p1) { - smlDestroyTableInfo(info, (SSmlTableInfo *)(*p1)); - p1 = (void **)taosHashIterate(info->childTables, p1); - } - taosHashCleanup(info->childTables); - - // destroy info->superTables - p1 = (void **)taosHashIterate(info->superTables, NULL); - while (p1) { - smlDestroySTableMeta((SSmlSTableMeta *)(*p1)); - p1 = (void **)taosHashIterate(info->superTables, p1); - } - taosHashCleanup(info->superTables); - - // destroy info->pVgHash - taosHashCleanup(info->pVgHash); - taosHashCleanup(info->dumplicateKey); - if (!info->dataFormat) { - taosArrayDestroy(info->colsContainer); - } - - cJSON_Delete(info->root); - taosMemoryFreeClear(info); -} - -static SSmlHandle *smlBuildSmlInfo(STscObj *pTscObj, SRequestObj *request, SMLProtocolType protocol, int8_t precision) { - int32_t code = TSDB_CODE_SUCCESS; - SSmlHandle *info = (SSmlHandle *)taosMemoryCalloc(1, sizeof(SSmlHandle)); - if (NULL == info) { - return NULL; - } - info->id = smlGenId(); - - info->pQuery = (SQuery *)nodesMakeNode(QUERY_NODE_QUERY); - if (NULL == info->pQuery) { - uError("SML:0x%" PRIx64 " create info->pQuery error", info->id); - goto cleanup; - } - info->pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; - info->pQuery->haveResultSet = false; - info->pQuery->msgType = TDMT_VND_SUBMIT; - info->pQuery->pRoot = (SNode *)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); - if (NULL == info->pQuery->pRoot) { - uError("SML:0x%" PRIx64 " create info->pQuery->pRoot error", info->id); - goto cleanup; - } - - if (pTscObj) { - info->taos = pTscObj; - code = catalogGetHandle(info->taos->pAppInfo->clusterId, &info->pCatalog); - if (code != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " get catalog error %d", info->id, code); - goto cleanup; - } - } + SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i); - info->precision = precision; - info->protocol = protocol; - if (protocol == TSDB_SML_LINE_PROTOCOL) { - info->dataFormat = tsSmlDataFormat; - } else { - info->dataFormat = true; - } - - if (request) { - info->pRequest = request; - info->msgBuf.buf = info->pRequest->msgBuf; - info->msgBuf.len = ERROR_MSG_BUF_DEFAULT_SIZE; - info->pRequest->stmtType = info->pQuery->pRoot->type; - } - - info->exec = smlInitHandle(info->pQuery); - info->childTables = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); - info->superTables = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); - info->pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); - - info->dumplicateKey = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); - if (!info->dataFormat) { - info->colsContainer = taosArrayInit(32, POINTER_BYTES); - if (NULL == info->colsContainer) { - uError("SML:0x%" PRIx64 " create info failed", info->id); - goto cleanup; - } - } - if (NULL == info->exec || NULL == info->childTables || NULL == info->superTables || NULL == info->pVgHash || - NULL == info->dumplicateKey) { - uError("SML:0x%" PRIx64 " create info failed", info->id); - goto cleanup; - } - - return info; -cleanup: - smlDestroyInfo(info); - return NULL; -} - -/************* TSDB_SML_JSON_PROTOCOL function start **************/ -static int32_t smlParseMetricFromJSON(SSmlHandle *info, cJSON *root, SSmlTableInfo *tinfo) { - cJSON *metric = cJSON_GetObjectItem(root, "metric"); - if (!cJSON_IsString(metric)) { - return TSDB_CODE_TSC_INVALID_JSON; - } - - tinfo->sTableNameLen = strlen(metric->valuestring); - if (IS_INVALID_TABLE_LEN(tinfo->sTableNameLen)) { - uError("OTD:0x%" PRIx64 " Metric lenght is 0 or large than 192", info->id); - return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; - } - - tinfo->sTableName = metric->valuestring; - return TSDB_CODE_SUCCESS; -} - -static int32_t smlParseTSFromJSONObj(SSmlHandle *info, cJSON *root, int64_t *tsVal) { - int32_t size = cJSON_GetArraySize(root); - if (size != OTD_JSON_SUB_FIELDS_NUM) { - return TSDB_CODE_TSC_INVALID_JSON; - } - - cJSON *value = cJSON_GetObjectItem(root, "value"); - if (!cJSON_IsNumber(value)) { - return TSDB_CODE_TSC_INVALID_JSON; - } - - cJSON *type = cJSON_GetObjectItem(root, "type"); - if (!cJSON_IsString(type)) { - return TSDB_CODE_TSC_INVALID_JSON; - } - - double timeDouble = value->valuedouble; - if (smlDoubleToInt64OverFlow(timeDouble)) { - smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); - return TSDB_CODE_INVALID_TIMESTAMP; - } - - if (timeDouble == 0) { - *tsVal = taosGetTimestampNs(); - return TSDB_CODE_SUCCESS; - } - - if (timeDouble < 0) { - return TSDB_CODE_INVALID_TIMESTAMP; - } - - *tsVal = timeDouble; - size_t typeLen = strlen(type->valuestring); - if (typeLen == 1 && (type->valuestring[0] == 's' || type->valuestring[0] == 'S')) { - // seconds - *tsVal = *tsVal * NANOSECOND_PER_SEC; - timeDouble = timeDouble * NANOSECOND_PER_SEC; - if (smlDoubleToInt64OverFlow(timeDouble)) { - smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); - return TSDB_CODE_INVALID_TIMESTAMP; - } - } else if (typeLen == 2 && (type->valuestring[1] == 's' || type->valuestring[1] == 'S')) { - switch (type->valuestring[0]) { - case 'm': - case 'M': - // milliseconds - *tsVal = *tsVal * NANOSECOND_PER_MSEC; - timeDouble = timeDouble * NANOSECOND_PER_MSEC; - if (smlDoubleToInt64OverFlow(timeDouble)) { - smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); - return TSDB_CODE_INVALID_TIMESTAMP; - } - break; - case 'u': - case 'U': - // microseconds - *tsVal = *tsVal * NANOSECOND_PER_USEC; - timeDouble = timeDouble * NANOSECOND_PER_USEC; - if (smlDoubleToInt64OverFlow(timeDouble)) { - smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); - return TSDB_CODE_INVALID_TIMESTAMP; + int16_t *index = (int16_t *)taosHashGet(metaHash, kv->key, kv->keyLen); + if (index) { + SSmlKv *value = (SSmlKv *)taosArrayGet(metaArray, *index); + if (isTag) { + if (kv->length > value->length) { + value->length = kv->length; } - break; - case 'n': - case 'N': - break; - default: - return TSDB_CODE_TSC_INVALID_JSON; - } - } else { - return TSDB_CODE_TSC_INVALID_JSON; - } - - return TSDB_CODE_SUCCESS; -} - -static uint8_t smlGetTimestampLen(int64_t num) { - uint8_t len = 0; - while ((num /= 10) != 0) { - len++; - } - len++; - return len; -} - -static int32_t smlParseTSFromJSON(SSmlHandle *info, cJSON *root, SArray *cols) { - // Timestamp must be the first KV to parse - int64_t tsVal = 0; - - cJSON *timestamp = cJSON_GetObjectItem(root, "timestamp"); - if (cJSON_IsNumber(timestamp)) { - // timestamp value 0 indicates current system time - double timeDouble = timestamp->valuedouble; - if (smlDoubleToInt64OverFlow(timeDouble)) { - smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); - return TSDB_CODE_INVALID_TIMESTAMP; - } - - if (timeDouble < 0) { - return TSDB_CODE_INVALID_TIMESTAMP; - } - - uint8_t tsLen = smlGetTimestampLen((int64_t)timeDouble); - tsVal = (int64_t)timeDouble; - if (tsLen == TSDB_TIME_PRECISION_SEC_DIGITS) { - tsVal = tsVal * NANOSECOND_PER_SEC; - timeDouble = timeDouble * NANOSECOND_PER_SEC; - if (smlDoubleToInt64OverFlow(timeDouble)) { - smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); - return TSDB_CODE_INVALID_TIMESTAMP; + continue; } - } else if (tsLen == TSDB_TIME_PRECISION_MILLI_DIGITS) { - tsVal = tsVal * NANOSECOND_PER_MSEC; - timeDouble = timeDouble * NANOSECOND_PER_MSEC; - if (smlDoubleToInt64OverFlow(timeDouble)) { - smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); - return TSDB_CODE_INVALID_TIMESTAMP; + if (kv->type != value->type) { + smlBuildInvalidDataMsg(msg, "the type is not the same like before", kv->key); + return TSDB_CODE_SML_NOT_SAME_TYPE; } - } else if (timeDouble == 0) { - tsVal = taosGetTimestampNs(); - } else { - return TSDB_CODE_INVALID_TIMESTAMP; - } - } else if (cJSON_IsObject(timestamp)) { - int32_t ret = smlParseTSFromJSONObj(info, timestamp, &tsVal); - if (ret != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " Failed to parse timestamp from JSON Obj", info->id); - return ret; - } - } else { - return TSDB_CODE_TSC_INVALID_JSON; - } - - // add ts to - SSmlKv *kv = (SSmlKv *)taosMemoryCalloc(sizeof(SSmlKv), 1); - if (!kv) { - return TSDB_CODE_OUT_OF_MEMORY; - } - kv->key = TS; - kv->keyLen = TS_LEN; - kv->i = tsVal; - kv->type = TSDB_DATA_TYPE_TIMESTAMP; - kv->length = (int16_t)tDataTypes[kv->type].bytes; - taosArrayPush(cols, &kv); - return TSDB_CODE_SUCCESS; -} - -static int32_t smlConvertJSONBool(SSmlKv *pVal, char *typeStr, cJSON *value) { - if (strcasecmp(typeStr, "bool") != 0) { - uError("OTD:invalid type(%s) for JSON Bool", typeStr); - return TSDB_CODE_TSC_INVALID_JSON_TYPE; - } - pVal->type = TSDB_DATA_TYPE_BOOL; - pVal->length = (int16_t)tDataTypes[pVal->type].bytes; - pVal->i = value->valueint; - - return TSDB_CODE_SUCCESS; -} - -static int32_t smlConvertJSONNumber(SSmlKv *pVal, char *typeStr, cJSON *value) { - // tinyint - if (strcasecmp(typeStr, "i8") == 0 || strcasecmp(typeStr, "tinyint") == 0) { - if (!IS_VALID_TINYINT(value->valuedouble)) { - uError("OTD:JSON value(%f) cannot fit in type(tinyint)", value->valuedouble); - return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; - } - pVal->type = TSDB_DATA_TYPE_TINYINT; - pVal->length = (int16_t)tDataTypes[pVal->type].bytes; - pVal->i = value->valuedouble; - return TSDB_CODE_SUCCESS; - } - // smallint - if (strcasecmp(typeStr, "i16") == 0 || strcasecmp(typeStr, "smallint") == 0) { - if (!IS_VALID_SMALLINT(value->valuedouble)) { - uError("OTD:JSON value(%f) cannot fit in type(smallint)", value->valuedouble); - return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; - } - pVal->type = TSDB_DATA_TYPE_SMALLINT; - pVal->length = (int16_t)tDataTypes[pVal->type].bytes; - pVal->i = value->valuedouble; - return TSDB_CODE_SUCCESS; - } - // int - if (strcasecmp(typeStr, "i32") == 0 || strcasecmp(typeStr, "int") == 0) { - if (!IS_VALID_INT(value->valuedouble)) { - uError("OTD:JSON value(%f) cannot fit in type(int)", value->valuedouble); - return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; - } - pVal->type = TSDB_DATA_TYPE_INT; - pVal->length = (int16_t)tDataTypes[pVal->type].bytes; - pVal->i = value->valuedouble; - return TSDB_CODE_SUCCESS; - } - // bigint - if (strcasecmp(typeStr, "i64") == 0 || strcasecmp(typeStr, "bigint") == 0) { - pVal->type = TSDB_DATA_TYPE_BIGINT; - pVal->length = (int16_t)tDataTypes[pVal->type].bytes; - if (value->valuedouble >= (double)INT64_MAX) { - pVal->i = INT64_MAX; - } else if (value->valuedouble <= (double)INT64_MIN) { - pVal->i = INT64_MIN; - } else { - pVal->i = value->valuedouble; - } - return TSDB_CODE_SUCCESS; - } - // float - if (strcasecmp(typeStr, "f32") == 0 || strcasecmp(typeStr, "float") == 0) { - if (!IS_VALID_FLOAT(value->valuedouble)) { - uError("OTD:JSON value(%f) cannot fit in type(float)", value->valuedouble); - return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; - } - pVal->type = TSDB_DATA_TYPE_FLOAT; - pVal->length = (int16_t)tDataTypes[pVal->type].bytes; - pVal->f = value->valuedouble; - return TSDB_CODE_SUCCESS; - } - // double - if (strcasecmp(typeStr, "f64") == 0 || strcasecmp(typeStr, "double") == 0) { - pVal->type = TSDB_DATA_TYPE_DOUBLE; - pVal->length = (int16_t)tDataTypes[pVal->type].bytes; - pVal->d = value->valuedouble; - return TSDB_CODE_SUCCESS; - } - // if reach here means type is unsupported - uError("OTD:invalid type(%s) for JSON Number", typeStr); - return TSDB_CODE_TSC_INVALID_JSON_TYPE; -} - -static int32_t smlConvertJSONString(SSmlKv *pVal, char *typeStr, cJSON *value) { - if (strcasecmp(typeStr, "binary") == 0) { - pVal->type = TSDB_DATA_TYPE_BINARY; - } else if (strcasecmp(typeStr, "nchar") == 0) { - pVal->type = TSDB_DATA_TYPE_NCHAR; - } else { - uError("OTD:invalid type(%s) for JSON String", typeStr); - return TSDB_CODE_TSC_INVALID_JSON_TYPE; - } - pVal->length = (int16_t)strlen(value->valuestring); - - if (pVal->type == TSDB_DATA_TYPE_BINARY && pVal->length > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) { - return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; - } - if (pVal->type == TSDB_DATA_TYPE_NCHAR && - pVal->length > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { - return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; - } - - pVal->value = value->valuestring; - return TSDB_CODE_SUCCESS; -} - -static int32_t smlParseValueFromJSONObj(cJSON *root, SSmlKv *kv) { - int32_t ret = TSDB_CODE_SUCCESS; - int32_t size = cJSON_GetArraySize(root); - - if (size != OTD_JSON_SUB_FIELDS_NUM) { - return TSDB_CODE_TSC_INVALID_JSON; - } - - cJSON *value = cJSON_GetObjectItem(root, "value"); - if (value == NULL) { - return TSDB_CODE_TSC_INVALID_JSON; - } - - cJSON *type = cJSON_GetObjectItem(root, "type"); - if (!cJSON_IsString(type)) { - return TSDB_CODE_TSC_INVALID_JSON; - } - - switch (value->type) { - case cJSON_True: - case cJSON_False: { - ret = smlConvertJSONBool(kv, type->valuestring, value); - if (ret != TSDB_CODE_SUCCESS) { - return ret; - } - break; - } - case cJSON_Number: { - ret = smlConvertJSONNumber(kv, type->valuestring, value); - if (ret != TSDB_CODE_SUCCESS) { - return ret; + if (IS_VAR_DATA_TYPE(kv->type) && (kv->length > value->length)) { // update string len, if bigger + value->length = kv->length; } - break; - } - case cJSON_String: { - ret = smlConvertJSONString(kv, type->valuestring, value); - if (ret != TSDB_CODE_SUCCESS) { - return ret; + } else { + size_t tmp = taosArrayGetSize(metaArray); + if (tmp > INT16_MAX) { + smlBuildInvalidDataMsg(msg, "too many cols or tags", kv->key); + uError("too many cols or tags"); + return TSDB_CODE_SML_INVALID_DATA; } - break; - } - default: - return TSDB_CODE_TSC_INVALID_JSON_TYPE; - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t smlParseValueFromJSON(cJSON *root, SSmlKv *kv) { - switch (root->type) { - case cJSON_True: - case cJSON_False: { - kv->type = TSDB_DATA_TYPE_BOOL; - kv->length = (int16_t)tDataTypes[kv->type].bytes; - kv->i = root->valueint; - break; - } - case cJSON_Number: { - kv->type = TSDB_DATA_TYPE_DOUBLE; - kv->length = (int16_t)tDataTypes[kv->type].bytes; - kv->d = root->valuedouble; - break; - } - case cJSON_String: { - /* set default JSON type to binary/nchar according to - * user configured parameter tsDefaultJSONStrType - */ - - char *tsDefaultJSONStrType = "nchar"; // todo - smlConvertJSONString(kv, tsDefaultJSONStrType, root); - break; - } - case cJSON_Object: { - int32_t ret = smlParseValueFromJSONObj(root, kv); - if (ret != TSDB_CODE_SUCCESS) { - uError("OTD:Failed to parse value from JSON Obj"); - return ret; + int16_t size = tmp; + int ret = taosHashPut(metaHash, kv->key, kv->keyLen, &size, SHORT_BYTES); + if (ret == 0) { + taosArrayPush(metaArray, kv); } - break; } - default: - return TSDB_CODE_TSC_INVALID_JSON; } return TSDB_CODE_SUCCESS; } -static int32_t smlParseColsFromJSON(cJSON *root, SArray *cols) { - if (!cols) return TSDB_CODE_OUT_OF_MEMORY; - cJSON *metricVal = cJSON_GetObjectItem(root, "value"); - if (metricVal == NULL) { - return TSDB_CODE_TSC_INVALID_JSON; +void smlDestroyTableInfo(SSmlHandle *info, SSmlTableInfo *tag) { + for (size_t i = 0; i < taosArrayGetSize(tag->cols); i++) { + SHashObj *kvHash = (SHashObj *)taosArrayGetP(tag->cols, i); + taosHashCleanup(kvHash); } - SSmlKv *kv = (SSmlKv *)taosMemoryCalloc(sizeof(SSmlKv), 1); - if (!kv) { - return TSDB_CODE_OUT_OF_MEMORY; - } - taosArrayPush(cols, &kv); + // if (info->parseJsonByLib) { + // SSmlLineInfo *key = (SSmlLineInfo *)(tag->key); + // if (key != NULL) taosMemoryFree(key->tags); + // } + // taosMemoryFree(tag->key); + taosArrayDestroy(tag->cols); + taosArrayDestroyEx(tag->tags, freeSSmlKv); + taosMemoryFree(tag); +} - kv->key = VALUE; - kv->keyLen = VALUE_LEN; - int32_t ret = smlParseValueFromJSON(metricVal, kv); - if (ret != TSDB_CODE_SUCCESS) { - return ret; +void clearColValArray(SArray *pCols) { + int32_t num = taosArrayGetSize(pCols); + for (int32_t i = 0; i < num; ++i) { + SColVal *pCol = taosArrayGet(pCols, i); + if (TSDB_DATA_TYPE_NCHAR == pCol->type) { + taosMemoryFreeClear(pCol->value.pData); + } } - return TSDB_CODE_SUCCESS; } -static int32_t smlParseTagsFromJSON(cJSON *root, SArray *pKVs, char *childTableName, SHashObj *dumplicateKey, - SSmlMsgBuf *msg) { - int32_t ret = TSDB_CODE_SUCCESS; - if (!pKVs) { - return TSDB_CODE_OUT_OF_MEMORY; +void freeSSmlKv(void* data){ + SSmlKv *kv = (SSmlKv*)data; + if(kv->keyEscaped) taosMemoryFree((void*)(kv->key)); + if(kv->valueEscaped) taosMemoryFree((void*)(kv->value)); +} + +void smlDestroyInfo(SSmlHandle *info) { + if (!info) return; + qDestroyQuery(info->pQuery); + + // destroy info->childTables + SSmlTableInfo **oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, NULL); + while (oneTable) { + smlDestroyTableInfo(info, *oneTable); + oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, oneTable); } - cJSON *tags = cJSON_GetObjectItem(root, "tags"); - if (tags == NULL || tags->type != cJSON_Object) { - return TSDB_CODE_TSC_INVALID_JSON; + + // destroy info->superTables + SSmlSTableMeta **oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, NULL); + while (oneSTable) { + smlDestroySTableMeta(*oneSTable); + oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, oneSTable); } - size_t childTableNameLen = strlen(tsSmlChildTableName); - int32_t tagNum = cJSON_GetArraySize(tags); - for (int32_t i = 0; i < tagNum; ++i) { - cJSON *tag = cJSON_GetArrayItem(tags, i); - if (tag == NULL) { - return TSDB_CODE_TSC_INVALID_JSON; - } - size_t keyLen = strlen(tag->string); - if (IS_INVALID_COL_LEN(keyLen)) { - uError("OTD:Tag key length is 0 or too large than 64"); - return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; - } - // check duplicate keys - if (smlCheckDuplicateKey(tag->string, keyLen, dumplicateKey)) { - return TSDB_CODE_TSC_DUP_NAMES; - } + // destroy info->pVgHash + taosHashCleanup(info->pVgHash); + taosHashCleanup(info->childTables); + taosHashCleanup(info->superTables); + taosHashCleanup(info->tableUids); - // handle child table name - if (childTableNameLen != 0 && strcmp(tag->string, tsSmlChildTableName) == 0) { - if (!cJSON_IsString(tag)) { - uError("OTD:ID must be JSON string"); - return TSDB_CODE_TSC_INVALID_JSON; - } - memset(childTableName, 0, TSDB_TABLE_NAME_LEN); - tstrncpy(childTableName, tag->valuestring, TSDB_TABLE_NAME_LEN); - continue; - } + for (int i = 0; i < taosArrayGetSize(info->tagJsonArray); i++) { + cJSON *tags = (cJSON *)taosArrayGetP(info->tagJsonArray, i); + cJSON_Delete(tags); + } + taosArrayDestroy(info->tagJsonArray); - // add kv to SSmlKv - SSmlKv *kv = (SSmlKv *)taosMemoryCalloc(sizeof(SSmlKv), 1); - if (!kv) return TSDB_CODE_OUT_OF_MEMORY; - taosArrayPush(pKVs, &kv); + for (int i = 0; i < taosArrayGetSize(info->valueJsonArray); i++) { + cJSON *value = (cJSON *)taosArrayGetP(info->valueJsonArray, i); + cJSON_Delete(value); + } + taosArrayDestroy(info->valueJsonArray); - // key - kv->keyLen = keyLen; - kv->key = tag->string; + taosArrayDestroyEx(info->preLineTagKV, freeSSmlKv); - // value - ret = smlParseValueFromJSON(tag, kv); - if (ret != TSDB_CODE_SUCCESS) { - return ret; + if (!info->dataFormat) { + for (int i = 0; i < info->lineNum; i++) { + taosArrayDestroyEx(info->lines[i].colArray, freeSSmlKv); + if (info->parseJsonByLib) { + taosMemoryFree(info->lines[i].tags); + } + if (info->lines[i].measureTagsLen != 0) taosMemoryFree(info->lines[i].measureTag); } + taosMemoryFree(info->lines); } - return ret; + cJSON_Delete(info->root); + taosMemoryFreeClear(info); } -static int32_t smlParseJSONString(SSmlHandle *info, cJSON *root, SSmlTableInfo *tinfo, SArray *cols) { - int32_t ret = TSDB_CODE_SUCCESS; - - if (!cJSON_IsObject(root)) { - uError("OTD:0x%" PRIx64 " data point needs to be JSON object", info->id); - return TSDB_CODE_TSC_INVALID_JSON; +SSmlHandle *smlBuildSmlInfo(TAOS *taos) { + int32_t code = TSDB_CODE_SUCCESS; + SSmlHandle *info = (SSmlHandle *)taosMemoryCalloc(1, sizeof(SSmlHandle)); + if (NULL == info) { + return NULL; } - - int32_t size = cJSON_GetArraySize(root); - // outmost json fields has to be exactly 4 - if (size != OTD_JSON_FIELDS_NUM) { - uError("OTD:0x%" PRIx64 " Invalid number of JSON fields in data point %d", info->id, size); - return TSDB_CODE_TSC_INVALID_JSON; + if (taos != NULL) { + info->taos = acquireTscObj(*(int64_t *)taos); + if (info->taos == NULL) { + goto cleanup; + } + code = catalogGetHandle(info->taos->pAppInfo->clusterId, &info->pCatalog); + if (code != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " get catalog error %d", info->id, code); + goto cleanup; + } } - // Parse metric - ret = smlParseMetricFromJSON(info, root, tinfo); - if (ret != TSDB_CODE_SUCCESS) { - uError("OTD:0x%" PRIx64 " Unable to parse metric from JSON payload", info->id); - return ret; - } - uDebug("OTD:0x%" PRIx64 " Parse metric from JSON payload finished", info->id); + info->pVgHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); + info->childTables = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); + info->tableUids = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); + info->superTables = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); - // Parse timestamp - ret = smlParseTSFromJSON(info, root, cols); - if (ret) { - uError("OTD:0x%" PRIx64 " Unable to parse timestamp from JSON payload", info->id); - return ret; - } - uDebug("OTD:0x%" PRIx64 " Parse timestamp from JSON payload finished", info->id); + info->id = smlGenId(); + info->pQuery = smlInitHandle(); + info->dataFormat = true; - // Parse metric value - ret = smlParseColsFromJSON(root, cols); - if (ret) { - uError("OTD:0x%" PRIx64 " Unable to parse metric value from JSON payload", info->id); - return ret; - } - uDebug("OTD:0x%" PRIx64 " Parse metric value from JSON payload finished", info->id); + info->tagJsonArray = taosArrayInit(8, POINTER_BYTES); + info->valueJsonArray = taosArrayInit(8, POINTER_BYTES); + info->preLineTagKV = taosArrayInit(8, sizeof(SSmlKv)); - // Parse tags - ret = smlParseTagsFromJSON(root, tinfo->tags, tinfo->childTableName, info->dumplicateKey, &info->msgBuf); - if (ret) { - uError("OTD:0x%" PRIx64 " Unable to parse tags from JSON payload", info->id); - return ret; + if (NULL == info->pVgHash || NULL == info->childTables || NULL == info->superTables || NULL == info->tableUids) { + uError("create SSmlHandle failed"); + goto cleanup; } - uDebug("OTD:0x%" PRIx64 " Parse tags from JSON payload finished", info->id); - return TSDB_CODE_SUCCESS; -} -/************* TSDB_SML_JSON_PROTOCOL function end **************/ + return info; -static int32_t smlParseInfluxLine(SSmlHandle *info, const char *sql, const int len) { - SSmlLineInfo elements = {0}; - uDebug("SML:0x%" PRIx64 " smlParseInfluxLine raw:%d, len:%d, sql:%s", info->id, info->isRawLine, len, (info->isRawLine ? "rawdata" : sql)); +cleanup: + smlDestroyInfo(info); + return NULL; +} - int ret = smlParseInfluxString(sql, sql + len, &elements, &info->msgBuf); - if (ret != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlParseInfluxLine failed", info->id); - return ret; +static int32_t smlPushCols(SArray *colsArray, SArray *cols) { + SHashObj *kvHash = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + if (!kvHash) { + uError("SML:smlDealCols failed to allocate memory"); + return TSDB_CODE_OUT_OF_MEMORY; } - - SArray *cols = NULL; - if (info->dataFormat) { // if dataFormat, cols need new memory to save data - cols = taosArrayInit(16, POINTER_BYTES); - if (cols == NULL) { - uError("SML:0x%" PRIx64 " smlParseInfluxLine failed to allocate memory", info->id); - return TSDB_CODE_OUT_OF_MEMORY; + for (size_t i = 0; i < taosArrayGetSize(cols); i++) { + SSmlKv *kv = (SSmlKv *)taosArrayGet(cols, i); + terrno = 0; + taosHashPut(kvHash, kv->key, kv->keyLen, &kv, POINTER_BYTES); + if (terrno == TSDB_CODE_DUP_KEY) { + taosHashCleanup(kvHash); + return terrno; } - } else { // if dataFormat is false, cols do not need to save data, there is another new memory to save data - cols = info->colsContainer; } - ret = smlParseTS(info, elements.timestamp, elements.timestampLen, cols); - if (ret != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlParseTS failed", info->id); - if (info->dataFormat) taosArrayDestroy(cols); - return ret; - } - ret = smlParseCols(elements.cols, elements.colsLen, cols, NULL, false, info->dumplicateKey, &info->msgBuf); - if (ret != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlParseCols parse cloums fields failed", info->id); - smlDestroyCols(cols); - if (info->dataFormat) taosArrayDestroy(cols); - return ret; - } + taosArrayPush(colsArray, &kvHash); + return TSDB_CODE_SUCCESS; +} - bool hasTable = true; - SSmlTableInfo *tinfo = NULL; - SSmlTableInfo **oneTable = - (SSmlTableInfo **)taosHashGet(info->childTables, elements.measure, elements.measureTagsLen); - if (!oneTable) { - tinfo = smlBuildTableInfo(); - if (!tinfo) { - smlDestroyCols(cols); - if (info->dataFormat) taosArrayDestroy(cols); - return TSDB_CODE_OUT_OF_MEMORY; - } - taosHashPut(info->childTables, elements.measure, elements.measureTagsLen, &tinfo, POINTER_BYTES); - oneTable = &tinfo; - hasTable = false; - } +static int32_t smlParseLineBottom(SSmlHandle *info) { + uDebug("SML:0x%" PRIx64 " smlParseLineBottom start, format:%d, linenum:%d", info->id, info->dataFormat, + info->lineNum); + if (info->dataFormat) return TSDB_CODE_SUCCESS; - ret = smlDealCols(*oneTable, info->dataFormat, cols); - if (ret != TSDB_CODE_SUCCESS) { - return ret; - } + for (int32_t i = 0; i < info->lineNum; i++) { + SSmlLineInfo *elements = info->lines + i; + SSmlTableInfo *tinfo = NULL; + if (info->protocol == TSDB_SML_LINE_PROTOCOL) { + SSmlTableInfo **tmp = + (SSmlTableInfo **)taosHashGet(info->childTables, elements->measure, elements->measureTagsLen); + if (tmp) tinfo = *tmp; + } else if (info->protocol == TSDB_SML_TELNET_PROTOCOL) { + SSmlTableInfo **tmp = (SSmlTableInfo **)taosHashGet(info->childTables, elements->measureTag, + elements->measureLen + elements->tagsLen); + if (tmp) tinfo = *tmp; + } else { + SSmlTableInfo **tmp = (SSmlTableInfo **)taosHashGet(info->childTables, elements->measureTag, + elements->measureLen + elements->tagsLen); + if (tmp) tinfo = *tmp; + } - if (!hasTable) { - ret = smlParseCols(elements.tags, elements.tagsLen, (*oneTable)->tags, (*oneTable)->childTableName, true, - info->dumplicateKey, &info->msgBuf); - if (ret != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlParseCols parse tag fields failed", info->id); - return ret; + if (tinfo == NULL) { + uError("SML:0x%" PRIx64 "get oneTable failed, line num:%d", info->id, i); + smlBuildInvalidDataMsg(&info->msgBuf, "get oneTable failed", elements->measure); + return TSDB_CODE_SML_INVALID_DATA; } - if (taosArrayGetSize((*oneTable)->tags) > TSDB_MAX_TAGS) { + if (taosArrayGetSize(tinfo->tags) > TSDB_MAX_TAGS) { smlBuildInvalidDataMsg(&info->msgBuf, "too many tags than 128", NULL); return TSDB_CODE_PAR_INVALID_TAGS_NUM; } - if (taosArrayGetSize(cols) + taosArrayGetSize((*oneTable)->tags) > TSDB_MAX_COLUMNS) { + if (taosArrayGetSize(elements->colArray) + taosArrayGetSize(tinfo->tags) > TSDB_MAX_COLUMNS) { smlBuildInvalidDataMsg(&info->msgBuf, "too many columns than 4096", NULL); return TSDB_CODE_PAR_TOO_MANY_COLUMNS; } - (*oneTable)->sTableName = elements.measure; - (*oneTable)->sTableNameLen = elements.measureLen; - if (strlen((*oneTable)->childTableName) == 0) { - RandTableName rName = {(*oneTable)->tags, (*oneTable)->sTableName, (uint8_t)(*oneTable)->sTableNameLen, - (*oneTable)->childTableName}; - - buildChildTableName(&rName); - } - (*oneTable)->uid = info->uid++; - } - - SSmlSTableMeta **tableMeta = (SSmlSTableMeta **)taosHashGet(info->superTables, elements.measure, elements.measureLen); - if (tableMeta) { // update meta - ret = smlUpdateMeta((*tableMeta)->colHash, (*tableMeta)->cols, cols, &info->msgBuf); - if (!hasTable && ret == TSDB_CODE_SUCCESS) { - ret = smlUpdateMeta((*tableMeta)->tagHash, (*tableMeta)->tags, (*oneTable)->tags, &info->msgBuf); - } + int ret = smlPushCols(tinfo->cols, elements->colArray); if (ret != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlUpdateMeta failed", info->id); return ret; } - } else { - SSmlSTableMeta *meta = smlBuildSTableMeta(); - smlInsertMeta(meta->tagHash, meta->tags, (*oneTable)->tags); - smlInsertMeta(meta->colHash, meta->cols, cols); - taosHashPut(info->superTables, elements.measure, elements.measureLen, &meta, POINTER_BYTES); - } - - if (!info->dataFormat) { - taosArrayClear(info->colsContainer); - } - taosHashClear(info->dumplicateKey); - return TSDB_CODE_SUCCESS; -} - -static int32_t smlParseTelnetLine(SSmlHandle *info, void *data, const int len) { - int ret = TSDB_CODE_SUCCESS; - SSmlTableInfo *tinfo = smlBuildTableInfo(); - if (!tinfo) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - SArray *cols = taosArrayInit(16, POINTER_BYTES); - if (cols == NULL) { - uError("SML:0x%" PRIx64 " smlParseTelnetLine failed to allocate memory", info->id); - return TSDB_CODE_OUT_OF_MEMORY; - } - - if (info->protocol == TSDB_SML_TELNET_PROTOCOL) { - ret = smlParseTelnetString(info, (const char *)data, (char *)data + len, tinfo, cols); - } else if (info->protocol == TSDB_SML_JSON_PROTOCOL) { - ret = smlParseJSONString(info, (cJSON *)data, tinfo, cols); - } else { - ASSERT(0); - } - if (ret != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlParseTelnetLine failed", info->id); - smlDestroyTableInfo(info, tinfo); - smlDestroyCols(cols); - taosArrayDestroy(cols); - return ret; - } - if (taosArrayGetSize(tinfo->tags) <= 0 || taosArrayGetSize(tinfo->tags) > TSDB_MAX_TAGS) { - smlBuildInvalidDataMsg(&info->msgBuf, "invalidate tags length:[1,128]", NULL); - smlDestroyTableInfo(info, tinfo); - smlDestroyCols(cols); - taosArrayDestroy(cols); - return TSDB_CODE_PAR_INVALID_TAGS_NUM; - } - taosHashClear(info->dumplicateKey); - - if (strlen(tinfo->childTableName) == 0) { - RandTableName rName = {tinfo->tags, tinfo->sTableName, (uint8_t)tinfo->sTableNameLen, tinfo->childTableName}; - buildChildTableName(&rName); - } - - bool hasTable = true; - SSmlTableInfo **oneTable = - (SSmlTableInfo **)taosHashGet(info->childTables, tinfo->childTableName, strlen(tinfo->childTableName)); - if (!oneTable) { - taosHashPut(info->childTables, tinfo->childTableName, strlen(tinfo->childTableName), &tinfo, POINTER_BYTES); - oneTable = &tinfo; - tinfo->uid = info->uid++; - hasTable = false; - } else { - smlDestroyTableInfo(info, tinfo); - } - - taosArrayPush((*oneTable)->cols, &cols); - SSmlSTableMeta **tableMeta = - (SSmlSTableMeta **)taosHashGet(info->superTables, (*oneTable)->sTableName, (*oneTable)->sTableNameLen); - if (tableMeta) { // update meta - ret = smlUpdateMeta((*tableMeta)->colHash, (*tableMeta)->cols, cols, &info->msgBuf); - if (!hasTable && ret == TSDB_CODE_SUCCESS) { - ret = smlUpdateMeta((*tableMeta)->tagHash, (*tableMeta)->tags, (*oneTable)->tags, &info->msgBuf); - } - if (ret != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " smlUpdateMeta failed", info->id); - return ret; + SSmlSTableMeta **tableMeta = + (SSmlSTableMeta **)taosHashGet(info->superTables, elements->measure, elements->measureLen); + if (tableMeta) { // update meta + uDebug("SML:0x%" PRIx64 " smlParseLineBottom update meta, format:%d, linenum:%d", info->id, info->dataFormat, + info->lineNum); + ret = smlUpdateMeta((*tableMeta)->colHash, (*tableMeta)->cols, elements->colArray, false, &info->msgBuf); + if (ret == TSDB_CODE_SUCCESS) { + ret = smlUpdateMeta((*tableMeta)->tagHash, (*tableMeta)->tags, tinfo->tags, true, &info->msgBuf); + } + if (ret != TSDB_CODE_SUCCESS) { + uError("SML:0x%" PRIx64 " smlUpdateMeta failed", info->id); + return ret; + } + } else { + // ret = smlJudgeDupColName(elements->colArray, tinfo->tags, &info->msgBuf); + // if (ret != TSDB_CODE_SUCCESS) { + // uError("SML:0x%" PRIx64 " smlUpdateMeta failed", info->id); + // return ret; + // } + uDebug("SML:0x%" PRIx64 " smlParseLineBottom add meta, format:%d, linenum:%d", info->id, info->dataFormat, + info->lineNum); + SSmlSTableMeta *meta = smlBuildSTableMeta(info->dataFormat); + taosHashPut(info->superTables, elements->measure, elements->measureLen, &meta, POINTER_BYTES); + terrno = 0; + smlInsertMeta(meta->tagHash, meta->tags, tinfo->tags); + if (terrno == TSDB_CODE_DUP_KEY) { + return terrno; + } + smlInsertMeta(meta->colHash, meta->cols, elements->colArray); } - } else { - SSmlSTableMeta *meta = smlBuildSTableMeta(); - smlInsertMeta(meta->tagHash, meta->tags, (*oneTable)->tags); - smlInsertMeta(meta->colHash, meta->cols, cols); - taosHashPut(info->superTables, (*oneTable)->sTableName, (*oneTable)->sTableNameLen, &meta, POINTER_BYTES); } + uDebug("SML:0x%" PRIx64 " smlParseLineBottom end, format:%d, linenum:%d", info->id, info->dataFormat, info->lineNum); return TSDB_CODE_SUCCESS; } -static int32_t smlParseJSON(SSmlHandle *info, char *payload) { - int32_t payloadNum = 0; - int32_t ret = TSDB_CODE_SUCCESS; - - if (payload == NULL) { - uError("SML:0x%" PRIx64 " empty JSON Payload", info->id); - return TSDB_CODE_TSC_INVALID_JSON; - } - - info->root = cJSON_Parse(payload); - if (info->root == NULL) { - uError("SML:0x%" PRIx64 " parse json failed:%s", info->id, payload); - return TSDB_CODE_TSC_INVALID_JSON; - } - // multiple data points must be sent in JSON array - if (cJSON_IsObject(info->root)) { - payloadNum = 1; - } else if (cJSON_IsArray(info->root)) { - payloadNum = cJSON_GetArraySize(info->root); - } else { - uError("SML:0x%" PRIx64 " Invalid JSON Payload", info->id); - ret = TSDB_CODE_TSC_INVALID_JSON; - goto end; - } - - for (int32_t i = 0; i < payloadNum; ++i) { - cJSON *dataPoint = (payloadNum == 1 && cJSON_IsObject(info->root)) ? info->root : cJSON_GetArrayItem(info->root, i); - ret = smlParseTelnetLine(info, dataPoint, -1); - if (ret != TSDB_CODE_SUCCESS) { - uError("SML:0x%" PRIx64 " Invalid JSON Payload", info->id); - goto end; - } - } - -end: - return ret; -} - static int32_t smlInsertData(SSmlHandle *info) { int32_t code = TSDB_CODE_SUCCESS; + uDebug("SML:0x%" PRIx64 " smlInsertData start, format:%d", info->id, info->dataFormat); + + if (info->pRequest->dbList == NULL) { + info->pRequest->dbList = taosArrayInit(1, TSDB_DB_FNAME_LEN); + } + char *data = (char*)taosArrayReserve(info->pRequest->dbList, 1); + SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}}; + tstrncpy(pName.dbname, info->pRequest->pDb, sizeof(pName.dbname)); + tNameGetFullDbName(&pName, data); SSmlTableInfo **oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, NULL); while (oneTable) { SSmlTableInfo *tableData = *oneTable; + tstrncpy(pName.tname, tableData->sTableName, tableData->sTableNameLen + 1); - SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}}; - tstrncpy(pName.dbname, info->pRequest->pDb, sizeof(pName.dbname)); - memcpy(pName.tname, tableData->childTableName, strlen(tableData->childTableName)); + if (info->pRequest->tableList == NULL) { + info->pRequest->tableList = taosArrayInit(1, sizeof(SName)); + } + taosArrayPush(info->pRequest->tableList, &pName); + + strcpy(pName.tname, tableData->childTableName); SRequestConnInfo conn = {0}; conn.pTrans = info->taos->pAppInfo->pTransporter; @@ -2317,15 +1369,26 @@ static int32_t smlInsertData(SSmlHandle *info) { SSmlSTableMeta **pMeta = (SSmlSTableMeta **)taosHashGet(info->superTables, tableData->sTableName, tableData->sTableNameLen); - ASSERT(NULL != pMeta && NULL != *pMeta); + if (unlikely(NULL == pMeta || NULL == (*pMeta)->tableMeta)) { + uError("SML:0x%" PRIx64 " NULL == pMeta. table name: %s", info->id, tableData->childTableName); + return TSDB_CODE_SML_INTERNAL_ERROR; + } // use tablemeta of stable to save vgid and uid of child table (*pMeta)->tableMeta->vgId = vg.vgId; (*pMeta)->tableMeta->uid = tableData->uid; // one table merge data block together according uid + uDebug("SML:0x%" PRIx64 " smlInsertData table:%s, uid:%" PRIu64 ", format:%d", info->id, pName.tname, + tableData->uid, info->dataFormat); + + int measureLen = tableData->sTableNameLen; + char* measure = (char*)taosMemoryMalloc(tableData->sTableNameLen); + memcpy(measure, tableData->sTableName, tableData->sTableNameLen); + PROCESS_SLASH_IN_MEASUREMENT(measure, measureLen); - code = smlBindData(info->exec, tableData->tags, (*pMeta)->cols, tableData->cols, info->dataFormat, - (*pMeta)->tableMeta, tableData->childTableName, tableData->sTableName, tableData->sTableNameLen, + code = smlBindData(info->pQuery, info->dataFormat, tableData->tags, (*pMeta)->cols, tableData->cols, + (*pMeta)->tableMeta, tableData->childTableName, measure, measureLen, info->ttl, info->msgBuf.buf, info->msgBuf.len); + taosMemoryFree(measure); if (code != TSDB_CODE_SUCCESS) { uError("SML:0x%" PRIx64 " smlBindData failed", info->id); return code; @@ -2333,7 +1396,7 @@ static int32_t smlInsertData(SSmlHandle *info) { oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, oneTable); } - code = smlBuildOutput(info->exec, info->pVgHash); + code = smlBuildOutput(info->pQuery, info->pVgHash); if (code != TSDB_CODE_SUCCESS) { uError("SML:0x%" PRIx64 " smlBuildOutput failed", info->id); return code; @@ -2344,22 +1407,65 @@ static int32_t smlInsertData(SSmlHandle *info) { atomic_add_fetch_64((int64_t *)&pActivity->numOfInsertsReq, 1); launchQueryImpl(info->pRequest, info->pQuery, true, NULL); + uDebug("SML:0x%" PRIx64 " smlInsertData end, format:%d, code:%d,%s", info->id, info->dataFormat, info->pRequest->code, + tstrerror(info->pRequest->code)); + return info->pRequest->code; } static void smlPrintStatisticInfo(SSmlHandle *info) { - uError("SML:0x%" PRIx64 - " smlInsertLines result, code:%d,lineNum:%d,stable num:%d,ctable num:%d,create stable num:%d,alter stable tag num:%d,alter stable col num:%d \ + uDebug( + "SML:0x%" PRIx64 + " smlInsertLines result, code:%d, msg:%s, lineNum:%d,stable num:%d,ctable num:%d,create stable num:%d,alter stable tag num:%d,alter stable col num:%d \ parse cost:%" PRId64 ",schema cost:%" PRId64 ",bind cost:%" PRId64 ",rpc cost:%" PRId64 ",total cost:%" PRId64 - "", - info->id, info->cost.code, info->cost.lineNum, info->cost.numOfSTables, info->cost.numOfCTables, - info->cost.numOfCreateSTables, info->cost.numOfAlterTagSTables, info->cost.numOfAlterColSTables, - info->cost.schemaTime - info->cost.parseTime, - info->cost.insertBindTime - info->cost.schemaTime, info->cost.insertRpcTime - info->cost.insertBindTime, - info->cost.endTime - info->cost.insertRpcTime, info->cost.endTime - info->cost.parseTime); + "", + info->id, info->cost.code, tstrerror(info->cost.code), info->cost.lineNum, info->cost.numOfSTables, + info->cost.numOfCTables, info->cost.numOfCreateSTables, info->cost.numOfAlterTagSTables, + info->cost.numOfAlterColSTables, info->cost.schemaTime - info->cost.parseTime, + info->cost.insertBindTime - info->cost.schemaTime, info->cost.insertRpcTime - info->cost.insertBindTime, + info->cost.endTime - info->cost.insertRpcTime, info->cost.endTime - info->cost.parseTime); +} + +int32_t smlClearForRerun(SSmlHandle *info) { + info->reRun = false; + // clear info->childTables + SSmlTableInfo **oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, NULL); + while (oneTable) { + smlDestroyTableInfo(info, *oneTable); + oneTable = (SSmlTableInfo **)taosHashIterate(info->childTables, oneTable); + } + + // clear info->superTables + SSmlSTableMeta **oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, NULL); + while (oneSTable) { + smlDestroySTableMeta(*oneSTable); + oneSTable = (SSmlSTableMeta **)taosHashIterate(info->superTables, oneSTable); + } + + taosHashClear(info->childTables); + taosHashClear(info->superTables); + taosHashClear(info->tableUids); + + if (!info->dataFormat) { + if (unlikely(info->lines != NULL)) { + uError("SML:0x%" PRIx64 " info->lines != NULL", info->id); + return TSDB_CODE_SML_INVALID_DATA; + } + info->lines = (SSmlLineInfo *)taosMemoryCalloc(info->lineNum, sizeof(SSmlLineInfo)); + } + + memset(&info->preLine, 0, sizeof(SSmlLineInfo)); + info->currSTableMeta = NULL; + info->currTableDataCtx = NULL; + + SVnodeModifyOpStmt *stmt = (SVnodeModifyOpStmt *)(info->pQuery->pRoot); + stmt->freeHashFunc(stmt->pTableBlockHashObj); + stmt->pTableBlockHashObj = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK); + return TSDB_CODE_SUCCESS; } static int32_t smlParseLine(SSmlHandle *info, char *lines[], char *rawLine, char *rawLineEnd, int numLines) { + uDebug("SML:0x%" PRIx64 " smlParseLine start", info->id); int32_t code = TSDB_CODE_SUCCESS; if (info->protocol == TSDB_SML_JSON_PROTOCOL) { if (lines) { @@ -2374,7 +1480,9 @@ static int32_t smlParseLine(SSmlHandle *info, char *lines[], char *rawLine, char return code; } - for (int32_t i = 0; i < numLines; ++i) { + char *oldRaw = rawLine; + int32_t i = 0; + while (i < numLines) { char *tmp = NULL; int len = 0; if (lines) { @@ -2393,18 +1501,55 @@ static int32_t smlParseLine(SSmlHandle *info, char *lines[], char *rawLine, char } } + char cTmp = 0; // for print tmp if is raw + if (info->isRawLine) { + cTmp = tmp[len]; + tmp[len] = '\0'; + } + + uDebug("SML:0x%" PRIx64 " smlParseLine israw:%d, numLines:%d, protocol:%d, len:%d, sql:%s", info->id, + info->isRawLine, numLines, info->protocol, len, tmp); + if (info->isRawLine) { + tmp[len] = cTmp; + } + if (info->protocol == TSDB_SML_LINE_PROTOCOL) { - code = smlParseInfluxLine(info, tmp, len); + if (info->dataFormat) { + SSmlLineInfo element = {0}; + code = smlParseInfluxString(info, tmp, tmp + len, &element); + } else { + code = smlParseInfluxString(info, tmp, tmp + len, info->lines + i); + } } else if (info->protocol == TSDB_SML_TELNET_PROTOCOL) { - code = smlParseTelnetLine(info, tmp, len); + if (info->dataFormat) { + SSmlLineInfo element = {0}; + code = smlParseTelnetString(info, (char *)tmp, (char *)tmp + len, &element); + if (element.measureTagsLen != 0) taosMemoryFree(element.measureTag); + } else { + code = smlParseTelnetString(info, (char *)tmp, (char *)tmp + len, info->lines + i); + } } else { - ASSERT(0); + code = TSDB_CODE_SML_INVALID_PROTOCOL_TYPE; } if (code != TSDB_CODE_SUCCESS) { + tmp[len] = '\0'; uError("SML:0x%" PRIx64 " smlParseLine failed. line %d : %s", info->id, i, tmp); return code; } + if (info->reRun) { + uDebug("SML:0x%" PRIx64 " smlParseLine re run", info->id); + i = 0; + rawLine = oldRaw; + code = smlClearForRerun(info); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + continue; + } + i++; } + uDebug("SML:0x%" PRIx64 " smlParseLine end", info->id); + return code; } @@ -2419,8 +1564,13 @@ static int smlProcess(SSmlHandle *info, char *lines[], char *rawLine, char *rawL uError("SML:0x%" PRIx64 " smlParseLine error : %s", info->id, tstrerror(code)); return code; } + code = smlParseLineBottom(info); + if (code != 0) { + uError("SML:0x%" PRIx64 " smlParseLineBottom error : %s", info->id, tstrerror(code)); + return code; + } - info->cost.lineNum = numLines; + info->cost.lineNum = info->lineNum; info->cost.numOfSTables = taosHashGetSize(info->superTables); info->cost.numOfCTables = taosHashGetSize(info->childTables); @@ -2428,7 +1578,13 @@ static int smlProcess(SSmlHandle *info, char *lines[], char *rawLine, char *rawL do { code = smlModifyDBSchemas(info); - if (code == 0) break; + if (code == 0 || code == TSDB_CODE_SML_INVALID_DATA || code == TSDB_CODE_PAR_TOO_MANY_COLUMNS + || code == TSDB_CODE_PAR_INVALID_TAGS_NUM || code == TSDB_CODE_PAR_INVALID_TAGS_LENGTH + || code == TSDB_CODE_PAR_INVALID_ROW_LENGTH || code == TSDB_CODE_MND_FIELD_VALUE_OVERFLOW) { + break; + } + taosMsleep(100); + uInfo("SML:0x%" PRIx64 " smlModifyDBSchemas retry code:%s, times:%d", info->id, tstrerror(code), retryNum); } while (retryNum++ < taosHashGetSize(info->superTables) * MAX_RETRY_TIMES); if (code != 0) { @@ -2446,96 +1602,93 @@ static int smlProcess(SSmlHandle *info, char *lines[], char *rawLine, char *rawL return code; } -static int32_t isSchemalessDb(STscObj *taos, SRequestObj *request) { - // SCatalog *catalog = NULL; - // int32_t code = catalogGetHandle(((STscObj *)taos)->pAppInfo->clusterId, &catalog); - // if (code != TSDB_CODE_SUCCESS) { - // uError("SML get catalog error %d", code); - // return code; - // } - // - // SName name; - // tNameSetDbName(&name, taos->acctId, taos->db, strlen(taos->db)); - // char dbFname[TSDB_DB_FNAME_LEN] = {0}; - // tNameGetFullDbName(&name, dbFname); - // SDbCfgInfo pInfo = {0}; - // - // SRequestConnInfo conn = {0}; - // conn.pTrans = taos->pAppInfo->pTransporter; - // conn.requestId = request->requestId; - // conn.requestObjRefId = request->self; - // conn.mgmtEps = getEpSet_s(&taos->pAppInfo->mgmtEp); - // - // code = catalogGetDBCfg(catalog, &conn, dbFname, &pInfo); - // if (code != TSDB_CODE_SUCCESS) { - // return code; - // } - // taosArrayDestroy(pInfo.pRetensions); - // - // if (!pInfo.schemaless) { - // return TSDB_CODE_SML_INVALID_DB_CONF; - // } - return TSDB_CODE_SUCCESS; -} - -TAOS_RES *taos_schemaless_insert_inner(SRequestObj *request, char *lines[], char *rawLine, char *rawLineEnd, - int numLines, int protocol, int precision, int32_t ttl) { - STscObj *pTscObj = request->pTscObj; - SSmlHandle *info = NULL; - pTscObj->schemalessType = 1; - SSmlMsgBuf msg = {ERROR_MSG_BUF_DEFAULT_SIZE, request->msgBuf}; - - if (request->pDb == NULL) { - request->code = TSDB_CODE_PAR_DB_NOT_SPECIFIED; - smlBuildInvalidDataMsg(&msg, "Database not specified", NULL); - goto end; +TAOS_RES *taos_schemaless_insert_inner(TAOS *taos, char *lines[], char *rawLine, char *rawLineEnd, int numLines, + int protocol, int precision, int32_t ttl, int64_t reqid) { + int32_t code = TSDB_CODE_SUCCESS; + if (NULL == taos) { + terrno = TSDB_CODE_TSC_DISCONNECTED; + return NULL; } + SRequestObj *request = NULL; + SSmlHandle *info = NULL; + int cnt = 0; + while (1) { + request = (SRequestObj *)createRequest(*(int64_t *)taos, TSDB_SQL_INSERT, reqid); + if (request == NULL) { + uError("SML:taos_schemaless_insert error request is null"); + return NULL; + } - if (isSchemalessDb(pTscObj, request) != TSDB_CODE_SUCCESS) { - request->code = TSDB_CODE_SML_INVALID_DB_CONF; - smlBuildInvalidDataMsg(&msg, "Cannot write data to a non schemaless database", NULL); - goto end; - } + info = smlBuildSmlInfo(taos); + if (info == NULL) { + request->code = TSDB_CODE_OUT_OF_MEMORY; + uError("SML:taos_schemaless_insert error SSmlHandle is null"); + return (TAOS_RES *)request; + } + info->pRequest = request; + info->isRawLine = rawLine != NULL; + info->ttl = ttl; + info->precision = precision; + info->protocol = (TSDB_SML_PROTOCOL_TYPE)protocol; + info->msgBuf.buf = info->pRequest->msgBuf; + info->msgBuf.len = ERROR_MSG_BUF_DEFAULT_SIZE; + info->lineNum = numLines; - if (protocol < TSDB_SML_LINE_PROTOCOL || protocol > TSDB_SML_JSON_PROTOCOL) { - request->code = TSDB_CODE_SML_INVALID_PROTOCOL_TYPE; - smlBuildInvalidDataMsg(&msg, "protocol invalidate", NULL); - goto end; - } + SSmlMsgBuf msg = {ERROR_MSG_BUF_DEFAULT_SIZE, request->msgBuf}; + if (request->pDb == NULL) { + request->code = TSDB_CODE_PAR_DB_NOT_SPECIFIED; + smlBuildInvalidDataMsg(&msg, "Database not specified", NULL); + goto end; + } - if (protocol == TSDB_SML_LINE_PROTOCOL && - (precision < TSDB_SML_TIMESTAMP_NOT_CONFIGURED || precision > TSDB_SML_TIMESTAMP_NANO_SECONDS)) { - request->code = TSDB_CODE_SML_INVALID_PRECISION_TYPE; - smlBuildInvalidDataMsg(&msg, "precision invalidate for line protocol", NULL); - goto end; - } + if (protocol < TSDB_SML_LINE_PROTOCOL || protocol > TSDB_SML_JSON_PROTOCOL) { + request->code = TSDB_CODE_SML_INVALID_PROTOCOL_TYPE; + smlBuildInvalidDataMsg(&msg, "protocol invalidate", NULL); + goto end; + } - if (protocol == TSDB_SML_JSON_PROTOCOL) { - numLines = 1; - } else if (numLines <= 0) { - request->code = TSDB_CODE_SML_INVALID_DATA; - smlBuildInvalidDataMsg(&msg, "line num is invalid", NULL); - goto end; - } + if (protocol == TSDB_SML_LINE_PROTOCOL && + (precision < TSDB_SML_TIMESTAMP_NOT_CONFIGURED || precision > TSDB_SML_TIMESTAMP_NANO_SECONDS)) { + request->code = TSDB_CODE_SML_INVALID_PRECISION_TYPE; + smlBuildInvalidDataMsg(&msg, "precision invalidate for line protocol", NULL); + goto end; + } - info = smlBuildSmlInfo(pTscObj, request, (SMLProtocolType)protocol, precision); - if (!info) { - request->code = TSDB_CODE_OUT_OF_MEMORY; - uError("SML:taos_schemaless_insert error SSmlHandle is null"); - goto end; - } + if (protocol == TSDB_SML_JSON_PROTOCOL) { + numLines = 1; + } else if (numLines <= 0) { + request->code = TSDB_CODE_SML_INVALID_DATA; + smlBuildInvalidDataMsg(&msg, "line num is invalid", NULL); + goto end; + } - info->isRawLine = (rawLine == NULL); - info->ttl = ttl; - request->code = smlProcess(info, lines, rawLine, rawLineEnd, numLines); + code = smlProcess(info, lines, rawLine, rawLineEnd, numLines); + request->code = code; + info->cost.endTime = taosGetTimestampUs(); + info->cost.code = code; + if (code == TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER || code == TSDB_CODE_SDB_OBJ_CREATING || + code == TSDB_CODE_PAR_VALUE_TOO_LONG || code == TSDB_CODE_MND_TRANS_CONFLICT || + code == TSDB_CODE_PAR_TABLE_NOT_EXIST) { + if (cnt++ >= 10) { + uInfo("SML:%" PRIx64 " retry:%d/10 end code:%d, msg:%s", info->id, cnt, code, tstrerror(code)); + break; + } + taosMsleep(100); + refreshMeta(request->pTscObj, request); + uInfo("SML:%" PRIx64 " retry:%d/10,ver is old retry or object is creating code:%d, msg:%s", info->id, cnt, code, + tstrerror(code)); + smlDestroyInfo(info); + info = NULL; + taos_free_result(request); + request = NULL; + continue; + } + smlPrintStatisticInfo(info); + break; + } end: - uDebug("SML:0x%" PRIx64 " insert finished, code: %d", info->id, request->code); - info->cost.endTime = taosGetTimestampUs(); - info->cost.code = request->code; - smlPrintStatisticInfo(info); smlDestroyInfo(info); - return (TAOS_RES *)request; } @@ -2560,59 +1713,26 @@ end: TAOS_RES *taos_schemaless_insert_ttl_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, int precision, int32_t ttl, int64_t reqid) { - if (NULL == taos) { - terrno = TSDB_CODE_TSC_DISCONNECTED; - return NULL; - } - - SRequestObj *request = (SRequestObj *)createRequest(*(int64_t *)taos, TSDB_SQL_INSERT, reqid); - if (!request) { - uError("SML:taos_schemaless_insert error request is null"); - return NULL; - } - - if (!lines) { - SSmlMsgBuf msg = {ERROR_MSG_BUF_DEFAULT_SIZE, request->msgBuf}; - request->code = TSDB_CODE_SML_INVALID_DATA; - smlBuildInvalidDataMsg(&msg, "lines is null", NULL); - return (TAOS_RES *)request; - } - - return taos_schemaless_insert_inner(request, lines, NULL, NULL, numLines, protocol, precision, ttl); + return taos_schemaless_insert_inner(taos, lines, NULL, NULL, numLines, protocol, precision, ttl, reqid); } TAOS_RES *taos_schemaless_insert(TAOS *taos, char *lines[], int numLines, int protocol, int precision) { return taos_schemaless_insert_ttl_with_reqid(taos, lines, numLines, protocol, precision, TSDB_DEFAULT_TABLE_TTL, 0); } -TAOS_RES *taos_schemaless_insert_ttl(TAOS *taos, char *lines[], int numLines, int protocol, int precision, int32_t ttl) { +TAOS_RES *taos_schemaless_insert_ttl(TAOS *taos, char *lines[], int numLines, int protocol, int precision, + int32_t ttl) { return taos_schemaless_insert_ttl_with_reqid(taos, lines, numLines, protocol, precision, ttl, 0); } -TAOS_RES *taos_schemaless_insert_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, int precision, int64_t reqid) { - return taos_schemaless_insert_ttl_with_reqid(taos, lines, numLines, protocol, precision, TSDB_DEFAULT_TABLE_TTL, reqid); +TAOS_RES *taos_schemaless_insert_with_reqid(TAOS *taos, char *lines[], int numLines, int protocol, int precision, + int64_t reqid) { + return taos_schemaless_insert_ttl_with_reqid(taos, lines, numLines, protocol, precision, TSDB_DEFAULT_TABLE_TTL, + reqid); } TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, - int precision, int32_t ttl, int64_t reqid) { - if (NULL == taos) { - terrno = TSDB_CODE_TSC_DISCONNECTED; - return NULL; - } - - SRequestObj *request = (SRequestObj *)createRequest(*(int64_t *)taos, TSDB_SQL_INSERT, reqid); - if (!request) { - uError("SML:taos_schemaless_insert error request is null"); - return NULL; - } - - if (!lines || len <= 0) { - SSmlMsgBuf msg = {ERROR_MSG_BUF_DEFAULT_SIZE, request->msgBuf}; - request->code = TSDB_CODE_SML_INVALID_DATA; - smlBuildInvalidDataMsg(&msg, "lines is null", NULL); - return (TAOS_RES *)request; - } - + int precision, int32_t ttl, int64_t reqid) { int numLines = 0; *totalRows = 0; char *tmp = lines; @@ -2625,16 +1745,21 @@ TAOS_RES *taos_schemaless_insert_raw_ttl_with_reqid(TAOS *taos, char *lines, int tmp = lines + i + 1; } } - return taos_schemaless_insert_inner(request, NULL, lines, lines + len, numLines, protocol, precision, ttl); + return taos_schemaless_insert_inner(taos, NULL, lines, lines + len, *totalRows, protocol, precision, ttl, reqid); } -TAOS_RES *taos_schemaless_insert_raw_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision, int64_t reqid) { - return taos_schemaless_insert_raw_ttl_with_reqid(taos, lines, len, totalRows, protocol, precision, TSDB_DEFAULT_TABLE_TTL, reqid); +TAOS_RES *taos_schemaless_insert_raw_with_reqid(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, + int precision, int64_t reqid) { + return taos_schemaless_insert_raw_ttl_with_reqid(taos, lines, len, totalRows, protocol, precision, + TSDB_DEFAULT_TABLE_TTL, reqid); } -TAOS_RES *taos_schemaless_insert_raw_ttl(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision, int32_t ttl) { +TAOS_RES *taos_schemaless_insert_raw_ttl(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, + int precision, int32_t ttl) { return taos_schemaless_insert_raw_ttl_with_reqid(taos, lines, len, totalRows, protocol, precision, ttl, 0); } -TAOS_RES *taos_schemaless_insert_raw(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, int precision) { - return taos_schemaless_insert_raw_ttl_with_reqid(taos, lines, len, totalRows, protocol, precision, TSDB_DEFAULT_TABLE_TTL, 0); +TAOS_RES *taos_schemaless_insert_raw(TAOS *taos, char *lines, int len, int32_t *totalRows, int protocol, + int precision) { + return taos_schemaless_insert_raw_ttl_with_reqid(taos, lines, len, totalRows, protocol, precision, + TSDB_DEFAULT_TABLE_TTL, 0); } diff --git a/source/client/src/clientSmlJson.c b/source/client/src/clientSmlJson.c new file mode 100644 index 0000000000000000000000000000000000000000..7ccf9309648583cd9610a6375fc717297fc7352d --- /dev/null +++ b/source/client/src/clientSmlJson.c @@ -0,0 +1,1272 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include "clientSml.h" + +#define OTD_JSON_SUB_FIELDS_NUM 2 + +#define JUMP_JSON_SPACE(start) \ + while (*(start)) { \ + if (unlikely(*(start) > 32)) \ + break; \ + else \ + (start)++; \ + } + +// SArray *smlJsonParseTags(char *start, char *end){ +// SArray *tags = taosArrayInit(4, sizeof(SSmlKv)); +// while(start < end){ +// SSmlKv kv = {0}; +// kv.type = TSDB_DATA_TYPE_NCHAR; +// bool isInQuote = false; +// while(start < end){ +// if(unlikely(!isInQuote && *start == '"')){ +// start++; +// kv.key = start; +// isInQuote = true; +// continue; +// } +// if(unlikely(isInQuote && *start == '"')){ +// kv.keyLen = start - kv.key; +// start++; +// break; +// } +// start++; +// } +// bool hasColon = false; +// while(start < end){ +// if(unlikely(!hasColon && *start == ':')){ +// start++; +// hasColon = true; +// continue; +// } +// if(unlikely(hasColon && kv.value == NULL && (*start > 32 && *start != '"'))){ +// kv.value = start; +// start++; +// continue; +// } +// +// if(unlikely(hasColon && kv.value != NULL && (*start == '"' || *start == ',' || *start == '}'))){ +// kv.length = start - kv.value; +// taosArrayPush(tags, &kv); +// start++; +// break; +// } +// start++; +// } +// } +// return tags; +// } + +// static int32_t smlParseTagsFromJSON(SSmlHandle *info, SSmlLineInfo *elements) { +// int32_t ret = TSDB_CODE_SUCCESS; +// +// if(is_same_child_table_telnet(elements, &info->preLine) == 0){ +// return TSDB_CODE_SUCCESS; +// } +// +// bool isSameMeasure = IS_SAME_SUPER_TABLE; +// +// int cnt = 0; +// SArray *preLineKV = info->preLineTagKV; +// bool isSuperKVInit = true; +// SArray *superKV = NULL; +// if(info->dataFormat){ +// if(unlikely(!isSameMeasure)){ +// SSmlSTableMeta *sMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, elements->measure, +// elements->measureLen, NULL); +// +// if(unlikely(sMeta == NULL)){ +// sMeta = smlBuildSTableMeta(info->dataFormat); +// STableMeta * pTableMeta = smlGetMeta(info, elements->measure, elements->measureLen); +// sMeta->tableMeta = pTableMeta; +// if(pTableMeta == NULL){ +// info->dataFormat = false; +// info->reRun = true; +// return TSDB_CODE_SUCCESS; +// } +// nodeListSet(&info->superTables, elements->measure, elements->measureLen, sMeta, NULL); +// } +// info->currSTableMeta = sMeta->tableMeta; +// superKV = sMeta->tags; +// +// if(unlikely(taosArrayGetSize(superKV) == 0)){ +// isSuperKVInit = false; +// } +// taosArraySetSize(preLineKV, 0); +// } +// }else{ +// taosArraySetSize(preLineKV, 0); +// } +// +// SArray *tags = smlJsonParseTags(elements->tags, elements->tags + elements->tagsLen); +// int32_t tagNum = taosArrayGetSize(tags); +// if (tagNum == 0) { +// uError("SML:tag is empty:%s", elements->tags) +// taosArrayDestroy(tags); +// return TSDB_CODE_SML_INVALID_DATA; +// } +// for (int32_t i = 0; i < tagNum; ++i) { +// SSmlKv kv = *(SSmlKv*)taosArrayGet(tags, i); +// +// if(info->dataFormat){ +// if(unlikely(cnt + 1 > info->currSTableMeta->tableInfo.numOfTags)){ +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// +// if(isSameMeasure){ +// if(unlikely(cnt >= taosArrayGetSize(preLineKV))) { +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// SSmlKv *preKV = (SSmlKv *)taosArrayGet(preLineKV, cnt); +// if(unlikely(kv.length > preKV->length)){ +// preKV->length = kv.length; +// SSmlSTableMeta *tableMeta = (SSmlSTableMeta *)nodeListGet(info->superTables, elements->measure, +// elements->measureLen, NULL); +// if(unlikely(NULL == tableMeta)){ +// uError("SML:0x%" PRIx64 " NULL == tableMeta", info->id); +// return TSDB_CODE_SML_INTERNAL_ERROR; +// } +// +// SSmlKv *oldKV = (SSmlKv *)taosArrayGet(tableMeta->tags, cnt); +// oldKV->length = kv.length; +// info->needModifySchema = true; +// } +// if(unlikely(!IS_SAME_KEY)){ +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// }else{ +// if(isSuperKVInit){ +// if(unlikely(cnt >= taosArrayGetSize(superKV))) { +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// SSmlKv *preKV = (SSmlKv *)taosArrayGet(superKV, cnt); +// if(unlikely(kv.length > preKV->length)) { +// preKV->length = kv.length; +// }else{ +// kv.length = preKV->length; +// } +// info->needModifySchema = true; +// +// if(unlikely(!IS_SAME_KEY)){ +// info->dataFormat = false; +// info->reRun = true; +// taosArrayDestroy(tags); +// return TSDB_CODE_SUCCESS; +// } +// }else{ +// taosArrayPush(superKV, &kv); +// } +// taosArrayPush(preLineKV, &kv); +// } +// }else{ +// taosArrayPush(preLineKV, &kv); +// } +// cnt++; +// } +// taosArrayDestroy(tags); +// +// SSmlTableInfo *tinfo = (SSmlTableInfo *)nodeListGet(info->childTables, elements, POINTER_BYTES, +// is_same_child_table_telnet); if (unlikely(tinfo == NULL)) { +// tinfo = smlBuildTableInfo(1, elements->measure, elements->measureLen); +// if (unlikely(!tinfo)) { +// return TSDB_CODE_OUT_OF_MEMORY; +// } +// tinfo->tags = taosArrayDup(preLineKV, NULL); +// +// smlSetCTableName(tinfo); +// if (info->dataFormat) { +// info->currSTableMeta->uid = tinfo->uid; +// tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta); +// if (tinfo->tableDataCtx == NULL) { +// smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL); +// return TSDB_CODE_SML_INVALID_DATA; +// } +// } +// +// SSmlLineInfo *key = (SSmlLineInfo *)taosMemoryMalloc(sizeof(SSmlLineInfo)); +// *key = *elements; +// tinfo->key = key; +// nodeListSet(&info->childTables, key, POINTER_BYTES, tinfo, is_same_child_table_telnet); +// } +// if (info->dataFormat) info->currTableDataCtx = tinfo->tableDataCtx; +// +// return ret; +// } + +static char *smlJsonGetObj(char *payload) { + int leftBracketCnt = 0; + bool isInQuote = false; + while (*payload) { + if (*payload == '"' && *(payload - 1) != '\\') { + isInQuote = !isInQuote; + } else if (!isInQuote && unlikely(*payload == '{')) { + leftBracketCnt++; + payload++; + continue; + } else if (!isInQuote && unlikely(*payload == '}')) { + leftBracketCnt--; + payload++; + if (leftBracketCnt == 0) { + return payload; + } else if (leftBracketCnt < 0) { + return NULL; + } + continue; + } + payload++; + } + return NULL; +} + +int smlJsonParseObjFirst(char **start, SSmlLineInfo *element, int8_t *offset) { + int index = 0; + while (*(*start)) { + if ((*start)[0] != '"') { + (*start)++; + continue; + } + + if (unlikely(index >= OTD_JSON_FIELDS_NUM)) { + uError("index >= %d, %s", OTD_JSON_FIELDS_NUM, *start) return -1; + } + + char *sTmp = *start; + if ((*start)[1] == 'm' && (*start)[2] == 'e' && (*start)[3] == 't' && (*start)[4] == 'r' && (*start)[5] == 'i' && + (*start)[6] == 'c' && (*start)[7] == '"') { + (*start) += 8; + bool isInQuote = false; + while (*(*start)) { + if (unlikely(!isInQuote && *(*start) == '"')) { + (*start)++; + offset[index++] = *start - sTmp; + element->measure = (*start); + isInQuote = true; + continue; + } + if (unlikely(isInQuote && *(*start) == '"')) { + element->measureLen = (*start) - element->measure; + (*start)++; + break; + } + (*start)++; + } + } else if ((*start)[1] == 't' && (*start)[2] == 'i' && (*start)[3] == 'm' && (*start)[4] == 'e' && + (*start)[5] == 's' && (*start)[6] == 't' && (*start)[7] == 'a' && (*start)[8] == 'm' && + (*start)[9] == 'p' && (*start)[10] == '"') { + (*start) += 11; + bool hasColon = false; + while (*(*start)) { + if (unlikely(!hasColon && *(*start) == ':')) { + (*start)++; + JUMP_JSON_SPACE((*start)) + offset[index++] = *start - sTmp; + element->timestamp = (*start); + if (*(*start) == '{') { + char *tmp = smlJsonGetObj((*start)); + if (tmp) { + element->timestampLen = tmp - (*start); + *start = tmp; + } + break; + } + hasColon = true; + continue; + } + if (unlikely(hasColon && (*(*start) == ',' || *(*start) == '}' || (*(*start)) <= 32))) { + element->timestampLen = (*start) - element->timestamp; + break; + } + (*start)++; + } + } else if ((*start)[1] == 'v' && (*start)[2] == 'a' && (*start)[3] == 'l' && (*start)[4] == 'u' && + (*start)[5] == 'e' && (*start)[6] == '"') { + (*start) += 7; + + bool hasColon = false; + while (*(*start)) { + if (unlikely(!hasColon && *(*start) == ':')) { + (*start)++; + JUMP_JSON_SPACE((*start)) + offset[index++] = *start - sTmp; + element->cols = (*start); + if (*(*start) == '{') { + char *tmp = smlJsonGetObj((*start)); + if (tmp) { + element->colsLen = tmp - (*start); + *start = tmp; + } + break; + } + hasColon = true; + continue; + } + if (unlikely(hasColon && (*(*start) == ',' || *(*start) == '}' || (*(*start)) <= 32))) { + element->colsLen = (*start) - element->cols; + break; + } + (*start)++; + } + } else if ((*start)[1] == 't' && (*start)[2] == 'a' && (*start)[3] == 'g' && (*start)[4] == 's' && + (*start)[5] == '"') { + (*start) += 6; + + while (*(*start)) { + if (unlikely(*(*start) == ':')) { + (*start)++; + JUMP_JSON_SPACE((*start)) + offset[index++] = *start - sTmp; + element->tags = (*start); + char *tmp = smlJsonGetObj((*start)); + if (tmp) { + element->tagsLen = tmp - (*start); + *start = tmp; + } + break; + } + (*start)++; + } + } + if (*(*start) == '\0') { + break; + } + if (*(*start) == '}') { + (*start)++; + break; + } + (*start)++; + } + + if (unlikely(index != OTD_JSON_FIELDS_NUM) || element->tags == NULL || element->cols == NULL || + element->measure == NULL || element->timestamp == NULL) { + uError("elements != %d or element parse null", OTD_JSON_FIELDS_NUM) return -1; + } + return 0; +} + +int smlJsonParseObj(char **start, SSmlLineInfo *element, int8_t *offset) { + int index = 0; + while (*(*start)) { + if ((*start)[0] != '"') { + (*start)++; + continue; + } + + if (unlikely(index >= OTD_JSON_FIELDS_NUM)) { + uError("index >= %d, %s", OTD_JSON_FIELDS_NUM, *start) return -1; + } + + if ((*start)[1] == 'm') { + (*start) += offset[index++]; + element->measure = *start; + while (*(*start)) { + if (unlikely(*(*start) == '"')) { + element->measureLen = (*start) - element->measure; + (*start)++; + break; + } + (*start)++; + } + } else if ((*start)[1] == 't' && (*start)[2] == 'i') { + (*start) += offset[index++]; + element->timestamp = *start; + if (*(*start) == '{') { + char *tmp = smlJsonGetObj((*start)); + if (tmp) { + element->timestampLen = tmp - (*start); + *start = tmp; + } + } else { + while (*(*start)) { + if (unlikely(*(*start) == ',' || *(*start) == '}' || (*(*start)) <= 32)) { + element->timestampLen = (*start) - element->timestamp; + break; + } + (*start)++; + } + } + } else if ((*start)[1] == 'v') { + (*start) += offset[index++]; + element->cols = *start; + if (*(*start) == '{') { + char *tmp = smlJsonGetObj((*start)); + if (tmp) { + element->colsLen = tmp - (*start); + *start = tmp; + } + } else { + while (*(*start)) { + if (unlikely(*(*start) == ',' || *(*start) == '}' || (*(*start)) <= 32)) { + element->colsLen = (*start) - element->cols; + break; + } + (*start)++; + } + } + } else if ((*start)[1] == 't' && (*start)[2] == 'a') { + (*start) += offset[index++]; + element->tags = (*start); + char *tmp = smlJsonGetObj((*start)); + if (tmp) { + element->tagsLen = tmp - (*start); + *start = tmp; + } + } + if (*(*start) == '}') { + (*start)++; + break; + } + (*start)++; + } + + if (unlikely(index != 0 && index != OTD_JSON_FIELDS_NUM)) { + uError("elements != %d", OTD_JSON_FIELDS_NUM) return -1; + } + return 0; +} + +static inline int32_t smlParseMetricFromJSON(SSmlHandle *info, cJSON *metric, SSmlLineInfo *elements) { + elements->measureLen = strlen(metric->valuestring); + if (IS_INVALID_TABLE_LEN(elements->measureLen)) { + uError("OTD:0x%" PRIx64 " Metric lenght is 0 or large than 192", info->id); + return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; + } + + elements->measure = metric->valuestring; + return TSDB_CODE_SUCCESS; +} + +const char *jsonName[OTD_JSON_FIELDS_NUM] = {"metric", "timestamp", "value", "tags"}; +static int32_t smlGetJsonElements(cJSON *root, cJSON ***marks) { + for (int i = 0; i < OTD_JSON_FIELDS_NUM; ++i) { + cJSON *child = root->child; + while (child != NULL) { + if (strcasecmp(child->string, jsonName[i]) == 0) { + *marks[i] = child; + break; + } + child = child->next; + } + if (*marks[i] == NULL) { + uError("smlGetJsonElements error, not find mark:%d:%s", i, jsonName[i]); + return -1; + } + } + return TSDB_CODE_SUCCESS; +} + +static int32_t smlConvertJSONBool(SSmlKv *pVal, char *typeStr, cJSON *value) { + if (strcasecmp(typeStr, "bool") != 0) { + uError("OTD:invalid type(%s) for JSON Bool", typeStr); + return TSDB_CODE_TSC_INVALID_JSON_TYPE; + } + pVal->type = TSDB_DATA_TYPE_BOOL; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->i = value->valueint; + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlConvertJSONNumber(SSmlKv *pVal, char *typeStr, cJSON *value) { + // tinyint + if (strcasecmp(typeStr, "i8") == 0 || strcasecmp(typeStr, "tinyint") == 0) { + if (!IS_VALID_TINYINT(value->valuedouble)) { + uError("OTD:JSON value(%f) cannot fit in type(tinyint)", value->valuedouble); + return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; + } + pVal->type = TSDB_DATA_TYPE_TINYINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->i = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + // smallint + if (strcasecmp(typeStr, "i16") == 0 || strcasecmp(typeStr, "smallint") == 0) { + if (!IS_VALID_SMALLINT(value->valuedouble)) { + uError("OTD:JSON value(%f) cannot fit in type(smallint)", value->valuedouble); + return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; + } + pVal->type = TSDB_DATA_TYPE_SMALLINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->i = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + // int + if (strcasecmp(typeStr, "i32") == 0 || strcasecmp(typeStr, "int") == 0) { + if (!IS_VALID_INT(value->valuedouble)) { + uError("OTD:JSON value(%f) cannot fit in type(int)", value->valuedouble); + return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; + } + pVal->type = TSDB_DATA_TYPE_INT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->i = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + // bigint + if (strcasecmp(typeStr, "i64") == 0 || strcasecmp(typeStr, "bigint") == 0) { + pVal->type = TSDB_DATA_TYPE_BIGINT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + if (value->valuedouble >= (double)INT64_MAX) { + pVal->i = INT64_MAX; + } else if (value->valuedouble <= (double)INT64_MIN) { + pVal->i = INT64_MIN; + } else { + pVal->i = value->valuedouble; + } + return TSDB_CODE_SUCCESS; + } + // float + if (strcasecmp(typeStr, "f32") == 0 || strcasecmp(typeStr, "float") == 0) { + if (!IS_VALID_FLOAT(value->valuedouble)) { + uError("OTD:JSON value(%f) cannot fit in type(float)", value->valuedouble); + return TSDB_CODE_TSC_VALUE_OUT_OF_RANGE; + } + pVal->type = TSDB_DATA_TYPE_FLOAT; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->f = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + // double + if (strcasecmp(typeStr, "f64") == 0 || strcasecmp(typeStr, "double") == 0) { + pVal->type = TSDB_DATA_TYPE_DOUBLE; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + pVal->d = value->valuedouble; + return TSDB_CODE_SUCCESS; + } + + // if reach here means type is unsupported + uError("OTD:invalid type(%s) for JSON Number", typeStr); + return TSDB_CODE_TSC_INVALID_JSON_TYPE; +} + +static int32_t smlConvertJSONString(SSmlKv *pVal, char *typeStr, cJSON *value) { + if (strcasecmp(typeStr, "binary") == 0) { + pVal->type = TSDB_DATA_TYPE_BINARY; + } else if (strcasecmp(typeStr, "nchar") == 0) { + pVal->type = TSDB_DATA_TYPE_NCHAR; + } else { + uError("OTD:invalid type(%s) for JSON String", typeStr); + return TSDB_CODE_TSC_INVALID_JSON_TYPE; + } + pVal->length = strlen(value->valuestring); + + if (pVal->type == TSDB_DATA_TYPE_BINARY && pVal->length > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) { + return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + } + if (pVal->type == TSDB_DATA_TYPE_NCHAR && + pVal->length > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { + return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + } + + pVal->value = value->valuestring; + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseValueFromJSONObj(cJSON *root, SSmlKv *kv) { + int32_t ret = TSDB_CODE_SUCCESS; + int32_t size = cJSON_GetArraySize(root); + + if (size != OTD_JSON_SUB_FIELDS_NUM) { + return TSDB_CODE_TSC_INVALID_JSON; + } + + cJSON *value = cJSON_GetObjectItem(root, "value"); + if (value == NULL) { + return TSDB_CODE_TSC_INVALID_JSON; + } + + cJSON *type = cJSON_GetObjectItem(root, "type"); + if (!cJSON_IsString(type)) { + return TSDB_CODE_TSC_INVALID_JSON; + } + + switch (value->type) { + case cJSON_True: + case cJSON_False: { + ret = smlConvertJSONBool(kv, type->valuestring, value); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + break; + } + case cJSON_Number: { + ret = smlConvertJSONNumber(kv, type->valuestring, value); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + break; + } + case cJSON_String: { + ret = smlConvertJSONString(kv, type->valuestring, value); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + break; + } + default: + return TSDB_CODE_TSC_INVALID_JSON_TYPE; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseValueFromJSON(cJSON *root, SSmlKv *kv) { + switch (root->type) { + case cJSON_True: + case cJSON_False: { + kv->type = TSDB_DATA_TYPE_BOOL; + kv->length = (int16_t)tDataTypes[kv->type].bytes; + kv->i = root->valueint; + break; + } + case cJSON_Number: { + kv->type = TSDB_DATA_TYPE_DOUBLE; + kv->length = (int16_t)tDataTypes[kv->type].bytes; + kv->d = root->valuedouble; + break; + } + case cJSON_String: { + /* set default JSON type to binary/nchar according to + * user configured parameter tsDefaultJSONStrType + */ + + char *tsDefaultJSONStrType = "binary"; // todo + smlConvertJSONString(kv, tsDefaultJSONStrType, root); + break; + } + case cJSON_Object: { + int32_t ret = smlParseValueFromJSONObj(root, kv); + if (ret != TSDB_CODE_SUCCESS) { + uError("OTD:Failed to parse value from JSON Obj"); + return ret; + } + break; + } + default: + return TSDB_CODE_TSC_INVALID_JSON; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseTagsFromJSON(SSmlHandle *info, cJSON *tags, SSmlLineInfo *elements) { + int32_t ret = TSDB_CODE_SUCCESS; + + bool isSameMeasure = IS_SAME_SUPER_TABLE; + + int cnt = 0; + SArray *preLineKV = info->preLineTagKV; + if (info->dataFormat) { + if (unlikely(!isSameMeasure)) { + SSmlSTableMeta **tmp = (SSmlSTableMeta **)taosHashGet(info->superTables, elements->measure, elements->measureLen); + SSmlSTableMeta *sMeta = NULL; + if (unlikely(tmp == NULL)) { + STableMeta *pTableMeta = smlGetMeta(info, elements->measure, elements->measureLen); + if (pTableMeta == NULL) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + sMeta = smlBuildSTableMeta(info->dataFormat); + sMeta->tableMeta = pTableMeta; + taosHashPut(info->superTables, elements->measure, elements->measureLen, &sMeta, POINTER_BYTES); + for(int i = pTableMeta->tableInfo.numOfColumns; i < pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns; i++){ + SSchema *tag = pTableMeta->schema + i; + SSmlKv kv = {.key = tag->name, .keyLen = strlen(tag->name), .type = tag->type, .length = (tag->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE }; + taosArrayPush(sMeta->tags, &kv); + } + tmp = &sMeta; + } + info->currSTableMeta = (*tmp)->tableMeta; + info->maxTagKVs = (*tmp)->tags; + } + } + taosArrayClear(preLineKV); + + int32_t tagNum = cJSON_GetArraySize(tags); + if (unlikely(tagNum == 0)) { + uError("SML:Tag should not be empty"); + return TSDB_CODE_TSC_INVALID_JSON; + } + for (int32_t i = 0; i < tagNum; ++i) { + cJSON *tag = cJSON_GetArrayItem(tags, i); + if (unlikely(tag == NULL)) { + return TSDB_CODE_TSC_INVALID_JSON; + } + // if(unlikely(tag == cMeasure)) continue; + size_t keyLen = strlen(tag->string); + if (unlikely(IS_INVALID_COL_LEN(keyLen))) { + uError("OTD:Tag key length is 0 or too large than 64"); + return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; + } + + // add kv to SSmlKv + SSmlKv kv = {.key = tag->string, .keyLen = keyLen}; + // value + ret = smlParseValueFromJSON(tag, &kv); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + return ret; + } + + if (info->dataFormat) { + if (unlikely(cnt + 1 > info->currSTableMeta->tableInfo.numOfTags)) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + + if (unlikely(cnt >= taosArrayGetSize(info->maxTagKVs))) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(info->maxTagKVs, cnt); + if (unlikely(!IS_SAME_KEY)) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + if (unlikely(kv.length > maxKV->length)) { + maxKV->length = kv.length; + info->needModifySchema = true; + } + } + taosArrayPush(preLineKV, &kv); + cnt++; + } + + elements->measureTag = (char *)taosMemoryMalloc(elements->measureLen + elements->tagsLen); + memcpy(elements->measureTag, elements->measure, elements->measureLen); + memcpy(elements->measureTag + elements->measureLen, elements->tags, elements->tagsLen); + elements->measureTagsLen = elements->measureLen + elements->tagsLen; + + SSmlTableInfo **tmp = + (SSmlTableInfo **)taosHashGet(info->childTables, elements->measureTag, elements->measureLen + elements->tagsLen); + SSmlTableInfo *tinfo = NULL; + if (unlikely(tmp == NULL)) { + tinfo = smlBuildTableInfo(1, elements->measure, elements->measureLen); + if (unlikely(!tinfo)) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tinfo->tags = taosArrayDup(preLineKV, NULL); + + smlSetCTableName(tinfo); + getTableUid(info, elements, tinfo); + if (info->dataFormat) { + info->currSTableMeta->uid = tinfo->uid; + tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta); + if (tinfo->tableDataCtx == NULL) { + smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL); + smlDestroyTableInfo(info, tinfo); + return TSDB_CODE_SML_INVALID_DATA; + } + } + + // SSmlLineInfo *key = (SSmlLineInfo *)taosMemoryMalloc(sizeof(SSmlLineInfo)); + // *key = *elements; + // if(info->parseJsonByLib){ + // key->tags = taosMemoryMalloc(elements->tagsLen + 1); + // memcpy(key->tags, elements->tags, elements->tagsLen); + // key->tags[elements->tagsLen] = 0; + // } + // tinfo->key = key; + taosHashPut(info->childTables, elements->measureTag, elements->measureLen + elements->tagsLen, &tinfo, + POINTER_BYTES); + tmp = &tinfo; + } + if (info->dataFormat) info->currTableDataCtx = (*tmp)->tableDataCtx; + + return ret; +} + +static int64_t smlParseTSFromJSONObj(SSmlHandle *info, cJSON *root, int32_t toPrecision) { + int32_t size = cJSON_GetArraySize(root); + if (unlikely(size != OTD_JSON_SUB_FIELDS_NUM)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalidate json", NULL); + return -1; + } + + cJSON *value = cJSON_GetObjectItem(root, "value"); + if (unlikely(!cJSON_IsNumber(value))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalidate json", NULL); + return -1; + } + + cJSON *type = cJSON_GetObjectItem(root, "type"); + if (unlikely(!cJSON_IsString(type))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalidate json", NULL); + return -1; + } + + double timeDouble = value->valuedouble; + if (unlikely(smlDoubleToInt64OverFlow(timeDouble))) { + smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); + return -1; + } + + if (timeDouble == 0) { + return taosGetTimestampNs() / smlFactorNS[toPrecision]; + } + + if (timeDouble < 0) { + return timeDouble; + } + + int64_t tsInt64 = timeDouble; + size_t typeLen = strlen(type->valuestring); + if (typeLen == 1 && (type->valuestring[0] == 's' || type->valuestring[0] == 'S')) { + // seconds + int8_t fromPrecision = TSDB_TIME_PRECISION_SECONDS; + if (smlFactorS[toPrecision] < INT64_MAX / tsInt64) { + return tsInt64 * smlFactorS[toPrecision]; + } + return -1; + } else if (typeLen == 2 && (type->valuestring[1] == 's' || type->valuestring[1] == 'S')) { + switch (type->valuestring[0]) { + case 'm': + case 'M': + // milliseconds + return convertTimePrecision(tsInt64, TSDB_TIME_PRECISION_MILLI, toPrecision); + break; + case 'u': + case 'U': + // microseconds + return convertTimePrecision(tsInt64, TSDB_TIME_PRECISION_MICRO, toPrecision); + break; + case 'n': + case 'N': + return convertTimePrecision(tsInt64, TSDB_TIME_PRECISION_NANO, toPrecision); + break; + default: + return -1; + } + } else { + return -1; + } +} + +uint8_t smlGetTimestampLen(int64_t num) { + uint8_t len = 0; + while ((num /= 10) != 0) { + len++; + } + len++; + return len; +} + +static int64_t smlParseTSFromJSON(SSmlHandle *info, cJSON *timestamp) { + // Timestamp must be the first KV to parse + int32_t toPrecision = info->currSTableMeta ? info->currSTableMeta->tableInfo.precision : TSDB_TIME_PRECISION_NANO; + if (cJSON_IsNumber(timestamp)) { + // timestamp value 0 indicates current system time + double timeDouble = timestamp->valuedouble; + if (unlikely(smlDoubleToInt64OverFlow(timeDouble))) { + smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is too large", NULL); + return -1; + } + + if (unlikely(timeDouble < 0)) { + smlBuildInvalidDataMsg(&info->msgBuf, "timestamp is negative", NULL); + return timeDouble; + } else if (unlikely(timeDouble == 0)) { + return taosGetTimestampNs() / smlFactorNS[toPrecision]; + } + + uint8_t tsLen = smlGetTimestampLen((int64_t)timeDouble); + + int8_t fromPrecision = smlGetTsTypeByLen(tsLen); + if (unlikely(fromPrecision == -1)) { + smlBuildInvalidDataMsg(&info->msgBuf, + "timestamp precision can only be seconds(10 digits) or milli seconds(13 digits)", NULL); + return -1; + } + int64_t tsInt64 = timeDouble; + if (fromPrecision == TSDB_TIME_PRECISION_SECONDS) { + if (smlFactorS[toPrecision] < INT64_MAX / tsInt64) { + return tsInt64 * smlFactorS[toPrecision]; + } + return -1; + } else { + return convertTimePrecision(timeDouble, fromPrecision, toPrecision); + } + } else if (cJSON_IsObject(timestamp)) { + return smlParseTSFromJSONObj(info, timestamp, toPrecision); + } else { + smlBuildInvalidDataMsg(&info->msgBuf, "invalidate json", NULL); + return -1; + } +} + +static int32_t smlParseJSONStringExt(SSmlHandle *info, cJSON *root, SSmlLineInfo *elements) { + int32_t ret = TSDB_CODE_SUCCESS; + + cJSON *metricJson = NULL; + cJSON *tsJson = NULL; + cJSON *valueJson = NULL; + cJSON *tagsJson = NULL; + + int32_t size = cJSON_GetArraySize(root); + // outmost json fields has to be exactly 4 + if (size != OTD_JSON_FIELDS_NUM) { + uError("OTD:0x%" PRIx64 " Invalid number of JSON fields in data point %d", info->id, size); + return TSDB_CODE_TSC_INVALID_JSON; + } + + cJSON **marks[OTD_JSON_FIELDS_NUM] = {&metricJson, &tsJson, &valueJson, &tagsJson}; + ret = smlGetJsonElements(root, marks); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + return ret; + } + + // Parse metric + ret = smlParseMetricFromJSON(info, metricJson, elements); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + uError("OTD:0x%" PRIx64 " Unable to parse metric from JSON payload", info->id); + return ret; + } + + // Parse metric value + SSmlKv kv = {.key = VALUE, .keyLen = VALUE_LEN}; + ret = smlParseValueFromJSON(valueJson, &kv); + if (unlikely(ret)) { + uError("OTD:0x%" PRIx64 " Unable to parse metric value from JSON payload", info->id); + return ret; + } + + // Parse tags + bool needFree = info->dataFormat; + elements->tags = cJSON_PrintUnformatted(tagsJson); + elements->tagsLen = strlen(elements->tags); + if (is_same_child_table_telnet(elements, &info->preLine) != 0) { + ret = smlParseTagsFromJSON(info, tagsJson, elements); + if (unlikely(ret)) { + uError("OTD:0x%" PRIx64 " Unable to parse tags from JSON payload", info->id); + taosMemoryFree(elements->tags); + elements->tags = NULL; + return ret; + } + } else { + elements->measureTag = info->preLine.measureTag; + } + + if (needFree) { + taosMemoryFree(elements->tags); + elements->tags = NULL; + } + + if (unlikely(info->reRun)) { + return TSDB_CODE_SUCCESS; + } + + // Parse timestamp + // notice!!! put ts back to tag to ensure get meta->precision + int64_t ts = smlParseTSFromJSON(info, tsJson); + if (unlikely(ts < 0)) { + uError("OTD:0x%" PRIx64 " Unable to parse timestamp from JSON payload", info->id); + return TSDB_CODE_INVALID_TIMESTAMP; + } + SSmlKv kvTs = {.key = TS, + .keyLen = TS_LEN, + .type = TSDB_DATA_TYPE_TIMESTAMP, + .i = ts, + .length = (size_t)tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes}; + + if (info->dataFormat) { + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kvTs, 0); + if (ret == TSDB_CODE_SUCCESS) { + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kv, 1); + } + if (ret == TSDB_CODE_SUCCESS) { + ret = smlBuildRow(info->currTableDataCtx); + } + clearColValArray(info->currTableDataCtx->pValues); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + smlBuildInvalidDataMsg(&info->msgBuf, "smlBuildCol error", NULL); + return ret; + } + } else { + if (elements->colArray == NULL) { + elements->colArray = taosArrayInit(16, sizeof(SSmlKv)); + } + taosArrayPush(elements->colArray, &kvTs); + taosArrayPush(elements->colArray, &kv); + } + info->preLine = *elements; + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseJSONExt(SSmlHandle *info, char *payload) { + int32_t payloadNum = 0; + int32_t ret = TSDB_CODE_SUCCESS; + + if (unlikely(payload == NULL)) { + uError("SML:0x%" PRIx64 " empty JSON Payload", info->id); + return TSDB_CODE_TSC_INVALID_JSON; + } + + info->root = cJSON_Parse(payload); + if (unlikely(info->root == NULL)) { + uError("SML:0x%" PRIx64 " parse json failed:%s", info->id, payload); + return TSDB_CODE_TSC_INVALID_JSON; + } + + // multiple data points must be sent in JSON array + if (cJSON_IsArray(info->root)) { + payloadNum = cJSON_GetArraySize(info->root); + } else if (cJSON_IsObject(info->root)) { + payloadNum = 1; + } else { + uError("SML:0x%" PRIx64 " Invalid JSON Payload 3:%s", info->id, payload); + return TSDB_CODE_TSC_INVALID_JSON; + } + + info->lineNum = payloadNum; + info->dataFormat = true; + if (unlikely(info->lines != NULL)) { + taosMemoryFree(info->lines); + info->lines = NULL; + } + ret = smlClearForRerun(info); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + + info->parseJsonByLib = true; + cJSON *head = (payloadNum == 1 && cJSON_IsObject(info->root)) ? info->root : info->root->child; + + int cnt = 0; + cJSON *dataPoint = head; + while (dataPoint) { + if (info->dataFormat) { + SSmlLineInfo element = {0}; + ret = smlParseJSONStringExt(info, dataPoint, &element); + } else { + ret = smlParseJSONStringExt(info, dataPoint, info->lines + cnt); + } + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + uError("SML:0x%" PRIx64 " Invalid JSON Payload 2:%s", info->id, payload); + return ret; + } + + if (unlikely(info->reRun)) { + cnt = 0; + dataPoint = head; + info->lineNum = payloadNum; + ret = smlClearForRerun(info); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + continue; + } + cnt++; + dataPoint = dataPoint->next; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseJSONString(SSmlHandle *info, char **start, SSmlLineInfo *elements) { + int32_t ret = TSDB_CODE_SUCCESS; + + if (info->offset[0] == 0) { + ret = smlJsonParseObjFirst(start, elements, info->offset); + } else { + ret = smlJsonParseObj(start, elements, info->offset); + } + + if (ret != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_VALUE; + } + + if (unlikely(**start == '\0' && elements->measure == NULL)) return TSDB_CODE_SUCCESS; + + if (unlikely(IS_INVALID_TABLE_LEN(elements->measureLen))) { + smlBuildInvalidDataMsg(&info->msgBuf, "measure is empty or too large than 192", NULL); + return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; + } + + SSmlKv kv = {.key = VALUE, .keyLen = VALUE_LEN, .value = elements->cols, .length = (size_t)elements->colsLen}; + + if (unlikely(elements->colsLen == 0)) { + uError("SML:colsLen == 0"); + return TSDB_CODE_TSC_INVALID_VALUE; + } else if (unlikely(elements->cols[0] == '{')) { + char tmp = elements->cols[elements->colsLen]; + elements->cols[elements->colsLen] = '\0'; + cJSON *valueJson = cJSON_Parse(elements->cols); + if (unlikely(valueJson == NULL)) { + uError("SML:0x%" PRIx64 " parse json cols failed:%s", info->id, elements->cols); + return TSDB_CODE_TSC_INVALID_JSON; + } + taosArrayPush(info->tagJsonArray, &valueJson); + ret = smlParseValueFromJSONObj(valueJson, &kv); + if (ret != TSDB_CODE_SUCCESS) { + uError("SML:Failed to parse value from JSON Obj:%s", elements->cols); + elements->cols[elements->colsLen] = tmp; + return TSDB_CODE_TSC_INVALID_VALUE; + } + elements->cols[elements->colsLen] = tmp; + } else if (smlParseValue(&kv, &info->msgBuf) != TSDB_CODE_SUCCESS) { + uError("SML:cols invalidate:%s", elements->cols); + return TSDB_CODE_TSC_INVALID_VALUE; + } + + // Parse tags + if (is_same_child_table_telnet(elements, &info->preLine) != 0) { + char tmp = *(elements->tags + elements->tagsLen); + *(elements->tags + elements->tagsLen) = 0; + cJSON *tagsJson = cJSON_Parse(elements->tags); + *(elements->tags + elements->tagsLen) = tmp; + if (unlikely(tagsJson == NULL)) { + uError("SML:0x%" PRIx64 " parse json tag failed:%s", info->id, elements->tags); + return TSDB_CODE_TSC_INVALID_JSON; + } + + taosArrayPush(info->tagJsonArray, &tagsJson); + ret = smlParseTagsFromJSON(info, tagsJson, elements); + if (unlikely(ret)) { + uError("OTD:0x%" PRIx64 " Unable to parse tags from JSON payload", info->id); + return ret; + } + } else { + elements->measureTag = info->preLine.measureTag; + } + + if (unlikely(info->reRun)) { + return TSDB_CODE_SUCCESS; + } + + // Parse timestamp + // notice!!! put ts back to tag to ensure get meta->precision + int64_t ts = 0; + if (unlikely(elements->timestampLen == 0)) { + uError("OTD:0x%" PRIx64 " elements->timestampLen == 0", info->id); + return TSDB_CODE_INVALID_TIMESTAMP; + } else if (elements->timestamp[0] == '{') { + char tmp = elements->timestamp[elements->timestampLen]; + elements->timestamp[elements->timestampLen] = '\0'; + cJSON *tsJson = cJSON_Parse(elements->timestamp); + ts = smlParseTSFromJSON(info, tsJson); + if (unlikely(ts < 0)) { + uError("SML:0x%" PRIx64 " Unable to parse timestamp from JSON payload:%s", info->id, elements->timestamp); + elements->timestamp[elements->timestampLen] = tmp; + cJSON_Delete(tsJson); + return TSDB_CODE_INVALID_TIMESTAMP; + } + elements->timestamp[elements->timestampLen] = tmp; + cJSON_Delete(tsJson); + } else { + ts = smlParseOpenTsdbTime(info, elements->timestamp, elements->timestampLen); + if (unlikely(ts < 0)) { + uError("OTD:0x%" PRIx64 " Unable to parse timestamp from JSON payload", info->id); + return TSDB_CODE_INVALID_TIMESTAMP; + } + } + SSmlKv kvTs = {.key = TS, + .keyLen = TS_LEN, + .type = TSDB_DATA_TYPE_TIMESTAMP, + .i = ts, + .length = (size_t)tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes}; + + if (info->dataFormat) { + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kvTs, 0); + if (ret == TSDB_CODE_SUCCESS) { + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kv, 1); + } + if (ret == TSDB_CODE_SUCCESS) { + ret = smlBuildRow(info->currTableDataCtx); + } + clearColValArray(info->currTableDataCtx->pValues); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + smlBuildInvalidDataMsg(&info->msgBuf, "smlBuildCol error", NULL); + return ret; + } + } else { + if (elements->colArray == NULL) { + elements->colArray = taosArrayInit(16, sizeof(SSmlKv)); + } + taosArrayPush(elements->colArray, &kvTs); + taosArrayPush(elements->colArray, &kv); + } + info->preLine = *elements; + + return TSDB_CODE_SUCCESS; +} + +int32_t smlParseJSON(SSmlHandle *info, char *payload) { + int32_t payloadNum = 1 << 15; + int32_t ret = TSDB_CODE_SUCCESS; + + uDebug("SML:0x%" PRIx64 "json:%s", info->id, payload); + int cnt = 0; + char *dataPointStart = payload; + while (1) { + if (info->dataFormat) { + SSmlLineInfo element = {0}; + ret = smlParseJSONString(info, &dataPointStart, &element); + if (element.measureTagsLen != 0) taosMemoryFree(element.measureTag); + } else { + if (cnt >= payloadNum) { + payloadNum = payloadNum << 1; + void *tmp = taosMemoryRealloc(info->lines, payloadNum * sizeof(SSmlLineInfo)); + if (tmp == NULL) { + ret = TSDB_CODE_OUT_OF_MEMORY; + return ret; + } + info->lines = (SSmlLineInfo *)tmp; + memset(info->lines + cnt, 0, (payloadNum - cnt) * sizeof(SSmlLineInfo)); + } + ret = smlParseJSONString(info, &dataPointStart, info->lines + cnt); + if ((info->lines + cnt)->measure == NULL) break; + } + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + uError("SML:0x%" PRIx64 " Invalid JSON Payload 1:%s", info->id, payload); + return smlParseJSONExt(info, payload); + } + + if (unlikely(info->reRun)) { + cnt = 0; + dataPointStart = payload; + info->lineNum = payloadNum; + ret = smlClearForRerun(info); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + continue; + } + + cnt++; + if (*dataPointStart == '\0') break; + } + info->lineNum = cnt; + + return TSDB_CODE_SUCCESS; +} diff --git a/source/client/src/clientSmlLine.c b/source/client/src/clientSmlLine.c new file mode 100644 index 0000000000000000000000000000000000000000..2f7e8a0f972f068e6c6a83ee00653633f7f64433 --- /dev/null +++ b/source/client/src/clientSmlLine.c @@ -0,0 +1,657 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "clientSml.h" + +// comma , +#define IS_COMMA(sql) (*(sql) == COMMA && *((sql)-1) != SLASH) +// space +#define IS_SPACE(sql) (*(sql) == SPACE && *((sql)-1) != SLASH) +// equal = +#define IS_EQUAL(sql) (*(sql) == EQUAL && *((sql)-1) != SLASH) +// quote " +//#define IS_QUOTE(sql) (*(sql) == QUOTE && *((sql)-1) != SLASH) +// SLASH + +#define IS_SLASH_LETTER_IN_FIELD_VALUE(sql) \ + (*((sql)-1) == SLASH && (*(sql) == QUOTE || *(sql) == SLASH)) + +#define IS_SLASH_LETTER_IN_TAG_FIELD_KEY(sql) \ + (*((sql)-1) == SLASH && (*(sql) == COMMA || *(sql) == SPACE || *(sql) == EQUAL)) + +#define PROCESS_SLASH_IN_FIELD_VALUE(key, keyLen) \ + for (int i = 1; i < keyLen; ++i) { \ + if (IS_SLASH_LETTER_IN_FIELD_VALUE(key + i)) { \ + MOVE_FORWARD_ONE(key + i, keyLen - i); \ + keyLen--; \ + } \ + } + +#define PROCESS_SLASH_IN_TAG_FIELD_KEY(key, keyLen) \ + for (int i = 1; i < keyLen; ++i) { \ + if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(key + i)) { \ + MOVE_FORWARD_ONE(key + i, keyLen - i); \ + keyLen--; \ + } \ + } + +#define BINARY_ADD_LEN 2 // "binary" 2 means " " +#define NCHAR_ADD_LEN 3 // L"nchar" 3 means L" " + +uint8_t smlPrecisionConvert[7] = {TSDB_TIME_PRECISION_NANO, TSDB_TIME_PRECISION_HOURS, TSDB_TIME_PRECISION_MINUTES, + TSDB_TIME_PRECISION_SECONDS, TSDB_TIME_PRECISION_MILLI, TSDB_TIME_PRECISION_MICRO, + TSDB_TIME_PRECISION_NANO}; + +static int64_t smlParseInfluxTime(SSmlHandle *info, const char *data, int32_t len) { + uint8_t toPrecision = info->currSTableMeta ? info->currSTableMeta->tableInfo.precision : TSDB_TIME_PRECISION_NANO; + + if (unlikely(len == 0 || (len == 1 && data[0] == '0'))) { + return taosGetTimestampNs() / smlFactorNS[toPrecision]; + } + + uint8_t fromPrecision = smlPrecisionConvert[info->precision]; + + int64_t ts = smlGetTimeValue(data, len, fromPrecision, toPrecision); + if (unlikely(ts == -1)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", data); + return -1; + } + return ts; +} + +int32_t smlParseValue(SSmlKv *pVal, SSmlMsgBuf *msg) { + if (pVal->value[0] == '"') { // binary + if (pVal->length >= 2 && pVal->value[pVal->length - 1] == '"') { + pVal->type = TSDB_DATA_TYPE_BINARY; + pVal->length -= BINARY_ADD_LEN; + if (pVal->length > TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) { + return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + } + pVal->value += (BINARY_ADD_LEN - 1); + return TSDB_CODE_SUCCESS; + } + return TSDB_CODE_TSC_INVALID_VALUE; + } + + if (pVal->value[0] == 'l' || pVal->value[0] == 'L') { // nchar + if (pVal->value[1] == '"' && pVal->value[pVal->length - 1] == '"' && pVal->length >= 3) { + pVal->type = TSDB_DATA_TYPE_NCHAR; + pVal->length -= NCHAR_ADD_LEN; + if (pVal->length > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { + return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + } + pVal->value += (NCHAR_ADD_LEN - 1); + return TSDB_CODE_SUCCESS; + } + return TSDB_CODE_TSC_INVALID_VALUE; + } + + if (pVal->value[0] == 't' || pVal->value[0] == 'T') { + if (pVal->length == 1 || + (pVal->length == 4 && (pVal->value[1] == 'r' || pVal->value[1] == 'R') && + (pVal->value[2] == 'u' || pVal->value[2] == 'U') && (pVal->value[3] == 'e' || pVal->value[3] == 'E'))) { + pVal->i = TSDB_TRUE; + pVal->type = TSDB_DATA_TYPE_BOOL; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return TSDB_CODE_SUCCESS; + } + return TSDB_CODE_TSC_INVALID_VALUE; + } + + if (pVal->value[0] == 'f' || pVal->value[0] == 'F') { + if (pVal->length == 1 || + (pVal->length == 5 && (pVal->value[1] == 'a' || pVal->value[1] == 'A') && + (pVal->value[2] == 'l' || pVal->value[2] == 'L') && (pVal->value[3] == 's' || pVal->value[3] == 'S') && + (pVal->value[4] == 'e' || pVal->value[4] == 'E'))) { + pVal->i = TSDB_FALSE; + pVal->type = TSDB_DATA_TYPE_BOOL; + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return TSDB_CODE_SUCCESS; + } + return TSDB_CODE_TSC_INVALID_VALUE; + } + + // number + if (smlParseNumber(pVal, msg)) { + pVal->length = (int16_t)tDataTypes[pVal->type].bytes; + return TSDB_CODE_SUCCESS; + } + + return TSDB_CODE_TSC_INVALID_VALUE; +} + +static int32_t smlParseTagKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLineInfo *currElement, bool isSameMeasure, + bool isSameCTable) { + if (isSameCTable) { + return TSDB_CODE_SUCCESS; + } + + int cnt = 0; + SArray *preLineKV = info->preLineTagKV; + if (info->dataFormat) { + if (unlikely(!isSameMeasure)) { + SSmlSTableMeta **tmp = + (SSmlSTableMeta **)taosHashGet(info->superTables, currElement->measure, currElement->measureLen); + + SSmlSTableMeta *sMeta = NULL; + if (unlikely(tmp == NULL)) { + char* measure = currElement->measure; + int measureLen = currElement->measureLen; + if(currElement->measureEscaped){ + measure = (char*)taosMemoryMalloc(currElement->measureLen); + memcpy(measure, currElement->measure, currElement->measureLen); + PROCESS_SLASH_IN_MEASUREMENT(measure, measureLen); + } + STableMeta *pTableMeta = smlGetMeta(info, measure, measureLen); + if(currElement->measureEscaped){ + taosMemoryFree(measure); + } + if (pTableMeta == NULL) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + sMeta = smlBuildSTableMeta(info->dataFormat); + sMeta->tableMeta = pTableMeta; + taosHashPut(info->superTables, currElement->measure, currElement->measureLen, &sMeta, POINTER_BYTES); + for(int i = pTableMeta->tableInfo.numOfColumns; i < pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns; i++){ + SSchema *tag = pTableMeta->schema + i; + SSmlKv kv = {.key = tag->name, .keyLen = strlen(tag->name), .type = tag->type, .length = (tag->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE }; + taosArrayPush(sMeta->tags, &kv); + } + tmp = &sMeta; + } + info->currSTableMeta = (*tmp)->tableMeta; + info->maxTagKVs = (*tmp)->tags; + } + } + taosArrayClearEx(preLineKV, freeSSmlKv); + + while (*sql < sqlEnd) { + if (unlikely(IS_SPACE(*sql))) { + break; + } + + // parse key + const char *key = *sql; + size_t keyLen = 0; + bool keyEscaped = false; + size_t keyLenEscaped = 0; + while (*sql < sqlEnd) { + if (unlikely(IS_COMMA(*sql))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", *sql); + return TSDB_CODE_SML_INVALID_DATA; + } + if (unlikely(IS_EQUAL(*sql))) { + keyLen = *sql - key; + (*sql)++; + break; + } + if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(*sql)) { + keyLenEscaped++; + keyEscaped = true; + } + (*sql)++; + } + + if (unlikely(IS_INVALID_COL_LEN(keyLen - keyLenEscaped))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid key or key is too long than 64", key); + return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; + } + + // parse value + const char *value = *sql; + size_t valueLen = 0; + bool valueEscaped = false; + size_t valueLenEscaped = 0; + while (*sql < sqlEnd) { + // parse value + if (unlikely(IS_SPACE(*sql) || IS_COMMA(*sql))) { + break; + } else if (unlikely(IS_EQUAL(*sql))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", *sql); + return TSDB_CODE_SML_INVALID_DATA; + } + + if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(*sql)) { + valueLenEscaped++; + valueEscaped = true; + } + + (*sql)++; + } + valueLen = *sql - value; + + if (unlikely(valueLen == 0)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid value", value); + return TSDB_CODE_SML_INVALID_DATA; + } + + if (unlikely(valueLen - valueLenEscaped > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)) { + return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + } + + if (keyEscaped){ + char *tmp = (char*)taosMemoryMalloc(keyLen); + memcpy(tmp, key, keyLen); + PROCESS_SLASH_IN_TAG_FIELD_KEY(tmp, keyLen); + key = tmp; + } + if (valueEscaped){ + char *tmp = (char*)taosMemoryMalloc(valueLen); + memcpy(tmp, value, valueLen); + PROCESS_SLASH_IN_TAG_FIELD_KEY(tmp, valueLen); + value = tmp; + } + SSmlKv kv = {.key = key, .keyLen = keyLen, .type = TSDB_DATA_TYPE_NCHAR, .value = value, .length = valueLen, .keyEscaped = keyEscaped, .valueEscaped = valueEscaped}; + taosArrayPush(preLineKV, &kv); + if (info->dataFormat) { + if (unlikely(cnt + 1 > info->currSTableMeta->tableInfo.numOfTags)) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + + if (unlikely(cnt >= taosArrayGetSize(info->maxTagKVs))) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(info->maxTagKVs, cnt); + + if (unlikely(!IS_SAME_KEY)) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + + if (unlikely(kv.length > maxKV->length)) { + maxKV->length = kv.length; + info->needModifySchema = true; + } + } + + cnt++; + if (IS_SPACE(*sql)) { + break; + } + (*sql)++; + } + + void *oneTable = taosHashGet(info->childTables, currElement->measure, currElement->measureTagsLen); + if ((oneTable != NULL)) { + return TSDB_CODE_SUCCESS; + } + + SSmlTableInfo *tinfo = smlBuildTableInfo(1, currElement->measure, currElement->measureLen); + if (unlikely(!tinfo)) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tinfo->tags = taosArrayDup(preLineKV, NULL); + for(size_t i = 0; i < taosArrayGetSize(preLineKV); i++){ + SSmlKv *kv = (SSmlKv *)taosArrayGet(preLineKV, i); + if(kv->keyEscaped)kv->key = NULL; + if(kv->valueEscaped)kv->value = NULL; + } + + smlSetCTableName(tinfo); + getTableUid(info, currElement, tinfo); + if (info->dataFormat) { + info->currSTableMeta->uid = tinfo->uid; + tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta); + if (tinfo->tableDataCtx == NULL) { + smlDestroyTableInfo(info, tinfo); + smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL); + return TSDB_CODE_SML_INVALID_DATA; + } + } + + taosHashPut(info->childTables, currElement->measure, currElement->measureTagsLen, &tinfo, POINTER_BYTES); + + return TSDB_CODE_SUCCESS; +} + +static int32_t smlParseColKv(SSmlHandle *info, char **sql, char *sqlEnd, SSmlLineInfo *currElement, bool isSameMeasure, + bool isSameCTable) { + int cnt = 0; + if (info->dataFormat) { + if (unlikely(!isSameCTable)) { + SSmlTableInfo **oneTable = + (SSmlTableInfo **)taosHashGet(info->childTables, currElement->measure, currElement->measureTagsLen); + if (unlikely(oneTable == NULL)) { + smlBuildInvalidDataMsg(&info->msgBuf, "child table should inside", currElement->measure); + return TSDB_CODE_SML_INVALID_DATA; + } + info->currTableDataCtx = (*oneTable)->tableDataCtx; + } + + if (unlikely(!isSameMeasure)) { + SSmlSTableMeta **tmp = + (SSmlSTableMeta **)taosHashGet(info->superTables, currElement->measure, currElement->measureLen); + if (unlikely(tmp == NULL)) { + char* measure = currElement->measure; + int measureLen = currElement->measureLen; + if(currElement->measureEscaped){ + measure = (char*)taosMemoryMalloc(currElement->measureLen); + memcpy(measure, currElement->measure, currElement->measureLen); + PROCESS_SLASH_IN_MEASUREMENT(measure, measureLen); + } + STableMeta *pTableMeta = smlGetMeta(info, measure, measureLen); + if(currElement->measureEscaped){ + taosMemoryFree(measure); + } + if (pTableMeta == NULL) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + *tmp = smlBuildSTableMeta(info->dataFormat); + (*tmp)->tableMeta = pTableMeta; + taosHashPut(info->superTables, currElement->measure, currElement->measureLen, tmp, POINTER_BYTES); + + for(int i = 0; i < pTableMeta->tableInfo.numOfColumns; i++){ + SSchema *tag = pTableMeta->schema + i; + SSmlKv kv = {.key = tag->name, .keyLen = strlen(tag->name), .type = tag->type }; + if(tag->type == TSDB_DATA_TYPE_NCHAR){ + kv.length = (tag->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE; + }else if(tag->type == TSDB_DATA_TYPE_BINARY){ + kv.length = tag->bytes - VARSTR_HEADER_SIZE; + } + taosArrayPush((*tmp)->cols, &kv); + } + } + info->currSTableMeta = (*tmp)->tableMeta; + info->masColKVs = (*tmp)->cols; + } + } + + while (*sql < sqlEnd) { + if (unlikely(IS_SPACE(*sql))) { + break; + } + + // parse key + const char *key = *sql; + size_t keyLen = 0; + bool keyEscaped = false; + size_t keyLenEscaped = 0; + while (*sql < sqlEnd) { + if (unlikely(IS_COMMA(*sql))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", *sql); + return TSDB_CODE_SML_INVALID_DATA; + } + if (unlikely(IS_EQUAL(*sql))) { + keyLen = *sql - key; + (*sql)++; + break; + } + if (IS_SLASH_LETTER_IN_TAG_FIELD_KEY(*sql)) { + keyLenEscaped++; + keyEscaped = true; + } + (*sql)++; + } + + if (unlikely(IS_INVALID_COL_LEN(keyLen - keyLenEscaped))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid key or key is too long than 64", key); + return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; + } + + // parse value + const char *value = *sql; + size_t valueLen = 0; + bool valueEscaped = false; + size_t valueLenEscaped = 0; + bool isInQuote = false; + const char *escapeChar = NULL; + while (*sql < sqlEnd) { + // parse value + if (unlikely(*(*sql) == QUOTE && (*(*sql - 1) != SLASH || (*sql - 1) == escapeChar))) { + isInQuote = !isInQuote; + (*sql)++; + continue; + } + if (!isInQuote) { + if (unlikely(IS_SPACE(*sql) || IS_COMMA(*sql))) { + break; + } + } + if (IS_SLASH_LETTER_IN_FIELD_VALUE(*sql) && (*sql - 1) != escapeChar) { + escapeChar = *sql; + valueEscaped = true; + valueLenEscaped++; + } + + (*sql)++; + } + valueLen = *sql - value; + + if (unlikely(isInQuote)) { + smlBuildInvalidDataMsg(&info->msgBuf, "only one quote", value); + return TSDB_CODE_SML_INVALID_DATA; + } + if (unlikely(valueLen == 0)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid value", value); + return TSDB_CODE_SML_INVALID_DATA; + } + + SSmlKv kv = {.key = key, .keyLen = keyLen, .value = value, .length = valueLen}; + int32_t ret = smlParseValue(&kv, &info->msgBuf); + if (ret != TSDB_CODE_SUCCESS) { + smlBuildInvalidDataMsg(&info->msgBuf, "smlParseValue error", value); + return ret; + } + + if (keyEscaped){ + char *tmp = (char*)taosMemoryMalloc(kv.keyLen); + memcpy(tmp, key, kv.keyLen); + PROCESS_SLASH_IN_TAG_FIELD_KEY(tmp, kv.keyLen); + kv.key = tmp; + kv.keyEscaped = keyEscaped; + } + + if (valueEscaped){ + char *tmp = (char*)taosMemoryMalloc(kv.length); + memcpy(tmp, kv.value, kv.length); + PROCESS_SLASH_IN_FIELD_VALUE(tmp, kv.length); + kv.value = tmp; + kv.valueEscaped = valueEscaped; + } + + if (info->dataFormat) { + // cnt begin 0, add ts so + 2 + if (unlikely(cnt + 2 > info->currSTableMeta->tableInfo.numOfColumns)) { + info->dataFormat = false; + info->reRun = true; + freeSSmlKv(&kv); + return TSDB_CODE_SUCCESS; + } + // bind data + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kv, cnt + 1); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + uDebug("smlBuildCol error, retry"); + info->dataFormat = false; + info->reRun = true; + freeSSmlKv(&kv); + return TSDB_CODE_SUCCESS; + } + if (cnt >= taosArrayGetSize(info->masColKVs)) { + info->dataFormat = false; + info->reRun = true; + freeSSmlKv(&kv); + return TSDB_CODE_SUCCESS; + } + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(info->masColKVs, cnt); + if (kv.type != maxKV->type) { + info->dataFormat = false; + info->reRun = true; + freeSSmlKv(&kv); + return TSDB_CODE_SUCCESS; + } + if (unlikely(!IS_SAME_KEY)) { + info->dataFormat = false; + info->reRun = true; + freeSSmlKv(&kv); + return TSDB_CODE_SUCCESS; + } + + if (unlikely(IS_VAR_DATA_TYPE(kv.type) && kv.length > maxKV->length)) { + maxKV->length = kv.length; + info->needModifySchema = true; + } + freeSSmlKv(&kv); + } else { + if (currElement->colArray == NULL) { + currElement->colArray = taosArrayInit_s(sizeof(SSmlKv), 1); + } + taosArrayPush(currElement->colArray, &kv); // reserve for timestamp + } + + cnt++; + if (IS_SPACE(*sql)) { + break; + } + (*sql)++; + } + + return TSDB_CODE_SUCCESS; +} + +int32_t smlParseInfluxString(SSmlHandle *info, char *sql, char *sqlEnd, SSmlLineInfo *elements) { + if (!sql) return TSDB_CODE_SML_INVALID_DATA; + JUMP_SPACE(sql, sqlEnd) + if (unlikely(*sql == COMMA)) return TSDB_CODE_SML_INVALID_DATA; + elements->measure = sql; + + // parse measure + size_t measureLenEscaped = 0; + while (sql < sqlEnd) { + if (unlikely((sql != elements->measure) && IS_SLASH_LETTER_IN_MEASUREMENT(sql))) { + elements->measureEscaped = true; + measureLenEscaped++; + sql++; + continue; + } + if (unlikely(IS_COMMA(sql))) { + break; + } + + if (unlikely(IS_SPACE(sql))) { + break; + } + sql++; + } + elements->measureLen = sql - elements->measure; + if (unlikely(IS_INVALID_TABLE_LEN(elements->measureLen - measureLenEscaped))) { + smlBuildInvalidDataMsg(&info->msgBuf, "measure is empty or too large than 192", NULL); + return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; + } + + // to get measureTagsLen before + const char *tmp = sql; + while (tmp < sqlEnd) { + if (unlikely(IS_SPACE(tmp))) { + break; + } + tmp++; + } + elements->measureTagsLen = tmp - elements->measure; + + bool isSameCTable = false; + bool isSameMeasure = false; + if (IS_SAME_CHILD_TABLE) { + isSameCTable = true; + isSameMeasure = true; + } else if (info->dataFormat) { + isSameMeasure = IS_SAME_SUPER_TABLE; + } + // parse tag + if (*sql == COMMA) sql++; + elements->tags = sql; + + int ret = smlParseTagKv(info, &sql, sqlEnd, elements, isSameMeasure, isSameCTable); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + return ret; + } + if (unlikely(info->reRun)) { + return TSDB_CODE_SUCCESS; + } + + sql = elements->measure + elements->measureTagsLen; + elements->tagsLen = sql - elements->tags; + + // parse cols + JUMP_SPACE(sql, sqlEnd) + elements->cols = sql; + + ret = smlParseColKv(info, &sql, sqlEnd, elements, isSameMeasure, isSameCTable); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + return ret; + } + + if (unlikely(info->reRun)) { + return TSDB_CODE_SUCCESS; + } + + elements->colsLen = sql - elements->cols; + if (unlikely(elements->colsLen == 0)) { + smlBuildInvalidDataMsg(&info->msgBuf, "cols is empty", NULL); + return TSDB_CODE_SML_INVALID_DATA; + } + + // parse timestamp + JUMP_SPACE(sql, sqlEnd) + elements->timestamp = sql; + while (sql < sqlEnd) { + if (unlikely(isspace(*sql))) { + break; + } + sql++; + } + elements->timestampLen = sql - elements->timestamp; + + int64_t ts = smlParseInfluxTime(info, elements->timestamp, elements->timestampLen); + if (unlikely(ts <= 0)) { + uError("SML:0x%" PRIx64 " smlParseTS error:%" PRId64, info->id, ts); + return TSDB_CODE_INVALID_TIMESTAMP; + } + // add ts to + SSmlKv kv = {.key = TS, + .keyLen = TS_LEN, + .type = TSDB_DATA_TYPE_TIMESTAMP, + .i = ts, + .length = (size_t)tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes, + .keyEscaped = false, + .valueEscaped = false}; + if (info->dataFormat) { + uDebug("SML:0x%" PRIx64 " smlParseInfluxString format true, ts:%" PRId64, info->id, ts); + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kv, 0); + if(ret != TSDB_CODE_SUCCESS){return ret;} + ret = smlBuildRow(info->currTableDataCtx); + if(ret != TSDB_CODE_SUCCESS){return ret;} + clearColValArray(info->currTableDataCtx->pValues); + } else { + uDebug("SML:0x%" PRIx64 " smlParseInfluxString format false, ts:%" PRId64, info->id, ts); + taosArraySet(elements->colArray, 0, &kv); + } + info->preLine = *elements; + + return ret; +} diff --git a/source/client/src/clientSmlTelnet.c b/source/client/src/clientSmlTelnet.c new file mode 100644 index 0000000000000000000000000000000000000000..c5dd20ba7b8b6696d222b58cb3dc34c08b73f9ec --- /dev/null +++ b/source/client/src/clientSmlTelnet.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "clientSml.h" + +int32_t is_same_child_table_telnet(const void *a, const void *b) { + SSmlLineInfo *t1 = (SSmlLineInfo *)a; + SSmlLineInfo *t2 = (SSmlLineInfo *)b; + // uError("is_same_child_table_telnet len:%d,%d %s,%s @@@ len:%d,%d %s,%s", t1->measureLen, t2->measureLen, + // t1->measure, t2->measure, t1->tagsLen, t2->tagsLen, t1->tags, t2->tags); + if (t1 == NULL || t2 == NULL || t1->measure == NULL || t2->measure == NULL || t1->tags == NULL || t2->tags == NULL) + return 1; + return (((t1->measureLen == t2->measureLen) && memcmp(t1->measure, t2->measure, t1->measureLen) == 0) && + ((t1->tagsLen == t2->tagsLen) && memcmp(t1->tags, t2->tags, t1->tagsLen) == 0)) + ? 0 + : 1; +} + +int64_t smlParseOpenTsdbTime(SSmlHandle *info, const char *data, int32_t len) { + uint8_t toPrecision = info->currSTableMeta ? info->currSTableMeta->tableInfo.precision : TSDB_TIME_PRECISION_NANO; + + if (unlikely(!data)) { + smlBuildInvalidDataMsg(&info->msgBuf, "timestamp can not be null", NULL); + return -1; + } + if (unlikely(len == 1 && data[0] == '0')) { + return taosGetTimestampNs() / smlFactorNS[toPrecision]; + } + int8_t fromPrecision = smlGetTsTypeByLen(len); + if (unlikely(fromPrecision == -1)) { + smlBuildInvalidDataMsg(&info->msgBuf, + "timestamp precision can only be seconds(10 digits) or milli seconds(13 digits)", data); + return -1; + } + int64_t ts = smlGetTimeValue(data, len, fromPrecision, toPrecision); + if (unlikely(ts == -1)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", data); + return -1; + } + return ts; +} + +static void smlParseTelnetElement(char **sql, char *sqlEnd, char **data, int32_t *len) { + while (*sql < sqlEnd) { + if (unlikely((**sql != SPACE && !(*data)))) { + *data = *sql; + } else if (unlikely(**sql == SPACE && *data)) { + *len = *sql - *data; + break; + } + (*sql)++; + } +} + +static int32_t smlParseTelnetTags(SSmlHandle *info, char *data, char *sqlEnd, SSmlLineInfo *elements, SSmlMsgBuf *msg) { + if (is_same_child_table_telnet(elements, &info->preLine) == 0) { + elements->measureTag = info->preLine.measureTag; + return TSDB_CODE_SUCCESS; + } + + bool isSameMeasure = IS_SAME_SUPER_TABLE; + + int cnt = 0; + SArray *preLineKV = info->preLineTagKV; + if (info->dataFormat) { + if (!isSameMeasure) { + SSmlSTableMeta **tmp = (SSmlSTableMeta **)taosHashGet(info->superTables, elements->measure, elements->measureLen); + SSmlSTableMeta *sMeta = NULL; + if (unlikely(tmp == NULL)) { + STableMeta *pTableMeta = smlGetMeta(info, elements->measure, elements->measureLen); + if (pTableMeta == NULL) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + sMeta = smlBuildSTableMeta(info->dataFormat); + sMeta->tableMeta = pTableMeta; + taosHashPut(info->superTables, elements->measure, elements->measureLen, &sMeta, POINTER_BYTES); + for(int i = pTableMeta->tableInfo.numOfColumns; i < pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns; i++){ + SSchema *tag = pTableMeta->schema + i; + SSmlKv kv = {.key = tag->name, .keyLen = strlen(tag->name), .type = tag->type, .length = (tag->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE }; + taosArrayPush(sMeta->tags, &kv); + } + tmp = &sMeta; + } + info->currSTableMeta = (*tmp)->tableMeta; + info->maxTagKVs = (*tmp)->tags; + } + } + + taosArrayClear(preLineKV); + const char *sql = data; + while (sql < sqlEnd) { + JUMP_SPACE(sql, sqlEnd) + if (unlikely(*sql == '\0')) break; + + const char *key = sql; + size_t keyLen = 0; + + // parse key + while (sql < sqlEnd) { + if (unlikely(*sql == SPACE)) { + smlBuildInvalidDataMsg(msg, "invalid data", sql); + return TSDB_CODE_SML_INVALID_DATA; + } + if (unlikely(*sql == EQUAL)) { + keyLen = sql - key; + sql++; + break; + } + sql++; + } + + if (unlikely(IS_INVALID_COL_LEN(keyLen))) { + smlBuildInvalidDataMsg(msg, "invalid key or key is too long than 64", key); + return TSDB_CODE_TSC_INVALID_COLUMN_LENGTH; + } + // if (smlCheckDuplicateKey(key, keyLen, dumplicateKey)) { + // smlBuildInvalidDataMsg(msg, "dumplicate key", key); + // return TSDB_CODE_TSC_DUP_NAMES; + // } + + // parse value + const char *value = sql; + size_t valueLen = 0; + while (sql < sqlEnd) { + // parse value + if (unlikely(*sql == SPACE)) { + break; + } + if (unlikely(*sql == EQUAL)) { + smlBuildInvalidDataMsg(msg, "invalid data", sql); + return TSDB_CODE_SML_INVALID_DATA; + } + sql++; + } + valueLen = sql - value; + + if (unlikely(valueLen == 0)) { + smlBuildInvalidDataMsg(msg, "invalid value", value); + return TSDB_CODE_TSC_INVALID_VALUE; + } + + if (unlikely(valueLen > (TSDB_MAX_NCHAR_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)) { + return TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN; + } + + SSmlKv kv = {.key = key, .keyLen = keyLen, .type = TSDB_DATA_TYPE_NCHAR, .value = value, .length = valueLen}; + + if (info->dataFormat) { + if (unlikely(cnt + 1 > info->currSTableMeta->tableInfo.numOfTags)) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + if (unlikely(cnt >= taosArrayGetSize(info->maxTagKVs))) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + SSmlKv *maxKV = (SSmlKv *)taosArrayGet(info->maxTagKVs, cnt); + if (unlikely(!IS_SAME_KEY)) { + info->dataFormat = false; + info->reRun = true; + return TSDB_CODE_SUCCESS; + } + if (unlikely(kv.length > maxKV->length)) { + maxKV->length = kv.length; + info->needModifySchema = true; + } + } + taosArrayPush(preLineKV, &kv); + cnt++; + } + + elements->measureTag = (char *)taosMemoryMalloc(elements->measureLen + elements->tagsLen); + memcpy(elements->measureTag, elements->measure, elements->measureLen); + memcpy(elements->measureTag + elements->measureLen, elements->tags, elements->tagsLen); + elements->measureTagsLen = elements->measureLen + elements->tagsLen; + + SSmlTableInfo **tmp = + (SSmlTableInfo **)taosHashGet(info->childTables, elements->measureTag, elements->measureLen + elements->tagsLen); + SSmlTableInfo *tinfo = NULL; + if (unlikely(tmp == NULL)) { + tinfo = smlBuildTableInfo(1, elements->measure, elements->measureLen); + if (!tinfo) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tinfo->tags = taosArrayDup(preLineKV, NULL); + + smlSetCTableName(tinfo); + getTableUid(info, elements, tinfo); + if (info->dataFormat) { + info->currSTableMeta->uid = tinfo->uid; + tinfo->tableDataCtx = smlInitTableDataCtx(info->pQuery, info->currSTableMeta); + if (tinfo->tableDataCtx == NULL) { + smlBuildInvalidDataMsg(&info->msgBuf, "smlInitTableDataCtx error", NULL); + smlDestroyTableInfo(info, tinfo); + return TSDB_CODE_SML_INVALID_DATA; + } + } + + // SSmlLineInfo *key = (SSmlLineInfo *)taosMemoryMalloc(sizeof(SSmlLineInfo)); + // *key = *elements; + // tinfo->key = key; + taosHashPut(info->childTables, elements->measureTag, elements->measureLen + elements->tagsLen, &tinfo, + POINTER_BYTES); + tmp = &tinfo; + } + if (info->dataFormat) info->currTableDataCtx = (*tmp)->tableDataCtx; + + return TSDB_CODE_SUCCESS; +} + +// format: =[ =] +int32_t smlParseTelnetString(SSmlHandle *info, char *sql, char *sqlEnd, SSmlLineInfo *elements) { + if (!sql) return TSDB_CODE_SML_INVALID_DATA; + + // parse metric + smlParseTelnetElement(&sql, sqlEnd, &elements->measure, &elements->measureLen); + if (unlikely((!(elements->measure) || IS_INVALID_TABLE_LEN(elements->measureLen)))) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid data", sql); + return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; + } + + // parse timestamp + smlParseTelnetElement(&sql, sqlEnd, &elements->timestamp, &elements->timestampLen); + if (unlikely(!elements->timestamp || elements->timestampLen == 0)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", sql); + return TSDB_CODE_SML_INVALID_DATA; + } + + bool needConverTime = false; // get TS before parse tag(get meta), so need conver time + if (info->dataFormat && info->currSTableMeta == NULL) { + needConverTime = true; + } + int64_t ts = smlParseOpenTsdbTime(info, elements->timestamp, elements->timestampLen); + if (unlikely(ts < 0)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid timestamp", sql); + return TSDB_CODE_INVALID_TIMESTAMP; + } + SSmlKv kvTs = {.key = TS, + .keyLen = TS_LEN, + .type = TSDB_DATA_TYPE_TIMESTAMP, + .i = ts, + .length = (size_t)tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes}; + + // parse value + smlParseTelnetElement(&sql, sqlEnd, &elements->cols, &elements->colsLen); + if (unlikely(!elements->cols || elements->colsLen == 0)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid value", sql); + return TSDB_CODE_TSC_INVALID_VALUE; + } + + SSmlKv kv = {.key = VALUE, .keyLen = VALUE_LEN, .value = elements->cols, .length = (size_t)elements->colsLen}; + if (smlParseValue(&kv, &info->msgBuf) != TSDB_CODE_SUCCESS) { + return TSDB_CODE_TSC_INVALID_VALUE; + } + + JUMP_SPACE(sql, sqlEnd) + + elements->tags = sql; + elements->tagsLen = sqlEnd - sql; + if (unlikely(!elements->tags || elements->tagsLen == 0)) { + smlBuildInvalidDataMsg(&info->msgBuf, "invalid value", sql); + return TSDB_CODE_TSC_INVALID_VALUE; + } + + int ret = smlParseTelnetTags(info, sql, sqlEnd, elements, &info->msgBuf); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + return ret; + } + + if (unlikely(info->reRun)) { + return TSDB_CODE_SUCCESS; + } + + if (info->dataFormat && info->currSTableMeta != NULL) { + if (needConverTime) { + kvTs.i = convertTimePrecision(kvTs.i, TSDB_TIME_PRECISION_NANO, info->currSTableMeta->tableInfo.precision); + } + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kvTs, 0); + if (ret == TSDB_CODE_SUCCESS) { + ret = smlBuildCol(info->currTableDataCtx, info->currSTableMeta->schema, &kv, 1); + } + if (ret == TSDB_CODE_SUCCESS) { + ret = smlBuildRow(info->currTableDataCtx); + } + clearColValArray(info->currTableDataCtx->pValues); + if (unlikely(ret != TSDB_CODE_SUCCESS)) { + smlBuildInvalidDataMsg(&info->msgBuf, "smlBuildCol error", NULL); + return ret; + } + } else { + if (elements->colArray == NULL) { + elements->colArray = taosArrayInit(16, sizeof(SSmlKv)); + } + taosArrayPush(elements->colArray, &kvTs); + taosArrayPush(elements->colArray, &kv); + } + info->preLine = *elements; + + return TSDB_CODE_SUCCESS; +} \ No newline at end of file diff --git a/source/client/src/clientStmt.c b/source/client/src/clientStmt.c index 5646f58ee14885b910ec4781bd5c6f0a8620ff47..975b304bf4574bb84e16b1287b3dfec73c8ce869 100644 --- a/source/client/src/clientStmt.c +++ b/source/client/src/clientStmt.c @@ -32,8 +32,14 @@ int32_t stmtSwitchStatus(STscStmt* pStmt, STMT_STATUS newStatus) { STMT_LOG_SEQ(newStatus); } + if (pStmt->errCode && newStatus != STMT_PREPARE) { + STMT_DLOG("stmt already failed with err: %s", tstrerror(pStmt->errCode)); + return pStmt->errCode; + } + switch (newStatus) { case STMT_PREPARE: + pStmt->errCode = 0; break; case STMT_SETTBNAME: if (STMT_STATUS_EQ(INIT) || STMT_STATUS_EQ(BIND) || STMT_STATUS_EQ(BIND_COL)) { @@ -172,12 +178,11 @@ int32_t stmtUpdateBindInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags, return TSDB_CODE_SUCCESS; } -int32_t stmtUpdateExecInfo(TAOS_STMT* stmt, SHashObj* pVgHash, SHashObj* pBlockHash, bool autoCreateTbl) { +int32_t stmtUpdateExecInfo(TAOS_STMT* stmt, SHashObj* pVgHash, SHashObj* pBlockHash) { STscStmt* pStmt = (STscStmt*)stmt; pStmt->sql.pVgHash = pVgHash; pStmt->exec.pBlockHash = pBlockHash; - pStmt->exec.autoCreateTbl = autoCreateTbl; return TSDB_CODE_SUCCESS; } @@ -187,7 +192,7 @@ int32_t stmtUpdateInfo(TAOS_STMT* stmt, STableMeta* pTableMeta, void* tags, SNam STscStmt* pStmt = (STscStmt*)stmt; STMT_ERR_RET(stmtUpdateBindInfo(stmt, pTableMeta, tags, tbName, sTableName, autoCreateTbl)); - STMT_ERR_RET(stmtUpdateExecInfo(stmt, pVgHash, pBlockHash, autoCreateTbl)); + STMT_ERR_RET(stmtUpdateExecInfo(stmt, pVgHash, pBlockHash)); pStmt->sql.autoCreateTbl = autoCreateTbl; @@ -198,7 +203,10 @@ int32_t stmtGetExecInfo(TAOS_STMT* stmt, SHashObj** pVgHash, SHashObj** pBlockHa STscStmt* pStmt = (STscStmt*)stmt; *pVgHash = pStmt->sql.pVgHash; + pStmt->sql.pVgHash = NULL; + *pBlockHash = pStmt->exec.pBlockHash; + pStmt->exec.pBlockHash = NULL; return TSDB_CODE_SUCCESS; } @@ -215,16 +223,16 @@ int32_t stmtCacheBlock(STscStmt* pStmt) { return TSDB_CODE_SUCCESS; } - STableDataBlocks** pSrc = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); + STableDataCxt** pSrc = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (!pSrc) { return TSDB_CODE_OUT_OF_MEMORY; } - STableDataBlocks* pDst = NULL; + STableDataCxt* pDst = NULL; - STMT_ERR_RET(qCloneStmtDataBlock(&pDst, *pSrc)); + STMT_ERR_RET(qCloneStmtDataBlock(&pDst, *pSrc, true)); SStmtTableCache cache = { - .pDataBlock = pDst, + .pDataCtx = pDst, .boundTags = pStmt->bInfo.boundTags, }; @@ -242,6 +250,8 @@ int32_t stmtCacheBlock(STscStmt* pStmt) { } int32_t stmtParseSql(STscStmt* pStmt) { + pStmt->exec.pCurrBlock = NULL; + SStmtCallback stmtCb = { .pStmt = pStmt, .getTbNameFn = stmtGetTbName, @@ -274,7 +284,7 @@ int32_t stmtCleanBindInfo(STscStmt* pStmt) { pStmt->bInfo.tbName[0] = 0; pStmt->bInfo.tbFName[0] = 0; if (!pStmt->bInfo.tagsCached) { - destroyBoundColumnInfo(pStmt->bInfo.boundTags); + qDestroyBoundColInfo(pStmt->bInfo.boundTags); taosMemoryFreeClear(pStmt->bInfo.boundTags); } memset(pStmt->bInfo.stbFName, 0, TSDB_TABLE_FNAME_LEN); @@ -290,12 +300,13 @@ int32_t stmtCleanExecInfo(STscStmt* pStmt, bool keepTable, bool deepClean) { size_t keyLen = 0; void* pIter = taosHashIterate(pStmt->exec.pBlockHash, NULL); while (pIter) { - STableDataBlocks* pBlocks = *(STableDataBlocks**)pIter; - char* key = taosHashGetKey(pIter, &keyLen); - STableMeta* pMeta = qGetTableMetaInDataBlock(pBlocks); + STableDataCxt* pBlocks = *(STableDataCxt**)pIter; + char* key = taosHashGetKey(pIter, &keyLen); + STableMeta* pMeta = qGetTableMetaInDataBlock(pBlocks); - if (keepTable && (strlen(pStmt->bInfo.tbFName) == keyLen) && strncmp(pStmt->bInfo.tbFName, key, keyLen) == 0) { - STMT_ERR_RET(qResetStmtDataBlock(pBlocks, true)); + if (keepTable && pBlocks == pStmt->exec.pCurrBlock) { + TSWAP(pBlocks->pData, pStmt->exec.pCurrTbData); + STMT_ERR_RET(qResetStmtDataBlock(pBlocks, false)); pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter); continue; @@ -307,8 +318,6 @@ int32_t stmtCleanExecInfo(STscStmt* pStmt, bool keepTable, bool deepClean) { pIter = taosHashIterate(pStmt->exec.pBlockHash, pIter); } - pStmt->exec.autoCreateTbl = false; - if (keepTable) { return TSDB_CODE_SUCCESS; } @@ -316,12 +325,17 @@ int32_t stmtCleanExecInfo(STscStmt* pStmt, bool keepTable, bool deepClean) { taosHashCleanup(pStmt->exec.pBlockHash); pStmt->exec.pBlockHash = NULL; + tDestroySubmitTbData(pStmt->exec.pCurrTbData, TSDB_MSG_FLG_ENCODE); + taosMemoryFreeClear(pStmt->exec.pCurrTbData); + STMT_ERR_RET(stmtCleanBindInfo(pStmt)); return TSDB_CODE_SUCCESS; } int32_t stmtCleanSQLInfo(STscStmt* pStmt) { + STMT_DLOG_E("start to free SQL info"); + taosMemoryFree(pStmt->sql.queryRes.fields); taosMemoryFree(pStmt->sql.queryRes.userFields); taosMemoryFree(pStmt->sql.sqlStr); @@ -334,8 +348,8 @@ int32_t stmtCleanSQLInfo(STscStmt* pStmt) { while (pIter) { SStmtTableCache* pCache = (SStmtTableCache*)pIter; - qDestroyStmtDataBlock(pCache->pDataBlock); - destroyBoundColumnInfo(pCache->boundTags); + qDestroyStmtDataBlock(pCache->pDataCtx); + qDestroyBoundColInfo(pCache->boundTags); taosMemoryFreeClear(pCache->boundTags); pIter = taosHashIterate(pStmt->sql.pTableCache, pIter); @@ -348,10 +362,13 @@ int32_t stmtCleanSQLInfo(STscStmt* pStmt) { memset(&pStmt->sql, 0, sizeof(pStmt->sql)); + STMT_DLOG_E("end to free SQL info"); + return TSDB_CODE_SUCCESS; } -int32_t stmtRebuildDataBlock(STscStmt* pStmt, STableDataBlocks* pDataBlock, STableDataBlocks** newBlock, uint64_t uid) { +int32_t stmtRebuildDataBlock(STscStmt* pStmt, STableDataCxt* pDataBlock, STableDataCxt** newBlock, uint64_t uid, + uint64_t suid) { SEpSet ep = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp); SVgroupInfo vgInfo = {0}; SRequestConnInfo conn = {.pTrans = pStmt->taos->pAppInfo->pTransporter, @@ -363,7 +380,9 @@ int32_t stmtRebuildDataBlock(STscStmt* pStmt, STableDataBlocks* pDataBlock, STab STMT_ERR_RET( taosHashPut(pStmt->sql.pVgHash, (const char*)&vgInfo.vgId, sizeof(vgInfo.vgId), (char*)&vgInfo, sizeof(vgInfo))); - STMT_ERR_RET(qRebuildStmtDataBlock(newBlock, pDataBlock, uid, vgInfo.vgId)); + STMT_ERR_RET(qRebuildStmtDataBlock(newBlock, pDataBlock, uid, suid, vgInfo.vgId, pStmt->sql.autoCreateTbl)); + + STMT_DLOG("tableDataCxt rebuilt, uid:%" PRId64 ", vgId:%d", uid, vgInfo.vgId); return TSDB_CODE_SUCCESS; } @@ -372,12 +391,13 @@ int32_t stmtGetFromCache(STscStmt* pStmt) { pStmt->bInfo.needParse = true; pStmt->bInfo.inExecCache = false; - STableDataBlocks* pBlockInExec = - taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); - if (pBlockInExec) { + STableDataCxt** pCxtInExec = taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); + if (pCxtInExec) { pStmt->bInfo.needParse = false; pStmt->bInfo.inExecCache = true; + pStmt->exec.pCurrBlock = *pCxtInExec; + if (pStmt->sql.autoCreateTbl) { tscDebug("reuse stmt block for tb %s in execBlock", pStmt->bInfo.tbFName); return TSDB_CODE_SUCCESS; @@ -386,7 +406,10 @@ int32_t stmtGetFromCache(STscStmt* pStmt) { if (NULL == pStmt->sql.pTableCache || taosHashGetSize(pStmt->sql.pTableCache) <= 0) { if (pStmt->bInfo.inExecCache) { - ASSERT(taosHashGetSize(pStmt->exec.pBlockHash) == 1); + if (ASSERT(taosHashGetSize(pStmt->exec.pBlockHash) == 1)) { + tscError("stmtGetFromCache error"); + return TSDB_CODE_TSC_STMT_CACHE_ERROR; + } pStmt->bInfo.needParse = false; tscDebug("reuse stmt block for tb %s in execBlock", pStmt->bInfo.tbFName); return TSDB_CODE_SUCCESS; @@ -404,18 +427,18 @@ int32_t stmtGetFromCache(STscStmt* pStmt) { SStmtTableCache* pCache = taosHashGet(pStmt->sql.pTableCache, &pStmt->bInfo.tbSuid, sizeof(pStmt->bInfo.tbSuid)); if (pCache) { pStmt->bInfo.needParse = false; - pStmt->exec.autoCreateTbl = true; - pStmt->bInfo.tbUid = 0; - STableDataBlocks* pNewBlock = NULL; - STMT_ERR_RET(stmtRebuildDataBlock(pStmt, pCache->pDataBlock, &pNewBlock, 0)); + STableDataCxt* pNewBlock = NULL; + STMT_ERR_RET(stmtRebuildDataBlock(pStmt, pCache->pDataCtx, &pNewBlock, 0, pStmt->bInfo.tbSuid)); if (taosHashPut(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName), &pNewBlock, POINTER_BYTES)) { STMT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } + pStmt->exec.pCurrBlock = pNewBlock; + tscDebug("reuse stmt block for tb %s in sqlBlock, suid:0x%" PRIx64, pStmt->bInfo.tbFName, pStmt->bInfo.tbSuid); return TSDB_CODE_SUCCESS; @@ -431,11 +454,10 @@ int32_t stmtGetFromCache(STscStmt* pStmt) { .mgmtEps = getEpSet_s(&pStmt->taos->pAppInfo->mgmtEp)}; int32_t code = catalogGetTableMeta(pStmt->pCatalog, &conn, &pStmt->bInfo.sname, &pTableMeta); if (TSDB_CODE_PAR_TABLE_NOT_EXIST == code) { - STMT_ERR_RET(stmtCleanBindInfo(pStmt)); - tscDebug("tb %s not exist", pStmt->bInfo.tbFName); + stmtCleanBindInfo(pStmt); - return TSDB_CODE_SUCCESS; + STMT_ERR_RET(code); } STMT_ERR_RET(code); @@ -486,14 +508,16 @@ int32_t stmtGetFromCache(STscStmt* pStmt) { pStmt->bInfo.boundTags = pCache->boundTags; pStmt->bInfo.tagsCached = true; - STableDataBlocks* pNewBlock = NULL; - STMT_ERR_RET(stmtRebuildDataBlock(pStmt, pCache->pDataBlock, &pNewBlock, uid)); + STableDataCxt* pNewBlock = NULL; + STMT_ERR_RET(stmtRebuildDataBlock(pStmt, pCache->pDataCtx, &pNewBlock, uid, suid)); if (taosHashPut(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName), &pNewBlock, POINTER_BYTES)) { STMT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } + pStmt->exec.pCurrBlock = pNewBlock; + tscDebug("tb %s in sqlBlock list, set to current", pStmt->bInfo.tbFName); return TSDB_CODE_SUCCESS; @@ -611,8 +635,8 @@ int stmtSetTbTags(TAOS_STMT* stmt, TAOS_MULTI_BIND* tags) { return TSDB_CODE_SUCCESS; } - STableDataBlocks** pDataBlock = - (STableDataBlocks**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); + STableDataCxt** pDataBlock = + (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (NULL == pDataBlock) { tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName); STMT_ERR_RET(TSDB_CODE_APP_ERROR); @@ -623,8 +647,6 @@ int stmtSetTbTags(TAOS_STMT* stmt, TAOS_MULTI_BIND* tags) { pStmt->bInfo.sname.tname, tags, pStmt->exec.pRequest->msgBuf, pStmt->exec.pRequest->msgBufLen)); - pStmt->exec.autoCreateTbl = true; - return TSDB_CODE_SUCCESS; } @@ -634,8 +656,8 @@ int stmtFetchTagFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD_E** fields STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR); } - STableDataBlocks** pDataBlock = - (STableDataBlocks**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); + STableDataCxt** pDataBlock = + (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (NULL == pDataBlock) { tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName); STMT_ERR_RET(TSDB_CODE_APP_ERROR); @@ -652,8 +674,8 @@ int stmtFetchColFields(STscStmt* pStmt, int32_t* fieldNum, TAOS_FIELD_E** fields STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR); } - STableDataBlocks** pDataBlock = - (STableDataBlocks**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); + STableDataCxt** pDataBlock = + (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); if (NULL == pDataBlock) { tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName); STMT_ERR_RET(TSDB_CODE_APP_ERROR); @@ -726,11 +748,18 @@ int stmtBindBatch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind, int32_t colIdx) { return TSDB_CODE_SUCCESS; } - STableDataBlocks** pDataBlock = - (STableDataBlocks**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); - if (NULL == pDataBlock) { - tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName); - STMT_ERR_RET(TSDB_CODE_APP_ERROR); + STableDataCxt** pDataBlock = NULL; + + if (pStmt->exec.pCurrBlock) { + pDataBlock = &pStmt->exec.pCurrBlock; + } else { + pDataBlock = + (STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName)); + if (NULL == pDataBlock) { + tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName); + STMT_ERR_RET(TSDB_CODE_TSC_STMT_CACHE_ERROR); + } + pStmt->exec.pCurrBlock = *pDataBlock; } if (colIdx < 0) { @@ -773,13 +802,13 @@ int stmtAddBatch(TAOS_STMT* stmt) { int stmtUpdateTableUid(STscStmt* pStmt, SSubmitRsp* pRsp) { tscDebug("stmt start to update tbUid, blockNum: %d", pRsp->nBlocks); - int32_t code = 0; - int32_t finalCode = 0; - size_t keyLen = 0; - STableDataBlocks** pIter = taosHashIterate(pStmt->exec.pBlockHash, NULL); + int32_t code = 0; + int32_t finalCode = 0; + size_t keyLen = 0; + void* pIter = taosHashIterate(pStmt->exec.pBlockHash, NULL); while (pIter) { - STableDataBlocks* pBlock = *pIter; - char* key = taosHashGetKey(pIter, &keyLen); + STableDataCxt* pBlock = *(STableDataCxt**)pIter; + char* key = taosHashGetKey(pIter, &keyLen); STableMeta* pMeta = qGetTableMetaInDataBlock(pBlock); if (pMeta->uid) { @@ -858,7 +887,6 @@ int stmtExec(TAOS_STMT* stmt) { STscStmt* pStmt = (STscStmt*)stmt; int32_t code = 0; SSubmitRsp* pRsp = NULL; - bool autoCreateTbl = pStmt->exec.autoCreateTbl; STMT_DLOG_E("start to exec"); @@ -867,8 +895,13 @@ int stmtExec(TAOS_STMT* stmt) { if (STMT_TYPE_QUERY == pStmt->sql.type) { launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL); } else { + tDestroySubmitTbData(pStmt->exec.pCurrTbData, TSDB_MSG_FLG_ENCODE); + taosMemoryFreeClear(pStmt->exec.pCurrTbData); + + STMT_ERR_RET(qCloneCurrentTbData(pStmt->exec.pCurrBlock, &pStmt->exec.pCurrTbData)); + STMT_ERR_RET(qBuildStmtOutput(pStmt->sql.pQuery, pStmt->sql.pVgHash, pStmt->exec.pBlockHash)); - launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, (autoCreateTbl ? (void**)&pRsp : NULL)); + launchQueryImpl(pStmt->exec.pRequest, pStmt->sql.pQuery, true, NULL); } if (pStmt->exec.pRequest->code && NEED_CLIENT_HANDLE_ERROR(pStmt->exec.pRequest->code)) { @@ -891,15 +924,6 @@ _return: stmtCleanExecInfo(pStmt, (code ? false : true), false); - if (TSDB_CODE_SUCCESS == code && autoCreateTbl) { - if (NULL == pRsp) { - tscError("no submit resp got for auto create table"); - code = TSDB_CODE_APP_ERROR; - } else { - code = stmtUpdateTableUid(pStmt, pRsp); - } - } - tFreeSSubmitRsp(pRsp); ++pStmt->sql.runTimes; @@ -910,9 +934,13 @@ _return: int stmtClose(TAOS_STMT* stmt) { STscStmt* pStmt = (STscStmt*)stmt; + STMT_DLOG_E("start to free stmt"); + stmtCleanSQLInfo(pStmt); taosMemoryFree(stmt); + STMT_DLOG_E("stmt freed"); + return TSDB_CODE_SUCCESS; } @@ -947,15 +975,17 @@ int stmtIsInsert(TAOS_STMT* stmt, int* insert) { } int stmtGetTagFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) { + int32_t code = 0; STscStmt* pStmt = (STscStmt*)stmt; + int32_t preCode = pStmt->errCode; STMT_DLOG_E("start to get tag fields"); if (STMT_TYPE_QUERY == pStmt->sql.type) { - STMT_RET(TSDB_CODE_TSC_STMT_API_ERROR); + STMT_ERRI_JRET(TSDB_CODE_TSC_STMT_API_ERROR); } - STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS)); + STMT_ERRI_JRET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS)); if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 && STMT_TYPE_MULTI_INSERT != pStmt->sql.type) { @@ -967,27 +997,33 @@ int stmtGetTagFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) { pStmt->exec.pRequest = NULL; } - STMT_ERR_RET(stmtCreateRequest(pStmt)); + STMT_ERRI_JRET(stmtCreateRequest(pStmt)); if (pStmt->bInfo.needParse) { - STMT_ERR_RET(stmtParseSql(pStmt)); + STMT_ERRI_JRET(stmtParseSql(pStmt)); } - STMT_ERR_RET(stmtFetchTagFields(stmt, nums, fields)); + STMT_ERRI_JRET(stmtFetchTagFields(stmt, nums, fields)); - return TSDB_CODE_SUCCESS; +_return: + + pStmt->errCode = preCode; + + return code; } int stmtGetColFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) { + int32_t code = 0; STscStmt* pStmt = (STscStmt*)stmt; + int32_t preCode = pStmt->errCode; STMT_DLOG_E("start to get col fields"); if (STMT_TYPE_QUERY == pStmt->sql.type) { - STMT_RET(TSDB_CODE_TSC_STMT_API_ERROR); + STMT_ERRI_JRET(TSDB_CODE_TSC_STMT_API_ERROR); } - STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS)); + STMT_ERRI_JRET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS)); if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 && STMT_TYPE_MULTI_INSERT != pStmt->sql.type) { @@ -999,15 +1035,19 @@ int stmtGetColFields(TAOS_STMT* stmt, int* nums, TAOS_FIELD_E** fields) { pStmt->exec.pRequest = NULL; } - STMT_ERR_RET(stmtCreateRequest(pStmt)); + STMT_ERRI_JRET(stmtCreateRequest(pStmt)); if (pStmt->bInfo.needParse) { - STMT_ERR_RET(stmtParseSql(pStmt)); + STMT_ERRI_JRET(stmtParseSql(pStmt)); } - STMT_ERR_RET(stmtFetchColFields(stmt, nums, fields)); + STMT_ERRI_JRET(stmtFetchColFields(stmt, nums, fields)); - return TSDB_CODE_SUCCESS; +_return: + + pStmt->errCode = preCode; + + return code; } int stmtGetParamNum(TAOS_STMT* stmt, int* nums) { diff --git a/source/client/src/clientTmq.c b/source/client/src/clientTmq.c index 22739108e2078f9a2c3a51ba8f769e86f2417439..b488af9ba18d4910c32f3a080235d102fd11e514 100644 --- a/source/client/src/clientTmq.c +++ b/source/client/src/clientTmq.c @@ -20,27 +20,24 @@ #include "tdatablock.h" #include "tdef.h" #include "tglobal.h" -#include "tmsgtype.h" #include "tqueue.h" #include "tref.h" #include "ttimer.h" -#if 0 -#undef tsem_post -#define tsem_post(x) \ - tscInfo("call sem post at %s %d", __FUNCTION__, __LINE__); \ - sem_post(x) -#endif +#define EMPTY_BLOCK_POLL_IDLE_DURATION 10 +#define DEFAULT_AUTO_COMMIT_INTERVAL 5000 -int32_t tmqAskEp(tmq_t* tmq, bool async); +typedef void (*__tmq_askep_fn_t)(tmq_t* pTmq, int32_t code, SDataBuf* pBuf, void* pParam); -typedef struct { +struct SMqMgmt { int8_t inited; tmr_h timer; int32_t rsetId; -} SMqMgmt; +}; -static SMqMgmt tmqMgmt = {0}; +static TdThreadOnce tmqInit = PTHREAD_ONCE_INIT; // initialize only once +volatile int32_t tmqInitRes = 0; // initialize rsp code +static struct SMqMgmt tmqMgmt = {0}; typedef struct { int8_t tmqRspType; @@ -58,16 +55,14 @@ struct tmq_list_t { }; struct tmq_conf_t { - char clientId[256]; - char groupId[TSDB_CGROUP_LEN]; - int8_t autoCommit; - int8_t resetOffset; - int8_t withTbName; - int8_t snapEnable; - int32_t snapBatchSize; - - bool hbBgEnable; - + char clientId[256]; + char groupId[TSDB_CGROUP_LEN]; + int8_t autoCommit; + int8_t resetOffset; + int8_t withTbName; + int8_t snapEnable; + int32_t snapBatchSize; + bool hbBgEnable; uint16_t port; int32_t autoCommitInterval; char* ip; @@ -78,19 +73,16 @@ struct tmq_conf_t { }; struct tmq_t { - int64_t refId; - // conf - char groupId[TSDB_CGROUP_LEN]; - char clientId[256]; - int8_t withTbName; - int8_t useSnapshot; - int8_t autoCommit; - int32_t autoCommitInterval; - int32_t resetOffsetCfg; - int64_t consumerId; - - bool hbBgEnable; - + int64_t refId; + char groupId[TSDB_CGROUP_LEN]; + char clientId[256]; + int8_t withTbName; + int8_t useSnapshot; + int8_t autoCommit; + int32_t autoCommitInterval; + int32_t resetOffsetCfg; + uint64_t consumerId; + bool hbBgEnable; tmq_commit_cb* commitCb; void* commitCbUserParam; @@ -101,27 +93,28 @@ struct tmq_t { int8_t epStatus; int32_t epSkipCnt; #endif + // poll info int64_t pollCnt; + int64_t totalRows; // timer - tmr_h hbLiveTimer; - tmr_h epTimer; - tmr_h reportTimer; - tmr_h commitTimer; - - // connection - STscObj* pTscObj; - - // container + tmr_h hbLiveTimer; + tmr_h epTimer; + tmr_h reportTimer; + tmr_h commitTimer; + STscObj* pTscObj; // connection SArray* clientTopics; // SArray STaosQueue* mqueue; // queue of rsp STaosQall* qall; STaosQueue* delayedTask; // delayed task queue for heartbeat and auto commit - - // ctl - tsem_t rspSem; + tsem_t rspSem; }; +typedef struct SAskEpInfo { + int32_t code; + tsem_t sem; +} SAskEpInfo; + enum { TMQ_VG_STATUS__IDLE = 0, TMQ_VG_STATUS__WAIT, @@ -141,33 +134,32 @@ enum { }; typedef struct { - // statistics - int64_t pollCnt; - // offset + int64_t pollCnt; + int64_t numOfRows; STqOffsetVal committedOffset; STqOffsetVal currentOffset; - // connection info - int32_t vgId; - int32_t vgStatus; - int32_t vgSkipCnt; - SEpSet epSet; + int32_t vgId; + int32_t vgStatus; + int32_t vgSkipCnt; + int64_t emptyBlockReceiveTs; // once empty block is received, idle for ignoreCnt then start to poll data + SEpSet epSet; } SMqClientVg; typedef struct { - // subscribe info - char topicName[TSDB_TOPIC_FNAME_LEN]; - char db[TSDB_DB_FNAME_LEN]; - - SArray* vgs; // SArray - + char topicName[TSDB_TOPIC_FNAME_LEN]; + char db[TSDB_DB_FNAME_LEN]; + SArray* vgs; // SArray SSchemaWrapper schema; } SMqClientTopic; typedef struct { int8_t tmqRspType; - int32_t epoch; + int32_t epoch; // epoch can be used to guard the vgHandle + int32_t vgId; SMqClientVg* vgHandle; SMqClientTopic* topicHandle; + uint64_t reqId; + SEpSet* pEpset; union { SMqDataRsp dataRsp; SMqMetaRsp metaRsp; @@ -183,11 +175,10 @@ typedef struct { } SMqSubscribeCbParam; typedef struct { - int64_t refId; - int32_t epoch; - int32_t code; - int32_t async; - tsem_t rspSem; + int64_t refId; + int32_t epoch; + void* pParam; + __tmq_askep_fn_t pUserFn; } SMqAskEpCbParam; typedef struct { @@ -196,66 +187,90 @@ typedef struct { SMqClientVg* pVg; SMqClientTopic* pTopic; int32_t vgId; - tsem_t rspSem; + uint64_t requestId; // request id for debug purpose } SMqPollCbParam; typedef struct { int64_t refId; int32_t epoch; - int8_t automatic; - int8_t async; int32_t waitingRspNum; int32_t totalRspNum; - int32_t rspErr; - tmq_commit_cb* userCb; + int32_t code; + tmq_commit_cb* callbackFn; /*SArray* successfulOffsets;*/ /*SArray* failedOffsets;*/ - void* userParam; - tsem_t rspSem; + void* userParam; } SMqCommitCbParamSet; typedef struct { SMqCommitCbParamSet* params; STqOffset* pOffset; - /*char topicName[TSDB_TOPIC_FNAME_LEN];*/ - /*int32_t vgId;*/ + char topicName[TSDB_TOPIC_FNAME_LEN]; + int32_t vgId; + tmq_t* pTmq; } SMqCommitCbParam; +typedef struct SSyncCommitInfo { + tsem_t sem; + int32_t code; +} SSyncCommitInfo; + +static int32_t doAskEp(tmq_t* tmq); +static int32_t makeTopicVgroupKey(char* dst, const char* topicName, int32_t vg); +static int32_t tmqCommitDone(SMqCommitCbParamSet* pParamSet); +static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicName, SMqCommitCbParamSet* pParamSet, + int32_t index, int32_t totalVgroups); +static void commitRspCountDown(SMqCommitCbParamSet* pParamSet, int64_t consumerId, const char* pTopic, int32_t vgId); +static void asyncAskEp(tmq_t* pTmq, __tmq_askep_fn_t askEpFn, void* param); +static void addToQueueCallbackFn(tmq_t* pTmq, int32_t code, SDataBuf* pDataBuf, void* param); + tmq_conf_t* tmq_conf_new() { tmq_conf_t* conf = taosMemoryCalloc(1, sizeof(tmq_conf_t)); + if (conf == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return conf; + } + conf->withTbName = false; conf->autoCommit = true; - conf->autoCommitInterval = 5000; - conf->resetOffset = TMQ_CONF__RESET_OFFSET__EARLIEAST; + conf->autoCommitInterval = DEFAULT_AUTO_COMMIT_INTERVAL; + conf->resetOffset = TMQ_OFFSET__RESET_EARLIEAST; conf->hbBgEnable = true; + return conf; } void tmq_conf_destroy(tmq_conf_t* conf) { if (conf) { - if (conf->ip) taosMemoryFree(conf->ip); - if (conf->user) taosMemoryFree(conf->user); - if (conf->pass) taosMemoryFree(conf->pass); + if (conf->ip) { + taosMemoryFree(conf->ip); + } + if (conf->user) { + taosMemoryFree(conf->user); + } + if (conf->pass) { + taosMemoryFree(conf->pass); + } taosMemoryFree(conf); } } tmq_conf_res_t tmq_conf_set(tmq_conf_t* conf, const char* key, const char* value) { - if (strcmp(key, "group.id") == 0) { + if (strcasecmp(key, "group.id") == 0) { tstrncpy(conf->groupId, value, TSDB_CGROUP_LEN); return TMQ_CONF_OK; } - if (strcmp(key, "client.id") == 0) { + if (strcasecmp(key, "client.id") == 0) { tstrncpy(conf->clientId, value, 256); return TMQ_CONF_OK; } - if (strcmp(key, "enable.auto.commit") == 0) { - if (strcmp(value, "true") == 0) { + if (strcasecmp(key, "enable.auto.commit") == 0) { + if (strcasecmp(value, "true") == 0) { conf->autoCommit = true; return TMQ_CONF_OK; - } else if (strcmp(value, "false") == 0) { + } else if (strcasecmp(value, "false") == 0) { conf->autoCommit = false; return TMQ_CONF_OK; } else { @@ -263,31 +278,31 @@ tmq_conf_res_t tmq_conf_set(tmq_conf_t* conf, const char* key, const char* value } } - if (strcmp(key, "auto.commit.interval.ms") == 0) { - conf->autoCommitInterval = atoi(value); + if (strcasecmp(key, "auto.commit.interval.ms") == 0) { + conf->autoCommitInterval = taosStr2int64(value); return TMQ_CONF_OK; } - if (strcmp(key, "auto.offset.reset") == 0) { - if (strcmp(value, "none") == 0) { - conf->resetOffset = TMQ_CONF__RESET_OFFSET__NONE; + if (strcasecmp(key, "auto.offset.reset") == 0) { + if (strcasecmp(value, "none") == 0) { + conf->resetOffset = TMQ_OFFSET__RESET_NONE; return TMQ_CONF_OK; - } else if (strcmp(value, "earliest") == 0) { - conf->resetOffset = TMQ_CONF__RESET_OFFSET__EARLIEAST; + } else if (strcasecmp(value, "earliest") == 0) { + conf->resetOffset = TMQ_OFFSET__RESET_EARLIEAST; return TMQ_CONF_OK; - } else if (strcmp(value, "latest") == 0) { - conf->resetOffset = TMQ_CONF__RESET_OFFSET__LATEST; + } else if (strcasecmp(value, "latest") == 0) { + conf->resetOffset = TMQ_OFFSET__RESET_LATEST; return TMQ_CONF_OK; } else { return TMQ_CONF_INVALID; } } - if (strcmp(key, "msg.with.table.name") == 0) { - if (strcmp(value, "true") == 0) { + if (strcasecmp(key, "msg.with.table.name") == 0) { + if (strcasecmp(value, "true") == 0) { conf->withTbName = true; return TMQ_CONF_OK; - } else if (strcmp(value, "false") == 0) { + } else if (strcasecmp(value, "false") == 0) { conf->withTbName = false; return TMQ_CONF_OK; } else { @@ -295,11 +310,11 @@ tmq_conf_res_t tmq_conf_set(tmq_conf_t* conf, const char* key, const char* value } } - if (strcmp(key, "experimental.snapshot.enable") == 0) { - if (strcmp(value, "true") == 0) { + if (strcasecmp(key, "experimental.snapshot.enable") == 0) { + if (strcasecmp(value, "true") == 0) { conf->snapEnable = true; return TMQ_CONF_OK; - } else if (strcmp(value, "false") == 0) { + } else if (strcasecmp(value, "false") == 0) { conf->snapEnable = false; return TMQ_CONF_OK; } else { @@ -307,60 +322,57 @@ tmq_conf_res_t tmq_conf_set(tmq_conf_t* conf, const char* key, const char* value } } - if (strcmp(key, "experimental.snapshot.batch.size") == 0) { - conf->snapBatchSize = atoi(value); + if (strcasecmp(key, "experimental.snapshot.batch.size") == 0) { + conf->snapBatchSize = taosStr2int64(value); return TMQ_CONF_OK; } - if (strcmp(key, "enable.heartbeat.background") == 0) { - if (strcmp(value, "true") == 0) { - conf->hbBgEnable = true; - return TMQ_CONF_OK; - } else if (strcmp(value, "false") == 0) { - conf->hbBgEnable = false; - return TMQ_CONF_OK; - } else { - return TMQ_CONF_INVALID; - } - return TMQ_CONF_OK; + if (strcasecmp(key, "enable.heartbeat.background") == 0) { + // if (strcasecmp(value, "true") == 0) { + // conf->hbBgEnable = true; + // return TMQ_CONF_OK; + // } else if (strcasecmp(value, "false") == 0) { + // conf->hbBgEnable = false; + // return TMQ_CONF_OK; + // } else { + tscError("the default value of enable.heartbeat.background is true, can not be seted"); + return TMQ_CONF_INVALID; + // } } - if (strcmp(key, "td.connect.ip") == 0) { - conf->ip = strdup(value); + if (strcasecmp(key, "td.connect.ip") == 0) { + conf->ip = taosStrdup(value); return TMQ_CONF_OK; } - if (strcmp(key, "td.connect.user") == 0) { - conf->user = strdup(value); + + if (strcasecmp(key, "td.connect.user") == 0) { + conf->user = taosStrdup(value); return TMQ_CONF_OK; } - if (strcmp(key, "td.connect.pass") == 0) { - conf->pass = strdup(value); + + if (strcasecmp(key, "td.connect.pass") == 0) { + conf->pass = taosStrdup(value); return TMQ_CONF_OK; } - if (strcmp(key, "td.connect.port") == 0) { - conf->port = atoi(value); + + if (strcasecmp(key, "td.connect.port") == 0) { + conf->port = taosStr2int64(value); return TMQ_CONF_OK; } - if (strcmp(key, "td.connect.db") == 0) { - /*conf->db = strdup(value);*/ + + if (strcasecmp(key, "td.connect.db") == 0) { return TMQ_CONF_OK; } return TMQ_CONF_UNKNOWN; } -tmq_list_t* tmq_list_new() { - // - return (tmq_list_t*)taosArrayInit(0, sizeof(void*)); -} +tmq_list_t* tmq_list_new() { return (tmq_list_t*)taosArrayInit(0, sizeof(void*)); } int32_t tmq_list_append(tmq_list_t* list, const char* src) { SArray* container = &list->container; if (src == NULL || src[0] == 0) return -1; - char* topic = strdup(src); - if (topic[0] != '`') { - strtolower(topic, src); - } + char* topic = taosStrdup(src); if (taosArrayPush(container, &topic) == NULL) return -1; return 0; } @@ -380,98 +392,104 @@ char** tmq_list_to_c_array(const tmq_list_t* list) { return container->pData; } -static int32_t tmqMakeTopicVgKey(char* dst, const char* topicName, int32_t vg) { - return sprintf(dst, "%s:%d", topicName, vg); -} +static SMqClientVg* foundClientVg(SArray* pTopicList, const char* pName, int32_t vgId, int32_t* index, + int32_t* numOfVgroups) { + int32_t numOfTopics = taosArrayGetSize(pTopicList); + *index = -1; + *numOfVgroups = 0; -int32_t tmqCommitDone(SMqCommitCbParamSet* pParamSet) { - tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, pParamSet->refId); - if (tmq == NULL) { - if (!pParamSet->async) { - tsem_destroy(&pParamSet->rspSem); + for (int32_t i = 0; i < numOfTopics; ++i) { + SMqClientTopic* pTopic = taosArrayGet(pTopicList, i); + if (strcmp(pTopic->topicName, pName) != 0) { + continue; } - taosMemoryFree(pParamSet); - terrno = TSDB_CODE_TMQ_CONSUMER_CLOSED; - return -1; - } - // if no more waiting rsp - if (pParamSet->async) { - // call async cb func - if (pParamSet->automatic && tmq->commitCb) { - tmq->commitCb(tmq, pParamSet->rspErr, tmq->commitCbUserParam); - } else if (!pParamSet->automatic && pParamSet->userCb) { - // sem post - pParamSet->userCb(tmq, pParamSet->rspErr, pParamSet->userParam); + *numOfVgroups = taosArrayGetSize(pTopic->vgs); + for (int32_t j = 0; j < (*numOfVgroups); ++j) { + SMqClientVg* pClientVg = taosArrayGet(pTopic->vgs, j); + if (pClientVg->vgId == vgId) { + *index = j; + return pClientVg; + } } - taosMemoryFree(pParamSet); - } else { - tsem_post(&pParamSet->rspSem); } -#if 0 - taosArrayDestroyP(pParamSet->successfulOffsets, taosMemoryFree); - taosArrayDestroyP(pParamSet->failedOffsets, taosMemoryFree); -#endif - return 0; -} - -static void tmqCommitRspCountDown(SMqCommitCbParamSet* pParamSet) { - int32_t waitingRspNum = atomic_sub_fetch_32(&pParamSet->waitingRspNum, 1); - ASSERT(waitingRspNum >= 0); - if (waitingRspNum == 0) { - tmqCommitDone(pParamSet); - } + return NULL; } -int32_t tmqCommitCb(void* param, SDataBuf* pBuf, int32_t code) { +// Two problems do not need to be addressed here +// 1. update to of epset. the response of poll request will automatically handle this problem +// 2. commit failure. This one needs to be resolved. +static int32_t tmqCommitCb(void* param, SDataBuf* pBuf, int32_t code) { SMqCommitCbParam* pParam = (SMqCommitCbParam*)param; SMqCommitCbParamSet* pParamSet = (SMqCommitCbParamSet*)pParam->params; - // push into array -#if 0 - if (code == 0) { - taosArrayPush(pParamSet->failedOffsets, &pParam->pOffset); - } else { - taosArrayPush(pParamSet->successfulOffsets, &pParam->pOffset); - } -#endif + + // if (code != TSDB_CODE_SUCCESS) { // if commit offset failed, let's try again + // taosThreadMutexLock(&pParam->pTmq->lock); + // int32_t numOfVgroups, index; + // SMqClientVg* pVg = foundClientVg(pParam->pTmq->clientTopics, pParam->topicName, pParam->vgId, &index, + // &numOfVgroups); if (pVg == NULL) { + // tscDebug("consumer:0x%" PRIx64 + // " subKey:%s vgId:%d commit failed, code:%s has been transferred to other consumer, no need retry + // ordinal:%d/%d", pParam->pTmq->consumerId, pParam->pOffset->subKey, pParam->vgId, tstrerror(code), + // index + 1, numOfVgroups); + // } else { // let's retry the commit + // int32_t code1 = doSendCommitMsg(pParam->pTmq, pVg, pParam->topicName, pParamSet, index, numOfVgroups); + // if (code1 != TSDB_CODE_SUCCESS) { // retry failed. + // tscError("consumer:0x%" PRIx64 " topic:%s vgId:%d offset:%" PRId64 + // " retry failed, ignore this commit. code:%s ordinal:%d/%d", + // pParam->pTmq->consumerId, pParam->topicName, pVg->vgId, pVg->committedOffset.version, + // tstrerror(terrno), index + 1, numOfVgroups); + // } + // } + // + // taosThreadMutexUnlock(&pParam->pTmq->lock); + // + // taosMemoryFree(pParam->pOffset); + // taosMemoryFree(pBuf->pData); + // taosMemoryFree(pBuf->pEpSet); + // + // commitRspCountDown(pParamSet, pParam->pTmq->consumerId, pParam->topicName, pParam->vgId); + // return 0; + // } + // + // // todo replace the pTmq with refId taosMemoryFree(pParam->pOffset); taosMemoryFree(pBuf->pData); taosMemoryFree(pBuf->pEpSet); - /*tscDebug("receive offset commit cb of %s on vgId:%d, offset is %" PRId64, pParam->pOffset->subKey, pParam->->vgId, - * pOffset->version);*/ - - tmqCommitRspCountDown(pParamSet); - + commitRspCountDown(pParamSet, pParam->pTmq->consumerId, pParam->topicName, pParam->vgId); return 0; } -static int32_t tmqSendCommitReq(tmq_t* tmq, SMqClientVg* pVg, SMqClientTopic* pTopic, SMqCommitCbParamSet* pParamSet) { +static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicName, SMqCommitCbParamSet* pParamSet, + int32_t index, int32_t totalVgroups) { STqOffset* pOffset = taosMemoryCalloc(1, sizeof(STqOffset)); if (pOffset == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return -1; + return TSDB_CODE_OUT_OF_MEMORY; } + pOffset->val = pVg->currentOffset; int32_t groupLen = strlen(tmq->groupId); memcpy(pOffset->subKey, tmq->groupId, groupLen); pOffset->subKey[groupLen] = TMQ_SEPARATOR; - strcpy(pOffset->subKey + groupLen + 1, pTopic->topicName); + strcpy(pOffset->subKey + groupLen + 1, pTopicName); - int32_t len; - int32_t code; + int32_t len = 0; + int32_t code = 0; tEncodeSize(tEncodeSTqOffset, pOffset, len, code); if (code < 0) { - return -1; + return TSDB_CODE_INVALID_PARA; } + void* buf = taosMemoryCalloc(1, sizeof(SMsgHead) + len); if (buf == NULL) { taosMemoryFree(pOffset); - return -1; + return TSDB_CODE_OUT_OF_MEMORY; } + ((SMsgHead*)buf)->vgId = htonl(pVg->vgId); void* abuf = POINTER_SHIFT(buf, sizeof(SMsgHead)); @@ -486,10 +504,15 @@ static int32_t tmqSendCommitReq(tmq_t* tmq, SMqClientVg* pVg, SMqClientTopic* pT if (pParam == NULL) { taosMemoryFree(pOffset); taosMemoryFree(buf); - return -1; + return TSDB_CODE_OUT_OF_MEMORY; } + pParam->params = pParamSet; pParam->pOffset = pOffset; + pParam->vgId = pVg->vgId; + pParam->pTmq = tmq; + + tstrncpy(pParam->topicName, pTopicName, tListLen(pParam->topicName)); // build send info SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); @@ -497,19 +520,10 @@ static int32_t tmqSendCommitReq(tmq_t* tmq, SMqClientVg* pVg, SMqClientTopic* pT taosMemoryFree(pOffset); taosMemoryFree(buf); taosMemoryFree(pParam); - return -1; + return TSDB_CODE_OUT_OF_MEMORY; } - pMsgSendInfo->msgInfo = (SDataBuf){ - .pData = buf, - .len = sizeof(SMsgHead) + len, - .handle = NULL, - }; - tscDebug("consumer:%" PRId64 ", commit offset of %s on vgId:%d, offset is %" PRId64, tmq->consumerId, pOffset->subKey, - pVg->vgId, pOffset->val.version); - - // TODO: put into cb - pVg->committedOffset = pVg->currentOffset; + pMsgSendInfo->msgInfo = (SDataBuf) { .pData = buf, .len = sizeof(SMsgHead) + len, .handle = NULL }; pMsgSendInfo->requestId = generateRequestId(); pMsgSendInfo->requestObjRefId = 0; @@ -517,198 +531,197 @@ static int32_t tmqSendCommitReq(tmq_t* tmq, SMqClientVg* pVg, SMqClientTopic* pT pMsgSendInfo->paramFreeFp = taosMemoryFree; pMsgSendInfo->fp = tmqCommitCb; pMsgSendInfo->msgType = TDMT_VND_TMQ_COMMIT_OFFSET; - // send msg atomic_add_fetch_32(&pParamSet->waitingRspNum, 1); atomic_add_fetch_32(&pParamSet->totalRspNum, 1); + SEp* pEp = GET_ACTIVE_EP(&pVg->epSet); + char offsetBuf[80] = {0}; + tFormatOffset(offsetBuf, tListLen(offsetBuf), &pOffset->val); + + char commitBuf[80] = {0}; + tFormatOffset(commitBuf, tListLen(commitBuf), &pVg->committedOffset); + tscDebug("consumer:0x%" PRIx64 " topic:%s on vgId:%d send offset:%s prev:%s, ep:%s:%d, ordinal:%d/%d, req:0x%" PRIx64, + tmq->consumerId, pOffset->subKey, pVg->vgId, offsetBuf, commitBuf, pEp->fqdn, pEp->port, index + 1, + totalVgroups, pMsgSendInfo->requestId); + int64_t transporterId = 0; asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &pVg->epSet, &transporterId, pMsgSendInfo); - return 0; + + return TSDB_CODE_SUCCESS; } -int32_t tmqCommitMsgImpl(tmq_t* tmq, const TAOS_RES* msg, int8_t async, tmq_commit_cb* userCb, void* userParam) { - char* topic; - int32_t vgId; - ASSERT(msg != NULL); - if (TD_RES_TMQ(msg)) { - SMqRspObj* pRspObj = (SMqRspObj*)msg; - topic = pRspObj->topic; +static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* pCommitFp, void* userParam) { + char* pTopicName = NULL; + int32_t vgId = 0; + int32_t code = 0; + + if (pRes == NULL || tmq == NULL) { + pCommitFp(tmq, TSDB_CODE_INVALID_PARA, userParam); + return; + } + + if (TD_RES_TMQ(pRes)) { + SMqRspObj* pRspObj = (SMqRspObj*)pRes; + pTopicName = pRspObj->topic; vgId = pRspObj->vgId; - } else if (TD_RES_TMQ_META(msg)) { - SMqMetaRspObj* pMetaRspObj = (SMqMetaRspObj*)msg; - topic = pMetaRspObj->topic; + } else if (TD_RES_TMQ_META(pRes)) { + SMqMetaRspObj* pMetaRspObj = (SMqMetaRspObj*)pRes; + pTopicName = pMetaRspObj->topic; vgId = pMetaRspObj->vgId; - } else if (TD_RES_TMQ_METADATA(msg)) { - SMqTaosxRspObj* pRspObj = (SMqTaosxRspObj*)msg; - topic = pRspObj->topic; + } else if (TD_RES_TMQ_METADATA(pRes)) { + SMqTaosxRspObj* pRspObj = (SMqTaosxRspObj*)pRes; + pTopicName = pRspObj->topic; vgId = pRspObj->vgId; } else { - return TSDB_CODE_TMQ_INVALID_MSG; + pCommitFp(tmq, TSDB_CODE_TMQ_INVALID_MSG, userParam); + return; } SMqCommitCbParamSet* pParamSet = taosMemoryCalloc(1, sizeof(SMqCommitCbParamSet)); if (pParamSet == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return -1; + pCommitFp(tmq, TSDB_CODE_OUT_OF_MEMORY, userParam); + return; } + pParamSet->refId = tmq->refId; pParamSet->epoch = tmq->epoch; - pParamSet->automatic = 0; - pParamSet->async = async; - pParamSet->userCb = userCb; + pParamSet->callbackFn = pCommitFp; pParamSet->userParam = userParam; - tsem_init(&pParamSet->rspSem, 0, 0); - int32_t code = -1; + int32_t numOfTopics = taosArrayGetSize(tmq->clientTopics); - for (int32_t i = 0; i < taosArrayGetSize(tmq->clientTopics); i++) { - SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i); - if (strcmp(pTopic->topicName, topic) != 0) continue; - for (int32_t j = 0; j < taosArrayGetSize(pTopic->vgs); j++) { - SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j); - if (pVg->vgId != vgId) continue; + tscDebug("consumer:0x%" PRIx64 " do manual commit offset for %s, vgId:%d", tmq->consumerId, pTopicName, vgId); - if (pVg->currentOffset.type > 0 && !tOffsetEqual(&pVg->currentOffset, &pVg->committedOffset)) { - if (tmqSendCommitReq(tmq, pVg, pTopic, pParamSet) < 0) { - tsem_destroy(&pParamSet->rspSem); - taosMemoryFree(pParamSet); - goto FAIL; - } - goto HANDLE_RSP; - } + int32_t i = 0; + for (; i < numOfTopics; i++) { + SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i); + if (strcmp(pTopic->topicName, pTopicName) == 0) { + break; } } -HANDLE_RSP: - if (pParamSet->totalRspNum == 0) { - tsem_destroy(&pParamSet->rspSem); + if (i == numOfTopics) { + tscWarn("consumer:0x%" PRIx64 " failed to find the specified topic:%s, total topics:%d", tmq->consumerId, + pTopicName, numOfTopics); taosMemoryFree(pParamSet); - return 0; + pCommitFp(tmq, TSDB_CODE_SUCCESS, userParam); + return; + } + + SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i); + + int32_t j = 0; + int32_t numOfVgroups = taosArrayGetSize(pTopic->vgs); + for (j = 0; j < numOfVgroups; j++) { + SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j); + if (pVg->vgId == vgId) { + break; + } } - if (!async) { - tsem_wait(&pParamSet->rspSem); - code = pParamSet->rspErr; - tsem_destroy(&pParamSet->rspSem); + if (j == numOfVgroups) { + tscWarn("consumer:0x%" PRIx64 " failed to find the specified vgId:%d, total Vgs:%d, topic:%s", tmq->consumerId, + vgId, numOfVgroups, pTopicName); taosMemoryFree(pParamSet); - return code; - } else { - code = 0; + pCommitFp(tmq, TSDB_CODE_SUCCESS, userParam); + return; } -FAIL: - if (code != 0 && async) { - userCb(tmq, code, userParam); + SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j); + if (pVg->currentOffset.type > 0 && !tOffsetEqual(&pVg->currentOffset, &pVg->committedOffset)) { + code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups); + + // failed to commit, callback user function directly. + if (code != TSDB_CODE_SUCCESS) { + taosMemoryFree(pParamSet); + pCommitFp(tmq, code, userParam); + } + } else { // do not perform commit, callback user function directly. + taosMemoryFree(pParamSet); + pCommitFp(tmq, code, userParam); } - return 0; } -static int32_t tmqCommitConsumerImpl(tmq_t* tmq, int8_t automatic, int8_t async, tmq_commit_cb* userCb, - void* userParam) { - int32_t code = -1; - +static void asyncCommitAllOffsets(tmq_t* tmq, tmq_commit_cb* pCommitFp, void* userParam) { SMqCommitCbParamSet* pParamSet = taosMemoryCalloc(1, sizeof(SMqCommitCbParamSet)); if (pParamSet == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - if (async) { - if (automatic) { - tmq->commitCb(tmq, code, tmq->commitCbUserParam); - } else { - userCb(tmq, code, userParam); - } - } - return -1; + pCommitFp(tmq, TSDB_CODE_OUT_OF_MEMORY, userParam); + return; } pParamSet->refId = tmq->refId; pParamSet->epoch = tmq->epoch; - - pParamSet->automatic = automatic; - pParamSet->async = async; - pParamSet->userCb = userCb; + pParamSet->callbackFn = pCommitFp; pParamSet->userParam = userParam; - tsem_init(&pParamSet->rspSem, 0, 0); // init as 1 to prevent concurrency issue pParamSet->waitingRspNum = 1; - for (int32_t i = 0; i < taosArrayGetSize(tmq->clientTopics); i++) { - SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i); + int32_t numOfTopics = taosArrayGetSize(tmq->clientTopics); + tscDebug("consumer:0x%" PRIx64 " start to commit offset for %d topics", tmq->consumerId, numOfTopics); - tscDebug("consumer:%" PRId64 ", begin commit for topic %s, vgNum %d", tmq->consumerId, pTopic->topicName, - (int32_t)taosArrayGetSize(pTopic->vgs)); + for (int32_t i = 0; i < numOfTopics; i++) { + SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i); + int32_t numOfVgroups = taosArrayGetSize(pTopic->vgs); - for (int32_t j = 0; j < taosArrayGetSize(pTopic->vgs); j++) { + tscDebug("consumer:0x%" PRIx64 " commit offset for topics:%s, numOfVgs:%d", tmq->consumerId, pTopic->topicName, + numOfVgroups); + for (int32_t j = 0; j < numOfVgroups; j++) { SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j); - tscDebug("consumer:%" PRId64 ", begin commit for topic %s, vgId:%d", tmq->consumerId, pTopic->topicName, - pVg->vgId); - if (pVg->currentOffset.type > 0 && !tOffsetEqual(&pVg->currentOffset, &pVg->committedOffset)) { - tscDebug("consumer: %" PRId64 ", vg:%d, current %" PRId64 ", committed %" PRId64 "", tmq->consumerId, pVg->vgId, - pVg->currentOffset.version, pVg->committedOffset.version); - if (tmqSendCommitReq(tmq, pVg, pTopic, pParamSet) < 0) { + int32_t code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups); + if (code != TSDB_CODE_SUCCESS) { + tscError("consumer:0x%" PRIx64 " topic:%s vgId:%d offset:%" PRId64 " failed, code:%s ordinal:%d/%d", + tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->committedOffset.version, tstrerror(terrno), + j + 1, numOfVgroups); continue; } + + // update the offset value. + pVg->committedOffset = pVg->currentOffset; + } else { + tscDebug("consumer:0x%" PRIx64 " topic:%s vgId:%d, no commit, current:%" PRId64 ", ordinal:%d/%d", + tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->currentOffset.version, j + 1, numOfVgroups); } } } + tscDebug("consumer:0x%" PRIx64 " total commit:%d for %d topics", tmq->consumerId, pParamSet->waitingRspNum - 1, + numOfTopics); + // no request is sent if (pParamSet->totalRspNum == 0) { - tsem_destroy(&pParamSet->rspSem); taosMemoryFree(pParamSet); - return 0; + pCommitFp(tmq, TSDB_CODE_SUCCESS, userParam); + return; } // count down since waiting rsp num init as 1 - tmqCommitRspCountDown(pParamSet); - - if (!async) { - tsem_wait(&pParamSet->rspSem); - code = pParamSet->rspErr; - tsem_destroy(&pParamSet->rspSem); - taosMemoryFree(pParamSet); -#if 0 - taosArrayDestroyP(pParamSet->successfulOffsets, taosMemoryFree); - taosArrayDestroyP(pParamSet->failedOffsets, taosMemoryFree); -#endif - } - - return code; -} - -int32_t tmqCommitInner(tmq_t* tmq, const TAOS_RES* msg, int8_t automatic, int8_t async, tmq_commit_cb* userCb, - void* userParam) { - if (msg) { - return tmqCommitMsgImpl(tmq, msg, async, userCb, userParam); - } else { - return tmqCommitConsumerImpl(tmq, automatic, async, userCb, userParam); - } + commitRspCountDown(pParamSet, tmq->consumerId, "", 0); } -void tmqAssignAskEpTask(void* param, void* tmrId) { - int64_t refId = *(int64_t*)param; - tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId); +static void generateTimedTask(int64_t refId, int32_t type) { + tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId); if (tmq != NULL) { int8_t* pTaskType = taosAllocateQitem(sizeof(int8_t), DEF_QITEM, 0); - *pTaskType = TMQ_DELAYED_TASK__ASK_EP; + *pTaskType = type; taosWriteQitem(tmq->delayedTask, pTaskType); tsem_post(&tmq->rspSem); } + taosReleaseRef(tmqMgmt.rsetId, refId); +} + +void tmqAssignAskEpTask(void* param, void* tmrId) { + int64_t refId = *(int64_t*)param; + generateTimedTask(refId, TMQ_DELAYED_TASK__ASK_EP); taosMemoryFree(param); } void tmqAssignDelayedCommitTask(void* param, void* tmrId) { int64_t refId = *(int64_t*)param; - tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId); - if (tmq != NULL) { - int8_t* pTaskType = taosAllocateQitem(sizeof(int8_t), DEF_QITEM, 0); - *pTaskType = TMQ_DELAYED_TASK__COMMIT; - taosWriteQitem(tmq->delayedTask, pTaskType); - tsem_post(&tmq->rspSem); - } + generateTimedTask(refId, TMQ_DELAYED_TASK__COMMIT); taosMemoryFree(param); } @@ -721,6 +734,8 @@ void tmqAssignDelayedReportTask(void* param, void* tmrId) { taosWriteQitem(tmq->delayedTask, pTaskType); tsem_post(&tmq->rspSem); } + + taosReleaseRef(tmqMgmt.rsetId, refId); taosMemoryFree(param); } @@ -734,7 +749,8 @@ int32_t tmqHbCb(void* param, SDataBuf* pMsg, int32_t code) { void tmqSendHbReq(void* param, void* tmrId) { int64_t refId = *(int64_t*)param; - tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId); + + tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId); if (tmq == NULL) { taosMemoryFree(param); return; @@ -747,17 +763,19 @@ void tmqSendHbReq(void* param, void* tmrId) { int32_t tlen = tSerializeSMqHbReq(NULL, 0, &req); if (tlen < 0) { tscError("tSerializeSMqHbReq failed"); - return; + goto OVER; } + void* pReq = taosMemoryCalloc(1, tlen); if (tlen < 0) { tscError("failed to malloc MqHbReq msg, size:%d", tlen); - return; + goto OVER; } + if (tSerializeSMqHbReq(pReq, tlen, &req) < 0) { tscError("tSerializeSMqHbReq %d failed", tlen); taosMemoryFree(pReq); - return; + goto OVER; } SMsgSendInfo* sendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); @@ -765,11 +783,8 @@ void tmqSendHbReq(void* param, void* tmrId) { taosMemoryFree(pReq); goto OVER; } - sendInfo->msgInfo = (SDataBuf){ - .pData = pReq, - .len = tlen, - .handle = NULL, - }; + + sendInfo->msgInfo = (SDataBuf){ .pData = pReq, .len = tlen, .handle = NULL }; sendInfo->requestId = generateRequestId(); sendInfo->requestObjRefId = 0; @@ -784,41 +799,59 @@ void tmqSendHbReq(void* param, void* tmrId) { OVER: taosTmrReset(tmqSendHbReq, 1000, param, tmqMgmt.timer, &tmq->hbLiveTimer); + taosReleaseRef(tmqMgmt.rsetId, refId); +} + +static void defaultCommitCbFn(tmq_t* pTmq, int32_t code, void* param) { + if (code != 0) { + tscDebug("consumer:0x%" PRIx64 ", failed to commit offset, code:%s", pTmq->consumerId, tstrerror(code)); + } } -int32_t tmqHandleAllDelayedTask(tmq_t* tmq) { +int32_t tmqHandleAllDelayedTask(tmq_t* pTmq) { STaosQall* qall = taosAllocateQall(); - taosReadAllQitems(tmq->delayedTask, qall); - while (1) { - int8_t* pTaskType = NULL; - taosGetQitem(qall, (void**)&pTaskType); - if (pTaskType == NULL) break; + taosReadAllQitems(pTmq->delayedTask, qall); + if (qall->numOfItems == 0) { + taosFreeQall(qall); + return TSDB_CODE_SUCCESS; + } + + tscDebug("consumer:0x%" PRIx64 " handle delayed %d tasks before poll data", pTmq->consumerId, qall->numOfItems); + int8_t* pTaskType = NULL; + taosGetQitem(qall, (void**)&pTaskType); + + while (pTaskType != NULL) { if (*pTaskType == TMQ_DELAYED_TASK__ASK_EP) { - tmqAskEp(tmq, true); + asyncAskEp(pTmq, addToQueueCallbackFn, NULL); int64_t* pRefId = taosMemoryMalloc(sizeof(int64_t)); - *pRefId = tmq->refId; + *pRefId = pTmq->refId; - taosTmrReset(tmqAssignAskEpTask, 1000, pRefId, tmqMgmt.timer, &tmq->epTimer); + tscDebug("consumer:0x%" PRIx64 " retrieve ep from mnode in 1s", pTmq->consumerId); + taosTmrReset(tmqAssignAskEpTask, 1000, pRefId, tmqMgmt.timer, &pTmq->epTimer); } else if (*pTaskType == TMQ_DELAYED_TASK__COMMIT) { - tmqCommitInner(tmq, NULL, 1, 1, tmq->commitCb, tmq->commitCbUserParam); + tmq_commit_cb* pCallbackFn = pTmq->commitCb ? pTmq->commitCb : defaultCommitCbFn; + asyncCommitAllOffsets(pTmq, pCallbackFn, pTmq->commitCbUserParam); int64_t* pRefId = taosMemoryMalloc(sizeof(int64_t)); - *pRefId = tmq->refId; + *pRefId = pTmq->refId; - taosTmrReset(tmqAssignDelayedCommitTask, tmq->autoCommitInterval, pRefId, tmqMgmt.timer, &tmq->commitTimer); + tscDebug("consumer:0x%" PRIx64 " next commit to vnode(s) in %.2fs", pTmq->consumerId, + pTmq->autoCommitInterval / 1000.0); + taosTmrReset(tmqAssignDelayedCommitTask, pTmq->autoCommitInterval, pRefId, tmqMgmt.timer, &pTmq->commitTimer); } else if (*pTaskType == TMQ_DELAYED_TASK__REPORT) { - } else { - ASSERT(0); } + taosFreeQitem(pTaskType); + taosGetQitem(qall, (void**)&pTaskType); } + taosFreeQall(qall); return 0; } -static void tmqFreeRspWrapper(SMqRspWrapper* rspWrapper) { +static void* tmqFreeRspWrapper(SMqRspWrapper* rspWrapper) { if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__END_RSP) { // do nothing } else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__EP_RSP) { @@ -826,23 +859,31 @@ static void tmqFreeRspWrapper(SMqRspWrapper* rspWrapper) { tDeleteSMqAskEpRsp(&pEpRspWrapper->msg); } else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_RSP) { SMqPollRspWrapper* pRsp = (SMqPollRspWrapper*)rspWrapper; + taosMemoryFreeClear(pRsp->pEpset); + taosArrayDestroyP(pRsp->dataRsp.blockData, taosMemoryFree); taosArrayDestroy(pRsp->dataRsp.blockDataLen); taosArrayDestroyP(pRsp->dataRsp.blockTbName, taosMemoryFree); - taosArrayDestroyP(pRsp->dataRsp.blockSchema, (FDelete)tDeleteSSchemaWrapper); + taosArrayDestroyP(pRsp->dataRsp.blockSchema, (FDelete)tDeleteSchemaWrapper); } else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_META_RSP) { SMqPollRspWrapper* pRsp = (SMqPollRspWrapper*)rspWrapper; + taosMemoryFreeClear(pRsp->pEpset); + taosMemoryFree(pRsp->metaRsp.metaRsp); } else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__TAOSX_RSP) { SMqPollRspWrapper* pRsp = (SMqPollRspWrapper*)rspWrapper; + taosMemoryFreeClear(pRsp->pEpset); + taosArrayDestroyP(pRsp->taosxRsp.blockData, taosMemoryFree); taosArrayDestroy(pRsp->taosxRsp.blockDataLen); taosArrayDestroyP(pRsp->taosxRsp.blockTbName, taosMemoryFree); - taosArrayDestroyP(pRsp->taosxRsp.blockSchema, (FDelete)tDeleteSSchemaWrapper); + taosArrayDestroyP(pRsp->taosxRsp.blockSchema, (FDelete)tDeleteSchemaWrapper); // taosx taosArrayDestroy(pRsp->taosxRsp.createTableLen); taosArrayDestroyP(pRsp->taosxRsp.createTableReq, taosMemoryFree); } + + return NULL; } void tmqClearUnhandleMsg(tmq_t* tmq) { @@ -908,75 +949,83 @@ int32_t tmq_unsubscribe(tmq_t* tmq) { return rsp; } +static void freeClientVgImpl(void* param) { + SMqClientTopic* pTopic = param; + taosMemoryFreeClear(pTopic->schema.pSchema); + taosArrayDestroy(pTopic->vgs); +} + void tmqFreeImpl(void* handle) { - tmq_t* tmq = (tmq_t*)handle; + tmq_t* tmq = (tmq_t*)handle; + int64_t id = tmq->consumerId; // TODO stop timer if (tmq->mqueue) { tmqClearUnhandleMsg(tmq); taosCloseQueue(tmq->mqueue); } - if (tmq->delayedTask) taosCloseQueue(tmq->delayedTask); - taosFreeQall(tmq->qall); + if (tmq->delayedTask) { + taosCloseQueue(tmq->delayedTask); + } + + taosFreeQall(tmq->qall); tsem_destroy(&tmq->rspSem); - int32_t sz = taosArrayGetSize(tmq->clientTopics); - for (int32_t i = 0; i < sz; i++) { - SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i); - taosMemoryFreeClear(pTopic->schema.pSchema); - taosArrayDestroy(pTopic->vgs); - } - taosArrayDestroy(tmq->clientTopics); + taosArrayDestroyEx(tmq->clientTopics, freeClientVgImpl); taos_close_internal(tmq->pTscObj); taosMemoryFree(tmq); + + tscDebug("consumer:0x%" PRIx64 " closed", id); +} + +static void tmqMgmtInit(void) { + tmqInitRes = 0; + tmqMgmt.timer = taosTmrInit(1000, 100, 360000, "TMQ"); + + if (tmqMgmt.timer == NULL) { + tmqInitRes = TSDB_CODE_OUT_OF_MEMORY; + } + + tmqMgmt.rsetId = taosOpenRef(10000, tmqFreeImpl); + if (tmqMgmt.rsetId < 0) { + tmqInitRes = terrno; + } } tmq_t* tmq_consumer_new(tmq_conf_t* conf, char* errstr, int32_t errstrLen) { - // init timer - int8_t inited = atomic_val_compare_exchange_8(&tmqMgmt.inited, 0, 1); - if (inited == 0) { - tmqMgmt.timer = taosTmrInit(1000, 100, 360000, "TMQ"); - if (tmqMgmt.timer == NULL) { - atomic_store_8(&tmqMgmt.inited, 0); - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - tmqMgmt.rsetId = taosOpenRef(10000, tmqFreeImpl); + taosThreadOnce(&tmqInit, tmqMgmtInit); + if (tmqInitRes != 0) { + terrno = tmqInitRes; + return NULL; } tmq_t* pTmq = taosMemoryCalloc(1, sizeof(tmq_t)); if (pTmq == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; - tscError("setting up new consumer failed since %s, consumer group %s", terrstr(), conf->groupId); + tscError("failed to create consumer, groupId:%s, code:%s", conf->groupId, terrstr()); return NULL; } const char* user = conf->user == NULL ? TSDB_DEFAULT_USER : conf->user; const char* pass = conf->pass == NULL ? TSDB_DEFAULT_PASS : conf->pass; - ASSERT(user); - ASSERT(pass); - ASSERT(conf->groupId[0]); - pTmq->clientTopics = taosArrayInit(0, sizeof(SMqClientTopic)); pTmq->mqueue = taosOpenQueue(); - pTmq->qall = taosAllocateQall(); pTmq->delayedTask = taosOpenQueue(); + pTmq->qall = taosAllocateQall(); - if (pTmq->clientTopics == NULL || pTmq->mqueue == NULL || pTmq->qall == NULL || pTmq->delayedTask == NULL) { + if (pTmq->clientTopics == NULL || pTmq->mqueue == NULL || pTmq->qall == NULL || pTmq->delayedTask == NULL || + conf->groupId[0] == 0) { terrno = TSDB_CODE_OUT_OF_MEMORY; - tscError("consumer %" PRId64 " setup failed since %s, consumer group %s", pTmq->consumerId, terrstr(), - pTmq->groupId); - goto FAIL; + tscError("consumer:0x%" PRIx64 " setup failed since %s, groupId:%s", pTmq->consumerId, terrstr(), pTmq->groupId); + goto _failed; } // init status pTmq->status = TMQ_CONSUMER_STATUS__INIT; pTmq->pollCnt = 0; pTmq->epoch = 0; - /*pTmq->epStatus = 0;*/ - /*pTmq->epSkipCnt = 0;*/ // set conf strcpy(pTmq->clientId, conf->clientId); @@ -996,24 +1045,22 @@ tmq_t* tmq_consumer_new(tmq_conf_t* conf, char* errstr, int32_t errstrLen) { // init semaphore if (tsem_init(&pTmq->rspSem, 0, 0) != 0) { - tscError("consumer %" PRId64 " setup failed since %s, consumer group %s", pTmq->consumerId, terrstr(), + tscError("consumer:0x %" PRIx64 " setup failed since %s, consumer group %s", pTmq->consumerId, terrstr(), pTmq->groupId); - goto FAIL; + goto _failed; } // init connection pTmq->pTscObj = taos_connect_internal(conf->ip, user, pass, NULL, NULL, conf->port, CONN_TYPE__TMQ); if (pTmq->pTscObj == NULL) { - tscError("consumer %" PRId64 " setup failed since %s, consumer group %s", pTmq->consumerId, terrstr(), - pTmq->groupId); + tscError("consumer:0x%" PRIx64 " setup failed since %s, groupId:%s", pTmq->consumerId, terrstr(), pTmq->groupId); tsem_destroy(&pTmq->rspSem); - goto FAIL; + goto _failed; } pTmq->refId = taosAddRef(tmqMgmt.rsetId, pTmq); if (pTmq->refId < 0) { - tmqFreeImpl(pTmq); - return NULL; + goto _failed; } if (pTmq->hbBgEnable) { @@ -1022,63 +1069,74 @@ tmq_t* tmq_consumer_new(tmq_conf_t* conf, char* errstr, int32_t errstrLen) { pTmq->hbLiveTimer = taosTmrStart(tmqSendHbReq, 1000, pRefId, tmqMgmt.timer); } - tscInfo("consumer %" PRId64 " is setup, consumer group %s", pTmq->consumerId, pTmq->groupId); + char buf[80] = {0}; + STqOffsetVal offset = {.type = pTmq->resetOffsetCfg}; + tFormatOffset(buf, tListLen(buf), &offset); + tscInfo("consumer:0x%" PRIx64 " is setup, refId:%" PRId64 + ", groupId:%s, snapshot:%d, autoCommit:%d, commitInterval:%dms, offset:%s, backgroudHB:%d", + pTmq->consumerId, pTmq->refId, pTmq->groupId, pTmq->useSnapshot, pTmq->autoCommit, pTmq->autoCommitInterval, + buf, pTmq->hbBgEnable); return pTmq; -FAIL: - if (pTmq->clientTopics) taosArrayDestroy(pTmq->clientTopics); - if (pTmq->mqueue) taosCloseQueue(pTmq->mqueue); - if (pTmq->delayedTask) taosCloseQueue(pTmq->delayedTask); - if (pTmq->qall) taosFreeQall(pTmq->qall); - taosMemoryFree(pTmq); +_failed: + tmqFreeImpl(pTmq); return NULL; } int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) { + const int32_t MAX_RETRY_COUNT = 120 * 2; // let's wait for 2 mins at most const SArray* container = &topic_list->container; int32_t sz = taosArrayGetSize(container); void* buf = NULL; SMsgSendInfo* sendInfo = NULL; SCMSubscribeReq req = {0}; - int32_t code = -1; + int32_t code = 0; - tscDebug("tmq subscribe, consumer: %" PRId64 ", topic num %d", tmq->consumerId, sz); + tscDebug("consumer:0x%" PRIx64 " cgroup:%s, subscribe %d topics", tmq->consumerId, tmq->groupId, sz); req.consumerId = tmq->consumerId; tstrncpy(req.clientId, tmq->clientId, 256); tstrncpy(req.cgroup, tmq->groupId, TSDB_CGROUP_LEN); req.topicNames = taosArrayInit(sz, sizeof(void*)); - if (req.topicNames == NULL) goto FAIL; - tscDebug("tmq subscribe, consumer: %" PRId64 ", topic num %d", tmq->consumerId, sz); + if (req.topicNames == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto FAIL; + } for (int32_t i = 0; i < sz; i++) { char* topic = taosArrayGetP(container, i); SName name = {0}; tNameSetDbName(&name, tmq->pTscObj->acctId, topic, strlen(topic)); - char* topicFName = taosMemoryCalloc(1, TSDB_TOPIC_FNAME_LEN); if (topicFName == NULL) { goto FAIL; } - tNameExtractFullName(&name, topicFName); - tscDebug("subscribe topic: %s", topicFName); + tNameExtractFullName(&name, topicFName); + tscDebug("consumer:0x%" PRIx64 " subscribe topic:%s", tmq->consumerId, topicFName); taosArrayPush(req.topicNames, &topicFName); } int32_t tlen = tSerializeSCMSubscribeReq(NULL, &req); + buf = taosMemoryMalloc(tlen); - if (buf == NULL) goto FAIL; + if (buf == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto FAIL; + } void* abuf = buf; tSerializeSCMSubscribeReq(&abuf, &req); sendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); - if (sendInfo == NULL) goto FAIL; + if (sendInfo == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto FAIL; + } SMqSubscribeCbParam param = { .rspErr = 0, @@ -1086,7 +1144,10 @@ int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) { .epoch = tmq->epoch, }; - if (tsem_init(¶m.rspSem, 0, 0) != 0) goto FAIL; + if (tsem_init(¶m.rspSem, 0, 0) != 0) { + code = TSDB_CODE_TSC_INTERNAL_ERROR; + goto FAIL; + } sendInfo->msgInfo = (SDataBuf){ .pData = buf, @@ -1112,15 +1173,20 @@ int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) { tsem_wait(¶m.rspSem); tsem_destroy(¶m.rspSem); - code = param.rspErr; - if (code != 0) goto FAIL; - + if (param.rspErr != 0) { + code = param.rspErr; + goto FAIL; + } + int32_t retryCnt = 0; - while (TSDB_CODE_MND_CONSUMER_NOT_READY == tmqAskEp(tmq, false)) { - if (retryCnt++ > 10) { + while (TSDB_CODE_MND_CONSUMER_NOT_READY == doAskEp(tmq)) { + if (retryCnt++ > MAX_RETRY_COUNT) { + tscError("consumer:0x%" PRIx64 ", mnd not ready for subscribe, retry:%d in 500ms", tmq->consumerId, retryCnt); + code = TSDB_CODE_TSC_INTERNAL_ERROR; goto FAIL; } - tscDebug("consumer not ready, retry"); + + tscDebug("consumer:0x%" PRIx64 ", mnd not ready for subscribe, retry:%d in 500ms", tmq->consumerId, retryCnt); taosMsleep(500); } @@ -1138,7 +1204,6 @@ int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) { tmq->commitTimer = taosTmrStart(tmqAssignDelayedCommitTask, tmq->autoCommitInterval, pRefId2, tmqMgmt.timer); } - code = 0; FAIL: taosArrayDestroyP(req.topicNames, taosMemoryFree); taosMemoryFree(buf); @@ -1148,19 +1213,19 @@ FAIL: } void tmq_conf_set_auto_commit_cb(tmq_conf_t* conf, tmq_commit_cb* cb, void* param) { - // conf->commitCb = cb; conf->commitCbUserParam = param; } int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) { SMqPollCbParam* pParam = (SMqPollCbParam*)param; + + int64_t refId = pParam->refId; SMqClientVg* pVg = pParam->pVg; SMqClientTopic* pTopic = pParam->pTopic; - tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, pParam->refId); + tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId); if (tmq == NULL) { - tsem_destroy(&pParam->rspSem); taosMemoryFree(pParam); taosMemoryFree(pMsg->pData); taosMemoryFree(pMsg->pEpSet); @@ -1168,30 +1233,39 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) { return -1; } - int32_t epoch = pParam->epoch; - int32_t vgId = pParam->vgId; + int32_t epoch = pParam->epoch; + int32_t vgId = pParam->vgId; + uint64_t requestId = pParam->requestId; + taosMemoryFree(pParam); + if (code != 0) { - tscWarn("msg discard from vgId:%d, epoch %d, since %s", vgId, epoch, terrstr()); if (pMsg->pData) taosMemoryFree(pMsg->pData); if (pMsg->pEpSet) taosMemoryFree(pMsg->pEpSet); + // in case of consumer mismatch, wait for 500ms and retry if (code == TSDB_CODE_TMQ_CONSUMER_MISMATCH) { + taosMsleep(500); atomic_store_8(&tmq->status, TMQ_CONSUMER_STATUS__RECOVER); - goto CREATE_MSG_FAIL; - } - if (code == TSDB_CODE_TQ_NO_COMMITTED_OFFSET) { + tscDebug("consumer:0x%" PRIx64 " wait for the re-balance, wait for 500ms and set status to be RECOVER", + tmq->consumerId); + } else if (code == TSDB_CODE_TQ_NO_COMMITTED_OFFSET) { SMqPollRspWrapper* pRspWrapper = taosAllocateQitem(sizeof(SMqPollRspWrapper), DEF_QITEM, 0); if (pRspWrapper == NULL) { - tscWarn("msg discard from vgId:%d, epoch %d since out of memory", vgId, epoch); + tscWarn("consumer:0x%" PRIx64 " msg from vgId:%d discarded, epoch %d since out of memory, reqId:0x%" PRIx64, + tmq->consumerId, vgId, epoch, requestId); goto CREATE_MSG_FAIL; } + pRspWrapper->tmqRspType = TMQ_MSG_TYPE__END_RSP; - /*pRspWrapper->vgHandle = pVg;*/ - /*pRspWrapper->topicHandle = pTopic;*/ taosWriteQitem(tmq->mqueue, pRspWrapper); - tsem_post(&tmq->rspSem); + } else if (code == TSDB_CODE_WAL_LOG_NOT_EXIST) { // poll data while insert + taosMsleep(500); + } else{ + tscError("consumer:0x%" PRIx64 " msg from vgId:%d discarded, epoch %d, since %s, reqId:0x%" PRIx64, tmq->consumerId, + vgId, epoch, tstrerror(code), requestId); } + goto CREATE_MSG_FAIL; } @@ -1199,16 +1273,21 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) { int32_t tmqEpoch = atomic_load_32(&tmq->epoch); if (msgEpoch < tmqEpoch) { // do not write into queue since updating epoch reset - tscWarn("msg discard from vgId:%d since from earlier epoch, rsp epoch %d, current epoch %d", vgId, msgEpoch, - tmqEpoch); + tscWarn("consumer:0x%" PRIx64 + " msg discard from vgId:%d since from earlier epoch, rsp epoch %d, current epoch %d, reqId:0x%" PRIx64, + tmq->consumerId, vgId, msgEpoch, tmqEpoch, requestId); + tsem_post(&tmq->rspSem); + taosReleaseRef(tmqMgmt.rsetId, refId); + taosMemoryFree(pMsg->pData); taosMemoryFree(pMsg->pEpSet); return 0; } if (msgEpoch != tmqEpoch) { - tscWarn("mismatch rsp from vgId:%d, epoch %d, current epoch %d", vgId, msgEpoch, tmqEpoch); + tscWarn("consumer:0x%" PRIx64 " mismatch rsp from vgId:%d, epoch %d, current epoch %d, reqId:0x%" PRIx64, + tmq->consumerId, vgId, msgEpoch, tmqEpoch, requestId); } // handle meta rsp @@ -1218,14 +1297,19 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) { if (pRspWrapper == NULL) { taosMemoryFree(pMsg->pData); taosMemoryFree(pMsg->pEpSet); - tscWarn("msg discard from vgId:%d, epoch %d since out of memory", vgId, epoch); + tscWarn("consumer:0x%" PRIx64 " msg discard from vgId:%d, epoch %d since out of memory", tmq->consumerId, vgId, + epoch); goto CREATE_MSG_FAIL; } pRspWrapper->tmqRspType = rspType; pRspWrapper->vgHandle = pVg; pRspWrapper->topicHandle = pTopic; + pRspWrapper->reqId = requestId; + pRspWrapper->pEpset = pMsg->pEpSet; + pRspWrapper->vgId = pVg->vgId; + pMsg->pEpSet = NULL; if (rspType == TMQ_MSG_TYPE__POLL_RSP) { SDecoder decoder; tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead)); @@ -1233,10 +1317,10 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) { tDecoderClear(&decoder); memcpy(&pRspWrapper->dataRsp, pMsg->pData, sizeof(SMqRspHead)); - tscDebug("consumer:%" PRId64 ", recv poll: vgId:%d, req offset %" PRId64 ", rsp offset %" PRId64 " type %d", - tmq->consumerId, pVg->vgId, pRspWrapper->dataRsp.reqOffset.version, pRspWrapper->dataRsp.rspOffset.version, - rspType); - + char buf[80]; + tFormatOffset(buf, 80, &pRspWrapper->dataRsp.rspOffset); + tscDebug("consumer:0x%" PRIx64 " recv poll rsp, vgId:%d, req ver:%" PRId64 ", rsp:%s type %d, reqId:0x%" PRIx64, + tmq->consumerId, vgId, pRspWrapper->dataRsp.reqOffset.version, buf, rspType, requestId); } else if (rspType == TMQ_MSG_TYPE__POLL_META_RSP) { SDecoder decoder; tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead)); @@ -1249,60 +1333,132 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) { tDecodeSTaosxRsp(&decoder, &pRspWrapper->taosxRsp); tDecoderClear(&decoder); memcpy(&pRspWrapper->taosxRsp, pMsg->pData, sizeof(SMqRspHead)); - } else { - ASSERT(0); + } else { // invalid rspType + tscError("consumer:0x%" PRIx64 " invalid rsp msg received, type:%d ignored", tmq->consumerId, rspType); } taosMemoryFree(pMsg->pData); - taosMemoryFree(pMsg->pEpSet); + taosWriteQitem(tmq->mqueue, pRspWrapper); - tscDebug("consumer:%" PRId64 ", put poll res into mqueue %p", tmq->consumerId, pRspWrapper); + int32_t total = taosQueueItemSize(tmq->mqueue); + tscDebug("consumer:0x%" PRIx64 " put poll res into mqueue, type:%d, vgId:%d, total in queue:%d, reqId:0x%" PRIx64, + tmq->consumerId, rspType, vgId, total, requestId); - taosWriteQitem(tmq->mqueue, pRspWrapper); tsem_post(&tmq->rspSem); + taosReleaseRef(tmqMgmt.rsetId, refId); return 0; + CREATE_MSG_FAIL: if (epoch == tmq->epoch) { atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); } + tsem_post(&tmq->rspSem); + taosReleaseRef(tmqMgmt.rsetId, refId); + return -1; } -bool tmqUpdateEp(tmq_t* tmq, int32_t epoch, const SMqAskEpRsp* pRsp) { +typedef struct SVgroupSaveInfo { + STqOffsetVal offset; + int64_t numOfRows; +} SVgroupSaveInfo; + +static void initClientTopicFromRsp(SMqClientTopic* pTopic, SMqSubTopicEp* pTopicEp, SHashObj* pVgOffsetHashMap, + tmq_t* tmq) { + pTopic->schema = pTopicEp->schema; + pTopicEp->schema.nCols = 0; + pTopicEp->schema.pSchema = NULL; + + char vgKey[TSDB_TOPIC_FNAME_LEN + 22]; + int32_t vgNumGet = taosArrayGetSize(pTopicEp->vgs); + + tstrncpy(pTopic->topicName, pTopicEp->topic, TSDB_TOPIC_FNAME_LEN); + tstrncpy(pTopic->db, pTopicEp->db, TSDB_DB_FNAME_LEN); + + tscDebug("consumer:0x%" PRIx64 ", update topic:%s, new numOfVgs:%d", tmq->consumerId, pTopic->topicName, vgNumGet); + pTopic->vgs = taosArrayInit(vgNumGet, sizeof(SMqClientVg)); + + for (int32_t j = 0; j < vgNumGet; j++) { + SMqSubVgEp* pVgEp = taosArrayGet(pTopicEp->vgs, j); + + makeTopicVgroupKey(vgKey, pTopic->topicName, pVgEp->vgId); + SVgroupSaveInfo* pInfo = taosHashGet(pVgOffsetHashMap, vgKey, strlen(vgKey)); + + int64_t numOfRows = 0; + STqOffsetVal offsetNew = {.type = tmq->resetOffsetCfg}; + if (pInfo != NULL) { + offsetNew = pInfo->offset; + numOfRows = pInfo->numOfRows; + } + + SMqClientVg clientVg = { + .pollCnt = 0, + .currentOffset = offsetNew, + .vgId = pVgEp->vgId, + .epSet = pVgEp->epSet, + .vgStatus = TMQ_VG_STATUS__IDLE, + .vgSkipCnt = 0, + .emptyBlockReceiveTs = 0, + .numOfRows = numOfRows, + }; + + taosArrayPush(pTopic->vgs, &clientVg); + } +} + +static void freeClientVgInfo(void* param) { + SMqClientTopic* pTopic = param; + if (pTopic->schema.nCols) { + taosMemoryFreeClear(pTopic->schema.pSchema); + } + + taosArrayDestroy(pTopic->vgs); +} + +static bool doUpdateLocalEp(tmq_t* tmq, int32_t epoch, const SMqAskEpRsp* pRsp) { bool set = false; + int32_t topicNumCur = taosArrayGetSize(tmq->clientTopics); int32_t topicNumGet = taosArrayGetSize(pRsp->topics); - char vgKey[TSDB_TOPIC_FNAME_LEN + 22]; - tscDebug("consumer:%" PRId64 ", update ep epoch %d to epoch %d, topic num:%d", tmq->consumerId, tmq->epoch, epoch, - topicNumGet); + + char vgKey[TSDB_TOPIC_FNAME_LEN + 22]; + tscDebug("consumer:0x%" PRIx64 " update ep epoch from %d to epoch %d, incoming topics:%d, existed topics:%d", + tmq->consumerId, tmq->epoch, epoch, topicNumGet, topicNumCur); + if (epoch <= tmq->epoch) { + return false; + } SArray* newTopics = taosArrayInit(topicNumGet, sizeof(SMqClientTopic)); if (newTopics == NULL) { return false; } - SHashObj* pHash = taosHashInit(64, MurmurHash3_32, false, HASH_NO_LOCK); - if (pHash == NULL) { + SHashObj* pVgOffsetHashMap = taosHashInit(64, MurmurHash3_32, false, HASH_NO_LOCK); + if (pVgOffsetHashMap == NULL) { taosArrayDestroy(newTopics); return false; } - int32_t topicNumCur = taosArrayGetSize(tmq->clientTopics); + + // todo extract method for (int32_t i = 0; i < topicNumCur; i++) { // find old topic SMqClientTopic* pTopicCur = taosArrayGet(tmq->clientTopics, i); if (pTopicCur->vgs) { int32_t vgNumCur = taosArrayGetSize(pTopicCur->vgs); - tscDebug("consumer:%" PRId64 ", new vg num: %d", tmq->consumerId, vgNumCur); + tscDebug("consumer:0x%" PRIx64 ", current vg num: %d", tmq->consumerId, vgNumCur); for (int32_t j = 0; j < vgNumCur; j++) { SMqClientVg* pVgCur = taosArrayGet(pTopicCur->vgs, j); - sprintf(vgKey, "%s:%d", pTopicCur->topicName, pVgCur->vgId); + makeTopicVgroupKey(vgKey, pTopicCur->topicName, pVgCur->vgId); + char buf[80]; tFormatOffset(buf, 80, &pVgCur->currentOffset); - tscDebug("consumer:%" PRId64 ", epoch %d vgId:%d vgKey is %s, offset is %s", tmq->consumerId, epoch, - pVgCur->vgId, vgKey, buf); - taosHashPut(pHash, vgKey, strlen(vgKey), &pVgCur->currentOffset, sizeof(STqOffsetVal)); + tscDebug("consumer:0x%" PRIx64 ", doUpdateLocalEp current vg, epoch:%d vgId:%d vgKey:%s, offset:%s", tmq->consumerId, tmq->epoch, pVgCur->vgId, + vgKey, buf); + + SVgroupSaveInfo info = {.offset = pVgCur->currentOffset, .numOfRows = pVgCur->numOfRows}; + taosHashPut(pVgOffsetHashMap, vgKey, strlen(vgKey), &info, sizeof(SVgroupSaveInfo)); } } } @@ -1310,81 +1466,50 @@ bool tmqUpdateEp(tmq_t* tmq, int32_t epoch, const SMqAskEpRsp* pRsp) { for (int32_t i = 0; i < topicNumGet; i++) { SMqClientTopic topic = {0}; SMqSubTopicEp* pTopicEp = taosArrayGet(pRsp->topics, i); - topic.schema = pTopicEp->schema; - pTopicEp->schema.nCols = 0; - pTopicEp->schema.pSchema = NULL; - tstrncpy(topic.topicName, pTopicEp->topic, TSDB_TOPIC_FNAME_LEN); - tstrncpy(topic.db, pTopicEp->db, TSDB_DB_FNAME_LEN); - - tscDebug("consumer:%" PRId64 ", update topic: %s", tmq->consumerId, topic.topicName); - - int32_t vgNumGet = taosArrayGetSize(pTopicEp->vgs); - topic.vgs = taosArrayInit(vgNumGet, sizeof(SMqClientVg)); - for (int32_t j = 0; j < vgNumGet; j++) { - SMqSubVgEp* pVgEp = taosArrayGet(pTopicEp->vgs, j); - sprintf(vgKey, "%s:%d", topic.topicName, pVgEp->vgId); - STqOffsetVal* pOffset = taosHashGet(pHash, vgKey, strlen(vgKey)); - STqOffsetVal offsetNew = {.type = tmq->resetOffsetCfg}; - if (pOffset != NULL) { - offsetNew = *pOffset; - } - - SMqClientVg clientVg = { - .pollCnt = 0, - .currentOffset = offsetNew, - .vgId = pVgEp->vgId, - .epSet = pVgEp->epSet, - .vgStatus = TMQ_VG_STATUS__IDLE, - .vgSkipCnt = 0, - }; - taosArrayPush(topic.vgs, &clientVg); - set = true; - } + initClientTopicFromRsp(&topic, pTopicEp, pVgOffsetHashMap, tmq); taosArrayPush(newTopics, &topic); } + + taosHashCleanup(pVgOffsetHashMap); + + // destroy current buffered existed topics info if (tmq->clientTopics) { - int32_t sz = taosArrayGetSize(tmq->clientTopics); - for (int32_t i = 0; i < sz; i++) { - SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i); - if (pTopic->schema.nCols) taosMemoryFreeClear(pTopic->schema.pSchema); - taosArrayDestroy(pTopic->vgs); - } - taosArrayDestroy(tmq->clientTopics); + taosArrayDestroyEx(tmq->clientTopics, freeClientVgInfo); } - taosHashCleanup(pHash); tmq->clientTopics = newTopics; - if (taosArrayGetSize(tmq->clientTopics) == 0) - atomic_store_8(&tmq->status, TMQ_CONSUMER_STATUS__NO_TOPIC); - else - atomic_store_8(&tmq->status, TMQ_CONSUMER_STATUS__READY); - + int8_t flag = (topicNumGet == 0) ? TMQ_CONSUMER_STATUS__NO_TOPIC : TMQ_CONSUMER_STATUS__READY; + atomic_store_8(&tmq->status, flag); atomic_store_32(&tmq->epoch, epoch); + + tscDebug("consumer:0x%" PRIx64 " update topic info completed", tmq->consumerId); return set; } -int32_t tmqAskEpCb(void* param, SDataBuf* pMsg, int32_t code) { +int32_t askEpCallbackFn(void* param, SDataBuf* pMsg, int32_t code) { SMqAskEpCbParam* pParam = (SMqAskEpCbParam*)param; - int8_t async = pParam->async; tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, pParam->refId); if (tmq == NULL) { - if (!async) { - tsem_destroy(&pParam->rspSem); - } else { - taosMemoryFree(pParam); - } + terrno = TSDB_CODE_TMQ_CONSUMER_CLOSED; + pParam->pUserFn(tmq, terrno, NULL, pParam->pParam); + taosMemoryFree(pMsg->pData); taosMemoryFree(pMsg->pEpSet); - terrno = TSDB_CODE_TMQ_CONSUMER_CLOSED; - return -1; + taosMemoryFree(pParam); + return terrno; } - pParam->code = code; - if (code != 0) { - tscError("consumer:%" PRId64 ", get topic endpoint error, not ready, wait:%d, code %x", tmq->consumerId, - pParam->async, code); - goto END; + if (code != TSDB_CODE_SUCCESS) { + tscError("consumer:0x%" PRIx64 ", get topic endpoint error, code:%s", tmq->consumerId, tstrerror(code)); + pParam->pUserFn(tmq, code, NULL, pParam->pParam); + + taosReleaseRef(tmqMgmt.rsetId, pParam->refId); + + taosMemoryFree(pMsg->pData); + taosMemoryFree(pMsg->pEpSet); + taosMemoryFree(pParam); + return code; } // tmq's epoch is monotonically increase, @@ -1392,147 +1517,47 @@ int32_t tmqAskEpCb(void* param, SDataBuf* pMsg, int32_t code) { // Epoch will only increase when received newer epoch ep msg SMqRspHead* head = pMsg->pData; int32_t epoch = atomic_load_32(&tmq->epoch); - tscDebug("consumer:%" PRId64 ", recv ep, msg epoch %d, current epoch %d", tmq->consumerId, head->epoch, epoch); if (head->epoch <= epoch) { - goto END; - } - - if (!async) { - SMqAskEpRsp rsp; - tDecodeSMqAskEpRsp(POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), &rsp); - /*printf("rsp epoch %" PRId64 " sz %" PRId64 "\n", rsp.epoch, rsp.topics->size);*/ - /*printf("tmq epoch %" PRId64 " sz %" PRId64 "\n", tmq->epoch, tmq->clientTopics->size);*/ - tmqUpdateEp(tmq, head->epoch, &rsp); - tDeleteSMqAskEpRsp(&rsp); - } else { - SMqAskEpRspWrapper* pWrapper = taosAllocateQitem(sizeof(SMqAskEpRspWrapper), DEF_QITEM, 0); - if (pWrapper == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - code = -1; - goto END; + tscDebug("consumer:0x%" PRIx64 ", recv ep, msg epoch %d, current epoch %d, no need to update local ep", + tmq->consumerId, head->epoch, epoch); + + if (tmq->status == TMQ_CONSUMER_STATUS__RECOVER) { + SMqAskEpRsp rsp; + tDecodeSMqAskEpRsp(POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), &rsp); + int8_t flag = (taosArrayGetSize(rsp.topics) == 0) ? TMQ_CONSUMER_STATUS__NO_TOPIC : TMQ_CONSUMER_STATUS__READY; + atomic_store_8(&tmq->status, flag); + tDeleteSMqAskEpRsp(&rsp); } - pWrapper->tmqRspType = TMQ_MSG_TYPE__EP_RSP; - pWrapper->epoch = head->epoch; - memcpy(&pWrapper->msg, pMsg->pData, sizeof(SMqRspHead)); - tDecodeSMqAskEpRsp(POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), &pWrapper->msg); - - taosWriteQitem(tmq->mqueue, pWrapper); - tsem_post(&tmq->rspSem); - } -END: - /*atomic_store_8(&tmq->epStatus, 0);*/ - if (!async) { - tsem_post(&pParam->rspSem); } else { - taosMemoryFree(pParam); + tscDebug("consumer:0x%" PRIx64 ", recv ep, msg epoch %d, current epoch %d, update local ep", tmq->consumerId, + head->epoch, epoch); } + pParam->pUserFn(tmq, code, pMsg, pParam->pParam); + + taosReleaseRef(tmqMgmt.rsetId, pParam->refId); taosMemoryFree(pMsg->pEpSet); taosMemoryFree(pMsg->pData); - return code; -} - -int32_t tmqAskEp(tmq_t* tmq, bool async) { - int32_t code = 0; -#if 0 - int8_t epStatus = atomic_val_compare_exchange_8(&tmq->epStatus, 0, 1); - if (epStatus == 1) { - int32_t epSkipCnt = atomic_add_fetch_32(&tmq->epSkipCnt, 1); - tscTrace("consumer:%" PRId64 ", skip ask ep cnt %d", tmq->consumerId, epSkipCnt); - if (epSkipCnt < 5000) return 0; - } - atomic_store_32(&tmq->epSkipCnt, 0); -#endif - SMqAskEpReq req = {0}; - req.consumerId = tmq->consumerId; - req.epoch = tmq->epoch; - strcpy(req.cgroup, tmq->groupId); - - int32_t tlen = tSerializeSMqAskEpReq(NULL, 0, &req); - if (tlen < 0) { - tscError("tSerializeSMqAskEpReq failed"); - return -1; - } - void* pReq = taosMemoryCalloc(1, tlen); - if (pReq == NULL) { - tscError("failed to malloc askEpReq msg, size:%d", tlen); - return -1; - } - if (tSerializeSMqAskEpReq(pReq, tlen, &req) < 0) { - tscError("tSerializeSMqAskEpReq %d failed", tlen); - taosMemoryFree(pReq); - return -1; - } - - SMqAskEpCbParam* pParam = taosMemoryCalloc(1, sizeof(SMqAskEpCbParam)); - if (pParam == NULL) { - tscError("failed to malloc subscribe param"); - taosMemoryFree(pReq); - /*atomic_store_8(&tmq->epStatus, 0);*/ - return -1; - } - pParam->refId = tmq->refId; - pParam->epoch = tmq->epoch; - pParam->async = async; - tsem_init(&pParam->rspSem, 0, 0); - - SMsgSendInfo* sendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); - if (sendInfo == NULL) { - tsem_destroy(&pParam->rspSem); - taosMemoryFree(pParam); - taosMemoryFree(pReq); - /*atomic_store_8(&tmq->epStatus, 0);*/ - return -1; - } - - sendInfo->msgInfo = (SDataBuf){ - .pData = pReq, - .len = tlen, - .handle = NULL, - }; - - sendInfo->requestId = generateRequestId(); - sendInfo->requestObjRefId = 0; - sendInfo->param = pParam; - sendInfo->fp = tmqAskEpCb; - sendInfo->msgType = TDMT_MND_TMQ_ASK_EP; - - SEpSet epSet = getEpSet_s(&tmq->pTscObj->pAppInfo->mgmtEp); - - tscDebug("consumer:%" PRId64 ", ask ep", tmq->consumerId); - - int64_t transporterId = 0; - asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &epSet, &transporterId, sendInfo); - - if (!async) { - tsem_wait(&pParam->rspSem); - code = pParam->code; - taosMemoryFree(pParam); - } + taosMemoryFree(pParam); return code; } void tmqBuildConsumeReqImpl(SMqPollReq* pReq, tmq_t* tmq, int64_t timeout, SMqClientTopic* pTopic, SMqClientVg* pVg) { - /*strcpy(pReq->topic, pTopic->topicName);*/ - /*strcpy(pReq->cgroup, tmq->groupId);*/ - int32_t groupLen = strlen(tmq->groupId); memcpy(pReq->subKey, tmq->groupId, groupLen); pReq->subKey[groupLen] = TMQ_SEPARATOR; strcpy(pReq->subKey + groupLen + 1, pTopic->topicName); pReq->withTbName = tmq->withTbName; - pReq->timeout = timeout; pReq->consumerId = tmq->consumerId; + pReq->timeout = timeout; pReq->epoch = tmq->epoch; /*pReq->currentOffset = reqOffset;*/ pReq->reqOffset = pVg->currentOffset; - pReq->reqId = generateRequestId(); - - pReq->useSnapshot = tmq->useSnapshot; - pReq->head.vgId = pVg->vgId; + pReq->useSnapshot = tmq->useSnapshot; + pReq->reqId = generateRequestId(); } SMqMetaRspObj* tmqBuildMetaRspFromWrapper(SMqPollRspWrapper* pWrapper) { @@ -1546,21 +1571,33 @@ SMqMetaRspObj* tmqBuildMetaRspFromWrapper(SMqPollRspWrapper* pWrapper) { return pRspObj; } -SMqRspObj* tmqBuildRspFromWrapper(SMqPollRspWrapper* pWrapper) { +SMqRspObj* tmqBuildRspFromWrapper(SMqPollRspWrapper* pWrapper, SMqClientVg* pVg, int64_t* numOfRows) { SMqRspObj* pRspObj = taosMemoryCalloc(1, sizeof(SMqRspObj)); pRspObj->resType = RES_TYPE__TMQ; + + (*numOfRows) = 0; tstrncpy(pRspObj->topic, pWrapper->topicHandle->topicName, TSDB_TOPIC_FNAME_LEN); tstrncpy(pRspObj->db, pWrapper->topicHandle->db, TSDB_DB_FNAME_LEN); + pRspObj->vgId = pWrapper->vgHandle->vgId; pRspObj->resIter = -1; memcpy(&pRspObj->rsp, &pWrapper->dataRsp, sizeof(SMqDataRsp)); pRspObj->resInfo.totalRows = 0; pRspObj->resInfo.precision = TSDB_TIME_PRECISION_MILLI; + if (!pWrapper->dataRsp.withSchema) { setResSchemaInfo(&pRspObj->resInfo, pWrapper->topicHandle->schema.pSchema, pWrapper->topicHandle->schema.nCols); } + // extract the rows in this data packet + for (int32_t i = 0; i < pRspObj->rsp.blockNum; ++i) { + SRetrieveTableRsp* pRetrieve = (SRetrieveTableRsp*)taosArrayGetP(pRspObj->rsp.blockData, i); + int64_t rows = htobe64(pRetrieve->numOfRows); + pVg->numOfRows += rows; + (*numOfRows) += rows; + } + return pRspObj; } @@ -1582,107 +1619,124 @@ SMqTaosxRspObj* tmqBuildTaosxRspFromWrapper(SMqPollRspWrapper* pWrapper) { return pRspObj; } -int32_t tmqPollImpl(tmq_t* tmq, int64_t timeout) { - for (int i = 0; i < taosArrayGetSize(tmq->clientTopics); i++) { +static int32_t handleErrorBeforePoll(SMqClientVg* pVg, tmq_t* pTmq) { + atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); + tsem_post(&pTmq->rspSem); + return -1; +} + +static int32_t doTmqPollImpl(tmq_t* pTmq, SMqClientTopic* pTopic, SMqClientVg* pVg, int64_t timeout) { + SMqPollReq req = {0}; + tmqBuildConsumeReqImpl(&req, pTmq, timeout, pTopic, pVg); + + int32_t msgSize = tSerializeSMqPollReq(NULL, 0, &req); + if (msgSize < 0) { + return handleErrorBeforePoll(pVg, pTmq); + } + + char* msg = taosMemoryCalloc(1, msgSize); + if (NULL == msg) { + return handleErrorBeforePoll(pVg, pTmq); + } + + if (tSerializeSMqPollReq(msg, msgSize, &req) < 0) { + taosMemoryFree(msg); + return handleErrorBeforePoll(pVg, pTmq); + } + + SMqPollCbParam* pParam = taosMemoryMalloc(sizeof(SMqPollCbParam)); + if (pParam == NULL) { + taosMemoryFree(msg); + return handleErrorBeforePoll(pVg, pTmq); + } + + pParam->refId = pTmq->refId; + pParam->epoch = pTmq->epoch; + pParam->pVg = pVg; // pVg may be released,fix it + pParam->pTopic = pTopic; + pParam->vgId = pVg->vgId; + pParam->requestId = req.reqId; + + SMsgSendInfo* sendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); + if (sendInfo == NULL) { + taosMemoryFree(pParam); + taosMemoryFree(msg); + return handleErrorBeforePoll(pVg, pTmq); + } + + sendInfo->msgInfo = (SDataBuf){ .pData = msg, .len = msgSize, .handle = NULL }; + + sendInfo->requestId = req.reqId; + sendInfo->requestObjRefId = 0; + sendInfo->param = pParam; + sendInfo->fp = tmqPollCb; + sendInfo->msgType = TDMT_VND_TMQ_CONSUME; + + int64_t transporterId = 0; + char offsetFormatBuf[80]; + tFormatOffset(offsetFormatBuf, tListLen(offsetFormatBuf), &pVg->currentOffset); + + tscDebug("consumer:0x%" PRIx64 " send poll to %s vgId:%d, epoch %d, req:%s, reqId:0x%" PRIx64, pTmq->consumerId, + pTopic->topicName, pVg->vgId, pTmq->epoch, offsetFormatBuf, req.reqId); + asyncSendMsgToServer(pTmq->pTscObj->pAppInfo->pTransporter, &pVg->epSet, &transporterId, sendInfo); + + pVg->pollCnt++; + pTmq->pollCnt++; + + return TSDB_CODE_SUCCESS; +} + +// broadcast the poll request to all related vnodes +static int32_t tmqPollImpl(tmq_t* tmq, int64_t timeout) { + int32_t numOfTopics = taosArrayGetSize(tmq->clientTopics); + tscDebug("consumer:0x%" PRIx64 " start to poll data, numOfTopics:%d", tmq->consumerId, numOfTopics); + + for (int i = 0; i < numOfTopics; i++) { SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i); - for (int j = 0; j < taosArrayGetSize(pTopic->vgs); j++) { + int32_t numOfVg = taosArrayGetSize(pTopic->vgs); + + for (int j = 0; j < numOfVg; j++) { SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j); - int32_t vgStatus = atomic_val_compare_exchange_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE, TMQ_VG_STATUS__WAIT); - if (vgStatus != TMQ_VG_STATUS__IDLE) { + if (taosGetTimestampMs() - pVg->emptyBlockReceiveTs < EMPTY_BLOCK_POLL_IDLE_DURATION) { // less than 100ms + tscTrace("consumer:0x%" PRIx64 " epoch %d, vgId:%d idle for 10ms before start next poll", tmq->consumerId, + tmq->epoch, pVg->vgId); + continue; + } + + int32_t vgStatus = atomic_val_compare_exchange_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE, TMQ_VG_STATUS__WAIT); + if (vgStatus == TMQ_VG_STATUS__WAIT) { int32_t vgSkipCnt = atomic_add_fetch_32(&pVg->vgSkipCnt, 1); - tscTrace("consumer:%" PRId64 ", epoch %d skip vgId:%d skip cnt %d", tmq->consumerId, tmq->epoch, pVg->vgId, - vgSkipCnt); + tscTrace("consumer:0x%" PRIx64 " epoch %d wait poll-rsp, skip vgId:%d skip cnt %d", tmq->consumerId, tmq->epoch, + pVg->vgId, vgSkipCnt); continue; - /*if (vgSkipCnt < 10000) continue;*/ #if 0 if (skipCnt < 30000) { continue; } else { - tscDebug("consumer:%" PRId64 ",skip vgId:%d skip too much reset", tmq->consumerId, pVg->vgId); + tscDebug("consumer:0x%" PRIx64 ",skip vgId:%d skip too much reset", tmq->consumerId, pVg->vgId); } #endif } - atomic_store_32(&pVg->vgSkipCnt, 0); - - SMqPollReq req = {0}; - tmqBuildConsumeReqImpl(&req, tmq, timeout, pTopic, pVg); - int32_t msgSize = tSerializeSMqPollReq(NULL, 0, &req); - if (msgSize < 0) { - atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); - tsem_post(&tmq->rspSem); - return -1; - } - char* msg = taosMemoryCalloc(1, msgSize); - if (NULL == msg) { - atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); - tsem_post(&tmq->rspSem); - return -1; - } - if (tSerializeSMqPollReq(msg, msgSize, &req) < 0) { - taosMemoryFree(msg); - atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); - tsem_post(&tmq->rspSem); - return -1; - } - - SMqPollCbParam* pParam = taosMemoryMalloc(sizeof(SMqPollCbParam)); - if (pParam == NULL) { - taosMemoryFree(msg); - atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); - tsem_post(&tmq->rspSem); - return -1; - } - pParam->refId = tmq->refId; - pParam->epoch = tmq->epoch; - - pParam->pVg = pVg; - pParam->pTopic = pTopic; - pParam->vgId = pVg->vgId; - - SMsgSendInfo* sendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); - if (sendInfo == NULL) { - taosMemoryFree(msg); - taosMemoryFree(pParam); - atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); - tsem_post(&tmq->rspSem); - return -1; + atomic_store_32(&pVg->vgSkipCnt, 0); + int32_t code = doTmqPollImpl(tmq, pTopic, pVg, timeout); + if (code != TSDB_CODE_SUCCESS) { + return code; } - - sendInfo->msgInfo = (SDataBuf){ - .pData = msg, - .len = msgSize, - .handle = NULL, - }; - sendInfo->requestId = req.reqId; - sendInfo->requestObjRefId = 0; - sendInfo->param = pParam; - sendInfo->fp = tmqPollCb; - sendInfo->msgType = TDMT_VND_TMQ_CONSUME; - - int64_t transporterId = 0; - /*printf("send poll\n");*/ - - char offsetFormatBuf[80]; - tFormatOffset(offsetFormatBuf, 80, &pVg->currentOffset); - tscDebug("consumer:%" PRId64 ", send poll to %s vgId:%d, epoch %d, req offset:%s, reqId:%" PRIu64, - tmq->consumerId, pTopic->topicName, pVg->vgId, tmq->epoch, offsetFormatBuf, req.reqId); - /*printf("send vgId:%d %" PRId64 "\n", pVg->vgId, pVg->currentOffset);*/ - asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &pVg->epSet, &transporterId, sendInfo); - pVg->pollCnt++; - tmq->pollCnt++; } } + + tscDebug("consumer:0x%" PRIx64 " end to poll data", tmq->consumerId); return 0; } -int32_t tmqHandleNoPollRsp(tmq_t* tmq, SMqRspWrapper* rspWrapper, bool* pReset) { +static int32_t tmqHandleNoPollRsp(tmq_t* tmq, SMqRspWrapper* rspWrapper, bool* pReset) { if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__EP_RSP) { /*printf("ep %d %d\n", rspMsg->head.epoch, tmq->epoch);*/ if (rspWrapper->epoch > atomic_load_32(&tmq->epoch)) { SMqAskEpRspWrapper* pEpRspWrapper = (SMqAskEpRspWrapper*)rspWrapper; SMqAskEpRsp* rspMsg = &pEpRspWrapper->msg; - tmqUpdateEp(tmq, rspWrapper->epoch, rspMsg); + doUpdateLocalEp(tmq, rspWrapper->epoch, rspMsg); /*tmqClearUnhandleMsg(tmq);*/ tDeleteSMqAskEpRsp(rspMsg); *pReset = true; @@ -1696,109 +1750,157 @@ int32_t tmqHandleNoPollRsp(tmq_t* tmq, SMqRspWrapper* rspWrapper, bool* pReset) return 0; } -void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) { +static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) { + tscDebug("consumer:0x%" PRIx64 " start to handle the rsp, total:%d", tmq->consumerId, tmq->qall->numOfItems); + while (1) { - SMqRspWrapper* rspWrapper = NULL; - taosGetQitem(tmq->qall, (void**)&rspWrapper); - if (rspWrapper == NULL) { - taosReadAllQitems(tmq->mqueue, tmq->qall); - taosGetQitem(tmq->qall, (void**)&rspWrapper); + SMqRspWrapper* pRspWrapper = NULL; + taosGetQitem(tmq->qall, (void**)&pRspWrapper); - if (rspWrapper == NULL) { - /*tscDebug("consumer %" PRId64 " mqueue empty", tmq->consumerId);*/ + if (pRspWrapper == NULL) { + taosReadAllQitems(tmq->mqueue, tmq->qall); + taosGetQitem(tmq->qall, (void**)&pRspWrapper); + if (pRspWrapper == NULL) { return NULL; } } - tscDebug("consumer:%" PRId64 " handle rsp %p", tmq->consumerId, rspWrapper); + tscDebug("consumer:0x%" PRIx64 " handle rsp, type:%d", tmq->consumerId, pRspWrapper->tmqRspType); - if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__END_RSP) { - taosFreeQitem(rspWrapper); + if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__END_RSP) { + taosFreeQitem(pRspWrapper); terrno = TSDB_CODE_TQ_NO_COMMITTED_OFFSET; + tscError("consumer:0x%" PRIx64 " unexpected rsp from poll, code:%s", tmq->consumerId, tstrerror(terrno)); return NULL; - } else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_RSP) { - SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)rspWrapper; - tscDebug("consumer %" PRId64 " actual process poll rsp", tmq->consumerId); - /*atomic_sub_fetch_32(&tmq->readyRequest, 1);*/ - int32_t consumerEpoch = atomic_load_32(&tmq->epoch); - if (pollRspWrapper->dataRsp.head.epoch == consumerEpoch) { + } else if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_RSP) { + SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)pRspWrapper; + + int32_t consumerEpoch = atomic_load_32(&tmq->epoch); + SMqDataRsp* pDataRsp = &pollRspWrapper->dataRsp; + + if (pDataRsp->head.epoch == consumerEpoch) { SMqClientVg* pVg = pollRspWrapper->vgHandle; - /*printf("vgId:%d, offset %" PRId64 " up to %" PRId64 "\n", pVg->vgId, pVg->currentOffset, - * rspMsg->msg.rspOffset);*/ - pVg->currentOffset = pollRspWrapper->dataRsp.rspOffset; + + // update the epset + if (pollRspWrapper->pEpset != NULL) { + SEp* pEp = GET_ACTIVE_EP(pollRspWrapper->pEpset); + SEp* pOld = GET_ACTIVE_EP(&(pVg->epSet)); + tscDebug("consumer:0x%" PRIx64 " update epset vgId:%d, ep:%s:%d, old ep:%s:%d", tmq->consumerId, pVg->vgId, + pEp->fqdn, pEp->port, pOld->fqdn, pOld->port); + pVg->epSet = *pollRspWrapper->pEpset; + } + + if(pDataRsp->rspOffset.type != 0){ // if offset is validate + pVg->currentOffset = pDataRsp->rspOffset; // update the local offset value only for the returned values. + } atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); - if (pollRspWrapper->dataRsp.blockNum == 0) { + + char buf[80]; + tFormatOffset(buf, 80, &pDataRsp->rspOffset); + if (pDataRsp->blockNum == 0) { + tscDebug("consumer:0x%" PRIx64 " empty block received, vgId:%d, offset:%s, vg total:%" PRId64 + " total:%" PRId64 " reqId:0x%" PRIx64, + tmq->consumerId, pVg->vgId, buf, pVg->numOfRows, tmq->totalRows, pollRspWrapper->reqId); + pRspWrapper = tmqFreeRspWrapper(pRspWrapper); + pVg->emptyBlockReceiveTs = taosGetTimestampMs(); taosFreeQitem(pollRspWrapper); - rspWrapper = NULL; - continue; + } else { // build rsp + int64_t numOfRows = 0; + SMqRspObj* pRsp = tmqBuildRspFromWrapper(pollRspWrapper, pVg, &numOfRows); + tmq->totalRows += numOfRows; + pVg->emptyBlockReceiveTs = 0; + tscDebug("consumer:0x%" PRIx64 " process poll rsp, vgId:%d, offset:%s, blocks:%d, rows:%" PRId64 + " vg total:%" PRId64 " total:%" PRId64 ", reqId:0x%" PRIx64, + tmq->consumerId, pVg->vgId, buf, pDataRsp->blockNum, numOfRows, pVg->numOfRows, tmq->totalRows, + pollRspWrapper->reqId); + taosFreeQitem(pollRspWrapper); + return pRsp; } - // build rsp - SMqRspObj* pRsp = tmqBuildRspFromWrapper(pollRspWrapper); - taosFreeQitem(pollRspWrapper); - return pRsp; } else { - tscDebug("msg discard since epoch mismatch: msg epoch %d, consumer epoch %d", - pollRspWrapper->dataRsp.head.epoch, consumerEpoch); - tmqFreeRspWrapper(rspWrapper); + tscDebug("consumer:0x%" PRIx64 " vgId:%d msg discard since epoch mismatch: msg epoch %d, consumer epoch %d", + tmq->consumerId, pollRspWrapper->vgId, pDataRsp->head.epoch, consumerEpoch); + pRspWrapper = tmqFreeRspWrapper(pRspWrapper); taosFreeQitem(pollRspWrapper); } - } else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_META_RSP) { - SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)rspWrapper; + } else if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_META_RSP) { + SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)pRspWrapper; int32_t consumerEpoch = atomic_load_32(&tmq->epoch); + + tscDebug("consumer:0x%" PRIx64 " process meta rsp", tmq->consumerId); + if (pollRspWrapper->metaRsp.head.epoch == consumerEpoch) { SMqClientVg* pVg = pollRspWrapper->vgHandle; - /*printf("vgId:%d, offset %" PRId64 " up to %" PRId64 "\n", pVg->vgId, pVg->currentOffset, - * rspMsg->msg.rspOffset);*/ - pVg->currentOffset = pollRspWrapper->metaRsp.rspOffset; + if(pollRspWrapper->metaRsp.rspOffset.type != 0){ // if offset is validate + pVg->currentOffset = pollRspWrapper->metaRsp.rspOffset; + } atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); // build rsp SMqMetaRspObj* pRsp = tmqBuildMetaRspFromWrapper(pollRspWrapper); taosFreeQitem(pollRspWrapper); return pRsp; } else { - tscDebug("msg discard since epoch mismatch: msg epoch %d, consumer epoch %d", - pollRspWrapper->metaRsp.head.epoch, consumerEpoch); - tmqFreeRspWrapper(rspWrapper); + tscDebug("consumer:0x%" PRIx64 " vgId:%d msg discard since epoch mismatch: msg epoch %d, consumer epoch %d", + tmq->consumerId, pollRspWrapper->vgId, pollRspWrapper->metaRsp.head.epoch, consumerEpoch); + pRspWrapper = tmqFreeRspWrapper(pRspWrapper); taosFreeQitem(pollRspWrapper); } - } else if (rspWrapper->tmqRspType == TMQ_MSG_TYPE__TAOSX_RSP) { - SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)rspWrapper; - /*atomic_sub_fetch_32(&tmq->readyRequest, 1);*/ - int32_t consumerEpoch = atomic_load_32(&tmq->epoch); + } else if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__TAOSX_RSP) { + SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)pRspWrapper; + int32_t consumerEpoch = atomic_load_32(&tmq->epoch); + if (pollRspWrapper->taosxRsp.head.epoch == consumerEpoch) { SMqClientVg* pVg = pollRspWrapper->vgHandle; - /*printf("vgId:%d, offset %" PRId64 " up to %" PRId64 "\n", pVg->vgId, pVg->currentOffset, - * rspMsg->msg.rspOffset);*/ - pVg->currentOffset = pollRspWrapper->taosxRsp.rspOffset; + if(pollRspWrapper->taosxRsp.rspOffset.type != 0){ // if offset is validate + pVg->currentOffset = pollRspWrapper->taosxRsp.rspOffset; + } atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE); + if (pollRspWrapper->taosxRsp.blockNum == 0) { + tscDebug("consumer:0x%" PRIx64 " taosx empty block received, vgId:%d, vg total:%" PRId64 " reqId:0x%" PRIx64, + tmq->consumerId, pVg->vgId, pVg->numOfRows, pollRspWrapper->reqId); + pVg->emptyBlockReceiveTs = taosGetTimestampMs(); + pRspWrapper = tmqFreeRspWrapper(pRspWrapper); taosFreeQitem(pollRspWrapper); - rspWrapper = NULL; continue; + } else { + pVg->emptyBlockReceiveTs = 0; // reset the ts } // build rsp - void* pRsp = NULL; + void* pRsp = NULL; + int64_t numOfRows = 0; if (pollRspWrapper->taosxRsp.createTableNum == 0) { - pRsp = tmqBuildRspFromWrapper(pollRspWrapper); + pRsp = tmqBuildRspFromWrapper(pollRspWrapper, pVg, &numOfRows); } else { pRsp = tmqBuildTaosxRspFromWrapper(pollRspWrapper); } + + tmq->totalRows += numOfRows; + + char buf[80]; + tFormatOffset(buf, 80, &pVg->currentOffset); + tscDebug("consumer:0x%" PRIx64 " process taosx poll rsp, vgId:%d, offset:%s, blocks:%d, rows:%" PRId64 + ", vg total:%" PRId64 " total:%" PRId64 " reqId:0x%" PRIx64, + tmq->consumerId, pVg->vgId, buf, pollRspWrapper->dataRsp.blockNum, numOfRows, pVg->numOfRows, + tmq->totalRows, pollRspWrapper->reqId); + taosFreeQitem(pollRspWrapper); return pRsp; + } else { - tscDebug("msg discard since epoch mismatch: msg epoch %d, consumer epoch %d", - pollRspWrapper->taosxRsp.head.epoch, consumerEpoch); - tmqFreeRspWrapper(rspWrapper); + tscDebug("consumer:0x%" PRIx64 " vgId:%d msg discard since epoch mismatch: msg epoch %d, consumer epoch %d", + tmq->consumerId, pollRspWrapper->vgId, pollRspWrapper->taosxRsp.head.epoch, consumerEpoch); + pRspWrapper = tmqFreeRspWrapper(pRspWrapper); taosFreeQitem(pollRspWrapper); } } else { - /*printf("handle ep rsp %d\n", rspMsg->head.mqMsgType);*/ + tscDebug("consumer:0x%" PRIx64 " not data msg received", tmq->consumerId); + bool reset = false; - tmqHandleNoPollRsp(tmq, rspWrapper, &reset); - taosFreeQitem(rspWrapper); + tmqHandleNoPollRsp(tmq, pRspWrapper, &reset); + taosFreeQitem(pRspWrapper); if (pollIfReset && reset) { - tscDebug("consumer:%" PRId64 ", reset and repoll", tmq->consumerId); + tscDebug("consumer:0x%" PRIx64 ", reset and repoll", tmq->consumerId); tmqPollImpl(tmq, timeout); } } @@ -1809,7 +1911,8 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) { void* rspObj; int64_t startTime = taosGetTimestampMs(); - tscDebug("consumer:%" PRId64 ", start poll at %" PRId64, tmq->consumerId, startTime); + tscDebug("consumer:0x%" PRIx64 " start to poll at %" PRId64 ", timeout:%" PRId64, tmq->consumerId, startTime, + timeout); #if 0 tmqHandleAllDelayedTask(tmq); @@ -1822,48 +1925,48 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) { // in no topic status, delayed task also need to be processed if (atomic_load_8(&tmq->status) == TMQ_CONSUMER_STATUS__INIT) { - tscDebug("consumer:%" PRId64 ", poll return since consumer status is init", tmq->consumerId); + tscDebug("consumer:0x%" PRIx64 " poll return since consumer is init", tmq->consumerId); + taosMsleep(500); // sleep for a while return NULL; } - if (atomic_load_8(&tmq->status) == TMQ_CONSUMER_STATUS__RECOVER) { + while (atomic_load_8(&tmq->status) == TMQ_CONSUMER_STATUS__RECOVER) { int32_t retryCnt = 0; - while (TSDB_CODE_MND_CONSUMER_NOT_READY == tmqAskEp(tmq, false)) { - if (retryCnt++ > 10) { + while (TSDB_CODE_MND_CONSUMER_NOT_READY == doAskEp(tmq)) { + if (retryCnt++ > 40) { return NULL; } - tscDebug("consumer not ready, retry"); + + tscDebug("consumer:0x%" PRIx64 " not ready, retry:%d/40 in 500ms", tmq->consumerId, retryCnt); taosMsleep(500); } } while (1) { tmqHandleAllDelayedTask(tmq); + if (tmqPollImpl(tmq, timeout) < 0) { - tscDebug("consumer:%" PRId64 " return since poll err", tmq->consumerId); - /*return NULL;*/ + tscDebug("consumer:0x%" PRIx64 " return due to poll error", tmq->consumerId); } rspObj = tmqHandleAllRsp(tmq, timeout, false); if (rspObj) { - tscDebug("consumer:%" PRId64 ", return rsp %p", tmq->consumerId, rspObj); + tscDebug("consumer:0x%" PRIx64 " return rsp %p", tmq->consumerId, rspObj); return (TAOS_RES*)rspObj; } else if (terrno == TSDB_CODE_TQ_NO_COMMITTED_OFFSET) { - tscDebug("consumer:%" PRId64 ", return null since no committed offset", tmq->consumerId); + tscDebug("consumer:0x%" PRIx64 " return null since no committed offset", tmq->consumerId); return NULL; } - if (timeout != -1) { + + if (timeout >= 0) { int64_t currentTime = taosGetTimestampMs(); - int64_t passedTime = currentTime - startTime; - if (passedTime > timeout) { - tscDebug("consumer:%" PRId64 ", (epoch %d) timeout, no rsp, start time %" PRId64 ", current time %" PRId64, + int64_t elapsedTime = currentTime - startTime; + if (elapsedTime > timeout) { + tscDebug("consumer:0x%" PRIx64 " (epoch %d) timeout, no rsp, start time %" PRId64 ", current time %" PRId64, tmq->consumerId, tmq->epoch, startTime, currentTime); return NULL; } - /*tscInfo("consumer:%" PRId64 ", (epoch %d) wait, start time %" PRId64 ", current time %" PRId64*/ - /*", left time %" PRId64,*/ - /*tmq->consumerId, tmq->epoch, startTime, currentTime, (timeout - passedTime));*/ - tsem_timewait(&tmq->rspSem, (timeout - passedTime)); + tsem_timewait(&tmq->rspSem, (timeout - elapsedTime)); } else { // use tsem_timewait instead of tsem_wait to avoid unexpected stuck tsem_timewait(&tmq->rspSem, 1000); @@ -1871,17 +1974,43 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) { } } +static void displayConsumeStatistics(const tmq_t* pTmq) { + int32_t numOfTopics = taosArrayGetSize(pTmq->clientTopics); + tscDebug("consumer:0x%" PRIx64 " closing poll:%" PRId64 " rows:%" PRId64 " topics:%d, final epoch:%d", + pTmq->consumerId, pTmq->pollCnt, pTmq->totalRows, numOfTopics, pTmq->epoch); + + tscDebug("consumer:0x%" PRIx64 " rows dist begin: ", pTmq->consumerId); + for (int32_t i = 0; i < numOfTopics; ++i) { + SMqClientTopic* pTopics = taosArrayGet(pTmq->clientTopics, i); + + tscDebug("consumer:0x%" PRIx64 " topic:%d", pTmq->consumerId, i); + int32_t numOfVgs = taosArrayGetSize(pTopics->vgs); + for (int32_t j = 0; j < numOfVgs; ++j) { + SMqClientVg* pVg = taosArrayGet(pTopics->vgs, j); + tscDebug("topic:%s, %d. vgId:%d rows:%" PRId64, pTopics->topicName, j, pVg->vgId, pVg->numOfRows); + } + } + + tscDebug("consumer:0x%" PRIx64 " rows dist end", pTmq->consumerId); +} + int32_t tmq_consumer_close(tmq_t* tmq) { + tscDebug("consumer:0x%" PRIx64 " start to close consumer, status:%d", tmq->consumerId, tmq->status); + displayConsumeStatistics(tmq); + if (tmq->status == TMQ_CONSUMER_STATUS__READY) { - int32_t rsp = tmq_commit_sync(tmq, NULL); - if (rsp != 0) { - return rsp; + // if auto commit is set, commit before close consumer. Otherwise, do nothing. + if (tmq->autoCommit) { + int32_t rsp = tmq_commit_sync(tmq, NULL); + if (rsp != 0) { + return rsp; + } } int32_t retryCnt = 0; tmq_list_t* lst = tmq_list_new(); while (1) { - rsp = tmq_subscribe(tmq, lst); + int32_t rsp = tmq_subscribe(tmq, lst); if (rsp != TSDB_CODE_MND_CONSUMER_NOT_READY || retryCnt > 5) { break; } else { @@ -1891,7 +2020,10 @@ int32_t tmq_consumer_close(tmq_t* tmq) { } tmq_list_destroy(lst); + } else { + tscWarn("consumer:0x%" PRIx64 " not in ready state, close it directly", tmq->consumerId); } + taosRemoveRef(tmqMgmt.rsetId, tmq->refId); return 0; } @@ -1982,12 +2114,212 @@ const char* tmq_get_table_name(TAOS_RES* res) { return NULL; } -void tmq_commit_async(tmq_t* tmq, const TAOS_RES* msg, tmq_commit_cb* cb, void* param) { - // - tmqCommitInner(tmq, msg, 0, 1, cb, param); +void tmq_commit_async(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* cb, void* param) { + if (pRes == NULL) { // here needs to commit all offsets. + asyncCommitAllOffsets(tmq, cb, param); + } else { // only commit one offset + asyncCommitOffset(tmq, pRes, cb, param); + } } -int32_t tmq_commit_sync(tmq_t* tmq, const TAOS_RES* msg) { - // - return tmqCommitInner(tmq, msg, 0, 0, NULL, NULL); +static void commitCallBackFn(tmq_t *pTmq, int32_t code, void* param) { + SSyncCommitInfo* pInfo = (SSyncCommitInfo*) param; + pInfo->code = code; + tsem_post(&pInfo->sem); +} + +int32_t tmq_commit_sync(tmq_t* tmq, const TAOS_RES* pRes) { + int32_t code = 0; + + SSyncCommitInfo* pInfo = taosMemoryMalloc(sizeof(SSyncCommitInfo)); + tsem_init(&pInfo->sem, 0, 0); + pInfo->code = 0; + + if (pRes == NULL) { + asyncCommitAllOffsets(tmq, commitCallBackFn, pInfo); + } else { + asyncCommitOffset(tmq, pRes, commitCallBackFn, pInfo); + } + + tsem_wait(&pInfo->sem); + code = pInfo->code; + + tsem_destroy(&pInfo->sem); + taosMemoryFree(pInfo); + + tscDebug("consumer:0x%" PRIx64 " sync commit done, code:%s", tmq->consumerId, tstrerror(code)); + return code; } + +void updateEpCallbackFn(tmq_t* pTmq, int32_t code, SDataBuf* pDataBuf, void* param) { + SAskEpInfo* pInfo = param; + pInfo->code = code; + + if (code == TSDB_CODE_SUCCESS) { + SMqRspHead* head = pDataBuf->pData; + + SMqAskEpRsp rsp; + tDecodeSMqAskEpRsp(POINTER_SHIFT(pDataBuf->pData, sizeof(SMqRspHead)), &rsp); + doUpdateLocalEp(pTmq, head->epoch, &rsp); + tDeleteSMqAskEpRsp(&rsp); + } + + tsem_post(&pInfo->sem); +} + +void addToQueueCallbackFn(tmq_t* pTmq, int32_t code, SDataBuf* pDataBuf, void* param) { + if (code != TSDB_CODE_SUCCESS) { + terrno = code; + return; + } + + SMqAskEpRspWrapper* pWrapper = taosAllocateQitem(sizeof(SMqAskEpRspWrapper), DEF_QITEM, 0); + if (pWrapper == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return; + } + + SMqRspHead* head = pDataBuf->pData; + + pWrapper->tmqRspType = TMQ_MSG_TYPE__EP_RSP; + pWrapper->epoch = head->epoch; + memcpy(&pWrapper->msg, pDataBuf->pData, sizeof(SMqRspHead)); + tDecodeSMqAskEpRsp(POINTER_SHIFT(pDataBuf->pData, sizeof(SMqRspHead)), &pWrapper->msg); + + taosWriteQitem(pTmq->mqueue, pWrapper); +} + +int32_t doAskEp(tmq_t* pTmq) { + SAskEpInfo* pInfo = taosMemoryMalloc(sizeof(SAskEpInfo)); + tsem_init(&pInfo->sem, 0, 0); + + asyncAskEp(pTmq, updateEpCallbackFn, pInfo); + tsem_wait(&pInfo->sem); + + int32_t code = pInfo->code; + tsem_destroy(&pInfo->sem); + taosMemoryFree(pInfo); + return code; +} + +void asyncAskEp(tmq_t* pTmq, __tmq_askep_fn_t askEpFn, void* param) { + SMqAskEpReq req = {0}; + req.consumerId = pTmq->consumerId; + req.epoch = pTmq->epoch; + strcpy(req.cgroup, pTmq->groupId); + + int32_t tlen = tSerializeSMqAskEpReq(NULL, 0, &req); + if (tlen < 0) { + tscError("consumer:0x%" PRIx64 ", tSerializeSMqAskEpReq failed", pTmq->consumerId); + askEpFn(pTmq, TSDB_CODE_INVALID_PARA, NULL, param); + return; + } + + void* pReq = taosMemoryCalloc(1, tlen); + if (pReq == NULL) { + tscError("consumer:0x%" PRIx64 ", failed to malloc askEpReq msg, size:%d", pTmq->consumerId, tlen); + askEpFn(pTmq, TSDB_CODE_OUT_OF_MEMORY, NULL, param); + return; + } + + if (tSerializeSMqAskEpReq(pReq, tlen, &req) < 0) { + tscError("consumer:0x%" PRIx64 ", tSerializeSMqAskEpReq %d failed", pTmq->consumerId, tlen); + taosMemoryFree(pReq); + + askEpFn(pTmq, TSDB_CODE_INVALID_PARA, NULL, param); + return; + } + + SMqAskEpCbParam* pParam = taosMemoryCalloc(1, sizeof(SMqAskEpCbParam)); + if (pParam == NULL) { + tscError("consumer:0x%" PRIx64 ", failed to malloc subscribe param", pTmq->consumerId); + taosMemoryFree(pReq); + + askEpFn(pTmq, TSDB_CODE_OUT_OF_MEMORY, NULL, param); + return; + } + + pParam->refId = pTmq->refId; + pParam->epoch = pTmq->epoch; + pParam->pUserFn = askEpFn; + pParam->pParam = param; + + SMsgSendInfo* sendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); + if (sendInfo == NULL) { + taosMemoryFree(pParam); + taosMemoryFree(pReq); + askEpFn(pTmq, TSDB_CODE_OUT_OF_MEMORY, NULL, param); + return; + } + + sendInfo->msgInfo = (SDataBuf){.pData = pReq, .len = tlen, .handle = NULL}; + + sendInfo->requestId = generateRequestId(); + sendInfo->requestObjRefId = 0; + sendInfo->param = pParam; + sendInfo->fp = askEpCallbackFn; + sendInfo->msgType = TDMT_MND_TMQ_ASK_EP; + + SEpSet epSet = getEpSet_s(&pTmq->pTscObj->pAppInfo->mgmtEp); + tscDebug("consumer:0x%" PRIx64 " ask ep from mnode, reqId:0x%" PRIx64, pTmq->consumerId, sendInfo->requestId); + + int64_t transporterId = 0; + asyncSendMsgToServer(pTmq->pTscObj->pAppInfo->pTransporter, &epSet, &transporterId, sendInfo); +} + +int32_t makeTopicVgroupKey(char* dst, const char* topicName, int32_t vg) { + return sprintf(dst, "%s:%d", topicName, vg); +} + +int32_t tmqCommitDone(SMqCommitCbParamSet* pParamSet) { + int64_t refId = pParamSet->refId; + + tmq_t* tmq = taosAcquireRef(tmqMgmt.rsetId, refId); + if (tmq == NULL) { + taosMemoryFree(pParamSet); + terrno = TSDB_CODE_TMQ_CONSUMER_CLOSED; + return -1; + } + + // if no more waiting rsp + pParamSet->callbackFn(tmq, pParamSet->code, pParamSet->userParam); + taosMemoryFree(pParamSet); + + taosReleaseRef(tmqMgmt.rsetId, refId); + return 0; +} + +void commitRspCountDown(SMqCommitCbParamSet* pParamSet, int64_t consumerId, const char* pTopic, int32_t vgId) { + int32_t waitingRspNum = atomic_sub_fetch_32(&pParamSet->waitingRspNum, 1); + if (waitingRspNum == 0) { + tscDebug("consumer:0x%" PRIx64 " topic:%s vgId:%d all commit-rsp received, commit completed", consumerId, pTopic, + vgId); + tmqCommitDone(pParamSet); + } else { + tscDebug("consumer:0x%" PRIx64 " topic:%s vgId:%d commit-rsp received, remain:%d", consumerId, pTopic, vgId, + waitingRspNum); + } +} + +SReqResultInfo* tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4) { + SMqRspObj* pRspObj = (SMqRspObj*)res; + pRspObj->resIter++; + + if (pRspObj->resIter < pRspObj->rsp.blockNum) { + SRetrieveTableRsp* pRetrieve = (SRetrieveTableRsp*)taosArrayGetP(pRspObj->rsp.blockData, pRspObj->resIter); + if (pRspObj->rsp.withSchema) { + SSchemaWrapper* pSW = (SSchemaWrapper*)taosArrayGetP(pRspObj->rsp.blockSchema, pRspObj->resIter); + setResSchemaInfo(&pRspObj->resInfo, pSW->pSchema, pSW->nCols); + taosMemoryFreeClear(pRspObj->resInfo.row); + taosMemoryFreeClear(pRspObj->resInfo.pCol); + taosMemoryFreeClear(pRspObj->resInfo.length); + taosMemoryFreeClear(pRspObj->resInfo.convertBuf); + taosMemoryFreeClear(pRspObj->resInfo.convertJson); + } + + setQueryResultFromRsp(&pRspObj->resInfo, pRetrieve, convertUcs4, false); + return &pRspObj->resInfo; + } + + return NULL; +} \ No newline at end of file diff --git a/source/client/src/clientTmqConnector.c b/source/client/src/clientTmqConnector.c index ccfc4980bc13d2c89c5d1be4554098257e7b1d7c..894c51d13c9dd8e4205763893206de7ef86cdf7c 100644 --- a/source/client/src/clientTmqConnector.c +++ b/source/client/src/clientTmqConnector.c @@ -17,6 +17,36 @@ #include "jniCommon.h" #include "taos.h" +int __init_tmq = 0; +jmethodID g_offsetCallback; + +void tmqGlobalMethod(JNIEnv *env) { + // make sure init function executed once + switch (atomic_val_compare_exchange_32(&__init_tmq, 0, 1)) { + case 0: + break; + case 1: + do { + taosMsleep(0); + } while (atomic_load_32(&__init_tmq) == 1); + case 2: + return; + } + + if (g_vm == NULL) { + (*env)->GetJavaVM(env, &g_vm); + } + + jclass offset = (*env)->FindClass(env, "com/taosdata/jdbc/tmq/OffsetWaitCallback"); + jclass g_offsetCallbackClass = (*env)->NewGlobalRef(env, offset); + g_offsetCallback = (*env)->GetMethodID(env, g_offsetCallbackClass, "commitCallbackHandler", "(I)V"); + (*env)->DeleteLocalRef(env, offset); + + atomic_store_32(&__init_tmq, 2); + jniDebug("tmq method register finished"); +} + +// deprecated void commit_cb(tmq_t *tmq, int32_t code, void *param) { JNIEnv *env = NULL; int status = (*g_vm)->GetEnv(g_vm, (void **)&env, JNI_VERSION_1_6); @@ -40,6 +70,28 @@ void commit_cb(tmq_t *tmq, int32_t code, void *param) { env = NULL; } +void consumer_callback(tmq_t *tmq, int32_t code, void *param) { + JNIEnv *env = NULL; + int status = (*g_vm)->GetEnv(g_vm, (void **)&env, JNI_VERSION_1_6); + bool needDetach = false; + if (status < 0) { + if ((*g_vm)->AttachCurrentThread(g_vm, (void **)&env, NULL) != 0) { + return; + } + needDetach = true; + } + + jobject obj = (jobject)param; + (*env)->CallVoidMethod(env, obj, g_offsetCallback, code); + (*env)->DeleteGlobalRef(env, obj); + param = NULL; + + if (needDetach) { + (*g_vm)->DetachCurrentThread(g_vm); + } + env = NULL; +} + JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqConfNewImp(JNIEnv *env, jobject jobj) { tmq_conf_t *conf = tmq_conf_new(); jniGetGlobalMethod(env); @@ -201,6 +253,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitSync(JNI return tmq_commit_sync(tmq, res); } +// deprecated JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitAsync(JNIEnv *env, jobject jobj, jlong jtmq, jlong jres, jobject consumer) { tmq_t *tmq = (tmq_t *)jtmq; @@ -213,6 +266,19 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqCommitAsync(JN tmq_commit_async(tmq, res, commit_cb, consumer); } +JNIEXPORT void JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_consumerCommitAsync(JNIEnv *env, jobject jobj, jlong jtmq, + jlong jres, jobject offset) { + tmqGlobalMethod(env); + tmq_t *tmq = (tmq_t *)jtmq; + if (tmq == NULL) { + jniError("jobj:%p, tmq is closed", jobj); + return; + } + TAOS_RES *res = (TAOS_RES *)jres; + offset = (*env)->NewGlobalRef(env, offset); + tmq_commit_async(tmq, res, consumer_callback, offset); +} + JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_tmqUnsubscribeImp(JNIEnv *env, jobject jobj, jlong jtmq) { tmq_t *tmq = (tmq_t *)jtmq; @@ -295,8 +361,8 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_tmq_TMQConnector_fetchRawBlockImp( TAOS_RES *tres = (TAOS_RES *)res; - void *data; - int32_t numOfRows; + void *data = NULL; + int32_t numOfRows = 0; int error_code = taos_fetch_raw_block(tres, &numOfRows, &data); if (numOfRows == 0) { if (error_code == JNI_SUCCESS) { diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp index a75411a8540c3eeb73e8a56bd392e46a84d66eee..56f68e5972c291c56e29a293be5873460254824f 100644 --- a/source/client/test/clientTests.cpp +++ b/source/client/test/clientTests.cpp @@ -52,15 +52,15 @@ void printResult(TAOS_RES* pRes) { int32_t n = 0; char str[512] = {0}; while ((pRow = taos_fetch_row(pRes)) != NULL) { -// int32_t* length = taos_fetch_lengths(pRes); -// for(int32_t i = 0; i < numOfFields; ++i) { -// printf("(%d):%d " , i, length[i]); -// } -// printf("\n"); -// -// int32_t code = taos_print_row(str, pRow, pFields, numOfFields); -// printf("%s\n", str); -// memset(str, 0, sizeof(str)); + // int32_t* length = taos_fetch_lengths(pRes); + // for(int32_t i = 0; i < numOfFields; ++i) { + // printf("(%d):%d " , i, length[i]); + // } + // printf("\n"); + // + // int32_t code = taos_print_row(str, pRow, pFields, numOfFields); + // printf("%s\n", str); + // memset(str, 0, sizeof(str)); } } @@ -112,7 +112,7 @@ void createNewTable(TAOS* pConn, int32_t index) { } taos_free_result(pRes); - for(int32_t i = 0; i < 2000; i += 20) { + for (int32_t i = 0; i < 100; i += 20) { char sql[1024] = {0}; sprintf(sql, "insert into tu%d values(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)" @@ -131,7 +131,7 @@ void createNewTable(TAOS* pConn, int32_t index) { } } -void *queryThread(void *arg) { +void* queryThread(void* arg) { TAOS* pConn = taos_connect("192.168.0.209", "root", "taosdata", NULL, 0); if (pConn == NULL) { printf("failed to connect to db, reason:%s", taos_errstr(pConn)); @@ -141,9 +141,10 @@ void *queryThread(void *arg) { int64_t el = 0; for (int32_t i = 0; i < 5000000; ++i) { - int64_t st = taosGetTimestampUs(); + int64_t st = taosGetTimestampUs(); TAOS_RES* pRes = taos_query(pConn, - "SELECT _wstart as ts,max(usage_user) FROM benchmarkcpu.host_49 WHERE ts >= 1451618560000 AND ts < 1451622160000 INTERVAL(1m) ;"); + "SELECT _wstart as ts,max(usage_user) FROM benchmarkcpu.host_49 WHERE ts >= " + "1451618560000 AND ts < 1451622160000 INTERVAL(1m) ;"); if (taos_errno(pRes) != 0) { printf("failed, reason:%s\n", taos_errstr(pRes)); } else { @@ -153,15 +154,94 @@ void *queryThread(void *arg) { taos_free_result(pRes); el += (taosGetTimestampUs() - st); if (i % 1000 == 0 && i != 0) { - printf("total:%d, avg time:%.2fms\n", i, el/(double)(i*1000)); + printf("total:%d, avg time:%.2fms\n", i, el / (double)(i * 1000)); + } + } + + taos_close(pConn); + return NULL; +} + +int32_t numOfThreads = 1; + +void tmq_commit_cb_print(tmq_t* pTmq, int32_t code, void* param) { +// printf("auto commit success, code:%d\n", code); +} + +void* doConsumeData(void* param) { + TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); + + tmq_conf_t* conf = tmq_conf_new(); + tmq_conf_set(conf, "enable.auto.commit", "true"); + tmq_conf_set(conf, "auto.commit.interval.ms", "1000"); + tmq_conf_set(conf, "group.id", "cgrpName41"); + tmq_conf_set(conf, "td.connect.user", "root"); + tmq_conf_set(conf, "td.connect.pass", "taosdata"); + tmq_conf_set(conf, "auto.offset.reset", "earliest"); + tmq_conf_set(conf, "experimental.snapshot.enable", "true"); + tmq_conf_set(conf, "msg.with.table.name", "true"); + tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL); + + tmq_t* tmq = tmq_consumer_new(conf, NULL, 0); + tmq_conf_destroy(conf); + + // 创建订阅 topics 列表 + tmq_list_t* topicList = tmq_list_new(); + tmq_list_append(topicList, "topic_t2"); + + // 启动订阅 + tmq_subscribe(tmq, topicList); + + tmq_list_destroy(topicList); + + TAOS_FIELD* fields = NULL; + int32_t numOfFields = 0; + int32_t precision = 0; + int32_t totalRows = 0; + int32_t msgCnt = 0; + int32_t timeout = 25000; + + int32_t count = 0; + + while (1) { + TAOS_RES* pRes = tmq_consumer_poll(tmq, timeout); + if (pRes) { + char buf[1024]; + + const char* topicName = tmq_get_topic_name(pRes); + const char* dbName = tmq_get_db_name(pRes); + int32_t vgroupId = tmq_get_vgroup_id(pRes); + + printf("topic: %s\n", topicName); + printf("db: %s\n", dbName); + printf("vgroup id: %d\n", vgroupId); + + while (1) { + TAOS_ROW row = taos_fetch_row(pRes); + if (row == NULL) { + break; + } + + fields = taos_fetch_fields(pRes); + numOfFields = taos_field_count(pRes); + precision = taos_result_precision(pRes); + taos_print_row(buf, row, fields, numOfFields); + totalRows += 1; + // printf("precision: %d, row content: %s\n", precision, buf); + } + + taos_free_result(pRes); + } else { + break; } } + tmq_consumer_close(tmq); taos_close(pConn); + fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows); return NULL; } -static int32_t numOfThreads = 1; } // namespace int main(int argc, char** argv) { @@ -176,22 +256,21 @@ int main(int argc, char** argv) { return RUN_ALL_TESTS(); } -TEST(testCase, driverInit_Test) { +TEST(clientCase, driverInit_Test) { // taosInitGlobalCfg(); // taos_init(); } -TEST(testCase, connect_Test) { +TEST(clientCase, connect_Test) { taos_options(TSDB_OPTION_CONFIGDIR, "~/first/cfg"); - TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); if (pConn == NULL) { printf("failed to connect to server, reason:%s\n", taos_errstr(NULL)); } taos_close(pConn); } -#if 0 -TEST(testCase, create_user_Test) { + +TEST(clientCase, create_user_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -204,7 +283,7 @@ TEST(testCase, create_user_Test) { taos_close(pConn); } -TEST(testCase, create_account_Test) { +TEST(clientCase, create_account_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -217,7 +296,7 @@ TEST(testCase, create_account_Test) { taos_close(pConn); } -TEST(testCase, drop_account_Test) { +TEST(clientCase, drop_account_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -230,7 +309,7 @@ TEST(testCase, drop_account_Test) { taos_close(pConn); } -TEST(testCase, show_user_Test) { +TEST(clientCase, show_user_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -250,7 +329,7 @@ TEST(testCase, show_user_Test) { taos_close(pConn); } -TEST(testCase, drop_user_Test) { +TEST(clientCase, drop_user_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -263,7 +342,7 @@ TEST(testCase, drop_user_Test) { taos_close(pConn); } -TEST(testCase, show_db_Test) { +TEST(clientCase, show_db_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -282,7 +361,7 @@ TEST(testCase, show_db_Test) { taos_close(pConn); } -TEST(testCase, create_db_Test) { +TEST(clientCase, create_db_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -306,7 +385,7 @@ TEST(testCase, create_db_Test) { taos_close(pConn); } -TEST(testCase, create_dnode_Test) { +TEST(clientCase, create_dnode_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -325,7 +404,7 @@ TEST(testCase, create_dnode_Test) { taos_close(pConn); } -TEST(testCase, drop_dnode_Test) { +TEST(clientCase, drop_dnode_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -349,7 +428,7 @@ TEST(testCase, drop_dnode_Test) { taos_close(pConn); } -TEST(testCase, use_db_test) { +TEST(clientCase, use_db_test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -367,7 +446,7 @@ TEST(testCase, use_db_test) { taos_close(pConn); } -// TEST(testCase, drop_db_test) { +// TEST(clientCase, drop_db_test) { // TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); // assert(pConn != NULL); // @@ -389,7 +468,7 @@ TEST(testCase, use_db_test) { // taos_close(pConn); //} -TEST(testCase, create_stable_Test) { +TEST(clientCase, create_stable_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -413,22 +492,22 @@ TEST(testCase, create_stable_Test) { ASSERT_EQ(numOfFields, 0); taos_free_result(pRes); -// pRes = taos_query(pConn, "create stable if not exists abc1.`123_$^)` (ts timestamp, `abc` int) tags(a int)"); -// if (taos_errno(pRes) != 0) { -// printf("failed to create super table 123_$^), reason:%s\n", taos_errstr(pRes)); -// } -// -// pRes = taos_query(pConn, "use abc1"); -// taos_free_result(pRes); -// pRes = taos_query(pConn, "drop stable `123_$^)`"); -// if (taos_errno(pRes) != 0) { -// printf("failed to drop super table 123_$^), reason:%s\n", taos_errstr(pRes)); -// } + // pRes = taos_query(pConn, "create stable if not exists abc1.`123_$^)` (ts timestamp, `abc` int) tags(a int)"); + // if (taos_errno(pRes) != 0) { + // printf("failed to create super table 123_$^), reason:%s\n", taos_errstr(pRes)); + // } + // + // pRes = taos_query(pConn, "use abc1"); + // taos_free_result(pRes); + // pRes = taos_query(pConn, "drop stable `123_$^)`"); + // if (taos_errno(pRes) != 0) { + // printf("failed to drop super table 123_$^), reason:%s\n", taos_errstr(pRes)); + // } taos_close(pConn); } -TEST(testCase, create_table_Test) { +TEST(clientCase, create_table_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -447,7 +526,7 @@ TEST(testCase, create_table_Test) { taos_close(pConn); } -TEST(testCase, create_ctable_Test) { +TEST(clientCase, create_ctable_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -472,7 +551,7 @@ TEST(testCase, create_ctable_Test) { taos_close(pConn); } -TEST(testCase, show_stable_Test) { +TEST(clientCase, show_stable_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != nullptr); @@ -497,7 +576,7 @@ TEST(testCase, show_stable_Test) { taos_close(pConn); } -TEST(testCase, show_vgroup_Test) { +TEST(clientCase, show_vgroup_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -529,7 +608,7 @@ TEST(testCase, show_vgroup_Test) { taos_close(pConn); } -TEST(testCase, create_multiple_tables) { +TEST(clientCase, create_multiple_tables) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); ASSERT_NE(pConn, nullptr); @@ -588,8 +667,7 @@ TEST(testCase, create_multiple_tables) { for (int32_t i = 0; i < 500; i += 2) { char sql[512] = {0}; - snprintf(sql, tListLen(sql), - "create table t_x_%d using st1 tags(2) t_x_%d using st1 tags(5)", i, i + 1); + snprintf(sql, tListLen(sql), "create table t_x_%d using st1 tags(2) t_x_%d using st1 tags(5)", i, i + 1); TAOS_RES* pres = taos_query(pConn, sql); if (taos_errno(pres) != 0) { printf("failed to create table %d\n, reason:%s", i, taos_errstr(pres)); @@ -600,7 +678,7 @@ TEST(testCase, create_multiple_tables) { taos_close(pConn); } -TEST(testCase, show_table_Test) { +TEST(clientCase, show_table_Test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); assert(pConn != NULL); @@ -623,7 +701,7 @@ TEST(testCase, show_table_Test) { int32_t numOfFields = taos_num_fields(pRes); int32_t count = 0; - char str[512] = {0}; + char str[512] = {0}; while ((pRow = taos_fetch_row(pRes)) != NULL) { int32_t code = taos_print_row(str, pRow, pFields, numOfFields); @@ -634,39 +712,39 @@ TEST(testCase, show_table_Test) { taos_close(pConn); } -//TEST(testCase, drop_stable_Test) { -// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); -// assert(pConn != nullptr); +// TEST(clientCase, drop_stable_Test) { +// TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); +// assert(pConn != nullptr); // -// TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1"); -// if (taos_errno(pRes) != 0) { -// printf("error in creating db, reason:%s\n", taos_errstr(pRes)); -// } -// taos_free_result(pRes); +// TAOS_RES* pRes = taos_query(pConn, "create database if not exists abc1"); +// if (taos_errno(pRes) != 0) { +// printf("error in creating db, reason:%s\n", taos_errstr(pRes)); +// } +// taos_free_result(pRes); // -// pRes = taos_query(pConn, "use abc1"); -// if (taos_errno(pRes) != 0) { -// printf("error in using db, reason:%s\n", taos_errstr(pRes)); -// } -// taos_free_result(pRes); +// pRes = taos_query(pConn, "use abc1"); +// if (taos_errno(pRes) != 0) { +// printf("error in using db, reason:%s\n", taos_errstr(pRes)); +// } +// taos_free_result(pRes); // -// pRes = taos_query(pConn, "drop stable st1"); -// if (taos_errno(pRes) != 0) { -// printf("failed to drop stable, reason:%s\n", taos_errstr(pRes)); -// } +// pRes = taos_query(pConn, "drop stable st1"); +// if (taos_errno(pRes) != 0) { +// printf("failed to drop stable, reason:%s\n", taos_errstr(pRes)); +// } // -// taos_free_result(pRes); -// taos_close(pConn); -//} +// taos_free_result(pRes); +// taos_close(pConn); +// } -TEST(testCase, generated_request_id_test) { +TEST(clientCase, generated_request_id_test) { SHashObj* phash = taosHashInit(10000, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_ENTRY_LOCK); for (int32_t i = 0; i < 50000; ++i) { uint64_t v = generateRequestId(); void* result = taosHashGet(phash, &v, sizeof(v)); if (result != nullptr) { - printf("0x%lx, index:%d\n", v, i); + // printf("0x%llx, index:%d\n", v, i); } assert(result == nullptr); taosHashPut(phash, &v, sizeof(v), NULL, 0); @@ -675,7 +753,7 @@ TEST(testCase, generated_request_id_test) { taosHashCleanup(phash); } -TEST(testCase, insert_test) { +TEST(clientCase, insert_test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); ASSERT_NE(pConn, nullptr); @@ -692,9 +770,8 @@ TEST(testCase, insert_test) { taos_free_result(pRes); taos_close(pConn); } -#endif -TEST(testCase, projection_query_tables) { +TEST(clientCase, projection_query_tables) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); ASSERT_NE(pConn, nullptr); @@ -704,7 +781,7 @@ TEST(testCase, projection_query_tables) { // } // taos_free_result(pRes); - TAOS_RES* pRes = taos_query(pConn, "use abc2"); + TAOS_RES* pRes = taos_query(pConn, "use abc1"); taos_free_result(pRes); pRes = taos_query(pConn, "create stable st1 (ts timestamp, k int) tags(a int)"); @@ -726,7 +803,7 @@ TEST(testCase, projection_query_tables) { } taos_free_result(pRes); - for (int32_t i = 0; i < 2; ++i) { + for (int32_t i = 0; i < 10000; ++i) { printf("create table :%d\n", i); createNewTable(pConn, i); } @@ -752,17 +829,16 @@ TEST(testCase, projection_query_tables) { taos_close(pConn); } -#if 0 -TEST(testCase, tsbs_perf_test) { +TEST(clientCase, tsbs_perf_test) { TdThread qid[20] = {0}; - for(int32_t i = 0; i < numOfThreads; ++i) { + for (int32_t i = 0; i < numOfThreads; ++i) { taosThreadCreate(&qid[i], NULL, queryThread, NULL); } getchar(); } -TEST(testCase, projection_query_stables) { +TEST(clientCase, projection_query_stables) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); ASSERT_NE(pConn, nullptr); @@ -782,15 +858,15 @@ TEST(testCase, projection_query_stables) { char str[512] = {0}; while ((pRow = taos_fetch_row(pRes)) != NULL) { -// int32_t code = taos_print_row(str, pRow, pFields, numOfFields); -// printf("%s\n", str); + // int32_t code = taos_print_row(str, pRow, pFields, numOfFields); + // printf("%s\n", str); } taos_free_result(pRes); taos_close(pConn); } -TEST(testCase, agg_query_tables) { +TEST(clientCase, agg_query_tables) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); ASSERT_NE(pConn, nullptr); @@ -822,10 +898,11 @@ use test; create table m1(ts timestamp, k int) tags(a int); create table tm0 using m1 tags(1); create table tm1 using m1 tags(2); -insert into tm0 values('2021-1-1 1:1:1.120', 1) ('2021-1-1 1:1:2.9', 2) tm1 values('2021-1-1 1:1:1.120', 11) ('2021-1-1 1:1:2.99', 22); +insert into tm0 values('2021-1-1 1:1:1.120', 1) ('2021-1-1 1:1:2.9', 2) tm1 values('2021-1-1 1:1:1.120', 11) ('2021-1-1 +1:1:2.99', 22); */ -TEST(testCase, async_api_test) { +TEST(clientCase, async_api_test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); ASSERT_NE(pConn, nullptr); @@ -836,7 +913,7 @@ TEST(testCase, async_api_test) { printf("failed, reason:%s\n", taos_errstr(pRes)); } - int32_t n = 0; + int32_t n = 0; TAOS_ROW pRow = NULL; TAOS_FIELD* pFields = taos_fetch_fields(pRes); int32_t numOfFields = taos_num_fields(pRes); @@ -844,8 +921,8 @@ TEST(testCase, async_api_test) { char str[512] = {0}; while ((pRow = taos_fetch_row(pRes)) != NULL) { int32_t* length = taos_fetch_lengths(pRes); - for(int32_t i = 0; i < numOfFields; ++i) { - printf("(%d):%d " , i, length[i]); + for (int32_t i = 0; i < numOfFields; ++i) { + printf("(%d):%d ", i, length[i]); } printf("\n"); @@ -859,7 +936,7 @@ TEST(testCase, async_api_test) { taos_close(pConn); } -TEST(testCase, update_test) { +TEST(clientCase, update_test) { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); ASSERT_NE(pConn, nullptr); @@ -887,14 +964,187 @@ TEST(testCase, update_test) { taos_free_result(pRes); - char s[256] = {0}; - for(int32_t i = 0; i < 17000; ++i) { + char s[256] = {0}; + for (int32_t i = 0; i < 17000; ++i) { sprintf(s, "insert into tup values(now+%da, %d)", i, i); pRes = taos_query(pConn, s); taos_free_result(pRes); } } -#endif +TEST(clientCase, sub_db_test) { + TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); + ASSERT_NE(pConn, nullptr); + + // TAOS_RES* pRes = taos_query(pConn, "create topic topic_t1 as select * from t1"); + // if (taos_errno(pRes) != TSDB_CODE_SUCCESS) { + // printf("failed to create topic, code:%s", taos_errstr(pRes)); + // taos_free_result(pRes); + // return; + // } + + tmq_conf_t* conf = tmq_conf_new(); + tmq_conf_set(conf, "enable.auto.commit", "true"); + tmq_conf_set(conf, "auto.commit.interval.ms", "1000"); + tmq_conf_set(conf, "group.id", "cgrpNamedb"); + tmq_conf_set(conf, "td.connect.user", "root"); + tmq_conf_set(conf, "td.connect.pass", "taosdata"); + tmq_conf_set(conf, "auto.offset.reset", "earliest"); + tmq_conf_set(conf, "experimental.snapshot.enable", "true"); + tmq_conf_set(conf, "msg.with.table.name", "true"); + tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL); + + tmq_t* tmq = tmq_consumer_new(conf, NULL, 0); + tmq_conf_destroy(conf); + + // 创建订阅 topics 列表 + tmq_list_t* topicList = tmq_list_new(); + tmq_list_append(topicList, "topic_t1"); + tmq_list_append(topicList, "topic_s2"); + + // 启动订阅 + tmq_subscribe(tmq, topicList); + tmq_list_destroy(topicList); + + TAOS_FIELD* fields = NULL; + int32_t numOfFields = 0; + int32_t precision = 0; + int32_t totalRows = 0; + int32_t msgCnt = 0; + int32_t timeout = 5000; + + int32_t count = 0; + + while (1) { + TAOS_RES* pRes = tmq_consumer_poll(tmq, timeout); + if (pRes) { + char buf[1024]; + int32_t rows = 0; + + const char* topicName = tmq_get_topic_name(pRes); + const char* dbName = tmq_get_db_name(pRes); + int32_t vgroupId = tmq_get_vgroup_id(pRes); + + printf("topic: %s\n", topicName); + printf("db: %s\n", dbName); + printf("vgroup id: %d\n", vgroupId); + + if (count++ > 200) { + tmq_unsubscribe(tmq); + break; + } + + while (1) { + TAOS_ROW row = taos_fetch_row(pRes); + if (row == NULL) break; + + fields = taos_fetch_fields(pRes); + numOfFields = taos_field_count(pRes); + precision = taos_result_precision(pRes); + rows++; + taos_print_row(buf, row, fields, numOfFields); + printf("precision: %d, row content: %s\n", precision, buf); + } + taos_free_result(pRes); + } + } + + fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows); +} + +TEST(clientCase, sub_tb_test) { + taos_options(TSDB_OPTION_CONFIGDIR, "~/first/cfg"); + + TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); + ASSERT_NE(pConn, nullptr); + + tmq_conf_t* conf = tmq_conf_new(); + + int32_t ts = taosGetTimestampMs()%INT32_MAX; + char consumerGroupid[128] = {0}; + sprintf(consumerGroupid, "group_id_%d", ts); + + tmq_conf_set(conf, "enable.auto.commit", "true"); + tmq_conf_set(conf, "auto.commit.interval.ms", "2000"); + tmq_conf_set(conf, "group.id", consumerGroupid); + tmq_conf_set(conf, "td.connect.user", "root"); + tmq_conf_set(conf, "td.connect.pass", "taosdata"); + tmq_conf_set(conf, "auto.offset.reset", "earliest"); + tmq_conf_set(conf, "experimental.snapshot.enable", "false"); + tmq_conf_set(conf, "msg.with.table.name", "true"); + tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL); + + tmq_t* tmq = tmq_consumer_new(conf, NULL, 0); + tmq_conf_destroy(conf); + + // 创建订阅 topics 列表 + tmq_list_t* topicList = tmq_list_new(); + tmq_list_append(topicList, "topic_t1"); + + // 启动订阅 + tmq_subscribe(tmq, topicList); + + tmq_list_destroy(topicList); + + TAOS_FIELD* fields = NULL; + int32_t numOfFields = 0; + int32_t precision = 0; + int32_t totalRows = 0; + int32_t msgCnt = 0; + int32_t timeout = 2500000; + + int32_t count = 0; + + while (1) { + TAOS_RES* pRes = tmq_consumer_poll(tmq, timeout); + if (pRes) { + char buf[128]; + + const char* topicName = tmq_get_topic_name(pRes); +// const char* dbName = tmq_get_db_name(pRes); +// int32_t vgroupId = tmq_get_vgroup_id(pRes); +// +// printf("topic: %s\n", topicName); +// printf("db: %s\n", dbName); +// printf("vgroup id: %d\n", vgroupId); + + while (1) { + TAOS_ROW row = taos_fetch_row(pRes); + if (row == NULL) { + break; + } + + fields = taos_fetch_fields(pRes); + numOfFields = taos_field_count(pRes); + totalRows += 1; +// if (totalRows % 100000 == 0) { + taos_print_row(buf, row, fields, numOfFields); + printf("row content: %s\n", buf); +// } + } + + taos_free_result(pRes); + } else { + break; + } + } + + tmq_consumer_close(tmq); + taos_close(pConn); + fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows); +} + +TEST(clientCase, sub_tb_mt_test) { + taos_options(TSDB_OPTION_CONFIGDIR, "~/first/cfg"); + TdThread qid[20] = {0}; + + for (int32_t i = 0; i < 1; ++i) { + taosThreadCreate(&qid[i], NULL, doConsumeData, NULL); + } + + for (int32_t i = 0; i < 4; ++i) { + taosThreadJoin(qid[i], NULL); + } +} #pragma GCC diagnostic pop diff --git a/source/client/test/smlTest.cpp b/source/client/test/smlTest.cpp index 54778e87a788190c55fafc0e4d0db732677d795d..1578b8b607f8ea19b4ee3efb7573c054b6c379fc 100644 --- a/source/client/test/smlTest.cpp +++ b/source/client/test/smlTest.cpp @@ -25,7 +25,7 @@ #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wsign-compare" -#include "../src/clientSml.c" +#include "../inc/clientSml.h" #include "taos.h" int main(int argc, char **argv) { @@ -40,15 +40,19 @@ TEST(testCase, smlParseInfluxString_Test) { msgBuf.len = 256; SSmlLineInfo elements = {0}; + SSmlHandle *info = smlBuildSmlInfo(NULL); + info->protocol = TSDB_SML_LINE_PROTOCOL; + info->dataFormat = false; // case 1 char *tmp = "\\,st,t1=3,t2=4,t3=t3 c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64 1626006833639000000 ,32,c=3"; char *sql = (char *)taosMemoryCalloc(256, 1); memcpy(sql, tmp, strlen(tmp) + 1); - int ret = smlParseInfluxString(sql, sql + strlen(sql), &elements, &msgBuf); + int ret = smlParseInfluxString(info, sql, sql + strlen(sql), &elements); ASSERT_EQ(ret, 0); ASSERT_EQ(elements.measure, sql); - ASSERT_EQ(elements.measureLen, strlen(",st")); - ASSERT_EQ(elements.measureTagsLen, strlen(",st,t1=3,t2=4,t3=t3")); + ASSERT_EQ(elements.measureLen, strlen("\\,st")); + ASSERT_EQ(elements.measureEscaped, true); + ASSERT_EQ(elements.measureTagsLen, strlen("\\,st,t1=3,t2=4,t3=t3")); ASSERT_EQ(elements.tags, sql + elements.measureLen + 1); ASSERT_EQ(elements.tagsLen, strlen("t1=3,t2=4,t3=t3")); @@ -58,28 +62,23 @@ TEST(testCase, smlParseInfluxString_Test) { ASSERT_EQ(elements.timestamp, sql + elements.measureTagsLen + 1 + elements.colsLen + 1); ASSERT_EQ(elements.timestampLen, strlen("1626006833639000000")); + taosArrayDestroy(elements.colArray); + elements.colArray = NULL; // case 2 false tmp = "st,t1=3,t2=4,t3=t3 c1=3i64,c3=\"passit hello,c1=2,c2=false,c4=4f64 1626006833639000000"; memcpy(sql, tmp, strlen(tmp) + 1); memset(&elements, 0, sizeof(SSmlLineInfo)); - ret = smlParseInfluxString(sql, sql + strlen(sql), &elements, &msgBuf); + ret = smlParseInfluxString(info, sql, sql + strlen(sql), &elements); ASSERT_NE(ret, 0); - - // case 3 false - tmp = "st, t1=3,t2=4,t3=t3 c1=3i64,c3=\"passit hello,c1=2,c2=false,c4=4f64 1626006833639000000"; - memcpy(sql, tmp, strlen(tmp) + 1); - memset(&elements, 0, sizeof(SSmlLineInfo)); - ret = smlParseInfluxString(sql, sql + strlen(sql), &elements, &msgBuf); - ASSERT_EQ(ret, 0); - ASSERT_EQ(elements.cols, sql + elements.measureTagsLen + 1); - ASSERT_EQ(elements.colsLen, strlen("t1=3,t2=4,t3=t3")); + taosArrayDestroy(elements.colArray); + elements.colArray = NULL; // case 4 tag is null tmp = "st, c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64 1626006833639000000"; memcpy(sql, tmp, strlen(tmp) + 1); memset(&elements, 0, sizeof(SSmlLineInfo)); - ret = smlParseInfluxString(sql, sql + strlen(sql), &elements, &msgBuf); + ret = smlParseInfluxString(info, sql, sql + strlen(sql), &elements); ASSERT_EQ(ret, 0); ASSERT_EQ(elements.measure, sql); ASSERT_EQ(elements.measureLen, strlen("st")); @@ -93,12 +92,14 @@ TEST(testCase, smlParseInfluxString_Test) { ASSERT_EQ(elements.timestamp, sql + elements.measureTagsLen + 1 + elements.colsLen + 1); ASSERT_EQ(elements.timestampLen, strlen("1626006833639000000")); + taosArrayDestroy(elements.colArray); + elements.colArray = NULL; // case 5 tag is null tmp = " st c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64 1626006833639000000 "; memcpy(sql, tmp, strlen(tmp) + 1); memset(&elements, 0, sizeof(SSmlLineInfo)); - ret = smlParseInfluxString(sql, sql + strlen(sql), &elements, &msgBuf); + ret = smlParseInfluxString(info, sql, sql + strlen(sql), &elements); ASSERT_EQ(ret, 0); ASSERT_EQ(elements.measure, sql + 1); ASSERT_EQ(elements.measureLen, strlen("st")); @@ -111,91 +112,123 @@ TEST(testCase, smlParseInfluxString_Test) { ASSERT_EQ(elements.timestamp, sql + 1 + elements.measureTagsLen + 3 + elements.colsLen + 2); ASSERT_EQ(elements.timestampLen, strlen("1626006833639000000")); + taosArrayDestroy(elements.colArray); + elements.colArray = NULL; // case 6 tmp = " st c1=3i64,c3=\"passit hello,c1=2\",c2=false,c4=4f64 "; memcpy(sql, tmp, strlen(tmp) + 1); memset(&elements, 0, sizeof(SSmlLineInfo)); - ret = smlParseInfluxString(sql, sql + strlen(sql), &elements, &msgBuf); + ret = smlParseInfluxString(info, sql, sql + strlen(sql), &elements); ASSERT_EQ(ret, 0); + taosArrayDestroy(elements.colArray); + elements.colArray = NULL; + smlClearForRerun(info); // case 7 tmp = " st , "; memcpy(sql, tmp, strlen(tmp) + 1); memset(&elements, 0, sizeof(SSmlLineInfo)); - ret = smlParseInfluxString(sql, sql + strlen(sql), &elements, &msgBuf); - ASSERT_EQ(ret, 0); + ret = smlParseInfluxString(info, sql, sql + strlen(sql), &elements); + ASSERT_NE(ret, 0); + taosArrayDestroy(elements.colArray); + elements.colArray = NULL; // case 8 false tmp = ", st , "; memcpy(sql, tmp, strlen(tmp) + 1); memset(&elements, 0, sizeof(SSmlLineInfo)); - ret = smlParseInfluxString(sql, sql + strlen(sql), &elements, &msgBuf); + ret = smlParseInfluxString(info, sql, sql + strlen(sql), &elements); ASSERT_NE(ret, 0); + taosArrayDestroy(elements.colArray); + elements.colArray = NULL; + taosMemoryFree(sql); + smlDestroyInfo(info); + } TEST(testCase, smlParseCols_Error_Test) { - const char *data[] = {"c=\"89sd", // binary, nchar - "c=j\"89sd\"", - "c=\"89sd\"k", - "c=u", // bool - "c=truet", - "c=f64", // double - "c=8f64f", - "c=8ef64", - "c=f32", // float - "c=8f32f", - "c=8wef32", - "c=-3.402823466e+39f32", - "c=", // double - "c=8f", - "c=8we", - "c=i8", // tiny int - "c=-8i8f", - "c=8wei8", - "c=-999i8", - "c=u8", // u tiny int - "c=8fu8", - "c=8weu8", - "c=999u8", - "c=-8u8", - "c=i16", // small int - "c=8fi16u", - "c=8wei16", - "c=-67787i16", - "c=u16", // u small int - "c=8u16f", - "c=8weu16", - "c=-9u16", - "c=67787u16", - "c=i32", // int - "c=8i32f", - "c=8wei32", - "c=2147483649i32", - "c=u32", // u int - "c=8u32f", - "c=8weu32", - "c=-4u32", - "c=42949672958u32", - "c=i64", // big int - "c=8i64i", - "c=8wei64", - "c=-9223372036854775809i64", - "c=i", // big int - "c=8fi", - "c=8wei", - "c=9223372036854775808i", - "c=u64", // u big int - "c=8u64f", - "c=8weu64", - "c=-3.402823466e+39u64", - "c=-339u64", - "c=18446744073709551616u64", - "c=1,c=2", - "c=1=2"}; - - SHashObj *dumplicateKey = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + const char *data[] = {"st,t=1 c=\"89sd 1626006833639000000", // binary, nchar + "st,t=1 c=j\"89sd\" 1626006833639000000", + "st,t=1 c=\"89sd\"k 1626006833639000000", + "st,t=1 c=u 1626006833639000000", // bool + "st,t=1 c=truet 1626006833639000000", + "st,t=1 c=f64 1626006833639000000", // double + "st,t=1 c=8f64f 1626006833639000000", + "st,t=1 c=8ef64 1626006833639000000", + "st,t=1 c=f32 1626006833639000000", // float + "st,t=1 c=8f32f 1626006833639000000", + "st,t=1 c=8wef32 1626006833639000000", + "st,t=1 c=-3.402823466e+39f32 1626006833639000000", + "st,t=1 c= 1626006833639000000", // double + "st,t=1 c=8f 1626006833639000000", + "st,t=1 c=8we 1626006833639000000", + "st,t=1 c=i8 1626006833639000000", // tiny int + "st,t=1 c=-8i8f 1626006833639000000", + "st,t=1 c=8wei8 1626006833639000000", + "st,t=1 c=-999i8 1626006833639000000", + "st,t=1 c=u8 1626006833639000000", // u tiny int + "st,t=1 c=8fu8 1626006833639000000", + "st,t=1 c=8weu8 1626006833639000000", + "st,t=1 c=999u8 1626006833639000000", + "st,t=1 c=-8u8 1626006833639000000", + "st,t=1 c=i16 1626006833639000000", // small int + "st,t=1 c=8fi16u 1626006833639000000", + "st,t=1 c=8wei16 1626006833639000000", + "st,t=1 c=-67787i16 1626006833639000000", + "st,t=1 c=u16 1626006833639000000", // u small int + "st,t=1 c=8u16f 1626006833639000000", + "st,t=1 c=8weu16 1626006833639000000", + "st,t=1 c=-9u16 1626006833639000000", + "st,t=1 c=67787u16 1626006833639000000", + "st,t=1 c=i32 1626006833639000000", // int + "st,t=1 c=8i32f 1626006833639000000", + "st,t=1 c=8wei32 1626006833639000000", + "st,t=1 c=2147483649i32 1626006833639000000", + "st,t=1 c=u32 1626006833639000000", // u int + "st,t=1 c=8u32f 1626006833639000000", + "st,t=1 c=8weu32 1626006833639000000", + "st,t=1 c=-4u32 1626006833639000000", + "st,t=1 c=42949672958u32 1626006833639000000", + "st,t=1 c=i64 1626006833639000000", // big int + "st,t=1 c=8i64i 1626006833639000000", + "st,t=1 c=8wei64 1626006833639000000", + "st,t=1 c=-9223372036854775809i64 1626006833639000000", + "st,t=1 c=i 1626006833639000000", // big int + "st,t=1 c=8fi 1626006833639000000", + "st,t=1 c=8wei 1626006833639000000", + "st,t=1 c=9223372036854775808i 1626006833639000000", + "st,t=1 c=u64 1626006833639000000", // u big int + "st,t=1 c=8u64f 1626006833639000000", + "st,t=1 c=8weu64 1626006833639000000", + "st,t=1 c=-3.402823466e+39u64 1626006833639000000", + "st,t=1 c=-339u64 1626006833639000000", + "st,t=1 c=18446744073709551616u64 1626006833639000000", + "st,t=1 c=1=2 1626006833639000000,", + // escape error test + // measure comma,space + "s,t,t=1 c=1 1626006833639000000,", + "s t,t=1 c=1 1626006833639000000,", + //tag key comma,equal,space + "st,t,t=1 c=2 1626006833639000000,", + "st,t=t=1 c=2 1626006833639000000,", + "st,t t=1 c=2 1626006833639000000,", + //tag value comma,equal,space + "st,tt=a,a c=2 1626006833639000000,", + "st,t=t=a a c=2 1626006833639000000,", + "st,t t=a=a c=2 1626006833639000000,", + //field key comma,equal,space + "st,tt=aa c,1=2 1626006833639000000,", + "st,tt=aa c=1=2 1626006833639000000,", + "st,tt=aa c 1=2 1626006833639000000,", + //field value double quote,slash + "st,tt=aa c=\"a\"a\" 1626006833639000000,", + }; + + SSmlHandle *info = smlBuildSmlInfo(NULL); + info->protocol = TSDB_SML_LINE_PROTOCOL; + info->dataFormat = false; for (int i = 0; i < sizeof(data) / sizeof(data[0]); i++) { char msg[256] = {0}; SSmlMsgBuf msgBuf; @@ -204,76 +237,14 @@ TEST(testCase, smlParseCols_Error_Test) { int32_t len = strlen(data[i]); char *sql = (char *)taosMemoryCalloc(256, 1); memcpy(sql, data[i], len + 1); - SArray *cols = taosArrayInit(8, POINTER_BYTES); - int32_t ret = smlParseCols(sql, len, cols, NULL, false, dumplicateKey, &msgBuf); - printf("i:%d\n", i); + SSmlLineInfo elements = {0}; + int32_t ret = smlParseInfluxString(info, sql, sql + len, &elements); +// printf("i:%d\n", i); ASSERT_NE(ret, TSDB_CODE_SUCCESS); - taosHashClear(dumplicateKey); taosMemoryFree(sql); - for (int j = 0; j < taosArrayGetSize(cols); j++) { - void *kv = taosArrayGetP(cols, j); - taosMemoryFree(kv); - } - taosArrayDestroy(cols); + taosArrayDestroy(elements.colArray); } - taosHashCleanup(dumplicateKey); -} - -TEST(testCase, smlParseCols_tag_Test) { - char msg[256] = {0}; - SSmlMsgBuf msgBuf; - msgBuf.buf = msg; - msgBuf.len = 256; - - SArray *cols = taosArrayInit(16, POINTER_BYTES); - ASSERT_NE(cols, nullptr); - SHashObj *dumplicateKey = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); - - const char *data = - "cbin=\"passit " - "helloc\",cnch=L\"iisdfsf\",cbool=false,cf64=4.31f64,cf64_=8.32,cf32=8.23f32,ci8=-34i8,cu8=89u8,ci16=233i16,cu16=" - "898u16,ci32=98289i32,cu32=12323u32,ci64=-89238i64,ci=989i,cu64=8989323u64,cbooltrue=true,cboolt=t,cboolf=f,cnch_" - "=l\"iuwq\""; - int32_t len = strlen(data); - int32_t ret = smlParseCols(data, len, cols, NULL, true, dumplicateKey, &msgBuf); - ASSERT_EQ(ret, TSDB_CODE_SUCCESS); - int32_t size = taosArrayGetSize(cols); - ASSERT_EQ(size, 19); - - // nchar - SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, 0); - ASSERT_EQ(strncasecmp(kv->key, "cbin", 4), 0); - ASSERT_EQ(kv->keyLen, 4); - ASSERT_EQ(kv->type, TSDB_DATA_TYPE_NCHAR); - ASSERT_EQ(kv->length, 15); - ASSERT_EQ(strncasecmp(kv->value, "\"passit", 7), 0); - - // nchar - kv = (SSmlKv *)taosArrayGetP(cols, 3); - ASSERT_EQ(strncasecmp(kv->key, "cf64", 4), 0); - ASSERT_EQ(kv->keyLen, 4); - ASSERT_EQ(kv->type, TSDB_DATA_TYPE_NCHAR); - ASSERT_EQ(kv->length, 7); - ASSERT_EQ(strncasecmp(kv->value, "4.31f64", 7), 0); - - for (int i = 0; i < size; i++) { - void *tmp = taosArrayGetP(cols, i); - taosMemoryFree(tmp); - } - taosArrayClear(cols); - - // test tag is null - data = "t=3e"; - len = 0; - memset(msgBuf.buf, 0, msgBuf.len); - taosHashClear(dumplicateKey); - ret = smlParseCols(data, len, cols, NULL, true, dumplicateKey, &msgBuf); - ASSERT_EQ(ret, TSDB_CODE_SUCCESS); - size = taosArrayGetSize(cols); - ASSERT_EQ(size, 0); - - taosArrayDestroy(cols); - taosHashCleanup(dumplicateKey); + smlDestroyInfo(info); } TEST(testCase, smlParseCols_Test) { @@ -281,202 +252,185 @@ TEST(testCase, smlParseCols_Test) { SSmlMsgBuf msgBuf; msgBuf.buf = msg; msgBuf.len = 256; - - SArray *cols = taosArrayInit(16, POINTER_BYTES); - ASSERT_NE(cols, nullptr); - - SHashObj *dumplicateKey = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); + SSmlHandle *info = smlBuildSmlInfo(NULL); + info->protocol = TSDB_SML_LINE_PROTOCOL; + info->dataFormat = false; + SSmlLineInfo elements = {0}; + info->msgBuf = msgBuf; const char *data = - "cb\\=in=\"pass\\,it " + "st,t=1 cb\\=in=\"pass\\,it " "hello,c=2\",cnch=L\"ii\\=sdfsf\",cbool=false,cf64=4.31f64,cf64_=8.32,cf32=8.23f32,ci8=-34i8,cu8=89u8,ci16=" "233i16,cu16=898u16,ci32=98289i32,cu32=12323u32,ci64=-89238i64,ci=989i,cu64=8989323u64,cbooltrue=true,cboolt=t," - "cboolf=f,cnch_=l\"iuwq\""; + "cboolf=f,cnch_=l\"iuwq\" 1626006833639000000"; int32_t len = strlen(data); char *sql = (char *)taosMemoryCalloc(1024, 1); memcpy(sql, data, len + 1); - int32_t ret = smlParseCols(sql, len, cols, NULL, false, dumplicateKey, &msgBuf); + int32_t ret = smlParseInfluxString(info, sql, sql + len, &elements); ASSERT_EQ(ret, TSDB_CODE_SUCCESS); - int32_t size = taosArrayGetSize(cols); - ASSERT_EQ(size, 19); + int32_t size = taosArrayGetSize(elements.colArray); + ASSERT_EQ(size, 20); // binary - SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, 0); + SSmlKv *kv = (SSmlKv *)taosArrayGet(elements.colArray, 1); ASSERT_EQ(strncasecmp(kv->key, "cb=in", 5), 0); ASSERT_EQ(kv->keyLen, 5); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BINARY); - ASSERT_EQ(kv->length, 17); - ASSERT_EQ(strncasecmp(kv->value, "pass,it ", 8), 0); - taosMemoryFree(kv); + ASSERT_EQ(kv->length, 18); + ASSERT_EQ(kv->keyEscaped, true); + ASSERT_EQ(kv->valueEscaped, false); + ASSERT_EQ(strncasecmp(kv->value, "pass\\,it ", 9), 0); // nchar - kv = (SSmlKv *)taosArrayGetP(cols, 1); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 2); ASSERT_EQ(strncasecmp(kv->key, "cnch", 4), 0); ASSERT_EQ(kv->keyLen, 4); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_NCHAR); - ASSERT_EQ(kv->length, 8); - ASSERT_EQ(strncasecmp(kv->value, "ii=sd", 5), 0); - taosMemoryFree(kv); + ASSERT_EQ(kv->length, 9); + ASSERT_EQ(strncasecmp(kv->value, "ii\\=sd", 5), 0); // bool - kv = (SSmlKv *)taosArrayGetP(cols, 2); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 3); ASSERT_EQ(strncasecmp(kv->key, "cbool", 5), 0); ASSERT_EQ(kv->keyLen, 5); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BOOL); ASSERT_EQ(kv->length, 1); ASSERT_EQ(kv->i, false); - taosMemoryFree(kv); // double - kv = (SSmlKv *)taosArrayGetP(cols, 3); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 4); ASSERT_EQ(strncasecmp(kv->key, "cf64", 4), 0); ASSERT_EQ(kv->keyLen, 4); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_DOUBLE); ASSERT_EQ(kv->length, 8); // ASSERT_EQ(kv->d, 4.31); printf("4.31 = kv->d:%f\n", kv->d); - taosMemoryFree(kv); // float - kv = (SSmlKv *)taosArrayGetP(cols, 4); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 5); ASSERT_EQ(strncasecmp(kv->key, "cf64_", 5), 0); ASSERT_EQ(kv->keyLen, 5); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_DOUBLE); ASSERT_EQ(kv->length, 8); // ASSERT_EQ(kv->f, 8.32); printf("8.32 = kv->d:%f\n", kv->d); - taosMemoryFree(kv); // float - kv = (SSmlKv *)taosArrayGetP(cols, 5); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 6); ASSERT_EQ(strncasecmp(kv->key, "cf32", 4), 0); ASSERT_EQ(kv->keyLen, 4); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_FLOAT); ASSERT_EQ(kv->length, 4); // ASSERT_EQ(kv->f, 8.23); printf("8.23 = kv->f:%f\n", kv->f); - taosMemoryFree(kv); // tiny int - kv = (SSmlKv *)taosArrayGetP(cols, 6); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 7); ASSERT_EQ(strncasecmp(kv->key, "ci8", 3), 0); ASSERT_EQ(kv->keyLen, 3); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_TINYINT); ASSERT_EQ(kv->length, 1); ASSERT_EQ(kv->i, -34); - taosMemoryFree(kv); // unsigned tiny int - kv = (SSmlKv *)taosArrayGetP(cols, 7); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 8); ASSERT_EQ(strncasecmp(kv->key, "cu8", 3), 0); ASSERT_EQ(kv->keyLen, 3); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_UTINYINT); ASSERT_EQ(kv->length, 1); ASSERT_EQ(kv->u, 89); - taosMemoryFree(kv); // small int - kv = (SSmlKv *)taosArrayGetP(cols, 8); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 9); ASSERT_EQ(strncasecmp(kv->key, "ci16", 4), 0); ASSERT_EQ(kv->keyLen, 4); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_SMALLINT); ASSERT_EQ(kv->length, 2); ASSERT_EQ(kv->u, 233); - taosMemoryFree(kv); // unsigned smallint - kv = (SSmlKv *)taosArrayGetP(cols, 9); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 10); ASSERT_EQ(strncasecmp(kv->key, "cu16", 4), 0); ASSERT_EQ(kv->keyLen, 4); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_USMALLINT); ASSERT_EQ(kv->length, 2); ASSERT_EQ(kv->u, 898); - taosMemoryFree(kv); // int - kv = (SSmlKv *)taosArrayGetP(cols, 10); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 11); ASSERT_EQ(strncasecmp(kv->key, "ci32", 4), 0); ASSERT_EQ(kv->keyLen, 4); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_INT); ASSERT_EQ(kv->length, 4); ASSERT_EQ(kv->u, 98289); - taosMemoryFree(kv); // unsigned int - kv = (SSmlKv *)taosArrayGetP(cols, 11); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 12); ASSERT_EQ(strncasecmp(kv->key, "cu32", 4), 0); ASSERT_EQ(kv->keyLen, 4); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_UINT); ASSERT_EQ(kv->length, 4); ASSERT_EQ(kv->u, 12323); - taosMemoryFree(kv); // bigint - kv = (SSmlKv *)taosArrayGetP(cols, 12); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 13); ASSERT_EQ(strncasecmp(kv->key, "ci64", 4), 0); ASSERT_EQ(kv->keyLen, 4); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BIGINT); ASSERT_EQ(kv->length, 8); ASSERT_EQ(kv->i, -89238); - taosMemoryFree(kv); // bigint - kv = (SSmlKv *)taosArrayGetP(cols, 13); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 14); ASSERT_EQ(strncasecmp(kv->key, "ci", 2), 0); ASSERT_EQ(kv->keyLen, 2); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BIGINT); ASSERT_EQ(kv->length, 8); ASSERT_EQ(kv->i, 989); - taosMemoryFree(kv); // unsigned bigint - kv = (SSmlKv *)taosArrayGetP(cols, 14); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 15); ASSERT_EQ(strncasecmp(kv->key, "cu64", 4), 0); ASSERT_EQ(kv->keyLen, 4); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_UBIGINT); ASSERT_EQ(kv->length, 8); ASSERT_EQ(kv->u, 8989323); - taosMemoryFree(kv); // bool - kv = (SSmlKv *)taosArrayGetP(cols, 15); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 16); ASSERT_EQ(strncasecmp(kv->key, "cbooltrue", 9), 0); ASSERT_EQ(kv->keyLen, 9); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BOOL); ASSERT_EQ(kv->length, 1); ASSERT_EQ(kv->i, true); - taosMemoryFree(kv); // bool - kv = (SSmlKv *)taosArrayGetP(cols, 16); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 17); ASSERT_EQ(strncasecmp(kv->key, "cboolt", 6), 0); ASSERT_EQ(kv->keyLen, 6); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BOOL); ASSERT_EQ(kv->length, 1); ASSERT_EQ(kv->i, true); - taosMemoryFree(kv); // bool - kv = (SSmlKv *)taosArrayGetP(cols, 17); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 18); ASSERT_EQ(strncasecmp(kv->key, "cboolf", 6), 0); ASSERT_EQ(kv->keyLen, 6); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_BOOL); ASSERT_EQ(kv->length, 1); ASSERT_EQ(kv->i, false); - taosMemoryFree(kv); // nchar - kv = (SSmlKv *)taosArrayGetP(cols, 18); + kv = (SSmlKv *)taosArrayGet(elements.colArray, 19); ASSERT_EQ(strncasecmp(kv->key, "cnch_", 5), 0); ASSERT_EQ(kv->keyLen, 5); ASSERT_EQ(kv->type, TSDB_DATA_TYPE_NCHAR); ASSERT_EQ(kv->length, 4); ASSERT_EQ(strncasecmp(kv->value, "iuwq", 4), 0); - taosMemoryFree(kv); - taosArrayDestroy(cols); - taosHashCleanup(dumplicateKey); + taosArrayDestroy(elements.colArray); taosMemoryFree(sql); + smlDestroyInfo(info); } TEST(testCase, smlGetTimestampLen_Test) { @@ -515,7 +469,9 @@ TEST(testCase, smlParseNumber_Test) { } TEST(testCase, smlParseTelnetLine_error_Test) { - SSmlHandle *info = smlBuildSmlInfo(NULL, NULL, TSDB_SML_TELNET_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + SSmlHandle *info = smlBuildSmlInfo(NULL); + info->dataFormat = false; + info->protocol = TSDB_SML_TELNET_PROTOCOL; ASSERT_NE(info, nullptr); const char *sql[] = { @@ -532,479 +488,95 @@ TEST(testCase, smlParseTelnetLine_error_Test) { "sys.procs.running 1479496100 42 ", "sys.procs.running 1479496100 42 host= ", "sys.procs.running 1479496100 42or host=web01", - "sys.procs.running 1479496100 true host=web01", - "sys.procs.running 1479496100 \"binary\" host=web01", - "sys.procs.running 1479496100 L\"rfr\" host=web01", +// "sys.procs.running 1479496100 true host=web01", +// "sys.procs.running 1479496100 \"binary\" host=web01", +// "sys.procs.running 1479496100 L\"rfr\" host=web01", "sys.procs.running 1479496100 42 host=web01 cpu= ", - "sys.procs.running 1479496100 42 host=web01 host=w2", "sys.procs.running 1479496100 42 host=web01 host", "sys.procs.running 1479496100 42 host=web01=er", "sys.procs.running 1479496100 42 host= web01", }; for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); i++) { - int ret = smlParseTelnetLine(info, (void *)sql[i], strlen(sql[i])); + SSmlLineInfo elements = {0}; + int ret = smlParseTelnetString(info, (char*)sql[i], (char*)(sql[i] + strlen(sql[i])), &elements); +// printf("i:%d\n", i); ASSERT_NE(ret, 0); } smlDestroyInfo(info); } -TEST(testCase, smlParseTelnetLine_diff_type_Test) { - SSmlHandle *info = smlBuildSmlInfo(NULL, NULL, TSDB_SML_TELNET_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - ASSERT_NE(info, nullptr); - - const char *sql[] = {"sys.procs.running 1479496104000 42 host=web01", - "sys.procs.running 1479496104000 42u8 host=web01", - "appywjnuct 1626006833641 True id=\"appywjnuct_40601_49808_1\" t0=t t1=127i8 " - "id=\"appywjnuct_40601_49808_2\" t2=32767i16 t3=2147483647i32 t4=9223372036854775807i64 " - "t5=11.12345f32 t6=22.123456789f64 t7=\"binaryTagValue\" t8=L\"ncharTagValue\""}; - - int ret = TSDB_CODE_SUCCESS; - for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); i++) { - ret = smlParseTelnetLine(info, (void *)sql[i], strlen(sql[i])); - if (ret != TSDB_CODE_SUCCESS) break; - } - ASSERT_NE(ret, 0); - smlDestroyInfo(info); -} - -TEST(testCase, smlParseTelnetLine_json_error_Test) { - SSmlHandle *info = smlBuildSmlInfo(NULL, NULL, TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); +TEST(testCase, smlParseTelnetLine_Test) { + SSmlHandle *info = smlBuildSmlInfo(NULL); + info->dataFormat = false; + info->protocol = TSDB_SML_TELNET_PROTOCOL; ASSERT_NE(info, nullptr); const char *sql[] = { - "[\n" - " {\n" - " \"metric\": \"sys.cpu.nice\",\n" - " \"timestamp\": 13468464009999333322222223,\n" - " \"value\": 18,\n" - " \"tags\": {\n" - " \"host\": \"web01\",\n" - " \"dc\": \"lga\"\n" - " }\n" - " },\n" - "]", - "[\n" - " {\n" - " \"metric\": \"sys.cpu.nice\",\n" - " \"timestamp\": 1346846400i,\n" - " \"value\": 18,\n" - " \"tags\": {\n" - " \"host\": \"web01\",\n" - " \"dc\": \"lga\"\n" - " }\n" - " },\n" - "]", - "[\n" - " {\n" - " \"metric\": \"sys.cpu.nice\",\n" - " \"timestamp\": 1346846400,\n" - " \"value\": 18,\n" - " \"tags\": {\n" - " \"groupid\": { \n" - " \"value\" : 2,\n" - " \"type\" : \"nchar\"\n" - " },\n" - " \"location\": { \n" - " \"value\" : \"北京\",\n" - " \"type\" : \"binary\"\n" - " },\n" - " \"id\": \"d1001\"\n" - " }\n" - " },\n" - "]", + "twudyr 1626006833641 \"abcd`~!@#$%^&*()_-{[}]|:;<.>?lfjal\" id=twudyr_17102_17825 t0=t t1=127i8 t2=32767i16 t3=2147483647i32 t4=9223372036854775807i64 t5=11.12345f32 t6=22.123456789f64 t7=\"abcd`~!@#$%^&*()_-{[}]|:;<.>?lfjal\" t8=L\"abcd`~!@#$%^&*()_-{[}]|:;<.>?lfjal\"", }; - - int ret = TSDB_CODE_SUCCESS; for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); i++) { - ret = smlParseTelnetLine(info, (void *)sql[i], strlen(sql[i])); - ASSERT_NE(ret, 0); + SSmlLineInfo elements = {0}; + int ret = smlParseTelnetString(info, (char*)sql[i], (char*)(sql[i] + strlen(sql[i])), &elements); +// printf("i:%d\n", i); + ASSERT_EQ(ret, 0); } smlDestroyInfo(info); } -TEST(testCase, smlParseTelnetLine_diff_json_type1_Test) { - SSmlHandle *info = smlBuildSmlInfo(NULL, NULL, TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - ASSERT_NE(info, nullptr); - - const char *sql[] = { - "[\n" - " {\n" - " \"metric\": \"sys.cpu.nice\",\n" - " \"timestamp\": 1346846400,\n" - " \"value\": 18,\n" - " \"tags\": {\n" - " \"host\": \"lga\"\n" - " }\n" - " },\n" - "]", - "[\n" - " {\n" - " \"metric\": \"sys.cpu.nice\",\n" - " \"timestamp\": 1346846400,\n" - " \"value\": 18,\n" - " \"tags\": {\n" - " \"host\": 8\n" - " }\n" - " },\n" - "]", - }; - - int ret = TSDB_CODE_SUCCESS; - for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); i++) { - ret = smlParseTelnetLine(info, (void *)sql[i], strlen(sql[i])); - if (ret != TSDB_CODE_SUCCESS) break; - } - ASSERT_NE(ret, 0); - smlDestroyInfo(info); -} - -TEST(testCase, smlParseTelnetLine_diff_json_type2_Test) { - SSmlHandle *info = smlBuildSmlInfo(NULL, NULL, TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - ASSERT_NE(info, nullptr); - - const char *sql[] = { - "[\n" - " {\n" - " \"metric\": \"sys.cpu.nice\",\n" - " \"timestamp\": 1346846400,\n" - " \"value\": 18,\n" - " \"tags\": {\n" - " \"host\": \"lga\"\n" - " }\n" - " },\n" - "]", - "[\n" - " {\n" - " \"metric\": \"sys.cpu.nice\",\n" - " \"timestamp\": 1346846400,\n" - " \"value\": \"18\",\n" - " \"tags\": {\n" - " \"host\": \"fff\"\n" - " }\n" - " },\n" - "]", - }; - int ret = TSDB_CODE_SUCCESS; - for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); i++) { - ret = smlParseTelnetLine(info, (void *)sql[i], strlen(sql[i])); - if (ret != TSDB_CODE_SUCCESS) break; - } - ASSERT_NE(ret, 0); - smlDestroyInfo(info); -} - -TEST(testCase, sml_col_4096_Test) { - SSmlHandle *info = smlBuildSmlInfo(NULL, NULL, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - ASSERT_NE(info, nullptr); - - const char *sql[] = { - "spgwgvldxv,id=spgwgvldxv_1,t0=f " - "c0=t,c1=t,c2=t,c3=t,c4=t,c5=t,c6=t,c7=t,c8=t,c9=t,c10=t,c11=t,c12=t,c13=t,c14=t,c15=t,c16=t,c17=t,c18=t,c19=t," - "c20=t,c21=t,c22=t,c23=t,c24=t,c25=t,c26=t,c27=t,c28=t,c29=t,c30=t,c31=t,c32=t,c33=t,c34=t,c35=t,c36=t,c37=t,c38=" - "t,c39=t,c40=t,c41=t,c42=t,c43=t,c44=t,c45=t,c46=t,c47=t,c48=t,c49=t,c50=t,c51=t,c52=t,c53=t,c54=t,c55=t,c56=t," - "c57=t,c58=t,c59=t,c60=t,c61=t,c62=t,c63=t,c64=t,c65=t,c66=t,c67=t,c68=t,c69=t,c70=t,c71=t,c72=t,c73=t,c74=t,c75=" - "t,c76=t,c77=t,c78=t,c79=t,c80=t,c81=t,c82=t,c83=t,c84=t,c85=t,c86=t,c87=t,c88=t,c89=t,c90=t,c91=t,c92=t,c93=t," - "c94=t,c95=t,c96=t,c97=t,c98=t,c99=t,c100=t," - "c101=t,c102=t,c103=t,c104=t,c105=t,c106=t,c107=t,c108=t,c109=t,c110=t,c111=t,c112=t,c113=t,c114=t,c115=t,c116=t," - "c117=t,c118=t,c119=t,c120=t,c121=t,c122=t,c123=t,c124=t,c125=t,c126=t,c127=t,c128=t,c129=t,c130=t,c131=t,c132=t," - "c133=t,c134=t,c135=t,c136=t,c137=t,c138=t,c139=t,c140=t,c141=t,c142=t,c143=t,c144=t,c145=t,c146=t,c147=t,c148=t," - "c149=t,c150=t,c151=t,c152=t,c153=t,c154=t,c155=t,c156=t,c157=t,c158=t,c159=t,c160=t,c161=t,c162=t,c163=t,c164=t," - "c165=t,c166=t,c167=t,c168=t,c169=t,c170=t,c171=t,c172=t,c173=t,c174=t,c175=t,c176=t,c177=t,c178=t,c179=t,c180=t," - "c181=t,c182=t,c183=t,c184=t,c185=t,c186=t,c187=t,c188=t,c189=t," - "c190=t,c191=t,c192=t,c193=t,c194=t,c195=t,c196=t,c197=t,c198=t,c199=t,c200=t,c201=t,c202=t,c203=t,c204=t,c205=t," - "c206=t,c207=t,c208=t,c209=t,c210=t,c211=t,c212=t,c213=t,c214=t,c215=t,c216=t,c217=t,c218=t,c219=t,c220=t,c221=t," - "c222=t,c223=t,c224=t,c225=t,c226=t,c227=t,c228=t,c229=t,c230=t,c231=t,c232=t,c233=t,c234=t,c235=t,c236=t,c237=t," - "c238=t,c239=t,c240=t,c241=t,c242=t,c243=t,c244=t,c245=t,c246=t,c247=t,c248=t,c249=t,c250=t,c251=t,c252=t,c253=t," - "c254=t,c255=t,c256=t,c257=t,c258=t,c259=t,c260=t,c261=t,c262=t,c263=t,c264=t,c265=t,c266=t,c267=t,c268=t,c269=t," - "c270=t,c271=t,c272=t,c273=t,c274=t,c275=t,c276=t,c277=t,c278=t," - "c279=t,c280=t,c281=t,c282=t,c283=t,c284=t,c285=t,c286=t,c287=t,c288=t,c289=t,c290=t,c291=t,c292=t,c293=t,c294=t," - "c295=t,c296=t,c297=t,c298=t,c299=t,c300=t,c301=t,c302=t,c303=t,c304=t,c305=t,c306=t,c307=t,c308=t,c309=t,c310=t," - "c311=t,c312=t,c313=t,c314=t,c315=t,c316=t,c317=t,c318=t,c319=t,c320=t,c321=t,c322=t,c323=t,c324=t,c325=t,c326=t," - "c327=t,c328=t,c329=t,c330=t,c331=t,c332=t,c333=t,c334=t,c335=t,c336=t,c337=t,c338=t,c339=t,c340=t,c341=t,c342=t," - "c343=t,c344=t,c345=t,c346=t,c347=t,c348=t,c349=t,c350=t,c351=t,c352=t,c353=t,c354=t,c355=t,c356=t,c357=t,c358=t," - "c359=t,c360=t,c361=t,c362=t,c363=t,c364=t,c365=t,c366=t,c367=t,c368=t,c369=t,c370=t,c371=t,c372=t,c373=t,c374=t," - "c375=t,c376=t,c377=t,c378=t,c379=t,c380=t,c381=t,c382=t,c383=t,c384=t,c385=t,c386=t,c387=t,c388=t,c389=t,c390=t," - "c391=t,c392=t,c393=t,c394=t,c395=t,c396=t,c397=t,c398=t,c399=t,c400=t,c401=t,c402=t,c403=t,c404=t,c405=t,c406=t," - "c407=t,c408=t,c409=t,c410=t,c411=t,c412=t,c413=t,c414=t,c415=t,c416=t,c417=t,c418=t,c419=t,c420=t,c421=t,c422=t," - "c423=t,c424=t,c425=t,c426=t,c427=t,c428=t,c429=t,c430=t,c431=t,c432=t,c433=t,c434=t,c435=t,c436=t,c437=t,c438=t," - "c439=t,c440=t,c441=t,c442=t,c443=t,c444=t,c445=t,c446=t," - "c447=t,c448=t,c449=t,c450=t,c451=t,c452=t,c453=t,c454=t,c455=t,c456=t,c457=t,c458=t,c459=t,c460=t,c461=t,c462=t," - "c463=t,c464=t,c465=t,c466=t,c467=t,c468=t,c469=t,c470=t,c471=t,c472=t,c473=t,c474=t,c475=t,c476=t,c477=t,c478=t," - "c479=t,c480=t,c481=t,c482=t,c483=t,c484=t,c485=t,c486=t,c487=t,c488=t,c489=t,c490=t,c491=t,c492=t,c493=t,c494=t," - "c495=t,c496=t,c497=t,c498=t,c499=t,c500=t,c501=t,c502=t,c503=t,c504=t,c505=t,c506=t,c507=t,c508=t,c509=t,c510=t," - "c511=t,c512=t,c513=t,c514=t,c515=t,c516=t,c517=t,c518=t,c519=t,c520=t,c521=t,c522=t,c523=t,c524=t,c525=t,c526=t," - "c527=t,c528=t,c529=t,c530=t,c531=t,c532=t,c533=t,c534=t,c535=t,c536=t,c537=t,c538=t,c539=t,c540=t,c541=t,c542=t," - "c543=t,c544=t,c545=t,c546=t,c547=t,c548=t,c549=t,c550=t,c551=t,c552=t,c553=t,c554=t,c555=t,c556=t,c557=t,c558=t," - "c559=t,c560=t,c561=t,c562=t,c563=t,c564=t,c565=t,c566=t,c567=t,c568=t,c569=t,c570=t,c571=t,c572=t,c573=t,c574=t," - "c575=t,c576=t,c577=t,c578=t,c579=t,c580=t,c581=t,c582=t,c583=t,c584=t,c585=t,c586=t,c587=t,c588=t,c589=t,c590=t," - "c591=t,c592=t,c593=t,c594=t,c595=t,c596=t,c597=t,c598=t,c599=t,c600=t,c601=t,c602=t,c603=t,c604=t,c605=t,c606=t," - "c607=t,c608=t,c609=t,c610=t,c611=t,c612=t,c613=t,c614=t," - "c615=t,c616=t,c617=t,c618=t,c619=t,c620=t,c621=t,c622=t,c623=t,c624=t,c625=t,c626=t,c627=t,c628=t,c629=t,c630=t," - "c631=t,c632=t,c633=t,c634=t,c635=t,c636=t,c637=t,c638=t,c639=t,c640=t,c641=t,c642=t,c643=t,c644=t,c645=t,c646=t," - "c647=t,c648=t,c649=t,c650=t,c651=t,c652=t,c653=t,c654=t,c655=t,c656=t,c657=t,c658=t,c659=t,c660=t,c661=t,c662=t," - "c663=t,c664=t,c665=t,c666=t,c667=t,c668=t,c669=t,c670=t,c671=t,c672=t,c673=t,c674=t,c675=t,c676=t,c677=t,c678=t," - "c679=t,c680=t,c681=t,c682=t,c683=t,c684=t,c685=t,c686=t,c687=t,c688=t,c689=t,c690=t,c691=t,c692=t,c693=t,c694=t," - "c695=t,c696=t,c697=t,c698=t,c699=t,c700=t,c701=t,c702=t,c703=t,c704=t,c705=t,c706=t,c707=t,c708=t,c709=t,c710=t," - "c711=t,c712=t,c713=t,c714=t,c715=t,c716=t,c717=t,c718=t,c719=t,c720=t,c721=t,c722=t,c723=t,c724=t,c725=t,c726=t," - "c727=t,c728=t,c729=t,c730=t,c731=t,c732=t,c733=t,c734=t,c735=t,c736=t,c737=t,c738=t,c739=t,c740=t,c741=t,c742=t," - "c743=t,c744=t,c745=t,c746=t,c747=t,c748=t,c749=t,c750=t,c751=t,c752=t,c753=t,c754=t,c755=t,c756=t,c757=t,c758=t," - "c759=t,c760=t,c761=t,c762=t,c763=t,c764=t,c765=t,c766=t,c767=t,c768=t,c769=t,c770=t,c771=t,c772=t,c773=t,c774=t," - "c775=t,c776=t,c777=t,c778=t,c779=t,c780=t,c781=t,c782=t," - "c783=t,c784=t,c785=t,c786=t,c787=t,c788=t,c789=t,c790=t,c791=t,c792=t,c793=t,c794=t,c795=t,c796=t,c797=t,c798=t," - "c799=t,c800=t,c801=t,c802=t,c803=t,c804=t,c805=t,c806=t,c807=t,c808=t,c809=t,c810=t,c811=t,c812=t,c813=t," - "c814=t,c815=t,c816=t,c817=t,c818=t,c819=t,c820=t,c821=t,c822=t,c823=t,c824=t,c825=t,c826=t,c827=t,c828=t,c829=t," - "c830=t,c831=t,c832=t,c833=t,c834=t,c835=t,c836=t,c837=t,c838=t,c839=t,c840=t,c841=t,c842=t,c843=t,c844=t,c845=t," - "c846=t,c847=t,c848=t,c849=t,c850=t,c851=t,c852=t,c853=t,c854=t,c855=t,c856=t,c857=t,c858=t,c859=t,c860=t,c861=t," - "c862=t," - "c863=t,c864=t,c865=t,c866=t,c867=t,c868=t,c869=t,c870=t,c871=t,c872=t,c873=t,c874=t,c875=t,c876=t,c877=t,c878=t," - "c879=t,c880=t,c881=t,c882=t,c883=t,c884=t,c885=t,c886=t,c887=t,c888=t,c889=t,c890=t,c891=t,c892=t,c893=t,c894=t," - "c895=t,c896=t,c897=t,c898=t,c899=t,c900=t,c901=t,c902=t,c903=t,c904=t,c905=t,c906=t,c907=t,c908=t,c909=t,c910=t," - "c911=t,c912=t,c913=t,c914=t,c915=t,c916=t,c917=t,c918=t,c919=t,c920=t,c921=t,c922=t,c923=t,c924=t,c925=t,c926=t," - "c927=t,c928=t,c929=t,c930=t,c931=t,c932=t,c933=t,c934=t,c935=t,c936=t,c937=t,c938=t,c939=t,c940=t,c941=t,c942=t," - "c943=t,c944=t,c945=t,c946=t,c947=t,c948=t,c949=t,c950=t,c951=t,c952=t,c953=t,c954=t,c955=t,c956=t,c957=t,c958=t," - "c959=t,c960=t,c961=t,c962=t,c963=t,c964=t,c965=t,c966=t,c967=t,c968=t,c969=t,c970=t,c971=t,c972=t,c973=t,c974=t," - "c975=t,c976=t,c977=t,c978=t,c979=t,c980=t,c981=t,c982=t,c983=t,c984=t,c985=t,c986=t,c987=t,c988=t,c989=t,c990=t," - "c991=t,c992=t,c993=t,c994=t,c995=t,c996=t,c997=t,c998=t,c999=t,c1000=t,c1001=t,c1002=t,c1003=t,c1004=t,c1005=t," - "c1006=t,c1007=t,c1008=t,c1009=t,c1010=t,c1011=t,c1012=t,c1013=t,c1014=t,c1015=t,c1016=t,c1017=t,c1018=t,c1019=t," - "c1020=t,c1021=t,c1022=t,c1023=t,c1024=t,c1025=t,c1026=t," - "c1027=t,c1028=t,c1029=t,c1030=t,c1031=t,c1032=t,c1033=t,c1034=t,c1035=t,c1036=t,c1037=t,c1038=t,c1039=t,c1040=t," - "c1041=t,c1042=t,c1043=t,c1044=t,c1045=t,c1046=t,c1047=t,c1048=t,c1049=t,c1050=t,c1051=t,c1052=t,c1053=t,c1054=t," - "c1055=t,c1056=t,c1057=t,c1058=t,c1059=t,c1060=t,c1061=t,c1062=t,c1063=t,c1064=t,c1065=t,c1066=t,c1067=t,c1068=t," - "c1069=t,c1070=t,c1071=t,c1072=t,c1073=t,c1074=t,c1075=t,c1076=t,c1077=t,c1078=t,c1079=t,c1080=t,c1081=t,c1082=t," - "c1083=t,c1084=t,c1085=t,c1086=t,c1087=t,c1088=t,c1089=t,c1090=t,c1091=t,c1092=t,c1093=t,c1094=t,c1095=t,c1096=t," - "c1097=t,c1098=t,c1099=t,c1100=t,c1101=t,c1102=t,c1103=t,c1104=t,c1105=t,c1106=t,c1107=t,c1108=t,c1109=t,c1110=t," - "c1111=t,c1112=t,c1113=t,c1114=t,c1115=t,c1116=t,c1117=t,c1118=t,c1119=t,c1120=t,c1121=t,c1122=t,c1123=t,c1124=t," - "c1125=t,c1126=t,c1127=t,c1128=t,c1129=t,c1130=t,c1131=t,c1132=t,c1133=t,c1134=t,c1135=t,c1136=t,c1137=t,c1138=t," - "c1139=t,c1140=t,c1141=t,c1142=t,c1143=t,c1144=t,c1145=t,c1146=t,c1147=t,c1148=t,c1149=t,c1150=t,c1151=t,c1152=t," - "c1153=t,c1154=t,c1155=t,c1156=t,c1157=t,c1158=t,c1159=t,c1160=t,c1161=t,c1162=t,c1163=t,c1164=t,c1165=t,c1166=t," - "c1167=t,c1168=t,c1169=t,c1170=t,c1171=t,c1172=t,c1173=t," - "c1174=t,c1175=t,c1176=t,c1177=t,c1178=t,c1179=t,c1180=t,c1181=t,c1182=t,c1183=t,c1184=t,c1185=t,c1186=t,c1187=t," - "c1188=t,c1189=t,c1190=t,c1191=t,c1192=t,c1193=t,c1194=t,c1195=t,c1196=t,c1197=t,c1198=t,c1199=t,c1200=t,c1201=t," - "c1202=t,c1203=t,c1204=t,c1205=t,c1206=t,c1207=t,c1208=t,c1209=t,c1210=t,c1211=t,c1212=t,c1213=t,c1214=t,c1215=t," - "c1216=t,c1217=t,c1218=t,c1219=t,c1220=t,c1221=t,c1222=t,c1223=t,c1224=t,c1225=t,c1226=t,c1227=t,c1228=t,c1229=t," - "c1230=t,c1231=t,c1232=t,c1233=t,c1234=t,c1235=t,c1236=t,c1237=t,c1238=t,c1239=t,c1240=t,c1241=t,c1242=t,c1243=t," - "c1244=t,c1245=t,c1246=t,c1247=t,c1248=t,c1249=t,c1250=t,c1251=t,c1252=t,c1253=t,c1254=t,c1255=t,c1256=t,c1257=t," - "c1258=t,c1259=t,c1260=t,c1261=t,c1262=t,c1263=t,c1264=t,c1265=t,c1266=t,c1267=t,c1268=t,c1269=t,c1270=t,c1271=t," - "c1272=t,c1273=t,c1274=t,c1275=t,c1276=t,c1277=t,c1278=t,c1279=t,c1280=t,c1281=t,c1282=t,c1283=t,c1284=t,c1285=t," - "c1286=t,c1287=t,c1288=t,c1289=t,c1290=t,c1291=t,c1292=t,c1293=t,c1294=t,c1295=t,c1296=t,c1297=t,c1298=t,c1299=t," - "c1300=t,c1301=t,c1302=t,c1303=t,c1304=t,c1305=t,c1306=t,c1307=t,c1308=t,c1309=t,c1310=t,c1311=t,c1312=t,c1313=t," - "c1314=t,c1315=t,c1316=t,c1317=t,c1318=t,c1319=t,c1320=t," - "c1321=t,c1322=t,c1323=t,c1324=t,c1325=t,c1326=t,c1327=t,c1328=t,c1329=t,c1330=t,c1331=t,c1332=t,c1333=t,c1334=t," - "c1335=t,c1336=t,c1337=t,c1338=t,c1339=t,c1340=t,c1341=t,c1342=t,c1343=t,c1344=t,c1345=t,c1346=t,c1347=t," - "c1348=t,c1349=t,c1350=t,c1351=t,c1352=t,c1353=t,c1354=t,c1355=t,c1356=t,c1357=t,c1358=t,c1359=t,c1360=t,c1361=t," - "c1362=t,c1363=t,c1364=t,c1365=t,c1366=t,c1367=t,c1368=t,c1369=t,c1370=t,c1371=t,c1372=t,c1373=t,c1374=t,c1375=t," - "c1376=t,c1377=t,c1378=t,c1379=t,c1380=t,c1381=t,c1382=t,c1383=t,c1384=t,c1385=t,c1386=t,c1387=t,c1388=t,c1389=t," - "c1390=t,c1391=t,c1392=t,c1393=t,c1394=t,c1395=t,c1396=t,c1397=t,c1398=t,c1399=t,c1400=t,c1401=t,c1402=t,c1403=t," - "c1404=t,c1405=t,c1406=t,c1407=t,c1408=t,c1409=t,c1410=t,c1411=t,c1412=t,c1413=t,c1414=t,c1415=t,c1416=t,c1417=t," - "c1418=t,c1419=t,c1420=t,c1421=t,c1422=t,c1423=t,c1424=t,c1425=t,c1426=t,c1427=t,c1428=t,c1429=t,c1430=t,c1431=t," - "c1432=t,c1433=t,c1434=t,c1435=t,c1436=t,c1437=t,c1438=t,c1439=t,c1440=t,c1441=t,c1442=t,c1443=t,c1444=t,c1445=t," - "c1446=t,c1447=t,c1448=t,c1449=t,c1450=t,c1451=t,c1452=t,c1453=t,c1454=t,c1455=t,c1456=t,c1457=t,c1458=t,c1459=t," - "c1460=t,c1461=t,c1462=t,c1463=t,c1464=t,c1465=t,c1466=t,c1467=t,c1468=t,c1469=t,c1470=t,c1471=t,c1472=t,c1473=t," - "c1474=t,c1475=t,c1476=t,c1477=t,c1478=t,c1479=t,c1480=t,c1481=t,c1482=t,c1483=t,c1484=t,c1485=t,c1486=t,c1487=t," - "c1488=t,c1489=t,c1490=t,c1491=t,c1492=t,c1493=t,c1494=t," - "c1495=t,c1496=t,c1497=t,c1498=t,c1499=t,c1500=t,c1501=t,c1502=t,c1503=t,c1504=t,c1505=t,c1506=t,c1507=t,c1508=t," - "c1509=t,c1510=t,c1511=t,c1512=t,c1513=t,c1514=t,c1515=t,c1516=t,c1517=t,c1518=t,c1519=t,c1520=t,c1521=t,c1522=t," - "c1523=t,c1524=t,c1525=t,c1526=t,c1527=t,c1528=t,c1529=t,c1530=t,c1531=t,c1532=t,c1533=t,c1534=t,c1535=t,c1536=t," - "c1537=t,c1538=t,c1539=t,c1540=t,c1541=t,c1542=t,c1543=t,c1544=t,c1545=t,c1546=t,c1547=t,c1548=t,c1549=t,c1550=t," - "c1551=t,c1552=t,c1553=t,c1554=t,c1555=t,c1556=t,c1557=t,c1558=t,c1559=t,c1560=t,c1561=t,c1562=t,c1563=t,c1564=t," - "c1565=t,c1566=t,c1567=t,c1568=t,c1569=t,c1570=t,c1571=t,c1572=t,c1573=t,c1574=t,c1575=t,c1576=t,c1577=t,c1578=t," - "c1579=t,c1580=t,c1581=t,c1582=t,c1583=t,c1584=t,c1585=t,c1586=t,c1587=t,c1588=t,c1589=t,c1590=t,c1591=t,c1592=t," - "c1593=t,c1594=t,c1595=t,c1596=t,c1597=t,c1598=t,c1599=t,c1600=t,c1601=t,c1602=t,c1603=t,c1604=t,c1605=t,c1606=t," - "c1607=t,c1608=t,c1609=t,c1610=t,c1611=t,c1612=t,c1613=t,c1614=t,c1615=t,c1616=t,c1617=t,c1618=t,c1619=t,c1620=t," - "c1621=t,c1622=t,c1623=t,c1624=t,c1625=t,c1626=t,c1627=t,c1628=t,c1629=t,c1630=t,c1631=t,c1632=t,c1633=t,c1634=t," - "c1635=t,c1636=t,c1637=t,c1638=t,c1639=t,c1640=t,c1641=t," - "c1642=t,c1643=t,c1644=t,c1645=t,c1646=t,c1647=t,c1648=t,c1649=t,c1650=t,c1651=t,c1652=t,c1653=t,c1654=t,c1655=t," - "c1656=t,c1657=t,c1658=t,c1659=t,c1660=t,c1661=t,c1662=t,c1663=t,c1664=t,c1665=t,c1666=t,c1667=t,c1668=t,c1669=t," - "c1670=t,c1671=t,c1672=t,c1673=t,c1674=t,c1675=t,c1676=t,c1677=t,c1678=t,c1679=t,c1680=t,c1681=t,c1682=t,c1683=t," - "c1684=t,c1685=t,c1686=t,c1687=t,c1688=t,c1689=t,c1690=t,c1691=t,c1692=t,c1693=t,c1694=t,c1695=t,c1696=t,c1697=t," - "c1698=t,c1699=t,c1700=t,c1701=t,c1702=t,c1703=t,c1704=t,c1705=t,c1706=t,c1707=t,c1708=t,c1709=t,c1710=t,c1711=t," - "c1712=t,c1713=t,c1714=t,c1715=t,c1716=t,c1717=t,c1718=t,c1719=t,c1720=t,c1721=t,c1722=t,c1723=t,c1724=t,c1725=t," - "c1726=t,c1727=t,c1728=t,c1729=t,c1730=t,c1731=t,c1732=t,c1733=t,c1734=t,c1735=t,c1736=t,c1737=t,c1738=t,c1739=t," - "c1740=t,c1741=t,c1742=t,c1743=t,c1744=t,c1745=t,c1746=t,c1747=t,c1748=t,c1749=t,c1750=t,c1751=t,c1752=t,c1753=t," - "c1754=t,c1755=t,c1756=t,c1757=t,c1758=t,c1759=t,c1760=t,c1761=t,c1762=t,c1763=t,c1764=t,c1765=t,c1766=t,c1767=t," - "c1768=t,c1769=t,c1770=t,c1771=t,c1772=t,c1773=t,c1774=t,c1775=t,c1776=t,c1777=t,c1778=t,c1779=t,c1780=t,c1781=t," - "c1782=t,c1783=t,c1784=t,c1785=t,c1786=t,c1787=t,c1788=t," - "c1789=t,c1790=t,c1791=t,c1792=t,c1793=t,c1794=t,c1795=t,c1796=t,c1797=t,c1798=t,c1799=t,c1800=t,c1801=t,c1802=t," - "c1803=t,c1804=t,c1805=t,c1806=t,c1807=t,c1808=t,c1809=t,c1810=t,c1811=t,c1812=t,c1813=t,c1814=t,c1815=t," - "c1816=t,c1817=t,c1818=t,c1819=t,c1820=t,c1821=t,c1822=t,c1823=t,c1824=t,c1825=t,c1826=t,c1827=t,c1828=t,c1829=t," - "c1830=t,c1831=t,c1832=t,c1833=t,c1834=t,c1835=t,c1836=t,c1837=t,c1838=t,c1839=t,c1840=t,c1841=t,c1842=t,c1843=t," - "c1844=t,c1845=t,c1846=t,c1847=t,c1848=t,c1849=t,c1850=t,c1851=t,c1852=t,c1853=t,c1854=t,c1855=t,c1856=t,c1857=t," - "c1858=t,c1859=t,c1860=t,c1861=t,c1862=t,c1863=t,c1864=t,c1865=t,c1866=t,c1867=t,c1868=t,c1869=t,c1870=t,c1871=t," - "c1872=t,c1873=t,c1874=t,c1875=t,c1876=t,c1877=t,c1878=t,c1879=t,c1880=t,c1881=t,c1882=t,c1883=t,c1884=t,c1885=t," - "c1886=t,c1887=t,c1888=t,c1889=t,c1890=t,c1891=t,c1892=t,c1893=t,c1894=t,c1895=t,c1896=t,c1897=t,c1898=t,c1899=t," - "c1900=t,c1901=t,c1902=t,c1903=t,c1904=t,c1905=t,c1906=t,c1907=t,c1908=t,c1909=t,c1910=t,c1911=t,c1912=t,c1913=t," - "c1914=t,c1915=t,c1916=t,c1917=t,c1918=t,c1919=t,c1920=t,c1921=t,c1922=t,c1923=t,c1924=t,c1925=t,c1926=t,c1927=t," - "c1928=t,c1929=t,c1930=t,c1931=t,c1932=t,c1933=t,c1934=t,c1935=t,c1936=t,c1937=t,c1938=t,c1939=t,c1940=t,c1941=t," - "c1942=t,c1943=t,c1944=t,c1945=t,c1946=t,c1947=t,c1948=t,c1949=t,c1950=t,c1951=t,c1952=t,c1953=t,c1954=t,c1955=t," - "c1956=t,c1957=t,c1958=t,c1959=t,c1960=t,c1961=t,c1962=t," - "c1963=t,c1964=t,c1965=t,c1966=t,c1967=t,c1968=t,c1969=t,c1970=t,c1971=t,c1972=t,c1973=t,c1974=t,c1975=t,c1976=t," - "c1977=t,c1978=t,c1979=t,c1980=t,c1981=t,c1982=t,c1983=t,c1984=t,c1985=t,c1986=t,c1987=t,c1988=t,c1989=t,c1990=t," - "c1991=t,c1992=t,c1993=t,c1994=t,c1995=t,c1996=t,c1997=t,c1998=t,c1999=t,c2000=t,c2001=t,c2002=t,c2003=t,c2004=t," - "c2005=t,c2006=t,c2007=t,c2008=t,c2009=t,c2010=t,c2011=t,c2012=t,c2013=t,c2014=t,c2015=t,c2016=t,c2017=t,c2018=t," - "c2019=t,c2020=t,c2021=t,c2022=t,c2023=t,c2024=t,c2025=t,c2026=t,c2027=t,c2028=t,c2029=t,c2030=t,c2031=t,c2032=t," - "c2033=t,c2034=t,c2035=t,c2036=t,c2037=t,c2038=t,c2039=t,c2040=t,c2041=t,c2042=t,c2043=t,c2044=t,c2045=t,c2046=t," - "c2047=t,c2048=t,c2049=t,c2050=t,c2051=t,c2052=t,c2053=t,c2054=t,c2055=t,c2056=t,c2057=t,c2058=t,c2059=t,c2060=t," - "c2061=t,c2062=t,c2063=t,c2064=t,c2065=t,c2066=t,c2067=t,c2068=t,c2069=t,c2070=t,c2071=t,c2072=t,c2073=t,c2074=t," - "c2075=t,c2076=t,c2077=t,c2078=t,c2079=t,c2080=t,c2081=t,c2082=t,c2083=t,c2084=t,c2085=t,c2086=t,c2087=t,c2088=t," - "c2089=t,c2090=t,c2091=t,c2092=t,c2093=t,c2094=t,c2095=t,c2096=t,c2097=t,c2098=t,c2099=t,c2100=t,c2101=t,c2102=t," - "c2103=t,c2104=t,c2105=t,c2106=t,c2107=t,c2108=t,c2109=t," - "c2110=t,c2111=t,c2112=t,c2113=t,c2114=t,c2115=t,c2116=t,c2117=t,c2118=t,c2119=t,c2120=t,c2121=t,c2122=t,c2123=t," - "c2124=t,c2125=t,c2126=t,c2127=t,c2128=t,c2129=t,c2130=t,c2131=t,c2132=t,c2133=t,c2134=t,c2135=t,c2136=t,c2137=t," - "c2138=t,c2139=t,c2140=t,c2141=t,c2142=t,c2143=t,c2144=t,c2145=t,c2146=t,c2147=t,c2148=t,c2149=t,c2150=t,c2151=t," - "c2152=t,c2153=t,c2154=t,c2155=t,c2156=t,c2157=t,c2158=t,c2159=t,c2160=t,c2161=t,c2162=t,c2163=t,c2164=t,c2165=t," - "c2166=t,c2167=t,c2168=t,c2169=t,c2170=t,c2171=t,c2172=t,c2173=t,c2174=t,c2175=t,c2176=t,c2177=t,c2178=t,c2179=t," - "c2180=t,c2181=t,c2182=t,c2183=t,c2184=t,c2185=t,c2186=t,c2187=t,c2188=t,c2189=t,c2190=t,c2191=t,c2192=t,c2193=t," - "c2194=t,c2195=t,c2196=t,c2197=t,c2198=t,c2199=t,c2200=t,c2201=t,c2202=t,c2203=t,c2204=t,c2205=t,c2206=t,c2207=t," - "c2208=t,c2209=t,c2210=t,c2211=t,c2212=t,c2213=t,c2214=t,c2215=t,c2216=t,c2217=t,c2218=t,c2219=t,c2220=t,c2221=t," - "c2222=t,c2223=t,c2224=t,c2225=t,c2226=t,c2227=t,c2228=t,c2229=t,c2230=t,c2231=t,c2232=t,c2233=t,c2234=t,c2235=t," - "c2236=t,c2237=t,c2238=t,c2239=t,c2240=t,c2241=t,c2242=t,c2243=t,c2244=t,c2245=t,c2246=t,c2247=t,c2248=t,c2249=t," - "c2250=t,c2251=t,c2252=t,c2253=t,c2254=t,c2255=t,c2256=t," - "c2257=t,c2258=t,c2259=t,c2260=t,c2261=t,c2262=t,c2263=t,c2264=t,c2265=t,c2266=t,c2267=t,c2268=t,c2269=t,c2270=t," - "c2271=t,c2272=t,c2273=t,c2274=t,c2275=t,c2276=t,c2277=t,c2278=t,c2279=t,c2280=t,c2281=t,c2282=t,c2283=t," - "c2284=t,c2285=t,c2286=t,c2287=t,c2288=t,c2289=t,c2290=t,c2291=t,c2292=t,c2293=t,c2294=t,c2295=t,c2296=t,c2297=t," - "c2298=t,c2299=t,c2300=t,c2301=t,c2302=t,c2303=t,c2304=t,c2305=t,c2306=t,c2307=t,c2308=t,c2309=t,c2310=t,c2311=t," - "c2312=t,c2313=t,c2314=t,c2315=t,c2316=t,c2317=t,c2318=t,c2319=t,c2320=t,c2321=t,c2322=t,c2323=t,c2324=t,c2325=t," - "c2326=t,c2327=t,c2328=t,c2329=t,c2330=t,c2331=t,c2332=t,c2333=t,c2334=t,c2335=t,c2336=t,c2337=t,c2338=t,c2339=t," - "c2340=t,c2341=t,c2342=t,c2343=t,c2344=t,c2345=t,c2346=t,c2347=t,c2348=t,c2349=t,c2350=t,c2351=t,c2352=t,c2353=t," - "c2354=t,c2355=t,c2356=t,c2357=t,c2358=t,c2359=t,c2360=t,c2361=t,c2362=t,c2363=t,c2364=t,c2365=t,c2366=t,c2367=t," - "c2368=t,c2369=t,c2370=t,c2371=t,c2372=t,c2373=t,c2374=t,c2375=t,c2376=t,c2377=t,c2378=t,c2379=t,c2380=t,c2381=t," - "c2382=t,c2383=t,c2384=t,c2385=t,c2386=t,c2387=t,c2388=t,c2389=t,c2390=t,c2391=t,c2392=t,c2393=t,c2394=t,c2395=t," - "c2396=t,c2397=t,c2398=t,c2399=t,c2400=t,c2401=t,c2402=t,c2403=t,c2404=t,c2405=t,c2406=t,c2407=t,c2408=t,c2409=t," - "c2410=t,c2411=t,c2412=t,c2413=t,c2414=t,c2415=t,c2416=t,c2417=t,c2418=t,c2419=t,c2420=t,c2421=t,c2422=t,c2423=t," - "c2424=t,c2425=t,c2426=t,c2427=t,c2428=t,c2429=t,c2430=t," - "c2431=t,c2432=t,c2433=t,c2434=t,c2435=t,c2436=t,c2437=t,c2438=t,c2439=t,c2440=t,c2441=t,c2442=t,c2443=t,c2444=t," - "c2445=t,c2446=t,c2447=t,c2448=t,c2449=t,c2450=t,c2451=t,c2452=t,c2453=t,c2454=t,c2455=t,c2456=t,c2457=t,c2458=t," - "c2459=t,c2460=t,c2461=t,c2462=t,c2463=t,c2464=t,c2465=t,c2466=t,c2467=t,c2468=t,c2469=t,c2470=t,c2471=t,c2472=t," - "c2473=t,c2474=t,c2475=t,c2476=t,c2477=t,c2478=t,c2479=t,c2480=t,c2481=t,c2482=t,c2483=t,c2484=t,c2485=t,c2486=t," - "c2487=t,c2488=t,c2489=t,c2490=t,c2491=t,c2492=t,c2493=t,c2494=t,c2495=t,c2496=t,c2497=t,c2498=t,c2499=t,c2500=t," - "c2501=t,c2502=t,c2503=t,c2504=t,c2505=t,c2506=t,c2507=t,c2508=t,c2509=t,c2510=t,c2511=t,c2512=t,c2513=t,c2514=t," - "c2515=t,c2516=t,c2517=t,c2518=t,c2519=t,c2520=t,c2521=t,c2522=t,c2523=t,c2524=t,c2525=t,c2526=t,c2527=t,c2528=t," - "c2529=t,c2530=t,c2531=t,c2532=t,c2533=t,c2534=t,c2535=t,c2536=t,c2537=t,c2538=t,c2539=t,c2540=t,c2541=t,c2542=t," - "c2543=t,c2544=t,c2545=t,c2546=t,c2547=t,c2548=t,c2549=t,c2550=t,c2551=t,c2552=t,c2553=t,c2554=t,c2555=t,c2556=t," - "c2557=t,c2558=t,c2559=t,c2560=t,c2561=t,c2562=t,c2563=t,c2564=t,c2565=t,c2566=t,c2567=t,c2568=t,c2569=t,c2570=t," - "c2571=t,c2572=t,c2573=t,c2574=t,c2575=t,c2576=t,c2577=t," - "c2578=t,c2579=t,c2580=t,c2581=t,c2582=t,c2583=t,c2584=t,c2585=t,c2586=t,c2587=t,c2588=t,c2589=t,c2590=t,c2591=t," - "c2592=t,c2593=t,c2594=t,c2595=t,c2596=t,c2597=t,c2598=t,c2599=t,c2600=t,c2601=t,c2602=t,c2603=t,c2604=t,c2605=t," - "c2606=t,c2607=t,c2608=t,c2609=t,c2610=t,c2611=t,c2612=t,c2613=t,c2614=t,c2615=t,c2616=t,c2617=t,c2618=t,c2619=t," - "c2620=t,c2621=t,c2622=t,c2623=t,c2624=t,c2625=t,c2626=t,c2627=t,c2628=t,c2629=t,c2630=t,c2631=t,c2632=t,c2633=t," - "c2634=t,c2635=t,c2636=t,c2637=t,c2638=t,c2639=t,c2640=t,c2641=t,c2642=t,c2643=t,c2644=t,c2645=t,c2646=t,c2647=t," - "c2648=t,c2649=t,c2650=t,c2651=t,c2652=t,c2653=t,c2654=t,c2655=t,c2656=t,c2657=t,c2658=t,c2659=t,c2660=t,c2661=t," - "c2662=t,c2663=t,c2664=t,c2665=t,c2666=t,c2667=t,c2668=t,c2669=t,c2670=t,c2671=t,c2672=t,c2673=t,c2674=t,c2675=t," - "c2676=t,c2677=t,c2678=t,c2679=t,c2680=t,c2681=t,c2682=t,c2683=t,c2684=t,c2685=t,c2686=t,c2687=t,c2688=t,c2689=t," - "c2690=t,c2691=t,c2692=t,c2693=t,c2694=t,c2695=t,c2696=t,c2697=t,c2698=t,c2699=t,c2700=t,c2701=t,c2702=t,c2703=t," - "c2704=t,c2705=t,c2706=t,c2707=t,c2708=t,c2709=t,c2710=t,c2711=t,c2712=t,c2713=t,c2714=t,c2715=t,c2716=t,c2717=t," - "c2718=t,c2719=t,c2720=t,c2721=t,c2722=t,c2723=t,c2724=t," - "c2725=t,c2726=t,c2727=t,c2728=t,c2729=t,c2730=t,c2731=t,c2732=t,c2733=t,c2734=t,c2735=t,c2736=t,c2737=t,c2738=t," - "c2739=t,c2740=t,c2741=t,c2742=t,c2743=t,c2744=t,c2745=t,c2746=t,c2747=t,c2748=t,c2749=t,c2750=t,c2751=t,c2752=t," - "c2753=t,c2754=t,c2755=t,c2756=t,c2757=t,c2758=t,c2759=t,c2760=t,c2761=t,c2762=t,c2763=t,c2764=t,c2765=t,c2766=t," - "c2767=t,c2768=t,c2769=t,c2770=t,c2771=t,c2772=t,c2773=t,c2774=t,c2775=t,c2776=t,c2777=t,c2778=t,c2779=t,c2780=t," - "c2781=t,c2782=t,c2783=t,c2784=t,c2785=t,c2786=t,c2787=t,c2788=t,c2789=t,c2790=t,c2791=t,c2792=t,c2793=t,c2794=t," - "c2795=t,c2796=t,c2797=t,c2798=t,c2799=t,c2800=t,c2801=t,c2802=t,c2803=t,c2804=t,c2805=t,c2806=t,c2807=t,c2808=t," - "c2809=t,c2810=t,c2811=t,c2812=t,c2813=t,c2814=t,c2815=t,c2816=t,c2817=t,c2818=t,c2819=t,c2820=t,c2821=t,c2822=t," - "c2823=t,c2824=t,c2825=t,c2826=t,c2827=t,c2828=t,c2829=t,c2830=t,c2831=t,c2832=t,c2833=t,c2834=t,c2835=t,c2836=t," - "c2837=t,c2838=t,c2839=t,c2840=t,c2841=t,c2842=t,c2843=t,c2844=t,c2845=t,c2846=t,c2847=t,c2848=t,c2849=t,c2850=t," - "c2851=t,c2852=t,c2853=t,c2854=t,c2855=t,c2856=t,c2857=t,c2858=t,c2859=t,c2860=t,c2861=t,c2862=t,c2863=t,c2864=t," - "c2865=t,c2866=t,c2867=t,c2868=t,c2869=t,c2870=t,c2871=t," - "c2872=t,c2873=t,c2874=t,c2875=t,c2876=t,c2877=t,c2878=t,c2879=t,c2880=t,c2881=t,c2882=t,c2883=t,c2884=t,c2885=t," - "c2886=t,c2887=t,c2888=t,c2889=t,c2890=t,c2891=t,c2892=t,c2893=t,c2894=t,c2895=t,c2896=t,c2897=t,c2898=t,c2899=t," - "c2900=t,c2901=t,c2902=t,c2903=t,c2904=t,c2905=t,c2906=t,c2907=t,c2908=t,c2909=t,c2910=t,c2911=t,c2912=t,c2913=t," - "c2914=t,c2915=t,c2916=t,c2917=t,c2918=t,c2919=t,c2920=t,c2921=t,c2922=t,c2923=t,c2924=t,c2925=t,c2926=t,c2927=t," - "c2928=t,c2929=t,c2930=t,c2931=t,c2932=t,c2933=t,c2934=t,c2935=t,c2936=t,c2937=t,c2938=t,c2939=t,c2940=t,c2941=t," - "c2942=t,c2943=t,c2944=t,c2945=t,c2946=t,c2947=t,c2948=t,c2949=t,c2950=t,c2951=t,c2952=t,c2953=t,c2954=t,c2955=t," - "c2956=t,c2957=t,c2958=t,c2959=t,c2960=t,c2961=t,c2962=t,c2963=t,c2964=t,c2965=t,c2966=t,c2967=t,c2968=t,c2969=t," - "c2970=t,c2971=t,c2972=t,c2973=t,c2974=t,c2975=t,c2976=t,c2977=t,c2978=t,c2979=t,c2980=t,c2981=t,c2982=t,c2983=t," - "c2984=t,c2985=t,c2986=t,c2987=t,c2988=t,c2989=t,c2990=t,c2991=t,c2992=t,c2993=t,c2994=t,c2995=t,c2996=t,c2997=t," - "c2998=t,c2999=t,c3000=t,c3001=t,c3002=t,c3003=t,c3004=t,c3005=t,c3006=t,c3007=t,c3008=t,c3009=t,c3010=t,c3011=t," - "c3012=t,c3013=t,c3014=t,c3015=t,c3016=t,c3017=t,c3018=t," - "c3019=t,c3020=t,c3021=t,c3022=t,c3023=t,c3024=t,c3025=t,c3026=t,c3027=t,c3028=t,c3029=t,c3030=t,c3031=t,c3032=t," - "c3033=t,c3034=t,c3035=t,c3036=t,c3037=t,c3038=t,c3039=t,c3040=t,c3041=t,c3042=t,c3043=t,c3044=t,c3045=t,c3046=t," - "c3047=t,c3048=t,c3049=t,c3050=t,c3051=t,c3052=t,c3053=t,c3054=t,c3055=t,c3056=t,c3057=t,c3058=t,c3059=t,c3060=t," - "c3061=t,c3062=t,c3063=t,c3064=t,c3065=t,c3066=t,c3067=t,c3068=t,c3069=t,c3070=t,c3071=t,c3072=t,c3073=t,c3074=t," - "c3075=t,c3076=t,c3077=t,c3078=t,c3079=t,c3080=t,c3081=t,c3082=t,c3083=t,c3084=t,c3085=t,c3086=t,c3087=t,c3088=t," - "c3089=t,c3090=t,c3091=t,c3092=t,c3093=t,c3094=t,c3095=t,c3096=t,c3097=t,c3098=t,c3099=t,c3100=t,c3101=t,c3102=t," - "c3103=t,c3104=t,c3105=t,c3106=t,c3107=t,c3108=t,c3109=t,c3110=t,c3111=t,c3112=t,c3113=t,c3114=t,c3115=t,c3116=t," - "c3117=t,c3118=t,c3119=t,c3120=t,c3121=t,c3122=t,c3123=t,c3124=t,c3125=t,c3126=t,c3127=t,c3128=t,c3129=t,c3130=t," - "c3131=t,c3132=t,c3133=t,c3134=t,c3135=t,c3136=t,c3137=t,c3138=t,c3139=t,c3140=t,c3141=t,c3142=t,c3143=t,c3144=t," - "c3145=t,c3146=t,c3147=t,c3148=t,c3149=t,c3150=t,c3151=t,c3152=t,c3153=t,c3154=t,c3155=t,c3156=t,c3157=t,c3158=t," - "c3159=t,c3160=t,c3161=t,c3162=t,c3163=t,c3164=t,c3165=t," - "c3166=t,c3167=t,c3168=t,c3169=t,c3170=t,c3171=t,c3172=t,c3173=t,c3174=t,c3175=t,c3176=t,c3177=t,c3178=t,c3179=t," - "c3180=t,c3181=t,c3182=t,c3183=t,c3184=t,c3185=t,c3186=t,c3187=t,c3188=t,c3189=t,c3190=t,c3191=t,c3192=t,c3193=t," - "c3194=t,c3195=t,c3196=t,c3197=t,c3198=t,c3199=t,c3200=t,c3201=t,c3202=t,c3203=t,c3204=t,c3205=t,c3206=t,c3207=t," - "c3208=t,c3209=t,c3210=t,c3211=t,c3212=t,c3213=t,c3214=t,c3215=t,c3216=t,c3217=t,c3218=t,c3219=t,c3220=t,c3221=t," - "c3222=t,c3223=t,c3224=t,c3225=t,c3226=t,c3227=t,c3228=t,c3229=t,c3230=t,c3231=t,c3232=t,c3233=t,c3234=t,c3235=t," - "c3236=t,c3237=t,c3238=t,c3239=t,c3240=t,c3241=t,c3242=t,c3243=t,c3244=t,c3245=t,c3246=t,c3247=t,c3248=t,c3249=t," - "c3250=t,c3251=t,c3252=t,c3253=t,c3254=t,c3255=t,c3256=t,c3257=t,c3258=t,c3259=t,c3260=t,c3261=t,c3262=t,c3263=t," - "c3264=t,c3265=t,c3266=t,c3267=t,c3268=t,c3269=t,c3270=t,c3271=t,c3272=t,c3273=t,c3274=t,c3275=t,c3276=t,c3277=t," - "c3278=t,c3279=t,c3280=t,c3281=t,c3282=t,c3283=t,c3284=t,c3285=t,c3286=t,c3287=t,c3288=t,c3289=t,c3290=t,c3291=t," - "c3292=t,c3293=t,c3294=t,c3295=t,c3296=t,c3297=t,c3298=t,c3299=t,c3300=t,c3301=t,c3302=t,c3303=t,c3304=t,c3305=t," - "c3306=t,c3307=t,c3308=t,c3309=t,c3310=t,c3311=t,c3312=t," - "c3313=t,c3314=t,c3315=t,c3316=t,c3317=t,c3318=t,c3319=t,c3320=t,c3321=t,c3322=t,c3323=t,c3324=t,c3325=t,c3326=t," - "c3327=t,c3328=t,c3329=t,c3330=t,c3331=t,c3332=t,c3333=t,c3334=t,c3335=t,c3336=t,c3337=t,c3338=t,c3339=t,c3340=t," - "c3341=t,c3342=t,c3343=t,c3344=t,c3345=t,c3346=t,c3347=t,c3348=t,c3349=t,c3350=t,c3351=t,c3352=t,c3353=t,c3354=t," - "c3355=t,c3356=t,c3357=t,c3358=t,c3359=t,c3360=t,c3361=t,c3362=t,c3363=t,c3364=t,c3365=t,c3366=t,c3367=t,c3368=t," - "c3369=t,c3370=t,c3371=t,c3372=t,c3373=t,c3374=t,c3375=t,c3376=t,c3377=t,c3378=t,c3379=t,c3380=t,c3381=t,c3382=t," - "c3383=t,c3384=t,c3385=t,c3386=t,c3387=t,c3388=t,c3389=t,c3390=t,c3391=t,c3392=t,c3393=t,c3394=t,c3395=t,c3396=t," - "c3397=t,c3398=t,c3399=t,c3400=t,c3401=t,c3402=t,c3403=t,c3404=t,c3405=t,c3406=t,c3407=t,c3408=t,c3409=t,c3410=t," - "c3411=t,c3412=t,c3413=t,c3414=t,c3415=t,c3416=t,c3417=t,c3418=t,c3419=t,c3420=t,c3421=t,c3422=t,c3423=t,c3424=t," - "c3425=t,c3426=t,c3427=t,c3428=t,c3429=t,c3430=t,c3431=t,c3432=t,c3433=t,c3434=t,c3435=t,c3436=t,c3437=t,c3438=t," - "c3439=t,c3440=t,c3441=t,c3442=t,c3443=t,c3444=t,c3445=t,c3446=t,c3447=t,c3448=t,c3449=t,c3450=t,c3451=t,c3452=t," - "c3453=t,c3454=t,c3455=t,c3456=t,c3457=t,c3458=t,c3459=t," - "c3460=t,c3461=t,c3462=t,c3463=t,c3464=t,c3465=t,c3466=t,c3467=t,c3468=t,c3469=t,c3470=t,c3471=t,c3472=t,c3473=t," - "c3474=t,c3475=t,c3476=t,c3477=t,c3478=t,c3479=t,c3480=t,c3481=t,c3482=t,c3483=t,c3484=t,c3485=t,c3486=t,c3487=t," - "c3488=t,c3489=t,c3490=t,c3491=t,c3492=t,c3493=t,c3494=t,c3495=t,c3496=t,c3497=t,c3498=t,c3499=t,c3500=t,c3501=t," - "c3502=t,c3503=t,c3504=t,c3505=t,c3506=t,c3507=t,c3508=t,c3509=t,c3510=t,c3511=t,c3512=t,c3513=t," - "c3514=t,c3515=t,c3516=t,c3517=t,c3518=t,c3519=t,c3520=t,c3521=t,c3522=t,c3523=t,c3524=t,c3525=t,c3526=t,c3527=t," - "c3528=t,c3529=t,c3530=t,c3531=t,c3532=t,c3533=t,c3534=t,c3535=t,c3536=t,c3537=t,c3538=t,c3539=t,c3540=t,c3541=t," - "c3542=t,c3543=t,c3544=t,c3545=t,c3546=t,c3547=t,c3548=t,c3549=t,c3550=t,c3551=t,c3552=t,c3553=t,c3554=t,c3555=t," - "c3556=t,c3557=t,c3558=t,c3559=t,c3560=t,c3561=t,c3562=t,c3563=t,c3564=t,c3565=t,c3566=t,c3567=t,c3568=t,c3569=t," - "c3570=t,c3571=t,c3572=t,c3573=t,c3574=t,c3575=t,c3576=t,c3577=t,c3578=t,c3579=t,c3580=t,c3581=t,c3582=t,c3583=t," - "c3584=t,c3585=t,c3586=t,c3587=t,c3588=t,c3589=t,c3590=t,c3591=t,c3592=t,c3593=t,c3594=t,c3595=t,c3596=t,c3597=t," - "c3598=t,c3599=t,c3600=t,c3601=t,c3602=t,c3603=t,c3604=t,c3605=t,c3606=t,c3607=t,c3608=t,c3609=t,c3610=t,c3611=t," - "c3612=t,c3613=t,c3614=t,c3615=t,c3616=t,c3617=t,c3618=t,c3619=t,c3620=t,c3621=t,c3622=t,c3623=t,c3624=t,c3625=t," - "c3626=t,c3627=t,c3628=t,c3629=t,c3630=t,c3631=t,c3632=t,c3633=t,c3634=t,c3635=t,c3636=t,c3637=t,c3638=t,c3639=t," - "c3640=t,c3641=t,c3642=t,c3643=t,c3644=t,c3645=t,c3646=t,c3647=t,c3648=t,c3649=t,c3650=t,c3651=t,c3652=t,c3653=t," - "c3654=t,c3655=t,c3656=t,c3657=t,c3658=t,c3659=t,c3660=t," - "c3661=t,c3662=t,c3663=t,c3664=t,c3665=t,c3666=t,c3667=t,c3668=t,c3669=t,c3670=t,c3671=t,c3672=t,c3673=t,c3674=t," - "c3675=t,c3676=t,c3677=t,c3678=t,c3679=t,c3680=t,c3681=t,c3682=t,c3683=t,c3684=t,c3685=t,c3686=t,c3687=t,c3688=t," - "c3689=t,c3690=t,c3691=t,c3692=t,c3693=t,c3694=t,c3695=t,c3696=t,c3697=t,c3698=t,c3699=t,c3700=t,c3701=t,c3702=t," - "c3703=t,c3704=t,c3705=t,c3706=t,c3707=t,c3708=t,c3709=t,c3710=t,c3711=t,c3712=t,c3713=t,c3714=t,c3715=t,c3716=t," - "c3717=t,c3718=t,c3719=t,c3720=t,c3721=t,c3722=t,c3723=t,c3724=t,c3725=t,c3726=t,c3727=t,c3728=t,c3729=t,c3730=t," - "c3731=t,c3732=t,c3733=t,c3734=t,c3735=t,c3736=t,c3737=t,c3738=t,c3739=t,c3740=t,c3741=t,c3742=t,c3743=t,c3744=t," - "c3745=t,c3746=t,c3747=t,c3748=t,c3749=t,c3750=t,c3751=t,c3752=t,c3753=t,c3754=t,c3755=t,c3756=t,c3757=t,c3758=t," - "c3759=t,c3760=t,c3761=t,c3762=t,c3763=t,c3764=t,c3765=t,c3766=t,c3767=t,c3768=t,c3769=t,c3770=t,c3771=t,c3772=t," - "c3773=t,c3774=t,c3775=t,c3776=t,c3777=t,c3778=t,c3779=t,c3780=t,c3781=t,c3782=t,c3783=t,c3784=t,c3785=t,c3786=t," - "c3787=t,c3788=t,c3789=t,c3790=t,c3791=t,c3792=t,c3793=t,c3794=t,c3795=t,c3796=t,c3797=t,c3798=t,c3799=t,c3800=t," - "c3801=t,c3802=t,c3803=t,c3804=t,c3805=t,c3806=t,c3807=t," - "c3808=t,c3809=t,c3810=t,c3811=t,c3812=t,c3813=t,c3814=t,c3815=t,c3816=t,c3817=t,c3818=t,c3819=t,c3820=t,c3821=t," - "c3822=t,c3823=t,c3824=t,c3825=t,c3826=t,c3827=t,c3828=t,c3829=t,c3830=t,c3831=t,c3832=t,c3833=t,c3834=t,c3835=t," - "c3836=t,c3837=t,c3838=t,c3839=t,c3840=t,c3841=t,c3842=t,c3843=t,c3844=t,c3845=t,c3846=t,c3847=t,c3848=t,c3849=t," - "c3850=t,c3851=t,c3852=t,c3853=t,c3854=t,c3855=t,c3856=t,c3857=t,c3858=t,c3859=t,c3860=t,c3861=t,c3862=t,c3863=t," - "c3864=t,c3865=t,c3866=t,c3867=t,c3868=t,c3869=t,c3870=t,c3871=t,c3872=t,c3873=t,c3874=t,c3875=t,c3876=t,c3877=t," - "c3878=t,c3879=t,c3880=t,c3881=t,c3882=t,c3883=t,c3884=t,c3885=t,c3886=t,c3887=t,c3888=t,c3889=t,c3890=t,c3891=t," - "c3892=t,c3893=t,c3894=t,c3895=t,c3896=t,c3897=t,c3898=t,c3899=t,c3900=t,c3901=t,c3902=t,c3903=t,c3904=t,c3905=t," - "c3906=t,c3907=t,c3908=t,c3909=t,c3910=t,c3911=t,c3912=t,c3913=t,c3914=t,c3915=t,c3916=t,c3917=t,c3918=t,c3919=t," - "c3920=t,c3921=t,c3922=t,c3923=t,c3924=t,c3925=t,c3926=t,c3927=t,c3928=t,c3929=t,c3930=t,c3931=t,c3932=t,c3933=t," - "c3934=t,c3935=t,c3936=t,c3937=t,c3938=t,c3939=t,c3940=t,c3941=t,c3942=t,c3943=t,c3944=t,c3945=t,c3946=t,c3947=t," - "c3948=t,c3949=t,c3950=t,c3951=t,c3952=t,c3953=t,c3954=t," - "c3955=t,c3956=t,c3957=t,c3958=t,c3959=t,c3960=t,c3961=t,c3962=t,c3963=t,c3964=t,c3965=t,c3966=t,c3967=t,c3968=t," - "c3969=t,c3970=t,c3971=t,c3972=t,c3973=t,c3974=t,c3975=t,c3976=t,c3977=t,c3978=t,c3979=t,c3980=t,c3981=t,c3982=t," - "c3983=t,c3984=t,c3985=t,c3986=t,c3987=t,c3988=t,c3989=t,c3990=t,c3991=t,c3992=t,c3993=t,c3994=t,c3995=t,c3996=t," - "c3997=t,c3998=t,c3999=t,c4000=t,c4001=t,c4002=t,c4003=t,c4004=t,c4005=t,c4006=t,c4007=t,c4008=t,c4009=t,c4010=t," - "c4011=t,c4012=t,c4013=t,c4014=t,c4015=t,c4016=t,c4017=t,c4018=t,c4019=t,c4020=t,c4021=t,c4022=t,c4023=t,c4024=t," - "c4025=t,c4026=t,c4027=t,c4028=t,c4029=t,c4030=t,c4031=t,c4032=t,c4033=t,c4034=t,c4035=t,c4036=t,c4037=t,c4038=t," - "c4039=t,c4040=t,c4041=t,c4042=t,c4043=t,c4044=t,c4045=t,c4046=t,c4047=t,c4048=t,c4049=t,c4050=t,c4051=t,c4052=t," - "c4053=t,c4054=t,c4055=t,c4056=t,c4057=t,c4058=t,c4059=t,c4060=t,c4061=t,c4062=t,c4063=t,c4064=t,c4065=t,c4066=t," - "c4067=t,c4068=t,c4069=t,c4070=t,c4071=t,c4072=t,c4073=t,c4074=t,c4075=t,c4076=t,c4077=t,c4078=t,c4079=t,c4080=t," - "c4081=t,c4082=t,c4083=t,c4084=t,c4085=t,c4086=t,c4087=t,c4088=t,c4089=t,c4090=t,c4091=t,c4092=t,c4093=t " - "1626006833640000000"}; - - int ret = TSDB_CODE_SUCCESS; - for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); i++) { - ret = smlParseInfluxLine(info, sql[i], strlen(sql[i])); - if (ret != TSDB_CODE_SUCCESS) break; +//TEST(testCase, smlParseTelnetLine_diff_json_type2_Test) { +// SSmlHandle *info = smlBuildSmlInfo(NULL); +// info->protocol = TSDB_SML_JSON_PROTOCOL; +// ASSERT_NE(info, nullptr); +// +// const char *sql[] = { +// "[{\"metric\":\"sys.cpu.nice\",\"timestamp\": 1346846400,\"value\": 18,\"tags\": {\"host\": \"lga\"}},{\"metric\": \"sys.sdfa\",\"timestamp\": 1346846400,\"value\": \"18\",\"tags\": {\"host\": 8932}},]", +// }; +// for (int i = 0; i < sizeof(sql) / sizeof(sql[0]); i++) { +// char *dataPointStart = (char *)sql[i]; +// int8_t offset[4] = {0}; +// while (1) { +// SSmlLineInfo elements = {0}; +// if(offset[0] == 0){ +// smlJsonParseObjFirst(&dataPointStart, &elements, offset); +// }else{ +// smlJsonParseObj(&dataPointStart, &elements, offset); +// } +// if(*dataPointStart == '\0') break; +// +// SArray *tags = smlJsonParseTags(elements.tags, elements.tags + elements.tagsLen); +// size_t num = taosArrayGetSize(tags); +// ASSERT_EQ(num, 1); +// +// taosArrayDestroy(tags); +// } +// } +// smlDestroyInfo(info); +//} + +TEST(testCase, smlParseNumber_performance_Test) { + char msg[256] = {0}; + SSmlMsgBuf msgBuf; + SSmlKv kv; + + char* str[3] = {"2893f64", "2323u32", "93u8"}; + for (int i = 0; i < 3; ++i) { + int64_t t1 = taosGetTimestampUs(); + for (int j = 0; j < 10000000; ++j) { + kv.value = str[i]; + kv.length = strlen(str[i]); + smlParseNumber(&kv, &msgBuf); + } + printf("smlParseNumber:%s cost:%" PRId64, str[i], taosGetTimestampUs() - t1); + printf("\n"); + int64_t t2 = taosGetTimestampUs(); + for (int j = 0; j < 10000000; ++j) { + kv.value = str[i]; + kv.length = strlen(str[i]); + smlParseNumberOld(&kv, &msgBuf); + } + printf("smlParseNumberOld:%s cost:%" PRId64, str[i], taosGetTimestampUs() - t2); + printf("\n\n"); } - ASSERT_NE(ret, 0); - smlDestroyInfo(info); -} +} \ No newline at end of file diff --git a/source/common/src/systable.c b/source/common/src/systable.c index 6c86743b696e23ddcdc403860ecafaeb2caa6448..cd3dd63ef04b56ca1ea933bbb8c3053da8917f4f 100644 --- a/source/common/src/systable.c +++ b/source/common/src/systable.c @@ -33,6 +33,7 @@ static const SSysDbTableSchema dnodesSchema[] = { {.name = "support_vnodes", .bytes = 2, .type = TSDB_DATA_TYPE_SMALLINT, .sysInfo = true}, {.name = "status", .bytes = 10 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, {.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = true}, + {.name = "reboot_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = true}, {.name = "note", .bytes = 256 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, }; @@ -42,6 +43,7 @@ static const SSysDbTableSchema mnodesSchema[] = { {.name = "role", .bytes = 12 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, {.name = "status", .bytes = 9 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, {.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = true}, + {.name = "reboot_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = true}, }; static const SSysDbTableSchema modulesSchema[] = { @@ -112,6 +114,9 @@ static const SSysDbTableSchema userFuncSchema[] = { {.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false}, {.name = "code_len", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false}, {.name = "bufsize", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false}, + {.name = "func_language", .bytes = TSDB_TYPE_STR_MAX_LEN - 1 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "func_body", .bytes = TSDB_MAX_BINARY_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "func_version", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false}, }; static const SSysDbTableSchema userIdxSchema[] = { @@ -120,6 +125,8 @@ static const SSysDbTableSchema userIdxSchema[] = { {.name = "table_name", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, {.name = "vgroup_id", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = true}, {.name = "create_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false}, + {.name = "column_name", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "index_type", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, }; static const SSysDbTableSchema userStbsSchema[] = { @@ -178,6 +185,18 @@ static const SSysDbTableSchema userTagsSchema[] = { {.name = "tag_value", .bytes = TSDB_MAX_TAGS_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, }; +static const SSysDbTableSchema userColsSchema[] = { + {.name = "table_name", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "db_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "table_type", .bytes = 21 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "col_name", .bytes = TSDB_COL_NAME_LEN - 1 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "col_type", .bytes = 32 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "col_length", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false}, + {.name = "col_precision", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false}, + {.name = "col_scale", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false}, + {.name = "col_nullable", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false} +}; + static const SSysDbTableSchema userTblDistSchema[] = { {.name = "db_name", .bytes = 32 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, {.name = "table_name", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, @@ -217,7 +236,9 @@ static const SSysDbTableSchema vgroupsSchema[] = { {.name = "v4_dnode", .bytes = 2, .type = TSDB_DATA_TYPE_SMALLINT, .sysInfo = true}, {.name = "v4_status", .bytes = 9 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true}, {.name = "cacheload", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = true}, + {.name = "cacheelements", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = true}, {.name = "tsma", .bytes = 1, .type = TSDB_DATA_TYPE_TINYINT, .sysInfo = true}, + // {.name = "compact_start_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false}, }; static const SSysDbTableSchema smaSchema[] = { @@ -278,7 +299,9 @@ static const SSysDbTableSchema vnodesSchema[] = { static const SSysDbTableSchema userUserPrivilegesSchema[] = { {.name = "user_name", .bytes = TSDB_USER_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, {.name = "privilege", .bytes = 10 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, - {.name = "object_name", .bytes = TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "db_name", .bytes = TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "table_name", .bytes = TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, + {.name = "condition", .bytes = TSDB_PRIVILEDGE_CONDITION_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false}, }; static const SSysTableMeta infosMeta[] = { @@ -294,6 +317,7 @@ static const SSysTableMeta infosMeta[] = { {TSDB_INS_TABLE_STABLES, userStbsSchema, tListLen(userStbsSchema), false}, {TSDB_INS_TABLE_TABLES, userTblsSchema, tListLen(userTblsSchema), false}, {TSDB_INS_TABLE_TAGS, userTagsSchema, tListLen(userTagsSchema), false}, + {TSDB_INS_TABLE_COLS, userColsSchema, tListLen(userColsSchema), false}, // {TSDB_INS_TABLE_TABLE_DISTRIBUTED, userTblDistSchema, tListLen(userTblDistSchema)}, {TSDB_INS_TABLE_USERS, userUsersSchema, tListLen(userUsersSchema), false}, {TSDB_INS_TABLE_LICENCES, grantsSchema, tListLen(grantsSchema), true}, diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index 86dcd1eceb9e26dbf0da4ed02481287e851ceb79..5f7e43668a746a814119e55bfd6bee5736100836 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -19,7 +19,7 @@ #include "tlog.h" #include "tname.h" -#define MALLOC_ALIGN_BYTES 256 +#define MALLOC_ALIGN_BYTES 32 int32_t colDataGetLength(const SColumnInfoData* pColumnInfoData, int32_t numOfRows) { if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) { @@ -37,7 +37,8 @@ int32_t colDataGetFullLength(const SColumnInfoData* pColumnInfoData, int32_t num if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) { return pColumnInfoData->varmeta.length + sizeof(int32_t) * numOfRows; } else { - return ((pColumnInfoData->info.type == TSDB_DATA_TYPE_NULL) ? 0 : pColumnInfoData->info.bytes * numOfRows) + BitmapLen(numOfRows); + return ((pColumnInfoData->info.type == TSDB_DATA_TYPE_NULL) ? 0 : pColumnInfoData->info.bytes * numOfRows) + + BitmapLen(numOfRows); } } @@ -63,13 +64,17 @@ int32_t getJsonValueLen(const char* data) { return dataLen; } -int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, bool isNull) { +int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull) { + return colDataSetVal(pColumnInfoData, rowIndex, pData, isNull); +} + +int32_t colDataSetVal(SColumnInfoData* pColumnInfoData, uint32_t rowIndex, const char* pData, bool isNull) { if (isNull) { // There is a placehold for each NULL value of binary or nchar type. if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) { - pColumnInfoData->varmeta.offset[currentRow] = -1; // it is a null value of VAR type. + pColumnInfoData->varmeta.offset[rowIndex] = -1; // it is a null value of VAR type. } else { - colDataSetNull_f_s(pColumnInfoData, currentRow); + colDataSetNull_f_s(pColumnInfoData, rowIndex); } pColumnInfoData->hasNull = true; @@ -94,6 +99,9 @@ int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, con while (newSize < pAttr->length + dataLen) { newSize = newSize * 1.5; + if (newSize > UINT32_MAX) { + return TSDB_CODE_OUT_OF_MEMORY; + } } char* buf = taosMemoryRealloc(pColumnInfoData->pData, newSize); @@ -106,12 +114,13 @@ int32_t colDataAppend(SColumnInfoData* pColumnInfoData, uint32_t currentRow, con } uint32_t len = pColumnInfoData->varmeta.length; - pColumnInfoData->varmeta.offset[currentRow] = len; + pColumnInfoData->varmeta.offset[rowIndex] = len; memmove(pColumnInfoData->pData + len, pData, dataLen); pColumnInfoData->varmeta.length += dataLen; } else { - memcpy(pColumnInfoData->pData + pColumnInfoData->info.bytes * currentRow, pData, pColumnInfoData->info.bytes); + memcpy(pColumnInfoData->pData + pColumnInfoData->info.bytes * rowIndex, pData, pColumnInfoData->info.bytes); + colDataClearNull_f(pColumnInfoData->nullbitmap, rowIndex); } return 0; @@ -139,9 +148,17 @@ int32_t colDataReserve(SColumnInfoData* pColumnInfoData, size_t newSize) { return TSDB_CODE_SUCCESS; } -static void doCopyNItems(struct SColumnInfoData* pColumnInfoData, int32_t currentRow, const char* pData, - int32_t itemLen, int32_t numOfRows) { - ASSERT(pColumnInfoData->info.bytes >= itemLen); +static int32_t doCopyNItems(struct SColumnInfoData* pColumnInfoData, int32_t currentRow, const char* pData, + int32_t itemLen, int32_t numOfRows, bool trimValue) { + if (pColumnInfoData->info.bytes < itemLen) { + uWarn("column/tag actual data len %d is bigger than schema len %d, trim it:%d", itemLen, pColumnInfoData->info.bytes, trimValue); + if (trimValue) { + itemLen = pColumnInfoData->info.bytes; + } else { + return TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER; + } + } + size_t start = 1; // the first item @@ -170,10 +187,12 @@ static void doCopyNItems(struct SColumnInfoData* pColumnInfoData, int32_t curren pColumnInfoData->varmeta.length += numOfRows * itemLen; } + + return TSDB_CODE_SUCCESS; } -int32_t colDataAppendNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, - uint32_t numOfRows) { +int32_t colDataSetNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRow, const char* pData, + uint32_t numOfRows, bool trimValue) { int32_t len = pColumnInfoData->info.bytes; if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) { len = varDataTLen(pData); @@ -185,8 +204,7 @@ int32_t colDataAppendNItems(SColumnInfoData* pColumnInfoData, uint32_t currentRo } } - doCopyNItems(pColumnInfoData, currentRow, pData, len, numOfRows); - return TSDB_CODE_SUCCESS; + return doCopyNItems(pColumnInfoData, currentRow, pData, len, numOfRows, trimValue); } static void doBitmapMerge(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, const SColumnInfoData* pSource, @@ -204,6 +222,7 @@ static void doBitmapMerge(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, c } uint8_t* p = (uint8_t*)pSource->nullbitmap; + pColumnInfoData->nullbitmap[BitmapLen(numOfRow1) - 1] &= (0B11111111 << shiftBits); // clear remind bits pColumnInfoData->nullbitmap[BitmapLen(numOfRow1) - 1] |= (p[0] >> remindBits); // copy remind bits if (BitmapLen(numOfRow1) == BitmapLen(total)) { @@ -215,6 +234,7 @@ static void doBitmapMerge(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, c uint8_t* start = (uint8_t*)&pColumnInfoData->nullbitmap[BitmapLen(numOfRow1)]; int32_t overCount = BitmapLen(total) - BitmapLen(numOfRow1); + memset(start, 0, overCount); while (i < len) { // size limit of pSource->nullbitmap if (i >= 1) { start[i - 1] |= (p[i] >> remindBits); // copy remind bits @@ -277,7 +297,7 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, int pColumnInfoData->varmeta.allocLen = len + oldLen; } - if (pColumnInfoData->pData && pSource->pData) { // TD-20382 + if (pColumnInfoData->pData && pSource->pData) { // TD-20382 memcpy(pColumnInfoData->pData + oldLen, pSource->pData, len); } pColumnInfoData->varmeta.length = len + oldLen; @@ -292,9 +312,11 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, int pColumnInfoData->pData = tmp; if (BitmapLen(numOfRow1) < BitmapLen(finalNumOfRows)) { char* btmp = taosMemoryRealloc(pColumnInfoData->nullbitmap, BitmapLen(finalNumOfRows)); + if (btmp == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } uint32_t extend = BitmapLen(finalNumOfRows) - BitmapLen(numOfRow1); memset(btmp + BitmapLen(numOfRow1), 0, extend); - pColumnInfoData->nullbitmap = btmp; } @@ -314,8 +336,7 @@ int32_t colDataMergeCol(SColumnInfoData* pColumnInfoData, int32_t numOfRow1, int int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* pSource, int32_t numOfRows, const SDataBlockInfo* pBlockInfo) { - if (pColumnInfoData->info.type != pSource->info.type || - (pBlockInfo != NULL && pBlockInfo->capacity < numOfRows)) { + if (pColumnInfoData->info.type != pSource->info.type || (pBlockInfo != NULL && pBlockInfo->capacity < numOfRows)) { return TSDB_CODE_FAILED; } @@ -356,14 +377,14 @@ size_t blockDataGetNumOfCols(const SSDataBlock* pBlock) { return taosArrayGetSiz size_t blockDataGetNumOfRows(const SSDataBlock* pBlock) { return pBlock->info.rows; } int32_t blockDataUpdateTsWindow(SSDataBlock* pDataBlock, int32_t tsColumnIndex) { - if (pDataBlock->info.rows > 0) { -// ASSERT(pDataBlock->info.dataLoad == 1); - } - if (pDataBlock == NULL || pDataBlock->info.rows <= 0 || pDataBlock->info.dataLoad == 0) { return 0; } + if (pDataBlock->info.rows > 0) { + // ASSERT(pDataBlock->info.dataLoad == 1); + } + size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock); if (numOfCols <= 0) { return -1; @@ -513,10 +534,10 @@ SSDataBlock* blockDataExtractBlock(SSDataBlock* pBlock, int32_t startIndex, int3 } if (isNull) { - colDataAppendNULL(pDstCol, j - startIndex); + colDataSetNULL(pDstCol, j - startIndex); } else { char* p = colDataGetData(pColData, j); - colDataAppend(pDstCol, j - startIndex, p, false); + colDataSetVal(pDstCol, j - startIndex, p, false); } } } @@ -619,6 +640,33 @@ int32_t blockDataFromBuf(SSDataBlock* pBlock, const char* buf) { return TSDB_CODE_SUCCESS; } +static bool colDataIsNNull(const SColumnInfoData* pColumnInfoData, int32_t startIndex, + uint32_t nRows) { + if (!pColumnInfoData->hasNull) { + return false; + } + + if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) { + for (int32_t i = startIndex; i < nRows; ++i) { + if (!colDataIsNull_var(pColumnInfoData, i)) { + return false; + } + } + } else { + if (pColumnInfoData->nullbitmap == NULL) { + return false; + } + + for (int32_t i = startIndex; i < nRows; ++i) { + if (!colDataIsNull_f(pColumnInfoData->nullbitmap, i)) { + return false; + } + } + } + + return true; +} + // todo remove this int32_t blockDataFromBuf1(SSDataBlock* pBlock, const char* buf, size_t capacity) { pBlock->info.rows = *(int32_t*)buf; @@ -661,7 +709,7 @@ int32_t blockDataFromBuf1(SSDataBlock* pBlock, const char* buf, size_t capacity) } } - if (!colDataIsNNull_s(pCol, 0, pBlock->info.rows)) { + if (!colDataIsNNull(pCol, 0, pBlock->info.rows)) { memcpy(pCol->pData, pStart, colLength); } @@ -783,13 +831,13 @@ static int32_t doAssignOneTuple(SColumnInfoData* pDstCols, int32_t numOfRows, co SColumnInfoData* pSrc = taosArrayGet(pSrcBlock->pDataBlock, i); if (pSrc->hasNull && colDataIsNull(pSrc, pSrcBlock->info.rows, tupleIndex, pSrcBlock->pBlockAgg[i])) { - code = colDataAppend(pDst, numOfRows, NULL, true); + code = colDataSetVal(pDst, numOfRows, NULL, true); if (code != TSDB_CODE_SUCCESS) { return code; } } else { char* p = colDataGetData(pSrc, tupleIndex); - code = colDataAppend(pDst, numOfRows, p, false); + code = colDataSetVal(pDst, numOfRows, p, false); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -939,7 +987,7 @@ int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) { taosSort(pColInfoData->pData, pDataBlock->info.rows, pColInfoData->info.bytes, fn); int64_t p1 = taosGetTimestampUs(); - uDebug("blockDataSort easy cost:%" PRId64 ", rows:%d\n", p1 - p0, pDataBlock->info.rows); + uDebug("blockDataSort easy cost:%" PRId64 ", rows:%" PRId64 "\n", p1 - p0, pDataBlock->info.rows); return TSDB_CODE_SUCCESS; } else { // var data type @@ -992,6 +1040,7 @@ int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) { return TSDB_CODE_SUCCESS; } +#if 0 typedef struct SHelper { int32_t index; union { @@ -1033,65 +1082,27 @@ SHelper* createTupleIndex_rv(int32_t numOfRows, SArray* pOrderInfo, SSDataBlock* offset += pInfo->pColData->info.bytes; } + taosMemoryFree(buf); return phelper; } int32_t dataBlockCompar_rv(const void* p1, const void* p2, const void* param) { const SSDataBlockSortHelper* pHelper = (const SSDataBlockSortHelper*)param; - // SSDataBlock* pDataBlock = pHelper->pDataBlock; - SHelper* left = (SHelper*)p1; SHelper* right = (SHelper*)p2; SArray* pInfo = pHelper->orderInfo; int32_t offset = 0; - // for(int32_t i = 0; i < pInfo->size; ++i) { - // SBlockOrderInfo* pOrder = TARRAY_GET_ELEM(pInfo, 0); - // SColumnInfoData* pColInfoData = pOrder->pColData;//TARRAY_GET_ELEM(pDataBlock->pDataBlock, pOrder->colIndex); - - // if (pColInfoData->hasNull) { - // bool leftNull = colDataIsNull(pColInfoData, pDataBlock->info.rows, left, pDataBlock->pBlockAgg); - // bool rightNull = colDataIsNull(pColInfoData, pDataBlock->info.rows, right, pDataBlock->pBlockAgg); - // if (leftNull && rightNull) { - // continue; // continue to next slot - // } - // - // if (rightNull) { - // return pHelper->nullFirst? 1:-1; - // } - // - // if (leftNull) { - // return pHelper->nullFirst? -1:1; - // } - // } - - // void* left1 = colDataGetData(pColInfoData, left); - // void* right1 = colDataGetData(pColInfoData, right); - - // switch(pColInfoData->info.type) { - // case TSDB_DATA_TYPE_INT: { int32_t leftx = *(int32_t*)left->pData; //*(int32_t*)(left->pData + offset); int32_t rightx = *(int32_t*)right->pData; //*(int32_t*)(right->pData + offset); - // offset += pColInfoData->info.bytes; if (leftx == rightx) { - // break; return 0; } else { - // if (pOrder->order == TSDB_ORDER_ASC) { return (leftx < rightx) ? -1 : 1; - // } else { - // return (leftx < rightx)? 1:-1; - // } - } - // } - // default: - // assert(0); - // } - // } - + } return 0; } @@ -1135,6 +1146,7 @@ int32_t blockDataSort_rv(SSDataBlock* pDataBlock, SArray* pOrderInfo, bool nullF // destroyTupleIndex(index); return 0; } +#endif void blockDataCleanup(SSDataBlock* pDataBlock) { blockDataEmpty(pDataBlock); @@ -1145,7 +1157,7 @@ void blockDataCleanup(SSDataBlock* pDataBlock) { void blockDataEmpty(SSDataBlock* pDataBlock) { SDataBlockInfo* pInfo = &pDataBlock->info; - if (pInfo->capacity == 0 || pInfo->rows > pDataBlock->info.capacity) { + if (pInfo->capacity == 0) { return; } @@ -1166,7 +1178,8 @@ void blockDataEmpty(SSDataBlock* pDataBlock) { * the all NULL value in this column. It is an internal representation of all NULL value column, and no visible to * any users. The length of TSDB_DATA_TYPE_NULL is 0, and it is an special case. */ -static int32_t doEnsureCapacity(SColumnInfoData* pColumn, const SDataBlockInfo* pBlockInfo, uint32_t numOfRows, bool clearPayload) { +static int32_t doEnsureCapacity(SColumnInfoData* pColumn, const SDataBlockInfo* pBlockInfo, uint32_t numOfRows, + bool clearPayload) { if (numOfRows <= 0 || numOfRows <= pBlockInfo->capacity) { return TSDB_CODE_SUCCESS; } @@ -1225,7 +1238,7 @@ static int32_t doEnsureCapacity(SColumnInfoData* pColumn, const SDataBlockInfo* return TSDB_CODE_SUCCESS; } -void colInfoDataCleanup(SColumnInfoData* pColumn, uint32_t numOfRows) { +void colInfoDataCleanup(SColumnInfoData* pColumn, uint32_t numOfRows) { pColumn->hasNull = false; if (IS_VAR_DATA_TYPE(pColumn->info.type)) { @@ -1274,7 +1287,6 @@ void blockDataFreeRes(SSDataBlock* pBlock) { taosArrayDestroy(pBlock->pDataBlock); pBlock->pDataBlock = NULL; taosMemoryFreeClear(pBlock->pBlockAgg); - taosMemoryFree(pBlock->info.pTag); memset(&pBlock->info, 0, sizeof(SDataBlockInfo)); } @@ -1413,7 +1425,7 @@ SSDataBlock* blockCopyOneRow(const SSDataBlock* pDataBlock, int32_t rowIdx) { SColumnInfoData* pSrc = taosArrayGet(pDataBlock->pDataBlock, i); void* pData = colDataGetData(pSrc, rowIdx); bool isNull = colDataIsNull(pSrc, pDataBlock->info.rows, rowIdx, NULL); - colDataAppend(pDst, 0, pData, isNull); + colDataSetVal(pDst, 0, pData, isNull); } pBlock->info.rows = 1; @@ -1583,12 +1595,13 @@ static void doShiftBitmap(char* nullBitmap, size_t n, size_t total) { i += 1; } } else if (n > 8) { - int32_t gap = len - newLen; + int32_t remain = (total % 8 != 0 && total % 8 <= tail) ? 1 : 0; + int32_t gap = len - newLen - remain; while (i < newLen) { uint8_t v = p[i + gap]; p[i] = (v << tail); - if (i < newLen - 1) { + if (i < newLen - 1 + remain) { uint8_t next = p[i + gap + 1]; p[i] |= (next >> (8 - tail)); } @@ -1644,7 +1657,7 @@ static void colDataTrimFirstNRows(SColumnInfoData* pColInfoData, size_t n, size_ } } -int32_t blockDataTrimFirstNRows(SSDataBlock* pBlock, size_t n) { +int32_t blockDataTrimFirstRows(SSDataBlock* pBlock, size_t n) { if (n == 0) { return TSDB_CODE_SUCCESS; } @@ -1704,14 +1717,14 @@ int32_t tEncodeDataBlock(void** buf, const SSDataBlock* pBlock) { int64_t tbUid = pBlock->info.id.uid; int16_t numOfCols = taosArrayGetSize(pBlock->pDataBlock); int16_t hasVarCol = pBlock->info.hasVarCol; - int32_t rows = pBlock->info.rows; + int64_t rows = pBlock->info.rows; int32_t sz = taosArrayGetSize(pBlock->pDataBlock); int32_t tlen = 0; tlen += taosEncodeFixedI64(buf, tbUid); tlen += taosEncodeFixedI16(buf, numOfCols); tlen += taosEncodeFixedI16(buf, hasVarCol); - tlen += taosEncodeFixedI32(buf, rows); + tlen += taosEncodeFixedI64(buf, rows); tlen += taosEncodeFixedI32(buf, sz); for (int32_t i = 0; i < sz; i++) { SColumnInfoData* pColData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, i); @@ -1742,7 +1755,7 @@ void* tDecodeDataBlock(const void* buf, SSDataBlock* pBlock) { buf = taosDecodeFixedU64(buf, &pBlock->info.id.uid); buf = taosDecodeFixedI16(buf, &numOfCols); buf = taosDecodeFixedI16(buf, &pBlock->info.hasVarCol); - buf = taosDecodeFixedI32(buf, &pBlock->info.rows); + buf = taosDecodeFixedI64(buf, &pBlock->info.rows); buf = taosDecodeFixedI32(buf, &sz); pBlock->pDataBlock = taosArrayInit(sz, sizeof(SColumnInfoData)); for (int32_t i = 0; i < sz; i++) { @@ -1829,7 +1842,9 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) { } } struct tm ptm = {0}; - taosLocalTime(&tt, &ptm); + if (taosLocalTime(&tt, &ptm, buf) == NULL) { + return buf; + } size_t pos = strftime(buf, 35, "%Y-%m-%d %H:%M:%S", &ptm); if (precision == TSDB_TIME_PRECISION_NANO) { @@ -1843,6 +1858,7 @@ static char* formatTimestamp(char* buf, int64_t val, int precision) { return buf; } +#if 0 void blockDebugShowDataBlock(SSDataBlock* pBlock, const char* flag) { SArray* dataBlocks = taosArrayInit(1, sizeof(SSDataBlock*)); taosArrayPush(dataBlocks, &pBlock); @@ -1854,7 +1870,7 @@ void blockDebugShowDataBlocks(const SArray* dataBlocks, const char* flag) { char pBuf[128] = {0}; int32_t sz = taosArrayGetSize(dataBlocks); for (int32_t i = 0; i < sz; i++) { - SSDataBlock* pDataBlock = taosArrayGetP(dataBlocks, i); + SSDataBlock* pDataBlock = taosArrayGet(dataBlocks, i); size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock); int32_t rows = pDataBlock->info.rows; @@ -1866,21 +1882,37 @@ void blockDebugShowDataBlocks(const SArray* dataBlocks, const char* flag) { for (int32_t k = 0; k < numOfCols; k++) { SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k); void* var = POINTER_SHIFT(pColInfoData->pData, j * pColInfoData->info.bytes); + if (k == 0) { + printf("cols:%d |", (int32_t)numOfCols); + } if (colDataIsNull(pColInfoData, rows, j, NULL)) { printf(" %15s |", "NULL"); continue; } + switch (pColInfoData->info.type) { case TSDB_DATA_TYPE_TIMESTAMP: formatTimestamp(pBuf, *(uint64_t*)var, TSDB_TIME_PRECISION_MILLI); printf(" %25s |", pBuf); break; case TSDB_DATA_TYPE_BOOL: - printf(" %15d |", *(int32_t*)var); + printf(" %15" PRIi8 " |", *(int8_t*)var); + break; + case TSDB_DATA_TYPE_TINYINT: + printf(" %15" PRIi8 " |", *(int8_t*)var); + break; + case TSDB_DATA_TYPE_SMALLINT: + printf(" %15" PRIi16 " |", *(int16_t*)var); break; case TSDB_DATA_TYPE_INT: printf(" %15d |", *(int32_t*)var); break; + case TSDB_DATA_TYPE_UTINYINT: + printf(" %15" PRIu8 " |", *(uint8_t*)var); + break; + case TSDB_DATA_TYPE_USMALLINT: + printf(" %15" PRIu16 " |", *(uint16_t*)var); + break; case TSDB_DATA_TYPE_UINT: printf(" %15u |", *(uint32_t*)var); break; @@ -1918,10 +1950,11 @@ void blockDebugShowDataBlocks(const SArray* dataBlocks, const char* flag) { } } } +#endif // for debug char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf) { - int32_t size = 2048; + int32_t size = 2048*1024; *pDataBuf = taosMemoryCalloc(size, 1); char* dumpBuf = *pDataBuf; char pBuf[128] = {0}; @@ -1930,13 +1963,14 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf) int32_t len = 0; len += snprintf(dumpBuf + len, size - len, "===stream===%s|block type %d|child id %d|group id:%" PRIu64 "|uid:%" PRId64 - "|rows:%d|version:%" PRIu64 "|cal start:%" PRIu64 "|cal end:%" PRIu64 "\n", + "|rows:%" PRId64 "|version:%" PRIu64 "|cal start:%" PRIu64 "|cal end:%" PRIu64 "|tbl:%s\n", flag, (int32_t)pDataBlock->info.type, pDataBlock->info.childId, pDataBlock->info.id.groupId, - pDataBlock->info.id.uid, pDataBlock->info.rows, pDataBlock->info.version, pDataBlock->info.calWin.skey, pDataBlock->info.calWin.ekey); + pDataBlock->info.id.uid, pDataBlock->info.rows, pDataBlock->info.version, + pDataBlock->info.calWin.skey, pDataBlock->info.calWin.ekey, pDataBlock->info.parTbName); if (len >= size - 1) return dumpBuf; for (int32_t j = 0; j < rows; j++) { - len += snprintf(dumpBuf + len, size - len, "%s |", flag); + len += snprintf(dumpBuf + len, size - len, "%s %d|", flag, j); if (len >= size - 1) return dumpBuf; for (int32_t k = 0; k < colNum; k++) { @@ -1951,7 +1985,7 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf) switch (pColInfoData->info.type) { case TSDB_DATA_TYPE_TIMESTAMP: memset(pBuf, 0, sizeof(pBuf)); - formatTimestamp(pBuf, *(uint64_t*)var, TSDB_TIME_PRECISION_MILLI); + formatTimestamp(pBuf, *(uint64_t*)var, pColInfoData->info.precision); len += snprintf(dumpBuf + len, size - len, " %25s |", pBuf); if (len >= size - 1) return dumpBuf; break; @@ -1992,8 +2026,8 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf) if (len >= size - 1) return dumpBuf; break; case TSDB_DATA_TYPE_DOUBLE: - // len += snprintf(dumpBuf + len, size - len, " %15lf |", *(double*)var); - // if (len >= size - 1) return dumpBuf; + len += snprintf(dumpBuf + len, size - len, " %15f |", *(double*)var); + if (len >= size - 1) return dumpBuf; break; case TSDB_DATA_TYPE_BOOL: len += snprintf(dumpBuf + len, size - len, " %15d |", *(bool*)var); @@ -2034,6 +2068,7 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf) * @param suid * */ +#if 0 int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SSDataBlock* pDataBlock, STSchema* pTSchema, int32_t vgId, tb_uid_t suid) { int32_t bufSize = sizeof(SSubmitReq); @@ -2197,35 +2232,193 @@ int32_t buildSubmitReqFromDataBlock(SSubmitReq** pReq, const SSDataBlock* pDataB return TSDB_CODE_SUCCESS; } +#endif + +int32_t buildSubmitReqFromDataBlock(SSubmitReq2** ppReq, const SSDataBlock* pDataBlock, const STSchema* pTSchema, + int64_t uid, int32_t vgId, tb_uid_t suid) { + SSubmitReq2* pReq = *ppReq; + SArray* pVals = NULL; + int32_t numOfBlks = 0; + int32_t sz = 1; + + terrno = TSDB_CODE_SUCCESS; + + if (NULL == pReq) { + if (!(pReq = taosMemoryMalloc(sizeof(SSubmitReq2)))) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _end; + } + + if (!(pReq->aSubmitTbData = taosArrayInit(1, sizeof(SSubmitTbData)))) { + goto _end; + } + } + + for (int32_t i = 0; i < sz; ++i) { + int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock); + int32_t rows = pDataBlock->info.rows; + + if (colNum <= 1) { // invalid if only with TS col + continue; + } + + // the rsma result should has the same column number with schema. + ASSERT(colNum == pTSchema->numOfCols); + + SSubmitTbData tbData = {0}; + + if (!(tbData.aRowP = taosArrayInit(rows, sizeof(SRow*)))) { + goto _end; + } + tbData.suid = suid; + tbData.uid = uid; + tbData.sver = pTSchema->version; + + if (!pVals && !(pVals = taosArrayInit(colNum, sizeof(SColVal)))) { + taosArrayDestroy(tbData.aRowP); + goto _end; + } + + for (int32_t j = 0; j < rows; ++j) { // iterate by row + + taosArrayClear(pVals); + + bool isStartKey = false; + int32_t offset = 0; + for (int32_t k = 0; k < colNum; ++k) { // iterate by column + SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, k); + const STColumn* pCol = &pTSchema->columns[k]; + void* var = POINTER_SHIFT(pColInfoData->pData, j * pColInfoData->info.bytes); + + switch (pColInfoData->info.type) { + case TSDB_DATA_TYPE_TIMESTAMP: + ASSERT(pColInfoData->info.type == pCol->type); + if (!isStartKey) { + isStartKey = true; + ASSERT(PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId); + SColVal cv = COL_VAL_VALUE(pCol->colId, pCol->type, (SValue){.val = *(TSKEY*)var}); + taosArrayPush(pVals, &cv); + } else if (colDataIsNull_s(pColInfoData, j)) { + SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type); + taosArrayPush(pVals, &cv); + } else { + SColVal cv = COL_VAL_VALUE(pCol->colId, pCol->type, (SValue){.val = *(int64_t*)var}); + taosArrayPush(pVals, &cv); + } + break; + case TSDB_DATA_TYPE_NCHAR: + case TSDB_DATA_TYPE_VARCHAR: { // TSDB_DATA_TYPE_BINARY + ASSERT(pColInfoData->info.type == pCol->type); + if (colDataIsNull_s(pColInfoData, j)) { + SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type); + taosArrayPush(pVals, &cv); + } else { + void* data = colDataGetVarData(pColInfoData, j); + SValue sv = (SValue){.nData = varDataLen(data), .pData = varDataVal(data)}; // address copy, no value + SColVal cv = COL_VAL_VALUE(pCol->colId, pCol->type, sv); + taosArrayPush(pVals, &cv); + } + break; + } + case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_MEDIUMBLOB: + uError("the column type %" PRIi16 " is defined but not implemented yet", pColInfoData->info.type); + ASSERT(0); + break; + default: + if (pColInfoData->info.type < TSDB_DATA_TYPE_MAX && pColInfoData->info.type > TSDB_DATA_TYPE_NULL) { + if (colDataIsNull_s(pColInfoData, j)) { + SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type); // should use pCol->type + taosArrayPush(pVals, &cv); + } else { + SValue sv; + if (pCol->type == pColInfoData->info.type) { + memcpy(&sv.val, var, tDataTypes[pCol->type].bytes); + } else { + /** + * 1. sum/avg would convert to int64_t/uint64_t/double during aggregation + * 2. below conversion may lead to overflow or loss, the app should select the right data type. + */ + char tv[8] = {0}; + if (pColInfoData->info.type == TSDB_DATA_TYPE_FLOAT) { + float v = 0; + GET_TYPED_DATA(v, float, pColInfoData->info.type, var); + SET_TYPED_DATA(&tv, pCol->type, v); + } else if (pColInfoData->info.type == TSDB_DATA_TYPE_DOUBLE) { + double v = 0; + GET_TYPED_DATA(v, double, pColInfoData->info.type, var); + SET_TYPED_DATA(&tv, pCol->type, v); + } else if (IS_SIGNED_NUMERIC_TYPE(pColInfoData->info.type)) { + int64_t v = 0; + GET_TYPED_DATA(v, int64_t, pColInfoData->info.type, var); + SET_TYPED_DATA(&tv, pCol->type, v); + } else { + uint64_t v = 0; + GET_TYPED_DATA(v, uint64_t, pColInfoData->info.type, var); + SET_TYPED_DATA(&tv, pCol->type, v); + } + memcpy(&sv.val, tv, tDataTypes[pCol->type].bytes); + } + SColVal cv = COL_VAL_VALUE(pCol->colId, pColInfoData->info.type, sv); + taosArrayPush(pVals, &cv); + } + } else { + uError("the column type %" PRIi16 " is undefined\n", pColInfoData->info.type); + ASSERT(0); + } + break; + } + } + SRow* pRow = NULL; + if ((terrno = tRowBuild(pVals, pTSchema, &pRow)) < 0) { + tDestroySubmitTbData(&tbData, TSDB_MSG_FLG_ENCODE); + goto _end; + } + ASSERT(pRow); + taosArrayPush(tbData.aRowP, &pRow); + } + + taosArrayPush(pReq->aSubmitTbData, &tbData); + } +_end: + taosArrayDestroy(pVals); + if (terrno != 0) { + *ppReq = NULL; + if (pReq) { + tDestroySubmitReq(pReq, TSDB_MSG_FLG_ENCODE); + taosMemoryFreeClear(pReq); + } + + return TSDB_CODE_FAILED; + } + *ppReq = pReq; + return TSDB_CODE_SUCCESS; +} char* buildCtbNameByGroupId(const char* stbFullName, uint64_t groupId) { if (stbFullName[0] == 0) { return NULL; } - SArray* tags = taosArrayInit(0, sizeof(void*)); + SArray* tags = taosArrayInit(0, sizeof(SSmlKv)); if (tags == NULL) { return NULL; } - SSmlKv* pTag = taosMemoryCalloc(1, sizeof(SSmlKv)); - if (pTag == NULL) { - taosArrayDestroy(tags); - return NULL; - } - void* cname = taosMemoryCalloc(1, TSDB_TABLE_NAME_LEN + 1); if (cname == NULL) { taosArrayDestroy(tags); - taosMemoryFree(pTag); return NULL; } - pTag->key = "group_id"; - pTag->keyLen = strlen(pTag->key); - pTag->type = TSDB_DATA_TYPE_UBIGINT; - pTag->u = groupId; - pTag->length = sizeof(uint64_t); + SSmlKv pTag = {.key = "group_id", + .keyLen = sizeof("group_id") - 1, + .type = TSDB_DATA_TYPE_UBIGINT, + .u = groupId, + .length = sizeof(uint64_t)}; taosArrayPush(tags, &pTag); RandTableName rname = { @@ -2237,7 +2430,6 @@ char* buildCtbNameByGroupId(const char* stbFullName, uint64_t groupId) { buildChildTableName(&rname); - taosMemoryFree(pTag); taosArrayDestroy(tags); if ((rname.ctbShortName && rname.ctbShortName[0]) == 0) { @@ -2316,6 +2508,7 @@ int32_t blockEncode(const SSDataBlock* pBlock, char* data, int32_t numOfCols) { data += colSizes[col]; colSizes[col] = htonl(colSizes[col]); +// uError("blockEncode col bytes:%d, type:%d, size:%d, htonl size:%d", pColRes->info.bytes, pColRes->info.type, htonl(colSizes[col]), colSizes[col]); } *actualLen = dataLen; @@ -2356,7 +2549,7 @@ const char* blockDecode(SSDataBlock* pBlock, const char* pData) { pStart += sizeof(uint64_t); if (pBlock->pDataBlock == NULL) { - pBlock->pDataBlock = taosArrayInit_s(numOfCols, sizeof(SColumnInfoData), numOfCols); + pBlock->pDataBlock = taosArrayInit_s(sizeof(SColumnInfoData), numOfCols); } for (int32_t i = 0; i < numOfCols; ++i) { diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index fc49c033794c946a9881b6ae1efeabcb101e99a7..b18bd882ae49d97cf0658d7463528fadbb949eb7 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -20,6 +20,9 @@ #include "tdatablock.h" #include "tlog.h" +static int32_t (*tColDataAppendValueImpl[8][3])(SColData *pColData, uint8_t *pData, uint32_t nData); +static int32_t (*tColDataUpdateValueImpl[8][3])(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward); + // SBuffer ================================ void tBufferDestroy(SBuffer *pBuffer) { tFree(pBuffer->pBuf); @@ -61,9 +64,9 @@ static int32_t tGetTagVal(uint8_t *p, STagVal *pTagVal, int8_t isJson); #define KV_FLG_MID ((uint8_t)0x20) #define KV_FLG_BIG ((uint8_t)0x30) -#define ROW_BIT_NONE ((uint8_t)0x0) -#define ROW_BIT_NULL ((uint8_t)0x1) -#define ROW_BIT_VALUE ((uint8_t)0x2) +#define BIT_FLG_NONE ((uint8_t)0x0) +#define BIT_FLG_NULL ((uint8_t)0x1) +#define BIT_FLG_VALUE ((uint8_t)0x2) #pragma pack(push, 1) typedef struct { @@ -95,28 +98,29 @@ typedef struct { } \ } while (0) -int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { +int32_t tRowBuild(SArray *aColVal, const STSchema *pTSchema, SRow **ppRow) { int32_t code = 0; - ASSERT(taosArrayGetSize(aColVal) > 0); + ASSERT(TARRAY_SIZE(aColVal) > 0); ASSERT(((SColVal *)aColVal->pData)[0].cid == PRIMARYKEY_TIMESTAMP_COL_ID); ASSERT(((SColVal *)aColVal->pData)[0].type == TSDB_DATA_TYPE_TIMESTAMP); // scan --------------- - uint8_t flag = 0; - int32_t iColVal = 1; - const int32_t nColVal = taosArrayGetSize(aColVal); - SColVal *pColVal = (iColVal < nColVal) ? (SColVal *)taosArrayGet(aColVal, iColVal) : NULL; - int32_t iTColumn = 1; - STColumn *pTColumn = pTSchema->columns + iTColumn; - int32_t ntp = 0; - int32_t nkv = 0; - int32_t maxIdx = 0; - int32_t nIdx = 0; + SRow *pRow = NULL; + SColVal *colVals = (SColVal *)TARRAY_DATA(aColVal); + uint8_t flag = 0; + int32_t iColVal = 1; + const int32_t nColVal = TARRAY_SIZE(aColVal); + SColVal *pColVal = (iColVal < nColVal) ? &colVals[iColVal] : NULL; + int32_t iTColumn = 1; + const STColumn *pTColumn = pTSchema->columns + iTColumn; + int32_t ntp = 0; + int32_t nkv = 0; + int32_t maxIdx = 0; + int32_t nIdx = 0; while (pTColumn) { if (pColVal) { if (pColVal->cid == pTColumn->colId) { - ntp += TYPE_BYTES[pTColumn->type]; if (COL_VAL_IS_VALUE(pColVal)) { // VALUE flag |= HAS_VALUE; maxIdx = nkv; @@ -135,21 +139,22 @@ int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { nkv += tPutI16v(NULL, -pTColumn->colId); nIdx++; } else { - ASSERT(0); + if (ASSERTS(0, "invalid input")) { + code = TSDB_CODE_INVALID_PARA; + goto _exit; + } } pTColumn = (++iTColumn < pTSchema->numOfCols) ? pTSchema->columns + iTColumn : NULL; - pColVal = (++iColVal < nColVal) ? (SColVal *)taosArrayGet(aColVal, iColVal) : NULL; + pColVal = (++iColVal < nColVal) ? &colVals[iColVal] : NULL; } else if (pColVal->cid > pTColumn->colId) { // NONE flag |= HAS_NONE; - ntp += TYPE_BYTES[pTColumn->type]; pTColumn = (++iTColumn < pTSchema->numOfCols) ? pTSchema->columns + iTColumn : NULL; } else { - pColVal = (++iColVal < nColVal) ? (SColVal *)taosArrayGet(aColVal, iColVal) : NULL; + pColVal = (++iColVal < nColVal) ? &colVals[iColVal] : NULL; } } else { // NONE flag |= HAS_NONE; - ntp += TYPE_BYTES[pTColumn->type]; pTColumn = (++iTColumn < pTSchema->numOfCols) ? pTSchema->columns + iTColumn : NULL; } } @@ -161,21 +166,23 @@ int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { ntp = sizeof(SRow); break; case HAS_VALUE: - ntp = sizeof(SRow) + ntp; + ntp = sizeof(SRow) + pTSchema->flen + ntp; break; case (HAS_NULL | HAS_NONE): ntp = sizeof(SRow) + BIT1_SIZE(pTSchema->numOfCols - 1); break; case (HAS_VALUE | HAS_NONE): case (HAS_VALUE | HAS_NULL): - ntp = sizeof(SRow) + BIT1_SIZE(pTSchema->numOfCols - 1) + ntp; + ntp = sizeof(SRow) + BIT1_SIZE(pTSchema->numOfCols - 1) + pTSchema->flen + ntp; break; case (HAS_VALUE | HAS_NULL | HAS_NONE): - ntp = sizeof(SRow) + BIT2_SIZE(pTSchema->numOfCols - 1) + ntp; + ntp = sizeof(SRow) + BIT2_SIZE(pTSchema->numOfCols - 1) + pTSchema->flen + ntp; break; default: - ASSERT(0); - break; + if (ASSERTS(0, "impossible")) { + code = TSDB_CODE_INVALID_PARA; + goto _exit; + } } if (maxIdx <= UINT8_MAX) { nkv = sizeof(SRow) + sizeof(SKVIdx) + nIdx + nkv; @@ -196,12 +203,14 @@ int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { } // alloc -------------- - SRow *pRow = NULL; - code = tBufferReserve(pBuffer, nRow, (void **)&pRow); - if (code) return code; + pRow = taosMemoryMalloc(nRow); + if (NULL == pRow) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } // build -------------- - pColVal = (SColVal *)taosArrayGet(aColVal, 0); + pColVal = &colVals[0]; pRow->flag = flag; pRow->rsv = 0; @@ -214,10 +223,10 @@ int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { } iColVal = 1; - pColVal = (iColVal < nColVal) ? (SColVal *)taosArrayGet(aColVal, iColVal) : NULL; + pColVal = (iColVal < nColVal) ? &colVals[iColVal] : NULL; iTColumn = 1; pTColumn = pTSchema->columns + iTColumn; - if (flag & 0xf0) { // KV + if (flag >> 4) { // KV SKVIdx *pIdx = (SKVIdx *)pRow->data; int32_t iIdx = 0; int32_t nv = 0; @@ -266,11 +275,11 @@ int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { } pTColumn = (++iTColumn < pTSchema->numOfCols) ? pTSchema->columns + iTColumn : NULL; - pColVal = (++iColVal < nColVal) ? (SColVal *)taosArrayGet(aColVal, iColVal) : NULL; + pColVal = (++iColVal < nColVal) ? &colVals[iColVal] : NULL; } else if (pColVal->cid > pTColumn->colId) { // NONE pTColumn = (++iTColumn < pTSchema->numOfCols) ? pTSchema->columns + iTColumn : NULL; } else { - pColVal = (++iColVal < nColVal) ? (SColVal *)taosArrayGet(aColVal, iColVal) : NULL; + pColVal = (++iColVal < nColVal) ? &colVals[iColVal] : NULL; } } else { // NONE pTColumn = (++iTColumn < pTSchema->numOfCols) ? pTSchema->columns + iTColumn : NULL; @@ -302,8 +311,18 @@ int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { pv = pf + pTSchema->flen; break; default: - ASSERT(0); - break; + if (ASSERTS(0, "impossible")) { + code = TSDB_CODE_INVALID_PARA; + goto _exit; + } + } + + if (pb) { + if (flag == (HAS_VALUE | HAS_NULL | HAS_NONE)) { + memset(pb, 0, BIT2_SIZE(pTSchema->numOfCols - 1)); + } else { + memset(pb, 0, BIT1_SIZE(pTSchema->numOfCols - 1)); + } } // build impl @@ -311,7 +330,7 @@ int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { if (pColVal) { if (pColVal->cid == pTColumn->colId) { if (COL_VAL_IS_VALUE(pColVal)) { // VALUE - ROW_SET_BITMAP(pb, flag, iTColumn - 1, ROW_BIT_VALUE); + ROW_SET_BITMAP(pb, flag, iTColumn - 1, BIT_FLG_VALUE); if (IS_VAR_DATA_TYPE(pTColumn->type)) { *(int32_t *)(pf + pTColumn->offset) = nv; @@ -324,24 +343,24 @@ int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { memcpy(pf + pTColumn->offset, &pColVal->value.val, TYPE_BYTES[pTColumn->type]); } } else if (COL_VAL_IS_NONE(pColVal)) { // NONE - ROW_SET_BITMAP(pb, flag, iTColumn - 1, ROW_BIT_NONE); + ROW_SET_BITMAP(pb, flag, iTColumn - 1, BIT_FLG_NONE); if (pf) memset(pf + pTColumn->offset, 0, TYPE_BYTES[pTColumn->type]); } else { // NULL - ROW_SET_BITMAP(pb, flag, iTColumn - 1, ROW_BIT_NULL); + ROW_SET_BITMAP(pb, flag, iTColumn - 1, BIT_FLG_NULL); if (pf) memset(pf + pTColumn->offset, 0, TYPE_BYTES[pTColumn->type]); } pTColumn = (++iTColumn < pTSchema->numOfCols) ? pTSchema->columns + iTColumn : NULL; - pColVal = (++iColVal < nColVal) ? (SColVal *)taosArrayGet(aColVal, iColVal) : NULL; + pColVal = (++iColVal < nColVal) ? &colVals[iColVal] : NULL; } else if (pColVal->cid > pTColumn->colId) { // NONE - ROW_SET_BITMAP(pb, flag, iTColumn - 1, ROW_BIT_NONE); + ROW_SET_BITMAP(pb, flag, iTColumn - 1, BIT_FLG_NONE); if (pf) memset(pf + pTColumn->offset, 0, TYPE_BYTES[pTColumn->type]); pTColumn = (++iTColumn < pTSchema->numOfCols) ? pTSchema->columns + iTColumn : NULL; } else { - pColVal = (++iColVal < nColVal) ? (SColVal *)taosArrayGet(aColVal, iColVal) : NULL; + pColVal = (++iColVal < nColVal) ? &colVals[iColVal] : NULL; } } else { // NONE - ROW_SET_BITMAP(pb, flag, iTColumn - 1, ROW_BIT_NONE); + ROW_SET_BITMAP(pb, flag, iTColumn - 1, BIT_FLG_NONE); if (pf) memset(pf + pTColumn->offset, 0, TYPE_BYTES[pTColumn->type]); pTColumn = (++iTColumn < pTSchema->numOfCols) ? pTSchema->columns + iTColumn : NULL; } @@ -349,10 +368,16 @@ int32_t tRowBuild(SArray *aColVal, STSchema *pTSchema, SBuffer *pBuffer) { } _exit: + if (code) { + *ppRow = NULL; + tRowDestroy(pRow); + } else { + *ppRow = pRow; + } return code; } -void tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal) { +int32_t tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal) { ASSERT(iCol < pTSchema->numOfCols); ASSERT(pRow->sver == pTSchema->version); @@ -363,20 +388,20 @@ void tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal) { pColVal->type = pTColumn->type; pColVal->flag = CV_FLAG_VALUE; memcpy(&pColVal->value.val, &pRow->ts, sizeof(TSKEY)); - return; + return 0; } if (pRow->flag == HAS_NONE) { *pColVal = COL_VAL_NONE(pTColumn->colId, pTColumn->type); - return; + return 0; } if (pRow->flag == HAS_NULL) { *pColVal = COL_VAL_NULL(pTColumn->colId, pTColumn->type); - return; + return 0; } - if (pRow->flag & 0xf0) { // KV Row + if (pRow->flag >> 4) { // KV Row SKVIdx *pIdx = (SKVIdx *)pRow->data; uint8_t *pv = NULL; if (pRow->flag & KV_FLG_LIT) { @@ -422,7 +447,7 @@ void tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal) { memcpy(&pColVal->value.val, pData, pTColumn->bytes); } } - return; + return 0; } else if (TABS(cid) < pTColumn->colId) { lidx = mid + 1; } else { @@ -432,62 +457,190 @@ void tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal) { *pColVal = COL_VAL_NONE(pTColumn->colId, pTColumn->type); } else { // Tuple Row - uint8_t *pf = NULL; - uint8_t *pv = NULL; - uint8_t bv = ROW_BIT_VALUE; + if (pRow->flag == HAS_VALUE) { + pColVal->cid = pTColumn->colId; + pColVal->type = pTColumn->type; + pColVal->flag = CV_FLAG_VALUE; + if (IS_VAR_DATA_TYPE(pTColumn->type)) { + uint8_t *pData = pRow->data + pTSchema->flen + *(int32_t *)(pRow->data + pTColumn->offset); + pData += tGetU32v(pData, &pColVal->value.nData); + if (pColVal->value.nData) { + pColVal->value.pData = pData; + } else { + pColVal->value.pData = NULL; + } + } else { + memcpy(&pColVal->value.val, pRow->data + pTColumn->offset, TYPE_BYTES[pTColumn->type]); + } + } else { + uint8_t *pf; + uint8_t *pv; + uint8_t bv = BIT_FLG_VALUE; - switch (pRow->flag) { - case HAS_VALUE: - pf = pRow->data; - pv = pf + pTSchema->flen; - break; - case (HAS_NULL | HAS_NONE): - bv = GET_BIT1(pRow->data, iCol - 1); - break; - case (HAS_VALUE | HAS_NONE): - bv = GET_BIT1(pRow->data, iCol - 1); - if (bv) bv++; - pf = pRow->data + BIT1_SIZE(pTSchema->numOfCols - 1); - pv = pf + pTSchema->flen; - break; - case (HAS_VALUE | HAS_NULL): - bv = GET_BIT1(pRow->data, iCol - 1); - bv++; - pf = pRow->data + BIT1_SIZE(pTSchema->numOfCols - 1); - pv = pf + pTSchema->flen; - break; - case (HAS_VALUE | HAS_NULL | HAS_NONE): - bv = GET_BIT2(pRow->data, iCol - 1); - pf = pRow->data + BIT2_SIZE(pTSchema->numOfCols - 1); - pv = pf + pTSchema->flen; - break; - default: - break; - } + switch (pRow->flag) { + case (HAS_NULL | HAS_NONE): + bv = GET_BIT1(pRow->data, iCol - 1); + break; + case (HAS_VALUE | HAS_NONE): + bv = GET_BIT1(pRow->data, iCol - 1); + if (bv) bv++; + pf = pRow->data + BIT1_SIZE(pTSchema->numOfCols - 1); + pv = pf + pTSchema->flen; + break; + case (HAS_VALUE | HAS_NULL): + bv = GET_BIT1(pRow->data, iCol - 1); + bv++; + pf = pRow->data + BIT1_SIZE(pTSchema->numOfCols - 1); + pv = pf + pTSchema->flen; + break; + case (HAS_VALUE | HAS_NULL | HAS_NONE): + bv = GET_BIT2(pRow->data, iCol - 1); + pf = pRow->data + BIT2_SIZE(pTSchema->numOfCols - 1); + pv = pf + pTSchema->flen; + break; + default: + ASSERTS(0, "invalid row format"); + return TSDB_CODE_IVLD_DATA_FMT; + } - if (bv == ROW_BIT_NONE) { - *pColVal = COL_VAL_NONE(pTColumn->colId, pTColumn->type); - return; - } else if (bv == ROW_BIT_NULL) { - *pColVal = COL_VAL_NULL(pTColumn->colId, pTColumn->type); - return; - } + if (bv == BIT_FLG_NONE) { + *pColVal = COL_VAL_NONE(pTColumn->colId, pTColumn->type); + return 0; + } else if (bv == BIT_FLG_NULL) { + *pColVal = COL_VAL_NULL(pTColumn->colId, pTColumn->type); + return 0; + } - pColVal->cid = pTColumn->colId; - pColVal->type = pTColumn->type; - pColVal->flag = CV_FLAG_VALUE; - if (IS_VAR_DATA_TYPE(pTColumn->type)) { - uint8_t *pData = pv + *(int32_t *)(pf + pTColumn->offset); - pData += tGetU32v(pData, &pColVal->value.nData); - if (pColVal->value.nData) { - pColVal->value.pData = pData; + pColVal->cid = pTColumn->colId; + pColVal->type = pTColumn->type; + pColVal->flag = CV_FLAG_VALUE; + if (IS_VAR_DATA_TYPE(pTColumn->type)) { + uint8_t *pData = pv + *(int32_t *)(pf + pTColumn->offset); + pData += tGetU32v(pData, &pColVal->value.nData); + if (pColVal->value.nData) { + pColVal->value.pData = pData; + } else { + pColVal->value.pData = NULL; + } } else { - pColVal->value.pData = NULL; + memcpy(&pColVal->value.val, pf + pTColumn->offset, TYPE_BYTES[pTColumn->type]); } - } else { - memcpy(&pColVal->value.val, pv + pTColumn->offset, pTColumn->bytes); } } + + return 0; +} + +void tRowDestroy(SRow *pRow) { + if (pRow) taosMemoryFree(pRow); +} + +static int32_t tRowPCmprFn(const void *p1, const void *p2) { + if ((*(SRow **)p1)->ts < (*(SRow **)p2)->ts) { + return -1; + } else if ((*(SRow **)p1)->ts > (*(SRow **)p2)->ts) { + return 1; + } + + return 0; +} +static void tRowPDestroy(SRow **ppRow) { tRowDestroy(*ppRow); } +static int32_t tRowMergeImpl(SArray *aRowP, STSchema *pTSchema, int32_t iStart, int32_t iEnd, int8_t flag) { + int32_t code = 0; + + int32_t nRow = iEnd - iStart; + SRowIter **aIter = NULL; + SArray *aColVal = NULL; + SRow *pRow = NULL; + + aIter = taosMemoryCalloc(nRow, sizeof(SRowIter *)); + if (aIter == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + for (int32_t i = 0; i < nRow; i++) { + SRow *pRowT = taosArrayGetP(aRowP, iStart + i); + + code = tRowIterOpen(pRowT, pTSchema, &aIter[i]); + if (code) goto _exit; + } + + // merge + aColVal = taosArrayInit(pTSchema->numOfCols, sizeof(SColVal)); + if (aColVal == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + for (int32_t iCol = 0; iCol < pTSchema->numOfCols; iCol++) { + SColVal *pColVal = NULL; + for (int32_t iRow = 0; iRow < nRow; iRow++) { + SColVal *pColValT = tRowIterNext(aIter[iRow]); + + // todo: take strategy according to the flag + if (COL_VAL_IS_VALUE(pColValT)) { + pColVal = pColValT; + } else if (COL_VAL_IS_NULL(pColValT)) { + if (pColVal == NULL) { + pColVal = pColValT; + } + } + } + + if (pColVal) taosArrayPush(aColVal, pColVal); + } + + // build + code = tRowBuild(aColVal, pTSchema, &pRow); + if (code) goto _exit; + + taosArrayRemoveBatch(aRowP, iStart, nRow, (FDelete)tRowPDestroy); + taosArrayInsert(aRowP, iStart, &pRow); + +_exit: + if (aIter) { + for (int32_t i = 0; i < nRow; i++) { + tRowIterClose(&aIter[i]); + } + taosMemoryFree(aIter); + } + if (aColVal) taosArrayDestroy(aColVal); + if (code) tRowDestroy(pRow); + return code; +} + +void tRowSort(SArray *aRowP) { + if (TARRAY_SIZE(aRowP) <= 1) return; + taosArraySort(aRowP, tRowPCmprFn); +} + +int32_t tRowMerge(SArray *aRowP, STSchema *pTSchema, int8_t flag) { + int32_t code = 0; + + int32_t iStart = 0; + while (iStart < aRowP->size) { + SRow *pRow = (SRow *)taosArrayGetP(aRowP, iStart); + + int32_t iEnd = iStart + 1; + while (iEnd < aRowP->size) { + SRow *pRowT = (SRow *)taosArrayGetP(aRowP, iEnd); + + if (pRow->ts != pRowT->ts) break; + + iEnd++; + } + + if (iEnd - iStart > 1) { + code = tRowMergeImpl(aRowP, pTSchema, iStart, iEnd, flag); + if (code) return code; + } + + // the array is also changing, so the iStart just ++ instead of iEnd + iStart++; + } + + return code; } // SRowIter ======================================== @@ -505,10 +658,9 @@ struct SRowIter { uint8_t *pb; uint8_t *pf; }; - uint8_t *pv; }; - - SColVal cv; + uint8_t *pv; + SColVal cv; }; int32_t tRowIterOpen(SRow *pRow, STSchema *pTSchema, SRowIter **ppIter) { @@ -528,15 +680,15 @@ int32_t tRowIterOpen(SRow *pRow, STSchema *pTSchema, SRowIter **ppIter) { if (pRow->flag == HAS_NONE || pRow->flag == HAS_NULL) goto _exit; - if (pRow->flag & 0xf0) { + if (pRow->flag >> 4) { pIter->iCol = 0; pIter->pIdx = (SKVIdx *)pRow->data; if (pRow->flag & KV_FLG_LIT) { pIter->pv = pIter->pIdx->idx + pIter->pIdx->nCol; } else if (pRow->flag & KV_FLG_MID) { - pIter->pv = pIter->pIdx->idx + (pIter->pIdx->nCol << 1); + pIter->pv = pIter->pIdx->idx + (pIter->pIdx->nCol << 1); // * sizeof(uint16_t) } else { - pIter->pv = pIter->pIdx->idx + (pIter->pIdx->nCol << 2); + pIter->pv = pIter->pIdx->idx + (pIter->pIdx->nCol << 2); // * sizeof(uint32_t) } } else { switch (pRow->flag) { @@ -567,7 +719,6 @@ int32_t tRowIterOpen(SRow *pRow, STSchema *pTSchema, SRowIter **ppIter) { _exit: if (code) { *ppIter = NULL; - if (pIter) taosMemoryFree(pIter); } else { *ppIter = pIter; } @@ -608,7 +759,7 @@ SColVal *tRowIterNext(SRowIter *pIter) { goto _exit; } - if (pIter->pRow->flag & 0xf0) { // KV + if (pIter->pRow->flag >> 4) { // KV if (pIter->iCol < pIter->pIdx->nCol) { uint8_t *pData; @@ -656,7 +807,7 @@ SColVal *tRowIterNext(SRowIter *pIter) { goto _exit; } } else { // Tuple - uint8_t bv = ROW_BIT_VALUE; + uint8_t bv = BIT_FLG_VALUE; if (pIter->pb) { switch (pIter->pRow->flag) { case (HAS_NULL | HAS_NONE): @@ -677,10 +828,10 @@ SColVal *tRowIterNext(SRowIter *pIter) { break; } - if (bv == ROW_BIT_NONE) { + if (bv == BIT_FLG_NONE) { pIter->cv = COL_VAL_NONE(pTColumn->colId, pTColumn->type); goto _exit; - } else if (bv == ROW_BIT_NULL) { + } else if (bv == BIT_FLG_NULL) { pIter->cv = COL_VAL_NULL(pTColumn->colId, pTColumn->type); goto _exit; } @@ -698,7 +849,7 @@ SColVal *tRowIterNext(SRowIter *pIter) { pIter->cv.value.pData = NULL; } } else { - memcpy(&pIter->cv.value.val, pIter->pv + pTColumn->offset, pTColumn->bytes); + memcpy(&pIter->cv.value.val, pIter->pf + pTColumn->offset, TYPE_BYTES[pTColumn->type]); } goto _exit; } @@ -708,7 +859,276 @@ _exit: return &pIter->cv; } -// STSchema ======================================== +static int32_t tRowNoneUpsertColData(SColData *aColData, int32_t nColData, int32_t flag) { + int32_t code = 0; + + if (flag) return code; + + for (int32_t iColData = 0; iColData < nColData; iColData++) { + code = tColDataAppendValueImpl[aColData[iColData].flag][CV_FLAG_NONE](&aColData[iColData], NULL, 0); + if (code) return code; + } + + return code; +} +static int32_t tRowNullUpsertColData(SColData *aColData, int32_t nColData, STSchema *pSchema, int32_t flag) { + int32_t code = 0; + + int32_t iColData = 0; + SColData *pColData = &aColData[iColData]; + int32_t iTColumn = 1; + STColumn *pTColumn = &pSchema->columns[iTColumn]; + + while (pColData) { + if (pTColumn) { + if (pTColumn->colId == pColData->cid) { // NULL + if (flag == 0) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0); + } else { + code = tColDataUpdateValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0, flag > 0); + } + if (code) goto _exit; + + pColData = (++iColData < nColData) ? &aColData[iColData] : NULL; + pTColumn = (++iTColumn < pSchema->numOfCols) ? &pSchema->columns[iTColumn] : NULL; + } else if (pTColumn->colId > pColData->cid) { // NONE + if (flag == 0 && (code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0))) goto _exit; + pColData = (++iColData < nColData) ? &aColData[iColData] : NULL; + } else { + pTColumn = (++iTColumn < pSchema->numOfCols) ? &pSchema->columns[iTColumn] : NULL; + } + } else { // NONE + if (flag == 0 && (code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0))) goto _exit; + pColData = (++iColData < nColData) ? &aColData[iColData] : NULL; + } + } + +_exit: + return code; +} +static int32_t tRowTupleUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *aColData, int32_t nColData, + int32_t flag) { + int32_t code = 0; + + int32_t iColData = 0; + SColData *pColData = &aColData[iColData]; + int32_t iTColumn = 1; + STColumn *pTColumn = &pTSchema->columns[iTColumn]; + + uint8_t *pb = NULL, *pf = NULL, *pv = NULL; + + switch (pRow->flag) { + case HAS_VALUE: + pf = pRow->data; + pv = pf + pTSchema->flen; + break; + case (HAS_NULL | HAS_NONE): + pb = pRow->data; + break; + case (HAS_VALUE | HAS_NONE): + case (HAS_VALUE | HAS_NULL): + pb = pRow->data; + pf = pb + BIT1_SIZE(pTSchema->numOfCols - 1); + pv = pf + pTSchema->flen; + break; + case (HAS_VALUE | HAS_NULL | HAS_NONE): + pb = pRow->data; + pf = pb + BIT2_SIZE(pTSchema->numOfCols - 1); + pv = pf + pTSchema->flen; + break; + default: + ASSERTS(0, "Invalid row flag"); + return TSDB_CODE_IVLD_DATA_FMT; + } + + while (pColData) { + if (pTColumn) { + if (pTColumn->colId == pColData->cid) { + ASSERT(pTColumn->type == pColData->type); + if (pb) { + uint8_t bv; + switch (pRow->flag) { + case (HAS_NULL | HAS_NONE): + bv = GET_BIT1(pb, iTColumn - 1); + break; + case (HAS_VALUE | HAS_NONE): + bv = GET_BIT1(pb, iTColumn - 1); + if (bv) bv++; + break; + case (HAS_VALUE | HAS_NULL): + bv = GET_BIT1(pb, iTColumn - 1) + 1; + break; + case (HAS_VALUE | HAS_NULL | HAS_NONE): + bv = GET_BIT2(pb, iTColumn - 1); + break; + default: + ASSERTS(0, "Invalid row flag"); + return TSDB_CODE_IVLD_DATA_FMT; + } + + if (bv == BIT_FLG_NONE) { + if (flag == 0 && (code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0))) + goto _exit; + goto _continue; + } else if (bv == BIT_FLG_NULL) { + if (flag == 0) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0); + } else { + code = tColDataUpdateValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0, flag > 0); + } + if (code) goto _exit; + goto _continue; + } + } + + if (IS_VAR_DATA_TYPE(pColData->type)) { + uint8_t *pData = pv + *(int32_t *)(pf + pTColumn->offset); + uint32_t nData; + pData += tGetU32v(pData, &nData); + if (flag == 0) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, pData, nData); + } else { + code = tColDataUpdateValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, pData, nData, flag > 0); + } + if (code) goto _exit; + } else { + if (flag == 0) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, pf + pTColumn->offset, + TYPE_BYTES[pColData->type]); + } else { + code = tColDataUpdateValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, pf + pTColumn->offset, + TYPE_BYTES[pColData->type], flag > 0); + } + if (code) goto _exit; + } + + _continue: + pColData = (++iColData < nColData) ? &aColData[iColData] : NULL; + pTColumn = (++iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; + } else if (pTColumn->colId > pColData->cid) { // NONE + if (flag == 0 && (code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0))) goto _exit; + pColData = (++iColData < nColData) ? &aColData[iColData] : NULL; + } else { + pTColumn = (++iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; + } + } else { + if (flag == 0 && (code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0))) goto _exit; + pColData = (++iColData < nColData) ? &aColData[iColData] : NULL; + } + } + +_exit: + return code; +} +static int32_t tRowKVUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *aColData, int32_t nColData, int32_t flag) { + int32_t code = 0; + + SKVIdx *pKVIdx = (SKVIdx *)pRow->data; + uint8_t *pv = NULL; + int32_t iColData = 0; + SColData *pColData = &aColData[iColData]; + int32_t iTColumn = 1; + STColumn *pTColumn = &pTSchema->columns[iTColumn]; + int32_t iCol = 0; + + if (pRow->flag & KV_FLG_LIT) { + pv = pKVIdx->idx + pKVIdx->nCol; + } else if (pRow->flag & KV_FLG_MID) { + pv = pKVIdx->idx + (pKVIdx->nCol << 1); + } else if (pRow->flag & KV_FLG_BIG) { + pv = pKVIdx->idx + (pKVIdx->nCol << 2); + } else { + ASSERT(0); + } + + while (pColData) { + if (pTColumn) { + if (pTColumn->colId == pColData->cid) { + while (iCol < pKVIdx->nCol) { + uint8_t *pData; + if (pRow->flag & KV_FLG_LIT) { + pData = pv + ((uint8_t *)pKVIdx->idx)[iCol]; + } else if (pRow->flag & KV_FLG_MID) { + pData = pv + ((uint16_t *)pKVIdx->idx)[iCol]; + } else if (pRow->flag & KV_FLG_BIG) { + pData = pv + ((uint32_t *)pKVIdx->idx)[iCol]; + } else { + ASSERTS(0, "Invalid KV row format"); + return TSDB_CODE_IVLD_DATA_FMT; + } + + int16_t cid; + pData += tGetI16v(pData, &cid); + + if (TABS(cid) == pTColumn->colId) { + if (cid < 0) { + if (flag == 0) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0); + } else { + code = tColDataUpdateValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0, flag > 0); + } + if (code) goto _exit; + } else { + uint32_t nData; + if (IS_VAR_DATA_TYPE(pTColumn->type)) { + pData += tGetU32v(pData, &nData); + } else { + nData = 0; + } + if (flag == 0) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, pData, nData); + } else { + code = tColDataUpdateValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, pData, nData, flag > 0); + } + if (code) goto _exit; + } + iCol++; + goto _continue; + } else if (TABS(cid) > pTColumn->colId) { // NONE + break; + } else { + iCol++; + } + } + + if (flag == 0 && (code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0))) goto _exit; + + _continue: + pColData = (++iColData < nColData) ? &aColData[iColData] : NULL; + pTColumn = (++iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; + } else if (pTColumn->colId > pColData->cid) { + if (flag == 0 && (code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0))) goto _exit; + pColData = (++iColData < nColData) ? &aColData[iColData] : NULL; + } else { + pTColumn = (++iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; + } + } else { + if (flag == 0 && (code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0))) goto _exit; + pColData = (++iColData < nColData) ? &aColData[iColData] : NULL; + } + } + +_exit: + return code; +} +/* flag > 0: forward update + * flag == 0: append + * flag < 0: backward update + */ +int32_t tRowUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *aColData, int32_t nColData, int32_t flag) { + ASSERT(pRow->sver == pTSchema->version); + ASSERT(nColData > 0); + + if (pRow->flag == HAS_NONE) { + return tRowNoneUpsertColData(aColData, nColData, flag); + } else if (pRow->flag == HAS_NULL) { + return tRowNullUpsertColData(aColData, nColData, pTSchema, flag); + } else if (pRow->flag >> 4) { // KV row + return tRowKVUpsertColData(pRow, pTSchema, aColData, nColData, flag); + } else { // TUPLE row + return tRowTupleUpsertColData(pRow, pTSchema, aColData, nColData, flag); + } +} // STag ======================================== static int tTagValCmprFn(const void *p1, const void *p2) { @@ -1086,134 +1506,59 @@ void tTagSetCid(const STag *pTag, int16_t iTag, int16_t cid) { tPutI16v(p + offset, cid); } -#if 1 // =================================================================================================================== -int tdInitTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version) { - if (pBuilder == NULL) return -1; +// STSchema ======================================== +STSchema *tBuildTSchema(SSchema *aSchema, int32_t numOfCols, int32_t version) { + STSchema *pTSchema = taosMemoryCalloc(1, sizeof(STSchema) + sizeof(STColumn) * numOfCols); + if (pTSchema == NULL) { + return NULL; + } - pBuilder->tCols = 256; - pBuilder->columns = (STColumn *)taosMemoryMalloc(sizeof(STColumn) * pBuilder->tCols); - if (pBuilder->columns == NULL) return -1; + pTSchema->numOfCols = numOfCols; + pTSchema->version = version; - tdResetTSchemaBuilder(pBuilder, version); - return 0; -} + // timestamp column + ASSERT(aSchema[0].type == TSDB_DATA_TYPE_TIMESTAMP); + ASSERT(aSchema[0].colId == PRIMARYKEY_TIMESTAMP_COL_ID); + pTSchema->columns[0].colId = aSchema[0].colId; + pTSchema->columns[0].type = aSchema[0].type; + pTSchema->columns[0].flags = aSchema[0].flags; + pTSchema->columns[0].bytes = TYPE_BYTES[aSchema[0].type]; + pTSchema->columns[0].offset = -1; -void tdDestroyTSchemaBuilder(STSchemaBuilder *pBuilder) { - if (pBuilder) { - taosMemoryFreeClear(pBuilder->columns); - } -} + // other columns + for (int32_t iCol = 1; iCol < numOfCols; iCol++) { + SSchema *pSchema = &aSchema[iCol]; + STColumn *pTColumn = &pTSchema->columns[iCol]; -void tdResetTSchemaBuilder(STSchemaBuilder *pBuilder, schema_ver_t version) { - pBuilder->nCols = 0; - pBuilder->tlen = 0; - pBuilder->flen = 0; - pBuilder->version = version; -} + pTColumn->colId = pSchema->colId; + pTColumn->type = pSchema->type; + pTColumn->flags = pSchema->flags; + pTColumn->offset = pTSchema->flen; -int32_t tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int8_t flags, col_id_t colId, col_bytes_t bytes) { - if (!isValidDataType(type)) return -1; + if (IS_VAR_DATA_TYPE(pSchema->type)) { + pTColumn->bytes = pSchema->bytes; + pTSchema->tlen += (TYPE_BYTES[pSchema->type] + pSchema->bytes); // todo: remove + } else { + pTColumn->bytes = TYPE_BYTES[pSchema->type]; + pTSchema->tlen += TYPE_BYTES[pSchema->type]; // todo: remove + } - if (pBuilder->nCols >= pBuilder->tCols) { - pBuilder->tCols *= 2; - STColumn *columns = (STColumn *)taosMemoryRealloc(pBuilder->columns, sizeof(STColumn) * pBuilder->tCols); - if (columns == NULL) return -1; - pBuilder->columns = columns; + pTSchema->flen += TYPE_BYTES[pTColumn->type]; } - STColumn *pCol = &(pBuilder->columns[pBuilder->nCols]); - pCol->type = type; - pCol->colId = colId; - pCol->flags = flags; - if (pBuilder->nCols == 0) { - pCol->offset = -1; - } else { - pCol->offset = pBuilder->flen; - pBuilder->flen += TYPE_BYTES[type]; - } +#if 1 // todo : remove this + pTSchema->tlen += (int32_t)TD_BITMAP_BYTES(numOfCols); +#endif - if (IS_VAR_DATA_TYPE(type)) { - pCol->bytes = bytes; - pBuilder->tlen += (TYPE_BYTES[type] + bytes); - } else { - pCol->bytes = TYPE_BYTES[type]; - pBuilder->tlen += TYPE_BYTES[type]; - } - - pBuilder->nCols++; - - ASSERT(pCol->offset < pBuilder->flen); - - return 0; -} - -STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder) { - if (pBuilder->nCols <= 0) return NULL; - - int tlen = sizeof(STSchema) + sizeof(STColumn) * pBuilder->nCols; - - STSchema *pSchema = (STSchema *)taosMemoryMalloc(tlen); - if (pSchema == NULL) return NULL; - - pSchema->version = pBuilder->version; - pSchema->numOfCols = pBuilder->nCols; - pSchema->tlen = pBuilder->tlen; - pSchema->flen = pBuilder->flen; - -#ifdef TD_SUPPORT_BITMAP - pSchema->tlen += (int)TD_BITMAP_BYTES(pSchema->numOfCols); -#endif - - memcpy(&pSchema->columns[0], pBuilder->columns, sizeof(STColumn) * pBuilder->nCols); - - return pSchema; -} - -#endif - -STSchema *tBuildTSchema(SSchema *aSchema, int32_t numOfCols, int32_t version) { - STSchema *pTSchema = taosMemoryCalloc(1, sizeof(STSchema) + sizeof(STColumn) * numOfCols); - if (pTSchema == NULL) return NULL; - - pTSchema->numOfCols = numOfCols; - pTSchema->version = version; - - // timestamp column - ASSERT(aSchema[0].type == TSDB_DATA_TYPE_TIMESTAMP); - ASSERT(aSchema[0].colId == PRIMARYKEY_TIMESTAMP_COL_ID); - pTSchema->columns[0].colId = aSchema[0].colId; - pTSchema->columns[0].type = aSchema[0].type; - pTSchema->columns[0].flags = aSchema[0].flags; - pTSchema->columns[0].bytes = aSchema[0].bytes; - pTSchema->columns[0].offset = -1; - - // other columns - for (int32_t iCol = 1; iCol < numOfCols; iCol++) { - SSchema *pSchema = &aSchema[iCol]; - STColumn *pTColumn = &pTSchema->columns[iCol]; - - pTColumn->colId = pSchema->colId; - pTColumn->type = pSchema->type; - pTColumn->flags = pSchema->flags; - pTColumn->bytes = pSchema->bytes; - pTColumn->offset = pTSchema->flen; - - pTSchema->flen += TYPE_BYTES[pTColumn->type]; - } - - return pTSchema; -} - -void tDestroyTSchema(STSchema *pTSchema) { - if (pTSchema) taosMemoryFree(pTSchema); -} + return pTSchema; +} // SColData ======================================== void tColDataDestroy(void *ph) { SColData *pColData = (SColData *)ph; tFree(pColData->pBitMap); - tFree((uint8_t *)pColData->aOffset); + tFree(pColData->aOffset); tFree(pColData->pData); } @@ -1225,30 +1570,45 @@ void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn) { } void tColDataClear(SColData *pColData) { + pColData->numOfNone = 0; + pColData->numOfNull = 0; + pColData->numOfValue = 0; pColData->nVal = 0; pColData->flag = 0; pColData->nData = 0; } -static FORCE_INLINE int32_t tColDataPutValue(SColData *pColData, SColVal *pColVal) { +void tColDataDeepClear(SColData *pColData) { + pColData->pBitMap = NULL; + pColData->aOffset = NULL; + pColData->pData = NULL; + + tColDataClear(pColData); +} + +static FORCE_INLINE int32_t tColDataPutValue(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; if (IS_VAR_DATA_TYPE(pColData->type)) { - code = tRealloc((uint8_t **)(&pColData->aOffset), sizeof(int32_t) * (pColData->nVal + 1)); + code = tRealloc((uint8_t **)(&pColData->aOffset), ((int64_t)(pColData->nVal + 1)) << 2); if (code) goto _exit; pColData->aOffset[pColData->nVal] = pColData->nData; - if (pColVal->value.nData) { - code = tRealloc(&pColData->pData, pColData->nData + pColVal->value.nData); + if (nData) { + code = tRealloc(&pColData->pData, pColData->nData + nData); if (code) goto _exit; - memcpy(pColData->pData + pColData->nData, pColVal->value.pData, pColVal->value.nData); - pColData->nData += pColVal->value.nData; + memcpy(pColData->pData + pColData->nData, pData, nData); + pColData->nData += nData; } } else { ASSERT(pColData->nData == tDataTypes[pColData->type].bytes * pColData->nVal); code = tRealloc(&pColData->pData, pColData->nData + tDataTypes[pColData->type].bytes); if (code) goto _exit; - memcpy(pColData->pData + pColData->nData, &pColVal->value.val, tDataTypes[pColData->type].bytes); + if (pData) { + memcpy(pColData->pData + pColData->nData, pData, TYPE_BYTES[pColData->type]); + } else { + memset(pColData->pData + pColData->nData, 0, TYPE_BYTES[pColData->type]); + } pColData->nData += tDataTypes[pColData->type].bytes; } pColData->nVal++; @@ -1256,21 +1616,24 @@ static FORCE_INLINE int32_t tColDataPutValue(SColData *pColData, SColVal *pColVa _exit: return code; } -static FORCE_INLINE int32_t tColDataAppendValue00(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue00(SColData *pColData, uint8_t *pData, uint32_t nData) { pColData->flag = HAS_VALUE; - return tColDataPutValue(pColData, pColVal); + pColData->numOfValue++; + return tColDataPutValue(pColData, pData, nData); } -static FORCE_INLINE int32_t tColDataAppendValue01(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue01(SColData *pColData, uint8_t *pData, uint32_t nData) { pColData->flag = HAS_NONE; + pColData->numOfNone++; pColData->nVal++; return 0; } -static FORCE_INLINE int32_t tColDataAppendValue02(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue02(SColData *pColData, uint8_t *pData, uint32_t nData) { pColData->flag = HAS_NULL; + pColData->numOfNull++; pColData->nVal++; return 0; } -static FORCE_INLINE int32_t tColDataAppendValue10(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue10(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; int32_t nBit = BIT1_SIZE(pColData->nVal + 1); @@ -1278,9 +1641,10 @@ static FORCE_INLINE int32_t tColDataAppendValue10(SColData *pColData, SColVal *p if (code) return code; memset(pColData->pBitMap, 0, nBit); - SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 1); pColData->flag |= HAS_VALUE; + pColData->numOfValue++; if (pColData->nVal) { if (IS_VAR_DATA_TYPE(pColData->type)) { @@ -1296,13 +1660,14 @@ static FORCE_INLINE int32_t tColDataAppendValue10(SColData *pColData, SColVal *p } } - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, pData, nData); } -static FORCE_INLINE int32_t tColDataAppendValue11(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue11(SColData *pColData, uint8_t *pData, uint32_t nData) { pColData->nVal++; + pColData->numOfNone++; return 0; } -static FORCE_INLINE int32_t tColDataAppendValue12(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue12(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; int32_t nBit = BIT1_SIZE(pColData->nVal + 1); @@ -1310,14 +1675,15 @@ static FORCE_INLINE int32_t tColDataAppendValue12(SColData *pColData, SColVal *p if (code) return code; memset(pColData->pBitMap, 0, nBit); - SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 1); pColData->flag |= HAS_NULL; + pColData->numOfNull++; pColData->nVal++; return code; } -static FORCE_INLINE int32_t tColDataAppendValue20(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue20(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; int32_t nBit = BIT1_SIZE(pColData->nVal + 1); @@ -1325,9 +1691,10 @@ static FORCE_INLINE int32_t tColDataAppendValue20(SColData *pColData, SColVal *p if (code) return code; memset(pColData->pBitMap, 0, nBit); - SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 1); pColData->flag |= HAS_VALUE; + pColData->numOfValue++; if (pColData->nVal) { if (IS_VAR_DATA_TYPE(pColData->type)) { @@ -1343,9 +1710,9 @@ static FORCE_INLINE int32_t tColDataAppendValue20(SColData *pColData, SColVal *p } } - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, pData, nData); } -static FORCE_INLINE int32_t tColDataAppendValue21(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue21(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; int32_t nBit = BIT1_SIZE(pColData->nVal + 1); @@ -1353,30 +1720,33 @@ static FORCE_INLINE int32_t tColDataAppendValue21(SColData *pColData, SColVal *p if (code) return code; memset(pColData->pBitMap, 255, nBit); - SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 0); pColData->flag |= HAS_NONE; + pColData->numOfNone++; pColData->nVal++; return code; } -static FORCE_INLINE int32_t tColDataAppendValue22(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue22(SColData *pColData, uint8_t *pData, uint32_t nData) { pColData->nVal++; + pColData->numOfNull++; return 0; } -static FORCE_INLINE int32_t tColDataAppendValue30(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue30(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; pColData->flag |= HAS_VALUE; + pColData->numOfValue++; uint8_t *pBitMap = NULL; code = tRealloc(&pBitMap, BIT2_SIZE(pColData->nVal + 1)); if (code) return code; for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { - SET_BIT2(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal)); + SET_BIT2_EX(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal)); } - SET_BIT2(pBitMap, pColData->nVal, 2); + SET_BIT2_EX(pBitMap, pColData->nVal, 2); tFree(pColData->pBitMap); pColData->pBitMap = pBitMap; @@ -1395,163 +1765,179 @@ static FORCE_INLINE int32_t tColDataAppendValue30(SColData *pColData, SColVal *p } } - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, pData, nData); } -static FORCE_INLINE int32_t tColDataAppendValue31(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue31(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); if (code) return code; - SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 0); + pColData->numOfNone++; pColData->nVal++; return code; } -static FORCE_INLINE int32_t tColDataAppendValue32(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue32(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); if (code) return code; - SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 1); + pColData->numOfNull++; pColData->nVal++; return code; } -#define tColDataAppendValue40 tColDataPutValue -static FORCE_INLINE int32_t tColDataAppendValue41(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue40(SColData *pColData, uint8_t *pData, uint32_t nData) { + pColData->numOfValue++; + return tColDataPutValue(pColData, pData, nData); +} +static FORCE_INLINE int32_t tColDataAppendValue41(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; pColData->flag |= HAS_NONE; + pColData->numOfNone++; int32_t nBit = BIT1_SIZE(pColData->nVal + 1); code = tRealloc(&pColData->pBitMap, nBit); if (code) return code; memset(pColData->pBitMap, 255, nBit); - SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 0); - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, NULL, 0); } -static FORCE_INLINE int32_t tColDataAppendValue42(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue42(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; pColData->flag |= HAS_NULL; + pColData->numOfNull++; int32_t nBit = BIT1_SIZE(pColData->nVal + 1); code = tRealloc(&pColData->pBitMap, nBit); if (code) return code; memset(pColData->pBitMap, 255, nBit); - SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 0); - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, NULL, 0); } -static FORCE_INLINE int32_t tColDataAppendValue50(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue50(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); if (code) return code; - SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 1); + pColData->numOfValue++; - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, pData, nData); } -static FORCE_INLINE int32_t tColDataAppendValue51(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue51(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); if (code) return code; - SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 0); + pColData->numOfNone++; - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, NULL, 0); } -static FORCE_INLINE int32_t tColDataAppendValue52(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue52(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; pColData->flag |= HAS_NULL; + pColData->numOfNull++; uint8_t *pBitMap = NULL; code = tRealloc(&pBitMap, BIT2_SIZE(pColData->nVal + 1)); if (code) return code; for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { - SET_BIT2(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal) ? 2 : 0); + SET_BIT2_EX(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal) ? 2 : 0); } - SET_BIT2(pBitMap, pColData->nVal, 1); + SET_BIT2_EX(pBitMap, pColData->nVal, 1); tFree(pColData->pBitMap); pColData->pBitMap = pBitMap; - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, NULL, 0); } -static FORCE_INLINE int32_t tColDataAppendValue60(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue60(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); if (code) return code; - SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 1); + pColData->numOfValue++; - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, pData, nData); } -static FORCE_INLINE int32_t tColDataAppendValue61(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue61(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; pColData->flag |= HAS_NONE; + pColData->numOfNone++; uint8_t *pBitMap = NULL; code = tRealloc(&pBitMap, BIT2_SIZE(pColData->nVal + 1)); if (code) return code; for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { - SET_BIT2(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal) ? 2 : 1); + SET_BIT2_EX(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal) ? 2 : 1); } - SET_BIT2(pBitMap, pColData->nVal, 0); + SET_BIT2_EX(pBitMap, pColData->nVal, 0); tFree(pColData->pBitMap); pColData->pBitMap = pBitMap; - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, NULL, 0); } -static FORCE_INLINE int32_t tColDataAppendValue62(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue62(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); if (code) return code; - SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + SET_BIT1_EX(pColData->pBitMap, pColData->nVal, 0); + pColData->numOfNull++; - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, NULL, 0); } -static FORCE_INLINE int32_t tColDataAppendValue70(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue70(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; code = tRealloc(&pColData->pBitMap, BIT2_SIZE(pColData->nVal + 1)); if (code) return code; - SET_BIT2(pColData->pBitMap, pColData->nVal, 2); + SET_BIT2_EX(pColData->pBitMap, pColData->nVal, 2); + pColData->numOfValue++; - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, pData, nData); } -static FORCE_INLINE int32_t tColDataAppendValue71(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue71(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; code = tRealloc(&pColData->pBitMap, BIT2_SIZE(pColData->nVal + 1)); if (code) return code; - SET_BIT2(pColData->pBitMap, pColData->nVal, 0); + SET_BIT2_EX(pColData->pBitMap, pColData->nVal, 0); + pColData->numOfNone++; - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, NULL, 0); } -static FORCE_INLINE int32_t tColDataAppendValue72(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue72(SColData *pColData, uint8_t *pData, uint32_t nData) { int32_t code = 0; code = tRealloc(&pColData->pBitMap, BIT2_SIZE(pColData->nVal + 1)); if (code) return code; - SET_BIT2(pColData->pBitMap, pColData->nVal, 1); + SET_BIT2_EX(pColData->pBitMap, pColData->nVal, 1); + pColData->numOfNull++; - return tColDataPutValue(pColData, pColVal); + return tColDataPutValue(pColData, NULL, 0); } -static int32_t (*tColDataAppendValueImpl[8][3])(SColData *pColData, SColVal *pColVal) = { +static int32_t (*tColDataAppendValueImpl[8][3])(SColData *pColData, uint8_t *pData, uint32_t nData) = { {tColDataAppendValue00, tColDataAppendValue01, tColDataAppendValue02}, // 0 {tColDataAppendValue10, tColDataAppendValue11, tColDataAppendValue12}, // HAS_NONE {tColDataAppendValue20, tColDataAppendValue21, tColDataAppendValue22}, // HAS_NULL @@ -1560,10 +1946,325 @@ static int32_t (*tColDataAppendValueImpl[8][3])(SColData *pColData, SColVal *pCo {tColDataAppendValue50, tColDataAppendValue51, tColDataAppendValue52}, // HAS_VALUE|HAS_NONE {tColDataAppendValue60, tColDataAppendValue61, tColDataAppendValue62}, // HAS_VALUE|HAS_NULL {tColDataAppendValue70, tColDataAppendValue71, tColDataAppendValue72}, // HAS_VALUE|HAS_NULL|HAS_NONE + + // VALUE NONE NULL }; int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) { ASSERT(pColData->cid == pColVal->cid && pColData->type == pColVal->type); - return tColDataAppendValueImpl[pColData->flag][pColVal->flag](pColData, pColVal); + return tColDataAppendValueImpl[pColData->flag][pColVal->flag]( + pColData, IS_VAR_DATA_TYPE(pColData->type) ? pColVal->value.pData : (uint8_t *)&pColVal->value.val, + pColVal->value.nData); +} + +static FORCE_INLINE int32_t tColDataUpdateValue10(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + pColData->numOfNone--; + pColData->nVal--; + if (pColData->numOfNone) { + return tColDataAppendValue10(pColData, pData, nData); + } else { + pColData->flag = 0; + return tColDataAppendValue00(pColData, pData, nData); + } +} +static FORCE_INLINE int32_t tColDataUpdateValue12(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + pColData->numOfNone--; + pColData->nVal--; + if (pColData->numOfNone) { + return tColDataAppendValue12(pColData, pData, nData); + } else { + pColData->flag = 0; + return tColDataAppendValue02(pColData, pData, nData); + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue20(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + if (forward) { + pColData->numOfNull--; + pColData->nVal--; + if (pColData->numOfNull) { + return tColDataAppendValue20(pColData, pData, nData); + } else { + pColData->flag = 0; + return tColDataAppendValue00(pColData, pData, nData); + } + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue30(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + if (GET_BIT1(pColData->pBitMap, pColData->nVal - 1) == 0) { // NONE ==> VALUE + pColData->numOfNone--; + pColData->nVal--; + if (pColData->numOfNone) { + return tColDataAppendValue30(pColData, pData, nData); + } else { + pColData->flag = HAS_NULL; + return tColDataAppendValue20(pColData, pData, nData); + } + } else if (forward) { // NULL ==> VALUE + pColData->numOfNull--; + pColData->nVal--; + if (pColData->numOfNull) { + return tColDataAppendValue30(pColData, pData, nData); + } else { + pColData->flag = HAS_NONE; + return tColDataAppendValue10(pColData, pData, nData); + } + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue32(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + if (GET_BIT1(pColData->pBitMap, pColData->nVal - 1) == 0) { // NONE ==> NULL + pColData->numOfNone--; + pColData->numOfNull++; + if (pColData->numOfNone) { + SET_BIT1(pColData->pBitMap, pColData->nVal - 1, 1); + } else { + pColData->flag = HAS_NULL; + } + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue40(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + if (forward) { // VALUE ==> VALUE + pColData->nVal--; + if (IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData = pColData->aOffset[pColData->nVal]; + } else { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + return tColDataPutValue(pColData, pData, nData); + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue42(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + if (forward) { // VALUE ==> NULL + pColData->numOfValue--; + pColData->nVal--; + if (pColData->numOfValue) { + if (IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData = pColData->aOffset[pColData->nVal]; + } else { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + return tColDataAppendValue42(pColData, pData, nData); + } else { + pColData->flag = 0; + pColData->nData = 0; + return tColDataAppendValue02(pColData, pData, nData); + } + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue50(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + if (GET_BIT1(pColData->pBitMap, pColData->nVal - 1) == 0) { // NONE ==> VALUE + pColData->numOfNone--; + pColData->nVal--; + if (!IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + if (pColData->numOfNone) { + return tColDataAppendValue50(pColData, pData, nData); + } else { + pColData->flag = HAS_VALUE; + return tColDataAppendValue40(pColData, pData, nData); + } + } else if (forward) { // VALUE ==> VALUE + pColData->nVal--; + if (IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData = pColData->aOffset[pColData->nVal]; + } else { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + return tColDataPutValue(pColData, pData, nData); + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue52(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + if (GET_BIT1(pColData->pBitMap, pColData->nVal - 1) == 0) { // NONE ==> NULL + pColData->numOfNone--; + pColData->nVal--; + if (!IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + if (pColData->numOfNone) { + return tColDataAppendValue52(pColData, pData, nData); + } else { + pColData->flag = HAS_VALUE; + return tColDataAppendValue42(pColData, pData, nData); + } + } else if (forward) { // VALUE ==> NULL + pColData->numOfValue--; + pColData->nVal--; + if (pColData->numOfValue) { + if (IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData = pColData->aOffset[pColData->nVal]; + } else { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + return tColDataAppendValue52(pColData, pData, nData); + } else { + pColData->flag = HAS_NONE; + pColData->nData = 0; + return tColDataAppendValue12(pColData, pData, nData); + } + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue60(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + if (forward) { + if (GET_BIT1(pColData->pBitMap, pColData->nVal - 1) == 0) { // NULL ==> VALUE + pColData->numOfNull--; + pColData->nVal--; + if (!IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + if (pColData->numOfNull) { + return tColDataAppendValue60(pColData, pData, nData); + } else { + pColData->flag = HAS_VALUE; + return tColDataAppendValue40(pColData, pData, nData); + } + } else { // VALUE ==> VALUE + pColData->nVal--; + if (IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData = pColData->aOffset[pColData->nVal]; + } else { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + return tColDataPutValue(pColData, pData, nData); + } + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue62(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + if (forward && (GET_BIT1(pColData->pBitMap, pColData->nVal - 1) == 1)) { // VALUE ==> NULL + pColData->numOfValue--; + pColData->nVal--; + if (pColData->numOfValue) { + if (IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData = pColData->aOffset[pColData->nVal]; + } else { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + return tColDataAppendValue62(pColData, pData, nData); + } else { + pColData->flag = HAS_NULL; + pColData->nData = 0; + return tColDataAppendValue20(pColData, pData, nData); + } + } + return 0; +} +static FORCE_INLINE int32_t tColDataUpdateValue70(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + int32_t code = 0; + + uint8_t bv = GET_BIT2(pColData->pBitMap, pColData->nVal - 1); + if (bv == 0) { // NONE ==> VALUE + pColData->numOfNone--; + pColData->nVal--; + if (!IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + if (pColData->numOfNone) { + return tColDataAppendValue70(pColData, pData, nData); + } else { + for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) { + SET_BIT1(pColData->pBitMap, iVal, GET_BIT2(pColData->pBitMap, iVal) - 1); + } + pColData->flag = (HAS_VALUE | HAS_NULL); + return tColDataAppendValue60(pColData, pData, nData); + } + } else if (bv == 1) { // NULL ==> VALUE + if (forward) { + pColData->numOfNull--; + pColData->nVal--; + if (!IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + if (pColData->numOfNull) { + return tColDataAppendValue70(pColData, pData, nData); + } else { + for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) { + SET_BIT1(pColData->pBitMap, iVal, GET_BIT2(pColData->pBitMap, iVal) ? 1 : 0); + } + pColData->flag = (HAS_VALUE | HAS_NONE); + return tColDataAppendValue50(pColData, pData, nData); + } + } + } else if (bv == 2) { // VALUE ==> VALUE + if (forward) { + pColData->nVal--; + if (IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData = pColData->aOffset[pColData->nVal]; + } else { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + return tColDataPutValue(pColData, pData, nData); + } + } else { + ASSERT(0); + } + return 0; +} +static int32_t tColDataUpdateValue72(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) { + uint8_t bv = GET_BIT2(pColData->pBitMap, pColData->nVal - 1); + if (bv == 0) { // NONE ==> NULL + pColData->numOfNone--; + pColData->nVal--; + if (!IS_VAR_DATA_TYPE(pColData->type)) { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + if (pColData->numOfNone) { + return tColDataAppendValue72(pColData, pData, nData); + } else { + for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) { + SET_BIT1(pColData->pBitMap, iVal, GET_BIT2(pColData->pBitMap, iVal) - 1); + } + pColData->flag = (HAS_VALUE | HAS_NULL); + return tColDataAppendValue62(pColData, pData, nData); + } + } else if (bv == 2 && forward) { // VALUE ==> NULL + pColData->numOfValue--; + pColData->nVal--; + if (pColData->numOfValue) { + if (IS_STR_DATA_TYPE(pColData->type)) { + pColData->nData = pColData->aOffset[pColData->nVal]; + } else { + pColData->nData -= TYPE_BYTES[pColData->type]; + } + return tColDataAppendValue72(pColData, pData, nData); + } else { + for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) { + SET_BIT1(pColData->pBitMap, iVal, GET_BIT2(pColData->pBitMap, iVal)); + } + pColData->flag = (HAS_NULL | HAS_NONE); + pColData->nData = 0; + return tColDataAppendValue32(pColData, pData, nData); + } + } + return 0; +} +static int32_t (*tColDataUpdateValueImpl[8][3])(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward) = { + {NULL, NULL, NULL}, // 0 + {tColDataUpdateValue10, NULL, tColDataUpdateValue12}, // HAS_NONE + {tColDataUpdateValue20, NULL, NULL}, // HAS_NULL + {tColDataUpdateValue30, NULL, tColDataUpdateValue32}, // HAS_NULL|HAS_NONE + {tColDataUpdateValue40, NULL, tColDataUpdateValue42}, // HAS_VALUE + {tColDataUpdateValue50, NULL, tColDataUpdateValue52}, // HAS_VALUE|HAS_NONE + {tColDataUpdateValue60, NULL, tColDataUpdateValue62}, // HAS_VALUE|HAS_NULL + {tColDataUpdateValue70, NULL, tColDataUpdateValue72}, // HAS_VALUE|HAS_NULL|HAS_NONE + + // VALUE NONE NULL +}; +int32_t tColDataUpdateValue(SColData *pColData, SColVal *pColVal, bool forward) { + ASSERT(pColData->cid == pColVal->cid && pColData->type == pColVal->type); + ASSERT(pColData->nVal > 0); + + if (tColDataUpdateValueImpl[pColData->flag][pColVal->flag] == NULL) return 0; + + return tColDataUpdateValueImpl[pColData->flag][pColVal->flag]( + pColData, IS_VAR_DATA_TYPE(pColData->type) ? pColVal->value.pData : (uint8_t *)&pColVal->value.val, + pColVal->value.nData, forward); } static FORCE_INLINE void tColDataGetValue1(SColData *pColData, int32_t iVal, SColVal *pColVal) { // HAS_NONE @@ -1572,7 +2273,8 @@ static FORCE_INLINE void tColDataGetValue1(SColData *pColData, int32_t iVal, SCo static FORCE_INLINE void tColDataGetValue2(SColData *pColData, int32_t iVal, SColVal *pColVal) { // HAS_NULL *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); } -static FORCE_INLINE void tColDataGetValue3(SColData *pColData, int32_t iVal, SColVal *pColVal) { // HAS_NULL|HAS_NONE +static FORCE_INLINE void tColDataGetValue3(SColData *pColData, int32_t iVal, + SColVal *pColVal) { // HAS_NULL|HAS_NONE switch (GET_BIT1(pColData->pBitMap, iVal)) { case 0: *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); @@ -1656,75 +2358,808 @@ void tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) { } uint8_t tColDataGetBitValue(const SColData *pColData, int32_t iVal) { - uint8_t v; switch (pColData->flag) { case HAS_NONE: - v = 0; - break; + return 0; case HAS_NULL: - v = 1; - break; + return 1; case (HAS_NULL | HAS_NONE): - v = GET_BIT1(pColData->pBitMap, iVal); - break; + return GET_BIT1(pColData->pBitMap, iVal); case HAS_VALUE: - v = 2; - break; + return 2; + case (HAS_VALUE | HAS_NONE): + return (GET_BIT1(pColData->pBitMap, iVal)) ? 2 : 0; + case (HAS_VALUE | HAS_NULL): + return GET_BIT1(pColData->pBitMap, iVal) + 1; + case (HAS_VALUE | HAS_NULL | HAS_NONE): + return GET_BIT2(pColData->pBitMap, iVal); + default: + ASSERTS(0, "not possible"); + return 0; + } +} + +int32_t tColDataCopy(SColData *pColDataFrom, SColData *pColData, xMallocFn xMalloc, void *arg) { + int32_t code = 0; + + *pColData = *pColDataFrom; + + // bitmap + switch (pColData->flag) { + case (HAS_NULL | HAS_NONE): case (HAS_VALUE | HAS_NONE): - v = GET_BIT1(pColData->pBitMap, iVal); - if (v) v = 2; - break; case (HAS_VALUE | HAS_NULL): - v = GET_BIT1(pColData->pBitMap, iVal) + 1; + pColData->pBitMap = xMalloc(arg, BIT1_SIZE(pColData->nVal)); + if (pColData->pBitMap == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + memcpy(pColData->pBitMap, pColDataFrom->pBitMap, BIT1_SIZE(pColData->nVal)); break; case (HAS_VALUE | HAS_NULL | HAS_NONE): - v = GET_BIT2(pColData->pBitMap, iVal); + pColData->pBitMap = xMalloc(arg, BIT2_SIZE(pColData->nVal)); + if (pColData->pBitMap == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + memcpy(pColData->pBitMap, pColDataFrom->pBitMap, BIT2_SIZE(pColData->nVal)); break; default: - ASSERT(0); + pColData->pBitMap = NULL; break; } - return v; + + // offset + if (IS_VAR_DATA_TYPE(pColData->type) && (pColData->flag & HAS_VALUE)) { + pColData->aOffset = xMalloc(arg, pColData->nVal << 2); + if (pColData->aOffset == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + memcpy(pColData->aOffset, pColDataFrom->aOffset, pColData->nVal << 2); + } else { + pColData->aOffset = NULL; + } + + // value + if (pColData->nData) { + pColData->pData = xMalloc(arg, pColData->nData); + if (pColData->pData == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + memcpy(pColData->pData, pColDataFrom->pData, pColData->nData); + } else { + pColData->pData = NULL; + } + +_exit: + return code; } -int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest) { +int32_t tColDataAddValueByDataBlock(SColData *pColData, int8_t type, int32_t bytes, int32_t nRows, char *lengthOrbitmap, + char *data) { int32_t code = 0; - int32_t size; + if(data == NULL){ + for (int32_t i = 0; i < nRows; ++i) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NONE](pColData, NULL, 0); + } + goto _exit; + } - ASSERT(pColDataSrc->nVal > 0); - ASSERT(pColDataDest->cid == pColDataSrc->cid); - ASSERT(pColDataDest->type == pColDataSrc->type); + if (IS_VAR_DATA_TYPE(type)) { // var-length data type + for (int32_t i = 0; i < nRows; ++i) { + int32_t offset = *((int32_t *)lengthOrbitmap + i); + if (offset == -1) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0); + if (code) goto _exit; + } else { + if(ASSERT(varDataTLen(data + offset) <= bytes)){ + uError("var data length invalid, varDataTLen(data + offset):%d <= bytes:%d", (int)varDataTLen(data + offset), bytes); + code = TSDB_CODE_INVALID_PARA; + goto _exit; + } + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, (uint8_t *)varDataVal(data + offset), + varDataLen(data + offset)); + } + } + } else { // fixed-length data type + bool allValue = true; + bool allNull = true; + for (int32_t i = 0; i < nRows; ++i) { + if (!colDataIsNull_f(lengthOrbitmap, i)) { + allNull = false; + } else { + allValue = false; + } + } - pColDataDest->smaOn = pColDataSrc->smaOn; - pColDataDest->nVal = pColDataSrc->nVal; - pColDataDest->flag = pColDataSrc->flag; + if (allValue) { + // optimize (todo) + for (int32_t i = 0; i < nRows; ++i) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, (uint8_t *)data + bytes * i, bytes); + } + } else if (allNull) { + // optimize (todo) + for (int32_t i = 0; i < nRows; ++i) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0); + if (code) goto _exit; + } + } else { + for (int32_t i = 0; i < nRows; ++i) { + if (colDataIsNull_f(lengthOrbitmap, i)) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0); + if (code) goto _exit; + } else { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE](pColData, (uint8_t *)data + bytes * i, bytes); + } + } + } + } + +_exit: + return code; +} + +int32_t tColDataAddValueByBind(SColData *pColData, TAOS_MULTI_BIND *pBind) { + int32_t code = 0; + + if (!(pBind->num == 1 && pBind->is_null && *pBind->is_null)) { + ASSERT(pColData->type == pBind->buffer_type); + } + + if (IS_VAR_DATA_TYPE(pColData->type)) { // var-length data type + for (int32_t i = 0; i < pBind->num; ++i) { + if (pBind->is_null && pBind->is_null[i]) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0); + if (code) goto _exit; + } else { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE]( + pColData, (uint8_t *)pBind->buffer + pBind->buffer_length * i, pBind->length[i]); + } + } + } else { // fixed-length data type + bool allValue; + bool allNull; + if (pBind->is_null) { + bool same = (memcmp(pBind->is_null, pBind->is_null + 1, pBind->num - 1) == 0); + allNull = (same && pBind->is_null[0] != 0); + allValue = (same && pBind->is_null[0] == 0); + } else { + allNull = false; + allValue = true; + } + + if (allValue) { + // optimize (todo) + for (int32_t i = 0; i < pBind->num; ++i) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE]( + pColData, (uint8_t *)pBind->buffer + TYPE_BYTES[pColData->type] * i, pBind->buffer_length); + } + } else if (allNull) { + // optimize (todo) + for (int32_t i = 0; i < pBind->num; ++i) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0); + if (code) goto _exit; + } + } else { + for (int32_t i = 0; i < pBind->num; ++i) { + if (pBind->is_null[i]) { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0); + if (code) goto _exit; + } else { + code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_VALUE]( + pColData, (uint8_t *)pBind->buffer + TYPE_BYTES[pColData->type] * i, pBind->buffer_length); + } + } + } + } + +_exit: + return code; +} + +static int32_t tColDataSwapValue(SColData *pColData, int32_t i, int32_t j) { + int32_t code = 0; + + if (IS_VAR_DATA_TYPE(pColData->type)) { + int32_t nData1 = pColData->aOffset[i + 1] - pColData->aOffset[i]; + int32_t nData2 = (j < pColData->nVal - 1) ? pColData->aOffset[j + 1] - pColData->aOffset[j] + : pColData->nData - pColData->aOffset[j]; + uint8_t *pData = taosMemoryMalloc(TMAX(nData1, nData2)); + if (pData == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + if (nData1 > nData2) { + memcpy(pData, pColData->pData + pColData->aOffset[i], nData1); + memcpy(pColData->pData + pColData->aOffset[i], pColData->pData + pColData->aOffset[j], nData2); + // memmove(pColData->pData + pColData->aOffset[i] + nData2, pColData->pData + pColData->aOffset[i] + nData1, + // pColData->aOffset[j] - pColData->aOffset[i + 1]); + memmove(pColData->pData + pColData->aOffset[i] + nData2, pColData->pData + pColData->aOffset[i + 1], + pColData->aOffset[j] - pColData->aOffset[i + 1]); + memcpy(pColData->pData + pColData->aOffset[j] + nData2 - nData1, pData, nData1); + } else { + memcpy(pData, pColData->pData + pColData->aOffset[j], nData2); + memcpy(pColData->pData + pColData->aOffset[j] + nData2 - nData1, pColData->pData + pColData->aOffset[i], nData1); + // memmove(pColData->pData + pColData->aOffset[j] + nData2 - nData1, pColData->pData + pColData->aOffset[i] + + // nData1, + // pColData->aOffset[j] - pColData->aOffset[i + 1]); + memmove(pColData->pData + pColData->aOffset[i] + nData2, pColData->pData + pColData->aOffset[i + 1], + pColData->aOffset[j] - pColData->aOffset[i + 1]); + memcpy(pColData->pData + pColData->aOffset[i], pData, nData2); + } + for (int32_t k = i + 1; k <= j; ++k) { + pColData->aOffset[k] = pColData->aOffset[k] + nData2 - nData1; + } + + taosMemoryFree(pData); + } else { + uint64_t val; + memcpy(&val, &pColData->pData[TYPE_BYTES[pColData->type] * i], TYPE_BYTES[pColData->type]); + memcpy(&pColData->pData[TYPE_BYTES[pColData->type] * i], &pColData->pData[TYPE_BYTES[pColData->type] * j], + TYPE_BYTES[pColData->type]); + memcpy(&pColData->pData[TYPE_BYTES[pColData->type] * j], &val, TYPE_BYTES[pColData->type]); + } + +_exit: + return code; +} + +static void tColDataSwap(SColData *pColData, int32_t i, int32_t j) { + ASSERT(i < j); + ASSERT(j < pColData->nVal); + + switch (pColData->flag) { + case HAS_NONE: + case HAS_NULL: + break; + case (HAS_NULL | HAS_NONE): { + uint8_t bv = GET_BIT1(pColData->pBitMap, i); + SET_BIT1(pColData->pBitMap, i, GET_BIT1(pColData->pBitMap, j)); + SET_BIT1(pColData->pBitMap, j, bv); + } break; + case HAS_VALUE: { + tColDataSwapValue(pColData, i, j); + } break; + case (HAS_VALUE | HAS_NONE): + case (HAS_VALUE | HAS_NULL): { + uint8_t bv = GET_BIT1(pColData->pBitMap, i); + SET_BIT1(pColData->pBitMap, i, GET_BIT1(pColData->pBitMap, j)); + SET_BIT1(pColData->pBitMap, j, bv); + tColDataSwapValue(pColData, i, j); + } break; + case (HAS_VALUE | HAS_NULL | HAS_NONE): { + uint8_t bv = GET_BIT2(pColData->pBitMap, i); + SET_BIT2(pColData->pBitMap, i, GET_BIT2(pColData->pBitMap, j)); + SET_BIT2(pColData->pBitMap, j, bv); + tColDataSwapValue(pColData, i, j); + } break; + default: + ASSERT(0); + break; + } +} + +static int32_t tColDataCopyRowCell(SColData *pFromColData, int32_t iFromRow, SColData *pToColData, int32_t iToRow) { + int32_t code = TSDB_CODE_SUCCESS; + + if (IS_VAR_DATA_TYPE(pToColData->type)) { + int32_t nData = (iFromRow < pFromColData->nVal - 1) + ? pFromColData->aOffset[iFromRow + 1] - pFromColData->aOffset[iFromRow] + : pFromColData->nData - pFromColData->aOffset[iFromRow]; + if (iToRow == 0) { + pToColData->aOffset[iToRow] = 0; + } + + if (iToRow < pToColData->nVal - 1) { + pToColData->aOffset[iToRow + 1] = pToColData->aOffset[iToRow] + nData; + } + + memcpy(pToColData->pData + pToColData->aOffset[iToRow], pFromColData->pData + pFromColData->aOffset[iFromRow], + nData); + } else { + memcpy(&pToColData->pData[TYPE_BYTES[pToColData->type] * iToRow], + &pFromColData->pData[TYPE_BYTES[pToColData->type] * iFromRow], TYPE_BYTES[pToColData->type]); + } + return code; +} + +static int32_t tColDataCopyRowSingleCol(SColData *pFromColData, int32_t iFromRow, SColData *pToColData, + int32_t iToRow) { + int32_t code = TSDB_CODE_SUCCESS; + + switch (pFromColData->flag) { + case HAS_NONE: + case HAS_NULL: + break; + case (HAS_NULL | HAS_NONE): { + SET_BIT1(pToColData->pBitMap, iToRow, GET_BIT1(pFromColData->pBitMap, iFromRow)); + } break; + case HAS_VALUE: { + tColDataCopyRowCell(pFromColData, iFromRow, pToColData, iToRow); + } break; + case (HAS_VALUE | HAS_NONE): + case (HAS_VALUE | HAS_NULL): { + SET_BIT1(pToColData->pBitMap, iToRow, GET_BIT1(pFromColData->pBitMap, iFromRow)); + tColDataCopyRowCell(pFromColData, iFromRow, pToColData, iToRow); + } break; + case (HAS_VALUE | HAS_NULL | HAS_NONE): { + SET_BIT2(pToColData->pBitMap, iToRow, GET_BIT2(pFromColData->pBitMap, iFromRow)); + tColDataCopyRowCell(pFromColData, iFromRow, pToColData, iToRow); + } break; + default: + return -1; + } + + return code; +} + +static int32_t tColDataCopyRow(SColData *aFromColData, int32_t iFromRow, SColData *aToColData, int32_t iToRow, + int32_t nColData) { + int32_t code = TSDB_CODE_SUCCESS; + + for (int32_t i = 0; i < nColData; i++) { + code = tColDataCopyRowSingleCol(&aFromColData[i], iFromRow, &aToColData[i], iToRow); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + + return code; +} + +static int32_t tColDataCopyRowAppend(SColData *aFromColData, int32_t iFromRow, SColData *aToColData, int32_t nColData) { + int32_t code = TSDB_CODE_SUCCESS; + + for (int32_t i = 0; i < nColData; i++) { + SColVal cv = {0}; + tColDataGetValue(&aFromColData[i], iFromRow, &cv); + code = tColDataAppendValue(&aToColData[i], &cv); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + + return code; +} + +static int32_t tColDataMergeSortMerge(SColData *aColData, int32_t start, int32_t mid, int32_t end, int32_t nColData) { + SColData *aDstColData = NULL; + TSKEY *aKey = (TSKEY *)aColData[0].pData; + + int32_t i = start, j = mid + 1, k = 0; + + if (end > start) { + aDstColData = taosMemoryCalloc(1, sizeof(SColData) * nColData); + for (int c = 0; c < nColData; ++c) { + tColDataInit(&aDstColData[c], aColData[c].cid, aColData[c].type, aColData[c].smaOn); + } + if (aDstColData == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + /* + for (int32_t i = 0; i < nColData; i++) { + tColDataCopy(&aColData[i], &aDstColData[i], tColDataDefaultMalloc, NULL); + } + */ + } + + while (i <= mid && j <= end) { + if (aKey[i] <= aKey[j]) { + // tColDataCopyRow(aColData, i++, aDstColData, k++); + tColDataCopyRowAppend(aColData, i++, aDstColData, nColData); + } else { + // tColDataCopyRow(aColData, j++, aDstColData, k++); + tColDataCopyRowAppend(aColData, j++, aDstColData, nColData); + } + } + + while (i <= mid) { + // tColDataCopyRow(aColData, i++, aDstColData, k++); + tColDataCopyRowAppend(aColData, i++, aDstColData, nColData); + } + + while (j <= end) { + // tColDataCopyRow(aColData, j++, aDstColData, k++); + tColDataCopyRowAppend(aColData, j++, aDstColData, nColData); + } + + for (i = start, k = 0; i <= end; ++i, ++k) { + tColDataCopyRow(aDstColData, k, aColData, i, nColData); + } + + if (aDstColData) { + for (int32_t i = 0; i < nColData; i++) { + tColDataDestroy(&aDstColData[i]); + } + taosMemoryFree(aDstColData); + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t tColDataMergeSort(SColData *aColData, int32_t start, int32_t end, int32_t nColData) { + int32_t ret = TSDB_CODE_SUCCESS; + int32_t mid; + + if (start >= end) { + return TSDB_CODE_SUCCESS; + } + + mid = (start + end) / 2; + + ret = tColDataMergeSort(aColData, start, mid, nColData); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + + ret = tColDataMergeSort(aColData, mid + 1, end, nColData); + if (ret != TSDB_CODE_SUCCESS) { + return ret; + } + + return tColDataMergeSortMerge(aColData, start, mid, end, nColData); +} + +static int32_t tColDataSort(SColData *aColData, int32_t nColData) { + int32_t nVal = aColData[0].nVal; + + if (nVal < 2) return TSDB_CODE_SUCCESS; + + return tColDataMergeSort(aColData, 0, nVal - 1, nColData); +} +static void tColDataMergeImpl(SColData *pColData, int32_t iStart, int32_t iEnd /* not included */) { + switch (pColData->flag) { + case HAS_NONE: + case HAS_NULL: { + pColData->nVal -= (iEnd - iStart - 1); + } break; + case (HAS_NULL | HAS_NONE): { + if (GET_BIT1(pColData->pBitMap, iStart) == 0) { + for (int32_t i = iStart + 1; i < iEnd; ++i) { + if (GET_BIT1(pColData->pBitMap, i) == 1) { + SET_BIT1(pColData->pBitMap, iStart, 1); + break; + } + } + } + for (int32_t i = iEnd, j = iStart + 1; i < pColData->nVal; ++i, ++j) { + SET_BIT1(pColData->pBitMap, j, GET_BIT1(pColData->pBitMap, i)); + } + + pColData->nVal -= (iEnd - iStart - 1); + + uint8_t flag = 0; + for (int32_t i = 0; i < pColData->nVal; ++i) { + uint8_t bv = GET_BIT1(pColData->pBitMap, i); + if (bv == BIT_FLG_NONE) { + flag |= HAS_NONE; + } else if (bv == BIT_FLG_NULL) { + flag |= HAS_NULL; + } else { + ASSERT(0); + } + + if (flag == pColData->flag) break; + } + pColData->flag = flag; + } break; + case HAS_VALUE: { + if (IS_VAR_DATA_TYPE(pColData->type)) { + int32_t nDiff = pColData->aOffset[iEnd - 1] - pColData->aOffset[iStart]; + + memmove(pColData->pData + pColData->aOffset[iStart], pColData->pData + pColData->aOffset[iEnd - 1], + pColData->nData - pColData->aOffset[iEnd - 1]); + pColData->nData -= nDiff; + + for (int32_t i = iEnd, j = iStart + 1; i < pColData->nVal; ++i, ++j) { + pColData->aOffset[j] = pColData->aOffset[i] - nDiff; + } + } else { + memmove(pColData->pData + TYPE_BYTES[pColData->type] * iStart, + pColData->pData + TYPE_BYTES[pColData->type] * (iEnd - 1), + TYPE_BYTES[pColData->type] * (pColData->nVal - iEnd + 1)); + pColData->nData -= (TYPE_BYTES[pColData->type] * (iEnd - iStart - 1)); + } + + pColData->nVal -= (iEnd - iStart - 1); + } break; + case (HAS_VALUE | HAS_NONE): { + uint8_t bv; + int32_t iv; + for (int32_t i = iEnd - 1; i >= iStart; --i) { + bv = GET_BIT1(pColData->pBitMap, i); + if (bv) { + iv = i; + break; + } + } + + if (bv) { // has a value + if (IS_VAR_DATA_TYPE(pColData->type)) { + if (iv != iStart) { + memmove(&pColData->pData[pColData->aOffset[iStart]], &pColData->pData[pColData->aOffset[iv]], + iv < (pColData->nVal - 1) ? pColData->aOffset[iv + 1] - pColData->aOffset[iv] + : pColData->nData - pColData->aOffset[iv]); + } + // TODO + ASSERT(0); + } else { + if (iv != iStart) { + memcpy(&pColData->pData[TYPE_BYTES[pColData->type] * iStart], + &pColData->pData[TYPE_BYTES[pColData->type] * iv], TYPE_BYTES[pColData->type]); + } + memmove(&pColData->pData[TYPE_BYTES[pColData->type] * (iStart + 1)], + &pColData->pData[TYPE_BYTES[pColData->type] * iEnd], + TYPE_BYTES[pColData->type] * (iEnd - iStart - 1)); + pColData->nData -= (TYPE_BYTES[pColData->type] * (iEnd - iStart - 1)); + } + + SET_BIT1(pColData->pBitMap, iStart, 1); + for (int32_t i = iEnd, j = iStart + 1; i < pColData->nVal; ++i, ++j) { + SET_BIT1(pColData->pBitMap, j, GET_BIT1(pColData->pBitMap, i)); + } + + uint8_t flag = HAS_VALUE; + for (int32_t i = 0; i < pColData->nVal - (iEnd - iStart - 1); ++i) { + if (GET_BIT1(pColData->pBitMap, i) == 0) { + flag |= HAS_NONE; + } + + if (flag == pColData->flag) break; + } + pColData->flag = flag; + } else { // all NONE + if (IS_VAR_DATA_TYPE(pColData->type)) { + int32_t nDiff = pColData->aOffset[iEnd - 1] - pColData->aOffset[iStart]; + + memmove(&pColData->pData[pColData->aOffset[iStart]], &pColData->pData[pColData->aOffset[iEnd - 1]], + pColData->nData - pColData->aOffset[iEnd - 1]); + pColData->nData -= nDiff; + + for (int32_t i = iEnd, j = iStart + 1; i < pColData->nVal; ++i, ++j) { + pColData->aOffset[j] = pColData->aOffset[i] - nDiff; + } + } else { + memmove(pColData->pData + TYPE_BYTES[pColData->type] * (iStart + 1), + pColData->pData + TYPE_BYTES[pColData->type] * iEnd, + TYPE_BYTES[pColData->type] * (pColData->nVal - iEnd + 1)); + pColData->nData -= (TYPE_BYTES[pColData->type] * (iEnd - iStart - 1)); + } + + for (int32_t i = iEnd, j = iStart + 1; i < pColData->nVal; ++i, ++j) { + SET_BIT1(pColData->pBitMap, j, GET_BIT1(pColData->pBitMap, i)); + } + } + pColData->nVal -= (iEnd - iStart - 1); + } break; + case (HAS_VALUE | HAS_NULL): { + if (IS_VAR_DATA_TYPE(pColData->type)) { + int32_t nDiff = pColData->aOffset[iEnd - 1] - pColData->aOffset[iStart]; + + memmove(pColData->pData + pColData->aOffset[iStart], pColData->pData + pColData->aOffset[iEnd - 1], + pColData->nData - pColData->aOffset[iEnd - 1]); + pColData->nData -= nDiff; + + for (int32_t i = iEnd, j = iStart + 1; i < pColData->nVal; ++i, ++j) { + pColData->aOffset[j] = pColData->aOffset[i] - nDiff; + } + } else { + memmove(pColData->pData + TYPE_BYTES[pColData->type] * iStart, + pColData->pData + TYPE_BYTES[pColData->type] * (iEnd - 1), + TYPE_BYTES[pColData->type] * (pColData->nVal - iEnd + 1)); + pColData->nData -= (TYPE_BYTES[pColData->type] * (iEnd - iStart - 1)); + } + + for (int32_t i = iEnd - 1, j = iStart; i < pColData->nVal; ++i, ++j) { + SET_BIT1(pColData->pBitMap, j, GET_BIT1(pColData->pBitMap, i)); + } + + pColData->nVal -= (iEnd - iStart - 1); + + uint8_t flag = 0; + for (int32_t i = 0; i < pColData->nVal; ++i) { + if (GET_BIT1(pColData->pBitMap, i)) { + flag |= HAS_VALUE; + } else { + flag |= HAS_NULL; + } + + if (flag == pColData->flag) break; + } + pColData->flag = flag; + } break; + case (HAS_VALUE | HAS_NULL | HAS_NONE): { + uint8_t bv; + int32_t iv; + for (int32_t i = iEnd - 1; i >= iStart; --i) { + bv = GET_BIT2(pColData->pBitMap, i); + if (bv) { + iv = i; + break; + } + } + + if (bv) { + // TODO + ASSERT(0); + } else { // ALL NONE + if (IS_VAR_DATA_TYPE(pColData->type)) { + // TODO + ASSERT(0); + } else { + memmove(pColData->pData + TYPE_BYTES[pColData->type] * (iStart + 1), + pColData->pData + TYPE_BYTES[pColData->type] * iEnd, + TYPE_BYTES[pColData->type] * (pColData->nVal - iEnd)); + pColData->nData -= (TYPE_BYTES[pColData->type] * (iEnd - iStart - 1)); + } + + for (int32_t i = iEnd, j = iStart + 1; i < pColData->nVal; ++i, ++j) { + SET_BIT2(pColData->pBitMap, j, GET_BIT2(pColData->pBitMap, i)); + } + } + pColData->nVal -= (iEnd - iStart - 1); + } break; + default: + ASSERT(0); + break; + } +} +static void tColDataMerge(SColData *aColData, int32_t nColData) { + int32_t iStart = 0; + for (;;) { + if (iStart >= aColData[0].nVal - 1) break; + + int32_t iEnd = iStart + 1; + while (iEnd < aColData[0].nVal) { + if (((TSKEY *)aColData[0].pData)[iEnd] != ((TSKEY *)aColData[0].pData)[iStart]) break; + + iEnd++; + } + + if (iEnd - iStart > 1) { + for (int32_t i = 0; i < nColData; i++) { + tColDataMergeImpl(&aColData[i], iStart, iEnd); + } + } + + iStart++; + } +} +void tColDataSortMerge(SArray *colDataArr) { + int32_t nColData = TARRAY_SIZE(colDataArr); + SColData *aColData = (SColData *)TARRAY_DATA(colDataArr); + + if (aColData[0].nVal <= 1) goto _exit; + + ASSERT(aColData[0].type == TSDB_DATA_TYPE_TIMESTAMP); + ASSERT(aColData[0].cid == PRIMARYKEY_TIMESTAMP_COL_ID); + ASSERT(aColData[0].flag == HAS_VALUE); + + int8_t doSort = 0; + int8_t doMerge = 0; + // scan ------- + TSKEY *aKey = (TSKEY *)aColData[0].pData; + for (int32_t iVal = 1; iVal < aColData[0].nVal; ++iVal) { + if (aKey[iVal] > aKey[iVal - 1]) { + continue; + } else if (aKey[iVal] < aKey[iVal - 1]) { + doSort = 1; + break; + } else { + doMerge = 1; + } + } + + // sort ------- + if (doSort) { + tColDataSort(aColData, nColData); + } + + if (doMerge != 1) { + for (int32_t iVal = 1; iVal < aColData[0].nVal; ++iVal) { + if (aKey[iVal] == aKey[iVal - 1]) { + doMerge = 1; + break; + } + } + } + + // merge ------- + if (doMerge) { + tColDataMerge(aColData, nColData); + } + +_exit: + return; +} + +int32_t tPutColData(uint8_t *pBuf, SColData *pColData) { + int32_t n = 0; + + n += tPutI16v(pBuf ? pBuf + n : NULL, pColData->cid); + n += tPutI8(pBuf ? pBuf + n : NULL, pColData->type); + n += tPutI32v(pBuf ? pBuf + n : NULL, pColData->nVal); + n += tPutI8(pBuf ? pBuf + n : NULL, pColData->flag); // bitmap - if (pColDataSrc->flag != HAS_NONE && pColDataSrc->flag != HAS_NULL && pColDataSrc->flag != HAS_VALUE) { - size = BIT2_SIZE(pColDataSrc->nVal); - code = tRealloc(&pColDataDest->pBitMap, size); - if (code) goto _exit; - memcpy(pColDataDest->pBitMap, pColDataSrc->pBitMap, size); + switch (pColData->flag) { + case (HAS_NULL | HAS_NONE): + case (HAS_VALUE | HAS_NONE): + case (HAS_VALUE | HAS_NULL): + if (pBuf) memcpy(pBuf + n, pColData->pBitMap, BIT1_SIZE(pColData->nVal)); + n += BIT1_SIZE(pColData->nVal); + break; + case (HAS_VALUE | HAS_NULL | HAS_NONE): + if (pBuf) memcpy(pBuf + n, pColData->pBitMap, BIT2_SIZE(pColData->nVal)); + n += BIT2_SIZE(pColData->nVal); + break; + default: + break; } - // offset - if (IS_VAR_DATA_TYPE(pColDataDest->type)) { - size = sizeof(int32_t) * pColDataSrc->nVal; + // value + if (pColData->flag & HAS_VALUE) { + if (IS_VAR_DATA_TYPE(pColData->type)) { + if (pBuf) memcpy(pBuf + n, pColData->aOffset, pColData->nVal << 2); + n += (pColData->nVal << 2); - code = tRealloc((uint8_t **)&pColDataDest->aOffset, size); - if (code) goto _exit; + n += tPutI32v(pBuf ? pBuf + n : NULL, pColData->nData); + if (pBuf) memcpy(pBuf + n, pColData->pData, pColData->nData); + n += pColData->nData; + } else { + if (pBuf) memcpy(pBuf + n, pColData->pData, pColData->nData); + n += pColData->nData; + } + } + + return n; +} + +int32_t tGetColData(uint8_t *pBuf, SColData *pColData) { + int32_t n = 0; + + n += tGetI16v(pBuf + n, &pColData->cid); + n += tGetI8(pBuf + n, &pColData->type); + n += tGetI32v(pBuf + n, &pColData->nVal); + n += tGetI8(pBuf + n, &pColData->flag); - memcpy(pColDataDest->aOffset, pColDataSrc->aOffset, size); + // bitmap + switch (pColData->flag) { + case (HAS_NULL | HAS_NONE): + case (HAS_VALUE | HAS_NONE): + case (HAS_VALUE | HAS_NULL): + pColData->pBitMap = pBuf + n; + n += BIT1_SIZE(pColData->nVal); + break; + case (HAS_VALUE | HAS_NULL | HAS_NONE): + pColData->pBitMap = pBuf + n; + n += BIT2_SIZE(pColData->nVal); + break; + default: + break; } // value - pColDataDest->nData = pColDataSrc->nData; - code = tRealloc(&pColDataDest->pData, pColDataSrc->nData); - if (code) goto _exit; - memcpy(pColDataDest->pData, pColDataSrc->pData, pColDataDest->nData); + if (pColData->flag & HAS_VALUE) { + if (IS_VAR_DATA_TYPE(pColData->type)) { + pColData->aOffset = (int32_t *)(pBuf + n); + n += (pColData->nVal << 2); -_exit: - return code; + n += tGetI32v(pBuf + n, &pColData->nData); + pColData->pData = pBuf + n; + n += pColData->nData; + } else { + pColData->pData = pBuf + n; + pColData->nData = TYPE_BYTES[pColData->type] * pColData->nVal; + n += pColData->nData; + } + } + + return n; } #define CALC_SUM_MAX_MIN(SUM, MAX, MIN, VAL) \ diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c index d4849650e6c80fcab7b3831f7fa01a10d29ec50b..b85dfa80b087504873486b82153c1d6d43eeb3f5 100644 --- a/source/common/src/tglobal.c +++ b/source/common/src/tglobal.c @@ -20,6 +20,10 @@ #include "tlog.h" #include "tmisce.h" +#if defined(CUS_NAME) || defined(CUS_PROMPT) || defined(CUS_EMAIL) +#include "cus_name.h" +#endif + GRANT_CFG_DECLARE; SConfig *tsCfg = NULL; @@ -41,6 +45,8 @@ bool tsPrintAuth = false; // queue & threads int32_t tsNumOfRpcThreads = 1; +int32_t tsNumOfRpcSessions = 10000; +int32_t tsTimeToGetAvailableConn = 500000; int32_t tsNumOfCommitThreads = 2; int32_t tsNumOfTaskQueueThreads = 4; int32_t tsNumOfMnodeQueryThreads = 4; @@ -61,7 +67,11 @@ int32_t tsHeartbeatInterval = 1000; int32_t tsHeartbeatTimeout = 20 * 1000; // vnode -int64_t tsVndCommitMaxIntervalMs = 60 * 1000; +int64_t tsVndCommitMaxIntervalMs = 600 * 1000; + +// mnode +int64_t tsMndSdbWriteDelta = 200; +int64_t tsMndLogRetention = 2000; // monitor bool tsEnableMonitor = true; @@ -74,26 +84,28 @@ bool tsMonitorComp = false; // telem bool tsEnableTelem = true; int32_t tsTelemInterval = 43200; -char tsTelemServer[TSDB_FQDN_LEN] = "telemetry.taosdata.com"; +char tsTelemServer[TSDB_FQDN_LEN] = "telemetry.tdengine.com"; uint16_t tsTelemPort = 80; -char* tsTelemUri = "/report"; +char *tsTelemUri = "/report"; -bool tsEnableCrashReport = true; -char* tsClientCrashReportUri = "/ccrashreport"; -char* tsSvrCrashReportUri = "/dcrashreport"; +bool tsEnableCrashReport = true; +char *tsClientCrashReportUri = "/ccrashreport"; +char *tsSvrCrashReportUri = "/dcrashreport"; // schemaless char tsSmlTagName[TSDB_COL_NAME_LEN] = "_tag_null"; char tsSmlChildTableName[TSDB_TABLE_NAME_LEN] = ""; // user defined child table name can be specified in tag value. // If set to empty system will generate table name using MD5 hash. // true means that the name and order of cols in each line are the same(only for influx protocol) -bool tsSmlDataFormat = false; -int32_t tsSmlBatchSize = 10000; +// bool tsSmlDataFormat = false; +// int32_t tsSmlBatchSize = 10000; // query int32_t tsQueryPolicy = 1; int32_t tsQueryRspPolicy = 0; +int64_t tsQueryMaxConcurrentTables = 200; // unit is TSDB_TABLE_NUM_UNIT bool tsEnableQueryHb = false; +bool tsEnableScience = false; // on taos-cli show float and doulbe with scientific notation if true int32_t tsQuerySmaOptimize = 0; int32_t tsQueryRsmaTolerance = 1000; // the tolerance time (ms) to judge from which level to query rsma data. bool tsQueryPlannerTrace = false; @@ -106,6 +118,7 @@ int32_t tsRedirectMaxPeriod = 1000; int32_t tsMaxRetryWaitTime = 10000; bool tsUseAdapter = false; + /* * denote if the server needs to compress response message at the application layer to client, including query rsp, * metricmeta rsp, and multi-meter query rsp message body. The client compress the submit message to server. @@ -148,6 +161,7 @@ char tsTagFilterCache = 0; // positive value (in MB) int32_t tsQueryBufferSize = -1; int64_t tsQueryBufferSizeBytes = -1; +int32_t tsCacheLazyLoadThreshold = 500; int32_t tsDiskCfgNum = 0; SDiskCfg tsDiskCfg[TFS_MAX_DISKS] = {0}; @@ -184,11 +198,12 @@ int32_t tsTransPullupInterval = 2; int32_t tsMqRebalanceInterval = 2; int32_t tsStreamCheckpointTickInterval = 1; int32_t tsTtlUnit = 86400; -int32_t tsTtlPushInterval = 86400; +int32_t tsTtlPushInterval = 3600; int32_t tsGrantHBInterval = 60; int32_t tsUptimeInterval = 300; // seconds char tsUdfdResFuncs[512] = ""; // udfd resident funcs that teardown when udfd exits char tsUdfdLdLibPath[512] = ""; +bool tsDisableStream = false; #ifndef _STORAGE int32_t taosSetTfsCfg(SConfig *pCfg) { @@ -211,9 +226,7 @@ int32_t taosSetTfsCfg(SConfig *pCfg) { int32_t taosSetTfsCfg(SConfig *pCfg); #endif -struct SConfig *taosGetCfg() { - return tsCfg; -} +struct SConfig *taosGetCfg() { return tsCfg; } static int32_t taosLoadCfg(SConfig *pCfg, const char **envCmd, const char *inputCfgDir, const char *envFile, char *apolloUrl) { @@ -222,7 +235,11 @@ static int32_t taosLoadCfg(SConfig *pCfg, const char **envCmd, const char *input taosExpandDir(inputCfgDir, cfgDir, PATH_MAX); if (taosIsDir(cfgDir)) { +#ifdef CUS_PROMPT + snprintf(cfgFile, sizeof(cfgFile), "%s" TD_DIRSEP "%s.cfg", cfgDir, CUS_PROMPT); +#else snprintf(cfgFile, sizeof(cfgFile), "%s" TD_DIRSEP "taos.cfg", cfgDir); +#endif } else { tstrncpy(cfgFile, cfgDir, sizeof(cfgDir)); } @@ -313,6 +330,7 @@ static int32_t taosAddClientCfg(SConfig *pCfg) { if (cfgAddInt32(pCfg, "compressColData", tsCompressColData, -1, 100000000, 1) != 0) return -1; if (cfgAddInt32(pCfg, "queryPolicy", tsQueryPolicy, 1, 4, 1) != 0) return -1; if (cfgAddBool(pCfg, "enableQueryHb", tsEnableQueryHb, false) != 0) return -1; + if (cfgAddBool(pCfg, "enableScience", tsEnableScience, false) != 0) return -1; if (cfgAddInt32(pCfg, "querySmaOptimize", tsQuerySmaOptimize, 0, 1, 1) != 0) return -1; if (cfgAddBool(pCfg, "queryPlannerTrace", tsQueryPlannerTrace, true) != 0) return -1; if (cfgAddInt32(pCfg, "queryNodeChunkSize", tsQueryNodeChunkSize, 1024, 128 * 1024, true) != 0) return -1; @@ -320,12 +338,23 @@ static int32_t taosAddClientCfg(SConfig *pCfg) { if (cfgAddBool(pCfg, "keepColumnName", tsKeepColumnName, true) != 0) return -1; if (cfgAddString(pCfg, "smlChildTableName", "", 1) != 0) return -1; if (cfgAddString(pCfg, "smlTagName", tsSmlTagName, 1) != 0) return -1; - if (cfgAddBool(pCfg, "smlDataFormat", tsSmlDataFormat, 1) != 0) return -1; - if (cfgAddInt32(pCfg, "smlBatchSize", tsSmlBatchSize, 1, INT32_MAX, true) != 0) return -1; + // if (cfgAddBool(pCfg, "smlDataFormat", tsSmlDataFormat, 1) != 0) return -1; + // if (cfgAddInt32(pCfg, "smlBatchSize", tsSmlBatchSize, 1, INT32_MAX, true) != 0) return -1; if (cfgAddInt32(pCfg, "maxMemUsedByInsert", tsMaxMemUsedByInsert, 1, INT32_MAX, true) != 0) return -1; if (cfgAddInt32(pCfg, "maxRetryWaitTime", tsMaxRetryWaitTime, 0, 86400000, 0) != 0) return -1; if (cfgAddBool(pCfg, "useAdapter", tsUseAdapter, true) != 0) return -1; if (cfgAddBool(pCfg, "crashReporting", tsEnableCrashReport, true) != 0) return -1; + if (cfgAddInt64(pCfg, "queryMaxConcurrentTables", tsQueryMaxConcurrentTables, INT64_MIN, INT64_MAX, 1) != 0) return -1; + + tsNumOfRpcThreads = tsNumOfCores / 2; + tsNumOfRpcThreads = TRANGE(tsNumOfRpcThreads, 2, TSDB_MAX_RPC_THREADS); + if (cfgAddInt32(pCfg, "numOfRpcThreads", tsNumOfRpcThreads, 1, 1024, 0) != 0) return -1; + + tsNumOfRpcSessions = TRANGE(tsNumOfRpcSessions, 100, 100000); + if (cfgAddInt32(pCfg, "numOfRpcSessions", tsNumOfRpcSessions, 1, 100000, 0) != 0) return -1; + + tsTimeToGetAvailableConn = TRANGE(tsTimeToGetAvailableConn, 20, 10000000); + if (cfgAddInt32(pCfg, "timeToGetAvailableConn", tsTimeToGetAvailableConn, 20, 1000000, 0) != 0) return -1; tsNumOfTaskQueueThreads = tsNumOfCores / 2; tsNumOfTaskQueueThreads = TMAX(tsNumOfTaskQueueThreads, 4); @@ -355,7 +384,9 @@ static int32_t taosAddSystemCfg(SConfig *pCfg) { if (cfgAddBool(pCfg, "tagFilterCache", tsTagFilterCache, 0) != 0) return -1; if (cfgAddInt64(pCfg, "openMax", tsOpenMax, 0, INT64_MAX, 1) != 0) return -1; +#if !defined(_ALPINE) if (cfgAddInt64(pCfg, "streamMax", tsStreamMax, 0, INT64_MAX, 1) != 0) return -1; +#endif if (cfgAddInt32(pCfg, "pageSizeKB", tsPageSizeKB, 0, INT64_MAX, 1) != 0) return -1; if (cfgAddInt64(pCfg, "totalMemoryKB", tsTotalMemoryKB, 0, INT64_MAX, 1) != 0) return -1; if (cfgAddString(pCfg, "os sysname", info.sysname, 1) != 0) return -1; @@ -390,9 +421,15 @@ static int32_t taosAddServerCfg(SConfig *pCfg) { if (cfgAddInt32(pCfg, "queryRspPolicy", tsQueryRspPolicy, 0, 1, 0) != 0) return -1; tsNumOfRpcThreads = tsNumOfCores / 2; - tsNumOfRpcThreads = TRANGE(tsNumOfRpcThreads, 1, TSDB_MAX_RPC_THREADS); + tsNumOfRpcThreads = TRANGE(tsNumOfRpcThreads, 2, TSDB_MAX_RPC_THREADS); if (cfgAddInt32(pCfg, "numOfRpcThreads", tsNumOfRpcThreads, 1, 1024, 0) != 0) return -1; + tsNumOfRpcSessions = TRANGE(tsNumOfRpcSessions, 100, 10000); + if (cfgAddInt32(pCfg, "numOfRpcSessions", tsNumOfRpcSessions, 1, 100000, 0) != 0) return -1; + + tsTimeToGetAvailableConn = TRANGE(tsTimeToGetAvailableConn, 20, 1000000); + if (cfgAddInt32(pCfg, "timeToGetAvailableConn", tsNumOfRpcSessions, 20, 1000000, 0) != 0) return -1; + tsNumOfCommitThreads = tsNumOfCores / 2; tsNumOfCommitThreads = TRANGE(tsNumOfCommitThreads, 2, 4); if (cfgAddInt32(pCfg, "numOfCommitThreads", tsNumOfCommitThreads, 1, 1024, 0) != 0) return -1; @@ -442,6 +479,9 @@ static int32_t taosAddServerCfg(SConfig *pCfg) { if (cfgAddInt64(pCfg, "vndCommitMaxInterval", tsVndCommitMaxIntervalMs, 1000, 1000 * 60 * 60, 0) != 0) return -1; + if (cfgAddInt64(pCfg, "mndSdbWriteDelta", tsMndSdbWriteDelta, 20, 10000, 0) != 0) return -1; + if (cfgAddInt64(pCfg, "mndLogRetention", tsMndLogRetention, 500, 10000, 0) != 0) return -1; + if (cfgAddBool(pCfg, "monitor", tsEnableMonitor, 0) != 0) return -1; if (cfgAddInt32(pCfg, "monitorInterval", tsMonitorInterval, 1, 200000, 0) != 0) return -1; if (cfgAddString(pCfg, "monitorFqdn", tsMonitorFqdn, 0) != 0) return -1; @@ -469,6 +509,10 @@ static int32_t taosAddServerCfg(SConfig *pCfg) { if (cfgAddString(pCfg, "udfdResFuncs", tsUdfdResFuncs, 0) != 0) return -1; if (cfgAddString(pCfg, "udfdLdLibPath", tsUdfdLdLibPath, 0) != 0) return -1; + if (cfgAddBool(pCfg, "disableStream", tsDisableStream, 0) != 0) return -1; + + if (cfgAddInt32(pCfg, "cacheLazyLoadThreshold", tsCacheLazyLoadThreshold, 0, 100000, 0) != 0) return -1; + GRANT_CFG_ADD; return 0; } @@ -498,11 +542,25 @@ static int32_t taosUpdateServerCfg(SConfig *pCfg) { pItem = cfgGetItem(tsCfg, "numOfRpcThreads"); if (pItem != NULL && pItem->stype == CFG_STYPE_DEFAULT) { tsNumOfRpcThreads = numOfCores / 2; - tsNumOfRpcThreads = TRANGE(tsNumOfRpcThreads, 1, 4); + tsNumOfRpcThreads = TRANGE(tsNumOfRpcThreads, 2, TSDB_MAX_RPC_THREADS); pItem->i32 = tsNumOfRpcThreads; pItem->stype = stype; } + pItem = cfgGetItem(tsCfg, "numOfRpcSessions"); + if (pItem != NULL && pItem->stype == CFG_STYPE_DEFAULT) { + tsNumOfRpcSessions = TRANGE(tsNumOfRpcSessions, 100, 10000); + pItem->i32 = tsNumOfRpcSessions; + pItem->stype = stype; + } + + pItem = cfgGetItem(tsCfg, "timeToGetAvailableConn"); + if (pItem != NULL && pItem->stype == CFG_STYPE_DEFAULT) { + tsTimeToGetAvailableConn = TRANGE(tsTimeToGetAvailableConn, 20, 1000000); + pItem->i32 = tsTimeToGetAvailableConn; + pItem->stype = stype; + } + pItem = cfgGetItem(tsCfg, "numOfCommitThreads"); if (pItem != NULL && pItem->stype == CFG_STYPE_DEFAULT) { tsNumOfCommitThreads = numOfCores / 2; @@ -664,9 +722,9 @@ static int32_t taosSetClientCfg(SConfig *pCfg) { tstrncpy(tsSmlChildTableName, cfgGetItem(pCfg, "smlChildTableName")->str, TSDB_TABLE_NAME_LEN); tstrncpy(tsSmlTagName, cfgGetItem(pCfg, "smlTagName")->str, TSDB_COL_NAME_LEN); - tsSmlDataFormat = cfgGetItem(pCfg, "smlDataFormat")->bval; + // tsSmlDataFormat = cfgGetItem(pCfg, "smlDataFormat")->bval; - tsSmlBatchSize = cfgGetItem(pCfg, "smlBatchSize")->i32; + // tsSmlBatchSize = cfgGetItem(pCfg, "smlBatchSize")->i32; tsMaxMemUsedByInsert = cfgGetItem(pCfg, "maxMemUsedByInsert")->i32; tsShellActivityTimer = cfgGetItem(pCfg, "shellActivityTimer")->i32; @@ -675,6 +733,7 @@ static int32_t taosSetClientCfg(SConfig *pCfg) { tsNumOfTaskQueueThreads = cfgGetItem(pCfg, "numOfTaskQueueThreads")->i32; tsQueryPolicy = cfgGetItem(pCfg, "queryPolicy")->i32; tsEnableQueryHb = cfgGetItem(pCfg, "enableQueryHb")->bval; + tsEnableScience = cfgGetItem(pCfg, "enableScience")->bval; tsQuerySmaOptimize = cfgGetItem(pCfg, "querySmaOptimize")->i32; tsQueryPlannerTrace = cfgGetItem(pCfg, "queryPlannerTrace")->bval; tsQueryNodeChunkSize = cfgGetItem(pCfg, "queryNodeChunkSize")->i32; @@ -682,8 +741,14 @@ static int32_t taosSetClientCfg(SConfig *pCfg) { tsKeepColumnName = cfgGetItem(pCfg, "keepColumnName")->bval; tsUseAdapter = cfgGetItem(pCfg, "useAdapter")->bval; tsEnableCrashReport = cfgGetItem(pCfg, "crashReporting")->bval; + tsQueryMaxConcurrentTables = cfgGetItem(pCfg, "queryMaxConcurrentTables")->i64; tsMaxRetryWaitTime = cfgGetItem(pCfg, "maxRetryWaitTime")->i32; + + tsNumOfRpcThreads = cfgGetItem(pCfg, "numOfRpcThreads")->i32; + tsNumOfRpcSessions = cfgGetItem(pCfg, "numOfRpcSessions")->i32; + + tsTimeToGetAvailableConn = cfgGetItem(pCfg, "timeToGetAvailableConn")->i32; return 0; } @@ -720,6 +785,9 @@ static int32_t taosSetServerCfg(SConfig *pCfg) { tsPrintAuth = cfgGetItem(pCfg, "printAuth")->bval; tsNumOfRpcThreads = cfgGetItem(pCfg, "numOfRpcThreads")->i32; + tsNumOfRpcSessions = cfgGetItem(pCfg, "numOfRpcSessions")->i32; + tsTimeToGetAvailableConn = cfgGetItem(pCfg, "timeToGetAvailableConn")->i32; + tsNumOfCommitThreads = cfgGetItem(pCfg, "numOfCommitThreads")->i32; tsNumOfMnodeReadThreads = cfgGetItem(pCfg, "numOfMnodeReadThreads")->i32; tsNumOfVnodeQueryThreads = cfgGetItem(pCfg, "numOfVnodeQueryThreads")->i32; @@ -727,7 +795,7 @@ static int32_t taosSetServerCfg(SConfig *pCfg) { tsNumOfVnodeFetchThreads = cfgGetItem(pCfg, "numOfVnodeFetchThreads")->i32; tsNumOfVnodeRsmaThreads = cfgGetItem(pCfg, "numOfVnodeRsmaThreads")->i32; tsNumOfQnodeQueryThreads = cfgGetItem(pCfg, "numOfQnodeQueryThreads")->i32; - // tsNumOfQnodeFetchThreads = cfgGetItem(pCfg, "numOfQnodeFetchThreads")->i32; + // tsNumOfQnodeFetchThreads = cfgGetItem(pCfg, "numOfQnodeFetchTereads")->i32; tsNumOfSnodeStreamThreads = cfgGetItem(pCfg, "numOfSnodeSharedThreads")->i32; tsNumOfSnodeWriteThreads = cfgGetItem(pCfg, "numOfSnodeUniqueThreads")->i32; tsRpcQueueMemoryAllowed = cfgGetItem(pCfg, "rpcQueueMemoryAllowed")->i64; @@ -764,12 +832,20 @@ static int32_t taosSetServerCfg(SConfig *pCfg) { tsVndCommitMaxIntervalMs = cfgGetItem(pCfg, "vndCommitMaxInterval")->i64; + tsMndSdbWriteDelta = cfgGetItem(pCfg, "mndSdbWriteDelta")->i64; + tsMndLogRetention = cfgGetItem(pCfg, "mndLogRetention")->i64; + tsStartUdfd = cfgGetItem(pCfg, "udf")->bval; tstrncpy(tsUdfdResFuncs, cfgGetItem(pCfg, "udfdResFuncs")->str, sizeof(tsUdfdResFuncs)); tstrncpy(tsUdfdLdLibPath, cfgGetItem(pCfg, "udfdLdLibPath")->str, sizeof(tsUdfdLdLibPath)); if (tsQueryBufferSize >= 0) { tsQueryBufferSizeBytes = tsQueryBufferSize * 1048576UL; } + + tsCacheLazyLoadThreshold = cfgGetItem(pCfg, "cacheLazyLoadThreshold")->i32; + + tsDisableStream = cfgGetItem(pCfg, "disableStream")->bval; + GRANT_CFG_GET; return 0; } @@ -976,6 +1052,8 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) { tsNumOfTaskQueueThreads = cfgGetItem(pCfg, "numOfTaskQueueThreads")->i32; } else if (strcasecmp("numOfRpcThreads", name) == 0) { tsNumOfRpcThreads = cfgGetItem(pCfg, "numOfRpcThreads")->i32; + } else if (strcasecmp("numOfRpcSessions", name) == 0) { + tsNumOfRpcSessions = cfgGetItem(pCfg, "numOfRpcSessions")->i32; } else if (strcasecmp("numOfCommitThreads", name) == 0) { tsNumOfCommitThreads = cfgGetItem(pCfg, "numOfCommitThreads")->i32; } else if (strcasecmp("numOfMnodeReadThreads", name) == 0) { @@ -1051,10 +1129,10 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) { tstrncpy(tsSmlChildTableName, cfgGetItem(pCfg, "smlChildTableName")->str, TSDB_TABLE_NAME_LEN); } else if (strcasecmp("smlTagName", name) == 0) { tstrncpy(tsSmlTagName, cfgGetItem(pCfg, "smlTagName")->str, TSDB_COL_NAME_LEN); - } else if (strcasecmp("smlDataFormat", name) == 0) { - tsSmlDataFormat = cfgGetItem(pCfg, "smlDataFormat")->bval; - } else if (strcasecmp("smlBatchSize", name) == 0) { - tsSmlBatchSize = cfgGetItem(pCfg, "smlBatchSize")->i32; + // } else if (strcasecmp("smlDataFormat", name) == 0) { + // tsSmlDataFormat = cfgGetItem(pCfg, "smlDataFormat")->bval; + // } else if (strcasecmp("smlBatchSize", name) == 0) { + // tsSmlBatchSize = cfgGetItem(pCfg, "smlBatchSize")->i32; } else if (strcasecmp("shellActivityTimer", name) == 0) { tsShellActivityTimer = cfgGetItem(pCfg, "shellActivityTimer")->i32; } else if (strcasecmp("supportVnodes", name) == 0) { @@ -1124,6 +1202,8 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) { tsStartUdfd = cfgGetItem(pCfg, "udf")->bval; } else if (strcasecmp("uDebugFlag", name) == 0) { uDebugFlag = cfgGetItem(pCfg, "uDebugFlag")->i32; + } else if (strcasecmp("useAdapter", name) == 0) { + tsUseAdapter = cfgGetItem(pCfg, "useAdapter")->bval; } break; } @@ -1173,13 +1253,13 @@ int32_t taosCreateLog(const char *logname, int32_t logFileNum, const char *cfgDi } if (taosLoadCfg(pCfg, envCmd, cfgDir, envFile, apolloUrl) != 0) { - uError("failed to load cfg since %s", terrstr()); + printf("failed to load cfg since %s", terrstr()); cfgCleanup(pCfg); return -1; } if (cfgLoadFromArray(pCfg, pArgs) != 0) { - uError("failed to load cfg from array since %s", terrstr()); + printf("failed to load cfg from array since %s", terrstr()); cfgCleanup(pCfg); return -1; } @@ -1194,13 +1274,14 @@ int32_t taosCreateLog(const char *logname, int32_t logFileNum, const char *cfgDi taosSetAllDebugFlag(cfgGetItem(pCfg, "debugFlag")->i32, false); if (taosMulModeMkDir(tsLogDir, 0777) != 0) { - uError("failed to create dir:%s since %s", tsLogDir, terrstr()); + terrno = TAOS_SYSTEM_ERROR(errno); + printf("failed to create dir:%s since %s", tsLogDir, terrstr()); cfgCleanup(pCfg); return -1; } if (taosInitLog(logname, logFileNum) != 0) { - uError("failed to init log file since %s", terrstr()); + printf("failed to init log file since %s", terrstr()); cfgCleanup(pCfg); return -1; } diff --git a/source/common/src/tmisce.c b/source/common/src/tmisce.c index dfb1917fcfbeddf5814a6689bba8864be44c180e..c195f5387cb2e01fb128895465980a2569b4d04a 100644 --- a/source/common/src/tmisce.c +++ b/source/common/src/tmisce.c @@ -15,6 +15,7 @@ #define _DEFAULT_SOURCE #include "tmisce.h" +#include "tjson.h" #include "tglobal.h" #include "tlog.h" #include "tname.h" @@ -60,6 +61,19 @@ bool isEpsetEqual(const SEpSet* s1, const SEpSet* s2) { return true; } +void epsetAssign(SEpSet* pDst, const SEpSet* pSrc) { + if (pSrc == NULL || pDst == NULL) { + return; + } + + pDst->inUse = pSrc->inUse; + pDst->numOfEps = pSrc->numOfEps; + for (int32_t i = 0; i < pSrc->numOfEps; ++i) { + pDst->eps[i].port = pSrc->eps[i].port; + tstrncpy(pDst->eps[i].fqdn, pSrc->eps[i].fqdn, tListLen(pSrc->eps[i].fqdn)); + } +} + void updateEpSet_s(SCorEpSet* pEpSet, SEpSet* pNewEpSet) { taosCorBeginWrite(&pEpSet->version); pEpSet->epSet = *pNewEpSet; @@ -74,3 +88,63 @@ SEpSet getEpSet_s(SCorEpSet* pEpSet) { return ep; } + +int32_t taosGenCrashJsonMsg(int signum, char** pMsg, int64_t clusterId, int64_t startTime) { + SJson* pJson = tjsonCreateObject(); + if (pJson == NULL) return -1; + char tmp[4096] = {0}; + + tjsonAddDoubleToObject(pJson, "reportVersion", 1); + + tjsonAddIntegerToObject(pJson, "clusterId", clusterId); + tjsonAddIntegerToObject(pJson, "startTime", startTime); + + // Do NOT invoke the taosGetFqdn here. + // this function may be invoked when memory exception occurs,so we should assume that it is running in a memory locked + // environment. The lock operation by taosGetFqdn may cause this program deadlock. + tjsonAddStringToObject(pJson, "fqdn", tsLocalFqdn); + + tjsonAddIntegerToObject(pJson, "pid", taosGetPId()); + + taosGetAppName(tmp, NULL); + tjsonAddStringToObject(pJson, "appName", tmp); + + if (taosGetOsReleaseName(tmp, sizeof(tmp)) == 0) { + tjsonAddStringToObject(pJson, "os", tmp); + } + + float numOfCores = 0; + if (taosGetCpuInfo(tmp, sizeof(tmp), &numOfCores) == 0) { + tjsonAddStringToObject(pJson, "cpuModel", tmp); + tjsonAddDoubleToObject(pJson, "numOfCpu", numOfCores); + } else { + tjsonAddDoubleToObject(pJson, "numOfCpu", tsNumOfCores); + } + + snprintf(tmp, sizeof(tmp), "%" PRId64 " kB", tsTotalMemoryKB); + tjsonAddStringToObject(pJson, "memory", tmp); + + tjsonAddStringToObject(pJson, "version", version); + tjsonAddStringToObject(pJson, "buildInfo", buildinfo); + tjsonAddStringToObject(pJson, "gitInfo", gitinfo); + + tjsonAddIntegerToObject(pJson, "crashSig", signum); + tjsonAddIntegerToObject(pJson, "crashTs", taosGetTimestampUs()); + +#ifdef _TD_DARWIN_64 + taosLogTraceToBuf(tmp, sizeof(tmp), 4); +#elif !defined(WINDOWS) + taosLogTraceToBuf(tmp, sizeof(tmp), 3); +#else + taosLogTraceToBuf(tmp, sizeof(tmp), 8); +#endif + + tjsonAddStringToObject(pJson, "stackInfo", tmp); + + char* pCont = tjsonToString(pJson); + tjsonDelete(pJson); + + *pMsg = pCont; + + return TSDB_CODE_SUCCESS; +} diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index 44d3f7be25d5ee9eea280b1e089973ff459a11e7..fde3a89081559d906b3b4ae23abc3d87958786b8 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -918,6 +918,65 @@ int32_t tDeserializeSMDropSmaReq(void *buf, int32_t bufLen, SMDropSmaReq *pReq) tDecoderClear(&decoder); return 0; } + +int32_t tSerializeSCreateTagIdxReq(void *buf, int32_t bufLen, SCreateTagIndexReq *pReq) { + SEncoder encoder = {0}; + tEncoderInit(&encoder, buf, bufLen); + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->dbFName) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->stbName) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->colName) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->idxName) < 0) return -1; + if (tEncodeI8(&encoder, pReq->idxType) < 0) return -1; + + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tEncoderClear(&encoder); + return tlen; +} +int32_t tDeserializeSCreateTagIdxReq(void *buf, int32_t bufLen, SCreateTagIndexReq *pReq) { + SDecoder decoder = {0}; + tDecoderInit(&decoder, buf, bufLen); + + if (tStartDecode(&decoder) < 0) return -1; + + if (tDecodeCStrTo(&decoder, pReq->dbFName) < 0) return -1; + if (tDecodeCStrTo(&decoder, pReq->stbName) < 0) return -1; + if (tDecodeCStrTo(&decoder, pReq->colName) < 0) return -1; + if (tDecodeCStrTo(&decoder, pReq->idxName) < 0) return -1; + if (tDecodeI8(&decoder, &pReq->idxType) < 0) return -1; + + tEndDecode(&decoder); + tDecoderClear(&decoder); + return 0; +} +int32_t tSerializeSDropTagIdxReq(void *buf, int32_t bufLen, SDropTagIndexReq *pReq) { + SEncoder encoder = {0}; + tEncoderInit(&encoder, buf, bufLen); + if (tStartEncode(&encoder) < 0) return -1; + tEndEncode(&encoder); + + if (tEncodeCStr(&encoder, pReq->name) < 0) return -1; + if (tEncodeI8(&encoder, pReq->igNotExists) < 0) return -1; + + int32_t tlen = encoder.pos; + tEncoderClear(&encoder); + return tlen; +} +int32_t tDeserializeSDropTagIdxReq(void *buf, int32_t bufLen, SDropTagIndexReq *pReq) { + SDecoder decoder = {0}; + tDecoderInit(&decoder, buf, bufLen); + if (tStartDecode(&decoder) < 0) return -1; + + if (tDecodeCStrTo(&decoder, pReq->name) < 0) return -1; + if (tDecodeI8(&decoder, &pReq->igNotExists) < 0) return -1; + + tEndDecode(&decoder); + tDecoderClear(&decoder); + + return 0; +} int32_t tSerializeSMCreateFullTextReq(void *buf, int32_t bufLen, SMCreateFullTextReq *pReq) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); @@ -1011,7 +1070,8 @@ int32_t tSerializeSStatusReq(void *buf, int32_t bufLen, SStatusReq *pReq) { if (tEncodeI64(&encoder, pload->totalStorage) < 0) return -1; if (tEncodeI64(&encoder, pload->compStorage) < 0) return -1; if (tEncodeI64(&encoder, pload->pointsWritten) < 0) return -1; - if (tEncodeI64(&encoder, reserved) < 0) return -1; + if (tEncodeI32(&encoder, pload->numOfCachedTables) < 0) return -1; + if (tEncodeI32(&encoder, reserved) < 0) return -1; if (tEncodeI64(&encoder, reserved) < 0) return -1; if (tEncodeI64(&encoder, reserved) < 0) return -1; } @@ -1089,7 +1149,8 @@ int32_t tDeserializeSStatusReq(void *buf, int32_t bufLen, SStatusReq *pReq) { if (tDecodeI64(&decoder, &vload.totalStorage) < 0) return -1; if (tDecodeI64(&decoder, &vload.compStorage) < 0) return -1; if (tDecodeI64(&decoder, &vload.pointsWritten) < 0) return -1; - if (tDecodeI64(&decoder, &reserved) < 0) return -1; + if (tDecodeI32(&decoder, &vload.numOfCachedTables) < 0) return -1; + if (tDecodeI32(&decoder, (int32_t *)&reserved) < 0) return -1; if (tDecodeI64(&decoder, &reserved) < 0) return -1; if (tDecodeI64(&decoder, &reserved) < 0) return -1; if (taosArrayPush(pReq->pVloads, &vload) == NULL) { @@ -1307,6 +1368,12 @@ int32_t tSerializeSAlterUserReq(void *buf, int32_t bufLen, SAlterUserReq *pReq) if (tEncodeCStr(&encoder, pReq->user) < 0) return -1; if (tEncodeCStr(&encoder, pReq->pass) < 0) return -1; if (tEncodeCStr(&encoder, pReq->objname) < 0) return -1; + int32_t len = strlen(pReq->tabName); + if (tEncodeI32(&encoder, len) < 0) return -1; + if (len > 0) { + if (tEncodeCStr(&encoder, pReq->tabName) < 0) return -1; + } + if (tEncodeBinary(&encoder, pReq->tagCond, pReq->tagCondLen) < 0) return -1; tEndEncode(&encoder); int32_t tlen = encoder.pos; @@ -1326,12 +1393,24 @@ int32_t tDeserializeSAlterUserReq(void *buf, int32_t bufLen, SAlterUserReq *pReq if (tDecodeCStrTo(&decoder, pReq->user) < 0) return -1; if (tDecodeCStrTo(&decoder, pReq->pass) < 0) return -1; if (tDecodeCStrTo(&decoder, pReq->objname) < 0) return -1; + if (!tDecodeIsEnd(&decoder)) { + int32_t len = 0; + if (tDecodeI32(&decoder, &len) < 0) return -1; + if (len > 0) { + if (tDecodeCStrTo(&decoder, pReq->tabName) < 0) return -1; + } + uint64_t tagCondLen = 0; + if (tDecodeBinaryAlloc(&decoder, (void **)&pReq->tagCond, &tagCondLen) < 0) return -1; + pReq->tagCondLen = tagCondLen; + } tEndDecode(&decoder); tDecoderClear(&decoder); return 0; } +void tFreeSAlterUserReq(SAlterUserReq *pReq) { taosMemoryFreeClear(pReq->tagCond); } + int32_t tSerializeSGetUserAuthReq(void *buf, int32_t bufLen, SGetUserAuthReq *pReq) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); @@ -1368,6 +1447,7 @@ int32_t tSerializeSGetUserAuthRspImpl(SEncoder *pEncoder, SGetUserAuthRsp *pRsp) int32_t numOfCreatedDbs = taosHashGetSize(pRsp->createdDbs); int32_t numOfReadDbs = taosHashGetSize(pRsp->readDbs); int32_t numOfWriteDbs = taosHashGetSize(pRsp->writeDbs); + if (tEncodeI32(pEncoder, numOfCreatedDbs) < 0) return -1; if (tEncodeI32(pEncoder, numOfReadDbs) < 0) return -1; if (tEncodeI32(pEncoder, numOfWriteDbs) < 0) return -1; @@ -1390,6 +1470,54 @@ int32_t tSerializeSGetUserAuthRspImpl(SEncoder *pEncoder, SGetUserAuthRsp *pRsp) db = taosHashIterate(pRsp->writeDbs, db); } + int32_t numOfReadTbs = taosHashGetSize(pRsp->readTbs); + int32_t numOfWriteTbs = taosHashGetSize(pRsp->writeTbs); + int32_t numOfUseTbs = taosHashGetSize(pRsp->useDbs); + if (tEncodeI32(pEncoder, numOfReadTbs) < 0) return -1; + if (tEncodeI32(pEncoder, numOfWriteTbs) < 0) return -1; + if (tEncodeI32(pEncoder, numOfUseTbs) < 0) return -1; + + char *tb = taosHashIterate(pRsp->readTbs, NULL); + while (tb != NULL) { + size_t keyLen = 0; + void *key = taosHashGetKey(tb, &keyLen); + if (tEncodeI32(pEncoder, keyLen) < 0) return -1; + if (tEncodeCStr(pEncoder, key) < 0) return -1; + + size_t valueLen = 0; + valueLen = strlen(tb); + if (tEncodeI32(pEncoder, valueLen) < 0) return -1; + if (tEncodeCStr(pEncoder, tb) < 0) return -1; + + tb = taosHashIterate(pRsp->readTbs, tb); + } + + tb = taosHashIterate(pRsp->writeTbs, NULL); + while (tb != NULL) { + size_t keyLen = 0; + void *key = taosHashGetKey(tb, &keyLen); + if (tEncodeI32(pEncoder, keyLen) < 0) return -1; + if (tEncodeCStr(pEncoder, key) < 0) return -1; + + size_t valueLen = 0; + valueLen = strlen(tb); + if (tEncodeI32(pEncoder, valueLen) < 0) return -1; + if (tEncodeCStr(pEncoder, tb) < 0) return -1; + + tb = taosHashIterate(pRsp->writeTbs, tb); + } + + int32_t *useDb = taosHashIterate(pRsp->useDbs, NULL); + while (useDb != NULL) { + size_t keyLen = 0; + void *key = taosHashGetKey(useDb, &keyLen); + if (tEncodeI32(pEncoder, keyLen) < 0) return -1; + if (tEncodeCStr(pEncoder, key) < 0) return -1; + + if (tEncodeI32(pEncoder, *useDb) < 0) return -1; + useDb = taosHashIterate(pRsp->useDbs, useDb); + } + return 0; } @@ -1412,7 +1540,11 @@ int32_t tDeserializeSGetUserAuthRspImpl(SDecoder *pDecoder, SGetUserAuthRsp *pRs pRsp->createdDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); pRsp->readDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); pRsp->writeDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); - if (pRsp->readDbs == NULL || pRsp->writeDbs == NULL) { + pRsp->readTbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + pRsp->writeTbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + pRsp->useDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + if (pRsp->createdDbs == NULL || pRsp->readDbs == NULL || pRsp->writeDbs == NULL || pRsp->readTbs == NULL || + pRsp->writeTbs == NULL || pRsp->useDbs == NULL) { return -1; } @@ -1451,6 +1583,64 @@ int32_t tDeserializeSGetUserAuthRspImpl(SDecoder *pDecoder, SGetUserAuthRsp *pRs taosHashPut(pRsp->writeDbs, db, len, db, len); } + if (!tDecodeIsEnd(pDecoder)) { + int32_t numOfReadTbs = 0; + int32_t numOfWriteTbs = 0; + int32_t numOfUseDbs = 0; + if (tDecodeI32(pDecoder, &numOfReadTbs) < 0) return -1; + if (tDecodeI32(pDecoder, &numOfWriteTbs) < 0) return -1; + if (tDecodeI32(pDecoder, &numOfUseDbs) < 0) return -1; + + for (int32_t i = 0; i < numOfReadTbs; ++i) { + int32_t keyLen = 0; + if (tDecodeI32(pDecoder, &keyLen) < 0) return -1; + + char *key = taosMemoryCalloc(keyLen + 1, sizeof(char)); + if (tDecodeCStrTo(pDecoder, key) < 0) return -1; + + int32_t valuelen = 0; + if (tDecodeI32(pDecoder, &valuelen) < 0) return -1; + char *value = taosMemoryCalloc(valuelen + 1, sizeof(char)); + if (tDecodeCStrTo(pDecoder, value) < 0) return -1; + + taosHashPut(pRsp->readTbs, key, strlen(key), value, valuelen + 1); + + taosMemoryFree(key); + taosMemoryFree(value); + } + + for (int32_t i = 0; i < numOfWriteTbs; ++i) { + int32_t keyLen = 0; + if (tDecodeI32(pDecoder, &keyLen) < 0) return -1; + + char *key = taosMemoryCalloc(keyLen + 1, sizeof(char)); + if (tDecodeCStrTo(pDecoder, key) < 0) return -1; + + int32_t valuelen = 0; + if (tDecodeI32(pDecoder, &valuelen) < 0) return -1; + char *value = taosMemoryCalloc(valuelen + 1, sizeof(char)); + if (tDecodeCStrTo(pDecoder, value) < 0) return -1; + + taosHashPut(pRsp->writeTbs, key, strlen(key), value, valuelen + 1); + + taosMemoryFree(key); + taosMemoryFree(value); + } + + for (int32_t i = 0; i < numOfUseDbs; ++i) { + int32_t keyLen = 0; + if (tDecodeI32(pDecoder, &keyLen) < 0) return -1; + + char *key = taosMemoryCalloc(keyLen + 1, sizeof(char)); + if (tDecodeCStrTo(pDecoder, key) < 0) return -1; + + int32_t ref = 0; + if (tDecodeI32(pDecoder, &ref) < 0) return -1; + taosHashPut(pRsp->useDbs, key, strlen(key), &ref, sizeof(ref)); + taosMemoryFree(key); + } + } + return 0; } @@ -1472,6 +1662,9 @@ void tFreeSGetUserAuthRsp(SGetUserAuthRsp *pRsp) { taosHashCleanup(pRsp->createdDbs); taosHashCleanup(pRsp->readDbs); taosHashCleanup(pRsp->writeDbs); + taosHashCleanup(pRsp->writeTbs); + taosHashCleanup(pRsp->readTbs); + taosHashCleanup(pRsp->useDbs); } int32_t tSerializeSCreateDropMQSNodeReq(void *buf, int32_t bufLen, SMCreateQnodeReq *pReq) { @@ -1641,6 +1834,8 @@ int32_t tSerializeSCreateFuncReq(void *buf, int32_t bufLen, SCreateFuncReq *pReq if (tEncodeCStr(&encoder, pReq->pComment) < 0) return -1; } + if (tEncodeI8(&encoder, pReq->orReplace) < 0) return -1; + tEndEncode(&encoder); int32_t tlen = encoder.pos; @@ -1683,6 +1878,12 @@ int32_t tDeserializeSCreateFuncReq(void *buf, int32_t bufLen, SCreateFuncReq *pR if (tDecodeCStrTo(&decoder, pReq->pComment) < 0) return -1; } + if (!tDecodeIsEnd(&decoder)) { + if (tDecodeI8(&decoder, &pReq->orReplace) < 0) return -1; + } else { + pReq->orReplace = false; + } + tEndDecode(&decoder); tDecoderClear(&decoder); @@ -1794,6 +1995,13 @@ int32_t tSerializeSRetrieveFuncRsp(void *buf, int32_t bufLen, SRetrieveFuncRsp * } } + if (pRsp->numOfFuncs != (int32_t)taosArrayGetSize(pRsp->pFuncExtraInfos)) return -1; + for (int32_t i = 0; i < pRsp->numOfFuncs; ++i) { + SFuncExtraInfo *extraInfo = taosArrayGet(pRsp->pFuncExtraInfos, i); + if (tEncodeI32(&encoder, extraInfo->funcVersion) < 0) return -1; + if (tEncodeI64(&encoder, extraInfo->funcCreatedTime) < 0) return -1; + } + tEndEncode(&encoder); int32_t tlen = encoder.pos; @@ -1841,6 +2049,22 @@ int32_t tDeserializeSRetrieveFuncRsp(void *buf, int32_t bufLen, SRetrieveFuncRsp taosArrayPush(pRsp->pFuncInfos, &fInfo); } + + pRsp->pFuncExtraInfos = taosArrayInit(pRsp->numOfFuncs, sizeof(SFuncExtraInfo)); + if (pRsp->pFuncExtraInfos == NULL) return -1; + if (tDecodeIsEnd(&decoder)) { + for (int32_t i = 0; i < pRsp->numOfFuncs; ++i) { + SFuncExtraInfo extraInfo = {0}; + taosArrayPush(pRsp->pFuncExtraInfos, &extraInfo); + } + } else { + for (int32_t i = 0; i < pRsp->numOfFuncs; ++i) { + SFuncExtraInfo extraInfo = {0}; + if (tDecodeI32(&decoder, &extraInfo.funcVersion) < 0) return -1; + if (tDecodeI64(&decoder, &extraInfo.funcCreatedTime) < 0) return -1; + taosArrayPush(pRsp->pFuncExtraInfos, &extraInfo); + } + } tEndDecode(&decoder); tDecoderClear(&decoder); @@ -1863,6 +2087,7 @@ void tFreeSRetrieveFuncRsp(SRetrieveFuncRsp *pRsp) { tFreeSFuncInfo(pInfo); } taosArrayDestroy(pRsp->pFuncInfos); + taosArrayDestroy(pRsp->pFuncExtraInfos); } int32_t tSerializeSTableCfgReq(void *buf, int32_t bufLen, STableCfgReq *pReq) { @@ -2160,6 +2385,12 @@ int32_t tSerializeSAlterDbReq(void *buf, int32_t bufLen, SAlterDbReq *pReq) { if (tEncodeI8(&encoder, pReq->cacheLast) < 0) return -1; if (tEncodeI8(&encoder, pReq->replications) < 0) return -1; if (tEncodeI32(&encoder, pReq->sstTrigger) < 0) return -1; + + // 1st modification + if (tEncodeI32(&encoder, pReq->minRows) < 0) return -1; + // 2nd modification + if (tEncodeI32(&encoder, pReq->walRetentionPeriod) < 0) return -1; + if (tEncodeI32(&encoder, pReq->walRetentionSize) < 0) return -1; tEndEncode(&encoder); int32_t tlen = encoder.pos; @@ -2187,6 +2418,22 @@ int32_t tDeserializeSAlterDbReq(void *buf, int32_t bufLen, SAlterDbReq *pReq) { if (tDecodeI8(&decoder, &pReq->cacheLast) < 0) return -1; if (tDecodeI8(&decoder, &pReq->replications) < 0) return -1; if (tDecodeI32(&decoder, &pReq->sstTrigger) < 0) return -1; + + // 1st modification + if (!tDecodeIsEnd(&decoder)) { + if (tDecodeI32(&decoder, &pReq->minRows) < 0) return -1; + } else { + pReq->minRows = -1; + } + + // 2nd modification + if (!tDecodeIsEnd(&decoder)) { + if (tDecodeI32(&decoder, &pReq->walRetentionPeriod) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->walRetentionSize) < 0) return -1; + } else { + pReq->walRetentionPeriod = -1; + pReq->walRetentionSize = -1; + } tEndDecode(&decoder); tDecoderClear(&decoder); @@ -2472,6 +2719,8 @@ int32_t tSerializeSCompactDbReq(void *buf, int32_t bufLen, SCompactDbReq *pReq) if (tStartEncode(&encoder) < 0) return -1; if (tEncodeCStr(&encoder, pReq->db) < 0) return -1; + if (tEncodeI64(&encoder, pReq->timeRange.skey) < 0) return -1; + if (tEncodeI64(&encoder, pReq->timeRange.ekey) < 0) return -1; tEndEncode(&encoder); int32_t tlen = encoder.pos; @@ -2485,6 +2734,8 @@ int32_t tDeserializeSCompactDbReq(void *buf, int32_t bufLen, SCompactDbReq *pReq if (tStartDecode(&decoder) < 0) return -1; if (tDecodeCStrTo(&decoder, pReq->db) < 0) return -1; + if (tDecodeI64(&decoder, &pReq->timeRange.skey) < 0) return -1; + if (tDecodeI64(&decoder, &pReq->timeRange.ekey) < 0) return -1; tEndDecode(&decoder); tDecoderClear(&decoder); @@ -2527,7 +2778,26 @@ int32_t tSerializeSUseDbRsp(void *buf, int32_t bufLen, const SUseDbRsp *pRsp) { return tlen; } -int32_t tSerializeSUseDbBatchRsp(void *buf, int32_t bufLen, SUseDbBatchRsp *pRsp) { +int32_t tSerializeSDbHbRspImp(SEncoder *pEncoder, const SDbHbRsp *pRsp) { + if (pRsp->useDbRsp) { + if (tEncodeI8(pEncoder, 1) < 0) return -1; + if (tSerializeSUseDbRspImp(pEncoder, pRsp->useDbRsp) < 0) return -1; + } else { + if (tEncodeI8(pEncoder, 0) < 0) return -1; + } + + if (pRsp->cfgRsp) { + if (tEncodeI8(pEncoder, 1) < 0) return -1; + if (tSerializeSDbCfgRspImpl(pEncoder, pRsp->cfgRsp) < 0) return -1; + } else { + if (tEncodeI8(pEncoder, 0) < 0) return -1; + } + + return 0; +} + + +int32_t tSerializeSDbHbBatchRsp(void *buf, int32_t bufLen, SDbHbBatchRsp *pRsp) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); @@ -2536,8 +2806,8 @@ int32_t tSerializeSUseDbBatchRsp(void *buf, int32_t bufLen, SUseDbBatchRsp *pRsp int32_t numOfBatch = taosArrayGetSize(pRsp->pArray); if (tEncodeI32(&encoder, numOfBatch) < 0) return -1; for (int32_t i = 0; i < numOfBatch; ++i) { - SUseDbRsp *pUsedbRsp = taosArrayGet(pRsp->pArray, i); - if (tSerializeSUseDbRspImp(&encoder, pUsedbRsp) < 0) return -1; + SDbHbRsp *pDbRsp = taosArrayGet(pRsp->pArray, i); + if (tSerializeSDbHbRspImp(&encoder, pDbRsp) < 0) return -1; } tEndEncode(&encoder); @@ -2590,7 +2860,25 @@ int32_t tDeserializeSUseDbRsp(void *buf, int32_t bufLen, SUseDbRsp *pRsp) { return 0; } -int32_t tDeserializeSUseDbBatchRsp(void *buf, int32_t bufLen, SUseDbBatchRsp *pRsp) { +int32_t tDeserializeSDbHbRspImp(SDecoder* decoder, SDbHbRsp* pRsp) { + int8_t flag = 0; + if (tDecodeI8(decoder, &flag) < 0) return -1; + if (flag) { + pRsp->useDbRsp = taosMemoryCalloc(1, sizeof(SUseDbRsp)); + if (NULL == pRsp->useDbRsp) return -1; + if (tDeserializeSUseDbRspImp(decoder, pRsp->useDbRsp) < 0) return -1; + } + if (tDecodeI8(decoder, &flag) < 0) return -1; + if (flag) { + pRsp->cfgRsp = taosMemoryCalloc(1, sizeof(SDbCfgRsp)); + if (NULL == pRsp->cfgRsp) return -1; + if (tDeserializeSDbCfgRspImpl(decoder, pRsp->cfgRsp) < 0) return -1; + } + + return 0; +} + +int32_t tDeserializeSDbHbBatchRsp(void *buf, int32_t bufLen, SDbHbBatchRsp *pRsp) { SDecoder decoder = {0}; tDecoderInit(&decoder, buf, bufLen); @@ -2599,19 +2887,19 @@ int32_t tDeserializeSUseDbBatchRsp(void *buf, int32_t bufLen, SUseDbBatchRsp *pR int32_t numOfBatch = taosArrayGetSize(pRsp->pArray); if (tDecodeI32(&decoder, &numOfBatch) < 0) return -1; - pRsp->pArray = taosArrayInit(numOfBatch, sizeof(SUseDbRsp)); + pRsp->pArray = taosArrayInit(numOfBatch, sizeof(SDbHbRsp)); if (pRsp->pArray == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } for (int32_t i = 0; i < numOfBatch; ++i) { - SUseDbRsp usedbRsp = {0}; - if (tDeserializeSUseDbRspImp(&decoder, &usedbRsp) < 0) { + SDbHbRsp rsp = {0}; + if (tDeserializeSDbHbRspImp(&decoder, &rsp) < 0) { tDecoderClear(&decoder); return -1; } - taosArrayPush(pRsp->pArray, &usedbRsp); + taosArrayPush(pRsp->pArray, &rsp); } tEndDecode(&decoder); @@ -2621,11 +2909,27 @@ int32_t tDeserializeSUseDbBatchRsp(void *buf, int32_t bufLen, SUseDbBatchRsp *pR void tFreeSUsedbRsp(SUseDbRsp *pRsp) { taosArrayDestroy(pRsp->pVgroupInfos); } -void tFreeSUseDbBatchRsp(SUseDbBatchRsp *pRsp) { +void tFreeSDbHbRsp(SDbHbRsp *pDbRsp) { + if (NULL == pDbRsp) { + return; + } + + if (pDbRsp->useDbRsp) { + tFreeSUsedbRsp(pDbRsp->useDbRsp); + taosMemoryFree(pDbRsp->useDbRsp); + } + + if (pDbRsp->cfgRsp) { + tFreeSDbCfgRsp(pDbRsp->cfgRsp); + taosMemoryFree(pDbRsp->cfgRsp); + } +} + +void tFreeSDbHbBatchRsp(SDbHbBatchRsp *pRsp) { int32_t numOfBatch = taosArrayGetSize(pRsp->pArray); for (int32_t i = 0; i < numOfBatch; ++i) { - SUseDbRsp *pUsedbRsp = taosArrayGet(pRsp->pArray, i); - tFreeSUsedbRsp(pUsedbRsp); + SDbHbRsp *pDbRsp = taosArrayGet(pRsp->pArray, i); + tFreeSDbHbRsp(pDbRsp); } taosArrayDestroy(pRsp->pArray); @@ -2788,71 +3092,93 @@ int32_t tDeserializeSVDropTtlTableReq(void *buf, int32_t bufLen, SVDropTtlTableR return 0; } +int32_t tSerializeSDbCfgRspImpl(SEncoder *encoder, const SDbCfgRsp *pRsp) { + if (tEncodeCStr(encoder, pRsp->db) < 0) return -1; + if (tEncodeI64(encoder, pRsp->dbId) < 0) return -1; + if (tEncodeI32(encoder, pRsp->cfgVersion) < 0) return -1; + if (tEncodeI32(encoder, pRsp->numOfVgroups) < 0) return -1; + if (tEncodeI32(encoder, pRsp->numOfStables) < 0) return -1; + if (tEncodeI32(encoder, pRsp->buffer) < 0) return -1; + if (tEncodeI32(encoder, pRsp->cacheSize) < 0) return -1; + if (tEncodeI32(encoder, pRsp->pageSize) < 0) return -1; + if (tEncodeI32(encoder, pRsp->pages) < 0) return -1; + if (tEncodeI32(encoder, pRsp->daysPerFile) < 0) return -1; + if (tEncodeI32(encoder, pRsp->daysToKeep0) < 0) return -1; + if (tEncodeI32(encoder, pRsp->daysToKeep1) < 0) return -1; + if (tEncodeI32(encoder, pRsp->daysToKeep2) < 0) return -1; + if (tEncodeI32(encoder, pRsp->minRows) < 0) return -1; + if (tEncodeI32(encoder, pRsp->maxRows) < 0) return -1; + if (tEncodeI32(encoder, pRsp->walFsyncPeriod) < 0) return -1; + if (tEncodeI16(encoder, pRsp->hashPrefix) < 0) return -1; + if (tEncodeI16(encoder, pRsp->hashSuffix) < 0) return -1; + if (tEncodeI8(encoder, pRsp->walLevel) < 0) return -1; + if (tEncodeI8(encoder, pRsp->precision) < 0) return -1; + if (tEncodeI8(encoder, pRsp->compression) < 0) return -1; + if (tEncodeI8(encoder, pRsp->replications) < 0) return -1; + if (tEncodeI8(encoder, pRsp->strict) < 0) return -1; + if (tEncodeI8(encoder, pRsp->cacheLast) < 0) return -1; + if (tEncodeI32(encoder, pRsp->tsdbPageSize) < 0) return -1; + if (tEncodeI32(encoder, pRsp->walRetentionPeriod) < 0) return -1; + if (tEncodeI32(encoder, pRsp->walRollPeriod) < 0) return -1; + if (tEncodeI64(encoder, pRsp->walRetentionSize) < 0) return -1; + if (tEncodeI64(encoder, pRsp->walSegmentSize) < 0) return -1; + if (tEncodeI32(encoder, pRsp->numOfRetensions) < 0) return -1; + for (int32_t i = 0; i < pRsp->numOfRetensions; ++i) { + SRetention *pRetension = taosArrayGet(pRsp->pRetensions, i); + if (tEncodeI64(encoder, pRetension->freq) < 0) return -1; + if (tEncodeI64(encoder, pRetension->keep) < 0) return -1; + if (tEncodeI8(encoder, pRetension->freqUnit) < 0) return -1; + if (tEncodeI8(encoder, pRetension->keepUnit) < 0) return -1; + } + if (tEncodeI8(encoder, pRsp->schemaless) < 0) return -1; + if (tEncodeI16(encoder, pRsp->sstTrigger) < 0) return -1; + + return 0; +} + int32_t tSerializeSDbCfgRsp(void *buf, int32_t bufLen, const SDbCfgRsp *pRsp) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); if (tStartEncode(&encoder) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->numOfVgroups) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->numOfStables) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->buffer) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->cacheSize) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->pageSize) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->pages) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->daysPerFile) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->daysToKeep0) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->daysToKeep1) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->daysToKeep2) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->minRows) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->maxRows) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->walFsyncPeriod) < 0) return -1; - if (tEncodeI8(&encoder, pRsp->walLevel) < 0) return -1; - if (tEncodeI8(&encoder, pRsp->precision) < 0) return -1; - if (tEncodeI8(&encoder, pRsp->compression) < 0) return -1; - if (tEncodeI8(&encoder, pRsp->replications) < 0) return -1; - if (tEncodeI8(&encoder, pRsp->strict) < 0) return -1; - if (tEncodeI8(&encoder, pRsp->cacheLast) < 0) return -1; - if (tEncodeI32(&encoder, pRsp->numOfRetensions) < 0) return -1; - for (int32_t i = 0; i < pRsp->numOfRetensions; ++i) { - SRetention *pRetension = taosArrayGet(pRsp->pRetensions, i); - if (tEncodeI64(&encoder, pRetension->freq) < 0) return -1; - if (tEncodeI64(&encoder, pRetension->keep) < 0) return -1; - if (tEncodeI8(&encoder, pRetension->freqUnit) < 0) return -1; - if (tEncodeI8(&encoder, pRetension->keepUnit) < 0) return -1; - } - if (tEncodeI8(&encoder, pRsp->schemaless) < 0) return -1; - if (tEncodeI16(&encoder, pRsp->sstTrigger) < 0) return -1; + tSerializeSDbCfgRspImpl(&encoder, pRsp); tEndEncode(&encoder); int32_t tlen = encoder.pos; tEncoderClear(&encoder); return tlen; } -int32_t tDeserializeSDbCfgRsp(void *buf, int32_t bufLen, SDbCfgRsp *pRsp) { - SDecoder decoder = {0}; - tDecoderInit(&decoder, buf, bufLen); - - if (tStartDecode(&decoder) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->numOfVgroups) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->numOfStables) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->buffer) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->cacheSize) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->pageSize) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->pages) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->daysPerFile) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->daysToKeep0) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->daysToKeep1) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->daysToKeep2) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->minRows) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->maxRows) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->walFsyncPeriod) < 0) return -1; - if (tDecodeI8(&decoder, &pRsp->walLevel) < 0) return -1; - if (tDecodeI8(&decoder, &pRsp->precision) < 0) return -1; - if (tDecodeI8(&decoder, &pRsp->compression) < 0) return -1; - if (tDecodeI8(&decoder, &pRsp->replications) < 0) return -1; - if (tDecodeI8(&decoder, &pRsp->strict) < 0) return -1; - if (tDecodeI8(&decoder, &pRsp->cacheLast) < 0) return -1; - if (tDecodeI32(&decoder, &pRsp->numOfRetensions) < 0) return -1; +int32_t tDeserializeSDbCfgRspImpl(SDecoder* decoder, SDbCfgRsp *pRsp) { + if (tDecodeCStrTo(decoder, pRsp->db) < 0) return -1; + if (tDecodeI64(decoder, &pRsp->dbId) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->cfgVersion) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->numOfVgroups) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->numOfStables) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->buffer) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->cacheSize) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->pageSize) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->pages) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->daysPerFile) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->daysToKeep0) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->daysToKeep1) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->daysToKeep2) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->minRows) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->maxRows) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->walFsyncPeriod) < 0) return -1; + if (tDecodeI16(decoder, &pRsp->hashPrefix) < 0) return -1; + if (tDecodeI16(decoder, &pRsp->hashSuffix) < 0) return -1; + if (tDecodeI8(decoder, &pRsp->walLevel) < 0) return -1; + if (tDecodeI8(decoder, &pRsp->precision) < 0) return -1; + if (tDecodeI8(decoder, &pRsp->compression) < 0) return -1; + if (tDecodeI8(decoder, &pRsp->replications) < 0) return -1; + if (tDecodeI8(decoder, &pRsp->strict) < 0) return -1; + if (tDecodeI8(decoder, &pRsp->cacheLast) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->tsdbPageSize) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->walRetentionPeriod) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->walRollPeriod) < 0) return -1; + if (tDecodeI64(decoder, &pRsp->walRetentionSize) < 0) return -1; + if (tDecodeI64(decoder, &pRsp->walSegmentSize) < 0) return -1; + if (tDecodeI32(decoder, &pRsp->numOfRetensions) < 0) return -1; if (pRsp->numOfRetensions > 0) { pRsp->pRetensions = taosArrayInit(pRsp->numOfRetensions, sizeof(SRetention)); if (pRsp->pRetensions == NULL) { @@ -2863,23 +3189,41 @@ int32_t tDeserializeSDbCfgRsp(void *buf, int32_t bufLen, SDbCfgRsp *pRsp) { for (int32_t i = 0; i < pRsp->numOfRetensions; ++i) { SRetention rentension = {0}; - if (tDecodeI64(&decoder, &rentension.freq) < 0) return -1; - if (tDecodeI64(&decoder, &rentension.keep) < 0) return -1; - if (tDecodeI8(&decoder, &rentension.freqUnit) < 0) return -1; - if (tDecodeI8(&decoder, &rentension.keepUnit) < 0) return -1; + if (tDecodeI64(decoder, &rentension.freq) < 0) return -1; + if (tDecodeI64(decoder, &rentension.keep) < 0) return -1; + if (tDecodeI8(decoder, &rentension.freqUnit) < 0) return -1; + if (tDecodeI8(decoder, &rentension.keepUnit) < 0) return -1; if (taosArrayPush(pRsp->pRetensions, &rentension) == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } } - if (tDecodeI8(&decoder, &pRsp->schemaless) < 0) return -1; - if (tDecodeI16(&decoder, &pRsp->sstTrigger) < 0) return -1; + if (tDecodeI8(decoder, &pRsp->schemaless) < 0) return -1; + if (tDecodeI16(decoder, &pRsp->sstTrigger) < 0) return -1; + + return 0; +} + +int32_t tDeserializeSDbCfgRsp(void *buf, int32_t bufLen, SDbCfgRsp *pRsp) { + SDecoder decoder = {0}; + tDecoderInit(&decoder, buf, bufLen); + + if (tStartDecode(&decoder) < 0) return -1; + if (tDeserializeSDbCfgRspImpl(&decoder, pRsp) < 0) return -1; tEndDecode(&decoder); tDecoderClear(&decoder); return 0; } +void tFreeSDbCfgRsp(SDbCfgRsp *pRsp) { + if (NULL == pRsp) { + return; + } + + taosArrayDestroy(pRsp->pRetensions); +} + int32_t tSerializeSUserIndexReq(void *buf, int32_t bufLen, SUserIndexReq *pReq) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); @@ -3002,7 +3346,7 @@ int32_t tSerializeSTableIndexRsp(void *buf, int32_t bufLen, const STableIndexRsp void tFreeSerializeSTableIndexRsp(STableIndexRsp *pRsp) { if (pRsp->pIndex != NULL) { - taosArrayDestroy(pRsp->pIndex); + tFreeSTableIndexRsp(pRsp); pRsp->pIndex = NULL; } } @@ -3192,6 +3536,7 @@ int32_t tSerializeSRetrieveTableReq(void *buf, int32_t bufLen, SRetrieveTableReq if (tEncodeI64(&encoder, pReq->showId) < 0) return -1; if (tEncodeCStr(&encoder, pReq->db) < 0) return -1; if (tEncodeCStr(&encoder, pReq->tb) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->filterTb) < 0) return -1; if (tEncodeCStr(&encoder, pReq->user) < 0) return -1; tEndEncode(&encoder); @@ -3208,6 +3553,7 @@ int32_t tDeserializeSRetrieveTableReq(void *buf, int32_t bufLen, SRetrieveTableR if (tDecodeI64(&decoder, &pReq->showId) < 0) return -1; if (tDecodeCStrTo(&decoder, pReq->db) < 0) return -1; if (tDecodeCStrTo(&decoder, pReq->tb) < 0) return -1; + if (tDecodeCStrTo(&decoder, pReq->filterTb) < 0) return -1; if (tDecodeCStrTo(&decoder, pReq->user) < 0) return -1; tEndDecode(&decoder); @@ -3662,6 +4008,7 @@ int32_t tSerializeSConnectReq(void *buf, int32_t bufLen, SConnectReq *pReq) { if (tEncodeCStr(&encoder, pReq->user) < 0) return -1; if (tEncodeCStrWithLen(&encoder, pReq->passwd, TSDB_PASSWORD_LEN) < 0) return -1; if (tEncodeI64(&encoder, pReq->startTime) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->sVer) < 0) return -1; tEndEncode(&encoder); int32_t tlen = encoder.pos; @@ -3681,6 +4028,12 @@ int32_t tDeserializeSConnectReq(void *buf, int32_t bufLen, SConnectReq *pReq) { if (tDecodeCStrTo(&decoder, pReq->user) < 0) return -1; if (tDecodeCStrTo(&decoder, pReq->passwd) < 0) return -1; if (tDecodeI64(&decoder, &pReq->startTime) < 0) return -1; + // Check the client version from version 3.0.3.0 + if (tDecodeIsEnd(&decoder)) { + tDecoderClear(&decoder); + return TSDB_CODE_VERSION_NOT_COMPATIBLE; + } + if (tDecodeCStrTo(&decoder, pReq->sVer) < 0) return -1; tEndDecode(&decoder); tDecoderClear(&decoder); @@ -3982,14 +4335,15 @@ int32_t tDeserializeSDropVnodeReq(void *buf, int32_t bufLen, SDropVnodeReq *pReq tDecoderClear(&decoder); return 0; } - -int32_t tSerializeSCompactVnodeReq(void *buf, int32_t bufLen, SCompactVnodeReq *pReq) { +int32_t tSerializeSDropIdxReq(void *buf, int32_t bufLen, SDropIndexReq *pReq) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->colName) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->stb) < 0) return -1; + if (tEncodeI64(&encoder, pReq->stbUid) < 0) return -1; if (tEncodeI64(&encoder, pReq->dbUid) < 0) return -1; - if (tEncodeCStr(&encoder, pReq->db) < 0) return -1; for (int32_t i = 0; i < 8; ++i) { if (tEncodeI64(&encoder, pReq->reserved[i]) < 0) return -1; } @@ -3998,20 +4352,68 @@ int32_t tSerializeSCompactVnodeReq(void *buf, int32_t bufLen, SCompactVnodeReq * int32_t tlen = encoder.pos; tEncoderClear(&encoder); return tlen; + // TODO + return 0; } - -int32_t tDeserializeSCompactVnodeReq(void *buf, int32_t bufLen, SCompactVnodeReq *pReq) { +int32_t tDeserializeSDropIdxReq(void *buf, int32_t bufLen, SDropIndexReq *pReq) { SDecoder decoder = {0}; tDecoderInit(&decoder, buf, bufLen); if (tStartDecode(&decoder) < 0) return -1; + if (tDecodeCStrTo(&decoder, pReq->colName) < 0) return -1; + if (tDecodeCStrTo(&decoder, pReq->stb) < 0) return -1; + if (tDecodeI64(&decoder, &pReq->stbUid) < 0) return -1; if (tDecodeI64(&decoder, &pReq->dbUid) < 0) return -1; - if (tDecodeCStrTo(&decoder, pReq->db) < 0) return -1; for (int32_t i = 0; i < 8; ++i) { if (tDecodeI64(&decoder, &pReq->reserved[i]) < 0) return -1; } tEndDecode(&decoder); + tDecoderClear(&decoder); + // TODO + return 0; +} + +int32_t tSerializeSCompactVnodeReq(void *buf, int32_t bufLen, SCompactVnodeReq *pReq) { + SEncoder encoder = {0}; + tEncoderInit(&encoder, buf, bufLen); + + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeI64(&encoder, pReq->dbUid) < 0) return -1; + if (tEncodeCStr(&encoder, pReq->db) < 0) return -1; + if (tEncodeI64(&encoder, pReq->compactStartTime) < 0) return -1; + + // 1.1 add tw.skey and tw.ekey + if (tEncodeI64(&encoder, pReq->tw.skey) < 0) return -1; + if (tEncodeI64(&encoder, pReq->tw.ekey) < 0) return -1; + + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tEncoderClear(&encoder); + return tlen; +} + +int32_t tDeserializeSCompactVnodeReq(void *buf, int32_t bufLen, SCompactVnodeReq *pReq) { + SDecoder decoder = {0}; + tDecoderInit(&decoder, buf, bufLen); + + if (tStartDecode(&decoder) < 0) return -1; + + if (tDecodeI64(&decoder, &pReq->dbUid) < 0) return -1; + if (tDecodeCStrTo(&decoder, pReq->db) < 0) return -1; + if (tDecodeI64(&decoder, &pReq->compactStartTime) < 0) return -1; + + // 1.1 + if (tDecodeIsEnd(&decoder)) { + pReq->tw.skey = TSKEY_MIN; + pReq->tw.ekey = TSKEY_MAX; + } else { + if (tDecodeI64(&decoder, &pReq->tw.skey) < 0) return -1; + if (tDecodeI64(&decoder, &pReq->tw.ekey) < 0) return -1; + } + + tEndDecode(&decoder); tDecoderClear(&decoder); return 0; } @@ -4037,6 +4439,13 @@ int32_t tSerializeSAlterVnodeConfigReq(void *buf, int32_t bufLen, SAlterVnodeCon for (int32_t i = 0; i < 8; ++i) { if (tEncodeI64(&encoder, pReq->reserved[i]) < 0) return -1; } + + // 1st modification + if (tEncodeI16(&encoder, pReq->sttTrigger) < 0) return -1; + if (tEncodeI32(&encoder, pReq->minRows) < 0) return -1; + // 2nd modification + if (tEncodeI32(&encoder, pReq->walRetentionPeriod) < 0) return -1; + if (tEncodeI32(&encoder, pReq->walRetentionSize) < 0) return -1; tEndEncode(&encoder); int32_t tlen = encoder.pos; @@ -4066,6 +4475,23 @@ int32_t tDeserializeSAlterVnodeConfigReq(void *buf, int32_t bufLen, SAlterVnodeC if (tDecodeI64(&decoder, &pReq->reserved[i]) < 0) return -1; } + // 1st modification + if (tDecodeIsEnd(&decoder)) { + pReq->sttTrigger = -1; + pReq->minRows = -1; + } else { + if (tDecodeI16(&decoder, &pReq->sttTrigger) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->minRows) < 0) return -1; + } + + // 2n modification + if (tDecodeIsEnd(&decoder)) { + pReq->walRetentionPeriod = -1; + pReq->walRetentionSize = -1; + } else { + if (tDecodeI32(&decoder, &pReq->walRetentionPeriod) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->walRetentionSize) < 0) return -1; + } tEndDecode(&decoder); tDecoderClear(&decoder); return 0; @@ -4116,6 +4542,68 @@ int32_t tDeserializeSAlterVnodeReplicaReq(void *buf, int32_t bufLen, SAlterVnode return 0; } +int32_t tSerializeSDisableVnodeWriteReq(void *buf, int32_t bufLen, SDisableVnodeWriteReq *pReq) { + SEncoder encoder = {0}; + tEncoderInit(&encoder, buf, bufLen); + + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeI32(&encoder, pReq->vgId) < 0) return -1; + if (tEncodeI8(&encoder, pReq->disable) < 0) return -1; + + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tEncoderClear(&encoder); + return tlen; +} + +int32_t tDeserializeSDisableVnodeWriteReq(void *buf, int32_t bufLen, SDisableVnodeWriteReq *pReq) { + SDecoder decoder = {0}; + tDecoderInit(&decoder, buf, bufLen); + + if (tStartDecode(&decoder) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->vgId) < 0) return -1; + if (tDecodeI8(&decoder, &pReq->disable) < 0) return -1; + + tEndDecode(&decoder); + tDecoderClear(&decoder); + return 0; +} + +int32_t tSerializeSAlterVnodeHashRangeReq(void *buf, int32_t bufLen, SAlterVnodeHashRangeReq *pReq) { + SEncoder encoder = {0}; + tEncoderInit(&encoder, buf, bufLen); + + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeI32(&encoder, pReq->srcVgId) < 0) return -1; + if (tEncodeI32(&encoder, pReq->dstVgId) < 0) return -1; + if (tEncodeI32(&encoder, pReq->hashBegin) < 0) return -1; + if (tEncodeI32(&encoder, pReq->hashEnd) < 0) return -1; + if (tEncodeI64(&encoder, pReq->reserved) < 0) return -1; + + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tEncoderClear(&encoder); + return tlen; +} + +int32_t tDeserializeSAlterVnodeHashRangeReq(void *buf, int32_t bufLen, SAlterVnodeHashRangeReq *pReq) { + SDecoder decoder = {0}; + tDecoderInit(&decoder, buf, bufLen); + + if (tStartDecode(&decoder) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->srcVgId) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->dstVgId) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->hashBegin) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->hashEnd) < 0) return -1; + if (tDecodeI64(&decoder, &pReq->reserved) < 0) return -1; + + tEndDecode(&decoder); + tDecoderClear(&decoder); + return 0; +} + int32_t tSerializeSKillQueryReq(void *buf, int32_t bufLen, SKillQueryReq *pReq) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); @@ -4216,6 +4704,31 @@ int32_t tDeserializeSBalanceVgroupReq(void *buf, int32_t bufLen, SBalanceVgroupR return 0; } +int32_t tSerializeSBalanceVgroupLeaderReq(void *buf, int32_t bufLen, SBalanceVgroupLeaderReq *pReq) { + SEncoder encoder = {0}; + tEncoderInit(&encoder, buf, bufLen); + + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeI32(&encoder, pReq->useless) < 0) return -1; + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tEncoderClear(&encoder); + return tlen; +} + +int32_t tDeserializeSBalanceVgroupLeaderReq(void *buf, int32_t bufLen, SBalanceVgroupLeaderReq *pReq) { + SDecoder decoder = {0}; + tDecoderInit(&decoder, buf, bufLen); + + if (tStartDecode(&decoder) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->useless) < 0) return -1; + tEndDecode(&decoder); + + tDecoderClear(&decoder); + return 0; +} + int32_t tSerializeSMergeVgroupReq(void *buf, int32_t bufLen, SMergeVgroupReq *pReq) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); @@ -4299,6 +4812,31 @@ int32_t tDeserializeSSplitVgroupReq(void *buf, int32_t bufLen, SSplitVgroupReq * return 0; } +int32_t tSerializeSForceBecomeFollowerReq(void *buf, int32_t bufLen, SForceBecomeFollowerReq *pReq) { + SEncoder encoder = {0}; + tEncoderInit(&encoder, buf, bufLen); + + if (tStartEncode(&encoder) < 0) return -1; + if (tEncodeI32(&encoder, pReq->vgId) < 0) return -1; + tEndEncode(&encoder); + + int32_t tlen = encoder.pos; + tEncoderClear(&encoder); + return tlen; +} + +int32_t tDeserializeSForceBecomeFollowerReq(void *buf, int32_t bufLen, SForceBecomeFollowerReq *pReq) { + SDecoder decoder = {0}; + tDecoderInit(&decoder, buf, bufLen); + + if (tStartDecode(&decoder) < 0) return -1; + if (tDecodeI32(&decoder, &pReq->vgId) < 0) return -1; + tEndDecode(&decoder); + + tDecoderClear(&decoder); + return 0; +} + int32_t tSerializeSDCreateMnodeReq(void *buf, int32_t bufLen, SDCreateMnodeReq *pReq) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, bufLen); @@ -4870,9 +5408,9 @@ int32_t tSerializeSMqPollReq(void *buf, int32_t bufLen, SMqPollReq *pReq) { int32_t tDeserializeSMqPollReq(void *buf, int32_t bufLen, SMqPollReq *pReq) { int32_t headLen = sizeof(SMsgHead); - SMsgHead *pHead = buf; - pHead->vgId = pReq->head.vgId; - pHead->contLen = pReq->head.contLen; +// SMsgHead *pHead = buf; +// pHead->vgId = pReq->head.vgId; +// pHead->contLen = pReq->head.contLen; SDecoder decoder = {0}; tDecoderInit(&decoder, (char *)buf + headLen, bufLen - headLen); @@ -5425,6 +5963,16 @@ int32_t tSerializeSCMCreateStreamReq(void *buf, int32_t bufLen, const SCMCreateS if (tEncodeI32(&encoder, pField->bytes) < 0) return -1; if (tEncodeCStr(&encoder, pField->name) < 0) return -1; } + + if (tEncodeI8(&encoder, pReq->createStb) < 0) return -1; + if (tEncodeU64(&encoder, pReq->targetStbUid) < 0) return -1; + if (tEncodeI32(&encoder, taosArrayGetSize(pReq->fillNullCols)) < 0) return -1; + for (int32_t i = 0; i < taosArrayGetSize(pReq->fillNullCols); ++i) { + SColLocation *pCol = taosArrayGet(pReq->fillNullCols, i); + if (tEncodeI16(&encoder, pCol->slotId) < 0) return -1; + if (tEncodeI16(&encoder, pCol->colId) < 0) return -1; + if (tEncodeI8(&encoder, pCol->type) < 0) return -1; + } if (tEncodeI64(&encoder, pReq->deleteMark) < 0) return -1; if (tEncodeI8(&encoder, pReq->igUpdate) < 0) return -1; @@ -5487,6 +6035,28 @@ int32_t tDeserializeSCMCreateStreamReq(void *buf, int32_t bufLen, SCMCreateStrea } } } + if (tDecodeI8(&decoder, &pReq->createStb) < 0) return -1; + if (tDecodeU64(&decoder, &pReq->targetStbUid) < 0) return -1; + int32_t numOfFillNullCols = 0; + if (tDecodeI32(&decoder, &numOfFillNullCols) < 0) return -1; + if (numOfFillNullCols > 0) { + pReq->fillNullCols = taosArrayInit(numOfFillNullCols, sizeof(SColLocation)); + if (pReq->fillNullCols == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return -1; + } + + for (int32_t i = 0; i < numOfFillNullCols; ++i) { + SColLocation col = {0}; + if (tDecodeI16(&decoder, &col.slotId) < 0) return -1; + if (tDecodeI16(&decoder, &col.colId) < 0) return -1; + if (tDecodeI8(&decoder, &col.type) < 0) return -1; + if (taosArrayPush(pReq->fillNullCols, &col) == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return -1; + } + } + } if (tDecodeI64(&decoder, &pReq->deleteMark) < 0) return -1; if (tDecodeI8(&decoder, &pReq->igUpdate) < 0) return -1; @@ -5559,6 +6129,7 @@ void tFreeSCMCreateStreamReq(SCMCreateStreamReq *pReq) { taosArrayDestroy(pReq->pTags); taosMemoryFreeClear(pReq->sql); taosMemoryFreeClear(pReq->ast); + taosArrayDestroy(pReq->fillNullCols); } int32_t tEncodeSRSmaParam(SEncoder *pCoder, const SRSmaParam *pRSmaParam) { @@ -5633,30 +6204,6 @@ int tDecodeSVCreateStbReq(SDecoder *pCoder, SVCreateStbReq *pReq) { return 0; } -STSchema *tdGetSTSChemaFromSSChema(SSchema *pSchema, int32_t nCols, int32_t sver) { - STSchemaBuilder schemaBuilder = {0}; - if (tdInitTSchemaBuilder(&schemaBuilder, sver) < 0) { - return NULL; - } - - for (int i = 0; i < nCols; i++) { - SSchema *schema = pSchema + i; - if (tdAddColToSchema(&schemaBuilder, schema->type, schema->flags, schema->colId, schema->bytes) < 0) { - tdDestroyTSchemaBuilder(&schemaBuilder); - return NULL; - } - } - - STSchema *pNSchema = tdGetSchemaFromBuilder(&schemaBuilder); - if (pNSchema == NULL) { - tdDestroyTSchemaBuilder(&schemaBuilder); - return NULL; - } - - tdDestroyTSchemaBuilder(&schemaBuilder); - return pNSchema; -} - int tEncodeSVCreateTbReq(SEncoder *pCoder, const SVCreateTbReq *pReq) { if (tStartEncode(pCoder) < 0) return -1; @@ -5734,6 +6281,25 @@ int tDecodeSVCreateTbReq(SDecoder *pCoder, SVCreateTbReq *pReq) { return 0; } +void tDestroySVCreateTbReq(SVCreateTbReq *pReq, int32_t flags) { + if (pReq == NULL) return; + + if (flags & TSDB_MSG_FLG_ENCODE) { + // TODO + } else if (flags & TSDB_MSG_FLG_DECODE) { + if (pReq->comment) { + pReq->comment = NULL; + taosMemoryFree(pReq->comment); + } + + if (pReq->type == TSDB_CHILD_TABLE) { + if (pReq->ctb.tagName) taosArrayDestroy(pReq->ctb.tagName); + } else if (pReq->type == TSDB_NORMAL_TABLE) { + if (pReq->ntb.schemaRow.pSchema) taosMemoryFree(pReq->ntb.schemaRow.pSchema); + } + } +} + int tEncodeSVCreateTbBatchReq(SEncoder *pCoder, const SVCreateTbBatchReq *pReq) { int32_t nReq = taosArrayGetSize(pReq->pArray); @@ -6352,10 +6918,8 @@ int32_t tEncodeSTqOffsetVal(SEncoder *pEncoder, const STqOffsetVal *pOffsetVal) if (tEncodeI64(pEncoder, pOffsetVal->ts) < 0) return -1; } else if (pOffsetVal->type == TMQ_OFFSET__LOG) { if (tEncodeI64(pEncoder, pOffsetVal->version) < 0) return -1; - } else if (pOffsetVal->type < 0) { - // do nothing } else { - ASSERT(0); + // do nothing } return 0; } @@ -6367,10 +6931,8 @@ int32_t tDecodeSTqOffsetVal(SDecoder *pDecoder, STqOffsetVal *pOffsetVal) { if (tDecodeI64(pDecoder, &pOffsetVal->ts) < 0) return -1; } else if (pOffsetVal->type == TMQ_OFFSET__LOG) { if (tDecodeI64(pDecoder, &pOffsetVal->version) < 0) return -1; - } else if (pOffsetVal->type < 0) { - // do nothing } else { - ASSERT(0); + // do nothing } return 0; } @@ -6385,10 +6947,11 @@ int32_t tFormatOffset(char *buf, int32_t maxLen, const STqOffsetVal *pVal) { } else if (pVal->type == TMQ_OFFSET__LOG) { snprintf(buf, maxLen, "offset(log) ver:%" PRId64, pVal->version); } else if (pVal->type == TMQ_OFFSET__SNAPSHOT_DATA || pVal->type == TMQ_OFFSET__SNAPSHOT_META) { - snprintf(buf, maxLen, "offset(ss data) uid:%" PRId64 ", ts:%" PRId64, pVal->uid, pVal->ts); + snprintf(buf, maxLen, "offset(snapshot) uid:%" PRId64 " ts:%" PRId64, pVal->uid, pVal->ts); } else { - ASSERT(0); + return TSDB_CODE_INVALID_PARA; } + return 0; } @@ -6571,11 +7134,10 @@ int32_t tDecodeSMqDataRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) { } void tDeleteSMqDataRsp(SMqDataRsp *pRsp) { - taosArrayDestroy(pRsp->blockDataLen); - pRsp->blockDataLen = NULL; + pRsp->blockDataLen = taosArrayDestroy(pRsp->blockDataLen); taosArrayDestroyP(pRsp->blockData, (FDelete)taosMemoryFree); pRsp->blockData = NULL; - taosArrayDestroyP(pRsp->blockSchema, (FDelete)tDeleteSSchemaWrapper); + taosArrayDestroyP(pRsp->blockSchema, (FDelete)tDeleteSchemaWrapper); pRsp->blockSchema = NULL; taosArrayDestroyP(pRsp->blockTbName, (FDelete)taosMemoryFree); pRsp->blockTbName = NULL; @@ -6676,7 +7238,7 @@ void tDeleteSTaosxRsp(STaosxRsp *pRsp) { pRsp->blockDataLen = NULL; taosArrayDestroyP(pRsp->blockData, (FDelete)taosMemoryFree); pRsp->blockData = NULL; - taosArrayDestroyP(pRsp->blockSchema, (FDelete)tDeleteSSchemaWrapper); + taosArrayDestroyP(pRsp->blockSchema, (FDelete)tDeleteSchemaWrapper); pRsp->blockSchema = NULL; taosArrayDestroyP(pRsp->blockTbName, (FDelete)taosMemoryFree); pRsp->blockTbName = NULL; @@ -6725,3 +7287,333 @@ int32_t tDecodeSBatchDeleteReq(SDecoder *pDecoder, SBatchDeleteReq *pReq) { } return 0; } + +static int32_t tEncodeSSubmitTbData(SEncoder *pCoder, const SSubmitTbData *pSubmitTbData) { + if (tStartEncode(pCoder) < 0) return -1; + + if (tEncodeI32v(pCoder, pSubmitTbData->flags) < 0) return -1; + + // auto create table + if (pSubmitTbData->flags & SUBMIT_REQ_AUTO_CREATE_TABLE) { + ASSERT(pSubmitTbData->pCreateTbReq); + if (tEncodeSVCreateTbReq(pCoder, pSubmitTbData->pCreateTbReq) < 0) return -1; + } + + // submit data + if (tEncodeI64(pCoder, pSubmitTbData->suid) < 0) return -1; + if (tEncodeI64(pCoder, pSubmitTbData->uid) < 0) return -1; + if (tEncodeI32v(pCoder, pSubmitTbData->sver) < 0) return -1; + + if (pSubmitTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + uint64_t nColData = TARRAY_SIZE(pSubmitTbData->aCol); + SColData *aColData = (SColData *)TARRAY_DATA(pSubmitTbData->aCol); + + if (tEncodeU64v(pCoder, nColData) < 0) return -1; + + for (uint64_t i = 0; i < nColData; i++) { + pCoder->pos += tPutColData(pCoder->data ? pCoder->data + pCoder->pos : NULL, &aColData[i]); + } + } else { + if (tEncodeU64v(pCoder, TARRAY_SIZE(pSubmitTbData->aRowP)) < 0) return -1; + + SRow **rows = (SRow **)TARRAY_DATA(pSubmitTbData->aRowP); + for (int32_t iRow = 0; iRow < TARRAY_SIZE(pSubmitTbData->aRowP); ++iRow) { + if (pCoder->data) memcpy(pCoder->data + pCoder->pos, rows[iRow], rows[iRow]->len); + pCoder->pos += rows[iRow]->len; + } + } + + tEndEncode(pCoder); + return 0; +} + +static int32_t tDecodeSSubmitTbData(SDecoder *pCoder, SSubmitTbData *pSubmitTbData) { + int32_t code = 0; + + if (tStartDecode(pCoder) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + if (tDecodeI32v(pCoder, &pSubmitTbData->flags) < 0) return -1; + + if (pSubmitTbData->flags & SUBMIT_REQ_AUTO_CREATE_TABLE) { + pSubmitTbData->pCreateTbReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq)); + if (pSubmitTbData->pCreateTbReq == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + if (tDecodeSVCreateTbReq(pCoder, pSubmitTbData->pCreateTbReq) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + } + + // submit data + if (tDecodeI64(pCoder, &pSubmitTbData->suid) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + if (tDecodeI64(pCoder, &pSubmitTbData->uid) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + if (tDecodeI32v(pCoder, &pSubmitTbData->sver) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + if (pSubmitTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + uint64_t nColData; + + if (tDecodeU64v(pCoder, &nColData) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + pSubmitTbData->aCol = taosArrayInit(nColData, sizeof(SColData)); + if (pSubmitTbData->aCol == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + for (int32_t i = 0; i < nColData; ++i) { + pCoder->pos += tGetColData(pCoder->data + pCoder->pos, taosArrayReserve(pSubmitTbData->aCol, 1)); + } + } else { + uint64_t nRow; + if (tDecodeU64v(pCoder, &nRow) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + pSubmitTbData->aRowP = taosArrayInit(nRow, sizeof(SRow *)); + if (pSubmitTbData->aRowP == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + for (int32_t iRow = 0; iRow < nRow; ++iRow) { + SRow **ppRow = taosArrayReserve(pSubmitTbData->aRowP, 1); + + *ppRow = (SRow *)(pCoder->data + pCoder->pos); + pCoder->pos += (*ppRow)->len; + } + } + + tEndDecode(pCoder); + +_exit: + if (code) { + // TODO: clear + } + return 0; +} + +int32_t tEncodeSubmitReq(SEncoder *pCoder, const SSubmitReq2 *pReq) { + if (tStartEncode(pCoder) < 0) return -1; + + if (tEncodeU64v(pCoder, taosArrayGetSize(pReq->aSubmitTbData)) < 0) return -1; + for (uint64_t i = 0; i < taosArrayGetSize(pReq->aSubmitTbData); i++) { + if (tEncodeSSubmitTbData(pCoder, taosArrayGet(pReq->aSubmitTbData, i)) < 0) return -1; + } + + tEndEncode(pCoder); + return 0; +} + +int32_t tDecodeSubmitReq(SDecoder *pCoder, SSubmitReq2 *pReq) { + int32_t code = 0; + + memset(pReq, 0, sizeof(*pReq)); + + // decode + if (tStartDecode(pCoder) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + uint64_t nSubmitTbData; + if (tDecodeU64v(pCoder, &nSubmitTbData) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + pReq->aSubmitTbData = taosArrayInit(nSubmitTbData, sizeof(SSubmitTbData)); + if (pReq->aSubmitTbData == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + for (uint64_t i = 0; i < nSubmitTbData; i++) { + if (tDecodeSSubmitTbData(pCoder, taosArrayReserve(pReq->aSubmitTbData, 1)) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + } + + tEndDecode(pCoder); + +_exit: + if (code) { + if (pReq->aSubmitTbData) { + // todo + taosArrayDestroy(pReq->aSubmitTbData); + pReq->aSubmitTbData = NULL; + } + } + return code; +} + +void tDestroySubmitTbData(SSubmitTbData *pTbData, int32_t flag) { + if (NULL == pTbData) { + return; + } + + if (flag == TSDB_MSG_FLG_ENCODE || flag == TSDB_MSG_FLG_CMPT) { + if (pTbData->pCreateTbReq) { + if (flag == TSDB_MSG_FLG_ENCODE) { + tdDestroySVCreateTbReq(pTbData->pCreateTbReq); + } else { + tDestroySVCreateTbReq(pTbData->pCreateTbReq, TSDB_MSG_FLG_DECODE); + } + taosMemoryFree(pTbData->pCreateTbReq); + } + + if (pTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + int32_t nColData = TARRAY_SIZE(pTbData->aCol); + SColData *aColData = (SColData *)TARRAY_DATA(pTbData->aCol); + + for (int32_t i = 0; i < nColData; ++i) { + tColDataDestroy(&aColData[i]); + } + taosArrayDestroy(pTbData->aCol); + } else { + int32_t nRow = TARRAY_SIZE(pTbData->aRowP); + SRow **rows = (SRow **)TARRAY_DATA(pTbData->aRowP); + + for (int32_t i = 0; i < nRow; ++i) { + tRowDestroy(rows[i]); + } + taosArrayDestroy(pTbData->aRowP); + } + } else if (flag == TSDB_MSG_FLG_DECODE) { + if (pTbData->pCreateTbReq) { + tDestroySVCreateTbReq(pTbData->pCreateTbReq, TSDB_MSG_FLG_DECODE); + taosMemoryFree(pTbData->pCreateTbReq); + } + + if (pTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + taosArrayDestroy(pTbData->aCol); + } else { + taosArrayDestroy(pTbData->aRowP); + } + } +} + +void tDestroySubmitReq(SSubmitReq2 *pReq, int32_t flag) { + if (pReq->aSubmitTbData == NULL) return; + + int32_t nSubmitTbData = TARRAY_SIZE(pReq->aSubmitTbData); + SSubmitTbData *aSubmitTbData = (SSubmitTbData *)TARRAY_DATA(pReq->aSubmitTbData); + + for (int32_t i = 0; i < nSubmitTbData; i++) { + tDestroySubmitTbData(&aSubmitTbData[i], flag); + } + taosArrayDestroy(pReq->aSubmitTbData); + pReq->aSubmitTbData = NULL; +} + +int32_t tEncodeSSubmitRsp2(SEncoder *pCoder, const SSubmitRsp2 *pRsp) { + if (tStartEncode(pCoder) < 0) return -1; + + if (tEncodeI32v(pCoder, pRsp->affectedRows) < 0) return -1; + + if (tEncodeU64v(pCoder, taosArrayGetSize(pRsp->aCreateTbRsp)) < 0) return -1; + for (int32_t i = 0; i < taosArrayGetSize(pRsp->aCreateTbRsp); ++i) { + if (tEncodeSVCreateTbRsp(pCoder, taosArrayGet(pRsp->aCreateTbRsp, i)) < 0) return -1; + } + + tEndEncode(pCoder); + return 0; +} + +int32_t tDecodeSSubmitRsp2(SDecoder *pCoder, SSubmitRsp2 *pRsp) { + int32_t code = 0; + + memset(pRsp, 0, sizeof(SSubmitRsp2)); + + // decode + if (tStartDecode(pCoder) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + if (tDecodeI32v(pCoder, &pRsp->affectedRows) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + uint64_t nCreateTbRsp; + if (tDecodeU64v(pCoder, &nCreateTbRsp) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + if (nCreateTbRsp) { + pRsp->aCreateTbRsp = taosArrayInit(nCreateTbRsp, sizeof(SVCreateTbRsp)); + if (pRsp->aCreateTbRsp == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + for (int32_t i = 0; i < nCreateTbRsp; ++i) { + SVCreateTbRsp *pCreateTbRsp = taosArrayReserve(pRsp->aCreateTbRsp, 1); + if (tDecodeSVCreateTbRsp(pCoder, pCreateTbRsp) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + } + } + + tEndDecode(pCoder); + +_exit: + if (code) { + if (pRsp->aCreateTbRsp) { + taosArrayDestroyEx(pRsp->aCreateTbRsp, NULL /* todo */); + } + } + return code; +} + +void tDestroySSubmitRsp2(SSubmitRsp2 *pRsp, int32_t flag) { + if (NULL == pRsp) { + return; + } + + if (flag & TSDB_MSG_FLG_ENCODE) { + if (pRsp->aCreateTbRsp) { + int32_t nCreateTbRsp = TARRAY_SIZE(pRsp->aCreateTbRsp); + SVCreateTbRsp *aCreateTbRsp = TARRAY_DATA(pRsp->aCreateTbRsp); + for (int32_t i = 0; i < nCreateTbRsp; ++i) { + if (aCreateTbRsp[i].pMeta) { + taosMemoryFree(aCreateTbRsp[i].pMeta); + } + } + taosArrayDestroy(pRsp->aCreateTbRsp); + } + } else if (flag & TSDB_MSG_FLG_DECODE) { + if (pRsp->aCreateTbRsp) { + int32_t nCreateTbRsp = TARRAY_SIZE(pRsp->aCreateTbRsp); + SVCreateTbRsp *aCreateTbRsp = TARRAY_DATA(pRsp->aCreateTbRsp); + for (int32_t i = 0; i < nCreateTbRsp; ++i) { + if (aCreateTbRsp[i].pMeta) { + taosMemoryFree(aCreateTbRsp[i].pMeta); + } + } + taosArrayDestroy(pRsp->aCreateTbRsp); + } + } +} diff --git a/source/common/src/tname.c b/source/common/src/tname.c index f21938ed29632817d84d6908af119a7fc1c73ffe..c6210ca8c9f5a7674295cbd13d454969779e68a8 100644 --- a/source/common/src/tname.c +++ b/source/common/src/tname.c @@ -90,10 +90,8 @@ int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, in SName* toName(int32_t acctId, const char* pDbName, const char* pTableName, SName* pName) { pName->type = TSDB_TABLE_NAME_T; pName->acctId = acctId; - memset(pName->dbname, 0, TSDB_DB_NAME_LEN); - strncpy(pName->dbname, pDbName, TSDB_DB_NAME_LEN - 1); - memset(pName->tname, 0, TSDB_TABLE_NAME_LEN); - strncpy(pName->tname, pTableName, TSDB_TABLE_NAME_LEN - 1); + snprintf(pName->dbname, sizeof(pName->dbname), "%s", pDbName); + snprintf(pName->tname, sizeof(pName->tname), "%s", pTableName); return pName; } @@ -124,10 +122,8 @@ int32_t tNameLen(const SName* name) { int32_t len2 = (int32_t)strlen(name->tname); if (name->type == TSDB_DB_NAME_T) { - ASSERT(len2 == 0); return len + len1 + TSDB_NAME_DELIMITER_LEN; } else { - ASSERT(len2 > 0); return len + len1 + len2 + TSDB_NAME_DELIMITER_LEN * 2; } } @@ -162,9 +158,7 @@ int32_t tNameGetFullDbName(const SName* name, char* dst) { return 0; } -bool tNameIsEmpty(const SName* name) { - return name->type == 0 || name->acctId == 0; -} +bool tNameIsEmpty(const SName* name) { return name->type == 0 || name->acctId == 0; } const char* tNameGetTableName(const SName* name) { ASSERT(name != NULL && name->type == TSDB_TABLE_NAME_T); @@ -284,8 +278,8 @@ int32_t tNameFromString(SName* dst, const char* str, uint32_t type) { } static int compareKv(const void* p1, const void* p2) { - SSmlKv* kv1 = *(SSmlKv**)p1; - SSmlKv* kv2 = *(SSmlKv**)p2; + SSmlKv* kv1 = (SSmlKv*)p1; + SSmlKv* kv2 = (SSmlKv*)p2; int32_t kvLen1 = kv1->keyLen; int32_t kvLen2 = kv2->keyLen; int32_t res = strncasecmp(kv1->key, kv2->key, TMIN(kvLen1, kvLen2)); @@ -302,11 +296,11 @@ static int compareKv(const void* p1, const void* p2) { void buildChildTableName(RandTableName* rName) { SStringBuilder sb = {0}; taosStringBuilderAppendStringLen(&sb, rName->stbFullName, rName->stbFullNameLen); - if(sb.buf == NULL) return; + if (sb.buf == NULL) return; taosArraySort(rName->tags, compareKv); for (int j = 0; j < taosArrayGetSize(rName->tags); ++j) { taosStringBuilderAppendChar(&sb, ','); - SSmlKv* tagKv = taosArrayGetP(rName->tags, j); + SSmlKv* tagKv = taosArrayGet(rName->tags, j); taosStringBuilderAppendStringLen(&sb, tagKv->key, tagKv->keyLen); taosStringBuilderAppendChar(&sb, '='); if (IS_VAR_DATA_TYPE(tagKv->type)) { diff --git a/source/common/src/trow.c b/source/common/src/trow.c index 969da4226fb3cf59e124432701d64a270f20c373..9d381ce15fa762b74cecf23eeec1fa6667a10b99 100644 --- a/source/common/src/trow.c +++ b/source/common/src/trow.c @@ -341,7 +341,7 @@ int32_t tdSTSRowNew(SArray *pArray, STSchema *pTSchema, STSRow **ppRow) { } if (iColumn == 0) { - ASSERT(pColVal->cid == pTColumn->colId); + ASSERT(pColVal && pColVal->cid == pTColumn->colId); ASSERT(pTColumn->type == TSDB_DATA_TYPE_TIMESTAMP); ASSERT(pTColumn->colId == PRIMARYKEY_TIMESTAMP_COL_ID); } else { diff --git a/source/common/src/ttime.c b/source/common/src/ttime.c index 165a4ff95b4d3c60612fe22516d92ba98f5e8b35..dbb31374de2f5600ff96d757b791beadf33e79c6 100644 --- a/source/common/src/ttime.c +++ b/source/common/src/ttime.c @@ -68,12 +68,12 @@ static int64_t user_mktime64(const uint32_t year0, const uint32_t mon0, const ui // ==== mktime() kernel code =================// static int64_t m_deltaUtc = 0; -void deltaToUtcInitOnce() { - struct tm tm = {0}; - (void)taosStrpTime("1970-01-01 00:00:00", (const char*)("%Y-%m-%d %H:%M:%S"), &tm); - m_deltaUtc = (int64_t)taosMktime(&tm); - // printf("====delta:%lld\n\n", seconds); +void deltaToUtcInitOnce() { + struct tm tm = {0}; + (void)taosStrpTime("1970-01-01 00:00:00", (const char*)("%Y-%m-%d %H:%M:%S"), &tm); + m_deltaUtc = (int64_t)taosMktime(&tm); + // printf("====delta:%lld\n\n", seconds); } static int64_t parseFraction(char* str, char** end, int32_t timePrec); @@ -724,7 +724,7 @@ int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision) { struct tm tm; time_t tt = (time_t)(t / TSDB_TICK_PER_SECOND(precision)); - taosLocalTime(&tt, &tm); + taosLocalTime(&tt, &tm, NULL); int32_t mon = tm.tm_year * 12 + tm.tm_mon + (int32_t)numOfMonth; tm.tm_year = mon / 12; tm.tm_mon = mon % 12; @@ -747,11 +747,11 @@ int32_t taosTimeCountInterval(int64_t skey, int64_t ekey, int64_t interval, char struct tm tm; time_t t = (time_t)skey; - taosLocalTime(&t, &tm); + taosLocalTime(&t, &tm, NULL); int32_t smon = tm.tm_year * 12 + tm.tm_mon; t = (time_t)ekey; - taosLocalTime(&t, &tm); + taosLocalTime(&t, &tm, NULL); int32_t emon = tm.tm_year * 12 + tm.tm_mon; if (unit == 'y') { @@ -774,7 +774,7 @@ int64_t taosTimeTruncate(int64_t ts, const SInterval* pInterval) { start /= (int64_t)(TSDB_TICK_PER_SECOND(precision)); struct tm tm; time_t tt = (time_t)start; - taosLocalTime(&tt, &tm); + taosLocalTime(&tt, &tm, NULL); tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour = 0; @@ -895,13 +895,17 @@ const char* fmtts(int64_t ts) { if (ts > -62135625943 && ts < 32503651200) { time_t t = (time_t)ts; - taosLocalTime(&t, &tm); + if (taosLocalTime(&t, &tm, buf) == NULL) { + return buf; + } pos += strftime(buf + pos, sizeof(buf), "s=%Y-%m-%d %H:%M:%S", &tm); } if (ts > -62135625943000 && ts < 32503651200000) { time_t t = (time_t)(ts / 1000); - taosLocalTime(&t, &tm); + if (taosLocalTime(&t, &tm, buf) == NULL) { + return buf; + } if (pos > 0) { buf[pos++] = ' '; buf[pos++] = '|'; @@ -913,7 +917,9 @@ const char* fmtts(int64_t ts) { { time_t t = (time_t)(ts / 1000000); - taosLocalTime(&t, &tm); + if (taosLocalTime(&t, &tm, buf) == NULL) { + return buf; + } if (pos > 0) { buf[pos++] = ' '; buf[pos++] = '|'; @@ -965,7 +971,9 @@ void taosFormatUtcTime(char* buf, int32_t bufLen, int64_t t, int32_t precision) ASSERT(false); } - taosLocalTime(", &ptm); + if (taosLocalTime(", &ptm, buf) == NULL) { + return; + } int32_t length = (int32_t)strftime(ts, 40, "%Y-%m-%dT%H:%M:%S", &ptm); length += snprintf(ts + length, fractionLen, format, mod); length += (int32_t)strftime(ts + length, 40 - length, "%z", &ptm); diff --git a/source/common/src/ttszip.c b/source/common/src/ttszip.c index 0faa6eb4c85a318a25e6324063cf8ede237c88f6..f415bd20cd3a1a98d0478dd5ae281d02f89cd39d 100644 --- a/source/common/src/ttszip.c +++ b/source/common/src/ttszip.c @@ -982,7 +982,6 @@ void tsBufSetCursor(STSBuf* pTSBuf, STSCursor* pCur) { return; } - // assert(pCur->vgroupIndex != -1 && pCur->tsIndex >= 0 && pCur->blockIndex >= 0); if (pCur->vgroupIndex != -1) { tsBufGetBlock(pTSBuf, pCur->vgroupIndex, pCur->blockIndex); } diff --git a/source/common/src/tvariant.c b/source/common/src/tvariant.c index de225581a679db43a4c5b7aaccc12854d75d0495..db69fe9d48ae14e880a82039bc084abbb80b7d74 100644 --- a/source/common/src/tvariant.c +++ b/source/common/src/tvariant.c @@ -145,19 +145,6 @@ void taosVariantDestroy(SVariant *pVar) { pVar->nLen = 0; } - // NOTE: this is only for string array - if (pVar->nType == TSDB_DATA_TYPE_POINTER_ARRAY) { - size_t num = taosArrayGetSize(pVar->arr); - for (size_t i = 0; i < num; i++) { - void *p = taosArrayGetP(pVar->arr, i); - taosMemoryFree(p); - } - taosArrayDestroy(pVar->arr); - pVar->arr = NULL; - } else if (pVar->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { - taosArrayDestroy(pVar->arr); - pVar->arr = NULL; - } } void taosVariantAssign(SVariant *pDst, const SVariant *pSrc) { @@ -180,28 +167,8 @@ void taosVariantAssign(SVariant *pDst, const SVariant *pSrc) { if (IS_NUMERIC_TYPE(pSrc->nType) || (pSrc->nType == TSDB_DATA_TYPE_BOOL)) { pDst->i = pSrc->i; - } else if (pSrc->nType == TSDB_DATA_TYPE_POINTER_ARRAY) { // this is only for string array - size_t num = taosArrayGetSize(pSrc->arr); - pDst->arr = taosArrayInit(num, sizeof(char *)); - for (size_t i = 0; i < num; i++) { - char *p = (char *)taosArrayGetP(pSrc->arr, i); - char *n = strdup(p); - taosArrayPush(pDst->arr, &n); - } - } else if (pSrc->nType == TSDB_DATA_TYPE_VALUE_ARRAY) { - size_t num = taosArrayGetSize(pSrc->arr); - pDst->arr = taosArrayInit(num, sizeof(int64_t)); - pDst->nLen = pSrc->nLen; - ASSERT(pSrc->nLen == num); - for (size_t i = 0; i < num; i++) { - int64_t *p = taosArrayGet(pSrc->arr, i); - taosArrayPush(pDst->arr, p); - } } - if (pDst->nType != TSDB_DATA_TYPE_POINTER_ARRAY && pDst->nType != TSDB_DATA_TYPE_VALUE_ARRAY) { - pDst->nLen = tDataTypes[pDst->nType].bytes; - } } int32_t taosVariantCompare(const SVariant *p1, const SVariant *p2) { diff --git a/source/common/test/commonTests.cpp b/source/common/test/commonTests.cpp index 8460d71e56ea70b5b5bc5c5a536476c98e007716..8a77087d23ecec00012baca351d9951639a9283d 100644 --- a/source/common/test/commonTests.cpp +++ b/source/common/test/commonTests.cpp @@ -109,14 +109,14 @@ TEST(testCase, Datablock_test) { if (i & 0x01) { int32_t len = sprintf(buf, str, i); STR_TO_VARSTR(varbuf, buf) - colDataAppend(p0, i, (const char*)&i, false); - colDataAppend(p1, i, (const char*)varbuf, false); + colDataSetVal(p0, i, (const char*)&i, false); + colDataSetVal(p1, i, (const char*)varbuf, false); memset(varbuf, 0, sizeof(varbuf)); memset(buf, 0, sizeof(buf)); } else { - colDataAppend(p0, i, (const char*)&i, true); - colDataAppend(p1, i, (const char*)varbuf, true); + colDataSetVal(p0, i, (const char*)&i, true); + colDataSetVal(p1, i, (const char*)varbuf, true); } b->info.rows++; @@ -185,8 +185,8 @@ TEST(testCase, non_var_dataBlock_split_test) { SColumnInfoData* p1 = (SColumnInfoData*)taosArrayGet(b->pDataBlock, 1); int8_t v = i; - colDataAppend(p0, i, (const char*)&i, false); - colDataAppend(p1, i, (const char*)&v, false); + colDataSetVal(p0, i, (const char*)&i, false); + colDataSetVal(p1, i, (const char*)&v, false); b->info.rows++; } @@ -231,12 +231,12 @@ TEST(testCase, var_dataBlock_split_test) { SColumnInfoData* p1 = (SColumnInfoData*)taosArrayGet(b->pDataBlock, 1); int8_t v = i; - colDataAppend(p0, i, (const char*)&i, false); + colDataSetVal(p0, i, (const char*)&i, false); sprintf(buf, "the number of row:%d", i); int32_t len = sprintf(buf1, buf, i); STR_TO_VARSTR(buf1, buf) - colDataAppend(p1, i, buf1, false); + colDataSetVal(p1, i, buf1, false); b->info.rows++; memset(buf, 0, sizeof(buf)); diff --git a/source/common/test/dataformatTest.cpp b/source/common/test/dataformatTest.cpp index b05ae602f8ee5299ed108756f73f648867d1f81a..4f8652d02cc0602583edff7f59354d9d093275fc 100644 --- a/source/common/test/dataformatTest.cpp +++ b/source/common/test/dataformatTest.cpp @@ -117,7 +117,7 @@ STSchema *genSTSchema(int16_t nCols) { } STSchema *pResult = NULL; - pResult = tdGetSTSChemaFromSSChema(pSchema, nCols, 1); + pResult = tBuildTSchema(pSchema, nCols, 1); taosMemoryFree(pSchema); return pResult; diff --git a/source/dnode/mgmt/exe/dmMain.c b/source/dnode/mgmt/exe/dmMain.c index 4910b0ac3faab414b4a3197cd2412a7e4badd21e..da9a57387d1f93f5dad60f3670ffa3f2bec7ed1e 100644 --- a/source/dnode/mgmt/exe/dmMain.c +++ b/source/dnode/mgmt/exe/dmMain.c @@ -18,7 +18,23 @@ #include "mnode.h" #include "tconfig.h" #include "tglobal.h" +#include "version.h" +#if defined(CUS_NAME) || defined(CUS_PROMPT) || defined(CUS_EMAIL) +#include "cus_name.h" +#else +#ifndef CUS_NAME + #define CUS_NAME "TDengine" +#endif + +#ifndef CUS_PROMPT + #define CUS_PROMPT "taos" +#endif + +#ifndef CUS_EMAIL + #define CUS_EMAIL "" +#endif +#endif // clang-format off #define DM_APOLLO_URL "The apollo string to use when configuring the server, such as: -a 'jsonFile:./tests/cfg.json', cfg.json text can be '{\"fqdn\":\"td1\"}'." #define DM_CFG_DIR "Configuration directory." @@ -29,6 +45,7 @@ #define DM_MACHINE_CODE "Get machine code." #define DM_VERSION "Print program version." #define DM_EMAIL "" +#define DM_MEM_DBG "Enable memory debug" // clang-format on static struct { #ifdef WINDOWS @@ -37,6 +54,7 @@ static struct { bool dumpConfig; bool dumpSdb; bool generateGrant; + bool memDbg; bool printAuth; bool printVersion; bool printHelp; @@ -69,33 +87,33 @@ static void dmStopDnode(int signum, void *sigInfo, void *context) { } void dmLogCrash(int signum, void *sigInfo, void *context) { - taosIgnSignal(SIGTERM); - taosIgnSignal(SIGHUP); - taosIgnSignal(SIGINT); - taosIgnSignal(SIGBREAK); + // taosIgnSignal(SIGTERM); + // taosIgnSignal(SIGHUP); + // taosIgnSignal(SIGINT); + // taosIgnSignal(SIGBREAK); -#ifndef WINDOWS +#ifndef WINDOWS taosIgnSignal(SIGBUS); #endif taosIgnSignal(SIGABRT); taosIgnSignal(SIGFPE); taosIgnSignal(SIGSEGV); - char *pMsg = NULL; + char *pMsg = NULL; const char *flags = "UTL FATAL "; ELogLevel level = DEBUG_FATAL; int32_t dflag = 255; - int64_t msgLen= -1; - + int64_t msgLen = -1; + if (tsEnableCrashReport) { if (taosGenCrashJsonMsg(signum, &pMsg, dmGetClusterId(), global.startTime)) { taosPrintLog(flags, level, dflag, "failed to generate crash json msg"); goto _return; } else { - msgLen = strlen(pMsg); + msgLen = strlen(pMsg); } } - + _return: taosLogCrashInfo("taosd", pMsg, msgLen, signum, sigInfo); @@ -121,7 +139,7 @@ static void dmSetSignalHandle() { #ifndef WINDOWS taosSetSignal(SIGBUS, dmLogCrash); -#endif +#endif taosSetSignal(SIGABRT, dmLogCrash); taosSetSignal(SIGFPE, dmLogCrash); taosSetSignal(SIGSEGV, dmLogCrash); @@ -132,7 +150,7 @@ static int32_t dmParseArgs(int32_t argc, char const *argv[]) { int32_t cmdEnvIndex = 0; if (argc < 2) return 0; - + global.envCmd = taosMemoryMalloc((argc - 1) * sizeof(char *)); memset(global.envCmd, 0, (argc - 1) * sizeof(char *)); for (int32_t i = 1; i < argc; ++i) { @@ -166,8 +184,10 @@ static int32_t dmParseArgs(int32_t argc, char const *argv[]) { } else if (strcmp(argv[i], "-e") == 0) { global.envCmd[cmdEnvIndex] = argv[++i]; cmdEnvIndex++; + } else if (strcmp(argv[i], "-dm") == 0) { + global.memDbg = true; } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--usage") == 0 || - strcmp(argv[i], "-?")) { + strcmp(argv[i], "-?") == 0) { global.printHelp = true; } else { } @@ -199,6 +219,9 @@ static void dmPrintVersion() { #endif printf("%s version: %s compatible_version: %s\n", releaseName, version, compatible_version); printf("gitinfo: %s\n", gitinfo); +#ifdef TD_ENTERPRISE + printf("gitinfoOfInternal: %s\n", gitinfoOfInternal); +#endif printf("buildInfo: %s\n", buildinfo); } @@ -212,6 +235,7 @@ static void dmPrintHelp() { printf("%s%s%s%s\n", indent, "-e,", indent, DM_ENV_CMD); printf("%s%s%s%s\n", indent, "-E,", indent, DM_ENV_FILE); printf("%s%s%s%s\n", indent, "-k,", indent, DM_MACHINE_CODE); + printf("%s%s%s%s\n", indent, "-dm,", indent, DM_MEM_DBG); printf("%s%s%s%s\n", indent, "-V,", indent, DM_VERSION); printf("\n\nReport bugs to %s.\n", DM_EMAIL); @@ -223,7 +247,7 @@ static void dmDumpCfg() { } static int32_t dmInitLog() { - return taosCreateLog("taosdlog", 1, configDir, global.envCmd, global.envFile, global.apolloUrl, global.pArgs, 0); + return taosCreateLog(CUS_PROMPT"dlog", 1, configDir, global.envCmd, global.envFile, global.apolloUrl, global.pArgs, 0); } static void taosCleanupArgs() { @@ -272,6 +296,18 @@ int mainWindows(int argc, char **argv) { return 0; } +#if defined(LINUX) + if (global.memDbg) { + int32_t code = taosMemoryDbgInit(); + if (code) { + printf("failed to init memory dbg, error:%s\n", tstrerror(code)); + return code; + } + tsAsyncLog = false; + printf("memory dbg enabled\n"); + } +#endif + if (dmInitLog() != 0) { printf("failed to start since init log error\n"); taosCleanupArgs(); diff --git a/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h b/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h index ff32cbcb08b2c743644df3b077408dfd4878e999..600a1f6829e11a1d38ffa262e7d360687c67b90d 100644 --- a/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h +++ b/source/dnode/mgmt/mgmt_dnode/inc/dmInt.h @@ -48,7 +48,7 @@ int32_t dmProcessAuthRsp(SDnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t dmProcessGrantRsp(SDnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t dmProcessServerRunStatus(SDnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t dmProcessRetrieve(SDnodeMgmt *pMgmt, SRpcMsg *pMsg); -int32_t dmProcessGrantReq(SRpcMsg *pMsg); +int32_t dmProcessGrantReq(void *pInfo, SRpcMsg *pMsg); // dmWorker.c int32_t dmPutNodeMsgToMgmtQueue(SDnodeMgmt *pMgmt, SRpcMsg *pMsg); diff --git a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c index 3e9084bd1119844300607d3772e7e124df596017..228f301aec7712fce516ddad2d22f4b2823a36b0 100644 --- a/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c +++ b/source/dnode/mgmt/mgmt_dnode/src/dmHandle.c @@ -61,6 +61,16 @@ static void dmProcessStatusRsp(SDnodeMgmt *pMgmt, SRpcMsg *pRsp) { rpcFreeCont(pRsp->pCont); } +void dmEpSetToStr(char *buf, int32_t len, SEpSet *epSet) { + int32_t n = 0; + n += snprintf(buf + n, len - n, "%s", "{"); + for (int i = 0; i < epSet->numOfEps; i++) { + n += snprintf(buf + n, len - n, "%s:%d%s", epSet->eps[i].fqdn, epSet->eps[i].port, + (i + 1 < epSet->numOfEps ? ", " : "")); + } + n += snprintf(buf + n, len - n, "%s", "}"); +} + void dmSendStatusReq(SDnodeMgmt *pMgmt) { SStatusReq req = {0}; @@ -119,11 +129,10 @@ void dmSendStatusReq(SDnodeMgmt *pMgmt) { dmGetMnodeEpSet(pMgmt->pData, &epSet); rpcSendRecv(pMgmt->msgCb.clientRpc, &epSet, &rpcMsg, &rpcRsp); if (rpcRsp.code != 0) { - dError("failed to send status req since %s, numOfEps:%d inUse:%d", tstrerror(rpcRsp.code), epSet.numOfEps, - epSet.inUse); - for (int32_t i = 0; i < epSet.numOfEps; ++i) { - dDebug("index:%d, mnode ep:%s:%u", i, epSet.eps[i].fqdn, epSet.eps[i].port); - } + dmRotateMnodeEpSet(pMgmt->pData); + char tbuf[256]; + dmEpSetToStr(tbuf, sizeof(tbuf), &epSet); + dError("failed to send status req since %s, epSet:%s, inUse:%d", tstrerror(rpcRsp.code), tbuf, epSet.inUse); } dmProcessStatusRsp(pMgmt, &rpcRsp); } @@ -242,19 +251,19 @@ int32_t dmAppendVariablesToBlock(SSDataBlock *pBlock, int32_t dnodeId) { GRANT_CFG_SKIP; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, c++); - colDataAppend(pColInfo, i, (const char *)&dnodeId, false); + colDataSetVal(pColInfo, i, (const char *)&dnodeId, false); char name[TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(name, pItem->name, TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE); pColInfo = taosArrayGet(pBlock->pDataBlock, c++); - colDataAppend(pColInfo, i, name, false); + colDataSetVal(pColInfo, i, name, false); char value[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0}; int32_t valueLen = 0; cfgDumpItemValue(pItem, &value[VARSTR_HEADER_SIZE], TSDB_CONFIG_VALUE_LEN, &valueLen); varDataSetLen(value, valueLen); pColInfo = taosArrayGet(pBlock->pDataBlock, c++); - colDataAppend(pColInfo, i, value, false); + colDataSetVal(pColInfo, i, value, false); numOfRows++; } diff --git a/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c b/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c index 76c8e09b70a31c8e9168809dea69bc1a1a3e5478..0d3b423771267cc567a4cfc95f2b550c508342d3 100644 --- a/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c +++ b/source/dnode/mgmt/mgmt_dnode/src/dmWorker.c @@ -234,7 +234,7 @@ static void dmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) { code = dmProcessRetrieve(pMgmt, pMsg); break; case TDMT_MND_GRANT: - code = dmProcessGrantReq(pMsg); + code = dmProcessGrantReq(&pMgmt->pData->clusterId, pMsg); break; default: terrno = TSDB_CODE_MSG_NOT_PROCESSED; diff --git a/source/dnode/mgmt/mgmt_mnode/inc/mmInt.h b/source/dnode/mgmt/mgmt_mnode/inc/mmInt.h index b47742b4ed8db0cf55df46118b20a07bf00bd6bd..24f75e3c8b01dd41f958ec5913352b9baba991b7 100644 --- a/source/dnode/mgmt/mgmt_mnode/inc/mmInt.h +++ b/source/dnode/mgmt/mgmt_mnode/inc/mmInt.h @@ -34,7 +34,7 @@ typedef struct SMnodeMgmt { SSingleWorker readWorker; SSingleWorker writeWorker; SSingleWorker syncWorker; - SSingleWorker syncCtrlWorker; + SSingleWorker syncRdWorker; bool stopped; int32_t refCount; TdThreadRwlock lock; @@ -54,7 +54,7 @@ int32_t mmStartWorker(SMnodeMgmt *pMgmt); void mmStopWorker(SMnodeMgmt *pMgmt); int32_t mmPutMsgToWriteQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t mmPutMsgToSyncQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg); -int32_t mmPutMsgToSyncCtrlQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg); +int32_t mmPutMsgToSyncRdQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t mmPutMsgToReadQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t mmPutMsgToQueryQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t mmPutMsgToFetchQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg); diff --git a/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c b/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c index cf4eaaf7d1b205d23360e93f444fd2b7495cc122..76977dd4a8178792f3867b3a615ef552c5449c1d 100644 --- a/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c +++ b/source/dnode/mgmt/mgmt_mnode/src/mmHandle.c @@ -126,6 +126,7 @@ SArray *mmGetMsgHandles() { if (dmSetMgmtHandle(pArray, TDMT_MND_MERGE_VGROUP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_MND_SPLIT_VGROUP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_MND_BALANCE_VGROUP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_MND_BALANCE_VGROUP_LEADER, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_FUNC, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_MND_RETRIEVE_FUNC, mmPutMsgToReadQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_MND_DROP_FUNC, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; @@ -157,6 +158,8 @@ SArray *mmGetMsgHandles() { if (dmSetMgmtHandle(pArray, TDMT_MND_AUTH, mmPutMsgToReadQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_MND_SHOW_VARIABLES, mmPutMsgToReadQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_MND_SERVER_VERSION, mmPutMsgToReadQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_MND_CREATE_INDEX, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_MND_DROP_INDEX, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY, mmPutMsgToQueryQueue, 1) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SCH_MERGE_QUERY, mmPutMsgToQueryQueue, 1) == NULL) goto _OVER; @@ -182,8 +185,11 @@ SArray *mmGetMsgHandles() { if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_CONFIRM_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_HASHRANGE_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_COMPACT_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_VND_CREATE_INDEX_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_VND_DROP_INDEX_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_VND_DISABLE_WRITE_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_TIMEOUT, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_TIMEOUT_ELECTION, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST_BATCH, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST_REPLY, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; @@ -193,11 +199,15 @@ SArray *mmGetMsgHandles() { if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES_BATCH, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES_REPLY, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_SEND, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_RSP, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_PRE_SNAPSHOT, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_PRE_SNAPSHOT_REPLY, mmPutMsgToSyncQueue, 1) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_HEARTBEAT, mmPutMsgToSyncCtrlQueue, 1) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_HEARTBEAT_REPLY, mmPutMsgToSyncCtrlQueue, 1) == NULL) goto _OVER; + + if (dmSetMgmtHandle(pArray, TDMT_SYNC_FORCE_FOLLOWER_RSP, mmPutMsgToWriteQueue, 0) == NULL) goto _OVER; + + if (dmSetMgmtHandle(pArray, TDMT_SYNC_TIMEOUT, mmPutMsgToSyncRdQueue, 1) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_HEARTBEAT, mmPutMsgToSyncRdQueue, 1) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_HEARTBEAT_REPLY, mmPutMsgToSyncRdQueue, 1) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_RSP, mmPutMsgToSyncRdQueue, 1) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_PRE_SNAPSHOT_REPLY, mmPutMsgToSyncRdQueue, 1) == NULL) goto _OVER; code = 0; diff --git a/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c b/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c index b0810d528f761d6362b27a818636d52e8421429c..bbd77c0828d8a7901433afbc5ae351aa737f96c2 100644 --- a/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c +++ b/source/dnode/mgmt/mgmt_mnode/src/mmWorker.c @@ -111,8 +111,8 @@ int32_t mmPutMsgToSyncQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) { return mmPutMsgToWorker(pMgmt, &pMgmt->syncWorker, pMsg); } -int32_t mmPutMsgToSyncCtrlQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) { - return mmPutMsgToWorker(pMgmt, &pMgmt->syncCtrlWorker, pMsg); +int32_t mmPutMsgToSyncRdQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) { + return mmPutMsgToWorker(pMgmt, &pMgmt->syncRdWorker, pMsg); } int32_t mmPutMsgToReadQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) { @@ -120,6 +120,11 @@ int32_t mmPutMsgToReadQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) { } int32_t mmPutMsgToQueryQueue(SMnodeMgmt *pMgmt, SRpcMsg *pMsg) { + if (NULL == pMgmt->pMnode) { + const STraceId *trace = &pMsg->info.traceId; + dGError("msg:%p, stop to pre-process in mnode since mnode is NULL, type:%s", pMsg, TMSG_INFO(pMsg->msgType)); + return -1; + } pMsg->info.node = pMgmt->pMnode; if (mndPreProcessQueryMsg(pMsg) != 0) { const STraceId *trace = &pMsg->info.traceId; @@ -151,8 +156,8 @@ int32_t mmPutMsgToQueue(SMnodeMgmt *pMgmt, EQueueType qtype, SRpcMsg *pRpc) { case SYNC_QUEUE: pWorker = &pMgmt->syncWorker; break; - case SYNC_CTRL_QUEUE: - pWorker = &pMgmt->syncCtrlWorker; + case SYNC_RD_QUEUE: + pWorker = &pMgmt->syncRdWorker; break; default: terrno = TSDB_CODE_INVALID_PARA; @@ -238,12 +243,12 @@ int32_t mmStartWorker(SMnodeMgmt *pMgmt) { SSingleWorkerCfg scCfg = { .min = 1, .max = 1, - .name = "mnode-sync-ctrl", + .name = "mnode-sync-rd", .fp = (FItem)mmProcessSyncMsg, .param = pMgmt, }; - if (tSingleWorkerInit(&pMgmt->syncCtrlWorker, &scCfg) != 0) { - dError("failed to start mnode mnode-sync-ctrl worker since %s", terrstr()); + if (tSingleWorkerInit(&pMgmt->syncRdWorker, &scCfg) != 0) { + dError("failed to start mnode mnode-sync-rd worker since %s", terrstr()); return -1; } @@ -259,6 +264,6 @@ void mmStopWorker(SMnodeMgmt *pMgmt) { tSingleWorkerCleanup(&pMgmt->readWorker); tSingleWorkerCleanup(&pMgmt->writeWorker); tSingleWorkerCleanup(&pMgmt->syncWorker); - tSingleWorkerCleanup(&pMgmt->syncCtrlWorker); + tSingleWorkerCleanup(&pMgmt->syncRdWorker); dDebug("mnode workers are closed"); } diff --git a/source/dnode/mgmt/mgmt_snode/src/smInt.c b/source/dnode/mgmt/mgmt_snode/src/smInt.c index 28097311ac3530788d83c965ed4918d4621effc4..e2223497671362e1c8af19e3481c797e8a2b3972 100644 --- a/source/dnode/mgmt/mgmt_snode/src/smInt.c +++ b/source/dnode/mgmt/mgmt_snode/src/smInt.c @@ -55,6 +55,7 @@ int32_t smOpen(SMgmtInputOpt *pInput, SMgmtOutputOpt *pOutput) { smClose(pMgmt); return -1; } + tmsgReportStartup("snode-impl", "initialized"); if (smStartWorker(pMgmt) != 0) { diff --git a/source/dnode/mgmt/mgmt_vnode/inc/vmInt.h b/source/dnode/mgmt/mgmt_vnode/inc/vmInt.h index 6e724f4d4322c3aee7a143b1cffaa4cae155d3e7..4374ae363cce8b4138ebb224ddf3528eae2b0784 100644 --- a/source/dnode/mgmt/mgmt_vnode/inc/vmInt.h +++ b/source/dnode/mgmt/mgmt_vnode/inc/vmInt.h @@ -54,11 +54,12 @@ typedef struct { int32_t vgVersion; int32_t refCount; int8_t dropped; + int8_t disable; char *path; SVnode *pImpl; SMultiWorker pWriteW; SMultiWorker pSyncW; - SMultiWorker pSyncCtrlW; + SMultiWorker pSyncRdW; SMultiWorker pApplyW; STaosQueue *pQueryQ; STaosQueue *pStreamQ; @@ -80,13 +81,15 @@ typedef struct { SVnodeObj *vmAcquireVnode(SVnodeMgmt *pMgmt, int32_t vgId); void vmReleaseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode); int32_t vmOpenVnode(SVnodeMgmt *pMgmt, SWrapperCfg *pCfg, SVnode *pImpl); -void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode); +void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode, bool commitAndRemoveWal); // vmHandle.c SArray *vmGetMsgHandles(); int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t vmProcessDropVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); -int32_t vmProcessAlterVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); +int32_t vmProcessAlterVnodeReplicaReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); +int32_t vmProcessDisableVnodeWriteReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); +int32_t vmProcessAlterHashRangeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); // vmFile.c int32_t vmGetVnodeListFromFile(SVnodeMgmt *pMgmt, SWrapperCfg **ppCfgs, int32_t *numOfVnodes); @@ -104,7 +107,7 @@ int32_t vmPutRpcMsgToQueue(SVnodeMgmt *pMgmt, EQueueType qtype, SRpcMsg *pRpc); int32_t vmPutMsgToWriteQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t vmPutMsgToSyncQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); -int32_t vmPutMsgToSyncCtrlQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); +int32_t vmPutMsgToSyncRdQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t vmPutMsgToQueryQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t vmPutMsgToFetchQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); int32_t vmPutMsgToStreamQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg); diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c index 220e55f7f38862b0f787a1ee4e13faee0fae44c2..fc724f2b45dc43c1a903833884d44f9f7d86e7ac 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c @@ -20,6 +20,8 @@ void vmGetVnodeLoads(SVnodeMgmt *pMgmt, SMonVloadInfo *pInfo, bool isReset) { pInfo->pVloads = taosArrayInit(pMgmt->state.totalVnodes, sizeof(SVnodeLoad)); if (pInfo->pVloads == NULL) return; + tfsUpdateSize(pMgmt->pTfs); + taosThreadRwlockRdlock(&pMgmt->lock); void *pIter = taosHashIterate(pMgmt->hash, NULL); @@ -157,6 +159,7 @@ static int32_t vmTsmaAdjustDays(SVnodeCfg *pCfg, SCreateVnodeReq *pReq) { return 0; } +#if 0 static int32_t vmTsmaProcessCreate(SVnode *pVnode, SCreateVnodeReq *pReq) { if (pReq->isTsma) { SMsgHead *smaMsg = pReq->pTsma; @@ -165,6 +168,7 @@ static int32_t vmTsmaProcessCreate(SVnode *pVnode, SCreateVnodeReq *pReq) { } return 0; } +#endif int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { SCreateVnodeReq req = {0}; @@ -245,12 +249,14 @@ int32_t vmProcessCreateVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { goto _OVER; } +#if 0 code = vmTsmaProcessCreate(pImpl, &req); if (code != 0) { dError("vgId:%d, failed to create tsma since %s", req.vgId, terrstr()); code = terrno; goto _OVER; } +#endif code = vnodeStart(pImpl); if (code != 0) { @@ -277,7 +283,94 @@ _OVER: return code; } -int32_t vmProcessAlterVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { +int32_t vmProcessDisableVnodeWriteReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { + SDisableVnodeWriteReq req = {0}; + if (tDeserializeSDisableVnodeWriteReq(pMsg->pCont, pMsg->contLen, &req) != 0) { + terrno = TSDB_CODE_INVALID_MSG; + return -1; + } + + dInfo("vgId:%d, vnode write disable:%d", req.vgId, req.disable); + + SVnodeObj *pVnode = vmAcquireVnode(pMgmt, req.vgId); + if (pVnode == NULL) { + dError("vgId:%d, failed to disable write since %s", req.vgId, terrstr()); + terrno = TSDB_CODE_VND_NOT_EXIST; + return -1; + } + + pVnode->disable = req.disable; + vmReleaseVnode(pMgmt, pVnode); + return 0; +} + +int32_t vmProcessAlterHashRangeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { + SAlterVnodeHashRangeReq req = {0}; + if (tDeserializeSAlterVnodeHashRangeReq(pMsg->pCont, pMsg->contLen, &req) != 0) { + terrno = TSDB_CODE_INVALID_MSG; + return -1; + } + + int32_t srcVgId = req.srcVgId; + int32_t dstVgId = req.dstVgId; + dInfo("vgId:%d, start to alter vnode hashrange:[%u, %u], dstVgId:%d", req.srcVgId, req.hashBegin, req.hashEnd, + req.dstVgId); + + SVnodeObj *pVnode = vmAcquireVnode(pMgmt, srcVgId); + if (pVnode == NULL) { + dError("vgId:%d, failed to alter hashrange since %s", srcVgId, terrstr()); + terrno = TSDB_CODE_VND_NOT_EXIST; + return -1; + } + + SWrapperCfg wrapperCfg = { + .dropped = pVnode->dropped, + .vgId = dstVgId, + .vgVersion = pVnode->vgVersion, + }; + tstrncpy(wrapperCfg.path, pVnode->path, sizeof(wrapperCfg.path)); + + dInfo("vgId:%d, close vnode", srcVgId); + vmCloseVnode(pMgmt, pVnode, true); + + char srcPath[TSDB_FILENAME_LEN] = {0}; + char dstPath[TSDB_FILENAME_LEN] = {0}; + snprintf(srcPath, TSDB_FILENAME_LEN, "vnode%svnode%d", TD_DIRSEP, srcVgId); + snprintf(dstPath, TSDB_FILENAME_LEN, "vnode%svnode%d", TD_DIRSEP, dstVgId); + + dInfo("vgId:%d, alter vnode hashrange at %s", srcVgId, srcPath); + if (vnodeAlterHashRange(srcPath, dstPath, &req, pMgmt->pTfs) < 0) { + dError("vgId:%d, failed to alter vnode hashrange since %s", srcVgId, terrstr()); + return -1; + } + + dInfo("vgId:%d, open vnode", dstVgId); + SVnode *pImpl = vnodeOpen(dstPath, pMgmt->pTfs, pMgmt->msgCb); + if (pImpl == NULL) { + dError("vgId:%d, failed to open vnode at %s since %s", dstVgId, dstPath, terrstr()); + return -1; + } + + if (vmOpenVnode(pMgmt, &wrapperCfg, pImpl) != 0) { + dError("vgId:%d, failed to open vnode mgmt since %s", dstVgId, terrstr()); + return -1; + } + + if (vnodeStart(pImpl) != 0) { + dError("vgId:%d, failed to start sync since %s", dstVgId, terrstr()); + return -1; + } + + if (vmWriteVnodeListToFile(pMgmt) != 0) { + dError("vgId:%d, failed to write vnode list since %s", dstVgId, terrstr()); + return -1; + } + + dInfo("vgId:%d, vnode hashrange is altered", dstVgId); + return 0; +} + +int32_t vmProcessAlterVnodeReplicaReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { SAlterVnodeReplicaReq alterReq = {0}; if (tDeserializeSAlterVnodeReplicaReq(pMsg->pCont, pMsg->contLen, &alterReq) != 0) { terrno = TSDB_CODE_INVALID_MSG; @@ -285,16 +378,16 @@ int32_t vmProcessAlterVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { } int32_t vgId = alterReq.vgId; - dInfo("vgId:%d, start to alter vnode, replica:%d selfIndex:%d strict:%d", alterReq.vgId, alterReq.replica, - alterReq.selfIndex, alterReq.strict); + dInfo("vgId:%d, start to alter vnode replica:%d selfIndex:%d strict:%d", vgId, alterReq.replica, alterReq.selfIndex, + alterReq.strict); for (int32_t i = 0; i < alterReq.replica; ++i) { SReplica *pReplica = &alterReq.replicas[i]; - dInfo("vgId:%d, replica:%d ep:%s:%u dnode:%d", alterReq.vgId, i, pReplica->fqdn, pReplica->port, pReplica->port); + dInfo("vgId:%d, replica:%d ep:%s:%u dnode:%d", vgId, i, pReplica->fqdn, pReplica->port, pReplica->port); } if (alterReq.replica <= 0 || alterReq.selfIndex < 0 || alterReq.selfIndex >= alterReq.replica) { terrno = TSDB_CODE_INVALID_MSG; - dError("vgId:%d, failed to alter replica since invalid msg", alterReq.vgId); + dError("vgId:%d, failed to alter replica since invalid msg", vgId); return -1; } @@ -302,7 +395,7 @@ int32_t vmProcessAlterVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { if (pReplica->id != pMgmt->pData->dnodeId || pReplica->port != tsServerPort || strcmp(pReplica->fqdn, tsLocalFqdn) != 0) { terrno = TSDB_CODE_INVALID_MSG; - dError("vgId:%d, dnodeId:%d ep:%s:%u not matched with local dnode", alterReq.vgId, pReplica->id, pReplica->fqdn, + dError("vgId:%d, dnodeId:%d ep:%s:%u not matched with local dnode", vgId, pReplica->id, pReplica->fqdn, pReplica->port); return -1; } @@ -321,18 +414,18 @@ int32_t vmProcessAlterVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { .vgVersion = pVnode->vgVersion, }; tstrncpy(wrapperCfg.path, pVnode->path, sizeof(wrapperCfg.path)); - vmCloseVnode(pMgmt, pVnode); + vmCloseVnode(pMgmt, pVnode, false); char path[TSDB_FILENAME_LEN] = {0}; snprintf(path, TSDB_FILENAME_LEN, "vnode%svnode%d", TD_DIRSEP, vgId); dInfo("vgId:%d, start to alter vnode replica at %s", vgId, path); - if (vnodeAlter(path, &alterReq, pMgmt->pTfs) < 0) { + if (vnodeAlterReplica(path, &alterReq, pMgmt->pTfs) < 0) { dError("vgId:%d, failed to alter vnode at %s since %s", vgId, path, terrstr()); return -1; } - dInfo("vgId:%d, start to open vnode", vgId); + dInfo("vgId:%d, close vnode", vgId); SVnode *pImpl = vnodeOpen(path, pMgmt->pTfs, pMgmt->msgCb); if (pImpl == NULL) { dError("vgId:%d, failed to open vnode at %s since %s", vgId, path, terrstr()); @@ -383,7 +476,7 @@ int32_t vmProcessDropVnodeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { return -1; } - vmCloseVnode(pMgmt, pVnode); + vmCloseVnode(pMgmt, pVnode, false); vmWriteVnodeListToFile(pMgmt); dInfo("vgId:%d, is dropped", vgId); @@ -426,11 +519,13 @@ SArray *vmGetMsgHandles() { if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_COMMIT_OFFSET, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_ADD_CHECKINFO, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_DEL_CHECKINFO, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_CONSUME, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_CONSUME, vmPutMsgToQueryQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_DELETE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_BATCH_DEL, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_COMMIT, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SCH_QUERY_HEARTBEAT, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_VND_CREATE_INDEX, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_VND_DROP_INDEX, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DROP, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_STREAM_TASK_DEPLOY, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; @@ -447,13 +542,14 @@ SArray *vmGetMsgHandles() { if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_REPLICA, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_CONFIG, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_CONFIRM, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_HASHRANGE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_VND_DISABLE_WRITE, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_VND_ALTER_HASHRANGE, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_COMPACT, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_VND_TRIM, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_DND_CREATE_VNODE, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_DND_DROP_VNODE, vmPutMsgToMgmtQueue, 0) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_TIMEOUT, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_TIMEOUT_ELECTION, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST_BATCH, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_CLIENT_REQUEST_REPLY, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; @@ -463,12 +559,14 @@ SArray *vmGetMsgHandles() { if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES_BATCH, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_APPEND_ENTRIES_REPLY, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_SEND, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_RSP, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; if (dmSetMgmtHandle(pArray, TDMT_SYNC_PRE_SNAPSHOT, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_PRE_SNAPSHOT_REPLY, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_FORCE_FOLLOWER, vmPutMsgToSyncQueue, 0) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_HEARTBEAT, vmPutMsgToSyncCtrlQueue, 0) == NULL) goto _OVER; - if (dmSetMgmtHandle(pArray, TDMT_SYNC_HEARTBEAT_REPLY, vmPutMsgToSyncCtrlQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_TIMEOUT, vmPutMsgToSyncRdQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_HEARTBEAT, vmPutMsgToSyncRdQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_HEARTBEAT_REPLY, vmPutMsgToSyncRdQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_SNAPSHOT_RSP, vmPutMsgToSyncRdQueue, 0) == NULL) goto _OVER; + if (dmSetMgmtHandle(pArray, TDMT_SYNC_PRE_SNAPSHOT_REPLY, vmPutMsgToSyncRdQueue, 0) == NULL) goto _OVER; code = 0; diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmInt.c b/source/dnode/mgmt/mgmt_vnode/src/vmInt.c index 951544c76625ab8091cadd6e944cd702ca5e3a44..16e7ffc5367c857dad1414c788dc46d9f6263b42 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmInt.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmInt.c @@ -15,6 +15,7 @@ #define _DEFAULT_SOURCE #include "vmInt.h" +#include "vnd.h" SVnodeObj *vmAcquireVnode(SVnodeMgmt *pMgmt, int32_t vgId) { SVnodeObj *pVnode = NULL; @@ -53,7 +54,7 @@ int32_t vmOpenVnode(SVnodeMgmt *pMgmt, SWrapperCfg *pCfg, SVnode *pImpl) { pVnode->vgVersion = pCfg->vgVersion; pVnode->refCount = 0; pVnode->dropped = 0; - pVnode->path = tstrdup(pCfg->path); + pVnode->path = taosStrdup(pCfg->path); pVnode->pImpl = pImpl; if (pVnode->path == NULL) { @@ -76,8 +77,13 @@ int32_t vmOpenVnode(SVnodeMgmt *pMgmt, SWrapperCfg *pCfg, SVnode *pImpl) { return code; } -void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) { +void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode, bool commitAndRemoveWal) { char path[TSDB_FILENAME_LEN] = {0}; + bool atExit = true; + + if (vnodeIsLeader(pVnode->pImpl)) { + vnodeProposeCommitOnNeed(pVnode->pImpl, atExit); + } taosThreadRwlockWrlock(&pMgmt->lock); taosHashRemove(pMgmt->hash, &pVnode->vgId, sizeof(int32_t)); @@ -98,9 +104,9 @@ void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) { pVnode->pSyncW.queue->threadId); tMultiWorkerCleanup(&pVnode->pSyncW); - dInfo("vgId:%d, wait for vnode sync ctrl queue:%p is empty, thread:%08" PRId64, pVnode->vgId, - pVnode->pSyncCtrlW.queue, pVnode->pSyncCtrlW.queue->threadId); - tMultiWorkerCleanup(&pVnode->pSyncCtrlW); + dInfo("vgId:%d, wait for vnode sync rd queue:%p is empty, thread:%08" PRId64, pVnode->vgId, pVnode->pSyncRdW.queue, + pVnode->pSyncRdW.queue->threadId); + tMultiWorkerCleanup(&pVnode->pSyncRdW); dInfo("vgId:%d, wait for vnode apply queue:%p is empty, thread:%08" PRId64, pVnode->vgId, pVnode->pApplyW.queue, pVnode->pApplyW.queue->threadId); @@ -113,6 +119,7 @@ void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) { pVnode->pFetchQ->threadId); while (!taosQueueEmpty(pVnode->pFetchQ)) taosMsleep(10); + tqNotifyClose(pVnode->pImpl->pTq); dInfo("vgId:%d, wait for vnode stream queue:%p is empty", pVnode->vgId, pVnode->pStreamQ); while (!taosQueueEmpty(pVnode->pStreamQ)) taosMsleep(10); @@ -122,10 +129,25 @@ void vmCloseVnode(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) { vnodePostClose(pVnode->pImpl); vmFreeQueue(pMgmt, pVnode); + + if (commitAndRemoveWal) { + dInfo("vgId:%d, commit data for vnode split", pVnode->vgId); + vnodeSyncCommit(pVnode->pImpl); + vnodeBegin(pVnode->pImpl); + dInfo("vgId:%d, commit data finished", pVnode->vgId); + } + vnodeClose(pVnode->pImpl); pVnode->pImpl = NULL; dInfo("vgId:%d, vnode is closed", pVnode->vgId); + if (commitAndRemoveWal) { + snprintf(path, TSDB_FILENAME_LEN, "vnode%svnode%d%swal", TD_DIRSEP, pVnode->vgId, TD_DIRSEP); + dInfo("vgId:%d, remove all wals, path:%s", pVnode->vgId, path); + tfsRmdir(pMgmt->pTfs, path); + tfsMkdir(pMgmt->pTfs, path); + } + if (pVnode->dropped) { dInfo("vgId:%d, vnode is destroyed, dropped:%d", pVnode->vgId, pVnode->dropped); snprintf(path, TSDB_FILENAME_LEN, "vnode%svnode%d", TD_DIRSEP, pVnode->vgId); @@ -255,7 +277,7 @@ static void *vmCloseVnodeInThread(void *param) { pMgmt->state.openVnodes, pMgmt->state.totalVnodes); tmsgReportStartup("vnode-close", stepDesc); - vmCloseVnode(pMgmt, pVnode); + vmCloseVnode(pMgmt, pVnode, false); } dInfo("thread:%d, numOfVnodes:%d is closed", pThread->threadIndex, pThread->vnodeNum); diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c index cd29b115508ccfcd51d9c130c4847b2ef265dba5..a318b9886ea699889b14b41169c521efc122c7a3 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmWorker.c @@ -41,7 +41,13 @@ static void vmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) { code = vmProcessDropVnodeReq(pMgmt, pMsg); break; case TDMT_VND_ALTER_REPLICA: - code = vmProcessAlterVnodeReq(pMgmt, pMsg); + code = vmProcessAlterVnodeReplicaReq(pMgmt, pMsg); + break; + case TDMT_VND_DISABLE_WRITE: + code = vmProcessDisableVnodeWriteReq(pMgmt, pMsg); + break; + case TDMT_VND_ALTER_HASHRANGE: + code = vmProcessAlterHashRangeReq(pMgmt, pMsg); break; default: terrno = TSDB_CODE_MSG_NOT_PROCESSED; @@ -51,7 +57,7 @@ static void vmProcessMgmtQueue(SQueueInfo *pInfo, SRpcMsg *pMsg) { if (IsReq(pMsg)) { if (code != 0) { if (terrno != 0) code = terrno; - dGError("msg:%p, failed to process since %s", pMsg, terrstr(code)); + dGError("msg:%p, failed to process since %s, type:%s", pMsg, terrstr(code), TMSG_INFO(pMsg->msgType)); } vmSendRsp(pMsg, code); } @@ -107,12 +113,20 @@ static void vmProcessFetchQueue(SQueueInfo *pInfo, STaosQall *qall, int32_t numO int32_t code = vnodeProcessFetchMsg(pVnode->pImpl, pMsg, pInfo); if (code != 0) { - if (terrno != 0) code = terrno; - dGError("vgId:%d, msg:%p failed to fetch since %s", pVnode->vgId, pMsg, terrstr(code)); + if (terrno != 0) { + code = terrno; + } + + if (code == TSDB_CODE_WAL_LOG_NOT_EXIST) { + dGDebug("vnodeProcessFetchMsg vgId:%d, msg:%p failed to fetch since %s", pVnode->vgId, pMsg, terrstr()); + } else { + dGError("vnodeProcessFetchMsg vgId:%d, msg:%p failed to fetch since %s", pVnode->vgId, pMsg, terrstr()); + } + vmSendRsp(pMsg, code); } - dGTrace("vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code); + dGTrace("vnodeProcessFetchMsg vgId:%d, msg:%p is freed, code:0x%x", pVnode->vgId, pMsg, code); rpcFreeCont(pMsg->pCont); taosFreeQitem(pMsg); } @@ -157,10 +171,9 @@ static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtyp SVnodeObj *pVnode = vmAcquireVnode(pMgmt, pHead->vgId); if (pVnode == NULL) { - dGError("vgId:%d, msg:%p failed to put into vnode queue since %s, type:%s qtype:%d contLen:%d", pHead->vgId, pMsg, - terrstr(), TMSG_INFO(pMsg->msgType), qtype, pHead->contLen); + dGWarn("vgId:%d, msg:%p failed to put into vnode queue since %s, type:%s qtype:%d contLen:%d", pHead->vgId, pMsg, + terrstr(), TMSG_INFO(pMsg->msgType), qtype, pHead->contLen); terrno = (terrno != 0) ? terrno : -1; - vmSendResponse(pMsg); return terrno; } @@ -187,26 +200,33 @@ static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtyp taosWriteQitem(pVnode->pFetchQ, pMsg); break; case WRITE_QUEUE: - if (!osDataSpaceAvailable()) { - terrno = TSDB_CODE_NO_DISKSPACE; + if (!osDataSpaceSufficient()) { + terrno = TSDB_CODE_NO_ENOUGH_DISKSPACE; code = terrno; dError("vgId:%d, msg:%p put into vnode-write queue failed since %s", pVnode->vgId, pMsg, terrstr(code)); - } else if ((pMsg->msgType == TDMT_VND_SUBMIT) && (grantCheck(TSDB_GRANT_STORAGE) != TSDB_CODE_SUCCESS)) { + break; + } + if (pMsg->msgType == TDMT_VND_SUBMIT && (grantCheck(TSDB_GRANT_STORAGE) != TSDB_CODE_SUCCESS)) { terrno = TSDB_CODE_VND_NO_WRITE_AUTH; code = terrno; dDebug("vgId:%d, msg:%p put into vnode-write queue failed since %s", pVnode->vgId, pMsg, terrstr(code)); - } else { - dGTrace("vgId:%d, msg:%p put into vnode-write queue", pVnode->vgId, pMsg); - taosWriteQitem(pVnode->pWriteW.queue, pMsg); + break; + } + if (pMsg->msgType != TDMT_VND_ALTER_CONFIRM && pVnode->disable) { + dDebug("vgId:%d, msg:%p put into vnode-write queue failed since its disable", pVnode->vgId, pMsg); + terrno = TSDB_CODE_VND_STOPPED; + break; } + dGTrace("vgId:%d, msg:%p put into vnode-write queue", pVnode->vgId, pMsg); + taosWriteQitem(pVnode->pWriteW.queue, pMsg); break; case SYNC_QUEUE: dGTrace("vgId:%d, msg:%p put into vnode-sync queue", pVnode->vgId, pMsg); taosWriteQitem(pVnode->pSyncW.queue, pMsg); break; - case SYNC_CTRL_QUEUE: - dGTrace("vgId:%d, msg:%p put into vnode-sync-ctrl queue", pVnode->vgId, pMsg); - taosWriteQitem(pVnode->pSyncCtrlW.queue, pMsg); + case SYNC_RD_QUEUE: + dGTrace("vgId:%d, msg:%p put into vnode-sync-rd queue", pVnode->vgId, pMsg); + taosWriteQitem(pVnode->pSyncRdW.queue, pMsg); break; case APPLY_QUEUE: dGTrace("vgId:%d, msg:%p put into vnode-apply queue", pVnode->vgId, pMsg); @@ -222,9 +242,7 @@ static int32_t vmPutMsgToQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg, EQueueType qtyp return code; } -int32_t vmPutMsgToSyncCtrlQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { - return vmPutMsgToQueue(pMgmt, pMsg, SYNC_CTRL_QUEUE); -} +int32_t vmPutMsgToSyncRdQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { return vmPutMsgToQueue(pMgmt, pMsg, SYNC_RD_QUEUE); } int32_t vmPutMsgToSyncQueue(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) { return vmPutMsgToQueue(pMgmt, pMsg, SYNC_QUEUE); } @@ -315,18 +333,18 @@ int32_t vmGetQueueSize(SVnodeMgmt *pMgmt, int32_t vgId, EQueueType qtype) { int32_t vmAllocQueue(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) { SMultiWorkerCfg wcfg = {.max = 1, .name = "vnode-write", .fp = (FItems)vnodeProposeWriteMsg, .param = pVnode->pImpl}; SMultiWorkerCfg scfg = {.max = 1, .name = "vnode-sync", .fp = (FItems)vmProcessSyncQueue, .param = pVnode}; - SMultiWorkerCfg sccfg = {.max = 1, .name = "vnode-sync-ctrl", .fp = (FItems)vmProcessSyncQueue, .param = pVnode}; + SMultiWorkerCfg sccfg = {.max = 1, .name = "vnode-sync-rd", .fp = (FItems)vmProcessSyncQueue, .param = pVnode}; SMultiWorkerCfg acfg = {.max = 1, .name = "vnode-apply", .fp = (FItems)vnodeApplyWriteMsg, .param = pVnode->pImpl}; (void)tMultiWorkerInit(&pVnode->pWriteW, &wcfg); (void)tMultiWorkerInit(&pVnode->pSyncW, &scfg); - (void)tMultiWorkerInit(&pVnode->pSyncCtrlW, &sccfg); + (void)tMultiWorkerInit(&pVnode->pSyncRdW, &sccfg); (void)tMultiWorkerInit(&pVnode->pApplyW, &acfg); pVnode->pQueryQ = tQWorkerAllocQueue(&pMgmt->queryPool, pVnode, (FItem)vmProcessQueryQueue); pVnode->pStreamQ = tAutoQWorkerAllocQueue(&pMgmt->streamPool, pVnode, (FItem)vmProcessStreamQueue); pVnode->pFetchQ = tWWorkerAllocQueue(&pMgmt->fetchPool, pVnode, (FItems)vmProcessFetchQueue); - if (pVnode->pWriteW.queue == NULL || pVnode->pSyncW.queue == NULL || pVnode->pSyncCtrlW.queue == NULL || + if (pVnode->pWriteW.queue == NULL || pVnode->pSyncW.queue == NULL || pVnode->pSyncRdW.queue == NULL || pVnode->pApplyW.queue == NULL || pVnode->pQueryQ == NULL || pVnode->pStreamQ == NULL || pVnode->pFetchQ == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -336,8 +354,8 @@ int32_t vmAllocQueue(SVnodeMgmt *pMgmt, SVnodeObj *pVnode) { pVnode->pWriteW.queue->threadId); dInfo("vgId:%d, sync-queue:%p is alloced, thread:%08" PRId64, pVnode->vgId, pVnode->pSyncW.queue, pVnode->pSyncW.queue->threadId); - dInfo("vgId:%d, sync-ctrl-queue:%p is alloced, thread:%08" PRId64, pVnode->vgId, pVnode->pSyncCtrlW.queue, - pVnode->pSyncCtrlW.queue->threadId); + dInfo("vgId:%d, sync-rd-queue:%p is alloced, thread:%08" PRId64, pVnode->vgId, pVnode->pSyncRdW.queue, + pVnode->pSyncRdW.queue->threadId); dInfo("vgId:%d, apply-queue:%p is alloced, thread:%08" PRId64, pVnode->vgId, pVnode->pApplyW.queue, pVnode->pApplyW.queue->threadId); dInfo("vgId:%d, query-queue:%p is alloced", pVnode->vgId, pVnode->pQueryQ); diff --git a/source/dnode/mgmt/node_mgmt/src/dmMgmt.c b/source/dnode/mgmt/node_mgmt/src/dmMgmt.c index b6cce249ea935a55e0515a84955702e5e463ca4d..d8841201478b948f396e8d62a64c714290559c96 100644 --- a/source/dnode/mgmt/node_mgmt/src/dmMgmt.c +++ b/source/dnode/mgmt/node_mgmt/src/dmMgmt.c @@ -79,6 +79,13 @@ static void dmClearVars(SDnode *pDnode) { SDnodeData *pData = &pDnode->data; taosThreadRwlockWrlock(&pData->lock); + if (pData->oldDnodeEps != NULL) { + if (dmWriteEps(pData) == 0) { + dmRemoveDnodePairs(pData); + } + taosArrayDestroy(pData->oldDnodeEps); + pData->oldDnodeEps = NULL; + } if (pData->dnodeEps != NULL) { taosArrayDestroy(pData->dnodeEps); pData->dnodeEps = NULL; @@ -117,7 +124,7 @@ int32_t dmInitDnode(SDnode *pDnode) { taosThreadRwlockInit(&pWrapper->lock, NULL); snprintf(path, sizeof(path), "%s%s%s", tsDataDir, TD_DIRSEP, pWrapper->name); - pWrapper->path = strdup(path); + pWrapper->path = taosStrdup(path); if (pWrapper->path == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; goto _OVER; diff --git a/source/dnode/mgmt/node_mgmt/src/dmNodes.c b/source/dnode/mgmt/node_mgmt/src/dmNodes.c index 08330e025f2f496fdbe904450b2a9a659d6d0198..19d5e06c5b6d118feaa8bf6d50fe222e7a73007f 100644 --- a/source/dnode/mgmt/node_mgmt/src/dmNodes.c +++ b/source/dnode/mgmt/node_mgmt/src/dmNodes.c @@ -109,9 +109,8 @@ static int32_t dmStartNodes(SDnode *pDnode) { } } - dInfo("TDengine initialized successfully"); - dmReportStartup("TDengine", "initialized successfully"); - + dInfo("The daemon initialized successfully"); + dmReportStartup("The daemon", "initialized successfully"); return 0; } @@ -133,17 +132,21 @@ int32_t dmRunDnode(SDnode *pDnode) { int32_t count = 0; if (dmOpenNodes(pDnode) != 0) { dError("failed to open nodes since %s", terrstr()); + dmCloseNodes(pDnode); return -1; } if (dmStartNodes(pDnode) != 0) { dError("failed to start nodes since %s", terrstr()); + dmSetStatus(pDnode, DND_STAT_STOPPED); + dmStopNodes(pDnode); + dmCloseNodes(pDnode); return -1; } while (1) { if (pDnode->stop) { - dInfo("TDengine is about to stop"); + dInfo("The daemon is about to stop"); dmSetStatus(pDnode, DND_STAT_STOPPED); dmStopNodes(pDnode); dmCloseNodes(pDnode); diff --git a/source/dnode/mgmt/node_mgmt/src/dmTransport.c b/source/dnode/mgmt/node_mgmt/src/dmTransport.c index dcb63f65246cfc103790c2e46b2ca4c8bd4beafe..ea46b7069385fba0c204c5e78f9f7e7983053d85 100644 --- a/source/dnode/mgmt/node_mgmt/src/dmTransport.c +++ b/source/dnode/mgmt/node_mgmt/src/dmTransport.c @@ -39,7 +39,7 @@ int32_t dmProcessNodeMsg(SMgmtWrapper *pWrapper, SRpcMsg *pMsg) { NodeMsgFp msgFp = pWrapper->msgFps[TMSG_INDEX(pMsg->msgType)]; if (msgFp == NULL) { terrno = TSDB_CODE_MSG_NOT_PROCESSED; - dGError("msg:%p, not processed since no handler", pMsg); + dGError("msg:%p, not processed since no handler, type:%s", pMsg, TMSG_INFO(pMsg->msgType)); return -1; } @@ -93,18 +93,30 @@ static void dmProcessRpcMsg(SDnode *pDnode, SRpcMsg *pRpc, SEpSet *pEpSet) { break; } - if (pDnode->status != DND_STAT_RUNNING) { - if (pRpc->msgType == TDMT_DND_SERVER_STATUS) { - dmProcessServerStartupStatus(pDnode, pRpc); - return; - } else { - if (pDnode->status == DND_STAT_INIT) { - terrno = TSDB_CODE_APP_IS_STARTING; + /* + pDnode is null, TD-22618 + at trans.c line 91 + before this line, dmProcessRpcMsg callback is set + after this line, parent is set + so when dmProcessRpcMsg is called, pDonde is still null. + */ + if (pDnode != NULL) { + if (pDnode->status != DND_STAT_RUNNING) { + if (pRpc->msgType == TDMT_DND_SERVER_STATUS) { + dmProcessServerStartupStatus(pDnode, pRpc); + return; } else { - terrno = TSDB_CODE_APP_IS_STOPPING; + if (pDnode->status == DND_STAT_INIT) { + terrno = TSDB_CODE_APP_IS_STARTING; + } else { + terrno = TSDB_CODE_APP_IS_STOPPING; + } + goto _OVER; } - goto _OVER; } + } else { + terrno = TSDB_CODE_APP_IS_STARTING; + goto _OVER; } if (pRpc->pCont == NULL && (IsReq(pRpc) || pRpc->contLen != 0)) { @@ -280,10 +292,20 @@ int32_t dmInitClient(SDnode *pDnode) { rpcInit.retryMaxInterval = tsRedirectMaxPeriod; rpcInit.retryMaxTimouet = tsMaxRetryWaitTime; - rpcInit.failFastInterval = 1000; // interval threshold(ms) + rpcInit.failFastInterval = 5000; // interval threshold(ms) rpcInit.failFastThreshold = 3; // failed threshold rpcInit.ffp = dmFailFastFp; + int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3); + connLimitNum = TMAX(connLimitNum, 10); + connLimitNum = TMIN(connLimitNum, 500); + + rpcInit.connLimitNum = connLimitNum; + rpcInit.connLimitLock = 1; + rpcInit.supportBatch = 1; + rpcInit.batchSize = 8 * 1024; + rpcInit.timeToGetConn = tsTimeToGetAvailableConn; + pTrans->clientRpc = rpcOpen(&rpcInit); if (pTrans->clientRpc == NULL) { dError("failed to init dnode rpc client"); diff --git a/source/dnode/mgmt/node_util/inc/dmUtil.h b/source/dnode/mgmt/node_util/inc/dmUtil.h index 784bb3c5e132cc5d012521ced390742009ad3262..cfdea40477b1dae1cabc35e8566c1ff7ad86a148 100644 --- a/source/dnode/mgmt/node_util/inc/dmUtil.h +++ b/source/dnode/mgmt/node_util/inc/dmUtil.h @@ -53,12 +53,12 @@ extern "C" { #define dDebug(...) { if (dDebugFlag & DEBUG_DEBUG) { taosPrintLog("DND ", DEBUG_DEBUG, dDebugFlag, __VA_ARGS__); }} #define dTrace(...) { if (dDebugFlag & DEBUG_TRACE) { taosPrintLog("DND ", DEBUG_TRACE, dDebugFlag, __VA_ARGS__); }} -#define dGFatal(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dFatal(param ", gtid:%s", __VA_ARGS__, buf);} -#define dGError(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dError(param ", gtid:%s", __VA_ARGS__, buf);} -#define dGWarn(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dWarn (param ", gtid:%s", __VA_ARGS__, buf);} -#define dGInfo(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dInfo (param ", gtid:%s", __VA_ARGS__, buf);} -#define dGDebug(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dDebug(param ", gtid:%s", __VA_ARGS__, buf);} -#define dGTrace(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dTrace(param ", gtid:%s", __VA_ARGS__, buf);} +#define dGFatal(param, ...) {if (dDebugFlag & DEBUG_FATAL) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dFatal(param ", gtid:%s", __VA_ARGS__, buf);}} +#define dGError(param, ...) {if (dDebugFlag & DEBUG_ERROR) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dError(param ", gtid:%s", __VA_ARGS__, buf);}} +#define dGWarn(param, ...) {if (dDebugFlag & DEBUG_WARN) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dWarn(param ", gtid:%s", __VA_ARGS__, buf);}} +#define dGInfo(param, ...) {if (dDebugFlag & DEBUG_INFO) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dInfo(param ", gtid:%s", __VA_ARGS__, buf);}} +#define dGDebug(param, ...) {if (dDebugFlag & DEBUG_DEBUG) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dDebug(param ", gtid:%s", __VA_ARGS__, buf);}} +#define dGTrace(param, ...) {if (dDebugFlag & DEBUG_TRACE) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); dTrace(param ", gtid:%s", __VA_ARGS__, buf);}} // clang-format on @@ -166,9 +166,11 @@ int32_t dmReadEps(SDnodeData *pData); int32_t dmWriteEps(SDnodeData *pData); void dmUpdateEps(SDnodeData *pData, SArray *pDnodeEps); void dmGetMnodeEpSet(SDnodeData *pData, SEpSet *pEpSet); +void dmRotateMnodeEpSet(SDnodeData *pData); void dmGetMnodeEpSetForRedirect(SDnodeData *pData, SRpcMsg *pMsg, SEpSet *pEpSet); void dmSetMnodeEpSet(SDnodeData *pData, SEpSet *pEpSet); -void dmUpdateDnodeInfo(void *pData, int32_t *dnodeId, int64_t *clusterId, char *fqdn, uint16_t *port); +bool dmUpdateDnodeInfo(void *pData, int32_t *dnodeId, int64_t *clusterId, char *fqdn, uint16_t *port); +void dmRemoveDnodePairs(SDnodeData *pData); #ifdef __cplusplus } diff --git a/source/dnode/mgmt/node_util/src/dmEps.c b/source/dnode/mgmt/node_util/src/dmEps.c index 4285eb5c0786f75c25850e5c18c2689ab17869b5..784d2b425b2ecf46faddea1c1300e5efb2181312 100644 --- a/source/dnode/mgmt/node_util/src/dmEps.c +++ b/source/dnode/mgmt/node_util/src/dmEps.c @@ -18,9 +18,18 @@ #include "tjson.h" #include "tmisce.h" -static void dmPrintEps(SDnodeData *pData); -static bool dmIsEpChanged(SDnodeData *pData, int32_t dnodeId, const char *ep); -static void dmResetEps(SDnodeData *pData, SArray *dnodeEps); +typedef struct { + int32_t id; + uint16_t oldPort; + uint16_t newPort; + char oldFqdn[TSDB_FQDN_LEN]; + char newFqdn[TSDB_FQDN_LEN]; +} SDnodeEpPair; + +static void dmPrintEps(SDnodeData *pData); +static bool dmIsEpChanged(SDnodeData *pData, int32_t dnodeId, const char *ep); +static void dmResetEps(SDnodeData *pData, SArray *dnodeEps); +static int32_t dmReadDnodePairs(SDnodeData *pData); static void dmGetDnodeEp(SDnodeData *pData, int32_t dnodeId, char *pEp, char *pFqdn, uint16_t *pPort) { taosThreadRwlockRdlock(&pData->lock); @@ -137,7 +146,7 @@ int32_t dmReadEps(SDnodeData *pData) { } code = 0; - dInfo("succceed to read mnode file %s", file); + dInfo("succceed to read dnode file %s", file); _OVER: if (content != NULL) taosMemoryFree(content); @@ -146,6 +155,7 @@ _OVER: if (code != 0) { dError("failed to read dnode file:%s since %s", file, terrstr()); + return code; } if (taosArrayGetSize(pData->dnodeEps) == 0) { @@ -155,11 +165,16 @@ _OVER: taosArrayPush(pData->dnodeEps, &dnodeEp); } + if (dmReadDnodePairs(pData) != 0) { + return -1; + } + dDebug("reset dnode list on startup"); dmResetEps(pData, pData->dnodeEps); - if (dmIsEpChanged(pData, pData->dnodeId, tsLocalEp)) { + if (pData->oldDnodeEps == NULL && dmIsEpChanged(pData, pData->dnodeId, tsLocalEp)) { dError("localEp %s different with %s and need reconfigured", tsLocalEp, file); + terrno = TSDB_CODE_INVALID_CFG; return -1; } @@ -222,7 +237,8 @@ int32_t dmWriteEps(SDnodeData *pData) { code = 0; pData->updateTime = taosGetTimestampMs(); - dInfo("succeed to write dnode file:%s, dnodeVer:%" PRId64, realfile, pData->dnodeVer); + dInfo("succeed to write dnode file:%s, num:%d ver:%" PRId64, realfile, (int32_t)taosArrayGetSize(pData->dnodeEps), + pData->dnodeVer); _OVER: if (pJson != NULL) tjsonDelete(pJson); @@ -309,6 +325,28 @@ void dmGetMnodeEpSet(SDnodeData *pData, SEpSet *pEpSet) { taosThreadRwlockUnlock(&pData->lock); } +static FORCE_INLINE void dmSwapEps(SEp *epLhs, SEp *epRhs) { + SEp epTmp; + + epTmp.port = epLhs->port; + tstrncpy(epTmp.fqdn, epLhs->fqdn, tListLen(epTmp.fqdn)); + + epLhs->port = epRhs->port; + tstrncpy(epLhs->fqdn, epRhs->fqdn, tListLen(epLhs->fqdn)); + + epRhs->port = epTmp.port; + tstrncpy(epRhs->fqdn, epTmp.fqdn, tListLen(epRhs->fqdn)); +} + +void dmRotateMnodeEpSet(SDnodeData *pData) { + taosThreadRwlockRdlock(&pData->lock); + SEpSet *pEpSet = &pData->mnodeEps; + for (int i = 1; i < pEpSet->numOfEps; i++) { + dmSwapEps(&pEpSet->eps[i - 1], &pEpSet->eps[i]); + } + taosThreadRwlockUnlock(&pData->lock); +} + void dmGetMnodeEpSetForRedirect(SDnodeData *pData, SRpcMsg *pMsg, SEpSet *pEpSet) { dmGetMnodeEpSet(pData, pEpSet); dTrace("msg is redirected, handle:%p num:%d use:%d", pMsg->info.handle, pEpSet->numOfEps, pEpSet->inUse); @@ -332,7 +370,8 @@ void dmSetMnodeEpSet(SDnodeData *pData, SEpSet *pEpSet) { } } -void dmUpdateDnodeInfo(void *data, int32_t *did, int64_t *clusterId, char *fqdn, uint16_t *port) { +bool dmUpdateDnodeInfo(void *data, int32_t *did, int64_t *clusterId, char *fqdn, uint16_t *port) { + bool updated = false; SDnodeData *pData = data; int32_t dnodeId = -1; if (did != NULL) dnodeId = *did; @@ -342,11 +381,12 @@ void dmUpdateDnodeInfo(void *data, int32_t *did, int64_t *clusterId, char *fqdn, if (pData->oldDnodeEps != NULL) { int32_t size = (int32_t)taosArrayGetSize(pData->oldDnodeEps); for (int32_t i = 0; i < size; ++i) { - SDnodeEp *pDnodeEp = taosArrayGet(pData->oldDnodeEps, i); - if (strcmp(pDnodeEp->ep.fqdn, fqdn) == 0 && pDnodeEp->ep.port == *port) { - dInfo("dnode:%d, update ep:%s:%u to %s:%u", dnodeId, fqdn, *port, pDnodeEp->ep.fqdn, pDnodeEp->ep.port); - tstrncpy(fqdn, pDnodeEp->ep.fqdn, TSDB_FQDN_LEN); - *port = pDnodeEp->ep.port; + SDnodeEpPair *pair = taosArrayGet(pData->oldDnodeEps, i); + if (strcmp(pair->oldFqdn, fqdn) == 0 && pair->oldPort == *port) { + dInfo("dnode:%d, update ep:%s:%u to %s:%u", dnodeId, fqdn, *port, pair->newFqdn, pair->newPort); + tstrncpy(fqdn, pair->newFqdn, TSDB_FQDN_LEN); + *port = pair->newPort; + updated = true; } } } @@ -370,10 +410,170 @@ void dmUpdateDnodeInfo(void *data, int32_t *did, int64_t *clusterId, char *fqdn, dInfo("dnode:%d, update ep:%s:%u to %s:%u", dnodeId, fqdn, *port, pDnodeEp->ep.fqdn, pDnodeEp->ep.port); tstrncpy(fqdn, pDnodeEp->ep.fqdn, TSDB_FQDN_LEN); *port = pDnodeEp->ep.port; + updated = true; } if (clusterId != NULL) *clusterId = pData->clusterId; } } taosThreadRwlockUnlock(&pData->lock); -} \ No newline at end of file + return updated; +} + +static int32_t dmDecodeEpPairs(SJson *pJson, SDnodeData *pData) { + int32_t code = 0; + + SJson *dnodes = tjsonGetObjectItem(pJson, "dnodes"); + if (dnodes == NULL) return -1; + int32_t numOfDnodes = tjsonGetArraySize(dnodes); + + for (int32_t i = 0; i < numOfDnodes; ++i) { + SJson *dnode = tjsonGetArrayItem(dnodes, i); + if (dnode == NULL) return -1; + + SDnodeEpPair pair = {0}; + tjsonGetInt32ValueFromDouble(dnode, "id", pair.id, code); + if (code < 0) return -1; + code = tjsonGetStringValue(dnode, "fqdn", pair.oldFqdn); + if (code < 0) return -1; + tjsonGetUInt16ValueFromDouble(dnode, "port", pair.oldPort, code); + if (code < 0) return -1; + code = tjsonGetStringValue(dnode, "new_fqdn", pair.newFqdn); + if (code < 0) return -1; + tjsonGetUInt16ValueFromDouble(dnode, "new_port", pair.newPort, code); + if (code < 0) return -1; + + if (taosArrayPush(pData->oldDnodeEps, &pair) == NULL) return -1; + } + + return code; +} + +void dmRemoveDnodePairs(SDnodeData *pData) { + char file[PATH_MAX] = {0}; + char bak[PATH_MAX] = {0}; + snprintf(file, sizeof(file), "%s%sdnode%sep.json", tsDataDir, TD_DIRSEP, TD_DIRSEP); + snprintf(bak, sizeof(bak), "%s%sdnode%sep.json.bak", tsDataDir, TD_DIRSEP, TD_DIRSEP); + dInfo("dnode file:%s is rename to bak file", file); + (void)taosRenameFile(file, bak); +} + +static int32_t dmReadDnodePairs(SDnodeData *pData) { + int32_t code = -1; + TdFilePtr pFile = NULL; + char *content = NULL; + SJson *pJson = NULL; + char file[PATH_MAX] = {0}; + snprintf(file, sizeof(file), "%s%sdnode%sep.json", tsDataDir, TD_DIRSEP, TD_DIRSEP); + + if (taosStatFile(file, NULL, NULL) < 0) { + dDebug("dnode file:%s not exist", file); + code = 0; + goto _OVER; + } + + pFile = taosOpenFile(file, TD_FILE_READ); + if (pFile == NULL) { + terrno = TAOS_SYSTEM_ERROR(errno); + dError("failed to open dnode file:%s since %s", file, terrstr()); + goto _OVER; + } + + int64_t size = 0; + if (taosFStatFile(pFile, &size, NULL) < 0) { + terrno = TAOS_SYSTEM_ERROR(errno); + dError("failed to fstat dnode file:%s since %s", file, terrstr()); + goto _OVER; + } + + content = taosMemoryMalloc(size + 1); + if (content == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _OVER; + } + + if (taosReadFile(pFile, content, size) != size) { + terrno = TAOS_SYSTEM_ERROR(errno); + dError("failed to read dnode file:%s since %s", file, terrstr()); + goto _OVER; + } + + content[size] = '\0'; + + pJson = tjsonParse(content); + if (pJson == NULL) { + terrno = TSDB_CODE_INVALID_JSON_FORMAT; + goto _OVER; + } + + pData->oldDnodeEps = taosArrayInit(1, sizeof(SDnodeEpPair)); + if (pData->oldDnodeEps == NULL) { + dError("failed to calloc dnodeEp array since %s", strerror(errno)); + goto _OVER; + } + + if (dmDecodeEpPairs(pJson, pData) < 0) { + taosArrayDestroy(pData->oldDnodeEps); + pData->oldDnodeEps = NULL; + terrno = TSDB_CODE_INVALID_JSON_FORMAT; + goto _OVER; + } + + code = 0; + dInfo("succceed to read dnode file %s", file); + +_OVER: + if (content != NULL) taosMemoryFree(content); + if (pJson != NULL) cJSON_Delete(pJson); + if (pFile != NULL) taosCloseFile(&pFile); + + if (code != 0) { + dError("failed to read dnode file:%s since %s", file, terrstr()); + return code; + } + + // update old fqdn and port + for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pData->oldDnodeEps); ++i) { + SDnodeEpPair *pair = taosArrayGet(pData->oldDnodeEps, i); + for (int32_t j = 0; j < (int32_t)taosArrayGetSize(pData->dnodeEps); ++j) { + SDnodeEp *pDnodeEp = taosArrayGet(pData->dnodeEps, j); + if (pDnodeEp->id == pair->id) { + tstrncpy(pair->oldFqdn, pDnodeEp->ep.fqdn, TSDB_FQDN_LEN); + pair->oldPort = pDnodeEp->ep.port; + } + } + } + + // check new fqdn and port + for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pData->oldDnodeEps); ++i) { + SDnodeEpPair *pair = taosArrayGet(pData->oldDnodeEps, i); + for (int32_t j = 0; j < (int32_t)taosArrayGetSize(pData->dnodeEps); ++j) { + SDnodeEp *pDnodeEp = taosArrayGet(pData->dnodeEps, j); + if (pDnodeEp->id != pair->id && + (strcmp(pDnodeEp->ep.fqdn, pair->newFqdn) == 0 && pDnodeEp->ep.port == pair->newPort)) { + dError("dnode:%d, can't update ep:%s:%u to %s:%u since already exists as dnode:%d", pair->id, pair->oldFqdn, + pair->oldPort, pair->newFqdn, pair->newPort, pDnodeEp->id); + taosArrayDestroy(pData->oldDnodeEps); + pData->oldDnodeEps = NULL; + terrno = TSDB_CODE_INVALID_CFG; + return -1; + } + } + } + + for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pData->oldDnodeEps); ++i) { + SDnodeEpPair *pair = taosArrayGet(pData->oldDnodeEps, i); + for (int32_t j = 0; j < (int32_t)taosArrayGetSize(pData->dnodeEps); ++j) { + SDnodeEp *pDnodeEp = taosArrayGet(pData->dnodeEps, j); + if (strcmp(pDnodeEp->ep.fqdn, pair->oldFqdn) == 0 && pDnodeEp->ep.port == pair->oldPort) { + dInfo("dnode:%d, will update ep:%s:%u to %s:%u", pDnodeEp->id, pDnodeEp->ep.fqdn, pDnodeEp->ep.port, + pair->newFqdn, pair->newPort); + tstrncpy(pDnodeEp->ep.fqdn, pair->newFqdn, TSDB_FQDN_LEN); + pDnodeEp->ep.port = pair->newPort; + } + } + } + + pData->dnodeVer = 0; + return 0; +} diff --git a/source/dnode/mnode/impl/CMakeLists.txt b/source/dnode/mnode/impl/CMakeLists.txt index 25a4397b7defabb855397862127ee4ecaead0ccd..b9aa8eb674b9b6f760f0c782f2a9e7aabe55eeb0 100644 --- a/source/dnode/mnode/impl/CMakeLists.txt +++ b/source/dnode/mnode/impl/CMakeLists.txt @@ -2,8 +2,10 @@ aux_source_directory(src MNODE_SRC) IF (TD_PRIVILEGE) ADD_DEFINITIONS(-D_PRIVILEGE) ENDIF () -IF (TD_PRIVILEGE) +IF (TD_ENTERPRISE) LIST(APPEND MNODE_SRC ${TD_ENTERPRISE_DIR}/src/plugins/privilege/src/privilege.c) + LIST(APPEND MNODE_SRC ${TD_ENTERPRISE_DIR}/src/plugins/mnode/src/mndDb.c) + LIST(APPEND MNODE_SRC ${TD_ENTERPRISE_DIR}/src/plugins/mnode/src/mndVgroup.c) ENDIF () add_library(mnode STATIC ${MNODE_SRC}) diff --git a/source/dnode/mnode/impl/inc/mndConsumer.h b/source/dnode/mnode/impl/inc/mndConsumer.h index 1176e1af0b8fa09328669f11066235870f39b06a..96401511d2cd4832ad6d548a4b7286ba62227a7d 100644 --- a/source/dnode/mnode/impl/inc/mndConsumer.h +++ b/source/dnode/mnode/impl/inc/mndConsumer.h @@ -23,13 +23,12 @@ extern "C" { #endif enum { - MQ_CONSUMER_STATUS__MODIFY = 1, - MQ_CONSUMER_STATUS__MODIFY_IN_REB, + MQ_CONSUMER_STATUS_REBALANCE = 1, +// MQ_CONSUMER_STATUS__MODIFY_IN_REB, // this value is not used anymore MQ_CONSUMER_STATUS__READY, MQ_CONSUMER_STATUS__LOST, - MQ_CONSUMER_STATUS__LOST_IN_REB, +// MQ_CONSUMER_STATUS__LOST_IN_REB, // this value is not used anymore MQ_CONSUMER_STATUS__LOST_REBD, - MQ_CONSUMER_STATUS__REMOVED, }; int32_t mndInitConsumer(SMnode *pMnode); diff --git a/source/dnode/mnode/impl/inc/mndDb.h b/source/dnode/mnode/impl/inc/mndDb.h index cea0a43b61bf53cd1bcc47cae52000295e80fd90..60d35ebe1d9e1a066426e0494e8f150362df2e4b 100644 --- a/source/dnode/mnode/impl/inc/mndDb.h +++ b/source/dnode/mnode/impl/inc/mndDb.h @@ -26,12 +26,15 @@ int32_t mndInitDb(SMnode *pMnode); void mndCleanupDb(SMnode *pMnode); SDbObj *mndAcquireDb(SMnode *pMnode, const char *db); void mndReleaseDb(SMnode *pMnode, SDbObj *pDb); -int32_t mndValidateDbInfo(SMnode *pMnode, SDbVgVersion *pDbs, int32_t numOfDbs, void **ppRsp, int32_t *pRspLen); +int32_t mndValidateDbInfo(SMnode *pMnode, SDbCacheInfo *pDbs, int32_t numOfDbs, void **ppRsp, int32_t *pRspLen); int32_t mndExtractDbInfo(SMnode *pMnode, SDbObj *pDb, SUseDbRsp *pRsp, const SUseDbReq *pReq); bool mndIsDbReady(SMnode *pMnode, SDbObj *pDb); +SSdbRaw *mndDbActionEncode(SDbObj *pDb); const char *mndGetDbStr(const char *src); +int32_t mndProcessCompactDbReq(SRpcMsg *pReq); + #ifdef __cplusplus } #endif diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h index 6f6f801c39a6e8d292d3adf4b52840b0f747ed66..2579ff5231dbba6ea69ef6bc960857b47c92fa30 100644 --- a/source/dnode/mnode/impl/inc/mndDef.h +++ b/source/dnode/mnode/impl/inc/mndDef.h @@ -108,7 +108,8 @@ typedef enum { TRN_STAGE_UNDO_ACTION = 3, TRN_STAGE_COMMIT = 4, TRN_STAGE_COMMIT_ACTION = 5, - TRN_STAGE_FINISHED = 6 + TRN_STAGE_FINISHED = 6, + TRN_STAGE_PRE_FINISH = 7 } ETrnStage; typedef enum { @@ -136,12 +137,12 @@ typedef enum { } EDndReason; typedef enum { - CONSUMER_UPDATE__TOUCH = 1, + CONSUMER_UPDATE__TOUCH = 1, // rebalance req do not need change consume topic CONSUMER_UPDATE__ADD, CONSUMER_UPDATE__REMOVE, CONSUMER_UPDATE__LOST, CONSUMER_UPDATE__RECOVER, - CONSUMER_UPDATE__MODIFY, + CONSUMER_UPDATE__REBALANCE, // subscribe req need change consume topic } ECsmUpdateType; typedef struct { @@ -175,6 +176,7 @@ typedef struct { char opername[TSDB_TRANS_OPER_LEN]; SArray* pRpcArray; SRWLatch lockRpcArray; + int64_t mTraceId; } STrans; typedef struct { @@ -279,6 +281,9 @@ typedef struct { SHashObj* readDbs; SHashObj* writeDbs; SHashObj* topics; + SHashObj* readTbs; + SHashObj* writeTbs; + SHashObj* useDbs; SRWLatch lock; } SUserObj; @@ -328,6 +333,7 @@ typedef struct { SDbCfg cfg; SRWLatch lock; int64_t stateTs; + int64_t compactStartTime; } SDbObj; typedef struct { @@ -357,6 +363,7 @@ typedef struct { int8_t replica; SVnodeGid vnodeGid[TSDB_MAX_REPLICA]; void* pTsma; + int32_t numOfCachedTables; } SVgObj; typedef struct { @@ -388,6 +395,18 @@ typedef struct { SSchemaWrapper schemaTag; // for dstVgroup } SSmaObj; +typedef struct { + char name[TSDB_INDEX_FNAME_LEN]; + char stb[TSDB_TABLE_FNAME_LEN]; + char db[TSDB_DB_FNAME_LEN]; + char dstTbName[TSDB_TABLE_FNAME_LEN]; + char colName[TSDB_COL_NAME_LEN]; + int64_t createdTime; + int64_t uid; + int64_t stbUid; + int64_t dbUid; +} SIdxObj; + typedef struct { char name[TSDB_TABLE_FNAME_LEN]; char db[TSDB_DB_FNAME_LEN]; @@ -431,6 +450,8 @@ typedef struct { int32_t codeSize; char* pComment; char* pCode; + int32_t funcVersion; + SRWLatch lock; } SFuncObj; typedef struct { @@ -442,8 +463,10 @@ typedef struct { void* pIter; SMnode* pMnode; STableMetaRsp* pMeta; + bool restore; bool sysDbRsp; char db[TSDB_DB_FNAME_LEN]; + char filterTb[TSDB_TABLE_NAME_LEN]; } SShowObj; typedef struct { @@ -528,7 +551,7 @@ void* tDecodeSMqConsumerObj(const void* buf, SMqConsumerObj* pConsumer typedef struct { int32_t vgId; - char* qmsg; + char* qmsg; // SubPlanToString SEpSet epSet; } SMqVgEp; @@ -601,7 +624,7 @@ typedef struct { SArray* rebVgs; // SArray SArray* newConsumers; // SArray SArray* removedConsumers; // SArray - SArray* touchedConsumers; // SArray + SArray* modifyConsumers; // SArray SMqSubscribeObj* pSub; SMqSubActionLogEntry* pLogEntry; } SMqRebOutputObj; diff --git a/source/dnode/mnode/impl/inc/mndIndex.h b/source/dnode/mnode/impl/inc/mndIndex.h new file mode 100644 index 0000000000000000000000000000000000000000..2d5479bc9b84bad7b65d9e6574a247193c854537 --- /dev/null +++ b/source/dnode/mnode/impl/inc/mndIndex.h @@ -0,0 +1,34 @@ +#ifndef _TD_MND_IDX_H_ +#define _TD_MND_IDX_H_ + +#include "mndInt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t mndInitIdx(SMnode *pMnode); +void mndCleanupIdx(SMnode *pMnode); +SIdxObj *mndAcquireIdx(SMnode *pMnode, char *Name); +void mndReleaseIdx(SMnode *pMnode, SIdxObj *pSma); +int32_t mndDropIdxsByStb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb); +int32_t mndDropIdxsByDb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb); +int32_t mndGetIdxsByTagName(SMnode *pMnode, SStbObj *pStb, char *tagName, SIdxObj *pIdx); +int32_t mndGetTableIdx(SMnode *pMnode, char *tbFName, STableIndexRsp *rsp, bool *exist); + +int32_t mndRetrieveTagIdx(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); +int32_t mndProcessDropTagIdxReq(SRpcMsg *pReq); + +int32_t mndSetCreateIdxRedoLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx); +int32_t mndSetCreateIdxCommitLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx); +int32_t mndSetDropIdxRedoLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx); +int32_t mndSetDropIdxCommitLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx); + +int32_t mndSetAlterIdxRedoLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx); +int32_t mndSetAlterIdxCommitLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx); + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_MND_IDX_H_*/ \ No newline at end of file diff --git a/source/libs/cache/inc/cacheDef.h b/source/dnode/mnode/impl/inc/mndIndexComm.h similarity index 65% rename from source/libs/cache/inc/cacheDef.h rename to source/dnode/mnode/impl/inc/mndIndexComm.h index 2e0dbfcdb6065ee7cdb15c479e7755dee9d4a77d..68112f0a2dce75bca0f2bd4295dbe1ea1b851115 100644 --- a/source/libs/cache/inc/cacheDef.h +++ b/source/dnode/mnode/impl/inc/mndIndexComm.h @@ -1,3 +1,4 @@ + /* * Copyright (c) 2019 TAOS Data, Inc. * @@ -13,15 +14,30 @@ * along with this program. If not, see . */ -#ifndef _TD_CACHE_DEF_H_ -#define _TD_CACHE_DEF_H_ +#ifndef _TD_MND_IDX_COMM_H_ +#define _TD_MND_IDX_COMM_H_ + +#include "mndInt.h" #ifdef __cplusplus extern "C" { #endif +typedef struct SSIdx { + int type; // sma or idx + void *pIdx; +} SSIdx; + +// retrieve sma index and tag index +typedef struct { + void *pSmaIter; + void *pIdxIter; +} SSmaAndTagIter; + +int32_t mndAcquireGlobalIdx(SMnode *pMnode, char *name, int type, SSIdx *idx); + #ifdef __cplusplus } #endif -#endif /*_TD_CACHE_DEF_H_*/ \ No newline at end of file +#endif /*_TD_MND_IDX_COMM_H_*/ \ No newline at end of file diff --git a/source/dnode/mnode/impl/inc/mndInt.h b/source/dnode/mnode/impl/inc/mndInt.h index 785ecc2bf502ca5f2a1e1203f1dc5fbe29b60a21..ffb2443808b9efdd2e0a3dfbe89662b88962f6be 100644 --- a/source/dnode/mnode/impl/inc/mndInt.h +++ b/source/dnode/mnode/impl/inc/mndInt.h @@ -41,12 +41,12 @@ extern "C" { #define mDebug(...) { if (mDebugFlag & DEBUG_DEBUG) { taosPrintLog("MND ", DEBUG_DEBUG, mDebugFlag, __VA_ARGS__); }} #define mTrace(...) { if (mDebugFlag & DEBUG_TRACE) { taosPrintLog("MND ", DEBUG_TRACE, mDebugFlag, __VA_ARGS__); }} -#define mGFatal(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mFatal(param ", gtid:%s", __VA_ARGS__, buf);} -#define mGError(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mError(param ", gtid:%s", __VA_ARGS__, buf);} -#define mGWarn(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mWarn (param ", gtid:%s", __VA_ARGS__, buf);} -#define mGInfo(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mInfo (param ", gtid:%s", __VA_ARGS__, buf);} -#define mGDebug(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mDebug(param ", gtid:%s", __VA_ARGS__, buf);} -#define mGTrace(param, ...) { char buf[40] = {0}; TRACE_TO_STR(trace, buf); mTrace(param ", gtid:%s", __VA_ARGS__, buf);} +#define mGFatal(param, ...) { if (mDebugFlag & DEBUG_FATAL){ char buf[40] = {0}; TRACE_TO_STR(trace, buf); mFatal(param ", gtid:%s", __VA_ARGS__, buf);}} +#define mGError(param, ...) { if (mDebugFlag & DEBUG_ERROR){ char buf[40] = {0}; TRACE_TO_STR(trace, buf); mError(param ", gtid:%s", __VA_ARGS__, buf);}} +#define mGWarn(param, ...) { if (mDebugFlag & DEBUG_WARN){ char buf[40] = {0}; TRACE_TO_STR(trace, buf); mWarn (param ", gtid:%s", __VA_ARGS__, buf);}} +#define mGInfo(param, ...) { if (mDebugFlag & DEBUG_INFO){ char buf[40] = {0}; TRACE_TO_STR(trace, buf); mInfo (param ", gtid:%s", __VA_ARGS__, buf);}} +#define mGDebug(param, ...) { if (mDebugFlag & DEBUG_DEBUG){ char buf[40] = {0}; TRACE_TO_STR(trace, buf); mDebug(param ", gtid:%s", __VA_ARGS__, buf);}} +#define mGTrace(param, ...) { if (mDebugFlag & DEBUG_TRACE){ char buf[40] = {0}; TRACE_TO_STR(trace, buf); mTrace(param ", gtid:%s", __VA_ARGS__, buf);}} // clang-format on #define SYSTABLE_SCH_TABLE_NAME_LEN ((TSDB_TABLE_NAME_LEN - 1) + VARSTR_HEADER_SIZE) @@ -58,7 +58,7 @@ typedef int32_t (*MndInitFp)(SMnode *pMnode); typedef void (*MndCleanupFp)(SMnode *pMnode); typedef int32_t (*ShowRetrieveFp)(SRpcMsg *pMsg, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); typedef void (*ShowFreeIterFp)(SMnode *pMnode, void *pIter); -typedef struct SQWorker SQHandle; +typedef struct SQueueWorker SQHandle; typedef struct { const char *name; @@ -80,7 +80,7 @@ typedef struct { typedef struct { TdThreadMutex lock; - char email[TSDB_FQDN_LEN]; + char email[TSDB_FQDN_LEN]; } STelemMgmt; typedef struct { @@ -113,6 +113,7 @@ typedef struct SMnode { bool deploy; char *path; int64_t checkTime; + SyncIndex applied; SSdb *pSdb; SArray *pSteps; SQHandle *pQuery; diff --git a/source/dnode/mnode/impl/inc/mndStb.h b/source/dnode/mnode/impl/inc/mndStb.h index 6a4031692301cfe835a2e6426eb51ca874d642ee..66d0ed1d12160b5ea6e9c30f145e0db6faa22b31 100644 --- a/source/dnode/mnode/impl/inc/mndStb.h +++ b/source/dnode/mnode/impl/inc/mndStb.h @@ -38,10 +38,16 @@ void mndFreeStb(SStbObj *pStb); int32_t mndBuildSMCreateStbRsp(SMnode *pMnode, char *dbFName, char *stbFName, void **pCont, int32_t *pLen); void mndExtractDbNameFromStbFullName(const char *stbFullName, char *dst); +void mndExtractShortDbNameFromStbFullName(const char *stbFullName, char *dst); void mndExtractTbNameFromStbFullName(const char *stbFullName, char *dst, int32_t dstSize); const char *mndGetStbStr(const char *src); +int32_t mndAllocStbSchemas(const SStbObj *pOld, SStbObj *pNew); +int32_t mndCheckColAndTagModifiable(SMnode *pMnode, const char *stbFullName, int64_t suid, col_id_t colId); +void *mndBuildVCreateStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pStb, int32_t *pContLen, void *alterOriData, + int32_t alterOriDataLen); + #ifdef __cplusplus } #endif diff --git a/source/dnode/mnode/impl/inc/mndTopic.h b/source/dnode/mnode/impl/inc/mndTopic.h index 8cd669c769a399282ba1137ca8d24eeace039237..b2b86775aba1e59ca7caecc935669eb9c53c4380 100644 --- a/source/dnode/mnode/impl/inc/mndTopic.h +++ b/source/dnode/mnode/impl/inc/mndTopic.h @@ -27,16 +27,12 @@ void mndCleanupTopic(SMnode *pMnode); SMqTopicObj *mndAcquireTopic(SMnode *pMnode, const char *topicName); void mndReleaseTopic(SMnode *pMnode, SMqTopicObj *pTopic); - -SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic); -SSdbRow *mndTopicActionDecode(SSdbRaw *pRaw); - -int32_t mndDropTopicByDB(SMnode *pMnode, STrans *pTrans, SDbObj *pDb); -int32_t mndCheckTopicExist(SMnode *pMnode, SDbObj *pDb); - -const char *mndTopicGetShowName(const char topic[TSDB_TOPIC_FNAME_LEN]); +int32_t mndDropTopicByDB(SMnode *pMnode, STrans *pTrans, SDbObj *pDb); +bool mndTopicExistsForDb(SMnode *pMnode, SDbObj *pDb); +const char *mndTopicGetShowName(const char topic[TSDB_TOPIC_FNAME_LEN]); int32_t mndSetTopicCommitLogs(SMnode *pMnode, STrans *pTrans, SMqTopicObj *pTopic); +int32_t mndGetNumOfTopics(SMnode *pMnode, char *dbName, int32_t *pNumOfTopics); #ifdef __cplusplus } diff --git a/source/dnode/mnode/impl/inc/mndTrans.h b/source/dnode/mnode/impl/inc/mndTrans.h index d6e5d322baf28dbad41d0ea13124e1ec21588f0b..057e3efbbcabe42d43c6030973707e371ccf4fd1 100644 --- a/source/dnode/mnode/impl/inc/mndTrans.h +++ b/source/dnode/mnode/impl/inc/mndTrans.h @@ -52,6 +52,8 @@ typedef struct { int32_t contLen; void *pCont; SSdbRaw *pRaw; + + int64_t mTraceId; } STransAction; typedef void (*TransCbFp)(SMnode *pMnode, void *param, int32_t paramLen); diff --git a/source/dnode/mnode/impl/inc/mndUser.h b/source/dnode/mnode/impl/inc/mndUser.h index 8943ba703ee47442a49fe25ab44ed7fcfb7867cd..95d15f6e5a608ebd218581d78f6f67f6b5e5fdc6 100644 --- a/source/dnode/mnode/impl/inc/mndUser.h +++ b/source/dnode/mnode/impl/inc/mndUser.h @@ -31,6 +31,7 @@ void mndReleaseUser(SMnode *pMnode, SUserObj *pUser); // for trans test SSdbRaw *mndUserActionEncode(SUserObj *pUser); SHashObj *mndDupDbHash(SHashObj *pOld); +SHashObj *mndDupTableHash(SHashObj *pOld); SHashObj *mndDupTopicHash(SHashObj *pOld); int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_t numOfUses, void **ppRsp, int32_t *pRspLen); diff --git a/source/dnode/mnode/impl/inc/mndVgroup.h b/source/dnode/mnode/impl/inc/mndVgroup.h index 765d4fd33da9fa52266a89e8fc57d247c6494a96..94c4eae83f519704abd6278bfbf459c5986c553a 100644 --- a/source/dnode/mnode/impl/inc/mndVgroup.h +++ b/source/dnode/mnode/impl/inc/mndVgroup.h @@ -43,11 +43,15 @@ int32_t mndAddDropVnodeAction(SMnode *, STrans *pTrans, SDbObj *pDb, SVgObj *pVg int32_t mndSetMoveVgroupsInfoToTrans(SMnode *, STrans *pTrans, int32_t dropDnodeId, bool force); int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pVgroup, SArray *pArray); +int32_t mndBuildCompactVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs, + STimeWindow tw); void *mndBuildCreateVnodeReq(SMnode *, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen); void *mndBuildDropVnodeReq(SMnode *, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen); bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid); +int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup); + #ifdef __cplusplus } #endif diff --git a/source/dnode/mnode/impl/src/mndCluster.c b/source/dnode/mnode/impl/src/mndCluster.c index e0d8ecb3eb949d4161f5330d62250b3267ed513b..4d05637a2b3ab872d5a0ba99c022e21f79ca9b05 100644 --- a/source/dnode/mnode/impl/src/mndCluster.c +++ b/source/dnode/mnode/impl/src/mndCluster.c @@ -67,7 +67,7 @@ int32_t mndGetClusterName(SMnode *pMnode, char *clusterName, int32_t len) { return 0; } -static SClusterObj *mndAcquireCluster(SMnode *pMnode) { +static SClusterObj *mndAcquireCluster(SMnode *pMnode, void **ppIter) { SSdb *pSdb = pMnode->pSdb; void *pIter = NULL; @@ -76,23 +76,27 @@ static SClusterObj *mndAcquireCluster(SMnode *pMnode) { pIter = sdbFetch(pSdb, SDB_CLUSTER, pIter, (void **)&pCluster); if (pIter == NULL) break; + *ppIter = pIter; + return pCluster; } return NULL; } -static void mndReleaseCluster(SMnode *pMnode, SClusterObj *pCluster) { +static void mndReleaseCluster(SMnode *pMnode, SClusterObj *pCluster, void *pIter) { SSdb *pSdb = pMnode->pSdb; + sdbCancelFetch(pSdb, pIter); sdbRelease(pSdb, pCluster); } int64_t mndGetClusterId(SMnode *pMnode) { int64_t clusterId = 0; - SClusterObj *pCluster = mndAcquireCluster(pMnode); + void *pIter = NULL; + SClusterObj *pCluster = mndAcquireCluster(pMnode, &pIter); if (pCluster != NULL) { clusterId = pCluster->id; - mndReleaseCluster(pMnode, pCluster); + mndReleaseCluster(pMnode, pCluster, pIter); } return clusterId; @@ -100,10 +104,11 @@ int64_t mndGetClusterId(SMnode *pMnode) { int64_t mndGetClusterCreateTime(SMnode *pMnode) { int64_t createTime = 0; - SClusterObj *pCluster = mndAcquireCluster(pMnode); + void *pIter = NULL; + SClusterObj *pCluster = mndAcquireCluster(pMnode, &pIter); if (pCluster != NULL) { createTime = pCluster->createdTime; - mndReleaseCluster(pMnode, pCluster); + mndReleaseCluster(pMnode, pCluster, pIter); } return createTime; @@ -121,10 +126,11 @@ static int32_t mndGetClusterUpTimeImp(SClusterObj *pCluster) { float mndGetClusterUpTime(SMnode *pMnode) { int64_t upTime = 0; - SClusterObj *pCluster = mndAcquireCluster(pMnode); + void *pIter = NULL; + SClusterObj *pCluster = mndAcquireCluster(pMnode, &pIter); if (pCluster != NULL) { upTime = mndGetClusterUpTimeImp(pCluster); - mndReleaseCluster(pMnode, pCluster); + mndReleaseCluster(pMnode, pCluster, pIter); } return upTime / 86400.0f; @@ -278,31 +284,31 @@ static int32_t mndRetrieveClusters(SRpcMsg *pMsg, SShowObj *pShow, SSDataBlock * cols = 0; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pCluster->id, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pCluster->id, false); char buf[tListLen(pCluster->name) + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(buf, pCluster->name, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, buf, false); + colDataSetVal(pColInfo, numOfRows, buf, false); int32_t upTime = mndGetClusterUpTimeImp(pCluster); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&upTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&upTime, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pCluster->createdTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pCluster->createdTime, false); char ver[12] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(ver, tsVersionName, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)ver, false); + colDataSetVal(pColInfo, numOfRows, (const char *)ver, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); if (tsExpireTime <= 0) { - colDataAppendNULL(pColInfo, numOfRows); + colDataSetNULL(pColInfo, numOfRows); } else { - colDataAppend(pColInfo, numOfRows, (const char *)&tsExpireTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&tsExpireTime, false); } sdbRelease(pSdb, pCluster); @@ -321,11 +327,12 @@ static void mndCancelGetNextCluster(SMnode *pMnode, void *pIter) { static int32_t mndProcessUptimeTimer(SRpcMsg *pReq) { SMnode *pMnode = pReq->info.node; SClusterObj clusterObj = {0}; - SClusterObj *pCluster = mndAcquireCluster(pMnode); + void *pIter = NULL; + SClusterObj *pCluster = mndAcquireCluster(pMnode, &pIter); if (pCluster != NULL) { memcpy(&clusterObj, pCluster, sizeof(SClusterObj)); clusterObj.upTime += tsUptimeInterval; - mndReleaseCluster(pMnode, pCluster); + mndReleaseCluster(pMnode, pCluster, pIter); } if (clusterObj.id <= 0) { diff --git a/source/dnode/mnode/impl/src/mndConsumer.c b/source/dnode/mnode/impl/src/mndConsumer.c index 1aa2fa997b684221e1d1cd61b85cdf5f1c6cc669..d144747e81aabe57362eb547886648bfb0cb76d6 100644 --- a/source/dnode/mnode/impl/src/mndConsumer.c +++ b/source/dnode/mnode/impl/src/mndConsumer.c @@ -15,35 +15,29 @@ #define _DEFAULT_SOURCE #include "mndConsumer.h" -#include "mndDb.h" -#include "mndDnode.h" -#include "mndMnode.h" #include "mndPrivilege.h" #include "mndShow.h" -#include "mndStb.h" #include "mndSubscribe.h" #include "mndTopic.h" #include "mndTrans.h" -#include "mndUser.h" -#include "mndVgroup.h" #include "tcompare.h" #include "tname.h" #define MND_CONSUMER_VER_NUMBER 1 #define MND_CONSUMER_RESERVE_SIZE 64 -#define MND_CONSUMER_LOST_HB_CNT 3 +#define MND_CONSUMER_LOST_HB_CNT 6 #define MND_CONSUMER_LOST_CLEAR_THRESHOLD 43200 -static int8_t mqRebInExecCnt = 0; +static int32_t mqRebInExecCnt = 0; static const char *mndConsumerStatusName(int status); static int32_t mndConsumerActionInsert(SSdb *pSdb, SMqConsumerObj *pConsumer); static int32_t mndConsumerActionDelete(SSdb *pSdb, SMqConsumerObj *pConsumer); -static int32_t mndConsumerActionUpdate(SSdb *pSdb, SMqConsumerObj *pConsumer, SMqConsumerObj *pNewConsumer); +static int32_t mndConsumerActionUpdate(SSdb *pSdb, SMqConsumerObj *pOldConsumer, SMqConsumerObj *pNewConsumer); static int32_t mndProcessConsumerMetaMsg(SRpcMsg *pMsg); -static int32_t mndRetrieveConsumer(SRpcMsg *pMsg, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); +static int32_t mndRetrieveConsumer(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); static void mndCancelGetNextConsumer(SMnode *pMnode, void *pIter); static int32_t mndProcessSubscribeReq(SRpcMsg *pMsg); @@ -82,15 +76,34 @@ int32_t mndInitConsumer(SMnode *pMnode) { void mndCleanupConsumer(SMnode *pMnode) {} bool mndRebTryStart() { - int8_t old = atomic_val_compare_exchange_8(&mqRebInExecCnt, 0, 1); + int32_t old = atomic_val_compare_exchange_32(&mqRebInExecCnt, 0, 1); + mDebug("tq timer, rebalance counter old val:%d", old); return old == 0; } -void mndRebEnd() { atomic_sub_fetch_8(&mqRebInExecCnt, 1); } +void mndRebEnd() { mndRebCntDec(); } -void mndRebCntInc() { atomic_add_fetch_8(&mqRebInExecCnt, 1); } +void mndRebCntInc() { + int32_t val = atomic_add_fetch_32(&mqRebInExecCnt, 1); + mInfo("rebalance trans start, rebalance counter:%d", val); +} -void mndRebCntDec() { atomic_sub_fetch_8(&mqRebInExecCnt, 1); } +void mndRebCntDec() { + while (1) { + int32_t val = atomic_load_32(&mqRebInExecCnt); + if (val <= 0) { + mError("rebalance trans end, rebalance counter:%d should not be less equalled than 0, ignore counter desc", val); + break; + } + + int32_t newVal = val - 1; + int32_t oldVal = atomic_val_compare_exchange_32(&mqRebInExecCnt, val, newVal); + if (oldVal == val) { + mDebug("rebalance trans end, rebalance counter:%d", newVal); + break; + } + } +} static int32_t mndProcessConsumerLostMsg(SRpcMsg *pMsg) { SMnode *pMnode = pMsg->info.node; @@ -100,7 +113,7 @@ static int32_t mndProcessConsumerLostMsg(SRpcMsg *pMsg) { return 0; } - mInfo("receive consumer lost msg, consumer id %" PRId64 ", status %s", pLostMsg->consumerId, + mInfo("process consumer lost msg, consumer:0x%" PRIx64 " status:%d(%s)", pLostMsg->consumerId, pConsumer->status, mndConsumerStatusName(pConsumer->status)); if (pConsumer->status != MQ_CONSUMER_STATUS__READY) { @@ -114,9 +127,17 @@ static int32_t mndProcessConsumerLostMsg(SRpcMsg *pMsg) { mndReleaseConsumer(pMnode, pConsumer); STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pMsg, "lost-csm"); - if (pTrans == NULL) goto FAIL; - if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) goto FAIL; - if (mndTransPrepare(pMnode, pTrans) != 0) goto FAIL; + if (pTrans == NULL) { + goto FAIL; + } + + if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) { + goto FAIL; + } + + if (mndTransPrepare(pMnode, pTrans) != 0) { + goto FAIL; + } tDeleteSMqConsumerObj(pConsumerNew); taosMemoryFree(pConsumerNew); @@ -133,10 +154,13 @@ static int32_t mndProcessConsumerRecoverMsg(SRpcMsg *pMsg) { SMnode *pMnode = pMsg->info.node; SMqConsumerRecoverMsg *pRecoverMsg = pMsg->pCont; SMqConsumerObj *pConsumer = mndAcquireConsumer(pMnode, pRecoverMsg->consumerId); - ASSERT(pConsumer); + if (pConsumer == NULL) { + mError("cannot find consumer %" PRId64 " when processing consumer recover msg", pRecoverMsg->consumerId); + return -1; + } - mInfo("receive consumer recover msg, consumer id %" PRId64 ", status %s", pRecoverMsg->consumerId, - mndConsumerStatusName(pConsumer->status)); + mInfo("receive consumer recover msg, consumer:0x%" PRIx64 " status:%d(%s)", pRecoverMsg->consumerId, + pConsumer->status, mndConsumerStatusName(pConsumer->status)); if (pConsumer->status != MQ_CONSUMER_STATUS__LOST_REBD) { mndReleaseConsumer(pMnode, pConsumer); @@ -150,7 +174,10 @@ static int32_t mndProcessConsumerRecoverMsg(SRpcMsg *pMsg) { mndReleaseConsumer(pMnode, pConsumer); STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pMsg, "recover-csm"); - if (pTrans == NULL) goto FAIL; + if (pTrans == NULL) { + goto FAIL; + } + if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) goto FAIL; if (mndTransPrepare(pMnode, pTrans) != 0) goto FAIL; @@ -165,15 +192,18 @@ FAIL: return -1; } +// todo check the clear process static int32_t mndProcessConsumerClearMsg(SRpcMsg *pMsg) { SMnode *pMnode = pMsg->info.node; SMqConsumerClearMsg *pClearMsg = pMsg->pCont; - SMqConsumerObj *pConsumer = mndAcquireConsumer(pMnode, pClearMsg->consumerId); + + SMqConsumerObj *pConsumer = mndAcquireConsumer(pMnode, pClearMsg->consumerId); if (pConsumer == NULL) { + mError("consumer:0x%"PRIx64" failed to be found to clear it", pClearMsg->consumerId); return 0; } - mInfo("receive consumer clear msg, consumer id %" PRId64 ", status %s", pClearMsg->consumerId, + mInfo("consumer:0x%" PRIx64 " needs to be cleared, status %s", pClearMsg->consumerId, mndConsumerStatusName(pConsumer->status)); if (pConsumer->status != MQ_CONSUMER_STATUS__LOST_REBD) { @@ -188,6 +218,8 @@ static int32_t mndProcessConsumerClearMsg(SRpcMsg *pMsg) { STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pMsg, "clear-csm"); if (pTrans == NULL) goto FAIL; + + // this is the drop action, not the update action if (mndSetConsumerDropLogs(pMnode, pTrans, pConsumerNew) != 0) goto FAIL; if (mndTransPrepare(pMnode, pTrans) != 0) goto FAIL; @@ -195,6 +227,7 @@ static int32_t mndProcessConsumerClearMsg(SRpcMsg *pMsg) { taosMemoryFree(pConsumerNew); mndTransDrop(pTrans); return 0; + FAIL: tDeleteSMqConsumerObj(pConsumerNew); taosMemoryFree(pConsumerNew); @@ -217,55 +250,90 @@ static SMqRebInfo *mndGetOrCreateRebSub(SHashObj *pHash, const char *key) { return pRebInfo; } +static void freeRebalanceItem(void *param) { + SMqRebInfo *pInfo = param; + taosArrayDestroy(pInfo->newConsumers); + taosArrayDestroy(pInfo->removedConsumers); +} + static int32_t mndProcessMqTimerMsg(SRpcMsg *pMsg) { SMnode *pMnode = pMsg->info.node; SSdb *pSdb = pMnode->pSdb; SMqConsumerObj *pConsumer; void *pIter = NULL; - mTrace("start to process mq timer"); + mDebug("start to process mq timer"); // rebalance cannot be parallel if (!mndRebTryStart()) { - mInfo("mq rebalance already in progress, do nothing"); + mDebug("mq rebalance already in progress, do nothing"); return 0; } SMqDoRebalanceMsg *pRebMsg = rpcMallocCont(sizeof(SMqDoRebalanceMsg)); + if (pRebMsg == NULL) { + mError("failed to create the rebalance msg, size:%d, quit mq timer", (int32_t)sizeof(SMqDoRebalanceMsg)); + mndRebEnd(); + return TSDB_CODE_OUT_OF_MEMORY; + } + pRebMsg->rebSubHash = taosHashInit(64, MurmurHash3_32, true, HASH_NO_LOCK); - // TODO set cleanfp + if (pRebMsg->rebSubHash == NULL) { + mError("failed to create rebalance hashmap"); + rpcFreeCont(pRebMsg); + mndRebEnd(); + return TSDB_CODE_OUT_OF_MEMORY; + } + + taosHashSetFreeFp(pRebMsg->rebSubHash, freeRebalanceItem); // iterate all consumers, find all modification while (1) { pIter = sdbFetch(pSdb, SDB_CONSUMER, pIter, (void **)&pConsumer); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } int32_t hbStatus = atomic_add_fetch_32(&pConsumer->hbStatus, 1); int32_t status = atomic_load_32(&pConsumer->status); - if (status == MQ_CONSUMER_STATUS__READY && hbStatus > MND_CONSUMER_LOST_HB_CNT) { - SMqConsumerLostMsg *pLostMsg = rpcMallocCont(sizeof(SMqConsumerLostMsg)); - - pLostMsg->consumerId = pConsumer->consumerId; - SRpcMsg rpcMsg = { - .msgType = TDMT_MND_TMQ_CONSUMER_LOST, - .pCont = pLostMsg, - .contLen = sizeof(SMqConsumerLostMsg), - }; - tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &rpcMsg); - } + + mDebug("check for consumer:0x%" PRIx64 " status:%d(%s), sub-time:%" PRId64 ", uptime:%" PRId64 ", hbstatus:%d", + pConsumer->consumerId, status, mndConsumerStatusName(status), pConsumer->subscribeTime, pConsumer->upTime, + hbStatus); if (status == MQ_CONSUMER_STATUS__READY) { - // do nothing + if (hbStatus > MND_CONSUMER_LOST_HB_CNT) { + SMqConsumerLostMsg *pLostMsg = rpcMallocCont(sizeof(SMqConsumerLostMsg)); + if (pLostMsg == NULL) { + mError("consumer:0x%"PRIx64" failed to transfer consumer status to lost due to out of memory. alloc size:%d", + pConsumer->consumerId, (int32_t)sizeof(SMqConsumerLostMsg)); + continue; + } + + pLostMsg->consumerId = pConsumer->consumerId; + SRpcMsg rpcMsg = { + .msgType = TDMT_MND_TMQ_CONSUMER_LOST, .pCont = pLostMsg, .contLen = sizeof(SMqConsumerLostMsg)}; + + mDebug("consumer:0x%"PRIx64" hb not received beyond threshold %d, set to lost", pConsumer->consumerId, + MND_CONSUMER_LOST_HB_CNT); + tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &rpcMsg); + } } else if (status == MQ_CONSUMER_STATUS__LOST_REBD) { + // if the client is lost longer than one day, clear it. Otherwise, do nothing about the lost consumers. if (hbStatus > MND_CONSUMER_LOST_CLEAR_THRESHOLD) { SMqConsumerClearMsg *pClearMsg = rpcMallocCont(sizeof(SMqConsumerClearMsg)); + if (pClearMsg == NULL) { + mError("consumer:0x%"PRIx64" failed to clear consumer due to out of memory. alloc size:%d", + pConsumer->consumerId, (int32_t)sizeof(SMqConsumerClearMsg)); + continue; + } pClearMsg->consumerId = pConsumer->consumerId; SRpcMsg rpcMsg = { - .msgType = TDMT_MND_TMQ_LOST_CONSUMER_CLEAR, - .pCont = pClearMsg, - .contLen = sizeof(SMqConsumerClearMsg), - }; + .msgType = TDMT_MND_TMQ_LOST_CONSUMER_CLEAR, .pCont = pClearMsg, .contLen = sizeof(SMqConsumerClearMsg)}; + + mDebug("consumer:0x%" PRIx64 " lost beyond threshold %d, clear it", pConsumer->consumerId, + MND_CONSUMER_LOST_CLEAR_THRESHOLD); tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &rpcMsg); } } else if (status == MQ_CONSUMER_STATUS__LOST) { @@ -279,8 +347,9 @@ static int32_t mndProcessMqTimerMsg(SRpcMsg *pMsg) { taosArrayPush(pRebSub->removedConsumers, &pConsumer->consumerId); } taosRUnLockLatch(&pConsumer->lock); - } else if (status == MQ_CONSUMER_STATUS__MODIFY) { + } else { // MQ_CONSUMER_STATUS_REBALANCE taosRLockLatch(&pConsumer->lock); + int32_t newTopicNum = taosArrayGetSize(pConsumer->rebNewTopics); for (int32_t i = 0; i < newTopicNum; i++) { char key[TSDB_SUBSCRIBE_KEY_LEN]; @@ -299,8 +368,6 @@ static int32_t mndProcessMqTimerMsg(SRpcMsg *pMsg) { taosArrayPush(pRebSub->removedConsumers, &pConsumer->consumerId); } taosRUnLockLatch(&pConsumer->lock); - } else { - // do nothing } mndReleaseConsumer(pMnode, pConsumer); @@ -317,7 +384,7 @@ static int32_t mndProcessMqTimerMsg(SRpcMsg *pMsg) { } else { taosHashCleanup(pRebMsg->rebSubHash); rpcFreeCont(pRebMsg); - mTrace("mq rebalance finished, no modification"); + mDebug("mq timer finished, no need to re-balance"); mndRebEnd(); } return 0; @@ -335,7 +402,7 @@ static int32_t mndProcessMqHbReq(SRpcMsg *pMsg) { int64_t consumerId = req.consumerId; SMqConsumerObj *pConsumer = mndAcquireConsumer(pMnode, consumerId); if (pConsumer == NULL) { - mError("consumer %" PRId64 " not exist", consumerId); + mError("consumer:0x%" PRIx64 " not exist", consumerId); terrno = TSDB_CODE_MND_CONSUMER_NOT_EXIST; return -1; } @@ -345,7 +412,7 @@ static int32_t mndProcessMqHbReq(SRpcMsg *pMsg) { int32_t status = atomic_load_32(&pConsumer->status); if (status == MQ_CONSUMER_STATUS__LOST_REBD) { - mInfo("try to recover consumer %" PRId64 "", consumerId); + mInfo("try to recover consumer:0x%" PRIx64 "", consumerId); SMqConsumerRecoverMsg *pRecoverMsg = rpcMallocCont(sizeof(SMqConsumerRecoverMsg)); pRecoverMsg->consumerId = consumerId; @@ -377,20 +444,26 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) { SMqConsumerObj *pConsumer = mndAcquireConsumer(pMnode, consumerId); if (pConsumer == NULL) { + mError("consumer:0x%" PRIx64 " group:%s not exists in sdb", consumerId, req.cgroup); terrno = TSDB_CODE_MND_CONSUMER_NOT_EXIST; return -1; } - ASSERT(strcmp(req.cgroup, pConsumer->cgroup) == 0); + int32_t ret = strncmp(req.cgroup, pConsumer->cgroup, tListLen(pConsumer->cgroup)); + if (ret != 0) { + mError("consumer:0x%" PRIx64 " group:%s not consistent with data in sdb, saved cgroup:%s", consumerId, req.cgroup, + pConsumer->cgroup); + terrno = TSDB_CODE_MND_CONSUMER_NOT_EXIST; + return -1; + } atomic_store_32(&pConsumer->hbStatus, 0); // 1. check consumer status int32_t status = atomic_load_32(&pConsumer->status); -#if 1 if (status == MQ_CONSUMER_STATUS__LOST_REBD) { - mInfo("try to recover consumer %" PRId64 "", consumerId); + mInfo("try to recover consumer:0x%" PRIx64, consumerId); SMqConsumerRecoverMsg *pRecoverMsg = rpcMallocCont(sizeof(SMqConsumerRecoverMsg)); pRecoverMsg->consumerId = consumerId; @@ -399,22 +472,23 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) { .pCont = pRecoverMsg, .contLen = sizeof(SMqConsumerRecoverMsg), }; + tmsgPutToQueue(&pMnode->msgCb, WRITE_QUEUE, &pRpcMsg); } -#endif if (status != MQ_CONSUMER_STATUS__READY) { - mInfo("consumer %" PRId64 " not ready, status: %s", consumerId, mndConsumerStatusName(status)); + mInfo("consumer:0x%" PRIx64 " not ready, status: %s", consumerId, mndConsumerStatusName(status)); terrno = TSDB_CODE_MND_CONSUMER_NOT_READY; return -1; } int32_t serverEpoch = atomic_load_32(&pConsumer->epoch); - // 2. check epoch, only send ep info when epoches do not match + // 2. check epoch, only send ep info when epochs do not match if (epoch != serverEpoch) { taosRLockLatch(&pConsumer->lock); - mInfo("process ask ep, consumer:%" PRId64 "(epoch %d), server epoch %d", consumerId, epoch, serverEpoch); + mInfo("process ask ep, consumer:0x%" PRIx64 "(epoch %d) update with server epoch %d", consumerId, epoch, + serverEpoch); int32_t numOfTopics = taosArrayGetSize(pConsumer->currentTopics); rsp.topics = taosArrayInit(numOfTopics, sizeof(SMqSubTopicEp)); @@ -424,13 +498,12 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) { goto FAIL; } - // handle all topic subscribed by the consumer + // handle all topics subscribed by this consumer for (int32_t i = 0; i < numOfTopics; i++) { char *topic = taosArrayGetP(pConsumer->currentTopics, i); SMqSubscribeObj *pSub = mndAcquireSubscribe(pMnode, pConsumer->cgroup, topic); - // txn guarantees pSub is created - ASSERT(pSub); + taosRLockLatch(&pSub->lock); SMqSubTopicEp topicEp = {0}; @@ -438,7 +511,6 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) { // 2.1 fetch topic schema SMqTopicObj *pTopic = mndAcquireTopic(pMnode, topic); - ASSERT(pTopic); taosRLockLatch(&pTopic->lock); tstrncpy(topicEp.db, pTopic->db, TSDB_DB_FNAME_LEN); topicEp.schema.nCols = pTopic->schema.nCols; @@ -453,6 +525,7 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) { SMqConsumerEp *pConsumerEp = taosHashGet(pSub->consumerHash, &consumerId, sizeof(int64_t)); int32_t vgNum = taosArrayGetSize(pConsumerEp->vgs); + // this customer assigned vgroups topicEp.vgs = taosArrayInit(vgNum, sizeof(SMqSubVgEp)); if (topicEp.vgs == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -482,6 +555,7 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) { } taosRUnLockLatch(&pConsumer->lock); } + // encode rsp int32_t tlen = sizeof(SMqRspHead) + tEncodeSMqAskEpRsp(NULL, &rsp); void *buf = rpcMallocCont(tlen); @@ -489,6 +563,7 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } + ((SMqRspHead *)buf)->mqMsgType = TMQ_MSG_TYPE__EP_RSP; ((SMqRspHead *)buf)->epoch = serverEpoch; ((SMqRspHead *)buf)->consumerId = pConsumer->consumerId; @@ -504,6 +579,7 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) { pMsg->info.rsp = buf; pMsg->info.rspLen = tlen; return 0; + FAIL: tDeleteSMqAskEpRsp(&rsp); mndReleaseConsumer(pMnode, pConsumer); @@ -526,118 +602,138 @@ int32_t mndSetConsumerCommitLogs(SMnode *pMnode, STrans *pTrans, SMqConsumerObj return 0; } -static int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) { - SMnode *pMnode = pMsg->info.node; - char *msgStr = pMsg->pCont; +static int32_t validateTopics(const SArray *pTopicList, SMnode *pMnode, const char *pUser) { + int32_t numOfTopics = taosArrayGetSize(pTopicList); + + for (int32_t i = 0; i < numOfTopics; i++) { + char *pOneTopic = taosArrayGetP(pTopicList, i); + SMqTopicObj *pTopic = mndAcquireTopic(pMnode, pOneTopic); + if (pTopic == NULL) { // terrno has been set by callee function + return -1; + } + + if (mndCheckTopicPrivilege(pMnode, pUser, MND_OPER_SUBSCRIBE, pTopic) != 0) { + mndReleaseTopic(pMnode, pTopic); + return -1; + } + + mndReleaseTopic(pMnode, pTopic); + } + + return 0; +} + +static void *topicNameDup(void *p) { return taosStrdup((char *)p); } + +static void freeItem(void *param) { + void *pItem = *(void **)param; + if (pItem != NULL) { + taosMemoryFree(pItem); + } +} + +int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) { + SMnode *pMnode = pMsg->info.node; + char *msgStr = pMsg->pCont; + SCMSubscribeReq subscribe = {0}; tDeserializeSCMSubscribeReq(msgStr, &subscribe); - int64_t consumerId = subscribe.consumerId; + + uint64_t consumerId = subscribe.consumerId; char *cgroup = subscribe.cgroup; - SMqConsumerObj *pConsumerOld = NULL; + SMqConsumerObj *pExistedConsumer = NULL; SMqConsumerObj *pConsumerNew = NULL; int32_t code = -1; - SArray *newSub = subscribe.topicNames; - taosArraySort(newSub, taosArrayCompareString); - taosArrayRemoveDuplicateP(newSub, taosArrayCompareString, taosMemoryFree); + SArray *pTopicList = subscribe.topicNames; + taosArraySort(pTopicList, taosArrayCompareString); + taosArrayRemoveDuplicate(pTopicList, taosArrayCompareString, freeItem); - int32_t newTopicNum = taosArrayGetSize(newSub); - // check topic existance - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pMsg, "subscribe"); - if (pTrans == NULL) goto SUBSCRIBE_OVER; - - for (int32_t i = 0; i < newTopicNum; i++) { - char *topic = taosArrayGetP(newSub, i); - SMqTopicObj *pTopic = mndAcquireTopic(pMnode, topic); - if (pTopic == NULL) { - terrno = TSDB_CODE_MND_TOPIC_NOT_EXIST; - goto SUBSCRIBE_OVER; - } + int32_t newTopicNum = taosArrayGetSize(pTopicList); - if (mndCheckTopicPrivilege(pMnode, pMsg->info.conn.user, MND_OPER_SUBSCRIBE, pTopic) != 0) { - mndReleaseTopic(pMnode, pTopic); - goto SUBSCRIBE_OVER; - } + // check topic existence + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_NOTHING, pMsg, "subscribe"); + if (pTrans == NULL) { + goto _over; + } - mndReleaseTopic(pMnode, pTopic); + code = validateTopics(pTopicList, pMnode, pMsg->info.conn.user); + if (code != TSDB_CODE_SUCCESS) { + goto _over; } - pConsumerOld = mndAcquireConsumer(pMnode, consumerId); - if (pConsumerOld == NULL) { - mInfo("receive subscribe request from new consumer:%" PRId64, consumerId); + pExistedConsumer = mndAcquireConsumer(pMnode, consumerId); + if (pExistedConsumer == NULL) { + mInfo("receive subscribe request from new consumer:0x%" PRIx64 " cgroup:%s, numOfTopics:%d", consumerId, + subscribe.cgroup, (int32_t)taosArrayGetSize(pTopicList)); pConsumerNew = tNewSMqConsumerObj(consumerId, cgroup); - tstrncpy(pConsumerNew->clientId, subscribe.clientId, 256); - pConsumerNew->updateType = CONSUMER_UPDATE__MODIFY; + tstrncpy(pConsumerNew->clientId, subscribe.clientId, tListLen(pConsumerNew->clientId)); + + // set the update type + pConsumerNew->updateType = CONSUMER_UPDATE__REBALANCE; + taosArrayDestroy(pConsumerNew->assignedTopics); + pConsumerNew->assignedTopics = taosArrayDup(pTopicList, topicNameDup); + + // all subscribed topics should re-balance. taosArrayDestroy(pConsumerNew->rebNewTopics); - pConsumerNew->rebNewTopics = newSub; + pConsumerNew->rebNewTopics = pTopicList; subscribe.topicNames = NULL; - for (int32_t i = 0; i < newTopicNum; i++) { - char *newTopicCopy = strdup(taosArrayGetP(newSub, i)); - taosArrayPush(pConsumerNew->assignedTopics, &newTopicCopy); - } - - if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) goto SUBSCRIBE_OVER; - if (mndTransPrepare(pMnode, pTrans) != 0) goto SUBSCRIBE_OVER; + if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) goto _over; + if (mndTransPrepare(pMnode, pTrans) != 0) goto _over; } else { - /*taosRLockLatch(&pConsumerOld->lock);*/ - - int32_t status = atomic_load_32(&pConsumerOld->status); + int32_t status = atomic_load_32(&pExistedConsumer->status); - mInfo("receive subscribe request from existing consumer:%" PRId64 ", current status: %s, subscribe topic num: %d", - consumerId, mndConsumerStatusName(status), newTopicNum); + mInfo("receive subscribe request from existed consumer:0x%" PRIx64 + " cgroup:%s, current status:%d(%s), subscribe topic num: %d", + consumerId, subscribe.cgroup, status, mndConsumerStatusName(status), newTopicNum); if (status != MQ_CONSUMER_STATUS__READY) { terrno = TSDB_CODE_MND_CONSUMER_NOT_READY; - goto SUBSCRIBE_OVER; + goto _over; } pConsumerNew = tNewSMqConsumerObj(consumerId, cgroup); if (pConsumerNew == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - goto SUBSCRIBE_OVER; + goto _over; } - pConsumerNew->updateType = CONSUMER_UPDATE__MODIFY; - for (int32_t i = 0; i < newTopicNum; i++) { - char *newTopicCopy = strdup(taosArrayGetP(newSub, i)); - taosArrayPush(pConsumerNew->assignedTopics, &newTopicCopy); - } + // set the update type + pConsumerNew->updateType = CONSUMER_UPDATE__REBALANCE; + taosArrayDestroy(pConsumerNew->assignedTopics); + pConsumerNew->assignedTopics = taosArrayDup(pTopicList, topicNameDup); - int32_t oldTopicNum = 0; - if (pConsumerOld->currentTopics) { - oldTopicNum = taosArrayGetSize(pConsumerOld->currentTopics); - } + int32_t oldTopicNum = (pExistedConsumer->currentTopics) ? taosArrayGetSize(pExistedConsumer->currentTopics) : 0; int32_t i = 0, j = 0; while (i < oldTopicNum || j < newTopicNum) { if (i >= oldTopicNum) { - char *newTopicCopy = strdup(taosArrayGetP(newSub, j)); + char *newTopicCopy = taosStrdup(taosArrayGetP(pTopicList, j)); taosArrayPush(pConsumerNew->rebNewTopics, &newTopicCopy); j++; continue; } else if (j >= newTopicNum) { - char *oldTopicCopy = strdup(taosArrayGetP(pConsumerOld->currentTopics, i)); + char *oldTopicCopy = taosStrdup(taosArrayGetP(pExistedConsumer->currentTopics, i)); taosArrayPush(pConsumerNew->rebRemovedTopics, &oldTopicCopy); i++; continue; } else { - char *oldTopic = taosArrayGetP(pConsumerOld->currentTopics, i); - char *newTopic = taosArrayGetP(newSub, j); - int comp = compareLenPrefixedStr(oldTopic, newTopic); + char *oldTopic = taosArrayGetP(pExistedConsumer->currentTopics, i); + char *newTopic = taosArrayGetP(pTopicList, j); + int comp = strcmp(oldTopic, newTopic); if (comp == 0) { i++; j++; continue; } else if (comp < 0) { - char *oldTopicCopy = strdup(oldTopic); + char *oldTopicCopy = taosStrdup(oldTopic); taosArrayPush(pConsumerNew->rebRemovedTopics, &oldTopicCopy); i++; continue; } else { - char *newTopicCopy = strdup(newTopic); + char *newTopicCopy = taosStrdup(newTopic); taosArrayPush(pConsumerNew->rebNewTopics, &newTopicCopy); j++; continue; @@ -645,33 +741,32 @@ static int32_t mndProcessSubscribeReq(SRpcMsg *pMsg) { } } - if (pConsumerOld && taosArrayGetSize(pConsumerNew->rebNewTopics) == 0 && - taosArrayGetSize(pConsumerNew->rebRemovedTopics) == 0) { - /*if (taosArrayGetSize(pConsumerNew->assignedTopics) == 0) {*/ - /*pConsumerNew->updateType = */ - /*}*/ - goto SUBSCRIBE_OVER; + // no topics need to be rebalanced + if (taosArrayGetSize(pConsumerNew->rebNewTopics) == 0 && taosArrayGetSize(pConsumerNew->rebRemovedTopics) == 0) { + goto _over; } - if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) goto SUBSCRIBE_OVER; - if (mndTransPrepare(pMnode, pTrans) != 0) goto SUBSCRIBE_OVER; + if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) goto _over; + if (mndTransPrepare(pMnode, pTrans) != 0) goto _over; } code = TSDB_CODE_ACTION_IN_PROGRESS; -SUBSCRIBE_OVER: +_over: mndTransDrop(pTrans); - if (pConsumerOld) { - /*taosRUnLockLatch(&pConsumerOld->lock);*/ - mndReleaseConsumer(pMnode, pConsumerOld); + if (pExistedConsumer) { + /*taosRUnLockLatch(&pExistedConsumer->lock);*/ + mndReleaseConsumer(pMnode, pExistedConsumer); } + if (pConsumerNew) { tDeleteSMqConsumerObj(pConsumerNew); taosMemoryFree(pConsumerNew); } + // TODO: replace with destroy subscribe msg - if (subscribe.topicNames) taosArrayDestroyP(subscribe.topicNames, (FDelete)taosMemoryFree); + taosArrayDestroyP(subscribe.topicNames, (FDelete)taosMemoryFree); return code; } @@ -702,23 +797,24 @@ SSdbRaw *mndConsumerActionEncode(SMqConsumerObj *pConsumer) { CM_ENCODE_OVER: taosMemoryFreeClear(buf); if (terrno != 0) { - mError("consumer:%" PRId64 ", failed to encode to raw:%p since %s", pConsumer->consumerId, pRaw, terrstr()); + mError("consumer:0x%" PRIx64 " failed to encode to raw:%p since %s", pConsumer->consumerId, pRaw, terrstr()); sdbFreeRaw(pRaw); return NULL; } - mTrace("consumer:%" PRId64 ", encode to raw:%p, row:%p", pConsumer->consumerId, pRaw, pConsumer); + mTrace("consumer:0x%" PRIx64 ", encode to raw:%p, row:%p", pConsumer->consumerId, pRaw, pConsumer); return pRaw; } SSdbRow *mndConsumerActionDecode(SSdbRaw *pRaw) { - terrno = TSDB_CODE_OUT_OF_MEMORY; SSdbRow *pRow = NULL; SMqConsumerObj *pConsumer = NULL; void *buf = NULL; int8_t sver = 0; - if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto CM_DECODE_OVER; + if (sdbGetRawSoftVer(pRaw, &sver) != 0) { + goto CM_DECODE_OVER; + } if (sver != MND_CONSUMER_VER_NUMBER) { terrno = TSDB_CODE_SDB_INVALID_DATA_VER; @@ -726,223 +822,228 @@ SSdbRow *mndConsumerActionDecode(SSdbRaw *pRaw) { } pRow = sdbAllocRow(sizeof(SMqConsumerObj)); - if (pRow == NULL) goto CM_DECODE_OVER; + if (pRow == NULL) { + goto CM_DECODE_OVER; + } pConsumer = sdbGetRowObj(pRow); - if (pConsumer == NULL) goto CM_DECODE_OVER; + if (pConsumer == NULL) { + goto CM_DECODE_OVER; + } int32_t dataPos = 0; int32_t len; SDB_GET_INT32(pRaw, dataPos, &len, CM_DECODE_OVER); buf = taosMemoryMalloc(len); - if (buf == NULL) goto CM_DECODE_OVER; + if (buf == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto CM_DECODE_OVER; + } + SDB_GET_BINARY(pRaw, dataPos, buf, len, CM_DECODE_OVER); SDB_GET_RESERVE(pRaw, dataPos, MND_CONSUMER_RESERVE_SIZE, CM_DECODE_OVER); if (tDecodeSMqConsumerObj(buf, pConsumer) == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; // TODO set correct error code goto CM_DECODE_OVER; } - tmsgUpdateDnodeEpSet(&pConsumer->ep); - terrno = TSDB_CODE_SUCCESS; + tmsgUpdateDnodeEpSet(&pConsumer->ep); CM_DECODE_OVER: taosMemoryFreeClear(buf); if (terrno != TSDB_CODE_SUCCESS) { - mError("consumer:%" PRId64 ", failed to decode from raw:%p since %s", pConsumer == NULL ? 0 : pConsumer->consumerId, - pRaw, terrstr()); + mError("consumer:0x%" PRIx64 " failed to decode from raw:%p since %s", + pConsumer == NULL ? 0 : pConsumer->consumerId, pRaw, terrstr()); taosMemoryFreeClear(pRow); - return NULL; } return pRow; } static int32_t mndConsumerActionInsert(SSdb *pSdb, SMqConsumerObj *pConsumer) { - mTrace("consumer:%" PRId64 ", perform insert action", pConsumer->consumerId); + mDebug("consumer:0x%" PRIx64 " cgroup:%s status:%d(%s) epoch:%d load from sdb, perform insert action", + pConsumer->consumerId, pConsumer->cgroup, pConsumer->status, mndConsumerStatusName(pConsumer->status), + pConsumer->epoch); pConsumer->subscribeTime = pConsumer->upTime; return 0; } static int32_t mndConsumerActionDelete(SSdb *pSdb, SMqConsumerObj *pConsumer) { - mTrace("consumer:%" PRId64 ", perform delete action", pConsumer->consumerId); + mDebug("consumer:0x%" PRIx64 " perform delete action, status:(%d)%s", pConsumer->consumerId, pConsumer->status, + mndConsumerStatusName(pConsumer->status)); tDeleteSMqConsumerObj(pConsumer); return 0; } -static int32_t mndConsumerActionUpdate(SSdb *pSdb, SMqConsumerObj *pOldConsumer, SMqConsumerObj *pNewConsumer) { - mTrace("consumer:%" PRId64 ", perform update action", pOldConsumer->consumerId); - - taosWLockLatch(&pOldConsumer->lock); +static void updateConsumerStatus(SMqConsumerObj *pConsumer) { + int32_t status = pConsumer->status; - if (pNewConsumer->updateType == CONSUMER_UPDATE__MODIFY) { - ASSERT(taosArrayGetSize(pOldConsumer->rebNewTopics) == 0); - ASSERT(taosArrayGetSize(pOldConsumer->rebRemovedTopics) == 0); + if (taosArrayGetSize(pConsumer->rebNewTopics) == 0 && taosArrayGetSize(pConsumer->rebRemovedTopics) == 0) { + if (status == MQ_CONSUMER_STATUS_REBALANCE) { + pConsumer->status = MQ_CONSUMER_STATUS__READY; + } else if (status == MQ_CONSUMER_STATUS__LOST) { + ASSERT(taosArrayGetSize(pConsumer->currentTopics) == 0); + pConsumer->status = MQ_CONSUMER_STATUS__LOST_REBD; + } + } +} - if (taosArrayGetSize(pNewConsumer->rebNewTopics) == 0 && taosArrayGetSize(pNewConsumer->rebRemovedTopics) == 0) { - pOldConsumer->status = MQ_CONSUMER_STATUS__READY; - } else { - SArray *tmp = pOldConsumer->rebNewTopics; - pOldConsumer->rebNewTopics = pNewConsumer->rebNewTopics; - pNewConsumer->rebNewTopics = tmp; +// remove from new topic +static void removeFromNewTopicList(SMqConsumerObj *pConsumer, const char *pTopic) { + int32_t size = taosArrayGetSize(pConsumer->rebNewTopics); + for (int32_t i = 0; i < size; i++) { + char *p = taosArrayGetP(pConsumer->rebNewTopics, i); + if (strcmp(pTopic, p) == 0) { + taosArrayRemove(pConsumer->rebNewTopics, i); + taosMemoryFree(p); + + mDebug("consumer:0x%" PRIx64 " remove new topic:%s in the topic list, remain newTopics:%d", pConsumer->consumerId, + pTopic, (int)taosArrayGetSize(pConsumer->rebNewTopics)); + break; + } + } +} - tmp = pOldConsumer->rebRemovedTopics; - pOldConsumer->rebRemovedTopics = pNewConsumer->rebRemovedTopics; - pNewConsumer->rebRemovedTopics = tmp; +// remove from removed topic +static void removeFromRemoveTopicList(SMqConsumerObj *pConsumer, const char *pTopic) { + int32_t size = taosArrayGetSize(pConsumer->rebRemovedTopics); + for (int32_t i = 0; i < size; i++) { + char *p = taosArrayGetP(pConsumer->rebRemovedTopics, i); + if (strcmp(pTopic, p) == 0) { + taosArrayRemove(pConsumer->rebRemovedTopics, i); + taosMemoryFree(p); + + mDebug("consumer:0x%" PRIx64 " remove topic:%s in the removed topic list, remain removedTopics:%d", + pConsumer->consumerId, pTopic, (int)taosArrayGetSize(pConsumer->rebRemovedTopics)); + break; + } + } +} - tmp = pOldConsumer->assignedTopics; - pOldConsumer->assignedTopics = pNewConsumer->assignedTopics; - pNewConsumer->assignedTopics = tmp; +static void removeFromCurrentTopicList(SMqConsumerObj *pConsumer, const char *pTopic) { + int32_t sz = taosArrayGetSize(pConsumer->currentTopics); + for (int32_t i = 0; i < sz; i++) { + char *topic = taosArrayGetP(pConsumer->currentTopics, i); + if (strcmp(pTopic, topic) == 0) { + taosArrayRemove(pConsumer->currentTopics, i); + taosMemoryFree(topic); + + mDebug("consumer:0x%" PRIx64 " remove topic:%s in the current topic list, remain currentTopics:%d", + pConsumer->consumerId, pTopic, (int)taosArrayGetSize(pConsumer->currentTopics)); + break; + } + } +} - pOldConsumer->subscribeTime = pNewConsumer->upTime; +static bool existInCurrentTopicList(const SMqConsumerObj* pConsumer, const char* pTopic) { + bool existing = false; + int32_t size = taosArrayGetSize(pConsumer->currentTopics); + for (int32_t i = 0; i < size; i++) { + char *topic = taosArrayGetP(pConsumer->currentTopics, i); - pOldConsumer->status = MQ_CONSUMER_STATUS__MODIFY; + if (strcmp(topic, pTopic) == 0) { + existing = true; + break; } - } else if (pNewConsumer->updateType == CONSUMER_UPDATE__LOST) { - ASSERT(taosArrayGetSize(pOldConsumer->rebNewTopics) == 0); - ASSERT(taosArrayGetSize(pOldConsumer->rebRemovedTopics) == 0); + } + return existing; +} + +static int32_t mndConsumerActionUpdate(SSdb *pSdb, SMqConsumerObj *pOldConsumer, SMqConsumerObj *pNewConsumer) { + mDebug("consumer:0x%" PRIx64 " perform update action, update type:%d, subscribe-time:%" PRId64 ", uptime:%" PRId64, + pOldConsumer->consumerId, pNewConsumer->updateType, pOldConsumer->subscribeTime, pOldConsumer->upTime); + + taosWLockLatch(&pOldConsumer->lock); + + if (pNewConsumer->updateType == CONSUMER_UPDATE__REBALANCE) { + TSWAP(pOldConsumer->rebNewTopics, pNewConsumer->rebNewTopics); + TSWAP(pOldConsumer->rebRemovedTopics, pNewConsumer->rebRemovedTopics); + TSWAP(pOldConsumer->assignedTopics, pNewConsumer->assignedTopics); + + pOldConsumer->subscribeTime = pNewConsumer->upTime; + pOldConsumer->status = MQ_CONSUMER_STATUS_REBALANCE; + } else if (pNewConsumer->updateType == CONSUMER_UPDATE__LOST) { int32_t sz = taosArrayGetSize(pOldConsumer->currentTopics); - /*pOldConsumer->rebRemovedTopics = taosArrayInit(sz, sizeof(void *));*/ for (int32_t i = 0; i < sz; i++) { - char *topic = strdup(taosArrayGetP(pOldConsumer->currentTopics, i)); + char *topic = taosStrdup(taosArrayGetP(pOldConsumer->currentTopics, i)); taosArrayPush(pOldConsumer->rebRemovedTopics, &topic); } pOldConsumer->rebalanceTime = pNewConsumer->upTime; + int32_t prevStatus = pOldConsumer->status; pOldConsumer->status = MQ_CONSUMER_STATUS__LOST; + mDebug("consumer:0x%" PRIx64 " state %s -> %s, reb-time:%" PRId64 ", reb-removed-topics:%d", + pOldConsumer->consumerId, mndConsumerStatusName(prevStatus), mndConsumerStatusName(pOldConsumer->status), + pOldConsumer->rebalanceTime, (int)taosArrayGetSize(pOldConsumer->rebRemovedTopics)); } else if (pNewConsumer->updateType == CONSUMER_UPDATE__RECOVER) { - ASSERT(taosArrayGetSize(pOldConsumer->currentTopics) == 0); - ASSERT(taosArrayGetSize(pOldConsumer->rebNewTopics) == 0); - int32_t sz = taosArrayGetSize(pOldConsumer->assignedTopics); for (int32_t i = 0; i < sz; i++) { - char *topic = strdup(taosArrayGetP(pOldConsumer->assignedTopics, i)); + char *topic = taosStrdup(taosArrayGetP(pOldConsumer->assignedTopics, i)); taosArrayPush(pOldConsumer->rebNewTopics, &topic); } pOldConsumer->rebalanceTime = pNewConsumer->upTime; - - pOldConsumer->status = MQ_CONSUMER_STATUS__MODIFY; + pOldConsumer->status = MQ_CONSUMER_STATUS_REBALANCE; } else if (pNewConsumer->updateType == CONSUMER_UPDATE__TOUCH) { atomic_add_fetch_32(&pOldConsumer->epoch, 1); pOldConsumer->rebalanceTime = pNewConsumer->upTime; } else if (pNewConsumer->updateType == CONSUMER_UPDATE__ADD) { - ASSERT(taosArrayGetSize(pNewConsumer->rebNewTopics) == 1); - ASSERT(taosArrayGetSize(pNewConsumer->rebRemovedTopics) == 0); - - char *addedTopic = strdup(taosArrayGetP(pNewConsumer->rebNewTopics, 0)); - // not exist in current topic - bool existing = false; -#if 1 - for (int32_t i = 0; i < taosArrayGetSize(pOldConsumer->currentTopics); i++) { - char *topic = taosArrayGetP(pOldConsumer->currentTopics, i); - if (strcmp(topic, addedTopic) == 0) { - existing = true; - } - } -#endif - - // remove from new topic - for (int32_t i = 0; i < taosArrayGetSize(pOldConsumer->rebNewTopics); i++) { - char *topic = taosArrayGetP(pOldConsumer->rebNewTopics, i); - if (strcmp(addedTopic, topic) == 0) { - taosArrayRemove(pOldConsumer->rebNewTopics, i); - taosMemoryFree(topic); - break; - } - } + char *pNewTopic = taosStrdup(taosArrayGetP(pNewConsumer->rebNewTopics, 0)); + + // check if exist in current topic + removeFromNewTopicList(pOldConsumer, pNewTopic); // add to current topic - if (!existing) { - taosArrayPush(pOldConsumer->currentTopics, &addedTopic); + bool existing = existInCurrentTopicList(pOldConsumer, pNewTopic); + if (existing) { + taosMemoryFree(pNewTopic); + } else { // added into current topic list + taosArrayPush(pOldConsumer->currentTopics, &pNewTopic); taosArraySort(pOldConsumer->currentTopics, taosArrayCompareString); } // set status - if (taosArrayGetSize(pOldConsumer->rebNewTopics) == 0 && taosArrayGetSize(pOldConsumer->rebRemovedTopics) == 0) { - if (pOldConsumer->status == MQ_CONSUMER_STATUS__MODIFY || - pOldConsumer->status == MQ_CONSUMER_STATUS__MODIFY_IN_REB) { - pOldConsumer->status = MQ_CONSUMER_STATUS__READY; - } else if (pOldConsumer->status == MQ_CONSUMER_STATUS__LOST_IN_REB || - pOldConsumer->status == MQ_CONSUMER_STATUS__LOST) { - pOldConsumer->status = MQ_CONSUMER_STATUS__LOST_REBD; - } - } else { - if (pOldConsumer->status == MQ_CONSUMER_STATUS__MODIFY || - pOldConsumer->status == MQ_CONSUMER_STATUS__MODIFY_IN_REB) { - pOldConsumer->status = MQ_CONSUMER_STATUS__MODIFY_IN_REB; - } else if (pOldConsumer->status == MQ_CONSUMER_STATUS__LOST || - pOldConsumer->status == MQ_CONSUMER_STATUS__LOST_IN_REB) { - pOldConsumer->status = MQ_CONSUMER_STATUS__LOST_IN_REB; - } - } + int32_t status = pOldConsumer->status; + updateConsumerStatus(pOldConsumer); + // the re-balance is triggered when the new consumer is launched. pOldConsumer->rebalanceTime = pNewConsumer->upTime; atomic_add_fetch_32(&pOldConsumer->epoch, 1); + mDebug("consumer:0x%" PRIx64 " state (%d)%s -> (%d)%s, new epoch:%d, reb-time:%" PRId64 + ", current topics:%d, newTopics:%d, removeTopics:%d", + pOldConsumer->consumerId, status, mndConsumerStatusName(status), pOldConsumer->status, + mndConsumerStatusName(pOldConsumer->status), pOldConsumer->epoch, pOldConsumer->rebalanceTime, + (int)taosArrayGetSize(pOldConsumer->currentTopics), (int)taosArrayGetSize(pOldConsumer->rebNewTopics), + (int)taosArrayGetSize(pOldConsumer->rebRemovedTopics)); + } else if (pNewConsumer->updateType == CONSUMER_UPDATE__REMOVE) { - ASSERT(taosArrayGetSize(pNewConsumer->rebNewTopics) == 0); - ASSERT(taosArrayGetSize(pNewConsumer->rebRemovedTopics) == 1); char *removedTopic = taosArrayGetP(pNewConsumer->rebRemovedTopics, 0); - // not exist in new topic -#if 1 - for (int32_t i = 0; i < taosArrayGetSize(pOldConsumer->rebNewTopics); i++) { - char *topic = taosArrayGetP(pOldConsumer->rebNewTopics, i); - ASSERT(strcmp(topic, removedTopic) != 0); - } -#endif - // remove from removed topic - for (int32_t i = 0; i < taosArrayGetSize(pOldConsumer->rebRemovedTopics); i++) { - char *topic = taosArrayGetP(pOldConsumer->rebRemovedTopics, i); - if (strcmp(removedTopic, topic) == 0) { - taosArrayRemove(pOldConsumer->rebRemovedTopics, i); - taosMemoryFree(topic); - break; - } - } + removeFromRemoveTopicList(pOldConsumer, removedTopic); // remove from current topic - int32_t i = 0; - int32_t sz = taosArrayGetSize(pOldConsumer->currentTopics); - for (i = 0; i < sz; i++) { - char *topic = taosArrayGetP(pOldConsumer->currentTopics, i); - if (strcmp(removedTopic, topic) == 0) { - taosArrayRemove(pOldConsumer->currentTopics, i); - taosMemoryFree(topic); - break; - } - } - // must find the topic - ASSERT(i < sz); + removeFromCurrentTopicList(pOldConsumer, removedTopic); // set status - if (taosArrayGetSize(pOldConsumer->rebNewTopics) == 0 && taosArrayGetSize(pOldConsumer->rebRemovedTopics) == 0) { - if (pOldConsumer->status == MQ_CONSUMER_STATUS__MODIFY || - pOldConsumer->status == MQ_CONSUMER_STATUS__MODIFY_IN_REB) { - pOldConsumer->status = MQ_CONSUMER_STATUS__READY; - } else if (pOldConsumer->status == MQ_CONSUMER_STATUS__LOST_IN_REB || - pOldConsumer->status == MQ_CONSUMER_STATUS__LOST) { - pOldConsumer->status = MQ_CONSUMER_STATUS__LOST_REBD; - } - } else { - if (pOldConsumer->status == MQ_CONSUMER_STATUS__MODIFY || - pOldConsumer->status == MQ_CONSUMER_STATUS__MODIFY_IN_REB) { - pOldConsumer->status = MQ_CONSUMER_STATUS__MODIFY_IN_REB; - } else if (pOldConsumer->status == MQ_CONSUMER_STATUS__LOST || - pOldConsumer->status == MQ_CONSUMER_STATUS__LOST_IN_REB) { - pOldConsumer->status = MQ_CONSUMER_STATUS__LOST_IN_REB; - } - } + int32_t status = pOldConsumer->status; + updateConsumerStatus(pOldConsumer); pOldConsumer->rebalanceTime = pNewConsumer->upTime; - atomic_add_fetch_32(&pOldConsumer->epoch, 1); + + mDebug("consumer:0x%" PRIx64 " state (%d)%s -> (%d)%s, new epoch:%d, reb-time:%" PRId64 + ", current topics:%d, newTopics:%d, removeTopics:%d", + pOldConsumer->consumerId, status, mndConsumerStatusName(status), pOldConsumer->status, + mndConsumerStatusName(pOldConsumer->status), pOldConsumer->epoch, pOldConsumer->rebalanceTime, + (int)taosArrayGetSize(pOldConsumer->currentTopics), (int)taosArrayGetSize(pOldConsumer->rebNewTopics), + (int)taosArrayGetSize(pOldConsumer->rebRemovedTopics)); } taosWUnLockLatch(&pOldConsumer->lock); @@ -971,16 +1072,18 @@ static int32_t mndRetrieveConsumer(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock * while (numOfRows < rowsCapacity) { pShow->pIter = sdbFetch(pSdb, SDB_CONSUMER, pShow->pIter, (void **)&pConsumer); - if (pShow->pIter == NULL) break; + if (pShow->pIter == NULL) { + break; + } + if (taosArrayGetSize(pConsumer->assignedTopics) == 0) { - mDebug("showing consumer %" PRId64 " no assigned topic, skip", pConsumer->consumerId); + mDebug("showing consumer:0x%" PRIx64 " no assigned topic, skip", pConsumer->consumerId); sdbRelease(pSdb, pConsumer); continue; } taosRLockLatch(&pConsumer->lock); - - mDebug("showing consumer %" PRId64, pConsumer->consumerId); + mDebug("showing consumer:0x%" PRIx64, pConsumer->consumerId); int32_t topicSz = taosArrayGetSize(pConsumer->assignedTopics); bool hasTopic = true; @@ -999,61 +1102,64 @@ static int32_t mndRetrieveConsumer(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock * // consumer id pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConsumer->consumerId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConsumer->consumerId, false); // consumer group char cgroup[TSDB_CGROUP_LEN + VARSTR_HEADER_SIZE] = {0}; - tstrncpy(varDataVal(cgroup), pConsumer->cgroup, TSDB_CGROUP_LEN); - varDataSetLen(cgroup, strlen(varDataVal(cgroup))); + STR_TO_VARSTR(cgroup, pConsumer->cgroup); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)cgroup, false); + colDataSetVal(pColInfo, numOfRows, (const char *)cgroup, false); // client id char clientId[256 + VARSTR_HEADER_SIZE] = {0}; - tstrncpy(varDataVal(clientId), pConsumer->clientId, 256); - varDataSetLen(clientId, strlen(varDataVal(clientId))); + STR_TO_VARSTR(clientId, pConsumer->clientId); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)clientId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)clientId, false); // status - char status[20 + VARSTR_HEADER_SIZE] = {0}; - tstrncpy(varDataVal(status), mndConsumerStatusName(pConsumer->status), 20); - varDataSetLen(status, strlen(varDataVal(status))); + char status[20 + VARSTR_HEADER_SIZE] = {0}; + const char *pStatusName = mndConsumerStatusName(pConsumer->status); + STR_TO_VARSTR(status, pStatusName); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)status, false); + colDataSetVal(pColInfo, numOfRows, (const char *)status, false); // one subscribed topic pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); if (hasTopic) { char topic[TSDB_TOPIC_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; const char *topicName = mndTopicGetShowName(taosArrayGetP(pConsumer->assignedTopics, i)); - tstrncpy(varDataVal(topic), topicName, TSDB_TOPIC_FNAME_LEN); - varDataSetLen(topic, strlen(varDataVal(topic))); - colDataAppend(pColInfo, numOfRows, (const char *)topic, false); + STR_TO_VARSTR(topic, topicName); + colDataSetVal(pColInfo, numOfRows, (const char *)topic, false); } else { - colDataAppend(pColInfo, numOfRows, NULL, true); + colDataSetVal(pColInfo, numOfRows, NULL, true); } // end point /*pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);*/ - /*colDataAppend(pColInfo, numOfRows, (const char *)&pConsumer->ep, true);*/ + /*colDataSetVal(pColInfo, numOfRows, (const char *)&pConsumer->ep, true);*/ // up time pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConsumer->upTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConsumer->upTime, false); // subscribe time pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConsumer->subscribeTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConsumer->subscribeTime, false); // rebalance time pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConsumer->rebalanceTime, pConsumer->rebalanceTime == 0); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConsumer->rebalanceTime, pConsumer->rebalanceTime == 0); numOfRows++; } + taosRUnLockLatch(&pConsumer->lock); sdbRelease(pSdb, pConsumer); + + pBlock->info.rows = numOfRows; } pShow->numOfRows += numOfRows; @@ -1071,10 +1177,8 @@ static const char *mndConsumerStatusName(int status) { return "ready"; case MQ_CONSUMER_STATUS__LOST: case MQ_CONSUMER_STATUS__LOST_REBD: - case MQ_CONSUMER_STATUS__LOST_IN_REB: return "lost"; - case MQ_CONSUMER_STATUS__MODIFY: - case MQ_CONSUMER_STATUS__MODIFY_IN_REB: + case MQ_CONSUMER_STATUS_REBALANCE: return "rebalancing"; default: return "unknown"; diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c index bdfda14a32772644a476b6ad6cbdc7d0e3989795..e93b06fdeafb273334bdd32c5588f8b43bd2d7dd 100644 --- a/source/dnode/mnode/impl/src/mndDb.c +++ b/source/dnode/mnode/impl/src/mndDb.c @@ -17,6 +17,7 @@ #include "mndDb.h" #include "mndCluster.h" #include "mndDnode.h" +#include "mndIndex.h" #include "mndPrivilege.h" #include "mndShow.h" #include "mndSma.h" @@ -30,9 +31,8 @@ #include "systable.h" #define DB_VER_NUMBER 1 -#define DB_RESERVE_SIZE 54 +#define DB_RESERVE_SIZE 46 -static SSdbRaw *mndDbActionEncode(SDbObj *pDb); static SSdbRow *mndDbActionDecode(SSdbRaw *pRaw); static int32_t mndDbActionInsert(SSdb *pSdb, SDbObj *pDb); static int32_t mndDbActionDelete(SSdb *pSdb, SDbObj *pDb); @@ -41,12 +41,15 @@ static int32_t mndProcessCreateDbReq(SRpcMsg *pReq); static int32_t mndProcessAlterDbReq(SRpcMsg *pReq); static int32_t mndProcessDropDbReq(SRpcMsg *pReq); static int32_t mndProcessUseDbReq(SRpcMsg *pReq); -static int32_t mndProcessCompactDbReq(SRpcMsg *pReq); static int32_t mndProcessTrimDbReq(SRpcMsg *pReq); static int32_t mndRetrieveDbs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rowsCapacity); static void mndCancelGetNextDb(SMnode *pMnode, void *pIter); static int32_t mndProcessGetDbCfgReq(SRpcMsg *pReq); +#ifndef TD_ENTERPRISE +int32_t mndProcessCompactDbReq(SRpcMsg *pReq) { return TSDB_CODE_OPS_NOT_SUPPORT; } +#endif + int32_t mndInitDb(SMnode *pMnode) { SSdbTable table = { .sdbType = SDB_DB, @@ -74,7 +77,7 @@ int32_t mndInitDb(SMnode *pMnode) { void mndCleanupDb(SMnode *pMnode) {} -static SSdbRaw *mndDbActionEncode(SDbObj *pDb) { +SSdbRaw *mndDbActionEncode(SDbObj *pDb) { terrno = TSDB_CODE_OUT_OF_MEMORY; int32_t size = sizeof(SDbObj) + pDb->cfg.numOfRetensions * sizeof(SRetention) + DB_RESERVE_SIZE; @@ -127,6 +130,7 @@ static SSdbRaw *mndDbActionEncode(SDbObj *pDb) { SDB_SET_INT16(pRaw, dataPos, pDb->cfg.hashPrefix, _OVER) SDB_SET_INT16(pRaw, dataPos, pDb->cfg.hashSuffix, _OVER) SDB_SET_INT32(pRaw, dataPos, pDb->cfg.tsdbPageSize, _OVER) + SDB_SET_INT64(pRaw, dataPos, pDb->compactStartTime, _OVER) SDB_SET_RESERVE(pRaw, dataPos, DB_RESERVE_SIZE, _OVER) SDB_SET_DATALEN(pRaw, dataPos, _OVER) @@ -216,6 +220,7 @@ static SSdbRow *mndDbActionDecode(SSdbRaw *pRaw) { SDB_GET_INT16(pRaw, dataPos, &pDb->cfg.hashPrefix, _OVER) SDB_GET_INT16(pRaw, dataPos, &pDb->cfg.hashSuffix, _OVER) SDB_GET_INT32(pRaw, dataPos, &pDb->cfg.tsdbPageSize, _OVER) + SDB_GET_INT64(pRaw, dataPos, &pDb->compactStartTime, _OVER) SDB_GET_RESERVE(pRaw, dataPos, DB_RESERVE_SIZE, _OVER) taosInitRWLatch(&pDb->lock); @@ -259,6 +264,7 @@ static int32_t mndDbActionUpdate(SSdb *pSdb, SDbObj *pOld, SDbObj *pNew) { pOld->updateTime = pNew->updateTime; pOld->cfgVersion = pNew->cfgVersion; pOld->vgVersion = pNew->vgVersion; + pOld->cfg.numOfVgroups = pNew->cfg.numOfVgroups; pOld->cfg.buffer = pNew->cfg.buffer; pOld->cfg.pageSize = pNew->cfg.pageSize; pOld->cfg.pages = pNew->cfg.pages; @@ -269,11 +275,16 @@ static int32_t mndDbActionUpdate(SSdb *pSdb, SDbObj *pOld, SDbObj *pNew) { pOld->cfg.daysToKeep2 = pNew->cfg.daysToKeep2; pOld->cfg.walFsyncPeriod = pNew->cfg.walFsyncPeriod; pOld->cfg.walLevel = pNew->cfg.walLevel; + pOld->cfg.walRetentionPeriod = pNew->cfg.walRetentionPeriod; + pOld->cfg.walRetentionSize = pNew->cfg.walRetentionSize; pOld->cfg.strict = pNew->cfg.strict; pOld->cfg.cacheLast = pNew->cfg.cacheLast; pOld->cfg.replications = pNew->cfg.replications; pOld->cfg.sstTrigger = pNew->cfg.sstTrigger; + pOld->cfg.minRows = pNew->cfg.minRows; + pOld->cfg.maxRows = pNew->cfg.maxRows; pOld->cfg.tsdbPageSize = pNew->cfg.tsdbPageSize; + pOld->compactStartTime = pNew->compactStartTime; taosWUnLockLatch(&pOld->lock); return 0; } @@ -362,6 +373,8 @@ static int32_t mndCheckDbCfg(SMnode *pMnode, SDbCfg *pCfg) { if (pCfg->sstTrigger < TSDB_MIN_STT_TRIGGER || pCfg->sstTrigger > TSDB_MAX_STT_TRIGGER) return -1; if (pCfg->hashPrefix < TSDB_MIN_HASH_PREFIX || pCfg->hashPrefix > TSDB_MAX_HASH_PREFIX) return -1; if (pCfg->hashSuffix < TSDB_MIN_HASH_SUFFIX || pCfg->hashSuffix > TSDB_MAX_HASH_SUFFIX) return -1; + if ((pCfg->hashSuffix * pCfg->hashPrefix) < 0) return -1; + if ((pCfg->hashPrefix + pCfg->hashSuffix) >= (TSDB_TABLE_NAME_LEN - 1)) return -1; if (pCfg->tsdbPageSize < TSDB_MIN_TSDB_PAGESIZE || pCfg->tsdbPageSize > TSDB_MAX_TSDB_PAGESIZE) return -1; if (taosArrayGetSize(pCfg->pRetensions) != pCfg->numOfRetensions) return -1; @@ -398,8 +411,6 @@ static void mndSetDefaultDbCfg(SDbCfg *pCfg) { if (pCfg->walRollPeriod < 0) pCfg->walRollPeriod = TSDB_REPS_DEF_DB_WAL_ROLL_PERIOD; if (pCfg->walSegmentSize < 0) pCfg->walSegmentSize = TSDB_DEFAULT_DB_WAL_SEGMENT_SIZE; if (pCfg->sstTrigger <= 0) pCfg->sstTrigger = TSDB_DEFAULT_SST_TRIGGER; - if (pCfg->hashPrefix < 0) pCfg->hashPrefix = TSDB_DEFAULT_HASH_PREFIX; - if (pCfg->hashSuffix < 0) pCfg->hashSuffix = TSDB_DEFAULT_HASH_SUFFIX; if (pCfg->tsdbPageSize <= 0) pCfg->tsdbPageSize = TSDB_DEFAULT_TSDB_PAGESIZE; } @@ -542,6 +553,10 @@ static int32_t mndCreateDb(SMnode *pMnode, SRpcMsg *pReq, SCreateDbReq *pCreate, int32_t dbLen = strlen(dbObj.name) + 1; mInfo("db:%s, hashPrefix adjust from %d to %d", dbObj.name, dbObj.cfg.hashPrefix, dbObj.cfg.hashPrefix + dbLen); dbObj.cfg.hashPrefix += dbLen; + } else if (dbObj.cfg.hashPrefix < 0) { + int32_t dbLen = strlen(dbObj.name) + 1; + mInfo("db:%s, hashPrefix adjust from %d to %d", dbObj.name, dbObj.cfg.hashPrefix, dbObj.cfg.hashPrefix - dbLen); + dbObj.cfg.hashPrefix -= dbLen; } SVgObj *pVgroups = NULL; @@ -609,13 +624,8 @@ static int32_t mndProcessCreateDbReq(SRpcMsg *pReq) { } } else { if (terrno == TSDB_CODE_MND_DB_IN_CREATING) { - if (mndSetRpcInfoForDbTrans(pMnode, pReq, MND_OPER_CREATE_DB, createReq.db) == 0) { - mInfo("db:%s, is creating and createdb response after trans finished", createReq.db); - code = TSDB_CODE_ACTION_IN_PROGRESS; - goto _OVER; - } else { - goto _OVER; - } + code = terrno; + goto _OVER; } else if (terrno == TSDB_CODE_MND_DB_IN_DROPPING) { goto _OVER; } else if (terrno == TSDB_CODE_MND_DB_NOT_EXIST) { @@ -718,6 +728,32 @@ static int32_t mndSetDbCfgFromAlterDbReq(SDbObj *pDb, SAlterDbReq *pAlter) { terrno = 0; } + if (pAlter->sstTrigger > 0 && pAlter->sstTrigger != pDb->cfg.sstTrigger) { + pDb->cfg.sstTrigger = pAlter->sstTrigger; + pDb->vgVersion++; + terrno = 0; + } + + if (pAlter->minRows > 0 && pAlter->minRows != pDb->cfg.minRows) { + pDb->cfg.minRows = pAlter->minRows; + pDb->vgVersion++; + terrno = 0; + } + + if (pAlter->walRetentionPeriod > TSDB_DB_MIN_WAL_RETENTION_PERIOD && + pAlter->walRetentionPeriod != pDb->cfg.walRetentionPeriod) { + pDb->cfg.walRetentionPeriod = pAlter->walRetentionPeriod; + pDb->vgVersion++; + terrno = 0; + } + + if (pAlter->walRetentionSize > TSDB_DB_MIN_WAL_RETENTION_SIZE && + pAlter->walRetentionSize != pDb->cfg.walRetentionSize) { + pDb->cfg.walRetentionSize = pAlter->walRetentionSize; + pDb->vgVersion++; + terrno = 0; + } + return terrno; } @@ -814,6 +850,18 @@ static int32_t mndProcessAlterDbReq(SRpcMsg *pReq) { goto _OVER; } + int32_t numOfTopics = 0; + if (mndGetNumOfTopics(pMnode, pDb->name, &numOfTopics) != 0) { + goto _OVER; + } + + if (numOfTopics != 0 && alterReq.walRetentionPeriod == 0) { + terrno = TSDB_CODE_MND_DB_RETENTION_PERIOD_ZERO; + mError("db:%s, not allowed to set WAL_RETENTION_PERIOD 0 when there are topics defined. numOfTopics:%d", pDb->name, + numOfTopics); + goto _OVER; + } + memcpy(&dbObj, pDb, sizeof(SDbObj)); if (dbObj.cfg.pRetensions != NULL) { dbObj.cfg.pRetensions = taosArrayDup(pDb->cfg.pRetensions, NULL); @@ -850,6 +898,42 @@ _OVER: return code; } +static void mndDumpDbCfgInfo(SDbCfgRsp *cfgRsp, SDbObj *pDb) { + strcpy(cfgRsp->db, pDb->name); + cfgRsp->dbId = pDb->uid; + cfgRsp->cfgVersion = pDb->cfgVersion; + cfgRsp->numOfVgroups = pDb->cfg.numOfVgroups; + cfgRsp->numOfStables = pDb->cfg.numOfStables; + cfgRsp->buffer = pDb->cfg.buffer; + cfgRsp->cacheSize = pDb->cfg.cacheLastSize; + cfgRsp->pageSize = pDb->cfg.pageSize; + cfgRsp->pages = pDb->cfg.pages; + cfgRsp->daysPerFile = pDb->cfg.daysPerFile; + cfgRsp->daysToKeep0 = pDb->cfg.daysToKeep0; + cfgRsp->daysToKeep1 = pDb->cfg.daysToKeep1; + cfgRsp->daysToKeep2 = pDb->cfg.daysToKeep2; + cfgRsp->minRows = pDb->cfg.minRows; + cfgRsp->maxRows = pDb->cfg.maxRows; + cfgRsp->walFsyncPeriod = pDb->cfg.walFsyncPeriod; + cfgRsp->hashPrefix = pDb->cfg.hashPrefix; + cfgRsp->hashSuffix = pDb->cfg.hashSuffix; + cfgRsp->walLevel = pDb->cfg.walLevel; + cfgRsp->precision = pDb->cfg.precision; + cfgRsp->compression = pDb->cfg.compression; + cfgRsp->replications = pDb->cfg.replications; + cfgRsp->strict = pDb->cfg.strict; + cfgRsp->cacheLast = pDb->cfg.cacheLast; + cfgRsp->tsdbPageSize = pDb->cfg.tsdbPageSize; + cfgRsp->walRetentionPeriod = pDb->cfg.walRetentionPeriod; + cfgRsp->walRollPeriod = pDb->cfg.walRollPeriod; + cfgRsp->walRetentionSize = pDb->cfg.walRetentionSize; + cfgRsp->walSegmentSize = pDb->cfg.walSegmentSize; + cfgRsp->numOfRetensions = pDb->cfg.numOfRetensions; + cfgRsp->pRetensions = pDb->cfg.pRetensions; + cfgRsp->schemaless = pDb->cfg.schemaless; + cfgRsp->sstTrigger = pDb->cfg.sstTrigger; +} + static int32_t mndProcessGetDbCfgReq(SRpcMsg *pReq) { SMnode *pMnode = pReq->info.node; int32_t code = -1; @@ -862,34 +946,15 @@ static int32_t mndProcessGetDbCfgReq(SRpcMsg *pReq) { goto _OVER; } - pDb = mndAcquireDb(pMnode, cfgReq.db); - if (pDb == NULL) { - goto _OVER; - } + if (strcasecmp(cfgReq.db, TSDB_INFORMATION_SCHEMA_DB) && strcasecmp(cfgReq.db, TSDB_PERFORMANCE_SCHEMA_DB)) { + pDb = mndAcquireDb(pMnode, cfgReq.db); + if (pDb == NULL) { + goto _OVER; + } - cfgRsp.numOfVgroups = pDb->cfg.numOfVgroups; - cfgRsp.numOfStables = pDb->cfg.numOfStables; - cfgRsp.buffer = pDb->cfg.buffer; - cfgRsp.cacheSize = pDb->cfg.cacheLastSize; - cfgRsp.pageSize = pDb->cfg.pageSize; - cfgRsp.pages = pDb->cfg.pages; - cfgRsp.daysPerFile = pDb->cfg.daysPerFile; - cfgRsp.daysToKeep0 = pDb->cfg.daysToKeep0; - cfgRsp.daysToKeep1 = pDb->cfg.daysToKeep1; - cfgRsp.daysToKeep2 = pDb->cfg.daysToKeep2; - cfgRsp.minRows = pDb->cfg.minRows; - cfgRsp.maxRows = pDb->cfg.maxRows; - cfgRsp.walFsyncPeriod = pDb->cfg.walFsyncPeriod; - cfgRsp.walLevel = pDb->cfg.walLevel; - cfgRsp.precision = pDb->cfg.precision; - cfgRsp.compression = pDb->cfg.compression; - cfgRsp.replications = pDb->cfg.replications; - cfgRsp.strict = pDb->cfg.strict; - cfgRsp.cacheLast = pDb->cfg.cacheLast; - cfgRsp.numOfRetensions = pDb->cfg.numOfRetensions; - cfgRsp.pRetensions = pDb->cfg.pRetensions; - cfgRsp.schemaless = pDb->cfg.schemaless; - cfgRsp.sstTrigger = pDb->cfg.sstTrigger; + mndDumpDbCfgInfo(&cfgRsp, pDb); + } + int32_t contLen = tSerializeSDbCfgRsp(NULL, 0, &cfgRsp); void *pRsp = rpcMallocCont(contLen); if (pRsp == NULL) { @@ -1035,13 +1100,23 @@ static int32_t mndBuildDropDbRsp(SDbObj *pDb, int32_t *pRspLen, void **ppRsp, bo static int32_t mndDropDb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb) { int32_t code = -1; + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq, "drop-db"); - if (pTrans == NULL) goto _OVER; + if (pTrans == NULL) { + goto _OVER; + } + + mInfo("trans:%d start to drop db:%s", pTrans->id, pDb->name); - mInfo("trans:%d, used to drop db:%s", pTrans->id, pDb->name); mndTransSetDbName(pTrans, pDb->name, NULL); - if (mndTrancCheckConflict(pMnode, pTrans) != 0) goto _OVER; - if (mndCheckTopicExist(pMnode, pDb) < 0) goto _OVER; + if (mndTrancCheckConflict(pMnode, pTrans) != 0) { + goto _OVER; + } + + if (mndTopicExistsForDb(pMnode, pDb)) { + terrno = TSDB_CODE_MND_TOPIC_MUST_BE_DELETED; + goto _OVER; + } if (mndSetDropDbRedoLogs(pMnode, pTrans, pDb) != 0) goto _OVER; if (mndSetDropDbCommitLogs(pMnode, pTrans, pDb) != 0) goto _OVER; @@ -1050,6 +1125,7 @@ static int32_t mndDropDb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb) { /*if (mndDropTopicByDB(pMnode, pTrans, pDb) != 0) goto _OVER;*/ if (mndDropStreamByDb(pMnode, pTrans, pDb) != 0) goto _OVER; if (mndDropSmasByDb(pMnode, pTrans, pDb) != 0) goto _OVER; + if (mndDropIdxsByDb(pMnode, pTrans, pDb) != 0) goto _OVER; if (mndSetDropDbRedoActions(pMnode, pTrans, pDb) != 0) goto _OVER; if (mndUserRemoveDb(pMnode, pTrans, pDb->name) != 0) goto _OVER; @@ -1092,10 +1168,12 @@ static int32_t mndProcessDropDbReq(SRpcMsg *pReq) { } code = mndDropDb(pMnode, pReq, pDb); - if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; + if (code == TSDB_CODE_SUCCESS) { + code = TSDB_CODE_ACTION_IN_PROGRESS; + } _OVER: - if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { + if (code != TSDB_CODE_SUCCESS && code != TSDB_CODE_ACTION_IN_PROGRESS) { mError("db:%s, failed to drop since %s", dropReq.db, terrstr()); } @@ -1231,14 +1309,9 @@ static int32_t mndProcessUseDbReq(SRpcMsg *pReq) { usedbRsp.errCode = terrno; if (terrno == TSDB_CODE_MND_DB_IN_CREATING) { - if (mndSetRpcInfoForDbTrans(pMnode, pReq, MND_OPER_CREATE_DB, usedbReq.db) == 0) { - mInfo("db:%s, is creating and usedb response after trans finished", usedbReq.db); - code = TSDB_CODE_ACTION_IN_PROGRESS; - goto _OVER; - } + code = terrno; + goto _OVER; } - - mError("db:%s, failed to process use db req since %s", usedbReq.db, terrstr()); } else { if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_USE_DB, pDb) != 0) { goto _OVER; @@ -1278,141 +1351,122 @@ _OVER: return code; } -int32_t mndValidateDbInfo(SMnode *pMnode, SDbVgVersion *pDbs, int32_t numOfDbs, void **ppRsp, int32_t *pRspLen) { - SUseDbBatchRsp batchUseRsp = {0}; - batchUseRsp.pArray = taosArrayInit(numOfDbs, sizeof(SUseDbRsp)); - if (batchUseRsp.pArray == NULL) { +int32_t mndValidateDbInfo(SMnode *pMnode, SDbCacheInfo *pDbs, int32_t numOfDbs, void **ppRsp, int32_t *pRspLen) { + SDbHbBatchRsp batchRsp = {0}; + batchRsp.pArray = taosArrayInit(numOfDbs, sizeof(SDbHbRsp)); + if (batchRsp.pArray == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } for (int32_t i = 0; i < numOfDbs; ++i) { - SDbVgVersion *pDbVgVersion = &pDbs[i]; - pDbVgVersion->dbId = be64toh(pDbVgVersion->dbId); - pDbVgVersion->vgVersion = htonl(pDbVgVersion->vgVersion); - pDbVgVersion->numOfTable = htonl(pDbVgVersion->numOfTable); - pDbVgVersion->stateTs = be64toh(pDbVgVersion->stateTs); + SDbCacheInfo *pDbCacheInfo = &pDbs[i]; + pDbCacheInfo->dbId = be64toh(pDbCacheInfo->dbId); + pDbCacheInfo->vgVersion = htonl(pDbCacheInfo->vgVersion); + pDbCacheInfo->cfgVersion = htonl(pDbCacheInfo->cfgVersion); + pDbCacheInfo->numOfTable = htonl(pDbCacheInfo->numOfTable); + pDbCacheInfo->stateTs = be64toh(pDbCacheInfo->stateTs); - SUseDbRsp usedbRsp = {0}; + SDbHbRsp rsp = {0}; - if ((0 == strcasecmp(pDbVgVersion->dbFName, TSDB_INFORMATION_SCHEMA_DB) || - (0 == strcasecmp(pDbVgVersion->dbFName, TSDB_PERFORMANCE_SCHEMA_DB)))) { - memcpy(usedbRsp.db, pDbVgVersion->dbFName, TSDB_DB_FNAME_LEN); + if ((0 == strcasecmp(pDbCacheInfo->dbFName, TSDB_INFORMATION_SCHEMA_DB) || + (0 == strcasecmp(pDbCacheInfo->dbFName, TSDB_PERFORMANCE_SCHEMA_DB)))) { int32_t vgVersion = mndGetGlobalVgroupVersion(pMnode); - if (pDbVgVersion->vgVersion < vgVersion) { - usedbRsp.pVgroupInfos = taosArrayInit(10, sizeof(SVgroupInfo)); - - mndBuildDBVgroupInfo(NULL, pMnode, usedbRsp.pVgroupInfos); - usedbRsp.vgVersion = vgVersion++; - } else { - usedbRsp.vgVersion = pDbVgVersion->vgVersion; + if (pDbCacheInfo->vgVersion >= vgVersion) { + continue; } - usedbRsp.vgNum = taosArrayGetSize(usedbRsp.pVgroupInfos); + + rsp.useDbRsp = taosMemoryCalloc(1, sizeof(SUseDbRsp)); + memcpy(rsp.useDbRsp->db, pDbCacheInfo->dbFName, TSDB_DB_FNAME_LEN); + rsp.useDbRsp->pVgroupInfos = taosArrayInit(10, sizeof(SVgroupInfo)); - taosArrayPush(batchUseRsp.pArray, &usedbRsp); + mndBuildDBVgroupInfo(NULL, pMnode, rsp.useDbRsp->pVgroupInfos); + rsp.useDbRsp->vgVersion = vgVersion++; + + rsp.useDbRsp->vgNum = taosArrayGetSize(rsp.useDbRsp->pVgroupInfos); + + taosArrayPush(batchRsp.pArray, &rsp); continue; } - SDbObj *pDb = mndAcquireDb(pMnode, pDbVgVersion->dbFName); + SDbObj *pDb = mndAcquireDb(pMnode, pDbCacheInfo->dbFName); if (pDb == NULL) { - mTrace("db:%s, no exist", pDbVgVersion->dbFName); - memcpy(usedbRsp.db, pDbVgVersion->dbFName, TSDB_DB_FNAME_LEN); - usedbRsp.uid = pDbVgVersion->dbId; - usedbRsp.vgVersion = -1; - taosArrayPush(batchUseRsp.pArray, &usedbRsp); + mTrace("db:%s, no exist", pDbCacheInfo->dbFName); + rsp.useDbRsp = taosMemoryCalloc(1, sizeof(SUseDbRsp)); + memcpy(rsp.useDbRsp->db, pDbCacheInfo->dbFName, TSDB_DB_FNAME_LEN); + rsp.useDbRsp->uid = pDbCacheInfo->dbId; + rsp.useDbRsp->vgVersion = -1; + taosArrayPush(batchRsp.pArray, &rsp); continue; } int32_t numOfTable = mndGetDBTableNum(pDb, pMnode); - if (pDbVgVersion->vgVersion >= pDb->vgVersion && numOfTable == pDbVgVersion->numOfTable && - pDbVgVersion->stateTs == pDb->stateTs) { - mTrace("db:%s, valid dbinfo, vgVersion:%d stateTs:%" PRId64 - " numOfTables:%d, not changed vgVersion:%d stateTs:%" PRId64 " numOfTables:%d", - pDbVgVersion->dbFName, pDbVgVersion->vgVersion, pDbVgVersion->stateTs, pDbVgVersion->numOfTable, - pDb->vgVersion, pDb->stateTs, numOfTable); + if (pDbCacheInfo->vgVersion >= pDb->vgVersion && + pDbCacheInfo->cfgVersion >= pDb->cfgVersion && + numOfTable == pDbCacheInfo->numOfTable && + pDbCacheInfo->stateTs == pDb->stateTs) { + mTrace("db:%s, valid dbinfo, vgVersion:%d cfgVersion:%d stateTs:%" PRId64 + " numOfTables:%d, not changed vgVersion:%d cfgVersion:%d stateTs:%" PRId64 " numOfTables:%d", + pDbCacheInfo->dbFName, pDbCacheInfo->vgVersion, pDbCacheInfo->cfgVersion, pDbCacheInfo->stateTs, pDbCacheInfo->numOfTable, + pDb->vgVersion, pDb->cfgVersion, pDb->stateTs, numOfTable); mndReleaseDb(pMnode, pDb); continue; } else { - mInfo("db:%s, valid dbinfo, vgVersion:%d stateTs:%" PRId64 - " numOfTables:%d, changed to vgVersion:%d stateTs:%" PRId64 " numOfTables:%d", - pDbVgVersion->dbFName, pDbVgVersion->vgVersion, pDbVgVersion->stateTs, pDbVgVersion->numOfTable, - pDb->vgVersion, pDb->stateTs, numOfTable); + mInfo("db:%s, valid dbinfo, vgVersion:%d cfgVersion:%d stateTs:%" PRId64 + " numOfTables:%d, changed to vgVersion:%d cfgVersion:%d stateTs:%" PRId64 " numOfTables:%d", + pDbCacheInfo->dbFName, pDbCacheInfo->vgVersion, pDbCacheInfo->cfgVersion, pDbCacheInfo->stateTs, pDbCacheInfo->numOfTable, + pDb->vgVersion, pDb->cfgVersion, pDb->stateTs, numOfTable); } - usedbRsp.pVgroupInfos = taosArrayInit(pDb->cfg.numOfVgroups, sizeof(SVgroupInfo)); - if (usedbRsp.pVgroupInfos == NULL) { - mndReleaseDb(pMnode, pDb); - mError("db:%s, failed to malloc usedb response", pDb->name); - continue; + if (pDbCacheInfo->cfgVersion < pDb->cfgVersion) { + rsp.cfgRsp = taosMemoryCalloc(1, sizeof(SDbCfgRsp)); + mndDumpDbCfgInfo(rsp.cfgRsp, pDb); } - mndBuildDBVgroupInfo(pDb, pMnode, usedbRsp.pVgroupInfos); - memcpy(usedbRsp.db, pDb->name, TSDB_DB_FNAME_LEN); - usedbRsp.uid = pDb->uid; - usedbRsp.vgVersion = pDb->vgVersion; - usedbRsp.stateTs = pDb->stateTs; - usedbRsp.vgNum = (int32_t)taosArrayGetSize(usedbRsp.pVgroupInfos); - usedbRsp.hashMethod = pDb->cfg.hashMethod; - usedbRsp.hashPrefix = pDb->cfg.hashPrefix; - usedbRsp.hashSuffix = pDb->cfg.hashSuffix; - - taosArrayPush(batchUseRsp.pArray, &usedbRsp); + if (pDbCacheInfo->vgVersion < pDb->vgVersion || + numOfTable != pDbCacheInfo->numOfTable || + pDbCacheInfo->stateTs != pDb->stateTs) { + rsp.useDbRsp = taosMemoryCalloc(1, sizeof(SUseDbRsp)); + rsp.useDbRsp->pVgroupInfos = taosArrayInit(pDb->cfg.numOfVgroups, sizeof(SVgroupInfo)); + if (rsp.useDbRsp->pVgroupInfos == NULL) { + mndReleaseDb(pMnode, pDb); + mError("db:%s, failed to malloc usedb response", pDb->name); + continue; + } + + mndBuildDBVgroupInfo(pDb, pMnode, rsp.useDbRsp->pVgroupInfos); + memcpy(rsp.useDbRsp->db, pDb->name, TSDB_DB_FNAME_LEN); + rsp.useDbRsp->uid = pDb->uid; + rsp.useDbRsp->vgVersion = pDb->vgVersion; + rsp.useDbRsp->stateTs = pDb->stateTs; + rsp.useDbRsp->vgNum = (int32_t)taosArrayGetSize(rsp.useDbRsp->pVgroupInfos); + rsp.useDbRsp->hashMethod = pDb->cfg.hashMethod; + rsp.useDbRsp->hashPrefix = pDb->cfg.hashPrefix; + rsp.useDbRsp->hashSuffix = pDb->cfg.hashSuffix; + } + + taosArrayPush(batchRsp.pArray, &rsp); mndReleaseDb(pMnode, pDb); } - int32_t rspLen = tSerializeSUseDbBatchRsp(NULL, 0, &batchUseRsp); + int32_t rspLen = tSerializeSDbHbBatchRsp(NULL, 0, &batchRsp); void *pRsp = taosMemoryMalloc(rspLen); if (pRsp == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; - tFreeSUseDbBatchRsp(&batchUseRsp); + tFreeSDbHbBatchRsp(&batchRsp); return -1; } - tSerializeSUseDbBatchRsp(pRsp, rspLen, &batchUseRsp); + tSerializeSDbHbBatchRsp(pRsp, rspLen, &batchRsp); *ppRsp = pRsp; *pRspLen = rspLen; - tFreeSUseDbBatchRsp(&batchUseRsp); + tFreeSDbHbBatchRsp(&batchRsp); return 0; } -static int32_t mndCompactDb(SMnode *pMnode, SDbObj *pDb) { return 0; } - -static int32_t mndProcessCompactDbReq(SRpcMsg *pReq) { - SMnode *pMnode = pReq->info.node; - int32_t code = -1; - SDbObj *pDb = NULL; - SCompactDbReq compactReq = {0}; - - if (tDeserializeSCompactDbReq(pReq->pCont, pReq->contLen, &compactReq) != 0) { - terrno = TSDB_CODE_INVALID_MSG; - goto _OVER; - } - - mInfo("db:%s, start to compact", compactReq.db); - - pDb = mndAcquireDb(pMnode, compactReq.db); - if (pDb == NULL) { - goto _OVER; - } - - if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_COMPACT_DB, pDb) != 0) { - goto _OVER; - } - - code = mndCompactDb(pMnode, pDb); - -_OVER: - if (code != 0) { - mError("db:%s, failed to process compact db req since %s", compactReq.db, terrstr()); - } - - mndReleaseDb(pMnode, pDb); - return code; -} - static int32_t mndTrimDb(SMnode *pMnode, SDbObj *pDb) { SSdb *pSdb = pMnode->pSdb; SVgObj *pVgroup = NULL; @@ -1641,46 +1695,46 @@ static void mndDumpDbInfoData(SMnode *pMnode, SSDataBlock *pBlock, SDbObj *pDb, for (int32_t i = 0; i < pShow->numOfColumns; ++i) { SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, i); if (i == 0) { - colDataAppend(pColInfo, rows, buf, false); + colDataSetVal(pColInfo, rows, buf, false); } else if (i == 1) { - colDataAppend(pColInfo, rows, (const char *)&pDb->createdTime, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->createdTime, false); } else if (i == 3) { - colDataAppend(pColInfo, rows, (const char *)&numOfTables, false); + colDataSetVal(pColInfo, rows, (const char *)&numOfTables, false); } else if (i == 14) { - colDataAppend(pColInfo, rows, precVstr, false); + colDataSetVal(pColInfo, rows, precVstr, false); } else if (i == 15) { - colDataAppend(pColInfo, rows, statusVstr, false); + colDataSetVal(pColInfo, rows, statusVstr, false); } else { - colDataAppendNULL(pColInfo, rows); + colDataSetNULL(pColInfo, rows); } } } else { SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, buf, false); + colDataSetVal(pColInfo, rows, buf, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->createdTime, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->createdTime, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.numOfVgroups, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.numOfVgroups, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&numOfTables, false); + colDataSetVal(pColInfo, rows, (const char *)&numOfTables, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.replications, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.replications, false); const char *strictStr = pDb->cfg.strict ? "on" : "off"; char strictVstr[24] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(strictVstr, strictStr, 24); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)strictVstr, false); + colDataSetVal(pColInfo, rows, (const char *)strictVstr, false); char durationVstr[128] = {0}; int32_t len = sprintf(&durationVstr[VARSTR_HEADER_SIZE], "%dm", pDb->cfg.daysPerFile); varDataSetLen(durationVstr, len); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)durationVstr, false); + colDataSetVal(pColInfo, rows, (const char *)durationVstr, false); char keepVstr[128] = {0}; if (pDb->cfg.daysToKeep0 > pDb->cfg.daysToKeep1 || pDb->cfg.daysToKeep0 > pDb->cfg.daysToKeep2) { @@ -1692,86 +1746,88 @@ static void mndDumpDbInfoData(SMnode *pMnode, SSDataBlock *pBlock, SDbObj *pDb, } varDataSetLen(keepVstr, len); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)keepVstr, false); + colDataSetVal(pColInfo, rows, (const char *)keepVstr, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.buffer, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.buffer, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.pageSize, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.pageSize, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.pages, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.pages, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.minRows, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.minRows, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.maxRows, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.maxRows, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.compression, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.compression, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)precVstr, false); + colDataSetVal(pColInfo, rows, (const char *)precVstr, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)statusVstr, false); + colDataSetVal(pColInfo, rows, (const char *)statusVstr, false); char *rentensionVstr = buildRetension(pDb->cfg.pRetensions); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); if (rentensionVstr == NULL) { - colDataAppendNULL(pColInfo, rows); + colDataSetNULL(pColInfo, rows); } else { - colDataAppend(pColInfo, rows, (const char *)rentensionVstr, false); + colDataSetVal(pColInfo, rows, (const char *)rentensionVstr, false); taosMemoryFree(rentensionVstr); } pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.numOfStables, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.numOfStables, false); const char *cacheModelStr = getCacheModelStr(pDb->cfg.cacheLast); char cacheModelVstr[24] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(cacheModelVstr, cacheModelStr, 24); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)cacheModelVstr, false); + colDataSetVal(pColInfo, rows, (const char *)cacheModelVstr, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.cacheLastSize, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.cacheLastSize, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walLevel, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.walLevel, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walFsyncPeriod, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.walFsyncPeriod, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walRetentionPeriod, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.walRetentionPeriod, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walRetentionSize, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.walRetentionSize, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walRollPeriod, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.walRollPeriod, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walSegmentSize, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.walSegmentSize, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.sstTrigger, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.sstTrigger, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); int16_t hashPrefix = pDb->cfg.hashPrefix; if (hashPrefix > 0) { hashPrefix = pDb->cfg.hashPrefix - strlen(pDb->name) - 1; + } else if (hashPrefix < 0) { + hashPrefix = pDb->cfg.hashPrefix + strlen(pDb->name) + 1; } - colDataAppend(pColInfo, rows, (const char *)&hashPrefix, false); + colDataSetVal(pColInfo, rows, (const char *)&hashPrefix, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.hashSuffix, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.hashSuffix, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.tsdbPageSize, false); + colDataSetVal(pColInfo, rows, (const char *)&pDb->cfg.tsdbPageSize, false); } taosMemoryFree(buf); diff --git a/source/dnode/mnode/impl/src/mndDef.c b/source/dnode/mnode/impl/src/mndDef.c index 75177f4158cf9bb386bf0e4d014eba17e6fead87..6dab0182362112d0ed5798f5829a1ad780a58768 100644 --- a/source/dnode/mnode/impl/src/mndDef.c +++ b/source/dnode/mnode/impl/src/mndDef.c @@ -70,7 +70,7 @@ int32_t tEncodeSStreamObj(SEncoder *pEncoder, const SStreamObj *pObj) { if (tEncodeI32(pEncoder, innerSz) < 0) return -1; for (int32_t j = 0; j < innerSz; j++) { SStreamTask *pTask = taosArrayGetP(pArray, j); - if (tEncodeSStreamTask(pEncoder, pTask) < 0) return -1; + if (tEncodeStreamTask(pEncoder, pTask) < 0) return -1; } } @@ -130,7 +130,7 @@ int32_t tDecodeSStreamObj(SDecoder *pDecoder, SStreamObj *pObj, int32_t sver) { taosArrayDestroy(pArray); return -1; } - if (tDecodeSStreamTask(pDecoder, pTask) < 0) { + if (tDecodeStreamTask(pDecoder, pTask) < 0) { taosMemoryFree(pTask); taosArrayDestroy(pArray); return -1; @@ -146,7 +146,9 @@ int32_t tDecodeSStreamObj(SDecoder *pDecoder, SStreamObj *pObj, int32_t sver) { // 3.0.20 if (sver >= 2) { if (tDecodeI64(pDecoder, &pObj->checkpointFreq) < 0) return -1; - if (tDecodeI8(pDecoder, &pObj->igCheckUpdate) < 0) return -1; + if (!tDecodeIsEnd(pDecoder)) { + if (tDecodeI8(pDecoder, &pObj->igCheckUpdate) < 0) return -1; + } } tEndDecode(pDecoder); return 0; @@ -156,7 +158,10 @@ void tFreeStreamObj(SStreamObj *pStream) { taosMemoryFree(pStream->sql); taosMemoryFree(pStream->ast); taosMemoryFree(pStream->physicalPlan); - if (pStream->outputSchema.nCols) taosMemoryFree(pStream->outputSchema.pSchema); + + if (pStream->outputSchema.nCols) { + taosMemoryFree(pStream->outputSchema.pSchema); + } int32_t sz = taosArrayGetSize(pStream->tasks); for (int32_t i = 0; i < sz; i++) { @@ -164,18 +169,25 @@ void tFreeStreamObj(SStreamObj *pStream) { int32_t taskSz = taosArrayGetSize(pLevel); for (int32_t j = 0; j < taskSz; j++) { SStreamTask *pTask = taosArrayGetP(pLevel, j); - tFreeSStreamTask(pTask); + tFreeStreamTask(pTask); } + taosArrayDestroy(pLevel); } + taosArrayDestroy(pStream->tasks); + + // tagSchema.pSchema + if (pStream->tagSchema.nCols > 0) { + taosMemoryFree(pStream->tagSchema.pSchema); + } } SMqVgEp *tCloneSMqVgEp(const SMqVgEp *pVgEp) { SMqVgEp *pVgEpNew = taosMemoryMalloc(sizeof(SMqVgEp)); if (pVgEpNew == NULL) return NULL; pVgEpNew->vgId = pVgEp->vgId; - pVgEpNew->qmsg = strdup(pVgEp->qmsg); + pVgEpNew->qmsg = taosStrdup(pVgEp->qmsg); pVgEpNew->epSet = pVgEp->epSet; return pVgEpNew; } @@ -213,7 +225,7 @@ SMqConsumerObj *tNewSMqConsumerObj(int64_t consumerId, char cgroup[TSDB_CGROUP_L memcpy(pConsumer->cgroup, cgroup, TSDB_CGROUP_LEN); pConsumer->epoch = 0; - pConsumer->status = MQ_CONSUMER_STATUS__MODIFY; + pConsumer->status = MQ_CONSUMER_STATUS_REBALANCE; pConsumer->hbStatus = 0; taosInitRWLatch(&pConsumer->lock); @@ -411,19 +423,21 @@ void *tDecodeSMqConsumerEp(const void *buf, SMqConsumerEp *pConsumerEp) { return (void *)buf; } -SMqSubscribeObj *tNewSubscribeObj(const char key[TSDB_SUBSCRIBE_KEY_LEN]) { - SMqSubscribeObj *pSubNew = taosMemoryCalloc(1, sizeof(SMqSubscribeObj)); - if (pSubNew == NULL) return NULL; - memcpy(pSubNew->key, key, TSDB_SUBSCRIBE_KEY_LEN); - taosInitRWLatch(&pSubNew->lock); - pSubNew->vgNum = 0; - pSubNew->consumerHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); - // TODO set hash free fp - /*taosHashSetFreeFp(pSubNew->consumerHash, tDeleteSMqConsumerEp);*/ +SMqSubscribeObj *tNewSubscribeObj(const char* key) { + SMqSubscribeObj *pSubObj = taosMemoryCalloc(1, sizeof(SMqSubscribeObj)); + if (pSubObj == NULL) { + return NULL; + } - pSubNew->unassignedVgs = taosArrayInit(0, sizeof(void *)); + memcpy(pSubObj->key, key, TSDB_SUBSCRIBE_KEY_LEN); + taosInitRWLatch(&pSubObj->lock); + pSubObj->vgNum = 0; + pSubObj->consumerHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); - return pSubNew; + // TODO set hash free fp + /*taosHashSetFreeFp(pSubObj->consumerHash, tDeleteSMqConsumerEp);*/ + pSubObj->unassignedVgs = taosArrayInit(0, POINTER_BYTES); + return pSubObj; } SMqSubscribeObj *tCloneSubscribeObj(const SMqSubscribeObj *pSub) { diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c index b8bafff104216edfb9e129ca3107438c94842842..1f58ae97a3c7034eda9ef8385e1e057cf0c510d2 100644 --- a/source/dnode/mnode/impl/src/mndDnode.c +++ b/source/dnode/mnode/impl/src/mndDnode.c @@ -25,6 +25,7 @@ #include "mndUser.h" #include "mndVgroup.h" #include "tmisce.h" +#include "mndCluster.h" #define TSDB_DNODE_VER_NUMBER 1 #define TSDB_DNODE_RESERVE_SIZE 64 @@ -180,7 +181,9 @@ static SSdbRow *mndDnodeActionDecode(SSdbRaw *pRaw) { SDB_GET_RESERVE(pRaw, dataPos, TSDB_DNODE_RESERVE_SIZE, _OVER) terrno = 0; - tmsgUpdateDnodeInfo(&pDnode->id, NULL, pDnode->fqdn, &pDnode->port); + if (tmsgUpdateDnodeInfo(&pDnode->id, NULL, pDnode->fqdn, &pDnode->port)) { + mInfo("dnode:%d, endpoint changed", pDnode->id); + } _OVER: if (terrno != 0) { @@ -189,7 +192,7 @@ _OVER: return NULL; } - mTrace("dnode:%d, decode from raw:%p, row:%p", pDnode->id, pRaw, pDnode); + mTrace("dnode:%d, decode from raw:%p, row:%p ep:%s:%u", pDnode->id, pRaw, pDnode, pDnode->fqdn, pDnode->port); return pRow; } @@ -364,6 +367,14 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) { goto _OVER; } + int64_t clusterid = mndGetClusterId(pMnode); + if (statusReq.clusterId != 0 && statusReq.clusterId != clusterid) { + code = TSDB_CODE_MND_DNODE_DIFF_CLUSTER; + mWarn("dnode:%d, %s, its clusterid:%" PRId64 " differ from current cluster:%" PRId64 ", code:0x%x", + statusReq.dnodeId, statusReq.dnodeEp, statusReq.clusterId, clusterid, code); + goto _OVER; + } + if (statusReq.dnodeId == 0) { pDnode = mndAcquireDnodeByEp(pMnode, statusReq.dnodeEp); if (pDnode == NULL) { @@ -410,6 +421,7 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) { if (pVgroup != NULL) { if (pVload->syncState == TAOS_SYNC_STATE_LEADER) { pVgroup->cacheUsage = pVload->cacheUsage; + pVgroup->numOfCachedTables = pVload->numOfCachedTables; pVgroup->numOfTables = pVload->numOfTables; pVgroup->numOfTimeSeries = pVload->numOfTimeSeries; pVgroup->totalStorage = pVload->totalStorage; @@ -438,7 +450,8 @@ static int32_t mndProcessStatusReq(SRpcMsg *pReq) { if (roleChanged) { SDbObj *pDb = mndAcquireDb(pMnode, pVgroup->dbName); if (pDb != NULL && pDb->stateTs != curMs) { - mInfo("db:%s, stateTs changed by status msg, old stateTs:%" PRId64 " new stateTs:%" PRId64, pDb->name, pDb->stateTs, curMs); + mInfo("db:%s, stateTs changed by status msg, old stateTs:%" PRId64 " new stateTs:%" PRId64, pDb->name, + pDb->stateTs, curMs); pDb->stateTs = curMs; } mndReleaseDb(pMnode, pDb); @@ -952,7 +965,7 @@ static int32_t mndProcessConfigDnodeReq(SRpcMsg *pReq) { tSerializeSDCfgDnodeReq(pBuf, bufLen, &dcfgReq); mInfo("dnode:%d, send config req to dnode, app:%p config:%s value:%s", cfgReq.dnodeId, pReq->info.ahandle, dcfgReq.config, dcfgReq.value); - SRpcMsg rpcMsg = {.msgType = TDMT_DND_CONFIG_DNODE, .pCont = pBuf, .contLen = bufLen}; + SRpcMsg rpcMsg = {.msgType = TDMT_DND_CONFIG_DNODE, .pCont = pBuf, .contLen = bufLen, .info = pReq->info}; tmsgSendReq(&epSet, &rpcMsg); code = 0; } @@ -1005,11 +1018,11 @@ static int32_t mndRetrieveConfigs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p STR_WITH_MAXSIZE_TO_VARSTR(buf, cfgOpts[i], TSDB_CONFIG_OPTION_LEN); SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)buf, false); + colDataSetVal(pColInfo, numOfRows, (const char *)buf, false); STR_WITH_MAXSIZE_TO_VARSTR(bufVal, cfgVals[i], TSDB_CONFIG_VALUE_LEN); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)bufVal, false); + colDataSetVal(pColInfo, numOfRows, (const char *)bufVal, false); numOfRows++; } @@ -1037,20 +1050,20 @@ static int32_t mndRetrieveDnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB cols = 0; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pDnode->id, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pDnode->id, false); char buf[tListLen(pDnode->ep) + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(buf, pDnode->ep, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, buf, false); + colDataSetVal(pColInfo, numOfRows, buf, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); int16_t id = mndGetVnodesNum(pMnode, pDnode->id); - colDataAppend(pColInfo, numOfRows, (const char *)&id, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&id, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pDnode->numOfSupportVnodes, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pDnode->numOfSupportVnodes, false); const char *status = "ready"; if (objStatus == SDB_STATUS_CREATING) status = "creating"; @@ -1067,16 +1080,19 @@ static int32_t mndRetrieveDnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB char b1[16] = {0}; STR_TO_VARSTR(b1, status); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, b1, false); + colDataSetVal(pColInfo, numOfRows, b1, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)&pDnode->createdTime, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pDnode->createdTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pDnode->rebootTime, false); char *b = taosMemoryCalloc(VARSTR_HEADER_SIZE + strlen(offlineReason[pDnode->offlineReason]) + 1, 1); STR_TO_VARSTR(b, online ? "" : offlineReason[pDnode->offlineReason]); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, b, false); + colDataSetVal(pColInfo, numOfRows, b, false); taosMemoryFreeClear(b); numOfRows++; diff --git a/source/dnode/mnode/impl/src/mndDump.c b/source/dnode/mnode/impl/src/mndDump.c index 7d0f5742f8bd69df9eb2d21836935dffb84875c0..44a7d49fff672e33af43bb892350ee0b5e02debd 100644 --- a/source/dnode/mnode/impl/src/mndDump.c +++ b/source/dnode/mnode/impl/src/mndDump.c @@ -629,7 +629,7 @@ void mndDumpSdb() { } taosWriteFile(pFile, pCont, contLen); taosWriteFile(pFile, "\n", 1); - taosFsyncFile(pFile); + UNUSED(taosFsyncFile(pFile)); taosCloseFile(&pFile); tjsonDelete(json); taosMemoryFree(pCont); diff --git a/source/dnode/mnode/impl/src/mndFunc.c b/source/dnode/mnode/impl/src/mndFunc.c index 244e6058d4a493a8d9f6b2cf794cca6a3db2cdad..51a231daf463c357eb494c87fad4b0187a9c43f6 100644 --- a/source/dnode/mnode/impl/src/mndFunc.c +++ b/source/dnode/mnode/impl/src/mndFunc.c @@ -21,7 +21,7 @@ #include "mndTrans.h" #include "mndUser.h" -#define SDB_FUNC_VER 1 +#define SDB_FUNC_VER 2 #define SDB_FUNC_RESERVE_SIZE 64 static SSdbRaw *mndFuncActionEncode(SFuncObj *pFunc); @@ -83,6 +83,7 @@ static SSdbRaw *mndFuncActionEncode(SFuncObj *pFunc) { SDB_SET_BINARY(pRaw, dataPos, pFunc->pComment, pFunc->commentSize, _OVER) } SDB_SET_BINARY(pRaw, dataPos, pFunc->pCode, pFunc->codeSize, _OVER) + SDB_SET_INT32(pRaw, dataPos, pFunc->funcVersion, _OVER) SDB_SET_RESERVE(pRaw, dataPos, SDB_FUNC_RESERVE_SIZE, _OVER) SDB_SET_DATALEN(pRaw, dataPos, _OVER); @@ -107,7 +108,7 @@ static SSdbRow *mndFuncActionDecode(SSdbRaw *pRaw) { int8_t sver = 0; if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER; - if (sver != SDB_FUNC_VER) { + if (sver != 1 && sver != 2) { terrno = TSDB_CODE_SDB_INVALID_DATA_VER; goto _OVER; } @@ -144,8 +145,15 @@ static SSdbRow *mndFuncActionDecode(SSdbRaw *pRaw) { goto _OVER; } SDB_GET_BINARY(pRaw, dataPos, pFunc->pCode, pFunc->codeSize, _OVER) + + if (sver >= 2) { + SDB_GET_INT32(pRaw, dataPos, &pFunc->funcVersion, _OVER) + } + SDB_GET_RESERVE(pRaw, dataPos, SDB_FUNC_RESERVE_SIZE, _OVER) + taosInitRWLatch(&pFunc->lock); + terrno = 0; _OVER: @@ -173,6 +181,44 @@ static int32_t mndFuncActionDelete(SSdb *pSdb, SFuncObj *pFunc) { static int32_t mndFuncActionUpdate(SSdb *pSdb, SFuncObj *pOld, SFuncObj *pNew) { mTrace("func:%s, perform update action, old row:%p new row:%p", pOld->name, pOld, pNew); + + taosWLockLatch(&pOld->lock); + + pOld->align = pNew->align; + pOld->bufSize = pNew->bufSize; + pOld->codeSize = pNew->codeSize; + pOld->commentSize = pNew->commentSize; + pOld->createdTime = pNew->createdTime; + pOld->funcType = pNew->funcType; + pOld->funcVersion = pNew->funcVersion; + pOld->outputLen = pNew->outputLen; + pOld->outputType = pNew->outputType; + + if (pOld->pComment != NULL) { + taosMemoryFree(pOld->pComment); + pOld->pComment = NULL; + } + if (pNew->commentSize > 0 && pNew->pComment != NULL) { + pOld->commentSize = pNew->commentSize; + pOld->pComment = taosMemoryMalloc(pOld->commentSize); + memcpy(pOld->pComment, pNew->pComment, pOld->commentSize); + } + + if (pOld->pCode != NULL) { + taosMemoryFree(pOld->pCode); + pOld->pCode = NULL; + } + if (pNew->codeSize > 0 && pNew->pCode != NULL) { + pOld->codeSize = pNew->codeSize; + pOld->pCode = taosMemoryMalloc(pOld->codeSize); + memcpy(pOld->pCode, pNew->pCode, pOld->codeSize); + } + + pOld->scriptType = pNew->scriptType; + pOld->signature = pNew->signature; + + taosWUnLockLatch(&pOld->lock); + return 0; } @@ -225,26 +271,47 @@ static int32_t mndCreateFunc(SMnode *pMnode, SRpcMsg *pReq, SCreateFuncReq *pCre pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "create-func"); if (pTrans == NULL) goto _OVER; - mInfo("trans:%d, used to create func:%s", pTrans->id, pCreate->name); - SSdbRaw *pRedoRaw = mndFuncActionEncode(&func); - if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) goto _OVER; - if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING) != 0) goto _OVER; + SFuncObj *oldFunc = mndAcquireFunc(pMnode, pCreate->name); + if (pCreate->orReplace == 1 && oldFunc != NULL) { + func.funcVersion = oldFunc->funcVersion + 1; + func.createdTime = oldFunc->createdTime; + + SSdbRaw *pRedoRaw = mndFuncActionEncode(oldFunc); + if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) goto _OVER; + if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY) != 0) goto _OVER; + + SSdbRaw *pUndoRaw = mndFuncActionEncode(oldFunc); + if (pUndoRaw == NULL || mndTransAppendUndolog(pTrans, pUndoRaw) != 0) goto _OVER; + if (sdbSetRawStatus(pUndoRaw, SDB_STATUS_READY) != 0) goto _OVER; - SSdbRaw *pUndoRaw = mndFuncActionEncode(&func); - if (pUndoRaw == NULL || mndTransAppendUndolog(pTrans, pUndoRaw) != 0) goto _OVER; - if (sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED) != 0) goto _OVER; + SSdbRaw *pCommitRaw = mndFuncActionEncode(&func); + if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) goto _OVER; + if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) goto _OVER; + } else { + SSdbRaw *pRedoRaw = mndFuncActionEncode(&func); + if (pRedoRaw == NULL || mndTransAppendRedolog(pTrans, pRedoRaw) != 0) goto _OVER; + if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING) != 0) goto _OVER; - SSdbRaw *pCommitRaw = mndFuncActionEncode(&func); - if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) goto _OVER; - if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) goto _OVER; + SSdbRaw *pUndoRaw = mndFuncActionEncode(&func); + if (pUndoRaw == NULL || mndTransAppendUndolog(pTrans, pUndoRaw) != 0) goto _OVER; + if (sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED) != 0) goto _OVER; + + SSdbRaw *pCommitRaw = mndFuncActionEncode(&func); + if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) goto _OVER; + if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) goto _OVER; + } if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; code = 0; _OVER: + if (oldFunc != NULL) { + mndReleaseFunc(pMnode, oldFunc); + } + taosMemoryFree(func.pCode); taosMemoryFree(func.pComment); mndTransDrop(pTrans); @@ -304,6 +371,9 @@ static int32_t mndProcessCreateFuncReq(SRpcMsg *pReq) { mInfo("func:%s, already exist, ignore exist is set", createReq.name); code = 0; goto _OVER; + } else if (createReq.orReplace) { + mInfo("func:%s, replace function is set", createReq.name); + code = 0; } else { terrno = TSDB_CODE_MND_FUNC_ALREADY_EXIST; goto _OVER; @@ -413,6 +483,12 @@ static int32_t mndProcessRetrieveFuncReq(SRpcMsg *pReq) { goto RETRIEVE_FUNC_OVER; } + retrieveRsp.pFuncExtraInfos = taosArrayInit(retrieveReq.numOfFuncs, sizeof(SFuncExtraInfo)); + if (retrieveRsp.pFuncExtraInfos == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto RETRIEVE_FUNC_OVER; + } + for (int32_t i = 0; i < retrieveReq.numOfFuncs; ++i) { char *funcName = taosArrayGet(retrieveReq.pFuncNames, i); @@ -451,6 +527,11 @@ static int32_t mndProcessRetrieveFuncReq(SRpcMsg *pReq) { } } taosArrayPush(retrieveRsp.pFuncInfos, &funcInfo); + SFuncExtraInfo extraInfo = {0}; + extraInfo.funcVersion = pFunc->funcVersion; + extraInfo.funcCreatedTime = pFunc->createdTime; + taosArrayPush(retrieveRsp.pFuncExtraInfos, &extraInfo); + mndReleaseFunc(pMnode, pFunc); } @@ -511,39 +592,65 @@ static int32_t mndRetrieveFuncs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl STR_WITH_MAXSIZE_TO_VARSTR(b1, pFunc->name, pShow->pMeta->pSchemas[cols].bytes); SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)b1, false); + colDataSetVal(pColInfo, numOfRows, (const char *)b1, false); if (pFunc->pComment) { char *b2 = taosMemoryCalloc(1, pShow->pMeta->pSchemas[cols].bytes); STR_WITH_MAXSIZE_TO_VARSTR(b2, pFunc->pComment, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)b2, false); + colDataSetVal(pColInfo, numOfRows, (const char *)b2, false); + taosMemoryFree(b2); } else { pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, NULL, true); + colDataSetVal(pColInfo, numOfRows, NULL, true); } int32_t isAgg = (pFunc->funcType == TSDB_FUNC_TYPE_AGGREGATE) ? 1 : 0; pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&isAgg, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&isAgg, false); char b3[TSDB_TYPE_STR_MAX_LEN + 1] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(b3, mnodeGenTypeStr(buf, TSDB_TYPE_STR_MAX_LEN, pFunc->outputType, pFunc->outputLen), pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)b3, false); + colDataSetVal(pColInfo, numOfRows, (const char *)b3, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)&pFunc->createdTime, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)&pFunc->codeSize, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)&pFunc->bufSize, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pFunc->createdTime, false); + char *language = ""; + if (pFunc->scriptType == TSDB_FUNC_SCRIPT_BIN_LIB) { + language = "C"; + } else if (pFunc->scriptType == TSDB_FUNC_SCRIPT_PYTHON) { + language = "Python"; + } + char varLang[TSDB_TYPE_STR_MAX_LEN + 1] = {0}; + varDataSetLen(varLang, strlen(language)); + strcpy(varDataVal(varLang), language); + colDataSetVal(pColInfo, numOfRows, (const char *)varLang, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pFunc->codeSize, false); + int32_t varCodeLen = (pFunc->codeSize + VARSTR_HEADER_SIZE) > TSDB_MAX_BINARY_LEN + ? TSDB_MAX_BINARY_LEN + : pFunc->codeSize + VARSTR_HEADER_SIZE; + char *b4 = taosMemoryMalloc(varCodeLen); + memcpy(varDataVal(b4), pFunc->pCode, varCodeLen - VARSTR_HEADER_SIZE); + varDataSetLen(b4, varCodeLen - VARSTR_HEADER_SIZE); + colDataSetVal(pColInfo, numOfRows, (const char *)b4, false); + taosMemoryFree(b4); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pFunc->bufSize, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pFunc->funcVersion, false); numOfRows++; sdbRelease(pSdb, pFunc); diff --git a/source/dnode/mnode/impl/src/mndGrant.c b/source/dnode/mnode/impl/src/mndGrant.c index 396de7eed33102d24979653cdd05d27507641c96..1b46e169618c2759bc509bf5c542d52c738731ac 100644 --- a/source/dnode/mnode/impl/src/mndGrant.c +++ b/source/dnode/mnode/impl/src/mndGrant.c @@ -29,85 +29,85 @@ static int32_t mndRetrieveGrant(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols); const char *src = "community"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "false"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); src = "unlimited"; STR_WITH_MAXSIZE_TO_VARSTR(tmp, src, 32); - colDataAppend(pColInfo, numOfRows, tmp, false); + colDataSetVal(pColInfo, numOfRows, tmp, false); numOfRows++; } @@ -129,7 +129,7 @@ void grantParseParameter() { mError("can't parsed parameter k"); } void grantReset(SMnode *pMnode, EGrantType grant, uint64_t value) {} void grantAdd(EGrantType grant, uint64_t value) {} void grantRestore(EGrantType grant, uint64_t value) {} -int32_t dmProcessGrantReq(SRpcMsg *pMsg) { return TSDB_CODE_SUCCESS; } +int32_t dmProcessGrantReq(void* pInfo, SRpcMsg *pMsg) { return TSDB_CODE_SUCCESS; } #endif diff --git a/source/dnode/mnode/impl/src/mndIndex.c b/source/dnode/mnode/impl/src/mndIndex.c new file mode 100644 index 0000000000000000000000000000000000000000..83172acf641608427a045623b835b9300901ad2c --- /dev/null +++ b/source/dnode/mnode/impl/src/mndIndex.c @@ -0,0 +1,863 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include "mndIndex.h" +#include "mndDb.h" +#include "mndDnode.h" +#include "mndIndexComm.h" +#include "mndInfoSchema.h" +#include "mndMnode.h" +#include "mndPrivilege.h" +#include "mndScheduler.h" +#include "mndShow.h" +#include "mndStb.h" +#include "mndStream.h" +#include "mndTrans.h" +#include "mndUser.h" +#include "mndVgroup.h" +#include "parser.h" +#include "tname.h" + +#define TSDB_IDX_VER_NUMBER 1 +#define TSDB_IDX_RESERVE_SIZE 64 + +static SSdbRaw *mndIdxActionEncode(SIdxObj *pSma); +static SSdbRow *mndIdxActionDecode(SSdbRaw *pRaw); +static int32_t mndIdxActionInsert(SSdb *pSdb, SIdxObj *pIdx); +static int32_t mndIdxActionDelete(SSdb *pSdb, SIdxObj *pIdx); +static int32_t mndIdxActionUpdate(SSdb *pSdb, SIdxObj *pOld, SIdxObj *pNew); +static int32_t mndProcessCreateIdxReq(SRpcMsg *pReq); +// static int32_t mndProcessDropIdxReq(SRpcMsg *pReq); +static int32_t mndProcessGetIdxReq(SRpcMsg *pReq); +static int32_t mndProcessGetTbIdxReq(SRpcMsg *pReq); +// static int32_t mndRetrieveIdx(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); +// static void mndCancelGetNextIdx(SMnode *pMnode, void *pIter); +static void mndDestroyIdxObj(SIdxObj *pIdxObj); + +static int32_t mndAddIndex(SMnode *pMnode, SRpcMsg *pReq, SCreateTagIndexReq *req, SDbObj *pDb, SStbObj *pStb); + +int32_t mndInitIdx(SMnode *pMnode) { + SSdbTable table = { + .sdbType = SDB_IDX, + .keyType = SDB_KEY_BINARY, + .encodeFp = (SdbEncodeFp)mndIdxActionEncode, + .decodeFp = (SdbDecodeFp)mndIdxActionDecode, + .insertFp = (SdbInsertFp)mndIdxActionInsert, + .updateFp = (SdbUpdateFp)mndIdxActionUpdate, + .deleteFp = (SdbDeleteFp)mndIdxActionDelete, + }; + + mndSetMsgHandle(pMnode, TDMT_MND_CREATE_INDEX, mndProcessCreateIdxReq); + // mndSetMsgHandle(pMnode, TDMT_MND_DROP_INDEX, mndProcessDropIdxReq); + + mndSetMsgHandle(pMnode, TDMT_VND_CREATE_INDEX_RSP, mndTransProcessRsp); + mndSetMsgHandle(pMnode, TDMT_VND_DROP_INDEX_RSP, mndTransProcessRsp); + + // mndSetMsgHandle(pMnode, TDMT_MND_CREATE_SMA, mndProcessCreateIdxReq); + // mndSetMsgHandle(pMnode, TDMT_MND_DROP_SMA, mndProcessDropIdxReq); + // mndSetMsgHandle(pMnode, TDMT_VND_CREATE_SMA_RSP, mndTransProcessRsp); + // mndSetMsgHandle(pMnode, TDMT_VND_DROP_SMA_RSP, mndTransProcessRsp); + // mndSetMsgHandle(pMnode, TDMT_MND_GET_INDEX, mndProcessGetIdxReq); + // mndSetMsgHandle(pMnode, TDMT_MND_GET_TABLE_INDEX, mndProcessGetTbIdxReq); + + // type same with sma + // mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_INDEX, mndRetrieveIdx); + // mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_INDEX, mndCancelGetNextIdx); + return sdbSetTable(pMnode->pSdb, table); +} + +static int32_t mndFindSuperTableTagId(const SStbObj *pStb, const char *tagName) { + for (int32_t tag = 0; tag < pStb->numOfTags; tag++) { + if (strcasecmp(pStb->pTags[tag].name, tagName) == 0) { + return tag; + } + } + + return -1; +} + +int mndSetCreateIdxRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb, SIdxObj *pIdx) { + SSdb *pSdb = pMnode->pSdb; + SVgObj *pVgroup = NULL; + void *pIter = NULL; + int32_t contLen; + + while (1) { + pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup); + if (pIter == NULL) break; + if (!mndVgroupInDb(pVgroup, pDb->uid)) { + sdbRelease(pSdb, pVgroup); + continue; + } + + void *pReq = mndBuildVCreateStbReq(pMnode, pVgroup, pStb, &contLen, NULL, 0); + if (pReq == NULL) { + sdbCancelFetch(pSdb, pIter); + sdbRelease(pSdb, pVgroup); + return -1; + } + STransAction action = {0}; + action.epSet = mndGetVgroupEpset(pMnode, pVgroup); + action.pCont = pReq; + action.contLen = contLen; + action.msgType = TDMT_VND_CREATE_INDEX; + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + sdbCancelFetch(pSdb, pIter); + sdbRelease(pSdb, pVgroup); + return -1; + } + sdbRelease(pSdb, pVgroup); + } + + return 0; +} +static void *mndBuildDropIdxReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pStbObj, SIdxObj *pIdx, int32_t *contLen) { + int32_t len = 0; + int32_t ret = 0; + + SDropIndexReq req = {0}; + memcpy(req.colName, pIdx->colName, sizeof(pIdx->colName)); + memcpy(req.stb, pIdx->stb, sizeof(pIdx->stb)); + req.dbUid = pIdx->dbUid; + req.stbUid = pIdx->stbUid; + + mInfo("idx: %s start to build drop index req", pIdx->name); + + len = tSerializeSDropIdxReq(NULL, 0, &req); + if (len < 0) { + goto _err; + } + + len += sizeof(SMsgHead); + SMsgHead *pHead = taosMemoryCalloc(1, len); + if (pHead == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _err; + } + + pHead->contLen = htonl(len); + pHead->vgId = htonl(pVgroup->vgId); + + void *pBuf = POINTER_SHIFT(pHead, sizeof(SMsgHead)); + tSerializeSDropIdxReq(pBuf, len - sizeof(SMsgHead), &req); + *contLen = len; + return pHead; +_err: + + return NULL; +} +int mndSetDropIdxRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb, SIdxObj *pIdx) { + SSdb *pSdb = pMnode->pSdb; + SVgObj *pVgroup = NULL; + void *pIter = NULL; + int32_t contLen; + + while (1) { + pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup); + if (pIter == NULL) break; + if (!mndVgroupInDb(pVgroup, pDb->uid)) { + sdbRelease(pSdb, pVgroup); + continue; + } + + int32_t len; + void *pReq = mndBuildDropIdxReq(pMnode, pVgroup, pStb, pIdx, &len); + if (pReq == NULL) { + sdbCancelFetch(pSdb, pIter); + sdbRelease(pSdb, pVgroup); + return -1; + } + STransAction action = {0}; + action.epSet = mndGetVgroupEpset(pMnode, pVgroup); + action.pCont = pReq; + action.contLen = len; + action.msgType = TDMT_VND_DROP_INDEX; + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + sdbCancelFetch(pSdb, pIter); + sdbRelease(pSdb, pVgroup); + return -1; + } + sdbRelease(pSdb, pVgroup); + } + + return 0; +} + +void mndCleanupIdx(SMnode *pMnode) { + // do nothing + return; +} + +static SSdbRaw *mndIdxActionEncode(SIdxObj *pIdx) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + + // int32_t size = + // sizeof(SSmaObj) + pSma->exprLen + pSma->tagsFilterLen + pSma->sqlLen + pSma->astLen + TSDB_IDX_RESERVE_SIZE; + int32_t size = sizeof(SIdxObj) + TSDB_IDX_RESERVE_SIZE; + + SSdbRaw *pRaw = sdbAllocRaw(SDB_IDX, TSDB_IDX_VER_NUMBER, size); + if (pRaw == NULL) goto _OVER; + + int32_t dataPos = 0; + SDB_SET_BINARY(pRaw, dataPos, pIdx->name, TSDB_TABLE_FNAME_LEN, _OVER) + SDB_SET_BINARY(pRaw, dataPos, pIdx->stb, TSDB_TABLE_FNAME_LEN, _OVER) + SDB_SET_BINARY(pRaw, dataPos, pIdx->db, TSDB_DB_FNAME_LEN, _OVER) + SDB_SET_BINARY(pRaw, dataPos, pIdx->dstTbName, TSDB_DB_FNAME_LEN, _OVER) + SDB_SET_BINARY(pRaw, dataPos, pIdx->colName, TSDB_COL_NAME_LEN, _OVER) + SDB_SET_INT64(pRaw, dataPos, pIdx->createdTime, _OVER) + SDB_SET_INT64(pRaw, dataPos, pIdx->uid, _OVER) + SDB_SET_INT64(pRaw, dataPos, pIdx->stbUid, _OVER) + SDB_SET_INT64(pRaw, dataPos, pIdx->dbUid, _OVER) + + SDB_SET_RESERVE(pRaw, dataPos, TSDB_IDX_RESERVE_SIZE, _OVER) + SDB_SET_DATALEN(pRaw, dataPos, _OVER) + + terrno = 0; + +_OVER: + if (terrno != 0) { + mError("idx:%s, failed to encode to raw:%p since %s", pIdx->name, pRaw, terrstr()); + sdbFreeRaw(pRaw); + return NULL; + } + + mTrace("idx:%s, encode to raw:%p, row:%p", pIdx->name, pRaw, pIdx); + return pRaw; +} + +static SSdbRow *mndIdxActionDecode(SSdbRaw *pRaw) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + SSdbRow *pRow = NULL; + SIdxObj *pIdx = NULL; + + int8_t sver = 0; + if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER; + + if (sver != TSDB_IDX_VER_NUMBER) { + terrno = TSDB_CODE_SDB_INVALID_DATA_VER; + goto _OVER; + } + + pRow = sdbAllocRow(sizeof(SIdxObj)); + if (pRow == NULL) goto _OVER; + + pIdx = sdbGetRowObj(pRow); + if (pIdx == NULL) goto _OVER; + + int32_t dataPos = 0; + + SDB_GET_BINARY(pRaw, dataPos, pIdx->name, TSDB_TABLE_FNAME_LEN, _OVER) + SDB_GET_BINARY(pRaw, dataPos, pIdx->stb, TSDB_TABLE_FNAME_LEN, _OVER) + SDB_GET_BINARY(pRaw, dataPos, pIdx->db, TSDB_DB_FNAME_LEN, _OVER) + SDB_GET_BINARY(pRaw, dataPos, pIdx->dstTbName, TSDB_DB_FNAME_LEN, _OVER) + SDB_GET_BINARY(pRaw, dataPos, pIdx->colName, TSDB_COL_NAME_LEN, _OVER) + SDB_GET_INT64(pRaw, dataPos, &pIdx->createdTime, _OVER) + SDB_GET_INT64(pRaw, dataPos, &pIdx->uid, _OVER) + SDB_GET_INT64(pRaw, dataPos, &pIdx->stbUid, _OVER) + SDB_GET_INT64(pRaw, dataPos, &pIdx->dbUid, _OVER) + + SDB_GET_RESERVE(pRaw, dataPos, TSDB_IDX_RESERVE_SIZE, _OVER) + + terrno = 0; + +_OVER: + if (terrno != 0) { + taosMemoryFree(pRow); + return NULL; + } + + mTrace("idx:%s, decode from raw:%p, row:%p", pIdx->name, pRaw, pIdx); + return pRow; +} + +static int32_t mndIdxActionInsert(SSdb *pSdb, SIdxObj *pIdx) { + mTrace("idx:%s, perform insert action, row:%p", pIdx->name, pIdx); + return 0; +} + +static int32_t mndIdxActionDelete(SSdb *pSdb, SIdxObj *pIdx) { + mTrace("idx:%s, perform delete action, row:%p", pIdx->name, pIdx); + return 0; +} + +static int32_t mndIdxActionUpdate(SSdb *pSdb, SIdxObj *pOld, SIdxObj *pNew) { + // lock no not + if (strncmp(pOld->colName, pNew->colName, TSDB_COL_NAME_LEN) != 0) { + memcpy(pOld->colName, pNew->colName, sizeof(pNew->colName)); + } + mTrace("idx:%s, perform update action, old row:%p new row:%p", pOld->name, pOld, pNew); + return 0; +} + +SIdxObj *mndAcquireIdx(SMnode *pMnode, char *idxName) { + SSdb *pSdb = pMnode->pSdb; + SIdxObj *pIdx = sdbAcquire(pSdb, SDB_IDX, idxName); + if (pIdx == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) { + terrno = TSDB_CODE_MND_TAG_INDEX_NOT_EXIST; + } + return pIdx; +} + +void mndReleaseIdx(SMnode *pMnode, SIdxObj *pIdx) { + SSdb *pSdb = pMnode->pSdb; + sdbRelease(pSdb, pIdx); +} + +SDbObj *mndAcquireDbByIdx(SMnode *pMnode, const char *idxName) { + SName name = {0}; + tNameFromString(&name, idxName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); + + char db[TSDB_TABLE_FNAME_LEN] = {0}; + tNameGetFullDbName(&name, db); + + return mndAcquireDb(pMnode, db); +} + +int32_t mndSetCreateIdxRedoLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx) { + SSdbRaw *pRedoRaw = mndIdxActionEncode(pIdx); + if (pRedoRaw == NULL) return -1; + if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) return -1; + if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING) != 0) return -1; + + return 0; +} + +int32_t mndSetCreateIdxCommitLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx) { + SSdbRaw *pCommitRaw = mndIdxActionEncode(pIdx); + if (pCommitRaw == NULL) return -1; + if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) return -1; + if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) return -1; + + return 0; +} + +int32_t mndSetAlterIdxRedoLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx) { + SSdbRaw *pRedoRaw = mndIdxActionEncode(pIdx); + if (pRedoRaw == NULL) return -1; + if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) { + sdbFreeRaw(pRedoRaw); + return -1; + } + if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY) != 0) return -1; + + return 0; +} + +int32_t mndSetAlterIdxCommitLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx) { + SSdbRaw *pCommitRaw = mndIdxActionEncode(pIdx); + if (pCommitRaw == NULL) return -1; + if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) { + sdbFreeRaw(pCommitRaw); + return -1; + } + if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) return -1; + + return 0; +} + +static int32_t mndSetCreateIdxVgroupRedoLogs(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup) { + SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup); + if (pVgRaw == NULL) return -1; + if (mndTransAppendRedolog(pTrans, pVgRaw) != 0) return -1; + if (sdbSetRawStatus(pVgRaw, SDB_STATUS_CREATING) != 0) return -1; + return 0; +} + +static int32_t mndSetCreateIdxVgroupCommitLogs(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup) { + SSdbRaw *pVgRaw = mndVgroupActionEncode(pVgroup); + if (pVgRaw == NULL) return -1; + if (mndTransAppendCommitlog(pTrans, pVgRaw) != 0) return -1; + if (sdbSetRawStatus(pVgRaw, SDB_STATUS_READY) != 0) return -1; + return 0; +} + +// static int32_t mndSetUpdateIdxStbCommitLogs(SMnode *pMnode, STrans *pTrans, SStbObj *pStb) { +// SStbObj stbObj = {0}; +// taosRLockLatch(&pStb->lock); +// memcpy(&stbObj, pStb, sizeof(SStbObj)); +// taosRUnLockLatch(&pStb->lock); +// stbObj.numOfColumns = 0; +// stbObj.pColumns = NULL; +// stbObj.numOfTags = 0; +// stbObj.pTags = NULL; +// stbObj.numOfFuncs = 0; +// stbObj.pFuncs = NULL; +// stbObj.updateTime = taosGetTimestampMs(); +// stbObj.lock = 0; +// stbObj.tagVer++; + +// SSdbRaw *pCommitRaw = mndStbActionEncode(&stbObj); +// if (pCommitRaw == NULL) return -1; +// if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) return -1; +// if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) return -1; +// +// return 0; +//} + +static void mndDestroyIdxObj(SIdxObj *pIdxObj) { + if (pIdxObj) { + // do nothing + } +} + +static int32_t mndProcessCreateIdxReq(SRpcMsg *pReq) { + SMnode *pMnode = pReq->info.node; + int32_t code = -1; + SStbObj *pStb = NULL; + SIdxObj *pIdx = NULL; + + SDbObj *pDb = NULL; + SCreateTagIndexReq createReq = {0}; + + if (tDeserializeSCreateTagIdxReq(pReq->pCont, pReq->contLen, &createReq) != 0) { + terrno = TSDB_CODE_INVALID_MSG; + goto _OVER; + } + + mInfo("idx:%s start to create", createReq.idxName); + // if (mndCheckCreateIdxReq(&createReq) != 0) { + // goto _OVER; + // } + + pDb = mndAcquireDbByStb(pMnode, createReq.stbName); + if (pDb == NULL) { + terrno = TSDB_CODE_MND_INVALID_DB; + goto _OVER; + } + + pStb = mndAcquireStb(pMnode, createReq.stbName); + if (pStb == NULL) { + mError("idx:%s, failed to create since stb:%s not exist", createReq.idxName, createReq.stbName); + goto _OVER; + } + SSIdx idx = {0}; + if (mndAcquireGlobalIdx(pMnode, createReq.idxName, SDB_IDX, &idx) == 0) { + pIdx = idx.pIdx; + } else { + goto _OVER; + } + if (pIdx != NULL) { + terrno = TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST; + goto _OVER; + } + + if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) { + goto _OVER; + } + + code = mndAddIndex(pMnode, pReq, &createReq, pDb, pStb); + if (terrno == TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST || terrno == TSDB_CODE_MND_TAG_NOT_EXIST) { + return terrno; + } else { + if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; + } + +_OVER: + if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { + mError("stb:%s, failed to create since %s", createReq.idxName, terrstr()); + } + + mndReleaseStb(pMnode, pStb); + mndReleaseIdx(pMnode, pIdx); + mndReleaseDb(pMnode, pDb); + + return code; +} + +int32_t mndSetDropIdxRedoLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx) { + SSdbRaw *pRedoRaw = mndIdxActionEncode(pIdx); + if (pRedoRaw == NULL) return -1; + if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) return -1; + if (sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING) != 0) return -1; + + return 0; +} + +int32_t mndSetDropIdxCommitLogs(SMnode *pMnode, STrans *pTrans, SIdxObj *pIdx) { + SSdbRaw *pCommitRaw = mndIdxActionEncode(pIdx); + if (pCommitRaw == NULL) return -1; + if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) return -1; + if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED) != 0) return -1; + + return 0; +} + +static int32_t mndProcessGetTbIdxReq(SRpcMsg *pReq) { + // + return 0; +} + +int32_t mndRetrieveTagIdx(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) { + SMnode *pMnode = pReq->info.node; + SSdb *pSdb = pMnode->pSdb; + int32_t numOfRows = 0; + SIdxObj *pIdx = NULL; + int32_t cols = 0; + + SDbObj *pDb = NULL; + if (strlen(pShow->db) > 0) { + pDb = mndAcquireDb(pMnode, pShow->db); + if (pDb == NULL) return 0; + } + SSmaAndTagIter *pIter = pShow->pIter; + int invalid = -1; + while (numOfRows < rows) { + pIter->pIdxIter = sdbFetch(pSdb, SDB_IDX, pIter->pIdxIter, (void **)&pIdx); + if (pIter->pIdxIter == NULL) break; + + if (NULL != pDb && pIdx->dbUid != pDb->uid) { + sdbRelease(pSdb, pIdx); + continue; + } + + cols = 0; + + SName idxName = {0}; + tNameFromString(&idxName, pIdx->name, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); + char n1[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + + STR_TO_VARSTR(n1, (char *)tNameGetTableName(&idxName)); + + char n2[TSDB_DB_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(n2, (char *)mndGetDbStr(pIdx->db)); + + SName stbName = {0}; + tNameFromString(&stbName, pIdx->stb, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); + char n3[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(n3, (char *)tNameGetTableName(&stbName)); + + SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)n1, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)n2, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)n3, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + + colDataAppend(pColInfo, numOfRows, (const char *)&invalid, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)&pIdx->createdTime, false); + + char col[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(col, (char *)pIdx->colName); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataAppend(pColInfo, numOfRows, (const char *)col, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + + char tag[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(tag, (char *)"tag_index"); + colDataAppend(pColInfo, numOfRows, (const char *)tag, false); + + numOfRows++; + sdbRelease(pSdb, pIdx); + } + + mndReleaseDb(pMnode, pDb); + pShow->numOfRows += numOfRows; + return numOfRows; +} + +// static void mndCancelGetNextIdx(SMnode *pMnode, void *pIter) { +// SSdb *pSdb = pMnode->pSdb; +// +// sdbCancelFetch(pSdb, pIter); +//} +static int32_t mndCheckIndexReq(SCreateTagIndexReq *pReq) { + // impl + return TSDB_CODE_SUCCESS; +} + +static int32_t mndSetUpdateIdxStbCommitLogs(SMnode *pMnode, STrans *pTrans, SStbObj *pOld, SStbObj *pNew, char *tagName, + int on) { + taosRLockLatch(&pOld->lock); + memcpy(pNew, pOld, sizeof(SStbObj)); + taosRUnLockLatch(&pOld->lock); + + pNew->pTags = NULL; + pNew->updateTime = taosGetTimestampMs(); + pNew->lock = 0; + + int32_t tag = mndFindSuperTableTagId(pOld, tagName); + if (tag < 0) { + terrno = TSDB_CODE_MND_TAG_NOT_EXIST; + return -1; + } + col_id_t colId = pOld->pTags[tag].colId; + if (mndCheckColAndTagModifiable(pMnode, pOld->name, pOld->uid, colId) != 0) { + return -1; + } + if (mndAllocStbSchemas(pOld, pNew) != 0) { + return -1; + } + SSchema *pTag = pNew->pTags + tag; + + if (on == 1) { + if (IS_IDX_ON(pTag)) { + terrno = TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST; + return -1; + } else { + SSCHMEA_SET_IDX_ON(pTag); + } + } else { + if (!IS_IDX_ON(pTag)) { + terrno = TSDB_CODE_MND_SMA_NOT_EXIST; + } else { + SSCHMEA_SET_IDX_OFF(pTag); + pTag->flags = 0; + } + } + pNew->tagVer++; + + SSdbRaw *pCommitRaw = mndStbActionEncode(pNew); + if (pCommitRaw == NULL) return -1; + if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) return -1; + if (sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY) != 0) return -1; + + return 0; +} +int32_t mndAddIndexImpl(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb, SIdxObj *pIdx) { + // impl later + int32_t code = -1; + SStbObj newStb = {0}; + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq, "create-stb-index"); + if (pTrans == NULL) goto _OVER; + + // mInfo("trans:%d, used to add index to stb:%s", pTrans->id, pStb->name); + mndTransSetDbName(pTrans, pDb->name, pStb->name); + if (mndTrancCheckConflict(pMnode, pTrans) != 0) goto _OVER; + + mndTransSetSerial(pTrans); + + if (mndSetCreateIdxRedoLogs(pMnode, pTrans, pIdx) != 0) goto _OVER; + if (mndSetCreateIdxCommitLogs(pMnode, pTrans, pIdx) != 0) goto _OVER; + + if (mndSetUpdateIdxStbCommitLogs(pMnode, pTrans, pStb, &newStb, pIdx->colName, 1) != 0) goto _OVER; + if (mndSetCreateIdxRedoActions(pMnode, pTrans, pDb, &newStb, pIdx) != 0) goto _OVER; + + if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; + + code = 0; + +_OVER: + // mndDestoryIdxObj(pIdx); + if (newStb.pTags != NULL) { + taosMemoryFree(newStb.pTags); + taosMemoryFree(newStb.pColumns); + } + mndTransDrop(pTrans); + return code; +} + +static int32_t mndAddIndex(SMnode *pMnode, SRpcMsg *pReq, SCreateTagIndexReq *req, SDbObj *pDb, SStbObj *pStb) { + int32_t code = -1; + SIdxObj idxObj = {0}; + memcpy(idxObj.name, req->idxName, TSDB_INDEX_FNAME_LEN); + memcpy(idxObj.stb, pStb->name, TSDB_TABLE_FNAME_LEN); + memcpy(idxObj.db, pDb->name, TSDB_DB_FNAME_LEN); + memcpy(idxObj.colName, req->colName, TSDB_COL_NAME_LEN); + + idxObj.createdTime = taosGetTimestampMs(); + idxObj.uid = mndGenerateUid(req->idxName, strlen(req->idxName)); + idxObj.stbUid = pStb->uid; + idxObj.dbUid = pStb->dbUid; + + int32_t tag = mndFindSuperTableTagId(pStb, req->colName); + if (tag < 0) { + terrno = TSDB_CODE_MND_TAG_NOT_EXIST; + return -1; + } else if (tag == 0) { + terrno = TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST; + return -1; + } + + col_id_t colId = pStb->pTags[tag].colId; + if (mndCheckColAndTagModifiable(pMnode, pStb->name, pStb->uid, colId) != 0) { + return -1; + } + + SSchema *pTag = pStb->pTags + tag; + if (IS_IDX_ON(pTag)) { + terrno = TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST; + return -1; + } + code = mndAddIndexImpl(pMnode, pReq, pDb, pStb, &idxObj); + + return code; +} + +static int32_t mndDropIdx(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SIdxObj *pIdx) { + int32_t code = -1; + SStbObj *pStb = NULL; + STrans *pTrans = NULL; + + SStbObj newObj = {0}; + + pStb = mndAcquireStb(pMnode, pIdx->stb); + if (pStb == NULL) goto _OVER; + + pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB, pReq, "drop-index"); + if (pTrans == NULL) goto _OVER; + + mInfo("trans:%d, used to drop idx:%s", pTrans->id, pIdx->name); + mndTransSetDbName(pTrans, pDb->name, NULL); + if (mndTrancCheckConflict(pMnode, pTrans) != 0) goto _OVER; + + mndTransSetSerial(pTrans); + if (mndSetDropIdxRedoLogs(pMnode, pTrans, pIdx) != 0) goto _OVER; + if (mndSetDropIdxCommitLogs(pMnode, pTrans, pIdx) != 0) goto _OVER; + + if (mndSetUpdateIdxStbCommitLogs(pMnode, pTrans, pStb, &newObj, pIdx->colName, 0) != 0) goto _OVER; + if (mndSetDropIdxRedoActions(pMnode, pTrans, pDb, &newObj, pIdx) != 0) goto _OVER; + if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; + + code = 0; + +_OVER: + taosMemoryFree(newObj.pTags); + taosMemoryFree(newObj.pColumns); + + mndTransDrop(pTrans); + mndReleaseStb(pMnode, pStb); + return code; +} +int32_t mndProcessDropTagIdxReq(SRpcMsg *pReq) { + SMnode *pMnode = pReq->info.node; + int32_t code = -1; + SDbObj *pDb = NULL; + SIdxObj *pIdx = NULL; + + SDropTagIndexReq req = {0}; + if (tDeserializeSDropTagIdxReq(pReq->pCont, pReq->contLen, &req) != 0) { + terrno = TSDB_CODE_INVALID_MSG; + goto _OVER; + } + mInfo("idx:%s, start to drop", req.name); + SSIdx idx = {0}; + if (mndAcquireGlobalIdx(pMnode, req.name, SDB_IDX, &idx) == 0) { + pIdx = idx.pIdx; + } else { + goto _OVER; + } + if (pIdx == NULL) { + if (req.igNotExists) { + mInfo("idx:%s, not exist, ignore not exist is set", req.name); + code = 0; + goto _OVER; + } else { + terrno = TSDB_CODE_MND_TAG_INDEX_NOT_EXIST; + goto _OVER; + } + } + + pDb = mndAcquireDbByIdx(pMnode, req.name); + if (pDb == NULL) { + terrno = TSDB_CODE_MND_DB_NOT_SELECTED; + goto _OVER; + } + + if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) { + goto _OVER; + } + + code = mndDropIdx(pMnode, pReq, pDb, pIdx); + if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; + +_OVER: + if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { + mError("idx:%s, failed to drop since %s", req.name, terrstr()); + } + mndReleaseIdx(pMnode, pIdx); + mndReleaseDb(pMnode, pDb); + return code; +} +static int32_t mndProcessGetIdxReq(SRpcMsg *pReq) { + // do nothing + return 0; +} + +int32_t mndDropIdxsByStb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb) { + SSdb *pSdb = pMnode->pSdb; + void *pIter = NULL; + + while (1) { + SIdxObj *pIdx = NULL; + pIter = sdbFetch(pSdb, SDB_IDX, pIter, (void **)&pIdx); + if (pIter == NULL) break; + + if (pIdx->stbUid == pStb->uid) { + if (mndSetDropIdxCommitLogs(pMnode, pTrans, pIdx) != 0) { + sdbRelease(pSdb, pIdx); + sdbCancelFetch(pSdb, pIdx); + return -1; + } + } + + sdbRelease(pSdb, pIdx); + } + + return 0; +} + +int32_t mndGetIdxsByTagName(SMnode *pMnode, SStbObj *pStb, char *tagName, SIdxObj *idx) { + SSdb *pSdb = pMnode->pSdb; + void *pIter = NULL; + + while (1) { + SIdxObj *pIdx = NULL; + pIter = sdbFetch(pSdb, SDB_IDX, pIter, (void **)&pIdx); + if (pIter == NULL) break; + + if (pIdx->stbUid == pStb->uid && strcasecmp(pIdx->colName, tagName) == 0) { + memcpy((char *)idx, (char *)pIdx, sizeof(SIdxObj)); + sdbRelease(pSdb, pIdx); + return 0; + } + + sdbRelease(pSdb, pIdx); + } + + return -1; +} +int32_t mndDropIdxsByDb(SMnode *pMnode, STrans *pTrans, SDbObj *pDb) { + SSdb *pSdb = pMnode->pSdb; + void *pIter = NULL; + + while (1) { + SIdxObj *pIdx = NULL; + pIter = sdbFetch(pSdb, SDB_IDX, pIter, (void **)&pIdx); + if (pIter == NULL) break; + + if (pIdx->dbUid == pDb->uid) { + if (mndSetDropIdxCommitLogs(pMnode, pTrans, pIdx) != 0) { + sdbRelease(pSdb, pIdx); + sdbCancelFetch(pSdb, pIdx); + return -1; + } + } + + sdbRelease(pSdb, pIdx); + } + + return 0; +} \ No newline at end of file diff --git a/source/dnode/mnode/impl/src/mndIndexCom.c b/source/dnode/mnode/impl/src/mndIndexCom.c new file mode 100644 index 0000000000000000000000000000000000000000..2858d7548eba72439a2ccfb5d6b75598bea0289b --- /dev/null +++ b/source/dnode/mnode/impl/src/mndIndexCom.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "mndIndex.h" +#include "mndIndexComm.h" +#include "mndSma.h" + +static void *mndGetIdx(SMnode *pMnode, char *name, int type) { + SSdb *pSdb = pMnode->pSdb; + void *pIdx = sdbAcquire(pSdb, type, name); + if (pIdx == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) { + terrno = 0; + } + return pIdx; +} + +int mndAcquireGlobalIdx(SMnode *pMnode, char *name, int type, SSIdx *idx) { + SSmaObj *pSma = mndGetIdx(pMnode, name, SDB_SMA); + SIdxObj *pIdx = mndGetIdx(pMnode, name, SDB_IDX); + + terrno = 0; + + if (pSma == NULL && pIdx == NULL) return 0; + + if (pSma != NULL) { + if (type == SDB_SMA) { + idx->type = SDB_SMA; + idx->pIdx = pSma; + } else { + mndReleaseSma(pMnode, pSma); + terrno = TSDB_CODE_MND_SMA_ALREADY_EXIST; + return -1; + } + } else { + if (type == SDB_IDX) { + idx->type = SDB_IDX; + idx->pIdx = pIdx; + } else { + mndReleaseIdx(pMnode, pIdx); + terrno = TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST; + return -1; + } + } + return 0; +} diff --git a/source/dnode/mnode/impl/src/mndMain.c b/source/dnode/mnode/impl/src/mndMain.c index 854535c82f72bf5ca4c3340355980ecad07ff7df..92ff550895e33ab7e2d7edef3555719704369ccc 100644 --- a/source/dnode/mnode/impl/src/mndMain.c +++ b/source/dnode/mnode/impl/src/mndMain.c @@ -21,6 +21,7 @@ #include "mndDnode.h" #include "mndFunc.h" #include "mndGrant.h" +#include "mndIndex.h" #include "mndInfoSchema.h" #include "mndMnode.h" #include "mndPerfSchema.h" @@ -123,15 +124,12 @@ static void mndCalMqRebalance(SMnode *pMnode) { int32_t contLen = 0; void *pReq = mndBuildTimerMsg(&contLen); if (pReq != NULL) { - SRpcMsg rpcMsg = { - .msgType = TDMT_MND_TMQ_TIMER, - .pCont = pReq, - .contLen = contLen, - }; + SRpcMsg rpcMsg = { .msgType = TDMT_MND_TMQ_TIMER, .pCont = pReq, .contLen = contLen }; tmsgPutToQueue(&pMnode->msgCb, READ_QUEUE, &rpcMsg); } } +#if 0 static void mndStreamCheckpointTick(SMnode *pMnode, int64_t sec) { int32_t contLen = 0; void *pReq = mndBuildCheckpointTickMsg(&contLen, sec); @@ -144,6 +142,7 @@ static void mndStreamCheckpointTick(SMnode *pMnode, int64_t sec) { tmsgPutToQueue(&pMnode->msgCb, READ_QUEUE, &rpcMsg); } } +#endif static void mndPullupTelem(SMnode *pMnode) { mTrace("pullup telem msg"); @@ -319,7 +318,7 @@ static void mndCleanupTimer(SMnode *pMnode) { } static int32_t mndCreateDir(SMnode *pMnode, const char *path) { - pMnode->path = strdup(path); + pMnode->path = taosStrdup(path); if (pMnode->path == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -341,8 +340,8 @@ static int32_t mndInitWal(SMnode *pMnode) { .fsyncPeriod = 0, .rollPeriod = -1, .segSize = -1, - .retentionPeriod = -1, - .retentionSize = -1, + .retentionPeriod = 0, + .retentionSize = 0, .level = TAOS_WAL_FSYNC, }; @@ -367,7 +366,6 @@ static int32_t mndInitSdb(SMnode *pMnode) { opt.path = pMnode->path; opt.pMnode = pMnode; opt.pWal = pMnode->pWal; - opt.sync = pMnode->syncMgmt.sync; pMnode->pSdb = sdbInit(&opt); if (pMnode->pSdb == NULL) { @@ -378,11 +376,13 @@ static int32_t mndInitSdb(SMnode *pMnode) { } static int32_t mndOpenSdb(SMnode *pMnode) { + int32_t code = 0; if (!pMnode->deploy) { - return sdbReadFile(pMnode->pSdb); - } else { - return 0; + code = sdbReadFile(pMnode->pSdb); } + + atomic_store_64(&pMnode->applied, pMnode->pSdb->commitIndex); + return code; } static void mndCleanupSdb(SMnode *pMnode) { @@ -425,6 +425,7 @@ static int32_t mndInitSteps(SMnode *pMnode) { if (mndAllocStep(pMnode, "mnode-vgroup", mndInitVgroup, mndCleanupVgroup) != 0) return -1; if (mndAllocStep(pMnode, "mnode-stb", mndInitStb, mndCleanupStb) != 0) return -1; if (mndAllocStep(pMnode, "mnode-sma", mndInitSma, mndCleanupSma) != 0) return -1; + if (mndAllocStep(pMnode, "mnode-idx", mndInitIdx, mndCleanupIdx) != 0) return -1; if (mndAllocStep(pMnode, "mnode-infos", mndInitInfos, mndCleanupInfos) != 0) return -1; if (mndAllocStep(pMnode, "mnode-perfs", mndInitPerfs, mndCleanupPerfs) != 0) return -1; if (mndAllocStep(pMnode, "mnode-db", mndInitDb, mndCleanupDb) != 0) return -1; @@ -548,16 +549,7 @@ void mndPreClose(SMnode *pMnode) { if (pMnode != NULL) { syncLeaderTransfer(pMnode->syncMgmt.sync); syncPreStop(pMnode->syncMgmt.sync); -#if 0 - while (syncSnapshotRecving(pMnode->syncMgmt.sync)) { - mInfo("vgId:1, snapshot is recving"); - taosMsleep(300); - } - while (syncSnapshotSending(pMnode->syncMgmt.sync)) { - mInfo("vgId:1, snapshot is sending"); - taosMsleep(300); - } -#endif + sdbWriteFile(pMnode->pSdb, 0); } } @@ -657,7 +649,7 @@ _OVER: pMsg->msgType == TDMT_MND_TRANS_TIMER || pMsg->msgType == TDMT_MND_TTL_TIMER || pMsg->msgType == TDMT_MND_UPTIME_TIMER) { mTrace("timer not process since mnode restored:%d stopped:%d, sync restored:%d role:%s ", pMnode->restored, - pMnode->stopped, state.restored, syncStr(state.restored)); + pMnode->stopped, state.restored, syncStr(state.state)); return -1; } @@ -669,9 +661,9 @@ _OVER: mGDebug( "msg:%p, type:%s failed to process since %s, mnode restored:%d stopped:%d, sync restored:%d " - "role:%s, redirect numOfEps:%d inUse:%d", + "role:%s, redirect numOfEps:%d inUse:%d, type:%s", pMsg, TMSG_INFO(pMsg->msgType), terrstr(), pMnode->restored, pMnode->stopped, state.restored, - syncStr(state.restored), epSet.numOfEps, epSet.inUse); + syncStr(state.restored), epSet.numOfEps, epSet.inUse, TMSG_INFO(pMsg->msgType)); if (epSet.numOfEps <= 0) return -1; @@ -712,7 +704,10 @@ int32_t mndProcessRpcMsg(SRpcMsg *pMsg) { } else if (code == 0) { mGTrace("msg:%p, successfully processed", pMsg); } else { - mGError("msg:%p, failed to process since %s, app:%p type:%s", pMsg, terrstr(), pMsg->info.ahandle, + if (code == -1) { + code = terrno; + } + mGError("msg:%p, failed to process since %s, app:%p type:%s", pMsg, tstrerror(code), pMsg->info.ahandle, TMSG_INFO(pMsg->msgType)); } @@ -762,6 +757,8 @@ int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pClusterInfo, SMonVgr pClusterInfo->connections_total = mndGetNumOfConnections(pMnode); pClusterInfo->dbs_total = sdbGetSize(pSdb, SDB_DB); pClusterInfo->stbs_total = sdbGetSize(pSdb, SDB_STB); + pClusterInfo->topics_toal = sdbGetSize(pSdb, SDB_TOPIC); + pClusterInfo->streams_total = sdbGetSize(pSdb, SDB_STREAM); void *pIter = NULL; while (1) { @@ -865,7 +862,7 @@ int32_t mndGetMonitorInfo(SMnode *pMnode, SMonClusterInfo *pClusterInfo, SMonVgr } // grant info - pGrantInfo->expire_time = (pMnode->grant.expireTimeMS - ms) / 86400000.0f; + pGrantInfo->expire_time = (pMnode->grant.expireTimeMS - ms) / 1000; pGrantInfo->timeseries_total = pMnode->grant.timeseriesAllowed; if (pMnode->grant.expireTimeMS == 0) { pGrantInfo->expire_time = INT32_MAX; diff --git a/source/dnode/mnode/impl/src/mndMnode.c b/source/dnode/mnode/impl/src/mndMnode.c index 7dcd287fb77c66bf1c0cfea6e7cd7fa793c5b61f..50fab447e3c7b8fb85ece7c025059358f6ab9e6f 100644 --- a/source/dnode/mnode/impl/src/mndMnode.c +++ b/source/dnode/mnode/impl/src/mndMnode.c @@ -608,13 +608,13 @@ static int32_t mndRetrieveMnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB cols = 0; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pObj->id, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->id, false); char b1[TSDB_EP_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(b1, pObj->pDnode->ep, TSDB_EP_LEN + VARSTR_HEADER_SIZE); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, b1, false); + colDataSetVal(pColInfo, numOfRows, b1, false); char role[20] = "offline"; if (pObj->id == pMnode->selfDnodeId) { @@ -630,7 +630,7 @@ static int32_t mndRetrieveMnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB char b2[12 + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(b2, role, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)b2, false); + colDataSetVal(pColInfo, numOfRows, (const char *)b2, false); const char *status = "ready"; if (objStatus == SDB_STATUS_CREATING) status = "creating"; @@ -639,10 +639,13 @@ static int32_t mndRetrieveMnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB char b3[9 + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(b3, status, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)b3, false); + colDataSetVal(pColInfo, numOfRows, (const char *)b3, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pObj->createdTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->createdTime, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->stateStartTime, false); numOfRows++; sdbRelease(pSdb, pObj); @@ -747,7 +750,7 @@ static void mndReloadSyncConfig(SMnode *pMnode) { pNode->clusterId = mndGetClusterId(pMnode); pNode->nodePort = pObj->pDnode->port; tstrncpy(pNode->nodeFqdn, pObj->pDnode->fqdn, TSDB_FQDN_LEN); - tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort); + (void)tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort); mInfo("vgId:1, ep:%s:%u dnode:%d", pNode->nodeFqdn, pNode->nodePort, pNode->nodeId); if (pObj->pDnode->id == pMnode->selfDnodeId) { cfg.myIndex = cfg.replicaNum; diff --git a/source/dnode/mnode/impl/src/mndPrivilege.c b/source/dnode/mnode/impl/src/mndPrivilege.c index ccb4140b83bc6bcc58eacdd52b357fc19ed3455b..de0374c6e89c506ce1b9cad966e2a4dd8905b7b7 100644 --- a/source/dnode/mnode/impl/src/mndPrivilege.c +++ b/source/dnode/mnode/impl/src/mndPrivilege.c @@ -35,6 +35,7 @@ int32_t mndCheckTopicPrivilegeByName(SMnode *pMnode, const char *user, EOperType int32_t mndSetUserAuthRsp(SMnode *pMnode, SUserObj *pUser, SGetUserAuthRsp *pRsp) { memcpy(pRsp->user, pUser->user, TSDB_USER_LEN); pRsp->superAuth = 1; + pRsp->enable = pUser->enable; pRsp->version = pUser->authVersion; return 0; } diff --git a/source/dnode/mnode/impl/src/mndProfile.c b/source/dnode/mnode/impl/src/mndProfile.c index ffc357b2e801f0bb51ad59dee2fc57a7cfad17bf..fbd845d448813dec1fa4366ac3ed1a2743eb1e5f 100644 --- a/source/dnode/mnode/impl/src/mndProfile.c +++ b/source/dnode/mnode/impl/src/mndProfile.c @@ -24,7 +24,7 @@ #include "mndStb.h" #include "mndUser.h" #include "tglobal.h" -#include "version.h" +#include "tversion.h" typedef struct { uint32_t id; @@ -221,11 +221,18 @@ static int32_t mndProcessConnectReq(SRpcMsg *pReq) { char ip[24] = {0}; const STraceId *trace = &pReq->info.traceId; - if (tDeserializeSConnectReq(pReq->pCont, pReq->contLen, &connReq) != 0) { - terrno = TSDB_CODE_INVALID_MSG; + if ((code = tDeserializeSConnectReq(pReq->pCont, pReq->contLen, &connReq)) != 0) { + terrno = (-1 == code ? TSDB_CODE_INVALID_MSG : code); + goto _OVER; + } + + if ((code = taosCheckVersionCompatibleFromStr(connReq.sVer, version, 3)) != 0) { + terrno = code; goto _OVER; } + code = -1; + taosIp2String(pReq->info.conn.clientIp, ip); if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_CONNECT) != 0) { mGError("user:%s, failed to login from %s since %s", pReq->info.conn.user, ip, terrstr()); @@ -249,10 +256,13 @@ static int32_t mndProcessConnectReq(SRpcMsg *pReq) { snprintf(db, TSDB_DB_FNAME_LEN, "%d%s%s", pUser->acctId, TS_PATH_DELIMITER, connReq.db); pDb = mndAcquireDb(pMnode, db); if (pDb == NULL) { - terrno = TSDB_CODE_MND_INVALID_DB; - mGError("user:%s, failed to login from %s while use db:%s since %s", pReq->info.conn.user, ip, connReq.db, - terrstr()); - goto _OVER; + if (0 != strcmp(connReq.db, TSDB_INFORMATION_SCHEMA_DB) && + (0 != strcmp(connReq.db, TSDB_PERFORMANCE_SCHEMA_DB))) { + terrno = TSDB_CODE_MND_INVALID_DB; + mGError("user:%s, failed to login from %s while use db:%s since %s", pReq->info.conn.user, ip, connReq.db, + terrstr()); + goto _OVER; + } } if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_READ_OR_WRITE_DB, pDb) != 0) { @@ -523,7 +533,7 @@ static int32_t mndProcessQueryHeartBeat(SMnode *pMnode, SRpcMsg *pMsg, SClientHb case HEARTBEAT_KEY_DBINFO: { void *rspMsg = NULL; int32_t rspLen = 0; - mndValidateDbInfo(pMnode, kv->value, kv->valueLen / sizeof(SDbVgVersion), &rspMsg, &rspLen); + mndValidateDbInfo(pMnode, kv->value, kv->valueLen / sizeof(SDbCacheInfo), &rspMsg, &rspLen); if (rspMsg && rspLen > 0) { SKv kv1 = {.key = HEARTBEAT_KEY_DBINFO, .valueLen = rspLen, .value = rspMsg}; taosArrayPush(hbRsp.info, &kv1); @@ -709,32 +719,32 @@ static int32_t mndRetrieveConns(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl cols = 0; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConn->id, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConn->id, false); char user[TSDB_USER_LEN + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(user, pConn->user); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)user, false); + colDataSetVal(pColInfo, numOfRows, (const char *)user, false); char app[TSDB_APP_NAME_LEN + VARSTR_HEADER_SIZE]; STR_TO_VARSTR(app, pConn->app); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)app, false); + colDataSetVal(pColInfo, numOfRows, (const char *)app, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConn->pid, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConn->pid, false); char endpoint[TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE] = {0}; sprintf(&endpoint[VARSTR_HEADER_SIZE], "%s:%d", taosIpStr(pConn->ip), pConn->port); varDataLen(endpoint) = strlen(&endpoint[VARSTR_HEADER_SIZE]); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)endpoint, false); + colDataSetVal(pColInfo, numOfRows, (const char *)endpoint, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConn->loginTimeMs, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConn->loginTimeMs, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConn->lastAccessTimeMs, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConn->lastAccessTimeMs, false); numOfRows++; } @@ -777,44 +787,44 @@ static int32_t mndRetrieveQueries(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p sprintf(&queryId[VARSTR_HEADER_SIZE], "%x:%" PRIx64, pConn->id, pQuery->reqRid); varDataLen(queryId) = strlen(&queryId[VARSTR_HEADER_SIZE]); SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)queryId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)queryId, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pQuery->queryId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pQuery->queryId, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConn->id, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConn->id, false); char app[TSDB_APP_NAME_LEN + VARSTR_HEADER_SIZE]; STR_TO_VARSTR(app, pConn->app); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)app, false); + colDataSetVal(pColInfo, numOfRows, (const char *)app, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConn->pid, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConn->pid, false); char user[TSDB_USER_LEN + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(user, pConn->user); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)user, false); + colDataSetVal(pColInfo, numOfRows, (const char *)user, false); char endpoint[TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE] = {0}; sprintf(&endpoint[VARSTR_HEADER_SIZE], "%s:%d", taosIpStr(pConn->ip), pConn->port); varDataLen(endpoint) = strlen(&endpoint[VARSTR_HEADER_SIZE]); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)endpoint, false); + colDataSetVal(pColInfo, numOfRows, (const char *)endpoint, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pQuery->stime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pQuery->stime, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pQuery->useconds, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pQuery->useconds, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pQuery->stableQuery, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pQuery->stableQuery, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pQuery->subPlanNum, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pQuery->subPlanNum, false); char subStatus[TSDB_SHOW_SUBQUERY_LEN + VARSTR_HEADER_SIZE] = {0}; int32_t strSize = sizeof(subStatus); @@ -828,12 +838,12 @@ static int32_t mndRetrieveQueries(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p } varDataLen(subStatus) = strlen(&subStatus[VARSTR_HEADER_SIZE]); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, subStatus, false); + colDataSetVal(pColInfo, numOfRows, subStatus, false); char sql[TSDB_SHOW_SQL_LEN + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(sql, pQuery->sql); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)sql, false); + colDataSetVal(pColInfo, numOfRows, (const char *)sql, false); numOfRows++; } @@ -867,55 +877,55 @@ static int32_t mndRetrieveApps(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlo cols = 0; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->appId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->appId, false); char ip[TSDB_IPv4ADDR_LEN + 6 + VARSTR_HEADER_SIZE] = {0}; sprintf(&ip[VARSTR_HEADER_SIZE], "%s", taosIpStr(pApp->ip)); varDataLen(ip) = strlen(&ip[VARSTR_HEADER_SIZE]); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)ip, false); + colDataSetVal(pColInfo, numOfRows, (const char *)ip, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->pid, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->pid, false); char name[TSDB_APP_NAME_LEN + 6 + VARSTR_HEADER_SIZE] = {0}; sprintf(&name[VARSTR_HEADER_SIZE], "%s", pApp->name); varDataLen(name) = strlen(&name[VARSTR_HEADER_SIZE]); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)name, false); + colDataSetVal(pColInfo, numOfRows, (const char *)name, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->startTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->startTime, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->summary.numOfInsertsReq, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->summary.numOfInsertsReq, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->summary.numOfInsertRows, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->summary.numOfInsertRows, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->summary.insertElapsedTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->summary.insertElapsedTime, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->summary.insertBytes, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->summary.insertBytes, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->summary.fetchBytes, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->summary.fetchBytes, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->summary.queryElapsedTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->summary.queryElapsedTime, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->summary.numOfSlowQueries, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->summary.numOfSlowQueries, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->summary.totalRequests, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->summary.totalRequests, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->summary.currentRequests, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->summary.currentRequests, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pApp->lastAccessTimeMs, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pApp->lastAccessTimeMs, false); numOfRows++; } diff --git a/source/dnode/mnode/impl/src/mndQnode.c b/source/dnode/mnode/impl/src/mndQnode.c index 28a5dee2dbd6a5590e057318efcd76fdd2a7f6a9..a8b2d5f4bbf5d053ea291357d2cd8a09883bb07b 100644 --- a/source/dnode/mnode/impl/src/mndQnode.c +++ b/source/dnode/mnode/impl/src/mndQnode.c @@ -507,15 +507,15 @@ static int32_t mndRetrieveQnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB cols = 0; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pObj->id, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->id, false); char ep[TSDB_EP_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(ep, pObj->pDnode->ep, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)ep, false); + colDataSetVal(pColInfo, numOfRows, (const char *)ep, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pObj->createdTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->createdTime, false); numOfRows++; sdbRelease(pSdb, pObj); diff --git a/source/dnode/mnode/impl/src/mndScheduler.c b/source/dnode/mnode/impl/src/mndScheduler.c index af1a29def08eae42072fffc889cd494a95dea239..734f624be0e19c942c10244f28263570d6ea4504 100644 --- a/source/dnode/mnode/impl/src/mndScheduler.c +++ b/source/dnode/mnode/impl/src/mndScheduler.c @@ -115,13 +115,11 @@ int32_t mndAddDispatcherToInnerTask(SMnode* pMnode, SStreamObj* pStream, SStream if (pStream->fixedSinkVgId == 0) { SDbObj* pDb = mndAcquireDb(pMnode, pStream->targetDb); - ASSERT(pDb); - if (pDb->cfg.numOfVgroups > 1) { + if (pDb != NULL && pDb->cfg.numOfVgroups > 1) { isShuffle = true; pTask->outputType = TASK_OUTPUT__SHUFFLE_DISPATCH; pTask->dispatchMsgType = TDMT_STREAM_TASK_DISPATCH; if (mndExtractDbInfo(pMnode, pDb, &pTask->shuffleDispatcher.dbInfo, NULL) < 0) { - ASSERT(0); return -1; } } @@ -140,9 +138,7 @@ int32_t mndAddDispatcherToInnerTask(SMnode* pMnode, SStreamObj* pStream, SStream for (int32_t j = 0; j < sinkLvSize; j++) { SStreamTask* pLastLevelTask = taosArrayGetP(sinkLv, j); if (pLastLevelTask->nodeId == pVgInfo->vgId) { - ASSERT(pVgInfo->vgId > 0); - pVgInfo->taskId = pLastLevelTask->taskId; - ASSERT(pVgInfo->taskId != 0); + pVgInfo->taskId = pLastLevelTask->id.taskId; break; } } @@ -152,9 +148,8 @@ int32_t mndAddDispatcherToInnerTask(SMnode* pMnode, SStreamObj* pStream, SStream pTask->dispatchMsgType = TDMT_STREAM_TASK_DISPATCH; SArray* pArray = taosArrayGetP(pStream->tasks, 0); // one sink only - ASSERT(taosArrayGetSize(pArray) == 1); SStreamTask* lastLevelTask = taosArrayGetP(pArray, 0); - pTask->fixedEpDispatcher.taskId = lastLevelTask->taskId; + pTask->fixedEpDispatcher.taskId = lastLevelTask->id.taskId; pTask->fixedEpDispatcher.nodeId = lastLevelTask->nodeId; pTask->fixedEpDispatcher.epSet = lastLevelTask->epSet; } @@ -170,7 +165,6 @@ int32_t mndAssignTaskToVg(SMnode* pMnode, SStreamTask* pTask, SSubplan* plan, co plan->execNode.epSet = pTask->epSet; if (qSubPlanToString(plan, &pTask->exec.qmsg, &msgLen) < 0) { - ASSERT(0); terrno = TSDB_CODE_QRY_INVALID_INPUT; return -1; } @@ -195,7 +189,6 @@ int32_t mndAssignTaskToSnode(SMnode* pMnode, SStreamTask* pTask, SSubplan* plan, plan->execNode.epSet = pTask->epSet; if (qSubPlanToString(plan, &pTask->exec.qmsg, &msgLen) < 0) { - ASSERT(0); terrno = TSDB_CODE_QRY_INVALID_INPUT; return -1; } @@ -222,8 +215,6 @@ int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, SStreamObj* pStream) { void* pIter = NULL; SArray* tasks = taosArrayGetP(pStream->tasks, 0); - ASSERT(taosArrayGetSize(pStream->tasks) == 1); - while (1) { SVgObj* pVgroup = NULL; pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void**)&pVgroup); @@ -233,7 +224,7 @@ int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, SStreamObj* pStream) { continue; } - SStreamTask* pTask = tNewSStreamTask(pStream->uid); + SStreamTask* pTask = tNewStreamTask(pStream->uid); if (pTask == NULL) { sdbRelease(pSdb, pVgroup); terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -257,7 +248,10 @@ int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, SStreamObj* pStream) { pTask->tbSink.stbUid = pStream->targetStbUid; memcpy(pTask->tbSink.stbFullName, pStream->targetSTbName, TSDB_TABLE_FNAME_LEN); pTask->tbSink.pSchemaWrapper = tCloneSSchemaWrapper(&pStream->outputSchema); - ASSERT(pTask->tbSink.pSchemaWrapper); + if (pTask->tbSink.pSchemaWrapper == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return -1; + } } sdbRelease(pSdb, pVgroup); } @@ -265,9 +259,8 @@ int32_t mndAddShuffleSinkTasksToStream(SMnode* pMnode, SStreamObj* pStream) { } int32_t mndAddFixedSinkTaskToStream(SMnode* pMnode, SStreamObj* pStream) { - ASSERT(pStream->fixedSinkVgId != 0); SArray* tasks = taosArrayGetP(pStream->tasks, 0); - SStreamTask* pTask = tNewSStreamTask(pStream->uid); + SStreamTask* pTask = tNewStreamTask(pStream->uid); if (pTask == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -275,8 +268,6 @@ int32_t mndAddFixedSinkTaskToStream(SMnode* pMnode, SStreamObj* pStream) { pTask->fillHistory = pStream->fillHistory; mndAddTaskToTaskSet(tasks, pTask); - ASSERT(pStream->fixedSinkVg.vgId == pStream->fixedSinkVgId); - pTask->nodeId = pStream->fixedSinkVgId; #if 0 SVgObj* pVgroup = mndAcquireVgroup(pMnode, pStream->fixedSinkVgId); @@ -311,13 +302,16 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) { return -1; } int32_t planTotLevel = LIST_LENGTH(pPlan->pSubplans); - ASSERT(planTotLevel <= 2); + pStream->tasks = taosArrayInit(planTotLevel, sizeof(void*)); bool hasExtraSink = false; bool externalTargetDB = strcmp(pStream->sourceDb, pStream->targetDb) != 0; SDbObj* pDbObj = mndAcquireDb(pMnode, pStream->targetDb); - ASSERT(pDbObj != NULL); + if (pDbObj == NULL) { + terrno = TSDB_CODE_QRY_INVALID_INPUT; + return -1; + } bool multiTarget = pDbObj->cfg.numOfVgroups > 1; sdbRelease(pSdb, pDbObj); @@ -351,14 +345,18 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) { SNodeListNode* inner = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 0); SSubplan* plan = (SSubplan*)nodesListGetNode(inner->pNodeList, 0); - ASSERT(plan->subplanType == SUBPLAN_TYPE_MERGE); + if (plan->subplanType != SUBPLAN_TYPE_MERGE) { + terrno = TSDB_CODE_QRY_INVALID_INPUT; + return -1; + } - pInnerTask = tNewSStreamTask(pStream->uid); + pInnerTask = tNewStreamTask(pStream->uid); if (pInnerTask == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; qDestroyQueryPlan(pPlan); return -1; } + pInnerTask->fillHistory = pStream->fillHistory; mndAddTaskToTaskSet(taskInnerLevel, pInnerTask); @@ -409,7 +407,10 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) { SNodeListNode* inner = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 1); SSubplan* plan = (SSubplan*)nodesListGetNode(inner->pNodeList, 0); - ASSERT(plan->subplanType == SUBPLAN_TYPE_SCAN); + if (plan->subplanType != SUBPLAN_TYPE_SCAN) { + terrno = TSDB_CODE_QRY_INVALID_INPUT; + return -1; + } void* pIter = NULL; while (1) { @@ -421,7 +422,7 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) { continue; } - SStreamTask* pTask = tNewSStreamTask(pStream->uid); + SStreamTask* pTask = tNewStreamTask(pStream->uid); if (pTask == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; sdbRelease(pSdb, pVgroup); @@ -440,7 +441,7 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) { pTask->dispatchMsgType = TDMT_STREAM_TASK_DISPATCH; pTask->outputType = TASK_OUTPUT__FIXED_DISPATCH; - pTask->fixedEpDispatcher.taskId = pInnerTask->taskId; + pTask->fixedEpDispatcher.taskId = pInnerTask->id.taskId; pTask->fixedEpDispatcher.nodeId = pInnerTask->nodeId; pTask->fixedEpDispatcher.epSet = pInnerTask->epSet; @@ -460,7 +461,7 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) { pEpInfo->childId = pTask->selfChildId; pEpInfo->epSet = pTask->epSet; pEpInfo->nodeId = pTask->nodeId; - pEpInfo->taskId = pTask->taskId; + pEpInfo->taskId = pTask->id.taskId; taosArrayPush(pInnerTask->childEpInfo, &pEpInfo); sdbRelease(pSdb, pVgroup); } @@ -471,9 +472,15 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) { taosArrayPush(pStream->tasks, &taskOneLevel); SNodeListNode* inner = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 0); - ASSERT(LIST_LENGTH(inner->pNodeList) == 1); + if (LIST_LENGTH(inner->pNodeList) != 1) { + terrno = TSDB_CODE_QRY_INVALID_INPUT; + return -1; + } SSubplan* plan = (SSubplan*)nodesListGetNode(inner->pNodeList, 0); - ASSERT(plan->subplanType == SUBPLAN_TYPE_SCAN); + if (plan->subplanType != SUBPLAN_TYPE_SCAN) { + terrno = TSDB_CODE_QRY_INVALID_INPUT; + return -1; + } void* pIter = NULL; while (1) { @@ -485,7 +492,7 @@ int32_t mndScheduleStream(SMnode* pMnode, SStreamObj* pStream) { continue; } - SStreamTask* pTask = tNewSStreamTask(pStream->uid); + SStreamTask* pTask = tNewStreamTask(pStream->uid); if (pTask == NULL) { sdbRelease(pSdb, pVgroup); qDestroyQueryPlan(pPlan); @@ -523,7 +530,7 @@ int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscrib SSdb* pSdb = pMnode->pSdb; SVgObj* pVgroup = NULL; SQueryPlan* pPlan = NULL; - SSubplan* plan = NULL; + SSubplan* pSubplan = NULL; if (pTopic->subType == TOPIC_SUB_TYPE__COLUMN) { pPlan = qStringToQueryPlan(pTopic->physicalPlan); @@ -539,24 +546,25 @@ int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscrib return -1; } - SNodeListNode* inner = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 0); + SNodeListNode* pNodeListNode = (SNodeListNode*)nodesListGetNode(pPlan->pSubplans, 0); - int32_t opNum = LIST_LENGTH(inner->pNodeList); + int32_t opNum = LIST_LENGTH(pNodeListNode->pNodeList); if (opNum != 1) { qDestroyQueryPlan(pPlan); terrno = TSDB_CODE_MND_INVALID_TOPIC_QUERY; return -1; } - plan = (SSubplan*)nodesListGetNode(inner->pNodeList, 0); - } - ASSERT(pSub->unassignedVgs); - ASSERT(taosHashGetSize(pSub->consumerHash) == 0); + pSubplan = (SSubplan*)nodesListGetNode(pNodeListNode->pNodeList, 0); + } void* pIter = NULL; while (1) { pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void**)&pVgroup); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } + if (!mndVgroupInDb(pVgroup, pTopic->dbUid)) { sdbRelease(pSdb, pVgroup); continue; @@ -569,32 +577,27 @@ int32_t mndSchedInitSubEp(SMnode* pMnode, const SMqTopicObj* pTopic, SMqSubscrib pVgEp->vgId = pVgroup->vgId; taosArrayPush(pSub->unassignedVgs, &pVgEp); - mDebug("init subscription %s, assign vg: %d", pSub->key, pVgEp->vgId); + mDebug("init subscription %s for topic:%s assign vgId:%d", pSub->key, pTopic->name, pVgEp->vgId); if (pTopic->subType == TOPIC_SUB_TYPE__COLUMN) { int32_t msgLen; - plan->execNode.epSet = pVgEp->epSet; - plan->execNode.nodeId = pVgEp->vgId; + pSubplan->execNode.epSet = pVgEp->epSet; + pSubplan->execNode.nodeId = pVgEp->vgId; - if (qSubPlanToString(plan, &pVgEp->qmsg, &msgLen) < 0) { + if (qSubPlanToString(pSubplan, &pVgEp->qmsg, &msgLen) < 0) { sdbRelease(pSdb, pVgroup); qDestroyQueryPlan(pPlan); terrno = TSDB_CODE_QRY_INVALID_INPUT; return -1; } } else { - pVgEp->qmsg = strdup(""); + pVgEp->qmsg = taosStrdup(""); } sdbRelease(pSdb, pVgroup); } - ASSERT(pSub->unassignedVgs->size > 0); - - ASSERT(taosHashGetSize(pSub->consumerHash) == 0); - qDestroyQueryPlan(pPlan); - return 0; } diff --git a/source/dnode/mnode/impl/src/mndShow.c b/source/dnode/mnode/impl/src/mndShow.c index 7a8de4099f0a11f313552a6f2629c797fda06f39..c50b205f37f569fced5a690f329ae3ba26c1ac6a 100644 --- a/source/dnode/mnode/impl/src/mndShow.c +++ b/source/dnode/mnode/impl/src/mndShow.c @@ -19,6 +19,7 @@ #include "systable.h" #define SHOW_STEP_SIZE 100 +#define SHOW_COLS_STEP_SIZE 4096 static SShowObj *mndCreateShowObj(SMnode *pMnode, SRetrieveTableReq *pReq); static void mndFreeShowObj(SShowObj *pShow); @@ -76,6 +77,8 @@ static int32_t convertToRetrieveType(char *name, int32_t len) { type = TSDB_MGMT_TABLE_TABLE; } else if (strncasecmp(name, TSDB_INS_TABLE_TAGS, len) == 0) { type = TSDB_MGMT_TABLE_TAG; + } else if (strncasecmp(name, TSDB_INS_TABLE_COLS, len) == 0) { + type = TSDB_MGMT_TABLE_COL; } else if (strncasecmp(name, TSDB_INS_TABLE_TABLE_DISTRIBUTED, len) == 0) { // type = TSDB_MGMT_TABLE_DIST; } else if (strncasecmp(name, TSDB_INS_TABLE_USERS, len) == 0) { @@ -131,6 +134,7 @@ static SShowObj *mndCreateShowObj(SMnode *pMnode, SRetrieveTableReq *pReq) { showObj.pMnode = pMnode; showObj.type = convertToRetrieveType(pReq->tb, tListLen(pReq->tb)); memcpy(showObj.db, pReq->db, TSDB_DB_FNAME_LEN); + tstrncpy(showObj.filterTb, pReq->filterTb, TSDB_TABLE_NAME_LEN); int32_t keepTime = tsShellActivityTimer * 6 * 1000; SShowObj *pShow = taosCachePut(pMgmt->cache, &showId, sizeof(int64_t), &showObj, size, keepTime); @@ -190,13 +194,15 @@ static int32_t mndProcessRetrieveSysTableReq(SRpcMsg *pReq) { int32_t rowsToRead = SHOW_STEP_SIZE; int32_t size = 0; int32_t rowsRead = 0; - + mDebug("mndProcessRetrieveSysTableReq start"); SRetrieveTableReq retrieveReq = {0}; if (tDeserializeSRetrieveTableReq(pReq->pCont, pReq->contLen, &retrieveReq) != 0) { terrno = TSDB_CODE_INVALID_MSG; return -1; } + mDebug("mndProcessRetrieveSysTableReq tb:%s", retrieveReq.tb); + if (retrieveReq.showId == 0) { STableMetaRsp *pMeta = taosHashGet(pMnode->infosMeta, retrieveReq.tb, strlen(retrieveReq.tb)); if (pMeta == NULL) { @@ -226,6 +232,9 @@ static int32_t mndProcessRetrieveSysTableReq(SRpcMsg *pReq) { } } + if(pShow->type == TSDB_MGMT_TABLE_COL){ // expend capacity for ins_columns + rowsToRead = SHOW_COLS_STEP_SIZE; + } ShowRetrieveFp retrieveFp = pMgmt->retrieveFps[pShow->type]; if (retrieveFp == NULL) { mndReleaseShowObj(pShow, false); @@ -315,7 +324,7 @@ static int32_t mndProcessRetrieveSysTableReq(SRpcMsg *pReq) { pReq->info.rsp = pRsp; pReq->info.rspLen = size; - if (rowsRead == 0 || rowsRead < rowsToRead) { + if (rowsRead == 0 || ((rowsRead < rowsToRead) && !pShow->restore)) { pRsp->completed = 1; mDebug("show:0x%" PRIx64 ", retrieve completed", pShow->id); mndReleaseShowObj(pShow, true); diff --git a/source/dnode/mnode/impl/src/mndSma.c b/source/dnode/mnode/impl/src/mndSma.c index fe0dc9e8578cd9afc46900e0530eb28788fa5c0b..3d654a23d87b082aa441012375d0691089e391d8 100644 --- a/source/dnode/mnode/impl/src/mndSma.c +++ b/source/dnode/mnode/impl/src/mndSma.c @@ -17,6 +17,8 @@ #include "mndSma.h" #include "mndDb.h" #include "mndDnode.h" +#include "mndIndex.h" +#include "mndIndexComm.h" #include "mndInfoSchema.h" #include "mndMnode.h" #include "mndPrivilege.h" @@ -43,9 +45,13 @@ static int32_t mndProcessDropSmaReq(SRpcMsg *pReq); static int32_t mndProcessGetSmaReq(SRpcMsg *pReq); static int32_t mndProcessGetTbSmaReq(SRpcMsg *pReq); static int32_t mndRetrieveSma(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); -static void mndCancelGetNextSma(SMnode *pMnode, void *pIter); static void mndDestroySmaObj(SSmaObj *pSmaObj); +// sma and tag index comm func +static int32_t mndProcessDropIdxReq(SRpcMsg *pReq); +static int32_t mndRetrieveIdx(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); +static void mndCancelRetrieveIdx(SMnode *pMnode, void *pIter); + int32_t mndInitSma(SMnode *pMnode) { SSdbTable table = { .sdbType = SDB_SMA, @@ -58,14 +64,14 @@ int32_t mndInitSma(SMnode *pMnode) { }; mndSetMsgHandle(pMnode, TDMT_MND_CREATE_SMA, mndProcessCreateSmaReq); - mndSetMsgHandle(pMnode, TDMT_MND_DROP_SMA, mndProcessDropSmaReq); + mndSetMsgHandle(pMnode, TDMT_MND_DROP_SMA, mndProcessDropIdxReq); mndSetMsgHandle(pMnode, TDMT_VND_CREATE_SMA_RSP, mndTransProcessRsp); mndSetMsgHandle(pMnode, TDMT_VND_DROP_SMA_RSP, mndTransProcessRsp); mndSetMsgHandle(pMnode, TDMT_MND_GET_INDEX, mndProcessGetSmaReq); mndSetMsgHandle(pMnode, TDMT_MND_GET_TABLE_INDEX, mndProcessGetTbSmaReq); - mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_INDEX, mndRetrieveSma); - mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_INDEX, mndCancelGetNextSma); + mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_INDEX, mndRetrieveIdx); + mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_INDEX, mndCancelRetrieveIdx); return sdbSetTable(pMnode->pSdb, table); } @@ -459,19 +465,33 @@ static int32_t mndSetCreateSmaVgroupRedoActions(SMnode *pMnode, STrans *pTrans, int32_t contLen = 0; void *pReq = mndBuildCreateVnodeReq(pMnode, pDnode, pDb, pVgroup, &contLen); - taosMemoryFreeClear(pSmaReq); - if (pReq == NULL) return -1; + if (pReq == NULL) { + taosMemoryFreeClear(pSmaReq); + return -1; + } + action.mTraceId = pTrans->mTraceId; action.pCont = pReq; action.contLen = contLen; action.msgType = TDMT_DND_CREATE_VNODE; action.acceptableCode = TSDB_CODE_VND_ALREADY_EXIST; if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFreeClear(pSmaReq); taosMemoryFree(pReq); return -1; } + action.pCont = pSmaReq; + action.contLen = smaContLen; + action.msgType = TDMT_VND_CREATE_SMA; + action.acceptableCode = TSDB_CODE_TSMA_ALREADY_EXIST; + + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFreeClear(pSmaReq); + return -1; + } + return 0; } @@ -533,14 +553,14 @@ static int32_t mndCreateSma(SMnode *pMnode, SRpcMsg *pReq, SMCreateSmaReq *pCrea streamObj.sourceDbUid = pDb->uid; streamObj.targetDbUid = pDb->uid; streamObj.version = 1; - streamObj.sql = strdup(pCreate->sql); + streamObj.sql = taosStrdup(pCreate->sql); streamObj.smaId = smaObj.uid; streamObj.watermark = pCreate->watermark; streamObj.deleteMark = pCreate->deleteMark; streamObj.fillHistory = STREAM_FILL_HISTORY_ON; streamObj.trigger = STREAM_TRIGGER_WINDOW_CLOSE; streamObj.triggerParam = pCreate->maxDelay; - streamObj.ast = strdup(smaObj.ast); + streamObj.ast = taosStrdup(smaObj.ast); // check the maxDelay if (streamObj.triggerParam < TSDB_MIN_ROLLUP_MAX_DELAY) { @@ -674,6 +694,8 @@ static int32_t mndProcessCreateSmaReq(SRpcMsg *pReq) { SDbObj *pDb = NULL; SMCreateSmaReq createReq = {0}; + int64_t mTraceId = TRACE_GET_ROOTID(&pReq->info.traceId); + if (tDeserializeSMCreateSmaReq(pReq->pCont, pReq->contLen, &createReq) != 0) { terrno = TSDB_CODE_INVALID_MSG; goto _OVER; @@ -699,8 +721,13 @@ static int32_t mndProcessCreateSmaReq(SRpcMsg *pReq) { terrno = TSDB_CODE_MND_STREAM_ALREADY_EXIST; goto _OVER; } + SSIdx idx = {0}; + if (mndAcquireGlobalIdx(pMnode, createReq.name, SDB_SMA, &idx) == 0) { + pSma = idx.pIdx; + } else { + goto _OVER; + } - pSma = mndAcquireSma(pMnode, createReq.name); if (pSma != NULL) { if (createReq.igExists) { mInfo("sma:%s, already exist in sma:%s, ignore exist is set", createReq.name, pSma->name); @@ -946,7 +973,12 @@ static int32_t mndProcessDropSmaReq(SRpcMsg *pReq) { mInfo("sma:%s, start to drop", dropReq.name); - pSma = mndAcquireSma(pMnode, dropReq.name); + SSIdx idx = {0}; + if (mndAcquireGlobalIdx(pMnode, dropReq.name, SDB_SMA, &idx) == 0) { + pSma = idx.pIdx; + } else { + goto _OVER; + } if (pSma == NULL) { if (dropReq.igNotExists) { mInfo("sma:%s, not exist, ignore not exist is set", dropReq.name); @@ -985,7 +1017,14 @@ static int32_t mndGetSma(SMnode *pMnode, SUserIndexReq *indexReq, SUserIndexRsp int32_t code = -1; SSmaObj *pSma = NULL; - pSma = mndAcquireSma(pMnode, indexReq->indexFName); + SSIdx idx = {0}; + if (0 == mndAcquireGlobalIdx(pMnode, indexReq->indexFName, SDB_SMA, &idx)) { + pSma = idx.pIdx; + } else { + *exist = false; + return 0; + } + if (pSma == NULL) { *exist = false; return 0; @@ -1194,10 +1233,10 @@ static int32_t mndRetrieveSma(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc pDb = mndAcquireDb(pMnode, pShow->db); if (pDb == NULL) return 0; } - + SSmaAndTagIter *pIter = pShow->pIter; while (numOfRows < rows) { - pShow->pIter = sdbFetch(pSdb, SDB_SMA, pShow->pIter, (void **)&pSma); - if (pShow->pIter == NULL) break; + pIter->pSmaIter = sdbFetch(pSdb, SDB_SMA, pIter->pSmaIter, (void **)&pSma); + if (pIter->pSmaIter == NULL) break; if (NULL != pDb && pSma->dbUid != pDb->uid) { sdbRelease(pSdb, pSma); @@ -1220,19 +1259,31 @@ static int32_t mndRetrieveSma(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc STR_TO_VARSTR(n3, (char *)tNameGetTableName(&stbName)); SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)n1, false); + colDataSetVal(pColInfo, numOfRows, (const char *)n1, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)n2, false); + colDataSetVal(pColInfo, numOfRows, (const char *)n2, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)n3, false); + colDataSetVal(pColInfo, numOfRows, (const char *)n3, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)&pSma->dstVgId, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)&pSma->createdTime, false); + + char col[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(col, (char *)""); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pSma->dstVgId, false); + colDataAppend(pColInfo, numOfRows, (const char *)col, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pSma->createdTime, false); + + char tag[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(tag, (char *)"sma_index"); + colDataAppend(pColInfo, numOfRows, (const char *)tag, false); numOfRows++; sdbRelease(pSdb, pSma); @@ -1243,7 +1294,30 @@ static int32_t mndRetrieveSma(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc return numOfRows; } -static void mndCancelGetNextSma(SMnode *pMnode, void *pIter) { - SSdb *pSdb = pMnode->pSdb; - sdbCancelFetch(pSdb, pIter); +// sma and tag index comm func +static int32_t mndProcessDropIdxReq(SRpcMsg *pReq) { + int ret = mndProcessDropSmaReq(pReq); + if (terrno == TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST) { + terrno = 0; + ret = mndProcessDropTagIdxReq(pReq); + } + return ret; +} + +static int32_t mndRetrieveIdx(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) { + if (pShow->pIter == NULL) { + pShow->pIter = taosMemoryCalloc(1, sizeof(SSmaAndTagIter)); + } + int32_t read = mndRetrieveSma(pReq, pShow, pBlock, rows); + if (read < rows) read += mndRetrieveTagIdx(pReq, pShow, pBlock, rows - read); + return read; +} +static void mndCancelRetrieveIdx(SMnode *pMnode, void *pIter) { + SSmaAndTagIter *p = pIter; + if (p != NULL) { + SSdb *pSdb = pMnode->pSdb; + sdbCancelFetch(pSdb, p->pSmaIter); + sdbCancelFetch(pSdb, p->pIdxIter); + } + taosMemoryFree(p); } diff --git a/source/dnode/mnode/impl/src/mndSnode.c b/source/dnode/mnode/impl/src/mndSnode.c index e6a253bcc08c35d28bf7e74bf5d2804573e134db..5e98380a08eb8a8194f8cdc89cbb817a56388135 100644 --- a/source/dnode/mnode/impl/src/mndSnode.c +++ b/source/dnode/mnode/impl/src/mndSnode.c @@ -441,16 +441,16 @@ static int32_t mndRetrieveSnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB cols = 0; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pObj->id, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->id, false); char ep[TSDB_EP_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(ep, pObj->pDnode->ep, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)ep, false); + colDataSetVal(pColInfo, numOfRows, (const char *)ep, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pObj->createdTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pObj->createdTime, false); numOfRows++; sdbRelease(pSdb, pObj); diff --git a/source/dnode/mnode/impl/src/mndStb.c b/source/dnode/mnode/impl/src/mndStb.c index 471c53b2f536cb45f52219096c728aae4f13fc01..dff0ef261fc4b655d13b43ad6f2b3222a0f356b7 100644 --- a/source/dnode/mnode/impl/src/mndStb.c +++ b/source/dnode/mnode/impl/src/mndStb.c @@ -17,6 +17,7 @@ #include "mndStb.h" #include "mndDb.h" #include "mndDnode.h" +#include "mndIndex.h" #include "mndInfoSchema.h" #include "mndMnode.h" #include "mndPerfSchema.h" @@ -44,11 +45,16 @@ static int32_t mndProcessDropStbReq(SRpcMsg *pReq); static int32_t mndProcessDropTtltbReq(SRpcMsg *pReq); static int32_t mndProcessTableMetaReq(SRpcMsg *pReq); static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); +static int32_t mndRetrieveStbCol(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); static void mndCancelGetNextStb(SMnode *pMnode, void *pIter); static int32_t mndProcessTableCfgReq(SRpcMsg *pReq); static int32_t mndAlterStbImp(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb, bool needRsp, void *alterOriData, int32_t alterOriDataLen); -static int32_t mndCheckColAndTagModifiable(SMnode *pMnode, const char *stbname, int64_t suid, col_id_t colId); +static int32_t mndAlterStbAndUpdateTagIdxImp(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb, bool needRsp, + void *alterOriData, int32_t alterOriDataLen, const SMAlterStbReq *pAlter); + +static int32_t mndProcessCreateIndexReq(SRpcMsg *pReq); +static int32_t mndProcessDropIndexReq(SRpcMsg *pReq); int32_t mndInitStb(SMnode *pMnode) { SSdbTable table = { @@ -71,10 +77,19 @@ int32_t mndInitStb(SMnode *pMnode) { mndSetMsgHandle(pMnode, TDMT_MND_TABLE_META, mndProcessTableMetaReq); mndSetMsgHandle(pMnode, TDMT_MND_TTL_TIMER, mndProcessTtlTimer); mndSetMsgHandle(pMnode, TDMT_MND_TABLE_CFG, mndProcessTableCfgReq); + // mndSetMsgHandle(pMnode, TDMT_MND_SYSTABLE_RETRIEVE, mndProcessRetrieveStbReq); + + // mndSetMsgHandle(pMnode, TDMT_MND_CREATE_INDEX, mndProcessCreateIndexReq); + // mndSetMsgHandle(pMnode, TDMT_MND_DROP_INDEX, mndProcessDropIndexReq); + // mndSetMsgHandle(pMnode, TDMT_VND_CREATE_INDEX_RSP, mndTransProcessRsp); + // mndSetMsgHandle(pMnode, TDMT_VND_DROP_INDEX_RSP, mndTransProcessRsp); mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STB, mndRetrieveStb); mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_STB, mndCancelGetNextStb); + mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_COL, mndRetrieveStbCol); + mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_COL, mndCancelGetNextStb); + return sdbSetTable(pMnode->pSdb, table); } @@ -421,8 +436,8 @@ static FORCE_INLINE int32_t schemaExColIdCompare(const void *colId, const void * return 0; } -static void *mndBuildVCreateStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pStb, int32_t *pContLen, - void *alterOriData, int32_t alterOriDataLen) { +void *mndBuildVCreateStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pStb, int32_t *pContLen, void *alterOriData, + int32_t alterOriDataLen) { SEncoder encoder = {0}; int32_t contLen; SName name = {0}; @@ -653,6 +668,7 @@ static int32_t mndSetCreateStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj } STransAction action = {0}; + action.mTraceId = pTrans->mTraceId; action.epSet = mndGetVgroupEpset(pMnode, pVgroup); action.pCont = pReq; action.contLen = contLen; @@ -781,6 +797,11 @@ int32_t mndBuildStbFromReq(SMnode *pMnode, SStbObj *pDst, SMCreateStbReq *pCreat return -1; } + if(pDst->nextColId < 0 || pDst->nextColId >= 0x7fff - pDst->numOfColumns - pDst->numOfTags){ + terrno = TSDB_CODE_MND_FIELD_VALUE_OVERFLOW; + return -1; + } + for (int32_t i = 0; i < pDst->numOfColumns; ++i) { SField *pField = taosArrayGet(pCreate->pColumns, i); SSchema *pSchema = &pDst->pColumns[i]; @@ -797,6 +818,9 @@ int32_t mndBuildStbFromReq(SMnode *pMnode, SStbObj *pDst, SMCreateStbReq *pCreat SSchema *pSchema = &pDst->pTags[i]; pSchema->type = pField->type; pSchema->bytes = pField->bytes; + if (i == 0) { + SSCHMEA_SET_IDX_ON(pSchema); + } memcpy(pSchema->name, pField->name, TSDB_COL_NAME_LEN); pSchema->colId = pDst->nextColId; pDst->nextColId++; @@ -859,7 +883,7 @@ static int32_t mndProcessTtlTimer(SRpcMsg *pReq) { pHead->vgId = htonl(pVgroup->vgId); tSerializeSVDropTtlTableReq((char *)pHead + sizeof(SMsgHead), contLen, &ttlReq); - SRpcMsg rpcMsg = {.msgType = TDMT_VND_DROP_TTL_TABLE, .pCont = pHead, .contLen = contLen}; + SRpcMsg rpcMsg = {.msgType = TDMT_VND_DROP_TTL_TABLE, .pCont = pHead, .contLen = contLen, .info = pReq->info}; SEpSet epSet = mndGetVgroupEpset(pMnode, pVgroup); int32_t code = tmsgSendReq(&epSet, &rpcMsg); if (code != 0) { @@ -875,7 +899,7 @@ static int32_t mndProcessTtlTimer(SRpcMsg *pReq) { static int32_t mndFindSuperTableTagIndex(const SStbObj *pStb, const char *tagName) { for (int32_t tag = 0; tag < pStb->numOfTags; tag++) { - if (strcasecmp(pStb->pTags[tag].name, tagName) == 0) { + if (strcmp(pStb->pTags[tag].name, tagName) == 0) { return tag; } } @@ -885,7 +909,7 @@ static int32_t mndFindSuperTableTagIndex(const SStbObj *pStb, const char *tagNam static int32_t mndFindSuperTableColumnIndex(const SStbObj *pStb, const char *colName) { for (int32_t col = 0; col < pStb->numOfColumns; col++) { - if (strcasecmp(pStb->pColumns[col].name, colName) == 0) { + if (strcmp(pStb->pColumns[col].name, colName) == 0) { return col; } } @@ -908,6 +932,11 @@ static int32_t mndBuildStbFromAlter(SStbObj *pStb, SStbObj *pDst, SMCreateStbReq return -1; } + if(pDst->nextColId < 0 || pDst->nextColId >= 0x7fff - pDst->numOfColumns - pDst->numOfTags){ + terrno = TSDB_CODE_MND_FIELD_VALUE_OVERFLOW; + return -1; + } + for (int32_t i = 0; i < pDst->numOfColumns; ++i) { SField *pField = taosArrayGet(createReq->pColumns, i); SSchema *pSchema = &pDst->pColumns[i]; @@ -968,9 +997,8 @@ static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) { code = 0; goto _OVER; } else if (pStb->uid != createReq.suid) { - mError("stb:%s, already exist while create, input suid:%" PRId64 " not match with exist suid:%" PRId64, - createReq.name, createReq.suid, pStb->uid); - terrno = TSDB_CODE_MND_STABLE_UID_NOT_MATCH; + mInfo("stb:%s, alter table does not need to be done, because table is deleted", createReq.name); + code = 0; goto _OVER; } else if (createReq.tagVer > 0 || createReq.colVer > 0) { int32_t tagDelta = createReq.tagVer - pStb->tagVer; @@ -1082,7 +1110,7 @@ static int32_t mndCheckAlterStbReq(SMAlterStbReq *pAlter) { return 0; } -static int32_t mndAllocStbSchemas(const SStbObj *pOld, SStbObj *pNew) { +int32_t mndAllocStbSchemas(const SStbObj *pOld, SStbObj *pNew) { pNew->pTags = taosMemoryCalloc(pNew->numOfTags, sizeof(SSchema)); pNew->pColumns = taosMemoryCalloc(pNew->numOfColumns, sizeof(SSchema)); if (pNew->pTags == NULL || pNew->pColumns == NULL) { @@ -1135,6 +1163,11 @@ static int32_t mndAddSuperTableTag(const SStbObj *pOld, SStbObj *pNew, SArray *p if (mndAllocStbSchemas(pOld, pNew) != 0) { return -1; } + + if(pNew->nextColId < 0 || pNew->nextColId >= 0x7fff - ntags){ + terrno = TSDB_CODE_MND_FIELD_VALUE_OVERFLOW; + return -1; + } for (int32_t i = 0; i < ntags; i++) { SField *pField = taosArrayGet(pFields, i); @@ -1344,6 +1377,10 @@ static int32_t mndDropSuperTableTag(SMnode *pMnode, const SStbObj *pOld, SStbObj pNew->numOfTags--; pNew->tagVer++; + + // if (mndDropIndexByTag(pMnode, pOld, tagName) != 0) { + // return -1; + // } mInfo("stb:%s, start to drop tag %s", pNew->name, tagName); return 0; } @@ -1439,6 +1476,11 @@ static int32_t mndAddSuperTableColumn(const SStbObj *pOld, SStbObj *pNew, SArray return -1; } + if(pNew->nextColId < 0 || pNew->nextColId >= 0x7fff - ncols){ + terrno = TSDB_CODE_MND_FIELD_VALUE_OVERFLOW; + return -1; + } + for (int32_t i = 0; i < ncols; i++) { SField *pField = taosArrayGet(pFields, i); if (mndFindSuperTableColumnIndex(pOld, pField->name) >= 0) { @@ -1605,6 +1647,43 @@ static int32_t mndSetAlterStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj return 0; } +static int32_t mndSetAlterStbRedoActions2(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb, + void *alterOriData, int32_t alterOriDataLen) { + SSdb *pSdb = pMnode->pSdb; + SVgObj *pVgroup = NULL; + void *pIter = NULL; + int32_t contLen; + + while (1) { + pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup); + if (pIter == NULL) break; + if (!mndVgroupInDb(pVgroup, pDb->uid)) { + sdbRelease(pSdb, pVgroup); + continue; + } + + void *pReq = mndBuildVCreateStbReq(pMnode, pVgroup, pStb, &contLen, alterOriData, alterOriDataLen); + if (pReq == NULL) { + sdbCancelFetch(pSdb, pIter); + sdbRelease(pSdb, pVgroup); + return -1; + } + STransAction action = {0}; + action.epSet = mndGetVgroupEpset(pMnode, pVgroup); + action.pCont = pReq; + action.contLen = contLen; + action.msgType = TDMT_VND_CREATE_INDEX; + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + sdbCancelFetch(pSdb, pIter); + sdbRelease(pSdb, pVgroup); + return -1; + } + sdbRelease(pSdb, pVgroup); + } + + return 0; +} static int32_t mndBuildStbSchemaImp(SDbObj *pDb, SStbObj *pStb, const char *tbName, STableMetaRsp *pRsp) { taosRLockLatch(&pStb->lock); @@ -1643,6 +1722,7 @@ static int32_t mndBuildStbSchemaImp(SDbObj *pDb, SStbObj *pStb, const char *tbNa SSchema *pSrcSchema = &pStb->pTags[i]; memcpy(pSchema->name, pSrcSchema->name, TSDB_COL_NAME_LEN); pSchema->type = pSrcSchema->type; + pSchema->flags = pSrcSchema->flags; pSchema->colId = pSrcSchema->colId; pSchema->bytes = pSrcSchema->bytes; } @@ -1675,7 +1755,7 @@ static int32_t mndBuildStbCfgImp(SDbObj *pDb, SStbObj *pStb, const char *tbName, pRsp->ttl = pStb->ttl; pRsp->commentLen = pStb->commentLen; if (pStb->commentLen > 0) { - pRsp->pComment = strdup(pStb->comment); + pRsp->pComment = taosStrdup(pStb->comment); } for (int32_t i = 0; i < pStb->numOfColumns; ++i) { @@ -1884,6 +1964,74 @@ _OVER: return code; } +static int32_t mndAlterStbAndUpdateTagIdxImp(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb, bool needRsp, + void *alterOriData, int32_t alterOriDataLen, const SMAlterStbReq *pAlter) { + int32_t code = -1; + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq, "alter-stb"); + if (pTrans == NULL) goto _OVER; + + mInfo("trans:%d, used to alter stb:%s", pTrans->id, pStb->name); + mndTransSetDbName(pTrans, pDb->name, pStb->name); + + if (mndTrancCheckConflict(pMnode, pTrans) != 0) goto _OVER; + + if (needRsp) { + void *pCont = NULL; + int32_t contLen = 0; + if (mndBuildSMAlterStbRsp(pDb, pStb, &pCont, &contLen) != 0) goto _OVER; + mndTransSetRpcRsp(pTrans, pCont, contLen); + } + + if (pAlter->alterType == TSDB_ALTER_TABLE_DROP_TAG) { + SIdxObj idxObj = {0}; + SField *pField0 = taosArrayGet(pAlter->pFields, 0); + bool exist = false; + if (mndGetIdxsByTagName(pMnode, pStb, pField0->name, &idxObj) == 0) { + exist = true; + } + if (mndSetAlterStbRedoLogs(pMnode, pTrans, pDb, pStb) != 0) goto _OVER; + if (mndSetAlterStbCommitLogs(pMnode, pTrans, pDb, pStb) != 0) goto _OVER; + + if (exist == true) { + if (mndSetDropIdxRedoLogs(pMnode, pTrans, &idxObj) != 0) goto _OVER; + if (mndSetDropIdxCommitLogs(pMnode, pTrans, &idxObj) != 0) goto _OVER; + } + + if (mndSetAlterStbRedoActions(pMnode, pTrans, pDb, pStb, alterOriData, alterOriDataLen) != 0) goto _OVER; + if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; + + } else if (pAlter->alterType == TSDB_ALTER_TABLE_UPDATE_TAG_NAME) { + SIdxObj idxObj = {0}; + SField *pField0 = taosArrayGet(pAlter->pFields, 0); + SField *pField1 = taosArrayGet(pAlter->pFields, 1); + const char *oTagName = pField0->name; + const char *nTagName = pField1->name; + bool exist = false; + + if (mndGetIdxsByTagName(pMnode, pStb, pField0->name, &idxObj) == 0) { + exist = true; + } + + if (mndSetAlterStbRedoLogs(pMnode, pTrans, pDb, pStb) != 0) goto _OVER; + if (mndSetAlterStbCommitLogs(pMnode, pTrans, pDb, pStb) != 0) goto _OVER; + + if (exist == true) { + memcpy(idxObj.colName, nTagName, strlen(nTagName)); + idxObj.colName[strlen(nTagName)] = 0; + if (mndSetAlterIdxRedoLogs(pMnode, pTrans, &idxObj) != 0) goto _OVER; + if (mndSetAlterIdxCommitLogs(pMnode, pTrans, &idxObj) != 0) goto _OVER; + } + + if (mndSetAlterStbRedoActions(pMnode, pTrans, pDb, pStb, alterOriData, alterOriDataLen) != 0) goto _OVER; + if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; + } + code = 0; + +_OVER: + mndTransDrop(pTrans); + return code; +} + static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *pAlter, SDbObj *pDb, SStbObj *pOld) { bool needRsp = true; int32_t code = -1; @@ -1897,7 +2045,7 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p stbObj.pTags = NULL; stbObj.updateTime = taosGetTimestampMs(); stbObj.lock = 0; - + bool updateTagIndex = false; switch (pAlter->alterType) { case TSDB_ALTER_TABLE_ADD_TAG: code = mndAddSuperTableTag(pOld, &stbObj, pAlter->pFields, pAlter->numOfFields); @@ -1905,9 +2053,11 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p case TSDB_ALTER_TABLE_DROP_TAG: pField0 = taosArrayGet(pAlter->pFields, 0); code = mndDropSuperTableTag(pMnode, pOld, &stbObj, pField0->name); + updateTagIndex = true; break; case TSDB_ALTER_TABLE_UPDATE_TAG_NAME: code = mndAlterStbTagName(pMnode, pOld, &stbObj, pAlter->pFields); + updateTagIndex = true; break; case TSDB_ALTER_TABLE_UPDATE_TAG_BYTES: pField0 = taosArrayGet(pAlter->pFields, 0); @@ -1935,7 +2085,11 @@ static int32_t mndAlterStb(SMnode *pMnode, SRpcMsg *pReq, const SMAlterStbReq *p } if (code != 0) goto _OVER; - code = mndAlterStbImp(pMnode, pReq, pDb, &stbObj, needRsp, pReq->pCont, pReq->contLen); + if (updateTagIndex == false) { + code = mndAlterStbImp(pMnode, pReq, pDb, &stbObj, needRsp, pReq->pCont, pReq->contLen); + } else { + code = mndAlterStbAndUpdateTagIdxImp(pMnode, pReq, pDb, &stbObj, needRsp, pReq->pCont, pReq->contLen, pAlter); + } _OVER: taosMemoryFreeClear(stbObj.pTags); @@ -2068,9 +2222,9 @@ static int32_t mndDropStb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *p if (mndSetDropStbRedoLogs(pMnode, pTrans, pStb) != 0) goto _OVER; if (mndSetDropStbCommitLogs(pMnode, pTrans, pStb) != 0) goto _OVER; if (mndSetDropStbRedoActions(pMnode, pTrans, pDb, pStb) != 0) goto _OVER; + if (mndDropIdxsByStb(pMnode, pTrans, pDb, pStb) != 0) goto _OVER; if (mndDropSmasByStb(pMnode, pTrans, pDb, pStb) != 0) goto _OVER; if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; - code = 0; _OVER: @@ -2178,9 +2332,7 @@ static int32_t mndCheckDropStbForStream(SMnode *pMnode, const char *stbFullName, return 0; } -static int32_t mndProcessDropTtltbReq(SRpcMsg *pRsp) { - return 0; -} +static int32_t mndProcessDropTtltbReq(SRpcMsg *pRsp) { return 0; } static int32_t mndProcessDropStbReq(SRpcMsg *pReq) { SMnode *pMnode = pReq->info.node; @@ -2392,6 +2544,9 @@ int32_t mndValidateStbInfo(SMnode *pMnode, SSTableVersion *pStbVersions, int32_t if (mndBuildStbSchema(pMnode, pStbVersion->dbFName, pStbVersion->stbName, &metaRsp, &smaVer) != 0) { metaRsp.numOfColumns = -1; metaRsp.suid = pStbVersion->suid; + tstrncpy(metaRsp.dbFName, pStbVersion->dbFName, sizeof(metaRsp.dbFName)); + tstrncpy(metaRsp.tbName, pStbVersion->stbName, sizeof(metaRsp.tbName)); + tstrncpy(metaRsp.stbName, pStbVersion->stbName, sizeof(metaRsp.stbName)); taosArrayPush(hbRsp.pMetaRsp, &metaRsp); continue; } @@ -2482,6 +2637,13 @@ void mndExtractDbNameFromStbFullName(const char *stbFullName, char *dst) { tNameGetFullDbName(&name, dst); } +void mndExtractShortDbNameFromStbFullName(const char *stbFullName, char *dst) { + SName name = {0}; + tNameFromString(&name, stbFullName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); + + tNameGetDbName(&name, dst); +} + void mndExtractTbNameFromStbFullName(const char *stbFullName, char *dst, int32_t dstSize) { int32_t pos = -1; int32_t num = 0; @@ -2495,6 +2657,282 @@ void mndExtractTbNameFromStbFullName(const char *stbFullName, char *dst, int32_t } } +// static int32_t mndProcessRetrieveStbReq(SRpcMsg *pReq) { +// SMnode *pMnode = pReq->info.node; +// SShowMgmt *pMgmt = &pMnode->showMgmt; +// SShowObj *pShow = NULL; +// int32_t rowsToRead = SHOW_STEP_SIZE; +// int32_t rowsRead = 0; +// +// SRetrieveTableReq retrieveReq = {0}; +// if (tDeserializeSRetrieveTableReq(pReq->pCont, pReq->contLen, &retrieveReq) != 0) { +// terrno = TSDB_CODE_INVALID_MSG; +// return -1; +// } +// +// SMnode *pMnode = pReq->info.node; +// SSdb *pSdb = pMnode->pSdb; +// int32_t numOfRows = 0; +// SDbObj *pDb = NULL; +// ESdbStatus objStatus = 0; +// +// SUserObj *pUser = mndAcquireUser(pMnode, pReq->info.conn.user); +// if (pUser == NULL) return 0; +// bool sysinfo = pUser->sysInfo; +// +// // Append the information_schema database into the result. +//// if (!pShow->sysDbRsp) { +//// SDbObj infoschemaDb = {0}; +//// setInformationSchemaDbCfg(pMnode, &infoschemaDb); +//// size_t numOfTables = 0; +//// getVisibleInfosTablesNum(sysinfo, &numOfTables); +//// mndDumpDbInfoData(pMnode, pBlock, &infoschemaDb, pShow, numOfRows, numOfTables, true, 0, 1); +//// +//// numOfRows += 1; +//// +//// SDbObj perfschemaDb = {0}; +//// setPerfSchemaDbCfg(pMnode, &perfschemaDb); +//// numOfTables = 0; +//// getPerfDbMeta(NULL, &numOfTables); +//// mndDumpDbInfoData(pMnode, pBlock, &perfschemaDb, pShow, numOfRows, numOfTables, true, 0, 1); +//// +//// numOfRows += 1; +//// pShow->sysDbRsp = true; +//// } +// +// SSDataBlock* p = buildInfoSchemaTableMetaBlock(TSDB_INS_TABLE_COLS); +// blockDataEnsureCapacity(p, rowsToRead); +// +// size_t size = 0; +// const SSysTableMeta* pSysDbTableMeta = NULL; +// +// getInfosDbMeta(&pSysDbTableMeta, &size); +// p->info.rows = buildDbColsInfoBlock(sysinfo, p, pSysDbTableMeta, size, TSDB_INFORMATION_SCHEMA_DB); +// +// getPerfDbMeta(&pSysDbTableMeta, &size); +// p->info.rows = buildDbColsInfoBlock(sysinfo, p, pSysDbTableMeta, size, TSDB_PERFORMANCE_SCHEMA_DB); +// +// blockDataDestroy(p); +// +// +// while (numOfRows < rowsToRead) { +// pShow->pIter = sdbFetchAll(pSdb, SDB_DB, pShow->pIter, (void **)&pDb, &objStatus, true); +// if (pShow->pIter == NULL) break; +// if (strncmp(retrieveReq.db, pDb->name, strlen(retrieveReq.db)) != 0){ +// continue; +// } +// if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_READ_OR_WRITE_DB, pDb) != 0) { +// continue; +// } +// +// while (numOfRows < rowsToRead) { +// pShow->pIter = sdbFetch(pSdb, SDB_STB, pShow->pIter, (void **)&pStb); +// if (pShow->pIter == NULL) break; +// +// if (pDb != NULL && pStb->dbUid != pDb->uid) { +// sdbRelease(pSdb, pStb); +// continue; +// } +// +// cols = 0; +// +// SName name = {0}; +// char stbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; +// mndExtractTbNameFromStbFullName(pStb->name, &stbName[VARSTR_HEADER_SIZE], TSDB_TABLE_NAME_LEN); +// varDataSetLen(stbName, strlen(&stbName[VARSTR_HEADER_SIZE])); +// +// SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// colDataSetVal(pColInfo, numOfRows, (const char *)stbName, false); +// +// char db[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; +// tNameFromString(&name, pStb->db, T_NAME_ACCT | T_NAME_DB); +// tNameGetDbName(&name, varDataVal(db)); +// varDataSetLen(db, strlen(varDataVal(db))); +// +// pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// colDataSetVal(pColInfo, numOfRows, (const char *)db, false); +// +// pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// colDataSetVal(pColInfo, numOfRows, (const char *)&pStb->createdTime, false); +// +// pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// colDataSetVal(pColInfo, numOfRows, (const char *)&pStb->numOfColumns, false); +// +// pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// colDataSetVal(pColInfo, numOfRows, (const char *)&pStb->numOfTags, false); +// +// pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// colDataSetVal(pColInfo, numOfRows, (const char *)&pStb->updateTime, false); // number of tables +// +// pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// if (pStb->commentLen > 0) { +// char comment[TSDB_TB_COMMENT_LEN + VARSTR_HEADER_SIZE] = {0}; +// STR_TO_VARSTR(comment, pStb->comment); +// colDataSetVal(pColInfo, numOfRows, comment, false); +// } else if (pStb->commentLen == 0) { +// char comment[VARSTR_HEADER_SIZE + VARSTR_HEADER_SIZE] = {0}; +// STR_TO_VARSTR(comment, ""); +// colDataSetVal(pColInfo, numOfRows, comment, false); +// } else { +// colDataSetNULL(pColInfo, numOfRows); +// } +// +// char watermark[64 + VARSTR_HEADER_SIZE] = {0}; +// sprintf(varDataVal(watermark), "%" PRId64 "a,%" PRId64 "a", pStb->watermark[0], pStb->watermark[1]); +// varDataSetLen(watermark, strlen(varDataVal(watermark))); +// +// pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// colDataSetVal(pColInfo, numOfRows, (const char *)watermark, false); +// +// char maxDelay[64 + VARSTR_HEADER_SIZE] = {0}; +// sprintf(varDataVal(maxDelay), "%" PRId64 "a,%" PRId64 "a", pStb->maxdelay[0], pStb->maxdelay[1]); +// varDataSetLen(maxDelay, strlen(varDataVal(maxDelay))); +// +// pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// colDataSetVal(pColInfo, numOfRows, (const char *)maxDelay, false); +// +// char rollup[160 + VARSTR_HEADER_SIZE] = {0}; +// int32_t rollupNum = (int32_t)taosArrayGetSize(pStb->pFuncs); +// char *sep = ", "; +// int32_t sepLen = strlen(sep); +// int32_t rollupLen = sizeof(rollup) - VARSTR_HEADER_SIZE - 2; +// for (int32_t i = 0; i < rollupNum; ++i) { +// char *funcName = taosArrayGet(pStb->pFuncs, i); +// if (i) { +// strncat(varDataVal(rollup), sep, rollupLen); +// rollupLen -= sepLen; +// } +// strncat(varDataVal(rollup), funcName, rollupLen); +// rollupLen -= strlen(funcName); +// } +// varDataSetLen(rollup, strlen(varDataVal(rollup))); +// +// pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); +// colDataSetVal(pColInfo, numOfRows, (const char *)rollup, false); +// +// numOfRows++; +// sdbRelease(pSdb, pStb); +// } +// +// if (pDb != NULL) { +// mndReleaseDb(pMnode, pDb); +// } +// +// sdbRelease(pSdb, pDb); +// } +// +// pShow->numOfRows += numOfRows; +// mndReleaseUser(pMnode, pUser); +// +// +// +// +// +// +// +// +// ShowRetrieveFp retrieveFp = pMgmt->retrieveFps[pShow->type]; +// if (retrieveFp == NULL) { +// mndReleaseShowObj(pShow, false); +// terrno = TSDB_CODE_MSG_NOT_PROCESSED; +// mError("show:0x%" PRIx64 ", failed to retrieve data since %s", pShow->id, terrstr()); +// return -1; +// } +// +// mDebug("show:0x%" PRIx64 ", start retrieve data, type:%d", pShow->id, pShow->type); +// if (retrieveReq.user[0] != 0) { +// memcpy(pReq->info.conn.user, retrieveReq.user, TSDB_USER_LEN); +// } else { +// memcpy(pReq->info.conn.user, TSDB_DEFAULT_USER, strlen(TSDB_DEFAULT_USER) + 1); +// } +// if (retrieveReq.db[0] && mndCheckShowPrivilege(pMnode, pReq->info.conn.user, pShow->type, retrieveReq.db) != 0) { +// return -1; +// } +// +// int32_t numOfCols = pShow->pMeta->numOfColumns; +// +// SSDataBlock *pBlock = createDataBlock(); +// for (int32_t i = 0; i < numOfCols; ++i) { +// SColumnInfoData idata = {0}; +// +// SSchema *p = &pShow->pMeta->pSchemas[i]; +// +// idata.info.bytes = p->bytes; +// idata.info.type = p->type; +// idata.info.colId = p->colId; +// blockDataAppendColInfo(pBlock, &idata); +// } +// +// blockDataEnsureCapacity(pBlock, rowsToRead); +// +// if (mndCheckRetrieveFinished(pShow)) { +// mDebug("show:0x%" PRIx64 ", read finished, numOfRows:%d", pShow->id, pShow->numOfRows); +// rowsRead = 0; +// } else { +// rowsRead = (*retrieveFp)(pReq, pShow, pBlock, rowsToRead); +// if (rowsRead < 0) { +// terrno = rowsRead; +// mDebug("show:0x%" PRIx64 ", retrieve completed", pShow->id); +// mndReleaseShowObj(pShow, true); +// blockDataDestroy(pBlock); +// return -1; +// } +// +// pBlock->info.rows = rowsRead; +// mDebug("show:0x%" PRIx64 ", stop retrieve data, rowsRead:%d numOfRows:%d", pShow->id, rowsRead, pShow->numOfRows); +// } +// +// size = sizeof(SRetrieveMetaTableRsp) + sizeof(int32_t) + sizeof(SSysTableSchema) * pShow->pMeta->numOfColumns + +// blockDataGetSize(pBlock) + blockDataGetSerialMetaSize(taosArrayGetSize(pBlock->pDataBlock)); +// +// SRetrieveMetaTableRsp *pRsp = rpcMallocCont(size); +// if (pRsp == NULL) { +// mndReleaseShowObj(pShow, false); +// terrno = TSDB_CODE_OUT_OF_MEMORY; +// mError("show:0x%" PRIx64 ", failed to retrieve data since %s", pShow->id, terrstr()); +// blockDataDestroy(pBlock); +// return -1; +// } +// +// pRsp->handle = htobe64(pShow->id); +// +// if (rowsRead > 0) { +// char *pStart = pRsp->data; +// SSchema *ps = pShow->pMeta->pSchemas; +// +// *(int32_t *)pStart = htonl(pShow->pMeta->numOfColumns); +// pStart += sizeof(int32_t); // number of columns +// +// for (int32_t i = 0; i < pShow->pMeta->numOfColumns; ++i) { +// SSysTableSchema *pSchema = (SSysTableSchema *)pStart; +// pSchema->bytes = htonl(ps[i].bytes); +// pSchema->colId = htons(ps[i].colId); +// pSchema->type = ps[i].type; +// +// pStart += sizeof(SSysTableSchema); +// } +// +// int32_t len = blockEncode(pBlock, pStart, pShow->pMeta->numOfColumns); +// } +// +// pRsp->numOfRows = htonl(rowsRead); +// pRsp->precision = TSDB_TIME_PRECISION_MILLI; // millisecond time precision +// pReq->info.rsp = pRsp; +// pReq->info.rspLen = size; +// +// if (rowsRead == 0 || rowsRead < rowsToRead) { +// pRsp->completed = 1; +// mDebug("show:0x%" PRIx64 ", retrieve completed", pShow->id); +// mndReleaseShowObj(pShow, true); +// } else { +// mDebug("show:0x%" PRIx64 ", retrieve not completed yet", pShow->id); +// mndReleaseShowObj(pShow, false); +// } +// +// blockDataDestroy(pBlock); +// return TSDB_CODE_SUCCESS; +//} + static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) { SMnode *pMnode = pReq->info.node; SSdb *pSdb = pMnode->pSdb; @@ -2525,7 +2963,7 @@ static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc varDataSetLen(stbName, strlen(&stbName[VARSTR_HEADER_SIZE])); SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)stbName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)stbName, false); char db[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; tNameFromString(&name, pStb->db, T_NAME_ACCT | T_NAME_DB); @@ -2533,31 +2971,31 @@ static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc varDataSetLen(db, strlen(varDataVal(db))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)db, false); + colDataSetVal(pColInfo, numOfRows, (const char *)db, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pStb->createdTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pStb->createdTime, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pStb->numOfColumns, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pStb->numOfColumns, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pStb->numOfTags, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pStb->numOfTags, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pStb->updateTime, false); // number of tables + colDataSetVal(pColInfo, numOfRows, (const char *)&pStb->updateTime, false); // number of tables pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); if (pStb->commentLen > 0) { char comment[TSDB_TB_COMMENT_LEN + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, pStb->comment); - colDataAppend(pColInfo, numOfRows, comment, false); + colDataSetVal(pColInfo, numOfRows, comment, false); } else if (pStb->commentLen == 0) { char comment[VARSTR_HEADER_SIZE + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, ""); - colDataAppend(pColInfo, numOfRows, comment, false); + colDataSetVal(pColInfo, numOfRows, comment, false); } else { - colDataAppendNULL(pColInfo, numOfRows); + colDataSetNULL(pColInfo, numOfRows); } char watermark[64 + VARSTR_HEADER_SIZE] = {0}; @@ -2565,14 +3003,14 @@ static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc varDataSetLen(watermark, strlen(varDataVal(watermark))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)watermark, false); + colDataSetVal(pColInfo, numOfRows, (const char *)watermark, false); char maxDelay[64 + VARSTR_HEADER_SIZE] = {0}; sprintf(varDataVal(maxDelay), "%" PRId64 "a,%" PRId64 "a", pStb->maxdelay[0], pStb->maxdelay[1]); varDataSetLen(maxDelay, strlen(varDataVal(maxDelay))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)maxDelay, false); + colDataSetVal(pColInfo, numOfRows, (const char *)maxDelay, false); char rollup[160 + VARSTR_HEADER_SIZE] = {0}; int32_t rollupNum = (int32_t)taosArrayGetSize(pStb->pFuncs); @@ -2591,7 +3029,7 @@ static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc varDataSetLen(rollup, strlen(varDataVal(rollup))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)rollup, false); + colDataSetVal(pColInfo, numOfRows, (const char *)rollup, false); numOfRows++; sdbRelease(pSdb, pStb); @@ -2605,6 +3043,206 @@ static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc return numOfRows; } +static int32_t buildDbColsInfoBlock(const SSDataBlock *p, const SSysTableMeta *pSysDbTableMeta, size_t size, + const char *dbName, const char *tbName) { + char tName[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + char dName[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + char typeName[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + int32_t numOfRows = p->info.rows; + + STR_TO_VARSTR(dName, dbName); + STR_TO_VARSTR(typeName, "SYSTEM_TABLE"); + + for (int32_t i = 0; i < size; ++i) { + const SSysTableMeta *pm = &pSysDbTableMeta[i]; + // if (pm->sysInfo) { + // continue; + // } + if (tbName[0] && strncmp(tbName, pm->name, TSDB_TABLE_NAME_LEN) != 0) { + continue; + } + + STR_TO_VARSTR(tName, pm->name); + + for (int32_t j = 0; j < pm->colNum; j++) { + // table name + SColumnInfoData *pColInfoData = taosArrayGet(p->pDataBlock, 0); + colDataSetVal(pColInfoData, numOfRows, tName, false); + + // database name + pColInfoData = taosArrayGet(p->pDataBlock, 1); + colDataSetVal(pColInfoData, numOfRows, dName, false); + + pColInfoData = taosArrayGet(p->pDataBlock, 2); + colDataSetVal(pColInfoData, numOfRows, typeName, false); + + // col name + char colName[TSDB_COL_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(colName, pm->schema[j].name); + pColInfoData = taosArrayGet(p->pDataBlock, 3); + colDataSetVal(pColInfoData, numOfRows, colName, false); + + // col type + int8_t colType = pm->schema[j].type; + pColInfoData = taosArrayGet(p->pDataBlock, 4); + char colTypeStr[VARSTR_HEADER_SIZE + 32]; + int colTypeLen = sprintf(varDataVal(colTypeStr), "%s", tDataTypes[colType].name); + if (colType == TSDB_DATA_TYPE_VARCHAR) { + colTypeLen += + sprintf(varDataVal(colTypeStr) + colTypeLen, "(%d)", (int32_t)(pm->schema[j].bytes - VARSTR_HEADER_SIZE)); + } else if (colType == TSDB_DATA_TYPE_NCHAR) { + colTypeLen += sprintf(varDataVal(colTypeStr) + colTypeLen, "(%d)", + (int32_t)((pm->schema[j].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)); + } + varDataSetLen(colTypeStr, colTypeLen); + colDataSetVal(pColInfoData, numOfRows, (char *)colTypeStr, false); + + pColInfoData = taosArrayGet(p->pDataBlock, 5); + colDataSetVal(pColInfoData, numOfRows, (const char *)&pm->schema[j].bytes, false); + for (int32_t k = 6; k <= 8; ++k) { + pColInfoData = taosArrayGet(p->pDataBlock, k); + colDataSetNULL(pColInfoData, numOfRows); + } + + numOfRows += 1; + } + } + + return numOfRows; +} + +static int32_t buildSysDbColsInfo(SSDataBlock *p, char *db, char *tb) { + size_t size = 0; + const SSysTableMeta *pSysDbTableMeta = NULL; + + if (db[0] && strncmp(db, TSDB_INFORMATION_SCHEMA_DB, TSDB_DB_FNAME_LEN) != 0 && + strncmp(db, TSDB_PERFORMANCE_SCHEMA_DB, TSDB_DB_FNAME_LEN) != 0) { + return p->info.rows; + } + + getInfosDbMeta(&pSysDbTableMeta, &size); + p->info.rows = buildDbColsInfoBlock(p, pSysDbTableMeta, size, TSDB_INFORMATION_SCHEMA_DB, tb); + + getPerfDbMeta(&pSysDbTableMeta, &size); + p->info.rows = buildDbColsInfoBlock(p, pSysDbTableMeta, size, TSDB_PERFORMANCE_SCHEMA_DB, tb); + + return p->info.rows; +} + +static int32_t mndRetrieveStbCol(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) { + SMnode *pMnode = pReq->info.node; + SSdb *pSdb = pMnode->pSdb; + SStbObj *pStb = NULL; + + int32_t numOfRows = buildSysDbColsInfo(pBlock, pShow->db, pShow->filterTb); + mDebug("mndRetrieveStbCol get system table cols, rows:%d, db:%s", numOfRows, pShow->db); + SDbObj *pDb = NULL; + if (strlen(pShow->db) > 0) { + pDb = mndAcquireDb(pMnode, pShow->db); + if (pDb == NULL) return terrno; + } + + char typeName[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(typeName, "SUPER_TABLE"); + bool fetch = pShow->restore ? false : true; + pShow->restore = false; + while (numOfRows < rows) { + if (fetch) { + pShow->pIter = sdbFetch(pSdb, SDB_STB, pShow->pIter, (void **)&pStb); + if (pShow->pIter == NULL) break; + } else { + fetch = true; + void *pKey = taosHashGetKey(pShow->pIter, NULL); + pStb = sdbAcquire(pSdb, SDB_STB, pKey); + if (!pStb) continue; + } + + if (pDb != NULL && pStb->dbUid != pDb->uid) { + sdbRelease(pSdb, pStb); + continue; + } + + SName name = {0}; + char stbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + mndExtractTbNameFromStbFullName(pStb->name, &stbName[VARSTR_HEADER_SIZE], TSDB_TABLE_NAME_LEN); + if (pShow->filterTb[0] && strncmp(pShow->filterTb, &stbName[VARSTR_HEADER_SIZE], TSDB_TABLE_NAME_LEN) != 0) { + sdbRelease(pSdb, pStb); + continue; + } + + if ((numOfRows + pStb->numOfColumns) > rows) { + pShow->restore = true; + if (numOfRows == 0) { + mError("mndRetrieveStbCol failed to get stable cols since buf:%d less than result:%d, stable name:%s, db:%s", + rows, pStb->numOfColumns, pStb->name, pStb->db); + } + sdbRelease(pSdb, pStb); + break; + } + + varDataSetLen(stbName, strlen(&stbName[VARSTR_HEADER_SIZE])); + + mDebug("mndRetrieveStbCol get stable cols, stable name:%s, db:%s", pStb->name, pStb->db); + + char db[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + tNameFromString(&name, pStb->db, T_NAME_ACCT | T_NAME_DB); + tNameGetDbName(&name, varDataVal(db)); + varDataSetLen(db, strlen(varDataVal(db))); + + for (int i = 0; i < pStb->numOfColumns; i++) { + int32_t cols = 0; + SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)stbName, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)db, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, typeName, false); + + // col name + char colName[TSDB_COL_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(colName, pStb->pColumns[i].name); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, colName, false); + + // col type + int8_t colType = pStb->pColumns[i].type; + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + char colTypeStr[VARSTR_HEADER_SIZE + 32]; + int colTypeLen = sprintf(varDataVal(colTypeStr), "%s", tDataTypes[colType].name); + if (colType == TSDB_DATA_TYPE_VARCHAR) { + colTypeLen += sprintf(varDataVal(colTypeStr) + colTypeLen, "(%d)", + (int32_t)(pStb->pColumns[i].bytes - VARSTR_HEADER_SIZE)); + } else if (colType == TSDB_DATA_TYPE_NCHAR) { + colTypeLen += sprintf(varDataVal(colTypeStr) + colTypeLen, "(%d)", + (int32_t)((pStb->pColumns[i].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)); + } + varDataSetLen(colTypeStr, colTypeLen); + colDataSetVal(pColInfo, numOfRows, (char *)colTypeStr, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)&pStb->pColumns[i].bytes, false); + while (cols < pShow->numOfColumns) { + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetNULL(pColInfo, numOfRows); + } + numOfRows++; + } + + sdbRelease(pSdb, pStb); + } + + if (pDb != NULL) { + mndReleaseDb(pMnode, pDb); + } + + pShow->numOfRows += numOfRows; + mDebug("mndRetrieveStbCol success, rows:%d, pShow->numOfRows:%d", numOfRows, pShow->numOfRows); + + return numOfRows; +} + static void mndCancelGetNextStb(SMnode *pMnode, void *pIter) { SSdb *pSdb = pMnode->pSdb; sdbCancelFetch(pSdb, pIter); @@ -2620,3 +3258,136 @@ const char *mndGetStbStr(const char *src) { if (posStb == NULL) return posDb; return posStb; } + +static int32_t mndCheckIndexReq(SCreateTagIndexReq *pReq) { + // impl + return TSDB_CODE_SUCCESS; +} + +/*int32_t mndAddIndexImpl(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb, bool needRsp, void *sql, + int32_t len) { + // impl later + int32_t code = 0; + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq, "create-stb-index"); + if (pTrans == NULL) goto _OVER; + + mInfo("trans:%d, used to add index to stb:%s", pTrans->id, pStb->name); + mndTransSetDbName(pTrans, pDb->name, pStb->name); + if (mndTrancCheckConflict(pMnode, pTrans) != 0) goto _OVER; + + if (mndSetAlterStbRedoLogs(pMnode, pTrans, pDb, pStb) != 0) goto _OVER; + if (mndSetAlterStbCommitLogs(pMnode, pTrans, pDb, pStb) != 0) goto _OVER; + if (mndSetAlterStbRedoActions2(pMnode, pTrans, pDb, pStb, sql, len) != 0) goto _OVER; + if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; + + return code; + +_OVER: + mndTransDrop(pTrans); + return code; +} +static int32_t mndAddIndex(SMnode *pMnode, SRpcMsg *pReq, SCreateTagIndexReq *tagIdxReq, SDbObj *pDb, SStbObj *pOld) { + bool needRsp = true; + int32_t code = -1; + SField *pField0 = NULL; + + SStbObj stbObj = {0}; + SStbObj *pNew = &stbObj; + + taosRLockLatch(&pOld->lock); + memcpy(&stbObj, pOld, sizeof(SStbObj)); + taosRUnLockLatch(&pOld->lock); + + stbObj.pColumns = NULL; + stbObj.pTags = NULL; + stbObj.updateTime = taosGetTimestampMs(); + stbObj.lock = 0; + + int32_t tag = mndFindSuperTableTagIndex(pOld, tagIdxReq->colName); + if (tag < 0) { + terrno = TSDB_CODE_MND_TAG_NOT_EXIST; + return -1; + } + col_id_t colId = pOld->pTags[tag].colId; + if (mndCheckColAndTagModifiable(pMnode, pOld->name, pOld->uid, colId) != 0) { + return -1; + } + if (mndAllocStbSchemas(pOld, pNew) != 0) { + return -1; + } + + SSchema *pTag = pNew->pTags + tag; + if (IS_IDX_ON(pTag)) { + terrno = TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST; + return -1; + } else { + pTag->flags |= COL_IDX_ON; + } + pNew->tagVer++; + + code = mndAddIndexImpl(pMnode, pReq, pDb, pNew, needRsp, pReq->pCont, pReq->contLen); + + return code; +} +static int32_t mndProcessCreateIndexReq(SRpcMsg *pReq) { + SMnode *pMnode = pReq->info.node; + int32_t code = -1; + SDbObj *pDb = NULL; + SStbObj *pStb = NULL; + SCreateTagIndexReq tagIdxReq = {0}; + + if (tDeserializeSCreateTagIdxReq(pReq->pCont, pReq->contLen, &tagIdxReq) != 0) { + terrno = TSDB_CODE_INVALID_MSG; + goto _OVER; + } + + mInfo("stb:%s, start to alter", tagIdxReq.stbName); + + if (mndCheckIndexReq(&tagIdxReq) != TSDB_CODE_SUCCESS) { + goto _OVER; + } + + pDb = mndAcquireDbByStb(pMnode, tagIdxReq.dbFName); + if (pDb == NULL) { + terrno = TSDB_CODE_MND_INVALID_DB; + goto _OVER; + } + + pStb = mndAcquireStb(pMnode, tagIdxReq.stbName); + if (pStb == NULL) { + terrno = TSDB_CODE_MND_STB_NOT_EXIST; + goto _OVER; + } + if (mndCheckDbPrivilege(pMnode, pReq->info.conn.user, MND_OPER_WRITE_DB, pDb) != 0) { + goto _OVER; + } + + code = mndAddIndex(pMnode, pReq, &tagIdxReq, pDb, pStb); + if (terrno == TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST || terrno == TSDB_CODE_MND_TAG_NOT_EXIST) { + return terrno; + } else { + if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; + } +_OVER: + if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { + mError("stb:%s, failed to create index since %s", tagIdxReq.stbName, terrstr()); + } + mndReleaseStb(pMnode, pStb); + mndReleaseDb(pMnode, pDb); + return code; +} +static int32_t mndProcessDropIndexReq(SRpcMsg *pReq) { + SMnode *pMnode = pReq->info.node; + int32_t code = -1; + SDbObj *pDb = NULL; + SStbObj *pStb = NULL; + SDropTagIndexReq dropReq = {0}; + if (tDeserializeSDropTagIdxReq(pReq->pCont, pReq->contLen, &dropReq) != 0) { + terrno = TSDB_CODE_INVALID_MSG; + goto _OVER; + } + // + return TSDB_CODE_SUCCESS; +_OVER: + return code; +}*/ diff --git a/source/dnode/mnode/impl/src/mndStream.c b/source/dnode/mnode/impl/src/mndStream.c index fc53fca27cb87efde05cf507272ce3773857b34c..76bb144fcb0b33ff5a832b01c9dd0b9ad9b95175 100644 --- a/source/dnode/mnode/impl/src/mndStream.c +++ b/source/dnode/mnode/impl/src/mndStream.c @@ -31,16 +31,16 @@ #define MND_STREAM_VER_NUMBER 2 #define MND_STREAM_RESERVE_SIZE 64 -#define MND_STREAM_MAX_NUM 10 +#define MND_STREAM_MAX_NUM 60 static int32_t mndStreamActionInsert(SSdb *pSdb, SStreamObj *pStream); static int32_t mndStreamActionDelete(SSdb *pSdb, SStreamObj *pStream); -static int32_t mndStreamActionUpdate(SSdb *pSdb, SStreamObj *pStream, SStreamObj *pNewStream); +static int32_t mndStreamActionUpdate(SSdb *pSdb, SStreamObj *pOldStream, SStreamObj *pNewStream); static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq); static int32_t mndProcessDropStreamReq(SRpcMsg *pReq); static int32_t mndProcessStreamCheckpointTmr(SRpcMsg *pReq); static int32_t mndProcessStreamDoCheckpoint(SRpcMsg *pReq); -/*static int32_t mndProcessRecoverStreamReq(SRpcMsg *pReq);*/ +static int32_t mndProcessRecoverStreamReq(SRpcMsg *pReq); static int32_t mndProcessStreamMetaReq(SRpcMsg *pReq); static int32_t mndGetStreamMeta(SRpcMsg *pReq, SShowObj *pShow, STableMetaRsp *pMeta); static int32_t mndRetrieveStream(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); @@ -66,8 +66,8 @@ int32_t mndInitStream(SMnode *pMnode) { mndSetMsgHandle(pMnode, TDMT_STREAM_TASK_DEPLOY_RSP, mndTransProcessRsp); mndSetMsgHandle(pMnode, TDMT_STREAM_TASK_DROP_RSP, mndTransProcessRsp); - mndSetMsgHandle(pMnode, TDMT_MND_STREAM_CHECKPOINT_TIMER, mndProcessStreamCheckpointTmr); - mndSetMsgHandle(pMnode, TDMT_MND_STREAM_BEGIN_CHECKPOINT, mndProcessStreamDoCheckpoint); + // mndSetMsgHandle(pMnode, TDMT_MND_STREAM_CHECKPOINT_TIMER, mndProcessStreamCheckpointTmr); + // mndSetMsgHandle(pMnode, TDMT_MND_STREAM_BEGIN_CHECKPOINT, mndProcessStreamDoCheckpoint); mndSetMsgHandle(pMnode, TDMT_STREAM_TASK_REPORT_CHECKPOINT, mndTransProcessRsp); mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_STREAMS, mndRetrieveStream); @@ -318,7 +318,11 @@ static int32_t mndBuildStreamObjFromCreateReq(SMnode *pMnode, SStreamObj *pObj, } tstrncpy(pObj->targetDb, pTargetDb->name, TSDB_DB_FNAME_LEN); - pObj->targetStbUid = mndGenerateUid(pObj->targetSTbName, TSDB_TABLE_FNAME_LEN); + if (pCreate->createStb == STREAM_CREATE_STABLE_TRUE) { + pObj->targetStbUid = mndGenerateUid(pObj->targetSTbName, TSDB_TABLE_FNAME_LEN); + } else { + pObj->targetStbUid = pCreate->targetStbUid; + } pObj->targetDbUid = pTargetDb->uid; mndReleaseDb(pMnode, pTargetDb); @@ -330,16 +334,46 @@ static int32_t mndBuildStreamObjFromCreateReq(SMnode *pMnode, SStreamObj *pObj, // deserialize ast if (nodesStringToNode(pObj->ast, &pAst) < 0) { - /*ASSERT(0);*/ goto FAIL; } // extract output schema from ast if (qExtractResultSchema(pAst, (int32_t *)&pObj->outputSchema.nCols, &pObj->outputSchema.pSchema) != 0) { - /*ASSERT(0);*/ goto FAIL; } + int32_t numOfNULL = taosArrayGetSize(pCreate->fillNullCols); + if (numOfNULL > 0) { + pObj->outputSchema.nCols += numOfNULL; + SSchema *pFullSchema = taosMemoryCalloc(pObj->outputSchema.nCols, sizeof(SSchema)); + if (!pFullSchema) { + goto FAIL; + } + + int32_t nullIndex = 0; + int32_t dataIndex = 0; + for (int16_t i = 0; i < pObj->outputSchema.nCols; i++) { + SColLocation *pos = taosArrayGet(pCreate->fillNullCols, nullIndex); + if (nullIndex >= numOfNULL || i < pos->slotId) { + pFullSchema[i].bytes = pObj->outputSchema.pSchema[dataIndex].bytes; + pFullSchema[i].colId = i + 1; // pObj->outputSchema.pSchema[dataIndex].colId; + pFullSchema[i].flags = pObj->outputSchema.pSchema[dataIndex].flags; + strcpy(pFullSchema[i].name, pObj->outputSchema.pSchema[dataIndex].name); + pFullSchema[i].type = pObj->outputSchema.pSchema[dataIndex].type; + dataIndex++; + } else { + pFullSchema[i].bytes = 0; + pFullSchema[i].colId = pos->colId; + pFullSchema[i].flags = COL_SET_NULL; + memset(pFullSchema[i].name, 0, TSDB_COL_NAME_LEN); + pFullSchema[i].type = pos->type; + nullIndex++; + } + } + taosMemoryFree(pObj->outputSchema.pSchema); + pObj->outputSchema.pSchema = pFullSchema; + } + SPlanContext cxt = { .pAstRoot = pAst, .topicQuery = false, @@ -353,13 +387,11 @@ static int32_t mndBuildStreamObjFromCreateReq(SMnode *pMnode, SStreamObj *pObj, // using ast and param to build physical plan if (qCreateQueryPlan(&cxt, &pPlan, NULL) < 0) { - /*ASSERT(0);*/ goto FAIL; } // save physcial plan if (nodesNodeToString((SNode *)pPlan, false, &pObj->physicalPlan, NULL) != 0) { - /*ASSERT(0);*/ goto FAIL; } @@ -367,7 +399,7 @@ static int32_t mndBuildStreamObjFromCreateReq(SMnode *pMnode, SStreamObj *pObj, if (pCreate->numOfTags) { pObj->tagSchema.pSchema = taosMemoryCalloc(pCreate->numOfTags, sizeof(SSchema)); } - ASSERT(pCreate->numOfTags == taosArrayGetSize(pCreate->pTags)); + /*A(pCreate->numOfTags == taosArrayGetSize(pCreate->pTags));*/ for (int32_t i = 0; i < pCreate->numOfTags; i++) { SField *pField = taosArrayGet(pCreate->pTags, i); pObj->tagSchema.pSchema[i].colId = pObj->outputSchema.nCols + i + 1; @@ -384,12 +416,9 @@ FAIL: } int32_t mndPersistTaskDeployReq(STrans *pTrans, const SStreamTask *pTask) { - if (pTask->taskLevel == TASK_LEVEL__AGG) { - ASSERT(taosArrayGetSize(pTask->childEpInfo) != 0); - } SEncoder encoder; tEncoderInit(&encoder, NULL, 0); - tEncodeSStreamTask(&encoder, pTask); + tEncodeStreamTask(&encoder, pTask); int32_t size = encoder.pos; int32_t tlen = sizeof(SMsgHead) + size; tEncoderClear(&encoder); @@ -401,10 +430,11 @@ int32_t mndPersistTaskDeployReq(STrans *pTrans, const SStreamTask *pTask) { ((SMsgHead *)buf)->vgId = htonl(pTask->nodeId); void *abuf = POINTER_SHIFT(buf, sizeof(SMsgHead)); tEncoderInit(&encoder, abuf, size); - tEncodeSStreamTask(&encoder, pTask); + tEncodeStreamTask(&encoder, pTask); tEncoderClear(&encoder); STransAction action = {0}; + action.mTraceId = pTrans->mTraceId; memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet)); action.pCont = buf; action.contLen = tlen; @@ -479,7 +509,7 @@ static int32_t mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStre tstrncpy(createReq.name, pStream->targetSTbName, TSDB_TABLE_FNAME_LEN); createReq.numOfColumns = pStream->outputSchema.nCols; createReq.numOfTags = 1; // group id - createReq.pColumns = taosArrayInit_s(createReq.numOfColumns, sizeof(SField), createReq.numOfColumns); + createReq.pColumns = taosArrayInit_s(sizeof(SField), createReq.numOfColumns); // build fields for (int32_t i = 0; i < createReq.numOfColumns; i++) { SField *pField = taosArrayGet(createReq.pColumns, i); @@ -488,14 +518,27 @@ static int32_t mndCreateStbForStream(SMnode *pMnode, STrans *pTrans, const SStre pField->type = pStream->outputSchema.pSchema[i].type; pField->bytes = pStream->outputSchema.pSchema[i].bytes; } - createReq.pTags = taosArrayInit_s(createReq.numOfTags, sizeof(SField), 1); - // build tags - SField *pField = taosArrayGet(createReq.pTags, 0); - strcpy(pField->name, "group_id"); - pField->type = TSDB_DATA_TYPE_UBIGINT; - pField->flags = 0; - pField->bytes = 8; + if (pStream->tagSchema.nCols == 0) { + createReq.numOfTags = 1; + createReq.pTags = taosArrayInit_s(sizeof(SField), 1); + // build tags + SField *pField = taosArrayGet(createReq.pTags, 0); + strcpy(pField->name, "group_id"); + pField->type = TSDB_DATA_TYPE_UBIGINT; + pField->flags = 0; + pField->bytes = 8; + } else { + createReq.numOfTags = pStream->tagSchema.nCols; + createReq.pTags = taosArrayInit_s(sizeof(SField), createReq.numOfTags); + for (int32_t i = 0; i < createReq.numOfTags; i++) { + SField *pField = taosArrayGet(createReq.pTags, i); + pField->bytes = pStream->tagSchema.pSchema[i].bytes; + pField->flags = pStream->tagSchema.pSchema[i].flags; + pField->type = pStream->tagSchema.pSchema[i].type; + tstrncpy(pField->name, pStream->tagSchema.pSchema[i].name, TSDB_COL_NAME_LEN); + } + } if (mndCheckCreateStbReq(&createReq) != 0) { goto _OVER; @@ -550,8 +593,6 @@ _OVER: } static int32_t mndPersistTaskDropReq(STrans *pTrans, SStreamTask *pTask) { - ASSERT(pTask->nodeId != 0); - // vnode /*if (pTask->nodeId > 0) {*/ SVDropStreamTaskReq *pReq = taosMemoryCalloc(1, sizeof(SVDropStreamTaskReq)); @@ -560,7 +601,7 @@ static int32_t mndPersistTaskDropReq(STrans *pTrans, SStreamTask *pTask) { return -1; } pReq->head.vgId = htonl(pTask->nodeId); - pReq->taskId = pTask->taskId; + pReq->taskId = pTask->id.taskId; STransAction action = {0}; memcpy(&action.epSet, &pTask->epSet, sizeof(SEpSet)); action.pCont = pReq; @@ -640,7 +681,7 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) { pIter = sdbFetch(pMnode->pSdb, SDB_STREAM, pIter, (void **)&pStream); if (pIter == NULL) { if (numOfStream > MND_STREAM_MAX_NUM) { - mError("too many streams, no more than 10 for each database"); + mError("too many streams, no more than %d for each database", MND_STREAM_MAX_NUM); terrno = TSDB_CODE_MND_TOO_MANY_STREAMS; goto _OVER; } @@ -652,10 +693,16 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) { } sdbRelease(pMnode->pSdb, pStream); if (numOfStream > MND_STREAM_MAX_NUM) { - mError("too many streams, no more than 10 for each database"); + mError("too many streams, no more than %d for each database", MND_STREAM_MAX_NUM); terrno = TSDB_CODE_MND_TOO_MANY_STREAMS; goto _OVER; } + + if (pStream->targetStbUid == streamObj.targetStbUid) { + mError("Cannot write the same stable as other stream:%s", pStream->name); + terrno = TSDB_CODE_MND_INVALID_TARGET_TABLE; + goto _OVER; + } } } @@ -677,10 +724,13 @@ static int32_t mndProcessCreateStreamReq(SRpcMsg *pReq) { mInfo("trans:%d, used to create stream:%s", pTrans->id, createStreamReq.name); mndTransSetDbName(pTrans, createStreamReq.sourceDB, streamObj.targetDb); - if (mndTrancCheckConflict(pMnode, pTrans) != 0) goto _OVER; - + if (mndTrancCheckConflict(pMnode, pTrans) != 0) { + mndTransDrop(pTrans); + goto _OVER; + } // create stb for stream - if (mndCreateStbForStream(pMnode, pTrans, &streamObj, pReq->info.conn.user) < 0) { + if (createStreamReq.createStb == STREAM_CREATE_STABLE_TRUE && + mndCreateStbForStream(pMnode, pTrans, &streamObj, pReq->info.conn.user) < 0) { mError("trans:%d, failed to create stb for stream %s since %s", pTrans->id, createStreamReq.name, terrstr()); mndTransDrop(pTrans); goto _OVER; @@ -732,6 +782,9 @@ _OVER: tFreeStreamObj(&streamObj); return code; } + +#if 0 + static int32_t mndProcessStreamCheckpointTmr(SRpcMsg *pReq) { SMnode *pMnode = pReq->info.node; SSdb *pSdb = pMnode->pSdb; @@ -842,10 +895,9 @@ static int32_t mndProcessStreamDoCheckpoint(SRpcMsg *pReq) { int32_t sz = taosArrayGetSize(pLevel); for (int32_t j = 0; j < sz; j++) { SStreamTask *pTask = taosArrayGetP(pLevel, j); - ASSERT(pTask->nodeId > 0); + /*A(pTask->nodeId > 0);*/ SVgObj *pVgObj = mndAcquireVgroup(pMnode, pTask->nodeId); if (pVgObj == NULL) { - ASSERT(0); taosRUnLockLatch(&pStream->lock); mndReleaseStream(pMnode, pStream); mndTransDrop(pTrans); @@ -897,6 +949,8 @@ static int32_t mndProcessStreamDoCheckpoint(SRpcMsg *pReq) { return 0; } +#endif + static int32_t mndProcessDropStreamReq(SRpcMsg *pReq) { SMnode *pMnode = pReq->info.node; SStreamObj *pStream = NULL; @@ -905,7 +959,6 @@ static int32_t mndProcessDropStreamReq(SRpcMsg *pReq) { SMDropStreamReq dropReq = {0}; if (tDeserializeSMDropStreamReq(pReq->pCont, pReq->contLen, &dropReq) < 0) { - ASSERT(0); terrno = TSDB_CODE_INVALID_MSG; return -1; } @@ -1055,52 +1108,52 @@ static int32_t mndRetrieveStream(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB char streamName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(streamName, mndGetDbStr(pStream->name), sizeof(streamName)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)streamName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)streamName, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pStream->createTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pStream->createTime, false); char sql[TSDB_SHOW_SQL_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(sql, pStream->sql, sizeof(sql)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)sql, false); + colDataSetVal(pColInfo, numOfRows, (const char *)sql, false); char status[20 + VARSTR_HEADER_SIZE] = {0}; char status2[20] = {0}; mndShowStreamStatus(status2, pStream); STR_WITH_MAXSIZE_TO_VARSTR(status, status2, sizeof(status)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&status, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&status, false); char sourceDB[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(sourceDB, mndGetDbStr(pStream->sourceDb), sizeof(sourceDB)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&sourceDB, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&sourceDB, false); char targetDB[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(targetDB, mndGetDbStr(pStream->targetDb), sizeof(targetDB)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&targetDB, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&targetDB, false); if (pStream->targetSTbName[0] == 0) { pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, NULL, true); + colDataSetVal(pColInfo, numOfRows, NULL, true); } else { char targetSTB[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(targetSTB, mndGetStbStr(pStream->targetSTbName), sizeof(targetSTB)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&targetSTB, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&targetSTB, false); } pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pStream->watermark, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pStream->watermark, false); char trigger[20 + VARSTR_HEADER_SIZE] = {0}; char trigger2[20] = {0}; mndShowStreamTrigger(trigger2, pStream); STR_WITH_MAXSIZE_TO_VARSTR(trigger, trigger2, sizeof(trigger)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&trigger, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&trigger, false); numOfRows++; sdbRelease(pSdb, pStream); @@ -1152,11 +1205,11 @@ static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock char streamName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(streamName, mndGetDbStr(pStream->name), sizeof(streamName)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)streamName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)streamName, false); // task id pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pTask->taskId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pTask->id.taskId, false); // node type char nodeType[20 + VARSTR_HEADER_SIZE] = {0}; @@ -1167,12 +1220,12 @@ static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock } else { memcpy(varDataVal(nodeType), "snode", 5); } - colDataAppend(pColInfo, numOfRows, nodeType, false); + colDataSetVal(pColInfo, numOfRows, nodeType, false); // node id pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - int32_t nodeId = TMAX(pTask->nodeId, 0); - colDataAppend(pColInfo, numOfRows, (const char *)&nodeId, false); + int64_t nodeId = TMAX(pTask->nodeId, 0); + colDataSetVal(pColInfo, numOfRows, (const char *)&nodeId, false); // level char level[20 + VARSTR_HEADER_SIZE] = {0}; @@ -1188,7 +1241,7 @@ static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock } else if (pTask->taskLevel == TASK_LEVEL__SINK) { } pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&level, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&level, false); // status char status[20 + VARSTR_HEADER_SIZE] = {0}; @@ -1196,7 +1249,7 @@ static int32_t mndRetrieveStreamTask(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock strcpy(status, "normal"); STR_WITH_MAXSIZE_TO_VARSTR(status, status2, sizeof(status)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&status, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&status, false); numOfRows++; } diff --git a/source/dnode/mnode/impl/src/mndSubscribe.c b/source/dnode/mnode/impl/src/mndSubscribe.c index 153bb8bd04b73bf3c025851a0f2d00b1f6908eac..e62102fa77254c37e0d8244ae437a9570f870dfb 100644 --- a/source/dnode/mnode/impl/src/mndSubscribe.c +++ b/source/dnode/mnode/impl/src/mndSubscribe.c @@ -16,15 +16,10 @@ #define _DEFAULT_SOURCE #include "mndSubscribe.h" #include "mndConsumer.h" -#include "mndDb.h" -#include "mndDnode.h" -#include "mndMnode.h" #include "mndScheduler.h" #include "mndShow.h" -#include "mndStb.h" #include "mndTopic.h" #include "mndTrans.h" -#include "mndUser.h" #include "mndVgroup.h" #include "tcompare.h" #include "tname.h" @@ -39,12 +34,10 @@ static SSdbRow *mndSubActionDecode(SSdbRaw *pRaw); static int32_t mndSubActionInsert(SSdb *pSdb, SMqSubscribeObj *); static int32_t mndSubActionDelete(SSdb *pSdb, SMqSubscribeObj *); static int32_t mndSubActionUpdate(SSdb *pSdb, SMqSubscribeObj *pOldSub, SMqSubscribeObj *pNewSub); - -static int32_t mndProcessRebalanceReq(SRpcMsg *pMsg); -static int32_t mndProcessDropCgroupReq(SRpcMsg *pMsg); - -static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); -static void mndCancelGetNextSubscribe(SMnode *pMnode, void *pIter); +static int32_t mndProcessRebalanceReq(SRpcMsg *pMsg); +static int32_t mndProcessDropCgroupReq(SRpcMsg *pMsg); +static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows); +static void mndCancelGetNextSubscribe(SMnode *pMnode, void *pIter); static int32_t mndSetSubRedoLogs(SMnode *pMnode, STrans *pTrans, SMqSubscribeObj *pSub) { SSdbRaw *pRedoRaw = mndSubActionEncode(pSub); @@ -85,12 +78,13 @@ int32_t mndInitSubscribe(SMnode *pMnode) { return sdbSetTable(pMnode->pSdb, table); } -static SMqSubscribeObj *mndCreateSub(SMnode *pMnode, const SMqTopicObj *pTopic, const char *subKey) { +static SMqSubscribeObj *mndCreateSubscription(SMnode *pMnode, const SMqTopicObj *pTopic, const char *subKey) { SMqSubscribeObj *pSub = tNewSubscribeObj(subKey); if (pSub == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } + pSub->dbUid = pTopic->dbUid; pSub->stbUid = pTopic->stbUid; pSub->subType = pTopic->subType; @@ -123,6 +117,7 @@ static int32_t mndBuildSubChangeReq(void **pBuf, int32_t *pLen, const SMqSubscri terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } + SMsgHead *pMsgHead = (SMsgHead *)buf; pMsgHead->contLen = htonl(tlen); @@ -138,10 +133,10 @@ static int32_t mndBuildSubChangeReq(void **pBuf, int32_t *pLen, const SMqSubscri static int32_t mndPersistSubChangeVgReq(SMnode *pMnode, STrans *pTrans, const SMqSubscribeObj *pSub, const SMqRebOutputVg *pRebVg) { - if (pRebVg->oldConsumerId == pRebVg->newConsumerId) { - terrno = TSDB_CODE_MND_INVALID_SUB_OPTION; - return -1; - } +// if (pRebVg->oldConsumerId == pRebVg->newConsumerId) { +// terrno = TSDB_CODE_MND_INVALID_SUB_OPTION; +// return -1; +// } void *buf; int32_t tlen; @@ -202,108 +197,126 @@ static SMqRebInfo *mndGetOrCreateRebSub(SHashObj *pHash, const char *key) { return pRebSub; } -static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqRebOutputObj *pOutput) { - int32_t totalVgNum = pOutput->pSub->vgNum; - const char *sub = pOutput->pSub->key; - mInfo("sub:%s, mq rebalance vgNum:%d", sub, pOutput->pSub->vgNum); - - // 1. build temporary hash(vgId -> SMqRebOutputVg) to store modified vg - SHashObj *pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); +static void doRemoveLostConsumers(SMqRebOutputObj *pOutput, SHashObj *pHash, const SMqRebInputObj *pInput) { + int32_t numOfRemoved = taosArrayGetSize(pInput->pRebInfo->removedConsumers); + const char *pSubKey = pOutput->pSub->key; - // 2. check and get actual removed consumers, put their vg into hash - int32_t removedNum = taosArrayGetSize(pInput->pRebInfo->removedConsumers); int32_t actualRemoved = 0; - for (int32_t i = 0; i < removedNum; i++) { - int64_t consumerId = *(int64_t *)taosArrayGet(pInput->pRebInfo->removedConsumers, i); + for (int32_t i = 0; i < numOfRemoved; i++) { + uint64_t consumerId = *(uint64_t *)taosArrayGet(pInput->pRebInfo->removedConsumers, i); SMqConsumerEp *pConsumerEp = taosHashGet(pOutput->pSub->consumerHash, &consumerId, sizeof(int64_t)); + // consumer exists till now if (pConsumerEp) { actualRemoved++; + int32_t consumerVgNum = taosArrayGetSize(pConsumerEp->vgs); for (int32_t j = 0; j < consumerVgNum; j++) { - SMqVgEp *pVgEp = taosArrayGetP(pConsumerEp->vgs, j); - SMqRebOutputVg outputVg = { - .oldConsumerId = consumerId, - .newConsumerId = -1, - .pVgEp = pVgEp, - }; + SMqVgEp *pVgEp = taosArrayGetP(pConsumerEp->vgs, j); + + SMqRebOutputVg outputVg = {.oldConsumerId = consumerId, .newConsumerId = -1, .pVgEp = pVgEp}; taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &outputVg, sizeof(SMqRebOutputVg)); - mInfo("sub:%s, mq rebalance remove vgId:%d from consumer:%" PRId64, sub, pVgEp->vgId, consumerId); + mInfo("sub:%s mq re-balance remove vgId:%d from consumer:%" PRIx64, pSubKey, pVgEp->vgId, consumerId); } + taosArrayDestroy(pConsumerEp->vgs); taosHashRemove(pOutput->pSub->consumerHash, &consumerId, sizeof(int64_t)); + // put into removed taosArrayPush(pOutput->removedConsumers, &consumerId); } } - if (removedNum != actualRemoved) { - mError("sub:%s, mq rebalance removedNum:%d not matched with actual:%d", sub, removedNum, actualRemoved); + if (numOfRemoved != actualRemoved) { + mError("sub:%s mq re-balance removedNum:%d not matched with actual:%d", pSubKey, numOfRemoved, actualRemoved); + } else { + mInfo("sub:%s removed %d consumers", pSubKey, numOfRemoved); } +} - // if previously no consumer, there are vgs not assigned - { - int32_t consumerVgNum = taosArrayGetSize(pOutput->pSub->unassignedVgs); - for (int32_t i = 0; i < consumerVgNum; i++) { - SMqVgEp *pVgEp = *(SMqVgEp **)taosArrayPop(pOutput->pSub->unassignedVgs); - SMqRebOutputVg rebOutput = { - .oldConsumerId = -1, - .newConsumerId = -1, - .pVgEp = pVgEp, - }; - taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &rebOutput, sizeof(SMqRebOutputVg)); - mInfo("sub:%s, mq rebalance remove vgId:%d from unassigned", sub, pVgEp->vgId); - } +static void doAddNewConsumers(SMqRebOutputObj *pOutput, const SMqRebInputObj *pInput) { + int32_t numOfNewConsumers = taosArrayGetSize(pInput->pRebInfo->newConsumers); + const char *pSubKey = pOutput->pSub->key; + + for (int32_t i = 0; i < numOfNewConsumers; i++) { + int64_t consumerId = *(int64_t *)taosArrayGet(pInput->pRebInfo->newConsumers, i); + + SMqConsumerEp newConsumerEp; + newConsumerEp.consumerId = consumerId; + newConsumerEp.vgs = taosArrayInit(0, sizeof(void *)); + + taosHashPut(pOutput->pSub->consumerHash, &consumerId, sizeof(int64_t), &newConsumerEp, sizeof(SMqConsumerEp)); + taosArrayPush(pOutput->newConsumers, &consumerId); + mInfo("sub:%s mq rebalance add new consumer:%" PRIx64, pSubKey, consumerId); } +} - // 3. calc vg number of each consumer - int32_t afterRebConsumerNum = pInput->oldConsumerNum + taosArrayGetSize(pInput->pRebInfo->newConsumers) - - taosArrayGetSize(pInput->pRebInfo->removedConsumers); - int32_t minVgCnt = 0; - int32_t imbConsumerNum = 0; - // calc num - if (afterRebConsumerNum) { - minVgCnt = totalVgNum / afterRebConsumerNum; - imbConsumerNum = totalVgNum % afterRebConsumerNum; +static void addUnassignedVgroups(SMqRebOutputObj *pOutput, SHashObj *pHash) { + const char *pSubKey = pOutput->pSub->key; + int32_t numOfVgroups = taosArrayGetSize(pOutput->pSub->unassignedVgs); + + for (int32_t i = 0; i < numOfVgroups; i++) { + SMqVgEp *pVgEp = *(SMqVgEp **)taosArrayPop(pOutput->pSub->unassignedVgs); + SMqRebOutputVg rebOutput = { + .oldConsumerId = -1, + .newConsumerId = -1, + .pVgEp = pVgEp, + }; + + taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &rebOutput, sizeof(SMqRebOutputVg)); + mInfo("sub:%s mq re-balance addUnassignedVgroups vgId:%d from unassigned", pSubKey, pVgEp->vgId); + } +} + +static void putNoTransferToOutput(SMqRebOutputObj *pOutput, SMqConsumerEp *pConsumerEp){ + for(int i = 0; i < taosArrayGetSize(pConsumerEp->vgs); i++){ + SMqVgEp *pVgEp = (SMqVgEp *)taosArrayGetP(pConsumerEp->vgs, i); + SMqRebOutputVg outputVg = { + .oldConsumerId = pConsumerEp->consumerId, + .newConsumerId = pConsumerEp->consumerId, + .pVgEp = pVgEp, + }; + taosArrayPush(pOutput->rebVgs, &outputVg); } - mInfo("sub:%s, mq rebalance %d consumer after rebalance, at least %d vg each, %d consumer has more vg", sub, - afterRebConsumerNum, minVgCnt, imbConsumerNum); +} + +static void transferVgroupsForConsumers(SMqRebOutputObj *pOutput, SHashObj *pHash, int32_t minVgCnt, + int32_t imbConsumerNum) { + const char *pSubKey = pOutput->pSub->key; - // 4. first scan: remove consumer more than wanted, put to remove hash int32_t imbCnt = 0; void *pIter = NULL; + while (1) { pIter = taosHashIterate(pOutput->pSub->consumerHash, pIter); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } + SMqConsumerEp *pConsumerEp = (SMqConsumerEp *)pIter; + int32_t consumerVgNum = taosArrayGetSize(pConsumerEp->vgs); - int32_t consumerVgNum = taosArrayGetSize(pConsumerEp->vgs); - // all old consumers still existing are touched - // TODO optimize: touch only consumer whose vgs changed - taosArrayPush(pOutput->touchedConsumers, &pConsumerEp->consumerId); + // all old consumers still existing need to be modified + // TODO optimize: modify only consumer whose vgs changed + taosArrayPush(pOutput->modifyConsumers, &pConsumerEp->consumerId); if (consumerVgNum > minVgCnt) { if (imbCnt < imbConsumerNum) { - if (consumerVgNum == minVgCnt + 1) { - imbCnt++; - continue; - } else { - // pop until equal minVg + 1 - while (taosArrayGetSize(pConsumerEp->vgs) > minVgCnt + 1) { - SMqVgEp *pVgEp = *(SMqVgEp **)taosArrayPop(pConsumerEp->vgs); - SMqRebOutputVg outputVg = { - .oldConsumerId = pConsumerEp->consumerId, - .newConsumerId = -1, - .pVgEp = pVgEp, - }; - taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &outputVg, sizeof(SMqRebOutputVg)); - mInfo("sub:%s, mq rebalance remove vgId:%d from consumer:%" PRId64 ",(first scan)", sub, pVgEp->vgId, - pConsumerEp->consumerId); - } - imbCnt++; + // pop until equal minVg + 1 + while (taosArrayGetSize(pConsumerEp->vgs) > minVgCnt + 1) { + SMqVgEp *pVgEp = *(SMqVgEp **)taosArrayPop(pConsumerEp->vgs); + SMqRebOutputVg outputVg = { + .oldConsumerId = pConsumerEp->consumerId, + .newConsumerId = -1, + .pVgEp = pVgEp, + }; + taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &outputVg, sizeof(SMqRebOutputVg)); + mInfo("sub:%s mq rebalance remove vgId:%d from consumer:0x%" PRIx64 ",(first scan)", pSubKey, pVgEp->vgId, + pConsumerEp->consumerId); } + imbCnt++; } else { - // pop until equal minVg + // all the remain consumers should only have the number of vgroups, which is equalled to the value of minVg while (taosArrayGetSize(pConsumerEp->vgs) > minVgCnt) { SMqVgEp *pVgEp = *(SMqVgEp **)taosArrayPop(pConsumerEp->vgs); SMqRebOutputVg outputVg = { @@ -312,36 +325,66 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR .pVgEp = pVgEp, }; taosHashPut(pHash, &pVgEp->vgId, sizeof(int32_t), &outputVg, sizeof(SMqRebOutputVg)); - mInfo("sub:%s, mq rebalance remove vgId:%d from consumer:%" PRId64 ",(first scan)", sub, pVgEp->vgId, + mInfo("sub:%s mq rebalance remove vgId:%d from consumer:0x%" PRIx64 ",(first scan)", pSubKey, pVgEp->vgId, pConsumerEp->consumerId); } } } + putNoTransferToOutput(pOutput, pConsumerEp); } +} - // 5. add new consumer into sub - { - int32_t consumerNum = taosArrayGetSize(pInput->pRebInfo->newConsumers); - for (int32_t i = 0; i < consumerNum; i++) { - int64_t consumerId = *(int64_t *)taosArrayGet(pInput->pRebInfo->newConsumers, i); - - SMqConsumerEp newConsumerEp; - newConsumerEp.consumerId = consumerId; - newConsumerEp.vgs = taosArrayInit(0, sizeof(void *)); - taosHashPut(pOutput->pSub->consumerHash, &consumerId, sizeof(int64_t), &newConsumerEp, sizeof(SMqConsumerEp)); - taosArrayPush(pOutput->newConsumers, &consumerId); - mInfo("sub:%s, mq rebalance add new consumer:%" PRId64, sub, consumerId); - } +static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqRebOutputObj *pOutput) { + int32_t totalVgNum = pOutput->pSub->vgNum; + const char *pSubKey = pOutput->pSub->key; + + int32_t numOfRemoved = taosArrayGetSize(pInput->pRebInfo->removedConsumers); + int32_t numOfAdded = taosArrayGetSize(pInput->pRebInfo->newConsumers); + mInfo("sub:%s mq re-balance %d vgroups, existed consumers:%d, added:%d, removed:%d", pSubKey, totalVgNum, + pInput->oldConsumerNum, numOfAdded, numOfRemoved); + + // 1. build temporary hash(vgId -> SMqRebOutputVg) to store vg that need to be assigned + SHashObj *pHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); + + // 2. check and get actual removed consumers, put their vg into pHash + doRemoveLostConsumers(pOutput, pHash, pInput); + + // 3. if previously no consumer, there are vgs not assigned, put these vg into pHash + addUnassignedVgroups(pOutput, pHash); + + // 4. calc vg number of each consumer + int32_t numOfFinal = pInput->oldConsumerNum + numOfAdded - numOfRemoved; + + int32_t minVgCnt = 0; + int32_t imbConsumerNum = 0; + + // calc num + if (numOfFinal) { + minVgCnt = totalVgNum / numOfFinal; + imbConsumerNum = totalVgNum % numOfFinal; + mInfo("sub:%s mq re-balance %d consumers: at least %d vgs each, %d consumers has 1 more vgroups than avg value", + pSubKey, numOfFinal, minVgCnt, imbConsumerNum); + } else { + mInfo("sub:%s no consumer subscribe this topic", pSubKey); } - // 6. second scan: find consumer do not have enough vg, extract from temporary hash and assign to new consumer. - // All related vg should be put into rebVgs + // 5. remove vgroups from consumers who have more vgroups than the threshold value(minVgCnt or minVgCnt + 1), and then another vg into pHash + transferVgroupsForConsumers(pOutput, pHash, minVgCnt, imbConsumerNum); + + // 6. add new consumer into sub + doAddNewConsumers(pOutput, pInput); + SMqRebOutputVg *pRebVg = NULL; void *pRemovedIter = NULL; - pIter = NULL; + void *pIter = NULL; + + // 7. extract bgroups from pHash and assign to consumers that do not have enough vgroups while (1) { pIter = taosHashIterate(pOutput->pSub->consumerHash, pIter); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } + SMqConsumerEp *pConsumerEp = (SMqConsumerEp *)pIter; // push until equal minVg @@ -349,88 +392,74 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR // iter hash and find one vg pRemovedIter = taosHashIterate(pHash, pRemovedIter); if (pRemovedIter == NULL) { - mError("sub:%s, removed iter is null", sub); - continue; + mError("sub:%s removed iter is null, never can reach hear", pSubKey); + break; } pRebVg = (SMqRebOutputVg *)pRemovedIter; - // push - taosArrayPush(pConsumerEp->vgs, &pRebVg->pVgEp); pRebVg->newConsumerId = pConsumerEp->consumerId; - taosArrayPush(pOutput->rebVgs, pRebVg); - mInfo("mq rebalance: add vgId:%d to consumer:%" PRId64 " (second scan) (not enough)", pRebVg->pVgEp->vgId, - pConsumerEp->consumerId); + taosArrayPush(pConsumerEp->vgs, &pRebVg->pVgEp); + mInfo("mq rebalance: add vgId:%d to consumer:0x%" PRIx64 " for average", pRebVg->pVgEp->vgId, pConsumerEp->consumerId); } } - // 7. handle unassigned vg - if (taosHashGetSize(pOutput->pSub->consumerHash) != 0) { - // if has consumer, assign all left vg - while (1) { - SMqConsumerEp *pConsumerEp = NULL; + while (1) { + pIter = taosHashIterate(pOutput->pSub->consumerHash, pIter); + if (pIter == NULL) { + break; + } + SMqConsumerEp *pConsumerEp = (SMqConsumerEp *)pIter; + + if (taosArrayGetSize(pConsumerEp->vgs) == minVgCnt) { pRemovedIter = taosHashIterate(pHash, pRemovedIter); if (pRemovedIter == NULL) { - if (pIter != NULL) { - taosHashCancelIterate(pOutput->pSub->consumerHash, pIter); - pIter = NULL; - } + mInfo("sub:%s removed iter is null", pSubKey); break; } - while (1) { - pIter = taosHashIterate(pOutput->pSub->consumerHash, pIter); - pConsumerEp = (SMqConsumerEp *)pIter; - if (taosArrayGetSize(pConsumerEp->vgs) == minVgCnt) { - break; - } - } pRebVg = (SMqRebOutputVg *)pRemovedIter; - taosArrayPush(pConsumerEp->vgs, &pRebVg->pVgEp); pRebVg->newConsumerId = pConsumerEp->consumerId; - if (pRebVg->newConsumerId == pRebVg->oldConsumerId) { - mInfo("mq rebalance: skip vg %d for same consumer:%" PRId64 " (second scan)", pRebVg->pVgEp->vgId, - pConsumerEp->consumerId); - continue; - } - taosArrayPush(pOutput->rebVgs, pRebVg); - mInfo("mq rebalance: add vgId:%d to consumer:%" PRId64 " (second scan) (unassigned)", pRebVg->pVgEp->vgId, - pConsumerEp->consumerId); + taosArrayPush(pConsumerEp->vgs, &pRebVg->pVgEp); + mInfo("mq rebalance: add vgId:%d to consumer:0x%" PRIx64 " for average + 1", pRebVg->pVgEp->vgId, pConsumerEp->consumerId); } - } else { - // if all consumer is removed, put all vg into unassigned - pIter = NULL; - SMqRebOutputVg *pRebOutput = NULL; - while (1) { - pIter = taosHashIterate(pHash, pIter); - if (pIter == NULL) break; - pRebOutput = (SMqRebOutputVg *)pIter; + } + // All assigned vg should be put into pOutput->rebVgs + if(pRemovedIter != NULL){ + mError("sub:%s error pRemovedIter should be NULL", pSubKey); + } + while (1) { + pRemovedIter = taosHashIterate(pHash, pRemovedIter); + if (pRemovedIter == NULL) { + break; + } + + SMqRebOutputVg* pRebOutput = (SMqRebOutputVg *)pRemovedIter; + taosArrayPush(pOutput->rebVgs, pRebOutput); + if(taosHashGetSize(pOutput->pSub->consumerHash) == 0){ // if all consumer is removed, put all vg into unassigned taosArrayPush(pOutput->pSub->unassignedVgs, &pRebOutput->pVgEp); - taosArrayPush(pOutput->rebVgs, pRebOutput); - mInfo("sub:%s, mq rebalance unassign vgId:%d (second scan)", sub, pRebOutput->pVgEp->vgId); } } // 8. generate logs - mInfo("sub:%s, mq rebalance calculation completed, rebalanced vg", sub); + mInfo("sub:%s mq re-balance calculation completed, re-balanced vg", pSubKey); for (int32_t i = 0; i < taosArrayGetSize(pOutput->rebVgs); i++) { SMqRebOutputVg *pOutputRebVg = taosArrayGet(pOutput->rebVgs, i); - mInfo("sub:%s, mq rebalance vgId:%d, moved from consumer:%" PRId64 ", to consumer:%" PRId64, sub, + mInfo("sub:%s mq re-balance vgId:%d, moved from consumer:0x%" PRIx64 ", to consumer:0x%" PRIx64, pSubKey, pOutputRebVg->pVgEp->vgId, pOutputRebVg->oldConsumerId, pOutputRebVg->newConsumerId); } - { - void *pIter = NULL; - while (1) { - pIter = taosHashIterate(pOutput->pSub->consumerHash, pIter); - if (pIter == NULL) break; - SMqConsumerEp *pConsumerEp = (SMqConsumerEp *)pIter; - int32_t sz = taosArrayGetSize(pConsumerEp->vgs); - mInfo("sub:%s, mq rebalance final cfg: consumer %" PRId64 " has %d vg", sub, pConsumerEp->consumerId, sz); - for (int32_t i = 0; i < sz; i++) { - SMqVgEp *pVgEp = taosArrayGetP(pConsumerEp->vgs, i); - mInfo("sub:%s, mq rebalance final cfg: vg %d to consumer %" PRId64 "", sub, pVgEp->vgId, - pConsumerEp->consumerId); - } + + pIter = NULL; + while (1) { + pIter = taosHashIterate(pOutput->pSub->consumerHash, pIter); + if (pIter == NULL) break; + SMqConsumerEp *pConsumerEp = (SMqConsumerEp *)pIter; + int32_t sz = taosArrayGetSize(pConsumerEp->vgs); + mInfo("sub:%s mq re-balance final cfg: consumer:0x%" PRIx64 " has %d vg", pSubKey, pConsumerEp->consumerId, sz); + for (int32_t i = 0; i < sz; i++) { + SMqVgEp *pVgEp = taosArrayGetP(pConsumerEp->vgs, i); + mInfo("sub:%s mq re-balance final cfg: vg %d to consumer:0x%" PRIx64, pSubKey, pVgEp->vgId, + pConsumerEp->consumerId); } } @@ -442,7 +471,9 @@ static int32_t mndDoRebalance(SMnode *pMnode, const SMqRebInputObj *pInput, SMqR static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOutputObj *pOutput) { STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB_INSIDE, pMsg, "tmq-reb"); - if (pTrans == NULL) return -1; + if (pTrans == NULL) { + return -1; + } mndTransSetDbName(pTrans, pOutput->pSub->dbName, NULL); if (mndTrancCheckConflict(pMnode, pTrans) != 0) { @@ -457,21 +488,23 @@ static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOu for (int32_t i = 0; i < vgNum; i++) { SMqRebOutputVg *pRebVg = taosArrayGet(rebVgs, i); if (mndPersistSubChangeVgReq(pMnode, pTrans, pOutput->pSub, pRebVg) < 0) { - goto REB_FAIL; + mndTransDrop(pTrans); + return -1; } } // 2. redo log: subscribe and vg assignment // subscribe if (mndSetSubCommitLogs(pMnode, pTrans, pOutput->pSub) != 0) { - goto REB_FAIL; + mndTransDrop(pTrans); + return -1; } // 3. commit log: consumer to update status and epoch // 3.1 set touched consumer - int32_t consumerNum = taosArrayGetSize(pOutput->touchedConsumers); + int32_t consumerNum = taosArrayGetSize(pOutput->modifyConsumers); for (int32_t i = 0; i < consumerNum; i++) { - int64_t consumerId = *(int64_t *)taosArrayGet(pOutput->touchedConsumers, i); + int64_t consumerId = *(int64_t *)taosArrayGet(pOutput->modifyConsumers, i); SMqConsumerObj *pConsumerOld = mndAcquireConsumer(pMnode, consumerId); SMqConsumerObj *pConsumerNew = tNewSMqConsumerObj(pConsumerOld->consumerId, pConsumerOld->cgroup); pConsumerNew->updateType = CONSUMER_UPDATE__TOUCH; @@ -479,11 +512,15 @@ static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOu if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) { tDeleteSMqConsumerObj(pConsumerNew); taosMemoryFree(pConsumerNew); - goto REB_FAIL; + + mndTransDrop(pTrans); + return -1; } + tDeleteSMqConsumerObj(pConsumerNew); taosMemoryFree(pConsumerNew); } + // 3.2 set new consumer consumerNum = taosArrayGetSize(pOutput->newConsumers); for (int32_t i = 0; i < consumerNum; i++) { @@ -500,8 +537,11 @@ static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOu if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) { tDeleteSMqConsumerObj(pConsumerNew); taosMemoryFree(pConsumerNew); - goto REB_FAIL; + + mndTransDrop(pTrans); + return -1; } + tDeleteSMqConsumerObj(pConsumerNew); taosMemoryFree(pConsumerNew); } @@ -522,8 +562,11 @@ static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOu if (mndSetConsumerCommitLogs(pMnode, pTrans, pConsumerNew) != 0) { tDeleteSMqConsumerObj(pConsumerNew); taosMemoryFree(pConsumerNew); - goto REB_FAIL; + + mndTransDrop(pTrans); + return -1; } + tDeleteSMqConsumerObj(pConsumerNew); taosMemoryFree(pConsumerNew); } @@ -536,35 +579,50 @@ static int32_t mndPersistRebResult(SMnode *pMnode, SRpcMsg *pMsg, const SMqRebOu // 6. execution if (mndTransPrepare(pMnode, pTrans) != 0) { mError("failed to prepare trans rebalance since %s", terrstr()); - goto REB_FAIL; + mndTransDrop(pTrans); + return -1; } mndTransDrop(pTrans); return 0; - -REB_FAIL: - mndTransDrop(pTrans); - return -1; } static int32_t mndProcessRebalanceReq(SRpcMsg *pMsg) { SMnode *pMnode = pMsg->info.node; SMqDoRebalanceMsg *pReq = pMsg->pCont; void *pIter = NULL; +// bool rebalanceOnce = false; // to ensure only once. - mInfo("mq rebalance start"); + mInfo("mq re-balance start, total required re-balanced trans:%d", taosHashGetSize(pReq->rebSubHash)); + // here we only handle one topic rebalance requirement to ensure the atomic execution of this transaction. while (1) { pIter = taosHashIterate(pReq->rebSubHash, pIter); - if (pIter == NULL) break; - SMqRebInputObj rebInput = {0}; + if (pIter == NULL) { + break; + } + SMqRebInputObj rebInput = {0}; SMqRebOutputObj rebOutput = {0}; rebOutput.newConsumers = taosArrayInit(0, sizeof(int64_t)); rebOutput.removedConsumers = taosArrayInit(0, sizeof(int64_t)); - rebOutput.touchedConsumers = taosArrayInit(0, sizeof(int64_t)); + rebOutput.modifyConsumers = taosArrayInit(0, sizeof(int64_t)); rebOutput.rebVgs = taosArrayInit(0, sizeof(SMqRebOutputVg)); + if (rebOutput.newConsumers == NULL || rebOutput.removedConsumers == NULL || rebOutput.modifyConsumers == NULL || + rebOutput.rebVgs == NULL) { + taosArrayDestroy(rebOutput.newConsumers); + taosArrayDestroy(rebOutput.removedConsumers); + taosArrayDestroy(rebOutput.modifyConsumers); + taosArrayDestroy(rebOutput.rebVgs); + + terrno = TSDB_CODE_OUT_OF_MEMORY; + mInfo("mq re-balance failed, due to out of memory"); + taosHashCleanup(pReq->rebSubHash); + mndRebEnd(); + return -1; + } + SMqRebInfo *pRebInfo = (SMqRebInfo *)pIter; SMqSubscribeObj *pSub = mndAcquireSubscribeByKey(pMnode, pRebInfo->key); @@ -575,51 +633,53 @@ static int32_t mndProcessRebalanceReq(SRpcMsg *pMsg) { char topic[TSDB_TOPIC_FNAME_LEN]; char cgroup[TSDB_CGROUP_LEN]; mndSplitSubscribeKey(pRebInfo->key, topic, cgroup, true); + SMqTopicObj *pTopic = mndAcquireTopic(pMnode, topic); if (pTopic == NULL) { - mError("mq rebalance %s failed since topic %s not exist, abort", pRebInfo->key, topic); + mError("mq re-balance %s ignored since topic %s doesn't exist", pRebInfo->key, topic); continue; } + taosRLockLatch(&pTopic->lock); - rebOutput.pSub = mndCreateSub(pMnode, pTopic, pRebInfo->key); + rebOutput.pSub = mndCreateSubscription(pMnode, pTopic, pRebInfo->key); if (rebOutput.pSub == NULL) { - mError("mq rebalance %s failed create sub since %s, abort", pRebInfo->key, terrstr()); + mError("mq rebalance %s failed create sub since %s, ignore", pRebInfo->key, terrstr()); taosRUnLockLatch(&pTopic->lock); mndReleaseTopic(pMnode, pTopic); continue; } - memcpy(rebOutput.pSub->dbName, pTopic->db, TSDB_DB_FNAME_LEN); + memcpy(rebOutput.pSub->dbName, pTopic->db, TSDB_DB_FNAME_LEN); taosRUnLockLatch(&pTopic->lock); mndReleaseTopic(pMnode, pTopic); rebInput.oldConsumerNum = 0; + mInfo("sub topic:%s has no consumers sub yet", pRebInfo->key); } else { taosRLockLatch(&pSub->lock); rebInput.oldConsumerNum = taosHashGetSize(pSub->consumerHash); rebOutput.pSub = tCloneSubscribeObj(pSub); taosRUnLockLatch(&pSub->lock); + + mInfo("sub topic:%s has %d consumers sub till now", pRebInfo->key, rebInput.oldConsumerNum); mndReleaseSubscribe(pMnode, pSub); } if (mndDoRebalance(pMnode, &rebInput, &rebOutput) < 0) { - mError("mq rebalance internal error"); + mError("mq re-balance internal error"); } // if add more consumer to balanced subscribe, // possibly no vg is changed - + // when each topic is re-balanced, issue an trans to save the results in sdb. if (mndPersistRebResult(pMnode, pMsg, &rebOutput) < 0) { - mError("mq rebalance persist rebalance output error, possibly vnode splitted or dropped"); + mError("mq re-balance persist output error, possibly vnode splitted or dropped,msg:%s", terrstr()); } - taosArrayDestroy(pRebInfo->lostConsumers); - taosArrayDestroy(pRebInfo->newConsumers); - taosArrayDestroy(pRebInfo->removedConsumers); taosArrayDestroy(rebOutput.newConsumers); - taosArrayDestroy(rebOutput.touchedConsumers); + taosArrayDestroy(rebOutput.modifyConsumers); taosArrayDestroy(rebOutput.removedConsumers); taosArrayDestroy(rebOutput.rebVgs); tDeleteSubscribeObj(rebOutput.pSub); @@ -627,19 +687,18 @@ static int32_t mndProcessRebalanceReq(SRpcMsg *pMsg) { } // reset flag - mInfo("mq rebalance completed successfully"); + mInfo("mq re-balance completed successfully"); taosHashCleanup(pReq->rebSubHash); mndRebEnd(); return 0; } -static int32_t mndProcessDropCgroupReq(SRpcMsg *pReq) { - SMnode *pMnode = pReq->info.node; - SSdb *pSdb = pMnode->pSdb; +static int32_t mndProcessDropCgroupReq(SRpcMsg *pMsg) { + SMnode *pMnode = pMsg->info.node; SMDropCgroupReq dropReq = {0}; - if (tDeserializeSMDropCgroupReq(pReq->pCont, pReq->contLen, &dropReq) != 0) { + if (tDeserializeSMDropCgroupReq(pMsg->pCont, pMsg->contLen, &dropReq) != 0) { terrno = TSDB_CODE_INVALID_MSG; return -1; } @@ -663,7 +722,7 @@ static int32_t mndProcessDropCgroupReq(SRpcMsg *pReq) { return -1; } - STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "drop-cgroup"); + STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pMsg, "drop-cgroup"); if (pTrans == NULL) { mError("cgroup: %s on topic:%s, failed to drop since %s", dropReq.cgroup, dropReq.topic, terrstr()); mndReleaseSubscribe(pMnode, pSub); @@ -764,7 +823,7 @@ static SSdbRow *mndSubActionDecode(SSdbRaw *pRaw) { if (pSub->unassignedVgs != NULL) { int32_t size = (int32_t)taosArrayGetSize(pSub->unassignedVgs); for (int32_t i = 0; i < size; ++i) { - SMqVgEp *pMqVgEp = taosArrayGet(pSub->unassignedVgs, i); + SMqVgEp *pMqVgEp = (SMqVgEp *)taosArrayGetP(pSub->unassignedVgs, i); tmsgUpdateDnodeEpSet(&pMqVgEp->epSet); } } @@ -774,7 +833,7 @@ static SSdbRow *mndSubActionDecode(SSdbRaw *pRaw) { SMqConsumerEp *pConsumerEp = pIter; int32_t size = (int32_t)taosArrayGetSize(pConsumerEp->vgs); for (int32_t i = 0; i < size; ++i) { - SMqVgEp *pMqVgEp = taosArrayGet(pConsumerEp->vgs, i); + SMqVgEp *pMqVgEp = (SMqVgEp *)taosArrayGetP(pConsumerEp->vgs, i); tmsgUpdateDnodeEpSet(&pMqVgEp->epSet); } pIter = taosHashIterate(pSub->consumerHash, pIter); @@ -956,7 +1015,7 @@ END: return code; } -static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rowsCapacity) { +int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rowsCapacity) { SMnode *pMnode = pReq->info.node; SSdb *pSdb = pMnode->pSdb; int32_t numOfRows = 0; @@ -966,7 +1025,9 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock while (numOfRows < rowsCapacity) { pShow->pIter = sdbFetch(pSdb, SDB_SUBSCRIBE, pShow->pIter, (void **)&pSub); - if (pShow->pIter == NULL) break; + if (pShow->pIter == NULL) { + break; + } taosRLockLatch(&pSub->lock); @@ -996,31 +1057,31 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock varDataSetLen(cgroup, strlen(varDataVal(cgroup))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)topic, false); + colDataSetVal(pColInfo, numOfRows, (const char *)topic, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)cgroup, false); + colDataSetVal(pColInfo, numOfRows, (const char *)cgroup, false); // vg id pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pVgEp->vgId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pVgEp->vgId, false); // consumer id pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pConsumerEp->consumerId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pConsumerEp->consumerId, false); - mDebug("mnd show subscriptions: topic %s, consumer %" PRId64 " cgroup %s vgid %d", varDataVal(topic), + mDebug("mnd show subscriptions: topic %s, consumer:0x%" PRIx64 " cgroup %s vgid %d", varDataVal(topic), pConsumerEp->consumerId, varDataVal(cgroup), pVgEp->vgId); // offset #if 0 // subscribe time pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pSub->subscribeTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pSub->subscribeTime, false); // rebalance time pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pSub->rebalanceTime, pConsumer->rebalanceTime == 0); + colDataSetVal(pColInfo, numOfRows, (const char *)&pSub->rebalanceTime, pConsumer->rebalanceTime == 0); #endif numOfRows++; @@ -1028,7 +1089,6 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock } // do not show for cleared subscription -#if 1 int32_t sz = taosArrayGetSize(pSub->unassignedVgs); for (int32_t i = 0; i < sz; i++) { SMqVgEp *pVgEp = taosArrayGetP(pSub->unassignedVgs, i); @@ -1044,18 +1104,18 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock varDataSetLen(cgroup, strlen(varDataVal(cgroup))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)topic, false); + colDataSetVal(pColInfo, numOfRows, (const char *)topic, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)cgroup, false); + colDataSetVal(pColInfo, numOfRows, (const char *)cgroup, false); // vg id pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pVgEp->vgId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pVgEp->vgId, false); // consumer id pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, NULL, true); + colDataSetVal(pColInfo, numOfRows, NULL, true); mDebug("mnd show subscriptions(unassigned): topic %s, cgroup %s vgid %d", varDataVal(topic), varDataVal(cgroup), pVgEp->vgId); @@ -1064,17 +1124,18 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock #if 0 // subscribe time pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pSub->subscribeTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pSub->subscribeTime, false); // rebalance time pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pSub->rebalanceTime, pConsumer->rebalanceTime == 0); + colDataSetVal(pColInfo, numOfRows, (const char *)&pSub->rebalanceTime, pConsumer->rebalanceTime == 0); #endif numOfRows++; } -#endif + pBlock->info.rows = numOfRows; + taosRUnLockLatch(&pSub->lock); sdbRelease(pSdb, pSub); } @@ -1085,7 +1146,7 @@ static int32_t mndRetrieveSubscribe(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock return numOfRows; } -static void mndCancelGetNextSubscribe(SMnode *pMnode, void *pIter) { +void mndCancelGetNextSubscribe(SMnode *pMnode, void *pIter) { SSdb *pSdb = pMnode->pSdb; sdbCancelFetch(pSdb, pIter); } diff --git a/source/dnode/mnode/impl/src/mndSync.c b/source/dnode/mnode/impl/src/mndSync.c index 1dc9ae9c4ba0ebd689da8757dd3aa11eb330a2c8..4965d5c34a2f09b3ce25edf4bc6ed902a2f23a42 100644 --- a/source/dnode/mnode/impl/src/mndSync.c +++ b/source/dnode/mnode/impl/src/mndSync.c @@ -33,7 +33,7 @@ static int32_t mndSyncEqCtrlMsg(const SMsgCb *msgcb, SRpcMsg *pMsg) { return -1; } - int32_t code = tmsgPutToQueue(msgcb, SYNC_CTRL_QUEUE, pMsg); + int32_t code = tmsgPutToQueue(msgcb, SYNC_RD_QUEUE, pMsg); if (code != 0) { rpcFreeCont(pMsg->pCont); pMsg->pCont = NULL; @@ -118,17 +118,25 @@ int32_t mndProcessWriteMsg(const SSyncFSM *pFsm, SRpcMsg *pMsg, const SFsmCbMeta transId, pTrans->createdTime, pMgmt->transId); mndTransExecute(pMnode, pTrans, false); mndReleaseTrans(pMnode, pTrans); - // sdbWriteFile(pMnode->pSdb, SDB_WRITE_DELTA); } else { mError("trans:%d, not found while execute in mnode since %s", transId, terrstr()); } } + sdbWriteFile(pMnode->pSdb, tsMndSdbWriteDelta); return 0; } int32_t mndSyncCommitMsg(const SSyncFSM *pFsm, SRpcMsg *pMsg, const SFsmCbMeta *pMeta) { int32_t code = 0; + pMsg->info.conn.applyIndex = pMeta->index; + pMsg->info.conn.applyTerm = pMeta->term; + + if (pMsg->code == 0) { + SMnode *pMnode = pFsm->data; + atomic_store_64(&pMnode->applied, pMsg->info.conn.applyIndex); + } + if (!syncUtilUserCommit(pMsg->msgType)) { goto _out; } @@ -140,6 +148,11 @@ _out: return code; } +SyncIndex mndSyncAppliedIndex(const SSyncFSM *pFSM) { + SMnode *pMnode = pFSM->data; + return atomic_load_64(&pMnode->applied); +} + int32_t mndSyncGetSnapshot(const SSyncFSM *pFsm, SSnapshot *pSnapshot, void *pReaderParam, void **ppReader) { mInfo("start to read snapshot from sdb in atomic way"); SMnode *pMnode = pFsm->data; @@ -153,7 +166,7 @@ static void mndSyncGetSnapshotInfo(const SSyncFSM *pFsm, SSnapshot *pSnapshot) { sdbGetCommitInfo(pMnode->pSdb, &pSnapshot->lastApplyIndex, &pSnapshot->lastApplyTerm, &pSnapshot->lastConfigIndex); } -void mndRestoreFinish(const SSyncFSM *pFsm) { +void mndRestoreFinish(const SSyncFSM *pFsm, const SyncIndex commitIdx) { SMnode *pMnode = pFsm->data; if (!pMnode->deploy) { @@ -167,6 +180,8 @@ void mndRestoreFinish(const SSyncFSM *pFsm) { } else { mInfo("vgId:1, sync restore finished"); } + + ASSERT(commitIdx == mndSyncAppliedIndex(pFsm)); } int32_t mndSnapshotStartRead(const SSyncFSM *pFsm, void *pParam, void **ppReader) { @@ -253,6 +268,7 @@ SSyncFSM *mndSyncMakeFsm(SMnode *pMnode) { SSyncFSM *pFsm = taosMemoryCalloc(1, sizeof(SSyncFSM)); pFsm->data = pMnode; pFsm->FpCommitCb = mndSyncCommitMsg; + pFsm->FpAppliedIndexCb = mndSyncAppliedIndex; pFsm->FpPreCommitCb = NULL; pFsm->FpRollBackCb = NULL; pFsm->FpRestoreFinishCb = mndRestoreFinish; @@ -308,7 +324,7 @@ int32_t mndInitSync(SMnode *pMnode) { pNode->nodeId = pMgmt->replicas[i].id; pNode->nodePort = pMgmt->replicas[i].port; tstrncpy(pNode->nodeFqdn, pMgmt->replicas[i].fqdn, sizeof(pNode->nodeFqdn)); - tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort); + (void)tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort); mInfo("vgId:1, index:%d ep:%s:%u dnode:%d cluster:%" PRId64, i, pNode->nodeFqdn, pNode->nodePort, pNode->nodeId, pNode->clusterId); } @@ -319,6 +335,7 @@ int32_t mndInitSync(SMnode *pMnode) { mError("failed to open sync since %s", terrstr()); return -1; } + pMnode->pSdb->sync = pMgmt->sync; mInfo("mnode-sync is opened, id:%" PRId64, pMgmt->sync); return 0; diff --git a/source/dnode/mnode/impl/src/mndTopic.c b/source/dnode/mnode/impl/src/mndTopic.c index 48c35f3f0704780b73e9d3af9b3ab31e0c58da63..f6da3709164158acc008708121873da5bb2b78d1 100644 --- a/source/dnode/mnode/impl/src/mndTopic.c +++ b/source/dnode/mnode/impl/src/mndTopic.c @@ -31,9 +31,12 @@ #define MND_TOPIC_VER_NUMBER 2 #define MND_TOPIC_RESERVE_SIZE 64 +SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic); +SSdbRow *mndTopicActionDecode(SSdbRaw *pRaw); + static int32_t mndTopicActionInsert(SSdb *pSdb, SMqTopicObj *pTopic); static int32_t mndTopicActionDelete(SSdb *pSdb, SMqTopicObj *pTopic); -static int32_t mndTopicActionUpdate(SSdb *pSdb, SMqTopicObj *pTopic, SMqTopicObj *pNewTopic); +static int32_t mndTopicActionUpdate(SSdb *pSdb, SMqTopicObj *pOldTopic, SMqTopicObj *pNewTopic); static int32_t mndProcessCreateTopicReq(SRpcMsg *pReq); static int32_t mndProcessDropTopicReq(SRpcMsg *pReq); @@ -79,6 +82,7 @@ SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) { if (pTopic->physicalPlan) { physicalPlanLen = strlen(pTopic->physicalPlan) + 1; } + int32_t schemaLen = 0; if (pTopic->schema.nCols) { schemaLen = taosEncodeSSchemaWrapper(NULL, &pTopic->schema); @@ -88,7 +92,9 @@ SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) { int32_t size = sizeof(SMqTopicObj) + physicalPlanLen + pTopic->sqlLen + pTopic->astLen + schemaLen + ntbColLen + MND_TOPIC_RESERVE_SIZE; SSdbRaw *pRaw = sdbAllocRaw(SDB_TOPIC, MND_TOPIC_VER_NUMBER, size); - if (pRaw == NULL) goto TOPIC_ENCODE_OVER; + if (pRaw == NULL) { + goto TOPIC_ENCODE_OVER; + } int32_t dataPos = 0; SDB_SET_BINARY(pRaw, dataPos, pTopic->name, TSDB_TOPIC_FNAME_LEN, TOPIC_ENCODE_OVER); @@ -106,6 +112,7 @@ SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) { SDB_SET_INT32(pRaw, dataPos, pTopic->sqlLen, TOPIC_ENCODE_OVER); SDB_SET_BINARY(pRaw, dataPos, pTopic->sql, pTopic->sqlLen, TOPIC_ENCODE_OVER); SDB_SET_INT32(pRaw, dataPos, pTopic->astLen, TOPIC_ENCODE_OVER); + if (pTopic->astLen) { SDB_SET_BINARY(pRaw, dataPos, pTopic->ast, pTopic->astLen, TOPIC_ENCODE_OVER); } @@ -123,6 +130,7 @@ SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) { taosEncodeSSchemaWrapper(&aswBuf, &pTopic->schema); SDB_SET_BINARY(pRaw, dataPos, swBuf, schemaLen, TOPIC_ENCODE_OVER); } + SDB_SET_INT64(pRaw, dataPos, pTopic->ntbUid, TOPIC_ENCODE_OVER); if (pTopic->ntbUid != 0) { int32_t sz = taosArrayGetSize(pTopic->ntbColIds); @@ -132,6 +140,7 @@ SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) { SDB_SET_INT16(pRaw, dataPos, colId, TOPIC_ENCODE_OVER); } } + SDB_SET_INT64(pRaw, dataPos, pTopic->ctbStbUid, TOPIC_ENCODE_OVER); SDB_SET_RESERVE(pRaw, dataPos, MND_TOPIC_RESERVE_SIZE, TOPIC_ENCODE_OVER); @@ -247,10 +256,9 @@ SSdbRow *mndTopicActionDecode(SSdbRaw *pRaw) { SDB_GET_INT16(pRaw, dataPos, &colId, TOPIC_DECODE_OVER); taosArrayPush(pTopic->ntbColIds, &colId); } - SDB_GET_INT64(pRaw, dataPos, &pTopic->ctbStbUid, TOPIC_DECODE_OVER); + SDB_GET_INT64(pRaw, dataPos, &pTopic->ctbStbUid, TOPIC_DECODE_OVER); SDB_GET_RESERVE(pRaw, dataPos, MND_TOPIC_RESERVE_SIZE, TOPIC_DECODE_OVER); - terrno = TSDB_CODE_SUCCESS; TOPIC_DECODE_OVER: @@ -266,12 +274,12 @@ TOPIC_DECODE_OVER: } static int32_t mndTopicActionInsert(SSdb *pSdb, SMqTopicObj *pTopic) { - mTrace("topic:%s, perform insert action", pTopic->name); + mTrace("topic:%s perform insert action", pTopic->name); return 0; } static int32_t mndTopicActionDelete(SSdb *pSdb, SMqTopicObj *pTopic) { - mTrace("topic:%s, perform delete action", pTopic->name); + mTrace("topic:%s perform delete action", pTopic->name); taosMemoryFreeClear(pTopic->sql); taosMemoryFreeClear(pTopic->ast); taosMemoryFreeClear(pTopic->physicalPlan); @@ -281,7 +289,7 @@ static int32_t mndTopicActionDelete(SSdb *pSdb, SMqTopicObj *pTopic) { } static int32_t mndTopicActionUpdate(SSdb *pSdb, SMqTopicObj *pOldTopic, SMqTopicObj *pNewTopic) { - mTrace("topic:%s, perform update action", pOldTopic->name); + mTrace("topic:%s perform update action", pOldTopic->name); atomic_exchange_64(&pOldTopic->updateTime, pNewTopic->updateTime); atomic_exchange_32(&pOldTopic->version, pNewTopic->version); @@ -364,7 +372,8 @@ static int32_t extractTopicTbInfo(SNode *pAst, SMqTopicObj *pTopic) { static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq *pCreate, SDbObj *pDb, const char *userName) { - mInfo("topic:%s to create", pCreate->name); + mInfo("start to create topic:%s", pCreate->name); + SMqTopicObj topicObj = {0}; tstrncpy(topicObj.name, pCreate->name, TSDB_TOPIC_FNAME_LEN); tstrncpy(topicObj.db, pDb->name, TSDB_DB_FNAME_LEN); @@ -379,23 +388,22 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq * topicObj.uid = mndGenerateUid(pCreate->name, strlen(pCreate->name)); topicObj.dbUid = pDb->uid; topicObj.version = 1; - topicObj.sql = strdup(pCreate->sql); + topicObj.sql = taosStrdup(pCreate->sql); topicObj.sqlLen = strlen(pCreate->sql) + 1; topicObj.subType = pCreate->subType; topicObj.withMeta = pCreate->withMeta; - if (topicObj.withMeta) { - if (topicObj.subType == TOPIC_SUB_TYPE__COLUMN) { + + if (pCreate->subType == TOPIC_SUB_TYPE__COLUMN) { + if (pCreate->withMeta) { terrno = TSDB_CODE_MND_INVALID_TOPIC_OPTION; mError("topic:%s, failed to create since %s", pCreate->name, terrstr()); return -1; } - } - if (pCreate->subType == TOPIC_SUB_TYPE__COLUMN) { - topicObj.ast = strdup(pCreate->ast); + topicObj.ast = taosStrdup(pCreate->ast); topicObj.astLen = strlen(pCreate->ast) + 1; - qDebugL("ast %s", topicObj.ast); + qDebugL("topic:%s ast %s", topicObj.name, topicObj.ast); SNode *pAst = NULL; if (nodesStringToNode(pCreate->ast, &pAst) != 0) { @@ -409,18 +417,20 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq * SPlanContext cxt = {.pAstRoot = pAst, .topicQuery = true}; if (qCreateQueryPlan(&cxt, &pPlan, NULL) != 0) { - mError("topic:%s, failed to create since %s", pCreate->name, terrstr()); + mError("failed to create topic:%s since %s", pCreate->name, terrstr()); taosMemoryFree(topicObj.ast); taosMemoryFree(topicObj.sql); return -1; } - int64_t ntbUid; topicObj.ntbColIds = taosArrayInit(0, sizeof(int16_t)); if (topicObj.ntbColIds == NULL) { + taosMemoryFree(topicObj.ast); + taosMemoryFree(topicObj.sql); terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } + extractTopicTbInfo(pAst, &topicObj); if (topicObj.ntbUid == 0) { @@ -449,6 +459,7 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq * terrno = TSDB_CODE_MND_STB_NOT_EXIST; return -1; } + topicObj.stbUid = pStb->uid; mndReleaseStb(pMnode, pStb); } @@ -467,7 +478,8 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq * taosMemoryFreeClear(topicObj.physicalPlan); return -1; } - mInfo("trans:%d, used to create topic:%s", pTrans->id, pCreate->name); + + mInfo("trans:%d to create topic:%s", pTrans->id, pCreate->name); SSdbRaw *pCommitRaw = mndTopicActionEncode(&topicObj); if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) { @@ -476,6 +488,7 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq * mndTransDrop(pTrans); return -1; } + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); if (topicObj.ntbUid != 0) { @@ -544,7 +557,11 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq * taosMemoryFreeClear(topicObj.sql); taosMemoryFreeClear(topicObj.ast); taosArrayDestroy(topicObj.ntbColIds); - if (topicObj.schema.nCols) taosMemoryFreeClear(topicObj.schema.pSchema); + + if (topicObj.schema.nCols) { + taosMemoryFreeClear(topicObj.schema.pSchema); + } + mndTransDrop(pTrans); return TSDB_CODE_ACTION_IN_PROGRESS; } @@ -561,17 +578,17 @@ static int32_t mndProcessCreateTopicReq(SRpcMsg *pReq) { goto _OVER; } - mInfo("topic:%s, start to create, sql:%s", createTopicReq.name, createTopicReq.sql); + mInfo("topic:%s start to create, sql:%s", createTopicReq.name, createTopicReq.sql); if (mndCheckCreateTopicReq(&createTopicReq) != 0) { - mError("topic:%s, failed to create since %s", createTopicReq.name, terrstr()); + mError("topic:%s failed to create since %s", createTopicReq.name, terrstr()); goto _OVER; } pTopic = mndAcquireTopic(pMnode, createTopicReq.name); if (pTopic != NULL) { if (createTopicReq.igExists) { - mInfo("topic:%s, already exist, ignore exist is set", createTopicReq.name); + mInfo("topic:%s already exist, ignore exist is set", createTopicReq.name); code = 0; goto _OVER; } else { @@ -588,12 +605,20 @@ static int32_t mndProcessCreateTopicReq(SRpcMsg *pReq) { goto _OVER; } + if (pDb->cfg.walRetentionPeriod == 0) { + terrno = TSDB_CODE_MND_DB_RETENTION_PERIOD_ZERO; + mError("db:%s, not allowed to create topic when WAL_RETENTION_PERIOD is zero", pDb->name); + goto _OVER; + } + code = mndCreateTopic(pMnode, pReq, &createTopicReq, pDb, pReq->info.conn.user); - if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS; + if (code == 0) { + code = TSDB_CODE_ACTION_IN_PROGRESS; + } _OVER: if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) { - mError("topic:%s, failed to create since %s", createTopicReq.name, terrstr()); + mError("failed to create topic:%s since %s", createTopicReq.name, terrstr()); } mndReleaseTopic(pMnode, pTopic); @@ -605,13 +630,18 @@ _OVER: static int32_t mndDropTopic(SMnode *pMnode, STrans *pTrans, SRpcMsg *pReq, SMqTopicObj *pTopic) { int32_t code = -1; - if (mndUserRemoveTopic(pMnode, pTrans, pTopic->name) != 0) goto _OVER; + if (mndUserRemoveTopic(pMnode, pTrans, pTopic->name) != 0) { + goto _OVER; + } SSdbRaw *pCommitRaw = mndTopicActionEncode(pTopic); if (pCommitRaw == NULL || mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) goto _OVER; (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED); - if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; + if (mndTransPrepare(pMnode, pTrans) != 0) { + goto _OVER; + } + code = 0; _OVER: @@ -650,7 +680,9 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) { SMqConsumerObj *pConsumer; while (1) { pIter = sdbFetch(pSdb, SDB_CONSUMER, pIter, (void **)&pConsumer); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } if (pConsumer->status == MQ_CONSUMER_STATUS__LOST_REBD) continue; @@ -661,8 +693,8 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) { mndReleaseConsumer(pMnode, pConsumer); mndReleaseTopic(pMnode, pTopic); terrno = TSDB_CODE_MND_TOPIC_SUBSCRIBED; - mError("topic:%s, failed to drop since subscribed by consumer:%" PRId64 ", in consumer group %s", dropReq.name, - pConsumer->consumerId, pConsumer->cgroup); + mError("topic:%s, failed to drop since subscribed by consumer:0x%" PRIx64 ", in consumer group %s", + dropReq.name, pConsumer->consumerId, pConsumer->cgroup); return -1; } } @@ -696,14 +728,9 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) { sdbRelease(pSdb, pConsumer); } -#if 0 - if (pTopic->refConsumerCnt != 0) { - mndReleaseTopic(pMnode, pTopic); - terrno = TSDB_CODE_MND_TOPIC_SUBSCRIBED; - mError("topic:%s, failed to drop since %s", dropReq.name, terrstr()); + if (mndCheckDbPrivilegeByName(pMnode, pReq->info.conn.user, MND_OPER_READ_DB, pTopic->db) != 0) { return -1; } -#endif STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_DB_INSIDE, pReq, "drop-topic"); if (pTrans == NULL) { @@ -731,8 +758,9 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) { if (pTopic->ntbUid != 0) { // broadcast to all vnode - void *pIter = NULL; + pIter = NULL; SVgObj *pVgroup = NULL; + while (1) { pIter = sdbFetch(pSdb, SDB_VGROUP, pIter, (void **)&pVgroup); if (pIter == NULL) break; @@ -771,7 +799,9 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) { return TSDB_CODE_ACTION_IN_PROGRESS; } -static int32_t mndGetNumOfTopics(SMnode *pMnode, char *dbName, int32_t *pNumOfTopics) { +int32_t mndGetNumOfTopics(SMnode *pMnode, char *dbName, int32_t *pNumOfTopics) { + *pNumOfTopics = 0; + SSdb *pSdb = pMnode->pSdb; SDbObj *pDb = mndAcquireDb(pMnode, dbName); if (pDb == NULL) { @@ -784,7 +814,9 @@ static int32_t mndGetNumOfTopics(SMnode *pMnode, char *dbName, int32_t *pNumOfTo while (1) { SMqTopicObj *pTopic = NULL; pIter = sdbFetch(pSdb, SDB_TOPIC, pIter, (void **)&pTopic); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } if (pTopic->dbUid == pDb->uid) { numOfTopics++; @@ -812,29 +844,29 @@ static int32_t mndRetrieveTopic(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl SName n; int32_t cols = 0; - char topicName[TSDB_TOPIC_NAME_LEN + VARSTR_HEADER_SIZE + 5] = {0}; - tstrncpy(varDataVal(topicName), mndGetDbStr(pTopic->name), sizeof(topicName) - 2); - /*tNameFromString(&n, pTopic->name, T_NAME_ACCT | T_NAME_DB);*/ - /*tNameGetDbName(&n, varDataVal(topicName));*/ - varDataSetLen(topicName, strlen(varDataVal(topicName))); + char topicName[TSDB_TOPIC_NAME_LEN + VARSTR_HEADER_SIZE + 5] = {0}; + const char *pName = mndGetDbStr(pTopic->name); + STR_TO_VARSTR(topicName, pName); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)topicName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)topicName, false); char dbName[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; tNameFromString(&n, pTopic->db, T_NAME_ACCT | T_NAME_DB); tNameGetDbName(&n, varDataVal(dbName)); varDataSetLen(dbName, strlen(varDataVal(dbName))); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)dbName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)dbName, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pTopic->createTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pTopic->createTime, false); char sql[TSDB_SHOW_SQL_LEN + VARSTR_HEADER_SIZE] = {0}; - tstrncpy(&sql[VARSTR_HEADER_SIZE], pTopic->sql, TSDB_SHOW_SQL_LEN); - varDataSetLen(sql, strlen(&sql[VARSTR_HEADER_SIZE])); + STR_TO_VARSTR(sql, pTopic->sql); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)sql, false); + colDataSetVal(pColInfo, numOfRows, (const char *)sql, false); numOfRows++; sdbRelease(pSdb, pTopic); @@ -867,24 +899,26 @@ static void mndCancelGetNextTopic(SMnode *pMnode, void *pIter) { sdbCancelFetch(pSdb, pIter); } -int32_t mndCheckTopicExist(SMnode *pMnode, SDbObj *pDb) { - SSdb *pSdb = pMnode->pSdb; - +bool mndTopicExistsForDb(SMnode *pMnode, SDbObj *pDb) { + SSdb *pSdb = pMnode->pSdb; void *pIter = NULL; SMqTopicObj *pTopic = NULL; + while (1) { pIter = sdbFetch(pSdb, SDB_TOPIC, pIter, (void **)&pTopic); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } if (pTopic->dbUid == pDb->uid) { sdbRelease(pSdb, pTopic); - terrno = TSDB_CODE_MND_TOPIC_MUST_BE_DELETED; - return -1; + return true; } sdbRelease(pSdb, pTopic); } - return 0; + + return false; } #if 0 @@ -915,4 +949,4 @@ int32_t mndDropTopicByDB(SMnode *pMnode, STrans *pTrans, SDbObj *pDb) { return code; } -#endif \ No newline at end of file +#endif diff --git a/source/dnode/mnode/impl/src/mndTrans.c b/source/dnode/mnode/impl/src/mndTrans.c index 6bb286cd6f379aea8d39f9b88e0f110698474ebb..106eea031384a93641c002200ab0c084f53fc76a 100644 --- a/source/dnode/mnode/impl/src/mndTrans.c +++ b/source/dnode/mnode/impl/src/mndTrans.c @@ -460,6 +460,8 @@ static const char *mndTransStr(ETrnStage stage) { return "commitAction"; case TRN_STAGE_FINISHED: return "finished"; + case TRN_STAGE_PRE_FINISH: + return "pre-finish"; default: return "invalid"; } @@ -503,14 +505,15 @@ static TransCbFp mndTransGetCbFp(ETrnFunc ftype) { } static int32_t mndTransActionInsert(SSdb *pSdb, STrans *pTrans) { - mTrace("trans:%d, perform insert action, row:%p stage:%s", pTrans->id, pTrans, mndTransStr(pTrans->stage)); + mInfo("trans:%d, perform insert action, row:%p stage:%s, callfunc:1, startFunc:%d", pTrans->id, pTrans, + mndTransStr(pTrans->stage), pTrans->startFunc); if (pTrans->startFunc > 0) { TransCbFp fp = mndTransGetCbFp(pTrans->startFunc); if (fp) { (*fp)(pSdb->pMnode, pTrans->param, pTrans->paramLen); } - pTrans->startFunc = 0; + // pTrans->startFunc = 0; } return 0; @@ -546,14 +549,15 @@ static void mndTransDropData(STrans *pTrans) { } static int32_t mndTransActionDelete(SSdb *pSdb, STrans *pTrans, bool callFunc) { - mTrace("trans:%d, perform delete action, row:%p stage:%s callfunc:%d", pTrans->id, pTrans, mndTransStr(pTrans->stage), - callFunc); + mInfo("trans:%d, perform delete action, row:%p stage:%s callfunc:%d, stopFunc:%d", pTrans->id, pTrans, + mndTransStr(pTrans->stage), callFunc, pTrans->stopFunc); + if (pTrans->stopFunc > 0 && callFunc) { TransCbFp fp = mndTransGetCbFp(pTrans->stopFunc); if (fp) { (*fp)(pSdb->pMnode, pTrans->param, pTrans->paramLen); } - pTrans->stopFunc = 0; + // pTrans->stopFunc = 0; } mndTransDropData(pTrans); @@ -572,9 +576,8 @@ static void mndTransUpdateActions(SArray *pOldArray, SArray *pNewArray) { } static int32_t mndTransActionUpdate(SSdb *pSdb, STrans *pOld, STrans *pNew) { - mTrace("trans:%d, perform update action, old row:%p stage:%s create:%" PRId64 ", new row:%p stage:%s create:%" PRId64, - pOld->id, pOld, mndTransStr(pOld->stage), pOld->createdTime, pNew, mndTransStr(pNew->stage), - pNew->createdTime); + mInfo("trans:%d, perform update action, old row:%p stage:%s create:%" PRId64 ", new row:%p stage:%s create:%" PRId64, + pOld->id, pOld, mndTransStr(pOld->stage), pOld->createdTime, pNew, mndTransStr(pNew->stage), pNew->createdTime); if (pOld->createdTime != pNew->createdTime) { mError("trans:%d, failed to perform update action since createTime not match, old row:%p stage:%s create:%" PRId64 @@ -598,10 +601,15 @@ static int32_t mndTransActionUpdate(SSdb *pSdb, STrans *pOld, STrans *pNew) { } if (pOld->stage == TRN_STAGE_ROLLBACK) { - pOld->stage = TRN_STAGE_REDO_ACTION; + pOld->stage = TRN_STAGE_UNDO_ACTION; mTrace("trans:%d, stage from rollback to undoAction since perform update action", pNew->id); } + if (pOld->stage == TRN_STAGE_PRE_FINISH) { + pOld->stage = TRN_STAGE_FINISHED; + mTrace("trans:%d, stage from pre-finish to finished since perform update action", pNew->id); + } + return 0; } @@ -641,6 +649,7 @@ STrans *mndTransCreate(SMnode *pMnode, ETrnPolicy policy, ETrnConflct conflict, pTrans->undoActions = taosArrayInit(TRANS_ARRAY_SIZE, sizeof(STransAction)); pTrans->commitActions = taosArrayInit(TRANS_ARRAY_SIZE, sizeof(STransAction)); pTrans->pRpcArray = taosArrayInit(1, sizeof(SRpcHandleInfo)); + pTrans->mTraceId = pReq ? TRACE_GET_ROOTID(&pReq->info.traceId) : 0; taosInitRWLatch(&pTrans->lockRpcArray); if (pTrans->redoActions == NULL || pTrans->undoActions == NULL || pTrans->commitActions == NULL || @@ -655,6 +664,7 @@ STrans *mndTransCreate(SMnode *pMnode, ETrnPolicy policy, ETrnConflct conflict, taosArrayPush(pTrans->pRpcArray, &pReq->info); pTrans->originRpcType = pReq->msgType; } + mTrace("trans:%d, local object is created, data:%p", pTrans->id, pTrans); return pTrans; } @@ -696,7 +706,8 @@ static int32_t mndTransAppendAction(SArray *pArray, STransAction *pAction) { } int32_t mndTransAppendRedolog(STrans *pTrans, SSdbRaw *pRaw) { - STransAction action = {.stage = TRN_STAGE_REDO_ACTION, .actionType = TRANS_ACTION_RAW, .pRaw = pRaw}; + STransAction action = { + .stage = TRN_STAGE_REDO_ACTION, .actionType = TRANS_ACTION_RAW, .pRaw = pRaw, .mTraceId = pTrans->mTraceId}; return mndTransAppendAction(pTrans->redoActions, &action); } @@ -718,6 +729,7 @@ int32_t mndTransAppendCommitlog(STrans *pTrans, SSdbRaw *pRaw) { int32_t mndTransAppendRedoAction(STrans *pTrans, STransAction *pAction) { pAction->stage = TRN_STAGE_REDO_ACTION; pAction->actionType = TRANS_ACTION_MSG; + pAction->mTraceId = pTrans->mTraceId; return mndTransAppendAction(pTrans->redoActions, pAction); } @@ -901,6 +913,7 @@ int32_t mndTransPrepare(SMnode *pMnode, STrans *pTrans) { pNew->pRpcArray = pTrans->pRpcArray; pNew->rpcRsp = pTrans->rpcRsp; pNew->rpcRspLen = pTrans->rpcRspLen; + pNew->mTraceId = pTrans->mTraceId; pTrans->pRpcArray = NULL; pTrans->rpcRsp = NULL; pTrans->rpcRspLen = 0; @@ -930,6 +943,16 @@ static int32_t mndTransRollback(SMnode *pMnode, STrans *pTrans) { return 0; } +static int32_t mndTransPreFinish(SMnode *pMnode, STrans *pTrans) { + mInfo("trans:%d, pre-finish transaction", pTrans->id); + if (mndTransSync(pMnode, pTrans) != 0) { + mError("trans:%d, failed to pre-finish since %s", pTrans->id, terrstr()); + return -1; + } + mInfo("trans:%d, pre-finish finished", pTrans->id); + return 0; +} + static void mndTransSendRpcRsp(SMnode *pMnode, STrans *pTrans) { bool sendRsp = false; int32_t code = pTrans->code; @@ -1008,6 +1031,12 @@ static void mndTransSendRpcRsp(SMnode *pMnode, STrans *pTrans) { if (0 == mndBuildSMCreateStbRsp(pMnode, pTrans->dbname, pTrans->stbname, &pCont, &contLen) != 0) { mndTransSetRpcRsp(pTrans, pCont, contLen); } + } else if (pTrans->originRpcType == TDMT_MND_CREATE_INDEX) { + void *pCont = NULL; + int32_t contLen = 0; + if (0 == mndBuildSMCreateStbRsp(pMnode, pTrans->dbname, pTrans->stbname, &pCont, &contLen) != 0) { + mndTransSetRpcRsp(pTrans, pCont, contLen); + } } if (pTrans->rpcRspLen != 0) { @@ -1064,10 +1093,13 @@ int32_t mndTransProcessRsp(SRpcMsg *pRsp) { pAction->msgReceived = 1; pAction->errCode = pRsp->code; pTrans->lastErrorNo = pRsp->code; + + mInfo("trans:%d, %s:%d response is received, code:0x%x, accept:0x%x retry:0x%x", transId, + mndTransStr(pAction->stage), action, pRsp->code, pAction->acceptableCode, pAction->retryCode); + } else { + mInfo("trans:%d, invalid action, index:%d, code:0x%x", transId, action, pRsp->code); } - mInfo("trans:%d, %s:%d response is received, code:0x%x, accept:0x%x retry:0x%x", transId, mndTransStr(pAction->stage), - action, pRsp->code, pAction->acceptableCode, pAction->retryCode); mndTransExecute(pMnode, pTrans, true); _OVER: @@ -1140,6 +1172,8 @@ static int32_t mndTransSendSingleMsg(SMnode *pMnode, STrans *pTrans, STransActio terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } + rpcMsg.info.traceId.rootId = pTrans->mTraceId; + memcpy(rpcMsg.pCont, pAction->pCont, pAction->contLen); char detail[1024] = {0}; @@ -1430,7 +1464,7 @@ static bool mndTransPerformCommitActionStage(SMnode *pMnode, STrans *pTrans) { if (code == 0) { pTrans->code = 0; - pTrans->stage = TRN_STAGE_FINISHED; + pTrans->stage = TRN_STAGE_FINISHED; // TRN_STAGE_PRE_FINISH is not necessary mInfo("trans:%d, stage from commitAction to finished", pTrans->id); continueExec = true; } else { @@ -1448,8 +1482,8 @@ static bool mndTransPerformUndoActionStage(SMnode *pMnode, STrans *pTrans) { int32_t code = mndTransExecuteUndoActions(pMnode, pTrans); if (code == 0) { - pTrans->stage = TRN_STAGE_FINISHED; - mInfo("trans:%d, stage from undoAction to finished", pTrans->id); + pTrans->stage = TRN_STAGE_PRE_FINISH; + mInfo("trans:%d, stage from undoAction to pre-finish", pTrans->id); continueExec = true; } else if (code == TSDB_CODE_ACTION_IN_PROGRESS) { mInfo("trans:%d, stage keep on undoAction since %s", pTrans->id, tstrerror(code)); @@ -1482,6 +1516,25 @@ static bool mndTransPerformRollbackStage(SMnode *pMnode, STrans *pTrans) { return continueExec; } +static bool mndTransPerfromPreFinishedStage(SMnode *pMnode, STrans *pTrans) { + if (mndCannotExecuteTransAction(pMnode)) return false; + + bool continueExec = true; + int32_t code = mndTransPreFinish(pMnode, pTrans); + + if (code == 0) { + pTrans->stage = TRN_STAGE_FINISHED; + mInfo("trans:%d, stage from pre-finish to finish", pTrans->id); + continueExec = true; + } else { + pTrans->failedTimes++; + mError("trans:%d, stage keep on pre-finish since %s, failedTimes:%d", pTrans->id, terrstr(), pTrans->failedTimes); + continueExec = false; + } + + return continueExec; +} + static bool mndTransPerfromFinishedStage(SMnode *pMnode, STrans *pTrans) { bool continueExec = false; @@ -1538,6 +1591,14 @@ void mndTransExecute(SMnode *pMnode, STrans *pTrans, bool isLeader) { case TRN_STAGE_UNDO_ACTION: continueExec = mndTransPerformUndoActionStage(pMnode, pTrans); break; + case TRN_STAGE_PRE_FINISH: + if (isLeader) { + continueExec = mndTransPerfromPreFinishedStage(pMnode, pTrans); + } else { + mInfo("trans:%d, can not pre-finish since not leader", pTrans->id); + continueExec = false; + } + break; case TRN_STAGE_FINISHED: continueExec = mndTransPerfromFinishedStage(pMnode, pTrans); break; @@ -1638,8 +1699,6 @@ void mndTransPullup(SMnode *pMnode) { } mndReleaseTrans(pMnode, pTrans); } - - sdbWriteFile(pMnode->pSdb, SDB_WRITE_DELTA); taosArrayDestroy(pArray); } @@ -1658,36 +1717,36 @@ static int32_t mndRetrieveTrans(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl cols = 0; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pTrans->id, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pTrans->id, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pTrans->createdTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pTrans->createdTime, false); char stage[TSDB_TRANS_STAGE_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(stage, mndTransStr(pTrans->stage), pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)stage, false); + colDataSetVal(pColInfo, numOfRows, (const char *)stage, false); char opername[TSDB_TRANS_OPER_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(opername, pTrans->opername, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)opername, false); + colDataSetVal(pColInfo, numOfRows, (const char *)opername, false); char dbname[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(dbname, mndGetDbStr(pTrans->dbname), pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)dbname, false); + colDataSetVal(pColInfo, numOfRows, (const char *)dbname, false); char stbname[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(stbname, mndGetDbStr(pTrans->stbname), pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)stbname, false); + colDataSetVal(pColInfo, numOfRows, (const char *)stbname, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pTrans->failedTimes, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pTrans->failedTimes, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pTrans->lastExecTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pTrans->lastExecTime, false); char lastInfo[TSDB_TRANS_ERROR_LEN + VARSTR_HEADER_SIZE] = {0}; char detail[TSDB_TRANS_ERROR_LEN + 1] = {0}; @@ -1703,7 +1762,7 @@ static int32_t mndRetrieveTrans(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl } STR_WITH_MAXSIZE_TO_VARSTR(lastInfo, detail, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)lastInfo, false); + colDataSetVal(pColInfo, numOfRows, (const char *)lastInfo, false); numOfRows++; sdbRelease(pSdb, pTrans); diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c index b965e1331649af7634385cea552f1d129750ad89..2a0d7537220a7eed3518557676d3d79bac6a11c1 100644 --- a/source/dnode/mnode/impl/src/mndUser.c +++ b/source/dnode/mnode/impl/src/mndUser.c @@ -18,11 +18,12 @@ #include "mndDb.h" #include "mndPrivilege.h" #include "mndShow.h" +#include "mndStb.h" #include "mndTopic.h" #include "mndTrans.h" #include "tbase64.h" -#define USER_VER_NUMBER 2 +#define USER_VER_NUMBER 3 #define USER_RESERVE_SIZE 64 static int32_t mndCreateDefaultUsers(SMnode *pMnode); @@ -124,9 +125,40 @@ SSdbRaw *mndUserActionEncode(SUserObj *pUser) { int32_t numOfReadDbs = taosHashGetSize(pUser->readDbs); int32_t numOfWriteDbs = taosHashGetSize(pUser->writeDbs); + int32_t numOfReadStbs = taosHashGetSize(pUser->readTbs); + int32_t numOfWriteStbs = taosHashGetSize(pUser->writeTbs); int32_t numOfTopics = taosHashGetSize(pUser->topics); - int32_t size = sizeof(SUserObj) + USER_RESERVE_SIZE + (numOfReadDbs + numOfWriteDbs) * TSDB_DB_FNAME_LEN + - numOfTopics * TSDB_TOPIC_FNAME_LEN; + int32_t numOfUseDbs = taosHashGetSize(pUser->useDbs); + int32_t size = sizeof(SUserObj) + USER_RESERVE_SIZE + + (numOfReadDbs + numOfWriteDbs + numOfUseDbs) * TSDB_DB_FNAME_LEN + numOfTopics * TSDB_TOPIC_FNAME_LEN; + + char *stb = taosHashIterate(pUser->readTbs, NULL); + while (stb != NULL) { + size_t keyLen = 0; + void *key = taosHashGetKey(stb, &keyLen); + size += sizeof(int32_t); + size += keyLen; + + size_t valueLen = 0; + valueLen = strlen(stb); + size += sizeof(int32_t); + size += valueLen; + stb = taosHashIterate(pUser->readTbs, stb); + } + + stb = taosHashIterate(pUser->writeTbs, NULL); + while (stb != NULL) { + size_t keyLen = 0; + void *key = taosHashGetKey(stb, &keyLen); + size += sizeof(int32_t); + size += keyLen; + + size_t valueLen = 0; + valueLen = strlen(stb); + size += sizeof(int32_t); + size += valueLen; + stb = taosHashIterate(pUser->writeTbs, stb); + } SSdbRaw *pRaw = sdbAllocRaw(SDB_USER, USER_VER_NUMBER, size); if (pRaw == NULL) goto _OVER; @@ -164,6 +196,49 @@ SSdbRaw *mndUserActionEncode(SUserObj *pUser) { topic = taosHashIterate(pUser->topics, topic); } + SDB_SET_INT32(pRaw, dataPos, numOfReadStbs, _OVER) + SDB_SET_INT32(pRaw, dataPos, numOfWriteStbs, _OVER) + SDB_SET_INT32(pRaw, dataPos, numOfUseDbs, _OVER) + + stb = taosHashIterate(pUser->readTbs, NULL); + while (stb != NULL) { + size_t keyLen = 0; + void *key = taosHashGetKey(stb, &keyLen); + SDB_SET_INT32(pRaw, dataPos, keyLen, _OVER) + SDB_SET_BINARY(pRaw, dataPos, key, keyLen, _OVER); + + size_t valueLen = 0; + valueLen = strlen(stb) + 1; + SDB_SET_INT32(pRaw, dataPos, valueLen, _OVER) + SDB_SET_BINARY(pRaw, dataPos, stb, valueLen, _OVER); + stb = taosHashIterate(pUser->readTbs, stb); + } + + stb = taosHashIterate(pUser->writeTbs, NULL); + while (stb != NULL) { + size_t keyLen = 0; + void *key = taosHashGetKey(stb, &keyLen); + SDB_SET_INT32(pRaw, dataPos, keyLen, _OVER) + SDB_SET_BINARY(pRaw, dataPos, key, keyLen, _OVER); + + size_t valueLen = 0; + valueLen = strlen(stb) + 1; + SDB_SET_INT32(pRaw, dataPos, valueLen, _OVER) + SDB_SET_BINARY(pRaw, dataPos, stb, valueLen, _OVER); + stb = taosHashIterate(pUser->writeTbs, stb); + } + + int32_t *useDb = taosHashIterate(pUser->useDbs, NULL); + while (useDb != NULL) { + size_t keyLen = 0; + void *key = taosHashGetKey(useDb, &keyLen); + SDB_SET_INT32(pRaw, dataPos, keyLen, _OVER) + SDB_SET_BINARY(pRaw, dataPos, key, keyLen, _OVER); + + SDB_SET_INT32(pRaw, dataPos, *useDb, _OVER) + useDb = taosHashIterate(pUser->useDbs, useDb); + } + SDB_SET_RESERVE(pRaw, dataPos, USER_RESERVE_SIZE, _OVER) SDB_SET_DATALEN(pRaw, dataPos, _OVER) @@ -188,7 +263,7 @@ static SSdbRow *mndUserActionDecode(SSdbRaw *pRaw) { int8_t sver = 0; if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER; - if (sver != 1 && sver != 2) { + if (sver != 1 && sver != 2 && sver != 3) { terrno = TSDB_CODE_SDB_INVALID_DATA_VER; goto _OVER; } @@ -249,6 +324,76 @@ static SSdbRow *mndUserActionDecode(SSdbRaw *pRaw) { } } + if (sver >= 3) { + int32_t numOfReadStbs = 0; + int32_t numOfWriteStbs = 0; + int32_t numOfUseDbs = 0; + SDB_GET_INT32(pRaw, dataPos, &numOfReadStbs, _OVER) + SDB_GET_INT32(pRaw, dataPos, &numOfWriteStbs, _OVER) + SDB_GET_INT32(pRaw, dataPos, &numOfUseDbs, _OVER) + + pUser->readTbs = + taosHashInit(numOfReadStbs, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + pUser->writeTbs = + taosHashInit(numOfWriteStbs, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + pUser->useDbs = taosHashInit(numOfUseDbs, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + + for (int32_t i = 0; i < numOfReadStbs; ++i) { + int32_t keyLen = 0; + SDB_GET_INT32(pRaw, dataPos, &keyLen, _OVER); + + char *key = taosMemoryCalloc(keyLen, sizeof(char)); + memset(key, 0, keyLen); + SDB_GET_BINARY(pRaw, dataPos, key, keyLen, _OVER); + + int32_t valuelen = 0; + SDB_GET_INT32(pRaw, dataPos, &valuelen, _OVER); + char *value = taosMemoryCalloc(valuelen, sizeof(char)); + memset(value, 0, valuelen); + SDB_GET_BINARY(pRaw, dataPos, value, valuelen, _OVER) + + taosHashPut(pUser->readTbs, key, keyLen, value, valuelen); + + taosMemoryFree(key); + taosMemoryFree(value); + } + + for (int32_t i = 0; i < numOfWriteStbs; ++i) { + int32_t keyLen = 0; + SDB_GET_INT32(pRaw, dataPos, &keyLen, _OVER); + + char *key = taosMemoryCalloc(keyLen, sizeof(char)); + memset(key, 0, keyLen); + SDB_GET_BINARY(pRaw, dataPos, key, keyLen, _OVER); + + int32_t valuelen = 0; + SDB_GET_INT32(pRaw, dataPos, &valuelen, _OVER); + char *value = taosMemoryCalloc(valuelen, sizeof(char)); + memset(value, 0, valuelen); + SDB_GET_BINARY(pRaw, dataPos, value, valuelen, _OVER) + + taosHashPut(pUser->writeTbs, key, keyLen, value, valuelen); + + taosMemoryFree(key); + taosMemoryFree(value); + } + + for (int32_t i = 0; i < numOfUseDbs; ++i) { + int32_t keyLen = 0; + SDB_GET_INT32(pRaw, dataPos, &keyLen, _OVER); + + char *key = taosMemoryCalloc(keyLen, sizeof(char)); + memset(key, 0, keyLen); + SDB_GET_BINARY(pRaw, dataPos, key, keyLen, _OVER); + + int32_t ref = 0; + SDB_GET_INT32(pRaw, dataPos, &ref, _OVER); + + taosHashPut(pUser->useDbs, key, keyLen, &ref, sizeof(ref)); + taosMemoryFree(key); + } + } + SDB_GET_RESERVE(pRaw, dataPos, USER_RESERVE_SIZE, _OVER) taosInitRWLatch(&pUser->lock); @@ -261,6 +406,9 @@ _OVER: taosHashCleanup(pUser->readDbs); taosHashCleanup(pUser->writeDbs); taosHashCleanup(pUser->topics); + taosHashCleanup(pUser->readTbs); + taosHashCleanup(pUser->writeTbs); + taosHashCleanup(pUser->useDbs); } taosMemoryFreeClear(pRow); return NULL; @@ -285,6 +433,57 @@ static int32_t mndUserActionInsert(SSdb *pSdb, SUserObj *pUser) { return 0; } +SHashObj *mndDupTableHash(SHashObj *pOld) { + SHashObj *pNew = + taosHashInit(taosHashGetSize(pOld), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + if (pNew == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + char *tb = taosHashIterate(pOld, NULL); + while (tb != NULL) { + size_t keyLen = 0; + char *key = taosHashGetKey(tb, &keyLen); + + int32_t valueLen = strlen(tb) + 1; + if (taosHashPut(pNew, key, keyLen, tb, valueLen) != 0) { + taosHashCancelIterate(pOld, tb); + taosHashCleanup(pNew); + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + tb = taosHashIterate(pOld, tb); + } + + return pNew; +} + +SHashObj *mndDupUseDbHash(SHashObj *pOld) { + SHashObj *pNew = + taosHashInit(taosHashGetSize(pOld), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); + if (pNew == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + int32_t *db = taosHashIterate(pOld, NULL); + while (db != NULL) { + size_t keyLen = 0; + char *key = taosHashGetKey(db, &keyLen); + + if (taosHashPut(pNew, key, keyLen, db, sizeof(*db)) != 0) { + taosHashCancelIterate(pOld, db); + taosHashCleanup(pNew); + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + db = taosHashIterate(pOld, db); + } + + return pNew; +} + static int32_t mndUserDupObj(SUserObj *pUser, SUserObj *pNew) { memcpy(pNew, pUser, sizeof(SUserObj)); pNew->authVersion++; @@ -293,7 +492,10 @@ static int32_t mndUserDupObj(SUserObj *pUser, SUserObj *pNew) { taosRLockLatch(&pUser->lock); pNew->readDbs = mndDupDbHash(pUser->readDbs); pNew->writeDbs = mndDupDbHash(pUser->writeDbs); + pNew->readTbs = mndDupTableHash(pUser->readTbs); + pNew->writeTbs = mndDupTableHash(pUser->writeTbs); pNew->topics = mndDupTopicHash(pUser->topics); + pNew->useDbs = mndDupUseDbHash(pUser->useDbs); taosRUnLockLatch(&pUser->lock); if (pNew->readDbs == NULL || pNew->writeDbs == NULL || pNew->topics == NULL) { @@ -306,9 +508,15 @@ static void mndUserFreeObj(SUserObj *pUser) { taosHashCleanup(pUser->readDbs); taosHashCleanup(pUser->writeDbs); taosHashCleanup(pUser->topics); + taosHashCleanup(pUser->readTbs); + taosHashCleanup(pUser->writeTbs); + taosHashCleanup(pUser->useDbs); pUser->readDbs = NULL; pUser->writeDbs = NULL; pUser->topics = NULL; + pUser->readTbs = NULL; + pUser->writeTbs = NULL; + pUser->useDbs = NULL; } static int32_t mndUserActionDelete(SSdb *pSdb, SUserObj *pUser) { @@ -328,6 +536,9 @@ static int32_t mndUserActionUpdate(SSdb *pSdb, SUserObj *pOld, SUserObj *pNew) { TSWAP(pOld->readDbs, pNew->readDbs); TSWAP(pOld->writeDbs, pNew->writeDbs); TSWAP(pOld->topics, pNew->topics); + TSWAP(pOld->readTbs, pNew->readTbs); + TSWAP(pOld->writeTbs, pNew->writeTbs); + TSWAP(pOld->useDbs, pNew->useDbs); taosWUnLockLatch(&pOld->lock); return 0; @@ -337,7 +548,11 @@ SUserObj *mndAcquireUser(SMnode *pMnode, const char *userName) { SSdb *pSdb = pMnode->pSdb; SUserObj *pUser = sdbAcquire(pSdb, SDB_USER, userName); if (pUser == NULL) { - terrno = TSDB_CODE_MND_USER_NOT_EXIST; + if (terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) { + terrno = TSDB_CODE_MND_USER_NOT_EXIST; + } else { + terrno = TSDB_CODE_MND_USER_NOT_AVAILABLE; + } } return pUser; } @@ -494,6 +709,71 @@ SHashObj *mndDupDbHash(SHashObj *pOld) { return mndDupObjHash(pOld, TSDB_DB_FNAM SHashObj *mndDupTopicHash(SHashObj *pOld) { return mndDupObjHash(pOld, TSDB_TOPIC_FNAME_LEN); } +static int32_t mndTablePriviledge(SMnode *pMnode, SHashObj *hash, SHashObj *useDbHash, SAlterUserReq *alterReq, + SSdb *pSdb) { + void *pIter = NULL; + char tbFName[TSDB_TABLE_FNAME_LEN] = {0}; + + snprintf(tbFName, sizeof(tbFName), "%s.%s", alterReq->objname, alterReq->tabName); + int32_t len = strlen(tbFName) + 1; + + if (alterReq->tagCond != NULL && alterReq->tagCondLen != 0) { + char *value = taosHashGet(hash, tbFName, len); + if (value != NULL) { + terrno = TSDB_CODE_MND_PRIVILEDGE_EXIST; + return -1; + } + + int32_t condLen = alterReq->tagCondLen; + if (taosHashPut(hash, tbFName, len, alterReq->tagCond, condLen) != 0) { + return -1; + } + } else { + if (taosHashPut(hash, tbFName, len, "t", 2) != 0) { + return -1; + } + } + + int32_t dbKeyLen = strlen(alterReq->objname) + 1; + int32_t ref = 1; + int32_t *currRef = taosHashGet(useDbHash, alterReq->objname, dbKeyLen); + if (NULL != currRef) { + ref = (*currRef) + 1; + } + if (taosHashPut(useDbHash, alterReq->objname, dbKeyLen, &ref, sizeof(ref)) != 0) { + return -1; + } + + return 0; +} + +static int32_t mndRemoveTablePriviledge(SMnode *pMnode, SHashObj *hash, SHashObj *useDbHash, SAlterUserReq *alterReq, + SSdb *pSdb) { + void *pIter = NULL; + char tbFName[TSDB_TABLE_FNAME_LEN] = {0}; + snprintf(tbFName, sizeof(tbFName), "%s.%s", alterReq->objname, alterReq->tabName); + int32_t len = strlen(tbFName) + 1; + + if (taosHashRemove(hash, tbFName, len) != 0) { + return -1; + } + + int32_t dbKeyLen = strlen(alterReq->objname) + 1; + int32_t *currRef = taosHashGet(useDbHash, alterReq->objname, dbKeyLen); + if (NULL == currRef || 1 == *currRef) { + if (taosHashRemove(useDbHash, alterReq->objname, dbKeyLen) != 0) { + return -1; + } + return 0; + } + int32_t ref = (*currRef) - 1; + if (taosHashPut(useDbHash, alterReq->objname, dbKeyLen, &ref, sizeof(ref)) != 0) { + return -1; + } + + return 0; +} + static int32_t mndProcessAlterUserReq(SRpcMsg *pReq) { SMnode *pMnode = pReq->info.node; SSdb *pSdb = pMnode->pSdb; @@ -633,6 +913,22 @@ static int32_t mndProcessAlterUserReq(SRpcMsg *pReq) { } } + if (alterReq.alterType == TSDB_ALTER_USER_ADD_READ_TABLE) { + if (mndTablePriviledge(pMnode, newUser.readTbs, newUser.useDbs, &alterReq, pSdb) != 0) goto _OVER; + } + + if (alterReq.alterType == TSDB_ALTER_USER_ADD_WRITE_TABLE) { + if (mndTablePriviledge(pMnode, newUser.writeTbs, newUser.useDbs, &alterReq, pSdb) != 0) goto _OVER; + } + + if (alterReq.alterType == TSDB_ALTER_USER_REMOVE_READ_TABLE) { + if (mndRemoveTablePriviledge(pMnode, newUser.readTbs, newUser.useDbs, &alterReq, pSdb) != 0) goto _OVER; + } + + if (alterReq.alterType == TSDB_ALTER_USER_REMOVE_WRITE_TABLE) { + if (mndRemoveTablePriviledge(pMnode, newUser.writeTbs, newUser.useDbs, &alterReq, pSdb) != 0) goto _OVER; + } + if (alterReq.alterType == TSDB_ALTER_USER_ADD_SUBSCRIBE_TOPIC) { int32_t len = strlen(alterReq.objname) + 1; SMqTopicObj *pTopic = mndAcquireTopic(pMnode, alterReq.objname); @@ -661,6 +957,7 @@ _OVER: mError("user:%s, failed to alter since %s", alterReq.user, terrstr()); } + tFreeSAlterUserReq(&alterReq); mndReleaseUser(pMnode, pOperUser); mndReleaseUser(pMnode, pUser); mndUserFreeObj(&newUser); @@ -795,23 +1092,23 @@ static int32_t mndRetrieveUsers(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols); char name[TSDB_USER_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(name, pUser->user, pShow->pMeta->pSchemas[cols].bytes); - colDataAppend(pColInfo, numOfRows, (const char *)name, false); + colDataSetVal(pColInfo, numOfRows, (const char *)name, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); - colDataAppend(pColInfo, numOfRows, (const char *)&pUser->superUser, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pUser->superUser, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); - colDataAppend(pColInfo, numOfRows, (const char *)&pUser->enable, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pUser->enable, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); - colDataAppend(pColInfo, numOfRows, (const char *)&pUser->sysInfo, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pUser->sysInfo, false); cols++; pColInfo = taosArrayGet(pBlock->pDataBlock, cols); - colDataAppend(pColInfo, numOfRows, (const char *)&pUser->createdTime, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pUser->createdTime, false); numOfRows++; sdbRelease(pSdb, pUser); @@ -826,6 +1123,70 @@ static void mndCancelGetNextUser(SMnode *pMnode, void *pIter) { sdbCancelFetch(pSdb, pIter); } +static void mndLoopHash(SHashObj *hash, char *priType, SSDataBlock *pBlock, int32_t *numOfRows, char *user, + SShowObj *pShow) { + char *value = taosHashIterate(hash, NULL); + int32_t cols = 0; + + while (value != NULL) { + cols = 0; + char userName[TSDB_USER_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(userName, user, pShow->pMeta->pSchemas[cols].bytes); + SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, *numOfRows, (const char *)userName, false); + + char privilege[20] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(privilege, priType, pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, *numOfRows, (const char *)privilege, false); + + size_t keyLen = 0; + void *key = taosHashGetKey(value, &keyLen); + + char dbName[TSDB_DB_NAME_LEN] = {0}; + mndExtractShortDbNameFromStbFullName(key, dbName); + char dbNameContent[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(dbNameContent, dbName, pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, *numOfRows, (const char *)dbNameContent, false); + + char tableName[TSDB_TABLE_NAME_LEN] = {0}; + mndExtractTbNameFromStbFullName(key, tableName, TSDB_TABLE_NAME_LEN); + char tableNameContent[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(tableNameContent, tableName, pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, *numOfRows, (const char *)tableNameContent, false); + + if (strcmp("t", value) != 0) { + SNode *pAst = NULL; + int32_t sqlLen = 0; + char sql[TSDB_EXPLAIN_RESULT_ROW_SIZE] = {0}; + + if (nodesStringToNode(value, &pAst) == 0) { + nodesNodeToSQL(pAst, sql, TSDB_EXPLAIN_RESULT_ROW_SIZE, &sqlLen); + nodesDestroyNode(pAst); + } else { + sqlLen = 5; + sprintf(sql, "error"); + } + + char obj[TSDB_PRIVILEDGE_CONDITION_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(obj, sql, pShow->pMeta->pSchemas[cols].bytes); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, *numOfRows, (const char *)obj, false); + } else { + char condition[TSDB_PRIVILEDGE_CONDITION_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(condition, "", pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, *numOfRows, (const char *)condition, false); + } + + (*numOfRows)++; + value = taosHashIterate(hash, value); + } +} + static int32_t mndRetrievePrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) { SMnode *pMnode = pReq->info.node; SSdb *pSdb = pMnode->pSdb; @@ -841,24 +1202,36 @@ static int32_t mndRetrievePrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock int32_t numOfReadDbs = taosHashGetSize(pUser->readDbs); int32_t numOfWriteDbs = taosHashGetSize(pUser->writeDbs); int32_t numOfTopics = taosHashGetSize(pUser->topics); - if (numOfRows + numOfReadDbs + numOfWriteDbs + numOfTopics >= rows) break; + int32_t numOfReadTbs = taosHashGetSize(pUser->readTbs); + int32_t numOfWriteTbs = taosHashGetSize(pUser->writeTbs); + if (numOfRows + numOfReadDbs + numOfWriteDbs + numOfTopics + numOfReadTbs + numOfWriteTbs >= rows) break; if (pUser->superUser) { cols = 0; char userName[TSDB_USER_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(userName, pUser->user, pShow->pMeta->pSchemas[cols].bytes); SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)userName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)userName, false); char privilege[20] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(privilege, "all", pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)privilege, false); + colDataSetVal(pColInfo, numOfRows, (const char *)privilege, false); char objName[20] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(objName, "all", pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)objName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)objName, false); + + char tableName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(tableName, "", pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)tableName, false); + + char condition[TSDB_PRIVILEDGE_CONDITION_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(condition, "", pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)condition, false); numOfRows++; } @@ -869,12 +1242,12 @@ static int32_t mndRetrievePrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock char userName[TSDB_USER_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(userName, pUser->user, pShow->pMeta->pSchemas[cols].bytes); SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)userName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)userName, false); char privilege[20] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(privilege, "read", pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)privilege, false); + colDataSetVal(pColInfo, numOfRows, (const char *)privilege, false); SName name = {0}; char objName[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; @@ -882,7 +1255,17 @@ static int32_t mndRetrievePrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock tNameGetDbName(&name, varDataVal(objName)); varDataSetLen(objName, strlen(varDataVal(objName))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)objName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)objName, false); + + char tableName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(tableName, "", pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)tableName, false); + + char condition[TSDB_PRIVILEDGE_CONDITION_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(condition, "", pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)condition, false); numOfRows++; db = taosHashIterate(pUser->readDbs, db); @@ -894,12 +1277,12 @@ static int32_t mndRetrievePrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock char userName[TSDB_USER_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(userName, pUser->user, pShow->pMeta->pSchemas[cols].bytes); SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)userName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)userName, false); char privilege[20] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(privilege, "write", pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)privilege, false); + colDataSetVal(pColInfo, numOfRows, (const char *)privilege, false); SName name = {0}; char objName[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; @@ -907,30 +1290,54 @@ static int32_t mndRetrievePrivileges(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock tNameGetDbName(&name, varDataVal(objName)); varDataSetLen(objName, strlen(varDataVal(objName))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)objName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)objName, false); + + char tableName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(tableName, "", pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)tableName, false); + + char condition[TSDB_PRIVILEDGE_CONDITION_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(condition, "", pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)condition, false); numOfRows++; db = taosHashIterate(pUser->writeDbs, db); } + mndLoopHash(pUser->readTbs, "read", pBlock, &numOfRows, pUser->user, pShow); + + mndLoopHash(pUser->writeTbs, "write", pBlock, &numOfRows, pUser->user, pShow); + char *topic = taosHashIterate(pUser->topics, NULL); while (topic != NULL) { cols = 0; char userName[TSDB_USER_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(userName, pUser->user, pShow->pMeta->pSchemas[cols].bytes); SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)userName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)userName, false); char privilege[20] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(privilege, "subscribe", pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)privilege, false); + colDataSetVal(pColInfo, numOfRows, (const char *)privilege, false); char topicName[TSDB_TOPIC_NAME_LEN + VARSTR_HEADER_SIZE + 5] = {0}; tstrncpy(varDataVal(topicName), mndGetDbStr(topic), TSDB_TOPIC_NAME_LEN - 2); varDataSetLen(topicName, strlen(varDataVal(topicName))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)topicName, false); + colDataSetVal(pColInfo, numOfRows, (const char *)topicName, false); + + char tableName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(tableName, "", pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)tableName, false); + + char condition[TSDB_PRIVILEDGE_CONDITION_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_WITH_MAXSIZE_TO_VARSTR(condition, "", pShow->pMeta->pSchemas[cols].bytes); + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)condition, false); numOfRows++; topic = taosHashIterate(pUser->topics, topic); @@ -1062,10 +1469,14 @@ int32_t mndUserRemoveTopic(SMnode *pMnode, STrans *pTrans, char *topic) { while (1) { pIter = sdbFetch(pSdb, SDB_USER, pIter, (void **)&pUser); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } code = -1; - if (mndUserDupObj(pUser, &newUser) != 0) break; + if (mndUserDupObj(pUser, &newUser) != 0) { + break; + } bool inTopic = (taosHashGet(newUser.topics, topic, len) != NULL); if (inTopic) { diff --git a/source/dnode/mnode/impl/src/mndVgroup.c b/source/dnode/mnode/impl/src/mndVgroup.c index 54ea9e7b2437b303088fcdd9d003eb1aa19af8e5..0003d07fd6fd4c94d20af741d55dff751cc65345 100644 --- a/source/dnode/mnode/impl/src/mndVgroup.c +++ b/source/dnode/mnode/impl/src/mndVgroup.c @@ -40,6 +40,7 @@ static void mndCancelGetNextVnode(SMnode *pMnode, void *pIter); static int32_t mndProcessRedistributeVgroupMsg(SRpcMsg *pReq); static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq); static int32_t mndProcessBalanceVgroupMsg(SRpcMsg *pReq); +static int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq); int32_t mndInitVgroup(SMnode *pMnode) { SSdbTable table = { @@ -59,10 +60,14 @@ int32_t mndInitVgroup(SMnode *pMnode) { mndSetMsgHandle(pMnode, TDMT_VND_ALTER_HASHRANGE_RSP, mndTransProcessRsp); mndSetMsgHandle(pMnode, TDMT_DND_DROP_VNODE_RSP, mndTransProcessRsp); mndSetMsgHandle(pMnode, TDMT_VND_COMPACT_RSP, mndTransProcessRsp); + mndSetMsgHandle(pMnode, TDMT_VND_DISABLE_WRITE_RSP, mndTransProcessRsp); + mndSetMsgHandle(pMnode, TDMT_SYNC_FORCE_FOLLOWER_RSP, mndTransProcessRsp); mndSetMsgHandle(pMnode, TDMT_MND_REDISTRIBUTE_VGROUP, mndProcessRedistributeVgroupMsg); mndSetMsgHandle(pMnode, TDMT_MND_SPLIT_VGROUP, mndProcessSplitVgroupMsg); + //mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessVgroupBalanceLeaderMsg); mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP, mndProcessBalanceVgroupMsg); + mndSetMsgHandle(pMnode, TDMT_MND_BALANCE_VGROUP_LEADER, mndProcessVgroupBalanceLeaderMsg); mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndRetrieveVgroups); mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_VGROUP, mndCancelGetNextVgroup); @@ -318,6 +323,10 @@ static void *mndBuildAlterVnodeConfigReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pV alterReq.walLevel = pDb->cfg.walLevel; alterReq.strict = pDb->cfg.strict; alterReq.cacheLast = pDb->cfg.cacheLast; + alterReq.sttTrigger = pDb->cfg.sstTrigger; + alterReq.minRows = pDb->cfg.minRows; + alterReq.walRetentionPeriod = pDb->cfg.walRetentionPeriod; + alterReq.walRetentionSize = pDb->cfg.walRetentionSize; mInfo("vgId:%d, build alter vnode config req", pVgroup->vgId); int32_t contLen = tSerializeSAlterVnodeConfigReq(NULL, 0, &alterReq); @@ -355,9 +364,7 @@ static void *mndBuildAlterVnodeReplicaReq(SMnode *pMnode, SDbObj *pDb, SVgObj *p SReplica *pReplica = &alterReq.replicas[v]; SVnodeGid *pVgid = &pVgroup->vnodeGid[v]; SDnodeObj *pVgidDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); - if (pVgidDnode == NULL) { - return NULL; - } + if (pVgidDnode == NULL) return NULL; pReplica->id = pVgidDnode->id; pReplica->port = pVgidDnode->port; @@ -397,6 +404,57 @@ static void *mndBuildAlterVnodeReplicaReq(SMnode *pMnode, SDbObj *pDb, SVgObj *p return pReq; } +static void *mndBuildDisableVnodeWriteReq(SMnode *pMnode, SDbObj *pDb, int32_t vgId, int32_t *pContLen) { + SDisableVnodeWriteReq disableReq = { + .vgId = vgId, + .disable = 1, + }; + + mInfo("vgId:%d, build disable vnode write req", vgId); + int32_t contLen = tSerializeSDisableVnodeWriteReq(NULL, 0, &disableReq); + if (contLen < 0) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + void *pReq = taosMemoryMalloc(contLen); + if (pReq == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + tSerializeSDisableVnodeWriteReq(pReq, contLen, &disableReq); + *pContLen = contLen; + return pReq; +} + +static void *mndBuildAlterVnodeHashRangeReq(SMnode *pMnode, SVgObj *pVgroup, int32_t dstVgId, int32_t *pContLen) { + SAlterVnodeHashRangeReq alterReq = { + .srcVgId = pVgroup->vgId, + .dstVgId = dstVgId, + .hashBegin = pVgroup->hashBegin, + .hashEnd = pVgroup->hashEnd, + }; + + mInfo("vgId:%d, build alter vnode hashrange req, dstVgId:%d, hashrange:[%u, %u]", pVgroup->vgId, dstVgId, + pVgroup->hashBegin, pVgroup->hashEnd); + int32_t contLen = tSerializeSAlterVnodeHashRangeReq(NULL, 0, &alterReq); + if (contLen < 0) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + void *pReq = taosMemoryMalloc(contLen); + if (pReq == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + tSerializeSAlterVnodeHashRangeReq(pReq, contLen, &alterReq); + *pContLen = contLen; + return pReq; +} + void *mndBuildDropVnodeReq(SMnode *pMnode, SDnodeObj *pDnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen) { SDropVnodeReq dropReq = {0}; dropReq.dnodeId = pDnode->id; @@ -478,7 +536,12 @@ SArray *mndBuildDnodesArray(SMnode *pMnode, int32_t exceptDnodeId) { return pArray; } -static int32_t mndCompareDnodeId(int32_t *dnode1Id, int32_t *dnode2Id) { return *dnode1Id >= *dnode2Id ? 1 : 0; } +static int32_t mndCompareDnodeId(int32_t *dnode1Id, int32_t *dnode2Id) { + if (*dnode1Id == *dnode2Id) { + return 0; + } + return *dnode1Id > *dnode2Id ? 1 : -1; +} static float mndGetDnodeScore(SDnodeObj *pDnode, int32_t additionDnodes, float ratio) { float totalDnodes = pDnode->numOfVnodes + (float)pDnode->numOfOtherNodes * ratio + additionDnodes; @@ -488,7 +551,10 @@ static float mndGetDnodeScore(SDnodeObj *pDnode, int32_t additionDnodes, float r static int32_t mndCompareDnodeVnodes(SDnodeObj *pDnode1, SDnodeObj *pDnode2) { float d1Score = mndGetDnodeScore(pDnode1, 0, 0.9); float d2Score = mndGetDnodeScore(pDnode2, 0, 0.9); - return d1Score >= d2Score ? 1 : 0; + if (d1Score == d2Score) { + return 0; + } + return d1Score > d2Score ? 1 : -1; } void mndSortVnodeGid(SVgObj *pVgroup) { @@ -681,7 +747,7 @@ static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p cols = 0; SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false); SName name = {0}; char db[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; @@ -690,17 +756,17 @@ static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p varDataSetLen(db, strlen(varDataVal(db))); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)db, false); + colDataSetVal(pColInfo, numOfRows, (const char *)db, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pVgroup->numOfTables, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->numOfTables, false); // default 3 replica, add 1 replica if move vnode for (int32_t i = 0; i < 4; ++i) { pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); if (i < pVgroup->replica) { int16_t dnodeId = (int16_t)pVgroup->vnodeGid[i].dnodeId; - colDataAppend(pColInfo, numOfRows, (const char *)&dnodeId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&dnodeId, false); bool exist = false; bool online = false; @@ -731,20 +797,30 @@ static int32_t mndRetrieveVgroups(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *p STR_WITH_MAXSIZE_TO_VARSTR(buf1, role, pShow->pMeta->pSchemas[cols].bytes); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)buf1, false); + colDataSetVal(pColInfo, numOfRows, (const char *)buf1, false); } else { - colDataAppendNULL(pColInfo, numOfRows); + colDataSetNULL(pColInfo, numOfRows); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppendNULL(pColInfo, numOfRows); + colDataSetNULL(pColInfo, numOfRows); } } pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); int32_t cacheUsage = (int32_t)pVgroup->cacheUsage; - colDataAppend(pColInfo, numOfRows, (const char *)&cacheUsage, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&cacheUsage, false); + + pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->numOfCachedTables, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pVgroup->isTsma, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->isTsma, false); + + // pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); + // if (pDb == NULL || pDb->compactStartTime <= 0) { + // colDataSetNULL(pColInfo, numOfRows); + // } else { + // colDataAppend(pColInfo, numOfRows, (const char *)&pDb->compactStartTime, false); + // } numOfRows++; sdbRelease(pSdb, pVgroup); @@ -840,15 +916,15 @@ static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB cols = 0; pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->vgId, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pVgroup->replica, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pVgroup->replica, false); char buf[20] = {0}; STR_TO_VARSTR(buf, syncStr(pVgid->syncState)); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)buf, false); + colDataSetVal(pColInfo, numOfRows, (const char *)buf, false); const char *dbname = mndGetDbStr(pVgroup->dbName); char b1[TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; @@ -858,10 +934,10 @@ static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB STR_WITH_MAXSIZE_TO_VARSTR(b1, "NULL", TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE); } pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)b1, false); + colDataSetVal(pColInfo, numOfRows, (const char *)b1, false); pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)&pVgid->dnodeId, false); + colDataSetVal(pColInfo, numOfRows, (const char *)&pVgid->dnodeId, false); SDnodeObj *pDnode = mndAcquireDnode(pMnode, pVgid->dnodeId); char b2[TSDB_EP_LEN + VARSTR_HEADER_SIZE] = {0}; @@ -871,7 +947,7 @@ static int32_t mndRetrieveVnodes(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pB STR_WITH_MAXSIZE_TO_VARSTR(b2, "NULL", TSDB_EP_LEN + VARSTR_HEADER_SIZE); } pColInfo = taosArrayGet(pBlock->pDataBlock, cols++); - colDataAppend(pColInfo, numOfRows, (const char *)b2, false); + colDataSetVal(pColInfo, numOfRows, (const char *)b2, false); numOfRows++; } @@ -1029,6 +1105,7 @@ int32_t mndAddAlterVnodeConfirmAction(SMnode *pMnode, STrans *pTrans, SDbObj *pD STransAction action = {0}; action.epSet = mndGetVgroupEpset(pMnode, pVgroup); + mInfo("vgId:%d, build alter vnode confirm req", pVgroup->vgId); int32_t contLen = sizeof(SMsgHead); SMsgHead *pHead = taosMemoryMalloc(contLen); if (pHead == NULL) { @@ -1053,7 +1130,25 @@ int32_t mndAddAlterVnodeConfirmAction(SMnode *pMnode, STrans *pTrans, SDbObj *pD return 0; } -int32_t mndAddAlterVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) { return 0; } +static int32_t mndAddAlterVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, int32_t dstVgId) { + STransAction action = {0}; + action.epSet = mndGetVgroupEpset(pMnode, pVgroup); + + int32_t contLen = 0; + void *pReq = mndBuildAlterVnodeHashRangeReq(pMnode, pVgroup, dstVgId, &contLen); + if (pReq == NULL) return -1; + + action.pCont = pReq; + action.contLen = contLen; + action.msgType = TDMT_VND_ALTER_HASHRANGE; + + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + + return 0; +} int32_t mndAddAlterVnodeConfigAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup) { STransAction action = {0}; @@ -1099,6 +1194,31 @@ int32_t mndAddAlterVnodeReplicaAction(SMnode *pMnode, STrans *pTrans, SDbObj *pD return 0; } +static int32_t mndAddDisableVnodeWriteAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, + int32_t dnodeId) { + SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId); + if (pDnode == NULL) return -1; + + STransAction action = {0}; + action.epSet = mndGetDnodeEpset(pDnode); + mndReleaseDnode(pMnode, pDnode); + + int32_t contLen = 0; + void *pReq = mndBuildDisableVnodeWriteReq(pMnode, pDb, pVgroup->vgId, &contLen); + if (pReq == NULL) return -1; + + action.pCont = pReq; + action.contLen = contLen; + action.msgType = TDMT_VND_DISABLE_WRITE; + + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + + return 0; +} + int32_t mndAddDropVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, SVnodeGid *pVgid, bool isRedo) { STransAction action = {0}; @@ -1659,6 +1779,130 @@ _OVER: return code; } +static void *mndBuildSForceBecomeFollowerReq(SMnode *pMnode, SVgObj *pVgroup, int32_t dnodeId, + int32_t *pContLen) { + SForceBecomeFollowerReq balanceReq = { + .vgId = pVgroup->vgId, + }; + + int32_t contLen = tSerializeSForceBecomeFollowerReq(NULL, 0, &balanceReq); + if (contLen < 0) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + contLen += sizeof(SMsgHead); + + void *pReq = taosMemoryMalloc(contLen); + if (pReq == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + SMsgHead *pHead = pReq; + pHead->contLen = htonl(contLen); + pHead->vgId = htonl(pVgroup->vgId); + + tSerializeSForceBecomeFollowerReq((char *)pReq + sizeof(SMsgHead), contLen, &balanceReq); + *pContLen = contLen; + return pReq; +} + +int32_t mndAddBalanceVgroupLeaderAction(SMnode *pMnode, STrans *pTrans, SVgObj *pVgroup, int32_t dnodeId) { + SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId); + if (pDnode == NULL) return -1; + + STransAction action = {0}; + action.epSet = mndGetDnodeEpset(pDnode); + mndReleaseDnode(pMnode, pDnode); + + int32_t contLen = 0; + void *pReq = mndBuildSForceBecomeFollowerReq(pMnode, pVgroup, dnodeId, &contLen); + if (pReq == NULL) return -1; + + action.pCont = pReq; + action.contLen = contLen; + action.msgType = TDMT_SYNC_FORCE_FOLLOWER; + + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + + return 0; +} + +int32_t mndAddVgroupBalanceToTrans(SMnode *pMnode, SVgObj *pVgroup, STrans *pTrans){ + SSdb *pSdb = pMnode->pSdb; + + int32_t vgid = pVgroup->vgId; + int8_t replica = pVgroup->replica; + + if(pVgroup->replica <= 1) { + mInfo("trans:%d, vgid:%d no need to balance, replica:%d", pTrans->id, vgid, replica); + return -1; + } + + int32_t dnodeId = pVgroup->vnodeGid[0].dnodeId; + + for(int i = 0; i < replica; i++) + { + if(pVgroup->vnodeGid[i].syncState == TAOS_SYNC_STATE_LEADER){ + dnodeId = pVgroup->vnodeGid[i].dnodeId; + break; + } + } + + bool exist = false; + bool online = false; + int64_t curMs = taosGetTimestampMs(); + SDnodeObj *pDnode = mndAcquireDnode(pMnode, dnodeId); + if (pDnode != NULL) { + exist = true; + online = mndIsDnodeOnline(pDnode, curMs); + mndReleaseDnode(pMnode, pDnode); + } + + if(exist && online) + { + mInfo("trans:%d, vgid:%d leader to dnode:%d", pTrans->id, vgid, dnodeId); + + if (mndAddBalanceVgroupLeaderAction(pMnode, pTrans, pVgroup, dnodeId) != 0) { + mError("trans:%d, vgid:%d failed to be balanced to dnode:%d", pTrans->id, vgid, dnodeId); + return -1; + } + + SSdbRaw *pRaw = mndVgroupActionEncode(pVgroup); + if (pRaw == NULL) { + mError("trans:%d, vgid:%d failed to encode action to dnode:%d", pTrans->id, vgid, dnodeId); + return -1; + } + if (mndTransAppendCommitlog(pTrans, pRaw) != 0) { + sdbFreeRaw(pRaw); + mError("trans:%d, vgid:%d failed to append commit log dnode:%d", pTrans->id, vgid, dnodeId); + return -1; + } + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); + } + else + { + mInfo("trans:%d, vgid:%d cant be balanced to dnode:%d, exist:%d, online:%d", pTrans->id, vgid, dnodeId, exist, online); + } + + return 0; +} + +extern int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq); + +int32_t mndProcessVgroupBalanceLeaderMsg(SRpcMsg *pReq) { + return mndProcessVgroupBalanceLeaderMsgImp(pReq); +} + +#ifndef TD_ENTERPRISE +int32_t mndProcessVgroupBalanceLeaderMsgImp(SRpcMsg *pReq) { + return 0; +} +#endif + static int32_t mndCheckDnodeMemory(SMnode *pMnode, SDbObj *pOldDb, SDbObj *pNewDb, SVgObj *pOldVgroup, SVgObj *pNewVgroup, SArray *pArray) { for (int32_t i = 0; i < (int32_t)taosArrayGetSize(pArray); ++i) { @@ -1762,10 +2006,12 @@ static int32_t mndAddAdjustVnodeHashRangeAction(SMnode *pMnode, STrans *pTrans, return 0; } -static int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup) { - int32_t code = -1; - STrans *pTrans = NULL; - SArray *pArray = mndBuildDnodesArray(pMnode, 0); +int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj *pVgroup) { + int32_t code = -1; + STrans *pTrans = NULL; + SSdbRaw *pRaw = NULL; + SDbObj dbObj = {0}; + SArray *pArray = mndBuildDnodesArray(pMnode, 0); pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, pReq, "split-vgroup"); if (pTrans == NULL) goto _OVER; @@ -1784,23 +2030,20 @@ static int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj if (mndAddVnodeToVgroup(pMnode, pTrans, &newVg1, pArray) != 0) goto _OVER; if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId) != 0) goto _OVER; if (mndAddCreateVnodeAction(pMnode, pTrans, pDb, &newVg1, &newVg1.vnodeGid[1]) != 0) goto _OVER; - if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1) != 0) goto _OVER; } else if (newVg1.replica == 3) { SVnodeGid del1 = {0}; if (mndRemoveVnodeFromVgroup(pMnode, pTrans, &newVg1, pArray, &del1) != 0) goto _OVER; if (mndAddDropVnodeAction(pMnode, pTrans, pDb, &newVg1, &del1, true) != 0) goto _OVER; if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[0].dnodeId) != 0) goto _OVER; if (mndAddAlterVnodeReplicaAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[1].dnodeId) != 0) goto _OVER; - if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1) != 0) goto _OVER; } else { goto _OVER; } - mInfo("vgId:%d, vgroup info after adjust replica, replica:%d hashBegin:%u hashEnd:%u vnode:0 dnode:%d", newVg1.vgId, - newVg1.replica, newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId); for (int32_t i = 0; i < newVg1.replica; ++i) { - mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId); + if (mndAddDisableVnodeWriteAction(pMnode, pTrans, pDb, &newVg1, newVg1.vnodeGid[i].dnodeId) != 0) goto _OVER; } + if (mndAddAlterVnodeConfirmAction(pMnode, pTrans, pDb, &newVg1) != 0) goto _OVER; SVgObj newVg2 = {0}; memcpy(&newVg2, &newVg1, sizeof(SVgObj)); @@ -1813,15 +2056,25 @@ static int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj memcpy(&newVg2.vnodeGid[0], &newVg2.vnodeGid[1], sizeof(SVnodeGid)); memset(&newVg2.vnodeGid[1], 0, sizeof(SVnodeGid)); - mInfo("vgId:%d, vgroup info after adjust hash, replica:%d hashBegin:%u hashEnd:%u vnode:0 dnode:%d", newVg1.vgId, - newVg1.replica, newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId); - mInfo("vgId:%d, vgroup info after adjust hash, replica:%d hashBegin:%u hashEnd:%u vnode:0 dnode:%d", newVg2.vgId, - newVg2.replica, newVg2.hashBegin, newVg2.hashEnd, newVg2.vnodeGid[0].dnodeId); + mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg1.vgId, newVg1.replica, + newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId); + for (int32_t i = 0; i < newVg1.replica; ++i) { + mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId); + } + mInfo("vgId:%d, vgroup info after split, replica:%d hashrange:[%u, %u] vnode:0 dnode:%d", newVg2.vgId, newVg2.replica, + newVg2.hashBegin, newVg2.hashEnd, newVg2.vnodeGid[0].dnodeId); + for (int32_t i = 0; i < newVg1.replica; ++i) { + mInfo("vgId:%d, vnode:%d dnode:%d", newVg2.vgId, i, newVg2.vnodeGid[i].dnodeId); + } - if (mndAddAlterVnodeHashRangeAction(pMnode, pTrans, pDb, &newVg1) != 0) goto _OVER; - if (mndAddAlterVnodeHashRangeAction(pMnode, pTrans, pDb, &newVg2) != 0) goto _OVER; + int32_t maxVgId = sdbGetMaxId(pMnode->pSdb, SDB_VGROUP); + if (mndAddAlterVnodeHashRangeAction(pMnode, pTrans, &newVg1, maxVgId) != 0) goto _OVER; + newVg1.vgId = maxVgId; + + maxVgId++; + if (mndAddAlterVnodeHashRangeAction(pMnode, pTrans, &newVg2, maxVgId) != 0) goto _OVER; + newVg2.vgId = maxVgId; -#if 0 // adjust vgroup replica if (pDb->cfg.replications != newVg1.replica) { if (mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg1, pArray) != 0) goto _OVER; @@ -1829,38 +2082,38 @@ static int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj if (pDb->cfg.replications != newVg2.replica) { if (mndBuildAlterVgroupAction(pMnode, pTrans, pDb, pDb, &newVg2, pArray) != 0) goto _OVER; } -#endif - { - SSdbRaw *pRaw = mndVgroupActionEncode(&newVg1); - if (pRaw == NULL) return -1; - if (mndTransAppendCommitlog(pTrans, pRaw) != 0) { - sdbFreeRaw(pRaw); - return -1; - } - (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); - } + pRaw = mndVgroupActionEncode(&newVg1); + if (pRaw == NULL) goto _OVER; + if (mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER; + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); + pRaw = NULL; - { - SSdbRaw *pRaw = mndVgroupActionEncode(&newVg2); - if (pRaw == NULL) return -1; - if (mndTransAppendCommitlog(pTrans, pRaw) != 0) { - sdbFreeRaw(pRaw); - return -1; - } - (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); - } + pRaw = mndVgroupActionEncode(&newVg2); + if (pRaw == NULL) goto _OVER; + if (mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER; + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); + pRaw = NULL; - mInfo("vgId:%d, vgroup info after adjust hash, replica:%d hashBegin:%u hashEnd:%u vnode:0 dnode:%d", newVg1.vgId, - newVg1.replica, newVg1.hashBegin, newVg1.hashEnd, newVg1.vnodeGid[0].dnodeId); - for (int32_t i = 0; i < newVg1.replica; ++i) { - mInfo("vgId:%d, vnode:%d dnode:%d", newVg1.vgId, i, newVg1.vnodeGid[i].dnodeId); - } - mInfo("vgId:%d, vgroup info after adjust hash, replica:%d hashBegin:%u hashEnd:%u vnode:0 dnode:%d", newVg2.vgId, - newVg2.replica, newVg2.hashBegin, newVg2.hashEnd, newVg2.vnodeGid[0].dnodeId); - for (int32_t i = 0; i < newVg1.replica; ++i) { - mInfo("vgId:%d, vnode:%d dnode:%d", newVg2.vgId, i, newVg2.vnodeGid[i].dnodeId); - } + pRaw = mndVgroupActionEncode(pVgroup); + if (pRaw == NULL) goto _OVER; + if (mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER; + (void)sdbSetRawStatus(pRaw, SDB_STATUS_DROPPED); + pRaw = NULL; + + memcpy(&dbObj, pDb, sizeof(SDbObj)); + if (dbObj.cfg.pRetensions != NULL) { + dbObj.cfg.pRetensions = taosArrayDup(pDb->cfg.pRetensions, NULL); + if (dbObj.cfg.pRetensions == NULL) goto _OVER; + } + dbObj.vgVersion++; + dbObj.updateTime = taosGetTimestampMs(); + dbObj.cfg.numOfVgroups++; + pRaw = mndDbActionEncode(&dbObj); + if (pRaw == NULL) goto _OVER; + if (mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER; + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); + pRaw = NULL; if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; code = 0; @@ -1868,22 +2121,29 @@ static int32_t mndSplitVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SVgObj _OVER: taosArrayDestroy(pArray); mndTransDrop(pTrans); + sdbFreeRaw(pRaw); + taosArrayDestroy(dbObj.cfg.pRetensions); return code; } static int32_t mndProcessSplitVgroupMsg(SRpcMsg *pReq) { SMnode *pMnode = pReq->info.node; int32_t code = -1; - int32_t vgId = 2; SVgObj *pVgroup = NULL; SDbObj *pDb = NULL; - mInfo("vgId:%d, start to split", vgId); + SSplitVgroupReq req = {0}; + if (tDeserializeSSplitVgroupReq(pReq->pCont, pReq->contLen, &req) != 0) { + terrno = TSDB_CODE_INVALID_MSG; + goto _OVER; + } + + mInfo("vgId:%d, start to split", req.vgId); if (mndCheckOperPrivilege(pMnode, pReq->info.conn.user, MND_OPER_SPLIT_VGROUP) != 0) { goto _OVER; } - pVgroup = mndAcquireVgroup(pMnode, vgId); + pVgroup = mndAcquireVgroup(pMnode, req.vgId); if (pVgroup == NULL) goto _OVER; pDb = mndAcquireDb(pMnode, pVgroup->dbName); @@ -2083,3 +2343,61 @@ _OVER: } bool mndVgroupInDb(SVgObj *pVgroup, int64_t dbUid) { return !pVgroup->isTsma && pVgroup->dbUid == dbUid; } + +static void *mndBuildCompactVnodeReq(SMnode *pMnode, SDbObj *pDb, SVgObj *pVgroup, int32_t *pContLen, int64_t compactTs, + STimeWindow tw) { + SCompactVnodeReq compactReq = {0}; + compactReq.dbUid = pDb->uid; + compactReq.compactStartTime = compactTs; + compactReq.tw = tw; + tstrncpy(compactReq.db, pDb->name, TSDB_DB_FNAME_LEN); + + mInfo("vgId:%d, build compact vnode config req", pVgroup->vgId); + int32_t contLen = tSerializeSCompactVnodeReq(NULL, 0, &compactReq); + if (contLen < 0) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + contLen += sizeof(SMsgHead); + + void *pReq = taosMemoryMalloc(contLen); + if (pReq == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + SMsgHead *pHead = pReq; + pHead->contLen = htonl(contLen); + pHead->vgId = htonl(pVgroup->vgId); + + tSerializeSCompactVnodeReq((char *)pReq + sizeof(SMsgHead), contLen, &compactReq); + *pContLen = contLen; + return pReq; +} + +static int32_t mndAddCompactVnodeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs, + STimeWindow tw) { + STransAction action = {0}; + action.epSet = mndGetVgroupEpset(pMnode, pVgroup); + + int32_t contLen = 0; + void *pReq = mndBuildCompactVnodeReq(pMnode, pDb, pVgroup, &contLen, compactTs, tw); + if (pReq == NULL) return -1; + + action.pCont = pReq; + action.contLen = contLen; + action.msgType = TDMT_VND_COMPACT; + + if (mndTransAppendRedoAction(pTrans, &action) != 0) { + taosMemoryFree(pReq); + return -1; + } + + return 0; +} + +int32_t mndBuildCompactVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SVgObj *pVgroup, int64_t compactTs, + STimeWindow tw) { + if (mndAddCompactVnodeAction(pMnode, pTrans, pDb, pVgroup, compactTs, tw) != 0) return -1; + return 0; +} diff --git a/source/dnode/mnode/impl/test/profile/profile.cpp b/source/dnode/mnode/impl/test/profile/profile.cpp index 2ae113e0514bdec8c5c7c038ee2cbb9497bf2dec..6ab6d364cb6f326e37521815b7b5cf0b8fdc82ef 100644 --- a/source/dnode/mnode/impl/test/profile/profile.cpp +++ b/source/dnode/mnode/impl/test/profile/profile.cpp @@ -32,13 +32,14 @@ TEST_F(MndTestProfile, 01_ConnectMsg) { connectReq.pid = 1234; char passwd[] = "taosdata"; - char secretEncrypt[TSDB_PASSWORD_LEN] = {0}; + char secretEncrypt[TSDB_PASSWORD_LEN + 1] = {0}; taosEncryptPass_c((uint8_t*)passwd, strlen(passwd), secretEncrypt); strcpy(connectReq.app, "mnode_test_profile"); strcpy(connectReq.db, ""); strcpy(connectReq.user, "root"); strcpy(connectReq.passwd, secretEncrypt); + strcpy(connectReq.sVer, version); int32_t contLen = tSerializeSConnectReq(NULL, 0, &connectReq); void* pReq = rpcMallocCont(contLen); @@ -66,7 +67,7 @@ TEST_F(MndTestProfile, 01_ConnectMsg) { TEST_F(MndTestProfile, 02_ConnectMsg_InvalidDB) { char passwd[] = "taosdata"; - char secretEncrypt[TSDB_PASSWORD_LEN] = {0}; + char secretEncrypt[TSDB_PASSWORD_LEN + 1] = {0}; taosEncryptPass_c((uint8_t*)passwd, strlen(passwd), secretEncrypt); SConnectReq connectReq = {0}; @@ -75,6 +76,7 @@ TEST_F(MndTestProfile, 02_ConnectMsg_InvalidDB) { strcpy(connectReq.db, "invalid_db"); strcpy(connectReq.user, "root"); strcpy(connectReq.passwd, secretEncrypt); + strcpy(connectReq.sVer, version); int32_t contLen = tSerializeSConnectReq(NULL, 0, &connectReq); void* pReq = rpcMallocCont(contLen); diff --git a/source/dnode/mnode/impl/test/show/show.cpp b/source/dnode/mnode/impl/test/show/show.cpp index 0ccefa7ca2c265afe299a55b218d46be291c463e..2e67ffa946d68edb8e7f73ef2082ea7a3c8fc734 100644 --- a/source/dnode/mnode/impl/test/show/show.cpp +++ b/source/dnode/mnode/impl/test/show/show.cpp @@ -55,7 +55,7 @@ TEST_F(MndTestShow, 02_ShowMsg_InvalidMsgStart) { TEST_F(MndTestShow, 03_ShowMsg_Conn) { char passwd[] = "taosdata"; - char secretEncrypt[TSDB_PASSWORD_LEN] = {0}; + char secretEncrypt[TSDB_PASSWORD_LEN + 1] = {0}; taosEncryptPass_c((uint8_t*)passwd, strlen(passwd), secretEncrypt); SConnectReq connectReq = {0}; @@ -64,6 +64,7 @@ TEST_F(MndTestShow, 03_ShowMsg_Conn) { strcpy(connectReq.db, ""); strcpy(connectReq.user, "root"); strcpy(connectReq.passwd, secretEncrypt); + strcpy(connectReq.sVer, version); int32_t contLen = tSerializeSConnectReq(NULL, 0, &connectReq); void* pReq = rpcMallocCont(contLen); diff --git a/source/dnode/mnode/impl/test/trans/trans2.cpp b/source/dnode/mnode/impl/test/trans/trans2.cpp index 89c2b6931a321adf551516a685286149a7b003b9..2d03631a37725dfd22e93a59dcb078d18fd952ee 100644 --- a/source/dnode/mnode/impl/test/trans/trans2.cpp +++ b/source/dnode/mnode/impl/test/trans/trans2.cpp @@ -124,7 +124,7 @@ class MndTestTrans2 : public ::testing::Test { mndTransAppendUndolog(pTrans, pUndoRaw); sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED); - char *param = strdup("====> test log <====="); + char *param = taosStrdup("====> test log <====="); mndTransSetCb(pTrans, TRANS_START_FUNC_TEST, TRANS_STOP_FUNC_TEST, param, strlen(param) + 1); if (pDb != NULL) { @@ -157,7 +157,7 @@ class MndTestTrans2 : public ::testing::Test { mndTransAppendUndolog(pTrans, pUndoRaw); sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED); - char *param = strdup("====> test action <====="); + char *param = taosStrdup("====> test action <====="); mndTransSetCb(pTrans, TRANS_START_FUNC_TEST, TRANS_STOP_FUNC_TEST, param, strlen(param) + 1); { @@ -229,7 +229,7 @@ class MndTestTrans2 : public ::testing::Test { mndTransAppendUndolog(pTrans, pUndoRaw); sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED); - char *param = strdup("====> test log <====="); + char *param = taosStrdup("====> test log <====="); mndTransSetCb(pTrans, TRANS_START_FUNC_TEST, TRANS_STOP_FUNC_TEST, param, strlen(param) + 1); int32_t code = mndTransPrepare(pMnode, pTrans); diff --git a/source/dnode/mnode/sdb/inc/sdb.h b/source/dnode/mnode/sdb/inc/sdb.h index 5a44e4279ff2456a9c0df4d134ecc6d4e49801dd..e9a9e425e3fd364a1702ca084edd8be4e0b4aeeb 100644 --- a/source/dnode/mnode/sdb/inc/sdb.h +++ b/source/dnode/mnode/sdb/inc/sdb.h @@ -37,8 +37,6 @@ extern "C" { #define mTrace(...) { if (mDebugFlag & DEBUG_TRACE) { taosPrintLog("MND ", DEBUG_TRACE, mDebugFlag, __VA_ARGS__); }} // clang-format on -#define SDB_WRITE_DELTA 20 - #define SDB_GET_VAL(pData, dataPos, val, pos, func, type) \ { \ if (func(pRaw, dataPos, val) != 0) { \ @@ -147,7 +145,8 @@ typedef enum { SDB_STB = 18, SDB_DB = 19, SDB_FUNC = 20, - SDB_MAX = 21 + SDB_IDX = 21, + SDB_MAX = 22 } ESdbType; typedef struct SSdbRaw { diff --git a/source/dnode/mnode/sdb/src/sdb.c b/source/dnode/mnode/sdb/src/sdb.c index 648ccff432dffe3b460a488940de3dcd953a8db8..9797dd8337b424fb0118e14222225f1847250b43 100644 --- a/source/dnode/mnode/sdb/src/sdb.c +++ b/source/dnode/mnode/sdb/src/sdb.c @@ -30,9 +30,9 @@ SSdb *sdbInit(SSdbOpt *pOption) { char path[PATH_MAX + 100] = {0}; snprintf(path, sizeof(path), "%s%sdata", pOption->path, TD_DIRSEP); - pSdb->currDir = strdup(path); + pSdb->currDir = taosStrdup(path); snprintf(path, sizeof(path), "%s%stmp", pOption->path, TD_DIRSEP); - pSdb->tmpDir = strdup(path); + pSdb->tmpDir = taosStrdup(path); if (pSdb->currDir == NULL || pSdb->tmpDir == NULL) { sdbCleanup(pSdb); terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -53,7 +53,6 @@ SSdb *sdbInit(SSdbOpt *pOption) { } pSdb->pWal = pOption->pWal; - pSdb->sync = pOption->sync; pSdb->applyIndex = -1; pSdb->applyTerm = -1; pSdb->applyConfig = -1; diff --git a/source/dnode/mnode/sdb/src/sdbFile.c b/source/dnode/mnode/sdb/src/sdbFile.c index c2d7a9757abf522d67b88e29a0990b2c95f87e68..2e182ec10bcb4833e837ec621d2079fe50b21f4c 100644 --- a/source/dnode/mnode/sdb/src/sdbFile.c +++ b/source/dnode/mnode/sdb/src/sdbFile.c @@ -472,10 +472,7 @@ int32_t sdbWriteFile(SSdb *pSdb, int32_t delta) { taosThreadMutexLock(&pSdb->filelock); if (pSdb->pWal != NULL) { - // code = walBeginSnapshot(pSdb->pWal, pSdb->applyIndex); - if (pSdb->sync == 0) { - code = 0; - } else { + if (pSdb->sync > 0) { code = syncBeginSnapshot(pSdb->sync, pSdb->applyIndex); } } @@ -484,11 +481,7 @@ int32_t sdbWriteFile(SSdb *pSdb, int32_t delta) { } if (code == 0) { if (pSdb->pWal != NULL) { - // code = walEndSnapshot(pSdb->pWal); - - if (pSdb->sync == 0) { - code = 0; - } else { + if (pSdb->sync > 0) { code = syncEndSnapshot(pSdb->sync); } } @@ -521,7 +514,7 @@ static SSdbIter *sdbCreateIter(SSdb *pSdb) { char name[PATH_MAX + 100] = {0}; snprintf(name, sizeof(name), "%s%ssdb.data.%" PRIu64, pSdb->tmpDir, TD_DIRSEP, (uint64_t)pIter); - pIter->name = strdup(name); + pIter->name = taosStrdup(name); if (pIter->name == NULL) { taosMemoryFree(pIter); terrno = TSDB_CODE_OUT_OF_MEMORY; diff --git a/source/dnode/mnode/sdb/src/sdbHash.c b/source/dnode/mnode/sdb/src/sdbHash.c index 505dee3d87053d2b406ba5679419f12bdc5d837b..f1cee6395b812c2bef8655530cd9f6ab211eedd3 100644 --- a/source/dnode/mnode/sdb/src/sdbHash.c +++ b/source/dnode/mnode/sdb/src/sdbHash.c @@ -60,6 +60,8 @@ const char *sdbTableName(ESdbType type) { return "db"; case SDB_FUNC: return "func"; + case SDB_IDX: + return "idx"; default: return "undefine"; } @@ -158,6 +160,7 @@ static int32_t sdbInsertRow(SSdb *pSdb, SHashObj *hash, SSdbRaw *pRaw, SSdbRow * if (insertFp != NULL) { code = (*insertFp)(pSdb, pRow->pObj); if (code != 0) { + if (terrno == 0) terrno = TSDB_CODE_MND_TRANS_UNKNOW_ERROR; code = terrno; taosHashRemove(hash, pRow->pObj, keySize); sdbFreeRow(pSdb, pRow, false); @@ -193,13 +196,13 @@ static int32_t sdbUpdateRow(SSdb *pSdb, SHashObj *hash, SSdbRaw *pRaw, SSdbRow * SSdbRow *pOldRow = *ppOldRow; pOldRow->status = pRaw->status; sdbPrintOper(pSdb, pOldRow, "update"); - sdbUnLock(pSdb, type); int32_t code = 0; SdbUpdateFp updateFp = pSdb->updateFps[type]; if (updateFp != NULL) { code = (*updateFp)(pSdb, pOldRow->pObj, pNewRow->pObj); } + sdbUnLock(pSdb, type); // sdbUnLock(pSdb, type); sdbFreeRow(pSdb, pNewRow, false); diff --git a/source/dnode/qnode/inc/qndInt.h b/source/dnode/qnode/inc/qndInt.h index e8ccb75040cbc54ab080e7887a877ce9ff67006b..86deda52ad242e371ab59542532234778e26864d 100644 --- a/source/dnode/qnode/inc/qndInt.h +++ b/source/dnode/qnode/inc/qndInt.h @@ -29,7 +29,7 @@ extern "C" { #endif -typedef struct SQWorker SQHandle; +typedef struct SQueueWorker SQHandle; typedef struct SQnode { int32_t qndId; diff --git a/source/dnode/snode/src/snode.c b/source/dnode/snode/src/snode.c index 1d2f4da26b8150c7d92344d091421afd151adcde..7352bbc0fec294e4e07e19c0130069039b00a176 100644 --- a/source/dnode/snode/src/snode.c +++ b/source/dnode/snode/src/snode.c @@ -32,6 +32,7 @@ void sndEnqueueStreamDispatch(SSnode *pSnode, SRpcMsg *pMsg) { tDecoderClear(&decoder); goto FAIL; } + tDecoderClear(&decoder); int32_t taskId = req.taskId; @@ -65,7 +66,7 @@ int32_t sndExpandTask(SSnode *pSnode, SStreamTask *pTask, int64_t ver) { ASSERT(taosArrayGetSize(pTask->childEpInfo) != 0); pTask->refCnt = 1; - pTask->schedStatus = TASK_SCHED_STATUS__INACTIVE; + pTask->status.schedStatus = TASK_SCHED_STATUS__INACTIVE; pTask->inputQueue = streamQueueOpen(); pTask->outputQueue = streamQueueOpen(); @@ -75,26 +76,22 @@ int32_t sndExpandTask(SSnode *pSnode, SStreamTask *pTask, int64_t ver) { pTask->inputStatus = TASK_INPUT_STATUS__NORMAL; pTask->outputStatus = TASK_OUTPUT_STATUS__NORMAL; - pTask->pMsgCb = &pSnode->msgCb; - - pTask->startVer = ver; + pTask->chkInfo.version = ver; + pTask->pMeta = pSnode->pMeta; pTask->pState = streamStateOpen(pSnode->path, pTask, false, -1, -1); if (pTask->pState == NULL) { return -1; } - SReadHandle mgHandle = { - .vnode = NULL, - .numOfVgroups = (int32_t)taosArrayGetSize(pTask->childEpInfo), - .pStateBackend = pTask->pState, - }; - pTask->exec.executor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &mgHandle); - ASSERT(pTask->exec.executor); + int32_t numOfChildEp = taosArrayGetSize(pTask->childEpInfo); + SReadHandle mgHandle = { .vnode = NULL, .numOfVgroups = numOfChildEp, .pStateBackend = pTask->pState }; - streamSetupTrigger(pTask); + pTask->exec.pExecutor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &mgHandle, 0); + ASSERT(pTask->exec.pExecutor); + streamSetupTrigger(pTask); return 0; } @@ -104,7 +101,7 @@ SSnode *sndOpen(const char *path, const SSnodeOpt *pOption) { terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } - pSnode->path = strdup(path); + pSnode->path = taosStrdup(path); if (pSnode->path == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; goto FAIL; @@ -142,9 +139,10 @@ int32_t sndProcessTaskDeployReq(SSnode *pSnode, char *msg, int32_t msgLen) { if (pTask == NULL) { return -1; } + SDecoder decoder; tDecoderInit(&decoder, (uint8_t *)msg, msgLen); - code = tDecodeSStreamTask(&decoder, pTask); + code = tDecodeStreamTask(&decoder, pTask); if (code < 0) { tDecoderClear(&decoder); taosMemoryFree(pTask); @@ -155,11 +153,15 @@ int32_t sndProcessTaskDeployReq(SSnode *pSnode, char *msg, int32_t msgLen) { ASSERT(pTask->taskLevel == TASK_LEVEL__AGG); // 2.save task - code = streamMetaAddTask(pSnode->pMeta, -1, pTask); + taosWLockLatch(&pSnode->pMeta->lock); + code = streamMetaAddDeployedTask(pSnode->pMeta, -1, pTask); if (code < 0) { + taosWUnLockLatch(&pSnode->pMeta->lock); return -1; } + taosWUnLockLatch(&pSnode->pMeta->lock); + // 3.go through recover steps to fill history if (pTask->fillHistory) { streamSetParamForRecover(pTask); diff --git a/source/dnode/vnode/CMakeLists.txt b/source/dnode/vnode/CMakeLists.txt index 1f7a059ffc30623ddbdc442a9cbeb770afb57fff..c713d1e247a8cd358fbe0c8a4a529f884e8810b6 100644 --- a/source/dnode/vnode/CMakeLists.txt +++ b/source/dnode/vnode/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources( "src/vnd/vnodeSvr.c" "src/vnd/vnodeSync.c" "src/vnd/vnodeSnapshot.c" + "src/vnd/vnodeRetention.c" # meta "src/meta/metaOpen.c" @@ -51,25 +52,37 @@ target_sources( "src/tsdb/tsdbCacheRead.c" "src/tsdb/tsdbRetention.c" "src/tsdb/tsdbDiskData.c" - "src/tsdb/tsdbCompact.c" "src/tsdb/tsdbMergeTree.c" + "src/tsdb/tsdbDataIter.c" # tq "src/tq/tq.c" - "src/tq/tqExec.c" + "src/tq/tqUtil.c" + "src/tq/tqScan.c" "src/tq/tqMeta.c" "src/tq/tqRead.c" "src/tq/tqOffset.c" "src/tq/tqPush.c" "src/tq/tqSink.c" "src/tq/tqCommit.c" + "src/tq/tqRestore.c" "src/tq/tqSnapshot.c" "src/tq/tqOffsetSnapshot.c" ) + +IF (TD_VNODE_PLUGINS) + target_sources( + vnode + PRIVATE + ${TD_ENTERPRISE_DIR}/src/plugins/vnode/src/tsdbCompact.c + ${TD_ENTERPRISE_DIR}/src/plugins/vnode/src/vnodeCompact.c + ) +ENDIF () + target_include_directories( vnode PUBLIC "inc" - PRIVATE "src/inc" + PUBLIC "src/inc" PUBLIC "${TD_SOURCE_DIR}/include/libs/scalar" ) target_link_libraries( diff --git a/source/dnode/vnode/inc/vnode.h b/source/dnode/vnode/inc/vnode.h index a9652fb2ff05767f439bfe3385633813ecdf73ed..cb83a561d24aed55c4fde3f824139d8d4dbd26e6 100644 --- a/source/dnode/vnode/inc/vnode.h +++ b/source/dnode/vnode/inc/vnode.h @@ -50,13 +50,16 @@ extern const SVnodeCfg vnodeCfgDefault; int32_t vnodeInit(int32_t nthreads); void vnodeCleanup(); int32_t vnodeCreate(const char *path, SVnodeCfg *pCfg, STfs *pTfs); -int32_t vnodeAlter(const char *path, SAlterVnodeReplicaReq *pReq, STfs *pTfs); +int32_t vnodeAlterReplica(const char *path, SAlterVnodeReplicaReq *pReq, STfs *pTfs); +int32_t vnodeAlterHashRange(const char *srcPath, const char *dstPath, SAlterVnodeHashRangeReq *pReq, STfs *pTfs); void vnodeDestroy(const char *path, STfs *pTfs); SVnode *vnodeOpen(const char *path, STfs *pTfs, SMsgCb msgCb); void vnodePreClose(SVnode *pVnode); void vnodePostClose(SVnode *pVnode); void vnodeSyncCheckTimeout(SVnode *pVnode); void vnodeClose(SVnode *pVnode); +int32_t vnodeSyncCommit(SVnode *pVnode); +int32_t vnodeBegin(SVnode *pVnode); int32_t vnodeStart(SVnode *pVnode); void vnodeStop(SVnode *pVnode); @@ -89,7 +92,7 @@ int32_t vnodeProcessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg); int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo); void vnodeProposeWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs); void vnodeApplyWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs); -void vnodeProposeCommitOnNeed(SVnode *pVnode); +void vnodeProposeCommitOnNeed(SVnode *pVnode, bool atExit); // meta typedef struct SMeta SMeta; // todo: remove @@ -120,6 +123,11 @@ int32_t metaUidFilterCachePut(SMeta *pMeta, uint64_t suid, const void *pKey, in int32_t payloadLen, double selectivityRatio); int32_t metaUidCacheClear(SMeta *pMeta, uint64_t suid); tb_uid_t metaGetTableEntryUidByName(SMeta *pMeta, const char *name); +int32_t metaTbGroupCacheClear(SMeta* pMeta, uint64_t suid); +int32_t metaGetCachedTbGroup(SMeta* pMeta, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray** pList); +int32_t metaPutTbGroupToCache(SMeta* pMeta, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload, + int32_t payloadLen); + int64_t metaGetTbNum(SMeta *pMeta); int64_t metaGetNtbNum(SMeta *pMeta); typedef struct { @@ -134,6 +142,7 @@ typedef struct SMetaFltParam { int16_t type; void *val; bool reverse; + bool equal; int (*filterFunc)(void *a, void *b, int16_t type); } SMetaFltParam; @@ -152,13 +161,12 @@ typedef struct SMTbCursor SMTbCursor; SMTbCursor *metaOpenTbCursor(SMeta *pMeta); void metaCloseTbCursor(SMTbCursor *pTbCur); -int32_t metaTbCursorNext(SMTbCursor *pTbCur); -int32_t metaTbCursorPrev(SMTbCursor *pTbCur); +int32_t metaTbCursorNext(SMTbCursor *pTbCur, ETableType jumpTableType); +int32_t metaTbCursorPrev(SMTbCursor *pTbCur, ETableType jumpTableType); #endif // tsdb -// typedef struct STsdb STsdb; typedef struct STsdbReader STsdbReader; #define TSDB_DEFAULT_STT_FILE 8 @@ -172,30 +180,34 @@ typedef struct STsdbReader STsdbReader; #define CACHESCAN_RETRIEVE_LAST_ROW 0x4 #define CACHESCAN_RETRIEVE_LAST 0x8 -int32_t tsdbSetTableList(STsdbReader *pReader, const void *pTableList, int32_t num); -int32_t tsdbReaderOpen(SVnode *pVnode, SQueryTableDataCond *pCond, void *pTableList, int32_t numOfTables, - SSDataBlock *pResBlock, STsdbReader **ppReader, const char *idstr); - +int32_t tsdbReaderOpen(SVnode *pVnode, SQueryTableDataCond *pCond, void *pTableList, int32_t numOfTables, + SSDataBlock *pResBlock, STsdbReader **ppReader, const char *idstr, bool countOnly, SHashObj** pIgnoreTables); void tsdbReaderClose(STsdbReader *pReader); -bool tsdbNextDataBlock(STsdbReader *pReader); +int32_t tsdbNextDataBlock(STsdbReader *pReader, bool *hasNext); int32_t tsdbRetrieveDatablockSMA(STsdbReader *pReader, SSDataBlock *pDataBlock, bool *allHave); +void tsdbReleaseDataBlock(STsdbReader *pReader); SSDataBlock *tsdbRetrieveDataBlock(STsdbReader *pTsdbReadHandle, SArray *pColumnIdList); int32_t tsdbReaderReset(STsdbReader *pReader, SQueryTableDataCond *pCond); int32_t tsdbGetFileBlocksDistInfo(STsdbReader *pReader, STableBlockDistInfo *pTableBlockInfo); int64_t tsdbGetNumOfRowsInMemTable(STsdbReader *pHandle); void *tsdbGetIdx(SMeta *pMeta); void *tsdbGetIvtIdx(SMeta *pMeta); -uint64_t getReaderMaxVersion(STsdbReader *pReader); +uint64_t tsdbGetReaderMaxVersion(STsdbReader *pReader); +int32_t tsdbSetTableList(STsdbReader *pReader, const void *pTableList, int32_t num); +void tsdbReaderSetId(STsdbReader *pReader, const char *idstr); +void tsdbReaderSetCloseFlag(STsdbReader *pReader); +int32_t tsdbReuseCacherowsReader(void* pReader, void* pTableIdList, int32_t numOfTables); int32_t tsdbCacherowsReaderOpen(void *pVnode, int32_t type, void *pTableIdList, int32_t numOfTables, int32_t numOfCols, uint64_t suid, void **pReader, const char *idstr); int32_t tsdbRetrieveCacheRows(void *pReader, SSDataBlock *pResBlock, const int32_t *slotIds, SArray *pTableUids); void *tsdbCacherowsReaderClose(void *pReader); int32_t tsdbGetTableSchema(SVnode *pVnode, int64_t uid, STSchema **pSchema, int64_t *suid); -void tsdbCacheSetCapacity(SVnode *pVnode, size_t capacity); -size_t tsdbCacheGetCapacity(SVnode *pVnode); -size_t tsdbCacheGetUsage(SVnode *pVnode); +void tsdbCacheSetCapacity(SVnode *pVnode, size_t capacity); +size_t tsdbCacheGetCapacity(SVnode *pVnode); +size_t tsdbCacheGetUsage(SVnode *pVnode); +int32_t tsdbCacheGetElems(SVnode *pVnode); // tq typedef struct SMetaTableInfo { @@ -221,44 +233,42 @@ typedef struct SSnapContext { SArray *idList; int32_t index; bool withMeta; - bool queryMetaOrData; // true-get meta, false-get data + bool queryMeta; // true-get meta, false-get data } SSnapContext; typedef struct STqReader { - int64_t ver; - const SSubmitReq *pMsg; - SSubmitBlk *pBlock; - SSubmitMsgIter msgIter; - SSubmitBlkIter blkIter; - - SWalReader *pWalReader; - - SMeta *pVnodeMeta; - SHashObj *tbIdHash; - SArray *pColIdList; // SArray - + SPackedData msg; + SSubmitReq2 submit; + int32_t nextBlk; + int64_t lastBlkUid; + SWalReader *pWalReader; + SMeta *pVnodeMeta; + SHashObj *tbIdHash; + SArray *pColIdList; // SArray int32_t cachedSchemaVer; int64_t cachedSchemaSuid; + int64_t cachedSchemaUid; SSchemaWrapper *pSchemaWrapper; - STSchema *pSchema; + SSDataBlock *pResBlock; } STqReader; -STqReader *tqOpenReader(SVnode *pVnode); +STqReader *tqReaderOpen(SVnode *pVnode); void tqCloseReader(STqReader *); void tqReaderSetColIdList(STqReader *pReader, SArray *pColIdList); int32_t tqReaderSetTbUidList(STqReader *pReader, const SArray *tbUidList); -int32_t tqReaderAddTbUidList(STqReader *pReader, const SArray *tbUidList); +int32_t tqReaderAddTbUidList(STqReader *pReader, const SArray *pTableUidList); int32_t tqReaderRemoveTbUidList(STqReader *pReader, const SArray *tbUidList); -int32_t tqSeekVer(STqReader *pReader, int64_t ver); -int32_t tqNextBlock(STqReader *pReader, SFetchRet *ret); +int32_t tqSeekVer(STqReader *pReader, int64_t ver, const char *id); +int32_t tqNextBlockInWal(STqReader* pReader); +bool tqNextBlockImpl(STqReader *pReader); -int32_t tqReaderSetDataMsg(STqReader *pReader, const SSubmitReq *pMsg, int64_t ver); -bool tqNextDataBlock(STqReader *pReader); +int32_t extractMsgFromWal(SWalReader* pReader, void** pItem, const char* id); +int32_t tqReaderSetSubmitMsg(STqReader *pReader, void *msgStr, int32_t msgLen, int64_t ver); bool tqNextDataBlockFilterOut(STqReader *pReader, SHashObj *filterOutUids); -int32_t tqRetrieveDataBlock(SSDataBlock *pBlock, STqReader *pReader); -int32_t tqRetrieveTaosxBlock(STqReader *pReader, SArray *blocks, SArray *schemas); +int32_t tqRetrieveDataBlock(STqReader *pReader, SSubmitTbData **pSubmitTbDataRet); +int32_t tqRetrieveTaosxBlock(STqReader *pReader, SArray *blocks, SArray *schemas, SSubmitTbData **pSubmitTbDataRet); int32_t vnodeEnqueueStreamMsg(SVnode *pVnode, SRpcMsg *pMsg); diff --git a/source/dnode/vnode/src/inc/sma.h b/source/dnode/vnode/src/inc/sma.h index 50e3c3a9c16e54a70d2b4f07a4640d87013a7776..c3e8d7ef1dacd2d0c7aaf143f09d3a9de88eec2e 100644 --- a/source/dnode/vnode/src/inc/sma.h +++ b/source/dnode/vnode/src/inc/sma.h @@ -44,7 +44,6 @@ typedef struct SRSmaInfoItem SRSmaInfoItem; typedef struct SRSmaFS SRSmaFS; typedef struct SQTaskFile SQTaskFile; typedef struct SQTaskFReader SQTaskFReader; -typedef struct SQTaskFWriter SQTaskFWriter; struct SSmaEnv { SRWLatch lock; @@ -85,22 +84,20 @@ struct STSmaStat { struct SQTaskFile { volatile int32_t nRef; - int32_t padding; + int8_t level; + int64_t suid; int64_t version; int64_t size; + int64_t mtime; }; struct SQTaskFReader { SSma *pSma; + int8_t level; + int64_t suid; int64_t version; TdFilePtr pReadH; }; -struct SQTaskFWriter { - SSma *pSma; - int64_t version; - TdFilePtr pWriteH; - char *fname; -}; struct SRSmaFS { SArray *aQTaskInf; // array of SQTaskFile @@ -212,87 +209,44 @@ static FORCE_INLINE void tdUnRefSmaStat(SSma *pSma, SSmaStat *pStat) { smaDebug("vgId:%d, unref sma stat:%p, val:%d", SMA_VID(pSma), pStat, ref); } +int32_t smaPreClose(SSma *pSma); + // rsma void *tdFreeRSmaInfo(SSma *pSma, SRSmaInfo *pInfo, bool isDeepFree); -int32_t tdRSmaFSOpen(SSma *pSma, int64_t version); +int32_t tdRSmaFSOpen(SSma *pSma, int64_t version, int8_t rollback); void tdRSmaFSClose(SRSmaFS *fs); -int32_t tdRSmaFSRef(SSma *pSma, SRSmaStat *pStat, int64_t version); -void tdRSmaFSUnRef(SSma *pSma, SRSmaStat *pStat, int64_t version); -int64_t tdRSmaFSMaxVer(SSma *pSma, SRSmaStat *pStat); -int32_t tdRSmaFSUpsertQTaskFile(SRSmaFS *pFS, SQTaskFile *qTaskFile); -int32_t tdRSmaRestore(SSma *pSma, int8_t type, int64_t committedVer); +int32_t tdRSmaFSPrepareCommit(SSma *pSma, SRSmaFS *pFSNew); +int32_t tdRSmaFSCommit(SSma *pSma); +int32_t tdRSmaFSFinishCommit(SSma *pSma); +int32_t tdRSmaFSCopy(SSma *pSma, SRSmaFS *pFS); +int32_t tdRSmaFSTakeSnapshot(SSma *pSma, SRSmaFS *pFS); +int32_t tdRSmaFSRef(SSma *pSma, SRSmaFS *pFS); +void tdRSmaFSUnRef(SSma *pSma, SRSmaFS *pFS); +int32_t tdRSmaFSUpsertQTaskFile(SSma *pSma, SRSmaFS *pFS, SQTaskFile *qTaskFile, int32_t nSize); +int32_t tdRSmaFSRollback(SSma *pSma); +int32_t tdRSmaRestore(SSma *pSma, int8_t type, int64_t committedVer, int8_t rollback); int32_t tdRSmaProcessCreateImpl(SSma *pSma, SRSmaParam *param, int64_t suid, const char *tbName); int32_t tdRSmaProcessExecImpl(SSma *pSma, ERsmaExecType type); int32_t tdRSmaPersistExecImpl(SRSmaStat *pRSmaStat, SHashObj *pInfoHash); -int32_t tdRSmaProcessRestoreImpl(SSma *pSma, int8_t type, int64_t qtaskFileVer); -void tdRSmaQTaskInfoGetFileName(int32_t vgId, int64_t version, char *outputName); -void tdRSmaQTaskInfoGetFullName(int32_t vgId, int64_t version, const char *path, char *outputName); +int32_t tdRSmaProcessRestoreImpl(SSma *pSma, int8_t type, int64_t qtaskFileVer, int8_t rollback); +void tdRSmaQTaskInfoGetFileName(int32_t vgId, int64_t suid, int8_t level, int64_t version, char *outputName); +void tdRSmaQTaskInfoGetFullName(int32_t vgId, int64_t suid, int8_t level, int64_t version, const char *path, + char *outputName); void tdRSmaQTaskInfoGetFullPath(int32_t vgId, int8_t level, const char *path, char *outputName); void tdRSmaQTaskInfoGetFullPathEx(int32_t vgId, tb_uid_t suid, int8_t level, const char *path, char *outputName); static FORCE_INLINE void tdRefRSmaInfo(SSma *pSma, SRSmaInfo *pRSmaInfo) { int32_t ref = T_REF_INC(pRSmaInfo); - smaDebug("vgId:%d, ref rsma info:%p, val:%d", SMA_VID(pSma), pRSmaInfo, ref); + smaTrace("vgId:%d, ref rsma info:%p, val:%d", SMA_VID(pSma), pRSmaInfo, ref); } static FORCE_INLINE void tdUnRefRSmaInfo(SSma *pSma, SRSmaInfo *pRSmaInfo) { int32_t ref = T_REF_DEC(pRSmaInfo); - smaDebug("vgId:%d, unref rsma info:%p, val:%d", SMA_VID(pSma), pRSmaInfo, ref); + smaTrace("vgId:%d, unref rsma info:%p, val:%d", SMA_VID(pSma), pRSmaInfo, ref); } -// smaFileUtil ================ - -#define TD_FILE_HEAD_SIZE 512 - -typedef struct STFInfo STFInfo; -typedef struct STFile STFile; - -struct STFInfo { - // common fields - uint32_t magic; - uint32_t ftype; - uint32_t fver; - int64_t fsize; -}; - -enum { - TD_FTYPE_RSMA_QTASKINFO = 0, -}; - -#if 0 -struct STFile { - uint8_t state; - STFInfo info; - char *fname; - TdFilePtr pFile; -}; - -#define TD_TFILE_PFILE(tf) ((tf)->pFile) -#define TD_TFILE_OPENED(tf) (TD_TFILE_PFILE(tf) != NULL) -#define TD_TFILE_FULL_NAME(tf) ((tf)->fname) -#define TD_TFILE_OPENED(tf) (TD_TFILE_PFILE(tf) != NULL) -#define TD_TFILE_CLOSED(tf) (!TD_TFILE_OPENED(tf)) -#define TD_TFILE_SET_CLOSED(f) (TD_TFILE_PFILE(f) = NULL) -#define TD_TFILE_SET_STATE(tf, s) ((tf)->state = (s)) - -int32_t tdInitTFile(STFile *pTFile, const char *dname, const char *fname); -int32_t tdCreateTFile(STFile *pTFile, bool updateHeader, int8_t fType); -int32_t tdOpenTFile(STFile *pTFile, int flags); -int64_t tdReadTFile(STFile *pTFile, void *buf, int64_t nbyte); -int64_t tdSeekTFile(STFile *pTFile, int64_t offset, int whence); -int64_t tdWriteTFile(STFile *pTFile, void *buf, int64_t nbyte); -int64_t tdAppendTFile(STFile *pTFile, void *buf, int64_t nbyte, int64_t *offset); -int64_t tdGetTFileSize(STFile *pTFile, int64_t *size); -int32_t tdRemoveTFile(STFile *pTFile); -int32_t tdLoadTFileHeader(STFile *pTFile, STFInfo *pInfo); -int32_t tdUpdateTFileHeader(STFile *pTFile); -void tdUpdateTFileMagic(STFile *pTFile, void *pCksm); -void tdCloseTFile(STFile *pTFile); -void tdDestroyTFile(STFile *pTFile); -#endif - -void tdGetVndFileName(int32_t vgId, const char *pdname, const char *dname, const char *fname, int64_t version, - char *outputName); -void tdGetVndDirName(int32_t vgId, const char *pdname, const char *dname, bool endWithSep, char *outputName); +void tdRSmaGetFileName(int32_t vgId, const char *pdname, const char *dname, const char *fname, int64_t suid, + int8_t level, int64_t version, char *outputName); +void tdRSmaGetDirName(int32_t vgId, const char *pdname, const char *dname, bool endWithSep, char *outputName); #ifdef __cplusplus } diff --git a/source/dnode/vnode/src/inc/tq.h b/source/dnode/vnode/src/inc/tq.h index 828341ddd8666bbb55c2cedce1b34c50f6b3362a..ef36b8429a2f8b599835234d9ddd700f3520506c 100644 --- a/source/dnode/vnode/src/inc/tq.h +++ b/source/dnode/vnode/src/inc/tq.h @@ -46,28 +46,28 @@ typedef struct STqOffsetStore STqOffsetStore; // tqPush -typedef struct { - // msg info - int64_t consumerId; - int64_t reqOffset; - int64_t processedVer; - int32_t epoch; - // rpc info - int64_t reqId; - SRpcHandleInfo rpcInfo; - tmr_h timerId; - int8_t tmrStopped; - // exec - int8_t inputStatus; - int8_t execStatus; - SStreamQueue inputQ; - SRWLatch lock; -} STqPushHandle; +//typedef struct { +// // msg info +// int64_t consumerId; +// int64_t reqOffset; +// int64_t processedVer; +// int32_t epoch; +// // rpc info +// int64_t reqId; +// SRpcHandleInfo rpcInfo; +// tmr_h timerId; +// int8_t tmrStopped; +// // exec +// int8_t inputStatus; +// int8_t execStatus; +// SStreamQueue inputQ; +// SRWLatch lock; +//} STqPushHandle; // tqExec typedef struct { - char* qmsg; + char* qmsg; // SubPlanToString } STqExecCol; typedef struct { @@ -79,63 +79,56 @@ typedef struct { } STqExecDb; typedef struct { - int8_t subType; - - STqReader* pExecReader; - qTaskInfo_t task; + int8_t subType; + STqReader* pTqReader; + qTaskInfo_t task; union { STqExecCol execCol; STqExecTb execTb; STqExecDb execDb; }; - int32_t numOfCols; // number of out pout column, temporarily used + int32_t numOfCols; // number of out pout column, temporarily used } STqExecHandle; -typedef struct { - // info - char subKey[TSDB_SUBSCRIBE_KEY_LEN]; - int64_t consumerId; - int32_t epoch; - int8_t fetchMeta; - - int64_t snapshotVer; - - SWalReader* pWalReader; - - SWalRef* pRef; - - // push - STqPushHandle pushHandle; - - // exec - STqExecHandle execHandle; +typedef enum tq_handle_status{ + TMQ_HANDLE_STATUS_IDLE = 0, + TMQ_HANDLE_STATUS_EXEC = 1, +}tq_handle_status; +typedef struct { + char subKey[TSDB_SUBSCRIBE_KEY_LEN]; + int64_t consumerId; + int32_t epoch; + int8_t fetchMeta; + int64_t snapshotVer; + SWalReader* pWalReader; + SWalRef* pRef; +// STqPushHandle pushHandle; // push + STqExecHandle execHandle; // exec + SRpcMsg* msg; + int32_t noDataPollCnt; + tq_handle_status status; } STqHandle; -typedef struct { - SMqDataRsp dataRsp; - char subKey[TSDB_SUBSCRIBE_KEY_LEN]; - SRpcHandleInfo pInfo; -} STqPushEntry; +//typedef struct { +// SMqDataRsp* pDataRsp; +// char subKey[TSDB_SUBSCRIBE_KEY_LEN]; +// SRpcHandleInfo info; +//} STqPushEntry; struct STQ { - SVnode* pVnode; - char* path; - int64_t walLogLastVer; - - SRWLatch pushLock; - - SHashObj* pPushMgr; // consumerId -> STqPushEntry - SHashObj* pHandle; // subKey -> STqHandle - SHashObj* pCheckInfo; // topic -> SAlterCheckInfo - + SVnode* pVnode; + char* path; + int64_t walLogLastVer; + SRWLatch lock; + SHashObj* pPushMgr; // subKey -> STqHandle + SHashObj* pHandle; // subKey -> STqHandle + SHashObj* pCheckInfo; // topic -> SAlterCheckInfo STqOffsetStore* pOffsetStore; - - TDB* pMetaDB; - TTB* pExecStore; - TTB* pCheckStore; - - SStreamMeta* pStreamMeta; + TDB* pMetaDB; + TTB* pExecStore; + TTB* pCheckStore; + SStreamMeta* pStreamMeta; }; typedef struct { @@ -143,6 +136,10 @@ typedef struct { tmr_h timer; } STqMgmt; +typedef struct { + int32_t size; +} STqOffsetHead; + static STqMgmt tqMgmt = {0}; int32_t tEncodeSTqHandle(SEncoder* pEncoder, const STqHandle* pHandle); @@ -151,13 +148,13 @@ int32_t tDecodeSTqHandle(SDecoder* pDecoder, STqHandle* pHandle); // tqRead int32_t tqScanTaosx(STQ* pTq, const STqHandle* pHandle, STaosxRsp* pRsp, SMqMetaRsp* pMetaRsp, STqOffsetVal* offset); int32_t tqScanData(STQ* pTq, const STqHandle* pHandle, SMqDataRsp* pRsp, STqOffsetVal* pOffset); -int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHead** pHeadWithCkSum); +int32_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHead** pHeadWithCkSum, uint64_t reqId); // tqExec -int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SSubmitReq* pReq, STaosxRsp* pRsp); +int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxRsp* pRsp, int32_t* totalRows); int32_t tqAddBlockDataToRsp(const SSDataBlock* pBlock, SMqDataRsp* pRsp, int32_t numOfCols, int8_t precision); -int32_t tqSendDataRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp); -int32_t tqPushDataRsp(STQ* pTq, STqPushEntry* pPushEntry); +int32_t tqSendDataRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp, int32_t type); +int32_t tqPushDataRsp(STQ* pTq, STqHandle* pHandle); // tqMeta int32_t tqMetaOpen(STQ* pTq); @@ -169,11 +166,7 @@ int32_t tqMetaSaveCheckInfo(STQ* pTq, const char* key, const void* value, int32_ int32_t tqMetaDeleteCheckInfo(STQ* pTq, const char* key); int32_t tqMetaRestoreCheckInfo(STQ* pTq); -typedef struct { - int32_t size; -} STqOffsetHead; - -STqOffsetStore* tqOffsetOpen(); +STqOffsetStore* tqOffsetOpen(STQ* pTq); void tqOffsetClose(STqOffsetStore*); STqOffset* tqOffsetRead(STqOffsetStore* pStore, const char* subscribeKey); int32_t tqOffsetWrite(STqOffsetStore* pStore, const STqOffset* pOffset); @@ -181,8 +174,9 @@ int32_t tqOffsetDelete(STqOffsetStore* pStore, const char* subscribeKey) int32_t tqOffsetCommitFile(STqOffsetStore* pStore); // tqSink -// void tqSinkToTableMerge(SStreamTask* pTask, void* vnode, int64_t ver, void* data); -void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* data); +int32_t tqBuildDeleteReq(SVnode* pVnode, const char* stbFullName, const SSDataBlock* pDataBlock, + SBatchDeleteReq* deleteReq); +void tqSinkToTablePipeline2(SStreamTask* pTask, void* vnode, int64_t ver, void* data); // tqOffset char* tqOffsetBuildFName(const char* path, int32_t fVer); @@ -190,6 +184,13 @@ int32_t tqOffsetRestoreFromFile(STqOffsetStore* pStore, const char* fname); // tqStream int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver); +int32_t tqStreamTasksScanWal(STQ* pTq); + +// tq util +int32_t extractDelDataBlock(const void* pData, int32_t len, int64_t ver, SStreamRefDataBlock** pRefBlock); +char* createStreamTaskIdStr(int64_t streamId, int32_t taskId); +int32_t tqAddInputBlockNLaunchTask(SStreamTask* pTask, SStreamQueueItem* pQueueItem); +int32_t tqExtractDataForMq(STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequest, SRpcMsg* pMsg); #ifdef __cplusplus } diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index 702cbea3334e4170f474a3da1435ec646481a57e..6102487400c5704848ab4f419de2022589b0ca8e 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -16,6 +16,7 @@ #ifndef _TD_VNODE_TSDB_H_ #define _TD_VNODE_TSDB_H_ +#include "tsimplehash.h" #include "vnodeInt.h" #ifdef __cplusplus @@ -69,6 +70,11 @@ typedef struct SDiskCol SDiskCol; typedef struct SDiskData SDiskData; typedef struct SDiskDataBuilder SDiskDataBuilder; typedef struct SBlkInfo SBlkInfo; +typedef struct STsdbDataIter2 STsdbDataIter2; +typedef struct STsdbFilterInfo STsdbFilterInfo; + +#define TSDBROW_ROW_FMT ((int8_t)0x0) +#define TSDBROW_COL_FMT ((int8_t)0x1) #define TSDB_FILE_DLMT ((uint32_t)0xF00AFA0F) #define TSDB_MAX_SUBBLOCKS 8 @@ -102,26 +108,29 @@ static FORCE_INLINE int64_t tsdbLogicToFileSize(int64_t lSize, int32_t szPage) { // tsdbUtil.c ============================================================================================== // TSDBROW -#define TSDBROW_TS(ROW) (((ROW)->type == 0) ? (ROW)->pTSRow->ts : (ROW)->pBlockData->aTSKEY[(ROW)->iRow]) -#define TSDBROW_VERSION(ROW) (((ROW)->type == 0) ? (ROW)->version : (ROW)->pBlockData->aVersion[(ROW)->iRow]) -#define TSDBROW_SVERSION(ROW) TD_ROW_SVER((ROW)->pTSRow) -#define TSDBROW_KEY(ROW) ((TSDBKEY){.version = TSDBROW_VERSION(ROW), .ts = TSDBROW_TS(ROW)}) -#define tsdbRowFromTSRow(VERSION, TSROW) ((TSDBROW){.type = 0, .version = (VERSION), .pTSRow = (TSROW)}) -#define tsdbRowFromBlockData(BLOCKDATA, IROW) ((TSDBROW){.type = 1, .pBlockData = (BLOCKDATA), .iRow = (IROW)}) -void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal); -// int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow); +#define TSDBROW_TS(ROW) (((ROW)->type == TSDBROW_ROW_FMT) ? (ROW)->pTSRow->ts : (ROW)->pBlockData->aTSKEY[(ROW)->iRow]) +#define TSDBROW_VERSION(ROW) \ + (((ROW)->type == TSDBROW_ROW_FMT) ? (ROW)->version : (ROW)->pBlockData->aVersion[(ROW)->iRow]) +#define TSDBROW_SVERSION(ROW) ((ROW)->type == TSDBROW_ROW_FMT ? (ROW)->pTSRow->sver : -1) +#define TSDBROW_KEY(ROW) ((TSDBKEY){.version = TSDBROW_VERSION(ROW), .ts = TSDBROW_TS(ROW)}) +#define tsdbRowFromTSRow(VERSION, TSROW) ((TSDBROW){.type = TSDBROW_ROW_FMT, .version = (VERSION), .pTSRow = (TSROW)}) +#define tsdbRowFromBlockData(BLOCKDATA, IROW) \ + ((TSDBROW){.type = TSDBROW_COL_FMT, .pBlockData = (BLOCKDATA), .iRow = (IROW)}) + +void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal); int32_t tsdbRowCmprFn(const void *p1, const void *p2); // STSDBRowIter -void tsdbRowIterInit(STSDBRowIter *pIter, TSDBROW *pRow, STSchema *pTSchema); +int32_t tsdbRowIterOpen(STSDBRowIter *pIter, TSDBROW *pRow, STSchema *pTSchema); +void tsdbRowClose(STSDBRowIter *pIter); SColVal *tsdbRowIterNext(STSDBRowIter *pIter); + // SRowMerger -int32_t tRowMergerInit2(SRowMerger *pMerger, STSchema *pResTSchema, TSDBROW *pRow, STSchema *pTSchema); -int32_t tRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema); +int32_t tsdbRowMergerInit(SRowMerger *pMerger, STSchema *pSchema); +int32_t tsdbRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema); +int32_t tsdbRowMergerGetRow(SRowMerger *pMerger, SRow **ppRow); +void tsdbRowMergerClear(SRowMerger *pMerger); +void tsdbRowMergerCleanup(SRowMerger *pMerger); -int32_t tRowMergerInit(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema); -void tRowMergerClear(SRowMerger *pMerger); -int32_t tRowMerge(SRowMerger *pMerger, TSDBROW *pRow); -int32_t tRowMergerGetRow(SRowMerger *pMerger, STSRow **ppRow); // TABLEID int32_t tTABLEIDCmprFn(const void *p1, const void *p2); // TSDBKEY @@ -146,24 +155,24 @@ int32_t tGetBlockIdx(uint8_t *p, void *ph); int32_t tCmprBlockIdx(void const *lhs, void const *rhs); int32_t tCmprBlockL(void const *lhs, void const *rhs); // SBlockData -#define tBlockDataFirstRow(PBLOCKDATA) tsdbRowFromBlockData(PBLOCKDATA, 0) -#define tBlockDataLastRow(PBLOCKDATA) tsdbRowFromBlockData(PBLOCKDATA, (PBLOCKDATA)->nRow - 1) -#define tBlockDataFirstKey(PBLOCKDATA) TSDBROW_KEY(&tBlockDataFirstRow(PBLOCKDATA)) -#define tBlockDataLastKey(PBLOCKDATA) TSDBROW_KEY(&tBlockDataLastRow(PBLOCKDATA)) - -int32_t tBlockDataCreate(SBlockData *pBlockData); -void tBlockDataDestroy(SBlockData *pBlockData, int8_t deepClear); -int32_t tBlockDataInit(SBlockData *pBlockData, TABLEID *pId, STSchema *pTSchema, int16_t *aCid, int32_t nCid); -void tBlockDataReset(SBlockData *pBlockData); -int32_t tBlockDataAppendRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTSchema, int64_t uid); -void tBlockDataClear(SBlockData *pBlockData); -SColData *tBlockDataGetColDataByIdx(SBlockData *pBlockData, int32_t idx); -void tBlockDataGetColData(SBlockData *pBlockData, int16_t cid, SColData **ppColData); -int32_t tBlockDataMerge(SBlockData *pBlockData1, SBlockData *pBlockData2, SBlockData *pBlockData); -int32_t tBlockDataAddColData(SBlockData *pBlockData, SColData **ppColData); -int32_t tCmprBlockData(SBlockData *pBlockData, int8_t cmprAlg, uint8_t **ppOut, int32_t *szOut, uint8_t *aBuf[], - int32_t aBufN[]); -int32_t tDecmprBlockData(uint8_t *pIn, int32_t szIn, SBlockData *pBlockData, uint8_t *aBuf[]); +#define tBlockDataFirstRow(PBLOCKDATA) tsdbRowFromBlockData(PBLOCKDATA, 0) +#define tBlockDataLastRow(PBLOCKDATA) tsdbRowFromBlockData(PBLOCKDATA, (PBLOCKDATA)->nRow - 1) +#define tBlockDataFirstKey(PBLOCKDATA) TSDBROW_KEY(&tBlockDataFirstRow(PBLOCKDATA)) +#define tBlockDataLastKey(PBLOCKDATA) TSDBROW_KEY(&tBlockDataLastRow(PBLOCKDATA)) +#define tBlockDataGetColDataByIdx(PBLOCKDATA, IDX) (&(PBLOCKDATA)->aColData[IDX]) + +int32_t tBlockDataCreate(SBlockData *pBlockData); +void tBlockDataDestroy(SBlockData *pBlockData); +int32_t tBlockDataInit(SBlockData *pBlockData, TABLEID *pId, STSchema *pTSchema, int16_t *aCid, int32_t nCid); +void tBlockDataReset(SBlockData *pBlockData); +int32_t tBlockDataAppendRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTSchema, int64_t uid); +int32_t tBlockDataTryUpsertRow(SBlockData *pBlockData, TSDBROW *pRow, int64_t uid); +int32_t tBlockDataUpsertRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTSchema, int64_t uid); +void tBlockDataClear(SBlockData *pBlockData); +void tBlockDataGetColData(SBlockData *pBlockData, int16_t cid, SColData **ppColData); +int32_t tCmprBlockData(SBlockData *pBlockData, int8_t cmprAlg, uint8_t **ppOut, int32_t *szOut, uint8_t *aBuf[], + int32_t aBufN[]); +int32_t tDecmprBlockData(uint8_t *pIn, int32_t szIn, SBlockData *pBlockData, uint8_t *aBuf[]); // SDiskDataHdr int32_t tPutDiskDataHdr(uint8_t *p, const SDiskDataHdr *pHdr); int32_t tGetDiskDataHdr(uint8_t *p, void *ph); @@ -206,16 +215,18 @@ int32_t tRowInfoCmprFn(const void *p1, const void *p2); // tsdbMemTable ============================================================================================== // SMemTable int32_t tsdbMemTableCreate(STsdb *pTsdb, SMemTable **ppMemTable); -void tsdbMemTableDestroy(SMemTable *pMemTable); +void tsdbMemTableDestroy(SMemTable *pMemTable, bool proactive); STbData *tsdbGetTbDataFromMemTable(SMemTable *pMemTable, tb_uid_t suid, tb_uid_t uid); -void tsdbRefMemTable(SMemTable *pMemTable); -void tsdbUnrefMemTable(SMemTable *pMemTable); +int32_t tsdbRefMemTable(SMemTable *pMemTable, SQueryNode *pQNode); +int32_t tsdbUnrefMemTable(SMemTable *pMemTable, SQueryNode *pNode, bool proactive); SArray *tsdbMemTableGetTbDataArray(SMemTable *pMemTable); // STbDataIter int32_t tsdbTbDataIterCreate(STbData *pTbData, TSDBKEY *pFrom, int8_t backward, STbDataIter **ppIter); void *tsdbTbDataIterDestroy(STbDataIter *pIter); void tsdbTbDataIterOpen(STbData *pTbData, TSDBKEY *pFrom, int8_t backward, STbDataIter *pIter); bool tsdbTbDataIterNext(STbDataIter *pIter); +void tsdbMemTableCountRows(SMemTable *pMemTable, SSHashObj *pTableMap, int64_t *rowsNum); + // STbData int32_t tsdbGetNRowsInTbData(STbData *pTbData); // tsdbFile.c ============================================================================================== @@ -274,6 +285,7 @@ int32_t tsdbReadDataBlk(SDataFReader *pReader, SBlockIdx *pBlockIdx, SMapData *m int32_t tsdbReadSttBlk(SDataFReader *pReader, int32_t iStt, SArray *aSttBlk); int32_t tsdbReadBlockSma(SDataFReader *pReader, SDataBlk *pBlock, SArray *aColumnDataAgg); int32_t tsdbReadDataBlock(SDataFReader *pReader, SDataBlk *pBlock, SBlockData *pBlockData); +int32_t tsdbReadDataBlockEx(SDataFReader *pReader, SDataBlk *pDataBlk, SBlockData *pBlockData); int32_t tsdbReadSttBlock(SDataFReader *pReader, int32_t iStt, SSttBlk *pSttBlk, SBlockData *pBlockData); int32_t tsdbReadSttBlockEx(SDataFReader *pReader, int32_t iStt, SSttBlk *pSttBlk, SBlockData *pBlockData); // SDelFWriter @@ -288,8 +300,8 @@ int32_t tsdbDelFReaderClose(SDelFReader **ppReader); int32_t tsdbReadDelData(SDelFReader *pReader, SDelIdx *pDelIdx, SArray *aDelData); int32_t tsdbReadDelIdx(SDelFReader *pReader, SArray *aDelIdx); // tsdbRead.c ============================================================================================== -int32_t tsdbTakeReadSnap(STsdb *pTsdb, STsdbReadSnap **ppSnap, const char *id); -void tsdbUntakeReadSnap(STsdb *pTsdb, STsdbReadSnap *pSnap, const char *id); +int32_t tsdbTakeReadSnap(STsdbReader *pReader, _query_reseek_func_t reseek, STsdbReadSnap **ppSnap); +void tsdbUntakeReadSnap(STsdbReader *pReader, STsdbReadSnap *pSnap, bool proactive); // tsdbMerge.c ============================================================================================== int32_t tsdbMerge(STsdb *pTsdb); @@ -305,6 +317,27 @@ int32_t tDiskDataBuilderInit(SDiskDataBuilder *pBuilder, STSchema *pTSchema, TAB int32_t tDiskDataBuilderClear(SDiskDataBuilder *pBuilder); int32_t tDiskDataAddRow(SDiskDataBuilder *pBuilder, TSDBROW *pRow, STSchema *pTSchema, TABLEID *pId); int32_t tGnrtDiskData(SDiskDataBuilder *pBuilder, const SDiskData **ppDiskData, const SBlkInfo **ppBlkInfo); +// tsdbDataIter.c ============================================================================================== +#define TSDB_MEM_TABLE_DATA_ITER 0 +#define TSDB_DATA_FILE_DATA_ITER 1 +#define TSDB_STT_FILE_DATA_ITER 2 +#define TSDB_TOMB_FILE_DATA_ITER 3 + +#define TSDB_FILTER_FLAG_BY_VERSION 0x1 +#define TSDB_FILTER_FLAG_BY_TABLEID 0x2 +#define TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE 0x4 + +#define TSDB_RBTN_TO_DATA_ITER(pNode) ((STsdbDataIter2 *)(((char *)pNode) - offsetof(STsdbDataIter2, rbtn))) +/* open */ +int32_t tsdbOpenDataFileDataIter(SDataFReader *pReader, STsdbDataIter2 **ppIter); +int32_t tsdbOpenSttFileDataIter(SDataFReader *pReader, int32_t iStt, STsdbDataIter2 **ppIter); +int32_t tsdbOpenTombFileDataIter(SDelFReader *pReader, STsdbDataIter2 **ppIter); +/* close */ +void tsdbCloseDataIter2(STsdbDataIter2 *pIter); +/* cmpr */ +int32_t tsdbDataIterCmprFn(const SRBTreeNode *pNode1, const SRBTreeNode *pNode2); +/* next */ +int32_t tsdbDataIterNext2(STsdbDataIter2 *pIter, STsdbFilterInfo *pFilterInfo); // structs ======================= struct STsdbFS { @@ -339,10 +372,13 @@ struct SVersionRange { typedef struct SMemSkipListNode SMemSkipListNode; struct SMemSkipListNode { int8_t level; + int8_t flag; // TSDBROW_ROW_FMT for row format, TSDBROW_COL_FMT for col format + int32_t iRow; int64_t version; - STSRow *pTSRow; + void *pData; SMemSkipListNode *forwards[0]; }; + typedef struct SMemSkipList { int64_t size; uint32_t seed; @@ -368,6 +404,8 @@ struct SMemTable { STsdb *pTsdb; SVBufPool *pPool; volatile int32_t nRef; + int64_t minVer; + int64_t maxVer; TSKEY minKey; TSKEY maxKey; int64_t nRow; @@ -380,11 +418,11 @@ struct SMemTable { }; struct TSDBROW { - int8_t type; // 0 for row from tsRow, 1 for row from block data + int8_t type; // TSDBROW_ROW_FMT for row from tsRow, TSDBROW_COL_FMT for row from block data union { struct { int64_t version; - STSRow *pTSRow; + SRow *pTSRow; }; struct { SBlockData *pBlockData; @@ -470,14 +508,14 @@ struct SSttBlk { // (SBlockData){.suid = suid, .uid = 0}: block data for N child tables int .last file // (SBlockData){.suid = 0, .uid = uid}: block data for 1 normal table int .last/.data file struct SBlockData { - int64_t suid; // 0 means normal table block data, otherwise child table block data - int64_t uid; // 0 means block data in .last file, otherwise in .data file - int32_t nRow; // number of rows - int64_t *aUid; // uids of each row, only exist in block data in .last file (uid == 0) - int64_t *aVersion; // versions of each row - TSKEY *aTSKEY; // timestamp of each row - int32_t nColData; - SArray *aColData; // SArray + int64_t suid; // 0 means normal table block data, otherwise child table block data + int64_t uid; // 0 means block data in .last file, otherwise in .data file + int32_t nRow; // number of rows + int64_t *aUid; // uids of each row, only exist in block data in .last file (uid == 0) + int64_t *aVersion; // versions of each row + TSKEY *aTSKEY; // timestamp of each row + int32_t nColData; + SColData *aColData; }; struct TABLEID { @@ -569,10 +607,14 @@ struct SDFileSet { }; struct STSDBRowIter { - TSDBROW *pRow; - STSchema *pTSchema; - SColVal colVal; - int32_t i; + TSDBROW *pRow; + union { + SRowIter *pIter; + struct { + int32_t iColData; + SColVal cv; + }; + }; }; struct SRowMerger { STSchema *pTSchema; @@ -598,9 +640,11 @@ struct SDelFWriter { }; struct STsdbReadSnap { - SMemTable *pMem; - SMemTable *pIMem; - STsdbFS fs; + SMemTable *pMem; + SQueryNode *pNode; + SMemTable *pIMem; + SQueryNode *pINode; + STsdbFS fs; }; struct SDataFWriter { @@ -630,6 +674,7 @@ struct SDataFReader { uint8_t *aBuf[3]; }; +// NOTE: do NOT change the order of the fields typedef struct { int64_t suid; int64_t uid; @@ -646,6 +691,8 @@ typedef struct SSttBlockLoadInfo { STSchema *pSchema; int16_t *colIds; int32_t numOfCols; + bool checkRemainingRow; + bool isLast; bool sttBlockLoaded; int32_t numOfStt; @@ -660,11 +707,11 @@ typedef struct SSttBlockLoadInfo { typedef struct SMergeTree { int8_t backward; SRBTree rbt; - SArray *pIterList; SLDataIter *pIter; bool destroyLoadInfo; SSttBlockLoadInfo *pLoadInfo; const char *idStr; + bool ignoreEarlierTs; } SMergeTree; typedef struct { @@ -705,12 +752,29 @@ struct SDiskDataBuilder { SBlkInfo bi; }; +typedef struct SLDataIter { + SRBTreeNode node; + SSttBlk *pSttBlk; + SDataFReader *pReader; + int32_t iStt; + int8_t backward; + int32_t iSttBlk; + int32_t iRow; + SRowInfo rInfo; + uint64_t uid; + STimeWindow timeWindow; + SVersionRange verRange; + SSttBlockLoadInfo *pBlockLoadInfo; + bool ignoreEarlierTs; +} SLDataIter; + +#define tMergeTreeGetRow(_t) (&((_t)->pIter->rInfo.row)) int32_t tMergeTreeOpen(SMergeTree *pMTree, int8_t backward, SDataFReader *pFReader, uint64_t suid, uint64_t uid, STimeWindow *pTimeWindow, SVersionRange *pVerRange, SSttBlockLoadInfo *pBlockLoadInfo, - bool destroyLoadInfo, const char *idStr); + bool destroyLoadInfo, const char *idStr, bool strictTimeRange, SLDataIter* pLDataIter); void tMergeTreeAddIter(SMergeTree *pMTree, SLDataIter *pIter); bool tMergeTreeNext(SMergeTree *pMTree); -TSDBROW tMergeTreeGetRow(SMergeTree *pMTree); +bool tMergeTreeIgnoreEarlierTs(SMergeTree *pMTree); void tMergeTreeClose(SMergeTree *pMTree); SSttBlockLoadInfo *tCreateLastBlockLoadInfo(STSchema *pSchema, int16_t *colList, int32_t numOfCols, int32_t numOfStt); @@ -720,8 +784,12 @@ void *destroyLastBlockLoadInfo(SSttBlockLoadInfo *pLoadInfo); // tsdbCache ============================================================================================== typedef struct SCacheRowsReader { + STsdb *pTsdb; + SVersionRange verRange; + TdThreadMutex readerMutex; SVnode *pVnode; STSchema *pSchema; + STSchema *pCurrSchema; uint64_t uid; uint64_t suid; char **transferBuf; // todo remove it soon @@ -731,10 +799,12 @@ typedef struct SCacheRowsReader { STableKeyInfo *pTableList; // table id list int32_t numOfTables; SSttBlockLoadInfo *pLoadInfo; + SLDataIter *pDataIter; STsdbReadSnap *pReadSnap; SDataFReader *pDataFReader; SDataFReader *pDataFReaderLast; const char *idstr; + int64_t lastTs; } SCacheRowsReader; typedef struct { @@ -744,8 +814,8 @@ typedef struct { int32_t tsdbOpenCache(STsdb *pTsdb); void tsdbCloseCache(STsdb *pTsdb); -int32_t tsdbCacheInsertLast(SLRUCache *pCache, tb_uid_t uid, STSRow *row, STsdb *pTsdb); -int32_t tsdbCacheInsertLastrow(SLRUCache *pCache, STsdb *pTsdb, tb_uid_t uid, STSRow *row, bool dup); +int32_t tsdbCacheInsertLast(SLRUCache *pCache, tb_uid_t uid, TSDBROW *row, STsdb *pTsdb); +int32_t tsdbCacheInsertLastrow(SLRUCache *pCache, STsdb *pTsdb, tb_uid_t uid, TSDBROW *row, bool dup); int32_t tsdbCacheGetLastH(SLRUCache *pCache, tb_uid_t uid, SCacheRowsReader *pr, LRUHandle **h); int32_t tsdbCacheGetLastrowH(SLRUCache *pCache, tb_uid_t uid, SCacheRowsReader *pr, LRUHandle **h); int32_t tsdbCacheRelease(SLRUCache *pCache, LRUHandle *h); @@ -760,6 +830,8 @@ int32_t tsdbCacheDelete(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey); void tsdbCacheSetCapacity(SVnode *pVnode, size_t capacity); size_t tsdbCacheGetCapacity(SVnode *pVnode); +// int32_t tsdbCacheLastArray2Row(SArray *pLastArray, STSRow **ppRow, STSchema *pSchema); + // ========== inline functions ========== static FORCE_INLINE int32_t tsdbKeyCmprFn(const void *p1, const void *p2) { TSDBKEY *pKey1 = (TSDBKEY *)p1; @@ -801,12 +873,76 @@ static FORCE_INLINE TSDBROW *tsdbTbDataIterGet(STbDataIter *pIter) { } pIter->pRow = &pIter->row; - pIter->pRow->version = pIter->pNode->version; - pIter->pRow->pTSRow = pIter->pNode->pTSRow; + if (pIter->pNode->flag == TSDBROW_ROW_FMT) { + pIter->row = tsdbRowFromTSRow(pIter->pNode->version, pIter->pNode->pData); + } else if (pIter->pNode->flag == TSDBROW_COL_FMT) { + pIter->row = tsdbRowFromBlockData(pIter->pNode->pData, pIter->pNode->iRow); + } else { + ASSERT(0); + } return pIter->pRow; } +int32_t tRowInfoCmprFn(const void *p1, const void *p2); + +typedef struct { + int64_t suid; + int64_t uid; + SDelData delData; +} SDelInfo; + +struct STsdbDataIter2 { + STsdbDataIter2 *next; + SRBTreeNode rbtn; + + int32_t type; + SRowInfo rowInfo; + SDelInfo delInfo; + union { + // TSDB_MEM_TABLE_DATA_ITER + struct { + SMemTable *pMemTable; + } mIter; + + // TSDB_DATA_FILE_DATA_ITER + struct { + SDataFReader *pReader; + SArray *aBlockIdx; // SArray + SMapData mDataBlk; + SBlockData bData; + int32_t iBlockIdx; + int32_t iDataBlk; + int32_t iRow; + } dIter; + + // TSDB_STT_FILE_DATA_ITER + struct { + SDataFReader *pReader; + int32_t iStt; + SArray *aSttBlk; + SBlockData bData; + int32_t iSttBlk; + int32_t iRow; + } sIter; + // TSDB_TOMB_FILE_DATA_ITER + struct { + SDelFReader *pReader; + SArray *aDelIdx; + SArray *aDelData; + int32_t iDelIdx; + int32_t iDelData; + } tIter; + }; +}; + +struct STsdbFilterInfo { + int32_t flag; + int64_t sver; + int64_t ever; + TABLEID tbid; +}; + #ifdef __cplusplus } #endif diff --git a/source/dnode/vnode/src/inc/vnd.h b/source/dnode/vnode/src/inc/vnd.h index e075d8a6ca0af9da2a0ca7f12eeb834599fce3e5..ae65e2ba3f199e53e682e6f429fbfc22c794e7fa 100644 --- a/source/dnode/vnode/src/inc/vnd.h +++ b/source/dnode/vnode/src/inc/vnd.h @@ -61,10 +61,19 @@ struct SVBufPoolNode { }; struct SVBufPool { - SVBufPool* next; + SVBufPool* freeNext; + SVBufPool* recycleNext; + SVBufPool* recyclePrev; + + // query handle list + TdThreadMutex mutex; + int32_t nQuery; + SQueryNode qList; + SVnode* pVnode; - TdThreadSpinlock* lock; + int32_t id; volatile int32_t nRef; + TdThreadSpinlock* lock; int64_t size; uint8_t* ptr; SVBufPoolNode* pTail; @@ -74,6 +83,8 @@ struct SVBufPool { int32_t vnodeOpenBufPool(SVnode* pVnode); int32_t vnodeCloseBufPool(SVnode* pVnode); void vnodeBufPoolReset(SVBufPool* pPool); +void vnodeBufPoolAddToFreeList(SVBufPool* pPool); +int32_t vnodeBufPoolRecycle(SVBufPool* pPool); // vnodeQuery.c int32_t vnodeQueryOpen(SVnode* pVnode); @@ -85,11 +96,11 @@ int32_t vnodeGetBatchMeta(SVnode* pVnode, SRpcMsg* pMsg); // vnodeCommit.c int32_t vnodeBegin(SVnode* pVnode); -int32_t vnodeShouldCommit(SVnode* pVnode); +int32_t vnodeShouldCommit(SVnode* pVnode, bool atExit); void vnodeUpdCommitSched(SVnode* pVnode); void vnodeRollback(SVnode* pVnode); int32_t vnodeSaveInfo(const char* dir, const SVnodeInfo* pCfg); -int32_t vnodeCommitInfo(const char* dir, const SVnodeInfo* pInfo); +int32_t vnodeCommitInfo(const char* dir); int32_t vnodeLoadInfo(const char* dir, SVnodeInfo* pInfo); int32_t vnodeSyncCommit(SVnode* pVnode); int32_t vnodeAsyncCommit(SVnode* pVnode); @@ -104,7 +115,6 @@ void vnodeSyncClose(SVnode* pVnode); void vnodeRedirectRpcMsg(SVnode* pVnode, SRpcMsg* pMsg, int32_t code); bool vnodeIsLeader(SVnode* pVnode); bool vnodeIsRoleLeader(SVnode* pVnode); -int vnodeShouldCommit(SVnode* pVnode); #ifdef __cplusplus } diff --git a/source/dnode/vnode/src/inc/vnodeInt.h b/source/dnode/vnode/src/inc/vnodeInt.h index ec925087d09c86fe60204c18457e2ea7b6d6823d..0173db976d816f25d483add64c6b53a83601f8e6 100644 --- a/source/dnode/vnode/src/inc/vnodeInt.h +++ b/source/dnode/vnode/src/inc/vnodeInt.h @@ -58,7 +58,7 @@ typedef struct STQ STQ; typedef struct SVState SVState; typedef struct SVStatis SVStatis; typedef struct SVBufPool SVBufPool; -typedef struct SQWorker SQHandle; +typedef struct SQueueWorker SQHandle; typedef struct STsdbKeepCfg STsdbKeepCfg; typedef struct SMetaSnapReader SMetaSnapReader; typedef struct SMetaSnapWriter SMetaSnapWriter; @@ -76,6 +76,8 @@ typedef struct SRSmaSnapReader SRSmaSnapReader; typedef struct SRSmaSnapWriter SRSmaSnapWriter; typedef struct SSnapDataHdr SSnapDataHdr; typedef struct SCommitInfo SCommitInfo; +typedef struct SCompactInfo SCompactInfo; +typedef struct SQueryNode SQueryNode; #define VNODE_META_DIR "meta" #define VNODE_TSDB_DIR "tsdb" @@ -87,16 +89,29 @@ typedef struct SCommitInfo SCommitInfo; #define VNODE_RSMA1_DIR "rsma1" #define VNODE_RSMA2_DIR "rsma2" +#define VNODE_BUFPOOL_SEGMENTS 3 + #define VND_INFO_FNAME "vnode.json" // vnd.h +typedef int32_t (*_query_reseek_func_t)(void* pQHandle); +struct SQueryNode { + SQueryNode* pNext; + SQueryNode** ppNext; + void* pQHandle; + _query_reseek_func_t reseek; +}; + void* vnodeBufPoolMalloc(SVBufPool* pPool, int size); void* vnodeBufPoolMallocAligned(SVBufPool* pPool, int size); void vnodeBufPoolFree(SVBufPool* pPool, void* p); void vnodeBufPoolRef(SVBufPool* pPool); -void vnodeBufPoolUnRef(SVBufPool* pPool); +void vnodeBufPoolUnRef(SVBufPool* pPool, bool proactive); int vnodeDecodeInfo(uint8_t* pData, SVnodeInfo* pInfo); +int32_t vnodeBufPoolRegisterQuery(SVBufPool* pPool, SQueryNode* pQNode); +void vnodeBufPoolDeregisterQuery(SVBufPool* pPool, SQueryNode* pQNode, bool proactive); + // meta typedef struct SMCtbCursor SMCtbCursor; typedef struct SMStbCursor SMStbCursor; @@ -127,6 +142,9 @@ int32_t metaGetTbTSchemaEx(SMeta* pMeta, tb_uid_t suid, tb_uid_t uid, in int metaGetTableEntryByName(SMetaReader* pReader, const char* name); int metaAlterCache(SMeta* pMeta, int32_t nPage); +int metaAddIndexToSTable(SMeta* pMeta, int64_t version, SVCreateStbReq* pReq); +int metaDropIndexFromSTable(SMeta* pMeta, int64_t version, SDropIndexReq* pReq); + int64_t metaGetTimeSeriesNum(SMeta* pMeta); SMCtbCursor* metaOpenCtbCursor(SMeta* pMeta, tb_uid_t uid, int lock); void metaCloseCtbCursor(SMCtbCursor* pCtbCur, int lock); @@ -159,22 +177,26 @@ int tsdbClose(STsdb** pTsdb); int32_t tsdbBegin(STsdb* pTsdb); int32_t tsdbPrepareCommit(STsdb* pTsdb); int32_t tsdbCommit(STsdb* pTsdb, SCommitInfo* pInfo); +int32_t tsdbCompact(STsdb* pTsdb, SCompactInfo* pInfo); int32_t tsdbFinishCommit(STsdb* pTsdb); int32_t tsdbRollbackCommit(STsdb* pTsdb); -int32_t tsdbDoRetention(STsdb* pTsdb, int64_t now); -int tsdbScanAndConvertSubmitMsg(STsdb* pTsdb, SSubmitReq* pMsg); -int tsdbInsertData(STsdb* pTsdb, int64_t version, SSubmitReq* pMsg, SSubmitRsp* pRsp); -int32_t tsdbInsertTableData(STsdb* pTsdb, int64_t version, SSubmitMsgIter* pMsgIter, SSubmitBlk* pBlock, - SSubmitBlkRsp* pRsp); +int tsdbScanAndConvertSubmitMsg(STsdb* pTsdb, SSubmitReq2* pMsg); +int tsdbInsertData(STsdb* pTsdb, int64_t version, SSubmitReq2* pMsg, SSubmitRsp2* pRsp); +int32_t tsdbInsertTableData(STsdb* pTsdb, int64_t version, SSubmitTbData* pSubmitTbData, int32_t* affectedRows); int32_t tsdbDeleteTableData(STsdb* pTsdb, int64_t version, tb_uid_t suid, tb_uid_t uid, TSKEY sKey, TSKEY eKey); int32_t tsdbSetKeepCfg(STsdb* pTsdb, STsdbCfg* pCfg); // tq -int tqInit(); -void tqCleanUp(); -STQ* tqOpen(const char* path, SVnode* pVnode); -void tqClose(STQ*); -int tqPushMsg(STQ*, void* msg, int32_t msgLen, tmsg_t msgType, int64_t ver); +int tqInit(); +void tqCleanUp(); +STQ* tqOpen(const char* path, SVnode* pVnode); +void tqNotifyClose(STQ*); +void tqClose(STQ*); +int tqPushMsg(STQ*, void* msg, int32_t msgLen, tmsg_t msgType, int64_t ver); +int tqRegisterPushHandle(STQ* pTq, void* handle, SRpcMsg* pMsg); +int tqUnregisterPushHandle(STQ* pTq, void* pHandle); +int tqStartStreamTasks(STQ* pTq); // restore all stream tasks after vnode launching completed. + int tqCommit(STQ*); int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd); int32_t tqCheckColModifiable(STQ* pTq, int64_t tbUid, int32_t colId); @@ -190,8 +212,8 @@ int32_t tqProcessTaskDeployReq(STQ* pTq, int64_t version, char* msg, int32_t msg int32_t tqProcessTaskDropReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen); int32_t tqProcessStreamTaskCheckReq(STQ* pTq, SRpcMsg* pMsg); int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t version, char* msg, int32_t msgLen); -int32_t tqProcessSubmitReq(STQ* pTq, SSubmitReq* data, int64_t ver); -int32_t tqProcessDelReq(STQ* pTq, void* pReq, int32_t len, int64_t ver); +int32_t tqProcessSubmitReqForSubscribe(STQ* pTq); +int32_t tqProcessDeleteDataReq(STQ* pTq, void* pReq, int32_t len, int64_t ver); int32_t tqProcessTaskRunReq(STQ* pTq, SRpcMsg* pMsg); int32_t tqProcessTaskDispatchReq(STQ* pTq, SRpcMsg* pMsg, bool exec); int32_t tqProcessTaskDispatchRsp(STQ* pTq, SRpcMsg* pMsg); @@ -203,19 +225,12 @@ int32_t tqProcessTaskRecoverFinishReq(STQ* pTq, SRpcMsg* pMsg); int32_t tqProcessTaskRecoverFinishRsp(STQ* pTq, SRpcMsg* pMsg); int32_t tqCheckLogInWal(STQ* pTq, int64_t version); -SSubmitReq* tqBlockToSubmit(SVnode* pVnode, const SArray* pBlocks, const STSchema* pSchema, - SSchemaWrapper* pTagSchemaWrapper, bool createTb, int64_t suid, const char* stbFullName, - SBatchDeleteReq* pDeleteReq); - // sma int32_t smaInit(); void smaCleanUp(); int32_t smaOpen(SVnode* pVnode, int8_t rollback); int32_t smaClose(SSma* pSma); int32_t smaBegin(SSma* pSma); -int32_t smaSyncPreCommit(SSma* pSma); -int32_t smaSyncCommit(SSma* pSma); -int32_t smaSyncPostCommit(SSma* pSma); int32_t smaPrepareAsyncCommit(SSma* pSma); int32_t smaCommit(SSma* pSma, SCommitInfo* pInfo); int32_t smaFinishCommit(SSma* pSma); @@ -226,11 +241,10 @@ int32_t tdProcessTSmaCreate(SSma* pSma, int64_t version, const char* msg); int32_t tdProcessTSmaInsert(SSma* pSma, int64_t indexUid, const char* msg); int32_t tdProcessRSmaCreate(SSma* pSma, SVCreateStbReq* pReq); -int32_t tdProcessRSmaSubmit(SSma* pSma, void* pMsg, int32_t inputType); +int32_t tdProcessRSmaSubmit(SSma* pSma, int64_t version, void* pReq, void* pMsg, int32_t len, int32_t inputType); int32_t tdProcessRSmaDrop(SSma* pSma, SVDropStbReq* pReq); int32_t tdFetchTbUidList(SSma* pSma, STbUidStore** ppStore, tb_uid_t suid, tb_uid_t uid); int32_t tdUpdateTbUidList(SSma* pSma, STbUidStore* pUidStore, bool isAdd); -void tdUidStoreDestory(STbUidStore* pStore); void* tdUidStoreFree(STbUidStore* pStore); // SMetaSnapReader ======================================== @@ -277,6 +291,7 @@ int32_t rsmaSnapRead(SRSmaSnapReader* pReader, uint8_t** ppData); // SRSmaSnapWriter ======================================== int32_t rsmaSnapWriterOpen(SSma* pSma, int64_t sver, int64_t ever, SRSmaSnapWriter** ppWriter); int32_t rsmaSnapWrite(SRSmaSnapWriter* pWriter, uint8_t* pData, uint32_t nData); +int32_t rsmaSnapWriterPrepareClose(SRSmaSnapWriter* pWriter); int32_t rsmaSnapWriterClose(SRSmaSnapWriter** ppWriter, int8_t rollback); typedef struct { @@ -338,16 +353,24 @@ typedef struct SVCommitSched { } SVCommitSched; struct SVnode { - char* path; - SVnodeCfg config; - SVState state; - SVStatis statis; - STfs* pTfs; - SMsgCb msgCb; + char* path; + SVnodeCfg config; + SVState state; + SVStatis statis; + STfs* pTfs; + SMsgCb msgCb; + + // Buffer Pool TdThreadMutex mutex; TdThreadCond poolNotEmpty; - SVBufPool* pPool; + SVBufPool* aBufPool[VNODE_BUFPOOL_SEGMENTS]; + SVBufPool* freeList; SVBufPool* inUse; + SVBufPool* onCommit; + SVBufPool* recycleHead; + SVBufPool* recycleTail; + SVBufPool* onRecycle; + SMeta* pMeta; SSma* pSma; STsdb* pTsdb; @@ -426,6 +449,7 @@ enum { struct SSnapDataHdr { int8_t type; + int8_t flag; int64_t index; int64_t size; uint8_t data[]; @@ -437,6 +461,13 @@ struct SCommitInfo { TXN* txn; }; +struct SCompactInfo { + SVnode* pVnode; + int32_t flag; + int64_t commitID; + STimeWindow tw; +}; + #ifdef __cplusplus } #endif diff --git a/source/dnode/vnode/src/meta/metaCache.c b/source/dnode/vnode/src/meta/metaCache.c index 366c072b6f83cf40e404408843504257b2b107f5..436ca1abd3c7939488796b536c28aed03029da80 100644 --- a/source/dnode/vnode/src/meta/metaCache.c +++ b/source/dnode/vnode/src/meta/metaCache.c @@ -14,6 +14,7 @@ */ #include "meta.h" +#define TAG_FILTER_RES_KEY_LEN 32 #define META_CACHE_BASE_BUCKET 1024 #define META_CACHE_STATS_BUCKET 16 @@ -32,9 +33,8 @@ typedef struct SMetaStbStatsEntry { } SMetaStbStatsEntry; typedef struct STagFilterResEntry { - SList list; // the linked list of md5 digest, extracted from the serialized tag query condition + SList list; // the linked list of md5 digest, extracted from the serialized tag query condition uint32_t hitTimes; // queried times for current super table - uint32_t accTime; } STagFilterResEntry; struct SMetaCache { @@ -55,10 +55,17 @@ struct SMetaCache { // query cache struct STagFilterResCache { TdThreadMutex lock; - uint32_t accTimes; - SHashObj* pTableEntry; - SLRUCache* pUidResCache; + uint32_t accTimes; + SHashObj* pTableEntry; + SLRUCache* pUidResCache; } sTagFilterResCache; + + struct STbGroupResCache { + TdThreadMutex lock; + uint32_t accTimes; + SHashObj* pTableEntry; + SLRUCache* pResCache; + } STbGroupResCache; }; static void entryCacheClose(SMeta* pMeta) { @@ -144,6 +151,25 @@ int32_t metaCacheOpen(SMeta* pMeta) { taosHashSetFreeFp(pCache->sTagFilterResCache.pTableEntry, freeCacheEntryFp); taosThreadMutexInit(&pCache->sTagFilterResCache.lock, NULL); + + pCache->STbGroupResCache.pResCache = taosLRUCacheInit(5 * 1024 * 1024, -1, 0.5); + if (pCache->STbGroupResCache.pResCache == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _err2; + } + + pCache->STbGroupResCache.accTimes = 0; + pCache->STbGroupResCache.pTableEntry = + taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_VARCHAR), false, HASH_NO_LOCK); + if (pCache->STbGroupResCache.pTableEntry == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _err2; + } + + taosHashSetFreeFp(pCache->STbGroupResCache.pTableEntry, freeCacheEntryFp); + taosThreadMutexInit(&pCache->STbGroupResCache.lock, NULL); + + pMeta->pCache = pCache; return code; @@ -165,6 +191,10 @@ void metaCacheClose(SMeta* pMeta) { taosThreadMutexDestroy(&pMeta->pCache->sTagFilterResCache.lock); taosHashCleanup(pMeta->pCache->sTagFilterResCache.pTableEntry); + taosLRUCacheCleanup(pMeta->pCache->STbGroupResCache.pResCache); + taosThreadMutexDestroy(&pMeta->pCache->STbGroupResCache.lock); + taosHashCleanup(pMeta->pCache->STbGroupResCache.pTableEntry); + taosMemoryFree(pMeta->pCache); pMeta->pCache = NULL; } @@ -212,7 +242,7 @@ _exit: int32_t metaCacheUpsert(SMeta* pMeta, SMetaInfo* pInfo) { int32_t code = 0; - // ASSERT(metaIsWLocked(pMeta)); + // meta is wlocked for calling this func. // search SMetaCache* pCache = pMeta->pCache; @@ -223,7 +253,10 @@ int32_t metaCacheUpsert(SMeta* pMeta, SMetaInfo* pInfo) { } if (*ppEntry) { // update - ASSERT(pInfo->suid == (*ppEntry)->info.suid); + if (pInfo->suid != (*ppEntry)->info.suid) { + metaError("meta/cache: suid should be same as the one in cache."); + return TSDB_CODE_FAILED; + } if (pInfo->version > (*ppEntry)->info.version) { (*ppEntry)->info.version = pInfo->version; (*ppEntry)->info.skmVer = pInfo->skmVer; @@ -342,7 +375,7 @@ _exit: int32_t metaStatsCacheUpsert(SMeta* pMeta, SMetaStbStats* pInfo) { int32_t code = 0; - // ASSERT(metaIsWLocked(pMeta)); + // meta is wlocked for calling this func. // search SMetaCache* pCache = pMeta->pCache; @@ -426,12 +459,13 @@ int32_t metaStatsCacheGet(SMeta* pMeta, int64_t uid, SMetaStbStats* pInfo) { return code; } -static int checkAllEntriesInCache(const STagFilterResEntry* pEntry, SArray* pInvalidRes, int32_t keyLen, SLRUCache* pCache, uint64_t suid) { +static int checkAllEntriesInCache(const STagFilterResEntry* pEntry, SArray* pInvalidRes, int32_t keyLen, + SLRUCache* pCache, uint64_t suid) { SListIter iter = {0}; tdListInitIter((SList*)&(pEntry->list), &iter, TD_LIST_FORWARD); SListNode* pNode = NULL; - uint64_t buf[3]; + uint64_t buf[3]; buf[0] = suid; int32_t len = sizeof(uint64_t) * tListLen(buf); @@ -451,26 +485,37 @@ static int checkAllEntriesInCache(const STagFilterResEntry* pEntry, SArray* pInv return 0; } +static FORCE_INLINE void setMD5DigestInKey(uint64_t* pBuf, const char* key, int32_t keyLen) { +// ASSERT(keyLen == sizeof(int64_t) * 2); + memcpy(&pBuf[2], key, keyLen); +} + +// the format of key: +// hash table address(8bytes) + suid(8bytes) + MD5 digest(16bytes) +static void initCacheKey(uint64_t* buf, const SHashObj* pHashMap, uint64_t suid, const char* key, int32_t keyLen) { + buf[0] = (uint64_t) pHashMap; + buf[1] = suid; + setMD5DigestInKey(buf, key, keyLen); + ASSERT(keyLen == sizeof(uint64_t) * 2); +} + int32_t metaGetCachedTableUidList(SMeta* pMeta, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray* pList1, bool* acquireRes) { + int32_t vgId = TD_VID(pMeta->pVnode); + // generate the composed key for LRU cache SLRUCache* pCache = pMeta->pCache->sTagFilterResCache.pUidResCache; SHashObj* pTableMap = pMeta->pCache->sTagFilterResCache.pTableEntry; TdThreadMutex* pLock = &pMeta->pCache->sTagFilterResCache.lock; - uint64_t buf[4]; - *acquireRes = 0; - - buf[0] = (uint64_t) pTableMap; - buf[1] = suid; - memcpy(&buf[2], pKey, keyLen); + uint64_t key[4]; + initCacheKey(key, pTableMap, suid, (const char*)pKey, keyLen); taosThreadMutexLock(pLock); pMeta->pCache->sTagFilterResCache.accTimes += 1; - int32_t len = keyLen + sizeof(uint64_t) * 2; - LRUHandle* pHandle = taosLRUCacheLookup(pCache, buf, len); + LRUHandle* pHandle = taosLRUCacheLookup(pCache, key, TAG_FILTER_RES_KEY_LEN); if (pHandle == NULL) { taosThreadMutexUnlock(pLock); return TSDB_CODE_SUCCESS; @@ -478,7 +523,11 @@ int32_t metaGetCachedTableUidList(SMeta* pMeta, tb_uid_t suid, const uint8_t* pK // do some book mark work after acquiring the filter result from cache STagFilterResEntry** pEntry = taosHashGet(pTableMap, &suid, sizeof(uint64_t)); - ASSERT(pEntry != NULL); + if (NULL == pEntry) { + metaError("meta/cache: pEntry should not be NULL."); + return TSDB_CODE_FAILED; + } + *acquireRes = 1; const char* p = taosLRUCacheValue(pCache, pHandle); @@ -491,7 +540,7 @@ int32_t metaGetCachedTableUidList(SMeta* pMeta, tb_uid_t suid, const uint8_t* pK uint32_t acc = pMeta->pCache->sTagFilterResCache.accTimes; if ((*pEntry)->hitTimes % 5000 == 0 && (*pEntry)->hitTimes > 0) { - metaInfo("cache hit:%d, total acc:%d, rate:%.2f", (*pEntry)->hitTimes, acc, ((double)(*pEntry)->hitTimes) / acc); + metaInfo("vgId:%d cache hit:%d, total acc:%d, rate:%.2f", vgId, (*pEntry)->hitTimes, acc, ((double)(*pEntry)->hitTimes) / acc); } taosLRUCacheRelease(pCache, pHandle, false); @@ -501,7 +550,7 @@ int32_t metaGetCachedTableUidList(SMeta* pMeta, tb_uid_t suid, const uint8_t* pK return TSDB_CODE_SUCCESS; } -static void freePayload(const void* key, size_t keyLen, void* value) { +static void freeUidCachePayload(const void* key, size_t keyLen, void* value) { if (value == NULL) { return; } @@ -512,10 +561,11 @@ static void freePayload(const void* key, size_t keyLen, void* value) { return; } - SHashObj* pHashObj = (SHashObj*)p[0]; + SHashObj* pHashObj = (SHashObj*)p[0]; + STagFilterResEntry** pEntry = taosHashGet(pHashObj, &p[1], sizeof(uint64_t)); - { + if (pEntry != NULL && (*pEntry) != NULL) { int64_t st = taosGetTimestampUs(); SListIter iter = {0}; @@ -528,9 +578,9 @@ static void freePayload(const void* key, size_t keyLen, void* value) { void* tmp = tdListPopNode(&((*pEntry)->list), pNode); taosMemoryFree(tmp); - int64_t et = taosGetTimestampUs(); - metaInfo("clear items in cache, remain cached item:%d, elapsed time:%.2fms", listNEles(&((*pEntry)->list)), - (et - st) / 1000.0); + double el = (taosGetTimestampUs() - st) / 1000.0; + metaInfo("clear items in meta-cache, remain cached item:%d, elapsed time:%.2fms", listNEles(&((*pEntry)->list)), + el); break; } } @@ -555,10 +605,13 @@ static int32_t addNewEntry(SHashObj* pTableEntry, const void* pKey, int32_t keyL // check both the payload size and selectivity ratio int32_t metaUidFilterCachePut(SMeta* pMeta, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload, int32_t payloadLen, double selectivityRatio) { + int32_t code = 0; + int32_t vgId = TD_VID(pMeta->pVnode); + if (selectivityRatio > tsSelectivityRatio) { metaDebug("vgId:%d, suid:%" PRIu64 " failed to add to uid list cache, due to selectivity ratio %.2f less than threshold %.2f", - TD_VID(pMeta->pVnode), suid, selectivityRatio, tsSelectivityRatio); + vgId, suid, selectivityRatio, tsSelectivityRatio); taosMemoryFree(pPayload); return TSDB_CODE_SUCCESS; } @@ -566,7 +619,7 @@ int32_t metaUidFilterCachePut(SMeta* pMeta, uint64_t suid, const void* pKey, int if (payloadLen > tsTagFilterResCacheSize) { metaDebug("vgId:%d, suid:%" PRIu64 " failed to add to uid list cache, due to payload length %d greater than threshold %d", - TD_VID(pMeta->pVnode), suid, payloadLen, tsTagFilterResCacheSize); + vgId, suid, payloadLen, tsTagFilterResCacheSize); taosMemoryFree(pPayload); return TSDB_CODE_SUCCESS; } @@ -575,26 +628,17 @@ int32_t metaUidFilterCachePut(SMeta* pMeta, uint64_t suid, const void* pKey, int SHashObj* pTableEntry = pMeta->pCache->sTagFilterResCache.pTableEntry; TdThreadMutex* pLock = &pMeta->pCache->sTagFilterResCache.lock; - // the format of key: - // hash table address(8bytes) + suid(8bytes) + MD5 digest(16bytes) - - uint64_t buf[4] = {0}; - buf[0] = (uint64_t) pTableEntry; - buf[1] = suid; - memcpy(&buf[2], pKey, keyLen); - ASSERT(keyLen == 16); + uint64_t key[4] = {0}; + initCacheKey(key, pTableEntry, suid, pKey, keyLen); - int32_t code = 0; taosThreadMutexLock(pLock); - STagFilterResEntry** pEntry = taosHashGet(pTableEntry, &suid, sizeof(uint64_t)); if (pEntry == NULL) { code = addNewEntry(pTableEntry, pKey, keyLen, suid); if (code != TSDB_CODE_SUCCESS) { goto _end; } - } else { - // check if it exists or not + } else { // check if it exists or not size_t size = listNEles(&(*pEntry)->list); if (size == 0) { tdListAppend(&(*pEntry)->list, pKey); @@ -612,12 +656,11 @@ int32_t metaUidFilterCachePut(SMeta* pMeta, uint64_t suid, const void* pKey, int } // add to cache. - taosLRUCacheInsert(pCache, buf, sizeof(uint64_t)*2 + keyLen, pPayload, payloadLen, freePayload, NULL, + taosLRUCacheInsert(pCache, key, TAG_FILTER_RES_KEY_LEN, pPayload, payloadLen, freeUidCachePayload, NULL, TAOS_LRU_PRIORITY_LOW); - _end: +_end: taosThreadMutexUnlock(pLock); - - metaDebug("vgId:%d, suid:%" PRIu64 " list cache added into cache, total:%d, tables:%d", TD_VID(pMeta->pVnode), suid, + metaDebug("vgId:%d, suid:%" PRIu64 " list cache added into cache, total:%d, tables:%d", vgId, suid, (int32_t)taosLRUCacheGetUsage(pCache), taosHashGetSize(pTableEntry)); return code; @@ -625,33 +668,213 @@ int32_t metaUidFilterCachePut(SMeta* pMeta, uint64_t suid, const void* pKey, int // remove the lru cache that are expired due to the tags value update, or creating, or dropping, of child tables int32_t metaUidCacheClear(SMeta* pMeta, uint64_t suid) { - int32_t keyLen = sizeof(uint64_t) * 3; - uint64_t p[4] = {0}; + uint64_t p[4] = {0}; + int32_t vgId = TD_VID(pMeta->pVnode); + SHashObj* pEntryHashMap = pMeta->pCache->sTagFilterResCache.pTableEntry; - p[0] = (uint64_t) pMeta->pCache->sTagFilterResCache.pTableEntry; - p[1] = suid; + uint64_t dummy[2] = {0}; + initCacheKey(p, pEntryHashMap, suid, (char*) &dummy[0], 16); TdThreadMutex* pLock = &pMeta->pCache->sTagFilterResCache.lock; - taosThreadMutexLock(pLock); - STagFilterResEntry** pEntry = taosHashGet(pMeta->pCache->sTagFilterResCache.pTableEntry, &suid, sizeof(uint64_t)); + + STagFilterResEntry** pEntry = taosHashGet(pEntryHashMap, &suid, sizeof(uint64_t)); if (pEntry == NULL || listNEles(&(*pEntry)->list) == 0) { taosThreadMutexUnlock(pLock); return TSDB_CODE_SUCCESS; } + (*pEntry)->hitTimes = 0; + SListIter iter = {0}; tdListInitIter(&(*pEntry)->list, &iter, TD_LIST_FORWARD); SListNode* pNode = NULL; while ((pNode = tdListNext(&iter)) != NULL) { - memcpy(&p[2], pNode->data, 16); - taosLRUCacheErase(pMeta->pCache->sTagFilterResCache.pUidResCache, p, keyLen); + setMD5DigestInKey(p, pNode->data, 2 * sizeof(uint64_t)); + taosLRUCacheErase(pMeta->pCache->sTagFilterResCache.pUidResCache, p, TAG_FILTER_RES_KEY_LEN); } - (*pEntry)->hitTimes = 0; tdListEmpty(&(*pEntry)->list); + taosThreadMutexUnlock(pLock); + + metaDebug("vgId:%d suid:%"PRId64" cached related tag filter uid list cleared", vgId, suid); + return TSDB_CODE_SUCCESS; +} + +int32_t metaGetCachedTbGroup(SMeta* pMeta, tb_uid_t suid, const uint8_t* pKey, int32_t keyLen, SArray** pList) { + int32_t vgId = TD_VID(pMeta->pVnode); + + // generate the composed key for LRU cache + SLRUCache* pCache = pMeta->pCache->STbGroupResCache.pResCache; + SHashObj* pTableMap = pMeta->pCache->STbGroupResCache.pTableEntry; + TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock; + + *pList = NULL; + uint64_t key[4]; + initCacheKey(key, pTableMap, suid, (const char*)pKey, keyLen); + + taosThreadMutexLock(pLock); + pMeta->pCache->STbGroupResCache.accTimes += 1; + + LRUHandle* pHandle = taosLRUCacheLookup(pCache, key, TAG_FILTER_RES_KEY_LEN); + if (pHandle == NULL) { + taosThreadMutexUnlock(pLock); + return TSDB_CODE_SUCCESS; + } + + STagFilterResEntry** pEntry = taosHashGet(pTableMap, &suid, sizeof(uint64_t)); + if (NULL == pEntry) { + metaDebug("suid %" PRIu64 " not in tb group cache", suid); + return TSDB_CODE_FAILED; + } + + *pList = taosArrayDup(taosLRUCacheValue(pCache, pHandle), NULL); + + (*pEntry)->hitTimes += 1; + + uint32_t acc = pMeta->pCache->STbGroupResCache.accTimes; + if ((*pEntry)->hitTimes % 5000 == 0 && (*pEntry)->hitTimes > 0) { + metaInfo("vgId:%d tb group cache hit:%d, total acc:%d, rate:%.2f", vgId, (*pEntry)->hitTimes, acc, ((double)(*pEntry)->hitTimes) / acc); + } + + taosLRUCacheRelease(pCache, pHandle, false); + + // unlock meta + taosThreadMutexUnlock(pLock); + return TSDB_CODE_SUCCESS; +} + + +static void freeTbGroupCachePayload(const void* key, size_t keyLen, void* value) { + if (value == NULL) { + return; + } + + const uint64_t* p = key; + if (keyLen != sizeof(int64_t) * 4) { + metaError("tb group key length is invalid, length:%d, expect:%d", (int32_t)keyLen, (int32_t)sizeof(uint64_t) * 2); + return; + } + + SHashObj* pHashObj = (SHashObj*)p[0]; + + STagFilterResEntry** pEntry = taosHashGet(pHashObj, &p[1], sizeof(uint64_t)); + + if (pEntry != NULL && (*pEntry) != NULL) { + int64_t st = taosGetTimestampUs(); + + SListIter iter = {0}; + tdListInitIter((SList*)&((*pEntry)->list), &iter, TD_LIST_FORWARD); + + SListNode* pNode = NULL; + while ((pNode = tdListNext(&iter)) != NULL) { + uint64_t* digest = (uint64_t*)pNode->data; + if (digest[0] == p[2] && digest[1] == p[3]) { + void* tmp = tdListPopNode(&((*pEntry)->list), pNode); + taosMemoryFree(tmp); + + double el = (taosGetTimestampUs() - st) / 1000.0; + metaDebug("clear one item in tb group cache, remain cached item:%d, elapsed time:%.2fms", listNEles(&((*pEntry)->list)), + el); + break; + } + } + } + + taosArrayDestroy((SArray*)value); +} + + +int32_t metaPutTbGroupToCache(SMeta* pMeta, uint64_t suid, const void* pKey, int32_t keyLen, void* pPayload, + int32_t payloadLen) { + int32_t code = 0; + int32_t vgId = TD_VID(pMeta->pVnode); + + if (payloadLen > tsTagFilterResCacheSize) { + metaDebug("vgId:%d, suid:%" PRIu64 + " ignore to add to tb group cache, due to payload length %d greater than threshold %d", + vgId, suid, payloadLen, tsTagFilterResCacheSize); + taosArrayDestroy((SArray*)pPayload); + return TSDB_CODE_SUCCESS; + } + + SLRUCache* pCache = pMeta->pCache->STbGroupResCache.pResCache; + SHashObj* pTableEntry = pMeta->pCache->STbGroupResCache.pTableEntry; + TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock; + + uint64_t key[4] = {0}; + initCacheKey(key, pTableEntry, suid, pKey, keyLen); + + taosThreadMutexLock(pLock); + STagFilterResEntry** pEntry = taosHashGet(pTableEntry, &suid, sizeof(uint64_t)); + if (pEntry == NULL) { + code = addNewEntry(pTableEntry, pKey, keyLen, suid); + if (code != TSDB_CODE_SUCCESS) { + goto _end; + } + } else { // check if it exists or not + size_t size = listNEles(&(*pEntry)->list); + if (size == 0) { + tdListAppend(&(*pEntry)->list, pKey); + } else { + SListNode* pNode = listHead(&(*pEntry)->list); + uint64_t* p = (uint64_t*)pNode->data; + if (p[1] == ((uint64_t*)pKey)[1] && p[0] == ((uint64_t*)pKey)[0]) { + // we have already found the existed items, no need to added to cache anymore. + taosThreadMutexUnlock(pLock); + return TSDB_CODE_SUCCESS; + } else { // not equal, append it + tdListAppend(&(*pEntry)->list, pKey); + } + } + } + + // add to cache. + taosLRUCacheInsert(pCache, key, TAG_FILTER_RES_KEY_LEN, pPayload, payloadLen, freeTbGroupCachePayload, NULL, + TAOS_LRU_PRIORITY_LOW); +_end: + taosThreadMutexUnlock(pLock); + metaDebug("vgId:%d, suid:%" PRIu64 " tb group added into cache, total:%d, tables:%d", vgId, suid, + (int32_t)taosLRUCacheGetUsage(pCache), taosHashGetSize(pTableEntry)); + + return code; +} + +// remove the lru cache that are expired due to the tags value update, or creating, or dropping, of child tables +int32_t metaTbGroupCacheClear(SMeta* pMeta, uint64_t suid) { + uint64_t p[4] = {0}; + int32_t vgId = TD_VID(pMeta->pVnode); + SHashObj* pEntryHashMap = pMeta->pCache->STbGroupResCache.pTableEntry; + uint64_t dummy[2] = {0}; + initCacheKey(p, pEntryHashMap, suid, (char*) &dummy[0], 16); + + TdThreadMutex* pLock = &pMeta->pCache->STbGroupResCache.lock; + taosThreadMutexLock(pLock); + + STagFilterResEntry** pEntry = taosHashGet(pEntryHashMap, &suid, sizeof(uint64_t)); + if (pEntry == NULL || listNEles(&(*pEntry)->list) == 0) { + taosThreadMutexUnlock(pLock); + return TSDB_CODE_SUCCESS; + } + + (*pEntry)->hitTimes = 0; + + SListIter iter = {0}; + tdListInitIter(&(*pEntry)->list, &iter, TD_LIST_FORWARD); + + SListNode* pNode = NULL; + while ((pNode = tdListNext(&iter)) != NULL) { + setMD5DigestInKey(p, pNode->data, 2 * sizeof(uint64_t)); + taosLRUCacheErase(pMeta->pCache->STbGroupResCache.pResCache, p, TAG_FILTER_RES_KEY_LEN); + } + + tdListEmpty(&(*pEntry)->list); taosThreadMutexUnlock(pLock); + + metaDebug("vgId:%d suid:%"PRId64" cached related tb group cleared", vgId, suid); return TSDB_CODE_SUCCESS; } + + diff --git a/source/dnode/vnode/src/meta/metaEntry.c b/source/dnode/vnode/src/meta/metaEntry.c index 60df66fc01e745642bcf74dcfe9b10d751edaa3f..e50931ac0618252eea58afc0d1a734d252a05d1e 100644 --- a/source/dnode/vnode/src/meta/metaEntry.c +++ b/source/dnode/vnode/src/meta/metaEntry.c @@ -51,7 +51,9 @@ int metaEncodeEntry(SEncoder *pCoder, const SMetaEntry *pME) { } else if (pME->type == TSDB_TSMA_TABLE) { if (tEncodeTSma(pCoder, pME->smaEntry.tsma) < 0) return -1; } else { - ASSERT(0); + metaError("meta/entry: invalide table type: %" PRId8 " encode failed.", pME->type); + + return -1; } tEndEncode(pCoder); diff --git a/source/dnode/vnode/src/meta/metaOpen.c b/source/dnode/vnode/src/meta/metaOpen.c index 550d7b587cd94c132cad65d6d84540395b0c01e9..1d0b11e26a58d047216196bf3fed7b8f13807922 100644 --- a/source/dnode/vnode/src/meta/metaOpen.c +++ b/source/dnode/vnode/src/meta/metaOpen.c @@ -361,7 +361,10 @@ static int tagIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kL return -1; } - ASSERT(pTagIdxKey1->type == pTagIdxKey2->type); + if (pTagIdxKey1->type != pTagIdxKey2->type) { + metaError("meta/open: incorrect tag idx type."); + return TSDB_CODE_FAILED; + } // check NULL, NULL is always the smallest if (pTagIdxKey1->isNull && !pTagIdxKey2->isNull) { diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c index 20f789b348f9b731f050c54ae89cb9d1a422b47f..d464f64de327969f4c302498fe2f6370676845d6 100644 --- a/source/dnode/vnode/src/meta/metaQuery.c +++ b/source/dnode/vnode/src/meta/metaQuery.c @@ -14,12 +14,14 @@ */ #include "meta.h" +#include "osMemory.h" +#include "tencode.h" void metaReaderInit(SMetaReader *pReader, SMeta *pMeta, int32_t flags) { memset(pReader, 0, sizeof(*pReader)); pReader->flags = flags; pReader->pMeta = pMeta; - if (!(flags & META_READER_NOLOCK)) { + if (pReader->pMeta && !(flags & META_READER_NOLOCK)) { metaRLock(pMeta); } } @@ -152,7 +154,7 @@ bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid) { } int metaGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid) { - SMeta *pMeta = pReader->pMeta; + SMeta *pMeta = pReader->pMeta; int64_t version1; // query uid.idx @@ -239,7 +241,6 @@ int metaGetTableSzNameByUid(void *meta, uint64_t uid, char *tbName) { return 0; } - int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid) { int code = 0; SMetaReader mr = {0}; @@ -311,7 +312,7 @@ void metaCloseTbCursor(SMTbCursor *pTbCur) { } } -int32_t metaTbCursorNext(SMTbCursor *pTbCur) { +int32_t metaTbCursorNext(SMTbCursor *pTbCur, ETableType jumpTableType) { int ret; void *pBuf; STbCfg tbCfg; @@ -325,7 +326,7 @@ int32_t metaTbCursorNext(SMTbCursor *pTbCur) { tDecoderClear(&pTbCur->mr.coder); metaGetTableEntryByVersion(&pTbCur->mr, ((SUidIdxVal *)pTbCur->pVal)[0].version, *(tb_uid_t *)pTbCur->pKey); - if (pTbCur->mr.me.type == TSDB_SUPER_TABLE) { + if (pTbCur->mr.me.type == jumpTableType) { continue; } @@ -335,7 +336,7 @@ int32_t metaTbCursorNext(SMTbCursor *pTbCur) { return 0; } -int32_t metaTbCursorPrev(SMTbCursor *pTbCur) { +int32_t metaTbCursorPrev(SMTbCursor *pTbCur, ETableType jumpTableType) { int ret; void *pBuf; STbCfg tbCfg; @@ -349,7 +350,7 @@ int32_t metaTbCursorPrev(SMTbCursor *pTbCur) { tDecoderClear(&pTbCur->mr.coder); metaGetTableEntryByVersion(&pTbCur->mr, ((SUidIdxVal *)pTbCur->pVal)[0].version, *(tb_uid_t *)pTbCur->pKey); - if (pTbCur->mr.me.type == TSDB_SUPER_TABLE) { + if (pTbCur->mr.me.type == jumpTableType) { continue; } @@ -359,7 +360,6 @@ int32_t metaTbCursorPrev(SMTbCursor *pTbCur) { return 0; } - SSchemaWrapper *metaGetTableSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, int lock) { void *pData = NULL; int nData = 0; @@ -637,23 +637,13 @@ tb_uid_t metaStbCursorNext(SMStbCursor *pStbCur) { } STSchema *metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, int lock) { - // SMetaReader mr = {0}; STSchema *pTSchema = NULL; SSchemaWrapper *pSW = NULL; - STSchemaBuilder sb = {0}; - SSchema *pSchema; pSW = metaGetTableSchema(pMeta, uid, sver, lock); if (!pSW) return NULL; - tdInitTSchemaBuilder(&sb, pSW->version); - for (int i = 0; i < pSW->nCols; i++) { - pSchema = pSW->pSchema + i; - tdAddColToSchema(&sb, pSchema->type, pSchema->flags, pSchema->colId, pSchema->bytes); - } - pTSchema = tdGetSchemaFromBuilder(&sb); - - tdDestroyTSchemaBuilder(&sb); + pTSchema = tBuildTSchema(pSW->pSchema, pSW->nCols, pSW->version); taosMemoryFree(pSW->pSchema); taosMemoryFree(pSW); @@ -687,7 +677,13 @@ int32_t metaGetTbTSchemaEx(SMeta *pMeta, tb_uid_t suid, tb_uid_t uid, int32_t sv goto _exit; } - ASSERT(c); + if (c == 0) { + metaULock(pMeta); + tdbTbcClose(pSkmDbC); + code = TSDB_CODE_FAILED; + metaError("meta/query: incorrect c: %" PRId32 ".", c); + goto _exit; + } if (c < 0) { tdbTbcMoveToPrev(pSkmDbC); @@ -711,7 +707,10 @@ int32_t metaGetTbTSchemaEx(SMeta *pMeta, tb_uid_t suid, tb_uid_t uid, int32_t sv } } - ASSERT(sver > 0); + if (ASSERTS(sver > 0, "failed to get table schema version: %d", sver)) { + code = TSDB_CODE_NOT_FOUND; + goto _exit; + } skmDbKey.uid = suid ? suid : uid; skmDbKey.sver = sver; @@ -734,21 +733,11 @@ int32_t metaGetTbTSchemaEx(SMeta *pMeta, tb_uid_t suid, tb_uid_t uid, int32_t sv tdbFree(pData); // convert - STSchemaBuilder sb = {0}; - - tdInitTSchemaBuilder(&sb, pSchemaWrapper->version); - for (int i = 0; i < pSchemaWrapper->nCols; i++) { - SSchema *pSchema = pSchemaWrapper->pSchema + i; - tdAddColToSchema(&sb, pSchema->type, pSchema->flags, pSchema->colId, pSchema->bytes); - } - - STSchema *pTSchema = tdGetSchemaFromBuilder(&sb); + STSchema *pTSchema = tBuildTSchema(pSchemaWrapper->pSchema, pSchemaWrapper->nCols, pSchemaWrapper->version); if (pTSchema == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; } - tdDestroyTSchemaBuilder(&sb); - *ppTSchema = pTSchema; taosMemoryFree(pSchemaWrapper->pSchema); @@ -781,9 +770,7 @@ int64_t metaGetTimeSeriesNum(SMeta *pMeta) { return pMeta->pVnode->config.vndStats.numOfTimeSeries + pMeta->pVnode->config.vndStats.numOfNTimeSeries; } -int64_t metaGetNtbNum(SMeta *pMeta) { - return pMeta->pVnode->config.vndStats.numOfNTables; -} +int64_t metaGetNtbNum(SMeta *pMeta) { return pMeta->pVnode->config.vndStats.numOfNTables; } typedef struct { SMeta *pMeta; @@ -1122,26 +1109,30 @@ int32_t metaFilterCreateTime(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) } int32_t valid = 0; - while (1) { + int32_t count = 0; + + static const int8_t TRY_ERROR_LIMIT = 1; + do { void *entryKey = NULL; int32_t nEntryKey = -1; valid = tdbTbcGet(pCursor->pCur, (const void **)&entryKey, &nEntryKey, NULL, NULL); if (valid < 0) break; SCtimeIdxKey *p = entryKey; + if (count > TRY_ERROR_LIMIT) break; int32_t cmp = (*param->filterFunc)((void *)&p->ctime, (void *)&pCtimeKey->ctime, param->type); - if (cmp == 0) taosArrayPush(pUids, &p->uid); - - if (param->reverse == false) { - if (cmp == -1) break; - } else if (param->reverse) { - if (cmp == 1) break; + if (cmp == 0) + taosArrayPush(pUids, &p->uid); + else { + if (param->equal == true) { + if (count > TRY_ERROR_LIMIT) break; + count++; + } } - valid = param->reverse ? tdbTbcMoveToPrev(pCursor->pCur) : tdbTbcMoveToNext(pCursor->pCur); if (valid < 0) break; - } + } while (1); END: if (pCursor->pMeta) metaULock(pCursor->pMeta); @@ -1176,29 +1167,34 @@ int32_t metaFilterTableName(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) { if (tdbTbcMoveTo(pCursor->pCur, pName, strlen(pName) + 1, &cmp) < 0) { goto END; } - bool first = true; int32_t valid = 0; - while (1) { + int32_t count = 0; + + int32_t TRY_ERROR_LIMIT = 1; + do { void *pEntryKey = NULL, *pEntryVal = NULL; int32_t nEntryKey = -1, nEntryVal = 0; valid = tdbTbcGet(pCursor->pCur, (const void **)pEntryKey, &nEntryKey, (const void **)&pEntryVal, &nEntryVal); if (valid < 0) break; + if (count > TRY_ERROR_LIMIT) break; + char *pTableKey = (char *)pEntryKey; cmp = (*param->filterFunc)(pTableKey, pName, pCursor->type); if (cmp == 0) { tb_uid_t tuid = *(tb_uid_t *)pEntryVal; taosArrayPush(pUids, &tuid); - } else if (cmp == 1) { - // next } else { - break; + if (param->equal == true) { + if (count > TRY_ERROR_LIMIT) break; + count++; + } } valid = param->reverse ? tdbTbcMoveToPrev(pCursor->pCur) : tdbTbcMoveToNext(pCursor->pCur); if (valid < 0) { break; } - } + } while (1); END: if (pCursor->pMeta) metaULock(pCursor->pMeta); @@ -1240,9 +1236,14 @@ END: return 0; } int32_t metaFilterTableIds(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) { - int32_t ret = 0; - char *buf = NULL; - + SMetaEntry oStbEntry = {0}; + int32_t ret = -1; + char *buf = NULL; + void *pData = NULL; + int nData = 0; + + SDecoder dc = {0}; + STbDbKey tbDbKey = {0}; STagIdxKey *pKey = NULL; int32_t nKey = 0; @@ -1254,8 +1255,34 @@ int32_t metaFilterTableIds(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) { pCursor->type = param->type; metaRLock(pMeta); - ret = tdbTbcOpen(pMeta->pCtimeIdx, &pCursor->pCur, NULL); - if (ret < 0) { + + if (tdbTbGet(pMeta->pUidIdx, ¶m->suid, sizeof(tb_uid_t), &pData, &nData) != 0) { + goto END; + } + tbDbKey.uid = param->suid; + tbDbKey.version = ((SUidIdxVal *)pData)[0].version; + tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pData, &nData); + + tDecoderInit(&dc, pData, nData); + ret = metaDecodeEntry(&dc, &oStbEntry); + + if (oStbEntry.stbEntry.schemaTag.pSchema == NULL || oStbEntry.stbEntry.schemaTag.pSchema == NULL) { + ret = -1; + goto END; + } + ret = -1; + for (int i = 0; i < oStbEntry.stbEntry.schemaTag.nCols; i++) { + SSchema *schema = oStbEntry.stbEntry.schemaTag.pSchema + i; + if (schema->colId == param->cid && param->type == schema->type && (IS_IDX_ON(schema) || i == 0)) { + ret = 0; + } + } + if (ret != 0) { + goto END; + } + + ret = tdbTbcOpen(pMeta->pTagIdx, &pCursor->pCur, NULL); + if (ret != 0) { goto END; } @@ -1276,6 +1303,7 @@ int32_t metaFilterTableIds(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) { maxSize = 4 * nTagData + 1; buf = taosMemoryCalloc(1, maxSize); if (false == taosMbsToUcs4(tagData, nTagData, (TdUcs4 *)buf, maxSize, &maxSize)) { + ret = -1; goto END; } @@ -1293,37 +1321,50 @@ int32_t metaFilterTableIds(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) { if (ret != 0) { goto END; } + int cmp = 0; - if (tdbTbcMoveTo(pCursor->pCur, pKey, nKey, &cmp) < 0) { + ret = tdbTbcMoveTo(pCursor->pCur, pKey, nKey, &cmp); + if (ret != 0) { goto END; } - bool first = true; + int count = 0; int32_t valid = 0; - while (1) { + bool found = false; + + static const int8_t TRY_ERROR_LIMIT = 1; + + /// src: [[suid, cid1, type1]....[suid, cid2, type2]....[suid, cid3, type3]...] + /// target: [suid, cid2, type2] + int diffCidCount = 0; + do { void *entryKey = NULL, *entryVal = NULL; int32_t nEntryKey, nEntryVal; valid = tdbTbcGet(pCursor->pCur, (const void **)&entryKey, &nEntryKey, (const void **)&entryVal, &nEntryVal); if (valid < 0) { - tdbFree(entryVal); break; } + if (count > TRY_ERROR_LIMIT) { + break; + } + STagIdxKey *p = entryKey; if (p == NULL) break; - if (p->type != pCursor->type) { - if (first) { - valid = param->reverse ? tdbTbcMoveToPrev(pCursor->pCur) : tdbTbcMoveToNext(pCursor->pCur); - if (valid < 0) break; - continue; - } else { + + if (p->type != pCursor->type || p->suid != pCursor->suid || p->cid != pCursor->cid) { + if (found == true) break; // + if (diffCidCount > TRY_ERROR_LIMIT) break; + diffCidCount++; + count++; + valid = param->reverse ? tdbTbcMoveToPrev(pCursor->pCur) : tdbTbcMoveToNext(pCursor->pCur); + if (valid < 0) { break; + } else { + continue; } } - if (p->suid != pKey->suid) { - break; - } - first = false; + int32_t cmp = (*param->filterFunc)(p->data, pKey->data, pKey->type); if (cmp == 0) { // match @@ -1334,21 +1375,26 @@ int32_t metaFilterTableIds(SMeta *pMeta, SMetaFltParam *param, SArray *pUids) { tuid = *(tb_uid_t *)(p->data + tDataTypes[pCursor->type].bytes); } taosArrayPush(pUids, &tuid); - } else if (cmp == 1) { - // not match but should continue to iter + found = true; } else { - // not match and no more result - break; + if (param->equal == true) { + if (count > TRY_ERROR_LIMIT) break; + count++; + } } valid = param->reverse ? tdbTbcMoveToPrev(pCursor->pCur) : tdbTbcMoveToNext(pCursor->pCur); if (valid < 0) { break; } - } + } while (1); END: if (pCursor->pMeta) metaULock(pCursor->pMeta); if (pCursor->pCur) tdbTbcClose(pCursor->pCur); + if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf); + tDecoderClear(&dc); + tdbFree(pData); + taosMemoryFree(buf); taosMemoryFree(pKey); @@ -1387,19 +1433,19 @@ int32_t metaGetTableTagsByUids(SMeta *pMeta, int64_t suid, SArray *uidList) { isLock = true; } -// if (taosHashGet(tags, &p->uid, sizeof(tb_uid_t)) == NULL) { - void *val = NULL; - int32_t len = 0; - if (metaGetTableTagByUid(pMeta, suid, p->uid, &val, &len, false) == 0) { - p->pTagVal = taosMemoryMalloc(len); - memcpy(p->pTagVal, val, len); - tdbFree(val); - } else { - metaError("vgId:%d, failed to table tags, suid: %" PRId64 ", uid: %" PRId64 "", TD_VID(pMeta->pVnode), suid, - p->uid); - } + // if (taosHashGet(tags, &p->uid, sizeof(tb_uid_t)) == NULL) { + void *val = NULL; + int32_t len = 0; + if (metaGetTableTagByUid(pMeta, suid, p->uid, &val, &len, false) == 0) { + p->pTagVal = taosMemoryMalloc(len); + memcpy(p->pTagVal, val, len); + tdbFree(val); + } else { + metaError("vgId:%d, failed to table tags, suid: %" PRId64 ", uid: %" PRId64 "", TD_VID(pMeta->pVnode), suid, + p->uid); } -// } + } + // } if (isLock) metaULock(pMeta); return 0; } @@ -1413,7 +1459,8 @@ int32_t metaGetTableTags(SMeta *pMeta, uint64_t suid, SArray *pUidTagInfo) { SHashObj *pSepecifiedUidMap = NULL; size_t numOfElems = taosArrayGetSize(pUidTagInfo); if (numOfElems > 0) { - pSepecifiedUidMap = taosHashInit(numOfElems / 0.7, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); + pSepecifiedUidMap = + taosHashInit(numOfElems / 0.7, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); for (int i = 0; i < numOfElems; i++) { STUidTagInfo *pTagInfo = taosArrayGet(pUidTagInfo, i); taosHashPut(pSepecifiedUidMap, &pTagInfo->uid, sizeof(uint64_t), &i, sizeof(int32_t)); diff --git a/source/dnode/vnode/src/meta/metaSnapshot.c b/source/dnode/vnode/src/meta/metaSnapshot.c index 8b023b7bc50292dbdd90b52fbeb83eab5d625429..707dd66e3011dd98cd8449f20bf748a2b6f2ff7c 100644 --- a/source/dnode/vnode/src/meta/metaSnapshot.c +++ b/source/dnode/vnode/src/meta/metaSnapshot.c @@ -100,7 +100,10 @@ int32_t metaSnapRead(SMetaSnapReader* pReader, uint8_t** ppData) { break; } - ASSERT(pData && nData); + if (!pData || !nData) { + metaError("meta/snap: invalide nData: %" PRId32 " meta snap read failed.", nData); + goto _exit; + } *ppData = taosMemoryMalloc(sizeof(SSnapDataHdr) + nData); if (*ppData == NULL) { @@ -184,23 +187,24 @@ _err: int32_t metaSnapWrite(SMetaSnapWriter* pWriter, uint8_t* pData, uint32_t nData) { int32_t code = 0; + int32_t line = 0; SMeta* pMeta = pWriter->pMeta; SMetaEntry metaEntry = {0}; SDecoder* pDecoder = &(SDecoder){0}; tDecoderInit(pDecoder, pData + sizeof(SSnapDataHdr), nData - sizeof(SSnapDataHdr)); code = metaDecodeEntry(pDecoder, &metaEntry); - if (code) goto _err; + VND_CHECK_CODE(code, line, _err); code = metaHandleEntry(pMeta, &metaEntry); - if (code) goto _err; + VND_CHECK_CODE(code, line, _err); tDecoderClear(pDecoder); return code; _err: tDecoderClear(pDecoder); - metaError("vgId:%d, vnode snapshot meta write failed since %s", TD_VID(pMeta->pVnode), tstrerror(code)); + metaError("vgId:%d, vnode snapshot meta write failed since %s at line:%d", TD_VID(pMeta->pVnode), terrstr(), line); return code; } @@ -213,8 +217,8 @@ typedef struct STableInfoForChildTable { static void destroySTableInfoForChildTable(void* data) { STableInfoForChildTable* pData = (STableInfoForChildTable*)data; taosMemoryFree(pData->tableName); - tDeleteSSchemaWrapper(pData->schemaRow); - tDeleteSSchemaWrapper(pData->tagRow); + tDeleteSchemaWrapper(pData->schemaRow); + tDeleteSchemaWrapper(pData->tagRow); } static void MoveToSnapShotVersion(SSnapContext* ctx) { @@ -249,7 +253,7 @@ static void saveSuperTableInfoForChildTable(SMetaEntry* me, SHashObj* suidInfo) return; } STableInfoForChildTable dataTmp = {0}; - dataTmp.tableName = strdup(me->name); + dataTmp.tableName = taosStrdup(me->name); dataTmp.schemaRow = tCloneSSchemaWrapper(&me->stbEntry.schemaRow); dataTmp.tagRow = tCloneSSchemaWrapper(&me->stbEntry.schemaTag); @@ -265,7 +269,7 @@ int32_t buildSnapContext(SMeta* pMeta, int64_t snapVersion, int64_t suid, int8_t ctx->snapVersion = snapVersion; ctx->suid = suid; ctx->subType = subType; - ctx->queryMetaOrData = withMeta; + ctx->queryMeta = withMeta; ctx->withMeta = withMeta; ctx->idVersion = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK); if (ctx->idVersion == NULL) { @@ -358,7 +362,11 @@ int32_t buildSnapContext(SMeta* pMeta, int64_t snapVersion, int64_t suid, int8_t for (int i = 0; i < taosArrayGetSize(ctx->idList); i++) { int64_t* uid = taosArrayGet(ctx->idList, i); SIdInfo* idData = (SIdInfo*)taosHashGet(ctx->idVersion, uid, sizeof(int64_t)); - ASSERT(idData); + if (!idData) { + metaError("meta/snap: null idData"); + return TSDB_CODE_FAILED; + } + idData->index = i; metaDebug("tmqsnap init idVersion uid:%" PRIi64 " version:%" PRIi64 " index:%d", *uid, idData->version, idData->index); @@ -468,14 +476,17 @@ int32_t getMetafromSnapShot(SSnapContext* ctx, void** pBuf, int32_t* contLen, in if (ctx->index >= taosArrayGetSize(ctx->idList)) { metaDebug("tmqsnap get meta end"); ctx->index = 0; - ctx->queryMetaOrData = false; // change to get data + ctx->queryMeta = false; // change to get data return 0; } int64_t* uidTmp = taosArrayGet(ctx->idList, ctx->index); ctx->index++; SIdInfo* idInfo = (SIdInfo*)taosHashGet(ctx->idVersion, uidTmp, sizeof(tb_uid_t)); - ASSERT(idInfo); + if (!idInfo) { + metaError("meta/snap: null idInfo"); + return TSDB_CODE_FAILED; + } *uid = *uidTmp; ret = MoveToPosition(ctx, idInfo->version, *uidTmp); @@ -509,7 +520,11 @@ int32_t getMetafromSnapShot(SSnapContext* ctx, void** pBuf, int32_t* contLen, in (ctx->subType == TOPIC_SUB_TYPE__TABLE && me.type == TSDB_CHILD_TABLE && me.ctbEntry.suid == ctx->suid)) { STableInfoForChildTable* data = (STableInfoForChildTable*)taosHashGet(ctx->suidInfo, &me.ctbEntry.suid, sizeof(tb_uid_t)); - ASSERT(data); + if (!data) { + metaError("meta/snap: null data"); + return TSDB_CODE_FAILED; + } + SVCreateTbReq req = {0}; req.type = TSDB_CHILD_TABLE; @@ -530,7 +545,8 @@ int32_t getMetafromSnapShot(SSnapContext* ctx, void** pBuf, int32_t* contLen, in } else { SArray* pTagVals = NULL; if (tTagToValArray((const STag*)p, &pTagVals) != 0) { - ASSERT(0); + metaError("meta/snap: tag to val array failed."); + return TSDB_CODE_FAILED; } int16_t nCols = taosArrayGetSize(pTagVals); for (int j = 0; j < nCols; ++j) { @@ -574,7 +590,8 @@ int32_t getMetafromSnapShot(SSnapContext* ctx, void** pBuf, int32_t* contLen, in ret = buildNormalChildTableInfo(&req, pBuf, contLen); *type = TDMT_VND_CREATE_TABLE; } else { - ASSERT(0); + metaError("meta/snap: invalid topic sub type: %" PRId8 " get meta from snap failed.", ctx->subType); + ret = -1; } tDecoderClear(&dc); @@ -595,7 +612,10 @@ SMetaTableInfo getUidfromSnapShot(SSnapContext* ctx) { int64_t* uidTmp = taosArrayGet(ctx->idList, ctx->index); ctx->index++; SIdInfo* idInfo = (SIdInfo*)taosHashGet(ctx->idVersion, uidTmp, sizeof(tb_uid_t)); - ASSERT(idInfo); + if (!idInfo) { + metaError("meta/snap: null idInfo"); + return result; + } int32_t ret = MoveToPosition(ctx, idInfo->version, *uidTmp); if (ret != 0) { diff --git a/source/dnode/vnode/src/meta/metaTable.c b/source/dnode/vnode/src/meta/metaTable.c index 7406f51d4ba06643af9aa8ce563645c7f8636fb2..0164a82c69cfd7be9dd7a20705ba6780d5123c38 100644 --- a/source/dnode/vnode/src/meta/metaTable.c +++ b/source/dnode/vnode/src/meta/metaTable.c @@ -46,7 +46,7 @@ static void metaGetEntryInfo(const SMetaEntry *pEntry, SMetaInfo *pInfo) { pInfo->suid = 0; pInfo->skmVer = pEntry->ntbEntry.schemaRow.version; } else { - ASSERT(0); + metaError("meta/table: invalide table type: %" PRId8 " get entry info failed.", pEntry->type); } } @@ -342,10 +342,23 @@ int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) { tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL); ret = tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = pReq->suid, .version = oversion}), sizeof(STbDbKey), &c); - ASSERT(ret == 0 && c == 0); + if (!(ret == 0 && c == 0)) { + tdbTbcClose(pUidIdxc); + tdbTbcClose(pTbDbc); + + terrno = TSDB_CODE_TDB_STB_NOT_EXIST; + metaError("meta/table: invalide ret: %" PRId32 " or c: %" PRId32 "alter stb failed.", ret, c); + return -1; + } ret = tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData); - ASSERT(ret == 0); + if (ret < 0) { + tdbTbcClose(pUidIdxc); + tdbTbcClose(pTbDbc); + + terrno = TSDB_CODE_TDB_STB_NOT_EXIST; + return -1; + } oStbEntry.pBuf = taosMemoryMalloc(nData); memcpy(oStbEntry.pBuf, pData, nData); @@ -381,6 +394,301 @@ int metaAlterSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) { tdbTbcClose(pUidIdxc); return 0; } +int metaAddIndexToSTable(SMeta *pMeta, int64_t version, SVCreateStbReq *pReq) { + SMetaEntry oStbEntry = {0}; + SMetaEntry nStbEntry = {0}; + + STbDbKey tbDbKey = {0}; + + TBC *pUidIdxc = NULL; + TBC *pTbDbc = NULL; + void *pData = NULL; + int nData = 0; + int64_t oversion; + SDecoder dc = {0}; + int32_t ret; + int32_t c = -2; + tb_uid_t suid = pReq->suid; + + // get super table + if (tdbTbGet(pMeta->pUidIdx, &suid, sizeof(tb_uid_t), &pData, &nData) != 0) { + ret = -1; + goto _err; + } + + tbDbKey.uid = suid; + tbDbKey.version = ((SUidIdxVal *)pData)[0].version; + tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pData, &nData); + + tDecoderInit(&dc, pData, nData); + ret = metaDecodeEntry(&dc, &oStbEntry); + if (ret < 0) { + goto _err; + } + + if (oStbEntry.stbEntry.schemaTag.pSchema == NULL || oStbEntry.stbEntry.schemaTag.pSchema == NULL) { + goto _err; + } + + if (oStbEntry.stbEntry.schemaTag.version == pReq->schemaTag.version) { + goto _err; + } + + if (oStbEntry.stbEntry.schemaTag.nCols != pReq->schemaTag.nCols) { + goto _err; + } + + int diffIdx = -1; + for (int i = 0; i < pReq->schemaTag.nCols; i++) { + SSchema *pNew = pReq->schemaTag.pSchema + i; + SSchema *pOld = oStbEntry.stbEntry.schemaTag.pSchema + i; + if (pNew->type != pOld->type || pNew->colId != pOld->colId || pNew->bytes != pOld->bytes || + strncmp(pOld->name, pNew->name, sizeof(pNew->name))) { + goto _err; + } + if (IS_IDX_ON(pNew) && !IS_IDX_ON(pOld)) { + if (diffIdx != -1) goto _err; + diffIdx = i; + } + } + + if (diffIdx == -1 && diffIdx == 0) { + goto _err; + } + + // Get target schema info + SSchemaWrapper *pTagSchema = &pReq->schemaTag; + if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) { + terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS; + goto _err; + } + SSchema *pCol = pTagSchema->pSchema + diffIdx; + + /* + * iterator all pTdDbc by uid and version + */ + TBC *pCtbIdxc = NULL; + tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL); + int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c); + if (rc < 0) { + tdbTbcClose(pCtbIdxc); + goto _err; + } + for (;;) { + void *pKey = NULL, *pVal = NULL; + int nKey = 0, nVal = 0; + rc = tdbTbcNext(pCtbIdxc, &pKey, &nKey, &pVal, &nVal); + if (rc < 0) { + tdbFree(pKey); + tdbFree(pVal); + tdbTbcClose(pCtbIdxc); + pCtbIdxc = NULL; + break; + } + if (((SCtbIdxKey *)pKey)->suid != suid) { + tdbFree(pKey); + tdbFree(pVal); + continue; + } + STagIdxKey *pTagIdxKey = NULL; + int32_t nTagIdxKey; + + const void *pTagData = NULL; + int32_t nTagData = 0; + + SCtbIdxKey *table = (SCtbIdxKey *)pKey; + STagVal tagVal = {.cid = pCol->colId}; + tTagGet((const STag *)pVal, &tagVal); + if (IS_VAR_DATA_TYPE(pCol->type)) { + pTagData = tagVal.pData; + nTagData = (int32_t)tagVal.nData; + } else { + pTagData = &(tagVal.i64); + nTagData = tDataTypes[pCol->type].bytes; + } + rc = metaCreateTagIdxKey(suid, pCol->colId, pTagData, nTagData, pCol->type, table->uid, &pTagIdxKey, &nTagIdxKey); + tdbFree(pKey); + tdbFree(pVal); + if (rc < 0) { + metaDestroyTagIdxKey(pTagIdxKey); + tdbTbcClose(pCtbIdxc); + goto _err; + } + + metaWLock(pMeta); + tdbTbUpsert(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, NULL, 0, pMeta->txn); + metaULock(pMeta); + metaDestroyTagIdxKey(pTagIdxKey); + } + + nStbEntry.version = version; + nStbEntry.type = TSDB_SUPER_TABLE; + nStbEntry.uid = pReq->suid; + nStbEntry.name = pReq->name; + nStbEntry.stbEntry.schemaRow = pReq->schemaRow; + nStbEntry.stbEntry.schemaTag = pReq->schemaTag; + + metaWLock(pMeta); + // update table.db + metaSaveToTbDb(pMeta, &nStbEntry); + // update uid index + metaUpdateUidIdx(pMeta, &nStbEntry); + metaULock(pMeta); + + if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf); + tDecoderClear(&dc); + tdbFree(pData); + + tdbTbcClose(pCtbIdxc); + return TSDB_CODE_SUCCESS; +_err: + if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf); + tDecoderClear(&dc); + tdbFree(pData); + + return TSDB_CODE_VND_COL_ALREADY_EXISTS; +} +int metaDropIndexFromSTable(SMeta *pMeta, int64_t version, SDropIndexReq *pReq) { + SMetaEntry oStbEntry = {0}; + SMetaEntry nStbEntry = {0}; + + STbDbKey tbDbKey = {0}; + TBC *pUidIdxc = NULL; + TBC *pTbDbc = NULL; + int ret = 0; + int c = -2; + void *pData = NULL; + int nData = 0; + int64_t oversion; + SDecoder dc = {0}; + + tb_uid_t suid = pReq->stbUid; + + if (tdbTbGet(pMeta->pUidIdx, &suid, sizeof(tb_uid_t), &pData, &nData) != 0) { + ret = -1; + goto _err; + } + + tbDbKey.uid = suid; + tbDbKey.version = ((SUidIdxVal *)pData)[0].version; + tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pData, &nData); + tDecoderInit(&dc, pData, nData); + ret = metaDecodeEntry(&dc, &oStbEntry); + if (ret < 0) { + goto _err; + } + + SSchema *pCol = NULL; + int32_t colId = -1; + for (int i = 0; i < oStbEntry.stbEntry.schemaTag.nCols; i++) { + SSchema *schema = oStbEntry.stbEntry.schemaTag.pSchema + i; + if (0 == strncmp(schema->name, pReq->colName, sizeof(pReq->colName))) { + if (i != 0 || IS_IDX_ON(schema)) { + pCol = schema; + } + break; + } + } + + if (pCol == NULL) { + goto _err; + } + + /* + * iterator all pTdDbc by uid and version + */ + TBC *pCtbIdxc = NULL; + tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL); + int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c); + if (rc < 0) { + tdbTbcClose(pCtbIdxc); + goto _err; + } + for (;;) { + void *pKey = NULL, *pVal = NULL; + int nKey = 0, nVal = 0; + rc = tdbTbcNext(pCtbIdxc, &pKey, &nKey, &pVal, &nVal); + if (rc < 0) { + tdbFree(pKey); + tdbFree(pVal); + tdbTbcClose(pCtbIdxc); + pCtbIdxc = NULL; + break; + } + if (((SCtbIdxKey *)pKey)->suid != suid) { + tdbFree(pKey); + tdbFree(pVal); + continue; + } + STagIdxKey *pTagIdxKey = NULL; + int32_t nTagIdxKey; + + const void *pTagData = NULL; + int32_t nTagData = 0; + + SCtbIdxKey *table = (SCtbIdxKey *)pKey; + STagVal tagVal = {.cid = pCol->colId}; + tTagGet((const STag *)pVal, &tagVal); + if (IS_VAR_DATA_TYPE(pCol->type)) { + pTagData = tagVal.pData; + nTagData = (int32_t)tagVal.nData; + } else { + pTagData = &(tagVal.i64); + nTagData = tDataTypes[pCol->type].bytes; + } + rc = metaCreateTagIdxKey(suid, pCol->colId, pTagData, nTagData, pCol->type, table->uid, &pTagIdxKey, &nTagIdxKey); + tdbFree(pKey); + tdbFree(pVal); + if (rc < 0) { + metaDestroyTagIdxKey(pTagIdxKey); + tdbTbcClose(pCtbIdxc); + goto _err; + } + + metaWLock(pMeta); + tdbTbDelete(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, pMeta->txn); + metaULock(pMeta); + metaDestroyTagIdxKey(pTagIdxKey); + } + + // clear idx flag + SSCHMEA_SET_IDX_OFF(pCol); + + nStbEntry.version = version; + nStbEntry.type = TSDB_SUPER_TABLE; + nStbEntry.uid = oStbEntry.uid; + nStbEntry.name = oStbEntry.name; + + SSchemaWrapper *row = tCloneSSchemaWrapper(&oStbEntry.stbEntry.schemaRow); + SSchemaWrapper *tag = tCloneSSchemaWrapper(&oStbEntry.stbEntry.schemaTag); + + nStbEntry.stbEntry.schemaRow = *row; + nStbEntry.stbEntry.schemaTag = *tag; + nStbEntry.stbEntry.rsmaParam = oStbEntry.stbEntry.rsmaParam; + + metaWLock(pMeta); + // update table.db + metaSaveToTbDb(pMeta, &nStbEntry); + // update uid index + metaUpdateUidIdx(pMeta, &nStbEntry); + metaULock(pMeta); + + tDeleteSchemaWrapper(tag); + tDeleteSchemaWrapper(row); + + if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf); + tDecoderClear(&dc); + tdbFree(pData); + + tdbTbcClose(pCtbIdxc); + return TSDB_CODE_SUCCESS; +_err: + if (oStbEntry.pBuf) taosMemoryFree(oStbEntry.pBuf); + tDecoderClear(&dc); + tdbFree(pData); + + return -1; +} int metaCreateTable(SMeta *pMeta, int64_t version, SVCreateTbReq *pReq, STableMetaRsp **pMetaRsp) { SMetaEntry me = {0}; @@ -459,6 +767,7 @@ int metaCreateTable(SMeta *pMeta, int64_t version, SVCreateTbReq *pReq, STableMe metaWLock(pMeta); metaUpdateStbStats(pMeta, me.ctbEntry.suid, 1); metaUidCacheClear(pMeta, me.ctbEntry.suid); + metaTbGroupCacheClear(pMeta, me.ctbEntry.suid); metaULock(pMeta); } else { me.ntbEntry.ctime = pReq->ctime; @@ -558,7 +867,8 @@ static void metaBuildTtlIdxKey(STtlIdxKey *ttlKey, const SMetaEntry *pME) { ctime = pME->ntbEntry.ctime; ttlDays = pME->ntbEntry.ttlDays; } else { - ASSERT(0); + metaError("meta/table: invalide table type: %" PRId8 " build ttl idx key failed.", pME->type); + return; } if (ttlDays <= 0) return; @@ -627,39 +937,45 @@ static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) { int tLen = 0; if (tdbTbGet(pMeta->pUidIdx, &e.ctbEntry.suid, sizeof(tb_uid_t), &tData, &tLen) == 0) { - version = ((SUidIdxVal *)tData)[0].version; - STbDbKey tbDbKey = {.uid = e.ctbEntry.suid, .version = version}; + STbDbKey tbDbKey = {.uid = e.ctbEntry.suid, .version = ((SUidIdxVal *)tData)[0].version}; if (tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &tData, &tLen) == 0) { SDecoder tdc = {0}; SMetaEntry stbEntry = {0}; tDecoderInit(&tdc, tData, tLen); metaDecodeEntry(&tdc, &stbEntry); - const SSchema *pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[0]; - if (pTagColumn->type == TSDB_DATA_TYPE_JSON) { + + SSchema *pTagColumn = NULL; + SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag; + if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) { + pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[0]; metaDelJsonVarFromIdx(pMeta, &e, pTagColumn); } else { - STagIdxKey *pTagIdxKey = NULL; - int32_t nTagIdxKey; - - const void *pTagData = NULL; - int32_t nTagData = 0; - - STagVal tagVal = {.cid = pTagColumn->colId}; - tTagGet((const STag *)e.ctbEntry.pTags, &tagVal); - if (IS_VAR_DATA_TYPE(pTagColumn->type)) { - pTagData = tagVal.pData; - nTagData = (int32_t)tagVal.nData; - } else { - pTagData = &(tagVal.i64); - nTagData = tDataTypes[pTagColumn->type].bytes; + for (int i = 0; i < pTagSchema->nCols; i++) { + pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[i]; + if (!IS_IDX_ON(pTagColumn)) continue; + STagIdxKey *pTagIdxKey = NULL; + int32_t nTagIdxKey; + + const void *pTagData = NULL; + int32_t nTagData = 0; + + STagVal tagVal = {.cid = pTagColumn->colId}; + tTagGet((const STag *)e.ctbEntry.pTags, &tagVal); + if (IS_VAR_DATA_TYPE(pTagColumn->type)) { + pTagData = tagVal.pData; + nTagData = (int32_t)tagVal.nData; + } else { + pTagData = &(tagVal.i64); + nTagData = tDataTypes[pTagColumn->type].bytes; + } + + if (metaCreateTagIdxKey(e.ctbEntry.suid, pTagColumn->colId, pTagData, nTagData, pTagColumn->type, uid, + &pTagIdxKey, &nTagIdxKey) == 0) { + tdbTbDelete(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, pMeta->txn); + } + metaDestroyTagIdxKey(pTagIdxKey); } - - if (metaCreateTagIdxKey(e.ctbEntry.suid, pTagColumn->colId, pTagData, nTagData, pTagColumn->type, uid, - &pTagIdxKey, &nTagIdxKey) == 0) { - tdbTbDelete(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, pMeta->txn); - } - metaDestroyTagIdxKey(pTagIdxKey); } tDecoderClear(&tdc); } @@ -683,6 +999,7 @@ static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) { metaUpdateStbStats(pMeta, e.ctbEntry.suid, -1); metaUidCacheClear(pMeta, e.ctbEntry.suid); + metaTbGroupCacheClear(pMeta, e.ctbEntry.suid); } else if (e.type == TSDB_NORMAL_TABLE) { // drop schema.db (todo) @@ -694,6 +1011,7 @@ static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type) { metaStatsCacheDrop(pMeta, uid); metaUidCacheClear(pMeta, uid); + metaTbGroupCacheClear(pMeta, uid); --pMeta->pVnode->config.vndStats.numOfSTables; } @@ -713,7 +1031,7 @@ int metaUpdateCtimeIdx(SMeta *pMeta, const SMetaEntry *pME) { metaTrace("vgId:%d, start to save version:%" PRId64 " uid:%" PRId64 " ctime:%" PRId64, TD_VID(pMeta->pVnode), pME->version, pME->uid, ctimeKey.ctime); - return tdbTbInsert(pMeta->pCtimeIdx, &ctimeKey, sizeof(ctimeKey), NULL, 0, pMeta->txn); + return tdbTbUpsert(pMeta->pCtimeIdx, &ctimeKey, sizeof(ctimeKey), NULL, 0, pMeta->txn); } int metaDeleteCtimeIdx(SMeta *pMeta, const SMetaEntry *pME) { @@ -728,7 +1046,7 @@ int metaUpdateNcolIdx(SMeta *pMeta, const SMetaEntry *pME) { if (metaBuildNColIdxKey(&ncolKey, pME) < 0) { return 0; } - return tdbTbInsert(pMeta->pNcolIdx, &ncolKey, sizeof(ncolKey), NULL, 0, pMeta->txn); + return tdbTbUpsert(pMeta->pNcolIdx, &ncolKey, sizeof(ncolKey), NULL, 0, pMeta->txn); } int metaDeleteNcolIdx(SMeta *pMeta, const SMetaEntry *pME) { @@ -773,7 +1091,11 @@ static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAl tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL); tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c); - ASSERT(c == 0); + if (c != 0) { + tdbTbcClose(pUidIdxc); + metaError("meta/table: invalide c: %" PRId32 " alt tb column failed.", c); + return -1; + } tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData); oversion = ((SUidIdxVal *)pData)[0].version; @@ -783,7 +1105,13 @@ static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAl tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL); tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c); - ASSERT(c == 0); + if (c != 0) { + tdbTbcClose(pUidIdxc); + tdbTbcClose(pTbDbc); + metaError("meta/table: invalide c: %" PRId32 " alt tb column failed.", c); + return -1; + } + tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData); // get table entry @@ -792,7 +1120,13 @@ static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAl memcpy(entry.pBuf, pData, nData); tDecoderInit(&dc, entry.pBuf, nData); ret = metaDecodeEntry(&dc, &entry); - ASSERT(ret == 0); + if (ret != 0) { + tdbTbcClose(pUidIdxc); + tdbTbcClose(pTbDbc); + tDecoderClear(&dc); + metaError("meta/table: invalide ret: %" PRId32 " alt tb column failed.", ret); + return -1; + } if (entry.type != TSDB_NORMAL_TABLE) { terrno = TSDB_CODE_VND_INVALID_TABLE_ACTION; @@ -812,7 +1146,11 @@ static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAl if (iCol >= pSchema->nCols) break; pColumn = &pSchema->pSchema[iCol]; - ASSERT(pAlterTbReq->colName); + if (NULL == pAlterTbReq->colName) { + metaError("meta/table: null pAlterTbReq->colName"); + return -1; + } + if (strcmp(pColumn->name, pAlterTbReq->colName) == 0) break; iCol++; } @@ -897,12 +1235,11 @@ static int metaAlterTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pAl entry.version = version; - metaDeleteNcolIdx(pMeta, &oldEntry); - metaUpdateNcolIdx(pMeta, &entry); - // do actual write metaWLock(pMeta); + metaDeleteNcolIdx(pMeta, &oldEntry); + metaUpdateNcolIdx(pMeta, &entry); // save to table db metaSaveToTbDb(pMeta, &entry); @@ -964,7 +1301,12 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL); tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c); - ASSERT(c == 0); + if (c != 0) { + tdbTbcClose(pUidIdxc); + terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST; + metaError("meta/table: invalide c: %" PRId32 " update tb tag val failed.", c); + return -1; + } tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData); oversion = ((SUidIdxVal *)pData)[0].version; @@ -977,7 +1319,14 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA /* get ctbEntry */ tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL); tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c); - ASSERT(c == 0); + if (c != 0) { + tdbTbcClose(pUidIdxc); + tdbTbcClose(pTbDbc); + terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST; + metaError("meta/table: invalide c: %" PRId32 " update tb tag val failed.", c); + return -1; + } + tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData); ctbEntry.pBuf = taosMemoryMalloc(nData); @@ -1071,16 +1420,19 @@ static int metaUpdateTableTagVal(SMeta *pMeta, int64_t version, SVAlterTbReq *pA // save to uid.idx metaUpdateUidIdx(pMeta, &ctbEntry); - if (iCol == 0) { - metaUpdateTagIdx(pMeta, &ctbEntry); + metaUpdateTagIdx(pMeta, &ctbEntry); + + if (NULL == ctbEntry.ctbEntry.pTags) { + metaError("meta/table: null tags, update tag val failed."); + goto _err; } - ASSERT(ctbEntry.ctbEntry.pTags); SCtbIdxKey ctbIdxKey = {.suid = ctbEntry.ctbEntry.suid, .uid = uid}; tdbTbUpsert(pMeta->pCtbIdx, &ctbIdxKey, sizeof(ctbIdxKey), ctbEntry.ctbEntry.pTags, ((STag *)(ctbEntry.ctbEntry.pTags))->len, pMeta->txn); metaUidCacheClear(pMeta, ctbEntry.ctbEntry.suid); + metaTbGroupCacheClear(pMeta, ctbEntry.ctbEntry.suid); metaULock(pMeta); @@ -1130,7 +1482,11 @@ static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *p tdbTbcOpen(pMeta->pUidIdx, &pUidIdxc, NULL); tdbTbcMoveTo(pUidIdxc, &uid, sizeof(uid), &c); - ASSERT(c == 0); + if (c != 0) { + tdbTbcClose(pUidIdxc); + metaError("meta/table: invalide c: %" PRId32 " update tb options failed.", c); + return -1; + } tdbTbcGet(pUidIdxc, NULL, NULL, &pData, &nData); oversion = ((SUidIdxVal *)pData)[0].version; @@ -1140,7 +1496,13 @@ static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *p tdbTbcOpen(pMeta->pTbDb, &pTbDbc, NULL); tdbTbcMoveTo(pTbDbc, &((STbDbKey){.uid = uid, .version = oversion}), sizeof(STbDbKey), &c); - ASSERT(c == 0); + if (c != 0) { + tdbTbcClose(pUidIdxc); + tdbTbcClose(pTbDbc); + metaError("meta/table: invalide c: %" PRId32 " update tb options failed.", c); + return -1; + } + tdbTbcGet(pTbDbc, NULL, NULL, &pData, &nData); // get table entry @@ -1149,7 +1511,13 @@ static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *p memcpy(entry.pBuf, pData, nData); tDecoderInit(&dc, entry.pBuf, nData); ret = metaDecodeEntry(&dc, &entry); - ASSERT(ret == 0); + if (ret != 0) { + tDecoderClear(&dc); + tdbTbcClose(pUidIdxc); + tdbTbcClose(pTbDbc); + metaError("meta/table: invalide ret: %" PRId32 " alt tb options failed.", ret); + return -1; + } entry.version = version; metaWLock(pMeta); @@ -1188,6 +1556,243 @@ static int metaUpdateTableOptions(SMeta *pMeta, int64_t version, SVAlterTbReq *p return 0; } +static int metaAddTagIndex(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) { + SMetaEntry stbEntry = {0}; + void *pVal = NULL; + int nVal = 0; + int ret; + int c; + tb_uid_t uid, suid; + int64_t oversion; + const void *pData = NULL; + int nData = 0; + SDecoder dc = {0}; + + if (pAlterTbReq->tagName == NULL) { + terrno = TSDB_CODE_INVALID_MSG; + return -1; + } + + // search name index + ret = tdbTbGet(pMeta->pNameIdx, pAlterTbReq->tbName, strlen(pAlterTbReq->tbName) + 1, &pVal, &nVal); + if (ret < 0) { + terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST; + return -1; + } + uid = *(tb_uid_t *)pVal; + tdbFree(pVal); + pVal = NULL; + + if (tdbTbGet(pMeta->pUidIdx, &uid, sizeof(tb_uid_t), &pVal, &nVal) == -1) { + ret = -1; + goto _err; + } + suid = ((SUidIdxVal *)pVal)[0].suid; + + STbDbKey tbDbKey = {0}; + tbDbKey.uid = suid; + tbDbKey.version = ((SUidIdxVal *)pVal)[0].version; + tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pVal, &nVal); + tDecoderInit(&dc, pVal, nVal); + ret = metaDecodeEntry(&dc, &stbEntry); + if (ret < 0) { + goto _err; + } + + // Get target schema info + SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag; + if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) { + terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS; + goto _err; + } + SSchema *pCol = NULL; + int32_t iCol = 0; + for (;;) { + pCol = NULL; + if (iCol >= pTagSchema->nCols) break; + pCol = &pTagSchema->pSchema[iCol]; + if (strcmp(pCol->name, pAlterTbReq->tagName) == 0) break; + iCol++; + } + + if (iCol == 0) { + terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS; + goto _err; + } + if (pCol == NULL) { + terrno = TSDB_CODE_VND_COL_NOT_EXISTS; + goto _err; + } + + /* + * iterator all pTdDbc by uid and version + */ + TBC *pCtbIdxc = NULL; + tdbTbcOpen(pMeta->pCtbIdx, &pCtbIdxc, NULL); + int rc = tdbTbcMoveTo(pCtbIdxc, &(SCtbIdxKey){.suid = suid, .uid = INT64_MIN}, sizeof(SCtbIdxKey), &c); + if (rc < 0) { + tdbTbcClose(pCtbIdxc); + goto _err; + } + for (;;) { + void *pKey, *pVal; + int nKey, nVal; + rc = tdbTbcNext(pCtbIdxc, &pKey, &nKey, &pVal, &nVal); + if (rc < 0) break; + if (((SCtbIdxKey *)pKey)->suid != uid) { + tdbFree(pKey); + tdbFree(pVal); + continue; + } + STagIdxKey *pTagIdxKey = NULL; + int32_t nTagIdxKey; + + const void *pTagData = NULL; + int32_t nTagData = 0; + + STagVal tagVal = {.cid = pCol->colId}; + tTagGet((const STag *)pVal, &tagVal); + if (IS_VAR_DATA_TYPE(pCol->type)) { + pTagData = tagVal.pData; + nTagData = (int32_t)tagVal.nData; + } else { + pTagData = &(tagVal.i64); + nTagData = tDataTypes[pCol->type].bytes; + } + if (metaCreateTagIdxKey(suid, pCol->colId, pTagData, nTagData, pCol->type, uid, &pTagIdxKey, &nTagIdxKey) < 0) { + metaDestroyTagIdxKey(pTagIdxKey); + goto _err; + } + tdbTbUpsert(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, NULL, 0, pMeta->txn); + metaDestroyTagIdxKey(pTagIdxKey); + } + return 0; + +_err: + // tDecoderClear(&dc1); + // tDecoderClear(&dc2); + // if (ctbEntry.pBuf) taosMemoryFree(ctbEntry.pBuf); + // if (stbEntry.pBuf) tdbFree(stbEntry.pBuf); + // tdbTbcClose(pTbDbc); + // tdbTbcClose(pUidIdxc); + return -1; +} + +typedef struct SMetaPair { + void *key; + int nkey; +} SMetaPair; + +static int metaDropTagIndex(SMeta *pMeta, int64_t version, SVAlterTbReq *pAlterTbReq) { + SMetaEntry stbEntry = {0}; + void *pVal = NULL; + int nVal = 0; + int ret; + int c; + tb_uid_t suid; + int64_t oversion; + const void *pData = NULL; + int nData = 0; + SDecoder dc = {0}; + + if (pAlterTbReq->tagName == NULL) { + terrno = TSDB_CODE_INVALID_MSG; + return -1; + } + + // search name index + ret = tdbTbGet(pMeta->pNameIdx, pAlterTbReq->tbName, strlen(pAlterTbReq->tbName) + 1, &pVal, &nVal); + if (ret < 0) { + terrno = TSDB_CODE_TDB_TABLE_NOT_EXIST; + return -1; + } + suid = *(tb_uid_t *)pVal; + tdbFree(pVal); + pVal = NULL; + + if (tdbTbGet(pMeta->pUidIdx, &suid, sizeof(tb_uid_t), &pVal, &nVal) == -1) { + ret = -1; + goto _err; + } + + STbDbKey tbDbKey = {0}; + tbDbKey.uid = suid; + tbDbKey.version = ((SUidIdxVal *)pVal)[0].version; + tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &pVal, &nVal); + + tDecoderInit(&dc, pVal, nVal); + ret = metaDecodeEntry(&dc, &stbEntry); + if (ret < 0) { + goto _err; + } + + // Get targe schema info + SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag; + if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) { + terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS; + goto _err; + } + SSchema *pCol = NULL; + int32_t iCol = 0; + for (;;) { + pCol = NULL; + if (iCol >= pTagSchema->nCols) break; + pCol = &pTagSchema->pSchema[iCol]; + if (strcmp(pCol->name, pAlterTbReq->tagName) == 0) break; + iCol++; + } + if (iCol == 0) { + // cannot drop 1th tag index + terrno = -1; + goto _err; + } + if (pCol == NULL) { + terrno = TSDB_CODE_VND_COL_NOT_EXISTS; + goto _err; + } + + if (IS_IDX_ON(pCol)) { + terrno = TSDB_CODE_VND_COL_ALREADY_EXISTS; + goto _err; + } + + SArray *tagIdxList = taosArrayInit(512, sizeof(SMetaPair)); + + TBC *pTagIdxc = NULL; + tdbTbcOpen(pMeta->pTagIdx, &pTagIdxc, NULL); + int rc = + tdbTbcMoveTo(pTagIdxc, &(STagIdxKey){.suid = suid, .cid = INT32_MIN, .type = pCol->type}, sizeof(STagIdxKey), &c); + for (;;) { + void *pKey, *pVal; + int nKey, nVal; + rc = tdbTbcNext(pTagIdxc, &pKey, &nKey, &pVal, &nVal); + STagIdxKey *pIdxKey = (STagIdxKey *)pKey; + if (pIdxKey->suid != suid || pIdxKey->cid != pCol->colId) { + tdbFree(pKey); + tdbFree(pVal); + continue; + } + + SMetaPair pair = {.key = pKey, nKey = nKey}; + taosArrayPush(tagIdxList, &pair); + } + tdbTbcClose(pTagIdxc); + + metaWLock(pMeta); + for (int i = 0; i < taosArrayGetSize(tagIdxList); i++) { + SMetaPair *pair = taosArrayGet(tagIdxList, i); + tdbTbDelete(pMeta->pTagIdx, pair->key, pair->nkey, pMeta->txn); + } + metaULock(pMeta); + + taosArrayDestroy(tagIdxList); + + // set pCol->flags; INDEX_ON + return 0; +_err: + return -1; +} + int metaAlterTable(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMetaRsp *pMetaRsp) { switch (pReq->action) { case TSDB_ALTER_TABLE_ADD_COLUMN: @@ -1199,6 +1804,10 @@ int metaAlterTable(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMeta return metaUpdateTableTagVal(pMeta, version, pReq); case TSDB_ALTER_TABLE_UPDATE_OPTIONS: return metaUpdateTableOptions(pMeta, version, pReq); + case TSDB_ALTER_TABLE_ADD_TAG_INDEX: + return metaAddTagIndex(pMeta, version, pReq); + case TSDB_ALTER_TABLE_DROP_TAG_INDEX: + return metaDropTagIndex(pMeta, version, pReq); default: terrno = TSDB_CODE_VND_INVALID_TABLE_ACTION; return -1; @@ -1272,24 +1881,24 @@ static int metaUpdateUidIdx(SMeta *pMeta, const SMetaEntry *pME) { } static int metaUpdateSuidIdx(SMeta *pMeta, const SMetaEntry *pME) { - return tdbTbInsert(pMeta->pSuidIdx, &pME->uid, sizeof(tb_uid_t), NULL, 0, pMeta->txn); + return tdbTbUpsert(pMeta->pSuidIdx, &pME->uid, sizeof(tb_uid_t), NULL, 0, pMeta->txn); } static int metaUpdateNameIdx(SMeta *pMeta, const SMetaEntry *pME) { - return tdbTbInsert(pMeta->pNameIdx, pME->name, strlen(pME->name) + 1, &pME->uid, sizeof(tb_uid_t), pMeta->txn); + return tdbTbUpsert(pMeta->pNameIdx, pME->name, strlen(pME->name) + 1, &pME->uid, sizeof(tb_uid_t), pMeta->txn); } static int metaUpdateTtlIdx(SMeta *pMeta, const SMetaEntry *pME) { STtlIdxKey ttlKey = {0}; metaBuildTtlIdxKey(&ttlKey, pME); if (ttlKey.dtime == 0) return 0; - return tdbTbInsert(pMeta->pTtlIdx, &ttlKey, sizeof(ttlKey), NULL, 0, pMeta->txn); + return tdbTbUpsert(pMeta->pTtlIdx, &ttlKey, sizeof(ttlKey), NULL, 0, pMeta->txn); } static int metaUpdateCtbIdx(SMeta *pMeta, const SMetaEntry *pME) { SCtbIdxKey ctbIdxKey = {.suid = pME->ctbEntry.suid, .uid = pME->uid}; - return tdbTbInsert(pMeta->pCtbIdx, &ctbIdxKey, sizeof(ctbIdxKey), pME->ctbEntry.pTags, + return tdbTbUpsert(pMeta->pCtbIdx, &ctbIdxKey, sizeof(ctbIdxKey), pME->ctbEntry.pTags, ((STag *)(pME->ctbEntry.pTags))->len, pMeta->txn); } @@ -1315,10 +1924,10 @@ int metaCreateTagIdxKey(tb_uid_t suid, int32_t cid, const void *pTagData, int32_ // refactor if (IS_VAR_DATA_TYPE(type)) { memcpy((*ppTagIdxKey)->data, (uint16_t *)&nTagData, VARSTR_HEADER_SIZE); - memcpy((*ppTagIdxKey)->data + VARSTR_HEADER_SIZE, pTagData, nTagData); + if (pTagData != NULL) memcpy((*ppTagIdxKey)->data + VARSTR_HEADER_SIZE, pTagData, nTagData); *(tb_uid_t *)((*ppTagIdxKey)->data + VARSTR_HEADER_SIZE + nTagData) = uid; } else { - memcpy((*ppTagIdxKey)->data, pTagData, nTagData); + if (pTagData != NULL) memcpy((*ppTagIdxKey)->data, pTagData, nTagData); *(tb_uid_t *)((*ppTagIdxKey)->data + nTagData) = uid; } @@ -1363,36 +1972,43 @@ static int metaUpdateTagIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry) { goto end; } - pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[0]; + SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag; + if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) { + pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[0]; + STagVal tagVal = {.cid = pTagColumn->colId}; - STagVal tagVal = {.cid = pTagColumn->colId}; - if (pTagColumn->type != TSDB_DATA_TYPE_JSON) { - tTagGet((const STag *)pCtbEntry->ctbEntry.pTags, &tagVal); - if (IS_VAR_DATA_TYPE(pTagColumn->type)) { - pTagData = tagVal.pData; - nTagData = (int32_t)tagVal.nData; - } else { - pTagData = &(tagVal.i64); - nTagData = tDataTypes[pTagColumn->type].bytes; - } - } else { - // pTagData = pCtbEntry->ctbEntry.pTags; - // nTagData = ((const STag *)pCtbEntry->ctbEntry.pTags)->len; pTagData = pCtbEntry->ctbEntry.pTags; nTagData = ((const STag *)pCtbEntry->ctbEntry.pTags)->len; ret = metaSaveJsonVarToIdx(pMeta, pCtbEntry, pTagColumn); goto end; - } - if (pTagData != NULL) { - if (metaCreateTagIdxKey(pCtbEntry->ctbEntry.suid, pTagColumn->colId, pTagData, nTagData, pTagColumn->type, - pCtbEntry->uid, &pTagIdxKey, &nTagIdxKey) < 0) { - ret = -1; - goto end; + } else { + for (int i = 0; i < pTagSchema->nCols; i++) { + pTagColumn = &pTagSchema->pSchema[i]; + if (i != 0 && !IS_IDX_ON(pTagColumn)) continue; + + STagVal tagVal = {.cid = pTagColumn->colId}; + tTagGet((const STag *)pCtbEntry->ctbEntry.pTags, &tagVal); + if (IS_VAR_DATA_TYPE(pTagColumn->type)) { + pTagData = tagVal.pData; + nTagData = (int32_t)tagVal.nData; + } else { + pTagData = &(tagVal.i64); + nTagData = tDataTypes[pTagColumn->type].bytes; + } + + if (pTagData != NULL) { + if (metaCreateTagIdxKey(pCtbEntry->ctbEntry.suid, pTagColumn->colId, pTagData, nTagData, pTagColumn->type, + pCtbEntry->uid, &pTagIdxKey, &nTagIdxKey) < 0) { + ret = -1; + goto end; + } + tdbTbUpsert(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, NULL, 0, pMeta->txn); + } + metaDestroyTagIdxKey(pTagIdxKey); } - tdbTbUpsert(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, NULL, 0, pMeta->txn); } end: - metaDestroyTagIdxKey(pTagIdxKey); + // metaDestroyTagIdxKey(pTagIdxKey); tDecoderClear(&dc); tdbFree(pData); return ret; @@ -1411,7 +2027,8 @@ static int metaSaveToSkmDb(SMeta *pMeta, const SMetaEntry *pME) { } else if (pME->type == TSDB_NORMAL_TABLE) { pSW = &pME->ntbEntry.schemaRow; } else { - ASSERT(0); + metaError("meta/table: invalide table type: %" PRId8 " save skm db failed.", pME->type); + return TSDB_CODE_FAILED; } skmDbKey.uid = pME->uid; @@ -1451,49 +2068,66 @@ _exit: } int metaHandleEntry(SMeta *pMeta, const SMetaEntry *pME) { + int32_t code = 0; + int32_t line = 0; metaWLock(pMeta); // save to table.db - if (metaSaveToTbDb(pMeta, pME) < 0) goto _err; + code = metaSaveToTbDb(pMeta, pME); + VND_CHECK_CODE(code, line, _err); // update uid.idx - if (metaUpdateUidIdx(pMeta, pME) < 0) goto _err; + code = metaUpdateUidIdx(pMeta, pME); + VND_CHECK_CODE(code, line, _err); // update name.idx - if (metaUpdateNameIdx(pMeta, pME) < 0) goto _err; + code = metaUpdateNameIdx(pMeta, pME); + VND_CHECK_CODE(code, line, _err); if (pME->type == TSDB_CHILD_TABLE) { // update ctb.idx - if (metaUpdateCtbIdx(pMeta, pME) < 0) goto _err; + code = metaUpdateCtbIdx(pMeta, pME); + VND_CHECK_CODE(code, line, _err); // update tag.idx - if (metaUpdateTagIdx(pMeta, pME) < 0) goto _err; + code = metaUpdateTagIdx(pMeta, pME); + VND_CHECK_CODE(code, line, _err); } else { // update schema.db - if (metaSaveToSkmDb(pMeta, pME) < 0) goto _err; + code = metaSaveToSkmDb(pMeta, pME); + VND_CHECK_CODE(code, line, _err); if (pME->type == TSDB_SUPER_TABLE) { - if (metaUpdateSuidIdx(pMeta, pME) < 0) goto _err; + code = metaUpdateSuidIdx(pMeta, pME); + VND_CHECK_CODE(code, line, _err); } } - if (metaUpdateCtimeIdx(pMeta, pME) < 0) goto _err; + code = metaUpdateCtimeIdx(pMeta, pME); + VND_CHECK_CODE(code, line, _err); if (pME->type == TSDB_NORMAL_TABLE) { - if (metaUpdateNcolIdx(pMeta, pME) < 0) goto _err; + code = metaUpdateNcolIdx(pMeta, pME); + VND_CHECK_CODE(code, line, _err); } if (pME->type != TSDB_SUPER_TABLE) { - if (metaUpdateTtlIdx(pMeta, pME) < 0) goto _err; + code = metaUpdateTtlIdx(pMeta, pME); + VND_CHECK_CODE(code, line, _err); } metaULock(pMeta); + metaDebug("vgId:%d, handle meta entry, ver:%" PRId64 ", uid:%" PRId64 ", name:%s", TD_VID(pMeta->pVnode), + pME->version, pME->uid, pME->name); return 0; _err: metaULock(pMeta); + metaError("vgId:%d, failed to handle meta entry since %s at line:%d, ver:%" PRId64 ", uid:%" PRId64 ", name:%s", + TD_VID(pMeta->pVnode), terrstr(), line, pME->version, pME->uid, pME->name); return -1; } + // refactor later void *metaGetIdx(SMeta *pMeta) { return pMeta->pTagIdx; } void *metaGetIvtIdx(SMeta *pMeta) { return pMeta->pTagIvtIdx; } diff --git a/source/dnode/vnode/src/sma/smaCommit.c b/source/dnode/vnode/src/sma/smaCommit.c index 20db35e5b561b559bbf5a0145b95bae0ec714d08..51011ef7916a7f5b4173418a6d67186a8ff7869f 100644 --- a/source/dnode/vnode/src/sma/smaCommit.c +++ b/source/dnode/vnode/src/sma/smaCommit.c @@ -17,41 +17,18 @@ extern SSmaMgmt smaMgmt; -#if 0 -static int32_t tdProcessRSmaSyncPreCommitImpl(SSma *pSma); -static int32_t tdProcessRSmaSyncCommitImpl(SSma *pSma); -static int32_t tdProcessRSmaSyncPostCommitImpl(SSma *pSma); -#endif -static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma); +static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma, bool isCommit); static int32_t tdProcessRSmaAsyncCommitImpl(SSma *pSma, SCommitInfo *pInfo); static int32_t tdProcessRSmaAsyncPostCommitImpl(SSma *pSma); static int32_t tdUpdateQTaskInfoFiles(SSma *pSma, SRSmaStat *pRSmaStat); -#if 0 -/** - * @brief Only applicable to Rollup SMA - * - * @param pSma - * @return int32_t - */ -int32_t smaSyncPreCommit(SSma *pSma) { return tdProcessRSmaSyncPreCommitImpl(pSma); } - /** - * @brief Only applicable to Rollup SMA + * @brief only applicable to Rollup SMA * * @param pSma * @return int32_t */ -int32_t smaSyncCommit(SSma *pSma) { return tdProcessRSmaSyncCommitImpl(pSma); } - -/** - * @brief Only applicable to Rollup SMA - * - * @param pSma - * @return int32_t - */ -int32_t smaSyncPostCommit(SSma *pSma) { return tdProcessRSmaSyncPostCommitImpl(pSma); } -#endif +int32_t smaPreClose(SSma *pSma) { return tdProcessRSmaAsyncPreCommitImpl(pSma, false); } /** * @brief async commit, only applicable to Rollup SMA @@ -59,7 +36,7 @@ int32_t smaSyncPostCommit(SSma *pSma) { return tdProcessRSmaSyncPostCommitImpl(p * @param pSma * @return int32_t */ -int32_t smaPrepareAsyncCommit(SSma *pSma) { return tdProcessRSmaAsyncPreCommitImpl(pSma); } +int32_t smaPrepareAsyncCommit(SSma *pSma) { return tdProcessRSmaAsyncPreCommitImpl(pSma, true); } /** * @brief async commit, only applicable to Rollup SMA @@ -128,166 +105,24 @@ _exit: int32_t smaFinishCommit(SSma *pSma) { int32_t code = 0; + int32_t lino = 0; SVnode *pVnode = pSma->pVnode; + code = tdRSmaFSFinishCommit(pSma); + TSDB_CHECK_CODE(code, lino, _exit); + if (VND_RSMA1(pVnode) && (code = tsdbFinishCommit(VND_RSMA1(pVnode))) < 0) { - smaError("vgId:%d, failed to finish commit tsdb rsma1 since %s", TD_VID(pVnode), tstrerror(code)); - goto _exit; + TSDB_CHECK_CODE(code, lino, _exit); } if (VND_RSMA2(pVnode) && (code = tsdbFinishCommit(VND_RSMA2(pVnode))) < 0) { - smaError("vgId:%d, failed to finish commit tsdb rsma2 since %s", TD_VID(pVnode), tstrerror(code)); - goto _exit; + TSDB_CHECK_CODE(code, lino, _exit); } _exit: - terrno = code; - return code; -} - -#if 0 -/** - * @brief pre-commit for rollup sma(sync commit). - * 1) set trigger stat of rsma timer TASK_TRIGGER_STAT_PAUSED. - * 2) wait for all triggered fetch tasks to finish - * 3) perform persist task for qTaskInfo - * - * @param pSma - * @return int32_t - */ -static int32_t tdProcessRSmaSyncPreCommitImpl(SSma *pSma) { - SSmaEnv *pSmaEnv = SMA_RSMA_ENV(pSma); - if (!pSmaEnv) { - return TSDB_CODE_SUCCESS; - } - - SSmaStat *pStat = SMA_ENV_STAT(pSmaEnv); - SRSmaStat *pRSmaStat = SMA_STAT_RSMA(pStat); - - // step 1: set rsma stat paused - atomic_store_8(RSMA_TRIGGER_STAT(pRSmaStat), TASK_TRIGGER_STAT_PAUSED); - - // step 2: wait for all triggered fetch tasks to finish - int32_t nLoops = 0; - while (1) { - if (T_REF_VAL_GET(pStat) == 0) { - smaDebug("vgId:%d, rsma fetch tasks are all finished", SMA_VID(pSma)); - break; - } else { - smaDebug("vgId:%d, rsma fetch tasks are not all finished yet", SMA_VID(pSma)); - } - ++nLoops; - if (nLoops > 1000) { - sched_yield(); - nLoops = 0; - } - } - - // step 3: perform persist task for qTaskInfo - pRSmaStat->commitAppliedVer = pSma->pVnode->state.applied; - tdRSmaPersistExecImpl(pRSmaStat, RSMA_INFO_HASH(pRSmaStat)); - - smaDebug("vgId:%d, rsma pre commit success", SMA_VID(pSma)); - - return TSDB_CODE_SUCCESS; -} - -/** - * @brief commit for rollup sma - * - * @param pSma - * @return int32_t - */ -static int32_t tdProcessRSmaSyncCommitImpl(SSma *pSma) { -#if 0 - SSmaEnv *pSmaEnv = SMA_RSMA_ENV(pSma); - if (!pSmaEnv) { - return TSDB_CODE_SUCCESS; - } -#endif - return TSDB_CODE_SUCCESS; -} -#endif - -// SQTaskFile ====================================================== - -/** - * @brief At most time, there is only one qtaskinfo file committed latest in aTaskFile. Sometimes, there would be - * multiple qtaskinfo files supporting snapshot replication. - * - * @param pSma - * @param pStat - * @return int32_t - */ -static int32_t tdUpdateQTaskInfoFiles(SSma *pSma, SRSmaStat *pStat) { - SVnode *pVnode = pSma->pVnode; - SRSmaFS *pFS = RSMA_FS(pStat); - int64_t committed = pStat->commitAppliedVer; - int64_t fsMaxVer = -1; - char qTaskInfoFullName[TSDB_FILENAME_LEN]; - - taosWLockLatch(RSMA_FS_LOCK(pStat)); - - for (int32_t i = 0; i < taosArrayGetSize(pFS->aQTaskInf);) { - SQTaskFile *pTaskF = taosArrayGet(pFS->aQTaskInf, i); - int32_t oldVal = atomic_fetch_sub_32(&pTaskF->nRef, 1); - if ((oldVal <= 1) && (pTaskF->version < committed)) { - tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pTaskF->version, tfsGetPrimaryPath(pVnode->pTfs), qTaskInfoFullName); - if (taosRemoveFile(qTaskInfoFullName) < 0) { - smaWarn("vgId:%d, cleanup qinf, committed %" PRIi64 ", failed to remove %s since %s", TD_VID(pVnode), committed, - qTaskInfoFullName, tstrerror(TAOS_SYSTEM_ERROR(errno))); - } else { - smaDebug("vgId:%d, cleanup qinf, committed %" PRIi64 ", success to remove %s", TD_VID(pVnode), committed, - qTaskInfoFullName); - } - taosArrayRemove(pFS->aQTaskInf, i); - continue; - } - ++i; + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); } - - if (taosArrayGetSize(pFS->aQTaskInf) > 0) { - fsMaxVer = ((SQTaskFile *)taosArrayGetLast(pFS->aQTaskInf))->version; - } - - if (fsMaxVer < committed) { - tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), committed, tfsGetPrimaryPath(pVnode->pTfs), qTaskInfoFullName); - if (taosCheckExistFile(qTaskInfoFullName)) { - SQTaskFile qFile = {.nRef = 1, .padding = 0, .version = committed, .size = 0}; - if (!taosArrayPush(pFS->aQTaskInf, &qFile)) { - taosWUnLockLatch(RSMA_FS_LOCK(pStat)); - terrno = TSDB_CODE_OUT_OF_MEMORY; - return TSDB_CODE_FAILED; - } - } - } else { - smaDebug("vgId:%d, update qinf, no need as committed %" PRIi64 " not larger than fsMaxVer %" PRIi64, TD_VID(pVnode), - committed, fsMaxVer); - } - - taosWUnLockLatch(RSMA_FS_LOCK(pStat)); - return TSDB_CODE_SUCCESS; -} - -#if 0 -/** - * @brief post-commit for rollup sma - * 1) clean up the outdated qtaskinfo files - * - * @param pSma - * @return int32_t - */ -static int32_t tdProcessRSmaSyncPostCommitImpl(SSma *pSma) { - SVnode *pVnode = pSma->pVnode; - if (!VND_IS_RSMA(pVnode)) { - return TSDB_CODE_SUCCESS; - } - - SRSmaStat *pRSmaStat = SMA_RSMA_STAT(pSma); - - tdUpdateQTaskInfoFiles(pSma, pRSmaStat); - - return TSDB_CODE_SUCCESS; + return code; } -#endif /** * @brief Rsma async commit implementation(only do some necessary light weighted task) @@ -295,12 +130,16 @@ static int32_t tdProcessRSmaSyncPostCommitImpl(SSma *pSma) { * 2) Wait all running fetch task finish to fetch and put submitMsg into level 2/3 wQueue(blocking level 1 write) * * @param pSma + * @param isCommit * @return int32_t */ -static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma) { +static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma, bool isCommit) { + int32_t code = 0; + int32_t lino = 0; + SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); if (!pEnv) { - return TSDB_CODE_SUCCESS; + return code; } SSmaStat *pStat = SMA_ENV_STAT(pEnv); @@ -309,24 +148,30 @@ static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma) { // step 1: set rsma stat atomic_store_8(RSMA_TRIGGER_STAT(pRSmaStat), TASK_TRIGGER_STAT_PAUSED); - while (atomic_val_compare_exchange_8(RSMA_COMMIT_STAT(pRSmaStat), 0, 1) != 0) { - ++nLoops; - if (nLoops > 1000) { - sched_yield(); - nLoops = 0; + if (isCommit) { + while (atomic_val_compare_exchange_8(RSMA_COMMIT_STAT(pRSmaStat), 0, 1) != 0) { + ++nLoops; + if (nLoops > 1000) { + sched_yield(); + nLoops = 0; + } } - } - pRSmaStat->commitAppliedVer = pSma->pVnode->state.applied; - ASSERT(pRSmaStat->commitAppliedVer > 0); + pRSmaStat->commitAppliedVer = pSma->pVnode->state.applied; + if (ASSERTS(pRSmaStat->commitAppliedVer >= -1, "commit applied version %" PRIi64 " < -1", + pRSmaStat->commitAppliedVer)) { + code = TSDB_CODE_APP_ERROR; + TSDB_CHECK_CODE(code, lino, _exit); + } + } // step 2: wait for all triggered fetch tasks to finish nLoops = 0; while (1) { - if (T_REF_VAL_GET(pStat) == 0) { - smaDebug("vgId:%d, rsma commit, fetch tasks are all finished", SMA_VID(pSma)); + if (atomic_load_32(&pRSmaStat->nFetchAll) <= 0) { + smaDebug("vgId:%d, rsma commit:%d, fetch tasks are all finished", SMA_VID(pSma), isCommit); break; } else { - smaDebug("vgId:%d, rsma commit, fetch tasks are not all finished yet", SMA_VID(pSma)); + smaDebug("vgId:%d, rsma commit%d, fetch tasks are not all finished yet", SMA_VID(pSma), isCommit); } ++nLoops; if (nLoops > 1000) { @@ -340,7 +185,7 @@ static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma) { * 1) This is high cost task and should not put in asyncPreCommit originally. * 2) But, if put in asyncCommit, would trigger taskInfo cloning frequently. */ - smaInfo("vgId:%d, rsma commit, wait for all items to be consumed, TID:%p", SMA_VID(pSma), + smaInfo("vgId:%d, rsma commit:%d, wait for all items to be consumed, TID:%p", SMA_VID(pSma), isCommit, (void *)taosGetSelfPthreadId()); nLoops = 0; while (atomic_load_64(&pRSmaStat->nBufItems) > 0) { @@ -350,10 +195,13 @@ static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma) { nLoops = 0; } } + + if (!isCommit) goto _exit; + smaInfo("vgId:%d, rsma commit, all items are consumed, TID:%p", SMA_VID(pSma), (void *)taosGetSelfPthreadId()); - if (tdRSmaPersistExecImpl(pRSmaStat, RSMA_INFO_HASH(pRSmaStat)) < 0) { - return TSDB_CODE_FAILED; - } + code = tdRSmaPersistExecImpl(pRSmaStat, RSMA_INFO_HASH(pRSmaStat)); + TSDB_CHECK_CODE(code, lino, _exit); + smaInfo("vgId:%d, rsma commit, operator state committed, TID:%p", SMA_VID(pSma), (void *)taosGetSelfPthreadId()); #if 0 // consuming task of qTaskInfo clone @@ -361,8 +209,6 @@ static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma) { // lock taosWLockLatch(SMA_ENV_LOCK(pEnv)); - ASSERT(RSMA_INFO_HASH(pRSmaStat)); - void *pIter = taosHashIterate(RSMA_INFO_HASH(pRSmaStat), NULL); while (pIter) { @@ -380,10 +226,20 @@ static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma) { // all rsma results are written completely STsdb *pTsdb = NULL; - if ((pTsdb = VND_RSMA1(pSma->pVnode))) tsdbPrepareCommit(pTsdb); - if ((pTsdb = VND_RSMA2(pSma->pVnode))) tsdbPrepareCommit(pTsdb); + if ((pTsdb = VND_RSMA1(pSma->pVnode))) { + code = tsdbPrepareCommit(pTsdb); + TSDB_CHECK_CODE(code, lino, _exit); + } + if ((pTsdb = VND_RSMA2(pSma->pVnode))) { + code = tsdbPrepareCommit(pTsdb); + TSDB_CHECK_CODE(code, lino, _exit); + } - return TSDB_CODE_SUCCESS; +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s(%d)", SMA_VID(pSma), __func__, lino, tstrerror(code), isCommit); + } + return code; } /** @@ -394,30 +250,27 @@ static int32_t tdProcessRSmaAsyncPreCommitImpl(SSma *pSma) { */ static int32_t tdProcessRSmaAsyncCommitImpl(SSma *pSma, SCommitInfo *pInfo) { int32_t code = 0; + int32_t lino = 0; SVnode *pVnode = pSma->pVnode; + SSmaEnv *pSmaEnv = SMA_RSMA_ENV(pSma); if (!pSmaEnv) { goto _exit; } -#if 0 - SRSmaStat *pRSmaStat = (SRSmaStat *)SMA_ENV_STAT(pSmaEnv); - // perform persist task for qTaskInfo operator - if (tdRSmaPersistExecImpl(pRSmaStat, RSMA_INFO_HASH(pRSmaStat)) < 0) { - return TSDB_CODE_FAILED; - } -#endif + code = tdRSmaFSCommit(pSma); + TSDB_CHECK_CODE(code, lino, _exit); + + code = tsdbCommit(VND_RSMA1(pVnode), pInfo); + TSDB_CHECK_CODE(code, lino, _exit); + + code = tsdbCommit(VND_RSMA2(pVnode), pInfo); + TSDB_CHECK_CODE(code, lino, _exit); - if ((code = tsdbCommit(VND_RSMA1(pVnode), pInfo)) < 0) { - smaError("vgId:%d, failed to commit tsdb rsma1 since %s", TD_VID(pVnode), tstrerror(code)); - goto _exit; - } - if ((code = tsdbCommit(VND_RSMA2(pVnode), pInfo)) < 0) { - smaError("vgId:%d, failed to commit tsdb rsma2 since %s", TD_VID(pVnode), tstrerror(code)); - goto _exit; - } _exit: - terrno = code; + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } return code; } @@ -477,8 +330,6 @@ static int32_t tdProcessRSmaAsyncPostCommitImpl(SSma *pSma) { taosWUnLockLatch(SMA_ENV_LOCK(pEnv)); } - tdUpdateQTaskInfoFiles(pSma, pRSmaStat); - atomic_store_8(RSMA_COMMIT_STAT(pRSmaStat), 0); return TSDB_CODE_SUCCESS; diff --git a/source/dnode/vnode/src/sma/smaEnv.c b/source/dnode/vnode/src/sma/smaEnv.c index a272f5fc97883943e95d8ee7feb1c60ec90d49cb..02766c8076b435e3cdac12885210f533c12e4c6e 100644 --- a/source/dnode/vnode/src/sma/smaEnv.c +++ b/source/dnode/vnode/src/sma/smaEnv.c @@ -131,7 +131,7 @@ static int32_t tdNewSmaEnv(SSma *pSma, int8_t smaType, SSmaEnv **ppEnv) { (smaType == TSDB_SMA_TYPE_TIME_RANGE) ? atomic_store_ptr(&SMA_TSMA_ENV(pSma), *ppEnv) : atomic_store_ptr(&SMA_RSMA_ENV(pSma), *ppEnv); - if (tdInitSmaStat(&SMA_ENV_STAT(pEnv), smaType, pSma) != TSDB_CODE_SUCCESS) { + if ((terrno = tdInitSmaStat(&SMA_ENV_STAT(pEnv), smaType, pSma)) != TSDB_CODE_SUCCESS) { tdFreeSmaEnv(pEnv); *ppEnv = NULL; (smaType == TSDB_SMA_TYPE_TIME_RANGE) ? atomic_store_ptr(&SMA_TSMA_ENV(pSma), NULL) @@ -193,10 +193,16 @@ static void tRSmaInfoHashFreeNode(void *data) { } static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType, const SSma *pSma) { - ASSERT(pSmaStat != NULL); + int32_t code = 0; + int32_t lino = 0; + + if (ASSERTS(pSmaStat != NULL, "pSmaStat is NULL")) { + terrno = TSDB_CODE_RSMA_INVALID_ENV; + TSDB_CHECK_CODE(code, lino, _exit); + } if (*pSmaStat) { // no lock - return TSDB_CODE_SUCCESS; + return code; // success, return directly } /** @@ -207,8 +213,8 @@ static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType, const SSma *pS if (!(*pSmaStat)) { *pSmaStat = (SSmaStat *)taosMemoryCalloc(1, sizeof(SSmaStat) + sizeof(TdThread) * tsNumOfVnodeRsmaThreads); if (!(*pSmaStat)) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return TSDB_CODE_FAILED; + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); } if (smaType == TSDB_SMA_TYPE_ROLLUP) { @@ -224,7 +230,8 @@ static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType, const SSma *pS if (refId < 0) { smaError("vgId:%d, taosAddRef refId:%" PRIi64 " to rsetId rsetId:%d max:%d failed since:%s", SMA_VID(pSma), refId, smaMgmt.rsetId, SMA_MGMT_REF_NUM, tstrerror(terrno)); - return TSDB_CODE_FAILED; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } else { smaDebug("vgId:%d, taosAddRef refId:%" PRIi64 " to rsetId rsetId:%d max:%d succeed", SMA_VID(pSma), refId, smaMgmt.rsetId, SMA_MGMT_REF_NUM); @@ -235,25 +242,30 @@ static int32_t tdInitSmaStat(SSmaStat **pSmaStat, int8_t smaType, const SSma *pS RSMA_INFO_HASH(pRSmaStat) = taosHashInit( RSMA_TASK_INFO_HASH_SLOT, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_ENTRY_LOCK); if (!RSMA_INFO_HASH(pRSmaStat)) { - return TSDB_CODE_FAILED; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } taosHashSetFreeFp(RSMA_INFO_HASH(pRSmaStat), tRSmaInfoHashFreeNode); if (tdRsmaStartExecutor(pSma) < 0) { - return TSDB_CODE_FAILED; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } - if (!(RSMA_FS(pRSmaStat)->aQTaskInf = taosArrayInit(1, sizeof(SQTaskFile)))) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return TSDB_CODE_FAILED; - } + taosInitRWLatch(RSMA_FS_LOCK(pRSmaStat)); } else if (smaType == TSDB_SMA_TYPE_TIME_RANGE) { // TODO } else { - ASSERT(0); + ASSERTS(0, "unknown smaType:%" PRIi8, smaType); + code = TSDB_CODE_APP_ERROR; + TSDB_CHECK_CODE(code, lino, _exit); } } - return TSDB_CODE_SUCCESS; +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", SMA_VID(pSma), __func__, lino, tstrerror(code)); + } + return code; } static void tdDestroyTSmaStat(STSmaStat *pStat) { @@ -279,10 +291,7 @@ static void tdDestroyRSmaStat(void *pRSmaStat) { // step 1: set rsma trigger stat cancelled atomic_store_8(RSMA_TRIGGER_STAT(pStat), TASK_TRIGGER_STAT_CANCELLED); - // step 2: destroy the rsma info and associated fetch tasks - taosHashCleanup(RSMA_INFO_HASH(pStat)); - - // step 3: wait for all triggered fetch tasks to finish + // step 2: wait for all triggered fetch tasks to finish int32_t nLoops = 0; while (1) { if (T_REF_VAL_GET((SSmaStat *)pStat) == 0) { @@ -298,9 +307,12 @@ static void tdDestroyRSmaStat(void *pRSmaStat) { } } - // step 4: + // step 3: tdRsmaStopExecutor(pSma); + // step 4: destroy the rsma info and associated fetch tasks + taosHashCleanup(RSMA_INFO_HASH(pStat)); + // step 5: tdRSmaFSClose(RSMA_FS(pStat)); @@ -342,7 +354,10 @@ static int32_t tdDestroySmaState(SSmaStat *pSmaStat, int8_t smaType) { smaDebug("vgId:%d, remove refId:%" PRIi64 " from rsmaRef:%" PRIi32 " succeed", vid, refId, smaMgmt.rsetId); } } else { - ASSERT(0); + ASSERTS(0, "unknown smaType:%" PRIi8, smaType); + terrno = TSDB_CODE_APP_ERROR; + smaError("%s failed at line %d since %s", __func__, __LINE__, terrstr()); + return -1; } } return 0; @@ -351,7 +366,7 @@ static int32_t tdDestroySmaState(SSmaStat *pSmaStat, int8_t smaType) { int32_t tdLockSma(SSma *pSma) { int code = taosThreadMutexLock(&pSma->mutex); if (code != 0) { - smaError("vgId:%d, failed to lock td since %s", SMA_VID(pSma), strerror(errno)); + smaError("vgId:%d, failed to lock since %s", SMA_VID(pSma), strerror(errno)); terrno = TAOS_SYSTEM_ERROR(code); return -1; } @@ -360,12 +375,17 @@ int32_t tdLockSma(SSma *pSma) { } int32_t tdUnLockSma(SSma *pSma) { - ASSERT(SMA_LOCKED(pSma)); + if (ASSERTS(SMA_LOCKED(pSma), "pSma %p is not locked:%d", pSma, pSma->locked)) { + terrno = TSDB_CODE_APP_ERROR; + smaError("vgId:%d, failed to unlock since %s", SMA_VID(pSma), tstrerror(terrno)); + return -1; + } + pSma->locked = false; int code = taosThreadMutexUnlock(&pSma->mutex); if (code != 0) { - smaError("vgId:%d, failed to unlock td since %s", SMA_VID(pSma), strerror(errno)); terrno = TAOS_SYSTEM_ERROR(code); + smaError("vgId:%d, failed to unlock since %s", SMA_VID(pSma), strerror(errno)); return -1; } return 0; diff --git a/source/dnode/vnode/src/sma/smaFS.c b/source/dnode/vnode/src/sma/smaFS.c index 8db36be741f3187834d4b2f2eca4fa302ca524fe..1211ef940585a44effb47aa7f09ee69d36abf5e1 100644 --- a/source/dnode/vnode/src/sma/smaFS.c +++ b/source/dnode/vnode/src/sma/smaFS.c @@ -17,250 +17,633 @@ // ================================================================================================= -static int32_t tdFetchQTaskInfoFiles(SSma *pSma, int64_t version, SArray **output); +// static int32_t tdFetchQTaskInfoFiles(SSma *pSma, int64_t version, SArray **output); static int32_t tdQTaskInfCmprFn1(const void *p1, const void *p2); -static int32_t tdQTaskInfCmprFn2(const void *p1, const void *p2); -/** - * @brief Open RSma FS from qTaskInfo files - * - * @param pSma - * @param version - * @return int32_t - */ -int32_t tdRSmaFSOpen(SSma *pSma, int64_t version) { - SVnode *pVnode = pSma->pVnode; - int64_t commitID = pVnode->state.commitID; - SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); - SRSmaStat *pStat = NULL; - SArray *output = NULL; - terrno = TSDB_CODE_SUCCESS; +static FORCE_INLINE int32_t tPutQTaskF(uint8_t *p, SQTaskFile *pFile) { + int32_t n = 0; - if (!pEnv) { - return TSDB_CODE_SUCCESS; - } + n += tPutI8(p ? p + n : p, pFile->level); + n += tPutI64v(p ? p + n : p, pFile->size); + n += tPutI64v(p ? p + n : p, pFile->suid); + n += tPutI64v(p ? p + n : p, pFile->version); + n += tPutI64v(p ? p + n : p, pFile->mtime); + + return n; +} - if (tdFetchQTaskInfoFiles(pSma, version, &output) < 0) { - goto _end; +static int32_t tdRSmaFSToBinary(uint8_t *p, SRSmaFS *pFS) { + int32_t n = 0; + uint32_t size = taosArrayGetSize(pFS->aQTaskInf); + + // version + n += tPutI8(p ? p + n : p, 0); + + // SArray + n += tPutU32v(p ? p + n : p, size); + for (uint32_t i = 0; i < size; ++i) { + n += tPutQTaskF(p ? p + n : p, taosArrayGet(pFS->aQTaskInf, i)); } - pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); + return n; +} + +int32_t tdRSmaGetQTaskF(uint8_t *p, SQTaskFile *pFile) { + int32_t n = 0; + + n += tGetI8(p + n, &pFile->level); + n += tGetI64v(p + n, &pFile->size); + n += tGetI64v(p + n, &pFile->suid); + n += tGetI64v(p + n, &pFile->version); + n += tGetI64v(p + n, &pFile->mtime); + + return n; +} + +static int32_t tsdbBinaryToFS(uint8_t *pData, int64_t nData, SRSmaFS *pFS) { + int32_t code = 0; + int32_t n = 0; + int8_t version = 0; + + // version + n += tGetI8(pData + n, &version); + + // SArray + taosArrayClear(pFS->aQTaskInf); + uint32_t size = 0; + n += tGetU32v(pData + n, &size); + for (uint32_t i = 0; i < size; ++i) { + SQTaskFile qTaskF = {0}; + + int32_t nt = tdRSmaGetQTaskF(pData + n, &qTaskF); + if (nt < 0) { + code = TSDB_CODE_FILE_CORRUPTED; + goto _exit; + } - for (int32_t i = 0; i < taosArrayGetSize(output); ++i) { - int32_t vid = 0; - int64_t version = -1; - sscanf((const char *)taosArrayGetP(output, i), "v%dqinf.v%" PRIi64, &vid, &version); - SQTaskFile qTaskFile = {.version = version, .nRef = 1}; - if ((terrno = tdRSmaFSUpsertQTaskFile(RSMA_FS(pStat), &qTaskFile)) < 0) { - goto _end; + n += nt; + if (taosArrayPush(pFS->aQTaskInf, &qTaskF) == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; } - smaInfo("vgId:%d, open fs, version:%" PRIi64 ", ref:%d", TD_VID(pVnode), qTaskFile.version, qTaskFile.nRef); } -_end: - for (int32_t i = 0; i < taosArrayGetSize(output); ++i) { - void *ptr = taosArrayGetP(output, i); - taosMemoryFreeClear(ptr); + if (ASSERTS(n + sizeof(TSCKSUM) == nData, "n:%d + sizeof(TSCKSUM):%d != nData:%d", n, (int32_t)sizeof(TSCKSUM), + nData)) { + code = TSDB_CODE_FILE_CORRUPTED; + goto _exit; + } + +_exit: + return code; +} + +static int32_t tdRSmaSaveFSToFile(SRSmaFS *pFS, const char *fname) { + int32_t code = 0; + int32_t lino = 0; + + // encode to binary + int32_t size = tdRSmaFSToBinary(NULL, pFS) + sizeof(TSCKSUM); + uint8_t *pData = taosMemoryMalloc(size); + if (pData == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + tdRSmaFSToBinary(pData, pFS); + taosCalcChecksumAppend(0, pData, size); + + // save to file + TdFilePtr pFD = taosCreateFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC); + if (pFD == NULL) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + int64_t n = taosWriteFile(pFD, pData, size); + if (n < 0) { + code = TAOS_SYSTEM_ERROR(errno); + taosCloseFile(&pFD); + TSDB_CHECK_CODE(code, lino, _exit); + } + + if (taosFsyncFile(pFD) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + taosCloseFile(&pFD); + TSDB_CHECK_CODE(code, lino, _exit); + } + + taosCloseFile(&pFD); + +_exit: + if (pData) taosMemoryFree(pData); + if (code) { + smaError("%s failed at line %d since %s, fname:%s", __func__, lino, tstrerror(code), fname); + } + return code; +} + +static int32_t tdRSmaFSCreate(SRSmaFS *pFS, int32_t size) { + int32_t code = 0; + + pFS->aQTaskInf = taosArrayInit(size, sizeof(SQTaskFile)); + if (pFS->aQTaskInf == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; } - taosArrayDestroy(output); - if (terrno != TSDB_CODE_SUCCESS) { - smaError("vgId:%d, open rsma fs failed since %s", TD_VID(pVnode), terrstr()); - return TSDB_CODE_FAILED; +_exit: + return code; +} + +static void tdRSmaGetCurrentFName(SSma *pSma, char *current, char *current_t) { + SVnode *pVnode = pSma->pVnode; + if (pVnode->pTfs) { + if (current) { + snprintf(current, TSDB_FILENAME_LEN - 1, "%s%svnode%svnode%d%srsma%sPRESENT", tfsGetPrimaryPath(pVnode->pTfs), + TD_DIRSEP, TD_DIRSEP, TD_VID(pVnode), TD_DIRSEP, TD_DIRSEP); + } + if (current_t) { + snprintf(current_t, TSDB_FILENAME_LEN - 1, "%s%svnode%svnode%d%srsma%sPRESENT.t", tfsGetPrimaryPath(pVnode->pTfs), + TD_DIRSEP, TD_DIRSEP, TD_VID(pVnode), TD_DIRSEP, TD_DIRSEP); + } + } else { +#if 0 + if (current) { + snprintf(current, TSDB_FILENAME_LEN - 1, "%s%sPRESENT", pTsdb->path, TD_DIRSEP); + } + if (current_t) { + snprintf(current_t, TSDB_FILENAME_LEN - 1, "%s%sPRESENT.t", pTsdb->path, TD_DIRSEP); + } +#endif } - return TSDB_CODE_SUCCESS; } -void tdRSmaFSClose(SRSmaFS *fs) { taosArrayDestroy(fs->aQTaskInf); } +static int32_t tdRSmaLoadFSFromFile(const char *fname, SRSmaFS *pFS) { + int32_t code = 0; + int32_t lino = 0; + uint8_t *pData = NULL; + + // load binary + TdFilePtr pFD = taosOpenFile(fname, TD_FILE_READ); + if (pFD == NULL) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + int64_t size; + if (taosFStatFile(pFD, &size, NULL) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + taosCloseFile(&pFD); + TSDB_CHECK_CODE(code, lino, _exit); + } + + pData = taosMemoryMalloc(size); + if (pData == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + taosCloseFile(&pFD); + TSDB_CHECK_CODE(code, lino, _exit); + } + + if (taosReadFile(pFD, pData, size) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + taosCloseFile(&pFD); + TSDB_CHECK_CODE(code, lino, _exit); + } + + if (!taosCheckChecksumWhole(pData, size)) { + code = TSDB_CODE_FILE_CORRUPTED; + taosCloseFile(&pFD); + TSDB_CHECK_CODE(code, lino, _exit); + } + + taosCloseFile(&pFD); + + // decode binary + code = tsdbBinaryToFS(pData, size, pFS); + TSDB_CHECK_CODE(code, lino, _exit); + +_exit: + if (pData) taosMemoryFree(pData); + if (code) { + smaError("%s failed at line %d since %s, fname:%s", __func__, lino, tstrerror(code), fname); + } + return code; +} static int32_t tdQTaskInfCmprFn1(const void *p1, const void *p2) { - if (*(int64_t *)p1 < ((SQTaskFile *)p2)->version) { + const SQTaskFile *q1 = (const SQTaskFile *)p1; + const SQTaskFile *q2 = (const SQTaskFile *)p2; + + if (q1->suid < q2->suid) { + return -1; + } else if (q1->suid > q2->suid) { + return 1; + } + + if (q1->level < q2->level) { return -1; - } else if (*(int64_t *)p1 > ((SQTaskFile *)p2)->version) { + } else if (q1->level > q2->level) { + return 1; + } + + if (q1->version < q2->version) { + return -2; + } else if (q1->version > q2->version) { return 1; } + return 0; } -int32_t tdRSmaFSRef(SSma *pSma, SRSmaStat *pStat, int64_t version) { - SArray *aQTaskInf = RSMA_FS(pStat)->aQTaskInf; - SQTaskFile *pTaskF = NULL; - int32_t oldVal = 0; +static int32_t tdRSmaFSApplyChange(SSma *pSma, SRSmaFS *pFSNew) { + int32_t code = 0; + int32_t lino = 0; + int32_t nRef = 0; + SVnode *pVnode = pSma->pVnode; + SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); + SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); + SRSmaFS *pFSOld = RSMA_FS(pStat); + int64_t version = pStat->commitAppliedVer; + char fname[TSDB_FILENAME_LEN] = {0}; + + // SQTaskFile + int32_t nNew = taosArrayGetSize(pFSNew->aQTaskInf); + int32_t iNew = 0; + while (iNew < nNew) { + SQTaskFile *pQTaskFNew = TARRAY_GET_ELEM(pFSNew->aQTaskInf, iNew++); + + int32_t idx = taosArraySearchIdx(pFSOld->aQTaskInf, pQTaskFNew, tdQTaskInfCmprFn1, TD_GE); + + if (idx < 0) { + idx = taosArrayGetSize(pFSOld->aQTaskInf); + pQTaskFNew->nRef = 1; + } else { + SQTaskFile *pTaskF = TARRAY_GET_ELEM(pFSOld->aQTaskInf, idx); + int32_t c1 = tdQTaskInfCmprFn1(pQTaskFNew, pTaskF); + if (c1 == 0) { + // utilize the item in pFSOld->qQTaskInf, instead of pFSNew + continue; + } else if (c1 < 0) { + // NOTHING TODO + } else { + code = TSDB_CODE_RSMA_FS_UPDATE; + TSDB_CHECK_CODE(code, lino, _exit); + } + } - taosRLockLatch(RSMA_FS_LOCK(pStat)); - if ((pTaskF = taosArraySearch(aQTaskInf, &version, tdQTaskInfCmprFn1, TD_EQ))) { - oldVal = atomic_fetch_add_32(&pTaskF->nRef, 1); - ASSERT(oldVal > 0); + if (taosArrayInsert(pFSOld->aQTaskInf, idx, pQTaskFNew) == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + + // remove previous version + while (--idx >= 0) { + SQTaskFile *preTaskF = TARRAY_GET_ELEM(pFSOld->aQTaskInf, idx); + int32_t c2 = tdQTaskInfCmprFn1(preTaskF, pQTaskFNew); + if (c2 == 0) { + code = TSDB_CODE_RSMA_FS_UPDATE; + TSDB_CHECK_CODE(code, lino, _exit); + } else if (c2 != -2) { + break; + } + + nRef = atomic_sub_fetch_32(&preTaskF->nRef, 1); + if (nRef <= 0) { + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), preTaskF->suid, preTaskF->level, preTaskF->version, + tfsGetPrimaryPath(pVnode->pTfs), fname); + (void)taosRemoveFile(fname); + taosArrayRemove(pFSOld->aQTaskInf, idx); + } + } } - taosRUnLockLatch(RSMA_FS_LOCK(pStat)); - return oldVal; + +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } + return code; } -int64_t tdRSmaFSMaxVer(SSma *pSma, SRSmaStat *pStat) { - SArray *aQTaskInf = RSMA_FS(pStat)->aQTaskInf; - int64_t version = -1; +static int32_t tdRSmaFSScanAndTryFix(SSma *pSma) { + int32_t code = 0; +#if 0 + int32_t lino = 0; + SVnode *pVnode = pSma->pVnode; + SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); + SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); + SRSmaFS *pFS = RSMA_FS(pStat); + char fname[TSDB_FILENAME_LEN] = {0}; + char fnameVer[TSDB_FILENAME_LEN] = {0}; + + // SArray + int32_t size = taosArrayGetSize(pFS->aQTaskInf); + for (int32_t i = 0; i < size; ++i) { + SQTaskFile *pTaskF = (SQTaskFile *)taosArrayGet(pFS->aQTaskInf, i); + + // main.tdb ========= + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pTaskF->suid, pTaskF->level, pTaskF->version, + tfsGetPrimaryPath(pVnode->pTfs), fnameVer); + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pTaskF->suid, pTaskF->level, -1, tfsGetPrimaryPath(pVnode->pTfs), fname); + + if (taosCheckExistFile(fnameVer)) { + if (taosRenameFile(fnameVer, fname) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + smaDebug("vgId:%d, %s:%d succeed to to rename %s to %s", TD_VID(pVnode), __func__, lino, fnameVer, fname); + } else if (taosCheckExistFile(fname)) { + if (taosRemoveFile(fname) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + smaDebug("vgId:%d, %s:%d succeed to to remove %s", TD_VID(pVnode), __func__, lino, fname); + } + } - taosRLockLatch(RSMA_FS_LOCK(pStat)); - if (taosArrayGetSize(aQTaskInf) > 0) { - version = ((SQTaskFile *)taosArrayGetLast(aQTaskInf))->version; + { + // remove those invalid files (todo) + // main.tdb-journal.5 // TDB should handle its clear for kill -9 } - taosRUnLockLatch(RSMA_FS_LOCK(pStat)); - return version; + +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } +#endif + return code; } -void tdRSmaFSUnRef(SSma *pSma, SRSmaStat *pStat, int64_t version) { - SVnode *pVnode = pSma->pVnode; - SArray *aQTaskInf = RSMA_FS(pStat)->aQTaskInf; - char qTaskFullName[TSDB_FILENAME_LEN]; - SQTaskFile *pTaskF = NULL; - int32_t idx = -1; +// EXPOSED APIS ==================================================================================== - taosWLockLatch(RSMA_FS_LOCK(pStat)); - if ((idx = taosArraySearchIdx(aQTaskInf, &version, tdQTaskInfCmprFn1, TD_EQ)) >= 0) { - ASSERT(idx < taosArrayGetSize(aQTaskInf)); - pTaskF = taosArrayGet(aQTaskInf, idx); - if (atomic_sub_fetch_32(&pTaskF->nRef, 1) <= 0) { - tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pTaskF->version, tfsGetPrimaryPath(pVnode->pTfs), qTaskFullName); - if (taosRemoveFile(qTaskFullName) < 0) { - smaWarn("vgId:%d, failed to remove %s since %s", TD_VID(pVnode), qTaskFullName, - tstrerror(TAOS_SYSTEM_ERROR(errno))); +int32_t tdRSmaFSOpen(SSma *pSma, int64_t version, int8_t rollback) { + int32_t code = 0; + int32_t lino = 0; + SVnode *pVnode = pSma->pVnode; + SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); + SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); + + // open handle + code = tdRSmaFSCreate(RSMA_FS(pStat), 0); + TSDB_CHECK_CODE(code, lino, _exit); + + // open impl + char current[TSDB_FILENAME_LEN] = {0}; + char current_t[TSDB_FILENAME_LEN] = {0}; + tdRSmaGetCurrentFName(pSma, current, current_t); + + if (taosCheckExistFile(current)) { + code = tdRSmaLoadFSFromFile(current, RSMA_FS(pStat)); + TSDB_CHECK_CODE(code, lino, _exit); + + if (taosCheckExistFile(current_t)) { + if (rollback) { + code = tdRSmaFSRollback(pSma); + TSDB_CHECK_CODE(code, lino, _exit); } else { - smaDebug("vgId:%d, success to remove %s", TD_VID(pVnode), qTaskFullName); + code = tdRSmaFSCommit(pSma); + TSDB_CHECK_CODE(code, lino, _exit); } - taosArrayRemove(aQTaskInf, idx); } + } else { + // 1st time open with empty current/qTaskInfoFile + code = tdRSmaSaveFSToFile(RSMA_FS(pStat), current); + TSDB_CHECK_CODE(code, lino, _exit); } - taosWUnLockLatch(RSMA_FS_LOCK(pStat)); + + // scan and try fix(remove main.db/main.db.xxx and use the one with version) + code = tdRSmaFSScanAndTryFix(pSma); + TSDB_CHECK_CODE(code, lino, _exit); + +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } + return code; } -/** - * @brief Fetch qtaskfiles LE than version - * - * @param pSma - * @param version - * @param output - * @return int32_t - */ -static int32_t tdFetchQTaskInfoFiles(SSma *pSma, int64_t version, SArray **output) { - SVnode *pVnode = pSma->pVnode; - TdDirPtr pDir = NULL; - TdDirEntryPtr pDirEntry = NULL; - char dir[TSDB_FILENAME_LEN]; - const char *pattern = "v[0-9]+qinf\\.v([0-9]+)?$"; - regex_t regex; - int code = 0; - - terrno = TSDB_CODE_SUCCESS; - - tdGetVndDirName(TD_VID(pVnode), tfsGetPrimaryPath(pVnode->pTfs), VNODE_RSMA_DIR, true, dir); - - if (!taosCheckExistFile(dir)) { - smaDebug("vgId:%d, fetch qtask files, no need as dir %s not exist", TD_VID(pVnode), dir); - return TSDB_CODE_SUCCESS; - } - - // Resource allocation and init - if ((code = regcomp(®ex, pattern, REG_EXTENDED)) != 0) { - terrno = TSDB_CODE_RSMA_REGEX_MATCH; - char errbuf[128]; - regerror(code, ®ex, errbuf, sizeof(errbuf)); - smaWarn("vgId:%d, fetch qtask files, regcomp for %s failed since %s", TD_VID(pVnode), dir, errbuf); - return TSDB_CODE_FAILED; - } - - if (!(pDir = taosOpenDir(dir))) { - regfree(®ex); - terrno = TAOS_SYSTEM_ERROR(errno); - smaError("vgId:%d, fetch qtask files, open dir %s failed since %s", TD_VID(pVnode), dir, terrstr()); - return TSDB_CODE_FAILED; - } - - int32_t dirLen = strlen(dir); - char *dirEnd = POINTER_SHIFT(dir, dirLen); - regmatch_t regMatch[2]; - while ((pDirEntry = taosReadDir(pDir))) { - char *entryName = taosGetDirEntryName(pDirEntry); - if (!entryName) { - continue; - } +void tdRSmaFSClose(SRSmaFS *pFS) { pFS->aQTaskInf = taosArrayDestroy(pFS->aQTaskInf); } - code = regexec(®ex, entryName, 2, regMatch, 0); +int32_t tdRSmaFSPrepareCommit(SSma *pSma, SRSmaFS *pFSNew) { + int32_t code = 0; + int32_t lino = 0; + char tfname[TSDB_FILENAME_LEN]; - if (code == 0) { - // match - smaInfo("vgId:%d, fetch qtask files, max ver:%" PRIi64 ", %s found", TD_VID(pVnode), version, entryName); + tdRSmaGetCurrentFName(pSma, NULL, tfname); - int64_t ver = -1; - sscanf((const char *)POINTER_SHIFT(entryName, regMatch[1].rm_so), "%" PRIi64, &ver); - if ((ver <= version) && (ver > -1)) { - if (!(*output)) { - if (!(*output = taosArrayInit(1, POINTER_BYTES))) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - goto _end; - } - } - char *entryDup = strdup(entryName); - if (!entryDup) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - goto _end; - } - if (!taosArrayPush(*output, &entryDup)) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - goto _end; - } - } else { - } - } else if (code == REG_NOMATCH) { - // not match - smaTrace("vgId:%d, fetch qtask files, not match %s", TD_VID(pVnode), entryName); - continue; - } else { - // has other error - char errbuf[128]; - regerror(code, ®ex, errbuf, sizeof(errbuf)); - smaWarn("vgId:%d, fetch qtask files, regexec failed since %s", TD_VID(pVnode), errbuf); - terrno = TSDB_CODE_RSMA_REGEX_MATCH; - goto _end; - } + // generate PRESENT.t + code = tdRSmaSaveFSToFile(pFSNew, tfname); + TSDB_CHECK_CODE(code, lino, _exit); + +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pSma->pVnode), __func__, lino, tstrerror(code)); } -_end: - taosCloseDir(&pDir); - regfree(®ex); - return terrno == 0 ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED; + return code; } -static int32_t tdQTaskFileCmprFn2(const void *p1, const void *p2) { - if (((SQTaskFile *)p1)->version < ((SQTaskFile *)p2)->version) { - return -1; - } else if (((SQTaskFile *)p1)->version > ((SQTaskFile *)p2)->version) { - return 1; +int32_t tdRSmaFSCommit(SSma *pSma) { + int32_t code = 0; + int32_t lino = 0; + SRSmaFS fs = {0}; + + char current[TSDB_FILENAME_LEN] = {0}; + char current_t[TSDB_FILENAME_LEN] = {0}; + tdRSmaGetCurrentFName(pSma, current, current_t); + + if (!taosCheckExistFile(current_t)) { + goto _exit; } - return 0; + // rename the file + if (taosRenameFile(current_t, current) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + // load the new FS + code = tdRSmaFSCreate(&fs, 1); + TSDB_CHECK_CODE(code, lino, _exit); + + code = tdRSmaLoadFSFromFile(current, &fs); + TSDB_CHECK_CODE(code, lino, _exit); + + // apply file change + code = tdRSmaFSApplyChange(pSma, &fs); + TSDB_CHECK_CODE(code, lino, _exit); + +_exit: + tdRSmaFSClose(&fs); + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", SMA_VID(pSma), __func__, lino, tstrerror(code)); + } + return code; } -int32_t tdRSmaFSUpsertQTaskFile(SRSmaFS *pFS, SQTaskFile *qTaskFile) { - int32_t code = 0; - int32_t idx = taosArraySearchIdx(pFS->aQTaskInf, qTaskFile, tdQTaskFileCmprFn2, TD_GE); +int32_t tdRSmaFSFinishCommit(SSma *pSma) { + int32_t code = 0; + int32_t lino = 0; + SSmaEnv *pSmaEnv = SMA_RSMA_ENV(pSma); + SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pSmaEnv); - if (idx < 0) { - idx = taosArrayGetSize(pFS->aQTaskInf); + taosWLockLatch(RSMA_FS_LOCK(pStat)); + code = tdRSmaFSCommit(pSma); + TSDB_CHECK_CODE(code, lino, _exit); + +_exit: + taosWUnLockLatch(RSMA_FS_LOCK(pStat)); + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", SMA_VID(pSma), __func__, lino, tstrerror(code)); } else { - SQTaskFile *pTaskF = (SQTaskFile *)taosArrayGet(pFS->aQTaskInf, idx); - int32_t c = tdQTaskFileCmprFn2(pTaskF, qTaskFile); - if (c == 0) { - pTaskF->nRef = qTaskFile->nRef; - pTaskF->version = qTaskFile->version; - pTaskF->size = qTaskFile->size; + smaInfo("vgId:%d, rsmaFS finish commit", SMA_VID(pSma)); + } + return code; +} + +int32_t tdRSmaFSRollback(SSma *pSma) { + int32_t code = 0; + int32_t lino = 0; + + char current_t[TSDB_FILENAME_LEN] = {0}; + tdRSmaGetCurrentFName(pSma, NULL, current_t); + (void)taosRemoveFile(current_t); + +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", SMA_VID(pSma), __func__, lino, tstrerror(errno)); + } + return code; +} + +int32_t tdRSmaFSUpsertQTaskFile(SSma *pSma, SRSmaFS *pFS, SQTaskFile *qTaskFile, int32_t nSize) { + int32_t code = 0; + + for (int32_t i = 0; i < nSize; ++i) { + SQTaskFile *qTaskF = qTaskFile + i; + + int32_t idx = taosArraySearchIdx(pFS->aQTaskInf, qTaskF, tdQTaskInfCmprFn1, TD_GE); + + if (idx < 0) { + idx = taosArrayGetSize(pFS->aQTaskInf); + } else { + SQTaskFile *pTaskF = (SQTaskFile *)taosArrayGet(pFS->aQTaskInf, idx); + int32_t c = tdQTaskInfCmprFn1(pTaskF, qTaskF); + if (c == 0) { + if (pTaskF->size != qTaskF->size) { + code = TSDB_CODE_RSMA_FS_UPDATE; + smaError("vgId:%d, %s failed at line %d since %s, level:%" PRIi8 ", suid:%" PRIi64 ", version:%" PRIi64 + ", size:%" PRIi64 " != %" PRIi64, + SMA_VID(pSma), __func__, __LINE__, tstrerror(code), pTaskF->level, pTaskF->suid, pTaskF->version, + pTaskF->size, qTaskF->size); + goto _exit; + } + continue; + } + } + + if (!taosArrayInsert(pFS->aQTaskInf, idx, qTaskF)) { + code = TSDB_CODE_OUT_OF_MEMORY; goto _exit; } } - if (taosArrayInsert(pFS->aQTaskInf, idx, qTaskFile) == NULL) { +_exit: + return code; +} + +int32_t tdRSmaFSRef(SSma *pSma, SRSmaFS *pFS) { + int32_t code = 0; + int32_t lino = 0; + int32_t nRef = 0; + SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); + SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); + SRSmaFS *qFS = RSMA_FS(pStat); + int32_t size = taosArrayGetSize(qFS->aQTaskInf); + + pFS->aQTaskInf = taosArrayInit_s(sizeof(SQTaskFile), size); + if (pFS->aQTaskInf == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; + TSDB_CHECK_CODE(code, lino, _exit); } + for (int32_t i = 0; i < size; ++i) { + SQTaskFile *qTaskF = (SQTaskFile *)taosArrayGet(qFS->aQTaskInf, i); + nRef = atomic_fetch_add_32(&qTaskF->nRef, 1); + if (nRef <= 0) { + code = TSDB_CODE_RSMA_FS_REF; + TSDB_CHECK_CODE(code, lino, _exit); + } + } + + memcpy(pFS->aQTaskInf->pData, qFS->aQTaskInf->pData, size * sizeof(SQTaskFile)); + _exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s, nRef %d", TD_VID(pSma->pVnode), __func__, lino, tstrerror(code), + nRef); + } return code; -} \ No newline at end of file +} + +void tdRSmaFSUnRef(SSma *pSma, SRSmaFS *pFS) { + int32_t nRef = 0; + char fname[TSDB_FILENAME_LEN]; + SVnode *pVnode = pSma->pVnode; + SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); + SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); + int32_t size = taosArrayGetSize(pFS->aQTaskInf); + + for (int32_t i = 0; i < size; ++i) { + SQTaskFile *pTaskF = (SQTaskFile *)taosArrayGet(pFS->aQTaskInf, i); + + nRef = atomic_sub_fetch_32(&pTaskF->nRef, 1); + if (nRef == 0) { + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pTaskF->suid, pTaskF->level, pTaskF->version, + tfsGetPrimaryPath(pVnode->pTfs), fname); + if (taosRemoveFile(fname) < 0) { + smaWarn("vgId:%d, failed to remove %s since %s", TD_VID(pVnode), fname, tstrerror(TAOS_SYSTEM_ERROR(errno))); + } else { + smaDebug("vgId:%d, success to remove %s", TD_VID(pVnode), fname); + } + } else if (nRef < 0) { + smaWarn("vgId:%d, abnormal unref %s since %s", TD_VID(pVnode), fname, tstrerror(TSDB_CODE_RSMA_FS_REF)); + } + } + + taosArrayDestroy(pFS->aQTaskInf); +} + +int32_t tdRSmaFSTakeSnapshot(SSma *pSma, SRSmaFS *pFS) { + int32_t code = 0; + int32_t lino = 0; + SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); + SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); + + taosRLockLatch(RSMA_FS_LOCK(pStat)); + code = tdRSmaFSRef(pSma, pFS); + TSDB_CHECK_CODE(code, lino, _exit); +_exit: + taosRUnLockLatch(RSMA_FS_LOCK(pStat)); + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pSma->pVnode), __func__, lino, tstrerror(code)); + } + return code; +} + +int32_t tdRSmaFSCopy(SSma *pSma, SRSmaFS *pFS) { + int32_t code = 0; + int32_t lino = 0; + SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); + SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); + SRSmaFS *qFS = RSMA_FS(pStat); + int32_t size = taosArrayGetSize(qFS->aQTaskInf); + + code = tdRSmaFSCreate(pFS, size); + TSDB_CHECK_CODE(code, lino, _exit); + taosArrayAddBatch(pFS->aQTaskInf, qFS->aQTaskInf->pData, size); + +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pSma->pVnode), __func__, lino, tstrerror(code)); + } + return code; +} diff --git a/source/dnode/vnode/src/sma/smaOpen.c b/source/dnode/vnode/src/sma/smaOpen.c index 2a769b68fe0ff93caa48a6a22030ca02b2af7023..00000cb12914d7a0fbda6b2218c09c1726e51e17 100644 --- a/source/dnode/vnode/src/sma/smaOpen.c +++ b/source/dnode/vnode/src/sma/smaOpen.c @@ -34,13 +34,16 @@ static int32_t rsmaRestore(SSma *pSma); SRetention *r = (SRetention *)VND_RETENTIONS(v) + l; \ if (!RETENTION_VALID(r)) { \ if (l == 0) { \ - goto _err; \ + code = TSDB_CODE_INVALID_PARA; \ + TSDB_CHECK_CODE(code, lino, _exit); \ } \ break; \ } \ - smaSetKeepCfg(v, &keepCfg, pCfg, TSDB_TYPE_RSMA_L##l); \ + code = smaSetKeepCfg(v, &keepCfg, pCfg, TSDB_TYPE_RSMA_L##l); \ + TSDB_CHECK_CODE(code, lino, _exit); \ if (tsdbOpen(v, &SMA_RSMA_TSDB##l(pSma), VNODE_RSMA##l##_DIR, &keepCfg, rollback) < 0) { \ - goto _err; \ + code = terrno; \ + TSDB_CHECK_CODE(code, lino, _exit); \ } \ } while (0) @@ -68,12 +71,10 @@ static int32_t smaEvalDays(SVnode *pVnode, SRetention *r, int8_t level, int8_t p days = keepDuration; } - if (level == TSDB_RETENTION_L0) { - goto end; + if (level < TSDB_RETENTION_L1 || level > TSDB_RETENTION_L2) { + goto _exit; } - ASSERT(level >= TSDB_RETENTION_L1 && level <= TSDB_RETENTION_L2); - freqDuration = convertTimeFromPrecisionToUnit((r + level)->freq, precision, TIME_UNIT_MINUTE); keepDuration = convertTimeFromPrecisionToUnit((r + level)->keep, precision, TIME_UNIT_MINUTE); @@ -91,16 +92,18 @@ static int32_t smaEvalDays(SVnode *pVnode, SRetention *r, int8_t level, int8_t p if (days < freqDuration) { days = freqDuration; } -end: +_exit: smaInfo("vgId:%d, evaluated duration for level %d is %d, raw val:%d", TD_VID(pVnode), level + 1, days, duration); return days; } int smaSetKeepCfg(SVnode *pVnode, STsdbKeepCfg *pKeepCfg, STsdbCfg *pCfg, int type) { + terrno = 0; pKeepCfg->precision = pCfg->precision; switch (type) { case TSDB_TYPE_TSMA: - ASSERT(0); + ASSERTS(0, "undefined smaType:%d", (int32_t)type); + terrno = TSDB_CODE_APP_ERROR; break; case TSDB_TYPE_RSMA_L0: SMA_SET_KEEP_CFG(pVnode, 0); @@ -112,21 +115,22 @@ int smaSetKeepCfg(SVnode *pVnode, STsdbKeepCfg *pKeepCfg, STsdbCfg *pCfg, int ty SMA_SET_KEEP_CFG(pVnode, 2); break; default: - ASSERT(0); + ASSERTS(0, "unknown smaType:%d", (int32_t)type); + terrno = TSDB_CODE_APP_ERROR; break; } - return 0; + return terrno; } int32_t smaOpen(SVnode *pVnode, int8_t rollback) { + int32_t code = 0; + int32_t lino = 0; STsdbCfg *pCfg = &pVnode->config.tsdbCfg; - ASSERT(!pVnode->pSma); - SSma *pSma = taosMemoryCalloc(1, sizeof(SSma)); if (!pSma) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return -1; + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); } pVnode->pSma = pSma; @@ -137,31 +141,33 @@ int32_t smaOpen(SVnode *pVnode, int8_t rollback) { if (VND_IS_RSMA(pVnode)) { STsdbKeepCfg keepCfg = {0}; - for (int i = 0; i < TSDB_RETENTION_MAX; ++i) { + for (int32_t i = 0; i < TSDB_RETENTION_MAX; ++i) { if (i == TSDB_RETENTION_L0) { SMA_OPEN_RSMA_IMPL(pVnode, 0); } else if (i == TSDB_RETENTION_L1) { SMA_OPEN_RSMA_IMPL(pVnode, 1); } else if (i == TSDB_RETENTION_L2) { SMA_OPEN_RSMA_IMPL(pVnode, 2); - } else { - ASSERT(0); } } // restore the rsma - if (tdRSmaRestore(pSma, RSMA_RESTORE_REBOOT, pVnode->state.committed) < 0) { - goto _err; + if (tdRSmaRestore(pSma, RSMA_RESTORE_REBOOT, pVnode->state.committed, rollback) < 0) { + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } } - return 0; -_err: - return -1; +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } + return code; } int32_t smaClose(SSma *pSma) { if (pSma) { + smaPreClose(pSma); taosThreadMutexDestroy(&pSma->mutex); SMA_TSMA_ENV(pSma) = tdFreeSmaEnv(SMA_TSMA_ENV(pSma)); SMA_RSMA_ENV(pSma) = tdFreeSmaEnv(SMA_RSMA_ENV(pSma)); @@ -181,8 +187,11 @@ int32_t smaClose(SSma *pSma) { * @param committedVer * @return int32_t */ -int32_t tdRSmaRestore(SSma *pSma, int8_t type, int64_t committedVer) { - ASSERT(VND_IS_RSMA(pSma->pVnode)); +int32_t tdRSmaRestore(SSma *pSma, int8_t type, int64_t committedVer, int8_t rollback) { + if (!VND_IS_RSMA(pSma->pVnode)) { + terrno = TSDB_CODE_RSMA_INVALID_ENV; + return TSDB_CODE_FAILED; + } - return tdRSmaProcessRestoreImpl(pSma, type, committedVer); + return tdRSmaProcessRestoreImpl(pSma, type, committedVer, rollback); } diff --git a/source/dnode/vnode/src/sma/smaRollup.c b/source/dnode/vnode/src/sma/smaRollup.c index ba99e5515d8b0b15892da433c80305477ab98dd4..20e04f122b20931b2f77e3b74b2605362a45655a 100644 --- a/source/dnode/vnode/src/sma/smaRollup.c +++ b/source/dnode/vnode/src/sma/smaRollup.c @@ -21,17 +21,17 @@ #define RSMA_FETCH_ACTIVE_MAX (1000) // ms #define RSMA_FETCH_INTERVAL (5000) // ms +#define RSMA_NEED_FETCH(r) (RSMA_INFO_ITEM((r), 0)->fetchLevel || RSMA_INFO_ITEM((r), 1)->fetchLevel) + SSmaMgmt smaMgmt = { .inited = 0, .rsetId = -1, }; -#define TD_QTASKINFO_FNAME_PREFIX "qinf.v" - typedef struct SRSmaQTaskInfoItem SRSmaQTaskInfoItem; -typedef struct SRSmaQTaskInfoIter SRSmaQTaskInfoIter; static int32_t tdUidStorePut(STbUidStore *pStore, tb_uid_t suid, tb_uid_t *uid); +static void tdUidStoreDestory(STbUidStore *pStore); static int32_t tdUpdateTbUidListImpl(SSma *pSma, tb_uid_t *suid, SArray *tbUids, bool isAdd); static int32_t tdSetRSmaInfoItemParams(SSma *pSma, SRSmaParam *param, SRSmaStat *pStat, SRSmaInfo *pRSmaInfo, int8_t idx); @@ -57,38 +57,6 @@ struct SRSmaQTaskInfoItem { void *qTaskInfo; }; -struct SRSmaQTaskInfoIter { - STFile *pTFile; - int64_t offset; - int64_t fsize; - int32_t nBytes; - int32_t nAlloc; - char *pBuf; - // ------------ - char *qBuf; // for iterator - int32_t nBufPos; -}; - -void tdRSmaQTaskInfoGetFileName(int32_t vgId, int64_t version, char *outputName) { - tdGetVndFileName(vgId, NULL, VNODE_RSMA_DIR, TD_QTASKINFO_FNAME_PREFIX, version, outputName); -} - -void tdRSmaQTaskInfoGetFullName(int32_t vgId, int64_t version, const char *path, char *outputName) { - tdGetVndFileName(vgId, path, VNODE_RSMA_DIR, TD_QTASKINFO_FNAME_PREFIX, version, outputName); -} - -void tdRSmaQTaskInfoGetFullPath(int32_t vgId, int8_t level, const char *path, char *outputName) { - tdGetVndDirName(vgId, path, VNODE_RSMA_DIR, true, outputName); - int32_t rsmaLen = strlen(outputName); - snprintf(outputName + rsmaLen, TSDB_FILENAME_LEN - rsmaLen, "%" PRIi8, level); -} - -void tdRSmaQTaskInfoGetFullPathEx(int32_t vgId, tb_uid_t suid, int8_t level, const char *path, char *outputName) { - tdGetVndDirName(vgId, path, VNODE_RSMA_DIR, true, outputName); - int32_t rsmaLen = strlen(outputName); - snprintf(outputName + rsmaLen, TSDB_FILENAME_LEN - rsmaLen, "%" PRIi64 "%s%" PRIi8, suid, TD_DIRSEP, level); -} - static void tdRSmaQTaskInfoFree(qTaskInfo_t *taskHandle, int32_t vgId, int32_t level) { // Note: free/kill may in RC if (!taskHandle || !(*taskHandle)) return; @@ -161,12 +129,17 @@ void *tdFreeRSmaInfo(SSma *pSma, SRSmaInfo *pInfo, bool isDeepFree) { } static FORCE_INLINE int32_t tdUidStoreInit(STbUidStore **pStore) { - ASSERT(*pStore == NULL); + if (ASSERTS(*pStore == NULL, "*pStore:%p != NULL", *pStore)) { + terrno = TSDB_CODE_APP_ERROR; + return TSDB_CODE_FAILED; + } + *pStore = taosMemoryCalloc(1, sizeof(STbUidStore)); if (*pStore == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return TSDB_CODE_FAILED; } + return TSDB_CODE_SUCCESS; } @@ -195,15 +168,14 @@ static int32_t tdUpdateTbUidListImpl(SSma *pSma, tb_uid_t *suid, SArray *tbUids, for (int32_t i = 0; i < TSDB_RETENTION_L2; ++i) { if (pRSmaInfo->taskInfo[i]) { - if (((terrno = qUpdateQualifiedTableId(pRSmaInfo->taskInfo[i], tbUids, isAdd)) < 0)) { + if ((terrno = qUpdateTableListForStreamScanner(pRSmaInfo->taskInfo[i], tbUids, isAdd)) < 0) { tdReleaseRSmaInfo(pSma, pRSmaInfo); smaError("vgId:%d, update tbUidList failed for uid:%" PRIi64 " level %d since %s", SMA_VID(pSma), *suid, i, terrstr()); return TSDB_CODE_FAILED; - } else { - smaDebug("vgId:%d, update tbUidList succeed for qTaskInfo:%p with suid:%" PRIi64 " uid:%" PRIi64 " level %d", - SMA_VID(pSma), pRSmaInfo->taskInfo[0], *suid, *(int64_t *)taosArrayGet(tbUids, 0), i); } + smaDebug("vgId:%d, update tbUidList succeed for qTaskInfo:%p with suid:%" PRIi64 " uid:%" PRIi64 " level %d", + SMA_VID(pSma), pRSmaInfo->taskInfo[i], *suid, *(int64_t *)taosArrayGet(tbUids, 0), i); } } @@ -264,8 +236,6 @@ int32_t tdFetchTbUidList(SSma *pSma, STbUidStore **ppStore, tb_uid_t suid, tb_ui return TSDB_CODE_SUCCESS; } - ASSERT(ppStore != NULL); - if (!(*ppStore)) { if (tdUidStoreInit(ppStore) < 0) { return TSDB_CODE_FAILED; @@ -292,7 +262,7 @@ static int32_t tdSetRSmaInfoItemParams(SSma *pSma, SRSmaParam *param, SRSmaStat // set the backend of stream state tdRSmaQTaskInfoGetFullPathEx(TD_VID(pVnode), pRSmaInfo->suid, idx + 1, tfsGetPrimaryPath(pVnode->pTfs), taskInfDir); if (!taosCheckExistFile(taskInfDir)) { - char *s = strdup(taskInfDir); + char *s = taosStrdup(taskInfDir); if (taosMulMkDir(taosDirName(s)) != 0) { terrno = TAOS_SYSTEM_ERROR(errno); taosMemoryFree(s); @@ -312,7 +282,7 @@ static int32_t tdSetRSmaInfoItemParams(SSma *pSma, SRSmaParam *param, SRSmaStat .initTqReader = 1, .pStateBackend = pStreamState, }; - pRSmaInfo->taskInfo[idx] = qCreateStreamExecTaskInfo(param->qmsg[idx], &handle); + pRSmaInfo->taskInfo[idx] = qCreateStreamExecTaskInfo(param->qmsg[idx], &handle, TD_VID(pVnode)); if (!pRSmaInfo->taskInfo[idx]) { terrno = TSDB_CODE_RSMA_QTASKINFO_CREATE; return TSDB_CODE_FAILED; @@ -332,12 +302,15 @@ static int32_t tdSetRSmaInfoItemParams(SSma *pSma, SRSmaParam *param, SRSmaStat } pItem->level = idx == 0 ? TSDB_RETENTION_L1 : TSDB_RETENTION_L2; - ASSERT(pItem->level > 0); + + if (ASSERTS(pItem->level > 0, "pItem level:%" PRIi8 " should > 0", pItem->level)) { + terrno = TSDB_CODE_APP_ERROR; + return TSDB_CODE_FAILED; + } SRSmaRef rsmaRef = {.refId = pStat->refId, .suid = pRSmaInfo->suid}; taosHashPut(smaMgmt.refHash, &pItem, POINTER_BYTES, &rsmaRef, sizeof(rsmaRef)); - pItem->fetchLevel = pItem->level; taosTmrReset(tdRSmaFetchTrigger, RSMA_FETCH_INTERVAL, pItem, smaMgmt.tmrHandle, &pItem->tmrId); smaInfo("vgId:%d, item:%p table:%" PRIi64 " level:%" PRIi8 " maxdelay:%" PRIi64 " watermark:%" PRIi64 @@ -363,10 +336,12 @@ int32_t tdRSmaProcessCreateImpl(SSma *pSma, SRSmaParam *param, int64_t suid, con return TSDB_CODE_SUCCESS; } +#if 0 if (tdCheckAndInitSmaEnv(pSma, TSDB_SMA_TYPE_ROLLUP) != TSDB_CODE_SUCCESS) { terrno = TSDB_CODE_TDB_INIT_FAILED; return TSDB_CODE_FAILED; } +#endif SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); SRSmaStat *pStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); @@ -374,13 +349,8 @@ int32_t tdRSmaProcessCreateImpl(SSma *pSma, SRSmaParam *param, int64_t suid, con pRSmaInfo = taosHashGet(RSMA_INFO_HASH(pStat), &suid, sizeof(tb_uid_t)); if (pRSmaInfo) { - // TODO: free original pRSmaInfo if exists abnormally - tdFreeRSmaInfo(pSma, *(SRSmaInfo **)pRSmaInfo, true); - if (taosHashRemove(RSMA_INFO_HASH(pStat), &suid, sizeof(tb_uid_t)) < 0) { - terrno = TSDB_CODE_RSMA_REMOVE_EXISTS; - goto _err; - } - smaWarn("vgId:%d, remove the rsma info already exists for table %s, %" PRIi64, SMA_VID(pSma), tbName, suid); + smaInfo("vgId:%d, rsma info already exists for table %s, %" PRIi64, SMA_VID(pSma), tbName, suid); + return TSDB_CODE_SUCCESS; } // from write queue: single thead @@ -449,8 +419,8 @@ int32_t tdProcessRSmaCreate(SSma *pSma, SVCreateStbReq *pReq) { } if (!VND_IS_RSMA(pVnode)) { - smaTrace("vgId:%d, not create rsma for stable %s %" PRIi64 " since vnd is not rsma", TD_VID(pVnode), pReq->name, - pReq->suid); + smaWarn("vgId:%d, not create rsma for stable %s %" PRIi64 " since vnd is not rsma", TD_VID(pVnode), pReq->name, + pReq->suid); return TSDB_CODE_SUCCESS; } @@ -494,9 +464,8 @@ int32_t tdProcessRSmaDrop(SSma *pSma, SVDropStbReq *pReq) { tdReleaseRSmaInfo(pSma, pRSmaInfo); - // save to file - // TODO - smaDebug("vgId:%d, drop rsma for table %" PRIi64 " succeed", TD_VID(pVnode), pReq->suid); + // no need to save to file as triggered by dropping stable + smaDebug("vgId:%d, drop rsma for stable %" PRIi64 " succeed", TD_VID(pVnode), pReq->suid); return TSDB_CODE_SUCCESS; } @@ -561,7 +530,7 @@ static int32_t tdUidStorePut(STbUidStore *pStore, tb_uid_t suid, tb_uid_t *uid) return TSDB_CODE_SUCCESS; } -void tdUidStoreDestory(STbUidStore *pStore) { +static void tdUidStoreDestory(STbUidStore *pStore) { if (pStore) { if (pStore->uidHash) { if (pStore->tbUids) { @@ -601,8 +570,8 @@ static int32_t tdProcessSubmitReq(STsdb *pTsdb, int64_t version, void *pReq) { return TSDB_CODE_FAILED; } - SSubmitReq *pSubmitReq = (SSubmitReq *)pReq; - // TODO: spin lock for race conditiond + SSubmitReq2 *pSubmitReq = (SSubmitReq2 *)pReq; + // spin lock for race condition during insert data if (tsdbInsertData(pTsdb, version, pSubmitReq, NULL) < 0) { return TSDB_CODE_FAILED; } @@ -610,32 +579,23 @@ static int32_t tdProcessSubmitReq(STsdb *pTsdb, int64_t version, void *pReq) { return TSDB_CODE_SUCCESS; } -static int32_t tdFetchSubmitReqSuids(SSubmitReq *pMsg, STbUidStore *pStore) { - SSubmitMsgIter msgIter = {0}; - SSubmitBlk *pBlock = NULL; - SSubmitBlkIter blkIter = {0}; - STSRow *row = NULL; +static int32_t tdFetchSubmitReqSuids(SSubmitReq2 *pMsg, STbUidStore *pStore) { + SArray *pSubmitTbData = pMsg ? pMsg->aSubmitTbData : NULL; + int32_t size = taosArrayGetSize(pSubmitTbData); terrno = TSDB_CODE_SUCCESS; - if (tInitSubmitMsgIter(pMsg, &msgIter) < 0) { - return -1; - } - while (true) { - if (tGetSubmitMsgNext(&msgIter, &pBlock) < 0) { + for (int32_t i = 0; i < size; ++i) { + SSubmitTbData *pData = TARRAY_GET_ELEM(pSubmitTbData, i); + if ((terrno = tdUidStorePut(pStore, pData->suid, NULL)) < 0) { return -1; } - - if (!pBlock) break; - tdUidStorePut(pStore, msgIter.suid, NULL); } - if (terrno != TSDB_CODE_SUCCESS) { - return -1; - } return 0; } +#if 0 /** * @brief retention of rsma1/rsma2 * @@ -659,6 +619,7 @@ int32_t smaDoRetention(SSma *pSma, int64_t now) { _end: return code; } +#endif static void tdBlockDataDestroy(SArray *pBlockArr) { for (int32_t i = 0; i < taosArrayGetSize(pBlockArr); ++i) { @@ -708,14 +669,14 @@ static int32_t tdRSmaExecAndSubmitResult(SSma *pSma, qTaskInfo_t taskInfo, SRSma #endif for (int32_t i = 0; i < taosArrayGetSize(pResList); ++i) { SSDataBlock *output = taosArrayGetP(pResList, i); - smaDebug("result block, uid:%" PRIu64 ", groupid:%" PRIu64 ", rows:%d", output->info.id.uid, output->info.id.groupId, - output->info.rows); + smaDebug("result block, uid:%" PRIu64 ", groupid:%" PRIu64 ", rows:%" PRId64, output->info.id.uid, + output->info.id.groupId, output->info.rows); - STsdb *sinkTsdb = (pItem->level == TSDB_RETENTION_L1 ? pSma->pRSmaTsdb[0] : pSma->pRSmaTsdb[1]); - SSubmitReq *pReq = NULL; + STsdb *sinkTsdb = (pItem->level == TSDB_RETENTION_L1 ? pSma->pRSmaTsdb[0] : pSma->pRSmaTsdb[1]); + SSubmitReq2 *pReq = NULL; // TODO: the schema update should be handled later(TD-17965) - if (buildSubmitReqFromDataBlock(&pReq, output, pTSchema, SMA_VID(pSma), suid) < 0) { + if (buildSubmitReqFromDataBlock(&pReq, output, pTSchema, output->info.id.groupId, SMA_VID(pSma), suid) < 0) { smaError("vgId:%d, build submit req for rsma table suid:%" PRIu64 ", uid:%" PRIu64 ", level %" PRIi8 " failed since %s", SMA_VID(pSma), suid, output->info.id.groupId, pItem->level, terrstr()); @@ -723,19 +684,21 @@ static int32_t tdRSmaExecAndSubmitResult(SSma *pSma, qTaskInfo_t taskInfo, SRSma } if (pReq && tdProcessSubmitReq(sinkTsdb, output->info.version, pReq) < 0) { - taosMemoryFreeClear(pReq); + tDestroySubmitReq(pReq, TSDB_MSG_FLG_ENCODE); + taosMemoryFree(pReq); smaError("vgId:%d, process submit req for rsma suid:%" PRIu64 ", uid:%" PRIu64 " level %" PRIi8 " failed since %s", SMA_VID(pSma), suid, output->info.id.groupId, pItem->level, terrstr()); goto _err; } - smaDebug("vgId:%d, process submit req for rsma suid:%" PRIu64 ",uid:%" PRIu64 ", level %" PRIi8 " ver %" PRIi64 - " len %" PRIu32, - SMA_VID(pSma), suid, output->info.id.groupId, pItem->level, output->info.version, - htonl(pReq->header.contLen)); + smaDebug("vgId:%d, process submit req for rsma suid:%" PRIu64 ",uid:%" PRIu64 ", level %" PRIi8 " ver %" PRIi64, + SMA_VID(pSma), suid, output->info.id.groupId, pItem->level, output->info.version); - taosMemoryFreeClear(pReq); + if (pReq) { + tDestroySubmitReq(pReq, TSDB_MSG_FLG_ENCODE); + taosMemoryFree(pReq); + } } } @@ -753,22 +716,29 @@ _err: * @brief Copy msg to rsmaQueueBuffer for batch process * * @param pSma + * @param version * @param pMsg + * @param len * @param inputType * @param pInfo * @param suid * @return int32_t */ -static int32_t tdExecuteRSmaImplAsync(SSma *pSma, const void *pMsg, int32_t inputType, SRSmaInfo *pInfo, - tb_uid_t suid) { - const SSubmitReq *pReq = (const SSubmitReq *)pMsg; +static int32_t tdExecuteRSmaImplAsync(SSma *pSma, int64_t version, const void *pMsg, int32_t len, int32_t inputType, + SRSmaInfo *pInfo, tb_uid_t suid) { + int32_t size = sizeof(int32_t) + sizeof(int64_t) + len; + void *qItem = taosAllocateQitem(size, DEF_QITEM, 0); - void *qItem = taosAllocateQitem(pReq->header.contLen, DEF_QITEM, 0); if (!qItem) { return TSDB_CODE_FAILED; } - memcpy(qItem, pMsg, pReq->header.contLen); + void *pItem = qItem; + + *(int32_t *)pItem = len; + pItem = POINTER_SHIFT(pItem, sizeof(int32_t)); + *(int64_t *)pItem = version; + memcpy(POINTER_SHIFT(pItem, sizeof(int64_t)), pMsg, len); taosWriteQitem(pInfo->queue, qItem); @@ -840,12 +810,13 @@ static int32_t tdExecuteRSmaImpl(SSma *pSma, const void *pMsg, int32_t msgSize, return TSDB_CODE_SUCCESS; } if (!pInfo->pTSchema) { + terrno = TSDB_CODE_INVALID_PTR; smaWarn("vgId:%d, no schema to execute rsma %" PRIi8 " task for suid:%" PRIu64, SMA_VID(pSma), level, pInfo->suid); return TSDB_CODE_FAILED; } - smaDebug("vgId:%d, execute rsma %" PRIi8 " task for qTaskInfo:%p suid:%" PRIu64, SMA_VID(pSma), level, - RSMA_INFO_QTASK(pInfo, idx), pInfo->suid); + smaDebug("vgId:%d, execute rsma %" PRIi8 " task for qTaskInfo:%p suid:%" PRIu64 " nMsg:%d", SMA_VID(pSma), level, + RSMA_INFO_QTASK(pInfo, idx), pInfo->suid, msgSize); #if 0 for (int32_t i = 0; i < msgSize; ++i) { @@ -854,7 +825,7 @@ static int32_t tdExecuteRSmaImpl(SSma *pSma, const void *pMsg, int32_t msgSize, tdRsmaPrintSubmitReq(pSma, pReq); } #endif - if (qSetSMAInput(qTaskInfo, pMsg, msgSize, inputType) < 0) { + if ((terrno = qSetSMAInput(qTaskInfo, pMsg, msgSize, inputType)) < 0) { smaError("vgId:%d, rsma %" PRIi8 " qSetStreamInput failed since %s", SMA_VID(pSma), level, tstrerror(terrno)); return TSDB_CODE_FAILED; } @@ -867,44 +838,51 @@ static int32_t tdExecuteRSmaImpl(SSma *pSma, const void *pMsg, int32_t msgSize, static int32_t tdCloneQTaskInfo(SSma *pSma, qTaskInfo_t dstTaskInfo, qTaskInfo_t srcTaskInfo, SRSmaParam *param, tb_uid_t suid, int8_t idx) { + int32_t code = 0; + int32_t lino = 0; SVnode *pVnode = pSma->pVnode; char *pOutput = NULL; int32_t len = 0; - if ((terrno = qSerializeTaskStatus(srcTaskInfo, &pOutput, &len)) < 0) { - smaError("vgId:%d, rsma clone, table %" PRIi64 " serialize qTaskInfo failed since %s", TD_VID(pVnode), suid, - terrstr()); - goto _err; + if (!srcTaskInfo) { + code = TSDB_CODE_INVALID_PTR; + smaWarn("vgId:%d, rsma clone, table %" PRIi64 ", no need since srcTaskInfo is NULL", TD_VID(pVnode), suid); + TSDB_CHECK_CODE(code, lino, _exit); } + code = qSerializeTaskStatus(srcTaskInfo, &pOutput, &len); + TSDB_CHECK_CODE(code, lino, _exit); + SReadHandle handle = { .meta = pVnode->pMeta, .vnode = pVnode, .initTqReader = 1, }; - ASSERT(!dstTaskInfo); - dstTaskInfo = qCreateStreamExecTaskInfo(param->qmsg[idx], &handle); - if (!dstTaskInfo) { - terrno = TSDB_CODE_RSMA_QTASKINFO_CREATE; - goto _err; + + if (ASSERTS(!dstTaskInfo, "dstTaskInfo:%p is not NULL", dstTaskInfo)) { + code = TSDB_CODE_APP_ERROR; + TSDB_CHECK_CODE(code, lino, _exit); } - if (qDeserializeTaskStatus(dstTaskInfo, pOutput, len) < 0) { - smaError("vgId:%d, rsma clone, restore rsma task for table:%" PRIi64 " failed since %s", TD_VID(pVnode), suid, - terrstr()); - goto _err; + dstTaskInfo = qCreateStreamExecTaskInfo(param->qmsg[idx], &handle, TD_VID(pVnode)); + if (!dstTaskInfo) { + code = TSDB_CODE_RSMA_QTASKINFO_CREATE; + TSDB_CHECK_CODE(code, lino, _exit); } + code = qDeserializeTaskStatus(dstTaskInfo, pOutput, len); + TSDB_CHECK_CODE(code, lino, _exit); + smaDebug("vgId:%d, rsma clone, restore rsma task for table:%" PRIi64 " succeed", TD_VID(pVnode), suid); +_exit: taosMemoryFreeClear(pOutput); - return TSDB_CODE_SUCCESS; -_err: - taosMemoryFreeClear(pOutput); - tdRSmaQTaskInfoFree(dstTaskInfo, TD_VID(pVnode), idx + 1); - smaError("vgId:%d, rsma clone, restore rsma task for table:%" PRIi64 " failed since %s", TD_VID(pVnode), suid, - terrstr()); - return TSDB_CODE_FAILED; + if (code) { + tdRSmaQTaskInfoFree(dstTaskInfo, TD_VID(pVnode), idx + 1); + smaError("vgId:%d, rsma clone, restore rsma task for table:%" PRIi64 " failed since %s", TD_VID(pVnode), suid, + terrstr()); + } + return code; } /** @@ -915,43 +893,53 @@ _err: * @return int32_t */ static int32_t tdRSmaInfoClone(SSma *pSma, SRSmaInfo *pInfo) { + int32_t code = 0; + int32_t lino = 0; SRSmaParam *param = NULL; + SMetaReader mr = {0}; + if (!pInfo) { return TSDB_CODE_SUCCESS; } - SMetaReader mr = {0}; metaReaderInit(&mr, SMA_META(pSma), 0); smaDebug("vgId:%d, rsma clone qTaskInfo for suid:%" PRIi64, SMA_VID(pSma), pInfo->suid); if (metaGetTableEntryByUidCache(&mr, pInfo->suid) < 0) { - smaError("vgId:%d, rsma clone, failed to get table meta for %" PRIi64 " since %s", SMA_VID(pSma), pInfo->suid, - terrstr()); - goto _err; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); + } + + if (mr.me.type != TSDB_SUPER_TABLE) { + code = TSDB_CODE_RSMA_INVALID_SCHEMA; + TSDB_CHECK_CODE(code, lino, _exit); + } + if (mr.me.uid != pInfo->suid) { + code = TSDB_CODE_RSMA_INVALID_SCHEMA; + TSDB_CHECK_CODE(code, lino, _exit); } - ASSERT(mr.me.type == TSDB_SUPER_TABLE); - ASSERT(mr.me.uid == pInfo->suid); + if (TABLE_IS_ROLLUP(mr.me.flags)) { param = &mr.me.stbEntry.rsmaParam; for (int32_t i = 0; i < TSDB_RETENTION_L2; ++i) { if (!pInfo->iTaskInfo[i]) { continue; } - if (tdCloneQTaskInfo(pSma, pInfo->taskInfo[i], pInfo->iTaskInfo[i], param, pInfo->suid, i) < 0) { - goto _err; - } + code = tdCloneQTaskInfo(pSma, pInfo->taskInfo[i], pInfo->iTaskInfo[i], param, pInfo->suid, i); + TSDB_CHECK_CODE(code, lino, _exit); } smaDebug("vgId:%d, rsma clone env success for %" PRIi64, SMA_VID(pSma), pInfo->suid); } else { - terrno = TSDB_CODE_RSMA_INVALID_SCHEMA; - goto _err; + code = TSDB_CODE_RSMA_INVALID_SCHEMA; + TSDB_CHECK_CODE(code, lino, _exit); } +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s, suid:%" PRIi64 ", flags:%" PRIi8 ",type:%" PRIi8 ", uid:%" PRIi64, + SMA_VID(pSma), __func__, lino, tstrerror(code), pInfo->suid, mr.me.flags, mr.me.type, mr.me.uid); + } metaReaderClear(&mr); - return TSDB_CODE_SUCCESS; -_err: - metaReaderClear(&mr); - smaError("vgId:%d, rsma clone env failed for %" PRIi64 " since %s", SMA_VID(pSma), pInfo->suid, terrstr()); - return TSDB_CODE_FAILED; + return code; } /** @@ -962,10 +950,14 @@ _err: * @return SRSmaInfo* */ static SRSmaInfo *tdAcquireRSmaInfoBySuid(SSma *pSma, int64_t suid) { + int32_t code = 0; + int32_t lino = 0; SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); SRSmaStat *pStat = NULL; SRSmaInfo *pRSmaInfo = NULL; + terrno = 0; + if (!pEnv) { terrno = TSDB_CODE_RSMA_INVALID_ENV; return NULL; @@ -985,14 +977,17 @@ static SRSmaInfo *tdAcquireRSmaInfoBySuid(SSma *pSma, int64_t suid) { return NULL; } if (!pRSmaInfo->taskInfo[0]) { - if (tdRSmaInfoClone(pSma, pRSmaInfo) < 0) { + if ((terrno = tdRSmaInfoClone(pSma, pRSmaInfo)) < 0) { taosRUnLockLatch(SMA_ENV_LOCK(pEnv)); return NULL; } } tdRefRSmaInfo(pSma, pRSmaInfo); taosRUnLockLatch(SMA_ENV_LOCK(pEnv)); - ASSERT(pRSmaInfo->suid == suid); + if (ASSERTS(pRSmaInfo->suid == suid, "suid:%" PRIi64 " != %" PRIi64, pRSmaInfo->suid, suid)) { + terrno = TSDB_CODE_APP_ERROR; + return NULL; + } return pRSmaInfo; } taosRUnLockLatch(SMA_ENV_LOCK(pEnv)); @@ -1010,12 +1005,14 @@ static FORCE_INLINE void tdReleaseRSmaInfo(SSma *pSma, SRSmaInfo *pInfo) { * @brief async mode * * @param pSma + * @param version * @param pMsg * @param inputType * @param suid * @return int32_t */ -static int32_t tdExecuteRSmaAsync(SSma *pSma, const void *pMsg, int32_t inputType, tb_uid_t suid) { +static int32_t tdExecuteRSmaAsync(SSma *pSma, int64_t version, const void *pMsg, int32_t len, int32_t inputType, + tb_uid_t suid) { SRSmaInfo *pRSmaInfo = tdAcquireRSmaInfoBySuid(pSma, suid); if (!pRSmaInfo) { smaDebug("vgId:%d, execute rsma, no rsma info for suid:%" PRIu64, SMA_VID(pSma), suid); @@ -1023,7 +1020,7 @@ static int32_t tdExecuteRSmaAsync(SSma *pSma, const void *pMsg, int32_t inputTyp } if (inputType == STREAM_INPUT__DATA_SUBMIT) { - if (tdExecuteRSmaImplAsync(pSma, pMsg, inputType, pRSmaInfo, suid) < 0) { + if (tdExecuteRSmaImplAsync(pSma, version, pMsg, len, inputType, pRSmaInfo, suid) < 0) { tdReleaseRSmaInfo(pSma, pRSmaInfo); return TSDB_CODE_FAILED; } @@ -1038,40 +1035,43 @@ static int32_t tdExecuteRSmaAsync(SSma *pSma, const void *pMsg, int32_t inputTyp } } } else { - ASSERT(0); + terrno = TSDB_CODE_APP_ERROR; + tdReleaseRSmaInfo(pSma, pRSmaInfo); + smaError("vgId:%d, execute rsma, failed for suid:%" PRIu64 " since %s, type:%d", SMA_VID(pSma), suid, + tstrerror(terrno), inputType); + return TSDB_CODE_FAILED; } tdReleaseRSmaInfo(pSma, pRSmaInfo); return TSDB_CODE_SUCCESS; } -int32_t tdProcessRSmaSubmit(SSma *pSma, void *pMsg, int32_t inputType) { +int32_t tdProcessRSmaSubmit(SSma *pSma, int64_t version, void *pReq, void *pMsg, int32_t len, int32_t inputType) { SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); if (!pEnv) { // only applicable when rsma env exists return TSDB_CODE_SUCCESS; } + STbUidStore uidStore = {0}; - SRetention *pRetention = SMA_RETENTION(pSma); - if (!RETENTION_VALID(pRetention + 1)) { - // return directly if retention level 1 is invalid - return TSDB_CODE_SUCCESS; - } if (inputType == STREAM_INPUT__DATA_SUBMIT) { - if (tdFetchSubmitReqSuids(pMsg, &uidStore) < 0) { + if (tdFetchSubmitReqSuids(pReq, &uidStore) < 0) { + smaError("vgId:%d, failed to process rsma submit fetch suid since: %s", SMA_VID(pSma), terrstr()); goto _err; } if (uidStore.suid != 0) { - if (tdExecuteRSmaAsync(pSma, pMsg, inputType, uidStore.suid) < 0) { + if (tdExecuteRSmaAsync(pSma, version, pMsg, len, inputType, uidStore.suid) < 0) { + smaError("vgId:%d, failed to process rsma submit exec 1 since: %s", SMA_VID(pSma), terrstr()); goto _err; } void *pIter = NULL; while ((pIter = taosHashIterate(uidStore.uidHash, pIter))) { tb_uid_t *pTbSuid = (tb_uid_t *)taosHashGetKey(pIter, NULL); - if (tdExecuteRSmaAsync(pSma, pMsg, inputType, *pTbSuid) < 0) { + if (tdExecuteRSmaAsync(pSma, version, pMsg, len, inputType, *pTbSuid) < 0) { + smaError("vgId:%d, failed to process rsma submit exec 2 since: %s", SMA_VID(pSma), terrstr()); goto _err; } } @@ -1081,7 +1081,6 @@ int32_t tdProcessRSmaSubmit(SSma *pSma, void *pMsg, int32_t inputType) { return TSDB_CODE_SUCCESS; _err: tdUidStoreDestory(&uidStore); - smaError("vgId:%d, failed to process rsma submit since: %s", SMA_VID(pSma), terrstr()); return TSDB_CODE_FAILED; } @@ -1093,19 +1092,22 @@ _err: * @return int32_t */ static int32_t tdRSmaRestoreQTaskInfoInit(SSma *pSma, int64_t *nTables) { + int32_t code = 0; + int32_t lino = 0; SVnode *pVnode = pSma->pVnode; SArray *suidList = NULL; STbUidStore uidStore = {0}; SMetaReader mr = {0}; + tb_uid_t suid = 0; if (!(suidList = taosArrayInit(1, sizeof(tb_uid_t)))) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - goto _err; + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); } if (vnodeGetStbIdList(pSma->pVnode, 0, suidList) < 0) { - smaError("vgId:%d, failed to restore rsma env since get stb id list error: %s", TD_VID(pVnode), terrstr()); - goto _err; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } int64_t arrSize = taosArrayGetSize(suidList); @@ -1122,19 +1124,26 @@ static int32_t tdRSmaRestoreQTaskInfoInit(SSma *pSma, int64_t *nTables) { int64_t nRsmaTables = 0; metaReaderInit(&mr, SMA_META(pSma), 0); if (!(uidStore.tbUids = taosArrayInit(1024, sizeof(tb_uid_t)))) { - goto _err; + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); } + for (int64_t i = 0; i < arrSize; ++i) { - tb_uid_t suid = *(tb_uid_t *)taosArrayGet(suidList, i); + suid = *(tb_uid_t *)taosArrayGet(suidList, i); smaDebug("vgId:%d, rsma restore, suid is %" PRIi64, TD_VID(pVnode), suid); if (metaGetTableEntryByUidCache(&mr, suid) < 0) { - smaError("vgId:%d, rsma restore, failed to get table meta for %" PRIi64 " since %s", TD_VID(pVnode), suid, - terrstr()); - goto _err; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } tDecoderClear(&mr.coder); - ASSERT(mr.me.type == TSDB_SUPER_TABLE); - ASSERT(mr.me.uid == suid); + if (mr.me.type != TSDB_SUPER_TABLE) { + code = TSDB_CODE_RSMA_INVALID_SCHEMA; + TSDB_CHECK_CODE(code, lino, _exit); + } + if (mr.me.uid != suid) { + code = TSDB_CODE_RSMA_INVALID_SCHEMA; + TSDB_CHECK_CODE(code, lino, _exit); + } if (TABLE_IS_ROLLUP(mr.me.flags)) { ++nRsmaTables; SRSmaParam *param = &mr.me.stbEntry.rsmaParam; @@ -1144,22 +1153,20 @@ static int32_t tdRSmaRestoreQTaskInfoInit(SSma *pSma, int64_t *nTables) { TD_VID(pVnode), suid, i, param->maxdelay[i], param->watermark[i], param->qmsgLen[i]); } if (tdRSmaProcessCreateImpl(pSma, &mr.me.stbEntry.rsmaParam, suid, mr.me.name) < 0) { - smaError("vgId:%d, rsma restore env failed for %" PRIi64 " since %s", TD_VID(pVnode), suid, terrstr()); - goto _err; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } // reload all ctbUids for suid uidStore.suid = suid; if (vnodeGetCtbIdList(pVnode, suid, uidStore.tbUids) < 0) { - smaError("vgId:%d, rsma restore, get ctb idlist failed for %" PRIi64 " since %s", TD_VID(pVnode), suid, - terrstr()); - goto _err; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } if (tdUpdateTbUidList(pVnode->pSma, &uidStore, true) < 0) { - smaError("vgId:%d, rsma restore, update tb uid list failed for %" PRIi64 " since %s", TD_VID(pVnode), suid, - terrstr()); - goto _err; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } taosArrayClear(uidStore.tbUids); @@ -1168,36 +1175,36 @@ static int32_t tdRSmaRestoreQTaskInfoInit(SSma *pSma, int64_t *nTables) { } } - metaReaderClear(&mr); - taosArrayDestroy(suidList); - tdUidStoreDestory(&uidStore); - if (nTables) { *nTables = nRsmaTables; } - - return TSDB_CODE_SUCCESS; -_err: +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s, suid:%" PRIi64 ", type:%" PRIi8 ", uid:%" PRIi64, TD_VID(pVnode), + __func__, lino, tstrerror(code), suid, mr.me.type, mr.me.uid); + } metaReaderClear(&mr); taosArrayDestroy(suidList); tdUidStoreDestory(&uidStore); - - return TSDB_CODE_FAILED; + return code; } /** - * @brief reload ts data from checkpoint - * - * @param pSma - * @return int32_t + * N.B. the data would be restored from the unified WAL replay procedure */ -static int32_t tdRSmaRestoreTSDataReload(SSma *pSma) { - // NOTHING TODO: the data would be restored from the unified WAL replay procedure - return TSDB_CODE_SUCCESS; -} +int32_t tdRSmaProcessRestoreImpl(SSma *pSma, int8_t type, int64_t qtaskFileVer, int8_t rollback) { + // step 1: init env + if (tdCheckAndInitSmaEnv(pSma, TSDB_SMA_TYPE_ROLLUP) != TSDB_CODE_SUCCESS) { + terrno = TSDB_CODE_TDB_INIT_FAILED; + return TSDB_CODE_FAILED; + } -int32_t tdRSmaProcessRestoreImpl(SSma *pSma, int8_t type, int64_t qtaskFileVer) { - // step 1: iterate all stables to restore the rsma env + // step 2: open SRSmaFS for qTaskFiles + if (tdRSmaFSOpen(pSma, qtaskFileVer, rollback) < 0) { + goto _err; + } + + // step 3: iterate all stables to restore the rsma env int64_t nTables = 0; if (tdRSmaRestoreQTaskInfoInit(pSma, &nTables) < 0) { goto _err; @@ -1207,16 +1214,6 @@ int32_t tdRSmaProcessRestoreImpl(SSma *pSma, int8_t type, int64_t qtaskFileVer) return TSDB_CODE_SUCCESS; } - // step 2: reload ts data from checkpoint - if (tdRSmaRestoreTSDataReload(pSma) < 0) { - goto _err; - } - - // step 3: open SRSmaFS for qTaskFiles - if (tdRSmaFSOpen(pSma, qtaskFileVer) < 0) { - goto _err; - } - smaInfo("vgId:%d, restore rsma task %" PRIi8 " from qtaskf %" PRIi64 " succeed", SMA_VID(pSma), type, qtaskFileVer); return TSDB_CODE_SUCCESS; _err: @@ -1226,19 +1223,26 @@ _err: } int32_t tdRSmaPersistExecImpl(SRSmaStat *pRSmaStat, SHashObj *pInfoHash) { - SSma *pSma = pRSmaStat->pSma; - SVnode *pVnode = pSma->pVnode; - int32_t vid = SMA_VID(pSma); + int32_t code = 0; + int32_t lino = 0; + SSma *pSma = pRSmaStat->pSma; + SVnode *pVnode = pSma->pVnode; + SArray *qTaskFArray = NULL; + int64_t version = pRSmaStat->commitAppliedVer; + TdFilePtr pOutFD = NULL; + TdFilePtr pInFD = NULL; + char fname[TSDB_FILENAME_LEN]; + char fnameVer[TSDB_FILENAME_LEN]; + SRSmaFS fs = {0}; if (taosHashGetSize(pInfoHash) <= 0) { return TSDB_CODE_SUCCESS; } - int64_t fsMaxVer = tdRSmaFSMaxVer(pSma, pRSmaStat); - if (pRSmaStat->commitAppliedVer <= fsMaxVer) { - smaDebug("vgId:%d, rsma persist, no need as applied %" PRIi64 " not larger than fsMaxVer %" PRIi64, vid, - pRSmaStat->commitAppliedVer, fsMaxVer); - return TSDB_CODE_SUCCESS; + qTaskFArray = taosArrayInit(taosHashGetSize(pInfoHash) << 1, sizeof(SQTaskFile)); + if (!qTaskFArray) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); } void *infoHash = NULL; @@ -1253,19 +1257,79 @@ int32_t tdRSmaPersistExecImpl(SRSmaStat *pRSmaStat, SHashObj *pInfoHash) { SRSmaInfoItem *pItem = RSMA_INFO_ITEM(pRSmaInfo, i); if (pItem && pItem->pStreamState) { if (streamStateCommit(pItem->pStreamState) < 0) { - terrno = TSDB_CODE_RSMA_STREAM_STATE_COMMIT; - goto _err; + code = TSDB_CODE_RSMA_STREAM_STATE_COMMIT; + TSDB_CHECK_CODE(code, lino, _exit); + } + smaDebug("vgId:%d, rsma persist, stream state commit success, table %" PRIi64 ", level %d", TD_VID(pVnode), + pRSmaInfo->suid, i + 1); + + // qTaskInfo file + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pRSmaInfo->suid, i + 1, -1, tfsGetPrimaryPath(pVnode->pTfs), fname); + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pRSmaInfo->suid, i + 1, version, tfsGetPrimaryPath(pVnode->pTfs), + fnameVer); + if (taosCheckExistFile(fnameVer)) { + smaWarn("vgId:%d, rsma persist, duplicate file %s exist", TD_VID(pVnode), fnameVer); + } + + pOutFD = taosCreateFile(fnameVer, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC); + if (pOutFD == NULL) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); } - smaDebug("vgId:%d, rsma persist, stream state commit success, table %" PRIi64 " level %d", vid, pRSmaInfo->suid, - i + 1); + pInFD = taosOpenFile(fname, TD_FILE_READ); + if (pInFD == NULL) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + int64_t size = 0; + uint32_t mtime = 0; + if (taosFStatFile(pInFD, &size, &mtime) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + int64_t offset = 0; + if (taosFSendFile(pOutFD, pInFD, &offset, size) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + smaError("vgId:%d, rsma persist, send qtaskinfo file %s to %s failed since %s", TD_VID(pVnode), fname, + fnameVer, tstrerror(code)); + TSDB_CHECK_CODE(code, lino, _exit); + } + taosCloseFile(&pOutFD); + taosCloseFile(&pInFD); + + SQTaskFile qTaskF = { + .nRef = 1, .level = i + 1, .suid = pRSmaInfo->suid, .version = version, .size = size, .mtime = mtime}; + + taosArrayPush(qTaskFArray, &qTaskF); } } } - return TSDB_CODE_SUCCESS; -_err: - smaError("vgId:%d, rsma persist failed since %s", vid, terrstr()); - return TSDB_CODE_FAILED; + // prepare + code = tdRSmaFSCopy(pSma, &fs); + TSDB_CHECK_CODE(code, lino, _exit); + + code = tdRSmaFSUpsertQTaskFile(pSma, &fs, qTaskFArray->pData, taosArrayGetSize(qTaskFArray)); + TSDB_CHECK_CODE(code, lino, _exit); + + code = tdRSmaFSPrepareCommit(pSma, &fs); + TSDB_CHECK_CODE(code, lino, _exit); + +_exit: + + taosArrayDestroy(fs.aQTaskInf); + taosArrayDestroy(qTaskFArray); + + if (code) { + if (pOutFD) taosCloseFile(&pOutFD); + if (pInFD) taosCloseFile(&pInFD); + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } + + terrno = code; + return code; } /** @@ -1343,21 +1407,18 @@ static void tdRSmaFetchTrigger(void *param, void *tmrId) { // async process pItem->fetchLevel = pItem->level; #if 0 + // debugging codes SRSmaInfo *qInfo = tdAcquireRSmaInfoBySuid(pSma, pRSmaInfo->suid); SRSmaInfoItem *qItem = RSMA_INFO_ITEM(qInfo, pItem->level - 1); - ASSERT(qItem->level == pItem->level); - ASSERT(qItem->fetchLevel == pItem->fetchLevel); + make sure(qItem->level == pItem->level); + make sure(qItem->fetchLevel == pItem->fetchLevel); #endif if (atomic_load_8(&pRSmaInfo->assigned) == 0) { tsem_post(&(pStat->notEmpty)); } } break; - case TASK_TRIGGER_STAT_PAUSED: { - smaDebug("vgId:%d, rsma fetch task not start for level:%" PRIi8 " suid:%" PRIi64 " since stat is paused", - SMA_VID(pSma), pItem->level, pRSmaInfo->suid); - } break; case TASK_TRIGGER_STAT_INACTIVE: { - smaDebug("vgId:%d, rsma fetch task not start for level:%" PRIi8 " suid:%" PRIi64 " since stat is inactive", + smaDebug("vgId:%d, rsma fetch task not start for level:%" PRIi8 " suid:%" PRIi64 " since stat is inactive ", SMA_VID(pSma), pItem->level, pRSmaInfo->suid); } break; case TASK_TRIGGER_STAT_INIT: { @@ -1365,8 +1426,9 @@ static void tdRSmaFetchTrigger(void *param, void *tmrId) { SMA_VID(pSma), pItem->level, pRSmaInfo->suid); } break; default: { - smaDebug("vgId:%d, rsma fetch task not start for level:%" PRIi8 " suid:%" PRIi64 " since stat is unknown", - SMA_VID(pSma), pItem->level, pRSmaInfo->suid); + smaDebug("vgId:%d, rsma fetch task not start for level:%" PRIi8 " suid:%" PRIi64 " since stat:%" PRIi8 + " is unknown", + SMA_VID(pSma), pItem->level, pRSmaInfo->suid, fetchTriggerStat); } break; } @@ -1378,7 +1440,8 @@ _end: static void tdFreeRSmaSubmitItems(SArray *pItems) { for (int32_t i = 0; i < taosArrayGetSize(pItems); ++i) { - taosFreeQitem(*(void **)taosArrayGet(pItems, i)); + SPackedData *packData = taosArrayGet(pItems, i); + taosFreeQitem(POINTER_SHIFT(packData->msgStr, -sizeof(int32_t) - sizeof(int64_t))); } taosArrayClear(pItems); } @@ -1447,7 +1510,11 @@ static int32_t tdRSmaBatchExec(SSma *pSma, SRSmaInfo *pInfo, STaosQall *qall, SA void *msg = NULL; taosGetQitem(qall, (void **)&msg); if (msg) { - if (!taosArrayPush(pSubmitArr, &msg)) { + SPackedData packData = {.msgLen = *(int32_t *)msg, + .ver = *(int64_t *)POINTER_SHIFT(msg, sizeof(int32_t)), + .msgStr = POINTER_SHIFT(msg, sizeof(int32_t) + sizeof(int64_t))}; + + if (!taosArrayPush(pSubmitArr, &packData)) { tdFreeRSmaSubmitItems(pSubmitArr); goto _err; } @@ -1460,7 +1527,6 @@ static int32_t tdRSmaBatchExec(SSma *pSma, SRSmaInfo *pInfo, STaosQall *qall, SA if (size > 0) { for (int32_t i = 1; i <= TSDB_RETENTION_L2; ++i) { if (tdExecuteRSmaImpl(pSma, pSubmitArr->pData, size, STREAM_INPUT__MERGED_SUBMIT, pInfo, type, i) < 0) { - tdFreeRSmaSubmitItems(pSubmitArr); goto _err; } } @@ -1468,6 +1534,9 @@ static int32_t tdRSmaBatchExec(SSma *pSma, SRSmaInfo *pInfo, STaosQall *qall, SA } return TSDB_CODE_SUCCESS; _err: + smaError("vgId:%d, batch exec for suid:%" PRIi64 " execType:%d size:%d failed since %s", SMA_VID(pSma), pInfo->suid, + type, (int32_t)taosArrayGetSize(pSubmitArr), terrstr()); + tdFreeRSmaSubmitItems(pSubmitArr); while (1) { void *msg = NULL; taosGetQitem(qall, (void **)&msg); @@ -1489,6 +1558,8 @@ _err: */ int32_t tdRSmaProcessExecImpl(SSma *pSma, ERsmaExecType type) { + int32_t code = 0; + int32_t lino = 0; SVnode *pVnode = pSma->pVnode; SSmaEnv *pEnv = SMA_RSMA_ENV(pSma); SRSmaStat *pRSmaStat = (SRSmaStat *)SMA_ENV_STAT(pEnv); @@ -1497,14 +1568,14 @@ int32_t tdRSmaProcessExecImpl(SSma *pSma, ERsmaExecType type) { bool isFetchAll = false; if (!pRSmaStat || !(infoHash = RSMA_INFO_HASH(pRSmaStat))) { - terrno = TSDB_CODE_RSMA_INVALID_STAT; - goto _err; + code = TSDB_CODE_RSMA_INVALID_STAT; + TSDB_CHECK_CODE(code, lino, _exit); } if (!(pSubmitArr = - taosArrayInit(TMIN(RSMA_SUBMIT_BATCH_SIZE, atomic_load_64(&pRSmaStat->nBufItems)), POINTER_BYTES))) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - goto _err; + taosArrayInit(TMIN(RSMA_SUBMIT_BATCH_SIZE, atomic_load_64(&pRSmaStat->nBufItems)), sizeof(SPackedData)))) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); } while (true) { @@ -1514,8 +1585,7 @@ int32_t tdRSmaProcessExecImpl(SSma *pSma, ERsmaExecType type) { while ((pIter = taosHashIterate(infoHash, pIter))) { SRSmaInfo *pInfo = *(SRSmaInfo **)pIter; if (atomic_val_compare_exchange_8(&pInfo->assigned, 0, 1) == 0) { - if ((taosQueueItemSize(pInfo->queue) > 0) || RSMA_INFO_ITEM(pInfo, 0)->fetchLevel || - RSMA_INFO_ITEM(pInfo, 1)->fetchLevel) { + if ((taosQueueItemSize(pInfo->queue) > 0) || RSMA_NEED_FETCH(pInfo)) { int32_t batchCnt = -1; int32_t batchMax = taosHashGetSize(infoHash) / tsNumOfVnodeRsmaThreads; bool occupied = (batchMax <= 1); @@ -1531,13 +1601,24 @@ int32_t tdRSmaProcessExecImpl(SSma *pSma, ERsmaExecType type) { smaDebug("vgId:%d, batchSize:%d, execType:%" PRIi32, SMA_VID(pSma), qallItemSize, type); } - if (RSMA_INFO_ITEM(pInfo, 0)->fetchLevel || RSMA_INFO_ITEM(pInfo, 1)->fetchLevel) { + if (RSMA_NEED_FETCH(pInfo)) { int8_t oldStat = atomic_val_compare_exchange_8(RSMA_COMMIT_STAT(pRSmaStat), 0, 2); if (oldStat == 0 || ((oldStat == 2) && atomic_load_8(RSMA_TRIGGER_STAT(pRSmaStat)) < TASK_TRIGGER_STAT_PAUSED)) { int32_t oldVal = atomic_fetch_add_32(&pRSmaStat->nFetchAll, 1); - ASSERT(oldVal >= 0); - tdRSmaFetchAllResult(pSma, pInfo); + + if (ASSERTS(oldVal >= 0, "oldVal of nFetchAll: %d < 0", oldVal)) { + code = TSDB_CODE_APP_ERROR; + TSDB_CHECK_CODE(code, lino, _exit); + } + + int8_t curStat = atomic_load_8(RSMA_COMMIT_STAT(pRSmaStat)); + if (curStat == 1) { + smaDebug("vgId:%d, fetch all not exec as commit stat is %" PRIi8, SMA_VID(pSma), curStat); + } else { + tdRSmaFetchAllResult(pSma, pInfo); + } + if (0 == atomic_sub_fetch_32(&pRSmaStat->nFetchAll, 1)) { atomic_store_8(RSMA_COMMIT_STAT(pRSmaStat), 0); } @@ -1547,17 +1628,9 @@ int32_t tdRSmaProcessExecImpl(SSma *pSma, ERsmaExecType type) { if (qallItemSize > 0) { atomic_fetch_sub_64(&pRSmaStat->nBufItems, qallItemSize); continue; - } else if (RSMA_INFO_ITEM(pInfo, 0)->fetchLevel || RSMA_INFO_ITEM(pInfo, 1)->fetchLevel) { - if (atomic_load_8(RSMA_COMMIT_STAT(pRSmaStat)) == 0) { - continue; - } - for (int32_t j = 0; j < TSDB_RETENTION_L2; ++j) { - SRSmaInfoItem *pItem = RSMA_INFO_ITEM(pInfo, j); - if (pItem->fetchLevel) { - pItem->fetchLevel = 0; - taosTmrReset(tdRSmaFetchTrigger, RSMA_FETCH_INTERVAL, pItem, smaMgmt.tmrHandle, &pItem->tmrId); - } - } + } + if (RSMA_NEED_FETCH(pInfo)) { + continue; } break; @@ -1567,7 +1640,9 @@ int32_t tdRSmaProcessExecImpl(SSma *pSma, ERsmaExecType type) { } } } else { - ASSERT(0); + ASSERTS(0, "unknown rsma exec type:%d", (int32_t)type); + code = TSDB_CODE_APP_ERROR; + TSDB_CHECK_CODE(code, lino, _exit); } if (atomic_load_64(&pRSmaStat->nBufItems) <= 0) { @@ -1586,10 +1661,10 @@ int32_t tdRSmaProcessExecImpl(SSma *pSma, ERsmaExecType type) { } // end of while(true) -_end: +_exit: taosArrayDestroy(pSubmitArr); - return TSDB_CODE_SUCCESS; -_err: - taosArrayDestroy(pSubmitArr); - return TSDB_CODE_FAILED; + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } + return code; } diff --git a/source/dnode/vnode/src/sma/smaSnapshot.c b/source/dnode/vnode/src/sma/smaSnapshot.c index 0a6fac0fe7c2d6c724855907e61f498a82abbd57..c00e96a06664db0a60184fdb09e16ee0b68c3d45 100644 --- a/source/dnode/vnode/src/sma/smaSnapshot.c +++ b/source/dnode/vnode/src/sma/smaSnapshot.c @@ -17,14 +17,13 @@ static int32_t rsmaSnapReadQTaskInfo(SRSmaSnapReader* pReader, uint8_t** ppData); static int32_t rsmaSnapWriteQTaskInfo(SRSmaSnapWriter* pWriter, uint8_t* pData, uint32_t nData); -static int32_t rsmaQTaskInfSnapReaderOpen(SRSmaSnapReader* pReader, int64_t version); -static int32_t rsmaQTaskInfSnapReaderClose(SQTaskFReader** ppReader); // SRSmaSnapReader ======================================== struct SRSmaSnapReader { SSma* pSma; int64_t sver; int64_t ever; + SRSmaFS fs; // for data file int8_t rsmaDataDone[TSDB_RETENTION_L2]; @@ -32,19 +31,23 @@ struct SRSmaSnapReader { // for qtaskinfo file int8_t qTaskDone; + int32_t fsIter; SQTaskFReader* pQTaskFReader; }; int32_t rsmaSnapReaderOpen(SSma* pSma, int64_t sver, int64_t ever, SRSmaSnapReader** ppReader) { int32_t code = 0; + int32_t lino = 0; SVnode* pVnode = pSma->pVnode; SRSmaSnapReader* pReader = NULL; + SSmaEnv* pEnv = SMA_RSMA_ENV(pSma); + SRSmaStat* pStat = (SRSmaStat*)SMA_ENV_STAT(pEnv); // alloc pReader = (SRSmaSnapReader*)taosMemoryCalloc(1, sizeof(*pReader)); if (pReader == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; - goto _err; + TSDB_CHECK_CODE(code, lino, _exit); } pReader->pSma = pSma; pReader->sver = sver; @@ -55,171 +58,147 @@ int32_t rsmaSnapReaderOpen(SSma* pSma, int64_t sver, int64_t ever, SRSmaSnapRead if (pSma->pRSmaTsdb[i]) { code = tsdbSnapReaderOpen(pSma->pRSmaTsdb[i], sver, ever, i == 0 ? SNAP_DATA_RSMA1 : SNAP_DATA_RSMA2, &pReader->pDataReader[i]); - if (code < 0) { - goto _err; - } + TSDB_CHECK_CODE(code, lino, _exit); } } // open qtaskinfo - if ((code = rsmaQTaskInfSnapReaderOpen(pReader, ever)) < 0) { - goto _err; + taosRLockLatch(RSMA_FS_LOCK(pStat)); + code = tdRSmaFSRef(pSma, &pReader->fs); + taosRUnLockLatch(RSMA_FS_LOCK(pStat)); + TSDB_CHECK_CODE(code, lino, _exit); + + if (taosArrayGetSize(pReader->fs.aQTaskInf) > 0) { + pReader->pQTaskFReader = taosMemoryCalloc(1, sizeof(SQTaskFReader)); + if (!pReader->pQTaskFReader) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + pReader->pQTaskFReader->pSma = pSma; + pReader->pQTaskFReader->version = pReader->ever; } *ppReader = pReader; - - return TSDB_CODE_SUCCESS; -_err: - if (pReader) rsmaSnapReaderClose(&pReader); - *ppReader = NULL; - smaError("vgId:%d, vnode snapshot rsma reader open failed since %s", TD_VID(pVnode), tstrerror(code)); - return TSDB_CODE_FAILED; -} - -static int32_t rsmaQTaskInfSnapReaderOpen(SRSmaSnapReader* pReader, int64_t version) { - int32_t code = 0; - SSma* pSma = pReader->pSma; - SVnode* pVnode = pSma->pVnode; - SSmaEnv* pEnv = NULL; - SRSmaStat* pStat = NULL; - - if (!(pEnv = SMA_RSMA_ENV(pSma))) { - smaInfo("vgId:%d, vnode snapshot rsma reader for qtaskinfo version %" PRIi64 " not need as env is NULL", - TD_VID(pVnode), version); - return TSDB_CODE_SUCCESS; - } - - pStat = (SRSmaStat*)SMA_ENV_STAT(pEnv); - - int32_t ref = tdRSmaFSRef(pReader->pSma, pStat, version); - if (ref < 1) { - smaInfo("vgId:%d, vnode snapshot rsma reader for qtaskinfo version %" PRIi64 " not need as ref is %d", - TD_VID(pVnode), version, ref); - return TSDB_CODE_SUCCESS; - } - - char qTaskInfoFullName[TSDB_FILENAME_LEN]; - tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), version, tfsGetPrimaryPath(pVnode->pTfs), qTaskInfoFullName); - - if (!taosCheckExistFile(qTaskInfoFullName)) { - tdRSmaFSUnRef(pSma, pStat, version); - smaInfo("vgId:%d, vnode snapshot rsma reader for qtaskinfo version %" PRIi64 " not need as %s not exist", - TD_VID(pVnode), version, qTaskInfoFullName); - return TSDB_CODE_SUCCESS; - } - - pReader->pQTaskFReader = taosMemoryCalloc(1, sizeof(SQTaskFReader)); - if (!pReader->pQTaskFReader) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _end; - } - - TdFilePtr fp = taosOpenFile(qTaskInfoFullName, TD_FILE_READ); - if (!fp) { - code = TAOS_SYSTEM_ERROR(errno); - taosMemoryFreeClear(pReader->pQTaskFReader); - goto _end; - } - - pReader->pQTaskFReader->pReadH = fp; - pReader->pQTaskFReader->pSma = pSma; - pReader->pQTaskFReader->version = pReader->ever; - -_end: - if (code < 0) { - tdRSmaFSUnRef(pSma, pStat, version); - smaError("vgId:%d, vnode snapshot rsma reader open %s succeed", TD_VID(pVnode), qTaskInfoFullName); - return TSDB_CODE_FAILED; - } - - smaInfo("vgId:%d, vnode snapshot rsma reader open %s succeed", TD_VID(pVnode), qTaskInfoFullName); - return TSDB_CODE_SUCCESS; -} - -static int32_t rsmaQTaskInfSnapReaderClose(SQTaskFReader** ppReader) { - if (!(*ppReader)) { - return TSDB_CODE_SUCCESS; +_exit: + if (code) { + if (pReader) rsmaSnapReaderClose(&pReader); + *ppReader = NULL; + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); } - - SSma* pSma = (*ppReader)->pSma; - SRSmaStat* pStat = SMA_RSMA_STAT(pSma); - int64_t version = (*ppReader)->version; - - taosCloseFile(&(*ppReader)->pReadH); - tdRSmaFSUnRef(pSma, pStat, version); - taosMemoryFreeClear(*ppReader); - smaInfo("vgId:%d, vnode snapshot rsma reader closed for qTaskInfo version %" PRIi64, SMA_VID(pSma), version); - - return TSDB_CODE_SUCCESS; + return code; } static int32_t rsmaSnapReadQTaskInfo(SRSmaSnapReader* pReader, uint8_t** ppBuf) { int32_t code = 0; - SSma* pSma = pReader->pSma; + int32_t lino = 0; + SVnode* pVnode = pReader->pSma->pVnode; + SQTaskFReader* qReader = pReader->pQTaskFReader; + SRSmaFS* pFS = &pReader->fs; int64_t n = 0; uint8_t* pBuf = NULL; - SQTaskFReader* qReader = pReader->pQTaskFReader; + int64_t version = pReader->ever; + char fname[TSDB_FILENAME_LEN]; if (!qReader) { *ppBuf = NULL; - smaInfo("vgId:%d, vnode snapshot rsma reader qtaskinfo, qTaskReader is NULL", SMA_VID(pSma)); - return 0; + smaInfo("vgId:%d, vnode snapshot rsma reader qtaskinfo, not needed since qTaskReader is NULL", TD_VID(pVnode)); + goto _exit; + } + + if (pReader->fsIter >= taosArrayGetSize(pFS->aQTaskInf)) { + *ppBuf = NULL; + smaInfo("vgId:%d, vnode snapshot rsma reader qtaskinfo, fsIter reach end", TD_VID(pVnode)); + goto _exit; + } + + while (pReader->fsIter < taosArrayGetSize(pFS->aQTaskInf)) { + SQTaskFile* qTaskF = taosArrayGet(pFS->aQTaskInf, pReader->fsIter++); + if (qTaskF->version != version) { + continue; + } + + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), qTaskF->suid, qTaskF->level, version, tfsGetPrimaryPath(pVnode->pTfs), + fname); + if (!taosCheckExistFile(fname)) { + smaError("vgId:%d, vnode snapshot rsma reader for qtaskinfo, table %" PRIi64 ", level %" PRIi8 + ", version %" PRIi64 " failed since %s not exist", + TD_VID(pVnode), qTaskF->suid, qTaskF->level, version, fname); + code = TSDB_CODE_RSMA_FS_SYNC; + TSDB_CHECK_CODE(code, lino, _exit); + } + + TdFilePtr fp = taosOpenFile(fname, TD_FILE_READ); + if (!fp) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + qReader->pReadH = fp; + qReader->level = qTaskF->level; + qReader->suid = qTaskF->suid; } if (!qReader->pReadH) { *ppBuf = NULL; - smaInfo("vgId:%d, vnode snapshot rsma reader qtaskinfo, readh is NULL", SMA_VID(pSma)); - return 0; + smaInfo("vgId:%d, vnode snapshot rsma reader qtaskinfo, not needed since readh is NULL", TD_VID(pVnode)); + goto _exit; } int64_t size = 0; if (taosFStatFile(qReader->pReadH, &size, NULL) < 0) { code = TAOS_SYSTEM_ERROR(errno); - goto _err; + TSDB_CHECK_CODE(code, lino, _exit); } // seek if (taosLSeekFile(qReader->pReadH, 0, SEEK_SET) < 0) { code = TAOS_SYSTEM_ERROR(errno); - goto _err; + TSDB_CHECK_CODE(code, lino, _exit); } - ASSERT(!(*ppBuf)); - // alloc - *ppBuf = taosMemoryCalloc(1, sizeof(SSnapDataHdr) + size); + if (*ppBuf) { + *ppBuf = taosMemoryRealloc(*ppBuf, sizeof(SSnapDataHdr) + size); + } else { + *ppBuf = taosMemoryMalloc(sizeof(SSnapDataHdr) + size); + } if (!(*ppBuf)) { code = TSDB_CODE_OUT_OF_MEMORY; - goto _err; + TSDB_CHECK_CODE(code, lino, _exit); } // read n = taosReadFile(qReader->pReadH, POINTER_SHIFT(*ppBuf, sizeof(SSnapDataHdr)), size); if (n < 0) { code = TAOS_SYSTEM_ERROR(errno); - goto _err; + TSDB_CHECK_CODE(code, lino, _exit); } else if (n != size) { code = TSDB_CODE_FILE_CORRUPTED; - goto _err; + TSDB_CHECK_CODE(code, lino, _exit); } - smaInfo("vgId:%d, vnode snapshot rsma read qtaskinfo, size:%" PRIi64, SMA_VID(pSma), size); + smaInfo("vgId:%d, vnode snapshot rsma read qtaskinfo, version:%" PRIi64 ", size:%" PRIi64, TD_VID(pVnode), version, + size); SSnapDataHdr* pHdr = (SSnapDataHdr*)(*ppBuf); pHdr->type = SNAP_DATA_QTASK; + pHdr->flag = qReader->level; + pHdr->index = qReader->suid; pHdr->size = size; _exit: - smaInfo("vgId:%d, vnode snapshot rsma read qtaskinfo succeed", SMA_VID(pSma)); - return code; + if (qReader) taosCloseFile(&qReader->pReadH); -_err: - *ppBuf = NULL; - smaError("vgId:%d, vnode snapshot rsma read qtaskinfo failed since %s", SMA_VID(pSma), tstrerror(code)); + if (code) { + *ppBuf = NULL; + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } else { + smaInfo("vgId:%d, vnode snapshot rsma read qtaskinfo succeed", TD_VID(pVnode)); + } return code; } int32_t rsmaSnapRead(SRSmaSnapReader* pReader, uint8_t** ppData) { int32_t code = 0; + int32_t lino = 0; *ppData = NULL; @@ -233,14 +212,11 @@ int32_t rsmaSnapRead(SRSmaSnapReader* pReader, uint8_t** ppData) { if (!pReader->rsmaDataDone[i]) { smaInfo("vgId:%d, vnode snapshot rsma read level %d not done", SMA_VID(pReader->pSma), i); code = tsdbSnapRead(pTsdbSnapReader, ppData); - if (code) { - goto _err; + TSDB_CHECK_CODE(code, lino, _exit); + if (*ppData) { + goto _exit; } else { - if (*ppData) { - goto _exit; - } else { - pReader->rsmaDataDone[i] = 1; - } + pReader->rsmaDataDone[i] = 1; } } else { smaInfo("vgId:%d, vnode snapshot rsma read level %d is done", SMA_VID(pReader->pSma), i); @@ -251,22 +227,21 @@ int32_t rsmaSnapRead(SRSmaSnapReader* pReader, uint8_t** ppData) { if (!pReader->qTaskDone) { smaInfo("vgId:%d, vnode snapshot rsma qtaskinfo not done", SMA_VID(pReader->pSma)); code = rsmaSnapReadQTaskInfo(pReader, ppData); - if (code) { - goto _err; + TSDB_CHECK_CODE(code, lino, _exit); + if (*ppData) { + goto _exit; } else { pReader->qTaskDone = 1; - if (*ppData) { - goto _exit; - } } } _exit: - smaInfo("vgId:%d, vnode snapshot rsma read succeed", SMA_VID(pReader->pSma)); - return code; - -_err: - smaError("vgId:%d, vnode snapshot rsma read failed since %s", SMA_VID(pReader->pSma), tstrerror(code)); + if (code) { + smaError("vgId:%d, vnode snapshot rsma read failed since %s", SMA_VID(pReader->pSma), tstrerror(code)); + rsmaSnapReaderClose(&pReader); + } else { + smaInfo("vgId:%d, vnode snapshot rsma read succeed", SMA_VID(pReader->pSma)); + } return code; } @@ -274,14 +249,15 @@ int32_t rsmaSnapReaderClose(SRSmaSnapReader** ppReader) { int32_t code = 0; SRSmaSnapReader* pReader = *ppReader; + tdRSmaFSUnRef(pReader->pSma, &pReader->fs); + taosMemoryFreeClear(pReader->pQTaskFReader); + for (int32_t i = 0; i < TSDB_RETENTION_L2; ++i) { if (pReader->pDataReader[i]) { tsdbSnapReaderClose(&pReader->pDataReader[i]); } } - rsmaQTaskInfSnapReaderClose(&pReader->pQTaskFReader); - smaInfo("vgId:%d, vnode snapshot rsma reader closed", SMA_VID(pReader->pSma)); taosMemoryFreeClear(*ppReader); @@ -293,28 +269,23 @@ struct SRSmaSnapWriter { SSma* pSma; int64_t sver; int64_t ever; - - // config - int64_t commitID; + SRSmaFS fs; // for data file STsdbSnapWriter* pDataWriter[TSDB_RETENTION_L2]; - - // for qtaskinfo file - SQTaskFReader* pQTaskFReader; - SQTaskFWriter* pQTaskFWriter; }; int32_t rsmaSnapWriterOpen(SSma* pSma, int64_t sver, int64_t ever, SRSmaSnapWriter** ppWriter) { int32_t code = 0; - SRSmaSnapWriter* pWriter = NULL; + int32_t lino = 0; SVnode* pVnode = pSma->pVnode; + SRSmaSnapWriter* pWriter = NULL; // alloc pWriter = (SRSmaSnapWriter*)taosMemoryCalloc(1, sizeof(*pWriter)); - if (pWriter == NULL) { + if (!pWriter) { code = TSDB_CODE_OUT_OF_MEMORY; - goto _err; + TSDB_CHECK_CODE(code, lino, _exit); } pWriter->pSma = pSma; pWriter->sver = sver; @@ -324,100 +295,152 @@ int32_t rsmaSnapWriterOpen(SSma* pSma, int64_t sver, int64_t ever, SRSmaSnapWrit for (int32_t i = 0; i < TSDB_RETENTION_L2; ++i) { if (pSma->pRSmaTsdb[i]) { code = tsdbSnapWriterOpen(pSma->pRSmaTsdb[i], sver, ever, &pWriter->pDataWriter[i]); - if (code < 0) { - goto _err; - } + TSDB_CHECK_CODE(code, lino, _exit); } } // qtaskinfo - SQTaskFWriter* qWriter = (SQTaskFWriter*)taosMemoryCalloc(1, sizeof(SQTaskFWriter)); - qWriter->pSma = pSma; - - char qTaskInfoFullName[TSDB_FILENAME_LEN]; - tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), 0, tfsGetPrimaryPath(pVnode->pTfs), qTaskInfoFullName); - TdFilePtr qTaskF = taosCreateFile(qTaskInfoFullName, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC); - if (!qTaskF) { - taosMemoryFree(qWriter); - code = TAOS_SYSTEM_ERROR(errno); - smaError("vgId:%d, rsma snapshot writer open %s failed since %s", TD_VID(pSma->pVnode), qTaskInfoFullName, - tstrerror(code)); - goto _err; - } - qWriter->pWriteH = qTaskF; - int32_t fnameLen = strlen(qTaskInfoFullName) + 1; - qWriter->fname = taosMemoryCalloc(1, fnameLen); - strncpy(qWriter->fname, qTaskInfoFullName, fnameLen); - pWriter->pQTaskFWriter = qWriter; - smaDebug("vgId:%d, rsma snapshot writer open succeed for %s", TD_VID(pSma->pVnode), qTaskInfoFullName); + code = tdRSmaFSCopy(pSma, &pWriter->fs); + TSDB_CHECK_CODE(code, lino, _exit); // snapWriter *ppWriter = pWriter; - - smaInfo("vgId:%d, rsma snapshot writer open succeed", TD_VID(pSma->pVnode)); +_exit: + if (code) { + if (pWriter) rsmaSnapWriterClose(&pWriter, 0); + *ppWriter = NULL; + smaError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } else { + smaInfo("vgId:%d, rsma snapshot writer open succeed", TD_VID(pSma->pVnode)); + } return code; +} -_err: - smaError("vgId:%d, rsma snapshot writer open failed since %s", TD_VID(pSma->pVnode), tstrerror(code)); - if (pWriter) rsmaSnapWriterClose(&pWriter, 0); - *ppWriter = NULL; +int32_t rsmaSnapWriterPrepareClose(SRSmaSnapWriter* pWriter) { + int32_t code = 0; + int32_t lino = 0; + + if (pWriter) { + code = tdRSmaFSPrepareCommit(pWriter->pSma, &pWriter->fs); + TSDB_CHECK_CODE(code, lino, _exit); + } + +_exit: + if (code) { + smaError("vgId:%d, %s failed at line %d since %s", SMA_VID(pWriter->pSma), __func__, lino, tstrerror(code)); + } return code; } int32_t rsmaSnapWriterClose(SRSmaSnapWriter** ppWriter, int8_t rollback) { int32_t code = 0; + int32_t lino = 0; + SSma* pSma = NULL; + SVnode* pVnode = NULL; + SSmaEnv* pEnv = NULL; + SRSmaStat* pStat = NULL; SRSmaSnapWriter* pWriter = *ppWriter; - SVnode* pVnode = pWriter->pSma->pVnode; + const char* primaryPath = NULL; + char fname[TSDB_FILENAME_LEN] = {0}; + char fnameVer[TSDB_FILENAME_LEN] = {0}; + TdFilePtr pOutFD = NULL; + TdFilePtr pInFD = NULL; + + if (!pWriter) { + goto _exit; + } - if (rollback) { - // TODO: rsma1/rsma2 - // qtaskinfo - if (pWriter->pQTaskFWriter) { - if (taosRemoveFile(pWriter->pQTaskFWriter->fname) != 0) { - smaWarn("vgId:%d, vnode snapshot rsma writer failed to remove %s since %s", SMA_VID(pWriter->pSma), - pWriter->pQTaskFWriter->fname ? pWriter->pQTaskFWriter->fname : "NULL", - tstrerror(TAOS_SYSTEM_ERROR(errno))); - } + pSma = pWriter->pSma; + pVnode = pSma->pVnode; + pEnv = SMA_RSMA_ENV(pSma); + pStat = (SRSmaStat*)SMA_ENV_STAT(pEnv); + primaryPath = tfsGetPrimaryPath(pVnode->pTfs); + + // rsma1/rsma2 + for (int32_t i = 0; i < TSDB_RETENTION_L2; ++i) { + if (pWriter->pDataWriter[i]) { + code = tsdbSnapWriterClose(&pWriter->pDataWriter[i], rollback); + TSDB_CHECK_CODE(code, lino, _exit); } + } + + // qtaskinfo + if (rollback) { + tdRSmaFSRollback(pSma); + // remove qTaskFiles } else { - // rsma1/rsma2 - for (int32_t i = 0; i < TSDB_RETENTION_L2; ++i) { - if (pWriter->pDataWriter[i]) { - code = tsdbSnapWriterClose(&pWriter->pDataWriter[i], rollback); - if (code) goto _err; + // sendFile from fname.Ver to fname + SRSmaFS* pFS = &pWriter->fs; + int32_t size = taosArrayGetSize(pFS->aQTaskInf); + for (int32_t i = 0; i < size; ++i) { + SQTaskFile* pTaskF = TARRAY_GET_ELEM(pFS->aQTaskInf, i); + if (pTaskF->version == pWriter->ever) { + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pTaskF->suid, pTaskF->level, pTaskF->version, primaryPath, fnameVer); + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pTaskF->suid, pTaskF->level, -1, primaryPath, fname); + + pInFD = taosOpenFile(fnameVer, TD_FILE_READ); + if (pInFD == NULL) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + pOutFD = taosCreateFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC); + if (pOutFD == NULL) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + int64_t size = 0; + if (taosFStatFile(pInFD, &size, NULL) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + int64_t offset = 0; + if (taosFSendFile(pOutFD, pInFD, &offset, size) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + smaError("vgId:%d, vnode snapshot rsma writer, send qtaskinfo file %s to %s failed since %s", TD_VID(pVnode), + fnameVer, fname, tstrerror(code)); + TSDB_CHECK_CODE(code, lino, _exit); + } + taosCloseFile(&pOutFD); + taosCloseFile(&pInFD); } } - // qtaskinfo - if (pWriter->pQTaskFWriter) { - char qTaskInfoFullName[TSDB_FILENAME_LEN]; - tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pWriter->ever, tfsGetPrimaryPath(pVnode->pTfs), qTaskInfoFullName); - if (taosRenameFile(pWriter->pQTaskFWriter->fname, qTaskInfoFullName) < 0) { - code = TAOS_SYSTEM_ERROR(errno); - goto _err; - } - smaInfo("vgId:%d, vnode snapshot rsma writer rename %s to %s", SMA_VID(pWriter->pSma), - pWriter->pQTaskFWriter->fname, qTaskInfoFullName); - // rsma restore - if ((code = tdRSmaRestore(pWriter->pSma, RSMA_RESTORE_SYNC, pWriter->ever)) < 0) { - goto _err; - } - smaInfo("vgId:%d, vnode snapshot rsma writer restore from %s succeed", SMA_VID(pWriter->pSma), qTaskInfoFullName); + // lock + taosWLockLatch(RSMA_FS_LOCK(pStat)); + code = tdRSmaFSCommit(pSma); + if (code) { + taosWUnLockLatch(RSMA_FS_LOCK(pStat)); + goto _exit; } + // unlock + taosWUnLockLatch(RSMA_FS_LOCK(pStat)); } - smaInfo("vgId:%d, vnode snapshot rsma writer close succeed", SMA_VID(pWriter->pSma)); - taosMemoryFree(pWriter); + // rsma restore + code = tdRSmaRestore(pWriter->pSma, RSMA_RESTORE_SYNC, pWriter->ever, rollback); + TSDB_CHECK_CODE(code, lino, _exit); + smaInfo("vgId:%d, vnode snapshot rsma writer restore from sync succeed", SMA_VID(pSma)); + +_exit: + if (pWriter) taosMemoryFree(pWriter); *ppWriter = NULL; - return code; + if (code) { + if (pOutFD) taosCloseFile(&pOutFD); + if (pInFD) taosCloseFile(&pInFD); + smaError("vgId:%d, vnode snapshot rsma writer close failed since %s", SMA_VID(pSma), tstrerror(code)); + } else { + smaInfo("vgId:%d, vnode snapshot rsma writer close succeed", pSma ? SMA_VID(pSma) : 0); + } -_err: - smaError("vgId:%d, vnode snapshot rsma writer close failed since %s", SMA_VID(pWriter->pSma), tstrerror(code)); return code; } int32_t rsmaSnapWrite(SRSmaSnapWriter* pWriter, uint8_t* pData, uint32_t nData) { int32_t code = 0; + int32_t lino = 0; SSnapDataHdr* pHdr = (SSnapDataHdr*)pData; // rsma1/rsma2 @@ -430,42 +453,81 @@ int32_t rsmaSnapWrite(SRSmaSnapWriter* pWriter, uint8_t* pData, uint32_t nData) } else if (pHdr->type == SNAP_DATA_QTASK) { code = rsmaSnapWriteQTaskInfo(pWriter, pData, nData); } else { - ASSERT(0); + code = TSDB_CODE_RSMA_FS_SYNC; } - if (code < 0) goto _err; + TSDB_CHECK_CODE(code, lino, _exit); _exit: - smaInfo("vgId:%d, rsma snapshot write for data type %" PRIi8 " succeed", SMA_VID(pWriter->pSma), pHdr->type); - return code; - -_err: - smaError("vgId:%d, rsma snapshot write for data type %" PRIi8 " failed since %s", SMA_VID(pWriter->pSma), pHdr->type, - tstrerror(code)); + if (code) { + smaError("vgId:%d, %s failed at line %d since %s, data type %" PRIi8, SMA_VID(pWriter->pSma), __func__, lino, + tstrerror(code), pHdr->type); + } else { + smaInfo("vgId:%d, rsma snapshot write for data type %" PRIi8 " succeed", SMA_VID(pWriter->pSma), pHdr->type); + } return code; } static int32_t rsmaSnapWriteQTaskInfo(SRSmaSnapWriter* pWriter, uint8_t* pData, uint32_t nData) { - int32_t code = 0; - SQTaskFWriter* qWriter = pWriter->pQTaskFWriter; - - if (qWriter && qWriter->pWriteH) { - SSnapDataHdr* pHdr = (SSnapDataHdr*)pData; - int64_t size = pHdr->size; - ASSERT(size == (nData - sizeof(SSnapDataHdr))); - int64_t contLen = taosWriteFile(qWriter->pWriteH, pHdr->data, size); - if (contLen != size) { - code = TAOS_SYSTEM_ERROR(errno); - goto _err; - } - smaInfo("vgId:%d, vnode snapshot rsma write qtaskinfo %s succeed", SMA_VID(pWriter->pSma), qWriter->fname); + int32_t code = 0; + int32_t lino = 0; + SSma* pSma = pWriter->pSma; + SVnode* pVnode = pSma->pVnode; + char fname[TSDB_FILENAME_LEN]; + TdFilePtr fp = NULL; + SSnapDataHdr* pHdr = (SSnapDataHdr*)pData; + + fname[0] = '\0'; + + if (pHdr->size != (nData - sizeof(SSnapDataHdr))) { + code = TSDB_CODE_RSMA_FS_SYNC; + TSDB_CHECK_CODE(code, lino, _exit); + } + + SQTaskFile qTaskFile = { + .nRef = 1, .level = pHdr->flag, .suid = pHdr->index, .version = pWriter->ever, .size = pHdr->size}; + + tdRSmaQTaskInfoGetFullName(TD_VID(pVnode), pHdr->index, pHdr->flag, qTaskFile.version, + tfsGetPrimaryPath(pVnode->pTfs), fname); + + fp = taosCreateFile(fname, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC); + if (!fp) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + int64_t contLen = taosWriteFile(fp, pHdr->data, pHdr->size); + if (contLen != pHdr->size) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + uint32_t mtime = 0; + if (taosFStatFile(fp, NULL, &mtime) != 0) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); } else { - smaInfo("vgId:%d, vnode snapshot rsma write qtaskinfo is not needed", SMA_VID(pWriter->pSma)); + qTaskFile.mtime = mtime; } + if (taosFsyncFile(fp) < 0) { + code = TAOS_SYSTEM_ERROR(errno); + TSDB_CHECK_CODE(code, lino, _exit); + } + + taosCloseFile(&fp); + + code = tdRSmaFSUpsertQTaskFile(pSma, &pWriter->fs, &qTaskFile, 1); + TSDB_CHECK_CODE(code, lino, _exit); + _exit: - return code; + if (code) { + if (fp) { + (void)taosRemoveFile(fname); + } + smaError("vgId:%d, %s failed at line %d since %s, file:%s", TD_VID(pVnode), __func__, lino, tstrerror(code), fname); + } else { + smaInfo("vgId:%d, vnode snapshot rsma write qtaskinfo %s succeed", TD_VID(pVnode), fname); + } -_err: - smaError("vgId:%d, vnode snapshot rsma write qtaskinfo failed since %s", SMA_VID(pWriter->pSma), tstrerror(code)); return code; } diff --git a/source/dnode/vnode/src/sma/smaTimeRange.c b/source/dnode/vnode/src/sma/smaTimeRange.c index a2c9484693a720243ccb205f0d311289c86f254e..6a4bddc991769963317e5f184890902ea78adf6c 100644 --- a/source/dnode/vnode/src/sma/smaTimeRange.c +++ b/source/dnode/vnode/src/sma/smaTimeRange.c @@ -14,6 +14,7 @@ */ #include "sma.h" +#include "tq.h" #include "tsdb.h" #define SMA_STORAGE_MINUTES_MAX 86400 @@ -24,14 +25,13 @@ static int32_t tdProcessTSmaCreateImpl(SSma *pSma, int64_t version, const char * static int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char *msg); static int32_t tdProcessTSmaGetDaysImpl(SVnodeCfg *pCfg, void *pCont, uint32_t contLen, int32_t *days); -// TODO: Who is responsible for resource allocate and release? int32_t tdProcessTSmaInsert(SSma *pSma, int64_t indexUid, const char *msg) { int32_t code = TSDB_CODE_SUCCESS; if ((code = tdProcessTSmaInsertImpl(pSma, indexUid, msg)) < 0) { smaWarn("vgId:%d, insert tsma data failed since %s", SMA_VID(pSma), tstrerror(terrno)); } - // TODO: destroy SSDataBlocks(msg) + return code; } @@ -41,7 +41,6 @@ int32_t tdProcessTSmaCreate(SSma *pSma, int64_t version, const char *msg) { if ((code = tdProcessTSmaCreateImpl(pSma, version, msg)) < 0) { smaWarn("vgId:%d, create tsma failed since %s", SMA_VID(pSma), tstrerror(terrno)); } - // TODO: destroy SSDataBlocks(msg) return code; } @@ -111,35 +110,240 @@ _err: * @return int32_t */ static int32_t tdProcessTSmaCreateImpl(SSma *pSma, int64_t version, const char *pMsg) { - SSmaCfg *pCfg = (SSmaCfg *)pMsg; + int32_t code = 0; + int32_t lino = 0; + SSmaCfg *pCfg = (SSmaCfg *)pMsg; + SName stbFullName = {0}; + SVCreateStbReq pReq = {0}; if (TD_VID(pSma->pVnode) == pCfg->dstVgId) { // create tsma meta in dstVgId if (metaCreateTSma(SMA_META(pSma), version, pCfg) < 0) { - return -1; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } // create stable to save tsma result in dstVgId - SName stbFullName = {0}; tNameFromString(&stbFullName, pCfg->dstTbName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); - SVCreateStbReq pReq = {0}; pReq.name = (char *)tNameGetTableName(&stbFullName); pReq.suid = pCfg->dstTbUid; pReq.schemaRow = pCfg->schemaRow; pReq.schemaTag = pCfg->schemaTag; if (metaCreateSTable(SMA_META(pSma), version, &pReq) < 0) { - return -1; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } + } else { + code = terrno = TSDB_CODE_TSMA_INVALID_STAT; + TSDB_CHECK_CODE(code, lino, _exit); + } +_exit: + if (code) { + smaError("vgId:%d, failed at line %d to create sma index %s %" PRIi64 " on stb:%" PRIi64 ", dstSuid:%" PRIi64 + " dstTb:%s dstVg:%d", + SMA_VID(pSma), lino, pCfg->indexName, pCfg->indexUid, pCfg->tableUid, pCfg->dstTbUid, pReq.name, + pCfg->dstVgId); + } else { smaDebug("vgId:%d, success to create sma index %s %" PRIi64 " on stb:%" PRIi64 ", dstSuid:%" PRIi64 " dstTb:%s dstVg:%d", SMA_VID(pSma), pCfg->indexName, pCfg->indexUid, pCfg->tableUid, pCfg->dstTbUid, pReq.name, pCfg->dstVgId); - } else { - ASSERT(0); } - return 0; + return code; +} + +int32_t smaBlockToSubmit(SVnode *pVnode, const SArray *pBlocks, const STSchema *pTSchema, + SSchemaWrapper *pTagSchemaWrapper, bool createTb, int64_t suid, const char *stbFullName, + SBatchDeleteReq *pDeleteReq, void **ppData, int32_t *pLen) { + void *pBuf = NULL; + int32_t len = 0; + SSubmitReq2 *pReq = NULL; + SArray *tagArray = NULL; + SArray *createTbArray = NULL; + SArray *pVals = NULL; + + int32_t sz = taosArrayGetSize(pBlocks); + + if (!(tagArray = taosArrayInit(1, sizeof(STagVal)))) { + goto _end; + } + + if (!(createTbArray = taosArrayInit(sz, POINTER_BYTES))) { + goto _end; + } + + if (!(pReq = taosMemoryCalloc(1, sizeof(SSubmitReq2)))) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _end; + } + + if (!(pReq->aSubmitTbData = taosArrayInit(1, sizeof(SSubmitTbData)))) { + goto _end; + } + + // create table req + if (createTb) { + for (int32_t i = 0; i < sz; ++i) { + SSDataBlock *pDataBlock = taosArrayGet(pBlocks, i); + SVCreateTbReq *pCreateTbReq = NULL; + if (pDataBlock->info.type == STREAM_DELETE_RESULT) { + taosArrayPush(createTbArray, &pCreateTbReq); + continue; + } + + if (!(pCreateTbReq = taosMemoryCalloc(1, sizeof(SVCreateStbReq)))) { + goto _end; + }; + + // don't move to the end of loop as to destroy in the end of func when error occur + taosArrayPush(createTbArray, &pCreateTbReq); + + // set const + pCreateTbReq->flags = 0; + pCreateTbReq->type = TSDB_CHILD_TABLE; + pCreateTbReq->ctb.suid = suid; + + // set super table name + SName name = {0}; + tNameFromString(&name, stbFullName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); + pCreateTbReq->ctb.stbName = taosStrdup((char *)tNameGetTableName(&name)); // taosStrdup(stbFullName); + + // set tag content + taosArrayClear(tagArray); + STagVal tagVal = { + .cid = taosArrayGetSize(pDataBlock->pDataBlock) + 1, + .type = TSDB_DATA_TYPE_UBIGINT, + .i64 = (int64_t)pDataBlock->info.id.groupId, + }; + taosArrayPush(tagArray, &tagVal); + pCreateTbReq->ctb.tagNum = taosArrayGetSize(tagArray); + + STag *pTag = NULL; + tTagNew(tagArray, 1, false, &pTag); + if (pTag == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _end; + } + pCreateTbReq->ctb.pTag = (uint8_t *)pTag; + + // set tag name + SArray *tagName = taosArrayInit(1, TSDB_COL_NAME_LEN); + char tagNameStr[TSDB_COL_NAME_LEN] = {0}; + strcpy(tagNameStr, "group_id"); + taosArrayPush(tagName, tagNameStr); + pCreateTbReq->ctb.tagName = tagName; + + // set table name + if (pDataBlock->info.parTbName[0]) { + pCreateTbReq->name = taosStrdup(pDataBlock->info.parTbName); + } else { + pCreateTbReq->name = buildCtbNameByGroupId(stbFullName, pDataBlock->info.id.groupId); + } + } + } + + // SSubmitTbData req + for (int32_t i = 0; i < sz; ++i) { + SSDataBlock *pDataBlock = taosArrayGet(pBlocks, i); + if (pDataBlock->info.type == STREAM_DELETE_RESULT) { + pDeleteReq->suid = suid; + pDeleteReq->deleteReqs = taosArrayInit(0, sizeof(SSingleDeleteReq)); + tqBuildDeleteReq(pVnode, stbFullName, pDataBlock, pDeleteReq); + continue; + } + + int32_t rows = pDataBlock->info.rows; + + SSubmitTbData tbData = {0}; + + if (!(tbData.aRowP = taosArrayInit(rows, sizeof(SRow *)))) { + goto _end; + } + tbData.suid = suid; + tbData.uid = 0; // uid is assigned by vnode + tbData.sver = pTSchema->version; + + if (createTb) { + tbData.pCreateTbReq = taosArrayGetP(createTbArray, i); + if (tbData.pCreateTbReq) tbData.flags = SUBMIT_REQ_AUTO_CREATE_TABLE; + } + + if (!pVals && !(pVals = taosArrayInit(pTSchema->numOfCols, sizeof(SColVal)))) { + taosArrayDestroy(tbData.aRowP); + goto _end; + } + + for (int32_t j = 0; j < rows; ++j) { + taosArrayClear(pVals); + for (int32_t k = 0; k < pTSchema->numOfCols; k++) { + const STColumn *pCol = &pTSchema->columns[k]; + SColumnInfoData *pColData = taosArrayGet(pDataBlock->pDataBlock, k); + if (colDataIsNull_s(pColData, j)) { + SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type); + taosArrayPush(pVals, &cv); + } else { + void *data = colDataGetData(pColData, j); + if (IS_STR_DATA_TYPE(pCol->type)) { + SValue sv = (SValue){.nData = varDataLen(data), .pData = varDataVal(data)}; // address copy, no value + SColVal cv = COL_VAL_VALUE(pCol->colId, pCol->type, sv); + taosArrayPush(pVals, &cv); + } else { + SValue sv; + memcpy(&sv.val, data, tDataTypes[pCol->type].bytes); + SColVal cv = COL_VAL_VALUE(pCol->colId, pCol->type, sv); + taosArrayPush(pVals, &cv); + } + } + } + SRow *pRow = NULL; + if ((terrno = tRowBuild(pVals, (STSchema *)pTSchema, &pRow)) < 0) { + tDestroySubmitTbData(&tbData, TSDB_MSG_FLG_ENCODE); + goto _end; + } + taosArrayPush(tbData.aRowP, &pRow); + } + + taosArrayPush(pReq->aSubmitTbData, &tbData); + } + + // encode + tEncodeSize(tEncodeSubmitReq, pReq, len, terrno); + if (TSDB_CODE_SUCCESS == terrno) { + SEncoder encoder; + len += sizeof(SSubmitReq2Msg); + pBuf = rpcMallocCont(len); + if (NULL == pBuf) { + goto _end; + } + ((SSubmitReq2Msg *)pBuf)->header.vgId = TD_VID(pVnode); + ((SSubmitReq2Msg *)pBuf)->header.contLen = htonl(len); + ((SSubmitReq2Msg *)pBuf)->version = htobe64(1); + tEncoderInit(&encoder, POINTER_SHIFT(pBuf, sizeof(SSubmitReq2Msg)), len - sizeof(SSubmitReq2Msg)); + if (tEncodeSubmitReq(&encoder, pReq) < 0) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + /*vError("failed to encode submit req since %s", terrstr());*/ + } + tEncoderClear(&encoder); + } +_end: + taosArrayDestroy(createTbArray); + taosArrayDestroy(tagArray); + taosArrayDestroy(pVals); + if (pReq) { + tDestroySubmitReq(pReq, TSDB_MSG_FLG_ENCODE); + taosMemoryFree(pReq); + } + + if (terrno != 0) { + rpcFreeCont(pBuf); + taosArrayDestroy(pDeleteReq->deleteReqs); + return TSDB_CODE_FAILED; + } + if (ppData) *ppData = pBuf; + if (pLen) *pLen = len; + return TSDB_CODE_SUCCESS; } /** @@ -174,7 +378,7 @@ static int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char STSmaStat *pTsmaStat = NULL; if (!pEnv || !(pStat = SMA_ENV_STAT(pEnv))) { - terrno = TSDB_CODE_TSMA_INVALID_STAT; + terrno = TSDB_CODE_TSMA_INVALID_ENV; return TSDB_CODE_FAILED; } @@ -204,27 +408,32 @@ static int32_t tdProcessTSmaInsertImpl(SSma *pSma, int64_t indexUid, const char } SBatchDeleteReq deleteReq = {0}; - SSubmitReq *pSubmitReq = - tqBlockToSubmit(pSma->pVnode, (const SArray *)msg, pTsmaStat->pTSchema, &pTsmaStat->pTSma->schemaTag, true, - pTsmaStat->pTSma->dstTbUid, pTsmaStat->pTSma->dstTbName, &deleteReq); - // TODO deleteReq - taosArrayDestroy(deleteReq.deleteReqs); - + void *pSubmitReq = NULL; + int32_t contLen = 0; - if (!pSubmitReq) { - smaError("vgId:%d, failed to gen submit blk while tsma insert for smaIndex %" PRIi64 " since %s", SMA_VID(pSma), + if (smaBlockToSubmit(pSma->pVnode, (const SArray *)msg, pTsmaStat->pTSchema, &pTsmaStat->pTSma->schemaTag, true, + pTsmaStat->pTSma->dstTbUid, pTsmaStat->pTSma->dstTbName, &deleteReq, &pSubmitReq, + &contLen) < 0) { + smaError("vgId:%d, failed to gen submit msg while tsma insert for smaIndex %" PRIi64 " since %s", SMA_VID(pSma), indexUid, tstrerror(terrno)); goto _err; } + // TODO deleteReq + taosArrayDestroy(deleteReq.deleteReqs); #if 0 - ASSERT(!strncasecmp("td.tsma.rst.tb", pTsmaStat->pTSma->dstTbName, 14)); + if (!strncasecmp("td.tsma.rst.tb", pTsmaStat->pTSma->dstTbName, 14)) { + terrno = TSDB_CODE_APP_ERROR; + smaError("vgId:%d, tsma insert for smaIndex %" PRIi64 " failed since %s, %s", SMA_VID(pSma), indexUid, + pTsmaStat->pTSma->indexUid, tstrerror(terrno), pTsmaStat->pTSma->dstTbName); + goto _err; + } #endif SRpcMsg submitReqMsg = { .msgType = TDMT_VND_SUBMIT, .pCont = pSubmitReq, - .contLen = ntohl(pSubmitReq->length), + .contLen = contLen, }; if (tmsgPutToQueue(&pSma->pVnode->msgCb, WRITE_QUEUE, &submitReqMsg) < 0) { diff --git a/source/dnode/vnode/src/sma/smaUtil.c b/source/dnode/vnode/src/sma/smaUtil.c index 4d09d690d684c68199f63165875216ea3685acad..7c538280e52ed127ff2815623a2afa00c126de7f 100644 --- a/source/dnode/vnode/src/sma/smaUtil.c +++ b/source/dnode/vnode/src/sma/smaUtil.c @@ -15,197 +15,72 @@ #include "sma.h" -// smaFileUtil ================ -#if 0 -#define TD_FILE_STATE_OK 0 -#define TD_FILE_STATE_BAD 1 +#define TD_QTASKINFO_FNAME_PREFIX "main.tdb" -#define TD_FILE_INIT_MAGIC 0xFFFFFFFF - -static int32_t tdEncodeTFInfo(void **buf, STFInfo *pInfo); -static void *tdDecodeTFInfo(void *buf, STFInfo *pInfo); - -static int32_t tdEncodeTFInfo(void **buf, STFInfo *pInfo) { - int32_t tlen = 0; - - tlen += taosEncodeFixedU32(buf, pInfo->magic); - tlen += taosEncodeFixedU32(buf, pInfo->ftype); - tlen += taosEncodeFixedU32(buf, pInfo->fver); - tlen += taosEncodeFixedI64(buf, pInfo->fsize); - - return tlen; -} - -static void *tdDecodeTFInfo(void *buf, STFInfo *pInfo) { - buf = taosDecodeFixedU32(buf, &(pInfo->magic)); - buf = taosDecodeFixedU32(buf, &(pInfo->ftype)); - buf = taosDecodeFixedU32(buf, &(pInfo->fver)); - buf = taosDecodeFixedI64(buf, &(pInfo->fsize)); - - return buf; -} - -int64_t tdWriteTFile(STFile *pTFile, void *buf, int64_t nbyte) { - ASSERT(TD_TFILE_OPENED(pTFile)); - - int64_t nwrite = taosWriteFile(pTFile->pFile, buf, nbyte); - if (nwrite < nbyte) { - terrno = TAOS_SYSTEM_ERROR(errno); - return -1; - } - - return nwrite; -} - -int64_t tdSeekTFile(STFile *pTFile, int64_t offset, int whence) { - ASSERT(TD_TFILE_OPENED(pTFile)); - - int64_t loffset = taosLSeekFile(TD_TFILE_PFILE(pTFile), offset, whence); - if (loffset < 0) { - terrno = TAOS_SYSTEM_ERROR(errno); - return -1; - } - - return loffset; -} - -int64_t tdGetTFileSize(STFile *pTFile, int64_t *size) { - ASSERT(TD_TFILE_OPENED(pTFile)); - return taosFStatFile(pTFile->pFile, size, NULL); -} - -int64_t tdReadTFile(STFile *pTFile, void *buf, int64_t nbyte) { - ASSERT(TD_TFILE_OPENED(pTFile)); - - int64_t nread = taosReadFile(pTFile->pFile, buf, nbyte); - if (nread < 0) { - terrno = TAOS_SYSTEM_ERROR(errno); - return -1; - } - - return nread; -} - -int32_t tdUpdateTFileHeader(STFile *pTFile) { - char buf[TD_FILE_HEAD_SIZE] = "\0"; - - if (tdSeekTFile(pTFile, 0, SEEK_SET) < 0) { - return -1; - } - - void *ptr = buf; - tdEncodeTFInfo(&ptr, &(pTFile->info)); - - taosCalcChecksumAppend(0, (uint8_t *)buf, TD_FILE_HEAD_SIZE); - if (tdWriteTFile(pTFile, buf, TD_FILE_HEAD_SIZE) < 0) { - return -1; - } - - return 0; -} - -int32_t tdLoadTFileHeader(STFile *pTFile, STFInfo *pInfo) { - char buf[TD_FILE_HEAD_SIZE] = "\0"; - uint32_t _version; - - ASSERT(TD_TFILE_OPENED(pTFile)); - - if (tdSeekTFile(pTFile, 0, SEEK_SET) < 0) { - return -1; - } - - if (tdReadTFile(pTFile, buf, TD_FILE_HEAD_SIZE) < 0) { - return -1; - } - - if (!taosCheckChecksumWhole((uint8_t *)buf, TD_FILE_HEAD_SIZE)) { - terrno = TSDB_CODE_FILE_CORRUPTED; - return -1; - } - - void *pBuf = buf; - pBuf = tdDecodeTFInfo(pBuf, pInfo); - return 0; -} - -void tdUpdateTFileMagic(STFile *pTFile, void *pCksm) { - pTFile->info.magic = taosCalcChecksum(pTFile->info.magic, (uint8_t *)(pCksm), sizeof(TSCKSUM)); +void tdRSmaQTaskInfoGetFileName(int32_t vgId, int64_t suid, int8_t level, int64_t version, char *outputName) { + tdRSmaGetFileName(vgId, NULL, VNODE_RSMA_DIR, TD_QTASKINFO_FNAME_PREFIX, suid, level, version, outputName); } -int64_t tdAppendTFile(STFile *pTFile, void *buf, int64_t nbyte, int64_t *offset) { - ASSERT(TD_TFILE_OPENED(pTFile)); - - int64_t toffset; - - if ((toffset = tdSeekTFile(pTFile, 0, SEEK_END)) < 0) { - return -1; - } - -#if 0 - smaDebug("append to file %s, offset:%" PRIi64 " nbyte:%" PRIi64 " fsize:%" PRIi64, TD_TFILE_FULL_NAME(pTFile), - toffset, nbyte, toffset + nbyte); -#endif - - ASSERT(pTFile->info.fsize == toffset); - - if (offset) { - *offset = toffset; - } - - if (tdWriteTFile(pTFile, buf, nbyte) < 0) { - return -1; - } - - pTFile->info.fsize += nbyte; - - return nbyte; +void tdRSmaQTaskInfoGetFullName(int32_t vgId, int64_t suid, int8_t level, int64_t version, const char *path, + char *outputName) { + tdRSmaGetFileName(vgId, path, VNODE_RSMA_DIR, TD_QTASKINFO_FNAME_PREFIX, suid, level, version, outputName); } -int32_t tdOpenTFile(STFile *pTFile, int flags) { - ASSERT(!TD_TFILE_OPENED(pTFile)); - - pTFile->pFile = taosOpenFile(TD_TFILE_FULL_NAME(pTFile), flags); - if (pTFile->pFile == NULL) { - terrno = TAOS_SYSTEM_ERROR(errno); - return -1; - } - - return 0; +void tdRSmaQTaskInfoGetFullPath(int32_t vgId, int8_t level, const char *path, char *outputName) { + tdRSmaGetDirName(vgId, path, VNODE_RSMA_DIR, true, outputName); + int32_t rsmaLen = strlen(outputName); + snprintf(outputName + rsmaLen, TSDB_FILENAME_LEN - rsmaLen, "%" PRIi8, level); } -void tdCloseTFile(STFile *pTFile) { - if (TD_TFILE_OPENED(pTFile)) { - taosCloseFile(&pTFile->pFile); - TD_TFILE_SET_CLOSED(pTFile); - } +void tdRSmaQTaskInfoGetFullPathEx(int32_t vgId, tb_uid_t suid, int8_t level, const char *path, char *outputName) { + tdRSmaGetDirName(vgId, path, VNODE_RSMA_DIR, true, outputName); + int32_t rsmaLen = strlen(outputName); + snprintf(outputName + rsmaLen, TSDB_FILENAME_LEN - rsmaLen, "%" PRIi8 "%s%" PRIi64, level, TD_DIRSEP, suid); } -void tdDestroyTFile(STFile *pTFile) { taosMemoryFreeClear(TD_TFILE_FULL_NAME(pTFile)); } - -#endif - -void tdGetVndFileName(int32_t vgId, const char *pdname, const char *dname, const char *fname, int64_t version, - char *outputName) { - if (version < 0) { - if (pdname) { - snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%sv%d%s", pdname, TD_DIRSEP, TD_DIRSEP, vgId, - TD_DIRSEP, dname, TD_DIRSEP, vgId, fname); +void tdRSmaGetFileName(int32_t vgId, const char *pdname, const char *dname, const char *fname, int64_t suid, + int8_t level, int64_t version, char *outputName) { + if (level >= 0 && suid > 0) { + if (version >= 0) { + if (pdname) { + snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%s%" PRIi8 "%s%" PRIi64 "%s%s.%" PRIi64, pdname, + TD_DIRSEP, TD_DIRSEP, vgId, TD_DIRSEP, dname, TD_DIRSEP, level, TD_DIRSEP, suid, TD_DIRSEP, fname, + version); + } else { + snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s%s%" PRIi8 "%s%" PRIi64 "%s%s.%" PRIi64, TD_DIRSEP, + vgId, TD_DIRSEP, dname, TD_DIRSEP, level, TD_DIRSEP, suid, TD_DIRSEP, fname, version); + } } else { - snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s%sv%d%s", TD_DIRSEP, vgId, TD_DIRSEP, dname, TD_DIRSEP, - vgId, fname); + if (pdname) { + snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%s%" PRIi8 "%s%" PRIi64 "%s%s", pdname, + TD_DIRSEP, TD_DIRSEP, vgId, TD_DIRSEP, dname, TD_DIRSEP, level, TD_DIRSEP, suid, TD_DIRSEP, fname); + } else { + snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s%s%" PRIi8 "%s%" PRIi64 "%s%s", TD_DIRSEP, vgId, + TD_DIRSEP, dname, TD_DIRSEP, level, TD_DIRSEP, suid, TD_DIRSEP, fname); + } } } else { - if (pdname) { - snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%sv%d%s%" PRIi64, pdname, TD_DIRSEP, TD_DIRSEP, - vgId, TD_DIRSEP, dname, TD_DIRSEP, vgId, fname, version); + if (version >= 0) { + if (pdname) { + snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%sv%d%s%" PRIi64, pdname, TD_DIRSEP, TD_DIRSEP, + vgId, TD_DIRSEP, dname, TD_DIRSEP, vgId, fname, version); + } else { + snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s%sv%d%s%" PRIi64, TD_DIRSEP, vgId, TD_DIRSEP, dname, + TD_DIRSEP, vgId, fname, version); + } } else { - snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s%sv%d%s%" PRIi64, TD_DIRSEP, vgId, TD_DIRSEP, dname, - TD_DIRSEP, vgId, fname, version); + if (pdname) { + snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%sv%d%s", pdname, TD_DIRSEP, TD_DIRSEP, vgId, + TD_DIRSEP, dname, TD_DIRSEP, vgId, fname); + } else { + snprintf(outputName, TSDB_FILENAME_LEN, "vnode%svnode%d%s%s%sv%d%s", TD_DIRSEP, vgId, TD_DIRSEP, dname, + TD_DIRSEP, vgId, fname); + } } } } -void tdGetVndDirName(int32_t vgId, const char *pdname, const char *dname, bool endWithSep, char *outputName) { +void tdRSmaGetDirName(int32_t vgId, const char *pdname, const char *dname, bool endWithSep, char *outputName) { if (pdname) { if (endWithSep) { snprintf(outputName, TSDB_FILENAME_LEN, "%s%svnode%svnode%d%s%s%s", pdname, TD_DIRSEP, TD_DIRSEP, vgId, TD_DIRSEP, @@ -223,81 +98,13 @@ void tdGetVndDirName(int32_t vgId, const char *pdname, const char *dname, bool e } } -#if 0 -int32_t tdInitTFile(STFile *pTFile, const char *dname, const char *fname) { - TD_TFILE_SET_STATE(pTFile, TD_FILE_STATE_OK); - TD_TFILE_SET_CLOSED(pTFile); - - memset(&(pTFile->info), 0, sizeof(pTFile->info)); - pTFile->info.magic = TD_FILE_INIT_MAGIC; - - char tmpName[TSDB_FILENAME_LEN * 2 + 32] = {0}; - snprintf(tmpName, TSDB_FILENAME_LEN * 2 + 32, "%s%s%s", dname, TD_DIRSEP, fname); - int32_t tmpNameLen = strlen(tmpName) + 1; - pTFile->fname = taosMemoryMalloc(tmpNameLen); - if (!pTFile->fname) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return -1; - } - tstrncpy(pTFile->fname, tmpName, tmpNameLen); - - return 0; -} - -int32_t tdCreateTFile(STFile *pTFile, bool updateHeader, int8_t fType) { - ASSERT(pTFile->info.fsize == 0 && pTFile->info.magic == TD_FILE_INIT_MAGIC); - pTFile->pFile = taosOpenFile(TD_TFILE_FULL_NAME(pTFile), TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC); - if (pTFile->pFile == NULL) { - if (errno == ENOENT) { - // Try to create directory recursively - char *s = strdup(TD_TFILE_FULL_NAME(pTFile)); - if (taosMulMkDir(taosDirName(s)) != 0) { - terrno = TAOS_SYSTEM_ERROR(errno); - taosMemoryFree(s); - return -1; - } - taosMemoryFree(s); - pTFile->pFile = taosOpenFile(TD_TFILE_FULL_NAME(pTFile), TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC); - if (pTFile->pFile == NULL) { - terrno = TAOS_SYSTEM_ERROR(errno); - return -1; - } - } - } - - if (!updateHeader) { - return 0; - } - - pTFile->info.fsize += TD_FILE_HEAD_SIZE; - pTFile->info.fver = 0; - - if (tdUpdateTFileHeader(pTFile) < 0) { - tdCloseTFile(pTFile); - tdRemoveTFile(pTFile); - return -1; - } - - return 0; -} - -int32_t tdRemoveTFile(STFile *pTFile) { - if (taosRemoveFile(TD_TFILE_FULL_NAME(pTFile)) != 0) { - terrno = TAOS_SYSTEM_ERROR(errno); - return -1; - }; - return 0; -} - -#endif - // smaXXXUtil ================ void *tdAcquireSmaRef(int32_t rsetId, int64_t refId) { void *pResult = taosAcquireRef(rsetId, refId); if (!pResult) { smaWarn("rsma acquire ref for rsetId:%d refId:%" PRIi64 " failed since %s", rsetId, refId, terrstr()); } else { - smaDebug("rsma acquire ref for rsetId:%d refId:%" PRIi64 " success", rsetId, refId); + smaTrace("rsma acquire ref for rsetId:%d refId:%" PRIi64 " success", rsetId, refId); } return pResult; } @@ -307,7 +114,7 @@ int32_t tdReleaseSmaRef(int32_t rsetId, int64_t refId) { smaWarn("rsma release ref for rsetId:%d refId:%" PRIi64 " failed since %s", rsetId, refId, terrstr()); return TSDB_CODE_FAILED; } - smaDebug("rsma release ref for rsetId:%d refId:%" PRIi64 " success", rsetId, refId); + smaTrace("rsma release ref for rsetId:%d refId:%" PRIi64 " success", rsetId, refId); return TSDB_CODE_SUCCESS; } \ No newline at end of file diff --git a/source/dnode/vnode/src/tq/tq.c b/source/dnode/vnode/src/tq/tq.c index 3e13eaa6e8d27e4141f5d198b4632102dedece89..9730ad2877a248ad98a2648964203c419b3053a2 100644 --- a/source/dnode/vnode/src/tq/tq.c +++ b/source/dnode/vnode/src/tq/tq.c @@ -15,6 +15,17 @@ #include "tq.h" +// 0: not init +// 1: already inited +// 2: wait to be inited or cleaup +#define WAL_READ_TASKS_ID (-1) + +static int32_t tqInitialize(STQ* pTq); + +static FORCE_INLINE bool tqIsHandleExec(STqHandle* pHandle) { return TMQ_HANDLE_STATUS_EXEC == pHandle->status; } +static FORCE_INLINE void tqSetHandleExec(STqHandle* pHandle) {pHandle->status = TMQ_HANDLE_STATUS_EXEC;} +static FORCE_INLINE void tqSetHandleIdle(STqHandle* pHandle) {pHandle->status = TMQ_HANDLE_STATUS_IDLE;} + int32_t tqInit() { int8_t old; while (1) { @@ -51,25 +62,30 @@ void tqCleanUp() { } } -static void destroySTqHandle(void* data) { +static void destroyTqHandle(void* data) { STqHandle* pData = (STqHandle*)data; qDestroyTask(pData->execHandle.task); + if (pData->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { taosMemoryFreeClear(pData->execHandle.execCol.qmsg); } else if (pData->execHandle.subType == TOPIC_SUB_TYPE__DB) { - tqCloseReader(pData->execHandle.pExecReader); + tqCloseReader(pData->execHandle.pTqReader); walCloseReader(pData->pWalReader); taosHashCleanup(pData->execHandle.execDb.pFilterOutTbUid); } else if (pData->execHandle.subType == TOPIC_SUB_TYPE__TABLE) { walCloseReader(pData->pWalReader); - tqCloseReader(pData->execHandle.pExecReader); + tqCloseReader(pData->execHandle.pTqReader); + } + if(pData->msg != NULL) { + rpcFreeCont(pData->msg->pCont); + taosMemoryFree(pData->msg); + pData->msg = NULL; } } -static void tqPushEntryFree(void* data) { - STqPushEntry* p = *(void**)data; - tDeleteSMqDataRsp(&p->dataRsp); - taosMemoryFree(p); +static bool tqOffsetLessOrEqual(const STqOffset* pLeft, const STqOffset* pRight) { + return pLeft->val.type == TMQ_OFFSET__LOG && pRight->val.type == TMQ_OFFSET__LOG && + pLeft->val.version <= pRight->val.version; } STQ* tqOpen(const char* path, SVnode* pVnode) { @@ -78,112 +94,103 @@ STQ* tqOpen(const char* path, SVnode* pVnode) { terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } - pTq->path = strdup(path); + + pTq->path = taosStrdup(path); pTq->pVnode = pVnode; pTq->walLogLastVer = pVnode->pWal->vers.lastVer; pTq->pHandle = taosHashInit(64, MurmurHash3_32, true, HASH_ENTRY_LOCK); - taosHashSetFreeFp(pTq->pHandle, destroySTqHandle); + taosHashSetFreeFp(pTq->pHandle, destroyTqHandle); - taosInitRWLatch(&pTq->pushLock); - pTq->pPushMgr = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK); - taosHashSetFreeFp(pTq->pPushMgr, tqPushEntryFree); + taosInitRWLatch(&pTq->lock); + pTq->pPushMgr = taosHashInit(64, MurmurHash3_32, false, HASH_NO_LOCK); pTq->pCheckInfo = taosHashInit(64, MurmurHash3_32, true, HASH_ENTRY_LOCK); taosHashSetFreeFp(pTq->pCheckInfo, (FDelete)tDeleteSTqCheckInfo); - if (tqMetaOpen(pTq) < 0) { + int32_t code = tqInitialize(pTq); + if (code != TSDB_CODE_SUCCESS) { + tqClose(pTq); return NULL; + } else { + return pTq; + } +} + +int32_t tqInitialize(STQ* pTq) { + if (tqMetaOpen(pTq) < 0) { + return -1; } pTq->pOffsetStore = tqOffsetOpen(pTq); if (pTq->pOffsetStore == NULL) { - return NULL; + return -1; } - pTq->pStreamMeta = streamMetaOpen(path, pTq, (FTaskExpand*)tqExpandTask, pTq->pVnode->config.vgId); + pTq->pStreamMeta = streamMetaOpen(pTq->path, pTq, (FTaskExpand*)tqExpandTask, pTq->pVnode->config.vgId); if (pTq->pStreamMeta == NULL) { - return NULL; + return -1; } - if (streamLoadTasks(pTq->pStreamMeta) < 0) { - return NULL; + // the version is kept in task's meta data + // todo check if this version is required or not + if (streamLoadTasks(pTq->pStreamMeta, walGetCommittedVer(pTq->pVnode->pWal)) < 0) { + return -1; } - return pTq; + return 0; } void tqClose(STQ* pTq) { - if (pTq) { - tqOffsetClose(pTq->pOffsetStore); - taosHashCleanup(pTq->pHandle); - taosHashCleanup(pTq->pPushMgr); - taosHashCleanup(pTq->pCheckInfo); - taosMemoryFree(pTq->path); - tqMetaClose(pTq); - streamMetaClose(pTq->pStreamMeta); - taosMemoryFree(pTq); - } -} - -int32_t tqSendMetaPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqMetaRsp* pRsp) { - int32_t len = 0; - int32_t code = 0; - tEncodeSize(tEncodeSMqMetaRsp, pRsp, len, code); - if (code < 0) { - return -1; - } - int32_t tlen = sizeof(SMqRspHead) + len; - void* buf = rpcMallocCont(tlen); - if (buf == NULL) { - return -1; + if (pTq == NULL) { + return; } - ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_META_RSP; - ((SMqRspHead*)buf)->epoch = pReq->epoch; - ((SMqRspHead*)buf)->consumerId = pReq->consumerId; - - void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead)); - - SEncoder encoder = {0}; - tEncoderInit(&encoder, abuf, len); - tEncodeSMqMetaRsp(&encoder, pRsp); - tEncoderClear(&encoder); - - SRpcMsg resp = { - .info = pMsg->info, - .pCont = buf, - .contLen = tlen, - .code = 0, - }; - tmsgSendRsp(&resp); - - tqDebug("vgId:%d, from consumer:%" PRId64 ", (epoch %d) send rsp, res msg type %d, offset type:%d", - TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->resMsgType, pRsp->rspOffset.type); - - return 0; + tqOffsetClose(pTq->pOffsetStore); + taosHashCleanup(pTq->pHandle); + taosHashCleanup(pTq->pPushMgr); + taosHashCleanup(pTq->pCheckInfo); + taosMemoryFree(pTq->path); + tqMetaClose(pTq); + streamMetaClose(pTq->pStreamMeta); + taosMemoryFree(pTq); } -int32_t tqPushDataRsp(STQ* pTq, STqPushEntry* pPushEntry) { - SMqDataRsp* pRsp = &pPushEntry->dataRsp; +void tqNotifyClose(STQ* pTq) { + if (pTq != NULL) { + taosWLockLatch(&pTq->pStreamMeta->lock); - ASSERT(taosArrayGetSize(pRsp->blockData) == pRsp->blockNum); - ASSERT(taosArrayGetSize(pRsp->blockDataLen) == pRsp->blockNum); + void* pIter = NULL; + while (1) { + pIter = taosHashIterate(pTq->pStreamMeta->pTasks, pIter); + if (pIter == NULL) { + break; + } + + SStreamTask* pTask = *(SStreamTask**)pIter; + tqDebug("vgId:%d s-task:%s set dropping flag", pTq->pStreamMeta->vgId, pTask->id.idStr); + pTask->status.taskStatus = TASK_STATUS__STOP; - ASSERT(!pRsp->withSchema); - ASSERT(taosArrayGetSize(pRsp->blockSchema) == 0); + int64_t st = taosGetTimestampMs(); + qKillTask(pTask->exec.pExecutor, TSDB_CODE_SUCCESS); + int64_t el = taosGetTimestampMs() - st; + tqDebug("vgId:%d s-task:%s is closed in %" PRId64 "ms", pTq->pStreamMeta->vgId, pTask->id.idStr, el); + } - if (pRsp->reqOffset.type == TMQ_OFFSET__LOG) { - /*if (pRsp->blockNum > 0) {*/ - /*ASSERT(pRsp->rspOffset.version > pRsp->reqOffset.version);*/ - /*} else {*/ - ASSERT(pRsp->rspOffset.version > pRsp->reqOffset.version); - /*}*/ + taosWUnLockLatch(&pTq->pStreamMeta->lock); } +} +static int32_t doSendDataRsp(const SRpcHandleInfo* pRpcHandleInfo, const SMqDataRsp* pRsp, int32_t epoch, + int64_t consumerId, int32_t type) { int32_t len = 0; int32_t code = 0; - tEncodeSize(tEncodeSMqDataRsp, pRsp, len, code); + + if (type == TMQ_MSG_TYPE__POLL_RSP) { + tEncodeSize(tEncodeSMqDataRsp, pRsp, len, code); + } else if (type == TMQ_MSG_TYPE__TAOSX_RSP) { + tEncodeSize(tEncodeSTaosxRsp, (STaosxRsp*)pRsp, len, code); + } if (code < 0) { return -1; @@ -195,210 +202,124 @@ int32_t tqPushDataRsp(STQ* pTq, STqPushEntry* pPushEntry) { return -1; } - memcpy(buf, &pPushEntry->dataRsp.head, sizeof(SMqRspHead)); + ((SMqRspHead*)buf)->mqMsgType = type; + ((SMqRspHead*)buf)->epoch = epoch; + ((SMqRspHead*)buf)->consumerId = consumerId; void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead)); SEncoder encoder = {0}; tEncoderInit(&encoder, abuf, len); - tEncodeSMqDataRsp(&encoder, pRsp); + + if (type == TMQ_MSG_TYPE__POLL_RSP) { + tEncodeSMqDataRsp(&encoder, pRsp); + } else if (type == TMQ_MSG_TYPE__TAOSX_RSP) { + tEncodeSTaosxRsp(&encoder, (STaosxRsp*)pRsp); + } + tEncoderClear(&encoder); SRpcMsg rsp = { - .info = pPushEntry->pInfo, + .info = *pRpcHandleInfo, .pCont = buf, .contLen = tlen, .code = 0, }; tmsgSendRsp(&rsp); - - char buf1[80] = {0}; - char buf2[80] = {0}; - tFormatOffset(buf1, 80, &pRsp->reqOffset); - tFormatOffset(buf2, 80, &pRsp->rspOffset); - tqDebug("vgId:%d, from consumer:%" PRId64 ", (epoch %d) push rsp, block num: %d, reqOffset:%s, rspOffset:%s", - TD_VID(pTq->pVnode), pRsp->head.consumerId, pRsp->head.epoch, pRsp->blockNum, buf1, buf2); - return 0; } -int32_t tqSendDataRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp) { - ASSERT(taosArrayGetSize(pRsp->blockData) == pRsp->blockNum); - ASSERT(taosArrayGetSize(pRsp->blockDataLen) == pRsp->blockNum); - - ASSERT(!pRsp->withSchema); - ASSERT(taosArrayGetSize(pRsp->blockSchema) == 0); - - if (pRsp->reqOffset.type == TMQ_OFFSET__LOG) { - if (pRsp->blockNum > 0) { - ASSERT(pRsp->rspOffset.version > pRsp->reqOffset.version); - } else { - ASSERT(pRsp->rspOffset.version >= pRsp->reqOffset.version); - } - } - - int32_t len = 0; - int32_t code = 0; - tEncodeSize(tEncodeSMqDataRsp, pRsp, len, code); - if (code < 0) { - return -1; - } - int32_t tlen = sizeof(SMqRspHead) + len; - void* buf = rpcMallocCont(tlen); - if (buf == NULL) { - return -1; - } - - ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_RSP; - ((SMqRspHead*)buf)->epoch = pReq->epoch; - ((SMqRspHead*)buf)->consumerId = pReq->consumerId; - - void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead)); - - SEncoder encoder = {0}; - tEncoderInit(&encoder, abuf, len); - tEncodeSMqDataRsp(&encoder, pRsp); - tEncoderClear(&encoder); - - SRpcMsg rsp = { - .info = pMsg->info, - .pCont = buf, - .contLen = tlen, - .code = 0, - }; - tmsgSendRsp(&rsp); +int32_t tqPushDataRsp(STQ* pTq, STqHandle* pHandle) { + SMqDataRsp dataRsp = {0}; + dataRsp.head.consumerId = pHandle->consumerId; + dataRsp.head.epoch = pHandle->epoch; + dataRsp.head.mqMsgType = TMQ_MSG_TYPE__POLL_RSP; + doSendDataRsp(&pHandle->msg->info, &dataRsp, pHandle->epoch, pHandle->consumerId, TMQ_MSG_TYPE__POLL_RSP); char buf1[80] = {0}; char buf2[80] = {0}; - tFormatOffset(buf1, 80, &pRsp->reqOffset); - tFormatOffset(buf2, 80, &pRsp->rspOffset); - tqDebug("vgId:%d, from consumer:%" PRId64 ", (epoch %d) send rsp, block num: %d, reqOffset:%s, rspOffset:%s", - TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->blockNum, buf1, buf2); - + tFormatOffset(buf1, tListLen(buf1), &dataRsp.reqOffset); + tFormatOffset(buf2, tListLen(buf2), &dataRsp.rspOffset); + tqDebug("vgId:%d, from consumer:0x%" PRIx64 " (epoch %d) push rsp, block num: %d, req:%s, rsp:%s", + TD_VID(pTq->pVnode), dataRsp.head.consumerId, dataRsp.head.epoch, dataRsp.blockNum, buf1, buf2); return 0; } -int32_t tqSendTaosxRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const STaosxRsp* pRsp) { - ASSERT(taosArrayGetSize(pRsp->blockData) == pRsp->blockNum); - ASSERT(taosArrayGetSize(pRsp->blockDataLen) == pRsp->blockNum); - - if (pRsp->withSchema) { - ASSERT(taosArrayGetSize(pRsp->blockSchema) == pRsp->blockNum); - } else { - ASSERT(taosArrayGetSize(pRsp->blockSchema) == 0); - } - - if (pRsp->reqOffset.type == TMQ_OFFSET__LOG) { - if (pRsp->blockNum > 0) { - ASSERT(pRsp->rspOffset.version > pRsp->reqOffset.version); - } else { - ASSERT(pRsp->rspOffset.version >= pRsp->reqOffset.version); - } - } - - int32_t len = 0; - int32_t code = 0; - tEncodeSize(tEncodeSTaosxRsp, pRsp, len, code); - if (code < 0) { - return -1; - } - int32_t tlen = sizeof(SMqRspHead) + len; - void* buf = rpcMallocCont(tlen); - if (buf == NULL) { - return -1; - } - - ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__TAOSX_RSP; - ((SMqRspHead*)buf)->epoch = pReq->epoch; - ((SMqRspHead*)buf)->consumerId = pReq->consumerId; - - void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead)); - - SEncoder encoder = {0}; - tEncoderInit(&encoder, abuf, len); - tEncodeSTaosxRsp(&encoder, pRsp); - tEncoderClear(&encoder); - - SRpcMsg rsp = { - .info = pMsg->info, - .pCont = buf, - .contLen = tlen, - .code = 0, - }; - tmsgSendRsp(&rsp); +int32_t tqSendDataRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp, int32_t type) { + doSendDataRsp(&pMsg->info, pRsp, pReq->epoch, pReq->consumerId, type); char buf1[80] = {0}; char buf2[80] = {0}; tFormatOffset(buf1, 80, &pRsp->reqOffset); tFormatOffset(buf2, 80, &pRsp->rspOffset); - tqDebug("taosx rsp, vgId:%d, from consumer:%" PRId64 - ", (epoch %d) send rsp, block num: %d, reqOffset:%s, rspOffset:%s", - TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->blockNum, buf1, buf2); - return 0; -} + tqDebug("vgId:%d consumer:0x%" PRIx64 " (epoch %d) send rsp, block num:%d, req:%s, rsp:%s, reqId:0x%" PRIx64, + TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->blockNum, buf1, buf2, pReq->reqId); -static FORCE_INLINE bool tqOffsetLessOrEqual(const STqOffset* pLeft, const STqOffset* pRight) { - return pLeft->val.type == TMQ_OFFSET__LOG && pRight->val.type == TMQ_OFFSET__LOG && - pLeft->val.version <= pRight->val.version; + return 0; } -int32_t tqProcessOffsetCommitReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen) { +int32_t tqProcessOffsetCommitReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) { STqOffset offset = {0}; - SDecoder decoder; - tDecoderInit(&decoder, msg, msgLen); + int32_t vgId = TD_VID(pTq->pVnode); + + SDecoder decoder; + tDecoderInit(&decoder, (uint8_t*)msg, msgLen); if (tDecodeSTqOffset(&decoder, &offset) < 0) { - ASSERT(0); return -1; } + tDecoderClear(&decoder); if (offset.val.type == TMQ_OFFSET__SNAPSHOT_DATA || offset.val.type == TMQ_OFFSET__SNAPSHOT_META) { tqDebug("receive offset commit msg to %s on vgId:%d, offset(type:snapshot) uid:%" PRId64 ", ts:%" PRId64, - offset.subKey, TD_VID(pTq->pVnode), offset.val.uid, offset.val.ts); + offset.subKey, vgId, offset.val.uid, offset.val.ts); } else if (offset.val.type == TMQ_OFFSET__LOG) { - tqDebug("receive offset commit msg to %s on vgId:%d, offset(type:log) version:%" PRId64, offset.subKey, - TD_VID(pTq->pVnode), offset.val.version); - if (offset.val.version + 1 == version) { + tqDebug("receive offset commit msg to %s on vgId:%d, offset(type:log) version:%" PRId64, offset.subKey, vgId, + offset.val.version); + if (offset.val.version + 1 == sversion) { offset.val.version += 1; } } else { - ASSERT(0); + tqError("invalid commit offset type:%d", offset.val.type); + return -1; } - STqOffset* pOffset = tqOffsetRead(pTq->pOffsetStore, offset.subKey); - if (pOffset != NULL && tqOffsetLessOrEqual(&offset, pOffset)) { - return 0; + + STqOffset* pSavedOffset = tqOffsetRead(pTq->pOffsetStore, offset.subKey); + if (pSavedOffset != NULL && tqOffsetLessOrEqual(&offset, pSavedOffset)) { + return 0; // no need to update the offset value } + // save the new offset value if (tqOffsetWrite(pTq->pOffsetStore, &offset) < 0) { - ASSERT(0); return -1; } if (offset.val.type == TMQ_OFFSET__LOG) { + taosWLockLatch(&pTq->lock); STqHandle* pHandle = taosHashGet(pTq->pHandle, offset.subKey, strlen(offset.subKey)); - if (pHandle) { - if (walRefVer(pHandle->pRef, offset.val.version) < 0) { - return -1; - } + if (pHandle && (walSetRefVer(pHandle->pRef, offset.val.version) < 0)) { + taosWUnLockLatch(&pTq->lock); + return -1; } + taosWUnLockLatch(&pTq->lock); } - // rsp - - /*}*/ - /*}*/ - return 0; } int32_t tqCheckColModifiable(STQ* pTq, int64_t tbUid, int32_t colId) { void* pIter = NULL; + while (1) { pIter = taosHashIterate(pTq->pCheckInfo, pIter); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } + STqCheckInfo* pCheck = (STqCheckInfo*)pIter; + if (pCheck->ntbUid == tbUid) { int32_t sz = taosArrayGetSize(pCheck->colIdList); for (int32_t i = 0; i < sz; i++) { @@ -410,331 +331,81 @@ int32_t tqCheckColModifiable(STQ* pTq, int64_t tbUid, int32_t colId) { } } } - return 0; -} - -static int32_t tqInitDataRsp(SMqDataRsp* pRsp, const SMqPollReq* pReq, int8_t subType) { - pRsp->reqOffset = pReq->reqOffset; - - pRsp->blockData = taosArrayInit(0, sizeof(void*)); - pRsp->blockDataLen = taosArrayInit(0, sizeof(int32_t)); - - if (pRsp->blockData == NULL || pRsp->blockDataLen == NULL) { - return -1; - } - - pRsp->withTbName = 0; -#if 0 - pRsp->withTbName = pReq->withTbName; - if (pRsp->withTbName) { - pRsp->blockTbName = taosArrayInit(0, sizeof(void*)); - if (pRsp->blockTbName == NULL) { - // TODO free - return -1; - } - } -#endif - - ASSERT(subType == TOPIC_SUB_TYPE__COLUMN); - pRsp->withSchema = false; return 0; } -static int32_t tqInitTaosxRsp(STaosxRsp* pRsp, const SMqPollReq* pReq) { - pRsp->reqOffset = pReq->reqOffset; - - pRsp->withTbName = 1; - pRsp->withSchema = 1; - pRsp->blockData = taosArrayInit(0, sizeof(void*)); - pRsp->blockDataLen = taosArrayInit(0, sizeof(int32_t)); - pRsp->blockTbName = taosArrayInit(0, sizeof(void*)); - pRsp->blockSchema = taosArrayInit(0, sizeof(void*)); - - if (pRsp->blockData == NULL || pRsp->blockDataLen == NULL || pRsp->blockTbName == NULL || pRsp->blockSchema == NULL) { - return -1; - } - return 0; -} - int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg) { - SMqPollReq req = {0}; - int32_t code = 0; - STqOffsetVal fetchOffsetNew; - SWalCkHead* pCkHead = NULL; - + SMqPollReq req = {0}; if (tDeserializeSMqPollReq(pMsg->pCont, pMsg->contLen, &req) < 0) { tqError("tDeserializeSMqPollReq %d failed", pMsg->contLen); + terrno = TSDB_CODE_INVALID_MSG; return -1; } int64_t consumerId = req.consumerId; int32_t reqEpoch = req.epoch; STqOffsetVal reqOffset = req.reqOffset; + int32_t vgId = TD_VID(pTq->pVnode); - // 1.find handle + taosWLockLatch(&pTq->lock); + // 1. find handle STqHandle* pHandle = taosHashGet(pTq->pHandle, req.subKey, strlen(req.subKey)); - /*ASSERT(pHandle);*/ if (pHandle == NULL) { - tqError("tmq poll: no consumer handle for consumer:%" PRId64 ", in vgId:%d, subkey %s", consumerId, - TD_VID(pTq->pVnode), req.subKey); + tqError("tmq poll: consumer:0x%" PRIx64 " vgId:%d subkey %s not found", consumerId, vgId, req.subKey); + terrno = TSDB_CODE_INVALID_MSG; + taosWUnLockLatch(&pTq->lock); return -1; } - // check rebalance + while (tqIsHandleExec(pHandle)) { + tqDebug("tmq poll: consumer:0x%" PRIx64 "vgId:%d, topic:%s, subscription is executing, wait for 5ms and retry", consumerId, vgId, req.subKey); + taosMsleep(5); + } + + // 2. check re-balance status if (pHandle->consumerId != consumerId) { - tqError("tmq poll: consumer handle mismatch for consumer:%" PRId64 - ", in vgId:%d, subkey %s, handle consumer id %" PRId64, + tqDebug("ERROR tmq poll: consumer:0x%" PRIx64 " vgId:%d, subkey %s, mismatch for saved handle consumer:0x%" PRIx64, consumerId, TD_VID(pTq->pVnode), req.subKey, pHandle->consumerId); terrno = TSDB_CODE_TMQ_CONSUMER_MISMATCH; + taosWUnLockLatch(&pTq->lock); return -1; } + tqSetHandleExec(pHandle); + taosWUnLockLatch(&pTq->lock); - // update epoch if need - int32_t consumerEpoch = atomic_load_32(&pHandle->epoch); - while (consumerEpoch < reqEpoch) { - consumerEpoch = atomic_val_compare_exchange_32(&pHandle->epoch, consumerEpoch, reqEpoch); + // 3. update the epoch value + int32_t savedEpoch = pHandle->epoch; + if (savedEpoch < reqEpoch) { + tqDebug("tmq poll: consumer:0x%" PRIx64 " epoch update from %d to %d by poll req", consumerId, savedEpoch, + reqEpoch); + pHandle->epoch = reqEpoch; } char buf[80]; tFormatOffset(buf, 80, &reqOffset); - tqDebug("tmq poll: consumer %" PRId64 " (epoch %d), subkey %s, recv poll req in vg %d, req offset %s", consumerId, - req.epoch, pHandle->subKey, TD_VID(pTq->pVnode), buf); - - // 2.reset offset if needed - if (reqOffset.type > 0) { - fetchOffsetNew = reqOffset; - } else { - STqOffset* pOffset = tqOffsetRead(pTq->pOffsetStore, req.subKey); - if (pOffset != NULL) { - fetchOffsetNew = pOffset->val; - char formatBuf[80]; - tFormatOffset(formatBuf, 80, &fetchOffsetNew); - tqDebug("tmq poll: consumer %" PRId64 ", subkey %s, vg %d, offset reset to %s", consumerId, pHandle->subKey, - TD_VID(pTq->pVnode), formatBuf); - } else { - if (reqOffset.type == TMQ_OFFSET__RESET_EARLIEAST) { - if (req.useSnapshot) { - if (pHandle->fetchMeta) { - tqOffsetResetToMeta(&fetchOffsetNew, 0); - } else { - tqOffsetResetToData(&fetchOffsetNew, 0, 0); - } - } else { - pHandle->pRef = walRefFirstVer(pTq->pVnode->pWal, pHandle->pRef); - if (pHandle->pRef == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return -1; - } - tqOffsetResetToLog(&fetchOffsetNew, pHandle->pRef->refVer - 1); - } - } else if (reqOffset.type == TMQ_OFFSET__RESET_LATEST) { - if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { - SMqDataRsp dataRsp = {0}; - tqInitDataRsp(&dataRsp, &req, pHandle->execHandle.subType); - - tqOffsetResetToLog(&dataRsp.rspOffset, walGetLastVer(pTq->pVnode->pWal)); - tqDebug("tmq poll: consumer %" PRId64 ", subkey %s, vg %d, offset reset to %" PRId64, consumerId, - pHandle->subKey, TD_VID(pTq->pVnode), dataRsp.rspOffset.version); - if (tqSendDataRsp(pTq, pMsg, &req, &dataRsp) < 0) { - code = -1; - } - tDeleteSMqDataRsp(&dataRsp); - return code; - } else { - STaosxRsp taosxRsp = {0}; - tqInitTaosxRsp(&taosxRsp, &req); - tqOffsetResetToLog(&taosxRsp.rspOffset, walGetLastVer(pTq->pVnode->pWal)); - if (tqSendTaosxRsp(pTq, pMsg, &req, &taosxRsp) < 0) { - code = -1; - } - tDeleteSTaosxRsp(&taosxRsp); - return code; - } - } else if (reqOffset.type == TMQ_OFFSET__RESET_NONE) { - tqError("tmq poll: subkey %s, no offset committed for consumer %" PRId64 - " in vg %d, subkey %s, reset none failed", - pHandle->subKey, consumerId, TD_VID(pTq->pVnode), req.subKey); - terrno = TSDB_CODE_TQ_NO_COMMITTED_OFFSET; - return -1; - } - } - } - - if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { - SMqDataRsp dataRsp = {0}; - tqInitDataRsp(&dataRsp, &req, pHandle->execHandle.subType); - // lock - taosWLockLatch(&pTq->pushLock); - tqScanData(pTq, pHandle, &dataRsp, &fetchOffsetNew); - -#if 1 - if (dataRsp.blockNum == 0 && dataRsp.reqOffset.type == TMQ_OFFSET__LOG && - dataRsp.reqOffset.version == dataRsp.rspOffset.version) { - STqPushEntry* pPushEntry = taosMemoryCalloc(1, sizeof(STqPushEntry)); - if (pPushEntry != NULL) { - pPushEntry->pInfo = pMsg->info; - memcpy(pPushEntry->subKey, pHandle->subKey, TSDB_SUBSCRIBE_KEY_LEN); - dataRsp.withTbName = 0; - memcpy(&pPushEntry->dataRsp, &dataRsp, sizeof(SMqDataRsp)); - pPushEntry->dataRsp.head.consumerId = consumerId; - pPushEntry->dataRsp.head.epoch = reqEpoch; - pPushEntry->dataRsp.head.mqMsgType = TMQ_MSG_TYPE__POLL_RSP; - taosHashPut(pTq->pPushMgr, pHandle->subKey, strlen(pHandle->subKey) + 1, &pPushEntry, sizeof(void*)); - tqDebug("tmq poll: consumer %" PRId64 ", subkey %s, vg %d save handle to push mgr", consumerId, pHandle->subKey, - TD_VID(pTq->pVnode)); - // unlock - taosWUnLockLatch(&pTq->pushLock); - return 0; - } - } -#endif - taosWUnLockLatch(&pTq->pushLock); - - if (tqSendDataRsp(pTq, pMsg, &req, &dataRsp) < 0) { - code = -1; - } - - tqDebug("tmq poll: consumer %" PRId64 - ", subkey %s, vg %d, send data blockNum:%d, offset type:%d, uid/version:%" PRId64 ", ts:%" PRId64 "", - consumerId, pHandle->subKey, TD_VID(pTq->pVnode), dataRsp.blockNum, dataRsp.rspOffset.type, - dataRsp.rspOffset.uid, dataRsp.rspOffset.ts); - - tDeleteSMqDataRsp(&dataRsp); - return code; - } - - // for taosx - ASSERT(pHandle->execHandle.subType != TOPIC_SUB_TYPE__COLUMN); - - SMqMetaRsp metaRsp = {0}; - - STaosxRsp taosxRsp = {0}; - tqInitTaosxRsp(&taosxRsp, &req); - - if (fetchOffsetNew.type != TMQ_OFFSET__LOG) { - tqScanTaosx(pTq, pHandle, &taosxRsp, &metaRsp, &fetchOffsetNew); - - if (metaRsp.metaRspLen > 0) { - if (tqSendMetaPollRsp(pTq, pMsg, &req, &metaRsp) < 0) { - code = -1; - } - tqDebug("tmq poll: consumer %" PRId64 ", subkey %s, vg %d, send meta offset type:%d,uid:%" PRId64 - ",version:%" PRId64 "", - consumerId, pHandle->subKey, TD_VID(pTq->pVnode), metaRsp.rspOffset.type, metaRsp.rspOffset.uid, - metaRsp.rspOffset.version); - taosMemoryFree(metaRsp.metaRsp); - tDeleteSTaosxRsp(&taosxRsp); - return code; - } - - if (taosxRsp.blockNum > 0) { - if (tqSendTaosxRsp(pTq, pMsg, &req, &taosxRsp) < 0) { - code = -1; - } - tDeleteSTaosxRsp(&taosxRsp); - return code; - } else { - fetchOffsetNew = taosxRsp.rspOffset; - } - - tqDebug("taosx poll: consumer %" PRId64 ", subkey %s, vg %d, send data blockNum:%d, offset type:%d,uid:%" PRId64 - ",version:%" PRId64 "", - consumerId, pHandle->subKey, TD_VID(pTq->pVnode), taosxRsp.blockNum, taosxRsp.rspOffset.type, - taosxRsp.rspOffset.uid, taosxRsp.rspOffset.version); - } - - if (fetchOffsetNew.type == TMQ_OFFSET__LOG) { - int64_t fetchVer = fetchOffsetNew.version + 1; - pCkHead = taosMemoryMalloc(sizeof(SWalCkHead) + 2048); - if (pCkHead == NULL) { - tDeleteSTaosxRsp(&taosxRsp); - return -1; - } - - walSetReaderCapacity(pHandle->pWalReader, 2048); - - while (1) { - consumerEpoch = atomic_load_32(&pHandle->epoch); - if (consumerEpoch > reqEpoch) { - tqWarn("tmq poll: consumer %" PRId64 " (epoch %d), subkey %s, vg %d offset %" PRId64 - ", found new consumer epoch %d, discard req epoch %d", - consumerId, req.epoch, pHandle->subKey, TD_VID(pTq->pVnode), fetchVer, consumerEpoch, reqEpoch); - break; - } - - if (tqFetchLog(pTq, pHandle, &fetchVer, &pCkHead) < 0) { - tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer); - if (tqSendTaosxRsp(pTq, pMsg, &req, &taosxRsp) < 0) { - code = -1; - } - tDeleteSTaosxRsp(&taosxRsp); - taosMemoryFreeClear(pCkHead); - return code; - } - - SWalCont* pHead = &pCkHead->head; - - tqDebug("tmq poll: consumer:%" PRId64 ", (epoch %d) iter log, vgId:%d offset %" PRId64 " msgType %d", consumerId, - req.epoch, TD_VID(pTq->pVnode), fetchVer, pHead->msgType); - - if (pHead->msgType == TDMT_VND_SUBMIT) { - SSubmitReq* pCont = (SSubmitReq*)&pHead->body; - - if (tqTaosxScanLog(pTq, pHandle, pCont, &taosxRsp) < 0) { - } - if (taosxRsp.blockNum > 0 /* threshold */) { - tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer); - if (tqSendTaosxRsp(pTq, pMsg, &req, &taosxRsp) < 0) { - code = -1; - } - tDeleteSTaosxRsp(&taosxRsp); - taosMemoryFreeClear(pCkHead); - return code; - } else { - fetchVer++; - } + tqDebug("tmq poll: consumer:0x%" PRIx64 " (epoch %d), subkey %s, recv poll req vgId:%d, req:%s, reqId:0x%" PRIx64, + consumerId, req.epoch, pHandle->subKey, vgId, buf, req.reqId); - } else { - ASSERT(pHandle->fetchMeta); - ASSERT(IS_META_MSG(pHead->msgType)); - tqDebug("fetch meta msg, ver:%" PRId64 ", type:%d", pHead->version, pHead->msgType); - tqOffsetResetToLog(&metaRsp.rspOffset, fetchVer); - metaRsp.resMsgType = pHead->msgType; - metaRsp.metaRspLen = pHead->bodyLen; - metaRsp.metaRsp = pHead->body; - if (tqSendMetaPollRsp(pTq, pMsg, &req, &metaRsp) < 0) { - code = -1; - taosMemoryFreeClear(pCkHead); - tDeleteSTaosxRsp(&taosxRsp); - return code; - } - code = 0; - taosMemoryFreeClear(pCkHead); - tDeleteSTaosxRsp(&taosxRsp); - return code; - } - } - } - tDeleteSTaosxRsp(&taosxRsp); - taosMemoryFreeClear(pCkHead); - return 0; + int code = tqExtractDataForMq(pTq, pHandle, &req, pMsg); + tqSetHandleIdle(pHandle); + return code; } -int32_t tqProcessDeleteSubReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen) { +int32_t tqProcessDeleteSubReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) { SMqVDeleteReq* pReq = (SMqVDeleteReq*)msg; + int32_t vgId = TD_VID(pTq->pVnode); - tqDebug("vgId:%d, delete sub: %s", pTq->pVnode->config.vgId, pReq->subKey); - - taosWLockLatch(&pTq->pushLock); - int32_t code = taosHashRemove(pTq->pPushMgr, pReq->subKey, strlen(pReq->subKey)); - if (code != 0) { - tqDebug("vgId:%d, tq remove push handle %s", pTq->pVnode->config.vgId, pReq->subKey); - } - taosWUnLockLatch(&pTq->pushLock); + tqDebug("vgId:%d, tq process delete sub req %s", pTq->pVnode->config.vgId, pReq->subKey); + int32_t code = 0; + taosWLockLatch(&pTq->lock); STqHandle* pHandle = taosHashGet(pTq->pHandle, pReq->subKey, strlen(pReq->subKey)); if (pHandle) { + while (tqIsHandleExec(pHandle)) { + tqDebug("vgId:%d, topic:%s, subscription is executing, wait for 5ms and retry", vgId, pHandle->subKey); + taosMsleep(5); + } if (pHandle->pRef) { walCloseRef(pTq->pVnode->pWal, pHandle->pRef->refId); } @@ -752,13 +423,15 @@ int32_t tqProcessDeleteSubReq(STQ* pTq, int64_t version, char* msg, int32_t msgL if (tqMetaDeleteHandle(pTq, pReq->subKey) < 0) { tqError("cannot process tq delete req %s, since no such offset in tdb", pReq->subKey); } + taosWUnLockLatch(&pTq->lock); + return 0; } -int32_t tqProcessAddCheckInfoReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen) { +int32_t tqProcessAddCheckInfoReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) { STqCheckInfo info = {0}; SDecoder decoder; - tDecoderInit(&decoder, msg, msgLen); + tDecoderInit(&decoder, (uint8_t*)msg, msgLen); if (tDecodeSTqCheckInfo(&decoder, &info) < 0) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -775,7 +448,7 @@ int32_t tqProcessAddCheckInfoReq(STQ* pTq, int64_t version, char* msg, int32_t m return 0; } -int32_t tqProcessDelCheckInfoReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen) { +int32_t tqProcessDelCheckInfoReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) { if (taosHashRemove(pTq->pCheckInfo, msg, strlen(msg)) < 0) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -787,25 +460,34 @@ int32_t tqProcessDelCheckInfoReq(STQ* pTq, int64_t version, char* msg, int32_t m return 0; } -int32_t tqProcessSubscribeReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen) { +int32_t tqProcessSubscribeReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) { + int ret = 0; SMqRebVgReq req = {0}; tDecodeSMqRebVgReq(msg, &req); - // todo lock + + SVnode* pVnode = pTq->pVnode; + int32_t vgId = TD_VID(pVnode); + + tqDebug("vgId:%d, tq process sub req:%s, Id:0x%" PRIx64 " -> Id:0x%" PRIx64, pVnode->config.vgId, req.subKey, + req.oldConsumerId, req.newConsumerId); + + taosWLockLatch(&pTq->lock); STqHandle* pHandle = taosHashGet(pTq->pHandle, req.subKey, strlen(req.subKey)); if (pHandle == NULL) { if (req.oldConsumerId != -1) { - tqError("vgId:%d, build new consumer handle %s for consumer %" PRId64 ", but old consumerId is %" PRId64 "", + tqError("vgId:%d, build new consumer handle %s for consumer:0x%" PRIx64 ", but old consumerId:0x%" PRIx64, req.vgId, req.subKey, req.newConsumerId, req.oldConsumerId); } + if (req.newConsumerId == -1) { - tqError("vgId:%d, tq invalid rebalance request, new consumerId %" PRId64 "", req.vgId, req.newConsumerId); - taosMemoryFree(req.qmsg); - return 0; + tqError("vgId:%d, tq invalid re-balance request, new consumerId %" PRId64 "", req.vgId, req.newConsumerId); + goto end; } + STqHandle tqHandle = {0}; pHandle = &tqHandle; - /*taosInitRWLatch(&pExec->lock);*/ + uint64_t oldConsumerId = pHandle->consumerId; memcpy(pHandle->subKey, req.subKey, TSDB_SUBSCRIBE_KEY_LEN); pHandle->consumerId = req.newConsumerId; pHandle->epoch = -1; @@ -814,89 +496,104 @@ int32_t tqProcessSubscribeReq(STQ* pTq, int64_t version, char* msg, int32_t msgL pHandle->fetchMeta = req.withMeta; // TODO version should be assigned and refed during preprocess - SWalRef* pRef = walRefCommittedVer(pTq->pVnode->pWal); + SWalRef* pRef = walRefCommittedVer(pVnode->pWal); if (pRef == NULL) { - return -1; + ret = -1; + goto end; } + int64_t ver = pRef->refVer; pHandle->pRef = pRef; SReadHandle handle = { - .meta = pTq->pVnode->pMeta, - .vnode = pTq->pVnode, - .initTableReader = true, - .initTqReader = true, - .version = ver, - }; + .meta = pVnode->pMeta, .vnode = pVnode, .initTableReader = true, .initTqReader = true, .version = ver}; pHandle->snapshotVer = ver; if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { pHandle->execHandle.execCol.qmsg = req.qmsg; req.qmsg = NULL; - pHandle->execHandle.task = - qCreateQueueExecTaskInfo(pHandle->execHandle.execCol.qmsg, &handle, &pHandle->execHandle.numOfCols, NULL); + pHandle->execHandle.task = qCreateQueueExecTaskInfo(pHandle->execHandle.execCol.qmsg, &handle, vgId, + &pHandle->execHandle.numOfCols, req.newConsumerId); void* scanner = NULL; qExtractStreamScanner(pHandle->execHandle.task, &scanner); - pHandle->execHandle.pExecReader = qExtractReaderFromStreamScanner(scanner); + pHandle->execHandle.pTqReader = qExtractReaderFromStreamScanner(scanner); } else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__DB) { - pHandle->pWalReader = walOpenReader(pTq->pVnode->pWal, NULL); - pHandle->execHandle.pExecReader = tqOpenReader(pTq->pVnode); + pHandle->pWalReader = walOpenReader(pVnode->pWal, NULL); + pHandle->execHandle.pTqReader = tqReaderOpen(pVnode); + pHandle->execHandle.execDb.pFilterOutTbUid = - taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); + taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_ENTRY_LOCK); buildSnapContext(handle.meta, handle.version, 0, pHandle->execHandle.subType, pHandle->fetchMeta, (SSnapContext**)(&handle.sContext)); - pHandle->execHandle.task = qCreateQueueExecTaskInfo(NULL, &handle, NULL, NULL); + pHandle->execHandle.task = qCreateQueueExecTaskInfo(NULL, &handle, vgId, NULL, req.newConsumerId); } else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__TABLE) { - pHandle->pWalReader = walOpenReader(pTq->pVnode->pWal, NULL); - + pHandle->pWalReader = walOpenReader(pVnode->pWal, NULL); pHandle->execHandle.execTb.suid = req.suid; SArray* tbUidList = taosArrayInit(0, sizeof(int64_t)); - vnodeGetCtbIdList(pTq->pVnode, req.suid, tbUidList); - tqDebug("vgId:%d, tq try to get all ctb, suid:%" PRId64, pTq->pVnode->config.vgId, req.suid); + vnodeGetCtbIdList(pVnode, req.suid, tbUidList); + tqDebug("vgId:%d, tq try to get all ctb, suid:%" PRId64, pVnode->config.vgId, req.suid); for (int32_t i = 0; i < taosArrayGetSize(tbUidList); i++) { int64_t tbUid = *(int64_t*)taosArrayGet(tbUidList, i); - tqDebug("vgId:%d, idx %d, uid:%" PRId64, TD_VID(pTq->pVnode), i, tbUid); + tqDebug("vgId:%d, idx %d, uid:%" PRId64, vgId, i, tbUid); } - pHandle->execHandle.pExecReader = tqOpenReader(pTq->pVnode); - tqReaderSetTbUidList(pHandle->execHandle.pExecReader, tbUidList); + pHandle->execHandle.pTqReader = tqReaderOpen(pVnode); + tqReaderSetTbUidList(pHandle->execHandle.pTqReader, tbUidList); taosArrayDestroy(tbUidList); buildSnapContext(handle.meta, handle.version, req.suid, pHandle->execHandle.subType, pHandle->fetchMeta, (SSnapContext**)(&handle.sContext)); - pHandle->execHandle.task = qCreateQueueExecTaskInfo(NULL, &handle, NULL, NULL); + pHandle->execHandle.task = qCreateQueueExecTaskInfo(NULL, &handle, vgId, NULL, req.newConsumerId); } + taosHashPut(pTq->pHandle, req.subKey, strlen(req.subKey), pHandle, sizeof(STqHandle)); - tqDebug("try to persist handle %s consumer %" PRId64, req.subKey, pHandle->consumerId); - if (tqMetaSaveHandle(pTq, req.subKey, pHandle) < 0) { - return -1; - } + tqDebug("try to persist handle %s consumer:0x%" PRIx64 " , old consumer:0x%" PRIx64, req.subKey, + pHandle->consumerId, oldConsumerId); + ret = tqMetaSaveHandle(pTq, req.subKey, pHandle); + goto end; } else { - /*ASSERT(pExec->consumerId == req.oldConsumerId);*/ - // TODO handle qmsg and exec modification - atomic_store_32(&pHandle->epoch, -1); - atomic_store_64(&pHandle->consumerId, req.newConsumerId); - atomic_add_fetch_32(&pHandle->epoch, 1); - taosMemoryFree(req.qmsg); - if (tqMetaSaveHandle(pTq, req.subKey, pHandle) < 0) { - return -1; + while (tqIsHandleExec(pHandle)) { + tqDebug("sub req vgId:%d, topic:%s, subscription is executing, wait for 5ms and retry", vgId, pHandle->subKey); + taosMsleep(5); + } + + if (pHandle->consumerId == req.newConsumerId) { // do nothing + tqInfo("vgId:%d consumer:0x%" PRIx64 " remains, no switch occurs", req.vgId, req.newConsumerId); + atomic_add_fetch_32(&pHandle->epoch, 1); + + } else { + tqInfo("vgId:%d switch consumer from Id:0x%" PRIx64 " to Id:0x%" PRIx64, req.vgId, pHandle->consumerId, + req.newConsumerId); + atomic_store_64(&pHandle->consumerId, req.newConsumerId); + atomic_store_32(&pHandle->epoch, 0); + } + // kill executing task + qTaskInfo_t pTaskInfo = pHandle->execHandle.task; + if (pTaskInfo != NULL) { + qKillTask(pTaskInfo, TSDB_CODE_SUCCESS); } - // close handle + if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { + qStreamCloseTsdbReader(pTaskInfo); + } + // remove if it has been register in the push manager, and return one empty block to consumer + tqUnregisterPushHandle(pTq, pHandle); + ret = tqMetaSaveHandle(pTq, req.subKey, pHandle); + goto end; } - return 0; +end: + taosWUnLockLatch(&pTq->lock); + taosMemoryFree(req.qmsg); + return ret; } int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver) { - if (pTask->taskLevel == TASK_LEVEL__AGG) { - ASSERT(taosArrayGetSize(pTask->childEpInfo) != 0); - } - + int32_t vgId = TD_VID(pTq->pVnode); + pTask->id.idStr = createStreamTaskIdStr(pTask->id.streamId, pTask->id.taskId); pTask->refCnt = 1; - pTask->schedStatus = TASK_SCHED_STATUS__INACTIVE; - + pTask->status.schedStatus = TASK_SCHED_STATUS__INACTIVE; pTask->inputQueue = streamQueueOpen(); pTask->outputQueue = streamQueueOpen(); @@ -906,15 +603,13 @@ int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver) { pTask->inputStatus = TASK_INPUT_STATUS__NORMAL; pTask->outputStatus = TASK_OUTPUT_STATUS__NORMAL; - pTask->pMsgCb = &pTq->pVnode->msgCb; - - pTask->startVer = ver; + pTask->pMeta = pTq->pStreamMeta; + pTask->chkInfo.version = ver; + pTask->chkInfo.currentVer = ver; // expand executor - if (pTask->fillHistory) { - pTask->taskStatus = TASK_STATUS__WAIT_DOWNSTREAM; - } + pTask->status.taskStatus = (pTask->fillHistory)? TASK_STATUS__WAIT_DOWNSTREAM:TASK_STATUS__NORMAL; if (pTask->taskLevel == TASK_LEVEL__SOURCE) { pTask->pState = streamStateOpen(pTq->pStreamMeta->path, pTask, false, -1, -1); @@ -923,26 +618,26 @@ int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver) { } SReadHandle handle = { - .meta = pTq->pVnode->pMeta, - .vnode = pTq->pVnode, - .initTqReader = 1, - .pStateBackend = pTask->pState, - }; - pTask->exec.executor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &handle); - ASSERT(pTask->exec.executor); + .meta = pTq->pVnode->pMeta, .vnode = pTq->pVnode, .initTqReader = 1, .pStateBackend = pTask->pState}; + + pTask->exec.pExecutor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &handle, vgId); + if (pTask->exec.pExecutor == NULL) { + return -1; + } } else if (pTask->taskLevel == TASK_LEVEL__AGG) { pTask->pState = streamStateOpen(pTq->pStreamMeta->path, pTask, false, -1, -1); if (pTask->pState == NULL) { return -1; } - SReadHandle mgHandle = { - .vnode = NULL, - .numOfVgroups = (int32_t)taosArrayGetSize(pTask->childEpInfo), - .pStateBackend = pTask->pState, - }; - pTask->exec.executor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &mgHandle); - ASSERT(pTask->exec.executor); + + int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTask->childEpInfo); + SReadHandle mgHandle = { .vnode = NULL, .numOfVgroups = numOfVgroups, .pStateBackend = pTask->pState}; + + pTask->exec.pExecutor = qCreateStreamExecTaskInfo(pTask->exec.qmsg, &mgHandle, vgId); + if (pTask->exec.pExecutor == NULL) { + return -1; + } } // sink @@ -952,20 +647,34 @@ int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver) { pTask->smaSink.smaSink = smaHandleRes; } else if (pTask->outputType == TASK_OUTPUT__TABLE) { pTask->tbSink.vnode = pTq->pVnode; - pTask->tbSink.tbSinkFunc = tqSinkToTablePipeline; + pTask->tbSink.tbSinkFunc = tqSinkToTablePipeline2; + + int32_t ver1 = 1; + SMetaInfo info = {0}; + int32_t code = metaGetInfo(pTq->pVnode->pMeta, pTask->tbSink.stbUid, &info, NULL); + if (code == TSDB_CODE_SUCCESS) { + ver1 = info.skmVer; + } - ASSERT(pTask->tbSink.pSchemaWrapper); - ASSERT(pTask->tbSink.pSchemaWrapper->pSchema); + SSchemaWrapper* pschemaWrapper = pTask->tbSink.pSchemaWrapper; + pTask->tbSink.pTSchema = tBuildTSchema(pschemaWrapper->pSchema, pschemaWrapper->nCols, ver1); + if(pTask->tbSink.pTSchema == NULL) { + return -1; + } + } - pTask->tbSink.pTSchema = - tdGetSTSChemaFromSSChema(pTask->tbSink.pSchemaWrapper->pSchema, pTask->tbSink.pSchemaWrapper->nCols, 1); - ASSERT(pTask->tbSink.pTSchema); + if (pTask->taskLevel == TASK_LEVEL__SOURCE) { + SWalFilterCond cond = {.deleteMsg = 1}; + pTask->exec.pWalReader = walOpenReader(pTq->pVnode->pWal, &cond); } streamSetupTrigger(pTask); - tqInfo("expand stream task on vg %d, task id %d, child id %d, level %d", TD_VID(pTq->pVnode), pTask->taskId, - pTask->selfChildId, pTask->taskLevel); + tqInfo("vgId:%d expand stream task, s-task:%s, checkpoint ver:%" PRId64 " child id:%d, level:%d", vgId, pTask->id.idStr, + pTask->chkInfo.version, pTask->selfChildId, pTask->taskLevel); + + // next valid version will add one + pTask->chkInfo.version += 1; return 0; } @@ -975,7 +684,7 @@ int32_t tqProcessStreamTaskCheckReq(STQ* pTq, SRpcMsg* pMsg) { int32_t msgLen = pMsg->contLen - sizeof(SMsgHead); SStreamTaskCheckReq req; SDecoder decoder; - tDecoderInit(&decoder, msgBody, msgLen); + tDecoderInit(&decoder, (uint8_t*)msgBody, msgLen); tDecodeSStreamTaskCheckReq(&decoder, &req); tDecoderClear(&decoder); int32_t taskId = req.downstreamTaskId; @@ -988,24 +697,31 @@ int32_t tqProcessStreamTaskCheckReq(STQ* pTq, SRpcMsg* pMsg) { .upstreamNodeId = req.upstreamNodeId, .upstreamTaskId = req.upstreamTaskId, }; + SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, taskId); - if (pTask && atomic_load_8(&pTask->taskStatus) == TASK_STATUS__NORMAL) { - rsp.status = 1; + + if (pTask) { + rsp.status = streamTaskCheckStatus(pTask); + streamMetaReleaseTask(pTq->pStreamMeta, pTask); + + tqDebug("tq recv task check req(reqId:0x%" PRIx64 + ") %d at node %d task status:%d, check req from task %d at node %d, rsp status %d", + rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, pTask->status.taskStatus, rsp.upstreamTaskId, + rsp.upstreamNodeId, rsp.status); } else { rsp.status = 0; + tqDebug("tq recv task check(taskId:%d not built yet) req(reqId:0x%" PRIx64 + ") %d at node %d, check req from task %d at node %d, rsp status %d", + taskId, rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, rsp.upstreamTaskId, rsp.upstreamNodeId, + rsp.status); } - if (pTask) streamMetaReleaseTask(pTq->pStreamMeta, pTask); - - tqDebug("tq recv task check req(reqId: %" PRId64 ") %d at node %d check req from task %d at node %d, status %d", - rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.status); - SEncoder encoder; int32_t code; int32_t len; tEncodeSize(tEncodeSStreamTaskCheckRsp, &rsp, len, code); if (code < 0) { - tqDebug("tq encode stream check rsp error"); + tqError("unable to encode rsp %d", __LINE__); return -1; } @@ -1017,18 +733,12 @@ int32_t tqProcessStreamTaskCheckReq(STQ* pTq, SRpcMsg* pMsg) { tEncodeSStreamTaskCheckRsp(&encoder, &rsp); tEncoderClear(&encoder); - SRpcMsg rspMsg = { - .code = 0, - .pCont = buf, - .contLen = sizeof(SMsgHead) + len, - .info = pMsg->info, - }; - + SRpcMsg rspMsg = { .code = 0, .pCont = buf, .contLen = sizeof(SMsgHead) + len, .info = pMsg->info }; tmsgSendRsp(&rspMsg); return 0; } -int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t version, char* msg, int32_t msgLen) { +int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) { int32_t code; SStreamTaskCheckRsp rsp; @@ -1039,9 +749,9 @@ int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t version, char* msg, int32_ tDecoderClear(&decoder); return -1; } - tDecoderClear(&decoder); - tqDebug("tq recv task check rsp(reqId: %" PRId64 ") %d at node %d check req from task %d at node %d, status %d", + tDecoderClear(&decoder); + tqDebug("tq recv task check rsp(reqId:0x%" PRIx64 ") %d at node %d check req from task %d at node %d, status %d", rsp.reqId, rsp.downstreamTaskId, rsp.downstreamNodeId, rsp.upstreamTaskId, rsp.upstreamNodeId, rsp.status); SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, rsp.upstreamTaskId); @@ -1049,44 +759,57 @@ int32_t tqProcessStreamTaskCheckRsp(STQ* pTq, int64_t version, char* msg, int32_ return -1; } - code = streamProcessTaskCheckRsp(pTask, &rsp, version); + code = streamProcessTaskCheckRsp(pTask, &rsp, sversion); streamMetaReleaseTask(pTq->pStreamMeta, pTask); return code; } -int32_t tqProcessTaskDeployReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen) { +int32_t tqProcessTaskDeployReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) { int32_t code; #if 0 code = streamMetaAddSerializedTask(pTq->pStreamMeta, version, msg, msgLen); if (code < 0) return code; #endif + if (tsDisableStream) { + return 0; + } // 1.deserialize msg and build task SStreamTask* pTask = taosMemoryCalloc(1, sizeof(SStreamTask)); if (pTask == NULL) { return -1; } + SDecoder decoder; tDecoderInit(&decoder, (uint8_t*)msg, msgLen); - code = tDecodeSStreamTask(&decoder, pTask); + code = tDecodeStreamTask(&decoder, pTask); if (code < 0) { tDecoderClear(&decoder); taosMemoryFree(pTask); return -1; } + tDecoderClear(&decoder); - // 2.save task - code = streamMetaAddTask(pTq->pStreamMeta, version, pTask); + // 2.save task, use the newest commit version as the initial start version of stream task. + taosWLockLatch(&pTq->pStreamMeta->lock); + code = streamMetaAddDeployedTask(pTq->pStreamMeta, sversion, pTask); if (code < 0) { + tqError("vgId:%d failed to add s-task:%s, total:%d", TD_VID(pTq->pVnode), pTask->id.idStr, + streamMetaGetNumOfTasks(pTq->pStreamMeta)); + taosWUnLockLatch(&pTq->pStreamMeta->lock); return -1; } + taosWUnLockLatch(&pTq->pStreamMeta->lock); + // 3.go through recover steps to fill history if (pTask->fillHistory) { - streamTaskCheckDownstream(pTask, version); + streamTaskCheckDownstream(pTask, sversion); } + tqDebug("vgId:%d s-task:%s is deployed and add meta from mnd, status:%d, total:%d", TD_VID(pTq->pVnode), + pTask->id.idStr, pTask->status.taskStatus, streamMetaGetNumOfTasks(pTq->pStreamMeta)); return 0; } @@ -1100,24 +823,27 @@ int32_t tqProcessTaskRecover1Req(STQ* pTq, SRpcMsg* pMsg) { if (pTask == NULL) { return -1; } - ASSERT(pReq->taskId == pTask->taskId); // check param - int64_t fillVer1 = pTask->startVer; + int64_t fillVer1 = pTask->chkInfo.version; if (fillVer1 <= 0) { - ASSERT(0); streamMetaReleaseTask(pTq->pStreamMeta, pTask); return -1; } // do recovery step 1 - streamSourceRecoverScanStep1(pTask); + tqDebug("s-task:%s start recover step 1 scan", pTask->id.idStr); + int64_t st = taosGetTimestampMs(); - if (atomic_load_8(&pTask->taskStatus) == TASK_STATUS__DROPPING) { + streamSourceRecoverScanStep1(pTask); + if (atomic_load_8(&pTask->status.taskStatus) == TASK_STATUS__DROPPING) { streamMetaReleaseTask(pTq->pStreamMeta, pTask); return 0; } + double el = (taosGetTimestampMs() - st) / 1000.0; + tqDebug("s-task:%s recover step 1 ended, elapsed time:%.2fs", pTask->id.idStr, el); + // build msg to launch next step SStreamRecoverStep2Req req; code = streamBuildSourceRecover2Req(pTask, &req); @@ -1128,7 +854,7 @@ int32_t tqProcessTaskRecover1Req(STQ* pTq, SRpcMsg* pMsg) { streamMetaReleaseTask(pTq->pStreamMeta, pTask); - if (atomic_load_8(&pTask->taskStatus) == TASK_STATUS__DROPPING) { + if (atomic_load_8(&pTask->status.taskStatus) == TASK_STATUS__DROPPING) { return 0; } @@ -1143,20 +869,17 @@ int32_t tqProcessTaskRecover1Req(STQ* pTq, SRpcMsg* pMsg) { memcpy(serializedReq, &req, len); // dispatch msg - SRpcMsg rpcMsg = { - .code = 0, - .contLen = len, - .msgType = TDMT_VND_STREAM_RECOVER_BLOCKING_STAGE, - .pCont = serializedReq, - }; + tqDebug("s-task:%s start to recover blocking stage", pTask->id.idStr); + SRpcMsg rpcMsg = { + .code = 0, .contLen = len, .msgType = TDMT_VND_STREAM_RECOVER_BLOCKING_STAGE, .pCont = serializedReq}; tmsgPutToQueue(&pTq->pVnode->msgCb, WRITE_QUEUE, &rpcMsg); - return 0; } -int32_t tqProcessTaskRecover2Req(STQ* pTq, int64_t version, char* msg, int32_t msgLen) { - int32_t code; +int32_t tqProcessTaskRecover2Req(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) { + int32_t code = 0; + SStreamRecoverStep2Req* pReq = (SStreamRecoverStep2Req*)msg; SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, pReq->taskId); if (pTask == NULL) { @@ -1164,13 +887,16 @@ int32_t tqProcessTaskRecover2Req(STQ* pTq, int64_t version, char* msg, int32_t m } // do recovery step 2 - code = streamSourceRecoverScanStep2(pTask, version); + code = streamSourceRecoverScanStep2(pTask, sversion); if (code < 0) { streamMetaReleaseTask(pTq->pStreamMeta, pTask); return -1; } - if (atomic_load_8(&pTask->taskStatus) == TASK_STATUS__DROPPING) { + qDebug("s-task:%s set the start wal offset to be:%"PRId64, pTask->id.idStr, sversion); + walReaderSeekVer(pTask->exec.pWalReader, sversion); + + if (atomic_load_8(&pTask->status.taskStatus) == TASK_STATUS__DROPPING) { streamMetaReleaseTask(pTq->pStreamMeta, pTask); return 0; } @@ -1196,6 +922,9 @@ int32_t tqProcessTaskRecover2Req(STQ* pTq, int64_t version, char* msg, int32_t m return -1; } + atomic_store_8(&pTask->fillHistory, 0); + streamMetaSaveTask(pTq->pStreamMeta, pTask); + streamMetaReleaseTask(pTq->pStreamMeta, pTask); return 0; @@ -1209,7 +938,7 @@ int32_t tqProcessTaskRecoverFinishReq(STQ* pTq, SRpcMsg* pMsg) { SStreamRecoverFinishReq req; SDecoder decoder; - tDecoderInit(&decoder, msg, msgLen); + tDecoderInit(&decoder, (uint8_t*)msg, msgLen); tDecodeSStreamRecoverFinishReq(&decoder, &req); tDecoderClear(&decoder); @@ -1233,7 +962,60 @@ int32_t tqProcessTaskRecoverFinishRsp(STQ* pTq, SRpcMsg* pMsg) { return 0; } -int32_t tqProcessDelReq(STQ* pTq, void* pReq, int32_t len, int64_t ver) { +int32_t extractDelDataBlock(const void* pData, int32_t len, int64_t ver, SStreamRefDataBlock** pRefBlock) { + SDecoder* pCoder = &(SDecoder){0}; + SDeleteRes* pRes = &(SDeleteRes){0}; + + *pRefBlock = NULL; + + pRes->uidList = taosArrayInit(0, sizeof(tb_uid_t)); + if (pRes->uidList == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + tDecoderInit(pCoder, (uint8_t*)pData, len); + tDecodeDeleteRes(pCoder, pRes); + tDecoderClear(pCoder); + + int32_t numOfTables = taosArrayGetSize(pRes->uidList); + if (numOfTables == 0 || pRes->affectedRows == 0) { + taosArrayDestroy(pRes->uidList); + return TSDB_CODE_SUCCESS; + } + + SSDataBlock* pDelBlock = createSpecialDataBlock(STREAM_DELETE_DATA); + blockDataEnsureCapacity(pDelBlock, numOfTables); + pDelBlock->info.rows = numOfTables; + pDelBlock->info.version = ver; + + for (int32_t i = 0; i < numOfTables; i++) { + // start key column + SColumnInfoData* pStartCol = taosArrayGet(pDelBlock->pDataBlock, START_TS_COLUMN_INDEX); + colDataSetVal(pStartCol, i, (const char*)&pRes->skey, false); // end key column + SColumnInfoData* pEndCol = taosArrayGet(pDelBlock->pDataBlock, END_TS_COLUMN_INDEX); + colDataSetVal(pEndCol, i, (const char*)&pRes->ekey, false); + // uid column + SColumnInfoData* pUidCol = taosArrayGet(pDelBlock->pDataBlock, UID_COLUMN_INDEX); + int64_t* pUid = taosArrayGet(pRes->uidList, i); + colDataSetVal(pUidCol, i, (const char*)pUid, false); + + colDataSetNULL(taosArrayGet(pDelBlock->pDataBlock, GROUPID_COLUMN_INDEX), i); + colDataSetNULL(taosArrayGet(pDelBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX), i); + colDataSetNULL(taosArrayGet(pDelBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX), i); + } + + taosArrayDestroy(pRes->uidList); + *pRefBlock = taosAllocateQitem(sizeof(SStreamRefDataBlock), DEF_QITEM, 0); + if (pRefBlock == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + (*pRefBlock)->type = STREAM_INPUT__REF_DATA_BLOCK; + (*pRefBlock)->pBlock = pDelBlock; + return TSDB_CODE_SUCCESS; +} + +int32_t tqProcessDeleteDataReq(STQ* pTq, void* pReq, int32_t len, int64_t ver) { bool failed = false; SDecoder* pCoder = &(SDecoder){0}; SDeleteRes* pRes = &(SDeleteRes){0}; @@ -1253,6 +1035,7 @@ int32_t tqProcessDelReq(STQ* pTq, void* pReq, int32_t len, int64_t ver) { taosArrayDestroy(pRes->uidList); return 0; } + SSDataBlock* pDelBlock = createSpecialDataBlock(STREAM_DELETE_DATA); blockDataEnsureCapacity(pDelBlock, sz); pDelBlock->info.rows = sz; @@ -1261,17 +1044,17 @@ int32_t tqProcessDelReq(STQ* pTq, void* pReq, int32_t len, int64_t ver) { for (int32_t i = 0; i < sz; i++) { // start key column SColumnInfoData* pStartCol = taosArrayGet(pDelBlock->pDataBlock, START_TS_COLUMN_INDEX); - colDataAppend(pStartCol, i, (const char*)&pRes->skey, false); // end key column + colDataSetVal(pStartCol, i, (const char*)&pRes->skey, false); // end key column SColumnInfoData* pEndCol = taosArrayGet(pDelBlock->pDataBlock, END_TS_COLUMN_INDEX); - colDataAppend(pEndCol, i, (const char*)&pRes->ekey, false); + colDataSetVal(pEndCol, i, (const char*)&pRes->ekey, false); // uid column SColumnInfoData* pUidCol = taosArrayGet(pDelBlock->pDataBlock, UID_COLUMN_INDEX); int64_t* pUid = taosArrayGet(pRes->uidList, i); - colDataAppend(pUidCol, i, (const char*)pUid, false); + colDataSetVal(pUidCol, i, (const char*)pUid, false); - colDataAppendNULL(taosArrayGet(pDelBlock->pDataBlock, GROUPID_COLUMN_INDEX), i); - colDataAppendNULL(taosArrayGet(pDelBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX), i); - colDataAppendNULL(taosArrayGet(pDelBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX), i); + colDataSetNULL(taosArrayGet(pDelBlock->pDataBlock, GROUPID_COLUMN_INDEX), i); + colDataSetNULL(taosArrayGet(pDelBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX), i); + colDataSetNULL(taosArrayGet(pDelBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX), i); } taosArrayDestroy(pRes->uidList); @@ -1279,32 +1062,35 @@ int32_t tqProcessDelReq(STQ* pTq, void* pReq, int32_t len, int64_t ver) { int32_t* pRef = taosMemoryMalloc(sizeof(int32_t)); *pRef = 1; + taosWLockLatch(&pTq->pStreamMeta->lock); + void* pIter = NULL; while (1) { pIter = taosHashIterate(pTq->pStreamMeta->pTasks, pIter); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } + SStreamTask* pTask = *(SStreamTask**)pIter; - if (pTask->taskLevel != TASK_LEVEL__SOURCE) continue; + if (pTask->taskLevel != TASK_LEVEL__SOURCE) { + continue; + } - qDebug("delete req enqueue stream task: %d, ver: %" PRId64, pTask->taskId, ver); + qDebug("s-task:%s delete req enqueue, ver: %" PRId64, pTask->id.idStr, ver); if (!failed) { SStreamRefDataBlock* pRefBlock = taosAllocateQitem(sizeof(SStreamRefDataBlock), DEF_QITEM, 0); pRefBlock->type = STREAM_INPUT__REF_DATA_BLOCK; pRefBlock->pBlock = pDelBlock; - pRefBlock->dataRef = pRef; - atomic_add_fetch_32(pRefBlock->dataRef, 1); - - if (streamTaskInput(pTask, (SStreamQueueItem*)pRefBlock) < 0) { - qError("stream task input del failed, task id %d", pTask->taskId); + if (tAppendDataToInputQueue(pTask, (SStreamQueueItem*)pRefBlock) < 0) { atomic_sub_fetch_32(pRef, 1); taosFreeQitem(pRefBlock); continue; } if (streamSchedExec(pTask) < 0) { - qError("stream task launch failed, task id %d", pTask->taskId); + qError("s-task:%s stream task launch failed", pTask->id.idStr); continue; } @@ -1313,8 +1099,9 @@ int32_t tqProcessDelReq(STQ* pTq, void* pReq, int32_t len, int64_t ver) { } } + taosWUnLockLatch(&pTq->pStreamMeta->lock); + int32_t ref = atomic_sub_fetch_32(pRef, 1); - ASSERT(ref >= 0); if (ref == 0) { blockDataDestroy(pDelBlock); taosMemoryFree(pRef); @@ -1330,13 +1117,13 @@ int32_t tqProcessDelReq(STQ* pTq, void* pReq, int32_t len, int64_t ver) { taosArrayPush(pStreamBlock->blocks, &block); if (!failed) { - if (streamTaskInput(pTask, (SStreamQueueItem*)pStreamBlock) < 0) { - qError("stream task input del failed, task id %d", pTask->taskId); + if (tAppendDataToInputQueue(pTask, (SStreamQueueItem*)pStreamBlock) < 0) { + qError("stream task input del failed, task id %d", pTask->id.taskId); continue; } if (streamSchedExec(pTask) < 0) { - qError("stream task launch failed, task id %d", pTask->taskId); + qError("stream task launch failed, task id %d", pTask->id.taskId); continue; } } else { @@ -1345,66 +1132,68 @@ int32_t tqProcessDelReq(STQ* pTq, void* pReq, int32_t len, int64_t ver) { } blockDataDestroy(pDelBlock); #endif - return 0; } -int32_t tqProcessSubmitReq(STQ* pTq, SSubmitReq* pReq, int64_t ver) { - void* pIter = NULL; - bool failed = false; - SStreamDataSubmit* pSubmit = NULL; +int32_t tqProcessSubmitReqForSubscribe(STQ* pTq) { + int32_t vgId = TD_VID(pTq->pVnode); - pSubmit = streamDataSubmitNew(pReq); - if (pSubmit == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - tqError("failed to create data submit for stream since out of memory"); - failed = true; - } + taosWLockLatch(&pTq->lock); - while (1) { - pIter = taosHashIterate(pTq->pStreamMeta->pTasks, pIter); - if (pIter == NULL) break; - SStreamTask* pTask = *(SStreamTask**)pIter; - if (pTask->taskLevel != TASK_LEVEL__SOURCE) continue; - if (pTask->taskStatus == TASK_STATUS__RECOVER_PREPARE || pTask->taskStatus == TASK_STATUS__WAIT_DOWNSTREAM) { - tqDebug("skip push task %d, task status %d", pTask->taskId, pTask->taskStatus); - continue; - } + if (taosHashGetSize(pTq->pPushMgr) > 0) { + void* pIter = taosHashIterate(pTq->pPushMgr, NULL); - tqDebug("data submit enqueue stream task: %d, ver: %" PRId64, pTask->taskId, ver); + while (pIter) { + STqHandle* pHandle = *(STqHandle**)pIter; + tqDebug("vgId:%d start set submit for pHandle:%p, consumer:0x%" PRIx64, vgId, pHandle, pHandle->consumerId); - if (!failed) { - if (streamTaskInput(pTask, (SStreamQueueItem*)pSubmit) < 0) { - tqError("stream task input failed, task id %d", pTask->taskId); - continue; + if (ASSERT(pHandle->msg != NULL)) { + tqError("pHandle->msg should not be null"); + break; + }else{ + SRpcMsg msg = {.msgType = TDMT_VND_TMQ_CONSUME, .pCont = pHandle->msg->pCont, .contLen = pHandle->msg->contLen, .info = pHandle->msg->info}; + tmsgPutToQueue(&pTq->pVnode->msgCb, QUERY_QUEUE, &msg); + taosMemoryFree(pHandle->msg); + pHandle->msg = NULL; } - if (streamSchedExec(pTask) < 0) { - tqError("stream task launch failed, task id %d", pTask->taskId); - continue; - } - } else { - streamTaskInputFail(pTask); + pIter = taosHashIterate(pTq->pPushMgr, pIter); } - } - if (pSubmit) { - streamDataSubmitRefDec(pSubmit); - taosFreeQitem(pSubmit); + taosHashClear(pTq->pPushMgr); } - return failed ? -1 : 0; + // unlock + taosWUnLockLatch(&pTq->lock); + return 0; } int32_t tqProcessTaskRunReq(STQ* pTq, SRpcMsg* pMsg) { SStreamTaskRunReq* pReq = pMsg->pCont; - int32_t taskId = pReq->taskId; - SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, taskId); - if (pTask) { - streamProcessRunReq(pTask); + + int32_t taskId = pReq->taskId; + int32_t vgId = TD_VID(pTq->pVnode); + + if (taskId == WAL_READ_TASKS_ID) { // all tasks are extracted submit data from the wal + tqStreamTasksScanWal(pTq); + return 0; + } + + SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, taskId); + if (pTask != NULL) { + if (pTask->status.taskStatus == TASK_STATUS__NORMAL) { + tqDebug("vgId:%d s-task:%s start to process block from wal, last chk point:%" PRId64, vgId, + pTask->id.idStr, pTask->chkInfo.version); + streamProcessRunReq(pTask); + } else { + tqDebug("vgId:%d s-task:%s ignore run req since not in ready state", vgId, pTask->id.idStr); + } + streamMetaReleaseTask(pTq->pStreamMeta, pTask); + tqStartStreamTasks(pTq); return 0; } else { + tqError("vgId:%d failed to found s-task, taskId:%d", vgId, taskId); return -1; } } @@ -1417,18 +1206,15 @@ int32_t tqProcessTaskDispatchReq(STQ* pTq, SRpcMsg* pMsg, bool exec) { SDecoder decoder; tDecoderInit(&decoder, (uint8_t*)msgBody, msgLen); tDecodeStreamDispatchReq(&decoder, &req); - int32_t taskId = req.taskId; - SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, taskId); + SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, req.taskId); if (pTask) { - SRpcMsg rsp = { - .info = pMsg->info, - .code = 0, - }; + SRpcMsg rsp = { .info = pMsg->info, .code = 0 }; streamProcessDispatchReq(pTask, &req, &rsp, exec); streamMetaReleaseTask(pTq->pStreamMeta, pTask); return 0; } else { + tDeleteStreamDispatchReq(&req); return -1; } } @@ -1437,7 +1223,7 @@ int32_t tqProcessTaskDispatchRsp(STQ* pTq, SRpcMsg* pMsg) { SStreamDispatchRsp* pRsp = POINTER_SHIFT(pMsg->pCont, sizeof(SMsgHead)); int32_t taskId = ntohl(pRsp->upstreamTaskId); SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, taskId); - tqDebug("recv dispatch rsp, code: %x", pMsg->code); + tqDebug("recv dispatch rsp, code:%x", pMsg->code); if (pTask) { streamProcessDispatchRsp(pTask, pRsp, pMsg->code); streamMetaReleaseTask(pTq->pStreamMeta, pTask); @@ -1447,7 +1233,7 @@ int32_t tqProcessTaskDispatchRsp(STQ* pTq, SRpcMsg* pMsg) { } } -int32_t tqProcessTaskDropReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen) { +int32_t tqProcessTaskDropReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) { SVDropStreamTaskReq* pReq = (SVDropStreamTaskReq*)msg; streamMetaRemoveTask(pTq->pStreamMeta, pReq->taskId); return 0; @@ -1459,21 +1245,19 @@ int32_t tqProcessTaskRetrieveReq(STQ* pTq, SRpcMsg* pMsg) { int32_t msgLen = pMsg->contLen - sizeof(SMsgHead); SStreamRetrieveReq req; SDecoder decoder; - tDecoderInit(&decoder, msgBody, msgLen); + tDecoderInit(&decoder, (uint8_t*)msgBody, msgLen); tDecodeStreamRetrieveReq(&decoder, &req); tDecoderClear(&decoder); int32_t taskId = req.dstTaskId; SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, taskId); if (pTask) { - SRpcMsg rsp = { - .info = pMsg->info, - .code = 0, - }; + SRpcMsg rsp = { .info = pMsg->info, .code = 0 }; streamProcessRetrieveReq(pTask, &req, &rsp); streamMetaReleaseTask(pTq->pStreamMeta, pTask); tDeleteStreamRetrieveReq(&req); return 0; } else { + tDeleteStreamRetrieveReq(&req); return -1; } } @@ -1492,7 +1276,7 @@ int32_t vnodeEnqueueStreamMsg(SVnode* pVnode, SRpcMsg* pMsg) { SStreamDispatchReq req; SDecoder decoder; - tDecoderInit(&decoder, msgBody, msgLen); + tDecoderInit(&decoder, (uint8_t*)msgBody, msgLen); if (tDecodeStreamDispatchReq(&decoder, &req) < 0) { code = TSDB_CODE_MSG_DECODE_ERROR; tDecoderClear(&decoder); @@ -1504,15 +1288,14 @@ int32_t vnodeEnqueueStreamMsg(SVnode* pVnode, SRpcMsg* pMsg) { SStreamTask* pTask = streamMetaAcquireTask(pTq->pStreamMeta, taskId); if (pTask) { - SRpcMsg rsp = { - .info = pMsg->info, - .code = 0, - }; + SRpcMsg rsp = { .info = pMsg->info, .code = 0 }; streamProcessDispatchReq(pTask, &req, &rsp, false); streamMetaReleaseTask(pTq->pStreamMeta, pTask); rpcFreeCont(pMsg->pCont); taosFreeQitem(pMsg); return 0; + } else { + tDeleteStreamDispatchReq(&req); } code = TSDB_CODE_STREAM_TASK_NOT_EXIST; @@ -1522,10 +1305,7 @@ FAIL: SMsgHead* pRspHead = rpcMallocCont(sizeof(SMsgHead) + sizeof(SStreamDispatchRsp)); if (pRspHead == NULL) { - SRpcMsg rsp = { - .code = TSDB_CODE_OUT_OF_MEMORY, - .info = pMsg->info, - }; + SRpcMsg rsp = { .code = TSDB_CODE_OUT_OF_MEMORY, .info = pMsg->info }; tqDebug("send dispatch error rsp, code: %x", code); tmsgSendRsp(&rsp); rpcFreeCont(pMsg->pCont); @@ -1543,11 +1323,7 @@ FAIL: pRsp->inputStatus = TASK_OUTPUT_STATUS__NORMAL; SRpcMsg rsp = { - .code = code, - .info = pMsg->info, - .contLen = sizeof(SMsgHead) + sizeof(SStreamDispatchRsp), - .pCont = pRspHead, - }; + .code = code, .info = pMsg->info, .contLen = sizeof(SMsgHead) + sizeof(SStreamDispatchRsp), .pCont = pRspHead}; tqDebug("send dispatch error rsp, code: %x", code); tmsgSendRsp(&rsp); rpcFreeCont(pMsg->pCont); @@ -1555,4 +1331,45 @@ FAIL: return -1; } -int32_t tqCheckLogInWal(STQ* pTq, int64_t version) { return version <= pTq->walLogLastVer; } +int32_t tqCheckLogInWal(STQ* pTq, int64_t sversion) { return sversion <= pTq->walLogLastVer; } + +int32_t tqStartStreamTasks(STQ* pTq) { + int32_t vgId = TD_VID(pTq->pVnode); + SStreamMeta* pMeta = pTq->pStreamMeta; + + taosWLockLatch(&pMeta->lock); + + int32_t numOfTasks = taosArrayGetSize(pMeta->pTaskList); + if (numOfTasks == 0) { + tqInfo("vgId:%d no stream tasks exists", vgId); + taosWUnLockLatch(&pTq->pStreamMeta->lock); + return 0; + } + + pMeta->walScanCounter += 1; + + if (pMeta->walScanCounter > 1) { + tqDebug("vgId:%d wal read task has been launched, remain scan times:%d", vgId, pMeta->walScanCounter); + taosWUnLockLatch(&pTq->pStreamMeta->lock); + return 0; + } + + SStreamTaskRunReq* pRunReq = rpcMallocCont(sizeof(SStreamTaskRunReq)); + if (pRunReq == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + tqError("vgId:%d failed restore stream tasks, code:%s", vgId, terrstr(terrno)); + taosWUnLockLatch(&pTq->pStreamMeta->lock); + return -1; + } + + tqDebug("vgId:%d start wal scan stream tasks, tasks:%d", vgId, numOfTasks); + pRunReq->head.vgId = vgId; + pRunReq->streamId = 0; + pRunReq->taskId = WAL_READ_TASKS_ID; + + SRpcMsg msg = {.msgType = TDMT_STREAM_TASK_RUN, .pCont = pRunReq, .contLen = sizeof(SStreamTaskRunReq)}; + tmsgPutToQueue(&pTq->pVnode->msgCb, STREAM_QUEUE, &msg); + taosWUnLockLatch(&pTq->pStreamMeta->lock); + + return 0; +} diff --git a/source/dnode/vnode/src/tq/tqCommit.c b/source/dnode/vnode/src/tq/tqCommit.c index 7fc66c49192eb011ce674bc7a2d396825ba1b435..0f5daa31ad412c8ed0773cca8e09cdeeb0fa80f5 100644 --- a/source/dnode/vnode/src/tq/tqCommit.c +++ b/source/dnode/vnode/src/tq/tqCommit.c @@ -16,10 +16,13 @@ #include "tq.h" int tqCommit(STQ* pTq) { +#if 0 + // stream meta commit does not be aligned to the vnode commit if (streamMetaCommit(pTq->pStreamMeta) < 0) { tqError("vgId:%d, failed to commit stream meta since %s", TD_VID(pTq->pVnode), terrstr()); return -1; } +#endif return tqOffsetCommitFile(pTq->pOffsetStore); } diff --git a/source/dnode/vnode/src/tq/tqMeta.c b/source/dnode/vnode/src/tq/tqMeta.c index 34f57bc697a2e6ad0fb80f8a437b12bb9070dea0..5654147b6df6d1518285e0c028e23db20997ff57 100644 --- a/source/dnode/vnode/src/tq/tqMeta.c +++ b/source/dnode/vnode/src/tq/tqMeta.c @@ -54,7 +54,7 @@ int32_t tDecodeSTqHandle(SDecoder* pDecoder, STqHandle* pHandle) { if (tDecodeCStrAlloc(pDecoder, &pHandle->execHandle.execCol.qmsg) < 0) return -1; } else if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__DB) { pHandle->execHandle.execDb.pFilterOutTbUid = - taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); + taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_ENTRY_LOCK); int32_t size = 0; if (tDecodeI32(pDecoder, &size) < 0) return -1; for (int32_t i = 0; i < size; i++) { @@ -132,19 +132,19 @@ int32_t tqMetaDeleteCheckInfo(STQ* pTq, const char* key) { if (tdbBegin(pTq->pMetaDB, &txn, tdbDefaultMalloc, tdbDefaultFree, NULL, TDB_TXN_WRITE | TDB_TXN_READ_UNCOMMITTED) < 0) { - ASSERT(0); + return -1; } if (tdbTbDelete(pTq->pCheckStore, key, (int)strlen(key), txn) < 0) { - /*ASSERT(0);*/ + tqWarn("vgId:%d, tq try delete checkinfo failed %s", pTq->pVnode->config.vgId, key); } if (tdbCommit(pTq->pMetaDB, txn) < 0) { - ASSERT(0); + return -1; } if (tdbPostCommit(pTq->pMetaDB, txn) < 0) { - ASSERT(0); + return -1; } return 0; @@ -153,7 +153,6 @@ int32_t tqMetaDeleteCheckInfo(STQ* pTq, const char* key) { int32_t tqMetaRestoreCheckInfo(STQ* pTq) { TBC* pCur = NULL; if (tdbTbcOpen(pTq->pCheckStore, &pCur, NULL) < 0) { - ASSERT(0); return -1; } @@ -194,9 +193,12 @@ int32_t tqMetaSaveHandle(STQ* pTq, const char* key, const STqHandle* pHandle) { int32_t code; int32_t vlen; tEncodeSize(tEncodeSTqHandle, pHandle, vlen, code); + if (code < 0) { + return -1; + } - tqDebug("tq save %s(%d) consumer %" PRId64 " vgId:%d", pHandle->subKey, (int32_t)strlen(pHandle->subKey), - pHandle->consumerId, TD_VID(pTq->pVnode)); + tqDebug("tq save %s(%d) handle consumer:0x%" PRIx64 " epoch:%d vgId:%d", pHandle->subKey, + (int32_t)strlen(pHandle->subKey), pHandle->consumerId, pHandle->epoch, TD_VID(pTq->pVnode)); void* buf = taosMemoryCalloc(1, vlen); if (buf == NULL) { @@ -249,31 +251,31 @@ int32_t tqMetaDeleteHandle(STQ* pTq, const char* key) { if (tdbBegin(pTq->pMetaDB, &txn, tdbDefaultMalloc, tdbDefaultFree, NULL, TDB_TXN_WRITE | TDB_TXN_READ_UNCOMMITTED) < 0) { - ASSERT(0); + return -1; } if (tdbTbDelete(pTq->pExecStore, key, (int)strlen(key), txn) < 0) { - /*ASSERT(0);*/ } if (tdbCommit(pTq->pMetaDB, txn) < 0) { - ASSERT(0); + return -1; } if (tdbPostCommit(pTq->pMetaDB, txn) < 0) { - ASSERT(0); + return -1; } return 0; } int32_t tqMetaRestoreHandle(STQ* pTq) { + int code = 0; TBC* pCur = NULL; if (tdbTbcOpen(pTq->pExecStore, &pCur, NULL) < 0) { - ASSERT(0); return -1; } + int32_t vgId = TD_VID(pTq->pVnode); void* pKey = NULL; int kLen = 0; void* pVal = NULL; @@ -283,16 +285,17 @@ int32_t tqMetaRestoreHandle(STQ* pTq) { tdbTbcMoveToFirst(pCur); while (tdbTbcNext(pCur, &pKey, &kLen, &pVal, &vLen) == 0) { - STqHandle handle; + STqHandle handle = {0}; tDecoderInit(&decoder, (uint8_t*)pVal, vLen); tDecodeSTqHandle(&decoder, &handle); tDecoderClear(&decoder); handle.pRef = walOpenRef(pTq->pVnode->pWal); if (handle.pRef == NULL) { - continue; + code = -1; + goto end; } - walRefVer(handle.pRef, handle.snapshotVer); + walSetRefVer(handle.pRef, handle.snapshotVer); SReadHandle reader = { .meta = pTq->pVnode->pMeta, @@ -304,20 +307,32 @@ int32_t tqMetaRestoreHandle(STQ* pTq) { if (handle.execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { handle.execHandle.task = - qCreateQueueExecTaskInfo(handle.execHandle.execCol.qmsg, &reader, &handle.execHandle.numOfCols, NULL); - ASSERT(handle.execHandle.task); + qCreateQueueExecTaskInfo(handle.execHandle.execCol.qmsg, &reader, vgId, &handle.execHandle.numOfCols, 0); + if (handle.execHandle.task == NULL) { + tqError("cannot create exec task for %s", handle.subKey); + code = -1; + goto end; + } void* scanner = NULL; qExtractStreamScanner(handle.execHandle.task, &scanner); - ASSERT(scanner); - handle.execHandle.pExecReader = qExtractReaderFromStreamScanner(scanner); - ASSERT(handle.execHandle.pExecReader); + if (scanner == NULL) { + tqError("cannot extract stream scanner for %s", handle.subKey); + code = -1; + goto end; + } + handle.execHandle.pTqReader = qExtractReaderFromStreamScanner(scanner); + if (handle.execHandle.pTqReader == NULL) { + tqError("cannot extract exec reader for %s", handle.subKey); + code = -1; + goto end; + } } else if (handle.execHandle.subType == TOPIC_SUB_TYPE__DB) { handle.pWalReader = walOpenReader(pTq->pVnode->pWal, NULL); - handle.execHandle.pExecReader = tqOpenReader(pTq->pVnode); + handle.execHandle.pTqReader = tqReaderOpen(pTq->pVnode); buildSnapContext(reader.meta, reader.version, 0, handle.execHandle.subType, handle.fetchMeta, (SSnapContext**)(&reader.sContext)); - handle.execHandle.task = qCreateQueueExecTaskInfo(NULL, &reader, NULL, NULL); + handle.execHandle.task = qCreateQueueExecTaskInfo(NULL, &reader, vgId, NULL, 0); } else if (handle.execHandle.subType == TOPIC_SUB_TYPE__TABLE) { handle.pWalReader = walOpenReader(pTq->pVnode->pWal, NULL); @@ -326,22 +341,25 @@ int32_t tqMetaRestoreHandle(STQ* pTq) { tqDebug("vgId:%d, tq try to get all ctb, suid:%" PRId64, pTq->pVnode->config.vgId, handle.execHandle.execTb.suid); for (int32_t i = 0; i < taosArrayGetSize(tbUidList); i++) { int64_t tbUid = *(int64_t*)taosArrayGet(tbUidList, i); - tqDebug("vgId:%d, idx %d, uid:%" PRId64, TD_VID(pTq->pVnode), i, tbUid); + tqDebug("vgId:%d, idx %d, uid:%" PRId64, vgId, i, tbUid); } - handle.execHandle.pExecReader = tqOpenReader(pTq->pVnode); - tqReaderSetTbUidList(handle.execHandle.pExecReader, tbUidList); + handle.execHandle.pTqReader = tqReaderOpen(pTq->pVnode); + tqReaderSetTbUidList(handle.execHandle.pTqReader, tbUidList); taosArrayDestroy(tbUidList); buildSnapContext(reader.meta, reader.version, handle.execHandle.execTb.suid, handle.execHandle.subType, handle.fetchMeta, (SSnapContext**)(&reader.sContext)); - handle.execHandle.task = qCreateQueueExecTaskInfo(NULL, &reader, NULL, NULL); + handle.execHandle.task = qCreateQueueExecTaskInfo(NULL, &reader, vgId, NULL, 0); } - tqDebug("tq restore %s consumer %" PRId64 " vgId:%d", handle.subKey, handle.consumerId, TD_VID(pTq->pVnode)); + tqDebug("tq restore %s consumer %" PRId64 " vgId:%d", handle.subKey, handle.consumerId, vgId); + taosWLockLatch(&pTq->lock); taosHashPut(pTq->pHandle, pKey, kLen, &handle, sizeof(STqHandle)); + taosWUnLockLatch(&pTq->lock); } +end: tdbFree(pKey); tdbFree(pVal); tdbTbcClose(pCur); - return 0; + return code; } diff --git a/source/dnode/vnode/src/tq/tqOffset.c b/source/dnode/vnode/src/tq/tqOffset.c index 338f9d6c2424d65e4dd289c728b72c01f0c971d7..377a5d18875c77b38d4ca6036a96cabfafa0ea3f 100644 --- a/source/dnode/vnode/src/tq/tqOffset.c +++ b/source/dnode/vnode/src/tq/tqOffset.c @@ -31,58 +31,69 @@ char* tqOffsetBuildFName(const char* path, int32_t fVer) { int32_t tqOffsetRestoreFromFile(STqOffsetStore* pStore, const char* fname) { TdFilePtr pFile = taosOpenFile(fname, TD_FILE_READ); - if (pFile != NULL) { - STqOffsetHead head = {0}; - int64_t code; - - while (1) { - if ((code = taosReadFile(pFile, &head, sizeof(STqOffsetHead))) != sizeof(STqOffsetHead)) { - if (code == 0) { - break; - } else { - ASSERT(0); - // TODO handle error - } - } - int32_t size = htonl(head.size); - void* memBuf = taosMemoryCalloc(1, size); - if (memBuf == NULL) { - return -1; - } - if ((code = taosReadFile(pFile, memBuf, size)) != size) { - taosMemoryFree(memBuf); - return -1; - } - STqOffset offset; - SDecoder decoder; - tDecoderInit(&decoder, memBuf, size); - if (tDecodeSTqOffset(&decoder, &offset) < 0) { - taosMemoryFree(memBuf); - tDecoderClear(&decoder); + if (pFile == NULL) { + return TSDB_CODE_SUCCESS; + } + + int32_t vgId = TD_VID(pStore->pTq->pVnode); + int64_t code = 0; + + STqOffsetHead head = {0}; + + while (1) { + if ((code = taosReadFile(pFile, &head, sizeof(STqOffsetHead))) != sizeof(STqOffsetHead)) { + if (code == 0) { + break; + } else { return -1; } + } + + int32_t size = htonl(head.size); + void* pMemBuf = taosMemoryCalloc(1, size); + if (pMemBuf == NULL) { + tqError("vgId:%d failed to restore offset from file, since out of memory, malloc size:%d", vgId, size); + terrno = TSDB_CODE_OUT_OF_MEMORY; + return -1; + } + if ((code = taosReadFile(pFile, pMemBuf, size)) != size) { + taosMemoryFree(pMemBuf); + return -1; + } + + STqOffset offset; + SDecoder decoder; + tDecoderInit(&decoder, pMemBuf, size); + if (tDecodeSTqOffset(&decoder, &offset) < 0) { + taosMemoryFree(pMemBuf); tDecoderClear(&decoder); - if (taosHashPut(pStore->pHash, offset.subKey, strlen(offset.subKey), &offset, sizeof(STqOffset)) < 0) { - return -1; - } + return code; + } - if (offset.val.type == TMQ_OFFSET__LOG) { - STqHandle* pHandle = taosHashGet(pStore->pTq->pHandle, offset.subKey, strlen(offset.subKey)); - if (pHandle) { - if (walRefVer(pHandle->pRef, offset.val.version) < 0) { - tqError("vgId: %d, tq handle %s ref ver %" PRId64 "error", pStore->pTq->pVnode->config.vgId, - pHandle->subKey, offset.val.version); - } + tDecoderClear(&decoder); + if (taosHashPut(pStore->pHash, offset.subKey, strlen(offset.subKey), &offset, sizeof(STqOffset)) < 0) { + return -1; + } + + // todo remove this + if (offset.val.type == TMQ_OFFSET__LOG) { + taosWLockLatch(&pStore->pTq->lock); + STqHandle* pHandle = taosHashGet(pStore->pTq->pHandle, offset.subKey, strlen(offset.subKey)); + if (pHandle) { + if (walSetRefVer(pHandle->pRef, offset.val.version) < 0) { +// tqError("vgId: %d, tq handle %s ref ver %" PRId64 "error", pStore->pTq->pVnode->config.vgId, pHandle->subKey, +// offset.val.version); } } - - taosMemoryFree(memBuf); + taosWUnLockLatch(&pStore->pTq->lock); } - taosCloseFile(&pFile); + taosMemoryFree(pMemBuf); } - return 0; + + taosCloseFile(&pFile); + return TSDB_CODE_SUCCESS; } STqOffsetStore* tqOffsetOpen(STQ* pTq) { @@ -90,6 +101,7 @@ STqOffsetStore* tqOffsetOpen(STQ* pTq) { if (pStore == NULL) { return NULL; } + pStore->pTq = pTq; pStore->needCommit = 0; pTq->pOffsetStore = pStore; @@ -99,11 +111,14 @@ STqOffsetStore* tqOffsetOpen(STQ* pTq) { taosMemoryFree(pStore); return NULL; } + char* fname = tqOffsetBuildFName(pStore->pTq->path, 0); if (tqOffsetRestoreFromFile(pStore, fname) < 0) { taosMemoryFree(fname); + taosMemoryFree(pStore); return NULL; } + taosMemoryFree(fname); return pStore; } @@ -128,34 +143,36 @@ int32_t tqOffsetDelete(STqOffsetStore* pStore, const char* subscribeKey) { } int32_t tqOffsetCommitFile(STqOffsetStore* pStore) { - if (!pStore->needCommit) return 0; + if (!pStore->needCommit) { + return 0; + } + // TODO file name should be with a newer version char* fname = tqOffsetBuildFName(pStore->pTq->path, 0); TdFilePtr pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND); if (pFile == NULL) { terrno = TAOS_SYSTEM_ERROR(errno); - - int32_t err = terrno; - const char* errStr = tstrerror(err); - int32_t sysErr = errno; - const char* sysErrStr = strerror(errno); - tqError("vgId:%d, cannot open file %s when commit offset since %s", pStore->pTq->pVnode->config.vgId, fname, - sysErrStr); + const char* err = strerror(errno); + tqError("vgId:%d, failed to open offset file %s, since %s", TD_VID(pStore->pTq->pVnode), fname, err); taosMemoryFree(fname); return -1; } + taosMemoryFree(fname); + void* pIter = NULL; while (1) { pIter = taosHashIterate(pStore->pHash, pIter); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } + STqOffset* pOffset = (STqOffset*)pIter; int32_t bodyLen; int32_t code; tEncodeSize(tEncodeSTqOffset, pOffset, bodyLen, code); - ASSERT(code == 0); + if (code < 0) { - ASSERT(0); taosHashCancelIterate(pStore->pHash, pIter); return -1; } @@ -168,17 +185,19 @@ int32_t tqOffsetCommitFile(STqOffsetStore* pStore) { SEncoder encoder; tEncoderInit(&encoder, abuf, bodyLen); tEncodeSTqOffset(&encoder, pOffset); + // write file int64_t writeLen; if ((writeLen = taosWriteFile(pFile, buf, totLen)) != totLen) { - ASSERT(0); tqError("write offset incomplete, len %d, write len %" PRId64, bodyLen, writeLen); taosHashCancelIterate(pStore->pHash, pIter); taosMemoryFree(buf); return -1; } + taosMemoryFree(buf); } + // close and rename file taosCloseFile(&pFile); pStore->needCommit = 0; diff --git a/source/dnode/vnode/src/tq/tqOffsetSnapshot.c b/source/dnode/vnode/src/tq/tqOffsetSnapshot.c index b63ff8af1d623aa2017ce5768a80e2dbf783d5a4..a4428aed4368fec9c96a2faae5fabd33cd8eb8f4 100644 --- a/source/dnode/vnode/src/tq/tqOffsetSnapshot.c +++ b/source/dnode/vnode/src/tq/tqOffsetSnapshot.c @@ -61,19 +61,23 @@ int32_t tqOffsetSnapRead(STqOffsetReader* pReader, uint8_t** ppData) { int64_t sz = 0; if (taosStatFile(fname, &sz, NULL) < 0) { - ASSERT(0); + taosCloseFile(&pFile); + taosMemoryFree(fname); + return -1; } taosMemoryFree(fname); SSnapDataHdr* buf = taosMemoryCalloc(1, sz + sizeof(SSnapDataHdr)); if (buf == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; + taosCloseFile(&pFile); return terrno; } void* abuf = POINTER_SHIFT(buf, sizeof(SSnapDataHdr)); int64_t contLen = taosReadFile(pFile, abuf, sz); if (contLen != sz) { - ASSERT(0); + taosCloseFile(&pFile); + taosMemoryFree(buf); return -1; } buf->size = sz; @@ -122,14 +126,17 @@ int32_t tqOffsetWriterClose(STqOffsetWriter** ppWriter, int8_t rollback) { if (rollback) { if (taosRemoveFile(pWriter->fname) < 0) { - ASSERT(0); + taosMemoryFree(fname); + return -1; } } else { if (taosRenameFile(pWriter->fname, fname) < 0) { - ASSERT(0); + taosMemoryFree(fname); + return -1; } if (tqOffsetRestoreFromFile(pTq->pOffsetStore, fname) < 0) { - ASSERT(0); + taosMemoryFree(fname); + return -1; } } taosMemoryFree(fname); @@ -146,14 +153,13 @@ int32_t tqOffsetSnapWrite(STqOffsetWriter* pWriter, uint8_t* pData, uint32_t nDa TdFilePtr pFile = taosOpenFile(pWriter->fname, TD_FILE_CREATE | TD_FILE_WRITE); SSnapDataHdr* pHdr = (SSnapDataHdr*)pData; int64_t size = pHdr->size; - ASSERT(size == nData - sizeof(SSnapDataHdr)); if (pFile) { int64_t contLen = taosWriteFile(pFile, pHdr->data, size); if (contLen != size) { - ASSERT(0); + taosCloseFile(&pFile); + return -1; } } else { - ASSERT(0); return -1; } return 0; diff --git a/source/dnode/vnode/src/tq/tqPush.c b/source/dnode/vnode/src/tq/tqPush.c index f89bc2036252961ff10d81774a9c6f756fdebf43..50d94c5ed55510cf2a4ac4108df089ad6468fca2 100644 --- a/source/dnode/vnode/src/tq/tqPush.c +++ b/source/dnode/vnode/src/tq/tqPush.c @@ -16,315 +16,72 @@ #include "tq.h" #include "vnd.h" -#if 0 -void tqTmrRspFunc(void* param, void* tmrId) { - STqHandle* pHandle = (STqHandle*)param; - atomic_store_8(&pHandle->pushHandle.tmrStopped, 1); -} +int32_t tqPushMsg(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_t ver) { -static int32_t tqLoopExecFromQueue(STQ* pTq, STqHandle* pHandle, SStreamDataSubmit** ppSubmit, SMqDataRsp* pRsp) { - SStreamDataSubmit* pSubmit = *ppSubmit; - while (pSubmit != NULL) { - ASSERT(pSubmit->ver == pHandle->pushHandle.processedVer + 1); - if (tqLogScanExec(pTq, &pHandle->execHandle, pSubmit->data, pRsp, 0) < 0) { - /*ASSERT(0);*/ - } - // update processed - atomic_store_64(&pHandle->pushHandle.processedVer, pSubmit->ver); - streamQueueProcessSuccess(&pHandle->pushHandle.inputQ); - streamDataSubmitRefDec(pSubmit); - if (pRsp->blockNum > 0) { - *ppSubmit = pSubmit; - return 0; - } else { - pSubmit = streamQueueNextItem(&pHandle->pushHandle.inputQ); - } + if (msgType == TDMT_VND_SUBMIT) { + tqProcessSubmitReqForSubscribe(pTq); } - *ppSubmit = pSubmit; - return -1; -} -int32_t tqExecFromInputQ(STQ* pTq, STqHandle* pHandle) { - SMqDataRsp rsp = {0}; - // 1. guard and set status executing - int8_t execStatus = atomic_val_compare_exchange_8(&pHandle->pushHandle.execStatus, TASK_EXEC_STATUS__IDLE, - TASK_EXEC_STATUS__EXECUTING); - if (execStatus == TASK_EXEC_STATUS__IDLE) { - SStreamDataSubmit* pSubmit = NULL; - // 2. check processedVer - // 2.1. if not missed, get msg from queue - // 2.2. if missed, scan wal - pSubmit = streamQueueNextItem(&pHandle->pushHandle.inputQ); - while (pHandle->pushHandle.processedVer <= pSubmit->ver) { - // read from wal - } - while (pHandle->pushHandle.processedVer > pSubmit->ver + 1) { - streamQueueProcessSuccess(&pHandle->pushHandle.inputQ); - streamDataSubmitRefDec(pSubmit); - pSubmit = streamQueueNextItem(&pHandle->pushHandle.inputQ); - if (pSubmit == NULL) break; - } - // 3. exec, after each success, update processed ver - // first run - if (tqLoopExecFromQueue(pTq, pHandle, &pSubmit, &rsp) == 0) { - goto SEND_RSP; - } - // set exec status closing - atomic_store_8(&pHandle->pushHandle.execStatus, TASK_EXEC_STATUS__CLOSING); - // second run - if (tqLoopExecFromQueue(pTq, pHandle, &pSubmit, &rsp) == 0) { - goto SEND_RSP; - } - // set exec status idle - atomic_store_8(&pHandle->pushHandle.execStatus, TASK_EXEC_STATUS__IDLE); - } -SEND_RSP: - // 4. if get result - // 4.1 set exec input status blocked and exec status idle - atomic_store_8(&pHandle->pushHandle.execStatus, TASK_EXEC_STATUS__IDLE); - // 4.2 rpc send - rsp.rspOffset = pHandle->pushHandle.processedVer; - /*if (tqSendPollRsp(pTq, pMsg, pReq, &rsp) < 0) {*/ - /*return -1;*/ - /*}*/ - // 4.3 clear rpc info - memset(&pHandle->pushHandle.rpcInfo, 0, sizeof(SRpcHandleInfo)); - return 0; -} + int32_t numOfTasks = streamMetaGetNumOfTasks(pTq->pStreamMeta); + tqDebug("handle submit, restore:%d, size:%d", pTq->pVnode->restored, numOfTasks); -int32_t tqOpenPushHandle(STQ* pTq, STqHandle* pHandle) { - memset(&pHandle->pushHandle, 0, sizeof(STqPushHandle)); - pHandle->pushHandle.inputQ.queue = taosOpenQueue(); - pHandle->pushHandle.inputQ.qall = taosAllocateQall(); - if (pHandle->pushHandle.inputQ.queue == NULL || pHandle->pushHandle.inputQ.qall == NULL) { - if (pHandle->pushHandle.inputQ.queue) { - taosCloseQueue(pHandle->pushHandle.inputQ.queue); - } - if (pHandle->pushHandle.inputQ.qall) { - taosFreeQall(pHandle->pushHandle.inputQ.qall); + // push data for stream processing: + // 1. the vnode has already been restored. + // 2. the vnode should be the leader. + // 3. the stream is not suspended yet. + if (!tsDisableStream && vnodeIsRoleLeader(pTq->pVnode) && pTq->pVnode->restored) { + if (numOfTasks == 0) { + return 0; } - return -1; - } - return 0; -} -int32_t tqPreparePush(STQ* pTq, STqHandle* pHandle, int64_t reqId, const SRpcHandleInfo* pInfo, int64_t processedVer, - int64_t timeout) { - memcpy(&pHandle->pushHandle.rpcInfo, pInfo, sizeof(SRpcHandleInfo)); - atomic_store_64(&pHandle->pushHandle.reqId, reqId); - atomic_store_64(&pHandle->pushHandle.processedVer, processedVer); - atomic_store_8(&pHandle->pushHandle.inputStatus, TASK_INPUT_STATUS__NORMAL); - atomic_store_8(&pHandle->pushHandle.tmrStopped, 0); - taosTmrReset(tqTmrRspFunc, (int32_t)timeout, pHandle, tqMgmt.timer, &pHandle->pushHandle.timerId); - return 0; -} + if (msgType == TDMT_VND_SUBMIT || msgType == TDMT_VND_DELETE) { + tqStartStreamTasks(pTq); + } -int32_t tqEnqueue(STqHandle* pHandle, SStreamDataSubmit* pSubmit) { - int8_t inputStatus = atomic_load_8(&pHandle->pushHandle.inputStatus); - if (inputStatus == TASK_INPUT_STATUS__NORMAL) { - SStreamDataSubmit* pSubmitClone = streamSubmitRefClone(pSubmit); - if (pSubmitClone == NULL) { - return -1; + if (msgType == TDMT_VND_DELETE) { +// tqProcessDeleteDataReq(pTq, POINTER_SHIFT(msg, sizeof(SMsgHead)), msgLen - sizeof(SMsgHead), ver); } - taosWriteQitem(pHandle->pushHandle.inputQ.queue, pSubmitClone); - return 0; } - return -1; -} -int32_t tqSendExecReq(STQ* pTq, STqHandle* pHandle) { - // return 0; } -int32_t tqPushMsgNew(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_t ver, SRpcHandleInfo handleInfo) { - if (msgType != TDMT_VND_SUBMIT) return 0; - void* pIter = NULL; - STqHandle* pHandle = NULL; - SSubmitReq* pReq = (SSubmitReq*)msg; - int32_t workerId = 4; - int64_t fetchOffset = ver; - - while (1) { - pIter = taosHashIterate(pTq->pushMgr, pIter); - if (pIter == NULL) break; - pHandle = *(STqHandle**)pIter; - - taosWLockLatch(&pHandle->pushHandle.lock); - - SMqDataRsp rsp = {0}; - rsp.reqOffset = pHandle->pushHandle.reqOffset; - rsp.blockData = taosArrayInit(0, sizeof(void*)); - rsp.blockDataLen = taosArrayInit(0, sizeof(int32_t)); - - if (msgType == TDMT_VND_SUBMIT) { - tqLogScanExec(pTq, &pHandle->execHandle, pReq, &rsp, workerId); - } else { - // TODO - ASSERT(0); - } - - if (rsp.blockNum == 0) { - taosWUnLockLatch(&pHandle->pushHandle.lock); - continue; - } - - ASSERT(taosArrayGetSize(rsp.blockData) == rsp.blockNum); - ASSERT(taosArrayGetSize(rsp.blockDataLen) == rsp.blockNum); - - rsp.rspOffset = fetchOffset; - - int32_t tlen = sizeof(SMqRspHead) + tEncodeSMqDataBlkRsp(NULL, &rsp); - void* buf = rpcMallocCont(tlen); - if (buf == NULL) { - // todo free - return -1; - } - - ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_RSP; - ((SMqRspHead*)buf)->epoch = pHandle->pushHandle.epoch; - ((SMqRspHead*)buf)->consumerId = pHandle->pushHandle.consumerId; - - void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead)); - tEncodeSMqDataBlkRsp(&abuf, &rsp); - - SRpcMsg resp = { - .info = pHandle->pushHandle.rpcInfo, - .pCont = buf, - .contLen = tlen, - .code = 0, - }; - tmsgSendRsp(&resp); - - memset(&pHandle->pushHandle.rpcInfo, 0, sizeof(SRpcHandleInfo)); - taosWUnLockLatch(&pHandle->pushHandle.lock); - - tqDebug("vgId:%d, offset %" PRId64 " from consumer:%" PRId64 ", (epoch %d) send rsp, block num: %d, reqOffset:%" PRId64 ", rspOffset:%" PRId64, - TD_VID(pTq->pVnode), fetchOffset, pHandle->pushHandle.consumerId, pHandle->pushHandle.epoch, rsp.blockNum, - rsp.reqOffset, rsp.rspOffset); - - // TODO destroy - taosArrayDestroy(rsp.blockData); - taosArrayDestroy(rsp.blockDataLen); +int32_t tqRegisterPushHandle(STQ* pTq, void* handle, SRpcMsg* pMsg) { + int32_t vgId = TD_VID(pTq->pVnode); + STqHandle* pHandle = (STqHandle*)handle; + + if (pHandle->msg == NULL) { + pHandle->msg = taosMemoryCalloc(1, sizeof(SRpcMsg)); + memcpy(pHandle->msg, pMsg, sizeof(SRpcMsg)); + pHandle->msg->pCont = rpcMallocCont(pMsg->contLen); + } else { + tqPushDataRsp(pTq, pHandle); + void* tmp = pHandle->msg->pCont; + memcpy(pHandle->msg, pMsg, sizeof(SRpcMsg)); + pHandle->msg->pCont = tmp; } + memcpy(pHandle->msg->pCont, pMsg->pCont, pMsg->contLen); + pHandle->msg->contLen = pMsg->contLen; + int32_t ret = taosHashPut(pTq->pPushMgr, pHandle->subKey, strlen(pHandle->subKey), &pHandle, POINTER_BYTES); + tqDebug("vgId:%d data is over, ret:%d, consumerId:0x%" PRIx64 ", register to pHandle:%p, pCont:%p, len:%d", vgId, ret, + pHandle->consumerId, pHandle, pHandle->msg->pCont, pHandle->msg->contLen); return 0; } -#endif - -int tqPushMsg(STQ* pTq, void* msg, int32_t msgLen, tmsg_t msgType, int64_t ver) { - tqDebug("vgId:%d, tq push msg ver %" PRId64 ", type: %s", pTq->pVnode->config.vgId, ver, TMSG_INFO(msgType)); - - if (msgType == TDMT_VND_SUBMIT) { - // lock push mgr to avoid potential msg lost - taosWLockLatch(&pTq->pushLock); - tqDebug("vgId:%d, push handle num %d", pTq->pVnode->config.vgId, taosHashGetSize(pTq->pPushMgr)); - if (taosHashGetSize(pTq->pPushMgr) != 0) { - SArray* cachedKeys = taosArrayInit(0, sizeof(void*)); - SArray* cachedKeyLens = taosArrayInit(0, sizeof(size_t)); - void* data = taosMemoryMalloc(msgLen); - if (data == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - tqError("failed to copy data for stream since out of memory"); - taosArrayDestroyP(cachedKeys, (FDelete)taosMemoryFree); - taosArrayDestroy(cachedKeyLens); - return -1; - } - memcpy(data, msg, msgLen); - SSubmitReq* pReq = (SSubmitReq*)data; - pReq->version = ver; - - void* pIter = NULL; - while (1) { - pIter = taosHashIterate(pTq->pPushMgr, pIter); - if (pIter == NULL) break; - STqPushEntry* pPushEntry = *(STqPushEntry**)pIter; - - STqHandle* pHandle = taosHashGet(pTq->pHandle, pPushEntry->subKey, strlen(pPushEntry->subKey)); - if (pHandle == NULL) { - tqDebug("vgId:%d, cannot find handle %s", pTq->pVnode->config.vgId, pPushEntry->subKey); - continue; - } - if (pPushEntry->dataRsp.reqOffset.version >= ver) { - tqDebug("vgId:%d, push entry req version %" PRId64 ", while push version %" PRId64 ", skip", - pTq->pVnode->config.vgId, pPushEntry->dataRsp.reqOffset.version, ver); - continue; - } - STqExecHandle* pExec = &pHandle->execHandle; - qTaskInfo_t task = pExec->task; - - SMqDataRsp* pRsp = &pPushEntry->dataRsp; - - // prepare scan mem data - qStreamScanMemData(task, pReq); - - // exec - while (1) { - SSDataBlock* pDataBlock = NULL; - uint64_t ts = 0; - if (qExecTask(task, &pDataBlock, &ts) < 0) { - ASSERT(0); - } - - if (pDataBlock == NULL) { - break; - } - tqAddBlockDataToRsp(pDataBlock, pRsp, pExec->numOfCols, pTq->pVnode->config.tsdbCfg.precision); - pRsp->blockNum++; - } +int32_t tqUnregisterPushHandle(STQ* pTq, void *handle) { + STqHandle *pHandle = (STqHandle*)handle; + int32_t vgId = TD_VID(pTq->pVnode); - tqDebug("vgId:%d, tq handle push, subkey: %s, block num: %d", pTq->pVnode->config.vgId, pPushEntry->subKey, - pRsp->blockNum); - if (pRsp->blockNum > 0) { - // set offset - tqOffsetResetToLog(&pRsp->rspOffset, ver); - // remove from hash - size_t kLen; - void* key = taosHashGetKey(pIter, &kLen); - void* keyCopy = taosMemoryMalloc(kLen); - memcpy(keyCopy, key, kLen); + int32_t ret = taosHashRemove(pTq->pPushMgr, pHandle->subKey, strlen(pHandle->subKey)); + tqError("vgId:%d remove pHandle:%p,ret:%d consumer Id:0x%" PRIx64, vgId, pHandle, ret, pHandle->consumerId); - taosArrayPush(cachedKeys, &keyCopy); - taosArrayPush(cachedKeyLens, &kLen); + if(pHandle->msg != NULL) { + tqPushDataRsp(pTq, pHandle); - tqPushDataRsp(pTq, pPushEntry); - } - } - // delete entry - for (int32_t i = 0; i < taosArrayGetSize(cachedKeys); i++) { - void* key = taosArrayGetP(cachedKeys, i); - size_t kLen = *(size_t*)taosArrayGet(cachedKeyLens, i); - if (taosHashRemove(pTq->pPushMgr, key, kLen) != 0) { - ASSERT(0); - } - } - taosArrayDestroyP(cachedKeys, (FDelete)taosMemoryFree); - taosArrayDestroy(cachedKeyLens); - taosMemoryFree(data); - } - // unlock - taosWUnLockLatch(&pTq->pushLock); - } - - if (vnodeIsRoleLeader(pTq->pVnode)) { - if (taosHashGetSize(pTq->pStreamMeta->pTasks) == 0) return 0; - if (msgType == TDMT_VND_SUBMIT) { - void* data = taosMemoryMalloc(msgLen); - if (data == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - tqError("failed to copy data for stream since out of memory"); - return -1; - } - memcpy(data, msg, msgLen); - SSubmitReq* pReq = (SSubmitReq*)data; - pReq->version = ver; - - tqProcessSubmitReq(pTq, data, ver); - } - if (msgType == TDMT_VND_DELETE) { - tqProcessDelReq(pTq, POINTER_SHIFT(msg, sizeof(SMsgHead)), msgLen - sizeof(SMsgHead), ver); - } + rpcFreeCont(pHandle->msg->pCont); + taosMemoryFree(pHandle->msg); + pHandle->msg = NULL; } return 0; diff --git a/source/dnode/vnode/src/tq/tqRead.c b/source/dnode/vnode/src/tq/tqRead.c index 46b31bc5b0fed0f42e3f570772ec46a190f70ea1..09574a6b620518f4ca49e74fe91eab21af5d19eb 100644 --- a/source/dnode/vnode/src/tq/tqRead.c +++ b/source/dnode/vnode/src/tq/tqRead.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include "tmsg.h" #include "tq.h" bool isValValidForTable(STqHandle* pHandle, SWalCont* pHead) { @@ -113,7 +114,7 @@ bool isValValidForTable(STqHandle* pHandle, SWalCont* pHead) { } SMetaReader mr = {0}; - metaReaderInit(&mr, pHandle->execHandle.pExecReader->pVnodeMeta, 0); + metaReaderInit(&mr, pHandle->execHandle.pTqReader->pVnodeMeta, 0); if (metaGetTableEntryByName(&mr, req.tbName) < 0) { metaReaderClear(&mr); @@ -176,8 +177,6 @@ bool isValValidForTable(STqHandle* pHandle, SWalCont* pHead) { goto end; } realTbSuid = req.suid; - } else { - ASSERT(0); } end: @@ -185,28 +184,29 @@ end: return tbSuid == realTbSuid; } -int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHead** ppCkHead) { +int32_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHead** ppCkHead, uint64_t reqId) { int32_t code = 0; + int32_t vgId = TD_VID(pTq->pVnode); + taosThreadMutexLock(&pHandle->pWalReader->mutex); int64_t offset = *fetchOffset; while (1) { if (walFetchHead(pHandle->pWalReader, offset, *ppCkHead) < 0) { - tqDebug("tmq poll: consumer:%" PRId64 ", (epoch %d) vgId:%d offset %" PRId64 ", no more log to return", - pHandle->consumerId, pHandle->epoch, TD_VID(pTq->pVnode), offset); + tqDebug("tmq poll: consumer:0x%" PRIx64 ", (epoch %d) vgId:%d offset %" PRId64 ", no more log to return, reqId:0x%"PRIx64, + pHandle->consumerId, pHandle->epoch, vgId, offset, reqId); *fetchOffset = offset - 1; code = -1; goto END; } - tqDebug("vgId:%d, taosx get msg ver %" PRId64 ", type: %s", pTq->pVnode->config.vgId, offset, - TMSG_INFO((*ppCkHead)->head.msgType)); + tqDebug("vgId:%d, consumer:0x%" PRIx64 " taosx get msg ver %" PRId64 ", type: %s, reqId:0x%" PRIx64, vgId, + pHandle->consumerId, offset, TMSG_INFO((*ppCkHead)->head.msgType), reqId); if ((*ppCkHead)->head.msgType == TDMT_VND_SUBMIT) { code = walFetchBody(pHandle->pWalReader, ppCkHead); if (code < 0) { - ASSERT(0); *fetchOffset = offset; code = -1; goto END; @@ -220,7 +220,6 @@ int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHea if (IS_META_MSG(pHead->msgType)) { code = walFetchBody(pHandle->pWalReader, ppCkHead); if (code < 0) { - ASSERT(0); *fetchOffset = offset; code = -1; goto END; @@ -238,7 +237,6 @@ int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHea } code = walSkipFetchBody(pHandle->pWalReader, *ppCkHead); if (code < 0) { - ASSERT(0); *fetchOffset = offset; code = -1; goto END; @@ -246,13 +244,14 @@ int64_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHea offset++; } } + END: taosThreadMutexUnlock(&pHandle->pWalReader->mutex); return code; } -STqReader* tqOpenReader(SVnode* pVnode) { - STqReader* pReader = taosMemoryMalloc(sizeof(STqReader)); +STqReader* tqReaderOpen(SVnode* pVnode) { + STqReader* pReader = taosMemoryCalloc(1, sizeof(STqReader)); if (pReader == NULL) { return NULL; } @@ -264,14 +263,12 @@ STqReader* tqOpenReader(SVnode* pVnode) { } pReader->pVnodeMeta = pVnode->pMeta; - pReader->pMsg = NULL; - pReader->ver = -1; pReader->pColIdList = NULL; pReader->cachedSchemaVer = 0; pReader->cachedSchemaSuid = 0; - pReader->pSchema = NULL; pReader->pSchemaWrapper = NULL; pReader->tbIdHash = NULL; + pReader->pResBlock = createDataBlock(); return pReader; } @@ -280,121 +277,219 @@ void tqCloseReader(STqReader* pReader) { if (pReader->pWalReader) { walCloseReader(pReader->pWalReader); } - // free cached schema - if (pReader->pSchema) { - taosMemoryFree(pReader->pSchema); - } + if (pReader->pSchemaWrapper) { - tDeleteSSchemaWrapper(pReader->pSchemaWrapper); + tDeleteSchemaWrapper(pReader->pSchemaWrapper); } + if (pReader->pColIdList) { taosArrayDestroy(pReader->pColIdList); } + // free hash + blockDataDestroy(pReader->pResBlock); taosHashCleanup(pReader->tbIdHash); + tDestroySubmitReq(&pReader->submit, TSDB_MSG_FLG_DECODE); taosMemoryFree(pReader); } -int32_t tqSeekVer(STqReader* pReader, int64_t ver) { - if (walReadSeekVer(pReader->pWalReader, ver) < 0) { - ASSERT(pReader->pWalReader->curInvalid); - ASSERT(pReader->pWalReader->curVersion == ver); +int32_t tqSeekVer(STqReader* pReader, int64_t ver, const char* id) { + if (walReaderSeekVer(pReader->pWalReader, ver) < 0) { return -1; } - ASSERT(pReader->pWalReader->curVersion == ver); + tqDebug("wal reader seek to ver:%"PRId64" %s", ver, id); return 0; } -int32_t tqNextBlock(STqReader* pReader, SFetchRet* ret) { - bool fromProcessedMsg = pReader->pMsg != NULL; +int32_t extractMsgFromWal(SWalReader* pReader, void** pItem, const char* id) { + int32_t code = walNextValidMsg(pReader); + if (code != TSDB_CODE_SUCCESS) { + return code; + } - while (1) { - if (!fromProcessedMsg) { - if (walNextValidMsg(pReader->pWalReader) < 0) { - pReader->ver = - pReader->pWalReader->curVersion - (pReader->pWalReader->curInvalid | pReader->pWalReader->curStopped); - ret->offset.type = TMQ_OFFSET__LOG; - ret->offset.version = pReader->ver; - ret->fetchType = FETCH_TYPE__NONE; - tqDebug("return offset %" PRId64 ", no more valid", ret->offset.version); - ASSERT(ret->offset.version >= 0); - return -1; + int64_t ver = pReader->pHead->head.version; + + if (pReader->pHead->head.msgType == TDMT_VND_SUBMIT) { + void* pBody = POINTER_SHIFT(pReader->pHead->head.body, sizeof(SSubmitReq2Msg)); + int32_t len = pReader->pHead->head.bodyLen - sizeof(SSubmitReq2Msg); + + void* data = taosMemoryMalloc(len); + if (data == NULL) { + // todo: for all stream in this vnode, keep this offset in the offset files, and wait for a moment, and then retry + terrno = TSDB_CODE_OUT_OF_MEMORY; + tqError("vgId:%d, failed to copy submit data for stream processing, since out of memory", 0); + return -1; + } + + memcpy(data, pBody, len); + SPackedData data1 = (SPackedData){.ver = ver, .msgLen = len, .msgStr = data}; + + *pItem = (SStreamQueueItem*)streamDataSubmitNew(data1, STREAM_INPUT__DATA_SUBMIT); + if (*pItem == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + tqError("%s failed to create data submit for stream since out of memory", id); + return terrno; + } + } else if (pReader->pHead->head.msgType == TDMT_VND_DELETE) { + void* pBody = POINTER_SHIFT(pReader->pHead->head.body, sizeof(SMsgHead)); + int32_t len = pReader->pHead->head.bodyLen - sizeof(SMsgHead); + + extractDelDataBlock(pBody, len, ver, (SStreamRefDataBlock**)pItem); + } else { + ASSERT(0); + } + + return 0; +} + +// todo ignore the error in wal? +int32_t tqNextBlockInWal(STqReader* pReader) { + SWalReader* pWalReader = pReader->pWalReader; + + while(1) { + SArray* pBlockList = pReader->submit.aSubmitTbData; + if (pBlockList == NULL || pReader->nextBlk >= taosArrayGetSize(pBlockList)) { + + // try next message in wal file + // todo always retry to avoid read failure caused by wal file deletion + if (walNextValidMsg(pWalReader) < 0) { + return FETCH_TYPE__NONE; } - void* body = pReader->pWalReader->pHead->head.body; -#if 0 - if (pReader->pWalReader->pHead->head.msgType != TDMT_VND_SUBMIT) { - // TODO do filter - ret->fetchType = FETCH_TYPE__META; - ret->meta = pReader->pWalReader->pHead->head.body; - return 0; - } else { -#endif - tqReaderSetDataMsg(pReader, body, pReader->pWalReader->pHead->head.version); -#if 0 + + void* pBody = POINTER_SHIFT(pWalReader->pHead->head.body, sizeof(SSubmitReq2Msg)); + int32_t bodyLen = pWalReader->pHead->head.bodyLen - sizeof(SSubmitReq2Msg); + int64_t ver = pWalReader->pHead->head.version; + + SDecoder decoder = {0}; + tDecoderInit(&decoder, pBody, bodyLen); + + { + int32_t nSubmitTbData = taosArrayGetSize(pReader->submit.aSubmitTbData); + for (int32_t i = 0; i < nSubmitTbData; i++) { + SSubmitTbData* pData = taosArrayGet(pReader->submit.aSubmitTbData, i); + if (pData->pCreateTbReq != NULL) { + taosArrayDestroy(pData->pCreateTbReq->ctb.tagName); + taosMemoryFreeClear(pData->pCreateTbReq); + } + pData->aRowP = taosArrayDestroy(pData->aRowP); + } + pReader->submit.aSubmitTbData = taosArrayDestroy(pReader->submit.aSubmitTbData); } -#endif - } - while (tqNextDataBlock(pReader)) { - // TODO mem free - memset(&ret->data, 0, sizeof(SSDataBlock)); - int32_t code = tqRetrieveDataBlock(&ret->data, pReader); - if (code != 0 || ret->data.info.rows == 0) { - ASSERT(0); - continue; + if (tDecodeSubmitReq(&decoder, &pReader->submit) < 0) { + tDecoderClear(&decoder); + tqError("decode wal file error, msgLen:%d, ver:%"PRId64, bodyLen, ver); + return FETCH_TYPE__NONE; } - ret->fetchType = FETCH_TYPE__DATA; - tqDebug("return data rows %d", ret->data.info.rows); - return 0; + + tDecoderClear(&decoder); + pReader->nextBlk = 0; } - if (fromProcessedMsg) { - ret->offset.type = TMQ_OFFSET__LOG; - ret->offset.version = pReader->ver; - ASSERT(pReader->ver >= 0); - ret->fetchType = FETCH_TYPE__SEP; - tqDebug("return offset %" PRId64 ", processed finish", ret->offset.version); - return 0; + size_t numOfBlocks = taosArrayGetSize(pReader->submit.aSubmitTbData); + while (pReader->nextBlk < numOfBlocks) { + tqDebug("tq reader next data block %p, %d %" PRId64 " %d", pReader->msg.msgStr, pReader->msg.msgLen, + pReader->msg.ver, pReader->nextBlk); + + SSubmitTbData* pSubmitTbData = taosArrayGet(pReader->submit.aSubmitTbData, pReader->nextBlk); + + if (pReader->tbIdHash == NULL) { + int32_t code = tqRetrieveDataBlock(pReader, NULL); + if (code == TSDB_CODE_SUCCESS && pReader->pResBlock->info.rows > 0) { + return FETCH_TYPE__DATA; + } + } + + void* ret = taosHashGet(pReader->tbIdHash, &pSubmitTbData->uid, sizeof(int64_t)); + if (ret != NULL) { + tqDebug("tq reader return submit block, uid:%"PRId64", ver:%"PRId64, pSubmitTbData->uid, pReader->msg.ver); + + int32_t code = tqRetrieveDataBlock(pReader, NULL); + if (code == TSDB_CODE_SUCCESS && pReader->pResBlock->info.rows > 0) { + return FETCH_TYPE__DATA; + } + } else { + pReader->nextBlk += 1; + tqDebug("tq reader discard submit block, uid:%"PRId64", continue", pSubmitTbData->uid); + } } + + tDestroySubmitReq(&pReader->submit, TSDB_MSG_FLG_DECODE); + pReader->msg.msgStr = NULL; } } -int32_t tqReaderSetDataMsg(STqReader* pReader, const SSubmitReq* pMsg, int64_t ver) { - pReader->pMsg = pMsg; +int32_t tqReaderSetSubmitMsg(STqReader* pReader, void* msgStr, int32_t msgLen, int64_t ver) { + pReader->msg.msgStr = msgStr; + pReader->msg.msgLen = msgLen; + pReader->msg.ver = ver; + + tqDebug("tq reader set msg %p %d", msgStr, msgLen); + SDecoder decoder; - if (tInitSubmitMsgIter(pMsg, &pReader->msgIter) < 0) return -1; - while (true) { - if (tGetSubmitMsgNext(&pReader->msgIter, &pReader->pBlock) < 0) return -1; - if (pReader->pBlock == NULL) break; + tDecoderInit(&decoder, pReader->msg.msgStr, pReader->msg.msgLen); + if (tDecodeSubmitReq(&decoder, &pReader->submit) < 0) { + tDecoderClear(&decoder); + tqError("DecodeSSubmitReq2 error, msgLen:%d, ver:%"PRId64, msgLen, ver); + return -1; } - if (tInitSubmitMsgIter(pMsg, &pReader->msgIter) < 0) return -1; - pReader->ver = ver; - memset(&pReader->blkIter, 0, sizeof(SSubmitBlkIter)); + tDecoderClear(&decoder); return 0; } -bool tqNextDataBlock(STqReader* pReader) { - if (pReader->pMsg == NULL) return false; - while (1) { - if (tGetSubmitMsgNext(&pReader->msgIter, &pReader->pBlock) < 0) { - return false; - } - if (pReader->pBlock == NULL) { - pReader->pMsg = NULL; - return false; - } +bool tqNextBlockImpl(STqReader* pReader) { + if (pReader->msg.msgStr == NULL) { + return false; + } + int32_t blockSz = taosArrayGetSize(pReader->submit.aSubmitTbData); + while (pReader->nextBlk < blockSz) { + tqDebug("tq reader next data block %p, %d %" PRId64 " %d", pReader->msg.msgStr, pReader->msg.msgLen, + pReader->msg.ver, pReader->nextBlk); + + SSubmitTbData* pSubmitTbData = taosArrayGet(pReader->submit.aSubmitTbData, pReader->nextBlk); if (pReader->tbIdHash == NULL) { return true; } - void* ret = taosHashGet(pReader->tbIdHash, &pReader->msgIter.uid, sizeof(int64_t)); - /*tqDebug("search uid %" PRId64, pHandle->msgIter.uid);*/ + + void* ret = taosHashGet(pReader->tbIdHash, &pSubmitTbData->uid, sizeof(int64_t)); if (ret != NULL) { - /*tqDebug("find uid %" PRId64, pHandle->msgIter.uid);*/ + tqDebug("tq reader block found, ver:%"PRId64", uid:%"PRId64, pReader->msg.ver, pSubmitTbData->uid); return true; + } else { + tqDebug("tq reader discard submit block, uid:%"PRId64", continue", pSubmitTbData->uid); } + + pReader->nextBlk++; } + + tDestroySubmitReq(&pReader->submit, TSDB_MSG_FLG_DECODE); + pReader->nextBlk = 0; + pReader->msg.msgStr = NULL; + + return false; +} + +bool tqNextDataBlockFilterOut(STqReader* pReader, SHashObj* filterOutUids) { + if (pReader->msg.msgStr == NULL) return false; + + int32_t blockSz = taosArrayGetSize(pReader->submit.aSubmitTbData); + while (pReader->nextBlk < blockSz) { + SSubmitTbData* pSubmitTbData = taosArrayGet(pReader->submit.aSubmitTbData, pReader->nextBlk); + if (filterOutUids == NULL) return true; + + void* ret = taosHashGet(filterOutUids, &pSubmitTbData->uid, sizeof(int64_t)); + if (ret == NULL) { + return true; + } + pReader->nextBlk++; + } + + tDestroySubmitReq(&pReader->submit, TSDB_MSG_FLG_DECODE); + pReader->nextBlk = 0; + pReader->msg.msgStr = NULL; + return false; } @@ -427,260 +522,453 @@ int32_t tqMaskBlock(SSchemaWrapper* pDst, SSDataBlock* pBlock, const SSchemaWrap return 0; } -bool tqNextDataBlockFilterOut(STqReader* pHandle, SHashObj* filterOutUids) { - while (1) { - if (tGetSubmitMsgNext(&pHandle->msgIter, &pHandle->pBlock) < 0) { - return false; - } - if (pHandle->pBlock == NULL) return false; - - ASSERT(pHandle->tbIdHash == NULL); - void* ret = taosHashGet(filterOutUids, &pHandle->msgIter.uid, sizeof(int64_t)); - if (ret == NULL) { - return true; - } +static int32_t buildResSDataBlock(SSDataBlock* pBlock, SSchemaWrapper* pSchema, const SArray* pColIdList) { + if (blockDataGetNumOfCols(pBlock) > 0) { + return TSDB_CODE_SUCCESS; } - return false; -} -int32_t tqRetrieveDataBlock(SSDataBlock* pBlock, STqReader* pReader) { - // TODO: cache multiple schema - int32_t sversion = htonl(pReader->pBlock->sversion); - if (pReader->cachedSchemaSuid == 0 || pReader->cachedSchemaVer != sversion || - pReader->cachedSchemaSuid != pReader->msgIter.suid) { - if (pReader->pSchema) taosMemoryFree(pReader->pSchema); - pReader->pSchema = metaGetTbTSchema(pReader->pVnodeMeta, pReader->msgIter.uid, sversion, 1); - if (pReader->pSchema == NULL) { - tqWarn("cannot found tsschema for table: uid:%" PRId64 " (suid:%" PRId64 "), version %d, possibly dropped table", - pReader->msgIter.uid, pReader->msgIter.suid, pReader->cachedSchemaVer); - /*ASSERT(0);*/ - pReader->cachedSchemaSuid = 0; - terrno = TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND; - return -1; - } + int32_t numOfCols = taosArrayGetSize(pColIdList); - if (pReader->pSchemaWrapper) tDeleteSSchemaWrapper(pReader->pSchemaWrapper); - pReader->pSchemaWrapper = metaGetTableSchema(pReader->pVnodeMeta, pReader->msgIter.uid, sversion, 1); - if (pReader->pSchemaWrapper == NULL) { - tqWarn("cannot found schema wrapper for table: suid:%" PRId64 ", version %d, possibly dropped table", - pReader->msgIter.uid, pReader->cachedSchemaVer); - /*ASSERT(0);*/ - pReader->cachedSchemaSuid = 0; - terrno = TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND; - return -1; - } - pReader->cachedSchemaVer = sversion; - pReader->cachedSchemaSuid = pReader->msgIter.suid; - } - - STSchema* pTschema = pReader->pSchema; - SSchemaWrapper* pSchemaWrapper = pReader->pSchemaWrapper; - - int32_t colNumNeed = taosArrayGetSize(pReader->pColIdList); - - if (colNumNeed == 0) { - int32_t colMeta = 0; - while (colMeta < pSchemaWrapper->nCols) { - SSchema* pColSchema = &pSchemaWrapper->pSchema[colMeta]; + if (numOfCols == 0) { // all columns are required + for (int32_t i = 0; i < pSchema->nCols; ++i) { + SSchema* pColSchema = &pSchema->pSchema[i]; SColumnInfoData colInfo = createColumnInfoData(pColSchema->type, pColSchema->bytes, pColSchema->colId); - int32_t code = blockDataAppendColInfo(pBlock, &colInfo); + + int32_t code = blockDataAppendColInfo(pBlock, &colInfo); if (code != TSDB_CODE_SUCCESS) { - goto FAIL; + blockDataFreeRes(pBlock); + return TSDB_CODE_OUT_OF_MEMORY; } - colMeta++; } } else { - if (colNumNeed > pSchemaWrapper->nCols) { - colNumNeed = pSchemaWrapper->nCols; + if (numOfCols > pSchema->nCols) { + numOfCols = pSchema->nCols; } - int32_t colMeta = 0; - int32_t colNeed = 0; - while (colMeta < pSchemaWrapper->nCols && colNeed < colNumNeed) { - SSchema* pColSchema = &pSchemaWrapper->pSchema[colMeta]; + int32_t i = 0; + int32_t j = 0; + while (i < pSchema->nCols && j < numOfCols) { + SSchema* pColSchema = &pSchema->pSchema[i]; col_id_t colIdSchema = pColSchema->colId; - col_id_t colIdNeed = *(col_id_t*)taosArrayGet(pReader->pColIdList, colNeed); + + col_id_t colIdNeed = *(col_id_t*)taosArrayGet(pColIdList, j); if (colIdSchema < colIdNeed) { - colMeta++; + i++; } else if (colIdSchema > colIdNeed) { - colNeed++; + j++; } else { SColumnInfoData colInfo = createColumnInfoData(pColSchema->type, pColSchema->bytes, pColSchema->colId); int32_t code = blockDataAppendColInfo(pBlock, &colInfo); if (code != TSDB_CODE_SUCCESS) { - goto FAIL; + return -1; } - colMeta++; - colNeed++; + i++; + j++; } } } - if (blockDataEnsureCapacity(pBlock, pReader->msgIter.numOfRows) < 0) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - goto FAIL; - } + return TSDB_CODE_SUCCESS; +} - int32_t colActual = blockDataGetNumOfCols(pBlock); +static int32_t doSetVal(SColumnInfoData* pColumnInfoData, int32_t rowIndex, SColVal* pColVal) { + int32_t code = TSDB_CODE_SUCCESS; - STSRowIter iter = {0}; - tdSTSRowIterInit(&iter, pTschema); - STSRow* row; - int32_t curRow = 0; + if (IS_STR_DATA_TYPE(pColVal->type)) { + char val[65535 + 2] = {0}; + if (pColVal->value.pData != NULL) { + memcpy(varDataVal(val), pColVal->value.pData, pColVal->value.nData); + varDataSetLen(val, pColVal->value.nData); + code = colDataSetVal(pColumnInfoData, rowIndex, val, !COL_VAL_IS_VALUE(pColVal)); + } else { + colDataSetNULL(pColumnInfoData, rowIndex); + } + } else { + code = colDataSetVal(pColumnInfoData, rowIndex, (void*)&pColVal->value.val, !COL_VAL_IS_VALUE(pColVal)); + } - tInitSubmitBlkIter(&pReader->msgIter, pReader->pBlock, &pReader->blkIter); + return code; +} - pBlock->info.id.uid = pReader->msgIter.uid; - pBlock->info.rows = pReader->msgIter.numOfRows; - pBlock->info.version = pReader->pMsg->version; - pBlock->info.dataLoad = 1; +int32_t tqRetrieveDataBlock(STqReader* pReader, SSubmitTbData** pSubmitTbDataRet) { + tqDebug("tq reader retrieve data block %p, index:%d", pReader->msg.msgStr, pReader->nextBlk); - while ((row = tGetSubmitBlkNext(&pReader->blkIter)) != NULL) { - tdSTSRowIterReset(&iter, row); - // get all wanted col of that block - for (int32_t i = 0; i < colActual; i++) { - SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, i); - SCellVal sVal = {0}; - if (!tdSTSRowIterFetch(&iter, pColData->info.colId, pColData->info.type, &sVal)) { - break; - } - if (colDataAppend(pColData, curRow, sVal.val, sVal.valType != TD_VTYPE_NORM) < 0) { - goto FAIL; - } - } - curRow++; + SSubmitTbData* pSubmitTbData = taosArrayGet(pReader->submit.aSubmitTbData, pReader->nextBlk++); + if (pSubmitTbDataRet) { + *pSubmitTbDataRet = pSubmitTbData; } - return 0; -FAIL: - blockDataFreeRes(pBlock); - return -1; -} + SSDataBlock* pBlock = pReader->pResBlock; + blockDataCleanup(pBlock); -int32_t tqRetrieveTaosxBlock(STqReader* pReader, SArray* blocks, SArray* schemas) { - int32_t sversion = htonl(pReader->pBlock->sversion); - - if (pReader->cachedSchemaSuid == 0 || pReader->cachedSchemaVer != sversion || - pReader->cachedSchemaSuid != pReader->msgIter.suid) { - if (pReader->pSchema) taosMemoryFree(pReader->pSchema); - pReader->pSchema = metaGetTbTSchema(pReader->pVnodeMeta, pReader->msgIter.uid, sversion, 1); - if (pReader->pSchema == NULL) { - tqWarn("cannot found tsschema for table: uid:%" PRId64 " (suid:%" PRId64 "), version %d, possibly dropped table", - pReader->msgIter.uid, pReader->msgIter.suid, pReader->cachedSchemaVer); - /*ASSERT(0);*/ - pReader->cachedSchemaSuid = 0; - terrno = TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND; - return -1; - } + int32_t sversion = pSubmitTbData->sver; + int64_t suid = pSubmitTbData->suid; + int64_t uid = pSubmitTbData->uid; + pReader->lastBlkUid = uid; + + pBlock->info.id.uid = uid; + pBlock->info.version = pReader->msg.ver; - if (pReader->pSchemaWrapper) tDeleteSSchemaWrapper(pReader->pSchemaWrapper); - pReader->pSchemaWrapper = metaGetTableSchema(pReader->pVnodeMeta, pReader->msgIter.uid, sversion, 1); + if ((suid != 0 && pReader->cachedSchemaSuid != suid) || (suid == 0 && pReader->cachedSchemaUid != uid) || (pReader->cachedSchemaVer != sversion)) { + tDeleteSchemaWrapper(pReader->pSchemaWrapper); + + pReader->pSchemaWrapper = metaGetTableSchema(pReader->pVnodeMeta, uid, sversion, 1); if (pReader->pSchemaWrapper == NULL) { - tqWarn("cannot found schema wrapper for table: suid:%" PRId64 ", version %d, possibly dropped table", - pReader->msgIter.uid, pReader->cachedSchemaVer); - /*ASSERT(0);*/ + tqWarn("vgId:%d, cannot found schema wrapper for table: suid:%" PRId64 ", uid:%" PRId64 "version %d, possibly dropped table", + pReader->pWalReader->pWal->cfg.vgId, suid, uid, pReader->cachedSchemaVer); pReader->cachedSchemaSuid = 0; terrno = TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND; return -1; } + + pReader->cachedSchemaUid = uid; + pReader->cachedSchemaSuid = suid; pReader->cachedSchemaVer = sversion; - pReader->cachedSchemaSuid = pReader->msgIter.suid; + + ASSERT(pReader->cachedSchemaVer == pReader->pSchemaWrapper->version); + if (blockDataGetNumOfCols(pBlock) == 0) { + int32_t code = buildResSDataBlock(pReader->pResBlock, pReader->pSchemaWrapper, pReader->pColIdList); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } } - STSchema* pTschema = pReader->pSchema; - SSchemaWrapper* pSchemaWrapper = pReader->pSchemaWrapper; + int32_t numOfRows = 0; + if (pSubmitTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + SColData* pCol = taosArrayGet(pSubmitTbData->aCol, 0); + numOfRows = pCol->nVal; + } else { + numOfRows = taosArrayGetSize(pSubmitTbData->aRowP); + } - int32_t colAtMost = pSchemaWrapper->nCols; + if (blockDataEnsureCapacity(pBlock, numOfRows) < 0) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return -1; + } - int32_t curRow = 0; - int32_t lastRow = 0; + pBlock->info.rows = numOfRows; - char* assigned = taosMemoryCalloc(1, pSchemaWrapper->nCols); - if (assigned == NULL) return -1; + int32_t colActual = blockDataGetNumOfCols(pBlock); + + // convert and scan one block + if (pSubmitTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + SArray* pCols = pSubmitTbData->aCol; + int32_t numOfCols = taosArrayGetSize(pCols); + int32_t targetIdx = 0; + int32_t sourceIdx = 0; + while (targetIdx < colActual) { + if (sourceIdx >= numOfCols) { + tqError("tqRetrieveDataBlock sourceIdx:%d >= numOfCols:%d", sourceIdx, numOfCols); + return -1; + } + + SColData* pCol = taosArrayGet(pCols, sourceIdx); + SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, targetIdx); + SColVal colVal; + + if (pCol->nVal != numOfRows) { + tqError("tqRetrieveDataBlock pCol->nVal:%d != numOfRows:%d", pCol->nVal, numOfRows); + return -1; + } - tInitSubmitBlkIter(&pReader->msgIter, pReader->pBlock, &pReader->blkIter); - STSRowIter iter = {0}; - tdSTSRowIterInit(&iter, pTschema); - STSRow* row; - - while ((row = tGetSubmitBlkNext(&pReader->blkIter)) != NULL) { - bool buildNew = false; - tdSTSRowIterReset(&iter, row); - - tqDebug("vgId:%d, row of block %d", pReader->pWalReader->pWal->cfg.vgId, curRow); - for (int32_t i = 0; i < colAtMost; i++) { - SCellVal sVal = {0}; - if (!tdSTSRowIterFetch(&iter, pSchemaWrapper->pSchema[i].colId, pSchemaWrapper->pSchema[i].type, &sVal)) { - break; - } - tqDebug("vgId:%d, %d col, type %d", pReader->pWalReader->pWal->cfg.vgId, i, sVal.valType); - if (curRow == 0) { - assigned[i] = sVal.valType != TD_VTYPE_NONE; - buildNew = true; + if (pCol->cid < pColData->info.colId) { + sourceIdx++; + } else if (pCol->cid == pColData->info.colId) { + for (int32_t i = 0; i < pCol->nVal; i++) { + tColDataGetValue(pCol, i, &colVal); + int32_t code = doSetVal(pColData, i, &colVal); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + sourceIdx++; + targetIdx++; } else { - bool currentRowAssigned = sVal.valType != TD_VTYPE_NONE; - if (currentRowAssigned != assigned[i]) { - assigned[i] = currentRowAssigned; - buildNew = true; + colDataSetNNULL(pColData, 0, pCol->nVal); + targetIdx++; + } + } + } else { + SArray* pRows = pSubmitTbData->aRowP; + SSchemaWrapper* pWrapper = pReader->pSchemaWrapper; + STSchema* pTSchema = tBuildTSchema(pWrapper->pSchema, pWrapper->nCols, pWrapper->version); + + for (int32_t i = 0; i < numOfRows; i++) { + SRow* pRow = taosArrayGetP(pRows, i); + int32_t sourceIdx = 0; + + for (int32_t j = 0; j < colActual; j++) { + SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, j); + while (1) { + SColVal colVal; + tqDebug("start to extract column id:%d, index:%d", pColData->info.colId, sourceIdx); + + tRowGet(pRow, pTSchema, sourceIdx, &colVal); + if (colVal.cid < pColData->info.colId) { + tqDebug("colIndex:%d column id:%d in row, ignore, the required colId:%d, total cols in schema:%d", + sourceIdx, colVal.cid, pColData->info.colId, pTSchema->numOfCols); + sourceIdx++; + continue; + } else if (colVal.cid == pColData->info.colId) { + int32_t code = doSetVal(pColData, i, &colVal); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + sourceIdx++; + break; + } else { + colDataSetNULL(pColData, i); + break; + } } } } - if (buildNew) { - if (taosArrayGetSize(blocks) > 0) { - SSDataBlock* pLastBlock = taosArrayGetLast(blocks); - pLastBlock->info.rows = curRow - lastRow; - lastRow = curRow; - } - SSDataBlock* pBlock = createDataBlock(); - SSchemaWrapper* pSW = taosMemoryCalloc(1, sizeof(SSchemaWrapper)); - if (tqMaskBlock(pSW, pBlock, pSchemaWrapper, assigned) < 0) { - blockDataDestroy(pBlock); - goto FAIL; + taosMemoryFreeClear(pTSchema); + } + + return 0; +} + +int32_t tqRetrieveTaosxBlock(STqReader* pReader, SArray* blocks, SArray* schemas, SSubmitTbData** pSubmitTbDataRet) { + tqDebug("tq reader retrieve data block %p, %d", pReader->msg.msgStr, pReader->nextBlk); + + SSubmitTbData* pSubmitTbData = taosArrayGet(pReader->submit.aSubmitTbData, pReader->nextBlk); + pReader->nextBlk++; + + if (pSubmitTbDataRet) *pSubmitTbDataRet = pSubmitTbData; + int32_t sversion = pSubmitTbData->sver; + int64_t suid = pSubmitTbData->suid; + int64_t uid = pSubmitTbData->uid; + pReader->lastBlkUid = uid; + + tDeleteSchemaWrapper(pReader->pSchemaWrapper); + pReader->pSchemaWrapper = metaGetTableSchema(pReader->pVnodeMeta, uid, sversion, 1); + if (pReader->pSchemaWrapper == NULL) { + tqWarn("vgId:%d, cannot found schema wrapper for table: suid:%" PRId64 ", version %d, possibly dropped table", + pReader->pWalReader->pWal->cfg.vgId, uid, pReader->cachedSchemaVer); + pReader->cachedSchemaSuid = 0; + terrno = TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND; + return -1; + } + + SSchemaWrapper* pSchemaWrapper = pReader->pSchemaWrapper; + int32_t numOfRows = 0; + + if (pSubmitTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + SArray* pCols = pSubmitTbData->aCol; + SColData* pCol = taosArrayGet(pCols, 0); + numOfRows = pCol->nVal; + } else { + SArray* pRows = pSubmitTbData->aRowP; + numOfRows = taosArrayGetSize(pRows); + } + + int32_t curRow = 0; + int32_t lastRow = 0; + char* assigned = taosMemoryCalloc(1, pSchemaWrapper->nCols); + if (assigned == NULL) return -1; + + // convert and scan one block + if (pSubmitTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + SArray* pCols = pSubmitTbData->aCol; + int32_t numOfCols = taosArrayGetSize(pCols); + for (int32_t i = 0; i < numOfRows; i++) { + bool buildNew = false; + + for (int32_t j = 0; j < numOfCols; j++) { + SColData* pCol = taosArrayGet(pCols, j); + SColVal colVal; + tColDataGetValue(pCol, i, &colVal); + if (curRow == 0) { + assigned[j] = !COL_VAL_IS_NONE(&colVal); + buildNew = true; + } else { + bool currentRowAssigned = !COL_VAL_IS_NONE(&colVal); + if (currentRowAssigned != assigned[j]) { + assigned[j] = currentRowAssigned; + buildNew = true; + } + } } - SSDataBlock block = {0}; - assignOneDataBlock(&block, pBlock); - blockDataDestroy(pBlock); - tqDebug("vgId:%d, build new block, col %d", pReader->pWalReader->pWal->cfg.vgId, - (int32_t)taosArrayGetSize(block.pDataBlock)); + if (buildNew) { + if (taosArrayGetSize(blocks) > 0) { + SSDataBlock* pLastBlock = taosArrayGetLast(blocks); + pLastBlock->info.rows = curRow - lastRow; + lastRow = curRow; + } - taosArrayPush(blocks, &block); - taosArrayPush(schemas, &pSW); - } + SSDataBlock block = {0}; + SSchemaWrapper* pSW = taosMemoryCalloc(1, sizeof(SSchemaWrapper)); + if (pSW == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto FAIL; + } - SSDataBlock* pBlock = taosArrayGetLast(blocks); - pBlock->info.id.uid = pReader->msgIter.uid; - pBlock->info.rows = 0; - pBlock->info.version = pReader->pMsg->version; + if (tqMaskBlock(pSW, &block, pSchemaWrapper, assigned) < 0) { + blockDataFreeRes(&block); + tDeleteSchemaWrapper(pSW); + goto FAIL; + } + tqDebug("vgId:%d, build new block, col %d", pReader->pWalReader->pWal->cfg.vgId, + (int32_t)taosArrayGetSize(block.pDataBlock)); + + block.info.id.uid = uid; + block.info.version = pReader->msg.ver; + if (blockDataEnsureCapacity(&block, numOfRows - curRow) < 0) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + blockDataFreeRes(&block); + tDeleteSchemaWrapper(pSW); + goto FAIL; + } + taosArrayPush(blocks, &block); + taosArrayPush(schemas, &pSW); + } - tqDebug("vgId:%d, taosx scan, block num: %d", pReader->pWalReader->pWal->cfg.vgId, - (int32_t)taosArrayGetSize(blocks)); + SSDataBlock* pBlock = taosArrayGetLast(blocks); + + tqDebug("vgId:%d, taosx scan, block num: %d", pReader->pWalReader->pWal->cfg.vgId, + (int32_t)taosArrayGetSize(blocks)); + + int32_t targetIdx = 0; + int32_t sourceIdx = 0; + int32_t colActual = blockDataGetNumOfCols(pBlock); + while (targetIdx < colActual) { + SColData* pCol = taosArrayGet(pCols, sourceIdx); + SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, targetIdx); + SColVal colVal; + + if (pCol->cid < pColData->info.colId) { + sourceIdx++; + } else if (pCol->cid == pColData->info.colId) { + tColDataGetValue(pCol, i, &colVal); + + if (IS_STR_DATA_TYPE(colVal.type)) { + if (colVal.value.pData != NULL) { + char val[65535 + 2]; + memcpy(varDataVal(val), colVal.value.pData, colVal.value.nData); + varDataSetLen(val, colVal.value.nData); + if (colDataSetVal(pColData, curRow - lastRow, val, !COL_VAL_IS_VALUE(&colVal)) < 0) { + goto FAIL; + } + } else { + colDataSetNULL(pColData, curRow - lastRow); + } + } else { + if (colDataSetVal(pColData, curRow - lastRow, (void*)&colVal.value.val, !COL_VAL_IS_VALUE(&colVal)) < 0) { + goto FAIL; + } + } + sourceIdx++; + targetIdx++; + } + } - if (blockDataEnsureCapacity(pBlock, pReader->msgIter.numOfRows - curRow) < 0) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - goto FAIL; + curRow++; } + } else { + SSchemaWrapper* pWrapper = pReader->pSchemaWrapper; + STSchema* pTSchema = tBuildTSchema(pWrapper->pSchema, pWrapper->nCols, pWrapper->version); + SArray* pRows = pSubmitTbData->aRowP; + + for (int32_t i = 0; i < numOfRows; i++) { + SRow* pRow = taosArrayGetP(pRows, i); + bool buildNew = false; + + for (int32_t j = 0; j < pTSchema->numOfCols; j++) { + SColVal colVal; + tRowGet(pRow, pTSchema, j, &colVal); + if (curRow == 0) { + assigned[j] = !COL_VAL_IS_NONE(&colVal); + buildNew = true; + } else { + bool currentRowAssigned = !COL_VAL_IS_NONE(&colVal); + if (currentRowAssigned != assigned[j]) { + assigned[j] = currentRowAssigned; + buildNew = true; + } + } + } - tdSTSRowIterReset(&iter, row); - for (int32_t i = 0; i < taosArrayGetSize(pBlock->pDataBlock); i++) { - SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, i); - SCellVal sVal = {0}; + if (buildNew) { + if (taosArrayGetSize(blocks) > 0) { + SSDataBlock* pLastBlock = taosArrayGetLast(blocks); + pLastBlock->info.rows = curRow - lastRow; + lastRow = curRow; + } - if (!tdSTSRowIterFetch(&iter, pColData->info.colId, pColData->info.type, &sVal)) { - break; - } + SSDataBlock block = {0}; + SSchemaWrapper* pSW = taosMemoryCalloc(1, sizeof(SSchemaWrapper)); + if (pSW == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto FAIL; + } - ASSERT(sVal.valType != TD_VTYPE_NONE); + if (tqMaskBlock(pSW, &block, pSchemaWrapper, assigned) < 0) { + blockDataFreeRes(&block); + tDeleteSchemaWrapper(pSW); + goto FAIL; + } + tqDebug("vgId:%d, build new block, col %d", pReader->pWalReader->pWal->cfg.vgId, + (int32_t)taosArrayGetSize(block.pDataBlock)); + + block.info.id.uid = uid; + block.info.version = pReader->msg.ver; + if (blockDataEnsureCapacity(&block, numOfRows - curRow) < 0) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + blockDataFreeRes(&block); + tDeleteSchemaWrapper(pSW); + goto FAIL; + } + taosArrayPush(blocks, &block); + taosArrayPush(schemas, &pSW); + } - if (colDataAppend(pColData, curRow, sVal.val, sVal.valType == TD_VTYPE_NULL) < 0) { - goto FAIL; + SSDataBlock* pBlock = taosArrayGetLast(blocks); + + tqDebug("vgId:%d, taosx scan, block num: %d", pReader->pWalReader->pWal->cfg.vgId, + (int32_t)taosArrayGetSize(blocks)); + + int32_t targetIdx = 0; + int32_t sourceIdx = 0; + int32_t colActual = blockDataGetNumOfCols(pBlock); + while (targetIdx < colActual) { + SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, targetIdx); + SColVal colVal; + tRowGet(pRow, pTSchema, sourceIdx, &colVal); + + if (colVal.cid < pColData->info.colId) { + sourceIdx++; + } else if (colVal.cid == pColData->info.colId) { + if (IS_STR_DATA_TYPE(colVal.type)) { + if (colVal.value.pData != NULL) { + char val[65535 + 2]; + memcpy(varDataVal(val), colVal.value.pData, colVal.value.nData); + varDataSetLen(val, colVal.value.nData); + if (colDataSetVal(pColData, curRow - lastRow, val, !COL_VAL_IS_VALUE(&colVal)) < 0) { + goto FAIL; + } + } else { + colDataSetNULL(pColData, curRow - lastRow); + } + } else { + if (colDataSetVal(pColData, curRow - lastRow, (void*)&colVal.value.val, !COL_VAL_IS_VALUE(&colVal)) < 0) { + goto FAIL; + } + } + sourceIdx++; + targetIdx++; + } } - tqDebug("vgId:%d, row %d col %d append %d", pReader->pWalReader->pWal->cfg.vgId, curRow, i, - sVal.valType == TD_VTYPE_NULL); + curRow++; } - curRow++; + + taosMemoryFreeClear(pTSchema); } + SSDataBlock* pLastBlock = taosArrayGetLast(blocks); pLastBlock->info.rows = curRow - lastRow; @@ -714,7 +1002,7 @@ int tqReaderSetTbUidList(STqReader* pReader, const SArray* tbUidList) { return 0; } -int tqReaderAddTbUidList(STqReader* pReader, const SArray* tbUidList) { +int tqReaderAddTbUidList(STqReader* pReader, const SArray* pTableUidList) { if (pReader->tbIdHash == NULL) { pReader->tbIdHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_ENTRY_LOCK); if (pReader->tbIdHash == NULL) { @@ -723,8 +1011,9 @@ int tqReaderAddTbUidList(STqReader* pReader, const SArray* tbUidList) { } } - for (int i = 0; i < taosArrayGetSize(tbUidList); i++) { - int64_t* pKey = (int64_t*)taosArrayGet(tbUidList, i); + int32_t numOfTables = taosArrayGetSize(pTableUidList); + for (int i = 0; i < numOfTables; i++) { + int64_t* pKey = (int64_t*)taosArrayGet(pTableUidList, i); taosHashPut(pReader->tbIdHash, pKey, sizeof(int64_t), NULL, 0); } @@ -732,8 +1021,6 @@ int tqReaderAddTbUidList(STqReader* pReader, const SArray* tbUidList) { } int tqReaderRemoveTbUidList(STqReader* pReader, const SArray* tbUidList) { - ASSERT(pReader->tbIdHash != NULL); - for (int32_t i = 0; i < taosArrayGetSize(tbUidList); i++) { int64_t* pKey = (int64_t*)taosArrayGet(tbUidList, i); taosHashRemove(pReader->tbIdHash, pKey, sizeof(int64_t)); @@ -742,24 +1029,35 @@ int tqReaderRemoveTbUidList(STqReader* pReader, const SArray* tbUidList) { return 0; } +// todo update the table list in wal reader int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd) { - void* pIter = NULL; + void* pIter = NULL; + int32_t vgId = TD_VID(pTq->pVnode); + + // update the table list for each consumer handle + taosWLockLatch(&pTq->lock); while (1) { pIter = taosHashIterate(pTq->pHandle, pIter); - if (pIter == NULL) break; - STqHandle* pExec = (STqHandle*)pIter; - if (pExec->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { - int32_t code = qUpdateQualifiedTableId(pExec->execHandle.task, tbUidList, isAdd); - ASSERT(code == 0); - } else if (pExec->execHandle.subType == TOPIC_SUB_TYPE__DB) { + if (pIter == NULL) { + break; + } + + STqHandle* pTqHandle = (STqHandle*)pIter; + if (pTqHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { + int32_t code = qUpdateTableListForStreamScanner(pTqHandle->execHandle.task, tbUidList, isAdd); + if (code != 0) { + tqError("update qualified table error for %s", pTqHandle->subKey); + continue; + } + } else if (pTqHandle->execHandle.subType == TOPIC_SUB_TYPE__DB) { if (!isAdd) { int32_t sz = taosArrayGetSize(tbUidList); for (int32_t i = 0; i < sz; i++) { int64_t tbUid = *(int64_t*)taosArrayGet(tbUidList, i); - taosHashPut(pExec->execHandle.execDb.pFilterOutTbUid, &tbUid, sizeof(int64_t), NULL, 0); + taosHashPut(pTqHandle->execHandle.execDb.pFilterOutTbUid, &tbUid, sizeof(int64_t), NULL, 0); } } - } else if (pExec->execHandle.subType == TOPIC_SUB_TYPE__TABLE) { + } else if (pTqHandle->execHandle.subType == TOPIC_SUB_TYPE__TABLE) { if (isAdd) { SArray* qa = taosArrayInit(4, sizeof(tb_uid_t)); SMetaReader mr = {0}; @@ -769,39 +1067,51 @@ int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd) { int32_t code = metaGetTableEntryByUidCache(&mr, *id); if (code != TSDB_CODE_SUCCESS) { - qError("failed to get table meta, uid:%" PRIu64 " code:%s", *id, tstrerror(terrno)); + tqError("failed to get table meta, uid:%" PRIu64 " code:%s", *id, tstrerror(terrno)); continue; } tDecoderClear(&mr.coder); - - if (mr.me.type != TSDB_CHILD_TABLE || mr.me.ctbEntry.suid != pExec->execHandle.execTb.suid) { + if (mr.me.type != TSDB_CHILD_TABLE || mr.me.ctbEntry.suid != pTqHandle->execHandle.execTb.suid) { tqDebug("table uid %" PRId64 " does not add to tq handle", *id); continue; } + tqDebug("table uid %" PRId64 " add to tq handle", *id); taosArrayPush(qa, id); } + metaReaderClear(&mr); if (taosArrayGetSize(qa) > 0) { - tqReaderAddTbUidList(pExec->execHandle.pExecReader, qa); + tqReaderAddTbUidList(pTqHandle->execHandle.pTqReader, qa); } + taosArrayDestroy(qa); } else { - // TODO handle delete table from stb + tqReaderRemoveTbUidList(pTqHandle->execHandle.pTqReader, tbUidList); } - } else { - ASSERT(0); } } + taosWUnLockLatch(&pTq->lock); + + // update the table list handle for each stream scanner/wal reader + taosWLockLatch(&pTq->pStreamMeta->lock); while (1) { pIter = taosHashIterate(pTq->pStreamMeta->pTasks, pIter); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } + SStreamTask* pTask = *(SStreamTask**)pIter; if (pTask->taskLevel == TASK_LEVEL__SOURCE) { - int32_t code = qUpdateQualifiedTableId(pTask->exec.executor, tbUidList, isAdd); - ASSERT(code == 0); + int32_t code = qUpdateTableListForStreamScanner(pTask->exec.pExecutor, tbUidList, isAdd); + if (code != 0) { + tqError("vgId:%d, s-task:%s update qualified table error for stream task", vgId, pTask->id.idStr); + continue; + } } } + + taosWUnLockLatch(&pTq->pStreamMeta->lock); return 0; } diff --git a/source/dnode/vnode/src/tq/tqRestore.c b/source/dnode/vnode/src/tq/tqRestore.c new file mode 100644 index 0000000000000000000000000000000000000000..7db078140de7c88405ab428da6c44dfb42c5368b --- /dev/null +++ b/source/dnode/vnode/src/tq/tqRestore.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "tq.h" + +static int32_t createStreamRunReq(SStreamMeta* pStreamMeta, bool* pScanIdle); + +// this function should be executed by stream threads. +// extract submit block from WAL, and add them into the input queue for the sources tasks. +int32_t tqStreamTasksScanWal(STQ* pTq) { + int32_t vgId = TD_VID(pTq->pVnode); + SStreamMeta* pMeta = pTq->pStreamMeta; + int64_t st = taosGetTimestampMs(); + + while (1) { + int32_t scan = pMeta->walScanCounter; + tqDebug("vgId:%d continue check if data in wal are available, walScanCounter:%d", vgId, scan); + + // check all restore tasks + bool shouldIdle = true; + createStreamRunReq(pTq->pStreamMeta, &shouldIdle); + + int32_t times = 0; + + if (shouldIdle) { + taosWLockLatch(&pMeta->lock); + + pMeta->walScanCounter -= 1; + times = pMeta->walScanCounter; + + ASSERT(pMeta->walScanCounter >= 0); + + if (pMeta->walScanCounter <= 0) { + taosWUnLockLatch(&pMeta->lock); + break; + } + + taosWUnLockLatch(&pMeta->lock); + tqDebug("vgId:%d scan wal for stream tasks for %d times", vgId, times); + } + } + + int64_t el = (taosGetTimestampMs() - st); + tqDebug("vgId:%d scan wal for stream tasks completed, elapsed time:%"PRId64" ms", vgId, el); + return 0; +} + +int32_t createStreamRunReq(SStreamMeta* pStreamMeta, bool* pScanIdle) { + *pScanIdle = true; + bool noNewDataInWal = true; + int32_t vgId = pStreamMeta->vgId; + + int32_t numOfTasks = taosArrayGetSize(pStreamMeta->pTaskList); + if (numOfTasks == 0) { + return TSDB_CODE_SUCCESS; + } + + SArray* pTaskList = NULL; + taosWLockLatch(&pStreamMeta->lock); + pTaskList = taosArrayDup(pStreamMeta->pTaskList, NULL); + taosWUnLockLatch(&pStreamMeta->lock); + + tqDebug("vgId:%d start to check wal to extract new submit block for %d tasks", vgId, numOfTasks); + + // update the new task number + numOfTasks = taosArrayGetSize(pTaskList); + + for (int32_t i = 0; i < numOfTasks; ++i) { + int32_t* pTaskId = taosArrayGet(pTaskList, i); + SStreamTask* pTask = streamMetaAcquireTask(pStreamMeta, *pTaskId); + if (pTask == NULL) { + continue; + } + + int32_t status = pTask->status.taskStatus; + if (pTask->taskLevel != TASK_LEVEL__SOURCE) { + tqDebug("s-task:%s not source task, no need to start", pTask->id.idStr); + streamMetaReleaseTask(pStreamMeta, pTask); + continue; + } + + if (streamTaskShouldStop(&pTask->status) || status == TASK_STATUS__RECOVER_PREPARE || + status == TASK_STATUS__WAIT_DOWNSTREAM) { + tqDebug("s-task:%s not ready for new submit block from wal, status:%d", pTask->id.idStr, status); + streamMetaReleaseTask(pStreamMeta, pTask); + continue; + } + + if (tInputQueueIsFull(pTask)) { + tqDebug("vgId:%d s-task:%s input queue is full, do nothing", vgId, pTask->id.idStr); + streamMetaReleaseTask(pStreamMeta, pTask); + continue; + } + + *pScanIdle = false; + + // seek the stored version and extract data from WAL + int64_t firstVer = walReaderGetValidFirstVer(pTask->exec.pWalReader); + if (pTask->chkInfo.currentVer < firstVer) { + pTask->chkInfo.currentVer = firstVer; + tqWarn("vgId:%d s-task:%s ver earlier than the first ver of wal range %" PRId64 ", forward to %" PRId64, vgId, + pTask->id.idStr, firstVer, pTask->chkInfo.currentVer); + + // todo need retry if failed + int32_t code = walReaderSeekVer(pTask->exec.pWalReader, pTask->chkInfo.currentVer); + if (code != TSDB_CODE_SUCCESS) { + streamMetaReleaseTask(pStreamMeta, pTask); + continue; + } + + // append the data for the stream + tqDebug("vgId:%d s-task:%s wal reader seek to ver:%" PRId64, vgId, pTask->id.idStr, pTask->chkInfo.currentVer); + } else { + int64_t currentVer = walReaderGetCurrentVer(pTask->exec.pWalReader); + if (currentVer == -1) { + int32_t code = walReaderSeekVer(pTask->exec.pWalReader, pTask->chkInfo.currentVer); + if (code != TSDB_CODE_SUCCESS) { // no data in wal, quit + streamMetaReleaseTask(pStreamMeta, pTask); + continue; + } + + // append the data for the stream + tqDebug("vgId:%d s-task:%s wal reader initial seek to ver:%" PRId64, vgId, pTask->id.idStr, pTask->chkInfo.currentVer); + } + } + + // append the data for the stream +// tqDebug("vgId:%d s-task:%s wal reader seek to ver:%" PRId64, vgId, pTask->id.idStr, pTask->chkInfo.currentVer); + + SStreamQueueItem* pItem = NULL; + int32_t code = extractMsgFromWal(pTask->exec.pWalReader, (void**) &pItem, pTask->id.idStr); + if (code != TSDB_CODE_SUCCESS) { // failed, continue + streamMetaReleaseTask(pStreamMeta, pTask); + continue; + } + + // delete ignore + if (pItem == NULL) { + streamMetaReleaseTask(pStreamMeta, pTask); + continue; + } + + noNewDataInWal = false; + + code = tqAddInputBlockNLaunchTask(pTask, pItem); + if (code == TSDB_CODE_SUCCESS) { + pTask->chkInfo.currentVer = walReaderGetCurrentVer(pTask->exec.pWalReader); + tqDebug("s-task:%s set the ver:%" PRId64 " from WALReader after extract block from WAL", pTask->id.idStr, + pTask->chkInfo.currentVer); + } else { + tqError("s-task:%s append input queue failed, ver:%"PRId64, pTask->id.idStr, pTask->chkInfo.currentVer); + } + + + streamMetaReleaseTask(pStreamMeta, pTask); + } + + // all wal are checked, and no new data available in wal. + if (noNewDataInWal) { + *pScanIdle = true; + } + + taosArrayDestroy(pTaskList); + return 0; +} + diff --git a/source/dnode/vnode/src/tq/tqExec.c b/source/dnode/vnode/src/tq/tqScan.c similarity index 50% rename from source/dnode/vnode/src/tq/tqExec.c rename to source/dnode/vnode/src/tq/tqScan.c index 093186ebbb188841bf0fa012be4dd59f8d0b5a1b..e4b2fa8821689a4bbaf169d00737b49a21dd7e0f 100644 --- a/source/dnode/vnode/src/tq/tqExec.c +++ b/source/dnode/vnode/src/tq/tqScan.c @@ -18,7 +18,9 @@ int32_t tqAddBlockDataToRsp(const SSDataBlock* pBlock, SMqDataRsp* pRsp, int32_t numOfCols, int8_t precision) { int32_t dataStrLen = sizeof(SRetrieveTableRsp) + blockGetEncodeSize(pBlock); void* buf = taosMemoryCalloc(1, dataStrLen); - if (buf == NULL) return -1; + if (buf == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } SRetrieveTableRsp* pRetrieve = (SRetrieveTableRsp*)buf; pRetrieve->useconds = 0; @@ -29,14 +31,14 @@ int32_t tqAddBlockDataToRsp(const SSDataBlock* pBlock, SMqDataRsp* pRsp, int32_t int32_t actualLen = blockEncode(pBlock, pRetrieve->data, numOfCols); actualLen += sizeof(SRetrieveTableRsp); - ASSERT(actualLen <= dataStrLen); taosArrayPush(pRsp->blockDataLen, &actualLen); taosArrayPush(pRsp->blockData, &buf); - return 0; + + return TSDB_CODE_SUCCESS; } -static int32_t tqAddBlockSchemaToRsp(const STqExecHandle* pExec, SMqDataRsp* pRsp) { - SSchemaWrapper* pSW = tCloneSSchemaWrapper(pExec->pExecReader->pSchemaWrapper); +static int32_t tqAddBlockSchemaToRsp(const STqExecHandle* pExec, STaosxRsp* pRsp) { + SSchemaWrapper* pSW = tCloneSSchemaWrapper(pExec->pTqReader->pSchemaWrapper); if (pSW == NULL) { return -1; } @@ -44,16 +46,18 @@ static int32_t tqAddBlockSchemaToRsp(const STqExecHandle* pExec, SMqDataRsp* pRs return 0; } -static int32_t tqAddTbNameToRsp(const STQ* pTq, int64_t uid, SMqDataRsp* pRsp, int32_t n) { +static int32_t tqAddTbNameToRsp(const STQ* pTq, int64_t uid, STaosxRsp* pRsp, int32_t n) { SMetaReader mr = {0}; metaReaderInit(&mr, pTq->pVnode->pMeta, 0); + // TODO add reference to gurantee success if (metaGetTableEntryByUidCache(&mr, uid) < 0) { metaReaderClear(&mr); return -1; } + for (int32_t i = 0; i < n; i++) { - char* tbName = strdup(mr.me.name); + char* tbName = taosStrdup(mr.me.name); taosArrayPush(pRsp->blockTbName, &tbName); } metaReaderClear(&mr); @@ -61,65 +65,53 @@ static int32_t tqAddTbNameToRsp(const STQ* pTq, int64_t uid, SMqDataRsp* pRsp, i } int32_t tqScanData(STQ* pTq, const STqHandle* pHandle, SMqDataRsp* pRsp, STqOffsetVal* pOffset) { - const STqExecHandle* pExec = &pHandle->execHandle; - ASSERT(pExec->subType == TOPIC_SUB_TYPE__COLUMN); + const int32_t MAX_ROWS_TO_RETURN = 4096; - qTaskInfo_t task = pExec->task; + int32_t vgId = TD_VID(pTq->pVnode); + int32_t code = 0; + int32_t totalRows = 0; + + const STqExecHandle* pExec = &pHandle->execHandle; + qTaskInfo_t task = pExec->task; if (qStreamPrepareScan(task, pOffset, pHandle->execHandle.subType) < 0) { - tqDebug("prepare scan failed, return"); - if (pOffset->type == TMQ_OFFSET__LOG) { - pRsp->rspOffset = *pOffset; - return 0; - } else { - tqOffsetResetToLog(pOffset, pHandle->snapshotVer); - if (qStreamPrepareScan(task, pOffset, pHandle->execHandle.subType) < 0) { - tqDebug("prepare scan failed, return"); - pRsp->rspOffset = *pOffset; - return 0; - } - } + return -1; } - int32_t rowCnt = 0; while (1) { SSDataBlock* pDataBlock = NULL; uint64_t ts = 0; - tqDebug("vgId:%d, tmq task start to execute", pTq->pVnode->config.vgId); - if (qExecTask(task, &pDataBlock, &ts) < 0) { - ASSERT(0); + qStreamSetOpen(task); + + tqDebug("consumer:0x%" PRIx64 " vgId:%d, tmq one task start execute", pHandle->consumerId, vgId); + if (qExecTask(task, &pDataBlock, &ts) != TSDB_CODE_SUCCESS) { + tqError("consumer:0x%" PRIx64 " vgId:%d, task exec error since %s", pHandle->consumerId, vgId, terrstr()); + return -1; } - tqDebug("vgId:%d, tmq task executed, get %p", pTq->pVnode->config.vgId, pDataBlock); + tqDebug("consumer:0x%" PRIx64 " vgId:%d tmq one task end executed, pDataBlock:%p", pHandle->consumerId, vgId, + pDataBlock); + // current scan should be stopped asap, since the rebalance occurs. if (pDataBlock == NULL) { break; } - tqAddBlockDataToRsp(pDataBlock, pRsp, pExec->numOfCols, pTq->pVnode->config.tsdbCfg.precision); - pRsp->blockNum++; - - if (pOffset->type == TMQ_OFFSET__SNAPSHOT_DATA) { - rowCnt += pDataBlock->info.rows; - if (rowCnt >= 4096) break; + code = tqAddBlockDataToRsp(pDataBlock, pRsp, pExec->numOfCols, pTq->pVnode->config.tsdbCfg.precision); + if (code != TSDB_CODE_SUCCESS) { + tqError("vgId:%d, failed to add block to rsp msg", vgId); + return code; } - } - if (qStreamExtractOffset(task, &pRsp->rspOffset) < 0) { - ASSERT(0); - return -1; - } - ASSERT(pRsp->rspOffset.type != 0); - - if (pRsp->withTbName) { - if (pRsp->rspOffset.type == TMQ_OFFSET__LOG) { - int64_t uid = pExec->pExecReader->msgIter.uid; - tqAddTbNameToRsp(pTq, uid, pRsp, 1); - } else { - pRsp->withTbName = false; + pRsp->blockNum++; + totalRows += pDataBlock->info.rows; + if (totalRows >= MAX_ROWS_TO_RETURN) { + break; } } - ASSERT(pRsp->withSchema == false); + tqDebug("consumer:0x%" PRIx64 " vgId:%d tmq task executed finished, total blocks:%d, totalRows:%d", + pHandle->consumerId, vgId, pRsp->blockNum, totalRows); + qStreamExtractOffset(task, &pRsp->rspOffset); return 0; } @@ -128,18 +120,7 @@ int32_t tqScanTaosx(STQ* pTq, const STqHandle* pHandle, STaosxRsp* pRsp, SMqMeta qTaskInfo_t task = pExec->task; if (qStreamPrepareScan(task, pOffset, pHandle->execHandle.subType) < 0) { - tqDebug("prepare scan failed, return"); - if (pOffset->type == TMQ_OFFSET__LOG) { - pRsp->rspOffset = *pOffset; - return 0; - } else { - tqOffsetResetToLog(pOffset, pHandle->snapshotVer); - if (qStreamPrepareScan(task, pOffset, pHandle->execHandle.subType) < 0) { - tqDebug("prepare scan failed, return"); - pRsp->rspOffset = *pOffset; - return 0; - } - } + return -1; } int32_t rowCnt = 0; @@ -148,26 +129,27 @@ int32_t tqScanTaosx(STQ* pTq, const STqHandle* pHandle, STaosxRsp* pRsp, SMqMeta uint64_t ts = 0; tqDebug("tmqsnap task start to execute"); if (qExecTask(task, &pDataBlock, &ts) < 0) { - ASSERT(0); + tqError("vgId:%d, task exec error since %s", pTq->pVnode->config.vgId, terrstr()); + return -1; } + tqDebug("tmqsnap task execute end, get %p", pDataBlock); - if (pDataBlock != NULL) { + if (pDataBlock != NULL && pDataBlock->info.rows > 0) { if (pRsp->withTbName) { - int64_t uid = 0; if (pOffset->type == TMQ_OFFSET__LOG) { - uid = pExec->pExecReader->msgIter.uid; - if (tqAddTbNameToRsp(pTq, uid, (SMqDataRsp*)pRsp, 1) < 0) { + int64_t uid = pExec->pTqReader->lastBlkUid; + if (tqAddTbNameToRsp(pTq, uid, pRsp, 1) < 0) { continue; } } else { - char* tbName = strdup(qExtractTbnameFromTask(task)); + char* tbName = taosStrdup(qExtractTbnameFromTask(task)); taosArrayPush(pRsp->blockTbName, &tbName); } } if (pRsp->withSchema) { if (pOffset->type == TMQ_OFFSET__LOG) { - tqAddBlockSchemaToRsp(pExec, (SMqDataRsp*)pRsp); + tqAddBlockSchemaToRsp(pExec, pRsp); } else { SSchemaWrapper* pSW = tCloneSSchemaWrapper(qExtractSchemaFromTask(task)); taosArrayPush(pRsp->blockSchema, &pSW); @@ -185,94 +167,95 @@ int32_t tqScanTaosx(STQ* pTq, const STqHandle* pHandle, STaosxRsp* pRsp, SMqMeta } } - if (pDataBlock == NULL && pOffset->type == TMQ_OFFSET__SNAPSHOT_DATA) { - if (qStreamExtractPrepareUid(task) != 0) { + // get meta + SMqMetaRsp* tmp = qStreamExtractMetaMsg(task); + if (tmp->metaRspLen > 0) { + qStreamExtractOffset(task, &tmp->rspOffset); + *pMetaRsp = *tmp; + + tqDebug("tmqsnap task get meta"); + break; + } + + if (pDataBlock == NULL) { + qStreamExtractOffset(task, pOffset); + if (pOffset->type == TMQ_OFFSET__SNAPSHOT_DATA) { continue; } tqDebug("tmqsnap vgId: %d, tsdb consume over, switch to wal, ver %" PRId64, TD_VID(pTq->pVnode), pHandle->snapshotVer + 1); + qStreamExtractOffset(task, &pRsp->rspOffset); break; } if (pRsp->blockNum > 0) { tqDebug("tmqsnap task exec exited, get data"); + qStreamExtractOffset(task, &pRsp->rspOffset); break; } - - SMqMetaRsp* tmp = qStreamExtractMetaMsg(task); - if (tmp->rspOffset.type == TMQ_OFFSET__SNAPSHOT_DATA) { - tqOffsetResetToData(pOffset, tmp->rspOffset.uid, tmp->rspOffset.ts); - qStreamPrepareScan(task, pOffset, pHandle->execHandle.subType); - tmp->rspOffset.type = TMQ_OFFSET__SNAPSHOT_META; - tqDebug("tmqsnap task exec change to get data"); - continue; - } - - *pMetaRsp = *tmp; - tqDebug("tmqsnap task exec exited, get meta"); - - tqDebug("task exec exited"); - break; - } - - if (qStreamExtractOffset(task, &pRsp->rspOffset) < 0) { - ASSERT(0); } - ASSERT(pRsp->rspOffset.type != 0); return 0; } -int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SSubmitReq* pReq, STaosxRsp* pRsp) { +int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxRsp* pRsp, int32_t* totalRows) { STqExecHandle* pExec = &pHandle->execHandle; - ASSERT(pExec->subType != TOPIC_SUB_TYPE__COLUMN); - - SArray* pBlocks = taosArrayInit(0, sizeof(SSDataBlock)); - SArray* pSchemas = taosArrayInit(0, sizeof(void*)); + SArray* pBlocks = taosArrayInit(0, sizeof(SSDataBlock)); + SArray* pSchemas = taosArrayInit(0, sizeof(void*)); if (pExec->subType == TOPIC_SUB_TYPE__TABLE) { - STqReader* pReader = pExec->pExecReader; - tqReaderSetDataMsg(pReader, pReq, 0); - while (tqNextDataBlock(pReader)) { - /*SSDataBlock block = {0};*/ - /*if (tqRetrieveDataBlock(&block, pReader) < 0) {*/ - /*if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) continue;*/ - /*}*/ - + STqReader* pReader = pExec->pTqReader; + tqReaderSetSubmitMsg(pReader, submit.msgStr, submit.msgLen, submit.ver); + while (tqNextBlockImpl(pReader)) { taosArrayClear(pBlocks); taosArrayClear(pSchemas); - if (tqRetrieveTaosxBlock(pReader, pBlocks, pSchemas) < 0) { + SSubmitTbData* pSubmitTbDataRet = NULL; + if (tqRetrieveTaosxBlock(pReader, pBlocks, pSchemas, &pSubmitTbDataRet) < 0) { if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) continue; } if (pRsp->withTbName) { - int64_t uid = pExec->pExecReader->msgIter.uid; - if (tqAddTbNameToRsp(pTq, uid, (SMqDataRsp*)pRsp, taosArrayGetSize(pBlocks)) < 0) { + int64_t uid = pExec->pTqReader->lastBlkUid; + if (tqAddTbNameToRsp(pTq, uid, pRsp, taosArrayGetSize(pBlocks)) < 0) { taosArrayDestroyEx(pBlocks, (FDelete)blockDataFreeRes); - taosArrayDestroyP(pSchemas, (FDelete)tDeleteSSchemaWrapper); + taosArrayDestroyP(pSchemas, (FDelete)tDeleteSchemaWrapper); pBlocks = taosArrayInit(0, sizeof(SSDataBlock)); pSchemas = taosArrayInit(0, sizeof(void*)); continue; } } - if (pHandle->fetchMeta) { - SSubmitBlk* pBlk = pReader->pBlock; - int32_t schemaLen = htonl(pBlk->schemaLen); - if (schemaLen > 0) { - if (pRsp->createTableNum == 0) { - pRsp->createTableLen = taosArrayInit(0, sizeof(int32_t)); - pRsp->createTableReq = taosArrayInit(0, sizeof(void*)); - } - void* createReq = taosMemoryCalloc(1, schemaLen); - memcpy(createReq, pBlk->data, schemaLen); - taosArrayPush(pRsp->createTableLen, &schemaLen); - taosArrayPush(pRsp->createTableReq, &createReq); - pRsp->createTableNum++; + if (pHandle->fetchMeta && pSubmitTbDataRet->pCreateTbReq != NULL) { + if (pRsp->createTableNum == 0) { + pRsp->createTableLen = taosArrayInit(0, sizeof(int32_t)); + pRsp->createTableReq = taosArrayInit(0, sizeof(void*)); + } + + int32_t code = TSDB_CODE_SUCCESS; + uint32_t len = 0; + tEncodeSize(tEncodeSVCreateTbReq, pSubmitTbDataRet->pCreateTbReq, len, code); + if (TSDB_CODE_SUCCESS != code) { + continue; + } + void* createReq = taosMemoryCalloc(1, len); + SEncoder encoder = {0}; + tEncoderInit(&encoder, createReq, len); + code = tEncodeSVCreateTbReq(&encoder, pSubmitTbDataRet->pCreateTbReq); + if (code < 0) { + tEncoderClear(&encoder); + taosMemoryFree(createReq); + continue; } + + taosArrayPush(pRsp->createTableLen, &len); + taosArrayPush(pRsp->createTableReq, &createReq); + pRsp->createTableNum++; + + tEncoderClear(&encoder); } for (int32_t i = 0; i < taosArrayGetSize(pBlocks); i++) { SSDataBlock* pBlock = taosArrayGet(pBlocks, i); tqAddBlockDataToRsp(pBlock, (SMqDataRsp*)pRsp, taosArrayGetSize(pBlock->pDataBlock), pTq->pVnode->config.tsdbCfg.precision); + totalRows += pBlock->info.rows; blockDataFreeRes(pBlock); SSchemaWrapper* pSW = taosArrayGetP(pSchemas, i); taosArrayPush(pRsp->blockSchema, &pSW); @@ -280,52 +263,58 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SSubmitReq* pReq, STaosxRsp } } } else if (pExec->subType == TOPIC_SUB_TYPE__DB) { - STqReader* pReader = pExec->pExecReader; - tqReaderSetDataMsg(pReader, pReq, 0); + STqReader* pReader = pExec->pTqReader; + tqReaderSetSubmitMsg(pReader, submit.msgStr, submit.msgLen, submit.ver); while (tqNextDataBlockFilterOut(pReader, pExec->execDb.pFilterOutTbUid)) { - /*SSDataBlock block = {0};*/ - /*if (tqRetrieveDataBlock(&block, pReader) < 0) {*/ - /*if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) continue;*/ - /*}*/ taosArrayClear(pBlocks); taosArrayClear(pSchemas); - if (tqRetrieveTaosxBlock(pReader, pBlocks, pSchemas) < 0) { + SSubmitTbData* pSubmitTbDataRet = NULL; + if (tqRetrieveTaosxBlock(pReader, pBlocks, pSchemas, &pSubmitTbDataRet) < 0) { if (terrno == TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND) continue; } if (pRsp->withTbName) { - int64_t uid = pExec->pExecReader->msgIter.uid; - if (tqAddTbNameToRsp(pTq, uid, (SMqDataRsp*)pRsp, taosArrayGetSize(pBlocks)) < 0) { + int64_t uid = pExec->pTqReader->lastBlkUid; + if (tqAddTbNameToRsp(pTq, uid, pRsp, taosArrayGetSize(pBlocks)) < 0) { taosArrayDestroyEx(pBlocks, (FDelete)blockDataFreeRes); - taosArrayDestroyP(pSchemas, (FDelete)tDeleteSSchemaWrapper); + taosArrayDestroyP(pSchemas, (FDelete)tDeleteSchemaWrapper); pBlocks = taosArrayInit(0, sizeof(SSDataBlock)); pSchemas = taosArrayInit(0, sizeof(void*)); continue; } } - if (pHandle->fetchMeta) { - SSubmitBlk* pBlk = pReader->pBlock; - int32_t schemaLen = htonl(pBlk->schemaLen); - if (schemaLen > 0) { - if (pRsp->createTableNum == 0) { - pRsp->createTableLen = taosArrayInit(0, sizeof(int32_t)); - pRsp->createTableReq = taosArrayInit(0, sizeof(void*)); - } - void* createReq = taosMemoryCalloc(1, schemaLen); - memcpy(createReq, pBlk->data, schemaLen); - taosArrayPush(pRsp->createTableLen, &schemaLen); - taosArrayPush(pRsp->createTableReq, &createReq); - pRsp->createTableNum++; + if (pHandle->fetchMeta && pSubmitTbDataRet->pCreateTbReq != NULL) { + if (pRsp->createTableNum == 0) { + pRsp->createTableLen = taosArrayInit(0, sizeof(int32_t)); + pRsp->createTableReq = taosArrayInit(0, sizeof(void*)); + } + + int32_t code = TSDB_CODE_SUCCESS; + uint32_t len = 0; + tEncodeSize(tEncodeSVCreateTbReq, pSubmitTbDataRet->pCreateTbReq, len, code); + if (TSDB_CODE_SUCCESS != code) { + continue; + } + void* createReq = taosMemoryCalloc(1, len); + SEncoder encoder = {0}; + tEncoderInit(&encoder, createReq, len); + code = tEncodeSVCreateTbReq(&encoder, pSubmitTbDataRet->pCreateTbReq); + if (code < 0) { + tEncoderClear(&encoder); + taosMemoryFree(createReq); + continue; } + + taosArrayPush(pRsp->createTableLen, &len); + taosArrayPush(pRsp->createTableReq, &createReq); + pRsp->createTableNum++; + + tEncoderClear(&encoder); } - /*tqAddBlockDataToRsp(&block, (SMqDataRsp*)pRsp, taosArrayGetSize(block.pDataBlock),*/ - /*pTq->pVnode->config.tsdbCfg.precision);*/ - /*blockDataFreeRes(&block);*/ - /*tqAddBlockSchemaToRsp(pExec, (SMqDataRsp*)pRsp);*/ - /*pRsp->blockNum++;*/ for (int32_t i = 0; i < taosArrayGetSize(pBlocks); i++) { SSDataBlock* pBlock = taosArrayGet(pBlocks, i); tqAddBlockDataToRsp(pBlock, (SMqDataRsp*)pRsp, taosArrayGetSize(pBlock->pDataBlock), pTq->pVnode->config.tsdbCfg.precision); + *totalRows += pBlock->info.rows; blockDataFreeRes(pBlock); SSchemaWrapper* pSW = taosArrayGetP(pSchemas, i); taosArrayPush(pRsp->blockSchema, &pSW); @@ -333,13 +322,7 @@ int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SSubmitReq* pReq, STaosxRsp } } } - taosArrayDestroy(pBlocks); taosArrayDestroy(pSchemas); - - if (pRsp->blockNum == 0) { - return -1; - } - return 0; } diff --git a/source/dnode/vnode/src/tq/tqSink.c b/source/dnode/vnode/src/tq/tqSink.c index 6d474d5aa1360e9d7425b8b6926439ee1aafd160..33d1e08c9cc33b4de68e45c0a19e9c9051e5a75e 100644 --- a/source/dnode/vnode/src/tq/tqSink.c +++ b/source/dnode/vnode/src/tq/tqSink.c @@ -19,7 +19,6 @@ int32_t tqBuildDeleteReq(SVnode* pVnode, const char* stbFullName, const SSDataBlock* pDataBlock, SBatchDeleteReq* deleteReq) { - ASSERT(pDataBlock->info.type == STREAM_DELETE_RESULT); int32_t totRow = pDataBlock->info.rows; SColumnInfoData* pStartTsCol = taosArrayGet(pDataBlock->pDataBlock, START_TS_COLUMN_INDEX); SColumnInfoData* pEndTsCol = taosArrayGet(pDataBlock->pDataBlock, END_TS_COLUMN_INDEX); @@ -72,234 +71,6 @@ int32_t tqBuildDeleteReq(SVnode* pVnode, const char* stbFullName, const SSDataBl return 0; } -SSubmitReq* tqBlockToSubmit(SVnode* pVnode, const SArray* pBlocks, const STSchema* pTSchema, - SSchemaWrapper* pTagSchemaWrapper, bool createTb, int64_t suid, const char* stbFullName, - SBatchDeleteReq* pDeleteReq) { - SSubmitReq* ret = NULL; - SArray* schemaReqs = NULL; - SArray* schemaReqSz = NULL; - SArray* tagArray = taosArrayInit(1, sizeof(STagVal)); - if (!tagArray) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - int32_t sz = taosArrayGetSize(pBlocks); - - if (createTb) { - schemaReqs = taosArrayInit(sz, sizeof(void*)); - schemaReqSz = taosArrayInit(sz, sizeof(int32_t)); - for (int32_t i = 0; i < sz; i++) { - SSDataBlock* pDataBlock = taosArrayGet(pBlocks, i); - if (pDataBlock->info.type == STREAM_DELETE_RESULT) { - int32_t padding1 = 0; - void* padding2 = NULL; - taosArrayPush(schemaReqSz, &padding1); - taosArrayPush(schemaReqs, &padding2); - continue; - } - - // STag* pTag = NULL; - // taosArrayClear(tagArray); - // SArray *tagName = taosArrayInit(1, TSDB_COL_NAME_LEN); - // for(int j = 0; j < pTagSchemaWrapper->nCols; j++){ - // STagVal tagVal = { - // .cid = pTagSchemaWrapper->pSchema[j].colId, - // .type = pTagSchemaWrapper->pSchema[j].type, - // .i64 = (int64_t)pDataBlock->info.id.groupId, - // }; - // taosArrayPush(tagArray, &tagVal); - // taosArrayPush(tagName, pTagSchemaWrapper->pSchema[j].name); - // } - // - // tTagNew(tagArray, 1, false, &pTag); - // if (pTag == NULL) { - // terrno = TSDB_CODE_OUT_OF_MEMORY; - // taosArrayDestroy(tagArray); - // taosArrayDestroy(tagName); - // return NULL; - // } - - SVCreateTbReq createTbReq = {0}; - - // set const - createTbReq.flags = 0; - createTbReq.type = TSDB_CHILD_TABLE; - createTbReq.ctb.suid = suid; - - // set super table name - SName name = {0}; - tNameFromString(&name, stbFullName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); - createTbReq.ctb.stbName = strdup((char*)tNameGetTableName(&name)); // strdup(stbFullName); - - // set tag content - taosArrayClear(tagArray); - STagVal tagVal = { - .cid = taosArrayGetSize(pDataBlock->pDataBlock) + 1, - .type = TSDB_DATA_TYPE_UBIGINT, - .i64 = (int64_t)pDataBlock->info.id.groupId, - }; - taosArrayPush(tagArray, &tagVal); - createTbReq.ctb.tagNum = taosArrayGetSize(tagArray); - - STag* pTag = NULL; - tTagNew(tagArray, 1, false, &pTag); - if (pTag == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - taosArrayDestroy(tagArray); - taosArrayDestroyP(schemaReqs, taosMemoryFree); - taosArrayDestroy(schemaReqSz); - return NULL; - } - createTbReq.ctb.pTag = (uint8_t*)pTag; - - // set tag name - SArray* tagName = taosArrayInit(1, TSDB_COL_NAME_LEN); - char tagNameStr[TSDB_COL_NAME_LEN] = {0}; - strcpy(tagNameStr, "group_id"); - taosArrayPush(tagName, tagNameStr); - createTbReq.ctb.tagName = tagName; - - // set table name - if (pDataBlock->info.parTbName[0]) { - createTbReq.name = strdup(pDataBlock->info.parTbName); - } else { - createTbReq.name = buildCtbNameByGroupId(stbFullName, pDataBlock->info.id.groupId); - } - - // save schema len - int32_t code; - int32_t schemaLen; - tEncodeSize(tEncodeSVCreateTbReq, &createTbReq, schemaLen, code); - if (code < 0) { - tdDestroySVCreateTbReq(&createTbReq); - taosArrayDestroy(tagArray); - taosArrayDestroyP(schemaReqs, taosMemoryFree); - taosArrayDestroy(schemaReqSz); - return NULL; - } - taosArrayPush(schemaReqSz, &schemaLen); - - // save schema str - void* schemaStr = taosMemoryMalloc(schemaLen); - if (schemaStr == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - tdDestroySVCreateTbReq(&createTbReq); - taosArrayDestroy(tagArray); - taosArrayDestroyP(schemaReqs, taosMemoryFree); - taosArrayDestroy(schemaReqSz); - return NULL; - } - taosArrayPush(schemaReqs, &schemaStr); - - SEncoder encoder = {0}; - tEncoderInit(&encoder, schemaStr, schemaLen); - code = tEncodeSVCreateTbReq(&encoder, &createTbReq); - if (code < 0) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - tdDestroySVCreateTbReq(&createTbReq); - taosArrayDestroy(tagArray); - taosArrayDestroyP(schemaReqs, taosMemoryFree); - taosArrayDestroy(schemaReqSz); - tEncoderClear(&encoder); - return NULL; - } - tEncoderClear(&encoder); - tdDestroySVCreateTbReq(&createTbReq); - } - } - taosArrayDestroy(tagArray); - - // cal size - int32_t cap = sizeof(SSubmitReq); - for (int32_t i = 0; i < sz; i++) { - SSDataBlock* pDataBlock = taosArrayGet(pBlocks, i); - if (pDataBlock->info.type == STREAM_DELETE_RESULT) { - continue; - } - int32_t rows = pDataBlock->info.rows; - /*int32_t rowSize = pDataBlock->info.rowSize;*/ - int32_t maxLen = TD_ROW_MAX_BYTES_FROM_SCHEMA(pTSchema); - - int32_t schemaLen = 0; - if (createTb) { - schemaLen = *(int32_t*)taosArrayGet(schemaReqSz, i); - } - cap += sizeof(SSubmitBlk) + schemaLen + rows * maxLen; - } - - // assign data - ret = rpcMallocCont(cap); - ret->header.vgId = pVnode->config.vgId; - ret->length = sizeof(SSubmitReq); - ret->numOfBlocks = htonl(sz); - - SSubmitBlk* blkHead = POINTER_SHIFT(ret, sizeof(SSubmitReq)); - for (int32_t i = 0; i < sz; i++) { - SSDataBlock* pDataBlock = taosArrayGet(pBlocks, i); - if (pDataBlock->info.type == STREAM_DELETE_RESULT) { - pDeleteReq->suid = suid; - pDeleteReq->deleteReqs = taosArrayInit(0, sizeof(SSingleDeleteReq)); - tqBuildDeleteReq(pVnode, stbFullName, pDataBlock, pDeleteReq); - continue; - } - - blkHead->numOfRows = htonl(pDataBlock->info.rows); - blkHead->sversion = htonl(pTSchema->version); - blkHead->suid = htobe64(suid); - // uid is assigned by vnode - blkHead->uid = 0; - - int32_t rows = pDataBlock->info.rows; - - tqDebug("tq sink, convert block1 %d, rows: %d", i, rows); - - int32_t dataLen = 0; - int32_t schemaLen = 0; - void* blkSchema = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk)); - if (createTb) { - schemaLen = *(int32_t*)taosArrayGet(schemaReqSz, i); - void* schemaStr = taosArrayGetP(schemaReqs, i); - memcpy(blkSchema, schemaStr, schemaLen); - } - blkHead->schemaLen = htonl(schemaLen); - - STSRow* rowData = POINTER_SHIFT(blkSchema, schemaLen); - for (int32_t j = 0; j < rows; j++) { - SRowBuilder rb = {0}; - tdSRowInit(&rb, pTSchema->version); - tdSRowSetTpInfo(&rb, pTSchema->numOfCols, pTSchema->flen); - tdSRowResetBuf(&rb, rowData); - - for (int32_t k = 0; k < pTSchema->numOfCols; k++) { - const STColumn* pColumn = &pTSchema->columns[k]; - SColumnInfoData* pColData = taosArrayGet(pDataBlock->pDataBlock, k); - if (colDataIsNull_s(pColData, j)) { - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NULL, NULL, false, pColumn->offset, k); - } else { - void* data = colDataGetData(pColData, j); - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, data, true, pColumn->offset, k); - } - } - tdSRowEnd(&rb); - int32_t rowLen = TD_ROW_LEN(rowData); - rowData = POINTER_SHIFT(rowData, rowLen); - dataLen += rowLen; - } - blkHead->dataLen = htonl(dataLen); - - ret->length += sizeof(SSubmitBlk) + schemaLen + dataLen; - blkHead = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk) + schemaLen + dataLen); - } - - ret->length = htonl(ret->length); - - taosArrayDestroyP(schemaReqs, taosMemoryFree); - taosArrayDestroy(schemaReqSz); - - return ret; -} - void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* data) { const SArray* pBlocks = (const SArray*)data; SVnode* pVnode = (SVnode*)vnode; @@ -316,7 +87,7 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d return; } - tqDebug("vgId:%d, task %d write into table, block num: %d", TD_VID(pVnode), pTask->taskId, blockSz); + tqDebug("vgId:%d, s-task:%s write into table, block num: %d", TD_VID(pVnode), pTask->id.idStr, blockSz); for (int32_t i = 0; i < blockSz; i++) { bool createTb = true; SSDataBlock* pDataBlock = taosArrayGet(pBlocks, i); @@ -334,8 +105,8 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d int32_t code; tEncodeSize(tEncodeSBatchDeleteReq, &deleteReq, len, code); if (code < 0) { - // - ASSERT(0); + terrno = TSDB_CODE_OUT_OF_MEMORY; + return; } SEncoder encoder; void* serializedDeleteReq = rpcMallocCont(len + sizeof(SMsgHead)); @@ -359,7 +130,7 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d char* ctbName = NULL; // set child table name if (pDataBlock->info.parTbName[0]) { - ctbName = strdup(pDataBlock->info.parTbName); + ctbName = taosStrdup(pDataBlock->info.parTbName); } else { ctbName = buildCtbNameByGroupId(stbFullName, pDataBlock->info.id.groupId); } @@ -384,7 +155,7 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d // set super table name SName name = {0}; tNameFromString(&name, stbFullName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); - createTbReq.ctb.stbName = strdup((char*)tNameGetTableName(&name)); // strdup(stbFullName); + createTbReq.ctb.stbName = taosStrdup((char*)tNameGetTableName(&name)); // taosStrdup(stbFullName); createTbReq.name = ctbName; ctbName = NULL; @@ -493,7 +264,7 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d blkHead->uid = 0; blkHead->schemaLen = 0; - tqDebug("tq sink, convert block2 %d, rows: %d", i, rows); + tqDebug("tq sink pipe1, convert block2 %d, rows: %d", i, rows); int32_t dataLen = 0; void* blkSchema = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk)); @@ -522,7 +293,7 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d } else { void* colData = colDataGetData(pColData, j); if (k == 0) { - tqDebug("tq sink, row %d ts %" PRId64, j, *(int64_t*)colData); + tqDebug("tq sink pipe1, row %d ts %" PRId64, j, *(int64_t*)colData); } tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, colData, true, pColumn->offset, k); } @@ -551,60 +322,411 @@ void tqSinkToTablePipeline(SStreamTask* pTask, void* vnode, int64_t ver, void* d taosArrayDestroy(tagArray); } -#if 0 -void tqSinkToTableMerge(SStreamTask* pTask, void* vnode, int64_t ver, void* data) { - const SArray* pRes = (const SArray*)data; - SVnode* pVnode = (SVnode*)vnode; - SBatchDeleteReq deleteReq = {0}; +static int32_t encodeCreateChildTableForRPC(SVCreateTbBatchReq* pReqs, int32_t vgId, void** pBuf, int32_t* contLen) { + int32_t ret = 0; - tqDebug("vgId:%d, task %d write into table, block num: %d", TD_VID(pVnode), pTask->taskId, (int32_t)pRes->size); - - ASSERT(pTask->tbSink.pTSchema); - deleteReq.deleteReqs = taosArrayInit(0, sizeof(SSingleDeleteReq)); - SSubmitReq* submitReq = tqBlockToSubmit(pVnode, pRes, pTask->tbSink.pTSchema, pTask->tbSink.pSchemaWrapper, true, - pTask->tbSink.stbUid, pTask->tbSink.stbFullName, &deleteReq); + tEncodeSize(tEncodeSVCreateTbBatchReq, pReqs, *contLen, ret); + if (ret < 0) { + ret = -1; + goto end; + } + *contLen += sizeof(SMsgHead); + *pBuf = rpcMallocCont(*contLen); + if (NULL == *pBuf) { + ret = -1; + goto end; + } + ((SMsgHead*)(*pBuf))->vgId = vgId; + ((SMsgHead*)(*pBuf))->contLen = htonl(*contLen); + SEncoder coder = {0}; + tEncoderInit(&coder, POINTER_SHIFT(*pBuf, sizeof(SMsgHead)), (*contLen) - sizeof(SMsgHead)); + if (tEncodeSVCreateTbBatchReq(&coder, pReqs) < 0) { + rpcFreeCont(*pBuf); + *pBuf = NULL; + *contLen = 0; + tEncoderClear(&coder); + ret = -1; + goto end; + } + tEncoderClear(&coder); - tqDebug("vgId:%d, task %d convert blocks over, put into write-queue", TD_VID(pVnode), pTask->taskId); +end: + return ret; +} - if (taosArrayGetSize(deleteReq.deleteReqs) != 0) { - int32_t code; - int32_t len; - tEncodeSize(tEncodeSBatchDeleteReq, &deleteReq, len, code); - if (code < 0) { - // - ASSERT(0); - } - SEncoder encoder; - void* serializedDeleteReq = rpcMallocCont(len + sizeof(SMsgHead)); - void* abuf = POINTER_SHIFT(serializedDeleteReq, sizeof(SMsgHead)); - tEncoderInit(&encoder, abuf, len); - tEncodeSBatchDeleteReq(&encoder, &deleteReq); - tEncoderClear(&encoder); - - ((SMsgHead*)serializedDeleteReq)->vgId = pVnode->config.vgId; - - SRpcMsg msg = { - .msgType = TDMT_VND_BATCH_DEL, - .pCont = serializedDeleteReq, - .contLen = len + sizeof(SMsgHead), - }; - if (tmsgPutToQueue(&pVnode->msgCb, WRITE_QUEUE, &msg) != 0) { - rpcFreeCont(serializedDeleteReq); - tqDebug("failed to put into write-queue since %s", terrstr()); - } - } - taosArrayDestroy(deleteReq.deleteReqs); +int32_t tqPutReqToQueue(SVnode* pVnode, SVCreateTbBatchReq* pReqs) { + void* buf = NULL; + int32_t tlen = 0; + encodeCreateChildTableForRPC(pReqs, TD_VID(pVnode), &buf, &tlen); - /*tPrintFixedSchemaSubmitReq(pReq, pTask->tbSink.pTSchema);*/ - // build write msg SRpcMsg msg = { - .msgType = TDMT_VND_SUBMIT, - .pCont = submitReq, - .contLen = ntohl(submitReq->length), + .msgType = TDMT_VND_CREATE_TABLE, + .pCont = buf, + .contLen = tlen, }; if (tmsgPutToQueue(&pVnode->msgCb, WRITE_QUEUE, &msg) != 0) { - tqDebug("failed to put into write-queue since %s", terrstr()); + tqError("failed to put into write-queue since %s", terrstr()); } + + return TSDB_CODE_SUCCESS; +} + +void tqSinkToTablePipeline2(SStreamTask* pTask, void* vnode, int64_t ver, void* data) { + const SArray* pBlocks = (const SArray*)data; + SVnode* pVnode = (SVnode*)vnode; + int64_t suid = pTask->tbSink.stbUid; + char* stbFullName = pTask->tbSink.stbFullName; + STSchema* pTSchema = pTask->tbSink.pTSchema; + /*SSchemaWrapper* pSchemaWrapper = pTask->tbSink.pSchemaWrapper;*/ + + int32_t blockSz = taosArrayGetSize(pBlocks); + + tqDebug("vgId:%d, s-task:%s write results blocks:%d into table", TD_VID(pVnode), pTask->id.idStr, blockSz); + + void* pBuf = NULL; + SArray* tagArray = NULL; + SArray* pVals = NULL; + SArray* crTblArray = NULL; + + for (int32_t i = 0; i < blockSz; i++) { + SSDataBlock* pDataBlock = taosArrayGet(pBlocks, i); + int32_t rows = pDataBlock->info.rows; + if (pDataBlock->info.type == STREAM_DELETE_RESULT) { + SBatchDeleteReq deleteReq = {0}; + deleteReq.deleteReqs = taosArrayInit(0, sizeof(SSingleDeleteReq)); + deleteReq.suid = suid; + tqBuildDeleteReq(pVnode, stbFullName, pDataBlock, &deleteReq); + if (taosArrayGetSize(deleteReq.deleteReqs) == 0) { + taosArrayDestroy(deleteReq.deleteReqs); + continue; + } + + int32_t len; + int32_t code; + tEncodeSize(tEncodeSBatchDeleteReq, &deleteReq, len, code); + if (code < 0) { + // + ASSERT(0); + } + SEncoder encoder; + void* serializedDeleteReq = rpcMallocCont(len + sizeof(SMsgHead)); + void* abuf = POINTER_SHIFT(serializedDeleteReq, sizeof(SMsgHead)); + tEncoderInit(&encoder, abuf, len); + tEncodeSBatchDeleteReq(&encoder, &deleteReq); + tEncoderClear(&encoder); + taosArrayDestroy(deleteReq.deleteReqs); + + ((SMsgHead*)serializedDeleteReq)->vgId = pVnode->config.vgId; + + SRpcMsg msg = { + .msgType = TDMT_VND_BATCH_DEL, + .pCont = serializedDeleteReq, + .contLen = len + sizeof(SMsgHead), + }; + if (tmsgPutToQueue(&pVnode->msgCb, WRITE_QUEUE, &msg) != 0) { + tqDebug("failed to put delete req into write-queue since %s", terrstr()); + } + } else if (pDataBlock->info.type == STREAM_CREATE_CHILD_TABLE) { + SVCreateTbBatchReq reqs = {0}; + crTblArray = reqs.pArray = taosArrayInit(1, sizeof(struct SVCreateTbReq)); + if (NULL == reqs.pArray) { + goto _end; + } + for (int32_t rowId = 0; rowId < rows; rowId++) { + SVCreateTbReq createTbReq = {0}; + SVCreateTbReq* pCreateTbReq = &createTbReq; + + // set const + pCreateTbReq->flags = 0; + pCreateTbReq->type = TSDB_CHILD_TABLE; + pCreateTbReq->ctb.suid = suid; + + // set super table name + SName name = {0}; + tNameFromString(&name, stbFullName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); + pCreateTbReq->ctb.stbName = taosStrdup((char*)tNameGetTableName(&name)); // taosStrdup(stbFullName); + + // set tag content + int32_t size = taosArrayGetSize(pDataBlock->pDataBlock); + if (size == 2) { + tagArray = taosArrayInit(1, sizeof(STagVal)); + if (!tagArray) { + tdDestroySVCreateTbReq(pCreateTbReq); + goto _end; + } + STagVal tagVal = { + .cid = pTSchema->numOfCols + 1, + .type = TSDB_DATA_TYPE_UBIGINT, + .i64 = (int64_t)pDataBlock->info.id.groupId, + }; + taosArrayPush(tagArray, &tagVal); + + // set tag name + SArray* tagName = taosArrayInit(1, TSDB_COL_NAME_LEN); + char tagNameStr[TSDB_COL_NAME_LEN] = "group_id"; + taosArrayPush(tagName, tagNameStr); + pCreateTbReq->ctb.tagName = tagName; + } else { + tagArray = taosArrayInit(size - 1, sizeof(STagVal)); + if (!tagArray) { + tdDestroySVCreateTbReq(pCreateTbReq); + goto _end; + } + for (int32_t tagId = UD_TAG_COLUMN_INDEX, step = 1; tagId < size; tagId++, step++) { + SColumnInfoData* pTagData = taosArrayGet(pDataBlock->pDataBlock, tagId); + + STagVal tagVal = {.cid = pTSchema->numOfCols + step, .type = pTagData->info.type}; + void* pData = colDataGetData(pTagData, rowId); + if (colDataIsNull_s(pTagData, rowId)) { + continue; + } else if (IS_VAR_DATA_TYPE(pTagData->info.type)) { + tagVal.nData = varDataLen(pData); + tagVal.pData = varDataVal(pData); + } else { + memcpy(&tagVal.i64, pData, pTagData->info.bytes); + } + taosArrayPush(tagArray, &tagVal); + } + } + pCreateTbReq->ctb.tagNum = TMAX(size - UD_TAG_COLUMN_INDEX, 1); + + STag* pTag = NULL; + tTagNew(tagArray, 1, false, &pTag); + tagArray = taosArrayDestroy(tagArray); + if (pTag == NULL) { + tdDestroySVCreateTbReq(pCreateTbReq); + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _end; + } + + + pCreateTbReq->ctb.pTag = (uint8_t*)pTag; + + // set table name + if (!pDataBlock->info.parTbName[0]) { + SColumnInfoData* pGpIdColInfo = taosArrayGet(pDataBlock->pDataBlock, UD_GROUPID_COLUMN_INDEX); + void* pGpIdData = colDataGetData(pGpIdColInfo, rowId); + pCreateTbReq->name = buildCtbNameByGroupId(stbFullName, *(uint64_t*)pGpIdData); + } else { + pCreateTbReq->name = taosStrdup(pDataBlock->info.parTbName); + } + taosArrayPush(reqs.pArray, pCreateTbReq); + } + reqs.nReqs = taosArrayGetSize(reqs.pArray); + if (tqPutReqToQueue(pVnode, &reqs) != TSDB_CODE_SUCCESS) { + goto _end; + } + tagArray = taosArrayDestroy(tagArray); + taosArrayDestroyEx(crTblArray, (FDelete)tdDestroySVCreateTbReq); + crTblArray = NULL; + } else { + SSubmitTbData tbData = {0}; + tqDebug("tq sink pipe2, convert block1 %d, rows: %d", i, rows); + + if (!(tbData.aRowP = taosArrayInit(rows, sizeof(SRow*)))) { + goto _end; + } + + tbData.suid = suid; + tbData.uid = 0; // uid is assigned by vnode + tbData.sver = pTSchema->version; + + char* ctbName = NULL; + tqDebug("vgId:%d, stream write into %s, table auto created", TD_VID(pVnode), pDataBlock->info.parTbName); + if (pDataBlock->info.parTbName[0]) { + ctbName = taosStrdup(pDataBlock->info.parTbName); + } else { + ctbName = buildCtbNameByGroupId(stbFullName, pDataBlock->info.id.groupId); + } + + SMetaReader mr = {0}; + metaReaderInit(&mr, pVnode->pMeta, 0); + if (metaGetTableEntryByName(&mr, ctbName) < 0) { + metaReaderClear(&mr); + tqDebug("vgId:%d, stream write into %s, table auto created", TD_VID(pVnode), ctbName); + + SVCreateTbReq* pCreateTbReq = NULL; + + if (!(pCreateTbReq = taosMemoryCalloc(1, sizeof(SVCreateStbReq)))) { + taosMemoryFree(ctbName); + goto _end; + }; + + // set const + pCreateTbReq->flags = 0; + pCreateTbReq->type = TSDB_CHILD_TABLE; + pCreateTbReq->ctb.suid = suid; + + // set super table name + SName name = {0}; + tNameFromString(&name, stbFullName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); + pCreateTbReq->ctb.stbName = taosStrdup((char*)tNameGetTableName(&name)); // taosStrdup(stbFullName); + + // set tag content + tagArray = taosArrayInit(1, sizeof(STagVal)); + if (!tagArray) { + taosMemoryFree(ctbName); + tdDestroySVCreateTbReq(pCreateTbReq); + goto _end; + } + STagVal tagVal = { + .cid = pTSchema->numOfCols + 1, + .type = TSDB_DATA_TYPE_UBIGINT, + .i64 = (int64_t)pDataBlock->info.id.groupId, + }; + taosArrayPush(tagArray, &tagVal); + pCreateTbReq->ctb.tagNum = taosArrayGetSize(tagArray); + + STag* pTag = NULL; + tTagNew(tagArray, 1, false, &pTag); + tagArray = taosArrayDestroy(tagArray); + if (pTag == NULL) { + taosMemoryFree(ctbName); + tdDestroySVCreateTbReq(pCreateTbReq); + terrno = TSDB_CODE_OUT_OF_MEMORY; + taosMemoryFree(ctbName); + tdDestroySVCreateTbReq(pCreateTbReq); + goto _end; + } + pCreateTbReq->ctb.pTag = (uint8_t*)pTag; + + // set tag name + SArray* tagName = taosArrayInit(1, TSDB_COL_NAME_LEN); + char tagNameStr[TSDB_COL_NAME_LEN] = {0}; + strcpy(tagNameStr, "group_id"); + taosArrayPush(tagName, tagNameStr); + pCreateTbReq->ctb.tagName = tagName; + + // set table name + pCreateTbReq->name = ctbName; + ctbName = NULL; + + tbData.pCreateTbReq = pCreateTbReq; + tbData.flags = SUBMIT_REQ_AUTO_CREATE_TABLE; + } else { + if (mr.me.type != TSDB_CHILD_TABLE) { + tqError("vgId:%d, failed to write into %s, since table type incorrect, type %d", TD_VID(pVnode), ctbName, + mr.me.type); + metaReaderClear(&mr); + taosMemoryFree(ctbName); + continue; + } + + if (mr.me.ctbEntry.suid != suid) { + tqError("vgId:%d, failed to write into %s, since suid mismatch, expect suid: %" PRId64 + ", actual suid %" PRId64 "", + TD_VID(pVnode), ctbName, suid, mr.me.ctbEntry.suid); + metaReaderClear(&mr); + taosMemoryFree(ctbName); + continue; + } + + tbData.uid = mr.me.uid; + metaReaderClear(&mr); + taosMemoryFreeClear(ctbName); + } + + // rows + if (!pVals && !(pVals = taosArrayInit(pTSchema->numOfCols, sizeof(SColVal)))) { + taosArrayDestroy(tbData.aRowP); + tdDestroySVCreateTbReq(tbData.pCreateTbReq); + goto _end; + } + + for (int32_t j = 0; j < rows; j++) { + taosArrayClear(pVals); + int32_t dataIndex = 0; + for (int32_t k = 0; k < pTSchema->numOfCols; k++) { + const STColumn* pCol = &pTSchema->columns[k]; + if (k == 0) { + SColumnInfoData* pColData = taosArrayGet(pDataBlock->pDataBlock, dataIndex); + void* colData = colDataGetData(pColData, j); + tqDebug("tq sink pipe2, row %d, col %d ts %" PRId64, j, k, *(int64_t*)colData); + } + if (IS_SET_NULL(pCol)) { + SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type); + taosArrayPush(pVals, &cv); + } else { + SColumnInfoData* pColData = taosArrayGet(pDataBlock->pDataBlock, dataIndex); + if (colDataIsNull_s(pColData, j)) { + SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type); + taosArrayPush(pVals, &cv); + dataIndex++; + } else { + void* colData = colDataGetData(pColData, j); + if (IS_STR_DATA_TYPE(pCol->type)) { + SValue sv = + (SValue){.nData = varDataLen(colData), .pData = varDataVal(colData)}; // address copy, no value + SColVal cv = COL_VAL_VALUE(pCol->colId, pCol->type, sv); + taosArrayPush(pVals, &cv); + } else { + SValue sv; + memcpy(&sv.val, colData, tDataTypes[pCol->type].bytes); + SColVal cv = COL_VAL_VALUE(pCol->colId, pCol->type, sv); + taosArrayPush(pVals, &cv); + } + dataIndex++; + } + } + } + SRow* pRow = NULL; + if ((terrno = tRowBuild(pVals, (STSchema*)pTSchema, &pRow)) < 0) { + tDestroySubmitTbData(&tbData, TSDB_MSG_FLG_ENCODE); + goto _end; + } + ASSERT(pRow); + taosArrayPush(tbData.aRowP, &pRow); + } + + SSubmitReq2 submitReq = {0}; + if (!(submitReq.aSubmitTbData = taosArrayInit(1, sizeof(SSubmitTbData)))) { + tDestroySubmitTbData(&tbData, TSDB_MSG_FLG_ENCODE); + goto _end; + } + + taosArrayPush(submitReq.aSubmitTbData, &tbData); + + // encode + int32_t len; + int32_t code; + tEncodeSize(tEncodeSubmitReq, &submitReq, len, code); + SEncoder encoder; + len += sizeof(SSubmitReq2Msg); + pBuf = rpcMallocCont(len); + if (NULL == pBuf) { + tDestroySubmitReq(&submitReq, TSDB_MSG_FLG_ENCODE); + goto _end; + } + ((SSubmitReq2Msg*)pBuf)->header.vgId = TD_VID(pVnode); + ((SSubmitReq2Msg*)pBuf)->header.contLen = htonl(len); + ((SSubmitReq2Msg*)pBuf)->version = htobe64(1); + tEncoderInit(&encoder, POINTER_SHIFT(pBuf, sizeof(SSubmitReq2Msg)), len - sizeof(SSubmitReq2Msg)); + if (tEncodeSubmitReq(&encoder, &submitReq) < 0) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + tqError("failed to encode submit req since %s", terrstr()); + tEncoderClear(&encoder); + rpcFreeCont(pBuf); + tDestroySubmitReq(&submitReq, TSDB_MSG_FLG_ENCODE); + continue; + } + tEncoderClear(&encoder); + tDestroySubmitReq(&submitReq, TSDB_MSG_FLG_ENCODE); + + SRpcMsg msg = { + .msgType = TDMT_VND_SUBMIT, + .pCont = pBuf, + .contLen = len, + }; + + if (tmsgPutToQueue(&pVnode->msgCb, WRITE_QUEUE, &msg) != 0) { + tqDebug("failed to put into write-queue since %s", terrstr()); + } + } + } +_end: + taosArrayDestroy(tagArray); + taosArrayDestroy(pVals); + taosArrayDestroyEx(crTblArray, (FDelete)tdDestroySVCreateTbReq); + // TODO: change } -#endif diff --git a/source/dnode/vnode/src/tq/tqSnapshot.c b/source/dnode/vnode/src/tq/tqSnapshot.c index 129a2dd8b309a78a1ef31bde0ab5367167999021..5c0649c10985b05dc1f5677fa9bfe1812dd07808 100644 --- a/source/dnode/vnode/src/tq/tqSnapshot.c +++ b/source/dnode/vnode/src/tq/tqSnapshot.c @@ -100,8 +100,6 @@ int32_t tqSnapRead(STqSnapReader* pReader, uint8_t** ppData) { } } - ASSERT(pVal && vLen); - *ppData = taosMemoryMalloc(sizeof(SSnapDataHdr) + vLen); if (*ppData == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; diff --git a/source/dnode/vnode/src/tq/tqStreamStateSnap.c b/source/dnode/vnode/src/tq/tqStreamStateSnap.c index b1f00bdf7446789fa3c572ff366bd20319db10ec..ab7093a701e0a5207b5f64072350ba5bc2bae703 100644 --- a/source/dnode/vnode/src/tq/tqStreamStateSnap.c +++ b/source/dnode/vnode/src/tq/tqStreamStateSnap.c @@ -100,8 +100,6 @@ int32_t tqSnapRead(STqSnapReader* pReader, uint8_t** ppData) { } } - ASSERT(pVal && vLen); - *ppData = taosMemoryMalloc(sizeof(SSnapDataHdr) + vLen); if (*ppData == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; @@ -168,7 +166,6 @@ int32_t tqSnapWriterClose(STqSnapWriter** ppWriter, int8_t rollback) { if (rollback) { tdbAbort(pWriter->pTq->pMetaDB, pWriter->txn); - ASSERT(0); } else { code = tdbCommit(pWriter->pTq->pMetaDB, pWriter->txn); if (code) goto _err; diff --git a/source/dnode/vnode/src/tq/tqStreamTaskSnap.c b/source/dnode/vnode/src/tq/tqStreamTaskSnap.c index 305378bc932f0484c71a9d1c91935a580189488e..ab7093a701e0a5207b5f64072350ba5bc2bae703 100644 --- a/source/dnode/vnode/src/tq/tqStreamTaskSnap.c +++ b/source/dnode/vnode/src/tq/tqStreamTaskSnap.c @@ -100,8 +100,6 @@ int32_t tqSnapRead(STqSnapReader* pReader, uint8_t** ppData) { } } - ASSERT(pVal && vLen); - *ppData = taosMemoryMalloc(sizeof(SSnapDataHdr) + vLen); if (*ppData == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; @@ -146,7 +144,7 @@ int32_t tqSnapWriterOpen(STQ* pTq, int64_t sver, int64_t ever, STqSnapWriter** p pWriter->sver = sver; pWriter->ever = ever; - if (tdbBegin(pTq->pMetaStore, &pWriter->txn, tdbDefaultMalloc, tdbDefaultFree, NULL, 0) < 0) { + if (tdbBegin(pTq->pMetaDB, &pWriter->txn, tdbDefaultMalloc, tdbDefaultFree, NULL, 0) < 0) { code = -1; taosMemoryFree(pWriter); goto _err; @@ -167,12 +165,11 @@ int32_t tqSnapWriterClose(STqSnapWriter** ppWriter, int8_t rollback) { STQ* pTq = pWriter->pTq; if (rollback) { - tdbAbort(pWriter->pTq->pMetaStore, pWriter->txn); - ASSERT(0); + tdbAbort(pWriter->pTq->pMetaDB, pWriter->txn); } else { - code = tdbCommit(pWriter->pTq->pMetaStore, pWriter->txn); + code = tdbCommit(pWriter->pTq->pMetaDB, pWriter->txn); if (code) goto _err; - code = tdbPostCommit(pWriter->pTq->pMetaStore, pWriter->txn); + code = tdbPostCommit(pWriter->pTq->pMetaDB, pWriter->txn); if (code) goto _err; } diff --git a/source/dnode/vnode/src/tq/tqUtil.c b/source/dnode/vnode/src/tq/tqUtil.c new file mode 100644 index 0000000000000000000000000000000000000000..622cc5b04936dc8aec8a6944bd095fd2ab39b2b4 --- /dev/null +++ b/source/dnode/vnode/src/tq/tqUtil.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "tq.h" + +#define IS_OFFSET_RESET_TYPE(_t) ((_t) < 0) +#define NO_POLL_CNT 5 + +static int32_t tqSendMetaPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqMetaRsp* pRsp); + +char* createStreamTaskIdStr(int64_t streamId, int32_t taskId) { + char buf[128] = {0}; + sprintf(buf, "0x%" PRIx64 "-%d", streamId, taskId); + return taosStrdup(buf); +} + +int32_t tqAddInputBlockNLaunchTask(SStreamTask* pTask, SStreamQueueItem* pQueueItem) { + int32_t code = tAppendDataToInputQueue(pTask, pQueueItem); + if (code < 0) { + tqError("s-task:%s failed to put into queue, too many", pTask->id.idStr); + return -1; + } + + if (streamSchedExec(pTask) < 0) { + tqError("stream task:%d failed to be launched, code:%s", pTask->id.taskId, tstrerror(terrno)); + return -1; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t tqInitDataRsp(SMqDataRsp* pRsp, const SMqPollReq* pReq, int8_t subType) { + pRsp->reqOffset = pReq->reqOffset; + + pRsp->blockData = taosArrayInit(0, sizeof(void*)); + pRsp->blockDataLen = taosArrayInit(0, sizeof(int32_t)); + + if (pRsp->blockData == NULL || pRsp->blockDataLen == NULL) { + return -1; + } + + pRsp->withTbName = 0; + pRsp->withSchema = false; + return 0; +} + +static int32_t tqInitTaosxRsp(STaosxRsp* pRsp, const SMqPollReq* pReq) { + pRsp->reqOffset = pReq->reqOffset; + + pRsp->withTbName = 1; + pRsp->withSchema = 1; + pRsp->blockData = taosArrayInit(0, sizeof(void*)); + pRsp->blockDataLen = taosArrayInit(0, sizeof(int32_t)); + pRsp->blockTbName = taosArrayInit(0, sizeof(void*)); + pRsp->blockSchema = taosArrayInit(0, sizeof(void*)); + + if (pRsp->blockData == NULL || pRsp->blockDataLen == NULL || pRsp->blockTbName == NULL || pRsp->blockSchema == NULL) { + if (pRsp->blockData != NULL) { + pRsp->blockData = taosArrayDestroy(pRsp->blockData); + } + + if (pRsp->blockDataLen != NULL) { + pRsp->blockDataLen = taosArrayDestroy(pRsp->blockDataLen); + } + + if (pRsp->blockTbName != NULL) { + pRsp->blockTbName = taosArrayDestroy(pRsp->blockTbName); + } + + if (pRsp->blockSchema != NULL) { + pRsp->blockSchema = taosArrayDestroy(pRsp->blockSchema); + } + return -1; + } + + return 0; +} + +static int32_t extractResetOffsetVal(STqOffsetVal* pOffsetVal, STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequest, + SRpcMsg* pMsg, bool* pBlockReturned) { + uint64_t consumerId = pRequest->consumerId; + STqOffsetVal reqOffset = pRequest->reqOffset; + STqOffset* pOffset = tqOffsetRead(pTq->pOffsetStore, pRequest->subKey); + int32_t vgId = TD_VID(pTq->pVnode); + + *pBlockReturned = false; + + // In this vnode, data has been polled by consumer for this topic, so let's continue from the last offset value. + if (pOffset != NULL) { + *pOffsetVal = pOffset->val; + + char formatBuf[80]; + tFormatOffset(formatBuf, 80, pOffsetVal); + tqDebug("tmq poll: consumer:0x%" PRIx64 ", subkey %s, vgId:%d, existed offset found, offset reset to %s and continue. reqId:0x%"PRIx64, + consumerId, pHandle->subKey, vgId, formatBuf, pRequest->reqId); + return 0; + } else { + // no poll occurs in this vnode for this topic, let's seek to the right offset value. + if (reqOffset.type == TMQ_OFFSET__RESET_EARLIEAST) { + if (pRequest->useSnapshot) { + tqDebug("tmq poll: consumer:0x%" PRIx64 ", subkey:%s, vgId:%d, (earliest) set offset to be snapshot", + consumerId, pHandle->subKey, vgId); + + if (pHandle->fetchMeta) { + tqOffsetResetToMeta(pOffsetVal, 0); + } else { + tqOffsetResetToData(pOffsetVal, 0, 0); + } + } else { + pHandle->pRef = walRefFirstVer(pTq->pVnode->pWal, pHandle->pRef); + if (pHandle->pRef == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return -1; + } + + // offset set to previous version when init + tqOffsetResetToLog(pOffsetVal, pHandle->pRef->refVer - 1); + } + } else if (reqOffset.type == TMQ_OFFSET__RESET_LATEST) { + if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { + SMqDataRsp dataRsp = {0}; + tqInitDataRsp(&dataRsp, pRequest, pHandle->execHandle.subType); + + tqOffsetResetToLog(&dataRsp.rspOffset, walGetLastVer(pTq->pVnode->pWal)); + tqDebug("tmq poll: consumer:0x%" PRIx64 ", subkey %s, vgId:%d, (latest) offset reset to %" PRId64, consumerId, + pHandle->subKey, vgId, dataRsp.rspOffset.version); + int32_t code = tqSendDataRsp(pTq, pMsg, pRequest, &dataRsp, TMQ_MSG_TYPE__POLL_RSP); + tDeleteSMqDataRsp(&dataRsp); + + *pBlockReturned = true; + return code; + } else { + STaosxRsp taosxRsp = {0}; + tqInitTaosxRsp(&taosxRsp, pRequest); + tqOffsetResetToLog(&taosxRsp.rspOffset, walGetLastVer(pTq->pVnode->pWal)); + int32_t code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP); + tDeleteSTaosxRsp(&taosxRsp); + + *pBlockReturned = true; + return code; + } + } else if (reqOffset.type == TMQ_OFFSET__RESET_NONE) { + tqError("tmq poll: subkey:%s, no offset committed for consumer:0x%" PRIx64 " in vg %d, subkey %s, reset none failed", + pHandle->subKey, consumerId, vgId, pRequest->subKey); + terrno = TSDB_CODE_TQ_NO_COMMITTED_OFFSET; + return -1; + } + } + + return 0; +} + +static int32_t extractDataAndRspForNormalSubscribe(STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequest, + SRpcMsg* pMsg, STqOffsetVal* pOffset) { + uint64_t consumerId = pRequest->consumerId; + int32_t vgId = TD_VID(pTq->pVnode); + int code = 0; + + SMqDataRsp dataRsp = {0}; + tqInitDataRsp(&dataRsp, pRequest, pHandle->execHandle.subType); + + qSetTaskId(pHandle->execHandle.task, consumerId, pRequest->reqId); + code = tqScanData(pTq, pHandle, &dataRsp, pOffset); + if(code != 0) { + goto end; + } + + // till now, all data has been transferred to consumer, new data needs to push client once arrived. + if (dataRsp.blockNum == 0 && dataRsp.reqOffset.type == TMQ_OFFSET__LOG && + dataRsp.reqOffset.version == dataRsp.rspOffset.version && pHandle->consumerId == pRequest->consumerId) { + if(pHandle->noDataPollCnt >= NO_POLL_CNT){ // send poll result to client if no data 5 times to avoid lost data + pHandle->noDataPollCnt = 0; + // lock + taosWLockLatch(&pTq->lock); + code = tqRegisterPushHandle(pTq, pHandle, pMsg); + taosWUnLockLatch(&pTq->lock); + tDeleteSMqDataRsp(&dataRsp); + return code; + } + else{ + pHandle->noDataPollCnt++; + } + } + + // NOTE: this pHandle->consumerId may have been changed already. + code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&dataRsp, TMQ_MSG_TYPE__POLL_RSP); + + end: + { + char buf[80] = {0}; + tFormatOffset(buf, 80, &dataRsp.rspOffset); + tqDebug("tmq poll: consumer:0x%" PRIx64 ", subkey %s, vgId:%d, rsp block:%d, rsp offset type:%s, reqId:0x%" PRIx64 " code:%d", + consumerId, pHandle->subKey, vgId, dataRsp.blockNum, buf, pRequest->reqId, code); + tDeleteSMqDataRsp(&dataRsp); + } + + return code; +} + + +static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequest, SRpcMsg* pMsg, STqOffsetVal *offset) { + int code = 0; + int32_t vgId = TD_VID(pTq->pVnode); + SWalCkHead* pCkHead = NULL; + SMqMetaRsp metaRsp = {0}; + STaosxRsp taosxRsp = {0}; + tqInitTaosxRsp(&taosxRsp, pRequest); + + if (offset->type != TMQ_OFFSET__LOG) { + if (tqScanTaosx(pTq, pHandle, &taosxRsp, &metaRsp, offset) < 0) { + code = -1; + goto end; + } + + if (metaRsp.metaRspLen > 0) { + code = tqSendMetaPollRsp(pTq, pMsg, pRequest, &metaRsp); + tqDebug("tmq poll: consumer:0x%" PRIx64 " subkey:%s vgId:%d, send meta offset type:%d,uid:%" PRId64 ",ts:%" PRId64, + pRequest->consumerId, pHandle->subKey, vgId, metaRsp.rspOffset.type, metaRsp.rspOffset.uid, metaRsp.rspOffset.ts); + taosMemoryFree(metaRsp.metaRsp); + goto end; + } + + tqDebug("taosx poll: consumer:0x%" PRIx64 " subkey:%s vgId:%d, send data blockNum:%d, offset type:%d,uid:%" PRId64 + ",ts:%" PRId64,pRequest->consumerId, pHandle->subKey, vgId, taosxRsp.blockNum, taosxRsp.rspOffset.type, taosxRsp.rspOffset.uid,taosxRsp.rspOffset.ts); + if (taosxRsp.blockNum > 0) { + code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP); + goto end; + }else { + *offset = taosxRsp.rspOffset; + } + } + + if (offset->type == TMQ_OFFSET__LOG) { + verifyOffset(pHandle->pWalReader, offset); + int64_t fetchVer = offset->version + 1; + pCkHead = taosMemoryMalloc(sizeof(SWalCkHead) + 2048); + if (pCkHead == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + code = -1; + goto end; + } + walSetReaderCapacity(pHandle->pWalReader, 2048); + int totalRows = 0; + while (1) { + int32_t savedEpoch = atomic_load_32(&pHandle->epoch); + if (savedEpoch > pRequest->epoch) { + tqWarn("tmq poll: consumer:0x%" PRIx64 " (epoch %d), subkey:%s vgId:%d offset %" PRId64 + ", found new consumer epoch %d, discard req epoch %d", pRequest->consumerId, pRequest->epoch, pHandle->subKey, vgId, fetchVer, savedEpoch, pRequest->epoch); + break; + } + + if (tqFetchLog(pTq, pHandle, &fetchVer, &pCkHead, pRequest->reqId) < 0) { + tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer); + code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP); + goto end; + } + + SWalCont* pHead = &pCkHead->head; + tqDebug("tmq poll: consumer:0x%" PRIx64 " (epoch %d) iter log, vgId:%d offset %" PRId64 " msgType %d", pRequest->consumerId, + pRequest->epoch, vgId, fetchVer, pHead->msgType); + + // process meta + if (pHead->msgType != TDMT_VND_SUBMIT) { + if(totalRows > 0) { + tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer - 1); + code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP); + goto end; + } + + tqDebug("fetch meta msg, ver:%" PRId64 ", type:%s", pHead->version, TMSG_INFO(pHead->msgType)); + tqOffsetResetToLog(&metaRsp.rspOffset, fetchVer); + metaRsp.resMsgType = pHead->msgType; + metaRsp.metaRspLen = pHead->bodyLen; + metaRsp.metaRsp = pHead->body; + code = tqSendMetaPollRsp(pTq, pMsg, pRequest, &metaRsp); + goto end; + } + + // process data + SPackedData submit = { + .msgStr = POINTER_SHIFT(pHead->body, sizeof(SSubmitReq2Msg)), + .msgLen = pHead->bodyLen - sizeof(SSubmitReq2Msg), + .ver = pHead->version, + }; + + code = tqTaosxScanLog(pTq, pHandle, submit, &taosxRsp, &totalRows); + if (code < 0) { + tqError("tmq poll: tqTaosxScanLog error %" PRId64 ", in vgId:%d, subkey %s", pRequest->consumerId, vgId, pRequest->subKey); + goto end; + } + + if (totalRows >= 4096 || taosxRsp.createTableNum > 0) { + tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer); + code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP); + goto end; + } else { + fetchVer++; + } + } + } + +end: + + tDeleteSTaosxRsp(&taosxRsp); + taosMemoryFreeClear(pCkHead); + return code; +} + +int32_t tqExtractDataForMq(STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequest, SRpcMsg* pMsg) { + int32_t code = -1; + STqOffsetVal offset = {0}; + STqOffsetVal reqOffset = pRequest->reqOffset; + + // 1. reset the offset if needed + if (IS_OFFSET_RESET_TYPE(reqOffset.type)) { + // handle the reset offset cases, according to the consumer's choice. + bool blockReturned = false; + code = extractResetOffsetVal(&offset, pTq, pHandle, pRequest, pMsg, &blockReturned); + if (code != 0) { + return code; + } + + // empty block returned, quit + if (blockReturned) { + return 0; + } + } else { // use the consumer specified offset + // the offset value can not be monotonious increase?? + offset = reqOffset; + } + + // this is a normal subscribe requirement + if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) { + return extractDataAndRspForNormalSubscribe(pTq, pHandle, pRequest, pMsg, &offset); + } else { // todo handle the case where re-balance occurs. + // for taosx + return extractDataAndRspForDbStbSubscribe(pTq, pHandle, pRequest, pMsg, &offset); + } +} + +int32_t tqSendMetaPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqMetaRsp* pRsp) { + int32_t len = 0; + int32_t code = 0; + tEncodeSize(tEncodeSMqMetaRsp, pRsp, len, code); + if (code < 0) { + return -1; + } + int32_t tlen = sizeof(SMqRspHead) + len; + void* buf = rpcMallocCont(tlen); + if (buf == NULL) { + return -1; + } + + ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_META_RSP; + ((SMqRspHead*)buf)->epoch = pReq->epoch; + ((SMqRspHead*)buf)->consumerId = pReq->consumerId; + + void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead)); + + SEncoder encoder = {0}; + tEncoderInit(&encoder, abuf, len); + tEncodeSMqMetaRsp(&encoder, pRsp); + tEncoderClear(&encoder); + + SRpcMsg resp = { + .info = pMsg->info, + .pCont = buf, + .contLen = tlen, + .code = 0, + }; + tmsgSendRsp(&resp); + + tqDebug("vgId:%d, from consumer:0x%" PRIx64 " (epoch %d) send rsp, res msg type %d, offset type:%d", + TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->resMsgType, pRsp->rspOffset.type); + + return 0; +} diff --git a/source/dnode/vnode/src/tsdb/tsdbCache.c b/source/dnode/vnode/src/tsdb/tsdbCache.c index 10ab541978f79543a00252d3f3615cba4aa377f9..65fc086f8d60a8d92649e45de4ba9526fd9aebc4 100644 --- a/source/dnode/vnode/src/tsdb/tsdbCache.c +++ b/source/dnode/vnode/src/tsdb/tsdbCache.c @@ -17,7 +17,7 @@ static int32_t tsdbOpenBICache(STsdb *pTsdb) { int32_t code = 0; - SLRUCache *pCache = taosLRUCacheInit(5 * 1024 * 1024, 1, .5); + SLRUCache *pCache = taosLRUCacheInit(10 * 1024 * 1024, 0, .5); if (pCache == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; goto _err; @@ -35,7 +35,11 @@ _err: static void tsdbCloseBICache(STsdb *pTsdb) { SLRUCache *pCache = pTsdb->biCache; if (pCache) { + int32_t elems = taosLRUCacheGetElems(pCache); + tsdbTrace("vgId:%d, elems: %d", TD_VID(pTsdb->pVnode), elems); taosLRUCacheEraseUnrefEntries(pCache); + elems = taosLRUCacheGetElems(pCache); + tsdbTrace("vgId:%d, elems: %d", TD_VID(pTsdb->pVnode), elems); taosLRUCacheCleanup(pCache); @@ -127,12 +131,10 @@ int32_t tsdbCacheDeleteLastrow(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey) { } } + taosLRUCacheRelease(pCache, h, invalidate); if (invalidate) { - taosLRUCacheRelease(pCache, h, true); - } else { - taosLRUCacheRelease(pCache, h, false); + taosLRUCacheErase(pCache, key, keyLen); } - // void taosLRUCacheErase(SLRUCache * cache, const void *key, size_t keyLen); } return code; @@ -160,12 +162,10 @@ int32_t tsdbCacheDeleteLast(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey) { } } + taosLRUCacheRelease(pCache, h, invalidate); if (invalidate) { - taosLRUCacheRelease(pCache, h, true); - } else { - taosLRUCacheRelease(pCache, h, false); + taosLRUCacheErase(pCache, key, keyLen); } - // void taosLRUCacheErase(SLRUCache * cache, const void *key, size_t keyLen); } return code; @@ -226,7 +226,7 @@ int32_t tsdbCacheDelete(SLRUCache *pCache, tb_uid_t uid, TSKEY eKey) { return code; } -int32_t tsdbCacheInsertLastrow(SLRUCache *pCache, STsdb *pTsdb, tb_uid_t uid, STSRow *row, bool dup) { +int32_t tsdbCacheInsertLastrow(SLRUCache *pCache, STsdb *pTsdb, tb_uid_t uid, TSDBROW *row, bool dup) { int32_t code = 0; STSRow *cacheRow = NULL; char key[32] = {0}; @@ -237,13 +237,48 @@ int32_t tsdbCacheInsertLastrow(SLRUCache *pCache, STsdb *pTsdb, tb_uid_t uid, ST LRUHandle *h = taosLRUCacheLookup(pCache, key, keyLen); if (h) { STSchema *pTSchema = metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1, 1); - TSKEY keyTs = row->ts; + TSKEY keyTs = TSDBROW_TS(row); bool invalidate = false; SArray *pLast = (SArray *)taosLRUCacheValue(pCache, h); int16_t nCol = taosArrayGetSize(pLast); int16_t iCol = 0; + if (nCol <= 0) { + nCol = pTSchema->numOfCols; + + STColumn *pTColumn = &pTSchema->columns[0]; + SColVal tColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.val = keyTs}); + if (taosArrayPush(pLast, &(SLastCol){.ts = keyTs, .colVal = tColVal}) == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + code = TSDB_CODE_OUT_OF_MEMORY; + goto _invalidate; + } + + for (iCol = 1; iCol < nCol; ++iCol) { + SColVal colVal = {0}; + tsdbRowGetColVal(row, pTSchema, iCol, &colVal); + + SLastCol lastCol = {.ts = keyTs, .colVal = colVal}; + if (IS_VAR_DATA_TYPE(colVal.type) && colVal.value.nData > 0) { + lastCol.colVal.value.pData = taosMemoryMalloc(colVal.value.nData); + if (lastCol.colVal.value.pData == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + code = TSDB_CODE_OUT_OF_MEMORY; + goto _invalidate; + } + memcpy(lastCol.colVal.value.pData, colVal.value.pData, colVal.value.nData); + } + + if (taosArrayPush(pLast, &lastCol) == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _invalidate; + } + } + + goto _invalidate; + } + if (nCol != pTSchema->numOfCols) { invalidate = true; goto _invalidate; @@ -263,7 +298,7 @@ int32_t tsdbCacheInsertLastrow(SLRUCache *pCache, STsdb *pTsdb, tb_uid_t uid, ST SColVal *tColVal = &tTsVal1->colVal; SColVal colVal = {0}; - tTSRowGetVal(row, pTSchema, iCol, &colVal); + tsdbRowGetColVal(row, pTSchema, iCol, &colVal); if (colVal.cid != tColVal->cid) { invalidate = true; @@ -309,7 +344,7 @@ int32_t tsdbCacheInsertLastrow(SLRUCache *pCache, STsdb *pTsdb, tb_uid_t uid, ST return code; } -int32_t tsdbCacheInsertLast(SLRUCache *pCache, tb_uid_t uid, STSRow *row, STsdb *pTsdb) { +int32_t tsdbCacheInsertLast(SLRUCache *pCache, tb_uid_t uid, TSDBROW *row, STsdb *pTsdb) { int32_t code = 0; STSRow *cacheRow = NULL; char key[32] = {0}; @@ -320,13 +355,48 @@ int32_t tsdbCacheInsertLast(SLRUCache *pCache, tb_uid_t uid, STSRow *row, STsdb LRUHandle *h = taosLRUCacheLookup(pCache, key, keyLen); if (h) { STSchema *pTSchema = metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1, 1); - TSKEY keyTs = row->ts; + TSKEY keyTs = TSDBROW_TS(row); bool invalidate = false; SArray *pLast = (SArray *)taosLRUCacheValue(pCache, h); int16_t nCol = taosArrayGetSize(pLast); int16_t iCol = 0; + if (nCol <= 0) { + nCol = pTSchema->numOfCols; + + STColumn *pTColumn = &pTSchema->columns[0]; + SColVal tColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.val = keyTs}); + if (taosArrayPush(pLast, &(SLastCol){.ts = keyTs, .colVal = tColVal}) == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + code = TSDB_CODE_OUT_OF_MEMORY; + goto _invalidate; + } + + for (iCol = 1; iCol < nCol; ++iCol) { + SColVal colVal = {0}; + tsdbRowGetColVal(row, pTSchema, iCol, &colVal); + + SLastCol lastCol = {.ts = keyTs, .colVal = colVal}; + if (IS_VAR_DATA_TYPE(colVal.type) && colVal.value.nData > 0) { + lastCol.colVal.value.pData = taosMemoryMalloc(colVal.value.nData); + if (lastCol.colVal.value.pData == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + code = TSDB_CODE_OUT_OF_MEMORY; + goto _invalidate; + } + memcpy(lastCol.colVal.value.pData, colVal.value.pData, colVal.value.nData); + } + + if (taosArrayPush(pLast, &lastCol) == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _invalidate; + } + } + + goto _invalidate; + } + if (nCol != pTSchema->numOfCols) { invalidate = true; goto _invalidate; @@ -346,7 +416,7 @@ int32_t tsdbCacheInsertLast(SLRUCache *pCache, tb_uid_t uid, STSRow *row, STsdb SColVal *tColVal = &tTsVal1->colVal; SColVal colVal = {0}; - tTSRowGetVal(row, pTSchema, iCol, &colVal); + tsdbRowGetColVal(row, pTSchema, iCol, &colVal); if (colVal.cid != tColVal->cid) { invalidate = true; @@ -440,6 +510,11 @@ static int32_t getTableDelData(STbData *pMem, STbData *pIMem, SDelFReader *pDelR SArray *aDelData) { int32_t code = 0; + if (pDelIdx) { + code = getTableDelDataFromDelIdx(pDelReader, pDelIdx, aDelData); + if (code) goto _err; + } + if (pMem) { code = getTableDelDataFromTbData(pMem, aDelData); if (code) goto _err; @@ -450,11 +525,6 @@ static int32_t getTableDelData(STbData *pMem, STbData *pIMem, SDelFReader *pDelR if (code) goto _err; } - if (pDelIdx) { - code = getTableDelDataFromDelIdx(pDelReader, pDelIdx, aDelData); - if (code) goto _err; - } - _err: return code; } @@ -524,14 +594,19 @@ typedef struct { SDataFReader **pDataFReader; TSDBROW row; + bool checkRemainingRow; SMergeTree mergeTree; SMergeTree *pMergeTree; SSttBlockLoadInfo *pLoadInfo; + SLDataIter* pDataIter; + int64_t lastTs; } SFSLastNextRowIter; -static int32_t getNextRowFromFSLast(void *iter, TSDBROW **ppRow) { +static int32_t getNextRowFromFSLast(void *iter, TSDBROW **ppRow, bool *pIgnoreEarlierTs, bool isLast, int16_t *aCols, + int nCols) { SFSLastNextRowIter *state = (SFSLastNextRowIter *)iter; int32_t code = 0; + bool checkRemainingRow = true; switch (state->state) { case SFSLASTNEXTROW_FS: @@ -564,26 +639,54 @@ static int32_t getNextRowFromFSLast(void *iter, TSDBROW **ppRow) { if (code) goto _err; } + for (int i = 0; i < state->pLoadInfo->numOfStt; ++i) { + state->pLoadInfo[i].colIds = aCols; + state->pLoadInfo[i].numOfCols = nCols; + state->pLoadInfo[i].isLast = isLast; + } tMergeTreeOpen(&state->mergeTree, 1, *state->pDataFReader, state->suid, state->uid, - &(STimeWindow){.skey = TSKEY_MIN, .ekey = TSKEY_MAX}, - &(SVersionRange){.minVer = 0, .maxVer = UINT64_MAX}, state->pLoadInfo, false, NULL); + &(STimeWindow){.skey = state->lastTs, .ekey = TSKEY_MAX}, + &(SVersionRange){.minVer = 0, .maxVer = UINT64_MAX}, state->pLoadInfo, false, NULL, true, state->pDataIter); state->pMergeTree = &state->mergeTree; + state->state = SFSLASTNEXTROW_BLOCKROW; + } + case SFSLASTNEXTROW_BLOCKROW: { + if (nCols != state->pLoadInfo->numOfCols) { + for (int i = 0; i < state->pLoadInfo->numOfStt; ++i) { + state->pLoadInfo[i].numOfCols = nCols; + + state->pLoadInfo[i].checkRemainingRow = state->checkRemainingRow; + } + } bool hasVal = tMergeTreeNext(&state->mergeTree); if (!hasVal) { + if (tMergeTreeIgnoreEarlierTs(&state->mergeTree)) { + *pIgnoreEarlierTs = true; + *ppRow = NULL; + return code; + } state->state = SFSLASTNEXTROW_FILESET; goto _next_fileset; } - state->state = SFSLASTNEXTROW_BLOCKROW; - } - case SFSLASTNEXTROW_BLOCKROW: - state->row = tMergeTreeGetRow(&state->mergeTree); + state->row = *tMergeTreeGetRow(&state->mergeTree); *ppRow = &state->row; - bool hasVal = tMergeTreeNext(&state->mergeTree); + + if (TSDBROW_TS(&state->row) <= state->lastTs) { + *pIgnoreEarlierTs = true; + *ppRow = NULL; + return code; + } + + *pIgnoreEarlierTs = false; if (!hasVal) { state->state = SFSLASTNEXTROW_FILESET; } + if (!state->checkRemainingRow) { + state->checkRemainingRow = true; + } return code; + } default: ASSERT(0); break; @@ -644,6 +747,7 @@ typedef struct SFSNextRowIter { SArray *aDFileSet; SDataFReader **pDataFReader; SArray *aBlockIdx; + LRUHandle *aBlockIdxHandle; SBlockIdx *pBlockIdx; SMapData blockMap; int32_t nBlock; @@ -655,11 +759,14 @@ typedef struct SFSNextRowIter { int32_t iRow; TSDBROW row; SSttBlockLoadInfo *pLoadInfo; + int64_t lastTs; } SFSNextRowIter; -static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow) { +static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow, bool *pIgnoreEarlierTs, bool isLast, int16_t *aCols, + int nCols) { SFSNextRowIter *state = (SFSNextRowIter *)iter; int32_t code = 0; + bool checkRemainingRow = true; switch (state->state) { case SFSNEXTROW_FS: @@ -677,7 +784,7 @@ static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow) { } else { // tBlockDataDestroy(&state->blockData, 1); if (state->pBlockData) { - tBlockDataDestroy(state->pBlockData, 1); + tBlockDataDestroy(state->pBlockData); state->pBlockData = NULL; } @@ -697,6 +804,7 @@ static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow) { } // tMapDataReset(&state->blockIdxMap); + /* if (!state->aBlockIdx) { state->aBlockIdx = taosArrayInit(0, sizeof(SBlockIdx)); } else { @@ -704,6 +812,12 @@ static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow) { } code = tsdbReadBlockIdx(*state->pDataFReader, state->aBlockIdx); if (code) goto _err; + */ + int32_t code = tsdbCacheGetBlockIdx(state->pTsdb->biCache, *state->pDataFReader, &state->aBlockIdxHandle); + if (code != TSDB_CODE_SUCCESS || state->aBlockIdxHandle == NULL) { + goto _err; + } + state->aBlockIdx = (SArray *)taosLRUCacheValue(state->pTsdb->biCache, state->aBlockIdxHandle); /* if (state->pBlockIdx) { */ /* } */ @@ -711,7 +825,12 @@ static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow) { * &state->blockIdx); */ state->pBlockIdx = taosArraySearch(state->aBlockIdx, state->pBlockIdxExp, tCmprBlockIdx, TD_EQ); - if (!state->pBlockIdx) { /* + if (!state->pBlockIdx) { + tsdbBICacheRelease(state->pTsdb->biCache, state->aBlockIdxHandle); + + state->aBlockIdxHandle = NULL; + state->aBlockIdx = NULL; + /* tsdbDataFReaderClose(state->pDataFReader); *state->pDataFReader = NULL; resetLastBlockLoadInfo(state->pLoadInfo);*/ @@ -733,33 +852,122 @@ static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow) { if (!state->pBlockData) { state->pBlockData = &state->blockData; - tBlockDataCreate(&state->blockData); + code = tBlockDataCreate(&state->blockData); + if (code) goto _err; } } case SFSNEXTROW_BLOCKDATA: + _next_datablock: if (state->iBlock >= 0) { SDataBlk block = {0}; + bool skipBlock = true; + int inputColIndex = 0; tDataBlkReset(&block); - // tBlockDataReset(&state->blockData); tBlockDataReset(state->pBlockData); tMapDataGetItemByIdx(&state->blockMap, state->iBlock, &block, tGetDataBlk); - /* code = tsdbReadBlockData(state->pDataFReader, &state->blockIdx, &block, &state->blockData, NULL, NULL); */ + if (block.maxKey.ts <= state->lastTs) { + *pIgnoreEarlierTs = true; + if (state->pBlockData) { + tBlockDataDestroy(state->pBlockData); + state->pBlockData = NULL; + } + + *ppRow = NULL; + return code; + } + *pIgnoreEarlierTs = false; tBlockDataReset(state->pBlockData); TABLEID tid = {.suid = state->suid, .uid = state->uid}; - code = tBlockDataInit(state->pBlockData, &tid, state->pTSchema, NULL, 0); + code = tBlockDataInit(state->pBlockData, &tid, state->pTSchema, aCols, nCols); if (code) goto _err; code = tsdbReadDataBlock(*state->pDataFReader, &block, state->pBlockData); if (code) goto _err; + for (int colIndex = 0; colIndex < state->pBlockData->nColData; ++colIndex) { + SColData *pColData = &state->pBlockData->aColData[colIndex]; + + if (isLast && (pColData->flag & HAS_VALUE)) { + skipBlock = false; + break; + } else if (pColData->flag & (HAS_VALUE | HAS_NULL)) { + skipBlock = false; + break; + } + } + + if (skipBlock) { + if (--state->iBlock < 0) { + tsdbDataFReaderClose(state->pDataFReader); + *state->pDataFReader = NULL; + // resetLastBlockLoadInfo(state->pLoadInfo); + + if (state->aBlockIdx) { + // taosArrayDestroy(state->aBlockIdx); + tsdbBICacheRelease(state->pTsdb->biCache, state->aBlockIdxHandle); + + state->aBlockIdxHandle = NULL; + state->aBlockIdx = NULL; + } + + state->state = SFSNEXTROW_FILESET; + goto _next_fileset; + } else { + goto _next_datablock; + } + } + state->nRow = state->blockData.nRow; state->iRow = state->nRow - 1; state->state = SFSNEXTROW_BLOCKROW; + checkRemainingRow = false; } - case SFSNEXTROW_BLOCKROW: + case SFSNEXTROW_BLOCKROW: { + if (checkRemainingRow) { + bool skipBlock = true; + int inputColIndex = 0; + for (int colIndex = 0; colIndex < state->pBlockData->nColData; ++colIndex) { + SColData *pColData = &state->pBlockData->aColData[colIndex]; + int16_t cid = pColData->cid; + + if (inputColIndex < nCols && cid == aCols[inputColIndex]) { + if (isLast && (pColData->flag & HAS_VALUE)) { + skipBlock = false; + break; + } else if (pColData->flag & (HAS_VALUE | HAS_NULL)) { + skipBlock = false; + break; + } + + ++inputColIndex; + } + } + + if (skipBlock) { + if (--state->iBlock < 0) { + tsdbDataFReaderClose(state->pDataFReader); + *state->pDataFReader = NULL; + // resetLastBlockLoadInfo(state->pLoadInfo); + + if (state->aBlockIdx) { + // taosArrayDestroy(state->aBlockIdx); + tsdbBICacheRelease(state->pTsdb->biCache, state->aBlockIdxHandle); + + state->aBlockIdxHandle = NULL; + state->aBlockIdx = NULL; + } + + state->state = SFSNEXTROW_FILESET; + goto _next_fileset; + } else { + goto _next_datablock; + } + } + } + if (state->iRow >= 0) { state->row = tsdbRowFromBlockData(state->pBlockData, state->iRow); *ppRow = &state->row; @@ -772,7 +980,10 @@ static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow) { // resetLastBlockLoadInfo(state->pLoadInfo); if (state->aBlockIdx) { - taosArrayDestroy(state->aBlockIdx); + // taosArrayDestroy(state->aBlockIdx); + tsdbBICacheRelease(state->pTsdb->biCache, state->aBlockIdxHandle); + + state->aBlockIdxHandle = NULL; state->aBlockIdx = NULL; } @@ -782,6 +993,7 @@ static int32_t getNextRowFromFS(void *iter, TSDBROW **ppRow) { } return code; + } default: ASSERT(0); break; @@ -795,11 +1007,14 @@ _err: resetLastBlockLoadInfo(state->pLoadInfo); }*/ if (state->aBlockIdx) { - taosArrayDestroy(state->aBlockIdx); + // taosArrayDestroy(state->aBlockIdx); + tsdbBICacheRelease(state->pTsdb->biCache, state->aBlockIdxHandle); + + state->aBlockIdxHandle = NULL; state->aBlockIdx = NULL; } if (state->pBlockData) { - tBlockDataDestroy(state->pBlockData, 1); + tBlockDataDestroy(state->pBlockData); state->pBlockData = NULL; } @@ -821,12 +1036,15 @@ int32_t clearNextRowFromFS(void *iter) { state->pDataFReader = NULL; }*/ if (state->aBlockIdx) { - taosArrayDestroy(state->aBlockIdx); + // taosArrayDestroy(state->aBlockIdx); + tsdbBICacheRelease(state->pTsdb->biCache, state->aBlockIdxHandle); + + state->aBlockIdxHandle = NULL; state->aBlockIdx = NULL; } if (state->pBlockData) { // tBlockDataDestroy(&state->blockData, 1); - tBlockDataDestroy(state->pBlockData, 1); + tBlockDataDestroy(state->pBlockData); state->pBlockData = NULL; } @@ -846,16 +1064,24 @@ typedef struct SMemNextRowIter { SMEMNEXTROWSTATES state; STbData *pMem; // [input] STbDataIter iter; // mem buffer skip list iterator + int64_t lastTs; // bool iterOpened; // TSDBROW *curRow; } SMemNextRowIter; -static int32_t getNextRowFromMem(void *iter, TSDBROW **ppRow) { +static int32_t getNextRowFromMem(void *iter, TSDBROW **ppRow, bool *pIgnoreEarlierTs, bool isLast, int16_t *aCols, + int nCols) { SMemNextRowIter *state = (SMemNextRowIter *)iter; int32_t code = 0; + *pIgnoreEarlierTs = false; switch (state->state) { case SMEMNEXTROW_ENTER: { if (state->pMem != NULL) { + if (state->pMem->maxKey <= state->lastTs) { + *ppRow = NULL; + *pIgnoreEarlierTs = true; + return code; + } tsdbTbDataIterOpen(state->pMem, NULL, 1, &state->iter); TSDBROW *pMemRow = tsdbTbDataIterGet(&state->iter); @@ -956,13 +1182,15 @@ static bool tsdbKeyDeleted(TSDBKEY *key, SArray *pSkyline, int64_t *iSkyline) { return deleted; } -typedef int32_t (*_next_row_fn_t)(void *iter, TSDBROW **ppRow); +typedef int32_t (*_next_row_fn_t)(void *iter, TSDBROW **ppRow, bool *pIgnoreEarlierTs, bool isLast, int16_t *aCols, + int nCols); typedef int32_t (*_next_row_clear_fn_t)(void *iter); typedef struct { TSDBROW *pRow; bool stop; bool next; + bool ignoreEarlierTs; void *iter; _next_row_fn_t nextRowFn; _next_row_clear_fn_t nextRowClearFn; @@ -984,8 +1212,8 @@ typedef struct { } CacheNextRowIter; static int32_t nextRowIterOpen(CacheNextRowIter *pIter, tb_uid_t uid, STsdb *pTsdb, STSchema *pTSchema, tb_uid_t suid, - SSttBlockLoadInfo *pLoadInfo, STsdbReadSnap *pReadSnap, SDataFReader **pDataFReader, - SDataFReader **pDataFReaderLast) { + SSttBlockLoadInfo *pLoadInfo, SLDataIter* pLDataIter, STsdbReadSnap *pReadSnap, SDataFReader **pDataFReader, + SDataFReader **pDataFReaderLast, int64_t lastTs) { int code = 0; STbData *pMem = NULL; @@ -1046,6 +1274,8 @@ static int32_t nextRowIterOpen(CacheNextRowIter *pIter, tb_uid_t uid, STsdb *pTs pIter->fsLastState.uid = uid; pIter->fsLastState.pLoadInfo = pLoadInfo; pIter->fsLastState.pDataFReader = pDataFReaderLast; + pIter->fsLastState.lastTs = lastTs; + pIter->fsLastState.pDataIter = pLDataIter; pIter->fsState.state = SFSNEXTROW_FS; pIter->fsState.pTsdb = pTsdb; @@ -1056,17 +1286,19 @@ static int32_t nextRowIterOpen(CacheNextRowIter *pIter, tb_uid_t uid, STsdb *pTs pIter->fsState.uid = uid; pIter->fsState.pLoadInfo = pLoadInfo; pIter->fsState.pDataFReader = pDataFReader; + pIter->fsState.lastTs = lastTs; - pIter->input[0] = (TsdbNextRowState){&pIter->memRow, true, false, &pIter->memState, getNextRowFromMem, NULL}; - pIter->input[1] = (TsdbNextRowState){&pIter->imemRow, true, false, &pIter->imemState, getNextRowFromMem, NULL}; - pIter->input[2] = (TsdbNextRowState){&pIter->fsLastRow, false, true, &pIter->fsLastState, getNextRowFromFSLast, - clearNextRowFromFSLast}; + pIter->input[0] = (TsdbNextRowState){&pIter->memRow, true, false, false, &pIter->memState, getNextRowFromMem, NULL}; + pIter->input[1] = (TsdbNextRowState){&pIter->imemRow, true, false, false, &pIter->imemState, getNextRowFromMem, NULL}; + pIter->input[2] = (TsdbNextRowState){ + &pIter->fsLastRow, false, true, false, &pIter->fsLastState, getNextRowFromFSLast, clearNextRowFromFSLast}; pIter->input[3] = - (TsdbNextRowState){&pIter->fsRow, false, true, &pIter->fsState, getNextRowFromFS, clearNextRowFromFS}; + (TsdbNextRowState){&pIter->fsRow, false, true, false, &pIter->fsState, getNextRowFromFS, clearNextRowFromFS}; if (pMem) { pIter->memState.pMem = pMem; pIter->memState.state = SMEMNEXTROW_ENTER; + pIter->memState.lastTs = lastTs; pIter->input[0].stop = false; pIter->input[0].next = true; } @@ -1074,6 +1306,7 @@ static int32_t nextRowIterOpen(CacheNextRowIter *pIter, tb_uid_t uid, STsdb *pTs if (pIMem) { pIter->imemState.pMem = pIMem; pIter->imemState.state = SMEMNEXTROW_ENTER; + pIter->imemState.lastTs = lastTs; pIter->input[1].stop = false; pIter->input[1].next = true; } @@ -1101,12 +1334,14 @@ _err: } // iterate next row non deleted backward ts, version (from high to low) -static int32_t nextRowIterGet(CacheNextRowIter *pIter, TSDBROW **ppRow) { +static int32_t nextRowIterGet(CacheNextRowIter *pIter, TSDBROW **ppRow, bool *pIgnoreEarlierTs, bool isLast, + int16_t *aCols, int nCols) { int code = 0; for (;;) { for (int i = 0; i < 4; ++i) { if (pIter->input[i].next && !pIter->input[i].stop) { - code = pIter->input[i].nextRowFn(pIter->input[i].iter, &pIter->input[i].pRow); + code = pIter->input[i].nextRowFn(pIter->input[i].iter, &pIter->input[i].pRow, &pIter->input[i].ignoreEarlierTs, + isLast, aCols, nCols); if (code) goto _err; if (pIter->input[i].pRow == NULL) { @@ -1118,6 +1353,8 @@ static int32_t nextRowIterGet(CacheNextRowIter *pIter, TSDBROW **ppRow) { if (pIter->input[0].stop && pIter->input[1].stop && pIter->input[2].stop && pIter->input[3].stop) { *ppRow = NULL; + *pIgnoreEarlierTs = (pIter->input[0].ignoreEarlierTs || pIter->input[1].ignoreEarlierTs || + pIter->input[2].ignoreEarlierTs || pIter->input[3].ignoreEarlierTs); return code; } @@ -1174,31 +1411,85 @@ _err: return code; } -static int32_t mergeLastRow(tb_uid_t uid, STsdb *pTsdb, bool *dup, SArray **ppColArray, SCacheRowsReader *pr) { - int32_t code = 0; +static int32_t initLastColArray(STSchema *pTSchema, SArray **ppColArray) { + SArray *pColArray = taosArrayInit(pTSchema->numOfCols, sizeof(SLastCol)); + if (NULL == pColArray) { + return TSDB_CODE_OUT_OF_MEMORY; + } + for (int32_t i = 0; i < pTSchema->numOfCols; ++i) { + SLastCol col = {.ts = 0, .colVal = COL_VAL_NULL(pTSchema->columns[i].colId, pTSchema->columns[i].type)}; + taosArrayPush(pColArray, &col); + } + *ppColArray = pColArray; + return TSDB_CODE_SUCCESS; +} + +static int32_t cloneTSchema(STSchema *pSrc, STSchema **ppDst) { + int32_t len = sizeof(STSchema) + sizeof(STColumn) * pSrc->numOfCols; + *ppDst = taosMemoryMalloc(len); + if (NULL == *ppDst) { + return TSDB_CODE_OUT_OF_MEMORY; + } + memcpy(*ppDst, pSrc, len); + return TSDB_CODE_SUCCESS; +} + +static int32_t updateTSchema(int32_t sversion, SCacheRowsReader *pReader, uint64_t uid) { + if (NULL == pReader->pCurrSchema && sversion == pReader->pSchema->version) { + return cloneTSchema(pReader->pSchema, &pReader->pCurrSchema); + } + + if (NULL != pReader->pCurrSchema && sversion == pReader->pCurrSchema->version) { + return TSDB_CODE_SUCCESS; + } + + taosMemoryFreeClear(pReader->pCurrSchema); + return metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->suid, uid, sversion, &pReader->pCurrSchema); +} + +static int32_t mergeLastRow(tb_uid_t uid, STsdb *pTsdb, bool *dup, SArray **ppColArray, SCacheRowsReader *pr) { STSchema *pTSchema = pr->pSchema; // metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1, 1); - int16_t nCol = pTSchema->numOfCols; + int16_t nLastCol = pTSchema->numOfCols; int16_t iCol = 0; int16_t noneCol = 0; bool setNoneCol = false; - SArray *pColArray = taosArrayInit(nCol, sizeof(SLastCol)); + bool hasRow = false; + bool ignoreEarlierTs = false; + SArray *pColArray = NULL; SColVal *pColVal = &(SColVal){0}; + int32_t code = initLastColArray(pTSchema, &pColArray); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + TSKEY lastRowTs = TSKEY_MAX; CacheNextRowIter iter = {0}; - nextRowIterOpen(&iter, uid, pTsdb, pTSchema, pr->suid, pr->pLoadInfo, pr->pReadSnap, &pr->pDataFReader, - &pr->pDataFReaderLast); + nextRowIterOpen(&iter, uid, pTsdb, pTSchema, pr->suid, pr->pLoadInfo, pr->pDataIter, pr->pReadSnap, &pr->pDataFReader, + &pr->pDataFReaderLast, pr->lastTs); do { TSDBROW *pRow = NULL; - nextRowIterGet(&iter, &pRow); + nextRowIterGet(&iter, &pRow, &ignoreEarlierTs, false, NULL, 0); if (!pRow) { break; } + hasRow = true; + + int32_t sversion = TSDBROW_SVERSION(pRow); + if (sversion != -1) { + code = updateTSchema(sversion, pr, uid); + if (TSDB_CODE_SUCCESS != code) { + goto _err; + } + pTSchema = pr->pCurrSchema; + } + int16_t nCol = pTSchema->numOfCols; + TSKEY rowTs = TSDBROW_TS(pRow); if (lastRowTs == TSKEY_MAX) { @@ -1206,29 +1497,27 @@ static int32_t mergeLastRow(tb_uid_t uid, STsdb *pTsdb, bool *dup, SArray **ppCo STColumn *pTColumn = &pTSchema->columns[0]; *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.val = lastRowTs}); - if (taosArrayPush(pColArray, &(SLastCol){.ts = lastRowTs, .colVal = *pColVal}) == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - code = TSDB_CODE_OUT_OF_MEMORY; - goto _err; - } + taosArraySet(pColArray, 0, &(SLastCol){.ts = lastRowTs, .colVal = *pColVal}); for (iCol = 1; iCol < nCol; ++iCol) { + if (iCol >= nLastCol) { + break; + } + SLastCol *pCol = taosArrayGet(pColArray, iCol); + if (pCol->colVal.cid != pTSchema->columns[iCol].colId) { + continue; + } tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal); - SLastCol lastCol = {.ts = lastRowTs, .colVal = *pColVal}; + *pCol = (SLastCol){.ts = lastRowTs, .colVal = *pColVal}; if (IS_VAR_DATA_TYPE(pColVal->type) && pColVal->value.nData > 0) { - lastCol.colVal.value.pData = taosMemoryMalloc(lastCol.colVal.value.nData); - if (lastCol.colVal.value.pData == NULL) { + pCol->colVal.value.pData = taosMemoryMalloc(pCol->colVal.value.nData); + if (pCol->colVal.value.pData == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; code = TSDB_CODE_OUT_OF_MEMORY; goto _err; } - memcpy(lastCol.colVal.value.pData, pColVal->value.pData, pColVal->value.nData); - } - - if (taosArrayPush(pColArray, &lastCol) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _err; + memcpy(pCol->colVal.value.pData, pColVal->value.pData, pColVal->value.nData); } if (COL_VAL_IS_NONE(pColVal) && !setNoneCol) { @@ -1281,12 +1570,20 @@ static int32_t mergeLastRow(tb_uid_t uid, STsdb *pTsdb, bool *dup, SArray **ppCo // build the result ts row here *dup = false; - if (taosArrayGetSize(pColArray) != nCol) { - *ppColArray = NULL; - taosArrayDestroy(pColArray); - } else { - *ppColArray = pColArray; + // if (taosArrayGetSize(pColArray) != nCol) { + //*ppColArray = NULL; + // taosArrayDestroy(pColArray); + //} else { + if (!hasRow) { + if (ignoreEarlierTs) { + taosArrayDestroy(pColArray); + pColArray = NULL; + } else { + taosArrayClear(pColArray); + } } + *ppColArray = pColArray; + //} nextRowIterClose(&iter); // taosMemoryFreeClear(pTSchema); @@ -1300,30 +1597,56 @@ _err: } static int32_t mergeLast(tb_uid_t uid, STsdb *pTsdb, SArray **ppLastArray, SCacheRowsReader *pr) { - int32_t code = 0; - STSchema *pTSchema = pr->pSchema; // metaGetTbTSchema(pTsdb->pVnode->pMeta, uid, -1, 1); - int16_t nCol = pTSchema->numOfCols; - int16_t iCol = 0; + int16_t nLastCol = pTSchema->numOfCols; int16_t noneCol = 0; bool setNoneCol = false; - SArray *pColArray = taosArrayInit(nCol, sizeof(SLastCol)); + bool hasRow = false; + bool ignoreEarlierTs = false; + SArray *pColArray = NULL; SColVal *pColVal = &(SColVal){0}; + int16_t nCols = nLastCol; + + int32_t code = initLastColArray(pTSchema, &pColArray); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + SArray *aColArray = taosArrayInit(nCols, sizeof(int16_t)); + if (NULL == aColArray) { + taosArrayDestroy(pColArray); + + return TSDB_CODE_OUT_OF_MEMORY; + } + for (int i = 1; i < pTSchema->numOfCols; ++i) { + taosArrayPush(aColArray, &pTSchema->columns[i].colId); + } TSKEY lastRowTs = TSKEY_MAX; CacheNextRowIter iter = {0}; - nextRowIterOpen(&iter, uid, pTsdb, pTSchema, pr->suid, pr->pLoadInfo, pr->pReadSnap, &pr->pDataFReader, - &pr->pDataFReaderLast); + nextRowIterOpen(&iter, uid, pTsdb, pTSchema, pr->suid, pr->pLoadInfo, pr->pDataIter, pr->pReadSnap, &pr->pDataFReader, + &pr->pDataFReaderLast, pr->lastTs); do { TSDBROW *pRow = NULL; - nextRowIterGet(&iter, &pRow); + nextRowIterGet(&iter, &pRow, &ignoreEarlierTs, true, TARRAY_DATA(aColArray), TARRAY_SIZE(aColArray)); if (!pRow) { break; } + hasRow = true; + + int32_t sversion = TSDBROW_SVERSION(pRow); + if (sversion != -1) { + code = updateTSchema(sversion, pr, uid); + if (TSDB_CODE_SUCCESS != code) { + goto _err; + } + pTSchema = pr->pCurrSchema; + } + int16_t nCol = pTSchema->numOfCols; + TSKEY rowTs = TSDBROW_TS(pRow); if (lastRowTs == TSKEY_MAX) { @@ -1331,33 +1654,37 @@ static int32_t mergeLast(tb_uid_t uid, STsdb *pTsdb, SArray **ppLastArray, SCach STColumn *pTColumn = &pTSchema->columns[0]; *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.val = lastRowTs}); - if (taosArrayPush(pColArray, &(SLastCol){.ts = lastRowTs, .colVal = *pColVal}) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _err; - } + taosArraySet(pColArray, 0, &(SLastCol){.ts = lastRowTs, .colVal = *pColVal}); - for (iCol = 1; iCol < nCol; ++iCol) { + for (int16_t iCol = 1; iCol < nCol; ++iCol) { + if (iCol >= nLastCol) { + break; + } + SLastCol *pCol = taosArrayGet(pColArray, iCol); + if (pCol->colVal.cid != pTSchema->columns[iCol].colId) { + continue; + } tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal); - SLastCol lastCol = {.ts = lastRowTs, .colVal = *pColVal}; + *pCol = (SLastCol){.ts = lastRowTs, .colVal = *pColVal}; if (IS_VAR_DATA_TYPE(pColVal->type) && pColVal->value.nData > 0) { - lastCol.colVal.value.pData = taosMemoryMalloc(lastCol.colVal.value.nData); - if (lastCol.colVal.value.pData == NULL) { + pCol->colVal.value.pData = taosMemoryMalloc(pCol->colVal.value.nData); + if (pCol->colVal.value.pData == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; code = TSDB_CODE_OUT_OF_MEMORY; goto _err; } - memcpy(lastCol.colVal.value.pData, pColVal->value.pData, pColVal->value.nData); - } - - if (taosArrayPush(pColArray, &lastCol) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _err; + memcpy(pCol->colVal.value.pData, pColVal->value.pData, pColVal->value.nData); } - if (!COL_VAL_IS_VALUE(pColVal) && !setNoneCol) { - noneCol = iCol; - setNoneCol = true; + if (!COL_VAL_IS_VALUE(pColVal)) { + if (!setNoneCol) { + noneCol = iCol; + setNoneCol = true; + } + } else { + int32_t aColIndex = taosArraySearchIdx(aColArray, &pColVal->cid, compareInt16Val, TD_EQ); + taosArrayRemove(aColArray, aColIndex); } } if (!setNoneCol) { @@ -1370,10 +1697,16 @@ static int32_t mergeLast(tb_uid_t uid, STsdb *pTsdb, SArray **ppLastArray, SCach // merge into pColArray setNoneCol = false; - for (iCol = noneCol; iCol < nCol; ++iCol) { + for (int16_t iCol = noneCol; iCol < nCol; ++iCol) { + if (iCol >= nLastCol) { + break; + } // high version's column value SLastCol *lastColVal = (SLastCol *)taosArrayGet(pColArray, iCol); - SColVal *tColVal = &lastColVal->colVal; + if (lastColVal->colVal.cid != pTSchema->columns[iCol].colId) { + continue; + } + SColVal *tColVal = &lastColVal->colVal; tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal); if (!COL_VAL_IS_VALUE(tColVal) && COL_VAL_IS_VALUE(pColVal)) { @@ -1392,6 +1725,8 @@ static int32_t mergeLast(tb_uid_t uid, STsdb *pTsdb, SArray **ppLastArray, SCach } taosArraySet(pColArray, iCol, &lastCol); + int32_t aColIndex = taosArraySearchIdx(aColArray, &lastCol.colVal.cid, compareInt16Val, TD_EQ); + taosArrayRemove(aColArray, aColIndex); } else if (!COL_VAL_IS_VALUE(tColVal) && !COL_VAL_IS_VALUE(pColVal) && !setNoneCol) { noneCol = iCol; setNoneCol = true; @@ -1399,14 +1734,23 @@ static int32_t mergeLast(tb_uid_t uid, STsdb *pTsdb, SArray **ppLastArray, SCach } } while (setNoneCol); - if (taosArrayGetSize(pColArray) <= 0) { - *ppLastArray = NULL; - taosArrayDestroy(pColArray); - } else { - *ppLastArray = pColArray; + // if (taosArrayGetSize(pColArray) <= 0) { + //*ppLastArray = NULL; + // taosArrayDestroy(pColArray); + //} else { + if (!hasRow) { + if (ignoreEarlierTs) { + taosArrayDestroy(pColArray); + pColArray = NULL; + } else { + taosArrayClear(pColArray); + } } + *ppLastArray = pColArray; + //} nextRowIterClose(&iter); + taosArrayDestroy(aColArray); // taosMemoryFreeClear(pTSchema); return code; @@ -1415,6 +1759,7 @@ _err: // taosMemoryFreeClear(pTSchema); *ppLastArray = NULL; taosArrayDestroy(pColArray); + taosArrayDestroy(aColArray); return code; } @@ -1435,7 +1780,7 @@ int32_t tsdbCacheGetLastrowH(SLRUCache *pCache, tb_uid_t uid, SCacheRowsReader * SArray *pArray = NULL; bool dup = false; // which is always false for now code = mergeLastRow(uid, pTsdb, &dup, &pArray, pr); - // if table's empty or error, return code of -1 + // if table's empty or error or ignore ignore earlier ts, set handle NULL and return if (code < 0 || pArray == NULL) { if (!dup && pArray) { taosArrayDestroy(pArray); @@ -1454,13 +1799,8 @@ int32_t tsdbCacheGetLastrowH(SLRUCache *pCache, tb_uid_t uid, SCacheRowsReader * if (status != TAOS_LRU_STATUS_OK) { code = -1; } - - // taosThreadMutexUnlock(&pTsdb->lruMutex); - - // h = taosLRUCacheLookup(pCache, key, keyLen); - } // else { + } taosThreadMutexUnlock(&pTsdb->lruMutex); - //} } *handle = h; @@ -1484,7 +1824,7 @@ int32_t tsdbCacheGetLastH(SLRUCache *pCache, tb_uid_t uid, SCacheRowsReader *pr, if (!h) { SArray *pLastArray = NULL; code = mergeLast(uid, pTsdb, &pLastArray, pr); - // if table's empty or error, return code of -1 + // if table's empty or error or ignore ignore earlier ts, set handle NULL and return if (code < 0 || pLastArray == NULL) { taosThreadMutexUnlock(&pTsdb->lruMutex); @@ -1499,13 +1839,8 @@ int32_t tsdbCacheGetLastH(SLRUCache *pCache, tb_uid_t uid, SCacheRowsReader *pr, if (status != TAOS_LRU_STATUS_OK) { code = -1; } - - // taosThreadMutexUnlock(&pTsdb->lruMutex); - - // h = taosLRUCacheLookup(pCache, key, keyLen); - } // else { + } taosThreadMutexUnlock(&pTsdb->lruMutex); - //} } *handle = h; @@ -1536,6 +1871,15 @@ size_t tsdbCacheGetUsage(SVnode *pVnode) { return usage; } +int32_t tsdbCacheGetElems(SVnode *pVnode) { + int32_t elems = 0; + if (pVnode->pTsdb != NULL) { + elems = taosLRUCacheGetElems(pVnode->pTsdb->lruCache); + } + + return elems; +} + static void getBICacheKey(int32_t fid, int64_t commitID, char *key, int *len) { struct { int32_t fid; @@ -1604,6 +1948,7 @@ int32_t tsdbCacheGetBlockIdx(SLRUCache *pCache, SDataFReader *pFileReader, LRUHa taosThreadMutexUnlock(&pTsdb->biMutex); } + tsdbTrace("bi cache:%p, ref", pCache); *handle = h; return code; @@ -1613,6 +1958,7 @@ int32_t tsdbBICacheRelease(SLRUCache *pCache, LRUHandle *h) { int32_t code = 0; taosLRUCacheRelease(pCache, h, false); + tsdbTrace("bi cache:%p, release", pCache); return code; } diff --git a/source/dnode/vnode/src/tsdb/tsdbCacheRead.c b/source/dnode/vnode/src/tsdb/tsdbCacheRead.c index c94d2130c5c1939d5c8b9b7769292d19c0a732df..a196c2d398c5e724422d4df323ea7783e7c0efa0 100644 --- a/source/dnode/vnode/src/tsdb/tsdbCacheRead.c +++ b/source/dnode/vnode/src/tsdb/tsdbCacheRead.c @@ -38,16 +38,17 @@ static int32_t saveOneRow(SArray* pRow, SSDataBlock* pBlock, SCacheRowsReader* p *(int64_t*)p->buf = pColVal->ts; allNullRow = false; } else { - int32_t slotId = slotIds[i]; - SLastCol* pColVal = (SLastCol*)taosArrayGet(pRow, slotId); - + int32_t slotId = slotIds[i]; // add check for null value, caused by the modification of table schema (new column added). - if (pColVal == NULL) { + if (slotId >= taosArrayGetSize(pRow)) { p->ts = 0; p->isNull = true; + colDataSetNULL(pColInfoData, numOfRows); continue; } + SLastCol* pColVal = (SLastCol*)taosArrayGet(pRow, slotId); + p->ts = pColVal->ts; p->isNull = !COL_VAL_IS_VALUE(&pColVal->colVal); allNullRow = p->isNull & allNullRow; @@ -67,7 +68,7 @@ static int32_t saveOneRow(SArray* pRow, SSDataBlock* pBlock, SCacheRowsReader* p // pColInfoData->info.bytes includes the VARSTR_HEADER_SIZE, need to substruct it p->hasResult = true; varDataSetLen(pRes[i], pColInfoData->info.bytes - VARSTR_HEADER_SIZE); - colDataAppend(pColInfoData, numOfRows, (const char*)pRes[i], false); + colDataSetVal(pColInfoData, numOfRows, (const char*)pRes[i], false); } pBlock->info.rows += allNullRow ? 0 : 1; @@ -77,22 +78,27 @@ static int32_t saveOneRow(SArray* pRow, SSDataBlock* pBlock, SCacheRowsReader* p if (slotIds[i] == -1) { SLastCol* pColVal = (SLastCol*)taosArrayGet(pRow, 0); - colDataAppend(pColInfoData, numOfRows, (const char*)&pColVal->ts, false); + colDataSetVal(pColInfoData, numOfRows, (const char*)&pColVal->ts, false); } else { - int32_t slotId = slotIds[i]; + int32_t slotId = slotIds[i]; + // add check for null value, caused by the modification of table schema (new column added). + if (slotId >= taosArrayGetSize(pRow)) { + colDataSetNULL(pColInfoData, numOfRows); + continue; + } SLastCol* pColVal = (SLastCol*)taosArrayGet(pRow, slotId); SColVal* pVal = &pColVal->colVal; if (IS_VAR_DATA_TYPE(pColVal->colVal.type)) { if (!COL_VAL_IS_VALUE(&pColVal->colVal)) { - colDataAppendNULL(pColInfoData, numOfRows); + colDataSetNULL(pColInfoData, numOfRows); } else { varDataSetLen(pReader->transferBuf[slotId], pVal->value.nData); memcpy(varDataVal(pReader->transferBuf[slotId]), pVal->value.pData, pVal->value.nData); - colDataAppend(pColInfoData, numOfRows, pReader->transferBuf[slotId], false); + colDataSetVal(pColInfoData, numOfRows, pReader->transferBuf[slotId], false); } } else { - colDataAppend(pColInfoData, numOfRows, (const char*)&pVal->value.val, !COL_VAL_IS_VALUE(pVal)); + colDataSetVal(pColInfoData, numOfRows, (const char*)&pVal->value.val, !COL_VAL_IS_VALUE(pVal)); } } } @@ -112,7 +118,6 @@ static int32_t setTableSchema(SCacheRowsReader* p, uint64_t suid, const char* id if (suid != 0) { p->pSchema = metaGetTbTSchema(p->pVnode->pMeta, suid, -1, 1); if (p->pSchema == NULL) { - taosMemoryFree(p); tsdbWarn("stable:%" PRIu64 " has been dropped, failed to retrieve cached rows, %s", suid, idstr); return TSDB_CODE_PAR_TABLE_NOT_EXIST; } @@ -129,7 +134,6 @@ static int32_t setTableSchema(SCacheRowsReader* p, uint64_t suid, const char* id // all queried tables have been dropped already, return immediately. if (p->pSchema == NULL) { - taosMemoryFree(p); tsdbWarn("all queried tables has been dropped, try next group, %s", idstr); return TSDB_CODE_PAR_TABLE_NOT_EXIST; } @@ -138,6 +142,18 @@ static int32_t setTableSchema(SCacheRowsReader* p, uint64_t suid, const char* id return TSDB_CODE_SUCCESS; } +int32_t tsdbReuseCacherowsReader(void* reader, void* pTableIdList, int32_t numOfTables) { + SCacheRowsReader* pReader = (SCacheRowsReader*)reader; + + pReader->pTableList = pTableIdList; + pReader->numOfTables = numOfTables; + pReader->lastTs = INT64_MIN; + + resetLastBlockLoadInfo(pReader->pLoadInfo); + + return TSDB_CODE_SUCCESS; +} + int32_t tsdbCacherowsReaderOpen(void* pVnode, int32_t type, void* pTableIdList, int32_t numOfTables, int32_t numOfCols, uint64_t suid, void** pReader, const char* idstr) { *pReader = NULL; @@ -148,6 +164,8 @@ int32_t tsdbCacherowsReaderOpen(void* pVnode, int32_t type, void* pTableIdList, p->type = type; p->pVnode = pVnode; + p->pTsdb = p->pVnode->pTsdb; + p->verRange = (SVersionRange){.minVer = 0, .maxVer = UINT64_MAX}; p->numOfCols = numOfCols; p->suid = suid; @@ -181,14 +199,25 @@ int32_t tsdbCacherowsReaderOpen(void* pVnode, int32_t type, void* pTableIdList, } } - int32_t numOfStt = ((SVnode*)pVnode)->config.sttTrigger; + SVnodeCfg* pCfg = &((SVnode*)pVnode)->config; + + int32_t numOfStt = pCfg->sttTrigger; p->pLoadInfo = tCreateLastBlockLoadInfo(p->pSchema, NULL, 0, numOfStt); if (p->pLoadInfo == NULL) { tsdbCacherowsReaderClose(p); return TSDB_CODE_OUT_OF_MEMORY; } - p->idstr = taosMemoryStrDup(idstr); + p->pDataIter = taosMemoryCalloc(pCfg->sttTrigger, sizeof(SLDataIter)); + if (p->pDataIter == NULL) { + tsdbCacherowsReaderClose(p); + return TSDB_CODE_OUT_OF_MEMORY; + } + + p->idstr = taosStrdup(idstr); + taosThreadMutexInit(&p->readerMutex, NULL); + + p->lastTs = INT64_MIN; *pReader = p; return TSDB_CODE_SUCCESS; @@ -206,9 +235,14 @@ void* tsdbCacherowsReaderClose(void* pReader) { taosMemoryFree(p->pSchema); } + taosMemoryFreeClear(p->pDataIter); + taosMemoryFree(p->pCurrSchema); + destroyLastBlockLoadInfo(p->pLoadInfo); taosMemoryFree((void*)p->idstr); + taosThreadMutexDestroy(&p->readerMutex); + taosMemoryFree(pReader); return NULL; } @@ -243,6 +277,27 @@ static void freeItem(void* pItem) { } } +static int32_t tsdbCacheQueryReseek(void* pQHandle) { + int32_t code = 0; + SCacheRowsReader* pReader = pQHandle; + + code = taosThreadMutexTryLock(&pReader->readerMutex); + if (code == 0) { + // pause current reader's state if not paused, save ts & version for resuming + // just wait for the big all tables' snapshot untaking for now + + code = TSDB_CODE_VND_QUERY_BUSY; + + taosThreadMutexUnlock(&pReader->readerMutex); + + return code; + } else if (code == EBUSY) { + return TSDB_CODE_VND_QUERY_BUSY; + } else { + return -1; + } +} + int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32_t* slotIds, SArray* pTableUidList) { if (pReader == NULL || pResBlock == NULL) { return TSDB_CODE_INVALID_PARA; @@ -264,7 +319,8 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 } for (int32_t j = 0; j < pr->numOfCols; ++j) { - pRes[j] = taosMemoryCalloc(1, sizeof(SFirstLastRes) + pr->pSchema->columns[slotIds[j]].bytes + VARSTR_HEADER_SIZE); + pRes[j] = taosMemoryCalloc( + 1, sizeof(SFirstLastRes) + pr->pSchema->columns[-1 == slotIds[j] ? 0 : slotIds[j]].bytes + VARSTR_HEADER_SIZE); SFirstLastRes* p = (SFirstLastRes*)varDataVal(pRes[j]); p->ts = INT64_MIN; } @@ -277,7 +333,7 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 for (int32_t i = 0; i < pr->pSchema->numOfCols; ++i) { struct STColumn* pCol = &pr->pSchema->columns[i]; - SLastCol p = {.ts = INT64_MIN, .colVal.type = pCol->type}; + SLastCol p = {.ts = INT64_MIN, .colVal.type = pCol->type, .colVal.flag = CV_FLAG_NULL}; if (IS_VAR_DATA_TYPE(pCol->type)) { p.colVal.value.pData = taosMemoryCalloc(pCol->bytes, sizeof(char)); @@ -285,16 +341,18 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 taosArrayPush(pLastCols, &p); } - code = tsdbTakeReadSnap(pr->pVnode->pTsdb, &pr->pReadSnap, "cache-l"); + taosThreadMutexLock(&pr->readerMutex); + code = tsdbTakeReadSnap((STsdbReader*)pr, tsdbCacheQueryReseek, &pr->pReadSnap); if (code != TSDB_CODE_SUCCESS) { goto _end; } - pr->pDataFReader = NULL; pr->pDataFReaderLast = NULL; // retrieve the only one last row of all tables in the uid list. if (HASTYPE(pr->type, CACHESCAN_RETRIEVE_TYPE_SINGLE)) { + int64_t st = taosGetTimestampUs(); + int64_t totalLastTs = INT64_MAX; for (int32_t i = 0; i < pr->numOfTables; ++i) { STableKeyInfo* pKeyInfo = &pr->pTableList[i]; @@ -306,8 +364,14 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 if (h == NULL) { continue; } + if (taosArrayGetSize(pRow) <= 0) { + tsdbCacheRelease(lruCache, h); + continue; + } { + bool hasNotNullRow = true; + int64_t singleTableLastTs = INT64_MAX; for (int32_t k = 0; k < pr->numOfCols; ++k) { int32_t slotId = slotIds[k]; @@ -318,6 +382,7 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 hasRes = true; p->ts = pCol->ts; p->colVal = pCol->colVal; + singleTableLastTs = pCol->ts; // only set value for last row query if (HASTYPE(pr->type, CACHESCAN_RETRIEVE_LAST_ROW)) { @@ -334,11 +399,17 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 if (pColVal->ts > p->ts) { if (!COL_VAL_IS_VALUE(&pColVal->colVal) && HASTYPE(pr->type, CACHESCAN_RETRIEVE_LAST)) { + if (!COL_VAL_IS_VALUE(&p->colVal)) { + hasNotNullRow = false; + } continue; } hasRes = true; p->ts = pColVal->ts; + if (pColVal->ts < singleTableLastTs && HASTYPE(pr->type, CACHESCAN_RETRIEVE_LAST)) { + singleTableLastTs = pColVal->ts; + } if (!IS_VAR_DATA_TYPE(pColVal->colVal.type)) { p->colVal = pColVal->colVal; @@ -355,6 +426,16 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 } } } + + if (hasNotNullRow) { + if (INT64_MAX == totalLastTs || (INT64_MAX != singleTableLastTs && totalLastTs < singleTableLastTs)) { + totalLastTs = singleTableLastTs; + } + double cost = (taosGetTimestampUs() - st) / 1000.0; + if (cost > tsCacheLazyLoadThreshold) { + pr->lastTs = totalLastTs; + } + } } tsdbCacheRelease(lruCache, h); @@ -363,7 +444,6 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 if (hasRes) { saveOneRow(pLastCols, pResBlock, pr, slotIds, pRes, pr->idstr); } - } else if (HASTYPE(pr->type, CACHESCAN_RETRIEVE_TYPE_ALL)) { for (int32_t i = pr->tableIndex; i < pr->numOfTables; ++i) { STableKeyInfo* pKeyInfo = &pr->pTableList[i]; @@ -375,6 +455,10 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 if (h == NULL) { continue; } + if (taosArrayGetSize(pRow) <= 0) { + tsdbCacheRelease(lruCache, h); + continue; + } saveOneRow(pRow, pResBlock, pr, slotIds, pRes, pr->idstr); // TODO reset the pRes @@ -395,11 +479,14 @@ _end: tsdbDataFReaderClose(&pr->pDataFReaderLast); tsdbDataFReaderClose(&pr->pDataFReader); - tsdbUntakeReadSnap(pr->pVnode->pTsdb, pr->pReadSnap, "cache-l"); resetLastBlockLoadInfo(pr->pLoadInfo); + tsdbUntakeReadSnap((STsdbReader*)pr, pr->pReadSnap, true); + taosThreadMutexUnlock(&pr->readerMutex); - for (int32_t j = 0; j < pr->numOfCols; ++j) { - taosMemoryFree(pRes[j]); + if (pRes != NULL) { + for (int32_t j = 0; j < pr->numOfCols; ++j) { + taosMemoryFree(pRes[j]); + } } taosMemoryFree(pRes); diff --git a/source/dnode/vnode/src/tsdb/tsdbCommit.c b/source/dnode/vnode/src/tsdb/tsdbCommit.c index 8ec59ea95949a4bccda38c7cc2fda25e2f769fb4..d15f848cfdcde11c946a943d96b0397933324b14 100644 --- a/source/dnode/vnode/src/tsdb/tsdbCommit.c +++ b/source/dnode/vnode/src/tsdb/tsdbCommit.c @@ -175,7 +175,7 @@ int32_t tsdbCommit(STsdb *pTsdb, SCommitInfo *pInfo) { pTsdb->imem = NULL; taosThreadRwlockUnlock(&pTsdb->rwLock); - tsdbUnrefMemTable(pMemTable); + tsdbUnrefMemTable(pMemTable, NULL, true); goto _exit; } @@ -913,24 +913,24 @@ static void tsdbCommitDataEnd(SCommitter *pCommitter) { // reader taosArrayDestroy(pCommitter->dReader.aBlockIdx); tMapDataClear(&pCommitter->dReader.mBlock); - tBlockDataDestroy(&pCommitter->dReader.bData, 1); + tBlockDataDestroy(&pCommitter->dReader.bData); // merger for (int32_t iStt = 0; iStt < TSDB_MAX_STT_TRIGGER; iStt++) { SDataIter *pIter = &pCommitter->aDataIter[iStt]; taosArrayDestroy(pIter->aSttBlk); - tBlockDataDestroy(&pIter->bData, 1); + tBlockDataDestroy(&pIter->bData); } // writer taosArrayDestroy(pCommitter->dWriter.aBlockIdx); taosArrayDestroy(pCommitter->dWriter.aSttBlk); tMapDataClear(&pCommitter->dWriter.mBlock); - tBlockDataDestroy(&pCommitter->dWriter.bData, 1); + tBlockDataDestroy(&pCommitter->dWriter.bData); #if USE_STREAM_COMPRESSION tDiskDataBuilderDestroy(pCommitter->dWriter.pBuilder); #else - tBlockDataDestroy(&pCommitter->dWriter.bDatal, 1); + tBlockDataDestroy(&pCommitter->dWriter.bDatal); #endif tDestroyTSchema(pCommitter->skmTable.pTSchema); tDestroyTSchema(pCommitter->skmRow.pTSchema); @@ -1183,7 +1183,6 @@ static int32_t tsdbCommitAheadBlock(SCommitter *pCommitter, SDataBlk *pDataBlk) tBlockDataClear(pBlockData); while (pRowInfo) { - ASSERT(pRowInfo->row.type == 0); code = tsdbCommitterUpdateRowSchema(pCommitter, id.suid, id.uid, TSDBROW_SVERSION(&pRowInfo->row)); TSDB_CHECK_CODE(code, lino, _exit); @@ -1251,7 +1250,6 @@ static int32_t tsdbCommitMergeBlock(SCommitter *pCommitter, SDataBlk *pDataBlk) pRow = NULL; } } else if (c > 0) { - ASSERT(pRowInfo->row.type == 0); code = tsdbCommitterUpdateRowSchema(pCommitter, id.suid, id.uid, TSDBROW_SVERSION(&pRowInfo->row)); TSDB_CHECK_CODE(code, lino, _exit); @@ -1493,7 +1491,7 @@ static int32_t tsdbCommitTableData(SCommitter *pCommitter, TABLEID id) { while (pRowInfo) { STSchema *pTSchema = NULL; - if (pRowInfo->row.type == 0) { + if (pRowInfo->row.type == TSDBROW_ROW_FMT) { code = tsdbCommitterUpdateRowSchema(pCommitter, id.suid, id.uid, TSDBROW_SVERSION(&pRowInfo->row)); TSDB_CHECK_CODE(code, lino, _exit); pTSchema = pCommitter->skmRow.pTSchema; @@ -1536,7 +1534,7 @@ static int32_t tsdbCommitTableData(SCommitter *pCommitter, TABLEID id) { while (pRowInfo) { STSchema *pTSchema = NULL; - if (pRowInfo->row.type == 0) { + if (pRowInfo->row.type == TSDBROW_ROW_FMT) { code = tsdbCommitterUpdateRowSchema(pCommitter, id.suid, id.uid, TSDBROW_SVERSION(&pRowInfo->row)); TSDB_CHECK_CODE(code, lino, _exit); pTSchema = pCommitter->skmRow.pTSchema; @@ -1666,7 +1664,7 @@ int32_t tsdbFinishCommit(STsdb *pTsdb) { // unlock taosThreadRwlockUnlock(&pTsdb->rwLock); if (pMemTable) { - tsdbUnrefMemTable(pMemTable); + tsdbUnrefMemTable(pMemTable, NULL, true); } _exit: diff --git a/source/dnode/vnode/src/tsdb/tsdbDataIter.c b/source/dnode/vnode/src/tsdb/tsdbDataIter.c new file mode 100644 index 0000000000000000000000000000000000000000..e27aec5b1bad10afeb06cb857661ee117aea7e12 --- /dev/null +++ b/source/dnode/vnode/src/tsdb/tsdbDataIter.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "tsdb.h" +#include "vnodeInt.h" + +// STsdbDataIter2 +/* open */ +int32_t tsdbOpenDataFileDataIter(SDataFReader* pReader, STsdbDataIter2** ppIter) { + int32_t code = 0; + int32_t lino = 0; + + // create handle + STsdbDataIter2* pIter = (STsdbDataIter2*)taosMemoryCalloc(1, sizeof(*pIter)); + if (pIter == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + + pIter->type = TSDB_DATA_FILE_DATA_ITER; + pIter->dIter.pReader = pReader; + if ((pIter->dIter.aBlockIdx = taosArrayInit(0, sizeof(SBlockIdx))) == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + + code = tBlockDataCreate(&pIter->dIter.bData); + TSDB_CHECK_CODE(code, lino, _exit); + + pIter->dIter.iBlockIdx = 0; + pIter->dIter.iDataBlk = 0; + pIter->dIter.iRow = 0; + + // read data + code = tsdbReadBlockIdx(pReader, pIter->dIter.aBlockIdx); + TSDB_CHECK_CODE(code, lino, _exit); + + if (taosArrayGetSize(pIter->dIter.aBlockIdx) == 0) goto _clear; + +_exit: + if (code) { + if (pIter) { + _clear: + tBlockDataDestroy(&pIter->dIter.bData); + taosArrayDestroy(pIter->dIter.aBlockIdx); + taosMemoryFree(pIter); + pIter = NULL; + } + } + *ppIter = pIter; + return code; +} + +int32_t tsdbOpenSttFileDataIter(SDataFReader* pReader, int32_t iStt, STsdbDataIter2** ppIter) { + int32_t code = 0; + int32_t lino = 0; + + // create handle + STsdbDataIter2* pIter = (STsdbDataIter2*)taosMemoryCalloc(1, sizeof(*pIter)); + if (pIter == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + + pIter->type = TSDB_STT_FILE_DATA_ITER; + pIter->sIter.pReader = pReader; + pIter->sIter.iStt = iStt; + pIter->sIter.aSttBlk = taosArrayInit(0, sizeof(SSttBlk)); + if (pIter->sIter.aSttBlk == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + + code = tBlockDataCreate(&pIter->sIter.bData); + TSDB_CHECK_CODE(code, lino, _exit); + + pIter->sIter.iSttBlk = 0; + pIter->sIter.iRow = 0; + + // read data + code = tsdbReadSttBlk(pReader, iStt, pIter->sIter.aSttBlk); + TSDB_CHECK_CODE(code, lino, _exit); + + if (taosArrayGetSize(pIter->sIter.aSttBlk) == 0) goto _clear; + +_exit: + if (code) { + if (pIter) { + _clear: + taosArrayDestroy(pIter->sIter.aSttBlk); + tBlockDataDestroy(&pIter->sIter.bData); + taosMemoryFree(pIter); + pIter = NULL; + } + } + *ppIter = pIter; + return code; +} + +int32_t tsdbOpenTombFileDataIter(SDelFReader* pReader, STsdbDataIter2** ppIter) { + int32_t code = 0; + int32_t lino = 0; + + STsdbDataIter2* pIter = (STsdbDataIter2*)taosMemoryCalloc(1, sizeof(*pIter)); + if (pIter == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + pIter->type = TSDB_TOMB_FILE_DATA_ITER; + + pIter->tIter.pReader = pReader; + if ((pIter->tIter.aDelIdx = taosArrayInit(0, sizeof(SDelIdx))) == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + if ((pIter->tIter.aDelData = taosArrayInit(0, sizeof(SDelData))) == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + + code = tsdbReadDelIdx(pReader, pIter->tIter.aDelIdx); + TSDB_CHECK_CODE(code, lino, _exit); + + if (taosArrayGetSize(pIter->tIter.aDelIdx) == 0) goto _clear; + + pIter->tIter.iDelIdx = 0; + pIter->tIter.iDelData = 0; + +_exit: + if (code) { + if (pIter) { + _clear: + taosArrayDestroy(pIter->tIter.aDelIdx); + taosArrayDestroy(pIter->tIter.aDelData); + taosMemoryFree(pIter); + pIter = NULL; + } + } + *ppIter = pIter; + return code; +} + +/* close */ +static void tsdbCloseDataFileDataIter(STsdbDataIter2* pIter) { + tBlockDataDestroy(&pIter->dIter.bData); + tMapDataClear(&pIter->dIter.mDataBlk); + taosArrayDestroy(pIter->dIter.aBlockIdx); + taosMemoryFree(pIter); +} + +static void tsdbCloseSttFileDataIter(STsdbDataIter2* pIter) { + tBlockDataDestroy(&pIter->sIter.bData); + taosArrayDestroy(pIter->sIter.aSttBlk); + taosMemoryFree(pIter); +} + +static void tsdbCloseTombFileDataIter(STsdbDataIter2* pIter) { + taosArrayDestroy(pIter->tIter.aDelData); + taosArrayDestroy(pIter->tIter.aDelIdx); + taosMemoryFree(pIter); +} + +void tsdbCloseDataIter2(STsdbDataIter2* pIter) { + if (pIter->type == TSDB_MEM_TABLE_DATA_ITER) { + ASSERT(0); + } else if (pIter->type == TSDB_DATA_FILE_DATA_ITER) { + tsdbCloseDataFileDataIter(pIter); + } else if (pIter->type == TSDB_STT_FILE_DATA_ITER) { + tsdbCloseSttFileDataIter(pIter); + } else if (pIter->type == TSDB_TOMB_FILE_DATA_ITER) { + tsdbCloseTombFileDataIter(pIter); + } else { + ASSERT(0); + } +} + +/* cmpr */ +int32_t tsdbDataIterCmprFn(const SRBTreeNode* pNode1, const SRBTreeNode* pNode2) { + STsdbDataIter2* pIter1 = TSDB_RBTN_TO_DATA_ITER(pNode1); + STsdbDataIter2* pIter2 = TSDB_RBTN_TO_DATA_ITER(pNode2); + return tRowInfoCmprFn(&pIter1->rowInfo, &pIter2->rowInfo); +} + +/* seek */ + +/* iter next */ +static int32_t tsdbDataFileDataIterNext(STsdbDataIter2* pIter, STsdbFilterInfo* pFilterInfo) { + int32_t code = 0; + int32_t lino = 0; + + for (;;) { + while (pIter->dIter.iRow < pIter->dIter.bData.nRow) { + if (pFilterInfo) { + if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { + if (pIter->dIter.bData.aVersion[pIter->dIter.iRow] < pFilterInfo->sver || + pIter->dIter.bData.aVersion[pIter->dIter.iRow] > pFilterInfo->ever) { + pIter->dIter.iRow++; + continue; + } + } + } + + ASSERT(pIter->rowInfo.suid == pIter->dIter.bData.suid); + ASSERT(pIter->rowInfo.uid == pIter->dIter.bData.uid); + pIter->rowInfo.row = tsdbRowFromBlockData(&pIter->dIter.bData, pIter->dIter.iRow); + pIter->dIter.iRow++; + goto _exit; + } + + for (;;) { + while (pIter->dIter.iDataBlk < pIter->dIter.mDataBlk.nItem) { + SDataBlk dataBlk; + tMapDataGetItemByIdx(&pIter->dIter.mDataBlk, pIter->dIter.iDataBlk, &dataBlk, tGetDataBlk); + + // filter + if (pFilterInfo) { + if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { + if (pFilterInfo->sver > dataBlk.maxVer || pFilterInfo->ever < dataBlk.minVer) { + pIter->dIter.iDataBlk++; + continue; + } + } + } + + code = tsdbReadDataBlockEx(pIter->dIter.pReader, &dataBlk, &pIter->dIter.bData); + TSDB_CHECK_CODE(code, lino, _exit); + + pIter->dIter.iDataBlk++; + pIter->dIter.iRow = 0; + + break; + } + + if (pIter->dIter.iRow < pIter->dIter.bData.nRow) break; + + for (;;) { + if (pIter->dIter.iBlockIdx < taosArrayGetSize(pIter->dIter.aBlockIdx)) { + SBlockIdx* pBlockIdx = taosArrayGet(pIter->dIter.aBlockIdx, pIter->dIter.iBlockIdx); + + if (pFilterInfo) { + if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_TABLEID) { + int32_t c = tTABLEIDCmprFn(pBlockIdx, &pFilterInfo->tbid); + if (c == 0) { + pIter->dIter.iBlockIdx++; + continue; + } else if (c < 0) { + ASSERT(0); + } + } + + if (pFilterInfo->flag & TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE) { + SMetaInfo info; + if (metaGetInfo(pIter->dIter.pReader->pTsdb->pVnode->pMeta, pBlockIdx->uid, &info, NULL)) { + pIter->dIter.iBlockIdx++; + continue; + } + } + } + + code = tsdbReadDataBlk(pIter->dIter.pReader, pBlockIdx, &pIter->dIter.mDataBlk); + TSDB_CHECK_CODE(code, lino, _exit); + + pIter->rowInfo.suid = pBlockIdx->suid; + pIter->rowInfo.uid = pBlockIdx->uid; + + pIter->dIter.iBlockIdx++; + pIter->dIter.iDataBlk = 0; + + break; + } else { + pIter->rowInfo = (SRowInfo){0}; + goto _exit; + } + } + } + } + +_exit: + if (code) { + tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code)); + } + return code; +} + +static int32_t tsdbSttFileDataIterNext(STsdbDataIter2* pIter, STsdbFilterInfo* pFilterInfo) { + int32_t code = 0; + int32_t lino = 0; + + for (;;) { + while (pIter->sIter.iRow < pIter->sIter.bData.nRow) { + if (pFilterInfo) { + int64_t uid = pIter->sIter.bData.uid ? pIter->sIter.bData.uid : pIter->sIter.bData.aUid[pIter->sIter.iRow]; + if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_TABLEID) { + if (pFilterInfo->tbid.uid == uid) { + pIter->sIter.iRow++; + continue; + } + } + + if (pFilterInfo->flag & TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE) { + if (pIter->rowInfo.uid != uid) { + SMetaInfo info; + if (metaGetInfo(pIter->sIter.pReader->pTsdb->pVnode->pMeta, uid, &info, NULL)) { + pIter->sIter.iRow++; + continue; + } + } + } + + if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { + if (pFilterInfo->sver > pIter->sIter.bData.aVersion[pIter->sIter.iRow] || + pFilterInfo->ever < pIter->sIter.bData.aVersion[pIter->sIter.iRow]) { + pIter->sIter.iRow++; + continue; + } + } + } + + pIter->rowInfo.suid = pIter->sIter.bData.suid; + pIter->rowInfo.uid = pIter->sIter.bData.uid ? pIter->sIter.bData.uid : pIter->sIter.bData.aUid[pIter->sIter.iRow]; + pIter->rowInfo.row = tsdbRowFromBlockData(&pIter->sIter.bData, pIter->sIter.iRow); + pIter->sIter.iRow++; + goto _exit; + } + + for (;;) { + if (pIter->sIter.iSttBlk < taosArrayGetSize(pIter->sIter.aSttBlk)) { + SSttBlk* pSttBlk = taosArrayGet(pIter->sIter.aSttBlk, pIter->sIter.iSttBlk); + + if (pFilterInfo) { + if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_TABLEID) { + if (pSttBlk->suid == pFilterInfo->tbid.suid && pSttBlk->minUid == pFilterInfo->tbid.uid && + pSttBlk->maxUid == pFilterInfo->tbid.uid) { + pIter->sIter.iSttBlk++; + continue; + } + } + + if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { + if (pFilterInfo->sver > pSttBlk->maxVer || pFilterInfo->ever < pSttBlk->minVer) { + pIter->sIter.iSttBlk++; + continue; + } + } + } + + code = tsdbReadSttBlockEx(pIter->sIter.pReader, pIter->sIter.iStt, pSttBlk, &pIter->sIter.bData); + TSDB_CHECK_CODE(code, lino, _exit); + + pIter->sIter.iRow = 0; + pIter->sIter.iSttBlk++; + break; + } else { + pIter->rowInfo = (SRowInfo){0}; + goto _exit; + } + } + } + +_exit: + if (code) { + tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code)); + } + return code; +} + +static int32_t tsdbTombFileDataIterNext(STsdbDataIter2* pIter, STsdbFilterInfo* pFilterInfo) { + int32_t code = 0; + int32_t lino = 0; + + for (;;) { + while (pIter->tIter.iDelData < taosArrayGetSize(pIter->tIter.aDelData)) { + SDelData* pDelData = taosArrayGet(pIter->tIter.aDelData, pIter->tIter.iDelData); + + if (pFilterInfo) { + if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { + if (pFilterInfo->sver > pDelData->version || pFilterInfo->ever < pDelData->version) { + pIter->tIter.iDelData++; + continue; + } + } + } + + pIter->delInfo.delData = *pDelData; + pIter->tIter.iDelData++; + goto _exit; + } + + for (;;) { + if (pIter->tIter.iDelIdx < taosArrayGetSize(pIter->tIter.aDelIdx)) { + SDelIdx* pDelIdx = taosArrayGet(pIter->tIter.aDelIdx, pIter->tIter.iDelIdx); + + if (pFilterInfo) { + if (pFilterInfo->flag & TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE) { + SMetaInfo info; + if (metaGetInfo(pIter->dIter.pReader->pTsdb->pVnode->pMeta, pDelIdx->uid, &info, NULL)) { + pIter->tIter.iDelIdx++; + continue; + } + } + } + + code = tsdbReadDelData(pIter->tIter.pReader, pDelIdx, pIter->tIter.aDelData); + TSDB_CHECK_CODE(code, lino, _exit); + + pIter->delInfo.suid = pDelIdx->suid; + pIter->delInfo.uid = pDelIdx->uid; + pIter->tIter.iDelData = 0; + pIter->tIter.iDelIdx++; + break; + } else { + pIter->delInfo = (SDelInfo){0}; + goto _exit; + } + } + } + +_exit: + if (code) { + tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code)); + } + return code; +} + +int32_t tsdbDataIterNext2(STsdbDataIter2* pIter, STsdbFilterInfo* pFilterInfo) { + int32_t code = 0; + + if (pIter->type == TSDB_MEM_TABLE_DATA_ITER) { + ASSERT(0); + return code; + } else if (pIter->type == TSDB_DATA_FILE_DATA_ITER) { + return tsdbDataFileDataIterNext(pIter, pFilterInfo); + } else if (pIter->type == TSDB_STT_FILE_DATA_ITER) { + return tsdbSttFileDataIterNext(pIter, pFilterInfo); + } else if (pIter->type == TSDB_TOMB_FILE_DATA_ITER) { + return tsdbTombFileDataIterNext(pIter, pFilterInfo); + } else { + ASSERT(0); + return code; + } +} + +/* get */ + +// STsdbFSetIter +typedef struct STsdbFSetDataIter { + STsdb* pTsdb; + int32_t flags; + + /* tombstone */ + SDelFReader* pDelFReader; + SArray* aDelIdx; // SArray + SArray* aDelData; // SArray + SArray* aSkeyLine; // SArray + int32_t iDelIdx; + int32_t iSkyLine; + + /* time-series data */ + SDataFReader* pReader; + STsdbDataIter2* iterList; + STsdbDataIter2* pIter; + SRBTree rbt; +} STsdbFSetDataIter; diff --git a/source/dnode/vnode/src/tsdb/tsdbDiskData.c b/source/dnode/vnode/src/tsdb/tsdbDiskData.c index b46a00363817666cdff7bc7756ff204483787c36..ae9af11f5ae8226c1fceefb57b4d83167800772a 100644 --- a/source/dnode/vnode/src/tsdb/tsdbDiskData.c +++ b/source/dnode/vnode/src/tsdb/tsdbDiskData.c @@ -596,7 +596,7 @@ int32_t tDiskDataAddRow(SDiskDataBuilder *pBuilder, TSDBROW *pRow, STSchema *pTS if (pBuilder->bi.maxKey < kRow.ts) pBuilder->bi.maxKey = kRow.ts; STSDBRowIter iter = {0}; - tsdbRowIterInit(&iter, pRow, pTSchema); + tsdbRowIterOpen(&iter, pRow, pTSchema); SColVal *pColVal = tsdbRowIterNext(&iter); for (int32_t iBuilder = 0; iBuilder < pBuilder->nBuilder; iBuilder++) { diff --git a/source/dnode/vnode/src/tsdb/tsdbFS.c b/source/dnode/vnode/src/tsdb/tsdbFS.c index 51fdc69a95cc0a935a6b6e2abd390d5927384a50..5519d43012f46dc2e24ad56083ff421d5fcff1c5 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS.c @@ -629,7 +629,15 @@ static int32_t tsdbFSApplyChange(STsdb *pTsdb, STsdbFS *pFS) { } } } else { - ASSERT(pTsdb->fs.pDelFile == NULL); + if (pTsdb->fs.pDelFile) { + nRef = atomic_sub_fetch_32(&pTsdb->fs.pDelFile->nRef, 1); + if (nRef == 0) { + tsdbDelFileName(pTsdb, pTsdb->fs.pDelFile, fname); + (void)taosRemoveFile(fname); + taosMemoryFree(pTsdb->fs.pDelFile); + } + pTsdb->fs.pDelFile = NULL; + } } // aDFileSet @@ -906,14 +914,21 @@ _exit: int32_t tsdbFSUpsertDelFile(STsdbFS *pFS, SDelFile *pDelFile) { int32_t code = 0; - if (pFS->pDelFile == NULL) { - pFS->pDelFile = (SDelFile *)taosMemoryMalloc(sizeof(SDelFile)); + if (pDelFile) { if (pFS->pDelFile == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; + pFS->pDelFile = (SDelFile *)taosMemoryMalloc(sizeof(SDelFile)); + if (pFS->pDelFile == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + } + *pFS->pDelFile = *pDelFile; + } else { + if (pFS->pDelFile) { + taosMemoryFree(pFS->pDelFile); + pFS->pDelFile = NULL; } } - *pFS->pDelFile = *pDelFile; _exit: return code; diff --git a/source/dnode/vnode/src/tsdb/tsdbFile.c b/source/dnode/vnode/src/tsdb/tsdbFile.c index 42728be657cee044e3a003fb6b437b56b6df3e71..d91475376b240812b8942227fa85e37cb5671dec 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFile.c +++ b/source/dnode/vnode/src/tsdb/tsdbFile.c @@ -148,10 +148,10 @@ bool tsdbDelFileIsSame(SDelFile *pDelFile1, SDelFile *pDelFile2) { return pDelFi int32_t tsdbDFileRollback(STsdb *pTsdb, SDFileSet *pSet, EDataFileT ftype) { int32_t code = 0; - int64_t size; + int64_t size = 0; int64_t n; TdFilePtr pFD; - char fname[TSDB_FILENAME_LEN]; + char fname[TSDB_FILENAME_LEN] = {0}; char hdr[TSDB_FHDR_SIZE] = {0}; // truncate @@ -167,7 +167,7 @@ int32_t tsdbDFileRollback(STsdb *pTsdb, SDFileSet *pSet, EDataFileT ftype) { tPutSmaFile(hdr, pSet->pSmaF); break; default: - ASSERT(0); + goto _err; // make the coverity scan happy } taosCalcChecksumAppend(0, hdr, TSDB_FHDR_SIZE); diff --git a/source/dnode/vnode/src/tsdb/tsdbMemTable.c b/source/dnode/vnode/src/tsdb/tsdbMemTable.c index ac27a0309610338f5da22afbc3941add7bf57c71..f27a28acb3ddb2cc16d6e7b181d720f9e6f31325 100644 --- a/source/dnode/vnode/src/tsdb/tsdbMemTable.c +++ b/source/dnode/vnode/src/tsdb/tsdbMemTable.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#include #include "tsdb.h" #define MEM_MIN_HASH 1024 @@ -32,8 +33,10 @@ static void tbDataMovePosTo(STbData *pTbData, SMemSkipListNode **pos, TSDBKEY *pKey, int32_t flags); static int32_t tsdbGetOrCreateTbData(SMemTable *pMemTable, tb_uid_t suid, tb_uid_t uid, STbData **ppTbData); -static int32_t tsdbInsertTableDataImpl(SMemTable *pMemTable, STbData *pTbData, int64_t version, - SSubmitMsgIter *pMsgIter, SSubmitBlk *pBlock, SSubmitBlkRsp *pRsp); +static int32_t tsdbInsertRowDataToTable(SMemTable *pMemTable, STbData *pTbData, int64_t version, + SSubmitTbData *pSubmitTbData, int32_t *affectedRows); +static int32_t tsdbInsertColDataToTable(SMemTable *pMemTable, STbData *pTbData, int64_t version, + SSubmitTbData *pSubmitTbData, int32_t *affectedRows); int32_t tsdbMemTableCreate(STsdb *pTsdb, SMemTable **ppMemTable) { int32_t code = 0; @@ -48,6 +51,8 @@ int32_t tsdbMemTableCreate(STsdb *pTsdb, SMemTable **ppMemTable) { pMemTable->pTsdb = pTsdb; pMemTable->pPool = pTsdb->pVnode->inUse; pMemTable->nRef = 1; + pMemTable->minVer = VERSION_MAX; + pMemTable->maxVer = VERSION_MIN; pMemTable->minKey = TSKEY_MAX; pMemTable->maxKey = TSKEY_MIN; pMemTable->nRow = 0; @@ -70,9 +75,9 @@ _err: return code; } -void tsdbMemTableDestroy(SMemTable *pMemTable) { +void tsdbMemTableDestroy(SMemTable *pMemTable, bool proactive) { if (pMemTable) { - vnodeBufPoolUnRef(pMemTable->pPool); + vnodeBufPoolUnRef(pMemTable->pPool, proactive); taosMemoryFree(pMemTable->aBucket); taosMemoryFree(pMemTable); } @@ -99,35 +104,12 @@ STbData *tsdbGetTbDataFromMemTable(SMemTable *pMemTable, tb_uid_t suid, tb_uid_t return pTbData; } -int32_t tsdbInsertTableData(STsdb *pTsdb, int64_t version, SSubmitMsgIter *pMsgIter, SSubmitBlk *pBlock, - SSubmitBlkRsp *pRsp) { +int32_t tsdbInsertTableData(STsdb *pTsdb, int64_t version, SSubmitTbData *pSubmitTbData, int32_t *affectedRows) { int32_t code = 0; SMemTable *pMemTable = pTsdb->mem; STbData *pTbData = NULL; - tb_uid_t suid = pMsgIter->suid; - tb_uid_t uid = pMsgIter->uid; - - SMetaInfo info; - code = metaGetInfo(pTsdb->pVnode->pMeta, uid, &info, NULL); - if (code) { - code = TSDB_CODE_TDB_TABLE_NOT_EXIST; - goto _err; - } - if (info.suid != suid) { - code = TSDB_CODE_INVALID_MSG; - goto _err; - } - if (info.suid) { - metaGetInfo(pTsdb->pVnode->pMeta, info.suid, &info, NULL); - } - if (pMsgIter->sversion != info.skmVer) { - tsdbError("vgId:%d, req sver:%d, skmVer:%d suid:%" PRId64 " uid:%" PRId64, TD_VID(pTsdb->pVnode), - pMsgIter->sversion, info.skmVer, suid, uid); - code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER; - goto _err; - } - - pRsp->sver = info.skmVer; + tb_uid_t suid = pSubmitTbData->suid; + tb_uid_t uid = pSubmitTbData->uid; // create/get STbData to op code = tsdbGetOrCreateTbData(pMemTable, suid, uid, &pTbData); @@ -136,10 +118,16 @@ int32_t tsdbInsertTableData(STsdb *pTsdb, int64_t version, SSubmitMsgIter *pMsgI } // do insert impl - code = tsdbInsertTableDataImpl(pMemTable, pTbData, version, pMsgIter, pBlock, pRsp); - if (code) { - goto _err; + if (pSubmitTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + code = tsdbInsertColDataToTable(pMemTable, pTbData, version, pSubmitTbData, affectedRows); + } else { + code = tsdbInsertRowDataToTable(pMemTable, pTbData, version, pSubmitTbData, affectedRows); } + if (code) goto _err; + + // update + pMemTable->minVer = TMIN(pMemTable->minVer, version); + pMemTable->maxVer = TMAX(pMemTable->maxVer, version); return code; @@ -192,6 +180,8 @@ int32_t tsdbDeleteTableData(STsdb *pTsdb, int64_t version, tb_uid_t suid, tb_uid } pMemTable->nDel++; + pMemTable->minVer = TMIN(pMemTable->minVer, version); + pMemTable->maxVer = TMIN(pMemTable->maxVer, version); if (TSDB_CACHE_LAST_ROW(pMemTable->pTsdb->pVnode->config) && tsdbKeyCmprFn(&lastKey, &pTbData->maxKey) >= 0) { tsdbCacheDeleteLastrow(pTsdb->lruCache, pTbData->uid, eKey); @@ -201,9 +191,9 @@ int32_t tsdbDeleteTableData(STsdb *pTsdb, int64_t version, tb_uid_t suid, tb_uid tsdbCacheDeleteLast(pTsdb->lruCache, pTbData->uid, eKey); } - tsdbInfo("vgId:%d, delete data from table suid:%" PRId64 " uid:%" PRId64 " skey:%" PRId64 " eKey:%" PRId64 - " at version %" PRId64 " since %s", - TD_VID(pTsdb->pVnode), suid, uid, sKey, eKey, version, tstrerror(code)); + tsdbTrace("vgId:%d, delete data from table suid:%" PRId64 " uid:%" PRId64 " skey:%" PRId64 " eKey:%" PRId64 + " at version %" PRId64, + TD_VID(pTsdb->pVnode), suid, uid, sKey, eKey, version); return code; _err: @@ -232,7 +222,6 @@ void *tsdbTbDataIterDestroy(STbDataIter *pIter) { if (pIter) { taosMemoryFree(pIter); } - return NULL; } @@ -246,7 +235,6 @@ void tsdbTbDataIterOpen(STbData *pTbData, TSDBKEY *pFrom, int8_t backward, STbDa pIter->pTbData = pTbData; pIter->backward = backward; pIter->pRow = NULL; - pIter->row.type = 0; if (pFrom == NULL) { // create from head or tail if (backward) { @@ -295,6 +283,40 @@ bool tsdbTbDataIterNext(STbDataIter *pIter) { return true; } +int64_t tsdbCountTbDataRows(STbData *pTbData) { + SMemSkipListNode *pNode = pTbData->sl.pHead; + int64_t rowsNum = 0; + + while (NULL != pNode) { + pNode = SL_GET_NODE_FORWARD(pNode, 0); + if (pNode == pTbData->sl.pTail) { + return rowsNum; + } + + rowsNum++; + } + + return rowsNum; +} + +void tsdbMemTableCountRows(SMemTable *pMemTable, SSHashObj* pTableMap, int64_t *rowsNum) { + taosRLockLatch(&pMemTable->latch); + for (int32_t i = 0; i < pMemTable->nBucket; ++i) { + STbData *pTbData = pMemTable->aBucket[i]; + while (pTbData) { + void* p = tSimpleHashGet(pTableMap, &pTbData->uid, sizeof(pTbData->uid)); + if (p == NULL) { + pTbData = pTbData->next; + continue; + } + + *rowsNum += tsdbCountTbDataRows(pTbData); + pTbData = pTbData->next; + } + } + taosRUnLockLatch(&pMemTable->latch); +} + static int32_t tsdbMemTableRehash(SMemTable *pMemTable) { int32_t code = 0; @@ -414,8 +436,13 @@ static void tbDataMovePosTo(STbData *pTbData, SMemSkipListNode **pos, TSDBKEY *p for (int8_t iLevel = pTbData->sl.level - 1; iLevel >= 0; iLevel--) { pn = SL_GET_NODE_BACKWARD(px, iLevel); while (pn != pTbData->sl.pHead) { - tKey.version = pn->version; - tKey.ts = pn->pTSRow->ts; + if (pn->flag == TSDBROW_ROW_FMT) { + tKey.version = pn->version; + tKey.ts = ((SRow *)pn->pData)->ts; + } else if (pn->flag == TSDBROW_COL_FMT) { + tKey.version = ((SBlockData *)pn->pData)->aVersion[pn->iRow]; + tKey.ts = ((SBlockData *)pn->pData)->aTSKEY[pn->iRow]; + } int32_t c = tsdbKeyCmprFn(&tKey, pKey); if (c <= 0) { @@ -444,8 +471,13 @@ static void tbDataMovePosTo(STbData *pTbData, SMemSkipListNode **pos, TSDBKEY *p for (int8_t iLevel = pTbData->sl.level - 1; iLevel >= 0; iLevel--) { pn = SL_GET_NODE_FORWARD(px, iLevel); while (pn != pTbData->sl.pTail) { - tKey.version = pn->version; - tKey.ts = pn->pTSRow->ts; + if (pn->flag == TSDBROW_ROW_FMT) { + tKey.version = pn->version; + tKey.ts = ((SRow *)pn->pData)->ts; + } else if (pn->flag == TSDBROW_COL_FMT) { + tKey.version = ((SBlockData *)pn->pData)->aVersion[pn->iRow]; + tKey.ts = ((SBlockData *)pn->pData)->aTSKEY[pn->iRow]; + } int32_t c = tsdbKeyCmprFn(&tKey, pKey); if (c >= 0) { @@ -472,26 +504,41 @@ static FORCE_INLINE int8_t tsdbMemSkipListRandLevel(SMemSkipList *pSl) { return level; } -static int32_t tbDataDoPut(SMemTable *pMemTable, STbData *pTbData, SMemSkipListNode **pos, int64_t version, - STSRow *pRow, int8_t forward) { +static int32_t tbDataDoPut(SMemTable *pMemTable, STbData *pTbData, SMemSkipListNode **pos, TSDBROW *pRow, + int8_t forward) { int32_t code = 0; int8_t level; - SMemSkipListNode *pNode; + SMemSkipListNode *pNode = NULL; SVBufPool *pPool = pMemTable->pTsdb->pVnode->inUse; int64_t nSize; // create node level = tsdbMemSkipListRandLevel(&pTbData->sl); nSize = SL_NODE_SIZE(level); - pNode = (SMemSkipListNode *)vnodeBufPoolMallocAligned(pPool, nSize + pRow->len); + if (pRow->type == TSDBROW_ROW_FMT) { + pNode = (SMemSkipListNode *)vnodeBufPoolMallocAligned(pPool, nSize + pRow->pTSRow->len); + } else if (pRow->type == TSDBROW_COL_FMT) { + pNode = (SMemSkipListNode *)vnodeBufPoolMallocAligned(pPool, nSize); + } else { + ASSERT(0); + } if (pNode == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; goto _exit; } + pNode->level = level; - pNode->version = version; - pNode->pTSRow = (STSRow *)((char *)pNode + nSize); - memcpy(pNode->pTSRow, pRow, pRow->len); + pNode->flag = pRow->type; + if (pRow->type == TSDBROW_ROW_FMT) { + pNode->version = pRow->version; + pNode->pData = (char *)pNode + nSize; + memcpy(pNode->pData, pRow->pTSRow, pRow->pTSRow->len); + } else if (pRow->type == TSDBROW_COL_FMT) { + pNode->iRow = pRow->iRow; + pNode->pData = pRow->pBlockData; + } else { + ASSERT(0); + } // set node if (forward) { @@ -536,69 +583,168 @@ _exit: return code; } -static int32_t tsdbInsertTableDataImpl(SMemTable *pMemTable, STbData *pTbData, int64_t version, - SSubmitMsgIter *pMsgIter, SSubmitBlk *pBlock, SSubmitBlkRsp *pRsp) { - int32_t code = 0; - SSubmitBlkIter blkIter = {0}; - TSDBKEY key = {.version = version}; - SMemSkipListNode *pos[SL_MAX_LEVEL]; - TSDBROW row = tsdbRowFromTSRow(version, NULL); - int32_t nRow = 0; - STSRow *pLastRow = NULL; +static int32_t tsdbInsertColDataToTable(SMemTable *pMemTable, STbData *pTbData, int64_t version, + SSubmitTbData *pSubmitTbData, int32_t *affectedRows) { + int32_t code = 0; - tInitSubmitBlkIter(pMsgIter, pBlock, &blkIter); + SVBufPool *pPool = pMemTable->pTsdb->pVnode->inUse; + int32_t nColData = TARRAY_SIZE(pSubmitTbData->aCol); + SColData *aColData = (SColData *)TARRAY_DATA(pSubmitTbData->aCol); - // backward put first data - row.pTSRow = tGetSubmitBlkNext(&blkIter); - if (row.pTSRow == NULL) return code; + ASSERT(aColData[0].cid == PRIMARYKEY_TIMESTAMP_COL_ID); + ASSERT(aColData[0].type == TSDB_DATA_TYPE_TIMESTAMP); + ASSERT(aColData[0].flag == HAS_VALUE); - key.ts = row.pTSRow->ts; - nRow++; - tbDataMovePosTo(pTbData, pos, &key, SL_MOVE_BACKWARD); - code = tbDataDoPut(pMemTable, pTbData, pos, version, row.pTSRow, 0); - if (code) { - goto _err; + // copy and construct block data + SBlockData *pBlockData = vnodeBufPoolMalloc(pPool, sizeof(*pBlockData)); + if (pBlockData == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + pBlockData->suid = pTbData->suid; + pBlockData->uid = pTbData->uid; + pBlockData->nRow = aColData[0].nVal; + pBlockData->aUid = NULL; + pBlockData->aVersion = vnodeBufPoolMalloc(pPool, aColData[0].nData); + if (pBlockData->aVersion == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + for (int32_t i = 0; i < pBlockData->nRow; i++) { // todo: here can be optimized + pBlockData->aVersion[i] = version; + } + + pBlockData->aTSKEY = vnodeBufPoolMalloc(pPool, aColData[0].nData); + if (pBlockData->aTSKEY == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + memcpy(pBlockData->aTSKEY, aColData[0].pData, aColData[0].nData); + + pBlockData->nColData = nColData - 1; + pBlockData->aColData = vnodeBufPoolMalloc(pPool, sizeof(SColData) * pBlockData->nColData); + if (pBlockData->aColData == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; } + for (int32_t iColData = 0; iColData < pBlockData->nColData; ++iColData) { + code = tColDataCopy(&aColData[iColData + 1], &pBlockData->aColData[iColData], (xMallocFn)vnodeBufPoolMalloc, pPool); + if (code) goto _exit; + } + + // loop to add each row to the skiplist + SMemSkipListNode *pos[SL_MAX_LEVEL]; + TSDBROW tRow = tsdbRowFromBlockData(pBlockData, 0); + TSDBKEY key = {.version = version, .ts = pBlockData->aTSKEY[0]}; + TSDBROW lRow; // last row + + // first row + tbDataMovePosTo(pTbData, pos, &key, SL_MOVE_BACKWARD); + if ((code = tbDataDoPut(pMemTable, pTbData, pos, &tRow, 0))) goto _exit; pTbData->minKey = TMIN(pTbData->minKey, key.ts); + lRow = tRow; + + // remain row + ++tRow.iRow; + if (tRow.iRow < pBlockData->nRow) { + for (int8_t iLevel = pos[0]->level; iLevel < pTbData->sl.maxLevel; iLevel++) { + pos[iLevel] = SL_NODE_BACKWARD(pos[iLevel], iLevel); + } + + while (tRow.iRow < pBlockData->nRow) { + key.ts = pBlockData->aTSKEY[tRow.iRow]; + + if (SL_NODE_FORWARD(pos[0], 0) != pTbData->sl.pTail) { + tbDataMovePosTo(pTbData, pos, &key, SL_MOVE_FROM_POS); + } + + if ((code = tbDataDoPut(pMemTable, pTbData, pos, &tRow, 1))) goto _exit; + lRow = tRow; + + ++tRow.iRow; + } + } + + if (key.ts >= pTbData->maxKey) { + pTbData->maxKey = key.ts; + + if (TSDB_CACHE_LAST_ROW(pMemTable->pTsdb->pVnode->config)) { + tsdbCacheInsertLastrow(pMemTable->pTsdb->lruCache, pMemTable->pTsdb, pTbData->uid, &lRow, true); + } + } + + if (TSDB_CACHE_LAST(pMemTable->pTsdb->pVnode->config)) { + tsdbCacheInsertLast(pMemTable->pTsdb->lruCache, pTbData->uid, &lRow, pMemTable->pTsdb); + } + + // SMemTable + pMemTable->minKey = TMIN(pMemTable->minKey, pTbData->minKey); + pMemTable->maxKey = TMAX(pMemTable->maxKey, pTbData->maxKey); + pMemTable->nRow += pBlockData->nRow; + + if (affectedRows) *affectedRows = pBlockData->nRow; + +_exit: + return code; +} - pLastRow = row.pTSRow; +static int32_t tsdbInsertRowDataToTable(SMemTable *pMemTable, STbData *pTbData, int64_t version, + SSubmitTbData *pSubmitTbData, int32_t *affectedRows) { + int32_t code = 0; + + int32_t nRow = TARRAY_SIZE(pSubmitTbData->aRowP); + SRow **aRow = (SRow **)TARRAY_DATA(pSubmitTbData->aRowP); + TSDBKEY key = {.version = version}; + SMemSkipListNode *pos[SL_MAX_LEVEL]; + TSDBROW tRow = {.type = TSDBROW_ROW_FMT, .version = version}; + int32_t iRow = 0; + TSDBROW lRow; + + // backward put first data + tRow.pTSRow = aRow[iRow++]; + key.ts = tRow.pTSRow->ts; + tbDataMovePosTo(pTbData, pos, &key, SL_MOVE_BACKWARD); + code = tbDataDoPut(pMemTable, pTbData, pos, &tRow, 0); + if (code) goto _exit; + lRow = tRow; + + pTbData->minKey = TMIN(pTbData->minKey, key.ts); // forward put rest data - row.pTSRow = tGetSubmitBlkNext(&blkIter); - if (row.pTSRow) { + if (iRow < nRow) { for (int8_t iLevel = pos[0]->level; iLevel < pTbData->sl.maxLevel; iLevel++) { pos[iLevel] = SL_NODE_BACKWARD(pos[iLevel], iLevel); } - do { - key.ts = row.pTSRow->ts; - nRow++; + + while (iRow < nRow) { + tRow.pTSRow = aRow[iRow]; + key.ts = tRow.pTSRow->ts; + if (SL_NODE_FORWARD(pos[0], 0) != pTbData->sl.pTail) { tbDataMovePosTo(pTbData, pos, &key, SL_MOVE_FROM_POS); } - code = tbDataDoPut(pMemTable, pTbData, pos, version, row.pTSRow, 1); - if (code) { - goto _err; - } - pLastRow = row.pTSRow; + code = tbDataDoPut(pMemTable, pTbData, pos, &tRow, 1); + if (code) goto _exit; + + lRow = tRow; - row.pTSRow = tGetSubmitBlkNext(&blkIter); - } while (row.pTSRow); + iRow++; + } } if (key.ts >= pTbData->maxKey) { - if (key.ts > pTbData->maxKey) { - pTbData->maxKey = key.ts; - } + pTbData->maxKey = key.ts; - if (TSDB_CACHE_LAST_ROW(pMemTable->pTsdb->pVnode->config) && pLastRow != NULL) { - tsdbCacheInsertLastrow(pMemTable->pTsdb->lruCache, pMemTable->pTsdb, pTbData->uid, pLastRow, true); + if (TSDB_CACHE_LAST_ROW(pMemTable->pTsdb->pVnode->config)) { + tsdbCacheInsertLastrow(pMemTable->pTsdb->lruCache, pMemTable->pTsdb, pTbData->uid, &lRow, true); } } if (TSDB_CACHE_LAST(pMemTable->pTsdb->pVnode->config)) { - tsdbCacheInsertLast(pMemTable->pTsdb->lruCache, pTbData->uid, pLastRow, pMemTable->pTsdb); + tsdbCacheInsertLast(pMemTable->pTsdb->lruCache, pTbData->uid, &lRow, pMemTable->pTsdb); } // SMemTable @@ -606,27 +752,38 @@ static int32_t tsdbInsertTableDataImpl(SMemTable *pMemTable, STbData *pTbData, i pMemTable->maxKey = TMAX(pMemTable->maxKey, pTbData->maxKey); pMemTable->nRow += nRow; - pRsp->numOfRows = nRow; - pRsp->affectedRows = nRow; + if (affectedRows) *affectedRows = nRow; - return code; - -_err: +_exit: return code; } int32_t tsdbGetNRowsInTbData(STbData *pTbData) { return pTbData->sl.size; } -void tsdbRefMemTable(SMemTable *pMemTable) { +int32_t tsdbRefMemTable(SMemTable *pMemTable, SQueryNode *pQNode) { + int32_t code = 0; + int32_t nRef = atomic_fetch_add_32(&pMemTable->nRef, 1); ASSERT(nRef > 0); + + vnodeBufPoolRegisterQuery(pMemTable->pPool, pQNode); + +_exit: + return code; } -void tsdbUnrefMemTable(SMemTable *pMemTable) { - int32_t nRef = atomic_sub_fetch_32(&pMemTable->nRef, 1); - if (nRef == 0) { - tsdbMemTableDestroy(pMemTable); +int32_t tsdbUnrefMemTable(SMemTable *pMemTable, SQueryNode *pNode, bool proactive) { + int32_t code = 0; + + if (pNode) { + vnodeBufPoolDeregisterQuery(pMemTable->pPool, pNode, proactive); } + + if (atomic_sub_fetch_32(&pMemTable->nRef, 1) == 0) { + tsdbMemTableDestroy(pMemTable, proactive); + } + + return code; } static FORCE_INLINE int32_t tbDataPCmprFn(const void *p1, const void *p2) { diff --git a/source/dnode/vnode/src/tsdb/tsdbMergeTree.c b/source/dnode/vnode/src/tsdb/tsdbMergeTree.c index 91152574d222983bbb4156314f4a6adb868281fa..79f4a17f65430c3dc0efc8177c7f131db60934e3 100644 --- a/source/dnode/vnode/src/tsdb/tsdbMergeTree.c +++ b/source/dnode/vnode/src/tsdb/tsdbMergeTree.c @@ -16,22 +16,8 @@ #include "tsdb.h" // SLDataIter ================================================= -struct SLDataIter { - SRBTreeNode node; - SSttBlk *pSttBlk; - SDataFReader *pReader; - int32_t iStt; - int8_t backward; - int32_t iSttBlk; - int32_t iRow; - SRowInfo rInfo; - uint64_t uid; - STimeWindow timeWindow; - SVersionRange verRange; - SSttBlockLoadInfo *pBlockLoadInfo; -}; - -SSttBlockLoadInfo *tCreateLastBlockLoadInfo(STSchema *pSchema, int16_t *colList, int32_t numOfCols, int32_t numOfSttTrigger) { +SSttBlockLoadInfo *tCreateLastBlockLoadInfo(STSchema *pSchema, int16_t *colList, int32_t numOfCols, + int32_t numOfSttTrigger) { SSttBlockLoadInfo *pLoadInfo = taosMemoryCalloc(numOfSttTrigger, sizeof(SSttBlockLoadInfo)); if (pLoadInfo == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -86,13 +72,17 @@ void getLastBlockLoadInfo(SSttBlockLoadInfo *pLoadInfo, int64_t *blocks, double } void *destroyLastBlockLoadInfo(SSttBlockLoadInfo *pLoadInfo) { + if (pLoadInfo == NULL) { + return NULL; + } + for (int32_t i = 0; i < pLoadInfo->numOfStt; ++i) { pLoadInfo[i].currentLoadBlockIndex = 1; pLoadInfo[i].blockIndex[0] = -1; pLoadInfo[i].blockIndex[1] = -1; - tBlockDataDestroy(&pLoadInfo[i].blockData[0], true); - tBlockDataDestroy(&pLoadInfo[i].blockData[1], true); + tBlockDataDestroy(&pLoadInfo[i].blockData[0]); + tBlockDataDestroy(&pLoadInfo[i].blockData[1]); taosArrayDestroy(pLoadInfo[i].aSttBlk); } @@ -162,7 +152,8 @@ static SBlockData *loadLastBlock(SLDataIter *pIter, const char *idStr) { pInfo->blockIndex[pInfo->currentLoadBlockIndex] = pIter->iSttBlk; pIter->iRow = (pIter->backward) ? pInfo->blockData[pInfo->currentLoadBlockIndex].nRow : -1; - tsdbDebug("last block index list:%d, %d, rowIndex:%d %s", pInfo->blockIndex[0], pInfo->blockIndex[1], pIter->iRow, idStr); + tsdbDebug("last block index list:%d, %d, rowIndex:%d %s", pInfo->blockIndex[0], pInfo->blockIndex[1], pIter->iRow, + idStr); return &pInfo->blockData[pInfo->currentLoadBlockIndex]; _exit: @@ -261,25 +252,21 @@ static int32_t binarySearchForStartRowIndex(uint64_t *uidList, int32_t num, uint } } -int32_t tLDataIterOpen(struct SLDataIter **pIter, SDataFReader *pReader, int32_t iStt, int8_t backward, uint64_t suid, +int32_t tLDataIterOpen(struct SLDataIter *pIter, SDataFReader *pReader, int32_t iStt, int8_t backward, uint64_t suid, uint64_t uid, STimeWindow *pTimeWindow, SVersionRange *pRange, SSttBlockLoadInfo *pBlockLoadInfo, - const char *idStr) { + const char *idStr, bool strictTimeRange) { int32_t code = TSDB_CODE_SUCCESS; - *pIter = taosMemoryCalloc(1, sizeof(SLDataIter)); - if (*pIter == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; - } + pIter->uid = uid; + pIter->pReader = pReader; + pIter->iStt = iStt; + pIter->backward = backward; + pIter->verRange.minVer = pRange->minVer; + pIter->verRange.maxVer = pRange->maxVer; + pIter->timeWindow.skey = pTimeWindow->skey; + pIter->timeWindow.ekey = pTimeWindow->ekey; - (*pIter)->uid = uid; - (*pIter)->pReader = pReader; - (*pIter)->iStt = iStt; - (*pIter)->backward = backward; - (*pIter)->verRange = *pRange; - (*pIter)->timeWindow = *pTimeWindow; - - (*pIter)->pBlockLoadInfo = pBlockLoadInfo; + pIter->pBlockLoadInfo = pBlockLoadInfo; if (!pBlockLoadInfo->sttBlockLoaded) { int64_t st = taosGetTimestampUs(); @@ -287,7 +274,7 @@ int32_t tLDataIterOpen(struct SLDataIter **pIter, SDataFReader *pReader, int32_t code = tsdbReadSttBlk(pReader, iStt, pBlockLoadInfo->aSttBlk); if (code) { - goto _exit; + return code; } // only apply to the child tables, ordinary tables will not incur this filter procedure. @@ -303,7 +290,7 @@ int32_t tLDataIterOpen(struct SLDataIter **pIter, SDataFReader *pReader, int32_t // no qualified stt block existed taosArrayClear(pBlockLoadInfo->aSttBlk); - (*pIter)->iSttBlk = -1; + pIter->iSttBlk = -1; double el = (taosGetTimestampUs() - st) / 1000.0; tsdbDebug("load the last file info completed, elapsed time:%.2fms, %s", el, idStr); return code; @@ -336,20 +323,27 @@ int32_t tLDataIterOpen(struct SLDataIter **pIter, SDataFReader *pReader, int32_t size_t size = taosArrayGetSize(pBlockLoadInfo->aSttBlk); // find the start block - (*pIter)->iSttBlk = binarySearchForStartBlock(pBlockLoadInfo->aSttBlk->pData, size, uid, backward); - if ((*pIter)->iSttBlk != -1) { - (*pIter)->pSttBlk = taosArrayGet(pBlockLoadInfo->aSttBlk, (*pIter)->iSttBlk); - (*pIter)->iRow = ((*pIter)->backward) ? (*pIter)->pSttBlk->nRow : -1; - } + pIter->iSttBlk = binarySearchForStartBlock(pBlockLoadInfo->aSttBlk->pData, size, uid, backward); + if (pIter->iSttBlk != -1) { + pIter->pSttBlk = taosArrayGet(pBlockLoadInfo->aSttBlk, pIter->iSttBlk); + pIter->iRow = (pIter->backward) ? pIter->pSttBlk->nRow : -1; + + if ((!backward) && ((strictTimeRange && pIter->pSttBlk->minKey >= pIter->timeWindow.ekey) || + (!strictTimeRange && pIter->pSttBlk->minKey > pIter->timeWindow.ekey))) { + pIter->pSttBlk = NULL; + } - return code; + if (backward && ((strictTimeRange && pIter->pSttBlk->maxKey <= pIter->timeWindow.skey) || + (!strictTimeRange && pIter->pSttBlk->maxKey < pIter->timeWindow.skey))) { + pIter->pSttBlk = NULL; + pIter->ignoreEarlierTs = true; + } + } -_exit: - taosMemoryFree(*pIter); return code; } -void tLDataIterClose(SLDataIter *pIter) { taosMemoryFree(pIter); } +void tLDataIterClose(SLDataIter *pIter) { /*taosMemoryFree(pIter); */} void tLDataIterNextBlock(SLDataIter *pIter, const char *idStr) { int32_t step = pIter->backward ? -1 : 1; @@ -404,7 +398,7 @@ void tLDataIterNextBlock(SLDataIter *pIter, const char *idStr) { tsdbDebug("try next last file block:%d from %d, trigger by uid:%" PRIu64 ", file index:%d, %s", pIter->iSttBlk, oldIndex, pIter->uid, pIter->iStt, idStr); } else { - tsdbDebug("no more last block qualified, uid:%" PRIu64 ", file index::%d, %s", pIter->uid, oldIndex, idStr); + tsdbDebug("no more last block qualified, uid:%" PRIu64 ", file index:%d, %s", pIter->uid, oldIndex, idStr); } } @@ -421,7 +415,7 @@ static void findNextValidRow(SLDataIter *pIter, const char *idStr) { pBlockData->aUid != NULL) { i = binarySearchForStartRowIndex((uint64_t *)pBlockData->aUid, pBlockData->nRow, pIter->uid, pIter->backward); if (i == -1) { - tsdbDebug("failed to find the data in pBlockData, uid:%"PRIu64" , %s", pIter->uid, idStr); + tsdbDebug("failed to find the data in pBlockData, uid:%" PRIu64 " , %s", pIter->uid, idStr); pIter->iRow = -1; return; } @@ -490,9 +484,34 @@ bool tLDataIterNextRow(SLDataIter *pIter, const char *idStr) { pIter->iRow += step; while (1) { + bool skipBlock = false; + findNextValidRow(pIter, idStr); - if (pIter->iRow >= pBlockData->nRow || pIter->iRow < 0) { + if (pIter->pBlockLoadInfo->checkRemainingRow) { + skipBlock = true; + int16_t *aCols = pIter->pBlockLoadInfo->colIds; + int nCols = pIter->pBlockLoadInfo->numOfCols; + bool isLast = pIter->pBlockLoadInfo->isLast; + for (int inputColIndex = 0; inputColIndex < nCols; ++inputColIndex) { + for (int colIndex = 0; colIndex < pBlockData->nColData; ++colIndex) { + SColData *pColData = &pBlockData->aColData[colIndex]; + int16_t cid = pColData->cid; + + if (cid == aCols[inputColIndex]) { + if (isLast && (pColData->flag & HAS_VALUE)) { + skipBlock = false; + break; + } else if (pColData->flag & (HAS_VALUE | HAS_NULL)) { + skipBlock = false; + break; + } + } + } + } + } + + if (skipBlock || pIter->iRow >= pBlockData->nRow || pIter->iRow < 0) { tLDataIterNextBlock(pIter, idStr); if (pIter->pSttBlk == NULL) { // no more data goto _exit; @@ -508,7 +527,7 @@ bool tLDataIterNextRow(SLDataIter *pIter, const char *idStr) { } // set start row index - pIter->iRow = pIter->backward? pBlockData->nRow-1:0; + pIter->iRow = pIter->backward ? pBlockData->nRow - 1 : 0; } } @@ -551,39 +570,38 @@ static FORCE_INLINE int32_t tLDataIterDescCmprFn(const SRBTreeNode *p1, const SR int32_t tMergeTreeOpen(SMergeTree *pMTree, int8_t backward, SDataFReader *pFReader, uint64_t suid, uint64_t uid, STimeWindow *pTimeWindow, SVersionRange *pVerRange, SSttBlockLoadInfo *pBlockLoadInfo, - bool destroyLoadInfo, const char *idStr) { + bool destroyLoadInfo, const char *idStr, bool strictTimeRange, SLDataIter* pLDataIter) { + int32_t code = TSDB_CODE_SUCCESS; + pMTree->backward = backward; pMTree->pIter = NULL; - pMTree->pIterList = taosArrayInit(4, POINTER_BYTES); - if (pMTree->pIterList == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - pMTree->idStr = idStr; + if (!pMTree->backward) { // asc tRBTreeCreate(&pMTree->rbt, tLDataIterCmprFn); } else { // desc tRBTreeCreate(&pMTree->rbt, tLDataIterDescCmprFn); } - int32_t code = TSDB_CODE_SUCCESS; pMTree->pLoadInfo = pBlockLoadInfo; pMTree->destroyLoadInfo = destroyLoadInfo; + pMTree->ignoreEarlierTs = false; for (int32_t i = 0; i < pFReader->pSet->nSttF; ++i) { // open all last file - struct SLDataIter *pIter = NULL; - code = tLDataIterOpen(&pIter, pFReader, i, pMTree->backward, suid, uid, pTimeWindow, pVerRange, - &pMTree->pLoadInfo[i], pMTree->idStr); + memset(&pLDataIter[i], 0, sizeof(SLDataIter)); + code = tLDataIterOpen(&pLDataIter[i], pFReader, i, pMTree->backward, suid, uid, pTimeWindow, pVerRange, + &pMTree->pLoadInfo[i], pMTree->idStr, strictTimeRange); if (code != TSDB_CODE_SUCCESS) { goto _end; } - bool hasVal = tLDataIterNextRow(pIter, pMTree->idStr); + bool hasVal = tLDataIterNextRow(&pLDataIter[i], pMTree->idStr); if (hasVal) { - taosArrayPush(pMTree->pIterList, &pIter); - tMergeTreeAddIter(pMTree, pIter); + tMergeTreeAddIter(pMTree, &pLDataIter[i]); } else { - tLDataIterClose(pIter); + if (!pMTree->ignoreEarlierTs) { + pMTree->ignoreEarlierTs = pLDataIter[i].ignoreEarlierTs; + } } } @@ -596,6 +614,8 @@ _end: void tMergeTreeAddIter(SMergeTree *pMTree, SLDataIter *pIter) { tRBTreePut(&pMTree->rbt, (SRBTreeNode *)pIter); } +bool tMergeTreeIgnoreEarlierTs(SMergeTree *pMTree) { return pMTree->ignoreEarlierTs; } + bool tMergeTreeNext(SMergeTree *pMTree) { int32_t code = TSDB_CODE_SUCCESS; if (pMTree->pIter) { @@ -629,18 +649,8 @@ bool tMergeTreeNext(SMergeTree *pMTree) { return pMTree->pIter != NULL; } -TSDBROW tMergeTreeGetRow(SMergeTree *pMTree) { return pMTree->pIter->rInfo.row; } - void tMergeTreeClose(SMergeTree *pMTree) { - size_t size = taosArrayGetSize(pMTree->pIterList); - for (int32_t i = 0; i < size; ++i) { - SLDataIter *pIter = taosArrayGetP(pMTree->pIterList, i); - tLDataIterClose(pIter); - } - - pMTree->pIterList = taosArrayDestroy(pMTree->pIterList); pMTree->pIter = NULL; - if (pMTree->destroyLoadInfo) { pMTree->pLoadInfo = destroyLastBlockLoadInfo(pMTree->pLoadInfo); pMTree->destroyLoadInfo = false; diff --git a/source/dnode/vnode/src/tsdb/tsdbOpen.c b/source/dnode/vnode/src/tsdb/tsdbOpen.c index f71b5b6706ccb152f4dc221d01f4a1ea6e207c7a..8901f644598ec4ca5343f4a35a7b063bf39096fd 100644 --- a/source/dnode/vnode/src/tsdb/tsdbOpen.c +++ b/source/dnode/vnode/src/tsdb/tsdbOpen.c @@ -88,7 +88,7 @@ _err: int tsdbClose(STsdb **pTsdb) { if (*pTsdb) { taosThreadRwlockWrlock(&(*pTsdb)->rwLock); - tsdbMemTableDestroy((*pTsdb)->mem); + tsdbMemTableDestroy((*pTsdb)->mem, true); (*pTsdb)->mem = NULL; taosThreadRwlockUnlock(&(*pTsdb)->rwLock); diff --git a/source/dnode/vnode/src/tsdb/tsdbRead.c b/source/dnode/vnode/src/tsdb/tsdbRead.c index 4e1b24750ada2c07ed659936a861ac8038432f5d..21b59e376cf50278d39ee55804a4a7d2bb646a88 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead.c @@ -15,8 +15,15 @@ #include "osDef.h" #include "tsdb.h" +#include "tsimplehash.h" #define ASCENDING_TRAVERSE(o) (o == TSDB_ORDER_ASC) +#define getCurrentKeyInLastBlock(_r) ((_r)->currentKey) + +typedef enum { + READER_STATUS_SUSPEND = 0x1, + READER_STATUS_NORMAL = 0x2, +} EReaderStatus; typedef enum { EXTERNAL_ROWS_PREV = 0x1, @@ -24,6 +31,11 @@ typedef enum { EXTERNAL_ROWS_NEXT = 0x3, } EContentData; +typedef enum { + READ_MODE_COUNT_ONLY = 0x1, + READ_MODE_ALL, +} EReadMode; + typedef struct { STbDataIter* iter; int32_t index; @@ -44,6 +56,7 @@ typedef struct SBlockIndex { typedef struct STableBlockScanInfo { uint64_t uid; TSKEY lastKey; + TSKEY lastKeyInStt; // last accessed key in stt SMapData mapData; // block info (compressed) SArray* pBlockList; // block data index list, SArray SIterInfo iter; // mem buffer skip list iterator @@ -79,9 +92,9 @@ typedef struct SIOCostSummary { int64_t composedBlocks; double buildComposedBlockTime; double createScanInfoList; -// double getTbFromMemTime; -// double getTbFromIMemTime; - double initDelSkylineIterTime; + // double getTbFromMemTime; + // double getTbFromIMemTime; + double initDelSkylineIterTime; } SIOCostSummary; typedef struct SBlockLoadSuppInfo { @@ -101,6 +114,7 @@ typedef struct SLastBlockReader { uint64_t uid; SMergeTree mergeTree; SSttBlockLoadInfo* pInfo; + int64_t currentKey; } SLastBlockReader; typedef struct SFilesetIter { @@ -118,12 +132,12 @@ typedef struct SFileDataBlockInfo { } SFileDataBlockInfo; typedef struct SDataBlockIter { - int32_t numOfBlocks; - int32_t index; - SArray* blockList; // SArray - int32_t order; - SDataBlk block; // current SDataBlk data - SHashObj* pTableMap; + int32_t numOfBlocks; + int32_t index; + SArray* blockList; // SArray + int32_t order; + SDataBlk block; // current SDataBlk data + SSHashObj* pTableMap; } SDataBlockIter; typedef struct SFileBlockDumpInfo { @@ -141,7 +155,8 @@ typedef struct STableUidList { typedef struct SReaderStatus { bool loadFromFile; // check file stage bool composedDataBlock; // the returned data block is a composed block or not - SHashObj* pTableMap; // SHash + bool mapDataCleaned; // mapData has been cleaned up alreay or not + SSHashObj* pTableMap; // SHash STableBlockScanInfo** pTableIter; // table iterator used in building in-memory buffer data blocks. STableUidList uidList; // check tables in uid order, to avoid the repeatly load of blocks in STT. SFileBlockDumpInfo fBlockDumpInfo; @@ -149,36 +164,60 @@ typedef struct SReaderStatus { SBlockData fileBlockData; SFilesetIter fileIter; SDataBlockIter blockIter; + SLDataIter* pLDataIter; + SRowMerger merger; + SColumnInfoData* pPrimaryTsCol; // primary time stamp output col info data } SReaderStatus; typedef struct SBlockInfoBuf { int32_t currentIndex; SArray* pData; int32_t numPerBucket; + int32_t numOfTables; } SBlockInfoBuf; +typedef struct STsdbReaderAttr { + STSchema* pSchema; + EReadMode readMode; + uint64_t rowsNum; + STimeWindow window; + bool freeBlock; + SVersionRange verRange; + int16_t order; +} STsdbReaderAttr; + +typedef struct SResultBlockInfo { + SSDataBlock* pResBlock; + bool freeBlock; + int64_t capacity; +} SResultBlockInfo; + struct STsdbReader { STsdb* pTsdb; + SVersionRange verRange; + TdThreadMutex readerMutex; + EReaderStatus flag; + int32_t code; uint64_t suid; int16_t order; - bool freeBlock; + EReadMode readMode; + uint64_t rowsNum; STimeWindow window; // the primary query time window that applies to all queries - SSDataBlock* pResBlock; - int32_t capacity; + SResultBlockInfo resBlockInfo; SReaderStatus status; char* idStr; // query info handle, for debug purpose int32_t type; // query type: 1. retrieve all data blocks, 2. retrieve direct prev|next rows SBlockLoadSuppInfo suppInfo; STsdbReadSnap* pReadSnap; SIOCostSummary cost; + SHashObj** pIgnoreTables; STSchema* pSchema; // the newest version schema - STSchema* pMemSchema; // the previous schema for in-memory data, to avoid load schema too many times + SSHashObj* pSchemaMap; // keep the retrieved schema info, to avoid the overhead by repeatly load schema SDataFReader* pFileReader; // the file reader SDelFReader* pDelFReader; // the del file reader SArray* pDelIdx; // del file block index; - SVersionRange verRange; SBlockInfoBuf blockInfoBuf; - int32_t step; + EContentData step; STsdbReader* innerReader[2]; }; @@ -186,24 +225,22 @@ static SFileDataBlockInfo* getCurrentBlockInfo(SDataBlockIter* pBlockIter); static int buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t endKey, int32_t capacity, STsdbReader* pReader); static TSDBROW* getValidMemRow(SIterInfo* pIter, const SArray* pDelList, STsdbReader* pReader); -static int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pScanInfo, STsdbReader* pReader, - SRowMerger* pMerger); +static int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pScanInfo, STsdbReader* pReader); static int32_t doMergeRowsInLastBlock(SLastBlockReader* pLastBlockReader, STableBlockScanInfo* pScanInfo, int64_t ts, - SRowMerger* pMerger, SVersionRange* pVerRange); -static int32_t doMergeRowsInBuf(SIterInfo* pIter, uint64_t uid, int64_t ts, SArray* pDelList, SRowMerger* pMerger, - STsdbReader* pReader); -static int32_t doAppendRowFromTSRow(SSDataBlock* pBlock, STsdbReader* pReader, STSRow* pTSRow, + SRowMerger* pMerger, SVersionRange* pVerRange, const char* id); +static int32_t doMergeRowsInBuf(SIterInfo* pIter, uint64_t uid, int64_t ts, SArray* pDelList, STsdbReader* pReader); +static int32_t doAppendRowFromTSRow(SSDataBlock* pBlock, STsdbReader* pReader, SRow* pTSRow, STableBlockScanInfo* pScanInfo); static int32_t doAppendRowFromFileBlock(SSDataBlock* pResBlock, STsdbReader* pReader, SBlockData* pBlockData, int32_t rowIndex); static void setComposedBlockFlag(STsdbReader* pReader, bool composed); -static bool hasBeenDropped(const SArray* pDelList, int32_t* index, TSDBKEY* pKey, int32_t order, +static bool hasBeenDropped(const SArray* pDelList, int32_t* index, int64_t key, int64_t ver, int32_t order, SVersionRange* pVerRange); static int32_t doMergeMemTableMultiRows(TSDBROW* pRow, uint64_t uid, SIterInfo* pIter, SArray* pDelList, - STSRow** pTSRow, STsdbReader* pReader, bool* freeTSRow); + TSDBROW* pResRow, STsdbReader* pReader, bool* freeTSRow); static int32_t doMergeMemIMemRows(TSDBROW* pRow, TSDBROW* piRow, STableBlockScanInfo* pBlockScanInfo, - STsdbReader* pReader, STSRow** pTSRow); + STsdbReader* pReader, SRow** pTSRow); static int32_t mergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pBlockScanInfo, int64_t key, STsdbReader* pReader); @@ -212,7 +249,6 @@ static int32_t initDelSkylineIterator(STableBlockScanInfo* pBlockScanInfo, STsdb static STsdb* getTsdbByRetentions(SVnode* pVnode, TSKEY winSKey, SRetention* retentions, const char* idstr, int8_t* pLevel); static SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, int8_t level); -static int64_t getCurrentKeyInLastBlock(SLastBlockReader* pLastBlockReader); static bool hasDataInLastBlock(SLastBlockReader* pLastBlockReader); static int32_t doBuildDataBlock(STsdbReader* pReader); static TSDBKEY getCurrentKeyInBuf(STableBlockScanInfo* pScanInfo, STsdbReader* pReader); @@ -220,7 +256,7 @@ static bool hasDataInFileBlock(const SBlockData* pBlockData, const SFil static void initBlockDumpInfo(STsdbReader* pReader, SDataBlockIter* pBlockIter); static int32_t getInitialDelIndex(const SArray* pDelSkyline, int32_t order); -static FORCE_INLINE STSchema* getLatestTableSchema(STsdbReader* pReader, uint64_t uid); +static STableBlockScanInfo* getTableBlockScanInfo(SSHashObj* pTableMap, uint64_t uid, const char* id); static bool outOfTimeWindow(int64_t ts, STimeWindow* pWindow) { return (ts > pWindow->ekey) || (ts < pWindow->skey); } @@ -298,6 +334,47 @@ static int32_t initBlockScanInfoBuf(SBlockInfoBuf* pBuf, int32_t numOfTables) { taosArrayPush(pBuf->pData, &p); } + pBuf->numOfTables = numOfTables; + + return TSDB_CODE_SUCCESS; +} + +static int32_t ensureBlockScanInfoBuf(SBlockInfoBuf* pBuf, int32_t numOfTables) { + if (numOfTables <= pBuf->numOfTables) { + return TSDB_CODE_SUCCESS; + } + + if (pBuf->numOfTables > 0) { + STableBlockScanInfo** p = (STableBlockScanInfo**)taosArrayPop(pBuf->pData); + taosMemoryFree(*p); + pBuf->numOfTables /= pBuf->numPerBucket; + } + + int32_t num = (numOfTables - pBuf->numOfTables) / pBuf->numPerBucket; + int32_t remainder = (numOfTables - pBuf->numOfTables) % pBuf->numPerBucket; + if (pBuf->pData == NULL) { + pBuf->pData = taosArrayInit(num + 1, POINTER_BYTES); + } + + for (int32_t i = 0; i < num; ++i) { + char* p = taosMemoryCalloc(pBuf->numPerBucket, sizeof(STableBlockScanInfo)); + if (p == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + taosArrayPush(pBuf->pData, &p); + } + + if (remainder > 0) { + char* p = taosMemoryCalloc(remainder, sizeof(STableBlockScanInfo)); + if (p == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + taosArrayPush(pBuf->pData, &p); + } + + pBuf->numOfTables = numOfTables; + return TSDB_CODE_SUCCESS; } @@ -328,12 +405,11 @@ static int32_t uidComparFunc(const void* p1, const void* p2) { } // NOTE: speedup the whole processing by preparing the buffer for STableBlockScanInfo in batch model -static SHashObj* createDataBlockScanInfo(STsdbReader* pTsdbReader, SBlockInfoBuf* pBuf, const STableKeyInfo* idList, - STableUidList *pUidList, int32_t numOfTables) { +static SSHashObj* createDataBlockScanInfo(STsdbReader* pTsdbReader, SBlockInfoBuf* pBuf, const STableKeyInfo* idList, + STableUidList* pUidList, int32_t numOfTables) { // allocate buffer in order to load data blocks from file // todo use simple hash instead, optimize the memory consumption - SHashObj* pTableMap = - taosHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); + SSHashObj* pTableMap = tSimpleHashInit(numOfTables, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT)); if (pTableMap == NULL) { return NULL; } @@ -343,8 +419,10 @@ static SHashObj* createDataBlockScanInfo(STsdbReader* pTsdbReader, SBlockInfoBuf pUidList->tableUidList = taosMemoryMalloc(numOfTables * sizeof(uint64_t)); if (pUidList->tableUidList == NULL) { + tSimpleHashCleanup(pTableMap); return NULL; } + pUidList->currentIndex = 0; for (int32_t j = 0; j < numOfTables; ++j) { @@ -356,12 +434,14 @@ static SHashObj* createDataBlockScanInfo(STsdbReader* pTsdbReader, SBlockInfoBuf if (ASCENDING_TRAVERSE(pTsdbReader->order)) { int64_t skey = pTsdbReader->window.skey; pScanInfo->lastKey = (skey > INT64_MIN) ? (skey - 1) : skey; + pScanInfo->lastKeyInStt = skey; } else { int64_t ekey = pTsdbReader->window.ekey; pScanInfo->lastKey = (ekey < INT64_MAX) ? (ekey + 1) : ekey; + pScanInfo->lastKeyInStt = ekey; } - taosHashPut(pTableMap, &pScanInfo->uid, sizeof(uint64_t), &pScanInfo, POINTER_BYTES); + tSimpleHashPut(pTableMap, &pScanInfo->uid, sizeof(uint64_t), &pScanInfo, POINTER_BYTES); tsdbTrace("%p check table uid:%" PRId64 " from lastKey:%" PRId64 " %s", pTsdbReader, pScanInfo->uid, pScanInfo->lastKey, pTsdbReader->idStr); } @@ -376,9 +456,11 @@ static SHashObj* createDataBlockScanInfo(STsdbReader* pTsdbReader, SBlockInfoBuf return pTableMap; } -static void resetAllDataBlockScanInfo(SHashObj* pTableMap, int64_t ts) { - STableBlockScanInfo** p = NULL; - while ((p = taosHashIterate(pTableMap, p)) != NULL) { +static void resetAllDataBlockScanInfo(SSHashObj* pTableMap, int64_t ts, int32_t step) { + void *p = NULL; + int32_t iter = 0; + + while ((p = tSimpleHashIterate(pTableMap, p, &iter)) != NULL) { STableBlockScanInfo* pInfo = *(STableBlockScanInfo**)p; pInfo->iterInit = false; @@ -395,6 +477,7 @@ static void resetAllDataBlockScanInfo(SHashObj* pTableMap, int64_t ts) { pInfo->delSkyline = taosArrayDestroy(pInfo->delSkyline); pInfo->lastKey = ts; + pInfo->lastKeyInStt = ts + step; } } @@ -417,13 +500,15 @@ static void clearBlockScanInfo(STableBlockScanInfo* p) { tMapDataClear(&p->mapData); } -static void destroyAllBlockScanInfo(SHashObj* pTableMap) { +static void destroyAllBlockScanInfo(SSHashObj* pTableMap) { void* p = NULL; - while ((p = taosHashIterate(pTableMap, p)) != NULL) { + int32_t iter = 0; + + while ((p = tSimpleHashIterate(pTableMap, p, &iter)) != NULL) { clearBlockScanInfo(*(STableBlockScanInfo**)p); } - taosHashCleanup(pTableMap); + tSimpleHashCleanup(pTableMap); } static bool isEmptyQueryTimeWindow(STimeWindow* pWindow) { return pWindow->skey > pWindow->ekey; } @@ -475,8 +560,7 @@ static int32_t initFilesetIterator(SFilesetIter* pIter, SArray* aDFileSet, STsdb SBlockLoadSuppInfo* pInfo = &pReader->suppInfo; int32_t numOfStt = pReader->pTsdb->pVnode->config.sttTrigger; - pLReader->pInfo = - tCreateLastBlockLoadInfo(pReader->pSchema, &pInfo->colId[1], pInfo->numOfCols - 1, numOfStt); + pLReader->pInfo = tCreateLastBlockLoadInfo(pReader->pSchema, &pInfo->colId[1], pInfo->numOfCols - 1, numOfStt); if (pLReader->pInfo == NULL) { tsdbDebug("init fileset iterator failed, code:%s %s", tstrerror(terrno), pReader->idStr); return terrno; @@ -487,13 +571,15 @@ static int32_t initFilesetIterator(SFilesetIter* pIter, SArray* aDFileSet, STsdb return TSDB_CODE_SUCCESS; } -static bool filesetIteratorNext(SFilesetIter* pIter, STsdbReader* pReader) { +static int32_t filesetIteratorNext(SFilesetIter* pIter, STsdbReader* pReader, bool* hasNext) { bool asc = ASCENDING_TRAVERSE(pIter->order); int32_t step = asc ? 1 : -1; pIter->index += step; + int32_t code = 0; if ((asc && pIter->index >= pIter->numOfFiles) || ((!asc) && pIter->index < 0)) { - return false; + *hasNext = false; + return TSDB_CODE_SUCCESS; } SIOCostSummary* pSum = &pReader->cost; @@ -513,7 +599,7 @@ static bool filesetIteratorNext(SFilesetIter* pIter, STsdbReader* pReader) { pReader->status.pCurrentFileset = (SDFileSet*)taosArrayGet(pIter->pFileList, pIter->index); - int32_t code = tsdbDataFReaderOpen(&pReader->pFileReader, pReader->pTsdb, pReader->status.pCurrentFileset); + code = tsdbDataFReaderOpen(&pReader->pFileReader, pReader->pTsdb, pReader->status.pCurrentFileset); if (code != TSDB_CODE_SUCCESS) { goto _err; } @@ -527,24 +613,28 @@ static bool filesetIteratorNext(SFilesetIter* pIter, STsdbReader* pReader) { if ((asc && win.skey > pReader->window.ekey) || (!asc && win.ekey < pReader->window.skey)) { tsdbDebug("%p remain files are not qualified for qrange:%" PRId64 "-%" PRId64 ", ignore, %s", pReader, pReader->window.skey, pReader->window.ekey, pReader->idStr); - return false; + *hasNext = false; + return TSDB_CODE_SUCCESS; } if ((asc && (win.ekey < pReader->window.skey)) || ((!asc) && (win.skey > pReader->window.ekey))) { pIter->index += step; if ((asc && pIter->index >= pIter->numOfFiles) || ((!asc) && pIter->index < 0)) { - return false; + *hasNext = false; + return TSDB_CODE_SUCCESS; } continue; } tsdbDebug("%p file found fid:%d for qrange:%" PRId64 "-%" PRId64 ", %s", pReader, fid, pReader->window.skey, pReader->window.ekey, pReader->idStr); - return true; + *hasNext = true; + return TSDB_CODE_SUCCESS; } _err: - return false; + *hasNext = false; + return code; } static void resetDataBlockIterator(SDataBlockIter* pIter, int32_t order) { @@ -587,6 +677,83 @@ static SSDataBlock* createResBlock(SQueryTableDataCond* pCond, int32_t capacity) return pResBlock; } +static int32_t tsdbInitReaderLock(STsdbReader* pReader) { + int32_t code = -1; + qTrace("tsdb/read: %p, pre-init read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + code = taosThreadMutexInit(&pReader->readerMutex, NULL); + + qTrace("tsdb/read: %p, post-init read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + return code; +} + +static int32_t tsdbUninitReaderLock(STsdbReader* pReader) { + int32_t code = -1; + qTrace("tsdb/read: %p, pre-uninit read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + code = taosThreadMutexDestroy(&pReader->readerMutex); + + qTrace("tsdb/read: %p, post-uninit read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + return code; +} + +static int32_t tsdbAcquireReader(STsdbReader* pReader) { + int32_t code = -1; + qTrace("tsdb/read: %p, pre-take read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + code = taosThreadMutexLock(&pReader->readerMutex); + + qTrace("tsdb/read: %p, post-take read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + return code; +} + +static int32_t tsdbTryAcquireReader(STsdbReader* pReader) { + int32_t code = -1; + qTrace("tsdb/read: %p, pre-trytake read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + code = taosThreadMutexTryLock(&pReader->readerMutex); + + qTrace("tsdb/read: %p, post-trytake read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + return code; +} + +static int32_t tsdbReleaseReader(STsdbReader* pReader) { + int32_t code = -1; + qTrace("tsdb/read: %p, pre-untake read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + code = taosThreadMutexUnlock(&pReader->readerMutex); + + qTrace("tsdb/read: %p, post-untake read mutex: %p, code: %d", pReader, &pReader->readerMutex, code); + + return code; +} + +void tsdbReleaseDataBlock(STsdbReader* pReader) { + SReaderStatus* pStatus = &pReader->status; + if (!pStatus->composedDataBlock) { + tsdbReleaseReader(pReader); + } +} + +static int32_t initResBlockInfo(SResultBlockInfo* pResBlockInfo, int64_t capacity, SSDataBlock* pResBlock, SQueryTableDataCond* pCond) { + pResBlockInfo->capacity = capacity; + pResBlockInfo->pResBlock = pResBlock; + terrno = 0; + + if (pResBlockInfo->pResBlock == NULL) { + pResBlockInfo->freeBlock = true; + pResBlockInfo->pResBlock = createResBlock(pCond, pResBlockInfo->capacity); + } else { + pResBlockInfo->freeBlock = false; + } + + return terrno; +} + static int32_t tsdbReaderCreate(SVnode* pVnode, SQueryTableDataCond* pCond, STsdbReader** ppReader, int32_t capacity, SSDataBlock* pResBlock, const char* idstr) { int32_t code = 0; @@ -606,21 +773,16 @@ static int32_t tsdbReaderCreate(SVnode* pVnode, SQueryTableDataCond* pCond, STsd pReader->pTsdb = getTsdbByRetentions(pVnode, pCond->twindows.skey, pVnode->config.tsdbCfg.retentions, idstr, &level); pReader->suid = pCond->suid; pReader->order = pCond->order; - pReader->capacity = capacity; - pReader->pResBlock = pResBlock; - pReader->idStr = (idstr != NULL) ? strdup(idstr) : NULL; + + pReader->idStr = (idstr != NULL) ? taosStrdup(idstr) : NULL; pReader->verRange = getQueryVerRange(pVnode, pCond, level); pReader->type = pCond->type; pReader->window = updateQueryTimeWindow(pReader->pTsdb, &pCond->twindows); pReader->blockInfoBuf.numPerBucket = 1000; // 1000 tables per bucket - if (pReader->pResBlock == NULL) { - pReader->freeBlock = true; - pReader->pResBlock = createResBlock(pCond, pReader->capacity); - if (pReader->pResBlock == NULL) { - code = terrno; - goto _end; - } + code = initResBlockInfo(&pReader->resBlockInfo, capacity, pResBlock, pCond); + if (code != TSDB_CODE_SUCCESS) { + goto _end; } if (pCond->numOfCols <= 0) { @@ -638,6 +800,7 @@ static int32_t tsdbReaderCreate(SVnode* pVnode, SQueryTableDataCond* pCond, STsd } pSup->tsColAgg.colId = PRIMARYKEY_TIMESTAMP_COL_ID; + setColumnIdSlotList(pSup, pCond->colList, pCond->pSlotList, pCond->numOfCols); code = tBlockDataCreate(&pReader->status.fileBlockData); if (code != TSDB_CODE_SUCCESS) { @@ -645,7 +808,22 @@ static int32_t tsdbReaderCreate(SVnode* pVnode, SQueryTableDataCond* pCond, STsd goto _end; } - setColumnIdSlotList(pSup, pCond->colList, pCond->pSlotList, pCond->numOfCols); + if (pReader->suppInfo.colId[0] != PRIMARYKEY_TIMESTAMP_COL_ID) { + tsdbError("the first column isn't primary timestamp, %d, %s", pReader->suppInfo.colId[0], pReader->idStr); + terrno = TSDB_CODE_INVALID_PARA; + goto _end; + } + + pReader->status.pPrimaryTsCol = taosArrayGet(pReader->resBlockInfo.pResBlock->pDataBlock, pSup->slotId[0]); + int32_t type = pReader->status.pPrimaryTsCol->info.type; + if (type != TSDB_DATA_TYPE_TIMESTAMP) { + tsdbError("the first column isn't primary timestamp in result block, actual: %s, %s", tDataTypes[type].name, + pReader->idStr); + terrno = TSDB_CODE_INVALID_PARA; + goto _end; + } + + tsdbInitReaderLock(pReader); *ppReader = pReader; return code; @@ -657,14 +835,14 @@ _end: } static int32_t doLoadBlockIndex(STsdbReader* pReader, SDataFReader* pFileReader, SArray* pIndexList) { - int64_t st = taosGetTimestampUs(); + int64_t st = taosGetTimestampUs(); LRUHandle* handle = NULL; int32_t code = tsdbCacheGetBlockIdx(pFileReader->pTsdb->biCache, pFileReader, &handle); if (code != TSDB_CODE_SUCCESS || handle == NULL) { goto _end; } - int32_t numOfTables = taosHashGetSize(pReader->status.pTableMap); + int32_t numOfTables = tSimpleHashGetSize(pReader->status.pTableMap); SArray* aBlockIdx = (SArray*)taosLRUCacheValue(pFileReader->pTsdb->biCache, handle); size_t num = taosArrayGetSize(aBlockIdx); @@ -676,11 +854,11 @@ static int32_t doLoadBlockIndex(STsdbReader* pReader, SDataFReader* pFileReader, // todo binary search to the start position int64_t et1 = taosGetTimestampUs(); - SBlockIdx* pBlockIdx = NULL; + SBlockIdx* pBlockIdx = NULL; STableUidList* pList = &pReader->status.uidList; int32_t i = 0, j = 0; - while(i < num && j < numOfTables) { + while (i < num && j < numOfTables) { pBlockIdx = (SBlockIdx*)taosArrayGet(aBlockIdx, i); if (pBlockIdx->suid != pReader->suid) { i += 1; @@ -699,13 +877,12 @@ static int32_t doLoadBlockIndex(STsdbReader* pReader, SDataFReader* pFileReader, if (pBlockIdx->uid == pList->tableUidList[j]) { // this block belongs to a table that is not queried. - void* p = taosHashGet(pReader->status.pTableMap, &pBlockIdx->uid, sizeof(uint64_t)); - if (p == NULL) { - tsdbError("failed to locate the tableBlockScan Info in hashmap, uid:%"PRIu64", %s", pBlockIdx->uid, pReader->idStr); - return TSDB_CODE_APP_ERROR; + STableBlockScanInfo* pScanInfo = getTableBlockScanInfo(pReader->status.pTableMap, pBlockIdx->uid, pReader->idStr); + if (pScanInfo == NULL) { + tsdbBICacheRelease(pFileReader->pTsdb->biCache, handle); + return terrno; } - STableBlockScanInfo* pScanInfo = *(STableBlockScanInfo**)p; if (pScanInfo->pBlockList == NULL) { pScanInfo->pBlockList = taosArrayInit(4, sizeof(SBlockIndex)); } @@ -729,33 +906,48 @@ _end: return code; } -static void cleanupTableScanInfo(SHashObj* pTableMap) { +static void doCleanupTableScanInfo(STableBlockScanInfo* pScanInfo) { + // reset the index in last block when handing a new file + tMapDataClear(&pScanInfo->mapData); + taosArrayClear(pScanInfo->pBlockList); +} + +static void cleanupTableScanInfo(SReaderStatus* pStatus) { + if (pStatus->mapDataCleaned) { + return; + } + + SSHashObj* pTableMap = pStatus->pTableMap; STableBlockScanInfo** px = NULL; + int32_t iter = 0; + while (1) { - px = taosHashIterate(pTableMap, px); + px = tSimpleHashIterate(pTableMap, px, &iter); if (px == NULL) { break; } - // reset the index in last block when handing a new file - tMapDataClear(&(*px)->mapData); - taosArrayClear((*px)->pBlockList); + doCleanupTableScanInfo(*px); } + + pStatus->mapDataCleaned = true; } -static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockNumber* pBlockNum) { - int32_t numOfQTable = 0; +static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockNumber* pBlockNum, SArray* pTableScanInfoList) { size_t sizeInDisk = 0; size_t numOfTables = taosArrayGetSize(pIndexList); int64_t st = taosGetTimestampUs(); - cleanupTableScanInfo(pReader->status.pTableMap); + cleanupTableScanInfo(&pReader->status); + // set the flag for the new file + pReader->status.mapDataCleaned = false; for (int32_t i = 0; i < numOfTables; ++i) { - SBlockIdx* pBlockIdx = taosArrayGet(pIndexList, i); - - STableBlockScanInfo* pScanInfo = - *(STableBlockScanInfo**)taosHashGet(pReader->status.pTableMap, &pBlockIdx->uid, sizeof(int64_t)); + SBlockIdx* pBlockIdx = taosArrayGet(pIndexList, i); + STableBlockScanInfo* pScanInfo = getTableBlockScanInfo(pReader->status.pTableMap, pBlockIdx->uid, pReader->idStr); + if (pScanInfo == NULL) { + return terrno; + } tMapDataReset(&pScanInfo->mapData); tsdbReadDataBlk(pReader->pFileReader, pBlockIdx, &pScanInfo->mapData); @@ -763,12 +955,25 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN sizeInDisk += pScanInfo->mapData.nData; + int32_t step = ASCENDING_TRAVERSE(pReader->order) ? 1 : -1; + STimeWindow w = pReader->window; + if (ASCENDING_TRAVERSE(pReader->order)) { + w.skey = pScanInfo->lastKey + step; + } else { + w.ekey = pScanInfo->lastKey + step; + } + + if (isEmptyQueryTimeWindow(&w)) { + continue; + } + SDataBlk block = {0}; for (int32_t j = 0; j < pScanInfo->mapData.nItem; ++j) { tGetDataBlk(pScanInfo->mapData.pData + pScanInfo->mapData.aOffset[j], &block); // 1. time range check - if (block.minKey.ts > pReader->window.ekey || block.maxKey.ts < pReader->window.skey) { + // if (block.minKey.ts > pReader->window.ekey || block.maxKey.ts < pReader->window.skey) { + if (block.minKey.ts > w.ekey || block.maxKey.ts < w.skey) { continue; } @@ -789,8 +994,8 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN pBlockNum->numOfBlocks += 1; } - if (pScanInfo->pBlockList != NULL && taosArrayGetSize(pScanInfo->pBlockList) > 0) { - numOfQTable += 1; + if (taosArrayGetSize(pScanInfo->pBlockList) > 0) { + taosArrayPush(pTableScanInfoList, &pScanInfo); } } @@ -801,8 +1006,8 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN tsdbDebug( "load block of %ld tables completed, blocks:%d in %d tables, last-files:%d, block-info-size:%.2f Kb, elapsed " "time:%.2f ms %s", - numOfTables, pBlockNum->numOfBlocks, numOfQTable, pBlockNum->numOfLastFiles, sizeInDisk / 1000.0, el, - pReader->idStr); + numOfTables, pBlockNum->numOfBlocks, (int32_t)taosArrayGetSize(pTableScanInfoList), pBlockNum->numOfLastFiles, + sizeInDisk / 1000.0, el, pReader->idStr); pReader->cost.numOfBlocks += total; pReader->cost.headFileLoadTime += el; @@ -816,23 +1021,29 @@ static void setBlockAllDumped(SFileBlockDumpInfo* pDumpInfo, int64_t maxKey, int pDumpInfo->lastKey = maxKey + step; } -static void doCopyColVal(SColumnInfoData* pColInfoData, int32_t rowIndex, int32_t colIndex, SColVal* pColVal, - SBlockLoadSuppInfo* pSup) { +static int32_t doCopyColVal(SColumnInfoData* pColInfoData, int32_t rowIndex, int32_t colIndex, SColVal* pColVal, + SBlockLoadSuppInfo* pSup) { if (IS_VAR_DATA_TYPE(pColVal->type)) { if (!COL_VAL_IS_VALUE(pColVal)) { - colDataAppendNULL(pColInfoData, rowIndex); + colDataSetNULL(pColInfoData, rowIndex); } else { varDataSetLen(pSup->buildBuf[colIndex], pColVal->value.nData); - ASSERT(pColVal->value.nData <= pColInfoData->info.bytes); + if (pColVal->value.nData > pColInfoData->info.bytes) { + tsdbWarn("column cid:%d actual data len %d is bigger than schema len %d", pColVal->cid, pColVal->value.nData, + pColInfoData->info.bytes); + return TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER; + } if (pColVal->value.nData > 0) { // pData may be null, if nData is 0 memcpy(varDataVal(pSup->buildBuf[colIndex]), pColVal->value.pData, pColVal->value.nData); } - colDataAppend(pColInfoData, rowIndex, pSup->buildBuf[colIndex], false); + colDataSetVal(pColInfoData, rowIndex, pSup->buildBuf[colIndex], false); } } else { - colDataAppend(pColInfoData, rowIndex, (const char*)&pColVal->value, !COL_VAL_IS_VALUE(pColVal)); + colDataSetVal(pColInfoData, rowIndex, (const char*)&pColVal->value, !COL_VAL_IS_VALUE(pColVal)); } + + return TSDB_CODE_SUCCESS; } static SFileDataBlockInfo* getCurrentBlockInfo(SDataBlockIter* pBlockIter) { @@ -854,9 +1065,7 @@ static int doBinarySearchKey(TSKEY* keyList, int num, int pos, TSKEY key, int or s = pos; // check - assert(pos >= 0 && pos < num); - assert(num > 0); - + ASSERT(pos >= 0 && pos < num && num > 0); if (order == TSDB_ORDER_ASC) { // find the first position which is smaller than the key e = num - 1; @@ -1034,8 +1243,9 @@ static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader) { SBlockData* pBlockData = &pStatus->fileBlockData; SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(pBlockIter); SDataBlk* pBlock = getCurrentBlock(pBlockIter); - SSDataBlock* pResBlock = pReader->pResBlock; + SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock; int32_t numOfOutputCols = pSupInfo->numOfCols; + int32_t code = TSDB_CODE_SUCCESS; SColVal cv = {0}; int64_t st = taosGetTimestampUs(); @@ -1044,8 +1254,8 @@ static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader) { // no data exists, return directly. if (pBlockData->nRow == 0 || pBlockData->aTSKEY == 0) { - tsdbWarn("%p no need to copy since no data in blockData, table uid:%" PRIu64 " has been dropped, %s", pReader, pBlockInfo->uid, - pReader->idStr); + tsdbWarn("%p no need to copy since no data in blockData, table uid:%" PRIu64 " has been dropped, %s", pReader, + pBlockInfo->uid, pReader->idStr); pResBlock->info.rows = 0; return 0; } @@ -1081,8 +1291,8 @@ static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader) { endIndex += step; int32_t dumpedRows = asc ? (endIndex - pDumpInfo->rowIndex) : (pDumpInfo->rowIndex - endIndex); - if (dumpedRows > pReader->capacity) { // output buffer check - dumpedRows = pReader->capacity; + if (dumpedRows > pReader->resBlockInfo.capacity) { // output buffer check + dumpedRows = pReader->resBlockInfo.capacity; } int32_t i = 0; @@ -1106,14 +1316,17 @@ static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader) { pColData = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]); if (pData->flag == HAS_NONE || pData->flag == HAS_NULL || pData->flag == (HAS_NULL | HAS_NONE)) { - colDataAppendNNULL(pColData, 0, dumpedRows); + colDataSetNNULL(pColData, 0, dumpedRows); } else { if (IS_MATHABLE_TYPE(pColData->info.type)) { copyNumericCols(pData, pDumpInfo, pColData, dumpedRows, asc); } else { // varchar/nchar type for (int32_t j = pDumpInfo->rowIndex; rowIndex < dumpedRows; j += step) { tColDataGetValue(pData, j, &cv); - doCopyColVal(pColData, rowIndex++, i, &cv, pSupInfo); + code = doCopyColVal(pColData, rowIndex++, i, &cv, pSupInfo); + if (code) { + return code; + } } } } @@ -1122,7 +1335,7 @@ static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader) { i += 1; } else { // the specified column does not exist in file block, fill with null data pColData = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]); - colDataAppendNNULL(pColData, 0, dumpedRows); + colDataSetNNULL(pColData, 0, dumpedRows); i += 1; } } @@ -1130,7 +1343,7 @@ static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader) { // fill the mis-matched columns with null value while (i < numOfOutputCols) { pColData = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]); - colDataAppendNNULL(pColData, 0, dumpedRows); + colDataSetNNULL(pColData, 0, dumpedRows); i += 1; } @@ -1161,20 +1374,44 @@ static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader) { return TSDB_CODE_SUCCESS; } +static FORCE_INLINE STSchema* getTableSchemaImpl(STsdbReader* pReader, uint64_t uid) { + ASSERT(pReader->pSchema == NULL); + + int32_t code = metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->suid, uid, -1, &pReader->pSchema); + if (code != TSDB_CODE_SUCCESS || pReader->pSchema == NULL) { + terrno = code; + tsdbError("failed to get table schema, uid:%" PRIu64 ", it may have been dropped, ver:-1, %s", uid, pReader->idStr); + return NULL; + } + + code = tsdbRowMergerInit(&pReader->status.merger, pReader->pSchema); + if (code != TSDB_CODE_SUCCESS) { + terrno = code; + tsdbError("failed to init merger, code:%s, %s", tstrerror(code), pReader->idStr); + return NULL; + } + + return pReader->pSchema; +} + static int32_t doLoadFileBlockData(STsdbReader* pReader, SDataBlockIter* pBlockIter, SBlockData* pBlockData, uint64_t uid) { - int32_t code = 0; - int64_t st = taosGetTimestampUs(); + int32_t code = 0; + STSchema* pSchema = pReader->pSchema; + int64_t st = taosGetTimestampUs(); tBlockDataReset(pBlockData); - STSchema* pSchema = getLatestTableSchema(pReader, uid); - if (pSchema == NULL) { - tsdbDebug("%p table uid:%"PRIu64" has been dropped, no data existed, %s", pReader, uid, pReader->idStr); - return code; + + if (pReader->pSchema == NULL) { + pSchema = getTableSchemaImpl(pReader, uid); + if (pSchema == NULL) { + tsdbDebug("%p table uid:%" PRIu64 " has been dropped, no data existed, %s", pReader, uid, pReader->idStr); + return code; + } } SBlockLoadSuppInfo* pSup = &pReader->suppInfo; - TABLEID tid = {.suid = pReader->suid, .uid = uid}; + TABLEID tid = {.suid = pReader->suid, .uid = uid}; code = tBlockDataInit(pBlockData, &tid, pSchema, &pSup->colId[1], pSup->numOfCols - 1); if (code != TSDB_CODE_SUCCESS) { return code; @@ -1257,14 +1494,13 @@ static int32_t fileDataBlockOrderCompar(const void* pLeft, const void* pRight, v static int32_t doSetCurrentBlock(SDataBlockIter* pBlockIter, const char* idStr) { SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(pBlockIter); if (pBlockInfo != NULL) { - STableBlockScanInfo** pScanInfo = taosHashGet(pBlockIter->pTableMap, &pBlockInfo->uid, sizeof(pBlockInfo->uid)); + STableBlockScanInfo* pScanInfo = getTableBlockScanInfo(pBlockIter->pTableMap, pBlockInfo->uid, idStr); if (pScanInfo == NULL) { - tsdbError("failed to locate the uid:%" PRIu64 " in query table uid list, %s", pBlockInfo->uid, idStr); - return TSDB_CODE_INVALID_PARA; + return terrno; } - SBlockIndex* pIndex = taosArrayGet((*pScanInfo)->pBlockList, pBlockInfo->tbBlockIdx); - tMapDataGetItemByIdx(&(*pScanInfo)->mapData, pIndex->ordinalIndex, &pBlockIter->block, tGetDataBlk); + SBlockIndex* pIndex = taosArrayGet(pScanInfo->pBlockList, pBlockInfo->tbBlockIdx); + tMapDataGetItemByIdx(&pScanInfo->mapData, pIndex->ordinalIndex, &pBlockIter->block, tGetDataBlk); } #if 0 @@ -1274,7 +1510,7 @@ static int32_t doSetCurrentBlock(SDataBlockIter* pBlockIter, const char* idStr) return TSDB_CODE_SUCCESS; } -static int32_t initBlockIterator(STsdbReader* pReader, SDataBlockIter* pBlockIter, int32_t numOfBlocks) { +static int32_t initBlockIterator(STsdbReader* pReader, SDataBlockIter* pBlockIter, int32_t numOfBlocks, SArray* pTableList) { bool asc = ASCENDING_TRAVERSE(pReader->order); SBlockOrderSupporter sup = {0}; @@ -1283,7 +1519,7 @@ static int32_t initBlockIterator(STsdbReader* pReader, SDataBlockIter* pBlockIte pBlockIter->pTableMap = pReader->status.pTableMap; // access data blocks according to the offset of each block in asc/desc order. - int32_t numOfTables = (int32_t)taosHashGetSize(pReader->status.pTableMap); + int32_t numOfTables = taosArrayGetSize(pTableList); int64_t st = taosGetTimestampUs(); int32_t code = initBlockOrderSupporter(&sup, numOfTables); @@ -1292,17 +1528,10 @@ static int32_t initBlockIterator(STsdbReader* pReader, SDataBlockIter* pBlockIte } int32_t cnt = 0; - void* ptr = NULL; - while (1) { - ptr = taosHashIterate(pReader->status.pTableMap, ptr); - if (ptr == NULL) { - break; - } - STableBlockScanInfo* pTableScanInfo = *(STableBlockScanInfo**)ptr; - if (pTableScanInfo->pBlockList == NULL || taosArrayGetSize(pTableScanInfo->pBlockList) == 0) { - continue; - } + for (int32_t i = 0; i < numOfTables; ++i) { + STableBlockScanInfo* pTableScanInfo = taosArrayGetP(pTableList, i); + ASSERT(pTableScanInfo->pBlockList != NULL && taosArrayGetSize(pTableScanInfo->pBlockList) > 0); size_t num = taosArrayGetSize(pTableScanInfo->pBlockList); sup.numOfBlocksPerTable[sup.numOfTables] = num; @@ -1578,7 +1807,7 @@ static void getBlockToLoadInfo(SDataBlockToLoadInfo* pInfo, SFileDataBlockInfo* pInfo->overlapWithLastBlock = !(pBlock->maxKey.ts < tsLast || pBlock->minKey.ts > tsLast); } - pInfo->moreThanCapcity = pBlock->nRow > pReader->capacity; + pInfo->moreThanCapcity = pBlock->nRow > pReader->resBlockInfo.capacity; pInfo->partiallyRequired = dataBlockPartiallyRequired(&pReader->window, &pReader->verRange, pBlock); pInfo->overlapWithKeyInBuf = keyOverlapFileBlock(keyInBuf, pBlock, &pReader->verRange); } @@ -1600,7 +1829,8 @@ static bool fileBlockShouldLoad(STsdbReader* pReader, SFileDataBlockInfo* pBlock // log the reason why load the datablock for profile if (loadDataBlock) { - tsdbDebug("%p uid:%" PRIu64 " need to load the datablock, overlapneighbor:%d, hasDup:%d, partiallyRequired:%d, " + tsdbDebug("%p uid:%" PRIu64 + " need to load the datablock, overlapneighbor:%d, hasDup:%d, partiallyRequired:%d, " "overlapWithKey:%d, greaterThanBuf:%d, overlapWithDel:%d, overlapWithlastBlock:%d, %s", pReader, pBlockInfo->uid, info.overlapWithNeighborBlock, info.hasDupTs, info.partiallyRequired, info.overlapWithKeyInBuf, info.moreThanCapcity, info.overlapWithDelInfo, info.overlapWithLastBlock, @@ -1624,10 +1854,10 @@ static int32_t buildDataBlockFromBuf(STsdbReader* pReader, STableBlockScanInfo* return TSDB_CODE_SUCCESS; } - SSDataBlock* pBlock = pReader->pResBlock; + SSDataBlock* pBlock = pReader->resBlockInfo.pResBlock; int64_t st = taosGetTimestampUs(); - int32_t code = buildDataBlockFromBufImpl(pBlockScanInfo, endKey, pReader->capacity, pReader); + int32_t code = buildDataBlockFromBufImpl(pBlockScanInfo, endKey, pReader->resBlockInfo.capacity, pReader); blockDataUpdateTsWindow(pBlock, pReader->suppInfo.slotId[0]); pBlock->info.id.uid = pBlockScanInfo->uid; @@ -1635,8 +1865,8 @@ static int32_t buildDataBlockFromBuf(STsdbReader* pReader, STableBlockScanInfo* setComposedBlockFlag(pReader, true); double elapsedTime = (taosGetTimestampUs() - st) / 1000.0; - tsdbDebug("%p build data block from cache completed, elapsed time:%.2f ms, numOfRows:%d, brange:%" PRId64 - " - %" PRId64 ", uid:%"PRIu64", %s", + tsdbDebug("%p build data block from cache completed, elapsed time:%.2f ms, numOfRows:%" PRId64 ", brange:%" PRId64 + " - %" PRId64 ", uid:%" PRIu64 ", %s", pReader, elapsedTime, pBlock->info.rows, pBlock->info.window.skey, pBlock->info.window.ekey, pBlockScanInfo->uid, pReader->idStr); @@ -1645,120 +1875,124 @@ static int32_t buildDataBlockFromBuf(STsdbReader* pReader, STableBlockScanInfo* } static bool tryCopyDistinctRowFromFileBlock(STsdbReader* pReader, SBlockData* pBlockData, int64_t key, - SFileBlockDumpInfo* pDumpInfo) { + SFileBlockDumpInfo* pDumpInfo, bool* copied) { // opt version // 1. it is not a border point // 2. the direct next point is not an duplicated timestamp + int32_t code = TSDB_CODE_SUCCESS; + + *copied = false; bool asc = (pReader->order == TSDB_ORDER_ASC); if ((pDumpInfo->rowIndex < pDumpInfo->totalRows - 1 && asc) || (pDumpInfo->rowIndex > 0 && (!asc))) { int32_t step = pReader->order == TSDB_ORDER_ASC ? 1 : -1; int64_t nextKey = pBlockData->aTSKEY[pDumpInfo->rowIndex + step]; if (nextKey != key) { // merge is not needed - doAppendRowFromFileBlock(pReader->pResBlock, pReader, pBlockData, pDumpInfo->rowIndex); + code = doAppendRowFromFileBlock(pReader->resBlockInfo.pResBlock, pReader, pBlockData, pDumpInfo->rowIndex); + if (code) { + return code; + } pDumpInfo->rowIndex += step; - return true; + *copied = true; } } - return false; + return code; } static bool nextRowFromLastBlocks(SLastBlockReader* pLastBlockReader, STableBlockScanInfo* pScanInfo, SVersionRange* pVerRange) { - int32_t step = ASCENDING_TRAVERSE(pLastBlockReader->order)? 1:-1; + int32_t step = ASCENDING_TRAVERSE(pLastBlockReader->order) ? 1 : -1; while (1) { bool hasVal = tMergeTreeNext(&pLastBlockReader->mergeTree); - if (!hasVal) { + if (!hasVal) { // the next value will be the accessed key in stt + pScanInfo->lastKeyInStt += step; return false; } - TSDBROW row = tMergeTreeGetRow(&pLastBlockReader->mergeTree); - TSDBKEY k = TSDBROW_KEY(&row); - if (hasBeenDropped(pScanInfo->delSkyline, &pScanInfo->lastBlockDelIndex, &k, pLastBlockReader->order, pVerRange)) { - pScanInfo->lastKey = k.ts; - } else { - // the qualifed ts may equal to k.ts, only a greater version one. - // here we need to fallback one step. - if (pScanInfo->lastKey == k.ts) { - pScanInfo->lastKey -= step; - } + TSDBROW* pRow = tMergeTreeGetRow(&pLastBlockReader->mergeTree); + int64_t key = pRow->pBlockData->aTSKEY[pRow->iRow]; + int64_t ver = pRow->pBlockData->aVersion[pRow->iRow]; + pLastBlockReader->currentKey = key; + pScanInfo->lastKeyInStt = key; + + if (!hasBeenDropped(pScanInfo->delSkyline, &pScanInfo->lastBlockDelIndex, key, ver, pLastBlockReader->order, pVerRange)) { return true; } } } static bool tryCopyDistinctRowFromSttBlock(TSDBROW* fRow, SLastBlockReader* pLastBlockReader, - STableBlockScanInfo* pScanInfo, int64_t ts, STsdbReader* pReader) { + STableBlockScanInfo* pScanInfo, int64_t ts, STsdbReader* pReader, + bool* copied) { + int32_t code = TSDB_CODE_SUCCESS; + + *copied = false; + bool hasVal = nextRowFromLastBlocks(pLastBlockReader, pScanInfo, &pReader->verRange); if (hasVal) { int64_t next1 = getCurrentKeyInLastBlock(pLastBlockReader); if (next1 != ts) { - doAppendRowFromFileBlock(pReader->pResBlock, pReader, fRow->pBlockData, fRow->iRow); - return true; + code = doAppendRowFromFileBlock(pReader->resBlockInfo.pResBlock, pReader, fRow->pBlockData, fRow->iRow); + if (code) { + return code; + } + + *copied = true; + return code; } } else { - doAppendRowFromFileBlock(pReader->pResBlock, pReader, fRow->pBlockData, fRow->iRow); - return true; - } - - return false; -} - -static FORCE_INLINE STSchema* getLatestTableSchema(STsdbReader* pReader, uint64_t uid) { - if (pReader->pSchema != NULL) { - return pReader->pSchema; - } + code = doAppendRowFromFileBlock(pReader->resBlockInfo.pResBlock, pReader, fRow->pBlockData, fRow->iRow); + if (code) { + return code; + } - pReader->pSchema = metaGetTbTSchema(pReader->pTsdb->pVnode->pMeta, uid, -1, 1); - if (pReader->pSchema == NULL) { - tsdbError("failed to get table schema, uid:%" PRIu64 ", it may have been dropped, ver:-1, %s", uid, pReader->idStr); + *copied = true; + return code; } - return pReader->pSchema; + return code; } static FORCE_INLINE STSchema* doGetSchemaForTSRow(int32_t sversion, STsdbReader* pReader, uint64_t uid) { // always set the newest schema version in pReader->pSchema if (pReader->pSchema == NULL) { - pReader->pSchema = metaGetTbTSchema(pReader->pTsdb->pVnode->pMeta, uid, -1, 1); + STSchema* ps = getTableSchemaImpl(pReader, uid); + if (ps == NULL) { + return NULL; + } } if (pReader->pSchema && sversion == pReader->pSchema->version) { return pReader->pSchema; } - if (pReader->pMemSchema == NULL) { - int32_t code = - metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->suid, uid, sversion, &pReader->pMemSchema); - if (code != TSDB_CODE_SUCCESS) { - terrno = code; - return NULL; - } else { - return pReader->pMemSchema; - } - } - - if (pReader->pMemSchema->version == sversion) { - return pReader->pMemSchema; + void** p = tSimpleHashGet(pReader->pSchemaMap, &sversion, sizeof(sversion)); + if (p != NULL) { + return *(STSchema**)p; } - taosMemoryFreeClear(pReader->pMemSchema); - int32_t code = metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->suid, uid, sversion, &pReader->pMemSchema); - if (code != TSDB_CODE_SUCCESS || pReader->pMemSchema == NULL) { + STSchema* ptr = NULL; + int32_t code = metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->suid, uid, sversion, &ptr); + if (code != TSDB_CODE_SUCCESS) { terrno = code; return NULL; } else { - return pReader->pMemSchema; + code = tSimpleHashPut(pReader->pSchemaMap, &sversion, sizeof(sversion), &ptr, POINTER_BYTES); + if (code != TSDB_CODE_SUCCESS) { + terrno = code; + return NULL; + } + return ptr; } } static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo, TSDBROW* pRow, SIterInfo* pIter, int64_t key, SLastBlockReader* pLastBlockReader) { - SRowMerger merge = {0}; - STSRow* pTSRow = NULL; + SRowMerger* pMerger = &pReader->status.merger; + SRow* pTSRow = NULL; SBlockData* pBlockData = &pReader->status.fileBlockData; SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo; @@ -1770,6 +2004,15 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* TSDBKEY k = TSDBROW_KEY(pRow); TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex); + // merge is not initialized yet, due to the fact that the pReader->pSchema is not initialized + if (pMerger->pArray == NULL) { + ASSERT(pReader->pSchema == NULL); + STSchema* ps = getTableSchemaImpl(pReader, pBlockScanInfo->uid); + if (ps == NULL) { + return terrno; + } + } + int64_t minKey = 0; if (pReader->order == TSDB_ORDER_ASC) { minKey = INT64_MAX; // chosen the minimum value @@ -1799,6 +2042,7 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* } } + // todo remove init bool init = false; // ASC: file block ---> last block -----> imem -----> mem @@ -1806,25 +2050,25 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* if (pReader->order == TSDB_ORDER_ASC) { if (minKey == key) { init = true; - int32_t code = tRowMergerInit(&merge, &fRow, pReader->pSchema); + int32_t code = tsdbRowMergerAdd(pMerger, &fRow, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } - doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge); + doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader); } if (minKey == tsLast) { - TSDBROW fRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); + TSDBROW* fRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); if (init) { - tRowMerge(&merge, &fRow1); + tsdbRowMergerAdd(pMerger, fRow1, NULL); } else { init = true; - int32_t code = tRowMergerInit(&merge, &fRow1, pReader->pSchema); + int32_t code = tsdbRowMergerAdd(pMerger, fRow1, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } } - doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLast, &merge, &pReader->verRange); + doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLast, pMerger, &pReader->verRange, pReader->idStr); } if (minKey == k.ts) { @@ -1833,15 +2077,15 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* return terrno; } if (init) { - tRowMergerAdd(&merge, pRow, pSchema); + tsdbRowMergerAdd(pMerger, pRow, pSchema); } else { init = true; - int32_t code = tRowMergerInit(&merge, pRow, pSchema); + int32_t code = tsdbRowMergerAdd(pMerger, pRow, pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } } - int32_t code = doMergeRowsInBuf(pIter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, &merge, pReader); + int32_t code = doMergeRowsInBuf(pIter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -1850,115 +2094,139 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* if (minKey == k.ts) { init = true; STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid); - int32_t code = tRowMergerInit(&merge, pRow, pSchema); + if (pSchema == NULL) { + return terrno; + } + + int32_t code = tsdbRowMergerAdd(pMerger, pRow, pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } - code = doMergeRowsInBuf(pIter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, &merge, pReader); - if (code != TSDB_CODE_SUCCESS || merge.pTSchema == NULL) { + code = doMergeRowsInBuf(pIter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, pReader); + if (code != TSDB_CODE_SUCCESS || pMerger->pTSchema == NULL) { return code; } } if (minKey == tsLast) { - TSDBROW fRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); + TSDBROW* fRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); if (init) { - tRowMerge(&merge, &fRow1); + tsdbRowMergerAdd(pMerger, fRow1, NULL); } else { init = true; - int32_t code = tRowMergerInit(&merge, &fRow1, pReader->pSchema); + int32_t code = tsdbRowMergerAdd(pMerger, fRow1, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } } - doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLast, &merge, &pReader->verRange); + doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLast, pMerger, &pReader->verRange, pReader->idStr); } if (minKey == key) { if (init) { - tRowMerge(&merge, &fRow); + tsdbRowMergerAdd(pMerger, &fRow, NULL); } else { init = true; - int32_t code = tRowMergerInit(&merge, &fRow, pReader->pSchema); + int32_t code = tsdbRowMergerAdd(pMerger, &fRow, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } } - doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge); + doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader); } } - int32_t code = tRowMergerGetRow(&merge, &pTSRow); + int32_t code = tsdbRowMergerGetRow(pMerger, &pTSRow); if (code != TSDB_CODE_SUCCESS) { return code; } - doAppendRowFromTSRow(pReader->pResBlock, pReader, pTSRow, pBlockScanInfo); + code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo); taosMemoryFree(pTSRow); - tRowMergerClear(&merge); - return TSDB_CODE_SUCCESS; + tsdbRowMergerClear(pMerger); + + return code; } static int32_t doMergeFileBlockAndLastBlock(SLastBlockReader* pLastBlockReader, STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo, SBlockData* pBlockData, bool mergeBlockData) { + SRowMerger* pMerger = &pReader->status.merger; SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo; - int64_t tsLastBlock = getCurrentKeyInLastBlock(pLastBlockReader); - STSRow* pTSRow = NULL; - SRowMerger merge = {0}; - TSDBROW fRow = tMergeTreeGetRow(&pLastBlockReader->mergeTree); - tsdbTrace("fRow ptr:%p, %d, uid:%" PRIu64 ", %s", fRow.pBlockData, fRow.iRow, pLastBlockReader->uid, pReader->idStr); + int64_t tsLastBlock = getCurrentKeyInLastBlock(pLastBlockReader); + bool copied = false; + int32_t code = TSDB_CODE_SUCCESS; + SRow* pTSRow = NULL; + TSDBROW* pRow = tMergeTreeGetRow(&pLastBlockReader->mergeTree); + + // create local variable to hold the row value + TSDBROW fRow = {.iRow = pRow->iRow, .type = TSDBROW_COL_FMT, .pBlockData = pRow->pBlockData}; + + tsdbTrace("fRow ptr:%p, %d, uid:%" PRIu64 ", %s", pRow->pBlockData, pRow->iRow, pLastBlockReader->uid, pReader->idStr); // only last block exists if ((!mergeBlockData) || (tsLastBlock != pBlockData->aTSKEY[pDumpInfo->rowIndex])) { - if (tryCopyDistinctRowFromSttBlock(&fRow, pLastBlockReader, pBlockScanInfo, tsLastBlock, pReader)) { + code = tryCopyDistinctRowFromSttBlock(&fRow, pLastBlockReader, pBlockScanInfo, tsLastBlock, pReader, &copied); + if (code) { + return code; + } + + if (copied) { pBlockScanInfo->lastKey = tsLastBlock; return TSDB_CODE_SUCCESS; } else { - int32_t code = tRowMergerInit(&merge, &fRow, pReader->pSchema); + code = tsdbRowMergerAdd(pMerger, &fRow, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } - TSDBROW fRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); - tRowMerge(&merge, &fRow1); - doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLastBlock, &merge, &pReader->verRange); + TSDBROW* pRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); + tsdbRowMergerAdd(pMerger, pRow1, NULL); + doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLastBlock, pMerger, &pReader->verRange, pReader->idStr); - code = tRowMergerGetRow(&merge, &pTSRow); + code = tsdbRowMergerGetRow(pMerger, &pTSRow); if (code != TSDB_CODE_SUCCESS) { return code; } - doAppendRowFromTSRow(pReader->pResBlock, pReader, pTSRow, pBlockScanInfo); + code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo); taosMemoryFree(pTSRow); - tRowMergerClear(&merge); + tsdbRowMergerClear(pMerger); + + if (code != TSDB_CODE_SUCCESS) { + return code; + } } } else { // not merge block data - int32_t code = tRowMergerInit(&merge, &fRow, pReader->pSchema); + code = tsdbRowMergerAdd(pMerger, &fRow, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } - doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLastBlock, &merge, &pReader->verRange); + doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLastBlock, pMerger, &pReader->verRange, pReader->idStr); // merge with block data if ts == key if (tsLastBlock == pBlockData->aTSKEY[pDumpInfo->rowIndex]) { - doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge); + doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader); } - code = tRowMergerGetRow(&merge, &pTSRow); + code = tsdbRowMergerGetRow(pMerger, &pTSRow); if (code != TSDB_CODE_SUCCESS) { return code; } - doAppendRowFromTSRow(pReader->pResBlock, pReader, pTSRow, pBlockScanInfo); + code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo); taosMemoryFree(pTSRow); - tRowMergerClear(&merge); + tsdbRowMergerClear(pMerger); + + if (code != TSDB_CODE_SUCCESS) { + return code; + } } return TSDB_CODE_SUCCESS; @@ -1967,6 +2235,16 @@ static int32_t doMergeFileBlockAndLastBlock(SLastBlockReader* pLastBlockReader, static int32_t mergeFileBlockAndLastBlock(STsdbReader* pReader, SLastBlockReader* pLastBlockReader, int64_t key, STableBlockScanInfo* pBlockScanInfo, SBlockData* pBlockData) { SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo; + SRowMerger* pMerger = &pReader->status.merger; + + // merge is not initialized yet, due to the fact that the pReader->pSchema is not initialized + if (pMerger->pArray == NULL) { + ASSERT(pReader->pSchema == NULL); + STSchema* ps = getTableSchemaImpl(pReader, pBlockScanInfo->uid); + if (ps == NULL) { + return terrno; + } + } if (hasDataInFileBlock(pBlockData, pDumpInfo)) { // no last block available, only data block exists @@ -1983,30 +2261,28 @@ static int32_t mergeFileBlockAndLastBlock(STsdbReader* pReader, SLastBlockReader if (key < ts) { // imem, mem are all empty, file blocks (data blocks and last block) exist return mergeRowsInFileBlocks(pBlockData, pBlockScanInfo, key, pReader); } else if (key == ts) { - STSRow* pTSRow = NULL; - SRowMerger merge = {0}; - - int32_t code = tRowMergerInit(&merge, &fRow, pReader->pSchema); + SRow* pTSRow = NULL; + int32_t code = tsdbRowMergerAdd(pMerger, &fRow, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } - doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge); + doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader); - TSDBROW fRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); - tRowMerge(&merge, &fRow1); + TSDBROW* pRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); + tsdbRowMergerAdd(pMerger, pRow1, NULL); - doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, ts, &merge, &pReader->verRange); + doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, ts, pMerger, &pReader->verRange, pReader->idStr); - code = tRowMergerGetRow(&merge, &pTSRow); + code = tsdbRowMergerGetRow(pMerger, &pTSRow); if (code != TSDB_CODE_SUCCESS) { return code; } - doAppendRowFromTSRow(pReader->pResBlock, pReader, pTSRow, pBlockScanInfo); + code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo); taosMemoryFree(pTSRow); - tRowMergerClear(&merge); + tsdbRowMergerClear(pMerger); return code; } else { return TSDB_CODE_SUCCESS; @@ -2021,8 +2297,8 @@ static int32_t mergeFileBlockAndLastBlock(STsdbReader* pReader, SLastBlockReader static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* pBlockScanInfo, SBlockData* pBlockData, SLastBlockReader* pLastBlockReader) { - SRowMerger merge = {0}; - STSRow* pTSRow = NULL; + SRowMerger* pMerger = &pReader->status.merger; + SRow* pTSRow = NULL; int32_t code = TSDB_CODE_SUCCESS; SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo; SArray* pDelList = pBlockScanInfo->delSkyline; @@ -2037,8 +2313,26 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* int64_t key = hasDataInFileBlock(pBlockData, pDumpInfo) ? pBlockData->aTSKEY[pDumpInfo->rowIndex] : INT64_MIN; - TSDBKEY k = TSDBROW_KEY(pRow); - TSDBKEY ik = TSDBROW_KEY(piRow); + TSDBKEY k = TSDBROW_KEY(pRow); + TSDBKEY ik = TSDBROW_KEY(piRow); + STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid); + if (pSchema == NULL) { + return code; + } + + STSchema* piSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(piRow), pReader, pBlockScanInfo->uid); + if (piSchema == NULL) { + return code; + } + + // merge is not initialized yet, due to the fact that the pReader->pSchema is not initialized + if (pMerger->pArray == NULL) { + ASSERT(pReader->pSchema == NULL); + STSchema* ps = getTableSchemaImpl(pReader, pBlockScanInfo->uid); + if (ps == NULL) { + return terrno; + } + } int64_t minKey = 0; if (ASCENDING_TRAVERSE(pReader->order)) { @@ -2085,47 +2379,41 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* if (minKey == key) { init = true; TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex); - code = tRowMergerInit(&merge, &fRow, pReader->pSchema); + code = tsdbRowMergerAdd(pMerger, &fRow, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } - doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge); + doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader); } if (minKey == tsLast) { - TSDBROW fRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); + TSDBROW* pRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); if (init) { - tRowMerge(&merge, &fRow1); + tsdbRowMergerAdd(pMerger, pRow1, NULL); } else { init = true; - code = tRowMergerInit(&merge, &fRow1, pReader->pSchema); + code = tsdbRowMergerAdd(pMerger, pRow1, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } } - doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLast, &merge, &pReader->verRange); + doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLast, pMerger, &pReader->verRange, pReader->idStr); } if (minKey == ik.ts) { if (init) { - tRowMerge(&merge, piRow); + tsdbRowMergerAdd(pMerger, piRow, piSchema); } else { init = true; - STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(piRow), pReader, pBlockScanInfo->uid); - if (pSchema == NULL) { + code = tsdbRowMergerAdd(pMerger, piRow, piSchema); + if (code != TSDB_CODE_SUCCESS) { return code; } + } - code = tRowMergerInit(&merge, piRow, pSchema); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - - code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, ik.ts, pBlockScanInfo->delSkyline, &merge, - pReader); + code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, ik.ts, pBlockScanInfo->delSkyline, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -2133,20 +2421,15 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* if (minKey == k.ts) { if (init) { - if (merge.pTSchema == NULL) { - return code; - } - - tRowMerge(&merge, pRow); + tsdbRowMergerAdd(pMerger, pRow, pSchema); } else { - STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid); - code = tRowMergerInit(&merge, pRow, pSchema); + // STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid); + code = tsdbRowMergerAdd(pMerger, pRow, pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } } - code = doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, &merge, - pReader); + code = doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -2154,14 +2437,12 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* } else { if (minKey == k.ts) { init = true; - STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid); - code = tRowMergerInit(&merge, pRow, pSchema); + code = tsdbRowMergerAdd(pMerger, pRow, pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } - code = doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, &merge, - pReader); + code = doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -2169,66 +2450,57 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* if (minKey == ik.ts) { if (init) { - tRowMerge(&merge, piRow); + tsdbRowMergerAdd(pMerger, piRow, piSchema); } else { init = true; - STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(piRow), pReader, pBlockScanInfo->uid); - code = tRowMergerInit(&merge, piRow, pSchema); + code = tsdbRowMergerAdd(pMerger, piRow, piSchema); if (code != TSDB_CODE_SUCCESS) { return code; } } - code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, ik.ts, pBlockScanInfo->delSkyline, &merge, - pReader); + code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, ik.ts, pBlockScanInfo->delSkyline, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } } if (minKey == tsLast) { - TSDBROW fRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); + TSDBROW* pRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); if (init) { - tRowMerge(&merge, &fRow1); + tsdbRowMergerAdd(pMerger, pRow1, NULL); } else { init = true; - code = tRowMergerInit(&merge, &fRow1, pReader->pSchema); + code = tsdbRowMergerAdd(pMerger, pRow1, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } } - doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLast, &merge, &pReader->verRange); + doMergeRowsInLastBlock(pLastBlockReader, pBlockScanInfo, tsLast, pMerger, &pReader->verRange, pReader->idStr); } if (minKey == key) { TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex); if (!init) { - code = tRowMergerInit(&merge, &fRow, pReader->pSchema); + code = tsdbRowMergerAdd(pMerger, &fRow, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } } else { - if (merge.pTSchema == NULL) { - return code; - } - tRowMerge(&merge, &fRow); + tsdbRowMergerAdd(pMerger, &fRow, NULL); } - doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge); + doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader); } } - if (merge.pTSchema == NULL) { - return code; - } - - code = tRowMergerGetRow(&merge, &pTSRow); + code = tsdbRowMergerGetRow(pMerger, &pTSRow); if (code != TSDB_CODE_SUCCESS) { return code; } - doAppendRowFromTSRow(pReader->pResBlock, pReader, pTSRow, pBlockScanInfo); + code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo); taosMemoryFree(pTSRow); - tRowMergerClear(&merge); + tsdbRowMergerClear(pMerger); return code; } @@ -2241,9 +2513,11 @@ static int32_t initMemDataIterator(STableBlockScanInfo* pBlockScanInfo, STsdbRea TSDBKEY startKey = {0}; if (ASCENDING_TRAVERSE(pReader->order)) { - startKey = (TSDBKEY){.ts = pReader->window.skey, .version = pReader->verRange.minVer}; + // startKey = (TSDBKEY){.ts = pReader->window.skey, .version = pReader->verRange.minVer}; + startKey = (TSDBKEY){.ts = pBlockScanInfo->lastKey + 1, .version = pReader->verRange.minVer}; } else { - startKey = (TSDBKEY){.ts = pReader->window.ekey, .version = pReader->verRange.maxVer}; + // startKey = (TSDBKEY){.ts = pReader->window.ekey, .version = pReader->verRange.maxVer}; + startKey = (TSDBKEY){.ts = pBlockScanInfo->lastKey - 1, .version = pReader->verRange.maxVer}; } int32_t backward = (!ASCENDING_TRAVERSE(pReader->order)); @@ -2320,8 +2594,7 @@ static bool isValidFileBlockRow(SBlockData* pBlockData, SFileBlockDumpInfo* pDum return false; } - TSDBKEY k = {.ts = ts, .version = ver}; - if (hasBeenDropped(pBlockScanInfo->delSkyline, &pBlockScanInfo->fileDelIndex, &k, pReader->order, + if (hasBeenDropped(pBlockScanInfo->delSkyline, &pBlockScanInfo->fileDelIndex, ts, ver, pReader->order, &pReader->verRange)) { return false; } @@ -2342,18 +2615,18 @@ static bool initLastBlockReader(SLastBlockReader* pLBlockReader, STableBlockScan initMemDataIterator(pScanInfo, pReader); pLBlockReader->uid = pScanInfo->uid; - int32_t step = ASCENDING_TRAVERSE(pLBlockReader->order) ? 1 : -1; STimeWindow w = pLBlockReader->window; if (ASCENDING_TRAVERSE(pLBlockReader->order)) { - w.skey = pScanInfo->lastKey + step; + w.skey = pScanInfo->lastKeyInStt; } else { - w.ekey = pScanInfo->lastKey + step; + w.ekey = pScanInfo->lastKeyInStt; } - tsdbDebug("init last block reader, window:%"PRId64"-%"PRId64", uid:%"PRIu64", %s", w.skey, w.ekey, pScanInfo->uid, pReader->idStr); + tsdbDebug("init last block reader, window:%" PRId64 "-%" PRId64 ", uid:%" PRIu64 ", %s", w.skey, w.ekey, + pScanInfo->uid, pReader->idStr); int32_t code = tMergeTreeOpen(&pLBlockReader->mergeTree, (pLBlockReader->order == TSDB_ORDER_DESC), pReader->pFileReader, pReader->suid, pScanInfo->uid, &w, &pLBlockReader->verRange, - pLBlockReader->pInfo, false, pReader->idStr); + pLBlockReader->pInfo, false, pReader->idStr, false, pReader->status.pLDataIter); if (code != TSDB_CODE_SUCCESS) { return false; } @@ -2361,11 +2634,6 @@ static bool initLastBlockReader(SLastBlockReader* pLBlockReader, STableBlockScan return nextRowFromLastBlocks(pLBlockReader, pScanInfo, &pReader->verRange); } -static int64_t getCurrentKeyInLastBlock(SLastBlockReader* pLastBlockReader) { - TSDBROW row = tMergeTreeGetRow(&pLastBlockReader->mergeTree); - return TSDBROW_TS(&row); -} - static bool hasDataInLastBlock(SLastBlockReader* pLastBlockReader) { return pLastBlockReader->mergeTree.pIter != NULL; } bool hasDataInFileBlock(const SBlockData* pBlockData, const SFileBlockDumpInfo* pDumpInfo) { @@ -2377,32 +2645,46 @@ bool hasDataInFileBlock(const SBlockData* pBlockData, const SFileBlockDumpInfo* int32_t mergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pBlockScanInfo, int64_t key, STsdbReader* pReader) { + SRowMerger* pMerger = &pReader->status.merger; SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo; - if (tryCopyDistinctRowFromFileBlock(pReader, pBlockData, key, pDumpInfo)) { + bool copied = false; + int32_t code = tryCopyDistinctRowFromFileBlock(pReader, pBlockData, key, pDumpInfo, &copied); + if (code) { + return code; + } + + // merge is not initialized yet, due to the fact that the pReader->pSchema is not initialized + if (pMerger->pArray == NULL) { + ASSERT(pReader->pSchema == NULL); + STSchema* ps = getTableSchemaImpl(pReader, pBlockScanInfo->uid); + if (ps == NULL) { + return terrno; + } + } + + if (copied) { pBlockScanInfo->lastKey = key; return TSDB_CODE_SUCCESS; } else { TSDBROW fRow = tsdbRowFromBlockData(pBlockData, pDumpInfo->rowIndex); - STSRow* pTSRow = NULL; - SRowMerger merge = {0}; - - int32_t code = tRowMergerInit(&merge, &fRow, pReader->pSchema); + SRow* pTSRow = NULL; + code = tsdbRowMergerAdd(pMerger, &fRow, pReader->pSchema); if (code != TSDB_CODE_SUCCESS) { return code; } - doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader, &merge); - code = tRowMergerGetRow(&merge, &pTSRow); + doMergeRowsInFileBlocks(pBlockData, pBlockScanInfo, pReader); + code = tsdbRowMergerGetRow(pMerger, &pTSRow); if (code != TSDB_CODE_SUCCESS) { return code; } - doAppendRowFromTSRow(pReader->pResBlock, pReader, pTSRow, pBlockScanInfo); + code = doAppendRowFromTSRow(pReader->resBlockInfo.pResBlock, pReader, pTSRow, pBlockScanInfo); taosMemoryFree(pTSRow); - tRowMergerClear(&merge); - return TSDB_CODE_SUCCESS; + tsdbRowMergerClear(pMerger); + return code; } } @@ -2480,7 +2762,7 @@ static int32_t loadNeighborIfOverlap(SFileDataBlockInfo* pBlockInfo, STableBlock } static void updateComposedBlockInfo(STsdbReader* pReader, double el, STableBlockScanInfo* pBlockScanInfo) { - SSDataBlock* pResBlock = pReader->pResBlock; + SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock; pResBlock->info.id.uid = (pBlockScanInfo != NULL) ? pBlockScanInfo->uid : 0; pResBlock->info.dataLoad = 1; @@ -2495,7 +2777,7 @@ static void updateComposedBlockInfo(STsdbReader* pReader, double el, STableBlock static int32_t buildComposedDataBlock(STsdbReader* pReader) { int32_t code = TSDB_CODE_SUCCESS; - SSDataBlock* pResBlock = pReader->pResBlock; + SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock; SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(&pReader->status.blockIter); SLastBlockReader* pLastBlockReader = pReader->status.fileIter.pLastBlockReader; @@ -2504,27 +2786,31 @@ static int32_t buildComposedDataBlock(STsdbReader* pReader) { int64_t st = taosGetTimestampUs(); int32_t step = asc ? 1 : -1; double el = 0; + SDataBlk* pBlock = getCurrentBlock(&pReader->status.blockIter); + SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo; STableBlockScanInfo* pBlockScanInfo = NULL; if (pBlockInfo != NULL) { - void* p = taosHashGet(pReader->status.pTableMap, &pBlockInfo->uid, sizeof(pBlockInfo->uid)); - if (p == NULL) { - code = TSDB_CODE_INVALID_PARA; - tsdbError("failed to locate the uid:%" PRIu64 " in query table uid list, total tables:%d, %s", pBlockInfo->uid, - taosHashGetSize(pReader->status.pTableMap), pReader->idStr); + if (pReader->pIgnoreTables && taosHashGet(*pReader->pIgnoreTables, &pBlockInfo->uid, sizeof(pBlockInfo->uid))) { + setBlockAllDumped(pDumpInfo, pBlock->maxKey.ts, pReader->order); + return code; + } + + pBlockScanInfo = getTableBlockScanInfo(pReader->status.pTableMap, pBlockInfo->uid, pReader->idStr); + if (pBlockScanInfo == NULL) { goto _end; } - pBlockScanInfo = *(STableBlockScanInfo**)p; - - SDataBlk* pBlock = getCurrentBlock(&pReader->status.blockIter); TSDBKEY keyInBuf = getCurrentKeyInBuf(pBlockScanInfo, pReader); // it is a clean block, load it directly if (isCleanFileDataBlock(pReader, pBlockInfo, pBlock, pBlockScanInfo, keyInBuf, pLastBlockReader) && - pBlock->nRow <= pReader->capacity) { + pBlock->nRow <= pReader->resBlockInfo.capacity) { if (asc || ((!asc) && (!hasDataInLastBlock(pLastBlockReader)))) { - copyBlockDataToSDataBlock(pReader); + code = copyBlockDataToSDataBlock(pReader); + if (code) { + goto _end; + } // record the last key value pBlockScanInfo->lastKey = asc ? pBlock->maxKey.ts : pBlock->minKey.ts; @@ -2533,15 +2819,19 @@ static int32_t buildComposedDataBlock(STsdbReader* pReader) { } } else { // file blocks not exist pBlockScanInfo = *pReader->status.pTableIter; + if (pReader->pIgnoreTables && taosHashGet(*pReader->pIgnoreTables, &pBlockScanInfo->uid, sizeof(pBlockScanInfo->uid))) { + setBlockAllDumped(pDumpInfo, pBlock->maxKey.ts, pReader->order); + return code; + } } - SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo; SBlockData* pBlockData = &pReader->status.fileBlockData; while (1) { bool hasBlockData = false; { - while (pBlockData->nRow > 0) { // find the first qualified row in data block + while (pBlockData->nRow > 0 && + pBlockData->uid == pBlockScanInfo->uid) { // find the first qualified row in data block if (isValidFileBlockRow(pBlockData, pDumpInfo, pBlockScanInfo, pReader)) { hasBlockData = true; break; @@ -2570,7 +2860,10 @@ static int32_t buildComposedDataBlock(STsdbReader* pReader) { break; } - buildComposedDataBlockImpl(pReader, pBlockScanInfo, pBlockData, pLastBlockReader); + code = buildComposedDataBlockImpl(pReader, pBlockScanInfo, pBlockData, pLastBlockReader); + if (code) { + goto _end; + } // currently loaded file data block is consumed if ((pBlockData->nRow > 0) && (pDumpInfo->rowIndex >= pBlockData->nRow || pDumpInfo->rowIndex < 0)) { @@ -2579,7 +2872,7 @@ static int32_t buildComposedDataBlock(STsdbReader* pReader) { break; } - if (pResBlock->info.rows >= pReader->capacity) { + if (pResBlock->info.rows >= pReader->resBlockInfo.capacity) { break; } } @@ -2589,8 +2882,8 @@ _end: updateComposedBlockInfo(pReader, el, pBlockScanInfo); if (pResBlock->info.rows > 0) { - tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 - " rows:%d, elapsed time:%.2f ms %s", + tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 " rows:%" PRId64 + ", elapsed time:%.2f ms %s", pReader, pResBlock->info.id.uid, pResBlock->info.window.skey, pResBlock->info.window.ekey, pResBlock->info.rows, el, pReader->idStr); } @@ -2669,11 +2962,11 @@ _err: TSDBKEY getCurrentKeyInBuf(STableBlockScanInfo* pScanInfo, STsdbReader* pReader) { bool asc = ASCENDING_TRAVERSE(pReader->order); -// TSKEY initialVal = asc? TSKEY_MIN:TSKEY_MAX; + // TSKEY initialVal = asc? TSKEY_MIN:TSKEY_MAX; - TSDBKEY key = {.ts = TSKEY_INITIAL_VAL}, ikey = {.ts = TSKEY_INITIAL_VAL}; + TSDBKEY key = {.ts = TSKEY_INITIAL_VAL}, ikey = {.ts = TSKEY_INITIAL_VAL}; - bool hasKey = false, hasIKey = false; + bool hasKey = false, hasIKey = false; TSDBROW* pRow = getValidMemRow(&pScanInfo->iter, pScanInfo->delSkyline, pReader); if (pRow != NULL) { hasKey = true; @@ -2687,11 +2980,11 @@ TSDBKEY getCurrentKeyInBuf(STableBlockScanInfo* pScanInfo, STsdbReader* pReader) } if (hasKey) { - if (hasIKey) { // has data in mem & imem + if (hasIKey) { // has data in mem & imem if (asc) { return key.ts <= ikey.ts ? key : ikey; - } else { - return key.ts <= ikey.ts ? ikey: key; + } else { + return key.ts <= ikey.ts ? ikey : key; } } else { // no data in imem return key; @@ -2703,29 +2996,41 @@ TSDBKEY getCurrentKeyInBuf(STableBlockScanInfo* pScanInfo, STsdbReader* pReader) } } -static int32_t moveToNextFile(STsdbReader* pReader, SBlockNumber* pBlockNum) { +static int32_t moveToNextFile(STsdbReader* pReader, SBlockNumber* pBlockNum, SArray* pTableList) { SReaderStatus* pStatus = &pReader->status; pBlockNum->numOfBlocks = 0; pBlockNum->numOfLastFiles = 0; - size_t numOfTables = taosHashGetSize(pReader->status.pTableMap); + size_t numOfTables = tSimpleHashGetSize(pReader->status.pTableMap); SArray* pIndexList = taosArrayInit(numOfTables, sizeof(SBlockIdx)); while (1) { - bool hasNext = filesetIteratorNext(&pStatus->fileIter, pReader); + // only check here, since the iterate data in memory is very fast. + if (pReader->code != TSDB_CODE_SUCCESS) { + tsdbWarn("tsdb reader is stopped ASAP, code:%s, %s", strerror(pReader->code), pReader->idStr); + return pReader->code; + } + + bool hasNext = false; + int32_t code = filesetIteratorNext(&pStatus->fileIter, pReader, &hasNext); + if (code != TSDB_CODE_SUCCESS) { + taosArrayDestroy(pIndexList); + return code; + } + if (!hasNext) { // no data files on disk break; } taosArrayClear(pIndexList); - int32_t code = doLoadBlockIndex(pReader, pReader->pFileReader, pIndexList); + code = doLoadBlockIndex(pReader, pReader->pFileReader, pIndexList); if (code != TSDB_CODE_SUCCESS) { taosArrayDestroy(pIndexList); return code; } if (taosArrayGetSize(pIndexList) > 0 || pReader->pFileReader->pSet->nSttF > 0) { - code = doLoadFileBlock(pReader, pIndexList, pBlockNum); + code = doLoadFileBlock(pReader, pIndexList, pBlockNum, pTableList); if (code != TSDB_CODE_SUCCESS) { taosArrayDestroy(pIndexList); return code; @@ -2766,23 +3071,23 @@ static int32_t moveToNextFile(STsdbReader* pReader, SBlockNumber* pBlockNum) { return TSDB_CODE_SUCCESS; } -static void resetTableListIndex(SReaderStatus *pStatus) { +static void resetTableListIndex(SReaderStatus* pStatus) { STableUidList* pList = &pStatus->uidList; pList->currentIndex = 0; uint64_t uid = pList->tableUidList[0]; - pStatus->pTableIter = taosHashGet(pStatus->pTableMap, &uid, sizeof(uid)); + pStatus->pTableIter = tSimpleHashGet(pStatus->pTableMap, &uid, sizeof(uid)); } static bool moveToNextTable(STableUidList* pOrderedCheckInfo, SReaderStatus* pStatus) { pOrderedCheckInfo->currentIndex += 1; - if (pOrderedCheckInfo->currentIndex >= taosHashGetSize(pStatus->pTableMap)) { + if (pOrderedCheckInfo->currentIndex >= tSimpleHashGetSize(pStatus->pTableMap)) { pStatus->pTableIter = NULL; return false; } uint64_t uid = pOrderedCheckInfo->tableUidList[pOrderedCheckInfo->currentIndex]; - pStatus->pTableIter = taosHashGet(pStatus->pTableMap, &uid, sizeof(uid)); + pStatus->pTableIter = tSimpleHashGet(pStatus->pTableMap, &uid, sizeof(uid)); return (pStatus->pTableIter != NULL); } @@ -2790,19 +3095,37 @@ static int32_t doLoadLastBlockSequentially(STsdbReader* pReader) { SReaderStatus* pStatus = &pReader->status; SLastBlockReader* pLastBlockReader = pStatus->fileIter.pLastBlockReader; STableUidList* pUidList = &pStatus->uidList; + int32_t code = TSDB_CODE_SUCCESS; - if (taosHashGetSize(pStatus->pTableMap) == 0) { + if (tSimpleHashGetSize(pStatus->pTableMap) == 0) { return TSDB_CODE_SUCCESS; } - SSDataBlock* pResBlock = pReader->pResBlock; + SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock; while (1) { + if (pReader->code != TSDB_CODE_SUCCESS) { + tsdbWarn("tsdb reader is stopped ASAP, code:%s, %s", strerror(pReader->code), pReader->idStr); + return pReader->code; + } + // load the last data block of current table STableBlockScanInfo* pScanInfo = *(STableBlockScanInfo**)pStatus->pTableIter; + if (pReader->pIgnoreTables && taosHashGet(*pReader->pIgnoreTables, &pScanInfo->uid, sizeof(pScanInfo->uid))) { + bool hasNexTable = moveToNextTable(pUidList, pStatus); + if (!hasNexTable) { + return TSDB_CODE_SUCCESS; + } + + continue; + } + + // reset the index in last block when handing a new file + doCleanupTableScanInfo(pScanInfo); + pStatus->mapDataCleaned = true; - bool hasVal = initLastBlockReader(pLastBlockReader, pScanInfo, pReader); - if (!hasVal) { + bool hasDataInLastFile = initLastBlockReader(pLastBlockReader, pScanInfo, pReader); + if (!hasDataInLastFile) { bool hasNexTable = moveToNextTable(pUidList, pStatus); if (!hasNexTable) { return TSDB_CODE_SUCCESS; @@ -2820,8 +3143,12 @@ static int32_t doLoadLastBlockSequentially(STsdbReader* pReader) { break; } - buildComposedDataBlockImpl(pReader, pScanInfo, &pReader->status.fileBlockData, pLastBlockReader); - if (pResBlock->info.rows >= pReader->capacity) { + code = buildComposedDataBlockImpl(pReader, pScanInfo, &pReader->status.fileBlockData, pLastBlockReader); + if (code) { + return code; + } + + if (pResBlock->info.rows >= pReader->resBlockInfo.capacity) { break; } } @@ -2830,8 +3157,8 @@ static int32_t doLoadLastBlockSequentially(STsdbReader* pReader) { updateComposedBlockInfo(pReader, el, pScanInfo); if (pResBlock->info.rows > 0) { - tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 - " rows:%d, elapsed time:%.2f ms %s", + tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 " rows:%" PRId64 + ", elapsed time:%.2f ms %s", pReader, pResBlock->info.id.uid, pResBlock->info.window.skey, pResBlock->info.window.ekey, pResBlock->info.rows, el, pReader->idStr); return TSDB_CODE_SUCCESS; @@ -2847,24 +3174,24 @@ static int32_t doLoadLastBlockSequentially(STsdbReader* pReader) { static int32_t doBuildDataBlock(STsdbReader* pReader) { int32_t code = TSDB_CODE_SUCCESS; - SDataBlk* pBlock = NULL; SReaderStatus* pStatus = &pReader->status; SDataBlockIter* pBlockIter = &pStatus->blockIter; STableBlockScanInfo* pScanInfo = NULL; SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(pBlockIter); SLastBlockReader* pLastBlockReader = pReader->status.fileIter.pLastBlockReader; + SDataBlk* pBlock = getCurrentBlock(pBlockIter); - ASSERT(pBlockInfo != NULL); + if (pReader->pIgnoreTables && taosHashGet(*pReader->pIgnoreTables, &pBlockInfo->uid, sizeof(pBlockInfo->uid))) { + setBlockAllDumped(&pStatus->fBlockDumpInfo, pBlock->maxKey.ts, pReader->order); + return code; + } - pScanInfo = *(STableBlockScanInfo**)taosHashGet(pReader->status.pTableMap, &pBlockInfo->uid, sizeof(pBlockInfo->uid)); + pScanInfo = getTableBlockScanInfo(pReader->status.pTableMap, pBlockInfo->uid, pReader->idStr); if (pScanInfo == NULL) { - tsdbError("failed to get table scan-info, %s", pReader->idStr); - code = TSDB_CODE_INVALID_PARA; - return code; + return terrno; } - pBlock = getCurrentBlock(pBlockIter); initLastBlockReader(pLastBlockReader, pScanInfo, pReader); TSDBKEY keyInBuf = getCurrentKeyInBuf(pScanInfo, pReader); @@ -2891,7 +3218,7 @@ static int32_t doBuildDataBlock(STsdbReader* pReader) { SBlockData* pBData = &pReader->status.fileBlockData; tBlockDataReset(pBData); - SSDataBlock* pResBlock = pReader->pResBlock; + SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock; tsdbDebug("load data in last block firstly, due to desc scan data, %s", pReader->idStr); int64_t st = taosGetTimestampUs(); @@ -2904,8 +3231,12 @@ static int32_t doBuildDataBlock(STsdbReader* pReader) { break; } - buildComposedDataBlockImpl(pReader, pScanInfo, &pReader->status.fileBlockData, pLastBlockReader); - if (pResBlock->info.rows >= pReader->capacity) { + code = buildComposedDataBlockImpl(pReader, pScanInfo, &pReader->status.fileBlockData, pLastBlockReader); + if (code) { + return code; + } + + if (pResBlock->info.rows >= pReader->resBlockInfo.capacity) { break; } } @@ -2914,13 +3245,13 @@ static int32_t doBuildDataBlock(STsdbReader* pReader) { updateComposedBlockInfo(pReader, el, pScanInfo); if (pResBlock->info.rows > 0) { - tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 - " rows:%d, elapsed time:%.2f ms %s", + tsdbDebug("%p uid:%" PRIu64 ", composed data block created, brange:%" PRIu64 "-%" PRIu64 " rows:%" PRId64 + ", elapsed time:%.2f ms %s", pReader, pResBlock->info.id.uid, pResBlock->info.window.skey, pResBlock->info.window.ekey, pResBlock->info.rows, el, pReader->idStr); } } else { // whole block is required, return it directly - SDataBlockInfo* pInfo = &pReader->pResBlock->info; + SDataBlockInfo* pInfo = &pReader->resBlockInfo.pResBlock->info; pInfo->rows = pBlock->nRow; pInfo->id.uid = pScanInfo->uid; pInfo->dataLoad = 0; @@ -2930,13 +3261,155 @@ static int32_t doBuildDataBlock(STsdbReader* pReader) { // update the last key for the corresponding table pScanInfo->lastKey = ASCENDING_TRAVERSE(pReader->order) ? pInfo->window.ekey : pInfo->window.skey; - tsdbDebug("%p uid:%" PRIu64 " clean file block retrieved from file, global index:%d, " + tsdbDebug("%p uid:%" PRIu64 + " clean file block retrieved from file, global index:%d, " "table index:%d, rows:%d, brange:%" PRId64 "-%" PRId64 ", %s", pReader, pScanInfo->uid, pBlockIter->index, pBlockInfo->tbBlockIdx, pBlock->nRow, pBlock->minKey.ts, pBlock->maxKey.ts, pReader->idStr); } } + return (pReader->code != TSDB_CODE_SUCCESS)? pReader->code:code; +} + +static int32_t doSumFileBlockRows(STsdbReader* pReader, SDataFReader* pFileReader) { + int64_t st = taosGetTimestampUs(); + LRUHandle* handle = NULL; + int32_t code = tsdbCacheGetBlockIdx(pFileReader->pTsdb->biCache, pFileReader, &handle); + if (code != TSDB_CODE_SUCCESS || handle == NULL) { + goto _end; + } + + int32_t numOfTables = tSimpleHashGetSize(pReader->status.pTableMap); + + SArray* aBlockIdx = (SArray*)taosLRUCacheValue(pFileReader->pTsdb->biCache, handle); + size_t num = taosArrayGetSize(aBlockIdx); + if (num == 0) { + tsdbBICacheRelease(pFileReader->pTsdb->biCache, handle); + return TSDB_CODE_SUCCESS; + } + + SBlockIdx* pBlockIdx = NULL; + for (int32_t i = 0; i < num; ++i) { + pBlockIdx = (SBlockIdx*)taosArrayGet(aBlockIdx, i); + if (pBlockIdx->suid != pReader->suid) { + continue; + } + + STableBlockScanInfo** p = tSimpleHashGet(pReader->status.pTableMap, &pBlockIdx->uid, sizeof(pBlockIdx->uid)); + if (p == NULL) { + continue; + } + + STableBlockScanInfo* pScanInfo = *p; + tMapDataReset(&pScanInfo->mapData); + tsdbReadDataBlk(pReader->pFileReader, pBlockIdx, &pScanInfo->mapData); + + SDataBlk block = {0}; + for (int32_t j = 0; j < pScanInfo->mapData.nItem; ++j) { + tGetDataBlk(pScanInfo->mapData.pData + pScanInfo->mapData.aOffset[j], &block); + pReader->rowsNum += block.nRow; + } + } + +_end: + tsdbBICacheRelease(pFileReader->pTsdb->biCache, handle); + return code; +} + +static int32_t doSumSttBlockRows(STsdbReader* pReader) { + int32_t code = TSDB_CODE_SUCCESS; + SLastBlockReader* pLastBlockReader = pReader->status.fileIter.pLastBlockReader; + SSttBlockLoadInfo* pBlockLoadInfo = NULL; + + for (int32_t i = 0; i < pReader->pFileReader->pSet->nSttF; ++i) { // open all last file + pBlockLoadInfo = &pLastBlockReader->pInfo[i]; + + code = tsdbReadSttBlk(pReader->pFileReader, i, pBlockLoadInfo->aSttBlk); + if (code) { + return code; + } + + size_t size = taosArrayGetSize(pBlockLoadInfo->aSttBlk); + if (size >= 1) { + SSttBlk* pStart = taosArrayGet(pBlockLoadInfo->aSttBlk, 0); + SSttBlk* pEnd = taosArrayGet(pBlockLoadInfo->aSttBlk, size - 1); + + // all identical + if (pStart->suid == pEnd->suid) { + if (pStart->suid != pReader->suid) { + // no qualified stt block existed + taosArrayClear(pBlockLoadInfo->aSttBlk); + continue; + } + for (int32_t j = 0; j < size; ++j) { + SSttBlk* p = taosArrayGet(pBlockLoadInfo->aSttBlk, j); + pReader->rowsNum += p->nRow; + } + } else { + for (int32_t j = 0; j < size; ++j) { + SSttBlk* p = taosArrayGet(pBlockLoadInfo->aSttBlk, j); + uint64_t s = p->suid; + if (s < pReader->suid) { + continue; + } + + if (s == pReader->suid) { + pReader->rowsNum += p->nRow; + } else if (s > pReader->suid) { + break; + } + } + } + } + } + + return code; +} + +static int32_t readRowsCountFromFiles(STsdbReader* pReader) { + int32_t code = TSDB_CODE_SUCCESS; + + while (1) { + bool hasNext = false; + code = filesetIteratorNext(&pReader->status.fileIter, pReader, &hasNext); + if (code) { + return code; + } + + if (!hasNext) { // no data files on disk + break; + } + + code = doSumFileBlockRows(pReader, pReader->pFileReader); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + code = doSumSttBlockRows(pReader); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + + pReader->status.loadFromFile = false; + + return code; +} + +static int32_t readRowsCountFromMem(STsdbReader* pReader) { + int32_t code = TSDB_CODE_SUCCESS; + int64_t memNum = 0, imemNum = 0; + if (pReader->pReadSnap->pMem != NULL) { + tsdbMemTableCountRows(pReader->pReadSnap->pMem, pReader->status.pTableMap, &memNum); + } + + if (pReader->pReadSnap->pIMem != NULL) { + tsdbMemTableCountRows(pReader->pReadSnap->pIMem, pReader->status.pTableMap, &imemNum); + } + + pReader->rowsNum += memNum + imemNum; + return code; } @@ -2945,14 +3418,19 @@ static int32_t buildBlockFromBufferSequentially(STsdbReader* pReader) { STableUidList* pUidList = &pStatus->uidList; while (1) { -// if (pStatus->pTableIter == NULL) { -// pStatus->pTableIter = taosHashIterate(pStatus->pTableMap, NULL); -// if (pStatus->pTableIter == NULL) { -// return TSDB_CODE_SUCCESS; -// } -// } + if (pReader->code != TSDB_CODE_SUCCESS) { + tsdbWarn("tsdb reader is stopped ASAP, code:%s, %s", strerror(pReader->code), pReader->idStr); + return pReader->code; + } STableBlockScanInfo** pBlockScanInfo = pStatus->pTableIter; + if (pReader->pIgnoreTables && taosHashGet(*pReader->pIgnoreTables, &(*pBlockScanInfo)->uid, sizeof((*pBlockScanInfo)->uid))) { + bool hasNexTable = moveToNextTable(pUidList, pStatus); + if (!hasNexTable) { + return TSDB_CODE_SUCCESS; + } + } + initMemDataIterator(*pBlockScanInfo, pReader); int64_t endKey = (ASCENDING_TRAVERSE(pReader->order)) ? INT64_MAX : INT64_MIN; @@ -2961,7 +3439,7 @@ static int32_t buildBlockFromBufferSequentially(STsdbReader* pReader) { return code; } - if (pReader->pResBlock->info.rows > 0) { + if (pReader->resBlockInfo.pResBlock->info.rows > 0) { return TSDB_CODE_SUCCESS; } @@ -2974,9 +3452,16 @@ static int32_t buildBlockFromBufferSequentially(STsdbReader* pReader) { } // set the correct start position in case of the first/last file block, according to the query time window -void initBlockDumpInfo(STsdbReader* pReader, SDataBlockIter* pBlockIter) { - SDataBlk* pBlock = getCurrentBlock(pBlockIter); - +static void initBlockDumpInfo(STsdbReader* pReader, SDataBlockIter* pBlockIter) { + int64_t lastKey = ASCENDING_TRAVERSE(pReader->order) ? INT64_MIN : INT64_MAX; + SDataBlk* pBlock = getCurrentBlock(pBlockIter); + SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(pBlockIter); + if (pBlockInfo) { + STableBlockScanInfo* pScanInfo = tSimpleHashGet(pBlockIter->pTableMap, &pBlockInfo->uid, sizeof(pBlockInfo->uid)); + if (pScanInfo) { + lastKey = pScanInfo->lastKey; + } + } SReaderStatus* pStatus = &pReader->status; SFileBlockDumpInfo* pDumpInfo = &pStatus->fBlockDumpInfo; @@ -2984,24 +3469,29 @@ void initBlockDumpInfo(STsdbReader* pReader, SDataBlockIter* pBlockIter) { pDumpInfo->totalRows = pBlock->nRow; pDumpInfo->allDumped = false; pDumpInfo->rowIndex = ASCENDING_TRAVERSE(pReader->order) ? 0 : pBlock->nRow - 1; + pDumpInfo->lastKey = lastKey; } static int32_t initForFirstBlockInFile(STsdbReader* pReader, SDataBlockIter* pBlockIter) { SBlockNumber num = {0}; - int32_t code = moveToNextFile(pReader, &num); + SArray* pTableList = taosArrayInit(40, POINTER_BYTES); + + int32_t code = moveToNextFile(pReader, &num, pTableList); if (code != TSDB_CODE_SUCCESS) { + taosArrayDestroy(pTableList); return code; } // all data files are consumed, try data in buffer if (num.numOfBlocks + num.numOfLastFiles == 0) { pReader->status.loadFromFile = false; + taosArrayDestroy(pTableList); return code; } // initialize the block iterator for a new fileset if (num.numOfBlocks > 0) { - code = initBlockIterator(pReader, pBlockIter, num.numOfBlocks); + code = initBlockIterator(pReader, pBlockIter, num.numOfBlocks, pTableList); } else { // no block data, only last block exists tBlockDataReset(&pReader->status.fileBlockData); resetDataBlockIterator(pBlockIter, pReader->order); @@ -3010,6 +3500,7 @@ static int32_t initForFirstBlockInFile(STsdbReader* pReader, SDataBlockIter* pBl // set the correct start position according to the query time window initBlockDumpInfo(pReader, pBlockIter); + taosArrayDestroy(pTableList); return code; } @@ -3018,46 +3509,64 @@ static bool fileBlockPartiallyRead(SFileBlockDumpInfo* pDumpInfo, bool asc) { ((pDumpInfo->rowIndex > 0 && asc) || (pDumpInfo->rowIndex < (pDumpInfo->totalRows - 1) && (!asc))); } -static int32_t buildBlockFromFiles(STsdbReader* pReader) { - int32_t code = TSDB_CODE_SUCCESS; - bool asc = ASCENDING_TRAVERSE(pReader->order); +typedef enum { + TSDB_READ_RETURN = 0x1, + TSDB_READ_CONTINUE = 0x2, +} ERetrieveType; +static ERetrieveType doReadDataFromLastFiles(STsdbReader* pReader) { + int32_t code = TSDB_CODE_SUCCESS; + SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock; SDataBlockIter* pBlockIter = &pReader->status.blockIter; - if (pBlockIter->numOfBlocks == 0) { - _begin: + while(1) { + terrno = 0; + code = doLoadLastBlockSequentially(pReader); if (code != TSDB_CODE_SUCCESS) { - return code; + terrno = code; + return TSDB_READ_RETURN; } - if (pReader->pResBlock->info.rows > 0) { - return TSDB_CODE_SUCCESS; + if (pResBlock->info.rows > 0) { + return TSDB_READ_RETURN; } // all data blocks are checked in this last block file, now let's try the next file - if (pReader->status.pTableIter == NULL) { - code = initForFirstBlockInFile(pReader, pBlockIter); + ASSERT(pReader->status.pTableIter == NULL); + code = initForFirstBlockInFile(pReader, pBlockIter); - // error happens or all the data files are completely checked - if ((code != TSDB_CODE_SUCCESS) || (pReader->status.loadFromFile == false)) { - return code; - } + // error happens or all the data files are completely checked + if ((code != TSDB_CODE_SUCCESS) || (pReader->status.loadFromFile == false)) { + terrno = code; + return TSDB_READ_RETURN; + } - // this file does not have data files, let's start check the last block file if exists - if (pBlockIter->numOfBlocks == 0) { - resetTableListIndex(&pReader->status); - goto _begin; - } + if (pBlockIter->numOfBlocks > 0) { // there are data blocks existed. + return TSDB_READ_CONTINUE; + } else { // all blocks in data file are checked, let's check the data in last files + resetTableListIndex(&pReader->status); } + } +} - code = doBuildDataBlock(pReader); - if (code != TSDB_CODE_SUCCESS) { - return code; +static int32_t buildBlockFromFiles(STsdbReader* pReader) { + int32_t code = TSDB_CODE_SUCCESS; + bool asc = ASCENDING_TRAVERSE(pReader->order); + + SDataBlockIter* pBlockIter = &pReader->status.blockIter; + SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock; + + if (pBlockIter->numOfBlocks == 0) { + // let's try to extract data from stt files. + ERetrieveType type = doReadDataFromLastFiles(pReader); + if (type == TSDB_READ_RETURN) { + return terrno; } - if (pReader->pResBlock->info.rows > 0) { - return TSDB_CODE_SUCCESS; + code = doBuildDataBlock(pReader); + if (code != TSDB_CODE_SUCCESS || pResBlock->info.rows > 0) { + return code; } } @@ -3074,25 +3583,22 @@ static int32_t buildBlockFromFiles(STsdbReader* pReader) { if (hasNext) { // check for the next block in the block accessed order list initBlockDumpInfo(pReader, pBlockIter); } else { - if (pReader->status.pCurrentFileset->nSttF > 0) { - // data blocks in current file are exhausted, let's try the next file now - tBlockDataReset(&pReader->status.fileBlockData); - resetDataBlockIterator(pBlockIter, pReader->order); - resetTableListIndex(&pReader->status); - goto _begin; - } else { - code = initForFirstBlockInFile(pReader, pBlockIter); - - // error happens or all the data files are completely checked - if ((code != TSDB_CODE_SUCCESS) || (pReader->status.loadFromFile == false)) { - return code; - } + // all data blocks in files are checked, let's check the data in last files. + ASSERT(pReader->status.pCurrentFileset->nSttF > 0); - // this file does not have blocks, let's start check the last block file - if (pBlockIter->numOfBlocks == 0) { - resetTableListIndex(&pReader->status); - goto _begin; - } + // data blocks in current file are exhausted, let's try the next file now + SBlockData* pBlockData = &pReader->status.fileBlockData; + if (pBlockData->uid != 0) { + tBlockDataClear(pBlockData); + } + + tBlockDataReset(pBlockData); + resetDataBlockIterator(pBlockIter, pReader->order); + resetTableListIndex(&pReader->status); + + ERetrieveType type = doReadDataFromLastFiles(pReader); + if (type == TSDB_READ_RETURN) { + return terrno; } } } @@ -3100,13 +3606,9 @@ static int32_t buildBlockFromFiles(STsdbReader* pReader) { code = doBuildDataBlock(pReader); } - if (code != TSDB_CODE_SUCCESS) { + if (code != TSDB_CODE_SUCCESS || pResBlock->info.rows > 0) { return code; } - - if (pReader->pResBlock->info.rows > 0) { - return TSDB_CODE_SUCCESS; - } } } @@ -3158,8 +3660,8 @@ SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, int8_ int64_t startVer = (pCond->startVersion == -1) ? 0 : pCond->startVersion; int64_t endVer = 0; - if (pCond->endVersion == - -1) { // user not specified end version, set current maximum version of vnode as the endVersion + if (pCond->endVersion == -1) { + // user not specified end version, set current maximum version of vnode as the endVersion endVer = pVnode->state.applied; } else { endVer = (pCond->endVersion > pVnode->state.applied) ? pVnode->state.applied : pCond->endVersion; @@ -3168,7 +3670,7 @@ SVersionRange getQueryVerRange(SVnode* pVnode, SQueryTableDataCond* pCond, int8_ return (SVersionRange){.minVer = startVer, .maxVer = endVer}; } -bool hasBeenDropped(const SArray* pDelList, int32_t* index, TSDBKEY* pKey, int32_t order, SVersionRange* pVerRange) { +bool hasBeenDropped(const SArray* pDelList, int32_t* index, int64_t key, int64_t ver, int32_t order, SVersionRange* pVerRange) { if (pDelList == NULL) { return false; } @@ -3180,29 +3682,29 @@ bool hasBeenDropped(const SArray* pDelList, int32_t* index, TSDBKEY* pKey, int32 if (asc) { if (*index >= num - 1) { TSDBKEY* last = taosArrayGetLast(pDelList); - ASSERT(pKey->ts >= last->ts); + ASSERT(key >= last->ts); - if (pKey->ts > last->ts) { + if (key > last->ts) { return false; - } else if (pKey->ts == last->ts) { + } else if (key == last->ts) { TSDBKEY* prev = taosArrayGet(pDelList, num - 2); - return (prev->version >= pKey->version && prev->version <= pVerRange->maxVer && + return (prev->version >= ver && prev->version <= pVerRange->maxVer && prev->version >= pVerRange->minVer); } } else { TSDBKEY* pCurrent = taosArrayGet(pDelList, *index); TSDBKEY* pNext = taosArrayGet(pDelList, (*index) + 1); - if (pKey->ts < pCurrent->ts) { + if (key < pCurrent->ts) { return false; } - if (pCurrent->ts <= pKey->ts && pNext->ts >= pKey->ts && pCurrent->version >= pKey->version && + if (pCurrent->ts <= key && pNext->ts >= key && pCurrent->version >= ver && pVerRange->maxVer >= pCurrent->version) { return true; } - while (pNext->ts <= pKey->ts && (*index) < num - 1) { + while (pNext->ts <= key && (*index) < num - 1) { (*index) += 1; if ((*index) < num - 1) { @@ -3214,7 +3716,7 @@ bool hasBeenDropped(const SArray* pDelList, int32_t* index, TSDBKEY* pKey, int32 continue; } - if (pCurrent->ts <= pKey->ts && pNext->ts >= pKey->ts && pCurrent->version >= pKey->version && + if (pCurrent->ts <= key && pNext->ts >= key && pCurrent->version >= ver && pVerRange->maxVer >= pCurrent->version) { return true; } @@ -3227,10 +3729,10 @@ bool hasBeenDropped(const SArray* pDelList, int32_t* index, TSDBKEY* pKey, int32 if (*index <= 0) { TSDBKEY* pFirst = taosArrayGet(pDelList, 0); - if (pKey->ts < pFirst->ts) { + if (key < pFirst->ts) { return false; - } else if (pKey->ts == pFirst->ts) { - return pFirst->version >= pKey->version; + } else if (key == pFirst->ts) { + return pFirst->version >= ver; } else { ASSERT(0); } @@ -3238,15 +3740,15 @@ bool hasBeenDropped(const SArray* pDelList, int32_t* index, TSDBKEY* pKey, int32 TSDBKEY* pCurrent = taosArrayGet(pDelList, *index); TSDBKEY* pPrev = taosArrayGet(pDelList, (*index) - 1); - if (pKey->ts > pCurrent->ts) { + if (key > pCurrent->ts) { return false; } - if (pPrev->ts <= pKey->ts && pCurrent->ts >= pKey->ts && pPrev->version >= pKey->version) { + if (pPrev->ts <= key && pCurrent->ts >= key && pPrev->version >= ver) { return true; } - while (pPrev->ts >= pKey->ts && (*index) > 1) { + while (pPrev->ts >= key && (*index) > 1) { (*index) += step; if ((*index) >= 1) { @@ -3258,7 +3760,7 @@ bool hasBeenDropped(const SArray* pDelList, int32_t* index, TSDBKEY* pKey, int32 continue; } - if (pPrev->ts <= pKey->ts && pCurrent->ts >= pKey->ts && pPrev->version >= pKey->version) { + if (pPrev->ts <= key && pCurrent->ts >= key && pPrev->version >= ver) { return true; } } @@ -3277,7 +3779,8 @@ TSDBROW* getValidMemRow(SIterInfo* pIter, const SArray* pDelList, STsdbReader* p } TSDBROW* pRow = tsdbTbDataIterGet(pIter->iter); - TSDBKEY key = {.ts = pRow->pTSRow->ts, .version = pRow->version}; + TSDBKEY key = TSDBROW_KEY(pRow); + if (outOfTimeWindow(key.ts, &pReader->window)) { pIter->hasVal = false; return NULL; @@ -3285,7 +3788,7 @@ TSDBROW* getValidMemRow(SIterInfo* pIter, const SArray* pDelList, STsdbReader* p // it is a valid data version if ((key.version <= pReader->verRange.maxVer && key.version >= pReader->verRange.minVer) && - (!hasBeenDropped(pDelList, &pIter->index, &key, pReader->order, &pReader->verRange))) { + (!hasBeenDropped(pDelList, &pIter->index, key.ts, key.version, pReader->order, &pReader->verRange))) { return pRow; } @@ -3304,14 +3807,15 @@ TSDBROW* getValidMemRow(SIterInfo* pIter, const SArray* pDelList, STsdbReader* p } if (key.version <= pReader->verRange.maxVer && key.version >= pReader->verRange.minVer && - (!hasBeenDropped(pDelList, &pIter->index, &key, pReader->order, &pReader->verRange))) { + (!hasBeenDropped(pDelList, &pIter->index, key.ts, key.version, pReader->order, &pReader->verRange))) { return pRow; } } } -int32_t doMergeRowsInBuf(SIterInfo* pIter, uint64_t uid, int64_t ts, SArray* pDelList, SRowMerger* pMerger, - STsdbReader* pReader) { +int32_t doMergeRowsInBuf(SIterInfo* pIter, uint64_t uid, int64_t ts, SArray* pDelList, STsdbReader* pReader) { + SRowMerger* pMerger = &pReader->status.merger; + while (1) { pIter->hasVal = tsdbTbDataIterNext(pIter->iter); if (!pIter->hasVal) { @@ -3330,12 +3834,16 @@ int32_t doMergeRowsInBuf(SIterInfo* pIter, uint64_t uid, int64_t ts, SArray* pDe break; } - STSchema* pTSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, uid); - if (pTSchema == NULL) { - return terrno; - } + if (pRow->type == TSDBROW_ROW_FMT) { + STSchema* pTSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, uid); + if (pTSchema == NULL) { + return terrno; + } - tRowMergerAdd(pMerger, pRow, pTSchema); + tsdbRowMergerAdd(pMerger, pRow, pTSchema); + } else { // column format + tsdbRowMergerAdd(pMerger, pRow, NULL); + } } return TSDB_CODE_SUCCESS; @@ -3350,7 +3858,7 @@ static int32_t doMergeRowsInFileBlockImpl(SBlockData* pBlockData, int32_t rowInd } TSDBROW fRow = tsdbRowFromBlockData(pBlockData, rowIndex); - tRowMerge(pMerger, &fRow); + tsdbRowMergerAdd(pMerger, &fRow, NULL); rowIndex += step; } @@ -3367,6 +3875,7 @@ static int32_t checkForNeighborFileBlock(STsdbReader* pReader, STableBlockScanIn CHECK_FILEBLOCK_STATE* state) { SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo; SBlockData* pBlockData = &pReader->status.fileBlockData; + bool asc = ASCENDING_TRAVERSE(pReader->order); *state = CHECK_FILEBLOCK_QUIT; int32_t step = ASCENDING_TRAVERSE(pReader->order) ? 1 : -1; @@ -3377,7 +3886,7 @@ static int32_t checkForNeighborFileBlock(STsdbReader* pReader, STableBlockScanIn if (loadNeighbor && (code == TSDB_CODE_SUCCESS)) { pDumpInfo->rowIndex = doMergeRowsInFileBlockImpl(pBlockData, pDumpInfo->rowIndex, key, pMerger, &pReader->verRange, step); - if (pDumpInfo->rowIndex >= pDumpInfo->totalRows) { + if ((pDumpInfo->rowIndex >= pDumpInfo->totalRows && asc) || (pDumpInfo->rowIndex < 0 && !asc)) { *state = CHECK_FILEBLOCK_CONT; } } @@ -3385,10 +3894,10 @@ static int32_t checkForNeighborFileBlock(STsdbReader* pReader, STableBlockScanIn return code; } -int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pScanInfo, STsdbReader* pReader, - SRowMerger* pMerger) { +int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pScanInfo, STsdbReader* pReader) { SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo; + SRowMerger* pMerger = &pReader->status.merger; bool asc = ASCENDING_TRAVERSE(pReader->order); int64_t key = pBlockData->aTSKEY[pDumpInfo->rowIndex]; int32_t step = asc ? 1 : -1; @@ -3406,6 +3915,11 @@ int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pSc SFileDataBlockInfo* pFileBlockInfo = getCurrentBlockInfo(&pReader->status.blockIter); SDataBlk* pCurrentBlock = getCurrentBlock(&pReader->status.blockIter); + if (pFileBlockInfo == NULL) { + st = CHECK_FILEBLOCK_QUIT; + break; + } + checkForNeighborFileBlock(pReader, pScanInfo, pCurrentBlock, pFileBlockInfo, pMerger, key, &st); if (st == CHECK_FILEBLOCK_QUIT) { break; @@ -3417,13 +3931,16 @@ int32_t doMergeRowsInFileBlocks(SBlockData* pBlockData, STableBlockScanInfo* pSc } int32_t doMergeRowsInLastBlock(SLastBlockReader* pLastBlockReader, STableBlockScanInfo* pScanInfo, int64_t ts, - SRowMerger* pMerger, SVersionRange* pVerRange) { + SRowMerger* pMerger, SVersionRange* pVerRange, const char* idStr) { while (nextRowFromLastBlocks(pLastBlockReader, pScanInfo, pVerRange)) { int64_t next1 = getCurrentKeyInLastBlock(pLastBlockReader); if (next1 == ts) { - TSDBROW fRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); - tRowMerge(pMerger, &fRow1); + TSDBROW* pRow1 = tMergeTreeGetRow(&pLastBlockReader->mergeTree); + tsdbRowMergerAdd(pMerger, pRow1, NULL); } else { + tsdbTrace("uid:%" PRIu64 " last del index:%d, del range:%d, lastKeyInStt:%" PRId64 ", %s", pScanInfo->uid, + pScanInfo->lastBlockDelIndex, (int32_t)taosArrayGetSize(pScanInfo->delSkyline), pScanInfo->lastKeyInStt, + idStr); break; } } @@ -3431,7 +3948,7 @@ int32_t doMergeRowsInLastBlock(SLastBlockReader* pLastBlockReader, STableBlockSc return TSDB_CODE_SUCCESS; } -int32_t doMergeMemTableMultiRows(TSDBROW* pRow, uint64_t uid, SIterInfo* pIter, SArray* pDelList, STSRow** pTSRow, +int32_t doMergeMemTableMultiRows(TSDBROW* pRow, uint64_t uid, SIterInfo* pIter, SArray* pDelList, TSDBROW* pResRow, STsdbReader* pReader, bool* freeTSRow) { TSDBROW* pNextRow = NULL; TSDBROW current = *pRow; @@ -3440,122 +3957,131 @@ int32_t doMergeMemTableMultiRows(TSDBROW* pRow, uint64_t uid, SIterInfo* pIter, pIter->hasVal = tsdbTbDataIterNext(pIter->iter); if (!pIter->hasVal) { - *pTSRow = current.pTSRow; + *pResRow = *pRow; *freeTSRow = false; return TSDB_CODE_SUCCESS; } else { // has next point in mem/imem pNextRow = getValidMemRow(pIter, pDelList, pReader); if (pNextRow == NULL) { - *pTSRow = current.pTSRow; + *pResRow = current; *freeTSRow = false; return TSDB_CODE_SUCCESS; } - if (current.pTSRow->ts != pNextRow->pTSRow->ts) { - *pTSRow = current.pTSRow; + if (TSDBROW_TS(¤t) != TSDBROW_TS(pNextRow)) { + *pResRow = current; *freeTSRow = false; return TSDB_CODE_SUCCESS; } } } - SRowMerger merge = {0}; - - // get the correct schema for data in memory terrno = 0; - STSchema* pTSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(¤t), pReader, uid); - if (pTSchema == NULL) { - return terrno; - } + int32_t code = 0; - if (pReader->pSchema == NULL) { - pReader->pSchema = pTSchema; + // start to merge duplicated rows + if (current.type == TSDBROW_ROW_FMT) { + // get the correct schema for data in memory + STSchema* pTSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(¤t), pReader, uid); + if (pTSchema == NULL) { + return terrno; + } + + code = tsdbRowMergerAdd(&pReader->status.merger, ¤t, pTSchema); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + STSchema* pTSchema1 = doGetSchemaForTSRow(TSDBROW_SVERSION(pNextRow), pReader, uid); + if (pTSchema1 == NULL) { + return terrno; + } + + tsdbRowMergerAdd(&pReader->status.merger,pNextRow, pTSchema1); + } else { // let's merge rows in file block + code = tsdbRowMergerAdd(&pReader->status.merger, ¤t, pReader->pSchema); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + tsdbRowMergerAdd(&pReader->status.merger,pNextRow, NULL); } - int32_t code = tRowMergerInit2(&merge, pReader->pSchema, ¤t, pTSchema); + code = doMergeRowsInBuf(pIter, uid, TSDBROW_TS(¤t), pDelList, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } - STSchema* pTSchema1 = doGetSchemaForTSRow(TSDBROW_SVERSION(pNextRow), pReader, uid); - if (pTSchema1 == NULL) { - return terrno; + code = tsdbRowMergerGetRow(&pReader->status.merger, &pResRow->pTSRow); + if (code != TSDB_CODE_SUCCESS) { + return code; } - tRowMergerAdd(&merge, pNextRow, pTSchema1); - - code = doMergeRowsInBuf(pIter, uid, current.pTSRow->ts, pDelList, &merge, pReader); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - code = tRowMergerGetRow(&merge, pTSRow); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - tRowMergerClear(&merge); + pResRow->type = TSDBROW_ROW_FMT; + tsdbRowMergerClear(&pReader->status.merger); *freeTSRow = true; + return TSDB_CODE_SUCCESS; } int32_t doMergeMemIMemRows(TSDBROW* pRow, TSDBROW* piRow, STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader, - STSRow** pTSRow) { - SRowMerger merge = {0}; + SRow** pTSRow) { + SRowMerger* pMerger = &pReader->status.merger; - TSDBKEY k = TSDBROW_KEY(pRow); - TSDBKEY ik = TSDBROW_KEY(piRow); + TSDBKEY k = TSDBROW_KEY(pRow); + TSDBKEY ik = TSDBROW_KEY(piRow); + STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid); + if (pSchema == NULL) { + return terrno; + } - if (ASCENDING_TRAVERSE(pReader->order)) { // ascending order imem --> mem - STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid); + STSchema* piSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(piRow), pReader, pBlockScanInfo->uid); + if (piSchema == NULL) { + return terrno; + } - int32_t code = tRowMergerInit(&merge, piRow, pSchema); + if (ASCENDING_TRAVERSE(pReader->order)) { // ascending order imem --> mem + int32_t code = tsdbRowMergerAdd(&pReader->status.merger, piRow, piSchema); if (code != TSDB_CODE_SUCCESS) { return code; } - code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, ik.ts, pBlockScanInfo->delSkyline, &merge, - pReader); + code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, ik.ts, pBlockScanInfo->delSkyline, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } - tRowMerge(&merge, pRow); + tsdbRowMergerAdd(&pReader->status.merger,pRow, pSchema); code = - doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, &merge, pReader); + doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } } else { - STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid); - - int32_t code = tRowMergerInit(&merge, pRow, pSchema); - if (code != TSDB_CODE_SUCCESS || merge.pTSchema == NULL) { + int32_t code = tsdbRowMergerAdd(&pReader->status.merger, pRow, pSchema); + if (code != TSDB_CODE_SUCCESS || pMerger->pTSchema == NULL) { return code; } - code = - doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, &merge, pReader); + code = doMergeRowsInBuf(&pBlockScanInfo->iter, pBlockScanInfo->uid, k.ts, pBlockScanInfo->delSkyline, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } - tRowMerge(&merge, piRow); - code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, ik.ts, pBlockScanInfo->delSkyline, &merge, - pReader); + tsdbRowMergerAdd(&pReader->status.merger, piRow, piSchema); + code = doMergeRowsInBuf(&pBlockScanInfo->iiter, pBlockScanInfo->uid, ik.ts, pBlockScanInfo->delSkyline, pReader); if (code != TSDB_CODE_SUCCESS) { return code; } } - int32_t code = tRowMergerGetRow(&merge, pTSRow); - tRowMergerClear(&merge); - + int32_t code = tsdbRowMergerGetRow(pMerger, pTSRow); + tsdbRowMergerClear(pMerger); return code; } -int32_t tsdbGetNextRowInMem(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader, STSRow** pTSRow, int64_t endKey, +int32_t tsdbGetNextRowInMem(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader, TSDBROW* pResRow, int64_t endKey, bool* freeTSRow) { TSDBROW* pRow = getValidMemRow(&pBlockScanInfo->iter, pBlockScanInfo->delSkyline, pReader); TSDBROW* piRow = getValidMemRow(&pBlockScanInfo->iiter, pBlockScanInfo->delSkyline, pReader); @@ -3585,13 +4111,14 @@ int32_t tsdbGetNextRowInMem(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pR int32_t code = TSDB_CODE_SUCCESS; if (ik.ts != k.ts) { if (((ik.ts < k.ts) && asc) || ((ik.ts > k.ts) && (!asc))) { // ik.ts < k.ts - code = doMergeMemTableMultiRows(piRow, uid, &pBlockScanInfo->iiter, pDelList, pTSRow, pReader, freeTSRow); + code = doMergeMemTableMultiRows(piRow, uid, &pBlockScanInfo->iiter, pDelList, pResRow, pReader, freeTSRow); } else if (((k.ts < ik.ts) && asc) || ((k.ts > ik.ts) && (!asc))) { - code = doMergeMemTableMultiRows(pRow, uid, &pBlockScanInfo->iter, pDelList, pTSRow, pReader, freeTSRow); + code = doMergeMemTableMultiRows(pRow, uid, &pBlockScanInfo->iter, pDelList, pResRow, pReader, freeTSRow); } } else { // ik.ts == k.ts *freeTSRow = true; - code = doMergeMemIMemRows(pRow, piRow, pBlockScanInfo, pReader, pTSRow); + pResRow->type = TSDBROW_ROW_FMT; + code = doMergeMemIMemRows(pRow, piRow, pBlockScanInfo, pReader, &pResRow->pTSRow); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -3601,24 +4128,27 @@ int32_t tsdbGetNextRowInMem(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pR } if (pBlockScanInfo->iter.hasVal && pRow != NULL) { - return doMergeMemTableMultiRows(pRow, pBlockScanInfo->uid, &pBlockScanInfo->iter, pDelList, pTSRow, pReader, + return doMergeMemTableMultiRows(pRow, pBlockScanInfo->uid, &pBlockScanInfo->iter, pDelList, pResRow, pReader, freeTSRow); } if (pBlockScanInfo->iiter.hasVal && piRow != NULL) { - return doMergeMemTableMultiRows(piRow, uid, &pBlockScanInfo->iiter, pDelList, pTSRow, pReader, freeTSRow); + return doMergeMemTableMultiRows(piRow, uid, &pBlockScanInfo->iiter, pDelList, pResRow, pReader, freeTSRow); } return TSDB_CODE_SUCCESS; } -int32_t doAppendRowFromTSRow(SSDataBlock* pBlock, STsdbReader* pReader, STSRow* pTSRow, - STableBlockScanInfo* pScanInfo) { +int32_t doAppendRowFromTSRow(SSDataBlock* pBlock, STsdbReader* pReader, SRow* pTSRow, STableBlockScanInfo* pScanInfo) { int32_t outputRowIndex = pBlock->info.rows; int64_t uid = pScanInfo->uid; + int32_t code = TSDB_CODE_SUCCESS; SBlockLoadSuppInfo* pSupInfo = &pReader->suppInfo; STSchema* pSchema = doGetSchemaForTSRow(pTSRow->sver, pReader, uid); + if (pSchema == NULL) { + return terrno; + } SColVal colVal = {0}; int32_t i = 0, j = 0; @@ -3635,14 +4165,17 @@ int32_t doAppendRowFromTSRow(SSDataBlock* pBlock, STsdbReader* pReader, STSRow* if (colId == pSchema->columns[j].colId) { SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pSupInfo->slotId[i]); - tTSRowGetVal(pTSRow, pSchema, j, &colVal); - doCopyColVal(pColInfoData, outputRowIndex, i, &colVal, pSupInfo); + tRowGet(pTSRow, pSchema, j, &colVal); + code = doCopyColVal(pColInfoData, outputRowIndex, i, &colVal, pSupInfo); + if (code) { + return code; + } i += 1; j += 1; } else if (colId < pSchema->columns[j].colId) { SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pSupInfo->slotId[i]); - colDataAppendNULL(pColInfoData, outputRowIndex); + colDataSetNULL(pColInfoData, outputRowIndex); i += 1; } else if (colId > pSchema->columns[j].colId) { j += 1; @@ -3652,7 +4185,7 @@ int32_t doAppendRowFromTSRow(SSDataBlock* pBlock, STsdbReader* pReader, STSRow* // set null value since current column does not exist in the "pSchema" while (i < pSupInfo->numOfCols) { SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pSupInfo->slotId[i]); - colDataAppendNULL(pColInfoData, outputRowIndex); + colDataSetNULL(pColInfoData, outputRowIndex); i += 1; } @@ -3666,13 +4199,11 @@ int32_t doAppendRowFromFileBlock(SSDataBlock* pResBlock, STsdbReader* pReader, S int32_t rowIndex) { int32_t i = 0, j = 0; int32_t outputRowIndex = pResBlock->info.rows; + int32_t code = TSDB_CODE_SUCCESS; SBlockLoadSuppInfo* pSupInfo = &pReader->suppInfo; - if (pReader->suppInfo.colId[i] == PRIMARYKEY_TIMESTAMP_COL_ID) { - SColumnInfoData* pColData = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]); - ((int64_t*)pColData->pData)[outputRowIndex] = pBlockData->aTSKEY[rowIndex]; - i += 1; - } + ((int64_t*)pReader->status.pPrimaryTsCol->pData)[outputRowIndex] = pBlockData->aTSKEY[rowIndex]; + i += 1; SColVal cv = {0}; int32_t numOfInputCols = pBlockData->nColData; @@ -3688,11 +4219,14 @@ int32_t doAppendRowFromFileBlock(SSDataBlock* pResBlock, STsdbReader* pReader, S SColumnInfoData* pCol = TARRAY_GET_ELEM(pResBlock->pDataBlock, pSupInfo->slotId[i]); if (pData->cid == pSupInfo->colId[i]) { tColDataGetValue(pData, rowIndex, &cv); - doCopyColVal(pCol, outputRowIndex, i, &cv, pSupInfo); + code = doCopyColVal(pCol, outputRowIndex, i, &cv, pSupInfo); + if (code) { + return code; + } j += 1; } else if (pData->cid > pCol->info.colId) { // the specified column does not exist in file block, fill with null data - colDataAppendNULL(pCol, outputRowIndex); + colDataSetNULL(pCol, outputRowIndex); } i += 1; @@ -3700,7 +4234,7 @@ int32_t doAppendRowFromFileBlock(SSDataBlock* pResBlock, STsdbReader* pReader, S while (i < numOfOutputCols) { SColumnInfoData* pCol = taosArrayGet(pResBlock->pDataBlock, pSupInfo->slotId[i]); - colDataAppendNULL(pCol, outputRowIndex); + colDataSetNULL(pCol, outputRowIndex); i += 1; } @@ -3711,20 +4245,33 @@ int32_t doAppendRowFromFileBlock(SSDataBlock* pResBlock, STsdbReader* pReader, S int32_t buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t endKey, int32_t capacity, STsdbReader* pReader) { - SSDataBlock* pBlock = pReader->pResBlock; + SSDataBlock* pBlock = pReader->resBlockInfo.pResBlock; + int32_t code = TSDB_CODE_SUCCESS; do { - STSRow* pTSRow = NULL; + // SRow* pTSRow = NULL; + TSDBROW row = {.type = -1}; bool freeTSRow = false; - tsdbGetNextRowInMem(pBlockScanInfo, pReader, &pTSRow, endKey, &freeTSRow); - if (pTSRow == NULL) { + tsdbGetNextRowInMem(pBlockScanInfo, pReader, &row, endKey, &freeTSRow); + if (row.type == -1) { break; } - doAppendRowFromTSRow(pBlock, pReader, pTSRow, pBlockScanInfo); + if (row.type == TSDBROW_ROW_FMT) { + code = doAppendRowFromTSRow(pBlock, pReader, row.pTSRow, pBlockScanInfo); - if (freeTSRow) { - taosMemoryFree(pTSRow); + if (freeTSRow) { + taosMemoryFree(row.pTSRow); + } + + if (code) { + return code; + } + } else { + code = doAppendRowFromFileBlock(pBlock, pReader, row.pBlockData, row.iRow); + if (code) { + break; + } } // no data in buffer, return immediately @@ -3737,22 +4284,35 @@ int32_t buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t e } } while (1); - return TSDB_CODE_SUCCESS; + return code; } // TODO refactor: with createDataBlockScanInfo int32_t tsdbSetTableList(STsdbReader* pReader, const void* pTableList, int32_t num) { - int32_t size = taosHashGetSize(pReader->status.pTableMap); + int32_t size = tSimpleHashGetSize(pReader->status.pTableMap); STableBlockScanInfo** p = NULL; - while ((p = taosHashIterate(pReader->status.pTableMap, p)) != NULL) { + int32_t iter = 0; + + while ((p = tSimpleHashIterate(pReader->status.pTableMap, p, &iter)) != NULL) { clearBlockScanInfo(*p); } - // todo handle the case where size is less than the value of num - ASSERT(size >= num); + if (size < num) { + int32_t code = ensureBlockScanInfoBuf(&pReader->blockInfoBuf, num); + if (code) { + return code; + } + + char* p1 = taosMemoryRealloc(pReader->status.uidList.tableUidList, sizeof(uint64_t) * num); + if (p1 == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } - taosHashClear(pReader->status.pTableMap); + pReader->status.uidList.tableUidList = (uint64_t*)p1; + } + + tSimpleHashClear(pReader->status.pTableMap); STableUidList* pUidList = &pReader->status.uidList; pUidList->currentIndex = 0; @@ -3762,7 +4322,18 @@ int32_t tsdbSetTableList(STsdbReader* pReader, const void* pTableList, int32_t n pInfo->uid = pList[i].uid; pUidList->tableUidList[i] = pList[i].uid; - taosHashPut(pReader->status.pTableMap, &pInfo->uid, sizeof(uint64_t), &pInfo, POINTER_BYTES); + // todo extract method + if (ASCENDING_TRAVERSE(pReader->order)) { + int64_t skey = pReader->window.skey; + pInfo->lastKey = (skey > INT64_MIN) ? (skey - 1) : skey; + pInfo->lastKeyInStt = skey; + } else { + int64_t ekey = pReader->window.ekey; + pInfo->lastKey = (ekey < INT64_MAX) ? (ekey + 1) : ekey; + pInfo->lastKeyInStt = ekey; + } + + tSimpleHashPut(pReader->status.pTableMap, &pInfo->uid, sizeof(uint64_t), &pInfo, POINTER_BYTES); } return TDB_CODE_SUCCESS; @@ -3782,7 +4353,7 @@ void* tsdbGetIvtIdx(SMeta* pMeta) { return metaGetIvtIdx(pMeta); } -uint64_t getReaderMaxVersion(STsdbReader* pReader) { return pReader->verRange.maxVer; } +uint64_t tsdbGetReaderMaxVersion(STsdbReader* pReader) { return pReader->verRange.maxVer; } static int32_t doOpenReaderImpl(STsdbReader* pReader) { SReaderStatus* pStatus = &pReader->status; @@ -3794,6 +4365,8 @@ static int32_t doOpenReaderImpl(STsdbReader* pReader) { int32_t code = TSDB_CODE_SUCCESS; if (pStatus->fileIter.numOfFiles == 0) { pStatus->loadFromFile = false; + } else if (READ_MODE_COUNT_ONLY == pReader->readMode) { + // DO NOTHING } else { code = initForFirstBlockInFile(pReader, pBlockIter); } @@ -3805,14 +4378,15 @@ static int32_t doOpenReaderImpl(STsdbReader* pReader) { return code; } +static void freeSchemaFunc(void* param) { + void **p = (void **)param; + taosMemoryFreeClear(*p); +} + // ====================================== EXPOSED APIs ====================================== int32_t tsdbReaderOpen(SVnode* pVnode, SQueryTableDataCond* pCond, void* pTableList, int32_t numOfTables, - SSDataBlock* pResBlock, STsdbReader** ppReader, const char* idstr) { + SSDataBlock* pResBlock, STsdbReader** ppReader, const char* idstr, bool countOnly, SHashObj** pIgnoreTables) { STimeWindow window = pCond->twindows; - if (pCond->type == TIMEWINDOW_RANGE_EXTERNAL) { - pCond->twindows.skey += 1; - pCond->twindows.ekey -= 1; - } int32_t capacity = pVnode->config.tsdbCfg.maxRows; if (pResBlock != NULL) { @@ -3835,11 +4409,11 @@ int32_t tsdbReaderOpen(SVnode* pVnode, SQueryTableDataCond* pCond, void* pTableL // update the SQueryTableDataCond to create inner reader int32_t order = pCond->order; if (order == TSDB_ORDER_ASC) { - pCond->twindows.ekey = window.skey; + pCond->twindows.ekey = window.skey - 1; pCond->twindows.skey = INT64_MIN; pCond->order = TSDB_ORDER_DESC; } else { - pCond->twindows.skey = window.ekey; + pCond->twindows.skey = window.ekey + 1; pCond->twindows.ekey = INT64_MAX; pCond->order = TSDB_ORDER_ASC; } @@ -3851,11 +4425,11 @@ int32_t tsdbReaderOpen(SVnode* pVnode, SQueryTableDataCond* pCond, void* pTableL } if (order == TSDB_ORDER_ASC) { - pCond->twindows.skey = window.ekey; + pCond->twindows.skey = window.ekey + 1; pCond->twindows.ekey = INT64_MAX; } else { pCond->twindows.skey = INT64_MIN; - pCond->twindows.ekey = window.ekey; + pCond->twindows.ekey = window.ekey - 1; } pCond->order = order; @@ -3881,6 +4455,18 @@ int32_t tsdbReaderOpen(SVnode* pVnode, SQueryTableDataCond* pCond, void* pTableL } } + if (pReader->pSchema != NULL) { + tsdbRowMergerInit(&pReader->status.merger, pReader->pSchema); + } + + pReader->pSchemaMap = tSimpleHashInit(8, taosFastHash); + if (pReader->pSchemaMap == NULL) { + tsdbError("failed init schema hash for reader %s", pReader->idStr); + code = TSDB_CODE_OUT_OF_MEMORY; + goto _err; + } + + tSimpleHashSetFreeFp(pReader->pSchemaMap, freeSchemaFunc); if (pReader->pSchema != NULL) { code = updateBlockSMAInfo(pReader->pSchema, &pReader->suppInfo); if (code != TSDB_CODE_SUCCESS) { @@ -3889,82 +4475,74 @@ int32_t tsdbReaderOpen(SVnode* pVnode, SQueryTableDataCond* pCond, void* pTableL } STsdbReader* p = (pReader->innerReader[0] != NULL) ? pReader->innerReader[0] : pReader; - pReader->status.pTableMap = createDataBlockScanInfo(p, &pReader->blockInfoBuf, pTableList, &pReader->status.uidList, numOfTables); + pReader->status.pTableMap = + createDataBlockScanInfo(p, &pReader->blockInfoBuf, pTableList, &pReader->status.uidList, numOfTables); if (pReader->status.pTableMap == NULL) { *ppReader = NULL; code = TSDB_CODE_OUT_OF_MEMORY; goto _err; } - if (numOfTables > 0) { - code = tsdbTakeReadSnap(pReader->pTsdb, &pReader->pReadSnap, pReader->idStr); - if (code != TSDB_CODE_SUCCESS) { - goto _err; - } - - if (pReader->type == TIMEWINDOW_RANGE_CONTAINED) { - code = doOpenReaderImpl(pReader); - if (code != TSDB_CODE_SUCCESS) { - goto _err; - } - } else { - STsdbReader* pPrevReader = pReader->innerReader[0]; - STsdbReader* pNextReader = pReader->innerReader[1]; + pReader->status.pLDataIter = taosMemoryCalloc(pVnode->config.sttTrigger, sizeof(SLDataIter)); + if (pReader->status.pLDataIter == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _err; + } - // we need only one row - pPrevReader->capacity = 1; - pPrevReader->status.pTableMap = pReader->status.pTableMap; - pPrevReader->status.uidList = pReader->status.uidList; - pPrevReader->pSchema = pReader->pSchema; - pPrevReader->pMemSchema = pReader->pMemSchema; - pPrevReader->pReadSnap = pReader->pReadSnap; - - pNextReader->capacity = 1; - pNextReader->status.pTableMap = pReader->status.pTableMap; - pNextReader->status.uidList = pReader->status.uidList; - pNextReader->pSchema = pReader->pSchema; - pNextReader->pMemSchema = pReader->pMemSchema; - pNextReader->pReadSnap = pReader->pReadSnap; + pReader->flag = READER_STATUS_SUSPEND; - code = doOpenReaderImpl(pPrevReader); - if (code != TSDB_CODE_SUCCESS) { - goto _err; - } - } + if (countOnly) { + pReader->readMode = READ_MODE_COUNT_ONLY; } + pReader->pIgnoreTables = pIgnoreTables; + tsdbDebug("%p total numOfTable:%d in this query %s", pReader, numOfTables, pReader->idStr); return code; _err: tsdbError("failed to create data reader, code:%s %s", tstrerror(code), idstr); tsdbReaderClose(pReader); - *ppReader = NULL; // reset the pointer value. + *ppReader = NULL; // reset the pointer value. return code; } +static void clearSharedPtr(STsdbReader* p) { + p->status.pLDataIter = NULL; + p->status.pTableMap = NULL; + p->status.uidList.tableUidList = NULL; + p->pReadSnap = NULL; + p->pSchema = NULL; + p->pSchemaMap = NULL; +} + +static void setSharedPtr(STsdbReader* pDst, const STsdbReader* pSrc) { + pDst->status.pTableMap = pSrc->status.pTableMap; + pDst->status.pLDataIter = pSrc->status.pLDataIter; + pDst->status.uidList = pSrc->status.uidList; + pDst->pSchema = pSrc->pSchema; + pDst->pSchemaMap = pSrc->pSchemaMap; + pDst->pReadSnap = pSrc->pReadSnap; + + if (pDst->pSchema) { + tsdbRowMergerInit(&pDst->status.merger, pDst->pSchema); + } +} + void tsdbReaderClose(STsdbReader* pReader) { if (pReader == NULL) { return; } + tsdbAcquireReader(pReader); + { if (pReader->innerReader[0] != NULL || pReader->innerReader[1] != NULL) { STsdbReader* p = pReader->innerReader[0]; - - p->status.pTableMap = NULL; - p->status.uidList.tableUidList = NULL; - p->pReadSnap = NULL; - p->pSchema = NULL; - p->pMemSchema = NULL; + clearSharedPtr(p); p = pReader->innerReader[1]; - - p->status.pTableMap = NULL; - p->status.uidList.tableUidList = NULL; - p->pReadSnap = NULL; - p->pSchema = NULL; - p->pMemSchema = NULL; + clearSharedPtr(p); tsdbReaderClose(pReader->innerReader[0]); tsdbReaderClose(pReader->innerReader[1]); @@ -3980,15 +4558,15 @@ void tsdbReaderClose(STsdbReader* pReader) { } } - if (pReader->freeBlock) { - pReader->pResBlock = blockDataDestroy(pReader->pResBlock); + if (pReader->resBlockInfo.freeBlock) { + pReader->resBlockInfo.pResBlock = blockDataDestroy(pReader->resBlockInfo.pResBlock); } taosMemoryFree(pSupInfo->colId); - tBlockDataDestroy(&pReader->status.fileBlockData, true); + tBlockDataDestroy(&pReader->status.fileBlockData); cleanupDataBlockIterator(&pReader->status.blockIter); - size_t numOfTables = taosHashGetSize(pReader->status.pTableMap); + size_t numOfTables = tSimpleHashGetSize(pReader->status.pTableMap); if (pReader->status.pTableMap != NULL) { destroyAllBlockScanInfo(pReader->status.pTableMap); clearBlockScanInfoBuf(&pReader->blockInfoBuf); @@ -4007,9 +4585,16 @@ void tsdbReaderClose(STsdbReader* pReader) { pReader->pDelIdx = NULL; } - tsdbUntakeReadSnap(pReader->pTsdb, pReader->pReadSnap, pReader->idStr); + qTrace("tsdb/reader-close: %p, untake snapshot", pReader); + tsdbUntakeReadSnap(pReader, pReader->pReadSnap, true); + pReader->pReadSnap = NULL; + + tsdbReleaseReader(pReader); + + tsdbUninitReaderLock(pReader); - taosMemoryFree(pReader->status.uidList.tableUidList); + taosMemoryFreeClear(pReader->status.pLDataIter); + taosMemoryFreeClear(pReader->status.uidList.tableUidList); SIOCostSummary* pCost = &pReader->cost; SFilesetIter* pFilesetIter = &pReader->status.fileIter; @@ -4028,68 +4613,306 @@ void tsdbReaderClose(STsdbReader* pReader) { " SMA-time:%.2f ms, fileBlocks:%" PRId64 ", fileBlocks-load-time:%.2f ms, " "build in-memory-block-time:%.2f ms, lastBlocks:%" PRId64 ", lastBlocks-time:%.2f ms, composed-blocks:%" PRId64 - ", composed-blocks-time:%.2fms, STableBlockScanInfo size:%.2f Kb, createTime:%.2f ms,initDelSkylineIterTime:%.2f ms, %s", + ", composed-blocks-time:%.2fms, STableBlockScanInfo size:%.2f Kb, createTime:%.2f ms,initDelSkylineIterTime:%.2f " + "ms, %s", pReader, pCost->headFileLoad, pCost->headFileLoadTime, pCost->smaDataLoad, pCost->smaLoadTime, pCost->numOfBlocks, pCost->blockLoadTime, pCost->buildmemBlock, pCost->lastBlockLoad, pCost->lastBlockLoadTime, pCost->composedBlocks, pCost->buildComposedBlockTime, numOfTables * sizeof(STableBlockScanInfo) / 1000.0, pCost->createScanInfoList, pCost->initDelSkylineIterTime, pReader->idStr); taosMemoryFree(pReader->idStr); + + tsdbRowMergerCleanup(&pReader->status.merger); taosMemoryFree(pReader->pSchema); - if (pReader->pMemSchema != pReader->pSchema) { - taosMemoryFree(pReader->pMemSchema); + tSimpleHashCleanup(pReader->pSchemaMap); + taosMemoryFreeClear(pReader); +} + +int32_t tsdbReaderSuspend(STsdbReader* pReader) { + int32_t code = 0; + + // save reader's base state & reset top state to be reconstructed from base state + SReaderStatus* pStatus = &pReader->status; + STableBlockScanInfo* pBlockScanInfo = NULL; + + if (pStatus->loadFromFile) { + SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(&pReader->status.blockIter); + if (pBlockInfo != NULL) { + pBlockScanInfo = getTableBlockScanInfo(pStatus->pTableMap, pBlockInfo->uid, pReader->idStr); + if (pBlockScanInfo == NULL) { + goto _err; + } + } else { + pBlockScanInfo = *pStatus->pTableIter; + } + + tsdbDataFReaderClose(&pReader->pFileReader); + + // resetDataBlockScanInfo excluding lastKey + STableBlockScanInfo** p = NULL; + int32_t iter = 0; + + while ((p = tSimpleHashIterate(pStatus->pTableMap, p, &iter)) != NULL) { + STableBlockScanInfo* pInfo = *(STableBlockScanInfo**)p; + + pInfo->iterInit = false; + pInfo->iter.hasVal = false; + pInfo->iiter.hasVal = false; + + if (pInfo->iter.iter != NULL) { + pInfo->iter.iter = tsdbTbDataIterDestroy(pInfo->iter.iter); + } + + if (pInfo->iiter.iter != NULL) { + pInfo->iiter.iter = tsdbTbDataIterDestroy(pInfo->iiter.iter); + } + + pInfo->delSkyline = taosArrayDestroy(pInfo->delSkyline); + } + } else { + // resetDataBlockScanInfo excluding lastKey + STableBlockScanInfo** p = NULL; + int32_t iter = 0; + + while ((p = tSimpleHashIterate(pStatus->pTableMap, p, &iter)) != NULL) { + STableBlockScanInfo* pInfo = *(STableBlockScanInfo**)p; + + pInfo->iterInit = false; + pInfo->iter.hasVal = false; + pInfo->iiter.hasVal = false; + + if (pInfo->iter.iter != NULL) { + pInfo->iter.iter = tsdbTbDataIterDestroy(pInfo->iter.iter); + } + + if (pInfo->iiter.iter != NULL) { + pInfo->iiter.iter = tsdbTbDataIterDestroy(pInfo->iiter.iter); + } + + pInfo->delSkyline = taosArrayDestroy(pInfo->delSkyline); + } + + pBlockScanInfo = pStatus->pTableIter == NULL ? NULL : *pStatus->pTableIter; + if (pBlockScanInfo) { + // save lastKey to restore memory iterator + STimeWindow w = pReader->resBlockInfo.pResBlock->info.window; + pBlockScanInfo->lastKey = ASCENDING_TRAVERSE(pReader->order) ? w.ekey : w.skey; + + // reset current current table's data block scan info, + pBlockScanInfo->iterInit = false; + pBlockScanInfo->iter.hasVal = false; + pBlockScanInfo->iiter.hasVal = false; + if (pBlockScanInfo->iter.iter != NULL) { + pBlockScanInfo->iter.iter = tsdbTbDataIterDestroy(pBlockScanInfo->iter.iter); + } + + if (pBlockScanInfo->iiter.iter != NULL) { + pBlockScanInfo->iiter.iter = tsdbTbDataIterDestroy(pBlockScanInfo->iiter.iter); + } + + pBlockScanInfo->pBlockList = taosArrayDestroy(pBlockScanInfo->pBlockList); + tMapDataClear(&pBlockScanInfo->mapData); + // TODO: keep skyline for reuse + pBlockScanInfo->delSkyline = taosArrayDestroy(pBlockScanInfo->delSkyline); + } } - taosMemoryFreeClear(pReader); + tsdbUntakeReadSnap(pReader, pReader->pReadSnap, false); + pReader->pReadSnap = NULL; + pReader->flag = READER_STATUS_SUSPEND; + + tsdbDebug("reader: %p suspended uid %" PRIu64 " in this query %s", pReader, pBlockScanInfo ? pBlockScanInfo->uid : 0, + pReader->idStr); + return code; + +_err: + tsdbError("failed to suspend data reader, code:%s %s", tstrerror(code), pReader->idStr); + return code; +} + +static int32_t tsdbSetQueryReseek(void* pQHandle) { + int32_t code = 0; + STsdbReader* pReader = pQHandle; + + code = tsdbTryAcquireReader(pReader); + if (code == 0) { + if (pReader->flag == READER_STATUS_SUSPEND) { + tsdbReleaseReader(pReader); + return code; + } + + tsdbReaderSuspend(pReader); + + tsdbReleaseReader(pReader); + + return code; + } else if (code == EBUSY) { + return TSDB_CODE_VND_QUERY_BUSY; + } else { + terrno = TAOS_SYSTEM_ERROR(code); + return TSDB_CODE_FAILED; + } } -static bool doTsdbNextDataBlock(STsdbReader* pReader) { +int32_t tsdbReaderResume(STsdbReader* pReader) { + int32_t code = 0; + + STableBlockScanInfo** pBlockScanInfo = pReader->status.pTableIter; + + // restore reader's state + // task snapshot + int32_t numOfTables = tSimpleHashGetSize(pReader->status.pTableMap); + if (numOfTables > 0) { + qTrace("tsdb/reader: %p, take snapshot", pReader); + code = tsdbTakeReadSnap(pReader, tsdbSetQueryReseek, &pReader->pReadSnap); + if (code != TSDB_CODE_SUCCESS) { + goto _err; + } + + if (pReader->type == TIMEWINDOW_RANGE_CONTAINED) { + code = doOpenReaderImpl(pReader); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } else { + STsdbReader* pPrevReader = pReader->innerReader[0]; + STsdbReader* pNextReader = pReader->innerReader[1]; + + // we need only one row + pPrevReader->resBlockInfo.capacity = 1; + setSharedPtr(pPrevReader, pReader); + + pNextReader->resBlockInfo.capacity = 1; + setSharedPtr(pNextReader, pReader); + + code = doOpenReaderImpl(pPrevReader); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + } + + pReader->flag = READER_STATUS_NORMAL; + tsdbDebug("reader: %p resumed uid %" PRIu64 ", numOfTable:%" PRId32 ", in this query %s", pReader, + pBlockScanInfo ? (*pBlockScanInfo)->uid : 0, numOfTables, pReader->idStr); + return code; + +_err: + tsdbError("failed to resume data reader, code:%s %s", tstrerror(code), pReader->idStr); + return code; +} + +static bool tsdbReadRowsCountOnly(STsdbReader* pReader) { + int32_t code = TSDB_CODE_SUCCESS; + SSDataBlock* pBlock = pReader->resBlockInfo.pResBlock; + + if (pReader->status.loadFromFile == false) { + return false; + } + + code = readRowsCountFromFiles(pReader); + if (code != TSDB_CODE_SUCCESS) { + return false; + } + + code = readRowsCountFromMem(pReader); + if (code != TSDB_CODE_SUCCESS) { + return false; + } + + pBlock->info.rows = pReader->rowsNum; + pBlock->info.id.uid = 0; + pBlock->info.dataLoad = 0; + + pReader->rowsNum = 0; + + return pBlock->info.rows > 0; +} + +static int32_t doTsdbNextDataBlock(STsdbReader* pReader, bool* hasNext) { + int32_t code = TSDB_CODE_SUCCESS; + // cleanup the data that belongs to the previous data block - SSDataBlock* pBlock = pReader->pResBlock; + SSDataBlock* pBlock = pReader->resBlockInfo.pResBlock; blockDataCleanup(pBlock); + *hasNext = false; + SReaderStatus* pStatus = &pReader->status; - if (taosHashGetSize(pStatus->pTableMap) == 0) { - return false; + if (tSimpleHashGetSize(pStatus->pTableMap) == 0) { + return code; + } + + if (READ_MODE_COUNT_ONLY == pReader->readMode) { + return tsdbReadRowsCountOnly(pReader); } if (pStatus->loadFromFile) { - int32_t code = buildBlockFromFiles(pReader); + code = buildBlockFromFiles(pReader); if (code != TSDB_CODE_SUCCESS) { - return false; + return code; } - if (pBlock->info.rows > 0) { - return true; - } else { + if (pBlock->info.rows <= 0) { resetTableListIndex(&pReader->status); - buildBlockFromBufferSequentially(pReader); - return pBlock->info.rows > 0; + code = buildBlockFromBufferSequentially(pReader); } } else { // no data in files, let's try the buffer - buildBlockFromBufferSequentially(pReader); - return pBlock->info.rows > 0; + code = buildBlockFromBufferSequentially(pReader); } + + *hasNext = pBlock->info.rows > 0; + + return code; } -bool tsdbNextDataBlock(STsdbReader* pReader) { - if (isEmptyQueryTimeWindow(&pReader->window) || pReader->step == EXTERNAL_ROWS_NEXT) { - return false; +int32_t tsdbNextDataBlock(STsdbReader* pReader, bool* hasNext) { + int32_t code = TSDB_CODE_SUCCESS; + + *hasNext = false; + + if (isEmptyQueryTimeWindow(&pReader->window) || pReader->step == EXTERNAL_ROWS_NEXT || pReader->code != TSDB_CODE_SUCCESS) { + return (pReader->code != TSDB_CODE_SUCCESS)? pReader->code:code; + } + + SReaderStatus* pStatus = &pReader->status; + + code = tsdbAcquireReader(pReader); + qTrace("tsdb/read: %p, take read mutex, code: %d", pReader, code); + + if (pReader->flag == READER_STATUS_SUSPEND) { + code = tsdbReaderResume(pReader); + if (code != TSDB_CODE_SUCCESS) { + tsdbReleaseReader(pReader); + return code; + } } - if (pReader->step == 0 && pReader->innerReader[0] != NULL) { - bool ret = doTsdbNextDataBlock(pReader->innerReader[0]); + if (pReader->innerReader[0] != NULL && pReader->step == 0) { + code = doTsdbNextDataBlock(pReader->innerReader[0], hasNext); + if (code) { + tsdbReleaseReader(pReader); + return code; + } + pReader->step = EXTERNAL_ROWS_PREV; - if (ret) { - return ret; + if (*hasNext) { + pStatus = &pReader->innerReader[0]->status; + if (pStatus->composedDataBlock) { + qTrace("tsdb/read: %p, unlock read mutex", pReader); + tsdbReleaseReader(pReader); + } + + return code; } } if (pReader->step == EXTERNAL_ROWS_PREV) { // prepare for the main scan - int32_t code = doOpenReaderImpl(pReader); - resetAllDataBlockScanInfo(pReader->status.pTableMap, pReader->innerReader[0]->window.ekey); + code = doOpenReaderImpl(pReader); + int32_t step = 1; + resetAllDataBlockScanInfo(pReader->status.pTableMap, pReader->innerReader[0]->window.ekey, step); if (code != TSDB_CODE_SUCCESS) { return code; @@ -4098,27 +4921,52 @@ bool tsdbNextDataBlock(STsdbReader* pReader) { pReader->step = EXTERNAL_ROWS_MAIN; } - bool ret = doTsdbNextDataBlock(pReader); - if (ret) { - return ret; + code = doTsdbNextDataBlock(pReader, hasNext); + if (code != TSDB_CODE_SUCCESS) { + tsdbReleaseReader(pReader); + return code; + } + + if (*hasNext) { + if (pStatus->composedDataBlock) { + qTrace("tsdb/read: %p, unlock read mutex", pReader); + tsdbReleaseReader(pReader); + } + + return code; } if (pReader->step == EXTERNAL_ROWS_MAIN && pReader->innerReader[1] != NULL) { // prepare for the next row scan - int32_t code = doOpenReaderImpl(pReader->innerReader[1]); - resetAllDataBlockScanInfo(pReader->innerReader[1]->status.pTableMap, pReader->window.ekey); + int32_t step = -1; + code = doOpenReaderImpl(pReader->innerReader[1]); + resetAllDataBlockScanInfo(pReader->innerReader[1]->status.pTableMap, pReader->window.ekey, step); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + code = doTsdbNextDataBlock(pReader->innerReader[1], hasNext); if (code != TSDB_CODE_SUCCESS) { + tsdbReleaseReader(pReader); return code; } - ret = doTsdbNextDataBlock(pReader->innerReader[1]); pReader->step = EXTERNAL_ROWS_NEXT; - if (ret) { - return ret; + if (*hasNext) { + pStatus = &pReader->innerReader[1]->status; + if (pStatus->composedDataBlock) { + qTrace("tsdb/read: %p, unlock read mutex", pReader); + tsdbReleaseReader(pReader); + } + + return code; } } - return false; + qTrace("tsdb/read: %p, unlock read mutex", pReader); + tsdbReleaseReader(pReader); + + return code; } static void doFillNullColSMA(SBlockLoadSuppInfo* pSup, int32_t numOfRows, int32_t numOfCols, SColumnDataAgg* pTsAgg) { @@ -4126,6 +4974,7 @@ static void doFillNullColSMA(SBlockLoadSuppInfo* pSup, int32_t numOfRows, int32_ int32_t i = 0, j = 0; int32_t size = (int32_t)taosArrayGetSize(pSup->pColAgg); taosArrayInsert(pSup->pColAgg, 0, pTsAgg); + size++; while (j < numOfCols && i < size) { SColumnDataAgg* pAgg = taosArrayGet(pSup->pColAgg, i); @@ -4138,10 +4987,21 @@ static void doFillNullColSMA(SBlockLoadSuppInfo* pSup, int32_t numOfRows, int32_ if (pSup->colId[j] != PRIMARYKEY_TIMESTAMP_COL_ID) { SColumnDataAgg nullColAgg = {.colId = pSup->colId[j], .numOfNull = numOfRows}; taosArrayInsert(pSup->pColAgg, i, &nullColAgg); + i += 1; + size++; } j += 1; } } + + while (j < numOfCols) { + if (pSup->colId[j] != PRIMARYKEY_TIMESTAMP_COL_ID) { + SColumnDataAgg nullColAgg = {.colId = pSup->colId[j], .numOfNull = numOfRows}; + taosArrayInsert(pSup->pColAgg, i, &nullColAgg); + i += 1; + } + j++; + } } int32_t tsdbRetrieveDatablockSMA(STsdbReader* pReader, SSDataBlock* pDataBlock, bool* allHave) { @@ -4163,10 +5023,12 @@ int32_t tsdbRetrieveDatablockSMA(STsdbReader* pReader, SSDataBlock* pDataBlock, SFileDataBlockInfo* pFBlock = getCurrentBlockInfo(&pReader->status.blockIter); SBlockLoadSuppInfo* pSup = &pReader->suppInfo; - if (pReader->pResBlock->info.id.uid != pFBlock->uid) { + if (pReader->resBlockInfo.pResBlock->info.id.uid != pFBlock->uid) { return TSDB_CODE_SUCCESS; } + int64_t st = taosGetTimestampUs(); + SDataBlk* pBlock = getCurrentBlock(&pReader->status.blockIter); if (tDataBlkHasSma(pBlock)) { code = tsdbReadBlockSma(pReader->pFileReader, pBlock, pSup->pColAgg); @@ -4187,8 +5049,8 @@ int32_t tsdbRetrieveDatablockSMA(STsdbReader* pReader, SSDataBlock* pDataBlock, pTsAgg->numOfNull = 0; pTsAgg->colId = PRIMARYKEY_TIMESTAMP_COL_ID; - pTsAgg->min = pReader->pResBlock->info.window.skey; - pTsAgg->max = pReader->pResBlock->info.window.ekey; + pTsAgg->min = pReader->resBlockInfo.pResBlock->info.window.skey; + pTsAgg->max = pReader->resBlockInfo.pResBlock->info.window.ekey; // update the number of NULL data rows size_t numOfCols = pSup->numOfCols; @@ -4199,10 +5061,10 @@ int32_t tsdbRetrieveDatablockSMA(STsdbReader* pReader, SSDataBlock* pDataBlock, taosArrayEnsureCap(pSup->pColAgg, colsNum); } - SSDataBlock* pResBlock = pReader->pResBlock; + SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock; if (pResBlock->pBlockAgg == NULL) { size_t num = taosArrayGetSize(pResBlock->pDataBlock); - pResBlock->pBlockAgg = taosMemoryCalloc(num, sizeof(SColumnDataAgg)); + pResBlock->pBlockAgg = taosMemoryCalloc(num, POINTER_BYTES); } // do fill all null column value SMA info @@ -4219,8 +5081,8 @@ int32_t tsdbRetrieveDatablockSMA(STsdbReader* pReader, SSDataBlock* pDataBlock, } else if (pAgg->colId < pSup->colId[j]) { i += 1; } else if (pSup->colId[j] < pAgg->colId) { - // ASSERT(pSup->colId[j] == PRIMARYKEY_TIMESTAMP_COL_ID); - pResBlock->pBlockAgg[pSup->slotId[j]] = &pSup->tsColAgg; + pResBlock->pBlockAgg[pSup->slotId[j]] = NULL; + *allHave = false; j += 1; } } @@ -4228,57 +5090,95 @@ int32_t tsdbRetrieveDatablockSMA(STsdbReader* pReader, SSDataBlock* pDataBlock, *pBlockSMA = pResBlock->pBlockAgg; pReader->cost.smaDataLoad += 1; + double elapsedTime = (taosGetTimestampUs() - st) / 1000.0; + pReader->cost.smaLoadTime += elapsedTime; + tsdbDebug("vgId:%d, succeed to load block SMA for uid %" PRIu64 ", %s", 0, pFBlock->uid, pReader->idStr); return code; } -static SSDataBlock* doRetrieveDataBlock(STsdbReader* pReader) { - SReaderStatus* pStatus = &pReader->status; - - if (pStatus->composedDataBlock) { - return pReader->pResBlock; +STableBlockScanInfo* getTableBlockScanInfo(SSHashObj* pTableMap, uint64_t uid, const char* id) { + STableBlockScanInfo** p = tSimpleHashGet(pTableMap, &uid, sizeof(uid)); + if (p == NULL || *p == NULL) { + terrno = TSDB_CODE_INVALID_PARA; + int32_t size = tSimpleHashGetSize(pTableMap); + tsdbError("failed to locate the uid:%" PRIu64 " in query table uid list, total tables:%d, %s", uid, size, id); + return NULL; } + return *p; +} + +static SSDataBlock* doRetrieveDataBlock(STsdbReader* pReader) { + SReaderStatus* pStatus = &pReader->status; + int32_t code = TSDB_CODE_SUCCESS; SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(&pStatus->blockIter); - STableBlockScanInfo* pBlockScanInfo = - *(STableBlockScanInfo**)taosHashGet(pStatus->pTableMap, &pBlockInfo->uid, sizeof(pBlockInfo->uid)); + STableBlockScanInfo* pBlockScanInfo = getTableBlockScanInfo(pStatus->pTableMap, pBlockInfo->uid, pReader->idStr); if (pBlockScanInfo == NULL) { - terrno = TSDB_CODE_INVALID_PARA; - tsdbError("failed to locate the uid:%" PRIu64 " in query table uid list, total tables:%d, %s", pBlockInfo->uid, - taosHashGetSize(pReader->status.pTableMap), pReader->idStr); return NULL; } - int32_t code = doLoadFileBlockData(pReader, &pStatus->blockIter, &pStatus->fileBlockData, pBlockScanInfo->uid); + code = doLoadFileBlockData(pReader, &pStatus->blockIter, &pStatus->fileBlockData, pBlockScanInfo->uid); if (code != TSDB_CODE_SUCCESS) { - tBlockDataDestroy(&pStatus->fileBlockData, 1); + tBlockDataDestroy(&pStatus->fileBlockData); terrno = code; return NULL; } - copyBlockDataToSDataBlock(pReader); - return pReader->pResBlock; + code = copyBlockDataToSDataBlock(pReader); + if (code != TSDB_CODE_SUCCESS) { + tBlockDataDestroy(&pStatus->fileBlockData); + terrno = code; + return NULL; + } + + return pReader->resBlockInfo.pResBlock; } SSDataBlock* tsdbRetrieveDataBlock(STsdbReader* pReader, SArray* pIdList) { + STsdbReader* pTReader = pReader; if (pReader->type == TIMEWINDOW_RANGE_EXTERNAL) { if (pReader->step == EXTERNAL_ROWS_PREV) { - return doRetrieveDataBlock(pReader->innerReader[0]); + pTReader = pReader->innerReader[0]; } else if (pReader->step == EXTERNAL_ROWS_NEXT) { - return doRetrieveDataBlock(pReader->innerReader[1]); + pTReader = pReader->innerReader[1]; } } - return doRetrieveDataBlock(pReader); + SReaderStatus* pStatus = &pTReader->status; + if (pStatus->composedDataBlock) { + return pTReader->resBlockInfo.pResBlock; + } + + SSDataBlock* ret = doRetrieveDataBlock(pTReader); + + qTrace("tsdb/read-retrieve: %p, unlock read mutex", pReader); + tsdbReleaseReader(pReader); + + return ret; } int32_t tsdbReaderReset(STsdbReader* pReader, SQueryTableDataCond* pCond) { + int32_t code = TSDB_CODE_SUCCESS; + + qTrace("tsdb/reader-reset: %p, take read mutex", pReader); + tsdbAcquireReader(pReader); + + if (pReader->flag == READER_STATUS_SUSPEND) { + code = tsdbReaderResume(pReader); + if (code != TSDB_CODE_SUCCESS) { + tsdbReleaseReader(pReader); + return code; + } + } + if (isEmptyQueryTimeWindow(&pReader->window) || pReader->pReadSnap == NULL) { + tsdbDebug("tsdb reader reset return %p, %s", pReader->pReadSnap, pReader->idStr); + tsdbReleaseReader(pReader); return TSDB_CODE_SUCCESS; } - SReaderStatus* pStatus = &pReader->status; - + SReaderStatus* pStatus = &pReader->status; SDataBlockIter* pBlockIter = &pStatus->blockIter; pReader->order = pCond->order; @@ -4293,16 +5193,16 @@ int32_t tsdbReaderReset(STsdbReader* pReader, SQueryTableDataCond* pCond) { pReader->suppInfo.tsColAgg.colId = PRIMARYKEY_TIMESTAMP_COL_ID; tsdbDataFReaderClose(&pReader->pFileReader); - int32_t numOfTables = taosHashGetSize(pStatus->pTableMap); + int32_t numOfTables = tSimpleHashGetSize(pStatus->pTableMap); initFilesetIterator(&pStatus->fileIter, pReader->pReadSnap->fs.aDFileSet, pReader); resetDataBlockIterator(pBlockIter, pReader->order); resetTableListIndex(&pReader->status); - int64_t ts = ASCENDING_TRAVERSE(pReader->order) ? pReader->window.skey - 1 : pReader->window.ekey + 1; - resetAllDataBlockScanInfo(pStatus->pTableMap, ts); - - int32_t code = 0; + bool asc = ASCENDING_TRAVERSE(pReader->order); + int32_t step = asc ? 1 : -1; + int64_t ts = asc ? pReader->window.skey - 1 : pReader->window.ekey + 1; + resetAllDataBlockScanInfo(pStatus->pTableMap, ts, step); // no data in files, let's try buffer in memory if (pStatus->fileIter.numOfFiles == 0) { @@ -4313,6 +5213,8 @@ int32_t tsdbReaderReset(STsdbReader* pReader, SQueryTableDataCond* pCond) { if (code != TSDB_CODE_SUCCESS) { tsdbError("%p reset reader failed, numOfTables:%d, query range:%" PRId64 " - %" PRId64 " in query %s", pReader, numOfTables, pReader->window.skey, pReader->window.ekey, pReader->idStr); + + tsdbReleaseReader(pReader); return code; } } @@ -4322,30 +5224,47 @@ int32_t tsdbReaderReset(STsdbReader* pReader, SQueryTableDataCond* pCond) { pReader, pReader->suid, numOfTables, pCond->twindows.skey, pReader->window.skey, pReader->window.ekey, pReader->idStr); + tsdbReleaseReader(pReader); + return code; } -static int32_t getBucketIndex(int32_t startRow, int32_t bucketRange, int32_t numOfRows) { - return (numOfRows - startRow) / bucketRange; +static int32_t getBucketIndex(int32_t startRow, int32_t bucketRange, int32_t numOfRows, int32_t numOfBucket) { + int32_t bucketIndex = ((numOfRows - startRow) / bucketRange); + if (bucketIndex == numOfBucket) { + bucketIndex -= 1; + } + return bucketIndex; } int32_t tsdbGetFileBlocksDistInfo(STsdbReader* pReader, STableBlockDistInfo* pTableBlockInfo) { int32_t code = TSDB_CODE_SUCCESS; pTableBlockInfo->totalSize = 0; pTableBlockInfo->totalRows = 0; + pTableBlockInfo->numOfVgroups = 1; + + const int32_t numOfBuckets = 20.0; // find the start data block in file + tsdbAcquireReader(pReader); + if (pReader->flag == READER_STATUS_SUSPEND) { + code = tsdbReaderResume(pReader); + if (code != TSDB_CODE_SUCCESS) { + tsdbReleaseReader(pReader); + return code; + } + } SReaderStatus* pStatus = &pReader->status; STsdbCfg* pc = &pReader->pTsdb->pVnode->config.tsdbCfg; pTableBlockInfo->defMinRows = pc->minRows; pTableBlockInfo->defMaxRows = pc->maxRows; - int32_t bucketRange = ceil((pc->maxRows - pc->minRows) / 20.0); + int32_t bucketRange = ceil(((double)(pc->maxRows - pc->minRows)) / numOfBuckets); pTableBlockInfo->numOfFiles += 1; - int32_t numOfTables = (int32_t)taosHashGetSize(pStatus->pTableMap); + int32_t numOfTables = (int32_t)tSimpleHashGetSize(pStatus->pTableMap); int defaultRows = 4096; SDataBlockIter* pBlockIter = &pStatus->blockIter; @@ -4379,7 +5298,7 @@ int32_t tsdbGetFileBlocksDistInfo(STsdbReader* pReader, STableBlockDistInfo* pTa pTableBlockInfo->totalSize += pBlock->aSubBlock[0].szBlock; - int32_t bucketIndex = getBucketIndex(pTableBlockInfo->defMinRows, bucketRange, numOfRows); + int32_t bucketIndex = getBucketIndex(pTableBlockInfo->defMinRows, bucketRange, numOfRows, numOfBuckets); pTableBlockInfo->blockRowsHisto[bucketIndex]++; hasNext = blockIteratorNext(&pStatus->blockIter, pReader->idStr); @@ -4396,15 +5315,26 @@ int32_t tsdbGetFileBlocksDistInfo(STsdbReader* pReader, STableBlockDistInfo* pTa // tsdbDebug("%p %d blocks found in file for %d table(s), fid:%d, %s", pReader, numOfBlocks, numOfTables, // pReader->pFileGroup->fid, pReader->idStr); } - + tsdbReleaseReader(pReader); return code; } int64_t tsdbGetNumOfRowsInMemTable(STsdbReader* pReader) { + int32_t code = TSDB_CODE_SUCCESS; int64_t rows = 0; SReaderStatus* pStatus = &pReader->status; - pStatus->pTableIter = taosHashIterate(pStatus->pTableMap, NULL); + tsdbAcquireReader(pReader); + if (pReader->flag == READER_STATUS_SUSPEND) { + code = tsdbReaderResume(pReader); + if (code != TSDB_CODE_SUCCESS) { + tsdbReleaseReader(pReader); + return code; + } + } + + int32_t iter = 0; + pStatus->pTableIter = tSimpleHashIterate(pStatus->pTableMap, NULL, &iter); while (pStatus->pTableIter != NULL) { STableBlockScanInfo* pBlockScanInfo = *(STableBlockScanInfo**)pStatus->pTableIter; @@ -4426,15 +5356,15 @@ int64_t tsdbGetNumOfRowsInMemTable(STsdbReader* pReader) { } // current table is exhausted, let's try the next table - pStatus->pTableIter = taosHashIterate(pStatus->pTableMap, pStatus->pTableIter); + pStatus->pTableIter = tSimpleHashIterate(pStatus->pTableMap, pStatus->pTableIter, &iter); } + tsdbReleaseReader(pReader); + return rows; } int32_t tsdbGetTableSchema(SVnode* pVnode, int64_t uid, STSchema** pSchema, int64_t* suid) { - int32_t sversion = 1; - SMetaReader mr = {0}; metaReaderInit(&mr, pVnode->pMeta, 0); int32_t code = metaGetTableEntryByUidCache(&mr, uid); @@ -4446,6 +5376,7 @@ int32_t tsdbGetTableSchema(SVnode* pVnode, int64_t uid, STSchema** pSchema, int6 *suid = 0; + // only child table and ordinary table is allowed, super table is not allowed. if (mr.me.type == TSDB_CHILD_TABLE) { tDecoderClear(&mr.coder); *suid = mr.me.ctbEntry.suid; @@ -4455,9 +5386,7 @@ int32_t tsdbGetTableSchema(SVnode* pVnode, int64_t uid, STSchema** pSchema, int6 metaReaderClear(&mr); return terrno; } - sversion = mr.me.stbEntry.schemaRow.version; - } else if (mr.me.type == TSDB_NORMAL_TABLE) { - sversion = mr.me.ntbEntry.schemaRow.version; + } else if (mr.me.type == TSDB_NORMAL_TABLE) { // do nothing } else { terrno = TSDB_CODE_INVALID_PARA; metaReaderClear(&mr); @@ -4465,71 +5394,106 @@ int32_t tsdbGetTableSchema(SVnode* pVnode, int64_t uid, STSchema** pSchema, int6 } metaReaderClear(&mr); - *pSchema = metaGetTbTSchema(pVnode->pMeta, uid, sversion, 1); - return TSDB_CODE_SUCCESS; + // get the newest table schema version + code = metaGetTbTSchemaEx(pVnode->pMeta, *suid, uid, -1, pSchema); + return code; } -int32_t tsdbTakeReadSnap(STsdb* pTsdb, STsdbReadSnap** ppSnap, const char* idStr) { - int32_t code = 0; +int32_t tsdbTakeReadSnap(STsdbReader* pReader, _query_reseek_func_t reseek, STsdbReadSnap** ppSnap) { + int32_t code = 0; + STsdb* pTsdb = pReader->pTsdb; + SVersionRange* pRange = &pReader->verRange; // alloc - *ppSnap = (STsdbReadSnap*)taosMemoryCalloc(1, sizeof(STsdbReadSnap)); - if (*ppSnap == NULL) { + STsdbReadSnap* pSnap = (STsdbReadSnap*)taosMemoryCalloc(1, sizeof(*pSnap)); + if (pSnap == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; goto _exit; } // lock - code = taosThreadRwlockRdlock(&pTsdb->rwLock); - if (code) { - code = TAOS_SYSTEM_ERROR(code); - goto _exit; - } + taosThreadRwlockRdlock(&pTsdb->rwLock); // take snapshot - (*ppSnap)->pMem = pTsdb->mem; - (*ppSnap)->pIMem = pTsdb->imem; + if (pTsdb->mem && (pRange->minVer <= pTsdb->mem->maxVer && pRange->maxVer >= pTsdb->mem->minVer)) { + pSnap->pMem = pTsdb->mem; + pSnap->pNode = taosMemoryMalloc(sizeof(*pSnap->pNode)); + if (pSnap->pNode == NULL) { + taosThreadRwlockUnlock(&pTsdb->rwLock); + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + pSnap->pNode->pQHandle = pReader; + pSnap->pNode->reseek = reseek; - if ((*ppSnap)->pMem) { - tsdbRefMemTable((*ppSnap)->pMem); + tsdbRefMemTable(pTsdb->mem, pSnap->pNode); } - if ((*ppSnap)->pIMem) { - tsdbRefMemTable((*ppSnap)->pIMem); + if (pTsdb->imem && (pRange->minVer <= pTsdb->imem->maxVer && pRange->maxVer >= pTsdb->imem->minVer)) { + pSnap->pIMem = pTsdb->imem; + pSnap->pINode = taosMemoryMalloc(sizeof(*pSnap->pINode)); + if (pSnap->pINode == NULL) { + taosThreadRwlockUnlock(&pTsdb->rwLock); + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + pSnap->pINode->pQHandle = pReader; + pSnap->pINode->reseek = reseek; + + tsdbRefMemTable(pTsdb->imem, pSnap->pINode); } // fs - code = tsdbFSRef(pTsdb, &(*ppSnap)->fs); + code = tsdbFSRef(pTsdb, &pSnap->fs); if (code) { taosThreadRwlockUnlock(&pTsdb->rwLock); goto _exit; } // unlock - code = taosThreadRwlockUnlock(&pTsdb->rwLock); - if (code) { - code = TAOS_SYSTEM_ERROR(code); - goto _exit; - } + taosThreadRwlockUnlock(&pTsdb->rwLock); + + tsdbTrace("vgId:%d, take read snapshot", TD_VID(pTsdb->pVnode)); - tsdbTrace("vgId:%d, take read snapshot, %s", TD_VID(pTsdb->pVnode), idStr); _exit: + if (code) { + *ppSnap = NULL; + if (pSnap) { + if (pSnap->pNode) taosMemoryFree(pSnap->pNode); + if (pSnap->pINode) taosMemoryFree(pSnap->pINode); + taosMemoryFree(pSnap); + } + } else { + *ppSnap = pSnap; + } return code; } -void tsdbUntakeReadSnap(STsdb* pTsdb, STsdbReadSnap* pSnap, const char* idStr) { +void tsdbUntakeReadSnap(STsdbReader* pReader, STsdbReadSnap* pSnap, bool proactive) { + STsdb* pTsdb = pReader->pTsdb; + if (pSnap) { if (pSnap->pMem) { - tsdbUnrefMemTable(pSnap->pMem); + tsdbUnrefMemTable(pSnap->pMem, pSnap->pNode, proactive); } if (pSnap->pIMem) { - tsdbUnrefMemTable(pSnap->pIMem); + tsdbUnrefMemTable(pSnap->pIMem, pSnap->pINode, proactive); } tsdbFSUnref(pTsdb, &pSnap->fs); + if (pSnap->pNode) taosMemoryFree(pSnap->pNode); + if (pSnap->pINode) taosMemoryFree(pSnap->pINode); taosMemoryFree(pSnap); } - tsdbTrace("vgId:%d, untake read snapshot, %s", TD_VID(pTsdb->pVnode), idStr); + tsdbTrace("vgId:%d, untake read snapshot", TD_VID(pTsdb->pVnode)); } + +// if failed, do nothing +void tsdbReaderSetId(STsdbReader* pReader, const char* idstr) { + taosMemoryFreeClear(pReader->idStr); + pReader->idStr = taosStrdup(idstr); +} + +void tsdbReaderSetCloseFlag(STsdbReader* pReader) { pReader->code = TSDB_CODE_TSC_QUERY_CANCELLED; } diff --git a/source/dnode/vnode/src/tsdb/tsdbRetention.c b/source/dnode/vnode/src/tsdb/tsdbRetention.c index c6e1ed99f18a511cf60c12ec045044b4023354c5..7c7e1bd0f79254197e1c99dd5ca0544770656cea 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRetention.c +++ b/source/dnode/vnode/src/tsdb/tsdbRetention.c @@ -15,7 +15,7 @@ #include "tsdb.h" -static bool tsdbShouldDoRetention(STsdb *pTsdb, int64_t now) { +static bool tsdbShouldDoRetentionImpl(STsdb *pTsdb, int64_t now) { for (int32_t iSet = 0; iSet < taosArrayGetSize(pTsdb->fs.aDFileSet); iSet++) { SDFileSet *pSet = (SDFileSet *)taosArrayGet(pTsdb->fs.aDFileSet, iSet); int32_t expLevel = tsdbFidLevel(pSet->fid, &pTsdb->keepCfg, now); @@ -38,19 +38,21 @@ static bool tsdbShouldDoRetention(STsdb *pTsdb, int64_t now) { return false; } +bool tsdbShouldDoRetention(STsdb *pTsdb, int64_t now) { + bool should; + taosThreadRwlockRdlock(&pTsdb->rwLock); + should = tsdbShouldDoRetentionImpl(pTsdb, now); + taosThreadRwlockUnlock(&pTsdb->rwLock); + return should; +} int32_t tsdbDoRetention(STsdb *pTsdb, int64_t now) { int32_t code = 0; - - if (!tsdbShouldDoRetention(pTsdb, now)) { - return code; - } - - // do retention + int32_t lino = 0; STsdbFS fs = {0}; code = tsdbFSCopy(pTsdb, &fs); - if (code) goto _err; + TSDB_CHECK_CODE(code, lino, _exit); for (int32_t iSet = 0; iSet < taosArrayGetSize(fs.aDFileSet); iSet++) { SDFileSet *pSet = (SDFileSet *)taosArrayGet(fs.aDFileSet, iSet); @@ -60,8 +62,10 @@ int32_t tsdbDoRetention(STsdb *pTsdb, int64_t now) { if (expLevel < 0) { taosMemoryFree(pSet->pHeadF); taosMemoryFree(pSet->pDataF); - taosMemoryFree(pSet->aSttF[0]); taosMemoryFree(pSet->pSmaF); + for (int32_t iStt = 0; iStt < pSet->nSttF; iStt++) { + taosMemoryFree(pSet->aSttF[iStt]); + } taosArrayRemove(fs.aDFileSet, iSet); iSet--; } else { @@ -78,35 +82,33 @@ int32_t tsdbDoRetention(STsdb *pTsdb, int64_t now) { fSet.diskId = did; code = tsdbDFileSetCopy(pTsdb, pSet, &fSet); - if (code) goto _err; + TSDB_CHECK_CODE(code, lino, _exit); code = tsdbFSUpsertFSet(&fs, &fSet); - if (code) goto _err; + TSDB_CHECK_CODE(code, lino, _exit); } } // do change fs code = tsdbFSPrepareCommit(pTsdb, &fs); - if (code) goto _err; - - taosThreadRwlockWrlock(&pTsdb->rwLock); + TSDB_CHECK_CODE(code, lino, _exit); - code = tsdbFSCommit(pTsdb); +_exit: if (code) { - taosThreadRwlockUnlock(&pTsdb->rwLock); - goto _err; + tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code)); + } else { + tsdbInfo("vgId:%d %s done", TD_VID(pTsdb->pVnode), __func__); } - - taosThreadRwlockUnlock(&pTsdb->rwLock); - tsdbFSDestroy(&fs); - -_exit: return code; +} -_err: - tsdbError("vgId:%d, tsdb do retention failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code)); - ASSERT(0); - // tsdbFSRollback(pTsdb->pFS); - return code; +static int32_t tsdbCommitRetentionImpl(STsdb *pTsdb) { return tsdbFSCommit(pTsdb); } + +int32_t tsdbCommitRetention(STsdb *pTsdb) { + taosThreadRwlockWrlock(&pTsdb->rwLock); + tsdbCommitRetentionImpl(pTsdb); + taosThreadRwlockUnlock(&pTsdb->rwLock); + tsdbInfo("vgId:%d %s done", TD_VID(pTsdb->pVnode), __func__); + return 0; } \ No newline at end of file diff --git a/source/dnode/vnode/src/tsdb/tsdbSnapshot.c b/source/dnode/vnode/src/tsdb/tsdbSnapshot.c index e8181f922f0262a72f2f40bed319a17008738cbb..dfea125cc1026eefca2abdb7ed5bcbc9bd02fd1c 100644 --- a/source/dnode/vnode/src/tsdb/tsdbSnapshot.c +++ b/source/dnode/vnode/src/tsdb/tsdbSnapshot.c @@ -15,457 +15,10 @@ #include "tsdb.h" -extern int32_t tsdbReadDataBlockEx(SDataFReader* pReader, SDataBlk* pDataBlk, SBlockData* pBlockData); extern int32_t tsdbUpdateTableSchema(SMeta* pMeta, int64_t suid, int64_t uid, SSkmInfo* pSkmInfo); extern int32_t tsdbWriteDataBlock(SDataFWriter* pWriter, SBlockData* pBlockData, SMapData* mDataBlk, int8_t cmprAlg); extern int32_t tsdbWriteSttBlock(SDataFWriter* pWriter, SBlockData* pBlockData, SArray* aSttBlk, int8_t cmprAlg); -// STsdbDataIter2 ======================================== -#define TSDB_MEM_TABLE_DATA_ITER 0 -#define TSDB_DATA_FILE_DATA_ITER 1 -#define TSDB_STT_FILE_DATA_ITER 2 -#define TSDB_TOMB_FILE_DATA_ITER 3 - -typedef struct STsdbDataIter2 STsdbDataIter2; -typedef struct STsdbFilterInfo STsdbFilterInfo; - -typedef struct { - int64_t suid; - int64_t uid; - SDelData delData; -} SDelInfo; - -struct STsdbDataIter2 { - STsdbDataIter2* next; - SRBTreeNode rbtn; - - int32_t type; - SRowInfo rowInfo; - SDelInfo delInfo; - union { - // TSDB_MEM_TABLE_DATA_ITER - struct { - SMemTable* pMemTable; - } mIter; - - // TSDB_DATA_FILE_DATA_ITER - struct { - SDataFReader* pReader; - SArray* aBlockIdx; // SArray - SMapData mDataBlk; - SBlockData bData; - int32_t iBlockIdx; - int32_t iDataBlk; - int32_t iRow; - } dIter; - - // TSDB_STT_FILE_DATA_ITER - struct { - SDataFReader* pReader; - int32_t iStt; - SArray* aSttBlk; - SBlockData bData; - int32_t iSttBlk; - int32_t iRow; - } sIter; - // TSDB_TOMB_FILE_DATA_ITER - struct { - SDelFReader* pReader; - SArray* aDelIdx; - SArray* aDelData; - int32_t iDelIdx; - int32_t iDelData; - } tIter; - }; -}; - -#define TSDB_FILTER_FLAG_BY_VERSION 0x1 -struct STsdbFilterInfo { - int32_t flag; - int64_t sver; - int64_t ever; -}; - -#define TSDB_RBTN_TO_DATA_ITER(pNode) ((STsdbDataIter2*)(((char*)pNode) - offsetof(STsdbDataIter2, rbtn))) - -/* open */ -static int32_t tsdbOpenDataFileDataIter(SDataFReader* pReader, STsdbDataIter2** ppIter) { - int32_t code = 0; - int32_t lino = 0; - - // create handle - STsdbDataIter2* pIter = (STsdbDataIter2*)taosMemoryCalloc(1, sizeof(*pIter)); - if (pIter == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - TSDB_CHECK_CODE(code, lino, _exit); - } - - pIter->type = TSDB_DATA_FILE_DATA_ITER; - pIter->dIter.pReader = pReader; - if ((pIter->dIter.aBlockIdx = taosArrayInit(0, sizeof(SBlockIdx))) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - TSDB_CHECK_CODE(code, lino, _exit); - } - - code = tBlockDataCreate(&pIter->dIter.bData); - TSDB_CHECK_CODE(code, lino, _exit); - - pIter->dIter.iBlockIdx = 0; - pIter->dIter.iDataBlk = 0; - pIter->dIter.iRow = 0; - - // read data - code = tsdbReadBlockIdx(pReader, pIter->dIter.aBlockIdx); - TSDB_CHECK_CODE(code, lino, _exit); - - if (taosArrayGetSize(pIter->dIter.aBlockIdx) == 0) goto _clear; - -_exit: - if (code) { - if (pIter) { - _clear: - tBlockDataDestroy(&pIter->dIter.bData, 1); - taosArrayDestroy(pIter->dIter.aBlockIdx); - taosMemoryFree(pIter); - pIter = NULL; - } - } - *ppIter = pIter; - return code; -} - -static int32_t tsdbOpenSttFileDataIter(SDataFReader* pReader, int32_t iStt, STsdbDataIter2** ppIter) { - int32_t code = 0; - int32_t lino = 0; - - // create handle - STsdbDataIter2* pIter = (STsdbDataIter2*)taosMemoryCalloc(1, sizeof(*pIter)); - if (pIter == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - TSDB_CHECK_CODE(code, lino, _exit); - } - - pIter->type = TSDB_STT_FILE_DATA_ITER; - pIter->sIter.pReader = pReader; - pIter->sIter.iStt = iStt; - pIter->sIter.aSttBlk = taosArrayInit(0, sizeof(SSttBlk)); - if (pIter->sIter.aSttBlk == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - TSDB_CHECK_CODE(code, lino, _exit); - } - - code = tBlockDataCreate(&pIter->sIter.bData); - TSDB_CHECK_CODE(code, lino, _exit); - - pIter->sIter.iSttBlk = 0; - pIter->sIter.iRow = 0; - - // read data - code = tsdbReadSttBlk(pReader, iStt, pIter->sIter.aSttBlk); - TSDB_CHECK_CODE(code, lino, _exit); - - if (taosArrayGetSize(pIter->sIter.aSttBlk) == 0) goto _clear; - -_exit: - if (code) { - if (pIter) { - _clear: - taosArrayDestroy(pIter->sIter.aSttBlk); - tBlockDataDestroy(&pIter->sIter.bData, 1); - taosMemoryFree(pIter); - pIter = NULL; - } - } - *ppIter = pIter; - return code; -} - -static int32_t tsdbOpenTombFileDataIter(SDelFReader* pReader, STsdbDataIter2** ppIter) { - int32_t code = 0; - int32_t lino = 0; - - STsdbDataIter2* pIter = (STsdbDataIter2*)taosMemoryCalloc(1, sizeof(*pIter)); - if (pIter == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - TSDB_CHECK_CODE(code, lino, _exit); - } - pIter->type = TSDB_TOMB_FILE_DATA_ITER; - - pIter->tIter.pReader = pReader; - if ((pIter->tIter.aDelIdx = taosArrayInit(0, sizeof(SDelIdx))) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - TSDB_CHECK_CODE(code, lino, _exit); - } - if ((pIter->tIter.aDelData = taosArrayInit(0, sizeof(SDelData))) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - TSDB_CHECK_CODE(code, lino, _exit); - } - - code = tsdbReadDelIdx(pReader, pIter->tIter.aDelIdx); - TSDB_CHECK_CODE(code, lino, _exit); - - if (taosArrayGetSize(pIter->tIter.aDelIdx) == 0) goto _clear; - - pIter->tIter.iDelIdx = 0; - pIter->tIter.iDelData = 0; - -_exit: - if (code) { - if (pIter) { - _clear: - taosArrayDestroy(pIter->tIter.aDelIdx); - taosArrayDestroy(pIter->tIter.aDelData); - taosMemoryFree(pIter); - pIter = NULL; - } - } - *ppIter = pIter; - return code; -} - -/* close */ -static void tsdbCloseDataFileDataIter(STsdbDataIter2* pIter) { - tBlockDataDestroy(&pIter->dIter.bData, 1); - tMapDataClear(&pIter->dIter.mDataBlk); - taosArrayDestroy(pIter->dIter.aBlockIdx); - taosMemoryFree(pIter); -} - -static void tsdbCloseSttFileDataIter(STsdbDataIter2* pIter) { - tBlockDataDestroy(&pIter->sIter.bData, 1); - taosArrayDestroy(pIter->sIter.aSttBlk); - taosMemoryFree(pIter); -} - -static void tsdbCloseTombFileDataIter(STsdbDataIter2* pIter) { - taosArrayDestroy(pIter->tIter.aDelData); - taosArrayDestroy(pIter->tIter.aDelIdx); - taosMemoryFree(pIter); -} - -static void tsdbCloseDataIter2(STsdbDataIter2* pIter) { - if (pIter->type == TSDB_MEM_TABLE_DATA_ITER) { - ASSERT(0); - } else if (pIter->type == TSDB_DATA_FILE_DATA_ITER) { - tsdbCloseDataFileDataIter(pIter); - } else if (pIter->type == TSDB_STT_FILE_DATA_ITER) { - tsdbCloseSttFileDataIter(pIter); - } else if (pIter->type == TSDB_TOMB_FILE_DATA_ITER) { - tsdbCloseTombFileDataIter(pIter); - } else { - ASSERT(0); - } -} - -/* cmpr */ -static int32_t tsdbDataIterCmprFn(const SRBTreeNode* pNode1, const SRBTreeNode* pNode2) { - STsdbDataIter2* pIter1 = TSDB_RBTN_TO_DATA_ITER(pNode1); - STsdbDataIter2* pIter2 = TSDB_RBTN_TO_DATA_ITER(pNode2); - return tRowInfoCmprFn(&pIter1->rowInfo, &pIter2->rowInfo); -} - -/* seek */ - -/* iter next */ -static int32_t tsdbDataFileDataIterNext(STsdbDataIter2* pIter, STsdbFilterInfo* pFilterInfo) { - int32_t code = 0; - int32_t lino = 0; - - for (;;) { - while (pIter->dIter.iRow < pIter->dIter.bData.nRow) { - if (pFilterInfo) { - if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { - if (pIter->dIter.bData.aVersion[pIter->dIter.iRow] < pFilterInfo->sver || - pIter->dIter.bData.aVersion[pIter->dIter.iRow] > pFilterInfo->ever) { - pIter->dIter.iRow++; - continue; - } - } - } - - pIter->rowInfo.suid = pIter->dIter.bData.suid; - pIter->rowInfo.uid = pIter->dIter.bData.uid; - pIter->rowInfo.row = tsdbRowFromBlockData(&pIter->dIter.bData, pIter->dIter.iRow); - pIter->dIter.iRow++; - goto _exit; - } - - for (;;) { - while (pIter->dIter.iDataBlk < pIter->dIter.mDataBlk.nItem) { - SDataBlk dataBlk; - tMapDataGetItemByIdx(&pIter->dIter.mDataBlk, pIter->dIter.iDataBlk, &dataBlk, tGetDataBlk); - - // filter - if (pFilterInfo) { - if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { - if (pFilterInfo->sver > dataBlk.maxVer || pFilterInfo->ever < dataBlk.minVer) { - pIter->dIter.iDataBlk++; - continue; - } - } - } - - code = tsdbReadDataBlockEx(pIter->dIter.pReader, &dataBlk, &pIter->dIter.bData); - TSDB_CHECK_CODE(code, lino, _exit); - - pIter->dIter.iDataBlk++; - pIter->dIter.iRow = 0; - - break; - } - - if (pIter->dIter.iRow < pIter->dIter.bData.nRow) break; - - for (;;) { - if (pIter->dIter.iBlockIdx < taosArrayGetSize(pIter->dIter.aBlockIdx)) { - SBlockIdx* pBlockIdx = taosArrayGet(pIter->dIter.aBlockIdx, pIter->dIter.iBlockIdx); - - code = tsdbReadDataBlk(pIter->dIter.pReader, pBlockIdx, &pIter->dIter.mDataBlk); - TSDB_CHECK_CODE(code, lino, _exit); - - pIter->dIter.iBlockIdx++; - pIter->dIter.iDataBlk = 0; - - break; - } else { - pIter->rowInfo = (SRowInfo){0}; - goto _exit; - } - } - } - } - -_exit: - if (code) { - tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code)); - } - return code; -} - -static int32_t tsdbSttFileDataIterNext(STsdbDataIter2* pIter, STsdbFilterInfo* pFilterInfo) { - int32_t code = 0; - int32_t lino = 0; - - for (;;) { - while (pIter->sIter.iRow < pIter->sIter.bData.nRow) { - if (pFilterInfo) { - if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { - if (pFilterInfo->sver > pIter->sIter.bData.aVersion[pIter->sIter.iRow] || - pFilterInfo->ever < pIter->sIter.bData.aVersion[pIter->sIter.iRow]) { - pIter->sIter.iRow++; - continue; - } - } - } - - pIter->rowInfo.suid = pIter->sIter.bData.suid; - pIter->rowInfo.uid = pIter->sIter.bData.uid ? pIter->sIter.bData.uid : pIter->sIter.bData.aUid[pIter->sIter.iRow]; - pIter->rowInfo.row = tsdbRowFromBlockData(&pIter->sIter.bData, pIter->sIter.iRow); - pIter->sIter.iRow++; - goto _exit; - } - - for (;;) { - if (pIter->sIter.iSttBlk < taosArrayGetSize(pIter->sIter.aSttBlk)) { - SSttBlk* pSttBlk = taosArrayGet(pIter->sIter.aSttBlk, pIter->sIter.iSttBlk); - - if (pFilterInfo) { - if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { - if (pFilterInfo->sver > pSttBlk->maxVer || pFilterInfo->ever < pSttBlk->minVer) { - pIter->sIter.iSttBlk++; - continue; - } - } - } - - code = tsdbReadSttBlockEx(pIter->sIter.pReader, pIter->sIter.iStt, pSttBlk, &pIter->sIter.bData); - TSDB_CHECK_CODE(code, lino, _exit); - - pIter->sIter.iRow = 0; - pIter->sIter.iSttBlk++; - break; - } else { - pIter->rowInfo = (SRowInfo){0}; - goto _exit; - } - } - } - -_exit: - if (code) { - tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code)); - } - return code; -} - -static int32_t tsdbTombFileDataIterNext(STsdbDataIter2* pIter, STsdbFilterInfo* pFilterInfo) { - int32_t code = 0; - int32_t lino = 0; - - for (;;) { - while (pIter->tIter.iDelData < taosArrayGetSize(pIter->tIter.aDelData)) { - SDelData* pDelData = taosArrayGet(pIter->tIter.aDelData, pIter->tIter.iDelData); - - if (pFilterInfo) { - if (pFilterInfo->flag & TSDB_FILTER_FLAG_BY_VERSION) { - if (pFilterInfo->sver > pDelData->version || pFilterInfo->ever < pDelData->version) { - pIter->tIter.iDelData++; - continue; - } - } - } - - pIter->delInfo.delData = *pDelData; - pIter->tIter.iDelData++; - goto _exit; - } - - for (;;) { - if (pIter->tIter.iDelIdx < taosArrayGetSize(pIter->tIter.aDelIdx)) { - SDelIdx* pDelIdx = taosArrayGet(pIter->tIter.aDelIdx, pIter->tIter.iDelIdx); - - code = tsdbReadDelData(pIter->tIter.pReader, pDelIdx, pIter->tIter.aDelData); - TSDB_CHECK_CODE(code, lino, _exit); - - pIter->delInfo.suid = pDelIdx->suid; - pIter->delInfo.uid = pDelIdx->uid; - pIter->tIter.iDelData = 0; - pIter->tIter.iDelIdx++; - break; - } else { - pIter->delInfo = (SDelInfo){0}; - goto _exit; - } - } - } - -_exit: - if (code) { - tsdbError("%s failed at line %d since %s", __func__, lino, tstrerror(code)); - } - return code; -} - -static int32_t tsdbDataIterNext2(STsdbDataIter2* pIter, STsdbFilterInfo* pFilterInfo) { - int32_t code = 0; - - if (pIter->type == TSDB_MEM_TABLE_DATA_ITER) { - ASSERT(0); - return code; - } else if (pIter->type == TSDB_DATA_FILE_DATA_ITER) { - return tsdbDataFileDataIterNext(pIter, pFilterInfo); - } else if (pIter->type == TSDB_STT_FILE_DATA_ITER) { - return tsdbSttFileDataIterNext(pIter, pFilterInfo); - } else if (pIter->type == TSDB_TOMB_FILE_DATA_ITER) { - return tsdbTombFileDataIterNext(pIter, pFilterInfo); - } else { - ASSERT(0); - return code; - } -} - -/* get */ - // STsdbSnapReader ======================================== struct STsdbSnapReader { STsdb* pTsdb; @@ -517,10 +70,11 @@ static int32_t tsdbSnapReadFileDataStart(STsdbSnapReader* pReader) { if (pReader->pIter) { // iter to next with filter info (sver, ever) - code = tsdbDataIterNext2(pReader->pIter, - &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION, // flag - .sver = pReader->sver, - .ever = pReader->ever}); + code = tsdbDataIterNext2( + pReader->pIter, + &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION | TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE, // flag + .sver = pReader->sver, + .ever = pReader->ever}); TSDB_CHECK_CODE(code, lino, _exit); if (pReader->pIter->rowInfo.suid || pReader->pIter->rowInfo.uid) { @@ -541,10 +95,11 @@ static int32_t tsdbSnapReadFileDataStart(STsdbSnapReader* pReader) { if (pReader->pIter) { // iter to valid row - code = tsdbDataIterNext2(pReader->pIter, - &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION, // flag - .sver = pReader->sver, - .ever = pReader->ever}); + code = tsdbDataIterNext2( + pReader->pIter, + &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION | TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE, // flag + .sver = pReader->sver, + .ever = pReader->ever}); TSDB_CHECK_CODE(code, lino, _exit); if (pReader->pIter->rowInfo.suid || pReader->pIter->rowInfo.uid) { @@ -586,7 +141,8 @@ static int32_t tsdbSnapReadNextRow(STsdbSnapReader* pReader, SRowInfo** ppRowInf int32_t lino = 0; if (pReader->pIter) { - code = tsdbDataIterNext2(pReader->pIter, &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION, // flag + code = tsdbDataIterNext2(pReader->pIter, &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION | + TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE, // flag .sver = pReader->sver, .ever = pReader->ever}); TSDB_CHECK_CODE(code, lino, _exit); @@ -645,7 +201,7 @@ static int32_t tsdbSnapCmprData(STsdbSnapReader* pReader, uint8_t** ppData) { ASSERT(pReader->bData.nRow); int32_t aBufN[5] = {0}; - code = tCmprBlockData(&pReader->bData, TWO_STAGE_COMP, NULL, NULL, pReader->aBuf, aBufN); + code = tCmprBlockData(&pReader->bData, NO_COMPRESSION, NULL, NULL, pReader->aBuf, aBufN); if (code) goto _exit; int32_t size = aBufN[0] + aBufN[1] + aBufN[2] + aBufN[3]; @@ -656,7 +212,7 @@ static int32_t tsdbSnapCmprData(STsdbSnapReader* pReader, uint8_t** ppData) { } SSnapDataHdr* pHdr = (SSnapDataHdr*)*ppData; - pHdr->type = SNAP_DATA_TSDB; + pHdr->type = pReader->type; pHdr->size = size; memcpy(pHdr->data, pReader->aBuf[3], aBufN[3]); @@ -723,7 +279,7 @@ static int32_t tsdbSnapReadTimeSeriesData(STsdbSnapReader* pReader, uint8_t** pp code = tsdbSnapReadNextRow(pReader, &pRowInfo); TSDB_CHECK_CODE(code, lino, _exit); - if (pReader->bData.nRow >= 4096) break; + if (pReader->bData.nRow >= 81920) break; } while (pRowInfo); ASSERT(pReader->bData.nRow > 0); @@ -732,6 +288,8 @@ static int32_t tsdbSnapReadTimeSeriesData(STsdbSnapReader* pReader, uint8_t** pp } if (pReader->bData.nRow > 0) { + ASSERT(pReader->bData.suid || pReader->bData.uid); + code = tsdbSnapCmprData(pReader, ppData); TSDB_CHECK_CODE(code, lino, _exit); } @@ -773,10 +331,6 @@ static int32_t tsdbSnapCmprTombData(STsdbSnapReader* pReader, uint8_t** ppData) _exit: if (code) { tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pReader->pTsdb->pVnode), __func__, lino, tstrerror(code)); - if (pData) { - taosMemoryFree(pData); - pData = NULL; - } } *ppData = pData; return code; @@ -795,8 +349,9 @@ static int32_t tsdbSnapReadNextTombData(STsdbSnapReader* pReader, SDelInfo** ppD int32_t lino = 0; code = tsdbDataIterNext2( - pReader->pTIter, - &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION, .sver = pReader->sver, .ever = pReader->ever}); + pReader->pTIter, &(STsdbFilterInfo){.flag = TSDB_FILTER_FLAG_BY_VERSION | TSDB_FILTER_FLAG_IGNORE_DROPPED_TABLE, + .sver = pReader->sver, + .ever = pReader->ever}); TSDB_CHECK_CODE(code, lino, _exit); if (ppDelInfo) { @@ -849,7 +404,7 @@ static int32_t tsdbSnapReadTombData(STsdbSnapReader* pReader, uint8_t** ppData) } while (pDelInfo && pDelInfo->suid == pReader->tbid.suid && pDelInfo->uid == pReader->tbid.uid) { - if (taosArrayPush(pReader->aDelData, &pDelInfo->delData) < 0) { + if (taosArrayPush(pReader->aDelData, &pDelInfo->delData) == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; TSDB_CHECK_CODE(code, lino, _exit); } @@ -907,7 +462,7 @@ _exit: tsdbError("vgId:%d %s failed at line %d since %s, sver:%" PRId64 " ever:%" PRId64 " type:%d", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code), sver, ever, type); if (pReader) { - tBlockDataDestroy(&pReader->bData, 1); + tBlockDataDestroy(&pReader->bData); tsdbFSUnref(pTsdb, &pReader->fs); taosMemoryFree(pReader); pReader = NULL; @@ -946,7 +501,7 @@ int32_t tsdbSnapReaderClose(STsdbSnapReader** ppReader) { if (pReader->pDataFReader) { tsdbDataFReaderClose(&pReader->pDataFReader); } - tBlockDataDestroy(&pReader->bData, 1); + tBlockDataDestroy(&pReader->bData); // other tDestroyTSchema(pReader->skmTable.pTSchema); @@ -1316,7 +871,7 @@ static int32_t tsdbSnapWriteFileDataStart(STsdbSnapWriter* pWriter, int32_t fid) TSDB_CHECK_CODE(code, lino, _exit); if (pWriter->pSIter) { - code = tsdbSttFileDataIterNext(pWriter->pSIter, NULL); + code = tsdbDataIterNext2(pWriter->pSIter, NULL); TSDB_CHECK_CODE(code, lino, _exit); // add to tree @@ -1697,7 +1252,7 @@ static int32_t tsdbSnapWriteDelTableData(STsdbSnapWriter* pWriter, TABLEID* pId, SDelData delData; n += tGetDelData(pData + n, &delData); - if (taosArrayPush(pWriter->aDelData, &delData) < 0) { + if (taosArrayPush(pWriter->aDelData, &delData) == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; TSDB_CHECK_CODE(code, lino, _exit); } @@ -1861,10 +1416,11 @@ _exit: if (code) { tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code)); if (pWriter) { - tBlockDataDestroy(&pWriter->sData, 1); - tBlockDataDestroy(&pWriter->bData, 1); - tBlockDataDestroy(&pWriter->inData, 1); + tBlockDataDestroy(&pWriter->sData); + tBlockDataDestroy(&pWriter->bData); + tBlockDataDestroy(&pWriter->inData); tsdbFSDestroy(&pWriter->fs); + taosMemoryFree(pWriter); pWriter = NULL; } } else { @@ -1928,13 +1484,13 @@ int32_t tsdbSnapWriterClose(STsdbSnapWriter** ppWriter, int8_t rollback) { taosArrayDestroy(pWriter->aDelIdx); // SNAP_DATA_TSDB - tBlockDataDestroy(&pWriter->sData, 1); - tBlockDataDestroy(&pWriter->bData, 1); + tBlockDataDestroy(&pWriter->sData); + tBlockDataDestroy(&pWriter->bData); taosArrayDestroy(pWriter->aSttBlk); tMapDataClear(&pWriter->mDataBlk); taosArrayDestroy(pWriter->aBlockIdx); tDestroyTSchema(pWriter->skmTable.pTSchema); - tBlockDataDestroy(&pWriter->inData, 1); + tBlockDataDestroy(&pWriter->inData); for (int32_t iBuf = 0; iBuf < sizeof(pWriter->aBuf) / sizeof(uint8_t*); iBuf++) { tFree(pWriter->aBuf[iBuf]); diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c index 853f0bcc2129e1a3aad964f8436d8b46a8f7a9c7..556ec335266e1019470555a0655ce6d6977a7253 100644 --- a/source/dnode/vnode/src/tsdb/tsdbUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c @@ -23,7 +23,7 @@ void tMapDataReset(SMapData *pMapData) { } void tMapDataClear(SMapData *pMapData) { - tFree((uint8_t *)pMapData->aOffset); + tFree(pMapData->aOffset); tFree(pMapData->pData); pMapData->pData = NULL; pMapData->aOffset = NULL; @@ -116,12 +116,7 @@ int32_t tMapDataToArray(SMapData *pMapData, int32_t itemSize, int32_t (*tGetItem } _exit: - if (code) { - *ppArray = NULL; - if (pArray) taosArrayDestroy(pArray); - } else { - *ppArray = pArray; - } + *ppArray = pArray; return code; } @@ -572,9 +567,9 @@ void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal * ASSERT(iCol > 0); - if (pRow->type == 0) { - tTSRowGetVal(pRow->pTSRow, pTSchema, iCol, pColVal); - } else if (pRow->type == 1) { + if (pRow->type == TSDBROW_ROW_FMT) { + tRowGet(pRow->pTSRow, pTSchema, iCol, pColVal); + } else if (pRow->type == TSDBROW_COL_FMT) { SColData *pColData; tBlockDataGetColData(pRow->pBlockData, pTColumn->colId, &pColData); @@ -589,263 +584,197 @@ void tsdbRowGetColVal(TSDBROW *pRow, STSchema *pTSchema, int32_t iCol, SColVal * } } -// int32_t tPutTSDBRow(uint8_t *p, TSDBROW *pRow) { -// int32_t n = 0; - -// n += tPutI64(p, pRow->version); -// if (p) memcpy(p + n, pRow->pTSRow, pRow->pTSRow->len); -// n += pRow->pTSRow->len; - -// return n; -// } - int32_t tsdbRowCmprFn(const void *p1, const void *p2) { return tsdbKeyCmprFn(&TSDBROW_KEY((TSDBROW *)p1), &TSDBROW_KEY((TSDBROW *)p2)); } // STSDBRowIter ====================================================== -void tsdbRowIterInit(STSDBRowIter *pIter, TSDBROW *pRow, STSchema *pTSchema) { +int32_t tsdbRowIterOpen(STSDBRowIter *pIter, TSDBROW *pRow, STSchema *pTSchema) { + int32_t code = 0; + pIter->pRow = pRow; - if (pRow->type == 0) { - ASSERT(pTSchema); - pIter->pTSchema = pTSchema; - pIter->i = 1; - } else if (pRow->type == 1) { - pIter->pTSchema = NULL; - pIter->i = 0; + if (pRow->type == TSDBROW_ROW_FMT) { + code = tRowIterOpen(pRow->pTSRow, pTSchema, &pIter->pIter); + if (code) goto _exit; + } else if (pRow->type == TSDBROW_COL_FMT) { + pIter->iColData = 0; } else { ASSERT(0); } + +_exit: + return code; } -SColVal *tsdbRowIterNext(STSDBRowIter *pIter) { - if (pIter->pRow->type == 0) { - if (pIter->i < pIter->pTSchema->numOfCols) { - tTSRowGetVal(pIter->pRow->pTSRow, pIter->pTSchema, pIter->i, &pIter->colVal); - pIter->i++; +void tsdbRowClose(STSDBRowIter *pIter) { + if (pIter->pRow->type == TSDBROW_ROW_FMT) { + tRowIterClose(&pIter->pIter); + } +} - return &pIter->colVal; +SColVal *tsdbRowIterNext(STSDBRowIter *pIter) { + if (pIter->pRow->type == TSDBROW_ROW_FMT) { + return tRowIterNext(pIter->pIter); + } else if (pIter->pRow->type == TSDBROW_COL_FMT) { + if (pIter->iColData == 0) { + pIter->cv = COL_VAL_VALUE(PRIMARYKEY_TIMESTAMP_COL_ID, TSDB_DATA_TYPE_TIMESTAMP, + (SValue){.val = pIter->pRow->pBlockData->aTSKEY[pIter->pRow->iRow]}); + ++pIter->iColData; + return &pIter->cv; } - } else { - if (pIter->i < pIter->pRow->pBlockData->nColData) { - SColData *pColData = tBlockDataGetColDataByIdx(pIter->pRow->pBlockData, pIter->i); - tColDataGetValue(pColData, pIter->pRow->iRow, &pIter->colVal); - pIter->i++; - - return &pIter->colVal; + if (pIter->iColData < pIter->pRow->pBlockData->nColData) { + tColDataGetValue(&pIter->pRow->pBlockData->aColData[pIter->iColData], pIter->pRow->iRow, &pIter->cv); + ++pIter->iColData; + return &pIter->cv; + } else { + return NULL; } + } else { + ASSERT(0); + return NULL; // suppress error report by compiler } - - return NULL; } // SRowMerger ====================================================== - -int32_t tRowMergerInit2(SRowMerger *pMerger, STSchema *pResTSchema, TSDBROW *pRow, STSchema *pTSchema) { +int32_t tsdbRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema) { int32_t code = 0; TSDBKEY key = TSDBROW_KEY(pRow); - SColVal *pColVal = &(SColVal){0}; + SColVal * pColVal = &(SColVal){0}; STColumn *pTColumn; - int32_t iCol, jCol = 0; - - pMerger->pTSchema = pResTSchema; - pMerger->version = key.version; + int32_t iCol, jCol = 1; - pMerger->pArray = taosArrayInit(pResTSchema->numOfCols, sizeof(SColVal)); - if (pMerger->pArray == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; + if (NULL == pTSchema) { + pTSchema = pMerger->pTSchema; } - // ts - pTColumn = &pTSchema->columns[jCol++]; + if (taosArrayGetSize(pMerger->pArray) == 0) { + // ts + jCol = 0; + pTColumn = &pTSchema->columns[jCol++]; - ASSERT(pTColumn->type == TSDB_DATA_TYPE_TIMESTAMP); - - *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.val = key.ts}); - if (taosArrayPush(pMerger->pArray, pColVal) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; - } - - // other - for (iCol = 1; jCol < pTSchema->numOfCols && iCol < pResTSchema->numOfCols; ++iCol) { - pTColumn = &pResTSchema->columns[iCol]; - if (pTSchema->columns[jCol].colId < pTColumn->colId) { - ++jCol; - --iCol; - continue; - } else if (pTSchema->columns[jCol].colId > pTColumn->colId) { - taosArrayPush(pMerger->pArray, &COL_VAL_NONE(pTColumn->colId, pTColumn->type)); - continue; - } - - tsdbRowGetColVal(pRow, pTSchema, jCol++, pColVal); - if ((!COL_VAL_IS_NONE(pColVal)) && (!COL_VAL_IS_NULL(pColVal)) && IS_VAR_DATA_TYPE(pColVal->type)) { - uint8_t *pVal = pColVal->value.pData; - - pColVal->value.pData = NULL; - code = tRealloc(&pColVal->value.pData, pColVal->value.nData); - if (code) goto _exit; - - if (pColVal->value.nData) { - memcpy(pColVal->value.pData, pVal, pColVal->value.nData); - } - } + ASSERT(pTColumn->type == TSDB_DATA_TYPE_TIMESTAMP); + *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.val = key.ts}); if (taosArrayPush(pMerger->pArray, pColVal) == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; + return code; + // goto _exit; } - } - for (; iCol < pResTSchema->numOfCols; ++iCol) { - pTColumn = &pResTSchema->columns[iCol]; - taosArrayPush(pMerger->pArray, &COL_VAL_NONE(pTColumn->colId, pTColumn->type)); - } + // other + for (iCol = 1; jCol < pTSchema->numOfCols && iCol < pMerger->pTSchema->numOfCols; ++iCol) { + pTColumn = &pMerger->pTSchema->columns[iCol]; + if (pTSchema->columns[jCol].colId < pTColumn->colId) { + ++jCol; + --iCol; + continue; + } else if (pTSchema->columns[jCol].colId > pTColumn->colId) { + taosArrayPush(pMerger->pArray, &COL_VAL_NONE(pTColumn->colId, pTColumn->type)); + continue; + } -_exit: - return code; -} + tsdbRowGetColVal(pRow, pTSchema, jCol++, pColVal); + if ((!COL_VAL_IS_NONE(pColVal)) && (!COL_VAL_IS_NULL(pColVal)) && IS_VAR_DATA_TYPE(pColVal->type)) { + uint8_t *pVal = pColVal->value.pData; -int32_t tRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema) { - int32_t code = 0; - TSDBKEY key = TSDBROW_KEY(pRow); - SColVal *pColVal = &(SColVal){0}; - STColumn *pTColumn; - int32_t iCol, jCol = 1; + pColVal->value.pData = NULL; + code = tRealloc(&pColVal->value.pData, pColVal->value.nData); + if (code) { + return TSDB_CODE_OUT_OF_MEMORY; + } - ASSERT(((SColVal *)pMerger->pArray->pData)->value.val == key.ts); + if (pColVal->value.nData) { + memcpy(pColVal->value.pData, pVal, pColVal->value.nData); + } + } - for (iCol = 1; iCol < pMerger->pTSchema->numOfCols && jCol < pTSchema->numOfCols; ++iCol) { - pTColumn = &pMerger->pTSchema->columns[iCol]; - if (pTSchema->columns[jCol].colId < pTColumn->colId) { - ++jCol; - --iCol; - continue; - } else if (pTSchema->columns[jCol].colId > pTColumn->colId) { - continue; + if (taosArrayPush(pMerger->pArray, pColVal) == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + return code; + } } - tsdbRowGetColVal(pRow, pTSchema, jCol++, pColVal); + for (; iCol < pMerger->pTSchema->numOfCols; ++iCol) { + pTColumn = &pMerger->pTSchema->columns[iCol]; + taosArrayPush(pMerger->pArray, &COL_VAL_NONE(pTColumn->colId, pTColumn->type)); + } - if (key.version > pMerger->version) { -#if 0 - if (!COL_VAL_IS_NONE(pColVal)) { - if ((!COL_VAL_IS_NULL(pColVal)) && IS_VAR_DATA_TYPE(pColVal->type)) { - SColVal *tColVal = taosArrayGet(pMerger->pArray, iCol); - code = tRealloc(&tColVal->value.pData, pColVal->value.nData); - if (code) return code; + pMerger->version = key.version; + return 0; + } else { + ASSERT(((SColVal *)pMerger->pArray->pData)->value.val == key.ts); + + for (iCol = 1; iCol < pMerger->pTSchema->numOfCols && jCol < pTSchema->numOfCols; ++iCol) { + pTColumn = &pMerger->pTSchema->columns[iCol]; + if (pTSchema->columns[jCol].colId < pTColumn->colId) { + ++jCol; + --iCol; + continue; + } else if (pTSchema->columns[jCol].colId > pTColumn->colId) { + continue; + } - tColVal->value.nData = pColVal->value.nData; - if (pColVal->value.nData) { - memcpy(tColVal->value.pData, pColVal->value.pData, pColVal->value.nData); + tsdbRowGetColVal(pRow, pTSchema, jCol++, pColVal); + + if (key.version > pMerger->version) { + if (!COL_VAL_IS_NONE(pColVal)) { + if (IS_VAR_DATA_TYPE(pColVal->type)) { + SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol); + if (!COL_VAL_IS_NULL(pColVal)) { + code = tRealloc(&pTColVal->value.pData, pColVal->value.nData); + if (code) return code; + + pTColVal->value.nData = pColVal->value.nData; + if (pTColVal->value.nData) { + memcpy(pTColVal->value.pData, pColVal->value.pData, pTColVal->value.nData); + } + pTColVal->flag = 0; + } else { + tFree(pTColVal->value.pData); + taosArraySet(pMerger->pArray, iCol, pColVal); + } + } else { + taosArraySet(pMerger->pArray, iCol, pColVal); } - tColVal->flag = 0; - } else { - taosArraySet(pMerger->pArray, iCol, pColVal); } - } -#endif - if (!COL_VAL_IS_NONE(pColVal)) { - if (IS_VAR_DATA_TYPE(pColVal->type)) { - SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol); - if (!COL_VAL_IS_NULL(pColVal)) { - code = tRealloc(&pTColVal->value.pData, pColVal->value.nData); + } else if (key.version < pMerger->version) { + SColVal *tColVal = (SColVal *)taosArrayGet(pMerger->pArray, iCol); + if (COL_VAL_IS_NONE(tColVal) && !COL_VAL_IS_NONE(pColVal)) { + if ((!COL_VAL_IS_NULL(pColVal)) && IS_VAR_DATA_TYPE(pColVal->type)) { + code = tRealloc(&tColVal->value.pData, pColVal->value.nData); if (code) return code; - pTColVal->value.nData = pColVal->value.nData; - if (pTColVal->value.nData) { - memcpy(pTColVal->value.pData, pColVal->value.pData, pTColVal->value.nData); + tColVal->value.nData = pColVal->value.nData; + if (pColVal->value.nData) { + memcpy(tColVal->value.pData, pColVal->value.pData, pColVal->value.nData); } - pTColVal->flag = 0; + tColVal->flag = 0; } else { - tFree(pTColVal->value.pData); - pTColVal->value.pData = NULL; taosArraySet(pMerger->pArray, iCol, pColVal); } - } else { - taosArraySet(pMerger->pArray, iCol, pColVal); - } - } - } else if (key.version < pMerger->version) { - SColVal *tColVal = (SColVal *)taosArrayGet(pMerger->pArray, iCol); - if (COL_VAL_IS_NONE(tColVal) && !COL_VAL_IS_NONE(pColVal)) { - if ((!COL_VAL_IS_NULL(pColVal)) && IS_VAR_DATA_TYPE(pColVal->type)) { - code = tRealloc(&tColVal->value.pData, pColVal->value.nData); - if (code) return code; - - tColVal->value.nData = pColVal->value.nData; - if (pColVal->value.nData) { - memcpy(tColVal->value.pData, pColVal->value.pData, pColVal->value.nData); - } - tColVal->flag = 0; - } else { - taosArraySet(pMerger->pArray, iCol, pColVal); } + } else { + ASSERT(0 && "dup versions not allowed"); } - } else { - ASSERT(0 && "dup versions not allowed"); } - } - pMerger->version = key.version; - return code; + pMerger->version = key.version; + return code; + } } -int32_t tRowMergerInit(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema) { - int32_t code = 0; - TSDBKEY key = TSDBROW_KEY(pRow); - SColVal *pColVal = &(SColVal){0}; - STColumn *pTColumn; - - pMerger->pTSchema = pTSchema; - pMerger->version = key.version; - - pMerger->pArray = taosArrayInit(pTSchema->numOfCols, sizeof(SColVal)); +int32_t tsdbRowMergerInit(SRowMerger* pMerger, STSchema *pSchema) { + pMerger->pTSchema = pSchema; + pMerger->pArray = taosArrayInit(pSchema->numOfCols, sizeof(SColVal)); if (pMerger->pArray == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; - } - - // ts - pTColumn = &pTSchema->columns[0]; - - ASSERT(pTColumn->type == TSDB_DATA_TYPE_TIMESTAMP); - - *pColVal = COL_VAL_VALUE(pTColumn->colId, pTColumn->type, (SValue){.val = key.ts}); - if (taosArrayPush(pMerger->pArray, pColVal) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; - } - - // other - for (int16_t iCol = 1; iCol < pTSchema->numOfCols; iCol++) { - tsdbRowGetColVal(pRow, pTSchema, iCol, pColVal); - if ((!COL_VAL_IS_NONE(pColVal)) && (!COL_VAL_IS_NULL(pColVal)) && IS_VAR_DATA_TYPE(pColVal->type)) { - uint8_t *pVal = pColVal->value.pData; - - pColVal->value.pData = NULL; - code = tRealloc(&pColVal->value.pData, pColVal->value.nData); - if (code) goto _exit; - - if (pColVal->value.nData) { - memcpy(pColVal->value.pData, pVal, pColVal->value.nData); - } - } - - if (taosArrayPush(pMerger->pArray, pColVal) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; - } + return TSDB_CODE_OUT_OF_MEMORY; + } else { + return TSDB_CODE_SUCCESS; } - -_exit: - return code; } -void tRowMergerClear(SRowMerger *pMerger) { +void tsdbRowMergerClear(SRowMerger* pMerger) { for (int32_t iCol = 1; iCol < pMerger->pTSchema->numOfCols; iCol++) { SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol); if (IS_VAR_DATA_TYPE(pTColVal->type)) { @@ -853,80 +782,23 @@ void tRowMergerClear(SRowMerger *pMerger) { } } - taosArrayDestroy(pMerger->pArray); + taosArrayClear(pMerger->pArray); } -int32_t tRowMerge(SRowMerger *pMerger, TSDBROW *pRow) { - int32_t code = 0; - TSDBKEY key = TSDBROW_KEY(pRow); - SColVal *pColVal = &(SColVal){0}; - - ASSERT(((SColVal *)pMerger->pArray->pData)->value.val == key.ts); - - for (int32_t iCol = 1; iCol < pMerger->pTSchema->numOfCols; iCol++) { - tsdbRowGetColVal(pRow, pMerger->pTSchema, iCol, pColVal); - - if (key.version > pMerger->version) { - if (!COL_VAL_IS_NONE(pColVal)) { - if (IS_VAR_DATA_TYPE(pColVal->type)) { - SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol); - if (!COL_VAL_IS_NULL(pColVal)) { - code = tRealloc(&pTColVal->value.pData, pColVal->value.nData); - if (code) goto _exit; - - pTColVal->value.nData = pColVal->value.nData; - if (pTColVal->value.nData) { - memcpy(pTColVal->value.pData, pColVal->value.pData, pTColVal->value.nData); - } - pTColVal->flag = 0; - } else { - tFree(pTColVal->value.pData); - pTColVal->value.pData = NULL; - taosArraySet(pMerger->pArray, iCol, pColVal); - } - } else { - taosArraySet(pMerger->pArray, iCol, pColVal); - } - } - } else if (key.version < pMerger->version) { - SColVal *tColVal = (SColVal *)taosArrayGet(pMerger->pArray, iCol); - if (COL_VAL_IS_NONE(tColVal) && !COL_VAL_IS_NONE(pColVal)) { - if (IS_VAR_DATA_TYPE(pColVal->type)) { - if (!COL_VAL_IS_NULL(pColVal)) { - code = tRealloc(&tColVal->value.pData, pColVal->value.nData); - if (code) goto _exit; - - tColVal->value.nData = pColVal->value.nData; - if (tColVal->value.nData) { - memcpy(tColVal->value.pData, pColVal->value.pData, tColVal->value.nData); - } - tColVal->flag = 0; - } else { - tFree(tColVal->value.pData); - tColVal->value.pData = NULL; - taosArraySet(pMerger->pArray, iCol, pColVal); - } - } else { - taosArraySet(pMerger->pArray, iCol, pColVal); - } - } - } else { - ASSERT(0); +void tsdbRowMergerCleanup(SRowMerger* pMerger) { + int32_t numOfCols = taosArrayGetSize(pMerger->pArray); + for (int32_t iCol = 1; iCol < numOfCols; iCol++) { + SColVal *pTColVal = taosArrayGet(pMerger->pArray, iCol); + if (IS_VAR_DATA_TYPE(pTColVal->type)) { + tFree(pTColVal->value.pData); } } - pMerger->version = key.version; - -_exit: - return code; + taosArrayDestroy(pMerger->pArray); } -int32_t tRowMergerGetRow(SRowMerger *pMerger, STSRow **ppRow) { - int32_t code = 0; - - code = tdSTSRowNew(pMerger->pArray, pMerger->pTSchema, ppRow); - - return code; +int32_t tsdbRowMergerGetRow(SRowMerger *pMerger, SRow **ppRow) { + return tRowBuild(pMerger->pArray, pMerger->pTSchema, ppRow); } /* @@ -1058,14 +930,13 @@ static int32_t tsdbMergeSkyline(SArray *pSkyline1, SArray *pSkyline2, SArray *pS return code; } - int32_t tsdbBuildDeleteSkylineImpl(SArray *aSkyline, int32_t sidx, int32_t eidx, SArray *pSkyline) { int32_t code = 0; SDelData *pDelData; int32_t midx; taosArrayClear(pSkyline); - if (sidx == eidx) { + if (sidx == eidx) { TSDBKEY *pItem1 = taosArrayGet(aSkyline, sidx * 2); TSDBKEY *pItem2 = taosArrayGet(aSkyline, sidx * 2 + 1); taosArrayPush(pSkyline, &pItem1); @@ -1098,14 +969,14 @@ int32_t tsdbBuildDeleteSkylineImpl(SArray *aSkyline, int32_t sidx, int32_t eidx, return code; } - int32_t tsdbBuildDeleteSkyline(SArray *aDelData, int32_t sidx, int32_t eidx, SArray *aSkyline) { SDelData *pDelData; - int32_t code = 0; - int32_t dataNum = eidx - sidx + 1; - SArray *aTmpSkyline = taosArrayInit(dataNum * 2, sizeof(TSDBKEY)); - SArray *pSkyline = taosArrayInit(dataNum * 2, POINTER_BYTES); - + int32_t code = 0; + int32_t dataNum = eidx - sidx + 1; + SArray *aTmpSkyline = taosArrayInit(dataNum * 2, sizeof(TSDBKEY)); + SArray *pSkyline = taosArrayInit(dataNum * 2, POINTER_BYTES); + + taosArrayClear(aSkyline); for (int32_t i = sidx; i <= eidx; ++i) { pDelData = (SDelData *)taosArrayGet(aDelData, i); taosArrayPush(aTmpSkyline, &(TSDBKEY){.ts = pDelData->sKey, .version = pDelData->version}); @@ -1117,8 +988,8 @@ int32_t tsdbBuildDeleteSkyline(SArray *aDelData, int32_t sidx, int32_t eidx, SAr int32_t skylineNum = taosArrayGetSize(pSkyline); for (int32_t i = 0; i < skylineNum; ++i) { - TSDBKEY *p = taosArrayGetP(pSkyline, i); - taosArrayPush(aSkyline, p); + TSDBKEY *p = taosArrayGetP(pSkyline, i); + taosArrayPush(aSkyline, p); } _clear: @@ -1179,27 +1050,47 @@ int32_t tBlockDataCreate(SBlockData *pBlockData) { pBlockData->aVersion = NULL; pBlockData->aTSKEY = NULL; pBlockData->nColData = 0; - pBlockData->aColData = taosArrayInit(0, sizeof(SColData)); - if (pBlockData->aColData == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; - } - -_exit: + pBlockData->aColData = NULL; return code; } -void tBlockDataDestroy(SBlockData *pBlockData, int8_t deepClear) { - tFree((uint8_t *)pBlockData->aUid); - tFree((uint8_t *)pBlockData->aVersion); - tFree((uint8_t *)pBlockData->aTSKEY); - taosArrayDestroyEx(pBlockData->aColData, deepClear ? tColDataDestroy : NULL); - pBlockData->aUid = NULL; - pBlockData->aVersion = NULL; - pBlockData->aTSKEY = NULL; - pBlockData->aColData = NULL; +void tBlockDataDestroy(SBlockData *pBlockData) { + tFree(pBlockData->aUid); + tFree(pBlockData->aVersion); + tFree(pBlockData->aTSKEY); + + for (int32_t i = 0; i < pBlockData->nColData; i++) { + tColDataDestroy(&pBlockData->aColData[i]); + } + + if (pBlockData->aColData) { + taosMemoryFree(pBlockData->aColData); + pBlockData->aColData = NULL; + } } +static int32_t tBlockDataAdjustColData(SBlockData *pBlockData, int32_t nColData) { + int32_t code = 0; + + if (pBlockData->nColData > nColData) { + for (int32_t i = nColData; i < pBlockData->nColData; i++) { + tColDataDestroy(&pBlockData->aColData[i]); + } + } else if (pBlockData->nColData < nColData) { + SColData *aColData = taosMemoryRealloc(pBlockData->aColData, sizeof(SBlockData) * nColData); + if (aColData == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + pBlockData->aColData = aColData; + memset(&pBlockData->aColData[pBlockData->nColData], 0, sizeof(SBlockData) * (nColData - pBlockData->nColData)); + } + pBlockData->nColData = nColData; + +_exit: + return code; +} int32_t tBlockDataInit(SBlockData *pBlockData, TABLEID *pId, STSchema *pTSchema, int16_t *aCid, int32_t nCid) { int32_t code = 0; @@ -1209,37 +1100,43 @@ int32_t tBlockDataInit(SBlockData *pBlockData, TABLEID *pId, STSchema *pTSchema, pBlockData->uid = pId->uid; pBlockData->nRow = 0; - pBlockData->nColData = 0; if (aCid) { + code = tBlockDataAdjustColData(pBlockData, nCid); + if (code) goto _exit; + int32_t iColumn = 1; STColumn *pTColumn = &pTSchema->columns[iColumn]; for (int32_t iCid = 0; iCid < nCid; iCid++) { - while (pTColumn && pTColumn->colId < aCid[iCid]) { - iColumn++; - pTColumn = (iColumn < pTSchema->numOfCols) ? &pTSchema->columns[iColumn] : NULL; - } + // aCid array (from taos client catalog) contains columns that does not exist in the pTSchema. the pTSchema is newer if (pTColumn == NULL) { - break; - } else if (pTColumn->colId == aCid[iCid]) { - SColData *pColData; - code = tBlockDataAddColData(pBlockData, &pColData); - if (code) goto _exit; - tColDataInit(pColData, pTColumn->colId, pTColumn->type, (pTColumn->flags & COL_SMA_ON) ? 1 : 0); + continue; + } + while (pTColumn->colId < aCid[iCid]) { iColumn++; - pTColumn = (iColumn < pTSchema->numOfCols) ? &pTSchema->columns[iColumn] : NULL; + ASSERT(iColumn < pTSchema->numOfCols); + pTColumn = &pTSchema->columns[iColumn]; + } + + if (pTColumn->colId != aCid[iCid]) { + continue; } + + tColDataInit(&pBlockData->aColData[iCid], pTColumn->colId, pTColumn->type, + (pTColumn->flags & COL_SMA_ON) ? 1 : 0); + + iColumn++; + pTColumn = (iColumn < pTSchema->numOfCols) ? &pTSchema->columns[iColumn] : NULL; } } else { - for (int32_t iColumn = 1; iColumn < pTSchema->numOfCols; iColumn++) { - STColumn *pTColumn = &pTSchema->columns[iColumn]; - - SColData *pColData; - code = tBlockDataAddColData(pBlockData, &pColData); - if (code) goto _exit; + code = tBlockDataAdjustColData(pBlockData, pTSchema->numOfCols - 1); + if (code) goto _exit; - tColDataInit(pColData, pTColumn->colId, pTColumn->type, (pTColumn->flags & COL_SMA_ON) ? 1 : 0); + for (int32_t iColData = 0; iColData < pBlockData->nColData; iColData++) { + STColumn *pTColumn = &pTSchema->columns[iColData + 1]; + tColDataInit(&pBlockData->aColData[iColData], pTColumn->colId, pTColumn->type, + (pTColumn->flags & COL_SMA_ON) ? 1 : 0); } } @@ -1251,7 +1148,11 @@ void tBlockDataReset(SBlockData *pBlockData) { pBlockData->suid = 0; pBlockData->uid = 0; pBlockData->nRow = 0; + for (int32_t i = 0; i < pBlockData->nColData; i++) { + tColDataDestroy(&pBlockData->aColData[i]); + } pBlockData->nColData = 0; + taosMemoryFreeClear(pBlockData->aColData); } void tBlockDataClear(SBlockData *pBlockData) { @@ -1259,211 +1160,43 @@ void tBlockDataClear(SBlockData *pBlockData) { pBlockData->nRow = 0; for (int32_t iColData = 0; iColData < pBlockData->nColData; iColData++) { - SColData *pColData = tBlockDataGetColDataByIdx(pBlockData, iColData); - tColDataClear(pColData); + tColDataClear(tBlockDataGetColDataByIdx(pBlockData, iColData)); } } -int32_t tBlockDataAddColData(SBlockData *pBlockData, SColData **ppColData) { - int32_t code = 0; - SColData *pColData = NULL; - - if (pBlockData->nColData >= taosArrayGetSize(pBlockData->aColData)) { - if (taosArrayPush(pBlockData->aColData, &((SColData){0})) == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _err; - } - } - pColData = (SColData *)taosArrayGet(pBlockData->aColData, pBlockData->nColData); - - pBlockData->nColData++; - - *ppColData = pColData; - return code; - -_err: - *ppColData = NULL; - return code; -} - -static int32_t tBlockDataAppendBlockRow(SBlockData *pBlockData, SBlockData *pBlockDataFrom, int32_t iRow) { +/* flag > 0: forward update + * flag == 0: insert + * flag < 0: backward update + */ +static int32_t tBlockDataUpsertBlockRow(SBlockData *pBlockData, SBlockData *pBlockDataFrom, int32_t iRow, + int32_t flag) { int32_t code = 0; SColVal cv = {0}; int32_t iColDataFrom = 0; - SColData *pColDataFrom = - (iColDataFrom < pBlockDataFrom->nColData) ? &((SColData *)pBlockDataFrom->aColData->pData)[iColDataFrom] : NULL; + SColData *pColDataFrom = (iColDataFrom < pBlockDataFrom->nColData) ? &pBlockDataFrom->aColData[iColDataFrom] : NULL; for (int32_t iColDataTo = 0; iColDataTo < pBlockData->nColData; iColDataTo++) { - SColData *pColDataTo = &((SColData *)pBlockData->aColData->pData)[iColDataTo]; + SColData *pColDataTo = &pBlockData->aColData[iColDataTo]; while (pColDataFrom && pColDataFrom->cid < pColDataTo->cid) { - iColDataFrom++; - pColDataFrom = (iColDataFrom < pBlockDataFrom->nColData) - ? &((SColData *)pBlockDataFrom->aColData->pData)[iColDataFrom] - : NULL; + pColDataFrom = (++iColDataFrom < pBlockDataFrom->nColData) ? &pBlockDataFrom->aColData[iColDataFrom] : NULL; } if (pColDataFrom == NULL || pColDataFrom->cid > pColDataTo->cid) { - code = tColDataAppendValue(pColDataTo, &COL_VAL_NONE(pColDataTo->cid, pColDataTo->type)); - if (code) goto _exit; + cv = COL_VAL_NONE(pColDataTo->cid, pColDataTo->type); + if (flag == 0 && (code = tColDataAppendValue(pColDataTo, &cv))) goto _exit; } else { tColDataGetValue(pColDataFrom, iRow, &cv); - code = tColDataAppendValue(pColDataTo, &cv); - if (code) goto _exit; - - iColDataFrom++; - pColDataFrom = (iColDataFrom < pBlockDataFrom->nColData) - ? &((SColData *)pBlockDataFrom->aColData->pData)[iColDataFrom] - : NULL; - } - } - -_exit: - return code; -} - -static int32_t tBlockDataAppendTPRow(SBlockData *pBlockData, STSRow *pRow, STSchema *pTSchema) { - int32_t code = 0; - - int32_t iTColumn = 1; - STColumn *pTColumn = (iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; - void *pBitmap = pRow->statis ? tdGetBitmapAddrTp(pRow, pTSchema->flen) : NULL; - - for (int32_t iColData = 0; iColData < pBlockData->nColData; iColData++) { - SColData *pColData = &((SColData *)pBlockData->aColData->pData)[iColData]; - - while (pTColumn && pTColumn->colId < pColData->cid) { - iTColumn++; - pTColumn = (iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; - } - - if (pTColumn == NULL || pTColumn->colId > pColData->cid) { - code = tColDataAppendValue(pColData, &COL_VAL_NONE(pColData->cid, pColData->type)); - if (code) goto _exit; - } else { - ASSERT(pTColumn->type == pColData->type); - - SColVal cv = {.cid = pTColumn->colId, .type = pTColumn->type}; - - if (pRow->statis) { - TDRowValT vt = TD_VTYPE_MAX; - tdGetBitmapValTypeII(pBitmap, iTColumn - 1, &vt); - - if (vt == TD_VTYPE_NORM) { - cv.flag = CV_FLAG_VALUE; - - if (IS_VAR_DATA_TYPE(pTColumn->type)) { - void *pData = (char *)pRow + *(int32_t *)(pRow->data + pTColumn->offset); - cv.value.nData = varDataLen(pData); - cv.value.pData = varDataVal(pData); - } else { - memcpy(&cv.value.val, pRow->data + pTColumn->offset, pTColumn->bytes); - } - - code = tColDataAppendValue(pColData, &cv); - if (code) goto _exit; - } else if (vt == TD_VTYPE_NONE) { - code = tColDataAppendValue(pColData, &COL_VAL_NONE(pColData->cid, pColData->type)); - if (code) goto _exit; - } else if (vt == TD_VTYPE_NULL) { - code = tColDataAppendValue(pColData, &COL_VAL_NULL(pColData->cid, pColData->type)); - if (code) goto _exit; - } else { - ASSERT(0); - } + if (flag) { + code = tColDataUpdateValue(pColDataTo, &cv, flag > 0); } else { - cv.flag = CV_FLAG_VALUE; - - if (IS_VAR_DATA_TYPE(pTColumn->type)) { - void *pData = (char *)pRow + *(int32_t *)(pRow->data + pTColumn->offset); - cv.value.nData = varDataLen(pData); - cv.value.pData = varDataVal(pData); - } else { - memcpy(&cv.value.val, pRow->data + pTColumn->offset, pTColumn->bytes); - } - - code = tColDataAppendValue(pColData, &cv); - if (code) goto _exit; + code = tColDataAppendValue(pColDataTo, &cv); } - - iTColumn++; - pTColumn = (iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; - } - } - -_exit: - return code; -} - -static int32_t tBlockDataAppendKVRow(SBlockData *pBlockData, STSRow *pRow, STSchema *pTSchema) { - int32_t code = 0; - - col_id_t kvIter = 0; - col_id_t nKvCols = tdRowGetNCols(pRow) - 1; - void *pColIdx = TD_ROW_COL_IDX(pRow); - void *pBitmap = tdGetBitmapAddrKv(pRow, tdRowGetNCols(pRow)); - int32_t iTColumn = 1; - STColumn *pTColumn = (iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; - - for (int32_t iColData = 0; iColData < pBlockData->nColData; iColData++) { - SColData *pColData = &((SColData *)pBlockData->aColData->pData)[iColData]; - - while (pTColumn && pTColumn->colId < pColData->cid) { - iTColumn++; - pTColumn = (iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; - } - - if (pTColumn == NULL || pTColumn->colId > pColData->cid) { - code = tColDataAppendValue(pColData, &COL_VAL_NONE(pColData->cid, pColData->type)); if (code) goto _exit; - } else { - ASSERT(pTColumn->type == pColData->type); - - SColVal cv = {.cid = pTColumn->colId, .type = pTColumn->type}; - TDRowValT vt = TD_VTYPE_NONE; // default is NONE - SKvRowIdx *pKvIdx = NULL; - - while (kvIter < nKvCols) { - pKvIdx = (SKvRowIdx *)POINTER_SHIFT(pColIdx, kvIter * sizeof(SKvRowIdx)); - if (pKvIdx->colId == pTColumn->colId) { - tdGetBitmapValTypeII(pBitmap, kvIter, &vt); - ++kvIter; - break; - } else if (pKvIdx->colId > pTColumn->colId) { - vt = TD_VTYPE_NONE; - break; - } else { - ++kvIter; - } - } - - if (vt == TD_VTYPE_NORM) { - cv.flag = CV_FLAG_VALUE; - - void *pData = POINTER_SHIFT(pRow, pKvIdx->offset); - if (IS_VAR_DATA_TYPE(pTColumn->type)) { - cv.value.nData = varDataLen(pData); - cv.value.pData = varDataVal(pData); - } else { - memcpy(&cv.value.val, pData, pTColumn->bytes); - } - code = tColDataAppendValue(pColData, &cv); - if (code) goto _exit; - } else if (vt == TD_VTYPE_NONE) { - code = tColDataAppendValue(pColData, &COL_VAL_NONE(pColData->cid, pColData->type)); - if (code) goto _exit; - } else if (vt == TD_VTYPE_NULL) { - code = tColDataAppendValue(pColData, &COL_VAL_NULL(pColData->cid, pColData->type)); - if (code) goto _exit; - } else { - ASSERT(0); - } - - iTColumn++; - pTColumn = (iTColumn < pTSchema->numOfCols) ? &pTSchema->columns[iTColumn] : NULL; + pColDataFrom = (++iColDataFrom < pBlockDataFrom->nColData) ? &pBlockDataFrom->aColData[iColDataFrom] : NULL; } } @@ -1480,159 +1213,75 @@ int32_t tBlockDataAppendRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTS if (pBlockData->uid == 0) { ASSERT(uid); code = tRealloc((uint8_t **)&pBlockData->aUid, sizeof(int64_t) * (pBlockData->nRow + 1)); - if (code) goto _err; + if (code) goto _exit; pBlockData->aUid[pBlockData->nRow] = uid; } // version code = tRealloc((uint8_t **)&pBlockData->aVersion, sizeof(int64_t) * (pBlockData->nRow + 1)); - if (code) goto _err; + if (code) goto _exit; pBlockData->aVersion[pBlockData->nRow] = TSDBROW_VERSION(pRow); // timestamp code = tRealloc((uint8_t **)&pBlockData->aTSKEY, sizeof(TSKEY) * (pBlockData->nRow + 1)); - if (code) goto _err; + if (code) goto _exit; pBlockData->aTSKEY[pBlockData->nRow] = TSDBROW_TS(pRow); - SColVal cv = {0}; - if (pRow->type == 0) { - if (TD_IS_TP_ROW(pRow->pTSRow)) { - code = tBlockDataAppendTPRow(pBlockData, pRow->pTSRow, pTSchema); - if (code) goto _err; - } else if (TD_IS_KV_ROW(pRow->pTSRow)) { - code = tBlockDataAppendKVRow(pBlockData, pRow->pTSRow, pTSchema); - if (code) goto _err; - } else { - ASSERT(0); - } + if (pRow->type == TSDBROW_ROW_FMT) { + code = tRowUpsertColData(pRow->pTSRow, pTSchema, pBlockData->aColData, pBlockData->nColData, 0 /* append */); + if (code) goto _exit; + } else if (pRow->type == TSDBROW_COL_FMT) { + code = tBlockDataUpsertBlockRow(pBlockData, pRow->pBlockData, pRow->iRow, 0 /* append */); + if (code) goto _exit; } else { - code = tBlockDataAppendBlockRow(pBlockData, pRow->pBlockData, pRow->iRow); - if (code) goto _err; + ASSERT(0); } pBlockData->nRow++; - return code; - -_err: - return code; -} - -int32_t tBlockDataCorrectSchema(SBlockData *pBlockData, SBlockData *pBlockDataFrom) { - int32_t code = 0; - - int32_t iColData = 0; - for (int32_t iColDataFrom = 0; iColDataFrom < pBlockDataFrom->nColData; iColDataFrom++) { - SColData *pColDataFrom = tBlockDataGetColDataByIdx(pBlockDataFrom, iColDataFrom); - - while (true) { - SColData *pColData; - if (iColData < pBlockData->nColData) { - pColData = tBlockDataGetColDataByIdx(pBlockData, iColData); - } else { - pColData = NULL; - } - - if (pColData == NULL || pColData->cid > pColDataFrom->cid) { - code = tBlockDataAddColData(pBlockData, &pColData); - if (code) goto _exit; - - tColDataInit(pColData, pColDataFrom->cid, pColDataFrom->type, pColDataFrom->smaOn); - for (int32_t iRow = 0; iRow < pBlockData->nRow; iRow++) { - code = tColDataAppendValue(pColData, &COL_VAL_NONE(pColData->cid, pColData->type)); - if (code) goto _exit; - } - - iColData++; - break; - } else if (pColData->cid == pColDataFrom->cid) { - iColData++; - break; - } else { - iColData++; - } - } - } - _exit: return code; } - -int32_t tBlockDataMerge(SBlockData *pBlockData1, SBlockData *pBlockData2, SBlockData *pBlockData) { +static int32_t tBlockDataUpdateRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTSchema) { int32_t code = 0; - ASSERT(pBlockData->suid == pBlockData1->suid); - ASSERT(pBlockData->uid == pBlockData1->uid); - ASSERT(pBlockData1->nRow > 0); - ASSERT(pBlockData2->nRow > 0); - - tBlockDataClear(pBlockData); - - TSDBROW row1 = tsdbRowFromBlockData(pBlockData1, 0); - TSDBROW row2 = tsdbRowFromBlockData(pBlockData2, 0); - TSDBROW *pRow1 = &row1; - TSDBROW *pRow2 = &row2; - - while (pRow1 && pRow2) { - int32_t c = tsdbRowCmprFn(pRow1, pRow2); - - if (c < 0) { - code = tBlockDataAppendRow(pBlockData, pRow1, NULL, - pBlockData1->uid ? pBlockData1->uid : pBlockData1->aUid[pRow1->iRow]); - if (code) goto _exit; - - pRow1->iRow++; - if (pRow1->iRow < pBlockData1->nRow) { - *pRow1 = tsdbRowFromBlockData(pBlockData1, pRow1->iRow); - } else { - pRow1 = NULL; - } - } else if (c > 0) { - code = tBlockDataAppendRow(pBlockData, pRow2, NULL, - pBlockData2->uid ? pBlockData2->uid : pBlockData2->aUid[pRow2->iRow]); - if (code) goto _exit; - - pRow2->iRow++; - if (pRow2->iRow < pBlockData2->nRow) { - *pRow2 = tsdbRowFromBlockData(pBlockData2, pRow2->iRow); - } else { - pRow2 = NULL; - } - } else { - ASSERT(0); - } + // version + int64_t lversion = pBlockData->aVersion[pBlockData->nRow - 1]; + int64_t rversion = TSDBROW_VERSION(pRow); + ASSERT(lversion != rversion); + if (rversion > lversion) { + pBlockData->aVersion[pBlockData->nRow - 1] = rversion; } - while (pRow1) { - code = tBlockDataAppendRow(pBlockData, pRow1, NULL, - pBlockData1->uid ? pBlockData1->uid : pBlockData1->aUid[pRow1->iRow]); + // update other rows + if (pRow->type == TSDBROW_ROW_FMT) { + code = tRowUpsertColData(pRow->pTSRow, pTSchema, pBlockData->aColData, pBlockData->nColData, + (rversion > lversion) ? 1 : -1 /* update */); if (code) goto _exit; - - pRow1->iRow++; - if (pRow1->iRow < pBlockData1->nRow) { - *pRow1 = tsdbRowFromBlockData(pBlockData1, pRow1->iRow); - } else { - pRow1 = NULL; - } - } - - while (pRow2) { - code = tBlockDataAppendRow(pBlockData, pRow2, NULL, - pBlockData2->uid ? pBlockData2->uid : pBlockData2->aUid[pRow2->iRow]); + } else if (pRow->type == TSDBROW_COL_FMT) { + code = tBlockDataUpsertBlockRow(pBlockData, pRow->pBlockData, pRow->iRow, (rversion > lversion) ? 1 : -1); if (code) goto _exit; - - pRow2->iRow++; - if (pRow2->iRow < pBlockData2->nRow) { - *pRow2 = tsdbRowFromBlockData(pBlockData2, pRow2->iRow); - } else { - pRow2 = NULL; - } + } else { + ASSERT(0); } _exit: return code; } -SColData *tBlockDataGetColDataByIdx(SBlockData *pBlockData, int32_t idx) { - ASSERT(idx >= 0 && idx < pBlockData->nColData); - return (SColData *)taosArrayGet(pBlockData->aColData, idx); +int32_t tBlockDataTryUpsertRow(SBlockData *pBlockData, TSDBROW *pRow, int64_t uid) { + if (pBlockData->nRow == 0) { + return 1; + } else if (pBlockData->aTSKEY[pBlockData->nRow - 1] == TSDBROW_TS(pRow)) { + return pBlockData->nRow; + } else { + return pBlockData->nRow + 1; + } +} + +int32_t tBlockDataUpsertRow(SBlockData *pBlockData, TSDBROW *pRow, STSchema *pTSchema, int64_t uid) { + if (pBlockData->nRow > 0 && pBlockData->aTSKEY[pBlockData->nRow - 1] == TSDBROW_TS(pRow)) { + return tBlockDataUpdateRow(pBlockData, pRow, pTSchema); + } else { + return tBlockDataAppendRow(pBlockData, pRow, pTSchema, uid); + } } void tBlockDataGetColData(SBlockData *pBlockData, int16_t cid, SColData **ppColData) { @@ -1641,7 +1290,7 @@ void tBlockDataGetColData(SBlockData *pBlockData, int16_t cid, SColData **ppColD int32_t ridx = pBlockData->nColData - 1; while (lidx <= ridx) { - int32_t midx = (lidx + ridx) / 2; + int32_t midx = (lidx + ridx) >> 1; SColData *pColData = tBlockDataGetColDataByIdx(pBlockData, midx); int32_t c = (pColData->cid == cid) ? 0 : ((pColData->cid > cid) ? 1 : -1); @@ -1788,15 +1437,25 @@ int32_t tDecmprBlockData(uint8_t *pIn, int32_t szIn, SBlockData *pBlockData, uin // loop to decode each column data if (hdr.szBlkCol == 0) goto _exit; + int32_t nColData = 0; int32_t nt = 0; while (nt < hdr.szBlkCol) { SBlockCol blockCol = {0}; nt += tGetBlockCol(pIn + n + nt, &blockCol); - ASSERT(nt <= hdr.szBlkCol); + ++nColData; + } + ASSERT(nt == hdr.szBlkCol); - SColData *pColData; - code = tBlockDataAddColData(pBlockData, &pColData); - if (code) goto _exit; + code = tBlockDataAdjustColData(pBlockData, nColData); + if (code) goto _exit; + + nt = 0; + int32_t iColData = 0; + while (nt < hdr.szBlkCol) { + SBlockCol blockCol = {0}; + nt += tGetBlockCol(pIn + n + nt, &blockCol); + + SColData *pColData = &pBlockData->aColData[iColData++]; tColDataInit(pColData, blockCol.cid, blockCol.type, blockCol.smaOn); if (blockCol.flag == HAS_NULL) { diff --git a/source/dnode/vnode/src/tsdb/tsdbWrite.c b/source/dnode/vnode/src/tsdb/tsdbWrite.c index 49d5eaac43c6dbd2356bf95ca4cfb9c70cb350c7..2dbac956ed1aacb1e13fd5fdcedfd2ad644755ea 100644 --- a/source/dnode/vnode/src/tsdb/tsdbWrite.c +++ b/source/dnode/vnode/src/tsdb/tsdbWrite.c @@ -22,17 +22,20 @@ * us: 3600*1000000*8765*1000 // 1970 + 1000 years * ns: 3600*1000000000*8765*292 // 1970 + 292 years */ -static int64_t tsMaxKeyByPrecision[] = {31556995200000L, 31556995200000000L, 9214646400000000000L}; +int64_t tsMaxKeyByPrecision[] = {31556995200000L, 31556995200000000L, 9214646400000000000L}; // static int tsdbScanAndConvertSubmitMsg(STsdb *pTsdb, SSubmitReq *pMsg); -int tsdbInsertData(STsdb *pTsdb, int64_t version, SSubmitReq *pMsg, SSubmitRsp *pRsp) { - SSubmitMsgIter msgIter = {0}; - SSubmitBlk *pBlock = NULL; - int32_t affectedrows = 0; - int32_t numOfRows = 0; +int tsdbInsertData(STsdb *pTsdb, int64_t version, SSubmitReq2 *pMsg, SSubmitRsp2 *pRsp) { + int32_t arrSize = 0; + int32_t affectedrows = 0; + int32_t numOfRows = 0; - ASSERT(pTsdb->mem != NULL); + if (ASSERTS(pTsdb->mem != NULL, "vgId:%d, mem is NULL", TD_VID(pTsdb->pVnode))) { + return -1; + } + + arrSize = taosArrayGetSize(pMsg->aSubmitTbData); // scan and convert if (tsdbScanAndConvertSubmitMsg(pTsdb, pMsg) < 0) { @@ -43,18 +46,10 @@ int tsdbInsertData(STsdb *pTsdb, int64_t version, SSubmitReq *pMsg, SSubmitRsp * } // loop to insert - if (tInitSubmitMsgIter(pMsg, &msgIter) < 0) { - return -1; - } - while (true) { - SSubmitBlkRsp r = {0}; - tGetSubmitMsgNext(&msgIter, &pBlock); - if (pBlock == NULL) break; - if ((terrno = tsdbInsertTableData(pTsdb, version, &msgIter, pBlock, &r)) < 0) { + for (int32_t i = 0; i < arrSize; ++i) { + if ((terrno = tsdbInsertTableData(pTsdb, version, taosArrayGet(pMsg->aSubmitTbData, i), &affectedrows)) < 0) { return -1; } - - numOfRows += msgIter.numOfRows; } if (pRsp != NULL) { @@ -65,104 +60,51 @@ int tsdbInsertData(STsdb *pTsdb, int64_t version, SSubmitReq *pMsg, SSubmitRsp * return 0; } -#if 0 -static FORCE_INLINE int tsdbCheckRowRange(STsdb *pTsdb, STable *pTable, STSRow *row, TSKEY minKey, TSKEY maxKey, - TSKEY now) { - TSKEY rowKey = TD_ROW_KEY(row); - if (rowKey < minKey || rowKey > maxKey) { - tsdbError("vgId:%d, table %s tid %d uid %" PRIu64 " timestamp is out of range! now %" PRId64 " minKey %" PRId64 - " maxKey %" PRId64 " row key %" PRId64, - REPO_ID(pTsdb), TABLE_CHAR_NAME(pTable), TABLE_TID(pTable), TABLE_UID(pTable), now, minKey, maxKey, - rowKey); - terrno = TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE; - return -1; - } - - return 0; -} -#endif - -static FORCE_INLINE int tsdbCheckRowRange(STsdb *pTsdb, tb_uid_t uid, STSRow *row, TSKEY minKey, TSKEY maxKey, +static FORCE_INLINE int tsdbCheckRowRange(STsdb *pTsdb, tb_uid_t uid, TSKEY rowKey, TSKEY minKey, TSKEY maxKey, TSKEY now) { - TSKEY rowKey = TD_ROW_KEY(row); if (rowKey < minKey || rowKey > maxKey) { tsdbError("vgId:%d, table uid %" PRIu64 " timestamp is out of range! now %" PRId64 " minKey %" PRId64 " maxKey %" PRId64 " row key %" PRId64, TD_VID(pTsdb->pVnode), uid, now, minKey, maxKey, rowKey); - terrno = TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE; - return -1; + return TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE; } return 0; } -int tsdbScanAndConvertSubmitMsg(STsdb *pTsdb, SSubmitReq *pMsg) { - ASSERT(pMsg != NULL); - // STsdbMeta * pMeta = pTsdb->tsdbMeta; - SSubmitMsgIter msgIter = {0}; - SSubmitBlk *pBlock = NULL; - SSubmitBlkIter blkIter = {0}; - STSRow *row = NULL; - STsdbKeepCfg *pCfg = &pTsdb->keepCfg; - TSKEY now = taosGetTimestamp(pCfg->precision); - TSKEY minKey = now - tsTickPerMin[pCfg->precision] * pCfg->keep2; - TSKEY maxKey = tsMaxKeyByPrecision[pCfg->precision]; - - terrno = TSDB_CODE_SUCCESS; - // pMsg->length = htonl(pMsg->length); - // pMsg->numOfBlocks = htonl(pMsg->numOfBlocks); - - if (tInitSubmitMsgIter(pMsg, &msgIter) < 0) return -1; - while (true) { - if (tGetSubmitMsgNext(&msgIter, &pBlock) < 0) return -1; - if (pBlock == NULL) break; - - // pBlock->uid = htobe64(pBlock->uid); - // pBlock->suid = htobe64(pBlock->suid); - // pBlock->sversion = htonl(pBlock->sversion); - // pBlock->dataLen = htonl(pBlock->dataLen); - // pBlock->schemaLen = htonl(pBlock->schemaLen); - // pBlock->numOfRows = htonl(pBlock->numOfRows); - -#if 0 - if (pBlock->tid <= 0 || pBlock->tid >= pMeta->maxTables) { - tsdbError("vgId:%d, failed to get table to insert data, uid %" PRIu64 " tid %d", REPO_ID(pTsdb), pBlock->uid, - pBlock->tid); - terrno = TSDB_CODE_TDB_INVALID_TABLE_ID; - return -1; - } - - STable *pTable = pMeta->tables[pBlock->tid]; - if (pTable == NULL || TABLE_UID(pTable) != pBlock->uid) { - tsdbError("vgId:%d, failed to get table to insert data, uid %" PRIu64 " tid %d", REPO_ID(pTsdb), pBlock->uid, - pBlock->tid); - terrno = TSDB_CODE_TDB_INVALID_TABLE_ID; - return -1; - } - - if (TABLE_TYPE(pTable) == TSDB_SUPER_TABLE) { - tsdbError("vgId:%d, invalid action trying to insert a super table %s", REPO_ID(pTsdb), TABLE_CHAR_NAME(pTable)); - terrno = TSDB_CODE_TDB_INVALID_ACTION; - return -1; - } - - // Check schema version and update schema if needed - if (tsdbCheckTableSchema(pTsdb, pBlock, pTable) < 0) { - if (terrno == TSDB_CODE_TDB_TABLE_RECONFIGURE) { - continue; - } else { - return -1; +int tsdbScanAndConvertSubmitMsg(STsdb *pTsdb, SSubmitReq2 *pMsg) { + int32_t code = 0; + STsdbKeepCfg *pCfg = &pTsdb->keepCfg; + TSKEY now = taosGetTimestamp(pCfg->precision); + TSKEY minKey = now - tsTickPerMin[pCfg->precision] * pCfg->keep2; + TSKEY maxKey = tsMaxKeyByPrecision[pCfg->precision]; + int32_t size = taosArrayGetSize(pMsg->aSubmitTbData); + + for (int32_t i = 0; i < size; ++i) { + SSubmitTbData *pData = TARRAY_GET_ELEM(pMsg->aSubmitTbData, i); + if (pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + uint64_t nColData = TARRAY_SIZE(pData->aCol); + SColData *aColData = (SColData *)TARRAY_DATA(pData->aCol); + if (nColData > 0) { + int32_t nRows = aColData[0].nVal; + TSKEY *aKey = (TSKEY *)aColData[0].pData; + for (int32_t r = 0; r < nRows; ++r) { + if ((code = tsdbCheckRowRange(pTsdb, pData->uid, aKey[r], minKey, maxKey, now)) < 0) { + goto _exit; + } + } } - } -#endif - tInitSubmitBlkIter(&msgIter, pBlock, &blkIter); - while ((row = tGetSubmitBlkNext(&blkIter)) != NULL) { - if (tsdbCheckRowRange(pTsdb, msgIter.uid, row, minKey, maxKey, now) < 0) { - return -1; + } else { + int32_t nRows = taosArrayGetSize(pData->aRowP); + for (int32_t r = 0; r < nRows; ++r) { + SRow *pRow = (SRow *)taosArrayGetP(pData->aRowP, r); + if ((code = tsdbCheckRowRange(pTsdb, pData->uid, pRow->ts, minKey, maxKey, now)) < 0) { + goto _exit; + } } } } - if (terrno != TSDB_CODE_SUCCESS) return -1; - return 0; +_exit: + return code; } \ No newline at end of file diff --git a/source/dnode/vnode/src/vnd/vnodeBufPool.c b/source/dnode/vnode/src/vnd/vnodeBufPool.c index 83a414dae08bd48e41e12682922daf7055e1f5a0..40112c55791fe8d2cd3545f57169e2ba7ec33838 100644 --- a/source/dnode/vnode/src/vnd/vnodeBufPool.c +++ b/source/dnode/vnode/src/vnd/vnodeBufPool.c @@ -16,9 +16,7 @@ #include "vnd.h" /* ------------------------ STRUCTURES ------------------------ */ -#define VNODE_BUFPOOL_SEGMENTS 3 - -static int vnodeBufPoolCreate(SVnode *pVnode, int64_t size, SVBufPool **ppPool) { +static int vnodeBufPoolCreate(SVnode *pVnode, int32_t id, int64_t size, SVBufPool **ppPool) { SVBufPool *pPool; pPool = taosMemoryMalloc(sizeof(SVBufPool) + size); @@ -26,6 +24,21 @@ static int vnodeBufPoolCreate(SVnode *pVnode, int64_t size, SVBufPool **ppPool) terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } + memset(pPool, 0, sizeof(SVBufPool)); + + // query handle list + taosThreadMutexInit(&pPool->mutex, NULL); + pPool->nQuery = 0; + pPool->qList.pNext = &pPool->qList; + pPool->qList.ppNext = &pPool->qList.pNext; + + pPool->pVnode = pVnode; + pPool->id = id; + pPool->ptr = pPool->node.data; + pPool->pTail = &pPool->node; + pPool->node.prev = NULL; + pPool->node.pnext = &pPool->pTail; + pPool->node.size = size; if (VND_IS_RSMA(pVnode)) { pPool->lock = taosMemoryMalloc(sizeof(TdThreadSpinlock)); @@ -44,16 +57,6 @@ static int vnodeBufPoolCreate(SVnode *pVnode, int64_t size, SVBufPool **ppPool) pPool->lock = NULL; } - pPool->next = NULL; - pPool->pVnode = pVnode; - pPool->nRef = 0; - pPool->size = 0; - pPool->ptr = pPool->node.data; - pPool->pTail = &pPool->node; - pPool->node.prev = NULL; - pPool->node.pnext = &pPool->pTail; - pPool->node.size = size; - *ppPool = pPool; return 0; } @@ -64,27 +67,25 @@ static int vnodeBufPoolDestroy(SVBufPool *pPool) { taosThreadSpinDestroy(pPool->lock); taosMemoryFree((void *)pPool->lock); } + taosThreadMutexDestroy(&pPool->mutex); taosMemoryFree(pPool); return 0; } int vnodeOpenBufPool(SVnode *pVnode) { - SVBufPool *pPool = NULL; - int64_t size = pVnode->config.szBuf / VNODE_BUFPOOL_SEGMENTS; + int64_t size = pVnode->config.szBuf / VNODE_BUFPOOL_SEGMENTS; - ASSERT(pVnode->pPool == NULL); - - for (int i = 0; i < 3; i++) { + for (int i = 0; i < VNODE_BUFPOOL_SEGMENTS; i++) { // create pool - if (vnodeBufPoolCreate(pVnode, size, &pPool)) { + if (vnodeBufPoolCreate(pVnode, i, size, &pVnode->aBufPool[i])) { vError("vgId:%d, failed to open vnode buffer pool since %s", TD_VID(pVnode), tstrerror(terrno)); vnodeCloseBufPool(pVnode); return -1; } - // add pool to vnode - pPool->next = pVnode->pPool; - pVnode->pPool = pPool; + // add to free list + pVnode->aBufPool[i]->freeNext = pVnode->freeList; + pVnode->freeList = pVnode->aBufPool[i]; } vDebug("vgId:%d, vnode buffer pool is opened, size:%" PRId64, TD_VID(pVnode), size); @@ -92,23 +93,19 @@ int vnodeOpenBufPool(SVnode *pVnode) { } int vnodeCloseBufPool(SVnode *pVnode) { - SVBufPool *pPool; - - for (pPool = pVnode->pPool; pPool; pPool = pVnode->pPool) { - pVnode->pPool = pPool->next; - vnodeBufPoolDestroy(pPool); + for (int32_t i = 0; i < VNODE_BUFPOOL_SEGMENTS; i++) { + if (pVnode->aBufPool[i]) { + vnodeBufPoolDestroy(pVnode->aBufPool[i]); + pVnode->aBufPool[i] = NULL; + } } - if (pVnode->inUse) { - vnodeBufPoolDestroy(pVnode->inUse); - pVnode->inUse = NULL; - } vDebug("vgId:%d, vnode buffer pool is closed", TD_VID(pVnode)); - return 0; } void vnodeBufPoolReset(SVBufPool *pPool) { + ASSERT(pPool->nQuery == 0); for (SVBufPoolNode *pNode = pPool->pTail; pNode->prev; pNode = pPool->pTail) { ASSERT(pNode->pnext == &pPool->pTail); pNode->prev->pnext = &pPool->pTail; @@ -215,35 +212,119 @@ void vnodeBufPoolRef(SVBufPool *pPool) { ASSERT(nRef > 0); } -void vnodeBufPoolUnRef(SVBufPool *pPool) { - if (pPool == NULL) { - return; +void vnodeBufPoolAddToFreeList(SVBufPool *pPool) { + SVnode *pVnode = pPool->pVnode; + + int64_t size = pVnode->config.szBuf / VNODE_BUFPOOL_SEGMENTS; + if (pPool->node.size != size) { + SVBufPool *pNewPool = NULL; + if (vnodeBufPoolCreate(pVnode, pPool->id, size, &pNewPool) < 0) { + vWarn("vgId:%d, failed to change buffer pool of id %d size from %" PRId64 " to %" PRId64 " since %s", + TD_VID(pVnode), pPool->id, pPool->node.size, size, tstrerror(errno)); + } else { + vInfo("vgId:%d, buffer pool of id %d size changed from %" PRId64 " to %" PRId64, TD_VID(pVnode), pPool->id, + pPool->node.size, size); + + vnodeBufPoolDestroy(pPool); + pPool = pNewPool; + pVnode->aBufPool[pPool->id] = pPool; + } } - int32_t nRef = atomic_sub_fetch_32(&pPool->nRef, 1); - if (nRef == 0) { - SVnode *pVnode = pPool->pVnode; - - vnodeBufPoolReset(pPool); - - taosThreadMutexLock(&pVnode->mutex); - - int64_t size = pVnode->config.szBuf / VNODE_BUFPOOL_SEGMENTS; - if (pPool->node.size != size) { - SVBufPool *pPoolT = NULL; - if (vnodeBufPoolCreate(pVnode, size, &pPoolT) < 0) { - vWarn("vgId:%d, try to change buf pools size from %" PRId64 " to %" PRId64 " since %s", TD_VID(pVnode), - pPool->node.size, size, tstrerror(errno)); - } else { - vnodeBufPoolDestroy(pPool); - pPool = pPoolT; - vDebug("vgId:%d, change buf pools size from %" PRId64 " to %" PRId64, TD_VID(pVnode), pPool->node.size, size); - } + + // add to free list + vDebug("vgId:%d, buffer pool %p of id %d is added to free list", TD_VID(pVnode), pPool, pPool->id); + vnodeBufPoolReset(pPool); + pPool->freeNext = pVnode->freeList; + pVnode->freeList = pPool; + taosThreadCondSignal(&pVnode->poolNotEmpty); +} + +void vnodeBufPoolUnRef(SVBufPool *pPool, bool proactive) { + if (pPool == NULL) return; + + SVnode *pVnode = pPool->pVnode; + + if (proactive) taosThreadMutexLock(&pVnode->mutex); + + if (atomic_sub_fetch_32(&pPool->nRef, 1) > 0) goto _exit; + + // remove from recycle queue or on-recycle position + if (pVnode->onRecycle == pPool) { + pVnode->onRecycle = NULL; + } else { + if (pPool->recyclePrev) { + pPool->recyclePrev->recycleNext = pPool->recycleNext; + } else { + pVnode->recycleHead = pPool->recycleNext; + } + + if (pPool->recycleNext) { + pPool->recycleNext->recyclePrev = pPool->recyclePrev; + } else { + pVnode->recycleTail = pPool->recyclePrev; } + pPool->recyclePrev = pPool->recycleNext = NULL; + } + + vnodeBufPoolAddToFreeList(pPool); + +_exit: + if (proactive) taosThreadMutexUnlock(&pVnode->mutex); + return; +} + +int32_t vnodeBufPoolRegisterQuery(SVBufPool *pPool, SQueryNode *pQNode) { + int32_t code = 0; + + taosThreadMutexLock(&pPool->mutex); + + pQNode->pNext = pPool->qList.pNext; + pQNode->ppNext = &pPool->qList.pNext; + pPool->qList.pNext->ppNext = &pQNode->pNext; + pPool->qList.pNext = pQNode; + pPool->nQuery++; - pPool->next = pVnode->pPool; - pVnode->pPool = pPool; - taosThreadCondSignal(&pVnode->poolNotEmpty); + taosThreadMutexUnlock(&pPool->mutex); - taosThreadMutexUnlock(&pVnode->mutex); +_exit: + return code; +} + +void vnodeBufPoolDeregisterQuery(SVBufPool *pPool, SQueryNode *pQNode, bool proactive) { + int32_t code = 0; + + if (proactive) taosThreadMutexLock(&pPool->mutex); + + pQNode->pNext->ppNext = pQNode->ppNext; + *pQNode->ppNext = pQNode->pNext; + pPool->nQuery--; + + if (proactive) taosThreadMutexUnlock(&pPool->mutex); +} + +int32_t vnodeBufPoolRecycle(SVBufPool *pPool) { + int32_t code = 0; + + SVnode *pVnode = pPool->pVnode; + + vDebug("vgId:%d, recycle buffer pool %p of id %d", TD_VID(pVnode), pPool, pPool->id); + + taosThreadMutexLock(&pPool->mutex); + + SQueryNode *pNode = pPool->qList.pNext; + while (pNode != &pPool->qList) { + SQueryNode *pTNode = pNode->pNext; + + int32_t rc = pNode->reseek(pNode->pQHandle); + if (rc == 0 || rc == TSDB_CODE_VND_QUERY_BUSY) { + pNode = pTNode; + } else { + code = rc; + goto _exit; + } } + +_exit: + taosThreadMutexUnlock(&pPool->mutex); + return code; } diff --git a/source/dnode/vnode/src/vnd/vnodeCfg.c b/source/dnode/vnode/src/vnd/vnodeCfg.c index 69af536a4454909be7816ebda880e99e648656c3..c326c8bfacbd897fc15527edaef5cd8e77c40f5f 100644 --- a/source/dnode/vnode/src/vnd/vnodeCfg.c +++ b/source/dnode/vnode/src/vnd/vnodeCfg.c @@ -262,9 +262,10 @@ int vnodeDecodeConfig(const SJson *pJson, void *pObj) { tjsonGetNumberValue(info, "nodePort", pNode->nodePort, code); if (code < 0) return -1; tjsonGetStringValue(info, "nodeFqdn", pNode->nodeFqdn); - if (code < 0) return -1; tjsonGetNumberValue(info, "nodeId", pNode->nodeId, code); + if (code < 0) return -1; tjsonGetNumberValue(info, "clusterId", pNode->clusterId, code); + if (code < 0) return -1; vDebug("vgId:%d, decode config, replica:%d ep:%s:%u dnode:%d", pCfg->vgId, i, pNode->nodeFqdn, pNode->nodePort, pNode->nodeId); } diff --git a/source/dnode/vnode/src/vnd/vnodeCommit.c b/source/dnode/vnode/src/vnd/vnodeCommit.c index cefa9e675562bf0b96d2e107b73f2beac4ebb8eb..3eb813f3948ae1f5434564400d10ae4f0e1701c0 100644 --- a/source/dnode/vnode/src/vnd/vnodeCommit.c +++ b/source/dnode/vnode/src/vnd/vnodeCommit.c @@ -21,63 +21,126 @@ static int vnodeEncodeInfo(const SVnodeInfo *pInfo, char **ppData); static int vnodeCommitImpl(SCommitInfo *pInfo); -#define WAIT_TIME_MILI_SEC 50 +#define WAIT_TIME_MILI_SEC 10 // miliseconds -int vnodeBegin(SVnode *pVnode) { - // alloc buffer pool - int32_t nTry = 0; - - taosThreadMutexLock(&pVnode->mutex); - - while (pVnode->pPool == NULL) { - vInfo("vgId:%d no free buffer pool on %d try, wait %d ms...", TD_VID(pVnode), ++nTry, WAIT_TIME_MILI_SEC); +static int32_t vnodeTryRecycleBufPool(SVnode *pVnode) { + int32_t code = 0; - struct timeval tv; - struct timespec ts; - taosGetTimeOfDay(&tv); - ts.tv_nsec = tv.tv_usec * 1000 + WAIT_TIME_MILI_SEC * 1000000; - if (ts.tv_nsec > 999999999l) { - ts.tv_sec = tv.tv_sec + 1; - ts.tv_nsec -= 1000000000l; + if (pVnode->onRecycle == NULL) { + if (pVnode->recycleHead == NULL) { + vDebug("vgId:%d, no recyclable buffer pool", TD_VID(pVnode)); + goto _exit; } else { - ts.tv_sec = tv.tv_sec; + vDebug("vgId:%d, buffer pool %p of id %d on recycle queue, try to recycle", TD_VID(pVnode), pVnode->recycleHead, + pVnode->recycleHead->id); + + pVnode->onRecycle = pVnode->recycleHead; + if (pVnode->recycleHead == pVnode->recycleTail) { + pVnode->recycleHead = pVnode->recycleTail = NULL; + } else { + pVnode->recycleHead = pVnode->recycleHead->recycleNext; + pVnode->recycleHead->recyclePrev = NULL; + } + pVnode->onRecycle->recycleNext = pVnode->onRecycle->recyclePrev = NULL; } + } - int32_t rc = taosThreadCondTimedWait(&pVnode->poolNotEmpty, &pVnode->mutex, &ts); - if (rc && rc != ETIMEDOUT) { - terrno = TAOS_SYSTEM_ERROR(rc); - taosThreadMutexUnlock(&pVnode->mutex); - return -1; - } + code = vnodeBufPoolRecycle(pVnode->onRecycle); + if (code) goto _exit; + +_exit: + if (code) { + vError("vgId:%d, %s failed since %s", TD_VID(pVnode), __func__, tstrerror(code)); } + return code; +} +static int32_t vnodeGetBufPoolToUse(SVnode *pVnode) { + int32_t code = 0; + int32_t lino = 0; + + taosThreadMutexLock(&pVnode->mutex); - pVnode->inUse = pVnode->pPool; - pVnode->inUse->nRef = 1; - pVnode->pPool = pVnode->inUse->next; - pVnode->inUse->next = NULL; + int32_t nTry = 0; + for (;;) { + ++nTry; + + if (pVnode->freeList) { + vDebug("vgId:%d, allocate free buffer pool on %d try, pPool:%p id:%d", TD_VID(pVnode), nTry, pVnode->freeList, + pVnode->freeList->id); + + pVnode->inUse = pVnode->freeList; + pVnode->inUse->nRef = 1; + pVnode->freeList = pVnode->inUse->freeNext; + pVnode->inUse->freeNext = NULL; + break; + } else { + vDebug("vgId:%d, no free buffer pool on %d try, try to recycle...", TD_VID(pVnode), nTry); + + code = vnodeTryRecycleBufPool(pVnode); + TSDB_CHECK_CODE(code, lino, _exit); + + if (pVnode->freeList == NULL) { + vDebug("vgId:%d, no free buffer pool on %d try, wait %d ms...", TD_VID(pVnode), nTry, WAIT_TIME_MILI_SEC); + + struct timeval tv; + struct timespec ts; + taosGetTimeOfDay(&tv); + ts.tv_nsec = tv.tv_usec * 1000 + WAIT_TIME_MILI_SEC * 1000000; + if (ts.tv_nsec > 999999999l) { + ts.tv_sec = tv.tv_sec + 1; + ts.tv_nsec -= 1000000000l; + } else { + ts.tv_sec = tv.tv_sec; + } + + int32_t rc = taosThreadCondTimedWait(&pVnode->poolNotEmpty, &pVnode->mutex, &ts); + if (rc && rc != ETIMEDOUT) { + code = TAOS_SYSTEM_ERROR(rc); + TSDB_CHECK_CODE(code, lino, _exit); + } + } + } + } +_exit: taosThreadMutexUnlock(&pVnode->mutex); + if (code) { + vError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } + return code; +} +int vnodeBegin(SVnode *pVnode) { + int32_t code = 0; + int32_t lino = 0; + + // alloc buffer pool + code = vnodeGetBufPoolToUse(pVnode); + TSDB_CHECK_CODE(code, lino, _exit); - pVnode->state.commitID++; // begin meta if (metaBegin(pVnode->pMeta, META_BEGIN_HEAP_BUFFERPOOL) < 0) { - vError("vgId:%d, failed to begin meta since %s", TD_VID(pVnode), tstrerror(terrno)); - return -1; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } // begin tsdb if (tsdbBegin(pVnode->pTsdb) < 0) { - vError("vgId:%d, failed to begin tsdb since %s", TD_VID(pVnode), tstrerror(terrno)); - return -1; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } // begin sma if (VND_IS_RSMA(pVnode) && smaBegin(pVnode->pSma) < 0) { - vError("vgId:%d, failed to begin sma since %s", TD_VID(pVnode), tstrerror(terrno)); - return -1; + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); } - return 0; +_exit: + if (code) { + terrno = code; + vError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } + return code; } void vnodeUpdCommitSched(SVnode *pVnode) { @@ -86,23 +149,20 @@ void vnodeUpdCommitSched(SVnode *pVnode) { pVnode->commitSched.maxWaitMs = tsVndCommitMaxIntervalMs + (randNum % tsVndCommitMaxIntervalMs); } -int vnodeShouldCommit(SVnode *pVnode) { - if (!pVnode->inUse || !osDataSpaceAvailable()) { - return false; - } - +int vnodeShouldCommit(SVnode *pVnode, bool atExit) { SVCommitSched *pSched = &pVnode->commitSched; int64_t nowMs = taosGetMonoTimestampMs(); + bool diskAvail = osDataSpaceAvailable(); + bool needCommit = false; - return (((pVnode->inUse->size > pVnode->inUse->node.size) && (pSched->commitMs + SYNC_VND_COMMIT_MIN_MS < nowMs)) || - (pVnode->inUse->size > 0 && pSched->commitMs + pSched->maxWaitMs < nowMs)); -} - -int vnodeShouldCommitOld(SVnode *pVnode) { - if (pVnode->inUse) { - return osDataSpaceAvailable() && (pVnode->inUse->size > pVnode->inUse->node.size); + taosThreadMutexLock(&pVnode->mutex); + if (pVnode->inUse && diskAvail) { + needCommit = + ((pVnode->inUse->size > pVnode->inUse->node.size) && (pSched->commitMs + SYNC_VND_COMMIT_MIN_MS < nowMs)) || + ((pVnode->inUse->size > 0) && atExit); } - return false; + taosThreadMutexUnlock(&pVnode->mutex); + return needCommit; } int vnodeSaveInfo(const char *dir, const SVnodeInfo *pInfo) { @@ -156,7 +216,7 @@ _err: return -1; } -int vnodeCommitInfo(const char *dir, const SVnodeInfo *pInfo) { +int vnodeCommitInfo(const char *dir) { char fname[TSDB_FILENAME_LEN]; char tfname[TSDB_FILENAME_LEN]; @@ -168,8 +228,7 @@ int vnodeCommitInfo(const char *dir, const SVnodeInfo *pInfo) { return -1; } - vInfo("vgId:%d, vnode info is committed", pInfo->config.vgId); - + vInfo("vnode info is committed, dir:%s", dir); return 0; } @@ -236,7 +295,7 @@ static int32_t vnodePrepareCommit(SVnode *pVnode, SCommitInfo *pInfo) { pInfo->info.config = pVnode->config; pInfo->info.state.committed = pVnode->state.applied; pInfo->info.state.commitTerm = pVnode->state.applyTerm; - pInfo->info.state.commitID = pVnode->state.commitID; + pInfo->info.state.commitID = ++pVnode->state.commitID; pInfo->pVnode = pVnode; pInfo->txn = metaGetTxn(pVnode->pMeta); @@ -254,36 +313,70 @@ static int32_t vnodePrepareCommit(SVnode *pVnode, SCommitInfo *pInfo) { } tsdbPrepareCommit(pVnode->pTsdb); - smaPrepareAsyncCommit(pVnode->pSma); metaPrepareAsyncCommit(pVnode->pMeta); - vnodeBufPoolUnRef(pVnode->inUse); + code = smaPrepareAsyncCommit(pVnode->pSma); + if (code) goto _exit; + + taosThreadMutexLock(&pVnode->mutex); + ASSERT(pVnode->onCommit == NULL); + pVnode->onCommit = pVnode->inUse; pVnode->inUse = NULL; + taosThreadMutexUnlock(&pVnode->mutex); _exit: if (code) { vError("vgId:%d, %s failed at line %d since %s, commit id:%" PRId64, TD_VID(pVnode), __func__, lino, tstrerror(code), pVnode->state.commitID); } else { - vDebug("vgId:%d, %s done", TD_VID(pVnode), __func__); + vDebug("vgId:%d, %s done, commit id:%" PRId64, TD_VID(pVnode), __func__, pInfo->info.state.commitID); } + return code; } +static void vnodeReturnBufPool(SVnode *pVnode) { + taosThreadMutexLock(&pVnode->mutex); + + SVBufPool *pPool = pVnode->onCommit; + int32_t nRef = atomic_sub_fetch_32(&pPool->nRef, 1); + + pVnode->onCommit = NULL; + if (nRef == 0) { + vnodeBufPoolAddToFreeList(pPool); + } else if (nRef > 0) { + vDebug("vgId:%d, buffer pool %p of id %d is added to recycle queue", TD_VID(pVnode), pPool, pPool->id); + + if (pVnode->recycleTail == NULL) { + pPool->recyclePrev = pPool->recycleNext = NULL; + pVnode->recycleHead = pVnode->recycleTail = pPool; + } else { + pPool->recyclePrev = pVnode->recycleTail; + pPool->recycleNext = NULL; + pVnode->recycleTail->recycleNext = pPool; + pVnode->recycleTail = pPool; + } + } else { + ASSERT(0); + } + taosThreadMutexUnlock(&pVnode->mutex); +} static int32_t vnodeCommitTask(void *arg) { int32_t code = 0; SCommitInfo *pInfo = (SCommitInfo *)arg; + SVnode *pVnode = pInfo->pVnode; // commit code = vnodeCommitImpl(pInfo); if (code) goto _exit; - // end commit - tsem_post(&pInfo->pVnode->canCommit); + vnodeReturnBufPool(pVnode); _exit: + // end commit + tsem_post(&pVnode->canCommit); taosMemoryFree(pInfo); return code; } @@ -304,14 +397,15 @@ int vnodeAsyncCommit(SVnode *pVnode) { } // schedule the task - vnodeScheduleTask(vnodeCommitTask, pInfo); + code = vnodeScheduleTask(vnodeCommitTask, pInfo); _exit: if (code) { if (NULL != pInfo) { taosMemoryFree(pInfo); } - vError("vgId:%d, vnode async commit failed since %s, commitId:%" PRId64, TD_VID(pVnode), tstrerror(code), + tsem_post(&pVnode->canCommit); + vError("vgId:%d, %s failed since %s, commit id:%" PRId64, TD_VID(pVnode), __func__, tstrerror(code), pVnode->state.commitID); } else { vInfo("vgId:%d, vnode async commit done, commitId:%" PRId64 " term:%" PRId64 " applied:%" PRId64, TD_VID(pVnode), @@ -368,7 +462,7 @@ static int vnodeCommitImpl(SCommitInfo *pInfo) { } // commit info - if (vnodeCommitInfo(dir, &pInfo->info) < 0) { + if (vnodeCommitInfo(dir) < 0) { code = terrno; TSDB_CHECK_CODE(code, lino, _exit); } diff --git a/source/dnode/vnode/src/vnd/vnodeOpen.c b/source/dnode/vnode/src/vnd/vnodeOpen.c index 97ee2e4a89597aa6021b08ee35bc1dd27684a353..c7d155be0d50600e419940b03297d2bad6d29528 100644 --- a/source/dnode/vnode/src/vnd/vnodeOpen.c +++ b/source/dnode/vnode/src/vnd/vnodeOpen.c @@ -48,8 +48,8 @@ int32_t vnodeCreate(const char *path, SVnodeCfg *pCfg, STfs *pTfs) { info.state.applied = -1; info.state.commitID = 0; - vInfo("vgId:%d, save config while create", pCfg->vgId); - if (vnodeSaveInfo(dir, &info) < 0 || vnodeCommitInfo(dir, &info) < 0) { + vInfo("vgId:%d, save config while create", info.config.vgId); + if (vnodeSaveInfo(dir, &info) < 0 || vnodeCommitInfo(dir) < 0) { vError("vgId:%d, failed to save vnode config since %s", pCfg ? pCfg->vgId : 0, tstrerror(terrno)); return -1; } @@ -58,7 +58,7 @@ int32_t vnodeCreate(const char *path, SVnodeCfg *pCfg, STfs *pTfs) { return 0; } -int32_t vnodeAlter(const char *path, SAlterVnodeReplicaReq *pReq, STfs *pTfs) { +int32_t vnodeAlterReplica(const char *path, SAlterVnodeReplicaReq *pReq, STfs *pTfs) { SVnodeInfo info = {0}; char dir[TSDB_FILENAME_LEN] = {0}; int32_t ret = 0; @@ -86,7 +86,7 @@ int32_t vnodeAlter(const char *path, SAlterVnodeReplicaReq *pReq, STfs *pTfs) { pNode->nodeId = pReq->replicas[i].id; pNode->nodePort = pReq->replicas[i].port; tstrncpy(pNode->nodeFqdn, pReq->replicas[i].fqdn, sizeof(pNode->nodeFqdn)); - tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort); + (void)tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort); vInfo("vgId:%d, replica:%d ep:%s:%u dnode:%d", pReq->vgId, i, pNode->nodeFqdn, pNode->nodePort, pNode->nodeId); } @@ -97,7 +97,7 @@ int32_t vnodeAlter(const char *path, SAlterVnodeReplicaReq *pReq, STfs *pTfs) { return -1; } - ret = vnodeCommitInfo(dir, &info); + ret = vnodeCommitInfo(dir); if (ret < 0) { vError("vgId:%d, failed to commit vnode config since %s", pReq->vgId, tstrerror(terrno)); return -1; @@ -107,6 +107,117 @@ int32_t vnodeAlter(const char *path, SAlterVnodeReplicaReq *pReq, STfs *pTfs) { return 0; } +int32_t vnodeRenameVgroupId(const char *srcPath, const char *dstPath, int32_t srcVgId, int32_t dstVgId, STfs *pTfs) { + int32_t ret = tfsRename(pTfs, srcPath, dstPath); + if (ret != 0) return ret; + + char oldRname[TSDB_FILENAME_LEN] = {0}; + char newRname[TSDB_FILENAME_LEN] = {0}; + char tsdbPath[TSDB_FILENAME_LEN] = {0}; + char tsdbFilePrefix[TSDB_FILENAME_LEN] = {0}; + snprintf(tsdbPath, TSDB_FILENAME_LEN, "%s%stsdb", dstPath, TD_DIRSEP); + snprintf(tsdbFilePrefix, TSDB_FILENAME_LEN, "tsdb%sv", TD_DIRSEP); + + STfsDir *tsdbDir = tfsOpendir(pTfs, tsdbPath); + if (tsdbDir == NULL) return 0; + + while (1) { + const STfsFile *tsdbFile = tfsReaddir(tsdbDir); + if (tsdbFile == NULL) break; + if (tsdbFile->rname[0] == '\0') continue; + tstrncpy(oldRname, tsdbFile->rname, TSDB_FILENAME_LEN); + + char *tsdbFilePrefixPos = strstr(oldRname, tsdbFilePrefix); + if (tsdbFilePrefixPos == NULL) continue; + + int32_t tsdbFileVgId = atoi(tsdbFilePrefixPos + 6); + if (tsdbFileVgId == srcVgId) { + char *tsdbFileSurfixPos = strstr(tsdbFilePrefixPos, "f"); + if (tsdbFileSurfixPos == NULL) continue; + + tsdbFilePrefixPos[6] = 0; + snprintf(newRname, TSDB_FILENAME_LEN, "%s%d%s", oldRname, dstVgId, tsdbFileSurfixPos); + vInfo("vgId:%d, rename file from %s to %s", dstVgId, tsdbFile->rname, newRname); + + ret = tfsRename(pTfs, tsdbFile->rname, newRname); + if (ret != 0) { + vInfo("vgId:%d, failed to rename file from %s to %s since %s", dstVgId, tsdbFile->rname, newRname, terrstr()); + tfsClosedir(tsdbDir); + return ret; + } + } + } + + tfsClosedir(tsdbDir); + return 0; +} + +int32_t vnodeAlterHashRange(const char *srcPath, const char *dstPath, SAlterVnodeHashRangeReq *pReq, STfs *pTfs) { + SVnodeInfo info = {0}; + char dir[TSDB_FILENAME_LEN] = {0}; + int32_t ret = 0; + + if (pTfs) { + snprintf(dir, TSDB_FILENAME_LEN, "%s%s%s", tfsGetPrimaryPath(pTfs), TD_DIRSEP, srcPath); + } else { + snprintf(dir, TSDB_FILENAME_LEN, "%s", srcPath); + } + + // todo add stat file to handle exception while vnode open + + ret = vnodeLoadInfo(dir, &info); + if (ret < 0) { + vError("vgId:%d, failed to read vnode config from %s since %s", pReq->srcVgId, srcPath, tstrerror(terrno)); + return -1; + } + + vInfo("vgId:%d, alter hashrange from [%u, %u] to [%u, %u]", pReq->srcVgId, info.config.hashBegin, info.config.hashEnd, + pReq->hashBegin, pReq->hashEnd); + info.config.vgId = pReq->dstVgId; + info.config.hashBegin = pReq->hashBegin; + info.config.hashEnd = pReq->hashEnd; + info.config.walCfg.vgId = pReq->dstVgId; + + SSyncCfg *pCfg = &info.config.syncCfg; + pCfg->myIndex = 0; + pCfg->replicaNum = 1; + memset(&pCfg->nodeInfo, 0, sizeof(pCfg->nodeInfo)); + + vInfo("vgId:%d, alter vnode replicas to 1", pReq->srcVgId); + SNodeInfo *pNode = &pCfg->nodeInfo[0]; + pNode->nodePort = tsServerPort; + tstrncpy(pNode->nodeFqdn, tsLocalFqdn, TSDB_FQDN_LEN); + (void)tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort); + vInfo("vgId:%d, ep:%s:%u dnode:%d", pReq->srcVgId, pNode->nodeFqdn, pNode->nodePort, pNode->nodeId); + + info.config.syncCfg = *pCfg; + + ret = vnodeSaveInfo(dir, &info); + if (ret < 0) { + vError("vgId:%d, failed to save vnode config since %s", pReq->dstVgId, tstrerror(terrno)); + return -1; + } + + ret = vnodeCommitInfo(dir); + if (ret < 0) { + vError("vgId:%d, failed to commit vnode config since %s", pReq->dstVgId, tstrerror(terrno)); + return -1; + } + + vInfo("vgId:%d, rename %s to %s", pReq->dstVgId, srcPath, dstPath); + ret = vnodeRenameVgroupId(srcPath, dstPath, pReq->srcVgId, pReq->dstVgId, pTfs); + if (ret < 0) { + vError("vgId:%d, failed to rename vnode from %s to %s since %s", pReq->dstVgId, srcPath, dstPath, + tstrerror(terrno)); + return -1; + } + + // todo vnode compact here + + vInfo("vgId:%d, vnode hashrange is altered", info.config.vgId); + return 0; +} + void vnodeDestroy(const char *path, STfs *pTfs) { vInfo("path:%s is removed while destroy vnode", path); tfsRmdir(pTfs, path); @@ -134,6 +245,21 @@ SVnode *vnodeOpen(const char *path, STfs *pTfs, SMsgCb msgCb) { return NULL; } + // save vnode info on dnode ep changed + bool updated = false; + SSyncCfg *pCfg = &info.config.syncCfg; + for (int32_t i = 0; i < pCfg->replicaNum; ++i) { + SNodeInfo *pNode = &pCfg->nodeInfo[i]; + if (tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort)) { + updated = true; + } + } + if (updated) { + vInfo("vgId:%d, save vnode info since dnode info changed", info.config.vgId); + (void)vnodeSaveInfo(dir, &info); + (void)vnodeCommitInfo(dir); + } + // create handle pVnode = taosMemoryCalloc(1, sizeof(*pVnode) + strlen(path) + 1); if (pVnode == NULL) { @@ -240,7 +366,7 @@ _err: if (pVnode->pTsdb) tsdbClose(&pVnode->pTsdb); if (pVnode->pSma) smaClose(pVnode->pSma); if (pVnode->pMeta) metaClose(&pVnode->pMeta); - if (pVnode->pPool) vnodeCloseBufPool(pVnode); + if (pVnode->freeList) vnodeCloseBufPool(pVnode); tsem_destroy(&(pVnode->canCommit)); taosMemoryFree(pVnode); diff --git a/source/dnode/vnode/src/vnd/vnodeQuery.c b/source/dnode/vnode/src/vnd/vnodeQuery.c index 1199127f6d42bf2d3f7488fb120e8fa9ab09c490..303d2a9ca449de504a582c8472951a1bf6c6c683 100644 --- a/source/dnode/vnode/src/vnd/vnodeQuery.c +++ b/source/dnode/vnode/src/vnd/vnodeQuery.c @@ -15,13 +15,13 @@ #include "vnd.h" -#define VNODE_GET_LOAD_RESET_VALS(pVar, oVal, vType, tags) \ - do { \ - int##vType##_t newVal = atomic_sub_fetch_##vType(&(pVar), (oVal)); \ - ASSERT(newVal >= 0); \ - if (newVal < 0) { \ - vWarn("vgId:%d %s, abnormal val:%" PRIi64 ", old val:%" PRIi64, TD_VID(pVnode), tags, newVal, (oVal)); \ - } \ +#define VNODE_GET_LOAD_RESET_VALS(pVar, oVal, vType, tags) \ + do { \ + int##vType##_t newVal = atomic_sub_fetch_##vType(&(pVar), (oVal)); \ + ASSERT(newVal >= 0); \ + if (newVal < 0) { \ + vWarn("vgId:%d, %s, abnormal val:%" PRIi64 ", old val:%" PRIi64, TD_VID(pVnode), tags, newVal, (oVal)); \ + } \ } while (0) int vnodeQueryOpen(SVnode *pVnode) { @@ -96,6 +96,7 @@ int vnodeGetTableMeta(SVnode *pVnode, SRpcMsg *pMsg, bool direct) { metaRsp.numOfColumns = schema.nCols; metaRsp.precision = pVnode->config.tsdbCfg.precision; metaRsp.sversion = schema.version; + metaRsp.tversion = schemaTag.version; metaRsp.pSchemas = (SSchema *)taosMemoryMalloc(sizeof(SSchema) * (metaRsp.numOfColumns + metaRsp.numOfTags)); memcpy(metaRsp.pSchemas, schema.pSchema, sizeof(SSchema) * schema.nCols); @@ -196,7 +197,7 @@ int vnodeGetTableCfg(SVnode *pVnode, SRpcMsg *pMsg, bool direct) { cfgRsp.ttl = mer1.me.ctbEntry.ttlDays; cfgRsp.commentLen = mer1.me.ctbEntry.commentLen; if (mer1.me.ctbEntry.commentLen > 0) { - cfgRsp.pComment = strdup(mer1.me.ctbEntry.comment); + cfgRsp.pComment = taosStrdup(mer1.me.ctbEntry.comment); } STag *pTag = (STag *)mer1.me.ctbEntry.pTags; cfgRsp.tagsLen = pTag->len; @@ -207,7 +208,7 @@ int vnodeGetTableCfg(SVnode *pVnode, SRpcMsg *pMsg, bool direct) { cfgRsp.ttl = mer1.me.ntbEntry.ttlDays; cfgRsp.commentLen = mer1.me.ntbEntry.commentLen; if (mer1.me.ntbEntry.commentLen > 0) { - cfgRsp.pComment = strdup(mer1.me.ntbEntry.comment); + cfgRsp.pComment = taosStrdup(mer1.me.ntbEntry.comment); } } else { ASSERT(0); @@ -264,26 +265,25 @@ _exit: return TSDB_CODE_SUCCESS; } -static FORCE_INLINE void vnodeFreeSBatchRspMsg(void* p) { +static FORCE_INLINE void vnodeFreeSBatchRspMsg(void *p) { if (NULL == p) { return; } - SBatchRspMsg* pRsp = (SBatchRspMsg*)p; + SBatchRspMsg *pRsp = (SBatchRspMsg *)p; rpcFreeCont(pRsp->msg); } - int32_t vnodeGetBatchMeta(SVnode *pVnode, SRpcMsg *pMsg) { - int32_t code = 0; - int32_t rspSize = 0; - SBatchReq batchReq = {0}; - SBatchMsg *req = NULL; + int32_t code = 0; + int32_t rspSize = 0; + SBatchReq batchReq = {0}; + SBatchMsg *req = NULL; SBatchRspMsg rsp = {0}; - SBatchRsp batchRsp = {0}; - SRpcMsg reqMsg = *pMsg; - SRpcMsg rspMsg = {0}; - void *pRsp = NULL; + SBatchRsp batchRsp = {0}; + SRpcMsg reqMsg = *pMsg; + SRpcMsg rspMsg = {0}; + void *pRsp = NULL; if (tDeserializeSBatchReq(pMsg->pCont, pMsg->contLen, &batchReq)) { code = TSDB_CODE_OUT_OF_MEMORY; @@ -291,7 +291,7 @@ int32_t vnodeGetBatchMeta(SVnode *pVnode, SRpcMsg *pMsg) { goto _exit; } - int32_t msgNum = taosArrayGetSize(batchReq.pMsgs); + int32_t msgNum = taosArrayGetSize(batchReq.pMsgs); if (msgNum >= MAX_META_MSG_IN_BATCH) { code = TSDB_CODE_INVALID_MSG; qError("too many msgs %d in vnode batch meta req", msgNum); @@ -382,6 +382,7 @@ int32_t vnodeGetLoad(SVnode *pVnode, SVnodeLoad *pLoad) { pLoad->syncRestore = state.restored; pLoad->syncCanRead = state.canRead; pLoad->cacheUsage = tsdbCacheGetUsage(pVnode); + pLoad->numOfCachedTables = tsdbCacheGetElems(pVnode); pLoad->numOfTables = metaGetTbNum(pVnode->pMeta); pLoad->numOfTimeSeries = metaGetTimeSeriesNum(pVnode->pMeta); pLoad->totalStorage = (int64_t)3 * 1073741824; @@ -405,7 +406,8 @@ void vnodeResetLoad(SVnode *pVnode, SVnodeLoad *pLoad) { VNODE_GET_LOAD_RESET_VALS(pVnode->statis.nInsert, pLoad->numOfInsertReqs, 64, "nInsert"); VNODE_GET_LOAD_RESET_VALS(pVnode->statis.nInsertSuccess, pLoad->numOfInsertSuccessReqs, 64, "nInsertSuccess"); VNODE_GET_LOAD_RESET_VALS(pVnode->statis.nBatchInsert, pLoad->numOfBatchInsertReqs, 64, "nBatchInsert"); - VNODE_GET_LOAD_RESET_VALS(pVnode->statis.nBatchInsertSuccess, pLoad->numOfBatchInsertSuccessReqs, 64, "nBatchInsertSuccess"); + VNODE_GET_LOAD_RESET_VALS(pVnode->statis.nBatchInsertSuccess, pLoad->numOfBatchInsertSuccessReqs, 64, + "nBatchInsertSuccess"); } void vnodeGetInfo(SVnode *pVnode, const char **dbname, int32_t *vgId) { diff --git a/source/dnode/vnode/src/vnd/vnodeRetention.c b/source/dnode/vnode/src/vnd/vnodeRetention.c new file mode 100644 index 0000000000000000000000000000000000000000..170deb42867d2bdd2df80ff01d84be31115d8ed3 --- /dev/null +++ b/source/dnode/vnode/src/vnd/vnodeRetention.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "vnd.h" + +typedef struct { + SVnode *pVnode; + int64_t now; + int64_t commitID; + SVnodeInfo info; +} SRetentionInfo; + +extern bool tsdbShouldDoRetention(STsdb *pTsdb, int64_t now); +extern int32_t tsdbDoRetention(STsdb *pTsdb, int64_t now); +extern int32_t tsdbCommitRetention(STsdb *pTsdb); + +static int32_t vnodePrepareRentention(SVnode *pVnode, SRetentionInfo *pInfo) { + int32_t code = 0; + int32_t lino = 0; + + tsem_wait(&pVnode->canCommit); + + pInfo->commitID = ++pVnode->state.commitID; + + char dir[TSDB_FILENAME_LEN] = {0}; + if (pVnode->pTfs) { + snprintf(dir, TSDB_FILENAME_LEN, "%s%s%s", tfsGetPrimaryPath(pVnode->pTfs), TD_DIRSEP, pVnode->path); + } else { + snprintf(dir, TSDB_FILENAME_LEN, "%s", pVnode->path); + } + + if (vnodeLoadInfo(dir, &pInfo->info) < 0) { + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); + } + +_exit: + if (code) { + vError("vgId:%d %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + tsem_post(&pVnode->canCommit); + } else { + vInfo("vgId:%d %s done", TD_VID(pVnode), __func__); + } + return code; +} + +static int32_t vnodeRetentionTask(void *param) { + int32_t code = 0; + int32_t lino = 0; + + SRetentionInfo *pInfo = (SRetentionInfo *)param; + SVnode *pVnode = pInfo->pVnode; + char dir[TSDB_FILENAME_LEN] = {0}; + + if (pVnode->pTfs) { + snprintf(dir, TSDB_FILENAME_LEN, "%s%s%s", tfsGetPrimaryPath(pVnode->pTfs), TD_DIRSEP, pVnode->path); + } else { + snprintf(dir, TSDB_FILENAME_LEN, "%s", pVnode->path); + } + + // save info + pInfo->info.state.commitID = pInfo->commitID; + + if (vnodeSaveInfo(dir, &pInfo->info) < 0) { + code = terrno; + TSDB_CHECK_CODE(code, lino, _exit); + } + + // do job + code = tsdbDoRetention(pInfo->pVnode->pTsdb, pInfo->now); + TSDB_CHECK_CODE(code, lino, _exit); + + // commit info + vnodeCommitInfo(dir); + + // commit sub-job + tsdbCommitRetention(pVnode->pTsdb); + +_exit: + if (code) { + vError("vgId:%d %s failed at line %d since %s", TD_VID(pInfo->pVnode), __func__, lino, tstrerror(code)); + } else { + vInfo("vgId:%d %s done", TD_VID(pInfo->pVnode), __func__); + } + tsem_post(&pInfo->pVnode->canCommit); + taosMemoryFree(pInfo); + return code; +} + +int32_t vnodeAsyncRentention(SVnode *pVnode, int64_t now) { + int32_t code = 0; + int32_t lino = 0; + + if (!tsdbShouldDoRetention(pVnode->pTsdb, now)) return code; + + SRetentionInfo *pInfo = (SRetentionInfo *)taosMemoryCalloc(1, sizeof(*pInfo)); + if (pInfo == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + TSDB_CHECK_CODE(code, lino, _exit); + } + + pInfo->pVnode = pVnode; + pInfo->now = now; + + code = vnodePrepareRentention(pVnode, pInfo); + TSDB_CHECK_CODE(code, lino, _exit); + + vnodeScheduleTask(vnodeRetentionTask, pInfo); + +_exit: + if (code) { + vError("vgId:%d %s failed at line %d since %s", TD_VID(pInfo->pVnode), __func__, lino, tstrerror(code)); + if (pInfo) taosMemoryFree(pInfo); + } else { + vInfo("vgId:%d %s done", TD_VID(pInfo->pVnode), __func__); + } + return 0; +} \ No newline at end of file diff --git a/source/dnode/vnode/src/vnd/vnodeSnapshot.c b/source/dnode/vnode/src/vnd/vnodeSnapshot.c index 448726161710cddabed9231554af47f4332b22db..052e4ab2c18e6dad651cf591962bcb4dd49a0a38 100644 --- a/source/dnode/vnode/src/vnd/vnodeSnapshot.c +++ b/source/dnode/vnode/src/vnd/vnodeSnapshot.c @@ -335,6 +335,7 @@ int32_t vnodeSnapWriterClose(SVSnapWriter *pWriter, int8_t rollback, SSnapshot * // commit json if (!rollback) { + pWriter->info.state.committed = pWriter->ever; pVnode->config = pWriter->info.config; pVnode->state = (SVState){.committed = pWriter->info.state.committed, .applied = pWriter->info.state.committed, @@ -349,7 +350,7 @@ int32_t vnodeSnapWriterClose(SVSnapWriter *pWriter, int8_t rollback, SSnapshot * snprintf(dir, TSDB_FILENAME_LEN, "%s", pWriter->pVnode->path); } - vnodeCommitInfo(dir, &pWriter->info); + vnodeCommitInfo(dir); } else { vnodeRollback(pWriter->pVnode); } diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c index 67990bc8c94174d6a09d09a8d97d6363e27a609a..c6084034564f5fd1063e8cdc2f5789c363eb2ba8 100644 --- a/source/dnode/vnode/src/vnd/vnodeSvr.c +++ b/source/dnode/vnode/src/vnd/vnodeSvr.c @@ -13,7 +13,11 @@ * along with this program. If not, see . */ +#include "tencode.h" +#include "tmsg.h" #include "vnd.h" +#include "vnode.h" +#include "vnodeInt.h" static int32_t vnodeProcessCreateStbReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessAlterStbReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); @@ -24,145 +28,276 @@ static int32_t vnodeProcessDropTbReq(SVnode *pVnode, int64_t version, void *pReq static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessCreateTSmaReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessAlterConfirmReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); -static int32_t vnodeProcessAlterHashRangeReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessAlterConfigReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessDropTtlTbReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessTrimReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessDeleteReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessBatchDeleteReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); +static int32_t vnodeProcessCreateIndexReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); +static int32_t vnodeProcessDropIndexReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); +static int32_t vnodeProcessCompactVnodeReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); -int32_t vnodePreProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg) { - int32_t code = 0; +static int32_t vnodePreprocessCreateTableReq(SVnode *pVnode, SDecoder *pCoder, int64_t ctime, int64_t *pUid) { + int32_t code = 0; + int32_t lino = 0; + + if (tStartDecode(pCoder) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } + + // flags + if (tDecodeI32v(pCoder, NULL) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } + + // name + char *name = NULL; + if (tDecodeCStr(pCoder, &name) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } + + // uid + int64_t uid = metaGetTableEntryUidByName(pVnode->pMeta, name); + if (uid == 0) { + uid = tGenIdPI64(); + } + *(int64_t *)(pCoder->data + pCoder->pos) = uid; + + // ctime + *(int64_t *)(pCoder->data + pCoder->pos + 8) = ctime; + + tEndDecode(pCoder); + +_exit: + if (code) { + vError("vgId:%d %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code)); + } else { + vTrace("vgId:%d %s done, table:%s uid generated:%" PRId64, TD_VID(pVnode), __func__, name, uid); + if (pUid) *pUid = uid; + } + return code; +} +static int32_t vnodePreProcessCreateTableMsg(SVnode *pVnode, SRpcMsg *pMsg) { + int32_t code = 0; + int32_t lino = 0; + + int64_t ctime = taosGetTimestampMs(); SDecoder dc = {0}; + int32_t nReqs; - switch (pMsg->msgType) { - case TDMT_VND_CREATE_TABLE: { - int64_t ctime = taosGetTimestampMs(); - int32_t nReqs; + tDecoderInit(&dc, (uint8_t *)pMsg->pCont + sizeof(SMsgHead), pMsg->contLen - sizeof(SMsgHead)); + if (tStartDecode(&dc) < 0) { + code = TSDB_CODE_INVALID_MSG; + return code; + } - tDecoderInit(&dc, (uint8_t *)pMsg->pCont + sizeof(SMsgHead), pMsg->contLen - sizeof(SMsgHead)); - if (tStartDecode(&dc) < 0) { - code = TSDB_CODE_INVALID_MSG; - return code; - } + if (tDecodeI32v(&dc, &nReqs) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } + for (int32_t iReq = 0; iReq < nReqs; iReq++) { + code = vnodePreprocessCreateTableReq(pVnode, &dc, ctime, NULL); + TSDB_CHECK_CODE(code, lino, _exit); + } - if (tDecodeI32v(&dc, &nReqs) < 0) { - code = TSDB_CODE_INVALID_MSG; - goto _err; - } - for (int32_t iReq = 0; iReq < nReqs; iReq++) { - tb_uid_t uid = tGenIdPI64(); - char *name = NULL; - if (tStartDecode(&dc) < 0) { - code = TSDB_CODE_INVALID_MSG; - goto _err; - } + tEndDecode(&dc); - if (tDecodeI32v(&dc, NULL) < 0) { - code = TSDB_CODE_INVALID_MSG; - return code; - } - if (tDecodeCStr(&dc, &name) < 0) { - code = TSDB_CODE_INVALID_MSG; - return code; - } - *(int64_t *)(dc.data + dc.pos) = uid; - *(int64_t *)(dc.data + dc.pos + 8) = ctime; +_exit: + tDecoderClear(&dc); + return code; +} +extern int64_t tsMaxKeyByPrecision[]; +static int32_t vnodePreProcessSubmitTbData(SVnode *pVnode, SDecoder *pCoder, int64_t ctime) { + int32_t code = 0; + int32_t lino = 0; - vTrace("vgId:%d, table:%s uid:%" PRId64 " is generated", pVnode->config.vgId, name, uid); - tEndDecode(&dc); - } + if (tStartDecode(pCoder) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } - tEndDecode(&dc); - tDecoderClear(&dc); - } break; - case TDMT_VND_SUBMIT: { - SSubmitMsgIter msgIter = {0}; - SSubmitReq *pSubmitReq = (SSubmitReq *)pMsg->pCont; - SSubmitBlk *pBlock = NULL; - int64_t ctime = taosGetTimestampMs(); - tb_uid_t uid; - - if (tInitSubmitMsgIter(pSubmitReq, &msgIter) < 0) { - code = terrno; - goto _err; - } + SSubmitTbData submitTbData; + if (tDecodeI32v(pCoder, &submitTbData.flags) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } - for (;;) { - tGetSubmitMsgNext(&msgIter, &pBlock); - if (pBlock == NULL) break; - - if (msgIter.schemaLen > 0) { - char *name = NULL; - - tDecoderInit(&dc, pBlock->data, msgIter.schemaLen); - if (tStartDecode(&dc) < 0) { - code = TSDB_CODE_INVALID_MSG; - return code; - } - - if (tDecodeI32v(&dc, NULL) < 0) { - code = TSDB_CODE_INVALID_MSG; - return code; - } - if (tDecodeCStr(&dc, &name) < 0) { - code = TSDB_CODE_INVALID_MSG; - return code; - } - - uid = metaGetTableEntryUidByName(pVnode->pMeta, name); - if (uid == 0) { - uid = tGenIdPI64(); - } - *(int64_t *)(dc.data + dc.pos) = uid; - *(int64_t *)(dc.data + dc.pos + 8) = ctime; - pBlock->uid = htobe64(uid); - - tEndDecode(&dc); - tDecoderClear(&dc); - } + int64_t uid; + if (submitTbData.flags & SUBMIT_REQ_AUTO_CREATE_TABLE) { + code = vnodePreprocessCreateTableReq(pVnode, pCoder, ctime, &uid); + TSDB_CHECK_CODE(code, lino, _exit); + } + + // submit data + if (tDecodeI64(pCoder, &submitTbData.suid) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } + + if (submitTbData.flags & SUBMIT_REQ_AUTO_CREATE_TABLE) { + *(int64_t *)(pCoder->data + pCoder->pos) = uid; + pCoder->pos += sizeof(int64_t); + } else { + if (tDecodeI64(pCoder, &submitTbData.uid) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } + } + + if (tDecodeI32v(pCoder, &submitTbData.sver) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } + + // scan and check + TSKEY now = ctime; + if (pVnode->config.tsdbCfg.precision == TSDB_TIME_PRECISION_MICRO) { + now *= 1000; + } else if (pVnode->config.tsdbCfg.precision == TSDB_TIME_PRECISION_NANO) { + now *= 1000000; + } + TSKEY minKey = now - tsTickPerMin[pVnode->config.tsdbCfg.precision] * pVnode->config.tsdbCfg.keep2; + TSKEY maxKey = tsMaxKeyByPrecision[pVnode->config.tsdbCfg.precision]; + if (submitTbData.flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + uint64_t nColData; + if (tDecodeU64v(pCoder, &nColData) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + SColData colData = {0}; + pCoder->pos += tGetColData(pCoder->data + pCoder->pos, &colData); + + if (colData.flag != HAS_VALUE) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + for (int32_t iRow = 0; iRow < colData.nVal; iRow++) { + if (((TSKEY *)colData.pData)[iRow] < minKey || ((TSKEY *)colData.pData)[iRow] > maxKey) { + code = TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE; + goto _exit; } + } + } else { + uint64_t nRow; + if (tDecodeU64v(pCoder, &nRow) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } - } break; - case TDMT_VND_DELETE: { - int32_t size; - int32_t ret; - uint8_t *pCont; - SEncoder *pCoder = &(SEncoder){0}; - SDeleteRes res = {0}; - SReadHandle handle = { - .meta = pVnode->pMeta, .config = &pVnode->config, .vnode = pVnode, .pMsgCb = &pVnode->msgCb}; - - code = qWorkerProcessDeleteMsg(&handle, pVnode->pQuery, pMsg, &res); - if (code) { - goto _err; + for (int32_t iRow = 0; iRow < nRow; ++iRow) { + SRow *pRow = (SRow *)(pCoder->data + pCoder->pos); + pCoder->pos += pRow->len; + + if (pRow->ts < minKey || pRow->ts > maxKey) { + code = TSDB_CODE_TDB_TIMESTAMP_OUT_OF_RANGE; + goto _exit; } + } + } + + tEndDecode(pCoder); + +_exit: + return code; +} +static int32_t vnodePreProcessSubmitMsg(SVnode *pVnode, SRpcMsg *pMsg) { + int32_t code = 0; + int32_t lino = 0; + + SDecoder *pCoder = &(SDecoder){0}; + + if (taosHton64(((SSubmitReq2Msg *)pMsg->pCont)->version) != 1) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } - // malloc and encode - tEncodeSize(tEncodeDeleteRes, &res, size, ret); - pCont = rpcMallocCont(size + sizeof(SMsgHead)); + tDecoderInit(pCoder, (uint8_t *)pMsg->pCont + sizeof(SSubmitReq2Msg), pMsg->contLen - sizeof(SSubmitReq2Msg)); - ((SMsgHead *)pCont)->contLen = size + sizeof(SMsgHead); - ((SMsgHead *)pCont)->vgId = TD_VID(pVnode); + if (tStartDecode(pCoder) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } + + uint64_t nSubmitTbData; + if (tDecodeU64v(pCoder, &nSubmitTbData) < 0) { + code = TSDB_CODE_INVALID_MSG; + TSDB_CHECK_CODE(code, lino, _exit); + } + + int64_t ctime = taosGetTimestampMs(); + for (int32_t i = 0; i < nSubmitTbData; i++) { + code = vnodePreProcessSubmitTbData(pVnode, pCoder, ctime); + TSDB_CHECK_CODE(code, lino, _exit); + } + + tEndDecode(pCoder); - tEncoderInit(pCoder, pCont + sizeof(SMsgHead), size); - tEncodeDeleteRes(pCoder, &res); - tEncoderClear(pCoder); +_exit: + tDecoderClear(pCoder); + return code; +} - rpcFreeCont(pMsg->pCont); - pMsg->pCont = pCont; - pMsg->contLen = size + sizeof(SMsgHead); +static int32_t vnodePreProcessDeleteMsg(SVnode *pVnode, SRpcMsg *pMsg) { + int32_t code = 0; - taosArrayDestroy(res.uidList); + int32_t size; + int32_t ret; + uint8_t *pCont; + SEncoder *pCoder = &(SEncoder){0}; + SDeleteRes res = {0}; + SReadHandle handle = {.meta = pVnode->pMeta, .config = &pVnode->config, .vnode = pVnode, .pMsgCb = &pVnode->msgCb}; + + code = qWorkerProcessDeleteMsg(&handle, pVnode->pQuery, pMsg, &res); + if (code) goto _exit; + + // malloc and encode + tEncodeSize(tEncodeDeleteRes, &res, size, ret); + pCont = rpcMallocCont(size + sizeof(SMsgHead)); + + ((SMsgHead *)pCont)->contLen = size + sizeof(SMsgHead); + ((SMsgHead *)pCont)->vgId = TD_VID(pVnode); + + tEncoderInit(pCoder, pCont + sizeof(SMsgHead), size); + tEncodeDeleteRes(pCoder, &res); + tEncoderClear(pCoder); + + rpcFreeCont(pMsg->pCont); + pMsg->pCont = pCont; + pMsg->contLen = size + sizeof(SMsgHead); + + taosArrayDestroy(res.uidList); + +_exit: + return code; +} + +int32_t vnodePreProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg) { + int32_t code = 0; + + switch (pMsg->msgType) { + case TDMT_VND_CREATE_TABLE: { + code = vnodePreProcessCreateTableMsg(pVnode, pMsg); + } break; + case TDMT_VND_SUBMIT: { + code = vnodePreProcessSubmitMsg(pVnode, pMsg); + } break; + case TDMT_VND_DELETE: { + code = vnodePreProcessDeleteMsg(pVnode, pMsg); } break; default: break; } - return code; - -_err: - vError("vgId%d, preprocess request failed since %s", TD_VID(pVnode), tstrerror(code)); +_exit: + if (code) { + vError("vgId%d failed to preprocess write request since %s, msg type:%d", TD_VID(pVnode), tstrerror(code), + pMsg->msgType); + } return code; } @@ -172,12 +307,6 @@ int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp int32_t len; int32_t ret; - if (!pVnode->inUse) { - terrno = TSDB_CODE_VND_NO_AVAIL_BUFPOOL; - vError("vgId:%d, not ready to write since %s", TD_VID(pVnode), terrstr()); - return -1; - } - if (version <= pVnode->state.applied) { vError("vgId:%d, duplicate write request. version: %" PRId64 ", applied: %" PRId64 "", TD_VID(pVnode), version, pVnode->state.applied); @@ -191,8 +320,8 @@ int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp ASSERT(pVnode->state.applyTerm <= pMsg->info.conn.applyTerm); ASSERT(pVnode->state.applied + 1 == version); - pVnode->state.applied = version; - pVnode->state.applyTerm = pMsg->info.conn.applyTerm; + atomic_store_64(&pVnode->state.applied, version); + atomic_store_64(&pVnode->state.applyTerm, pMsg->info.conn.applyTerm); if (!syncUtilUserCommit(pMsg->msgType)) goto _exit; @@ -271,7 +400,7 @@ int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp } break; case TDMT_STREAM_TASK_DEPLOY: { - if (tqProcessTaskDeployReq(pVnode->pTq, version, pReq, len) < 0) { + if (pVnode->restored && tqProcessTaskDeployReq(pVnode->pTq, version, pReq, len) < 0) { goto _err; } } break; @@ -293,15 +422,21 @@ int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp case TDMT_VND_ALTER_CONFIRM: vnodeProcessAlterConfirmReq(pVnode, version, pReq, len, pRsp); break; - case TDMT_VND_ALTER_HASHRANGE: - vnodeProcessAlterHashRangeReq(pVnode, version, pReq, len, pRsp); - break; case TDMT_VND_ALTER_CONFIG: vnodeProcessAlterConfigReq(pVnode, version, pReq, len, pRsp); break; case TDMT_VND_COMMIT: needCommit = true; break; + case TDMT_VND_CREATE_INDEX: + vnodeProcessCreateIndexReq(pVnode, version, pReq, len, pRsp); + break; + case TDMT_VND_DROP_INDEX: + vnodeProcessDropIndexReq(pVnode, version, pReq, len, pRsp); + break; + case TDMT_VND_COMPACT: + vnodeProcessCompactVnodeReq(pVnode, version, pReq, len, pRsp); + goto _exit; default: vError("vgId:%d, unprocessed msg, %d", TD_VID(pVnode), pMsg->msgType); return -1; @@ -312,18 +447,18 @@ int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp walApplyVer(pVnode->pWal, version); - /*vInfo("vgId:%d, push msg begin", pVnode->config.vgId);*/ if (tqPushMsg(pVnode->pTq, pMsg->pCont, pMsg->contLen, pMsg->msgType, version) < 0) { - /*vInfo("vgId:%d, push msg end", pVnode->config.vgId);*/ vError("vgId:%d, failed to push msg to TQ since %s", TD_VID(pVnode), tstrerror(terrno)); return -1; } - /*vInfo("vgId:%d, push msg end", pVnode->config.vgId);*/ // commit if need if (needCommit) { vInfo("vgId:%d, commit at version %" PRId64, TD_VID(pVnode), version); - vnodeAsyncCommit(pVnode); + if (vnodeAsyncCommit(pVnode) < 0) { + vError("vgId:%d, failed to vnode async commit since %s.", TD_VID(pVnode), tstrerror(terrno)); + goto _err; + } // start a new one if (vnodeBegin(pVnode) < 0) { @@ -351,12 +486,16 @@ int32_t vnodePreprocessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) { int32_t vnodeProcessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) { vTrace("message in vnode query queue is processing"); - // if ((pMsg->msgType == TDMT_SCH_QUERY) && !vnodeIsLeader(pVnode)) { - if ((pMsg->msgType == TDMT_SCH_QUERY) && !syncIsReadyForRead(pVnode->sync)) { + if ((pMsg->msgType == TDMT_SCH_QUERY || pMsg->msgType == TDMT_VND_TMQ_CONSUME) && !syncIsReadyForRead(pVnode->sync)) { vnodeRedirectRpcMsg(pVnode, pMsg, terrno); return 0; } + if (pMsg->msgType == TDMT_VND_TMQ_CONSUME && !pVnode->restored) { + vnodeRedirectRpcMsg(pVnode, pMsg, TSDB_CODE_SYN_RESTORING); + return 0; + } + SReadHandle handle = {.meta = pVnode->pMeta, .config = &pVnode->config, .vnode = pVnode, .pMsgCb = &pVnode->msgCb}; switch (pMsg->msgType) { case TDMT_SCH_QUERY: @@ -364,6 +503,8 @@ int32_t vnodeProcessQueryMsg(SVnode *pVnode, SRpcMsg *pMsg) { return qWorkerProcessQueryMsg(&handle, pVnode->pQuery, pMsg, 0); case TDMT_SCH_QUERY_CONTINUE: return qWorkerProcessCQueryMsg(&handle, pVnode->pQuery, pMsg, 0); + case TDMT_VND_TMQ_CONSUME: + return tqProcessPollReq(pVnode->pTq, pMsg); default: vError("unknown msg type:%d in query queue", pMsg->msgType); return TSDB_CODE_APP_ERROR; @@ -375,16 +516,10 @@ int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo) { if ((pMsg->msgType == TDMT_SCH_FETCH || pMsg->msgType == TDMT_VND_TABLE_META || pMsg->msgType == TDMT_VND_TABLE_CFG || pMsg->msgType == TDMT_VND_BATCH_META) && !syncIsReadyForRead(pVnode->sync)) { - // !vnodeIsLeader(pVnode)) { vnodeRedirectRpcMsg(pVnode, pMsg, terrno); return 0; } - if (pMsg->msgType == TDMT_VND_TMQ_CONSUME && !pVnode->restored) { - vnodeRedirectRpcMsg(pVnode, pMsg, TSDB_CODE_SYN_RESTORING); - return 0; - } - switch (pMsg->msgType) { case TDMT_SCH_FETCH: case TDMT_SCH_MERGE_FETCH: @@ -403,14 +538,10 @@ int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo) { return vnodeGetTableCfg(pVnode, pMsg, true); case TDMT_VND_BATCH_META: return vnodeGetBatchMeta(pVnode, pMsg); - case TDMT_VND_TMQ_CONSUME: - return tqProcessPollReq(pVnode->pTq, pMsg); case TDMT_STREAM_TASK_RUN: return tqProcessTaskRunReq(pVnode->pTq, pMsg); -#if 1 case TDMT_STREAM_TASK_DISPATCH: return tqProcessTaskDispatchReq(pVnode->pTq, pMsg, true); -#endif case TDMT_STREAM_TASK_CHECK: return tqProcessStreamTaskCheckReq(pVnode->pTq, pMsg); case TDMT_STREAM_TASK_DISPATCH_RSP: @@ -449,6 +580,7 @@ void vnodeUpdateMetaRsp(SVnode *pVnode, STableMetaRsp *pMetaRsp) { pMetaRsp->precision = pVnode->config.tsdbCfg.precision; } +extern int32_t vnodeAsyncRentention(SVnode *pVnode, int64_t now); static int32_t vnodeProcessTrimReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { int32_t code = 0; SVTrimDbReq trimReq = {0}; @@ -462,11 +594,9 @@ static int32_t vnodeProcessTrimReq(SVnode *pVnode, int64_t version, void *pReq, vInfo("vgId:%d, trim vnode request will be processed, time:%d", pVnode->config.vgId, trimReq.timestamp); // process - code = tsdbDoRetention(pVnode->pTsdb, trimReq.timestamp); - if (code) goto _exit; - - code = smaDoRetention(pVnode->pSma, trimReq.timestamp); - if (code) goto _exit; + vnodeAsyncRentention(pVnode, trimReq.timestamp); + tsem_wait(&pVnode->canCommit); + tsem_post(&pVnode->canCommit); _exit: return code; @@ -491,6 +621,8 @@ static int32_t vnodeProcessDropTtlTbReq(SVnode *pVnode, int64_t version, void *p tqUpdateTbUidList(pVnode->pTq, tbUids, false); } + vnodeAsyncRentention(pVnode, ttlReq.timestamp); + end: taosArrayDestroy(tbUids); return ret; @@ -854,176 +986,415 @@ static int32_t vnodeDebugPrintSingleSubmitMsg(SMeta *pMeta, SSubmitBlk *pBlock, return TSDB_CODE_SUCCESS; } -static int32_t vnodeDebugPrintSubmitMsg(SVnode *pVnode, SSubmitReq *pMsg, const char *tags) { - ASSERT(pMsg != NULL); - SSubmitMsgIter msgIter = {0}; - SMeta *pMeta = pVnode->pMeta; - SSubmitBlk *pBlock = NULL; +typedef struct SSubmitReqConvertCxt { + SSubmitMsgIter msgIter; + SSubmitBlk *pBlock; + SSubmitBlkIter blkIter; + STSRow *pRow; + STSRowIter rowIter; + SSubmitTbData *pTbData; + STSchema *pTbSchema; + SArray *pColValues; +} SSubmitReqConvertCxt; + +static int32_t vnodeResetTableCxt(SMeta *pMeta, SSubmitReqConvertCxt *pCxt) { + taosMemoryFreeClear(pCxt->pTbSchema); + pCxt->pTbSchema = metaGetTbTSchema(pMeta, pCxt->msgIter.suid > 0 ? pCxt->msgIter.suid : pCxt->msgIter.uid, + pCxt->msgIter.sversion, 1); + if (NULL == pCxt->pTbSchema) { + return TSDB_CODE_INVALID_MSG; + } + tdSTSRowIterInit(&pCxt->rowIter, pCxt->pTbSchema); - if (tInitSubmitMsgIter(pMsg, &msgIter) < 0) return -1; - while (true) { - if (tGetSubmitMsgNext(&msgIter, &pBlock) < 0) return -1; - if (pBlock == NULL) break; + tDestroySubmitTbData(pCxt->pTbData, TSDB_MSG_FLG_ENCODE); + if (NULL == pCxt->pTbData) { + pCxt->pTbData = taosMemoryCalloc(1, sizeof(SSubmitTbData)); + if (NULL == pCxt->pTbData) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } + pCxt->pTbData->flags = 0; + pCxt->pTbData->suid = pCxt->msgIter.suid; + pCxt->pTbData->uid = pCxt->msgIter.uid; + pCxt->pTbData->sver = pCxt->msgIter.sversion; + pCxt->pTbData->pCreateTbReq = NULL; + pCxt->pTbData->aRowP = taosArrayInit(128, POINTER_BYTES); + if (NULL == pCxt->pTbData->aRowP) { + return TSDB_CODE_OUT_OF_MEMORY; + } - vnodeDebugPrintSingleSubmitMsg(pMeta, pBlock, &msgIter, tags); + taosArrayDestroy(pCxt->pColValues); + pCxt->pColValues = taosArrayInit(pCxt->pTbSchema->numOfCols, sizeof(SColVal)); + if (NULL == pCxt->pColValues) { + return TSDB_CODE_OUT_OF_MEMORY; + } + for (int32_t i = 0; i < pCxt->pTbSchema->numOfCols; ++i) { + SColVal val = COL_VAL_NONE(pCxt->pTbSchema->columns[i].colId, pCxt->pTbSchema->columns[i].type); + taosArrayPush(pCxt->pColValues, &val); } - return 0; + return TSDB_CODE_SUCCESS; } -static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { - SSubmitReq *pSubmitReq = (SSubmitReq *)pReq; - SSubmitRsp submitRsp = {0}; - SSubmitMsgIter msgIter = {0}; - SSubmitBlk *pBlock = NULL; - SVCreateTbReq createTbReq = {0}; - SDecoder decoder = {0}; - int32_t nRows = 0; - int32_t tsize, ret; - SEncoder encoder = {0}; - SArray *newTbUids = NULL; - SVStatis statis = {0}; - bool tbCreated = false; - terrno = TSDB_CODE_SUCCESS; - - pRsp->code = 0; - pSubmitReq->version = version; - statis.nBatchInsert = 1; - -#ifdef TD_DEBUG_PRINT_ROW - vnodeDebugPrintSubmitMsg(pVnode, pReq, __func__); -#endif +static void vnodeDestroySubmitReqConvertCxt(SSubmitReqConvertCxt *pCxt) { + taosMemoryFreeClear(pCxt->pTbSchema); + tDestroySubmitTbData(pCxt->pTbData, TSDB_MSG_FLG_ENCODE); + taosMemoryFreeClear(pCxt->pTbData); + taosArrayDestroy(pCxt->pColValues); +} - if (tsdbScanAndConvertSubmitMsg(pVnode->pTsdb, pSubmitReq) < 0) { - pRsp->code = terrno; - goto _exit; +static int32_t vnodeCellValConvertToColVal(STColumn *pCol, SCellVal *pCellVal, SColVal *pColVal) { + if (tdValTypeIsNone(pCellVal->valType)) { + pColVal->flag = CV_FLAG_NONE; + return TSDB_CODE_SUCCESS; } - // handle the request - if (tInitSubmitMsgIter(pSubmitReq, &msgIter) < 0) { - pRsp->code = TSDB_CODE_INVALID_MSG; - goto _exit; + if (tdValTypeIsNull(pCellVal->valType)) { + pColVal->flag = CV_FLAG_NULL; + return TSDB_CODE_SUCCESS; } - submitRsp.pArray = taosArrayInit(msgIter.numOfBlocks, sizeof(SSubmitBlkRsp)); - newTbUids = taosArrayInit(msgIter.numOfBlocks, sizeof(int64_t)); - if (!submitRsp.pArray || !newTbUids) { - pRsp->code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; + if (IS_VAR_DATA_TYPE(pCol->type)) { + pColVal->value.nData = varDataLen(pCellVal->val); + pColVal->value.pData = varDataVal(pCellVal->val); + } else if (TSDB_DATA_TYPE_FLOAT == pCol->type) { + float f = GET_FLOAT_VAL(pCellVal->val); + memcpy(&pColVal->value.val, &f, sizeof(f)); + } else if (TSDB_DATA_TYPE_DOUBLE == pCol->type) { + pColVal->value.val = *(int64_t *)pCellVal->val; + } else { + GET_TYPED_DATA(pColVal->value.val, int64_t, pCol->type, pCellVal->val); } - for (;;) { - tGetSubmitMsgNext(&msgIter, &pBlock); - if (pBlock == NULL) break; + pColVal->flag = CV_FLAG_VALUE; + return TSDB_CODE_SUCCESS; +} - SSubmitBlkRsp submitBlkRsp = {0}; - tbCreated = false; +static int32_t vnodeTSRowConvertToColValArray(SSubmitReqConvertCxt *pCxt) { + int32_t code = TSDB_CODE_SUCCESS; + tdSTSRowIterReset(&pCxt->rowIter, pCxt->pRow); + for (int32_t i = 0; TSDB_CODE_SUCCESS == code && i < pCxt->pTbSchema->numOfCols; ++i) { + STColumn *pCol = pCxt->pTbSchema->columns + i; + SCellVal cellVal = {0}; + if (!tdSTSRowIterFetch(&pCxt->rowIter, pCol->colId, pCol->type, &cellVal)) { + break; + } + code = vnodeCellValConvertToColVal(pCol, &cellVal, (SColVal *)taosArrayGet(pCxt->pColValues, i)); + } + return code; +} - // create table for auto create table mode - if (msgIter.schemaLen > 0) { - tDecoderInit(&decoder, pBlock->data, msgIter.schemaLen); - if (tDecodeSVCreateTbReq(&decoder, &createTbReq) < 0) { - pRsp->code = TSDB_CODE_INVALID_MSG; - tDecoderClear(&decoder); - taosArrayDestroy(createTbReq.ctb.tagName); - goto _exit; - } +static int32_t vnodeDecodeCreateTbReq(SSubmitReqConvertCxt *pCxt) { + if (pCxt->msgIter.schemaLen <= 0) { + return TSDB_CODE_SUCCESS; + } - if ((terrno = grantCheck(TSDB_GRANT_TIMESERIES)) < 0) { - pRsp->code = terrno; - tDecoderClear(&decoder); - taosArrayDestroy(createTbReq.ctb.tagName); - goto _exit; + pCxt->pTbData->pCreateTbReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq)); + if (NULL == pCxt->pTbData->pCreateTbReq) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + SDecoder decoder = {0}; + tDecoderInit(&decoder, pCxt->pBlock->data, pCxt->msgIter.schemaLen); + int32_t code = tDecodeSVCreateTbReq(&decoder, pCxt->pTbData->pCreateTbReq); + tDecoderClear(&decoder); + + return code; +} + +static int32_t vnodeSubmitReqConvertToSubmitReq2(SVnode *pVnode, SSubmitReq *pReq, SSubmitReq2 *pReq2) { + pReq2->aSubmitTbData = taosArrayInit(128, sizeof(SSubmitTbData)); + if (NULL == pReq2->aSubmitTbData) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + SSubmitReqConvertCxt cxt = {0}; + + int32_t code = tInitSubmitMsgIter(pReq, &cxt.msgIter); + while (TSDB_CODE_SUCCESS == code) { + code = tGetSubmitMsgNext(&cxt.msgIter, &cxt.pBlock); + if (TSDB_CODE_SUCCESS == code) { + if (NULL == cxt.pBlock) { + break; + } + code = vnodeResetTableCxt(pVnode->pMeta, &cxt); + } + if (TSDB_CODE_SUCCESS == code) { + code = tInitSubmitBlkIter(&cxt.msgIter, cxt.pBlock, &cxt.blkIter); + } + if (TSDB_CODE_SUCCESS == code) { + code = vnodeDecodeCreateTbReq(&cxt); + } + while (TSDB_CODE_SUCCESS == code && (cxt.pRow = tGetSubmitBlkNext(&cxt.blkIter)) != NULL) { + code = vnodeTSRowConvertToColValArray(&cxt); + if (TSDB_CODE_SUCCESS == code) { + SRow **pNewRow = taosArrayReserve(cxt.pTbData->aRowP, 1); + code = tRowBuild(cxt.pColValues, cxt.pTbSchema, pNewRow); } + } + if (TSDB_CODE_SUCCESS == code) { + code = (NULL == taosArrayPush(pReq2->aSubmitTbData, cxt.pTbData) ? TSDB_CODE_OUT_OF_MEMORY : TSDB_CODE_SUCCESS); + } + if (TSDB_CODE_SUCCESS == code) { + taosMemoryFreeClear(cxt.pTbData); + } + } + + vnodeDestroySubmitReqConvertCxt(&cxt); + return code; +} + +static int32_t vnodeRebuildSubmitReqMsg(SSubmitReq2 *pSubmitReq, void **ppMsg) { + int32_t code = TSDB_CODE_SUCCESS; + char *pMsg = NULL; + uint32_t msglen = 0; + tEncodeSize(tEncodeSubmitReq, pSubmitReq, msglen, code); + if (TSDB_CODE_SUCCESS == code) { + pMsg = taosMemoryMalloc(msglen); + if (NULL == pMsg) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + } + if (TSDB_CODE_SUCCESS == code) { + SEncoder encoder; + tEncoderInit(&encoder, pMsg, msglen); + code = tEncodeSubmitReq(&encoder, pSubmitReq); + tEncoderClear(&encoder); + } + if (TSDB_CODE_SUCCESS == code) { + *ppMsg = pMsg; + } + return code; +} + +static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { + int32_t code = 0; + terrno = 0; + + SSubmitReq2 *pSubmitReq = &(SSubmitReq2){0}; + SSubmitRsp2 *pSubmitRsp = &(SSubmitRsp2){0}; + SArray *newTbUids = NULL; + int32_t ret; + SEncoder ec = {0}; + + pRsp->code = TSDB_CODE_SUCCESS; + + void *pAllocMsg = NULL; + SSubmitReq2Msg *pMsg = (SSubmitReq2Msg *)pReq; + if (0 == pMsg->version) { + code = vnodeSubmitReqConvertToSubmitReq2(pVnode, (SSubmitReq *)pMsg, pSubmitReq); + if (TSDB_CODE_SUCCESS == code) { + code = vnodeRebuildSubmitReqMsg(pSubmitReq, &pReq); + } + if (TSDB_CODE_SUCCESS == code) { + pAllocMsg = pReq; + } + if (TSDB_CODE_SUCCESS != code) { + goto _exit; + } + } else { + // decode + pReq = POINTER_SHIFT(pReq, sizeof(SSubmitReq2Msg)); + len -= sizeof(SSubmitReq2Msg); + SDecoder dc = {0}; + tDecoderInit(&dc, pReq, len); + if (tDecodeSubmitReq(&dc, pSubmitReq) < 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + tDecoderClear(&dc); + } - if ((terrno = grantCheck(TSDB_GRANT_TABLE)) < 0) { - pRsp->code = terrno; - tDecoderClear(&decoder); - taosArrayDestroy(createTbReq.ctb.tagName); + // scan + TSKEY now = taosGetTimestamp(pVnode->config.tsdbCfg.precision); + TSKEY minKey = now - tsTickPerMin[pVnode->config.tsdbCfg.precision] * pVnode->config.tsdbCfg.keep2; + TSKEY maxKey = tsMaxKeyByPrecision[pVnode->config.tsdbCfg.precision]; + for (int32_t i = 0; i < TARRAY_SIZE(pSubmitReq->aSubmitTbData); ++i) { + SSubmitTbData *pSubmitTbData = taosArrayGet(pSubmitReq->aSubmitTbData, i); + + if (pSubmitTbData->pCreateTbReq && pSubmitTbData->pCreateTbReq->uid == 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + if (pSubmitTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + if (TARRAY_SIZE(pSubmitTbData->aCol) <= 0) { + code = TSDB_CODE_INVALID_MSG; goto _exit; } - if (metaCreateTable(pVnode->pMeta, version, &createTbReq, &submitBlkRsp.pMeta) < 0) { - if (terrno != TSDB_CODE_TDB_TABLE_ALREADY_EXIST) { - submitBlkRsp.code = terrno; - pRsp->code = terrno; - tDecoderClear(&decoder); - taosArrayDestroy(createTbReq.ctb.tagName); + SColData *pColData = (SColData *)taosArrayGet(pSubmitTbData->aCol, 0); + TSKEY *aKey = (TSKEY *)(pColData->pData); + + for (int32_t iRow = 0; iRow < pColData->nVal; iRow++) { + if (aKey[iRow] < minKey || aKey[iRow] > maxKey || (iRow > 0 && aKey[iRow] <= aKey[iRow - 1])) { + code = TSDB_CODE_INVALID_MSG; + vError("vgId:%d %s failed since %s, version:%" PRId64, TD_VID(pVnode), __func__, tstrerror(terrno), version); goto _exit; } - } else { - if (NULL != submitBlkRsp.pMeta) { - vnodeUpdateMetaRsp(pVnode, submitBlkRsp.pMeta); + } + + } else { + int32_t nRow = TARRAY_SIZE(pSubmitTbData->aRowP); + SRow **aRow = (SRow **)TARRAY_DATA(pSubmitTbData->aRowP); + + for (int32_t iRow = 0; iRow < nRow; ++iRow) { + if (aRow[iRow]->ts < minKey || aRow[iRow]->ts > maxKey || (iRow > 0 && aRow[iRow]->ts <= aRow[iRow - 1]->ts)) { + code = TSDB_CODE_INVALID_MSG; + vError("vgId:%d %s failed since %s, version:%" PRId64, TD_VID(pVnode), __func__, tstrerror(terrno), version); + goto _exit; } + } + } + } + + for (int32_t i = 0; i < TARRAY_SIZE(pSubmitReq->aSubmitTbData); ++i) { + SSubmitTbData *pSubmitTbData = taosArrayGet(pSubmitReq->aSubmitTbData, i); - taosArrayPush(newTbUids, &createTbReq.uid); + if (pSubmitTbData->pCreateTbReq) { + pSubmitTbData->uid = pSubmitTbData->pCreateTbReq->uid; + } else { + SMetaInfo info = {0}; + + code = metaGetInfo(pVnode->pMeta, pSubmitTbData->uid, &info, NULL); + if (code) { + code = TSDB_CODE_TDB_TABLE_NOT_EXIST; + vWarn("vgId:%d, table uid:%" PRId64 " not exists", TD_VID(pVnode), pSubmitTbData->uid); + goto _exit; + } - submitBlkRsp.uid = createTbReq.uid; - submitBlkRsp.tblFName = taosMemoryMalloc(strlen(pVnode->config.dbname) + strlen(createTbReq.name) + 2); - sprintf(submitBlkRsp.tblFName, "%s.%s", pVnode->config.dbname, createTbReq.name); - tbCreated = true; + if (info.suid != pSubmitTbData->suid) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; } - msgIter.uid = createTbReq.uid; - if (createTbReq.type == TSDB_CHILD_TABLE) { - msgIter.suid = createTbReq.ctb.suid; - } else { - msgIter.suid = 0; + if (info.suid) { + metaGetInfo(pVnode->pMeta, info.suid, &info, NULL); } -#ifdef TD_DEBUG_PRINT_ROW - vnodeDebugPrintSingleSubmitMsg(pVnode->pMeta, pBlock, &msgIter, "real uid"); -#endif - tDecoderClear(&decoder); - taosArrayDestroy(createTbReq.ctb.tagName); + if (pSubmitTbData->sver != info.skmVer) { + code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER; + goto _exit; + } } - if (tsdbInsertTableData(pVnode->pTsdb, version, &msgIter, pBlock, &submitBlkRsp) < 0) { - submitBlkRsp.code = terrno; + if (pSubmitTbData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + int32_t nColData = TARRAY_SIZE(pSubmitTbData->aCol); + SColData *aColData = (SColData *)TARRAY_DATA(pSubmitTbData->aCol); + + if (nColData <= 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + if (aColData[0].cid != PRIMARYKEY_TIMESTAMP_COL_ID || aColData[0].type != TSDB_DATA_TYPE_TIMESTAMP || + aColData[0].nVal <= 0) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + + for (int32_t j = 1; j < nColData; j++) { + if (aColData[j].nVal != aColData[0].nVal) { + code = TSDB_CODE_INVALID_MSG; + goto _exit; + } + } } + } - submitRsp.numOfRows += submitBlkRsp.numOfRows; - submitRsp.affectedRows += submitBlkRsp.affectedRows; - if (tbCreated || submitBlkRsp.code) { - taosArrayPush(submitRsp.pArray, &submitBlkRsp); + vDebug("vgId:%d, submit block size %d", TD_VID(pVnode), (int32_t)taosArrayGetSize(pSubmitReq->aSubmitTbData)); + + // loop to handle + for (int32_t i = 0; i < TARRAY_SIZE(pSubmitReq->aSubmitTbData); ++i) { + SSubmitTbData *pSubmitTbData = taosArrayGet(pSubmitReq->aSubmitTbData, i); + + // create table + if (pSubmitTbData->pCreateTbReq) { + // check (TODO: move check to create table) + code = grantCheck(TSDB_GRANT_TIMESERIES); + if (code) goto _exit; + + code = grantCheck(TSDB_GRANT_TABLE); + if (code) goto _exit; + + // alloc if need + if (pSubmitRsp->aCreateTbRsp == NULL && + (pSubmitRsp->aCreateTbRsp = taosArrayInit(TARRAY_SIZE(pSubmitReq->aSubmitTbData), sizeof(SVCreateTbRsp))) == + NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + SVCreateTbRsp *pCreateTbRsp = taosArrayReserve(pSubmitRsp->aCreateTbRsp, 1); + + // create table + if (metaCreateTable(pVnode->pMeta, version, pSubmitTbData->pCreateTbReq, &pCreateTbRsp->pMeta) == 0) { + // create table success + + if (newTbUids == NULL && + (newTbUids = taosArrayInit(TARRAY_SIZE(pSubmitReq->aSubmitTbData), sizeof(int64_t))) == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto _exit; + } + + taosArrayPush(newTbUids, &pSubmitTbData->uid); + + if (pCreateTbRsp->pMeta) { + vnodeUpdateMetaRsp(pVnode, pCreateTbRsp->pMeta); + } + } else { // create table failed + if (terrno != TSDB_CODE_TDB_TABLE_ALREADY_EXIST) { + code = terrno; + goto _exit; + } + terrno = 0; + pSubmitTbData->uid = pSubmitTbData->pCreateTbReq->uid; // update uid if table exist for using below + } } + + // insert data + int32_t affectedRows; + code = tsdbInsertTableData(pVnode->pTsdb, version, pSubmitTbData, &affectedRows); + if (code) goto _exit; + + pSubmitRsp->affectedRows += affectedRows; } + // update the affected table uid list if (taosArrayGetSize(newTbUids) > 0) { vDebug("vgId:%d, add %d table into query table list in handling submit", TD_VID(pVnode), (int32_t)taosArrayGetSize(newTbUids)); + tqUpdateTbUidList(pVnode->pTq, newTbUids, true); } - tqUpdateTbUidList(pVnode->pTq, newTbUids, true); - _exit: - taosArrayDestroy(newTbUids); - tEncodeSize(tEncodeSSubmitRsp, &submitRsp, tsize, ret); - pRsp->pCont = rpcMallocCont(tsize); - pRsp->contLen = tsize; - tEncoderInit(&encoder, pRsp->pCont, tsize); - tEncodeSSubmitRsp(&encoder, &submitRsp); - tEncoderClear(&encoder); - - taosArrayDestroyEx(submitRsp.pArray, tFreeSSubmitBlkRsp); + // message + pRsp->code = code; + tEncodeSize(tEncodeSSubmitRsp2, pSubmitRsp, pRsp->contLen, ret); + pRsp->pCont = rpcMallocCont(pRsp->contLen); + tEncoderInit(&ec, pRsp->pCont, pRsp->contLen); + tEncodeSSubmitRsp2(&ec, pSubmitRsp); + tEncoderClear(&ec); - // TODO: the partial success scenario and the error case - // => If partial success, extract the success submitted rows and reconstruct a new submit msg, and push to level - // 1/level 2. - // TODO: refactor - if ((terrno == TSDB_CODE_SUCCESS) && (pRsp->code == TSDB_CODE_SUCCESS)) { - statis.nBatchInsertSuccess = 1; - tdProcessRSmaSubmit(pVnode->pSma, pReq, STREAM_INPUT__DATA_SUBMIT); + // update statistics + atomic_add_fetch_64(&pVnode->statis.nInsert, pSubmitRsp->affectedRows); + atomic_add_fetch_64(&pVnode->statis.nInsertSuccess, pSubmitRsp->affectedRows); + atomic_add_fetch_64(&pVnode->statis.nBatchInsert, 1); + if (code == 0) { + atomic_add_fetch_64(&pVnode->statis.nBatchInsertSuccess, 1); + tdProcessRSmaSubmit(pVnode->pSma, version, pSubmitReq, pReq, len, STREAM_INPUT__DATA_SUBMIT); } - // N.B. not strict as the following procedure is not atomic - atomic_add_fetch_64(&pVnode->statis.nInsert, submitRsp.numOfRows); - atomic_add_fetch_64(&pVnode->statis.nInsertSuccess, submitRsp.affectedRows); - atomic_add_fetch_64(&pVnode->statis.nBatchInsert, statis.nBatchInsert); - atomic_add_fetch_64(&pVnode->statis.nBatchInsertSuccess, statis.nBatchInsertSuccess); + // clear + taosArrayDestroy(newTbUids); + tDestroySubmitReq(pSubmitReq, 0 == pMsg->version ? TSDB_MSG_FLG_CMPT : TSDB_MSG_FLG_DECODE); + tDestroySSubmitRsp2(pSubmitRsp, TSDB_MSG_FLG_ENCODE); - vDebug("vgId:%d %s done, index:%" PRId64, TD_VID(pVnode), __func__, version); - return 0; + if (code) terrno = code; + + taosMemoryFree(pAllocMsg); + + return code; } static int32_t vnodeProcessCreateTSmaReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { @@ -1085,16 +1456,6 @@ static int32_t vnodeProcessAlterConfirmReq(SVnode *pVnode, int64_t version, void return 0; } -static int32_t vnodeProcessAlterHashRangeReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { - vInfo("vgId:%d, alter hashrange msg will be processed", TD_VID(pVnode)); - - // todo - // 1. stop work - // 2. adjust hash range / compact / remove wals / rename vgroups - // 3. reload sync - return 0; -} - static int32_t vnodeProcessAlterConfigReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { bool walChanged = false; bool tsdbChanged = false; @@ -1106,10 +1467,11 @@ static int32_t vnodeProcessAlterConfigReq(SVnode *pVnode, int64_t version, void } vInfo("vgId:%d, start to alter vnode config, page:%d pageSize:%d buffer:%d szPage:%d szBuf:%" PRIu64 - " cacheLast:%d cacheLastSize:%d days:%d keep0:%d keep1:%d keep2:%d fsync:%d level:%d", + " cacheLast:%d cacheLastSize:%d days:%d keep0:%d keep1:%d keep2:%d fsync:%d level:%d walRetentionPeriod:%d " + "walRetentionSize:%d", TD_VID(pVnode), req.pages, req.pageSize, req.buffer, req.pageSize * 1024, (uint64_t)req.buffer * 1024 * 1024, req.cacheLast, req.cacheLastSize, req.daysPerFile, req.daysToKeep0, req.daysToKeep1, req.daysToKeep2, - req.walFsyncPeriod, req.walLevel); + req.walFsyncPeriod, req.walLevel, req.walRetentionPeriod, req.walRetentionSize); if (pVnode->config.cacheLastSize != req.cacheLastSize) { pVnode->config.cacheLastSize = req.cacheLastSize; @@ -1139,13 +1501,21 @@ static int32_t vnodeProcessAlterConfigReq(SVnode *pVnode, int64_t version, void if (pVnode->config.walCfg.fsyncPeriod != req.walFsyncPeriod) { pVnode->config.walCfg.fsyncPeriod = req.walFsyncPeriod; - walChanged = true; } if (pVnode->config.walCfg.level != req.walLevel) { pVnode->config.walCfg.level = req.walLevel; + walChanged = true; + } + if (pVnode->config.walCfg.retentionPeriod != req.walRetentionPeriod) { + pVnode->config.walCfg.retentionPeriod = req.walRetentionPeriod; + walChanged = true; + } + + if (pVnode->config.walCfg.retentionSize != req.walRetentionSize) { + pVnode->config.walCfg.retentionSize = req.walRetentionSize; walChanged = true; } @@ -1170,6 +1540,14 @@ static int32_t vnodeProcessAlterConfigReq(SVnode *pVnode, int64_t version, void } } + if (req.sttTrigger != -1 && req.sttTrigger != pVnode->config.sttTrigger) { + pVnode->config.sttTrigger = req.sttTrigger; + } + + if (req.minRows != -1 && req.minRows != pVnode->config.tsdbCfg.minRows) { + pVnode->config.tsdbCfg.minRows = req.minRows; + } + if (walChanged) { walAlter(pVnode->pWal, &pVnode->config.walCfg); } @@ -1257,3 +1635,59 @@ static int32_t vnodeProcessDeleteReq(SVnode *pVnode, int64_t version, void *pReq _err: return code; } +static int32_t vnodeProcessCreateIndexReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { + SVCreateStbReq req = {0}; + SDecoder dc = {0}; + + pRsp->msgType = TDMT_VND_CREATE_INDEX_RSP; + pRsp->code = TSDB_CODE_SUCCESS; + pRsp->pCont = NULL; + pRsp->contLen = 0; + + tDecoderInit(&dc, pReq, len); + // decode req + if (tDecodeSVCreateStbReq(&dc, &req) < 0) { + terrno = TSDB_CODE_INVALID_MSG; + tDecoderClear(&dc); + return -1; + } + if (metaAddIndexToSTable(pVnode->pMeta, version, &req) < 0) { + pRsp->code = terrno; + goto _err; + } + tDecoderClear(&dc); + return 0; +_err: + tDecoderClear(&dc); + return -1; +} +static int32_t vnodeProcessDropIndexReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { + SDropIndexReq req = {0}; + pRsp->msgType = TDMT_VND_DROP_INDEX_RSP; + pRsp->code = TSDB_CODE_SUCCESS; + pRsp->pCont = NULL; + pRsp->contLen = 0; + + if (tDeserializeSDropIdxReq(pReq, len, &req)) { + terrno = TSDB_CODE_INVALID_MSG; + return -1; + } + + if (metaDropIndexFromSTable(pVnode->pMeta, version, &req) < 0) { + pRsp->code = terrno; + return -1; + } + return TSDB_CODE_SUCCESS; +} + +extern int32_t vnodeProcessCompactVnodeReqImpl(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp); + +static int32_t vnodeProcessCompactVnodeReq(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { + return vnodeProcessCompactVnodeReqImpl(pVnode, version, pReq, len, pRsp); +} + +#ifndef TD_ENTERPRISE +int32_t vnodeProcessCompactVnodeReqImpl(SVnode *pVnode, int64_t version, void *pReq, int32_t len, SRpcMsg *pRsp) { + return 0; +} +#endif diff --git a/source/dnode/vnode/src/vnd/vnodeSync.c b/source/dnode/vnode/src/vnd/vnodeSync.c index 6f3788616a5f45e440d07f23b89e3e493d07fa4d..1f958c569f7d6a8dc27e5b467b112c1284d111b0 100644 --- a/source/dnode/vnode/src/vnd/vnodeSync.c +++ b/source/dnode/vnode/src/vnd/vnodeSync.c @@ -129,8 +129,8 @@ static int32_t inline vnodeProposeMsg(SVnode *pVnode, SRpcMsg *pMsg, bool isWeak return code; } -void vnodeProposeCommitOnNeed(SVnode *pVnode) { - if (!vnodeShouldCommit(pVnode)) { +void vnodeProposeCommitOnNeed(SVnode *pVnode, bool atExit) { + if (!vnodeShouldCommit(pVnode, atExit)) { return; } @@ -145,18 +145,20 @@ void vnodeProposeCommitOnNeed(SVnode *pVnode) { rpcMsg.pCont = pHead; rpcMsg.info.noResp = 1; + vInfo("vgId:%d, propose vnode commit", pVnode->config.vgId); bool isWeak = false; - if (vnodeProposeMsg(pVnode, &rpcMsg, isWeak) < 0) { - vTrace("vgId:%d, failed to propose vnode commit since %s", pVnode->config.vgId, terrstr()); - goto _out; - } - vInfo("vgId:%d, proposed vnode commit", pVnode->config.vgId); + if (!atExit) { + if (vnodeProposeMsg(pVnode, &rpcMsg, isWeak) < 0) { + vTrace("vgId:%d, failed to propose vnode commit since %s", pVnode->config.vgId, terrstr()); + } + rpcFreeCont(rpcMsg.pCont); + rpcMsg.pCont = NULL; + } else { + tmsgPutToQueue(&pVnode->msgCb, WRITE_QUEUE, &rpcMsg); + } -_out: vnodeUpdCommitSched(pVnode); - rpcFreeCont(rpcMsg.pCont); - rpcMsg.pCont = NULL; } #if BATCH_ENABLE @@ -219,7 +221,7 @@ void vnodeProposeWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) isWeak, isBlock, msg, numOfMsgs, arrayPos, pMsg->info.handle); if (!pVnode->restored) { - vGError("vgId:%d, msg:%p failed to process since restore not finished", vgId, pMsg); + vGError("vgId:%d, msg:%p failed to process since restore not finished, type:%s", vgId, pMsg, TMSG_INFO(pMsg->msgType)); terrno = TSDB_CODE_SYN_RESTORING; vnodeHandleProposeError(pVnode, pMsg, TSDB_CODE_SYN_RESTORING); rpcFreeCont(pMsg->pCont); @@ -228,7 +230,7 @@ void vnodeProposeWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) } if (pMsgArr == NULL || pIsWeakArr == NULL) { - vGError("vgId:%d, msg:%p failed to process since out of memory", vgId, pMsg); + vGError("vgId:%d, msg:%p failed to process since out of memory, type:%s", vgId, pMsg, TMSG_INFO(pMsg->msgType)); terrno = TSDB_CODE_OUT_OF_MEMORY; vnodeHandleProposeError(pVnode, pMsg, terrno); rpcFreeCont(pMsg->pCont); @@ -236,7 +238,8 @@ void vnodeProposeWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) continue; } - vnodeProposeCommitOnNeed(pVnode); + bool atExit = false; + vnodeProposeCommitOnNeed(pVnode, atExit); code = vnodePreProcessWriteMsg(pVnode, pMsg); if (code != 0) { @@ -281,18 +284,19 @@ void vnodeProposeWriteMsg(SQueueInfo *pInfo, STaosQall *qall, int32_t numOfMsgs) vnodeIsMsgBlock(pMsg->msgType), msg, numOfMsgs, pMsg->info.handle); if (!pVnode->restored) { - vGError("vgId:%d, msg:%p failed to process since restore not finished", vgId, pMsg); + vGError("vgId:%d, msg:%p failed to process since restore not finished, type:%s", vgId, pMsg, TMSG_INFO(pMsg->msgType)); vnodeHandleProposeError(pVnode, pMsg, TSDB_CODE_SYN_RESTORING); rpcFreeCont(pMsg->pCont); taosFreeQitem(pMsg); continue; } - vnodeProposeCommitOnNeed(pVnode); + bool atExit = false; + vnodeProposeCommitOnNeed(pVnode, atExit); code = vnodePreProcessWriteMsg(pVnode, pMsg); if (code != 0) { - vGError("vgId:%d, msg:%p failed to pre-process since %s", vgId, pMsg, terrstr()); + vGError("vgId:%d, msg:%p failed to pre-process since %s", vgId, pMsg, tstrerror(code)); if (terrno != 0) code = terrno; vnodeHandleProposeError(pVnode, pMsg, code); rpcFreeCont(pMsg->pCont); @@ -378,7 +382,7 @@ static int32_t vnodeSyncEqCtrlMsg(const SMsgCb *msgcb, SRpcMsg *pMsg) { return -1; } - int32_t code = tmsgPutToQueue(msgcb, SYNC_CTRL_QUEUE, pMsg); + int32_t code = tmsgPutToQueue(msgcb, SYNC_RD_QUEUE, pMsg); if (code != 0) { rpcFreeCont(pMsg->pCont); pMsg->pCont = NULL; @@ -433,7 +437,23 @@ static int32_t vnodeSyncApplyMsg(const SSyncFSM *pFsm, SRpcMsg *pMsg, const SFsm } static int32_t vnodeSyncCommitMsg(const SSyncFSM *pFsm, SRpcMsg *pMsg, const SFsmCbMeta *pMeta) { - return vnodeSyncApplyMsg(pFsm, pMsg, pMeta); + if (pMsg->code == 0) { + return vnodeSyncApplyMsg(pFsm, pMsg, pMeta); + } + + const STraceId *trace = &pMsg->info.traceId; + SVnode *pVnode = pFsm->data; + vnodePostBlockMsg(pVnode, pMsg); + + SRpcMsg rsp = {.code = pMsg->code, .info = pMsg->info}; + if (rsp.info.handle != NULL) { + tmsgSendRsp(&rsp); + } + + vGTrace("vgId:%d, msg:%p is freed, code:0x%x index:%" PRId64, TD_VID(pVnode), pMsg, rsp.code, pMeta->index); + rpcFreeCont(pMsg->pCont); + pMsg->pCont = NULL; + return 0; } static int32_t vnodeSyncPreCommitMsg(const SSyncFSM *pFsm, SRpcMsg *pMsg, const SFsmCbMeta *pMeta) { @@ -443,6 +463,11 @@ static int32_t vnodeSyncPreCommitMsg(const SSyncFSM *pFsm, SRpcMsg *pMsg, const return 0; } +static SyncIndex vnodeSyncAppliedIndex(const SSyncFSM *pFSM) { + SVnode *pVnode = pFSM->data; + return atomic_load_64(&pVnode->state.applied); +} + static void vnodeSyncRollBackMsg(const SSyncFSM *pFsm, SRpcMsg *pMsg, const SFsmCbMeta *pMeta) { SVnode *pVnode = pFsm->data; vTrace("vgId:%d, rollback-cb is excuted, fsm:%p, index:%" PRId64 ", weak:%d, code:%d, state:%d %s, type:%s", @@ -505,24 +530,37 @@ static int32_t vnodeSnapshotDoWrite(const SSyncFSM *pFsm, void *pWriter, void *p return code; } -static void vnodeRestoreFinish(const SSyncFSM *pFsm) { +static void vnodeRestoreFinish(const SSyncFSM *pFsm, const SyncIndex commitIdx) { SVnode *pVnode = pFsm->data; + SyncIndex appliedIdx = -1; do { - int32_t itemSize = tmsgGetQueueSize(&pVnode->msgCb, pVnode->config.vgId, APPLY_QUEUE); - if (itemSize == 0) { - vInfo("vgId:%d, apply queue is empty, restore finish", pVnode->config.vgId); + appliedIdx = vnodeSyncAppliedIndex(pFsm); + ASSERT(appliedIdx <= commitIdx); + if (appliedIdx == commitIdx) { + vInfo("vgId:%d, no items to be applied, restore finish", pVnode->config.vgId); break; } else { - vInfo("vgId:%d, restore not finish since %d items in apply queue", pVnode->config.vgId, itemSize); + vInfo("vgId:%d, restore not finish since %" PRId64 " items to be applied. commit-index:%" PRId64 + ", applied-index:%" PRId64, + pVnode->config.vgId, commitIdx - appliedIdx, commitIdx, appliedIdx); taosMsleep(10); } } while (true); - walApplyVer(pVnode->pWal, pVnode->state.applied); + ASSERT(commitIdx == vnodeSyncAppliedIndex(pFsm)); + walApplyVer(pVnode->pWal, commitIdx); pVnode->restored = true; - vInfo("vgId:%d, sync restore finished", pVnode->config.vgId); + vInfo("vgId:%d, sync restore finished, start to restore stream tasks by replay wal", pVnode->config.vgId); + + // start to restore all stream tasks + if (tsDisableStream) { + vInfo("vgId:%d, not restore stream tasks, since disabled", pVnode->config.vgId); + } else { + vInfo("vgId:%d start to restore stream tasks", pVnode->config.vgId); + tqStartStreamTasks(pVnode->pTq); + } } static void vnodeBecomeFollower(const SSyncFSM *pFsm) { @@ -569,6 +607,7 @@ static SSyncFSM *vnodeSyncMakeFsm(SVnode *pVnode) { SSyncFSM *pFsm = taosMemoryCalloc(1, sizeof(SSyncFSM)); pFsm->data = pVnode; pFsm->FpCommitCb = vnodeSyncCommitMsg; + pFsm->FpAppliedIndexCb = vnodeSyncAppliedIndex; pFsm->FpPreCommitCb = vnodeSyncPreCommitMsg; pFsm->FpRollBackCb = vnodeSyncRollBackMsg; pFsm->FpGetSnapshotInfo = vnodeSyncGetSnapshotInfo; @@ -635,7 +674,7 @@ int32_t vnodeSyncStart(SVnode *pVnode) { } void vnodeSyncPreClose(SVnode *pVnode) { - vInfo("vgId:%d, pre close sync", pVnode->config.vgId); + vInfo("vgId:%d, sync pre close", pVnode->config.vgId); syncLeaderTransfer(pVnode->sync); syncPreStop(pVnode->sync); @@ -649,7 +688,7 @@ void vnodeSyncPreClose(SVnode *pVnode) { } void vnodeSyncPostClose(SVnode *pVnode) { - vInfo("vgId:%d, post close sync", pVnode->config.vgId); + vInfo("vgId:%d, sync post close", pVnode->config.vgId); syncPostStop(pVnode->sync); } diff --git a/source/libs/CMakeLists.txt b/source/libs/CMakeLists.txt index 72459f4d35437c704f7021d14126f6166388bbe5..e18be94ace94c35a486a7ebd8c54e4eb3ae2e009 100644 --- a/source/libs/CMakeLists.txt +++ b/source/libs/CMakeLists.txt @@ -1,5 +1,4 @@ add_subdirectory(tdb) -add_subdirectory(cache) add_subdirectory(transport) add_subdirectory(wal) add_subdirectory(monitor) diff --git a/source/libs/cache/CMakeLists.txt b/source/libs/cache/CMakeLists.txt deleted file mode 100644 index dc631e5bfd4126fe2edbc057668430043a43f31c..0000000000000000000000000000000000000000 --- a/source/libs/cache/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -aux_source_directory(src CACHE_SRC) -add_library(cache STATIC ${CACHE_SRC}) -target_include_directories( - cache - PUBLIC "${TD_SOURCE_DIR}/include/libs/cache" - PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" -) \ No newline at end of file diff --git a/source/libs/catalog/CMakeLists.txt b/source/libs/catalog/CMakeLists.txt index 632034d6b60ef0454ae53ba799534934608b9b07..bc56ff4c7f766862f2f70057d09af56d2a9f8895 100644 --- a/source/libs/catalog/CMakeLists.txt +++ b/source/libs/catalog/CMakeLists.txt @@ -8,9 +8,9 @@ target_include_directories( target_link_libraries( catalog - PRIVATE os util transport qcom + PRIVATE os util transport qcom nodes ) if(${BUILD_TEST}) ADD_SUBDIRECTORY(test) -endif(${BUILD_TEST}) \ No newline at end of file +endif(${BUILD_TEST}) diff --git a/source/libs/catalog/inc/catalogInt.h b/source/libs/catalog/inc/catalogInt.h index 41c7eca7f09ad01c59f694c64f6b554f0a705157..02935844871077fb28aa7c38a9db8addcd35e271 100644 --- a/source/libs/catalog/inc/catalogInt.h +++ b/source/libs/catalog/inc/catalogInt.h @@ -43,6 +43,33 @@ extern "C" { #define CTG_BATCH_FETCH 1 +typedef enum { + CTG_CI_CLUSTER = 0, + CTG_CI_DNODE, + CTG_CI_QNODE, + CTG_CI_DB, + CTG_CI_DB_VGROUP, + CTG_CI_DB_CFG, + CTG_CI_DB_INFO, + CTG_CI_STABLE_META, + CTG_CI_NTABLE_META, + CTG_CI_CTABLE_META, + CTG_CI_SYSTABLE_META, + CTG_CI_OTHERTABLE_META, + CTG_CI_TBL_SMA, + CTG_CI_TBL_CFG, + CTG_CI_TBL_TAG, + CTG_CI_INDEX_INFO, + CTG_CI_USER, + CTG_CI_UDF, + CTG_CI_SVR_VER, + CTG_CI_MAX_VALUE, +} CTG_CACHE_ITEM; + +#define CTG_CI_FLAG_LEVEL_GLOBAL (1) +#define CTG_CI_FLAG_LEVEL_CLUSTER (1 << 1) +#define CTG_CI_FLAG_LEVEL_DB (1 << 2) + enum { CTG_READ = 1, CTG_WRITE, @@ -55,6 +82,7 @@ enum { enum { CTG_OP_UPDATE_VGROUP = 0, + CTG_OP_UPDATE_DB_CFG, CTG_OP_UPDATE_TB_META, CTG_OP_DROP_DB_CACHE, CTG_OP_DROP_DB_VGROUP, @@ -76,14 +104,15 @@ typedef enum { CTG_TASK_GET_DB_INFO, CTG_TASK_GET_TB_META, CTG_TASK_GET_TB_HASH, - CTG_TASK_GET_TB_INDEX, + CTG_TASK_GET_TB_SMA_INDEX, CTG_TASK_GET_TB_CFG, - CTG_TASK_GET_INDEX, + CTG_TASK_GET_INDEX_INFO, CTG_TASK_GET_UDF, CTG_TASK_GET_USER, CTG_TASK_GET_SVR_VER, CTG_TASK_GET_TB_META_BATCH, CTG_TASK_GET_TB_HASH_BATCH, + CTG_TASK_GET_TB_TAG, } CTG_TASK_TYPE; typedef enum { @@ -96,9 +125,29 @@ typedef struct SCtgDebug { bool cacheEnable; bool apiEnable; bool metaEnable; + bool statEnable; uint32_t showCachePeriodSec; } SCtgDebug; +typedef struct SCtgCacheStat { + uint64_t cacheNum[CTG_CI_MAX_VALUE]; + uint64_t cacheHit[CTG_CI_MAX_VALUE]; + uint64_t cacheNHit[CTG_CI_MAX_VALUE]; +} SCtgCacheStat; + +typedef struct SCtgAuthReq { + SRequestConnInfo* pConn; + SUserAuthInfo* pRawReq; + SGetUserAuthRsp authInfo; + AUTH_TYPE singleType; + bool onlyCache; +} SCtgAuthReq; + +typedef struct SCtgAuthRsp { + SUserAuthRes* pRawRes; + bool metaNotExists; +} SCtgAuthRsp; + typedef struct SCtgTbCacheInfo { bool inCache; uint64_t dbId; @@ -106,6 +155,11 @@ typedef struct SCtgTbCacheInfo { int32_t tbType; } SCtgTbCacheInfo; +typedef struct SCtgTbMetaParam { + SName* pName; + int32_t flag; +} SCtgTbMetaParam; + typedef struct SCtgTbMetaCtx { SCtgTbCacheInfo tbInfo; int32_t vgId; @@ -140,6 +194,11 @@ typedef struct SCtgTbCfgCtx { SVgroupInfo* pVgInfo; } SCtgTbCfgCtx; +typedef struct SCtgTbTagCtx { + SName* pName; + SVgroupInfo* pVgInfo; +} SCtgTbTagCtx; + typedef struct SCtgDbVgCtx { char dbFName[TSDB_DB_FNAME_LEN]; } SCtgDbVgCtx; @@ -190,19 +249,26 @@ typedef struct SCtgVgCache { SDBVgInfo* vgInfo; } SCtgVgCache; +typedef struct SCtgCfgCache { + SRWLatch cfgLock; + SDbCfgInfo* cfgInfo; +} SCtgCfgCache; + typedef struct SCtgDBCache { - SRWLatch dbLock; // RC between destroy tbCache/stbCache and all reads - uint64_t dbId; - int8_t deleted; - SCtgVgCache vgCache; - SHashObj* tbCache; // key:tbname, value:SCtgTbCache - SHashObj* stbCache; // key:suid, value:char* + SRWLatch dbLock; // RC between destroy tbCache/stbCache and all reads + uint64_t dbId; + int8_t deleted; + SCtgVgCache vgCache; + SCtgCfgCache cfgCache; + SHashObj* tbCache; // key:tbname, value:SCtgTbCache + SHashObj* stbCache; // key:suid, value:char* + uint64_t dbCacheNum[CTG_CI_MAX_VALUE]; } SCtgDBCache; typedef struct SCtgRentSlot { SRWLatch lock; bool needSort; - SArray* meta; // element is SDbVgVersion or SSTableVersion + SArray* meta; // element is SDbCacheInfo or SSTableVersion } SCtgRentSlot; typedef struct SCtgRentMgmt { @@ -214,21 +280,18 @@ typedef struct SCtgRentMgmt { } SCtgRentMgmt; typedef struct SCtgUserAuth { - int32_t version; - SRWLatch lock; - bool superUser; - SHashObj* createdDbs; - SHashObj* readDbs; - SHashObj* writeDbs; + SRWLatch lock; + SGetUserAuthRsp userAuth; } SCtgUserAuth; typedef struct SCatalog { - uint64_t clusterId; - bool stopUpdate; - SHashObj* userCache; // key:user, value:SCtgUserAuth - SHashObj* dbCache; // key:dbname, value:SCtgDBCache - SCtgRentMgmt dbRent; - SCtgRentMgmt stbRent; + uint64_t clusterId; + bool stopUpdate; + SHashObj* userCache; // key:user, value:SCtgUserAuth + SHashObj* dbCache; // key:dbname, value:SCtgDBCache + SCtgRentMgmt dbRent; + SCtgRentMgmt stbRent; + SCtgCacheStat cacheStat; } SCatalog; typedef struct SCtgBatch { @@ -260,6 +323,7 @@ typedef struct SCtgJob { catalogCallback userFp; int32_t tbMetaNum; int32_t tbHashNum; + int32_t tbTagNum; int32_t dbVgNum; int32_t udfNum; int32_t qnodeNum; @@ -302,6 +366,7 @@ typedef struct SCtgSubRes { struct SCtgTask { CTG_TASK_TYPE type; + bool subTask; int32_t taskId; SCtgJob* pJob; void* taskCtx; @@ -347,25 +412,9 @@ typedef struct SCtgRuntimeStat { uint64_t numOfOpAbort; uint64_t numOfOpEnqueue; uint64_t numOfOpDequeue; + uint64_t numOfOpClearCache; } SCtgRuntimeStat; -typedef struct SCtgCacheStat { - uint64_t numOfCluster; - uint64_t numOfDb; - uint64_t numOfTbl; - uint64_t numOfStb; - uint64_t numOfUser; - uint64_t numOfVgHit; - uint64_t numOfVgMiss; - uint64_t numOfMetaHit; - uint64_t numOfMetaMiss; - uint64_t numOfIndexHit; - uint64_t numOfIndexMiss; - uint64_t numOfUserHit; - uint64_t numOfUserMiss; - uint64_t numOfClear; -} SCtgCacheStat; - typedef struct SCatalogStat { SCtgApiStat api; SCtgRuntimeStat runtime; @@ -383,6 +432,13 @@ typedef struct SCtgUpdateVgMsg { SDBVgInfo* dbInfo; } SCtgUpdateVgMsg; +typedef struct SCtgUpdateDbCfgMsg { + SCatalog* pCtg; + char dbFName[TSDB_DB_FNAME_LEN]; + uint64_t dbId; + SDbCfgInfo* cfgInfo; +} SCtgUpdateDbCfgMsg; + typedef struct SCtgUpdateTbMetaMsg { SCatalog* pCtg; STableMetaOutput* pMeta; @@ -472,7 +528,7 @@ typedef struct SCatalogMgmt { SCtgQueue queue; TdThread updateThread; SHashObj* pCluster; // key: clusterId, value: SCatalog* - SCatalogStat stat; + SCatalogStat statInfo; SCatalogCfg cfg; } SCatalogMgmt; @@ -485,7 +541,12 @@ typedef struct SCtgOperation { ctgOpFunc func; } SCtgOperation; -#define CTG_AUTH_READ(_t) ((_t) == AUTH_TYPE_READ || (_t) == AUTH_TYPE_READ_OR_WRITE) +typedef struct SCtgCacheItemInfo { + char* name; + int32_t flag; +} SCtgCacheItemInfo; + +#define CTG_AUTH_READ(_t) ((_t) == AUTH_TYPE_READ || (_t) == AUTH_TYPE_READ_OR_WRITE) #define CTG_AUTH_WRITE(_t) ((_t) == AUTH_TYPE_WRITE || (_t) == AUTH_TYPE_READ_OR_WRITE) #define CTG_QUEUE_INC() atomic_add_fetch_64(&gCtgMgmt.queue.qRemainNum, 1) @@ -495,9 +556,89 @@ typedef struct SCtgOperation { #define CTG_STAT_DEC(_item, _n) atomic_sub_fetch_64(&(_item), _n) #define CTG_STAT_GET(_item) atomic_load_64(&(_item)) -#define CTG_RT_STAT_INC(item, n) (CTG_STAT_INC(gCtgMgmt.stat.runtime.item, n)) -#define CTG_CACHE_STAT_INC(item, n) (CTG_STAT_INC(gCtgMgmt.stat.cache.item, n)) -#define CTG_CACHE_STAT_DEC(item, n) (CTG_STAT_DEC(gCtgMgmt.stat.cache.item, n)) +#define CTG_DB_NUM_INC(_item) dbCache->dbCacheNum[_item] += 1 +#define CTG_DB_NUM_DEC(_item) dbCache->dbCacheNum[_item] -= 1 +#define CTG_DB_NUM_SET(_item) dbCache->dbCacheNum[_item] = 1 +#define CTG_DB_NUM_RESET(_item) dbCache->dbCacheNum[_item] = 0 + +#define CTG_STAT_API_INC(item, n) (CTG_STAT_INC(gCtgMgmt.statInfo.api.item, n)) +#define CTG_STAT_RT_INC(item, n) (CTG_STAT_INC(gCtgMgmt.statInfo.runtime.item, n)) +#define CTG_STAT_NUM_INC(item, n) (CTG_STAT_INC(gCtgMgmt.statInfo.cache.cacheNum[item], n)) +#define CTG_STAT_NUM_DEC(item, n) (CTG_STAT_DEC(gCtgMgmt.statInfo.cache.cacheNum[item], n)) +#define CTG_STAT_HIT_INC(item, n) (CTG_STAT_INC(gCtgMgmt.statInfo.cache.cacheHit[item], n)) +#define CTG_STAT_HIT_DEC(item, n) (CTG_STAT_DEC(gCtgMgmt.statInfo.cache.cacheHit[item], n)) +#define CTG_STAT_NHIT_INC(item, n) (CTG_STAT_INC(gCtgMgmt.statInfo.cache.cacheNHit[item], n)) +#define CTG_STAT_NHIT_DEC(item, n) (CTG_STAT_DEC(gCtgMgmt.statInfo.cache.cacheNHit[item], n)) + +#define CTG_CACHE_NUM_INC(item, n) (CTG_STAT_INC(pCtg->cacheStat.cacheNum[item], n)) +#define CTG_CACHE_NUM_DEC(item, n) (CTG_STAT_DEC(pCtg->cacheStat.cacheNum[item], n)) +#define CTG_CACHE_HIT_INC(item, n) (CTG_STAT_INC(pCtg->cacheStat.cacheHit[item], n)) +#define CTG_CACHE_NHIT_INC(item, n) (CTG_STAT_INC(pCtg->cacheStat.cacheNHit[item], n)) + +#define CTG_META_NUM_INC(type) \ + do { \ + switch (type) { \ + case TSDB_SUPER_TABLE: \ + CTG_DB_NUM_INC(CTG_CI_STABLE_META); \ + break; \ + case TSDB_CHILD_TABLE: \ + CTG_DB_NUM_INC(CTG_CI_CTABLE_META); \ + break; \ + case TSDB_NORMAL_TABLE: \ + CTG_DB_NUM_INC(CTG_CI_NTABLE_META); \ + break; \ + case TSDB_SYSTEM_TABLE: \ + CTG_DB_NUM_INC(CTG_CI_SYSTABLE_META); \ + break; \ + default: \ + CTG_DB_NUM_INC(CTG_CI_OTHERTABLE_META); \ + break; \ + } \ + } while (0) + +#define CTG_META_NUM_DEC(type) \ + do { \ + switch (type) { \ + case TSDB_SUPER_TABLE: \ + CTG_DB_NUM_DEC(CTG_CI_STABLE_META); \ + break; \ + case TSDB_CHILD_TABLE: \ + CTG_DB_NUM_DEC(CTG_CI_CTABLE_META); \ + break; \ + case TSDB_NORMAL_TABLE: \ + CTG_DB_NUM_DEC(CTG_CI_NTABLE_META); \ + break; \ + case TSDB_SYSTEM_TABLE: \ + CTG_DB_NUM_DEC(CTG_CI_SYSTABLE_META); \ + break; \ + default: \ + CTG_DB_NUM_DEC(CTG_CI_OTHERTABLE_META); \ + break; \ + } \ + } while (0) + +#define CTG_META_HIT_INC(type) \ + do { \ + switch (type) { \ + case TSDB_SUPER_TABLE: \ + CTG_CACHE_HIT_INC(CTG_CI_STABLE_META, 1); \ + break; \ + case TSDB_CHILD_TABLE: \ + CTG_CACHE_HIT_INC(CTG_CI_CTABLE_META, 1); \ + break; \ + case TSDB_NORMAL_TABLE: \ + CTG_CACHE_HIT_INC(CTG_CI_NTABLE_META, 1); \ + break; \ + case TSDB_SYSTEM_TABLE: \ + CTG_CACHE_HIT_INC(CTG_CI_SYSTABLE_META, 1); \ + break; \ + default: \ + CTG_CACHE_HIT_INC(CTG_CI_OTHERTABLE_META, 1); \ + break; \ + } \ + } while (0) + +#define CTG_META_NHIT_INC() CTG_CACHE_NHIT_INC(CTG_CI_OTHERTABLE_META, 1) #define CTG_IS_META_NULL(type) ((type) == META_TYPE_NULL_TABLE) #define CTG_IS_META_CTABLE(type) ((type) == META_TYPE_CTABLE) @@ -510,6 +651,7 @@ typedef struct SCtgOperation { #define CTG_FLAG_SYS_DB 0x8 #define CTG_FLAG_FORCE_UPDATE 0x10 #define CTG_FLAG_ONLY_CACHE 0x20 +#define CTG_FLAG_SYNC_OP 0x40 #define CTG_FLAG_SET(_flag, _v) ((_flag) |= (_v)) @@ -557,7 +699,6 @@ typedef struct SCtgOperation { #define ctgTaskDebug(param, ...) qDebug("QID:%" PRIx64 " CTG:%p " param, pTask->pJob->queryId, pCtg, __VA_ARGS__) #define ctgTaskTrace(param, ...) qTrace("QID:%" PRIx64 " CTG:%p " param, pTask->pJob->queryId, pCtg, __VA_ARGS__) - #define CTG_LOCK_DEBUG(...) \ do { \ if (gCTGDebug.lockEnable) { \ @@ -579,38 +720,38 @@ typedef struct SCtgOperation { #define TD_RWLATCH_WRITE_FLAG_COPY 0x40000000 -#define CTG_LOCK(type, _lock) \ - do { \ - if (CTG_READ == (type)) { \ - assert(atomic_load_32((_lock)) >= 0); \ - CTG_LOCK_DEBUG("CTG RLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - taosRLockLatch(_lock); \ - CTG_LOCK_DEBUG("CTG RLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) > 0); \ - } else { \ - assert(atomic_load_32((_lock)) >= 0); \ - CTG_LOCK_DEBUG("CTG WLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - taosWLockLatch(_lock); \ - CTG_LOCK_DEBUG("CTG WLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY); \ - } \ +#define CTG_LOCK(type, _lock) \ + do { \ + if (CTG_READ == (type)) { \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value before read lock"); \ + CTG_LOCK_DEBUG("CTG RLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + taosRLockLatch(_lock); \ + CTG_LOCK_DEBUG("CTG RLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + ASSERTS(atomic_load_32((_lock)) > 0, "invalid lock value after read lock"); \ + } else { \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value before write lock"); \ + CTG_LOCK_DEBUG("CTG WLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + taosWLockLatch(_lock); \ + CTG_LOCK_DEBUG("CTG WLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + ASSERTS(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY, "invalid lock value after write lock"); \ + } \ } while (0) -#define CTG_UNLOCK(type, _lock) \ - do { \ - if (CTG_READ == (type)) { \ - assert(atomic_load_32((_lock)) > 0); \ - CTG_LOCK_DEBUG("CTG RULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - taosRUnLockLatch(_lock); \ - CTG_LOCK_DEBUG("CTG RULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) >= 0); \ - } else { \ - assert(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY); \ - CTG_LOCK_DEBUG("CTG WULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - taosWUnLockLatch(_lock); \ - CTG_LOCK_DEBUG("CTG WULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) >= 0); \ - } \ +#define CTG_UNLOCK(type, _lock) \ + do { \ + if (CTG_READ == (type)) { \ + ASSERTS(atomic_load_32((_lock)) > 0, "invalid lock value before read unlock"); \ + CTG_LOCK_DEBUG("CTG RULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + taosRUnLockLatch(_lock); \ + CTG_LOCK_DEBUG("CTG RULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value after read unlock"); \ + } else { \ + ASSERTS(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY, "invalid lock value before write unlock"); \ + CTG_LOCK_DEBUG("CTG WULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + taosWUnLockLatch(_lock); \ + CTG_LOCK_DEBUG("CTG WULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value after write unlock"); \ + } \ } while (0) #define CTG_ERR_RET(c) \ @@ -682,13 +823,16 @@ typedef struct SCtgOperation { void ctgdShowTableMeta(SCatalog* pCtg, const char* tbName, STableMeta* p); void ctgdShowClusterCache(SCatalog* pCtg); int32_t ctgdShowCacheInfo(void); +int32_t ctgdShowStatInfo(void); int32_t ctgRemoveTbMetaFromCache(SCatalog* pCtg, SName* pTableName, bool syncReq); int32_t ctgGetTbMetaFromCache(SCatalog* pCtg, SCtgTbMetaCtx* ctx, STableMeta** pTableMeta); int32_t ctgGetTbMetasFromCache(SCatalog* pCtg, SRequestConnInfo* pConn, SCtgTbMetasCtx* ctx, int32_t dbIdx, int32_t* fetchIdx, int32_t baseResIdx, SArray* pList); +void* ctgCloneDbCfgInfo(void* pSrc); int32_t ctgOpUpdateVgroup(SCtgCacheOperation* action); +int32_t ctgOpUpdateDbCfg(SCtgCacheOperation *operation); int32_t ctgOpUpdateTbMeta(SCtgCacheOperation* action); int32_t ctgOpDropDbCache(SCtgCacheOperation* action); int32_t ctgOpDropDbVgroup(SCtgCacheOperation* action); @@ -703,13 +847,14 @@ int32_t ctgTbMetaExistInCache(SCatalog* pCtg, char* dbFName, char* tbName, int32 int32_t ctgReadTbMetaFromCache(SCatalog* pCtg, SCtgTbMetaCtx* ctx, STableMeta** pTableMeta); int32_t ctgReadTbVerFromCache(SCatalog* pCtg, SName* pTableName, int32_t* sver, int32_t* tver, int32_t* tbType, uint64_t* suid, char* stbName); -int32_t ctgChkAuthFromCache(SCatalog* pCtg, char* user, char* dbFName, AUTH_TYPE type, bool* inCache, bool* pass); +int32_t ctgChkAuthFromCache(SCatalog* pCtg, SUserAuthInfo* pReq, bool* inCache, SCtgAuthRsp* pRes); int32_t ctgDropDbCacheEnqueue(SCatalog* pCtg, const char* dbFName, int64_t dbId); int32_t ctgDropDbVgroupEnqueue(SCatalog* pCtg, const char* dbFName, bool syncReq); int32_t ctgDropStbMetaEnqueue(SCatalog* pCtg, const char* dbFName, int64_t dbId, const char* stbName, uint64_t suid, bool syncReq); int32_t ctgDropTbMetaEnqueue(SCatalog* pCtg, const char* dbFName, int64_t dbId, const char* tbName, bool syncReq); int32_t ctgUpdateVgroupEnqueue(SCatalog* pCtg, const char* dbFName, int64_t dbId, SDBVgInfo* dbInfo, bool syncReq); +int32_t ctgUpdateDbCfgEnqueue(SCatalog *pCtg, const char *dbFName, int64_t dbId, SDbCfgInfo *cfgInfo, bool syncOp); int32_t ctgUpdateTbMetaEnqueue(SCatalog* pCtg, STableMetaOutput* output, bool syncReq); int32_t ctgUpdateUserEnqueue(SCatalog* pCtg, SGetUserAuthRsp* pAuth, bool syncReq); int32_t ctgUpdateVgEpsetEnqueue(SCatalog* pCtg, char* dbFName, int32_t vgId, SEpSet* pEpSet); @@ -776,13 +921,14 @@ void ctgFreeHandleImpl(SCatalog* pCtg); int32_t ctgGetVgInfoFromHashValue(SCatalog* pCtg, SDBVgInfo* dbInfo, const SName* pTableName, SVgroupInfo* pVgroup); int32_t ctgGetVgInfosFromHashValue(SCatalog* pCtg, SCtgTaskReq* tReq, SDBVgInfo* dbInfo, SCtgTbHashsCtx* pCtx, char* dbFName, SArray* pNames, bool update); -int32_t ctgGetVgIdsFromHashValue(SCatalog* pCtg, SDBVgInfo* dbInfo, char* dbFName, const char* pTbs[], int32_t tbNum, int32_t* vgId); +int32_t ctgGetVgIdsFromHashValue(SCatalog* pCtg, SDBVgInfo* dbInfo, char* dbFName, const char* pTbs[], int32_t tbNum, + int32_t* vgId); void ctgResetTbMetaTask(SCtgTask* pTask); void ctgFreeDbCache(SCtgDBCache* dbCache); int32_t ctgStbVersionSortCompare(const void* key1, const void* key2); -int32_t ctgDbVgVersionSortCompare(const void* key1, const void* key2); +int32_t ctgDbCacheInfoSortCompare(const void* key1, const void* key2); int32_t ctgStbVersionSearchCompare(const void* key1, const void* key2); -int32_t ctgDbVgVersionSearchCompare(const void* key1, const void* key2); +int32_t ctgDbCacheInfoSearchCompare(const void* key1, const void* key2); void ctgFreeSTableMetaOutput(STableMetaOutput* pOutput); int32_t ctgUpdateMsgCtx(SCtgMsgCtx* pCtx, int32_t reqType, void* out, char* target); int32_t ctgAddMsgCtx(SArray* pCtxs, int32_t reqType, void* out, char* target); @@ -797,19 +943,32 @@ void ctgFreeQNode(SCtgQNode* node); void ctgClearHandle(SCatalog* pCtg); void ctgFreeTbCacheImpl(SCtgTbCache* pCache); int32_t ctgRemoveTbMeta(SCatalog* pCtg, SName* pTableName); -int32_t ctgGetTbHashVgroup(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName, SVgroupInfo* pVgroup, bool* exists); +int32_t ctgGetTbHashVgroup(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName, SVgroupInfo* pVgroup, + bool* exists); SName* ctgGetFetchName(SArray* pNames, SCtgFetch* pFetch); -int32_t ctgdGetOneHandle(SCatalog **pHandle); +int32_t ctgdGetOneHandle(SCatalog** pHandle); int ctgVgInfoComp(const void* lp, const void* rp); int32_t ctgMakeVgArray(SDBVgInfo* dbInfo); -int32_t ctgAcquireVgMetaFromCache(SCatalog *pCtg, const char *dbFName, const char *tbName, SCtgDBCache **pDb, SCtgTbCache **pTb); -int32_t ctgCopyTbMeta(SCatalog *pCtg, SCtgTbMetaCtx *ctx, SCtgDBCache **pDb, SCtgTbCache **pTb, STableMeta **pTableMeta, char* dbFName); -void ctgReleaseVgMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, SCtgTbCache *pCache); -void ctgReleaseTbMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, SCtgTbCache *pCache); - -extern SCatalogMgmt gCtgMgmt; -extern SCtgDebug gCTGDebug; -extern SCtgAsyncFps gCtgAsyncFps[]; +int32_t ctgChkSetAuthRes(SCatalog *pCtg, SCtgAuthReq *req, SCtgAuthRsp* res); +int32_t ctgReadDBCfgFromCache(SCatalog *pCtg, const char* dbFName, SDbCfgInfo* pDbCfg); + +int32_t ctgAcquireVgMetaFromCache(SCatalog* pCtg, const char* dbFName, const char* tbName, SCtgDBCache** pDb, + SCtgTbCache** pTb); +int32_t ctgCopyTbMeta(SCatalog* pCtg, SCtgTbMetaCtx* ctx, SCtgDBCache** pDb, SCtgTbCache** pTb, STableMeta** pTableMeta, + char* dbFName); +void ctgReleaseVgMetaToCache(SCatalog* pCtg, SCtgDBCache* dbCache, SCtgTbCache* pCache); +void ctgReleaseTbMetaToCache(SCatalog* pCtg, SCtgDBCache* dbCache, SCtgTbCache* pCache); +void ctgGetGlobalCacheStat(SCtgCacheStat* pStat); +int32_t ctgChkSetAuthRes(SCatalog* pCtg, SCtgAuthReq* req, SCtgAuthRsp* res); +int32_t ctgGetTbMeta(SCatalog* pCtg, SRequestConnInfo* pConn, SCtgTbMetaCtx* ctx, STableMeta** pTableMeta); +int32_t ctgGetCachedStbNameFromSuid(SCatalog* pCtg, char* dbFName, uint64_t suid, char **stbName); +int32_t ctgGetTbTagCb(SCtgTask* pTask); +int32_t ctgGetUserCb(SCtgTask* pTask); + +extern SCatalogMgmt gCtgMgmt; +extern SCtgDebug gCTGDebug; +extern SCtgAsyncFps gCtgAsyncFps[]; +extern SCtgCacheItemInfo gCtgStatItem[CTG_CI_MAX_VALUE]; #ifdef __cplusplus } diff --git a/source/libs/catalog/src/catalog.c b/source/libs/catalog/src/catalog.c index f9a218835ea77d4a20aa1b7ac8086187c995c561..0deeafda9f1228828e413f4c4c471deab7e41f27 100644 --- a/source/libs/catalog/src/catalog.c +++ b/source/libs/catalog/src/catalog.c @@ -208,7 +208,7 @@ int32_t ctgGetTbMeta(SCatalog* pCtg, SRequestConnInfo* pConn, SCtgTbMetaCtx* ctx } while (true) { - CTG_ERR_JRET(ctgRefreshTbMeta(pCtg, pConn, ctx, &output, false)); + CTG_ERR_JRET(ctgRefreshTbMeta(pCtg, pConn, ctx, &output, ctx->flag & CTG_FLAG_SYNC_OP)); if (CTG_IS_META_TABLE(output->metaType)) { *pTableMeta = output->tbMeta; @@ -319,14 +319,13 @@ _return: CTG_RET(code); } -int32_t ctgChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, const char* user, const char* dbFName, AUTH_TYPE type, - bool* pass, bool* exists) { +int32_t ctgChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, SUserAuthInfo *pReq, SUserAuthRes* pRes, bool* exists) { bool inCache = false; int32_t code = 0; + SCtgAuthRsp rsp = {0}; + rsp.pRawRes = pRes; - *pass = false; - - CTG_ERR_RET(ctgChkAuthFromCache(pCtg, (char*)user, (char*)dbFName, type, &inCache, pass)); + CTG_ERR_RET(ctgChkAuthFromCache(pCtg, pReq, &inCache, &rsp)); if (inCache) { if (exists) { @@ -339,30 +338,22 @@ int32_t ctgChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, const char* user, co return TSDB_CODE_SUCCESS; } - SGetUserAuthRsp authRsp = {0}; - CTG_ERR_RET(ctgGetUserDbAuthFromMnode(pCtg, pConn, user, &authRsp, NULL)); + SCtgAuthReq req = {0}; + req.pRawReq = pReq; + req.pConn = pConn; + req.onlyCache = exists ? true : false; + CTG_ERR_RET(ctgGetUserDbAuthFromMnode(pCtg, pConn, pReq->user, &req.authInfo, NULL)); - if (authRsp.superAuth) { - *pass = true; - goto _return; - } - - if (authRsp.createdDbs && taosHashGet(authRsp.createdDbs, dbFName, strlen(dbFName))) { - *pass = true; - goto _return; - } - - if (CTG_AUTH_READ(type) && authRsp.readDbs && taosHashGet(authRsp.readDbs, dbFName, strlen(dbFName))) { - *pass = true; - } else if (CTG_AUTH_WRITE(type) && authRsp.writeDbs && taosHashGet(authRsp.writeDbs, dbFName, strlen(dbFName))) { - *pass = true; + CTG_ERR_JRET(ctgChkSetAuthRes(pCtg, &req, &rsp)); + if (rsp.metaNotExists && exists) { + *exists = false; } _return: - ctgUpdateUserEnqueue(pCtg, &authRsp, false); + ctgUpdateUserEnqueue(pCtg, &req.authInfo, false); - return TSDB_CODE_SUCCESS; + CTG_RET(code); } int32_t ctgGetTbType(SCatalog* pCtg, SRequestConnInfo* pConn, SName* pTableName, int32_t* tbType) { @@ -438,6 +429,48 @@ int32_t ctgGetTbCfg(SCatalog* pCtg, SRequestConnInfo* pConn, SName* pTableName, CTG_RET(TSDB_CODE_SUCCESS); } +int32_t ctgGetTbTag(SCatalog* pCtg, SRequestConnInfo* pConn, SName* pTableName, SArray** pRes) { + SVgroupInfo vgroupInfo = {0}; + STableCfg* pCfg = NULL; + int32_t code = 0; + + CTG_ERR_RET(ctgGetTbHashVgroup(pCtg, pConn, pTableName, &vgroupInfo, NULL)); + CTG_ERR_RET(ctgGetTableCfgFromVnode(pCtg, pConn, pTableName, &vgroupInfo, &pCfg, NULL)); + + if (NULL == pCfg->pTags || pCfg->tagsLen <= 0) { + ctgError("invalid tag in tbCfg rsp, pTags:%p, len:%d", pCfg->pTags, pCfg->tagsLen); + CTG_ERR_JRET(TSDB_CODE_INVALID_MSG); + } + + SArray* pTagVals = NULL; + STag* pTag = (STag*)pCfg->pTags; + + if (tTagIsJson(pTag)) { + pTagVals = taosArrayInit(1, sizeof(STagVal)); + if (NULL == pTagVals) { + CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + } + + char* pJson = parseTagDatatoJson(pTag); + STagVal tagVal; + tagVal.cid = 0; + tagVal.type = TSDB_DATA_TYPE_JSON; + tagVal.pData = pJson; + tagVal.nData = strlen(pJson); + taosArrayPush(pTagVals, &tagVal); + } else { + CTG_ERR_JRET(tTagToValArray((const STag*)pCfg->pTags, &pTagVals)); + } + + *pRes = pTagVals; + +_return: + + tFreeSTableCfgRsp((STableCfgRsp*)pCfg); + + CTG_RET(code); +} + int32_t ctgGetTbDistVgInfo(SCatalog* pCtg, SRequestConnInfo* pConn, SName* pTableName, SArray** pVgList) { STableMeta* tbMeta = NULL; int32_t code = 0; @@ -635,6 +668,23 @@ _return: CTG_RET(code); } +int32_t ctgGetDBCfg(SCatalog* pCtg, SRequestConnInfo* pConn, const char* dbFName, SDbCfgInfo* pDbCfg) { + CTG_ERR_RET(ctgReadDBCfgFromCache(pCtg, dbFName, pDbCfg)); + + if (pDbCfg->cfgVersion < 0) { + CTG_ERR_RET(ctgGetDBCfgFromMnode(pCtg, pConn, dbFName, pDbCfg, NULL)); + SDbCfgInfo *pCfg = ctgCloneDbCfgInfo(pDbCfg); + if (NULL == pCfg) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + CTG_ERR_RET(ctgUpdateDbCfgEnqueue(pCtg, dbFName, pDbCfg->dbId, pCfg, false)); + } + + return TSDB_CODE_SUCCESS; +} + + int32_t catalogInit(SCatalogCfg* cfg) { if (gCtgMgmt.pCluster) { qError("catalog already initialized"); @@ -721,10 +771,13 @@ int32_t catalogGetHandle(uint64_t clusterId, SCatalog** catalogHandle) { if (ctg && (*ctg)) { *catalogHandle = *ctg; + CTG_STAT_HIT_INC(CTG_CI_CLUSTER, 1); qDebug("got catalog handle from cache, clusterId:0x%" PRIx64 ", CTG:%p", clusterId, *ctg); CTG_API_LEAVE(TSDB_CODE_SUCCESS); } + CTG_STAT_NHIT_INC(CTG_CI_CLUSTER, 1); + clusterCtg = taosMemoryCalloc(1, sizeof(SCatalog)); if (NULL == clusterCtg) { qError("calloc %d failed", (int32_t)sizeof(SCatalog)); @@ -768,7 +821,7 @@ int32_t catalogGetHandle(uint64_t clusterId, SCatalog** catalogHandle) { *catalogHandle = clusterCtg; - CTG_CACHE_STAT_INC(numOfCluster, 1); + CTG_STAT_NUM_INC(CTG_CI_CLUSTER, 1); CTG_API_LEAVE(TSDB_CODE_SUCCESS); @@ -922,6 +975,23 @@ _return: CTG_API_LEAVE(code); } +int32_t catalogUpdateDbCfg(SCatalog* pCtg, const char* dbFName, uint64_t dbId, SDbCfgInfo* cfgInfo) { + CTG_API_ENTER(); + + int32_t code = 0; + + if (NULL == pCtg || NULL == dbFName || NULL == cfgInfo) { + freeDbCfgInfo(cfgInfo); + CTG_ERR_JRET(TSDB_CODE_CTG_INVALID_INPUT); + } + + code = ctgUpdateDbCfgEnqueue(pCtg, dbFName, dbId, cfgInfo, false); + +_return: + + CTG_API_LEAVE(code); +} + int32_t catalogRemoveDB(SCatalog* pCtg, const char* dbFName, uint64_t dbId) { CTG_API_ENTER(); @@ -1301,6 +1371,7 @@ int32_t catalogGetQnodeList(SCatalog* pCtg, SRequestConnInfo* pConn, SArray* pQn CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT); } + CTG_CACHE_NHIT_INC(CTG_CI_QNODE, 1); CTG_ERR_JRET(ctgGetQnodeListFromMnode(pCtg, pConn, pQnodeList, NULL)); _return: @@ -1316,6 +1387,7 @@ int32_t catalogGetDnodeList(SCatalog* pCtg, SRequestConnInfo* pConn, SArray** pD CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT); } + CTG_CACHE_NHIT_INC(CTG_CI_DNODE, 1); CTG_ERR_JRET(ctgGetDnodeListFromMnode(pCtg, pConn, pDnodeList, NULL)); _return: @@ -1333,14 +1405,14 @@ int32_t catalogGetExpiredSTables(SCatalog* pCtg, SSTableVersion** stables, uint3 CTG_API_LEAVE(ctgMetaRentGet(&pCtg->stbRent, (void**)stables, num, sizeof(SSTableVersion))); } -int32_t catalogGetExpiredDBs(SCatalog* pCtg, SDbVgVersion** dbs, uint32_t* num) { +int32_t catalogGetExpiredDBs(SCatalog* pCtg, SDbCacheInfo** dbs, uint32_t* num) { CTG_API_ENTER(); if (NULL == pCtg || NULL == dbs || NULL == num) { CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT); } - CTG_API_LEAVE(ctgMetaRentGet(&pCtg->dbRent, (void**)dbs, num, sizeof(SDbVgVersion))); + CTG_API_LEAVE(ctgMetaRentGet(&pCtg->dbRent, (void**)dbs, num, sizeof(SDbCacheInfo))); } int32_t catalogGetExpiredUsers(SCatalog* pCtg, SUserAuthVersion** users, uint32_t* num) { @@ -1368,7 +1440,7 @@ int32_t catalogGetExpiredUsers(SCatalog* pCtg, SUserAuthVersion** users, uint32_ void* key = taosHashGetKey(pAuth, &len); strncpy((*users)[i].user, key, len); (*users)[i].user[len] = 0; - (*users)[i].version = pAuth->version; + (*users)[i].version = pAuth->userAuth.version; ++i; if (i >= *num) { taosHashCancelIterate(pCtg->userCache, pAuth); @@ -1388,7 +1460,7 @@ int32_t catalogGetDBCfg(SCatalog* pCtg, SRequestConnInfo* pConn, const char* dbF CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT); } - CTG_API_LEAVE(ctgGetDBCfgFromMnode(pCtg, pConn, dbFName, pDbCfg, NULL)); + CTG_API_LEAVE(ctgGetDBCfg(pCtg, pConn, dbFName, pDbCfg)); } int32_t catalogGetIndexMeta(SCatalog* pCtg, SRequestConnInfo* pConn, const char* indexName, SIndexInfo* pInfo) { @@ -1416,6 +1488,21 @@ _return: CTG_API_LEAVE(code); } +int32_t catalogGetTableTag(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName, SArray** pRes) { + CTG_API_ENTER(); + + if (NULL == pCtg || NULL == pConn || NULL == pTableName || NULL == pRes) { + CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT); + } + + int32_t code = 0; + CTG_ERR_JRET(ctgGetTbTag(pCtg, pConn, (SName*)pTableName, pRes)); + +_return: + + CTG_API_LEAVE(code); +} + int32_t catalogRefreshGetTableCfg(SCatalog* pCtg, SRequestConnInfo* pConn, const SName* pTableName, STableCfg** pCfg) { CTG_API_ENTER(); @@ -1440,6 +1527,8 @@ int32_t catalogGetUdfInfo(SCatalog* pCtg, SRequestConnInfo* pConn, const char* f CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT); } + CTG_CACHE_NHIT_INC(CTG_CI_UDF, 1); + int32_t code = 0; CTG_ERR_JRET(ctgGetUdfInfoFromMnode(pCtg, pConn, funcName, pInfo, NULL)); @@ -1448,32 +1537,30 @@ _return: CTG_API_LEAVE(code); } -int32_t catalogChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, const char* user, const char* dbFName, AUTH_TYPE type, - bool* pass) { +int32_t catalogChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, SUserAuthInfo *pAuth, SUserAuthRes* pRes) { CTG_API_ENTER(); - if (NULL == pCtg || NULL == pConn || NULL == user || NULL == dbFName || NULL == pass) { + if (NULL == pCtg || NULL == pConn || NULL == pAuth || NULL == pRes) { CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT); } int32_t code = 0; - CTG_ERR_JRET(ctgChkAuth(pCtg, pConn, user, dbFName, type, pass, NULL)); + CTG_ERR_JRET(ctgChkAuth(pCtg, pConn, pAuth, pRes, NULL)); _return: CTG_API_LEAVE(code); } -int32_t catalogChkAuthFromCache(SCatalog* pCtg, const char* user, const char* dbFName, AUTH_TYPE type, - bool* pass, bool* exists) { +int32_t catalogChkAuthFromCache(SCatalog* pCtg, SUserAuthInfo *pAuth, SUserAuthRes* pRes, bool* exists) { CTG_API_ENTER(); - if (NULL == pCtg || NULL == user || NULL == dbFName || NULL == pass || NULL == exists) { + if (NULL == pCtg || NULL == pAuth || NULL == pRes || NULL == exists) { CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT); } int32_t code = 0; - CTG_ERR_JRET(ctgChkAuth(pCtg, NULL, user, dbFName, type, pass, exists)); + CTG_ERR_JRET(ctgChkAuth(pCtg, NULL, pAuth, pRes, exists)); _return: @@ -1488,6 +1575,8 @@ int32_t catalogGetServerVersion(SCatalog* pCtg, SRequestConnInfo* pConn, char** CTG_API_LEAVE(TSDB_CODE_CTG_INVALID_INPUT); } + CTG_CACHE_NHIT_INC(CTG_CI_SVR_VER, 1); + int32_t code = 0; CTG_ERR_JRET(ctgGetSvrVerFromMnode(pCtg, pConn, pVersion, NULL)); diff --git a/source/libs/catalog/src/ctgAsync.c b/source/libs/catalog/src/ctgAsync.c index 89e92b0cc84607ca7d1e0bc4e684261d715f0a2b..2b78b8dd1336174d3442e319578e15178be840da 100644 --- a/source/libs/catalog/src/ctgAsync.c +++ b/source/libs/catalog/src/ctgAsync.c @@ -21,7 +21,8 @@ #include "trpc.h" int32_t ctgInitGetTbMetaTask(SCtgJob* pJob, int32_t taskIdx, void* param) { - SName* name = (SName*)param; + SCtgTbMetaParam* pParam = (SCtgTbMetaParam*)param; + SName* name = pParam->pName; SCtgTask task = {0}; task.type = CTG_TASK_GET_TB_META; @@ -41,7 +42,7 @@ int32_t ctgInitGetTbMetaTask(SCtgJob* pJob, int32_t taskIdx, void* param) { } memcpy(ctx->pName, name, sizeof(*name)); - ctx->flag = CTG_FLAG_UNKNOWN_STB; + ctx->flag = pParam->flag | CTG_FLAG_UNKNOWN_STB; taosArrayPush(pJob->pTasks, &task); @@ -241,7 +242,7 @@ int32_t ctgInitGetIndexTask(SCtgJob* pJob, int32_t taskIdx, void* param) { char* name = (char*)param; SCtgTask task = {0}; - task.type = CTG_TASK_GET_INDEX; + task.type = CTG_TASK_GET_INDEX_INFO; task.taskId = taskIdx; task.pJob = pJob; @@ -330,7 +331,7 @@ int32_t ctgInitGetTbIndexTask(SCtgJob* pJob, int32_t taskIdx, void* param) { SName* name = (SName*)param; SCtgTask task = {0}; - task.type = CTG_TASK_GET_TB_INDEX; + task.type = CTG_TASK_GET_TB_SMA_INDEX; task.taskId = taskIdx; task.pJob = pJob; @@ -386,6 +387,37 @@ int32_t ctgInitGetTbCfgTask(SCtgJob* pJob, int32_t taskIdx, void* param) { return TSDB_CODE_SUCCESS; } +int32_t ctgInitGetTbTagTask(SCtgJob* pJob, int32_t taskIdx, void* param) { + SName* name = (SName*)param; + SCtgTask task = {0}; + + task.type = CTG_TASK_GET_TB_TAG; + task.taskId = taskIdx; + task.pJob = pJob; + + task.taskCtx = taosMemoryCalloc(1, sizeof(SCtgTbTagCtx)); + if (NULL == task.taskCtx) { + CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + } + + SCtgTbTagCtx* ctx = task.taskCtx; + ctx->pName = taosMemoryMalloc(sizeof(*name)); + if (NULL == ctx->pName) { + taosMemoryFree(task.taskCtx); + CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + } + + memcpy(ctx->pName, name, sizeof(*name)); + + taosArrayPush(pJob->pTasks, &task); + + qDebug("QID:0x%" PRIx64 " the %dth task type %s initialized, tbName:%s", pJob->queryId, taskIdx, + ctgTaskTypeStr(task.type), name->tname); + + return TSDB_CODE_SUCCESS; +} + + int32_t ctgHandleForceUpdate(SCatalog* pCtg, int32_t taskNum, SCtgJob* pJob, const SCatalogReq* pReq) { SHashObj* pDb = taosHashInit(taskNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); SHashObj* pTb = taosHashInit(taskNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); @@ -437,6 +469,15 @@ int32_t ctgHandleForceUpdate(SCatalog* pCtg, int32_t taskNum, SCtgJob* pJob, con char dbFName[TSDB_DB_FNAME_LEN]; tNameGetFullDbName(name, dbFName); taosHashPut(pDb, dbFName, strlen(dbFName), dbFName, TSDB_DB_FNAME_LEN); + taosHashPut(pTb, name, sizeof(SName), name, sizeof(SName)); + } + + for (int32_t i = 0; i < pJob->tbTagNum; ++i) { + SName* name = taosArrayGet(pReq->pTableTag, i); + char dbFName[TSDB_DB_FNAME_LEN]; + tNameGetFullDbName(name, dbFName); + taosHashPut(pDb, dbFName, strlen(dbFName), dbFName, TSDB_DB_FNAME_LEN); + taosHashPut(pTb, name, sizeof(SName), name, sizeof(SName)); } char* dbFName = taosHashIterate(pDb, NULL); @@ -505,9 +546,10 @@ int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo* pConn, SCtgJob** job, const int32_t dbInfoNum = (int32_t)taosArrayGetSize(pReq->pDbInfo); int32_t tbIndexNum = (int32_t)taosArrayGetSize(pReq->pTableIndex); int32_t tbCfgNum = (int32_t)taosArrayGetSize(pReq->pTableCfg); + int32_t tbTagNum = (int32_t)taosArrayGetSize(pReq->pTableTag); int32_t taskNum = tbMetaNum + dbVgNum + udfNum + tbHashNum + qnodeNum + dnodeNum + svrVerNum + dbCfgNum + indexNum + - userNum + dbInfoNum + tbIndexNum + tbCfgNum; + userNum + dbInfoNum + tbIndexNum + tbCfgNum + tbTagNum; *job = taosMemoryCalloc(1, sizeof(SCtgJob)); if (NULL == *job) { @@ -537,6 +579,7 @@ int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo* pConn, SCtgJob** job, const pJob->tbIndexNum = tbIndexNum; pJob->tbCfgNum = tbCfgNum; pJob->svrVerNum = svrVerNum; + pJob->tbTagNum = tbTagNum; #if CTG_BATCH_FETCH pJob->pBatchs = @@ -596,7 +639,7 @@ int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo* pConn, SCtgJob** job, const for (int32_t i = 0; i < tbIndexNum; ++i) { SName* name = taosArrayGet(pReq->pTableIndex, i); - CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_TB_INDEX, name, NULL)); + CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_TB_SMA_INDEX, name, NULL)); } for (int32_t i = 0; i < tbCfgNum; ++i) { @@ -604,9 +647,15 @@ int32_t ctgInitJob(SCatalog* pCtg, SRequestConnInfo* pConn, SCtgJob** job, const CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_TB_CFG, name, NULL)); } + for (int32_t i = 0; i < tbTagNum; ++i) { + SName* name = taosArrayGet(pReq->pTableTag, i); + CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_TB_TAG, name, NULL)); + } + + for (int32_t i = 0; i < indexNum; ++i) { char* indexName = taosArrayGet(pReq->pIndex, i); - CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_INDEX, indexName, NULL)); + CTG_ERR_JRET(ctgInitTask(pJob, CTG_TASK_GET_INDEX_INFO, indexName, NULL)); } for (int32_t i = 0; i < udfNum; ++i) { @@ -650,6 +699,10 @@ _return: } int32_t ctgDumpTbMetaRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pTableMeta) { pJob->jobRes.pTableMeta = taosArrayInit(pJob->tbMetaNum, sizeof(SMetaRes)); @@ -665,6 +718,10 @@ int32_t ctgDumpTbMetaRes(SCtgTask* pTask) { } int32_t ctgDumpTbMetasRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; pJob->jobRes.pTableMeta = pTask->res; @@ -673,6 +730,10 @@ int32_t ctgDumpTbMetasRes(SCtgTask* pTask) { } int32_t ctgDumpDbVgRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pDbVgroup) { pJob->jobRes.pDbVgroup = taosArrayInit(pJob->dbVgNum, sizeof(SMetaRes)); @@ -688,6 +749,10 @@ int32_t ctgDumpDbVgRes(SCtgTask* pTask) { } int32_t ctgDumpTbHashRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pTableHash) { pJob->jobRes.pTableHash = taosArrayInit(pJob->tbHashNum, sizeof(SMetaRes)); @@ -703,6 +768,10 @@ int32_t ctgDumpTbHashRes(SCtgTask* pTask) { } int32_t ctgDumpTbHashsRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; pJob->jobRes.pTableHash = pTask->res; @@ -711,9 +780,17 @@ int32_t ctgDumpTbHashsRes(SCtgTask* pTask) { } int32_t ctgDumpTbIndexRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pTableIndex) { - pJob->jobRes.pTableIndex = taosArrayInit(pJob->tbIndexNum, sizeof(SMetaRes)); + SArray* pRes = taosArrayInit(pJob->tbIndexNum, sizeof(SMetaRes)); + if (atomic_val_compare_exchange_ptr(&pJob->jobRes.pTableIndex, NULL, pRes)) { + taosArrayDestroy(pRes); + } + if (NULL == pJob->jobRes.pTableIndex) { CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } @@ -726,9 +803,17 @@ int32_t ctgDumpTbIndexRes(SCtgTask* pTask) { } int32_t ctgDumpTbCfgRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pTableCfg) { - pJob->jobRes.pTableCfg = taosArrayInit(pJob->tbCfgNum, sizeof(SMetaRes)); + SArray* pRes = taosArrayInit(pJob->tbCfgNum, sizeof(SMetaRes)); + if (atomic_val_compare_exchange_ptr(&pJob->jobRes.pTableCfg, NULL, pRes)) { + taosArrayDestroy(pRes); + } + if (NULL == pJob->jobRes.pTableCfg) { CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } @@ -740,7 +825,35 @@ int32_t ctgDumpTbCfgRes(SCtgTask* pTask) { return TSDB_CODE_SUCCESS; } +int32_t ctgDumpTbTagRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + + SCtgJob* pJob = pTask->pJob; + if (NULL == pJob->jobRes.pTableTag) { + SArray* pRes = taosArrayInit(pJob->tbTagNum, sizeof(SMetaRes)); + if (atomic_val_compare_exchange_ptr(&pJob->jobRes.pTableTag, NULL, pRes)) { + taosArrayDestroy(pRes); + } + + if (NULL == pJob->jobRes.pTableTag) { + CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + } + } + + SMetaRes res = {.code = pTask->code, .pRes = pTask->res}; + taosArrayPush(pJob->jobRes.pTableTag, &res); + + return TSDB_CODE_SUCCESS; +} + + int32_t ctgDumpIndexRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pIndex) { pJob->jobRes.pIndex = taosArrayInit(pJob->indexNum, sizeof(SMetaRes)); @@ -756,6 +869,10 @@ int32_t ctgDumpIndexRes(SCtgTask* pTask) { } int32_t ctgDumpQnodeRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pQnodeList) { pJob->jobRes.pQnodeList = taosArrayInit(1, sizeof(SMetaRes)); @@ -771,6 +888,10 @@ int32_t ctgDumpQnodeRes(SCtgTask* pTask) { } int32_t ctgDumpDnodeRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pDnodeList) { pJob->jobRes.pDnodeList = taosArrayInit(1, sizeof(SMetaRes)); @@ -786,6 +907,10 @@ int32_t ctgDumpDnodeRes(SCtgTask* pTask) { } int32_t ctgDumpDbCfgRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pDbCfg) { pJob->jobRes.pDbCfg = taosArrayInit(pJob->dbCfgNum, sizeof(SMetaRes)); @@ -801,6 +926,10 @@ int32_t ctgDumpDbCfgRes(SCtgTask* pTask) { } int32_t ctgDumpDbInfoRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pDbInfo) { pJob->jobRes.pDbInfo = taosArrayInit(pJob->dbInfoNum, sizeof(SMetaRes)); @@ -816,6 +945,10 @@ int32_t ctgDumpDbInfoRes(SCtgTask* pTask) { } int32_t ctgDumpUdfRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pUdfList) { pJob->jobRes.pUdfList = taosArrayInit(pJob->udfNum, sizeof(SMetaRes)); @@ -831,6 +964,10 @@ int32_t ctgDumpUdfRes(SCtgTask* pTask) { } int32_t ctgDumpUserRes(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pUser) { pJob->jobRes.pUser = taosArrayInit(pJob->userNum, sizeof(SMetaRes)); @@ -846,6 +983,10 @@ int32_t ctgDumpUserRes(SCtgTask* pTask) { } int32_t ctgDumpSvrVer(SCtgTask* pTask) { + if (pTask->subTask) { + return TSDB_CODE_SUCCESS; + } + SCtgJob* pJob = pTask->pJob; if (NULL == pJob->jobRes.pSvrVer) { pJob->jobRes.pSvrVer = taosMemoryCalloc(1, sizeof(SMetaRes)); @@ -1075,7 +1216,7 @@ int32_t ctgHandleGetTbMetaRsp(SCtgTaskReq* tReq, int32_t reqType, const SDataBuf STableMetaOutput* pOut = (STableMetaOutput*)pMsgCtx->out; - ctgUpdateTbMetaToCache(pCtg, pOut, false); + ctgUpdateTbMetaToCache(pCtg, pOut, flag & CTG_FLAG_SYNC_OP); if (CTG_IS_META_BOTH(pOut->metaType)) { memcpy(pOut->tbMeta, &pOut->ctbMeta, sizeof(pOut->ctbMeta)); @@ -1296,12 +1437,12 @@ _return: SMetaRes* pRes = taosArrayGet(ctx->pResList, pFetch->resIdx); pRes->code = code; pRes->pRes = NULL; + ctgTaskError("Get table %d.%s.%s meta failed with error %s", pName->acctId, pName->dbname, pName->tname, + tstrerror(code)); if (0 == atomic_sub_fetch_32(&ctx->fetchNum, 1)) { TSWAP(pTask->res, ctx->pResList); taskDone = true; } - ctgTaskError("Get table %d.%s.%s meta failed with error %s", pName->acctId, pName->dbname, pName->tname, - tstrerror(code)); } if (pTask->res && taskDone) { @@ -1446,7 +1587,6 @@ int32_t ctgHandleGetTbIndexRsp(SCtgTaskReq* tReq, int32_t reqType, const SDataBu CTG_ERR_JRET(ctgCloneTableIndex(pOut->pIndex, &pInfo)); pTask->res = pInfo; - SCtgTbIndexCtx* ctx = pTask->taskCtx; CTG_ERR_JRET(ctgUpdateTbIndexEnqueue(pTask->pJob->pCtg, (STableIndex**)&pTask->msgCtx.out, false)); _return: @@ -1473,11 +1613,60 @@ _return: CTG_RET(code); } + +int32_t ctgHandleGetTbTagRsp(SCtgTaskReq* tReq, int32_t reqType, const SDataBuf* pMsg, int32_t rspCode) { + int32_t code = 0; + SCtgTask* pTask = tReq->pTask; + SCatalog* pCtg = pTask->pJob->pCtg; + CTG_ERR_JRET(ctgProcessRspMsg(&pTask->msgCtx.out, reqType, pMsg->pData, pMsg->len, rspCode, pTask->msgCtx.target)); + + STableCfgRsp* pRsp = (STableCfgRsp*)pTask->msgCtx.out; + if (NULL == pRsp->pTags || pRsp->tagsLen <= 0) { + ctgError("invalid tag in tbCfg rsp, pTags:%p, len:%d", pRsp->pTags, pRsp->tagsLen); + CTG_ERR_JRET(TSDB_CODE_INVALID_MSG); + } + + SArray* pTagVals = NULL; + STag* pTag = (STag*)pRsp->pTags; + + if (tTagIsJson(pTag)) { + pTagVals = taosArrayInit(1, sizeof(STagVal)); + if (NULL == pTagVals) { + CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + } + + char* pJson = parseTagDatatoJson(pTag); + STagVal tagVal; + tagVal.cid = 0; + tagVal.type = TSDB_DATA_TYPE_JSON; + tagVal.pData = pJson; + tagVal.nData = strlen(pJson); + taosArrayPush(pTagVals, &tagVal); + } else { + CTG_ERR_JRET(tTagToValArray((const STag*)pRsp->pTags, &pTagVals)); + } + + pTask->res = pTagVals; + +_return: + + ctgHandleTaskEnd(pTask, code); + + CTG_RET(code); +} + + int32_t ctgHandleGetDbCfgRsp(SCtgTaskReq* tReq, int32_t reqType, const SDataBuf* pMsg, int32_t rspCode) { int32_t code = 0; SCtgTask* pTask = tReq->pTask; + SCtgDbCfgCtx* ctx = pTask->taskCtx; + CTG_ERR_JRET(ctgProcessRspMsg(pTask->msgCtx.out, reqType, pMsg->pData, pMsg->len, rspCode, pTask->msgCtx.target)); + SDbCfgInfo* pCfg = ctgCloneDbCfgInfo(pTask->msgCtx.out); + + CTG_ERR_RET(ctgUpdateDbCfgEnqueue(pTask->pJob->pCtg, ctx->dbFName, pCfg->dbId, pCfg, false)); + TSWAP(pTask->res, pTask->msgCtx.out); _return: @@ -1550,45 +1739,20 @@ _return: int32_t ctgHandleGetUserRsp(SCtgTaskReq* tReq, int32_t reqType, const SDataBuf* pMsg, int32_t rspCode) { int32_t code = 0; SCtgTask* pTask = tReq->pTask; - SCtgUserCtx* ctx = (SCtgUserCtx*)pTask->taskCtx; SCatalog* pCtg = pTask->pJob->pCtg; - bool pass = false; SGetUserAuthRsp* pOut = (SGetUserAuthRsp*)pTask->msgCtx.out; CTG_ERR_JRET(ctgProcessRspMsg(pTask->msgCtx.out, reqType, pMsg->pData, pMsg->len, rspCode, pTask->msgCtx.target)); - if (pOut->superAuth) { - pass = true; - goto _return; - } + ctgUpdateUserEnqueue(pCtg, pOut, true); + taosMemoryFreeClear(pTask->msgCtx.out); - if (pOut->createdDbs && taosHashGet(pOut->createdDbs, ctx->user.dbFName, strlen(ctx->user.dbFName))) { - pass = true; - goto _return; - } + CTG_ERR_JRET((*gCtgAsyncFps[pTask->type].launchFp)(pTask)); - if (CTG_AUTH_READ(ctx->user.type) && pOut->readDbs && - taosHashGet(pOut->readDbs, ctx->user.dbFName, strlen(ctx->user.dbFName))) { - pass = true; - } else if (CTG_AUTH_WRITE(ctx->user.type) && pOut->writeDbs && - taosHashGet(pOut->writeDbs, ctx->user.dbFName, strlen(ctx->user.dbFName))) { - pass = true; - } + return TSDB_CODE_SUCCESS; _return: - if (TSDB_CODE_SUCCESS == code) { - pTask->res = taosMemoryCalloc(1, sizeof(bool)); - if (NULL == pTask->res) { - code = TSDB_CODE_OUT_OF_MEMORY; - } else { - *(bool*)pTask->res = pass; - } - } - - ctgUpdateUserEnqueue(pCtg, pOut, false); - taosMemoryFreeClear(pTask->msgCtx.out); - ctgHandleTaskEnd(pTask, code); CTG_RET(code); @@ -1707,7 +1871,7 @@ int32_t ctgLaunchGetTbMetasTask(SCtgTask* pTask) { return TSDB_CODE_SUCCESS; } - pTask->msgCtxs = taosArrayInit_s(pCtx->fetchNum, sizeof(SCtgMsgCtx), pCtx->fetchNum); + pTask->msgCtxs = taosArrayInit_s(sizeof(SCtgMsgCtx), pCtx->fetchNum); for (int32_t i = 0; i < pCtx->fetchNum; ++i) { SCtgFetch* pFetch = taosArrayGet(pCtx->pFetchs, i); SName* pName = ctgGetFetchName(pCtx->pNames, pFetch); @@ -1857,7 +2021,7 @@ int32_t ctgLaunchGetTbHashsTask(SCtgTask* pTask) { return TSDB_CODE_SUCCESS; } - pTask->msgCtxs = taosArrayInit_s(pCtx->fetchNum, sizeof(SCtgMsgCtx), pCtx->fetchNum); + pTask->msgCtxs = taosArrayInit_s(sizeof(SCtgMsgCtx), pCtx->fetchNum); for (int32_t i = 0; i < pCtx->fetchNum; ++i) { SCtgFetch* pFetch = taosArrayGet(pCtx->pFetchs, i); @@ -1925,10 +2089,15 @@ int32_t ctgLaunchGetTbCfgTask(SCtgTask* pTask) { pMsgCtx->pBatchs = pJob->pBatchs; } + CTG_CACHE_NHIT_INC(CTG_CI_TBL_CFG, 1); + if (pCtx->tbType <= 0) { CTG_ERR_JRET(ctgReadTbTypeFromCache(pCtg, dbFName, pCtx->pName->tname, &pCtx->tbType)); if (pCtx->tbType <= 0) { - CTG_ERR_JRET(ctgLaunchSubTask(pTask, CTG_TASK_GET_TB_META, ctgGetTbCfgCb, pCtx->pName)); + SCtgTbMetaParam param; + param.pName = pCtx->pName; + param.flag = 0; + CTG_ERR_JRET(ctgLaunchSubTask(pTask, CTG_TASK_GET_TB_META, ctgGetTbCfgCb, ¶m)); return TSDB_CODE_SUCCESS; } } @@ -1958,6 +2127,45 @@ _return: CTG_RET(code); } + +int32_t ctgLaunchGetTbTagTask(SCtgTask* pTask) { + int32_t code = 0; + SCatalog* pCtg = pTask->pJob->pCtg; + SRequestConnInfo* pConn = &pTask->pJob->conn; + SCtgTbTagCtx* pCtx = (SCtgTbTagCtx*)pTask->taskCtx; + SArray* pRes = NULL; + char dbFName[TSDB_DB_FNAME_LEN]; + tNameGetFullDbName(pCtx->pName, dbFName); + SCtgJob* pJob = pTask->pJob; + SCtgMsgCtx* pMsgCtx = CTG_GET_TASK_MSGCTX(pTask, -1); + if (NULL == pMsgCtx->pBatchs) { + pMsgCtx->pBatchs = pJob->pBatchs; + } + + if (NULL == pCtx->pVgInfo) { + CTG_ERR_JRET(ctgGetTbHashVgroupFromCache(pCtg, pCtx->pName, &pCtx->pVgInfo)); + if (NULL == pCtx->pVgInfo) { + CTG_ERR_JRET(ctgLaunchSubTask(pTask, CTG_TASK_GET_DB_VGROUP, ctgGetTbTagCb, dbFName)); + return TSDB_CODE_SUCCESS; + } + } + + CTG_CACHE_NHIT_INC(CTG_CI_TBL_TAG, 1); + + CTG_ERR_JRET(ctgGetTableCfgFromVnode(pCtg, pConn, pCtx->pName, pCtx->pVgInfo, NULL, pTask)); + + return TSDB_CODE_SUCCESS; + +_return: + + if (CTG_TASK_LAUNCHED == pTask->status) { + ctgHandleTaskEnd(pTask, code); + } + + CTG_RET(code); +} + + int32_t ctgLaunchGetQnodeTask(SCtgTask* pTask) { SCatalog* pCtg = pTask->pJob->pCtg; SRequestConnInfo* pConn = &pTask->pJob->conn; @@ -1967,6 +2175,7 @@ int32_t ctgLaunchGetQnodeTask(SCtgTask* pTask) { pMsgCtx->pBatchs = pJob->pBatchs; } + CTG_CACHE_NHIT_INC(CTG_CI_QNODE, 1); CTG_ERR_RET(ctgGetQnodeListFromMnode(pCtg, pConn, NULL, pTask)); return TSDB_CODE_SUCCESS; } @@ -1980,6 +2189,7 @@ int32_t ctgLaunchGetDnodeTask(SCtgTask* pTask) { pMsgCtx->pBatchs = pJob->pBatchs; } + CTG_CACHE_NHIT_INC(CTG_CI_DNODE, 1); CTG_ERR_RET(ctgGetDnodeListFromMnode(pCtg, pConn, NULL, pTask)); return TSDB_CODE_SUCCESS; } @@ -1990,11 +2200,24 @@ int32_t ctgLaunchGetDbCfgTask(SCtgTask* pTask) { SCtgDbCfgCtx* pCtx = (SCtgDbCfgCtx*)pTask->taskCtx; SCtgJob* pJob = pTask->pJob; SCtgMsgCtx* pMsgCtx = CTG_GET_TASK_MSGCTX(pTask, -1); + SDbCfgInfo cfgInfo; if (NULL == pMsgCtx->pBatchs) { pMsgCtx->pBatchs = pJob->pBatchs; } - CTG_ERR_RET(ctgGetDBCfgFromMnode(pCtg, pConn, pCtx->dbFName, NULL, pTask)); + CTG_ERR_RET(ctgReadDBCfgFromCache(pCtg, pCtx->dbFName, &cfgInfo)); + + if (cfgInfo.cfgVersion < 0) { + CTG_ERR_RET(ctgGetDBCfgFromMnode(pCtg, pConn, pCtx->dbFName, NULL, pTask)); + } else { + pTask->res = taosMemoryCalloc(1, sizeof(SDbCfgInfo)); + if (NULL == pTask->res) { + CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + } + + memcpy(pTask->res, &cfgInfo, sizeof(cfgInfo)); + CTG_ERR_RET(ctgHandleTaskEnd(pTask, 0)); + } return TSDB_CODE_SUCCESS; } @@ -2023,10 +2246,14 @@ int32_t ctgLaunchGetDbInfoTask(SCtgTask* pTask) { pInfo->tbNum = dbCache->vgCache.vgInfo->numOfTable; pInfo->stateTs = dbCache->vgCache.vgInfo->stateTs; + CTG_CACHE_HIT_INC(CTG_CI_DB_INFO, 1); + ctgReleaseVgInfoToCache(pCtg, dbCache); dbCache = NULL; } else { pInfo->vgVer = CTG_DEFAULT_INVALID_VERSION; + + CTG_CACHE_NHIT_INC(CTG_CI_DB_INFO, 1); } CTG_ERR_JRET(ctgHandleTaskEnd(pTask, 0)); @@ -2046,6 +2273,8 @@ int32_t ctgLaunchGetIndexTask(SCtgTask* pTask) { pMsgCtx->pBatchs = pJob->pBatchs; } + CTG_CACHE_NHIT_INC(CTG_CI_INDEX_INFO, 1); + CTG_ERR_RET(ctgGetIndexInfoFromMnode(pCtg, pConn, pCtx->indexFName, NULL, pTask)); return TSDB_CODE_SUCCESS; @@ -2061,37 +2290,52 @@ int32_t ctgLaunchGetUdfTask(SCtgTask* pTask) { pMsgCtx->pBatchs = pJob->pBatchs; } + CTG_CACHE_NHIT_INC(CTG_CI_UDF, 1); + CTG_ERR_RET(ctgGetUdfInfoFromMnode(pCtg, pConn, pCtx->udfName, NULL, pTask)); return TSDB_CODE_SUCCESS; } int32_t ctgLaunchGetUserTask(SCtgTask* pTask) { + int32_t code = 0; SCatalog* pCtg = pTask->pJob->pCtg; SRequestConnInfo* pConn = &pTask->pJob->conn; SCtgUserCtx* pCtx = (SCtgUserCtx*)pTask->taskCtx; bool inCache = false; - bool pass = false; + SCtgAuthRsp rsp = {0}; SCtgJob* pJob = pTask->pJob; SCtgMsgCtx* pMsgCtx = CTG_GET_TASK_MSGCTX(pTask, -1); if (NULL == pMsgCtx->pBatchs) { pMsgCtx->pBatchs = pJob->pBatchs; } - CTG_ERR_RET(ctgChkAuthFromCache(pCtg, pCtx->user.user, pCtx->user.dbFName, pCtx->user.type, &inCache, &pass)); + rsp.pRawRes = taosMemoryCalloc(1, sizeof(SUserAuthRes)); + if (NULL == rsp.pRawRes) { + CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + } + + CTG_ERR_RET(ctgChkAuthFromCache(pCtg, &pCtx->user, &inCache, &rsp)); if (inCache) { - pTask->res = taosMemoryCalloc(1, sizeof(bool)); - if (NULL == pTask->res) { - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); - } - *(bool*)pTask->res = pass; + pTask->res = rsp.pRawRes; + + ctgTaskDebug("Final res got, pass:%d, pCond:%p", rsp.pRawRes->pass, rsp.pRawRes->pCond); CTG_ERR_RET(ctgHandleTaskEnd(pTask, 0)); return TSDB_CODE_SUCCESS; } - CTG_ERR_RET(ctgGetUserDbAuthFromMnode(pCtg, pConn, pCtx->user.user, NULL, pTask)); + taosMemoryFreeClear(rsp.pRawRes); + if (rsp.metaNotExists) { + SCtgTbMetaParam param; + param.pName = &pCtx->user.tbName; + param.flag = CTG_FLAG_SYNC_OP; + CTG_ERR_RET(ctgLaunchSubTask(pTask, CTG_TASK_GET_TB_META, ctgGetUserCb, ¶m)); + } else { + CTG_ERR_RET(ctgGetUserDbAuthFromMnode(pCtg, pConn, pCtx->user.user, NULL, pTask)); + } + return TSDB_CODE_SUCCESS; } @@ -2104,6 +2348,8 @@ int32_t ctgLaunchGetSvrVerTask(SCtgTask* pTask) { pMsgCtx->pBatchs = pJob->pBatchs; } + CTG_CACHE_NHIT_INC(CTG_CI_SVR_VER, 1); + CTG_ERR_RET(ctgGetSvrVerFromMnode(pCtg, pConn, NULL, pTask)); return TSDB_CODE_SUCCESS; @@ -2139,6 +2385,41 @@ _return: CTG_RET(ctgHandleTaskEnd(pTask, pTask->subRes.code)); } +int32_t ctgGetTbTagCb(SCtgTask* pTask) { + int32_t code = 0; + + CTG_ERR_JRET(pTask->subRes.code); + + SCtgTbTagCtx* pCtx = (SCtgTbTagCtx*)pTask->taskCtx; + SDBVgInfo* pDb = (SDBVgInfo*)pTask->subRes.res; + + if (NULL == pCtx->pVgInfo) { + pCtx->pVgInfo = taosMemoryCalloc(1, sizeof(SVgroupInfo)); + CTG_ERR_JRET(ctgGetVgInfoFromHashValue(pTask->pJob->pCtg, pDb, pCtx->pName, pCtx->pVgInfo)); + } + + CTG_RET(ctgLaunchGetTbTagTask(pTask)); + +_return: + + CTG_RET(ctgHandleTaskEnd(pTask, pTask->subRes.code)); +} + + + +int32_t ctgGetUserCb(SCtgTask* pTask) { + int32_t code = 0; + + CTG_ERR_JRET(pTask->subRes.code); + + CTG_RET(ctgLaunchGetUserTask(pTask)); + +_return: + + CTG_RET(ctgHandleTaskEnd(pTask, pTask->subRes.code)); +} + + int32_t ctgCompDbVgTasks(SCtgTask* pTask, void* param, bool* equal) { SCtgDbVgCtx* ctx = pTask->taskCtx; @@ -2149,8 +2430,12 @@ int32_t ctgCompDbVgTasks(SCtgTask* pTask, void* param, bool* equal) { int32_t ctgCompTbMetaTasks(SCtgTask* pTask, void* param, bool* equal) { SCtgTbMetaCtx* ctx = pTask->taskCtx; + SCtgTbMetaParam* pParam = (SCtgTbMetaParam*)param; - *equal = tNameTbNameEqual(ctx->pName, (SName*)param); + *equal = tNameTbNameEqual(ctx->pName, (SName*)pParam->pName); + if (*equal) { + ctx->flag |= pParam->flag; + } return TSDB_CODE_SUCCESS; } @@ -2184,6 +2469,7 @@ SCtgAsyncFps gCtgAsyncFps[] = { {ctgInitGetSvrVerTask, ctgLaunchGetSvrVerTask, ctgHandleGetSvrVerRsp, ctgDumpSvrVer, NULL, NULL}, {ctgInitGetTbMetasTask, ctgLaunchGetTbMetasTask, ctgHandleGetTbMetasRsp, ctgDumpTbMetasRes, NULL, NULL}, {ctgInitGetTbHashsTask, ctgLaunchGetTbHashsTask, ctgHandleGetTbHashsRsp, ctgDumpTbHashsRes, NULL, NULL}, + {ctgInitGetTbTagTask, ctgLaunchGetTbTagTask, ctgHandleGetTbTagRsp, ctgDumpTbTagRes, NULL, NULL}, }; int32_t ctgMakeAsyncRes(SCtgJob* pJob) { @@ -2271,6 +2557,9 @@ int32_t ctgLaunchSubTask(SCtgTask* pTask, CTG_TASK_TYPE type, ctgSubTaskCbFp fp, } SCtgTask* pSub = taosArrayGet(pJob->pTasks, subTaskId); + if (newTask) { + pSub->subTask = true; + } CTG_ERR_RET(ctgSetSubTaskCb(pSub, pTask)); diff --git a/source/libs/catalog/src/ctgCache.c b/source/libs/catalog/src/ctgCache.c index 06db2c3268a298c71d33586eead38643cae40d58..debd5f567c8622d28e5a05b720e00fa2dc8651bd 100644 --- a/source/libs/catalog/src/ctgCache.c +++ b/source/libs/catalog/src/ctgCache.c @@ -20,6 +20,7 @@ #include "trpc.h" SCtgOperation gCtgCacheOperation[CTG_OP_MAX] = {{CTG_OP_UPDATE_VGROUP, "update vgInfo", ctgOpUpdateVgroup}, + {CTG_OP_UPDATE_DB_CFG, "update dbCfg", ctgOpUpdateDbCfg}, {CTG_OP_UPDATE_TB_META, "update tbMeta", ctgOpUpdateTbMeta}, {CTG_OP_DROP_DB_CACHE, "drop DB", ctgOpDropDbCache}, {CTG_OP_DROP_DB_VGROUP, "drop DBVgroup", ctgOpDropDbVgroup}, @@ -31,6 +32,27 @@ SCtgOperation gCtgCacheOperation[CTG_OP_MAX] = {{CTG_OP_UPDATE_VGROUP, "update v {CTG_OP_DROP_TB_INDEX, "drop tbIndex", ctgOpDropTbIndex}, {CTG_OP_CLEAR_CACHE, "clear cache", ctgOpClearCache}}; +SCtgCacheItemInfo gCtgStatItem[CTG_CI_MAX_VALUE] = { + {"Cluster ", CTG_CI_FLAG_LEVEL_GLOBAL}, // CTG_CI_CLUSTER + {"Dnode ", CTG_CI_FLAG_LEVEL_CLUSTER}, // CTG_CI_DNODE, + {"Qnode ", CTG_CI_FLAG_LEVEL_CLUSTER}, // CTG_CI_QNODE, + {"DB ", CTG_CI_FLAG_LEVEL_CLUSTER}, // CTG_CI_DB, + {"DbVgroup ", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_DB_VGROUP, + {"DbCfg ", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_DB_CFG, + {"DbInfo ", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_DB_INFO, + {"StbMeta ", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_STABLE_META, + {"NtbMeta ", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_NTABLE_META, + {"CtbMeta ", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_CTABLE_META, + {"SysTblMeta", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_SYSTABLE_META, + {"OthTblMeta", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_OTHERTABLE_META, + {"TblSMA ", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_TBL_SMA, + {"TblCfg ", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_TBL_CFG, + {"IndexInfo ", CTG_CI_FLAG_LEVEL_DB}, // CTG_CI_INDEX_INFO, + {"User ", CTG_CI_FLAG_LEVEL_CLUSTER}, // CTG_CI_USER, + {"UDF ", CTG_CI_FLAG_LEVEL_CLUSTER}, // CTG_CI_UDF, + {"SvrVer ", CTG_CI_FLAG_LEVEL_CLUSTER} // CTG_CI_SVR_VER, +}; + int32_t ctgRLockVgInfo(SCatalog *pCtg, SCtgDBCache *dbCache, bool *inCache) { CTG_LOCK(CTG_READ, &dbCache->vgCache.vgLock); @@ -68,10 +90,15 @@ int32_t ctgWLockVgInfo(SCatalog *pCtg, SCtgDBCache *dbCache) { return TSDB_CODE_SUCCESS; } -void ctgRUnlockVgInfo(SCtgDBCache *dbCache) { CTG_UNLOCK(CTG_READ, &dbCache->vgCache.vgLock); } +void ctgRLockDbCfgInfo(SCtgDBCache *dbCache) { CTG_LOCK(CTG_READ, &dbCache->cfgCache.cfgLock); } +void ctgWLockDbCfgInfo(SCtgDBCache *dbCache) { CTG_LOCK(CTG_WRITE, &dbCache->cfgCache.cfgLock); } +void ctgRUnlockVgInfo(SCtgDBCache *dbCache) { CTG_UNLOCK(CTG_READ, &dbCache->vgCache.vgLock); } void ctgWUnlockVgInfo(SCtgDBCache *dbCache) { CTG_UNLOCK(CTG_WRITE, &dbCache->vgCache.vgLock); } +void ctgRUnlockDbCfgInfo(SCtgDBCache *dbCache) { CTG_UNLOCK(CTG_READ, &dbCache->cfgCache.cfgLock); } +void ctgWUnlockDbCfgInfo(SCtgDBCache *dbCache) { CTG_UNLOCK(CTG_WRITE, &dbCache->cfgCache.cfgLock); } + void ctgReleaseDBCache(SCatalog *pCtg, SCtgDBCache *dbCache) { CTG_UNLOCK(CTG_READ, &dbCache->dbLock); taosHashRelease(pCtg->dbCache, dbCache); @@ -93,6 +120,7 @@ int32_t ctgAcquireDBCacheImpl(SCatalog *pCtg, const char *dbFName, SCtgDBCache * if (NULL == dbCache) { *pCache = NULL; + CTG_CACHE_NHIT_INC(CTG_CI_DB, 1); ctgDebug("db not in cache, dbFName:%s", dbFName); return TSDB_CODE_SUCCESS; } @@ -107,11 +135,13 @@ int32_t ctgAcquireDBCacheImpl(SCatalog *pCtg, const char *dbFName, SCtgDBCache * } *pCache = NULL; + CTG_CACHE_NHIT_INC(CTG_CI_DB, 1); ctgDebug("db is removing from cache, dbFName:%s", dbFName); return TSDB_CODE_SUCCESS; } *pCache = dbCache; + CTG_CACHE_HIT_INC(CTG_CI_DB, 1); return TSDB_CODE_SUCCESS; } @@ -180,7 +210,7 @@ int32_t ctgAcquireVgInfoFromCache(SCatalog *pCtg, const char *dbFName, SCtgDBCac *pCache = dbCache; - CTG_CACHE_STAT_INC(numOfVgHit, 1); + CTG_CACHE_HIT_INC(CTG_CI_DB_VGROUP, 1); ctgDebug("Got db vgInfo from cache, dbFName:%s", dbFName); @@ -194,7 +224,7 @@ _return: *pCache = NULL; - CTG_CACHE_STAT_INC(numOfVgMiss, 1); + CTG_CACHE_NHIT_INC(CTG_CI_DB_VGROUP, 1); return TSDB_CODE_SUCCESS; } @@ -225,7 +255,7 @@ int32_t ctgAcquireTbMetaFromCache(SCatalog *pCtg, char *dbFName, char *tbName, S ctgDebug("tb %s meta got in cache, dbFName:%s", tbName, dbFName); - CTG_CACHE_STAT_INC(numOfMetaHit, 1); + CTG_META_HIT_INC(pCache->pMeta->tableType); return TSDB_CODE_SUCCESS; @@ -233,47 +263,48 @@ _return: ctgReleaseTbMetaToCache(pCtg, dbCache, pCache); - CTG_CACHE_STAT_INC(numOfMetaMiss, 1); + CTG_META_NHIT_INC(); return TSDB_CODE_SUCCESS; } -int32_t ctgAcquireVgMetaFromCache(SCatalog *pCtg, const char *dbFName, const char *tbName, SCtgDBCache **pDb, SCtgTbCache **pTb) { +int32_t ctgAcquireVgMetaFromCache(SCatalog *pCtg, const char *dbFName, const char *tbName, SCtgDBCache **pDb, + SCtgTbCache **pTb) { SCtgDBCache *dbCache = NULL; SCtgTbCache *tbCache = NULL; - bool vgInCache = false; + bool vgInCache = false; ctgAcquireDBCache(pCtg, dbFName, &dbCache); if (NULL == dbCache) { ctgDebug("db %s not in cache", dbFName); - CTG_CACHE_STAT_INC(numOfVgMiss, 1); + CTG_CACHE_NHIT_INC(CTG_CI_DB_VGROUP, 1); goto _return; } ctgRLockVgInfo(pCtg, dbCache, &vgInCache); if (!vgInCache) { ctgDebug("vgInfo of db %s not in cache", dbFName); - CTG_CACHE_STAT_INC(numOfVgMiss, 1); + CTG_CACHE_NHIT_INC(CTG_CI_DB_VGROUP, 1); goto _return; } *pDb = dbCache; - CTG_CACHE_STAT_INC(numOfVgHit, 1); + CTG_CACHE_HIT_INC(CTG_CI_DB_VGROUP, 1); ctgDebug("Got db vgInfo from cache, dbFName:%s", dbFName); tbCache = taosHashAcquire(dbCache->tbCache, tbName, strlen(tbName)); if (NULL == tbCache) { ctgDebug("tb %s not in cache, dbFName:%s", tbName, dbFName); - CTG_CACHE_STAT_INC(numOfMetaMiss, 1); + CTG_META_NHIT_INC(); goto _return; } CTG_LOCK(CTG_READ, &tbCache->metaLock); if (NULL == tbCache->pMeta) { ctgDebug("tb %s meta not in cache, dbFName:%s", tbName, dbFName); - CTG_CACHE_STAT_INC(numOfMetaMiss, 1); + CTG_META_NHIT_INC(); goto _return; } @@ -281,7 +312,7 @@ int32_t ctgAcquireVgMetaFromCache(SCatalog *pCtg, const char *dbFName, const cha ctgDebug("tb %s meta got in cache, dbFName:%s", tbName, dbFName); - CTG_CACHE_STAT_INC(numOfMetaHit, 1); + CTG_META_HIT_INC(tbCache->pMeta->tableType); return TSDB_CODE_SUCCESS; @@ -306,7 +337,6 @@ _return: return TSDB_CODE_SUCCESS; } - /* int32_t ctgAcquireStbMetaFromCache(SCatalog *pCtg, char *dbFName, uint64_t suid, SCtgDBCache **pDb, SCtgTbCache **pTb) { SCtgDBCache *dbCache = NULL; @@ -343,7 +373,7 @@ int32_t ctgAcquireStbMetaFromCache(SCatalog *pCtg, char *dbFName, uint64_t suid, ctgDebug("stb 0x%" PRIx64 " meta got in cache, dbFName:%s", suid, dbFName); - CTG_CACHE_STAT_INC(numOfMetaHit, 1); + CTG_META_HIT_INC(pCache->pMeta->tableType, 1); return TSDB_CODE_SUCCESS; @@ -351,7 +381,7 @@ _return: ctgReleaseTbMetaToCache(pCtg, dbCache, pCache); - CTG_CACHE_STAT_INC(numOfMetaMiss, 1); + CTG_META_NHIT_INC(1); *pDb = NULL; *pTb = NULL; @@ -360,9 +390,10 @@ _return: } */ -int32_t ctgAcquireStbMetaFromCache(SCtgDBCache *dbCache, SCatalog *pCtg, char *dbFName, uint64_t suid, SCtgTbCache **pTb) { +int32_t ctgAcquireStbMetaFromCache(SCtgDBCache *dbCache, SCatalog *pCtg, char *dbFName, uint64_t suid, + SCtgTbCache **pTb) { SCtgTbCache *pCache = NULL; - char *stName = taosHashAcquire(dbCache->stbCache, &suid, sizeof(suid)); + char *stName = taosHashAcquire(dbCache->stbCache, &suid, sizeof(suid)); if (NULL == stName) { ctgDebug("stb 0x%" PRIx64 " not in cache, dbFName:%s", suid, dbFName); goto _return; @@ -387,7 +418,7 @@ int32_t ctgAcquireStbMetaFromCache(SCtgDBCache *dbCache, SCatalog *pCtg, char *d ctgDebug("stb 0x%" PRIx64 " meta got in cache, dbFName:%s", suid, dbFName); - CTG_CACHE_STAT_INC(numOfMetaHit, 1); + CTG_META_HIT_INC(pCache->pMeta->tableType); return TSDB_CODE_SUCCESS; @@ -395,7 +426,7 @@ _return: ctgReleaseTbMetaToCache(pCtg, dbCache, pCache); - CTG_CACHE_STAT_INC(numOfMetaMiss, 1); + CTG_META_NHIT_INC(); *pTb = NULL; @@ -429,7 +460,7 @@ int32_t ctgAcquireTbIndexFromCache(SCatalog *pCtg, char *dbFName, char *tbName, ctgDebug("tb %s index got in cache, dbFName:%s", tbName, dbFName); - CTG_CACHE_STAT_INC(numOfIndexHit, 1); + CTG_CACHE_HIT_INC(CTG_CI_TBL_SMA, 1); return TSDB_CODE_SUCCESS; @@ -437,7 +468,7 @@ _return: ctgReleaseTbIndexToCache(pCtg, dbCache, pCache); - CTG_CACHE_STAT_INC(numOfIndexMiss, 1); + CTG_CACHE_NHIT_INC(CTG_CI_TBL_SMA, 1); return TSDB_CODE_SUCCESS; } @@ -459,10 +490,11 @@ int32_t ctgTbMetaExistInCache(SCatalog *pCtg, char *dbFName, char *tbName, int32 return TSDB_CODE_SUCCESS; } -int32_t ctgCopyTbMeta(SCatalog *pCtg, SCtgTbMetaCtx *ctx, SCtgDBCache **pDb, SCtgTbCache **pTb, STableMeta **pTableMeta, char* dbFName) { +int32_t ctgCopyTbMeta(SCatalog *pCtg, SCtgTbMetaCtx *ctx, SCtgDBCache **pDb, SCtgTbCache **pTb, STableMeta **pTableMeta, + char *dbFName) { SCtgDBCache *dbCache = *pDb; SCtgTbCache *tbCache = *pTb; - STableMeta *tbMeta = tbCache->pMeta; + STableMeta *tbMeta = tbCache->pMeta; ctx->tbInfo.inCache = true; ctx->tbInfo.dbId = dbCache->dbId; ctx->tbInfo.suid = tbMeta->suid; @@ -491,14 +523,12 @@ int32_t ctgCopyTbMeta(SCatalog *pCtg, SCtgTbMetaCtx *ctx, SCtgDBCache **pDb, SCt memcpy(*pTableMeta, tbMeta, metaSize); - //ctgReleaseTbMetaToCache(pCtg, dbCache, tbCache); + // ctgReleaseTbMetaToCache(pCtg, dbCache, tbCache); + + CTG_UNLOCK(CTG_READ, &tbCache->metaLock); + taosHashRelease(dbCache->tbCache, tbCache); + *pTb = NULL; - if (tbCache) { - CTG_UNLOCK(CTG_READ, &tbCache->metaLock); - taosHashRelease(dbCache->tbCache, tbCache); - *pTb = NULL; - } - ctgDebug("Got ctb %s meta from cache, will continue to get its stb meta, type:%d, dbFName:%s", ctx->pName->tname, ctx->tbInfo.tbType, dbFName); @@ -530,7 +560,6 @@ int32_t ctgCopyTbMeta(SCatalog *pCtg, SCtgTbMetaCtx *ctx, SCtgDBCache **pDb, SCt return TSDB_CODE_SUCCESS; } - int32_t ctgReadTbMetaFromCache(SCatalog *pCtg, SCtgTbMetaCtx *ctx, STableMeta **pTableMeta) { int32_t code = 0; SCtgDBCache *dbCache = NULL; @@ -600,17 +629,17 @@ int32_t ctgReadTbVerFromCache(SCatalog *pCtg, SName *pTableName, int32_t *sver, // PROCESS FOR CHILD TABLE - //ctgReleaseTbMetaToCache(pCtg, dbCache, tbCache); + // ctgReleaseTbMetaToCache(pCtg, dbCache, tbCache); if (tbCache) { CTG_UNLOCK(CTG_READ, &tbCache->metaLock); taosHashRelease(dbCache->tbCache, tbCache); } - + ctgDebug("Got ctb %s ver from cache, will continue to get its stb ver, dbFName:%s", pTableName->tname, dbFName); ctgAcquireStbMetaFromCache(dbCache, pCtg, dbFName, *suid, &tbCache); if (NULL == tbCache) { - //ctgReleaseTbMetaToCache(pCtg, dbCache, tbCache); + // ctgReleaseTbMetaToCache(pCtg, dbCache, tbCache); ctgDebug("stb 0x%" PRIx64 " meta not in cache", *suid); return TSDB_CODE_SUCCESS; } @@ -680,62 +709,110 @@ _return: CTG_RET(code); } -int32_t ctgChkAuthFromCache(SCatalog *pCtg, char *user, char *dbFName, AUTH_TYPE type, bool *inCache, bool *pass) { - char *p = strchr(dbFName, '.'); - if (p) { - ++p; +int32_t ctgReadDBCfgFromCache(SCatalog *pCtg, const char* dbFName, SDbCfgInfo* pDbCfg) { + int32_t code = 0; + SCtgDBCache *dbCache = NULL; + ctgAcquireDBCache(pCtg, dbFName, &dbCache); + if (NULL == dbCache) { + ctgDebug("db %s not in cache", dbFName); + pDbCfg->cfgVersion = -1; + CTG_CACHE_NHIT_INC(CTG_CI_DB_CFG, 1); + return TSDB_CODE_SUCCESS; + } + + CTG_LOCK(CTG_READ, &dbCache->cfgCache.cfgLock); + + if (dbCache->cfgCache.cfgInfo) { + SDbCfgInfo *pInfo = ctgCloneDbCfgInfo(dbCache->cfgCache.cfgInfo); + if (NULL == pInfo) { + CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + } + + memcpy(pDbCfg, pInfo, sizeof(*pInfo)); + taosMemoryFree(pInfo); + CTG_CACHE_HIT_INC(CTG_CI_DB_CFG, 1); } else { - p = dbFName; + pDbCfg->cfgVersion = -1; + CTG_CACHE_NHIT_INC(CTG_CI_DB_CFG, 1); } - if (IS_SYS_DBNAME(p)) { +_return: + + if (dbCache) { + CTG_UNLOCK(CTG_READ, &dbCache->cfgCache.cfgLock); + ctgReleaseDBCache(pCtg, dbCache); + } + + return code; +} + +int32_t ctgGetCachedStbNameFromSuid(SCatalog* pCtg, char* dbFName, uint64_t suid, char **stbName) { + *stbName = NULL; + + SCtgDBCache *dbCache = NULL; + ctgAcquireDBCache(pCtg, dbFName, &dbCache); + if (NULL == dbCache) { + ctgDebug("db %s not in cache", dbFName); + return TSDB_CODE_SUCCESS; + } + + char *stb = taosHashAcquire(dbCache->stbCache, &suid, sizeof(suid)); + if (NULL == stb) { + ctgDebug("stb 0x%" PRIx64 " not in cache, dbFName:%s", suid, dbFName); + return TSDB_CODE_SUCCESS; + } + + *stbName = taosStrdup(stb); + + taosHashRelease(dbCache->stbCache, stb); + + return TSDB_CODE_SUCCESS; +} + + +int32_t ctgChkAuthFromCache(SCatalog *pCtg, SUserAuthInfo *pReq, bool *inCache, SCtgAuthRsp *pRes) { + int32_t code = 0; + if (IS_SYS_DBNAME(pReq->tbName.dbname)) { *inCache = true; - *pass = true; - ctgDebug("sysdb %s, pass", dbFName); + pRes->pRawRes->pass = true; + ctgDebug("sysdb %s, pass", pReq->tbName.dbname); return TSDB_CODE_SUCCESS; } - SCtgUserAuth *pUser = (SCtgUserAuth *)taosHashGet(pCtg->userCache, user, strlen(user)); + SCtgUserAuth *pUser = (SCtgUserAuth *)taosHashGet(pCtg->userCache, pReq->user, strlen(pReq->user)); if (NULL == pUser) { - ctgDebug("user not in cache, user:%s", user); + ctgDebug("user not in cache, user:%s", pReq->user); goto _return; } *inCache = true; - ctgDebug("Got user from cache, user:%s", user); - CTG_CACHE_STAT_INC(numOfUserHit, 1); + ctgDebug("Got user from cache, user:%s", pReq->user); + CTG_CACHE_HIT_INC(CTG_CI_USER, 1); - if (pUser->superUser) { - *pass = true; - return TSDB_CODE_SUCCESS; - } + SCtgAuthReq req = {0}; + req.pRawReq = pReq; + req.onlyCache = true; CTG_LOCK(CTG_READ, &pUser->lock); - if (pUser->createdDbs && taosHashGet(pUser->createdDbs, dbFName, strlen(dbFName))) { - *pass = true; - CTG_UNLOCK(CTG_READ, &pUser->lock); - return TSDB_CODE_SUCCESS; - } - - if (pUser->readDbs && taosHashGet(pUser->readDbs, dbFName, strlen(dbFName)) && CTG_AUTH_READ(type)) { - *pass = true; - } + memcpy(&req.authInfo, &pUser->userAuth, sizeof(pUser->userAuth)); + code = ctgChkSetAuthRes(pCtg, &req, pRes); + CTG_UNLOCK(CTG_READ, &pUser->lock); + CTG_ERR_JRET(code); - if (pUser->writeDbs && taosHashGet(pUser->writeDbs, dbFName, strlen(dbFName)) && CTG_AUTH_WRITE(type)) { - *pass = true; + if (pRes->metaNotExists) { + goto _return; } - CTG_UNLOCK(CTG_READ, &pUser->lock); - - return TSDB_CODE_SUCCESS; + CTG_RET(code); _return: *inCache = false; - CTG_CACHE_STAT_INC(numOfUserMiss, 1); + CTG_CACHE_NHIT_INC(CTG_CI_USER, 1); + ctgDebug("Get user from cache failed, user:%s, metaNotExists:%d, code:%d", pReq->user, pRes->metaNotExists, code); - return TSDB_CODE_SUCCESS; + return code; } void ctgDequeue(SCtgCacheOperation **op) { @@ -786,7 +863,7 @@ int32_t ctgEnqueue(SCatalog *pCtg, SCtgCacheOperation *operation) { ctgDebug("action [%s] added into queue", opName); CTG_QUEUE_INC(); - CTG_RT_STAT_INC(numOfOpEnqueue, 1); + CTG_STAT_RT_INC(numOfOpEnqueue, 1); tsem_post(&gCtgMgmt.queue.reqSem); @@ -973,6 +1050,44 @@ _return: CTG_RET(code); } + +int32_t ctgUpdateDbCfgEnqueue(SCatalog *pCtg, const char *dbFName, int64_t dbId, SDbCfgInfo *cfgInfo, bool syncOp) { + int32_t code = 0; + SCtgCacheOperation *op = taosMemoryCalloc(1, sizeof(SCtgCacheOperation)); + op->opId = CTG_OP_UPDATE_DB_CFG; + op->syncOp = syncOp; + + SCtgUpdateDbCfgMsg *msg = taosMemoryMalloc(sizeof(SCtgUpdateDbCfgMsg)); + if (NULL == msg) { + ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateDbCfgMsg)); + taosMemoryFree(op); + freeDbCfgInfo(cfgInfo); + CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + } + + char *p = strchr(dbFName, '.'); + if (p && IS_SYS_DBNAME(p + 1)) { + dbFName = p + 1; + } + + tstrncpy(msg->dbFName, dbFName, sizeof(msg->dbFName)); + msg->pCtg = pCtg; + msg->dbId = dbId; + msg->cfgInfo = cfgInfo; + + op->data = msg; + + CTG_ERR_JRET(ctgEnqueue(pCtg, op)); + + return TSDB_CODE_SUCCESS; + +_return: + + freeDbCfgInfo(cfgInfo); + CTG_RET(code); +} + + int32_t ctgUpdateTbMetaEnqueue(SCatalog *pCtg, STableMetaOutput *output, bool syncOp) { int32_t code = 0; SCtgCacheOperation *op = taosMemoryCalloc(1, sizeof(SCtgCacheOperation)); @@ -1049,7 +1164,7 @@ int32_t ctgUpdateUserEnqueue(SCatalog *pCtg, SGetUserAuthRsp *pAuth, bool syncOp if (NULL == msg) { ctgError("malloc %d failed", (int32_t)sizeof(SCtgUpdateUserMsg)); taosMemoryFree(op); - CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); + CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); } msg->pCtg = pCtg; @@ -1384,17 +1499,17 @@ int32_t ctgAddNewDBCache(SCatalog *pCtg, const char *dbFName, uint64_t dbId) { CTG_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); } - CTG_CACHE_STAT_INC(numOfDb, 1); + CTG_CACHE_NUM_INC(CTG_CI_DB, 1); - SDbVgVersion vgVersion = {.dbId = newDBCache.dbId, .vgVersion = -1, .stateTs = 0}; - tstrncpy(vgVersion.dbFName, dbFName, sizeof(vgVersion.dbFName)); + SDbCacheInfo dbCacheInfo = {.dbId = newDBCache.dbId, .vgVersion = -1, .stateTs = 0, .cfgVersion = -1}; + tstrncpy(dbCacheInfo.dbFName, dbFName, sizeof(dbCacheInfo.dbFName)); ctgDebug("db added to cache, dbFName:%s, dbId:0x%" PRIx64, dbFName, dbId); if (!IS_SYS_DBNAME(dbFName)) { - CTG_ERR_RET(ctgMetaRentAdd(&pCtg->dbRent, &vgVersion, dbId, sizeof(SDbVgVersion))); + CTG_ERR_RET(ctgMetaRentAdd(&pCtg->dbRent, &dbCacheInfo, dbId, sizeof(SDbCacheInfo))); - ctgDebug("db added to rent, dbFName:%s, vgVersion:%d, dbId:0x%" PRIx64, dbFName, vgVersion.vgVersion, dbId); + ctgDebug("db added to rent, dbFName:%s, vgVersion:%d, dbId:0x%" PRIx64, dbFName, dbCacheInfo.vgVersion, dbId); } return TSDB_CODE_SUCCESS; @@ -1438,7 +1553,7 @@ int32_t ctgRemoveDBFromCache(SCatalog *pCtg, SCtgDBCache *dbCache, const char *d CTG_UNLOCK(CTG_WRITE, &dbCache->dbLock); - CTG_ERR_RET(ctgMetaRentRemove(&pCtg->dbRent, dbId, ctgDbVgVersionSortCompare, ctgDbVgVersionSearchCompare)); + CTG_ERR_RET(ctgMetaRentRemove(&pCtg->dbRent, dbId, ctgDbCacheInfoSortCompare, ctgDbCacheInfoSearchCompare)); ctgDebug("db removed from rent, dbFName:%s, dbId:0x%" PRIx64, dbFName, dbId); if (taosHashRemove(pCtg->dbCache, dbFName, strlen(dbFName))) { @@ -1446,7 +1561,7 @@ int32_t ctgRemoveDBFromCache(SCatalog *pCtg, SCtgDBCache *dbCache, const char *d CTG_ERR_RET(TSDB_CODE_CTG_DB_DROPPED); } - CTG_CACHE_STAT_DEC(numOfDb, 1); + CTG_CACHE_NUM_DEC(CTG_CI_DB, 1); ctgInfo("db removed from cache, dbFName:%s, dbId:0x%" PRIx64, dbFName, dbId); return TSDB_CODE_SUCCESS; @@ -1544,7 +1659,6 @@ int32_t ctgWriteTbMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFNam if (taosHashRemove(dbCache->stbCache, &orig->suid, sizeof(orig->suid))) { ctgError("stb not exist in stbCache, dbFName:%s, stb:%s, suid:0x%" PRIx64, dbFName, tbName, orig->suid); } else { - CTG_CACHE_STAT_DEC(numOfStb, 1); ctgDebug("stb removed from stbCache, dbFName:%s, stb:%s, suid:0x%" PRIx64, dbFName, tbName, orig->suid); } } @@ -1554,22 +1668,23 @@ int32_t ctgWriteTbMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFNam SCtgTbCache cache = {0}; cache.pMeta = meta; if (taosHashPut(dbCache->tbCache, tbName, strlen(tbName), &cache, sizeof(SCtgTbCache)) != 0) { - taosMemoryFree(meta); ctgError("taosHashPut new tbCache failed, dbFName:%s, tbName:%s, tbType:%d", dbFName, tbName, meta->tableType); + taosMemoryFree(meta); CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } pCache = taosHashGet(dbCache->tbCache, tbName, strlen(tbName)); } else { CTG_LOCK(CTG_WRITE, &pCache->metaLock); + if (orig) { + CTG_META_NUM_DEC(origType); + } taosMemoryFree(pCache->pMeta); pCache->pMeta = meta; CTG_UNLOCK(CTG_WRITE, &pCache->metaLock); } - if (NULL == orig) { - CTG_CACHE_STAT_INC(numOfTbl, 1); - } + CTG_META_NUM_INC(pCache->pMeta->tableType); ctgDebug("tbmeta updated to cache, dbFName:%s, tbName:%s, tbType:%d", dbFName, tbName, meta->tableType); ctgdShowTableMeta(pCtg, tbName, meta); @@ -1583,8 +1698,6 @@ int32_t ctgWriteTbMetaToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFNam CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } - CTG_CACHE_STAT_INC(numOfStb, 1); - ctgDebug("stb 0x%" PRIx64 " updated to cache, dbFName:%s, tbName:%s, tbType:%d", meta->suid, dbFName, tbName, meta->tableType); @@ -1617,6 +1730,8 @@ int32_t ctgWriteTbIndexToCache(SCatalog *pCtg, SCtgDBCache *dbCache, char *dbFNa CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } + CTG_DB_NUM_INC(CTG_CI_TBL_SMA); + *index = NULL; ctgDebug("table %s index updated to cache, ver:%d, num:%d", tbName, pIndex->version, (int32_t)taosArrayGetSize(pIndex->pIndex)); @@ -1702,9 +1817,9 @@ void ctgFreeAllInstance(void) { taosHashClear(gCtgMgmt.pCluster); } -int32_t ctgVgInfoIdComp(void const* lp, void const* rp) { - int32_t* key = (int32_t*)lp; - SVgroupInfo* pVg = (SVgroupInfo*)rp; +int32_t ctgVgInfoIdComp(void const *lp, void const *rp) { + int32_t *key = (int32_t *)lp; + SVgroupInfo *pVg = (SVgroupInfo *)rp; if (*key < pVg->vgId) { return -1; @@ -1715,7 +1830,6 @@ int32_t ctgVgInfoIdComp(void const* lp, void const* rp) { return 0; } - int32_t ctgOpUpdateVgroup(SCtgCacheOperation *operation) { int32_t code = 0; SCtgUpdateVgMsg *msg = operation->data; @@ -1734,8 +1848,8 @@ int32_t ctgOpUpdateVgroup(SCtgCacheOperation *operation) { } bool newAdded = false; - SDbVgVersion vgVersion = { - .dbId = msg->dbId, .vgVersion = dbInfo->vgVersion, .numOfTable = dbInfo->numOfTable, .stateTs = dbInfo->stateTs}; + SDbCacheInfo dbCacheInfo = { + .dbId = msg->dbId, .vgVersion = dbInfo->vgVersion, .cfgVersion = -1, .numOfTable = dbInfo->numOfTable, .stateTs = dbInfo->stateTs}; SCtgDBCache *dbCache = NULL; CTG_ERR_JRET(ctgGetAddDBCache(msg->pCtg, dbFName, msg->dbId, &dbCache)); @@ -1768,22 +1882,28 @@ int32_t ctgOpUpdateVgroup(SCtgCacheOperation *operation) { } freeVgInfo(vgInfo); + CTG_DB_NUM_RESET(CTG_CI_DB_VGROUP); + } + + if (dbCache->cfgCache.cfgInfo) { + dbCacheInfo.cfgVersion = dbCache->cfgCache.cfgInfo->cfgVersion; } vgCache->vgInfo = dbInfo; msg->dbInfo = NULL; + CTG_DB_NUM_SET(CTG_CI_DB_VGROUP); ctgDebug("db vgInfo updated, dbFName:%s, vgVer:%d, stateTs:%" PRId64 ", dbId:0x%" PRIx64, dbFName, - vgVersion.vgVersion, vgVersion.stateTs, vgVersion.dbId); + dbCacheInfo.vgVersion, dbCacheInfo.stateTs, dbCacheInfo.dbId); ctgWUnlockVgInfo(dbCache); dbCache = NULL; - //if (!IS_SYS_DBNAME(dbFName)) { - tstrncpy(vgVersion.dbFName, dbFName, sizeof(vgVersion.dbFName)); - CTG_ERR_JRET(ctgMetaRentUpdate(&msg->pCtg->dbRent, &vgVersion, vgVersion.dbId, sizeof(SDbVgVersion), - ctgDbVgVersionSortCompare, ctgDbVgVersionSearchCompare)); + // if (!IS_SYS_DBNAME(dbFName)) { + tstrncpy(dbCacheInfo.dbFName, dbFName, sizeof(dbCacheInfo.dbFName)); + CTG_ERR_JRET(ctgMetaRentUpdate(&msg->pCtg->dbRent, &dbCacheInfo, dbCacheInfo.dbId, sizeof(SDbCacheInfo), + ctgDbCacheInfoSortCompare, ctgDbCacheInfoSearchCompare)); //} _return: @@ -1794,6 +1914,67 @@ _return: CTG_RET(code); } +int32_t ctgOpUpdateDbCfg(SCtgCacheOperation *operation) { + int32_t code = 0; + SCtgUpdateDbCfgMsg *msg = operation->data; + SDbCfgInfo *cfgInfo = msg->cfgInfo; + char *dbFName = msg->dbFName; + SCatalog *pCtg = msg->pCtg; + + if (pCtg->stopUpdate || NULL == cfgInfo) { + goto _return; + } + + if (cfgInfo->cfgVersion < 0) { + ctgDebug("invalid db cfgInfo, dbFName:%s, cfgVersion:%d", dbFName, cfgInfo->cfgVersion); + CTG_ERR_JRET(TSDB_CODE_APP_ERROR); + } + + SCtgDBCache *dbCache = NULL; + CTG_ERR_JRET(ctgGetAddDBCache(msg->pCtg, dbFName, msg->dbId, &dbCache)); + if (NULL == dbCache) { + ctgInfo("conflict db update, ignore this update, dbFName:%s, dbId:0x%" PRIx64, dbFName, msg->dbId); + CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR); + } + + SDbCacheInfo cacheInfo = {0}; + cacheInfo.dbId = dbCache->dbId; + tstrncpy(cacheInfo.dbFName, dbFName, sizeof(cacheInfo.dbFName)); + cacheInfo.cfgVersion = cfgInfo->cfgVersion; + + SCtgVgCache *vgCache = &dbCache->vgCache; + if (vgCache->vgInfo) { + cacheInfo.vgVersion = vgCache->vgInfo->vgVersion; + cacheInfo.numOfTable = vgCache->vgInfo->numOfTable; + cacheInfo.stateTs = vgCache->vgInfo->stateTs; + } else { + cacheInfo.vgVersion = -1; + } + + ctgWLockDbCfgInfo(dbCache); + + freeDbCfgInfo(dbCache->cfgCache.cfgInfo); + dbCache->cfgCache.cfgInfo = cfgInfo; + cfgInfo = NULL; + + ctgWUnlockDbCfgInfo(dbCache); + + ctgDebug("db cfgInfo updated, dbFName:%s, cfgVer:%d", dbFName, dbCache->cfgCache.cfgInfo->cfgVersion); + + // if (!IS_SYS_DBNAME(dbFName)) { + CTG_ERR_JRET(ctgMetaRentUpdate(&msg->pCtg->dbRent, &cacheInfo, cacheInfo.dbId, sizeof(SDbCacheInfo), + ctgDbCacheInfoSortCompare, ctgDbCacheInfoSearchCompare)); + //} + +_return: + + freeDbCfgInfo(cfgInfo); + taosMemoryFreeClear(msg); + + CTG_RET(code); +} + + int32_t ctgOpDropDbCache(SCtgCacheOperation *operation) { int32_t code = 0; SCtgDropDBMsg *msg = operation->data; @@ -1844,6 +2025,7 @@ int32_t ctgOpDropDbVgroup(SCtgCacheOperation *operation) { freeVgInfo(dbCache->vgCache.vgInfo); dbCache->vgCache.vgInfo = NULL; + CTG_DB_NUM_RESET(CTG_CI_DB_VGROUP); ctgDebug("db vgInfo removed, dbFName:%s", msg->dbFName); ctgWUnlockVgInfo(dbCache); @@ -1913,6 +2095,7 @@ int32_t ctgOpDropStbMeta(SCtgCacheOperation *operation) { int32_t code = 0; SCtgDropStbMetaMsg *msg = operation->data; SCatalog *pCtg = msg->pCtg; + int32_t tblType = 0; if (pCtg->stopUpdate) { goto _return; @@ -1933,8 +2116,6 @@ int32_t ctgOpDropStbMeta(SCtgCacheOperation *operation) { if (taosHashRemove(dbCache->stbCache, &msg->suid, sizeof(msg->suid))) { ctgDebug("stb not exist in stbCache, may be removed, dbFName:%s, stb:%s, suid:0x%" PRIx64, msg->dbFName, msg->stbName, msg->suid); - } else { - CTG_CACHE_STAT_DEC(numOfStb, 1); } SCtgTbCache *pTbCache = taosHashGet(dbCache->tbCache, msg->stbName, strlen(msg->stbName)); @@ -1944,13 +2125,14 @@ int32_t ctgOpDropStbMeta(SCtgCacheOperation *operation) { } CTG_LOCK(CTG_WRITE, &pTbCache->metaLock); + tblType = pTbCache->pMeta->tableType; ctgFreeTbCacheImpl(pTbCache); CTG_UNLOCK(CTG_WRITE, &pTbCache->metaLock); if (taosHashRemove(dbCache->tbCache, msg->stbName, strlen(msg->stbName))) { ctgError("stb not exist in cache, dbFName:%s, stb:%s, suid:0x%" PRIx64, msg->dbFName, msg->stbName, msg->suid); } else { - CTG_CACHE_STAT_DEC(numOfTbl, 1); + CTG_META_NUM_DEC(tblType); } ctgInfo("stb removed from cache, dbFName:%s, stbName:%s, suid:0x%" PRIx64, msg->dbFName, msg->stbName, msg->suid); @@ -1970,6 +2152,7 @@ int32_t ctgOpDropTbMeta(SCtgCacheOperation *operation) { int32_t code = 0; SCtgDropTblMetaMsg *msg = operation->data; SCatalog *pCtg = msg->pCtg; + int32_t tblType = 0; if (pCtg->stopUpdate) { goto _return; @@ -1994,6 +2177,7 @@ int32_t ctgOpDropTbMeta(SCtgCacheOperation *operation) { } CTG_LOCK(CTG_WRITE, &pTbCache->metaLock); + tblType = pTbCache->pMeta->tableType; ctgFreeTbCacheImpl(pTbCache); CTG_UNLOCK(CTG_WRITE, &pTbCache->metaLock); @@ -2001,7 +2185,7 @@ int32_t ctgOpDropTbMeta(SCtgCacheOperation *operation) { ctgError("tb %s not exist in cache, dbFName:%s", msg->tbName, msg->dbFName); CTG_ERR_JRET(TSDB_CODE_CTG_INTERNAL_ERROR); } else { - CTG_CACHE_STAT_DEC(numOfTbl, 1); + CTG_META_NUM_DEC(tblType); } ctgDebug("table %s removed from cache, dbFName:%s", msg->tbName, msg->dbFName); @@ -2026,11 +2210,7 @@ int32_t ctgOpUpdateUser(SCtgCacheOperation *operation) { if (NULL == pUser) { SCtgUserAuth userAuth = {0}; - userAuth.version = msg->userAuth.version; - userAuth.superUser = msg->userAuth.superAuth; - userAuth.createdDbs = msg->userAuth.createdDbs; - userAuth.readDbs = msg->userAuth.readDbs; - userAuth.writeDbs = msg->userAuth.writeDbs; + memcpy(&userAuth.userAuth, &msg->userAuth, sizeof(msg->userAuth)); if (taosHashPut(pCtg->userCache, msg->userAuth.user, strlen(msg->userAuth.user), &userAuth, sizeof(userAuth))) { ctgError("taosHashPut user %s to cache failed", msg->userAuth.user); @@ -2039,24 +2219,28 @@ int32_t ctgOpUpdateUser(SCtgCacheOperation *operation) { taosMemoryFreeClear(msg); + CTG_CACHE_NUM_INC(CTG_CI_USER, 1); + return TSDB_CODE_SUCCESS; } - pUser->version = msg->userAuth.version; - CTG_LOCK(CTG_WRITE, &pUser->lock); - taosHashCleanup(pUser->createdDbs); - pUser->createdDbs = msg->userAuth.createdDbs; - msg->userAuth.createdDbs = NULL; + taosHashCleanup(pUser->userAuth.createdDbs); + taosHashCleanup(pUser->userAuth.readDbs); + taosHashCleanup(pUser->userAuth.writeDbs); + taosHashCleanup(pUser->userAuth.readTbs); + taosHashCleanup(pUser->userAuth.writeTbs); + taosHashCleanup(pUser->userAuth.useDbs); - taosHashCleanup(pUser->readDbs); - pUser->readDbs = msg->userAuth.readDbs; - msg->userAuth.readDbs = NULL; + memcpy(&pUser->userAuth, &msg->userAuth, sizeof(msg->userAuth)); - taosHashCleanup(pUser->writeDbs); - pUser->writeDbs = msg->userAuth.writeDbs; + msg->userAuth.createdDbs = NULL; + msg->userAuth.readDbs = NULL; msg->userAuth.writeDbs = NULL; + msg->userAuth.readTbs = NULL; + msg->userAuth.writeTbs = NULL; + msg->userAuth.useDbs = NULL; CTG_UNLOCK(CTG_WRITE, &pUser->lock); @@ -2065,6 +2249,9 @@ _return: taosHashCleanup(msg->userAuth.createdDbs); taosHashCleanup(msg->userAuth.readDbs); taosHashCleanup(msg->userAuth.writeDbs); + taosHashCleanup(msg->userAuth.readTbs); + taosHashCleanup(msg->userAuth.writeTbs); + taosHashCleanup(msg->userAuth.useDbs); taosMemoryFreeClear(msg); @@ -2257,6 +2444,9 @@ void ctgFreeCacheOperationData(SCtgCacheOperation *op) { taosHashCleanup(msg->userAuth.createdDbs); taosHashCleanup(msg->userAuth.readDbs); taosHashCleanup(msg->userAuth.writeDbs); + taosHashCleanup(msg->userAuth.readTbs); + taosHashCleanup(msg->userAuth.writeTbs); + taosHashCleanup(msg->userAuth.useDbs); taosMemoryFreeClear(op->data); break; } @@ -2292,10 +2482,10 @@ void ctgCleanupCacheQueue(void) { ctgDebug("process [%s] operation", gCtgCacheOperation[op->opId].name); (*gCtgCacheOperation[op->opId].func)(op); stopQueue = true; - CTG_RT_STAT_INC(numOfOpDequeue, 1); + CTG_STAT_RT_INC(numOfOpDequeue, 1); } else { ctgFreeCacheOperationData(op); - CTG_RT_STAT_INC(numOfOpAbort, 1); + CTG_STAT_RT_INC(numOfOpAbort, 1); } if (op->syncOp) { @@ -2351,9 +2541,10 @@ void *ctgUpdateThreadFunc(void *param) { taosMemoryFreeClear(operation); } - CTG_RT_STAT_INC(numOfOpDequeue, 1); + CTG_STAT_RT_INC(numOfOpDequeue, 1); ctgdShowCacheInfo(); + ctgdShowStatInfo(); } qInfo("catalog update thread stopped"); @@ -2494,6 +2685,7 @@ int32_t ctgGetTbMetasFromCache(SCatalog *pCtg, SRequestConnInfo *pConn, SCtgTbMe ctgDebug("tb %s not in cache, dbFName:%s", pName->tname, dbFName); ctgAddFetch(&ctx->pFetchs, dbIdx, i, fetchIdx, baseResIdx + i, flag); taosArrayPush(ctx->pResList, &(SMetaRes){0}); + CTG_META_NHIT_INC(); continue; } @@ -2504,12 +2696,15 @@ int32_t ctgGetTbMetasFromCache(SCatalog *pCtg, SRequestConnInfo *pConn, SCtgTbMe ctgDebug("tb %s meta not in cache, dbFName:%s", pName->tname, dbFName); ctgAddFetch(&ctx->pFetchs, dbIdx, i, fetchIdx, baseResIdx + i, flag); taosArrayPush(ctx->pResList, &(SMetaRes){0}); + CTG_META_NHIT_INC(); continue; } STableMeta *tbMeta = pCache->pMeta; + CTG_META_HIT_INC(tbMeta->tableType); + SCtgTbMetaCtx nctx = {0}; nctx.flag = flag; nctx.tbInfo.inCache = true; @@ -2577,8 +2772,9 @@ int32_t ctgGetTbMetasFromCache(SCatalog *pCtg, SRequestConnInfo *pConn, SCtgTbMe ctgDebug("stb 0x%" PRIx64 " not in cache, dbFName:%s", pTableMeta->suid, dbFName); ctgAddFetch(&ctx->pFetchs, dbIdx, i, fetchIdx, baseResIdx + i, flag); taosArrayPush(ctx->pResList, &(SMetaRes){0}); - taosMemoryFreeClear(pTableMeta); + + CTG_META_NHIT_INC(); continue; } @@ -2589,8 +2785,9 @@ int32_t ctgGetTbMetasFromCache(SCatalog *pCtg, SRequestConnInfo *pConn, SCtgTbMe ctgAddFetch(&ctx->pFetchs, dbIdx, i, fetchIdx, baseResIdx + i, flag); taosArrayPush(ctx->pResList, &(SMetaRes){0}); - taosMemoryFreeClear(pTableMeta); + + CTG_META_NHIT_INC(); continue; } @@ -2604,9 +2801,9 @@ int32_t ctgGetTbMetasFromCache(SCatalog *pCtg, SRequestConnInfo *pConn, SCtgTbMe ctgAddFetch(&ctx->pFetchs, dbIdx, i, fetchIdx, baseResIdx + i, flag); taosArrayPush(ctx->pResList, &(SMetaRes){0}); - taosMemoryFreeClear(pTableMeta); + CTG_META_NHIT_INC(); continue; } @@ -2620,9 +2817,9 @@ int32_t ctgGetTbMetasFromCache(SCatalog *pCtg, SRequestConnInfo *pConn, SCtgTbMe ctgAddFetch(&ctx->pFetchs, dbIdx, i, fetchIdx, baseResIdx + i, flag); taosArrayPush(ctx->pResList, &(SMetaRes){0}); - taosMemoryFreeClear(pTableMeta); + CTG_META_NHIT_INC(); continue; } @@ -2638,6 +2835,8 @@ int32_t ctgGetTbMetasFromCache(SCatalog *pCtg, SRequestConnInfo *pConn, SCtgTbMe CTG_UNLOCK(CTG_READ, &pCache->metaLock); taosHashRelease(dbCache->tbCache, pCache); + CTG_META_HIT_INC(pTableMeta->tableType); + res.pRes = pTableMeta; taosArrayPush(ctx->pResList, &res); diff --git a/source/libs/catalog/src/ctgDbg.c b/source/libs/catalog/src/ctgDbg.c index b6ff1c8b987278ee8ef223577e91771c12cefde8..8924e8c27cf0d4f9a421e87c0fa1615285659072 100644 --- a/source/libs/catalog/src/ctgDbg.c +++ b/source/libs/catalog/src/ctgDbg.c @@ -21,8 +21,9 @@ extern SCatalogMgmt gCtgMgmt; SCtgDebug gCTGDebug = {0}; +#if 0 + void ctgdUserCallback(SMetaData *pResult, void *param, int32_t code) { - ASSERT(*(int32_t *)param == 1); taosMemoryFree(param); qDebug("async call result: %s", tstrerror(code)); @@ -225,6 +226,7 @@ _return: CTG_RET(code); } +#endif int32_t ctgdEnableDebug(char *option, bool enable) { if (0 == strcasecmp(option, "lock")) { @@ -282,7 +284,7 @@ int32_t ctgdHandleDbgCommand(char *command) { CTG_RET(TSDB_CODE_INVALID_PARA); } - char *dup = strdup(command); + char *dup = taosStrdup(command); char *option = NULL; char *param = NULL; @@ -346,7 +348,7 @@ int32_t ctgdGetOneHandle(SCatalog **pHandle) { int32_t ctgdGetStatNum(char *option, void *res) { if (0 == strcasecmp(option, "runtime.numOfOpDequeue")) { - *(uint64_t *)res = atomic_load_64(&gCtgMgmt.stat.runtime.numOfOpDequeue); + *(uint64_t *)res = atomic_load_64(&gCtgMgmt.statInfo.runtime.numOfOpDequeue); return TSDB_CODE_SUCCESS; } @@ -499,6 +501,25 @@ void ctgdShowDBCache(SCatalog *pCtg, SHashObj *dbHash) { } } + if (dbCache->cfgCache.cfgInfo) { + SDbCfgInfo *pCfg = dbCache->cfgCache.cfgInfo; + ctgDebug("[%d] db [%.*s][0x%" PRIx64 + "] %s: cfgVersion:%d, numOfVgroups:%d, numOfStables:%d, buffer:%d, cacheSize:%d, pageSize:%d, pages:%d" + ", daysPerFile:%d, daysToKeep0:%d, daysToKeep1:%d, daysToKeep2:%d, minRows:%d, maxRows:%d, walFsyncPeriod:%d" + ", hashPrefix:%d, hashSuffix:%d, walLevel:%d, precision:%d, compression:%d, replications:%d, strict:%d" + ", cacheLast:%d, tsdbPageSize:%d, walRetentionPeriod:%d, walRollPeriod:%d, walRetentionSize:%" PRId64 "" + ", walSegmentSize:%" PRId64 ", numOfRetensions:%d, schemaless:%d, sstTrigger:%d", + i, (int32_t)len, dbFName, dbCache->dbId, dbCache->deleted ? "deleted" : "", + pCfg->cfgVersion, pCfg->numOfVgroups, pCfg->numOfStables, pCfg->buffer, + pCfg->cacheSize, pCfg->pageSize, pCfg->pages, pCfg->daysPerFile, pCfg->daysToKeep0, + pCfg->daysToKeep1, pCfg->daysToKeep2, pCfg->minRows, pCfg->maxRows, pCfg->walFsyncPeriod, + pCfg->hashPrefix, pCfg->hashSuffix, pCfg->walLevel, pCfg->precision, pCfg->compression, + pCfg->replications, pCfg->strict, pCfg->cacheLast, pCfg->tsdbPageSize, pCfg->walRetentionPeriod, + pCfg->walRollPeriod, pCfg->walRetentionSize, pCfg->walSegmentSize, pCfg->numOfRetensions, + pCfg->schemaless, pCfg->sstTrigger); + } + + ++i; pIter = taosHashIterate(dbHash, pIter); } } @@ -518,6 +539,27 @@ void ctgdShowClusterCache(SCatalog *pCtg) { ctgDebug("## cluster 0x%" PRIx64 " %p cache Info END ##", pCtg->clusterId, pCtg); } +int32_t ctgdShowStatInfo(void) { + if (!gCTGDebug.statEnable) { + return TSDB_CODE_CTG_OUT_OF_SERVICE; + } + + CTG_API_ENTER(); + + SCtgCacheStat cache; + ctgGetGlobalCacheStat(&cache); + + qDebug("## Global Stat Info %s ##", "begin"); + qDebug("## \t%s \t%s \t%s ##", "Num", "Hit", "Nhit"); + for (int32_t i = 0; i < CTG_CI_MAX_VALUE; ++i) { + qDebug("# %s \t%" PRIu64 " \t%" PRIu64 " \t%" PRIu64 " #", gCtgStatItem[i].name, cache.cacheNum[i], cache.cacheHit[i], cache.cacheNHit[i]); + } + qDebug("## Global Stat Info %s ##", "end"); + + CTG_API_LEAVE(TSDB_CODE_SUCCESS); +} + + int32_t ctgdShowCacheInfo(void) { if (!gCTGDebug.cacheEnable) { return TSDB_CODE_CTG_OUT_OF_SERVICE; diff --git a/source/libs/catalog/src/ctgRemote.c b/source/libs/catalog/src/ctgRemote.c index 7cc6c90d303c4c425358800eb646f986417cefdd..3b037e206290ff767a1f879e0b46aadf8b3e4f20 100644 --- a/source/libs/catalog/src/ctgRemote.c +++ b/source/libs/catalog/src/ctgRemote.c @@ -40,7 +40,9 @@ int32_t ctgHandleBatchRsp(SCtgJob* pJob, SCtgTaskCallbackParam* cbParam, SDataBu msgNum = taosArrayGetSize(batchRsp.pRsps); } - ASSERT(taskNum == msgNum || 0 == msgNum); + if (ASSERTS(taskNum == msgNum || 0 == msgNum, "taskNum %d mis-match msgNum %d", taskNum, msgNum)) { + msgNum = 0; + } ctgDebug("QID:0x%" PRIx64 " ctg got batch %d rsp %s", pJob->queryId, cbParam->batchId, TMSG_INFO(cbParam->reqType + 1)); @@ -58,11 +60,19 @@ int32_t ctgHandleBatchRsp(SCtgJob* pJob, SCtgTaskCallbackParam* cbParam, SDataBu if (msgNum > 0) { pRsp = taosArrayGet(batchRsp.pRsps, i); - taskMsg.msgType = pRsp->reqType; - taskMsg.pData = pRsp->msg; - taskMsg.len = pRsp->msgLen; - - ASSERT(pRsp->msgIdx == *msgIdx); + if (ASSERTS(pRsp->msgIdx == *msgIdx, "rsp msgIdx %d mis-match msgIdx %d", pRsp->msgIdx, *msgIdx)) { + pRsp = &rsp; + pRsp->msgIdx = *msgIdx; + pRsp->reqType = -1; + pRsp->rspCode = 0; + taskMsg.msgType = -1; + taskMsg.pData = NULL; + taskMsg.len = 0; + } else { + taskMsg.msgType = pRsp->reqType; + taskMsg.pData = pRsp->msg; + taskMsg.len = pRsp->msgLen; + } } else { pRsp = &rsp; pRsp->msgIdx = *msgIdx; diff --git a/source/libs/catalog/src/ctgUtil.c b/source/libs/catalog/src/ctgUtil.c index 3dd40a413996c458dc204b851ae08e6ca4280529..ae8fe0cca46488d7b6e9f8cd64e2d28368a676ea 100644 --- a/source/libs/catalog/src/ctgUtil.c +++ b/source/libs/catalog/src/ctgUtil.c @@ -77,12 +77,12 @@ char* ctgTaskTypeStr(CTG_TASK_TYPE type) { return "[get table meta]"; case CTG_TASK_GET_TB_HASH: return "[get table hash]"; - case CTG_TASK_GET_TB_INDEX: - return "[get table index]"; + case CTG_TASK_GET_TB_SMA_INDEX: + return "[get table sma]"; case CTG_TASK_GET_TB_CFG: return "[get table cfg]"; - case CTG_TASK_GET_INDEX: - return "[get index]"; + case CTG_TASK_GET_INDEX_INFO: + return "[get index info]"; case CTG_TASK_GET_UDF: return "[get udf]"; case CTG_TASK_GET_USER: @@ -170,13 +170,19 @@ void ctgFreeSMetaData(SMetaData* pData) { taosArrayDestroy(pData->pTableCfg); pData->pTableCfg = NULL; + taosArrayDestroy(pData->pTableTag); + pData->pTableTag = NULL; + taosMemoryFreeClear(pData->pSvrVer); } void ctgFreeSCtgUserAuth(SCtgUserAuth* userCache) { - taosHashCleanup(userCache->createdDbs); - taosHashCleanup(userCache->readDbs); - taosHashCleanup(userCache->writeDbs); + taosHashCleanup(userCache->userAuth.createdDbs); + taosHashCleanup(userCache->userAuth.readDbs); + taosHashCleanup(userCache->userAuth.writeDbs); + taosHashCleanup(userCache->userAuth.readTbs); + taosHashCleanup(userCache->userAuth.writeTbs); + taosHashCleanup(userCache->userAuth.useDbs); } void ctgFreeMetaRent(SCtgRentMgmt* mgmt) { @@ -203,7 +209,6 @@ void ctgFreeStbMetaCache(SCtgDBCache* dbCache) { int32_t stbNum = taosHashGetSize(dbCache->stbCache); taosHashCleanup(dbCache->stbCache); dbCache->stbCache = NULL; - CTG_CACHE_STAT_DEC(numOfStb, stbNum); } void ctgFreeTbCacheImpl(SCtgTbCache* pCache) { @@ -228,10 +233,10 @@ void ctgFreeTbCache(SCtgDBCache* dbCache) { } taosHashCleanup(dbCache->tbCache); dbCache->tbCache = NULL; - CTG_CACHE_STAT_DEC(numOfTbl, tblNum); } void ctgFreeVgInfoCache(SCtgDBCache* dbCache) { freeVgInfo(dbCache->vgCache.vgInfo); } +void ctgFreeCfgInfoCache(SCtgDBCache* dbCache) { freeDbCfgInfo(dbCache->cfgCache.cfgInfo); } void ctgFreeDbCache(SCtgDBCache* dbCache) { if (NULL == dbCache) { @@ -239,6 +244,7 @@ void ctgFreeDbCache(SCtgDBCache* dbCache) { } ctgFreeVgInfoCache(dbCache); + ctgFreeCfgInfoCache(dbCache); ctgFreeStbMetaCache(dbCache); ctgFreeTbCache(dbCache); } @@ -260,8 +266,6 @@ void ctgFreeInstDbCache(SHashObj* pDbCache) { } taosHashCleanup(pDbCache); - - CTG_CACHE_STAT_DEC(numOfDb, dbNum); } void ctgFreeInstUserCache(SHashObj* pUserCache) { @@ -280,8 +284,6 @@ void ctgFreeInstUserCache(SHashObj* pUserCache) { } taosHashCleanup(pUserCache); - - CTG_CACHE_STAT_DEC(numOfUser, userNum); } void ctgFreeHandleImpl(SCatalog* pCtg) { @@ -307,7 +309,7 @@ void ctgFreeHandle(SCatalog* pCtg) { ctgFreeInstDbCache(pCtg->dbCache); ctgFreeInstUserCache(pCtg->userCache); - CTG_CACHE_STAT_DEC(numOfCluster, 1); + CTG_STAT_NUM_DEC(CTG_CI_CLUSTER, 1); taosMemoryFree(pCtg); @@ -342,7 +344,9 @@ void ctgClearHandle(SCatalog* pCtg) { ctgError("taosHashInit %d user cache failed", gCtgMgmt.cfg.maxUserCacheNum); } - CTG_CACHE_STAT_INC(numOfClear, 1); + memset(pCtg->cacheStat.cacheNum, 0, sizeof(pCtg->cacheStat.cacheNum)); + + CTG_STAT_RT_INC(numOfOpClearCache, 1); ctgInfo("handle cleared, clusterId:0x%" PRIx64, clusterId); } @@ -423,6 +427,9 @@ void ctgFreeMsgCtx(SCtgMsgCtx* pCtx) { taosHashCleanup(pOut->createdDbs); taosHashCleanup(pOut->readDbs); taosHashCleanup(pOut->writeDbs); + taosHashCleanup(pOut->readTbs); + taosHashCleanup(pOut->writeTbs); + taosHashCleanup(pOut->useDbs); taosMemoryFreeClear(pCtx->out); break; } @@ -484,6 +491,18 @@ void ctgFreeBatchHash(void* hash) { taosMemoryFreeClear(pRes->pRes); } +void ctgFreeJsonTagVal(void* val) { + if (NULL == val) { + return; + } + + STagVal* pVal = (STagVal*)val; + + if (TSDB_DATA_TYPE_JSON == pVal->type) { + taosMemoryFree(pVal->pData); + } +} + void ctgFreeTaskRes(CTG_TASK_TYPE type, void** pRes) { switch (type) { case CTG_TASK_GET_QNODE: @@ -501,7 +520,7 @@ void ctgFreeTaskRes(CTG_TASK_TYPE type, void** pRes) { } break; } - case CTG_TASK_GET_TB_INDEX: { + case CTG_TASK_GET_TB_SMA_INDEX: { taosArrayDestroyEx(*pRes, tFreeSTableIndexInfo); *pRes = NULL; break; @@ -514,16 +533,32 @@ void ctgFreeTaskRes(CTG_TASK_TYPE type, void** pRes) { } break; } + case CTG_TASK_GET_USER: { + if (*pRes) { + SUserAuthRes* pAuth = (SUserAuthRes*)*pRes; + nodesDestroyNode(pAuth->pCond); + taosMemoryFreeClear(*pRes); + } + break; + } case CTG_TASK_GET_TB_HASH: case CTG_TASK_GET_DB_INFO: - case CTG_TASK_GET_INDEX: + case CTG_TASK_GET_INDEX_INFO: case CTG_TASK_GET_UDF: - case CTG_TASK_GET_USER: case CTG_TASK_GET_SVR_VER: case CTG_TASK_GET_TB_META: { taosMemoryFreeClear(*pRes); break; } + case CTG_TASK_GET_TB_TAG: { + if (1 == taosArrayGetSize(*pRes)) { + taosArrayDestroyEx(*pRes, ctgFreeJsonTagVal); + } else { + taosArrayDestroy(*pRes); + } + *pRes = NULL; + break; + } case CTG_TASK_GET_TB_META_BATCH: { SArray* pArray = (SArray*)*pRes; int32_t num = taosArrayGetSize(pArray); @@ -571,7 +606,7 @@ void ctgFreeSubTaskRes(CTG_TASK_TYPE type, void** pRes) { } break; } - case CTG_TASK_GET_TB_INDEX: { + case CTG_TASK_GET_TB_SMA_INDEX: { taosArrayDestroyEx(*pRes, tFreeSTableIndexInfo); *pRes = NULL; break; @@ -587,7 +622,7 @@ void ctgFreeSubTaskRes(CTG_TASK_TYPE type, void** pRes) { case CTG_TASK_GET_TB_META: case CTG_TASK_GET_DB_INFO: case CTG_TASK_GET_TB_HASH: - case CTG_TASK_GET_INDEX: + case CTG_TASK_GET_INDEX_INFO: case CTG_TASK_GET_UDF: case CTG_TASK_GET_SVR_VER: case CTG_TASK_GET_USER: { @@ -664,7 +699,7 @@ void ctgFreeTaskCtx(SCtgTask* pTask) { taosMemoryFreeClear(pTask->taskCtx); break; } - case CTG_TASK_GET_TB_INDEX: { + case CTG_TASK_GET_TB_SMA_INDEX: { SCtgTbIndexCtx* taskCtx = (SCtgTbIndexCtx*)pTask->taskCtx; taosMemoryFreeClear(taskCtx->pName); taosMemoryFreeClear(pTask->taskCtx); @@ -677,10 +712,17 @@ void ctgFreeTaskCtx(SCtgTask* pTask) { taosMemoryFreeClear(pTask->taskCtx); break; } + case CTG_TASK_GET_TB_TAG: { + SCtgTbTagCtx* taskCtx = (SCtgTbTagCtx*)pTask->taskCtx; + taosMemoryFreeClear(taskCtx->pName); + taosMemoryFreeClear(taskCtx->pVgInfo); + taosMemoryFreeClear(taskCtx); + break; + } case CTG_TASK_GET_DB_VGROUP: case CTG_TASK_GET_DB_CFG: case CTG_TASK_GET_DB_INFO: - case CTG_TASK_GET_INDEX: + case CTG_TASK_GET_INDEX_INFO: case CTG_TASK_GET_UDF: case CTG_TASK_GET_QNODE: case CTG_TASK_GET_USER: { @@ -742,7 +784,7 @@ int32_t ctgUpdateMsgCtx(SCtgMsgCtx* pCtx, int32_t reqType, void* out, char* targ pCtx->reqType = reqType; pCtx->out = out; if (target) { - pCtx->target = strdup(target); + pCtx->target = taosStrdup(target); if (NULL == pCtx->target) { CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } @@ -759,7 +801,7 @@ int32_t ctgAddMsgCtx(SArray* pCtxs, int32_t reqType, void* out, char* target) { ctx.reqType = reqType; ctx.out = out; if (target) { - ctx.target = strdup(target); + ctx.target = taosStrdup(target); if (NULL == ctx.target) { CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } @@ -869,19 +911,19 @@ int32_t ctgGetVgInfoFromHashValue(SCatalog* pCtg, SDBVgInfo* dbInfo, const SName vgInfo = taosArraySearch(dbInfo->vgArray, &hashValue, ctgHashValueComp, TD_EQ); -/* - void* pIter = taosHashIterate(dbInfo->vgHash, NULL); - while (pIter) { - vgInfo = pIter; - if (hashValue >= vgInfo->hashBegin && hashValue <= vgInfo->hashEnd) { - taosHashCancelIterate(dbInfo->vgHash, pIter); - break; - } + /* + void* pIter = taosHashIterate(dbInfo->vgHash, NULL); + while (pIter) { + vgInfo = pIter; + if (hashValue >= vgInfo->hashBegin && hashValue <= vgInfo->hashEnd) { + taosHashCancelIterate(dbInfo->vgHash, pIter); + break; + } - pIter = taosHashIterate(dbInfo->vgHash, pIter); - vgInfo = NULL; - } -*/ + pIter = taosHashIterate(dbInfo->vgHash, pIter); + vgInfo = NULL; + } + */ if (NULL == vgInfo) { ctgError("no hash range found for hash value [%u], db:%s, numOfVgId:%d", hashValue, db, @@ -906,7 +948,7 @@ int32_t ctgGetVgInfosFromHashValue(SCatalog* pCtg, SCtgTaskReq* tReq, SDBVgInfo* CTG_ERR_RET(ctgMakeVgArray(dbInfo)); - int32_t vgNum = taosArrayGetSize(dbInfo->vgArray); + int32_t vgNum = taosArrayGetSize(dbInfo->vgArray); if (vgNum <= 0) { ctgError("db vgroup cache invalid, db:%s, vgroup number:%d", dbFName, vgNum); CTG_ERR_RET(TSDB_CODE_CTG_INTERNAL_ERROR); @@ -986,43 +1028,43 @@ int32_t ctgGetVgInfosFromHashValue(SCatalog* pCtg, SCtgTaskReq* tReq, SDBVgInfo* CTG_RET(code); } -int32_t ctgGetVgIdsFromHashValue(SCatalog* pCtg, SDBVgInfo* dbInfo, char* dbFName, const char* pTbs[], int32_t tbNum, int32_t* vgId) { - int32_t code = 0; - CTG_ERR_RET(ctgMakeVgArray(dbInfo)); +int32_t ctgGetVgIdsFromHashValue(SCatalog* pCtg, SDBVgInfo* dbInfo, char* dbFName, const char* pTbs[], int32_t tbNum, + int32_t* vgId) { + int32_t code = 0; + CTG_ERR_RET(ctgMakeVgArray(dbInfo)); + + int32_t vgNum = taosArrayGetSize(dbInfo->vgArray); - int32_t vgNum = taosArrayGetSize(dbInfo->vgArray); + if (vgNum <= 0) { + ctgError("db vgroup cache invalid, db:%s, vgroup number:%d", dbFName, vgNum); + CTG_ERR_RET(TSDB_CODE_TSC_DB_NOT_SELECTED); + } - if (vgNum <= 0) { - ctgError("db vgroup cache invalid, db:%s, vgroup number:%d", dbFName, vgNum); - CTG_ERR_RET(TSDB_CODE_TSC_DB_NOT_SELECTED); - } + SVgroupInfo* vgInfo = NULL; + char tbFullName[TSDB_TABLE_FNAME_LEN]; + snprintf(tbFullName, sizeof(tbFullName), "%s.", dbFName); + int32_t offset = strlen(tbFullName); - SVgroupInfo* vgInfo = NULL; - char tbFullName[TSDB_TABLE_FNAME_LEN]; - snprintf(tbFullName, sizeof(tbFullName), "%s.", dbFName); - int32_t offset = strlen(tbFullName); - - for (int32_t i = 0; i < tbNum; ++i) { - snprintf(tbFullName + offset, sizeof(tbFullName) - offset, "%s", pTbs[i]); - uint32_t hashValue = taosGetTbHashVal(tbFullName, (uint32_t)strlen(tbFullName), dbInfo->hashMethod, - dbInfo->hashPrefix, dbInfo->hashSuffix); + for (int32_t i = 0; i < tbNum; ++i) { + snprintf(tbFullName + offset, sizeof(tbFullName) - offset, "%s", pTbs[i]); + uint32_t hashValue = taosGetTbHashVal(tbFullName, (uint32_t)strlen(tbFullName), dbInfo->hashMethod, + dbInfo->hashPrefix, dbInfo->hashSuffix); - vgInfo = taosArraySearch(dbInfo->vgArray, &hashValue, ctgHashValueComp, TD_EQ); - if (NULL == vgInfo) { - ctgError("no hash range found for hash value [%u], db:%s, numOfVgId:%d", hashValue, dbFName, - (int32_t)taosArrayGetSize(dbInfo->vgArray)); - CTG_ERR_RET(TSDB_CODE_CTG_INTERNAL_ERROR); - } + vgInfo = taosArraySearch(dbInfo->vgArray, &hashValue, ctgHashValueComp, TD_EQ); + if (NULL == vgInfo) { + ctgError("no hash range found for hash value [%u], db:%s, numOfVgId:%d", hashValue, dbFName, + (int32_t)taosArrayGetSize(dbInfo->vgArray)); + CTG_ERR_RET(TSDB_CODE_CTG_INTERNAL_ERROR); + } - vgId[i] = vgInfo->vgId; + vgId[i] = vgInfo->vgId; - ctgDebug("Got tb %s vgId:%d", tbFullName, vgInfo->vgId); - } + ctgDebug("Got tb %s vgId:%d", tbFullName, vgInfo->vgId); + } - CTG_RET(code); + CTG_RET(code); } - int32_t ctgStbVersionSearchCompare(const void* key1, const void* key2) { if (*(uint64_t*)key1 < ((SSTableVersion*)key2)->suid) { return -1; @@ -1033,10 +1075,10 @@ int32_t ctgStbVersionSearchCompare(const void* key1, const void* key2) { } } -int32_t ctgDbVgVersionSearchCompare(const void* key1, const void* key2) { - if (*(int64_t*)key1 < ((SDbVgVersion*)key2)->dbId) { +int32_t ctgDbCacheInfoSearchCompare(const void* key1, const void* key2) { + if (*(int64_t*)key1 < ((SDbCacheInfo*)key2)->dbId) { return -1; - } else if (*(int64_t*)key1 > ((SDbVgVersion*)key2)->dbId) { + } else if (*(int64_t*)key1 > ((SDbCacheInfo*)key2)->dbId) { return 1; } else { return 0; @@ -1053,10 +1095,10 @@ int32_t ctgStbVersionSortCompare(const void* key1, const void* key2) { } } -int32_t ctgDbVgVersionSortCompare(const void* key1, const void* key2) { - if (((SDbVgVersion*)key1)->dbId < ((SDbVgVersion*)key2)->dbId) { +int32_t ctgDbCacheInfoSortCompare(const void* key1, const void* key2) { + if (((SDbCacheInfo*)key1)->dbId < ((SDbCacheInfo*)key2)->dbId) { return -1; - } else if (((SDbVgVersion*)key1)->dbId > ((SDbVgVersion*)key2)->dbId) { + } else if (((SDbCacheInfo*)key1)->dbId > ((SDbCacheInfo*)key2)->dbId) { return 1; } else { return 0; @@ -1067,26 +1109,25 @@ int32_t ctgMakeVgArray(SDBVgInfo* dbInfo) { if (NULL == dbInfo) { return TSDB_CODE_SUCCESS; } - + if (dbInfo->vgHash && NULL == dbInfo->vgArray) { dbInfo->vgArray = taosArrayInit(100, sizeof(SVgroupInfo)); if (NULL == dbInfo->vgArray) { CTG_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } - - void* pIter = taosHashIterate(dbInfo->vgHash, NULL); + + void* pIter = taosHashIterate(dbInfo->vgHash, NULL); while (pIter) { taosArrayPush(dbInfo->vgArray, pIter); pIter = taosHashIterate(dbInfo->vgHash, pIter); } - + taosArraySort(dbInfo->vgArray, ctgVgInfoComp); } return TSDB_CODE_SUCCESS; } - int32_t ctgCloneVgInfo(SDBVgInfo* src, SDBVgInfo** dst) { CTG_ERR_RET(ctgMakeVgArray(src)); @@ -1169,7 +1210,7 @@ int32_t ctgCloneTableIndex(SArray* pIndex, SArray** pRes) { for (int32_t i = 0; i < num; ++i) { STableIndexInfo* pInfo = taosArrayGet(pIndex, i); pInfo = taosArrayPush(*pRes, pInfo); - pInfo->expr = strdup(pInfo->expr); + pInfo->expr = taosStrdup(pInfo->expr); } return TSDB_CODE_SUCCESS; @@ -1179,7 +1220,7 @@ int32_t ctgUpdateSendTargetInfo(SMsgSendInfo* pMsgSendInfo, int32_t msgType, cha if (msgType == TDMT_VND_TABLE_META || msgType == TDMT_VND_TABLE_CFG || msgType == TDMT_VND_BATCH_META) { pMsgSendInfo->target.type = TARGET_TYPE_VNODE; pMsgSendInfo->target.vgId = vgId; - pMsgSendInfo->target.dbFName = strdup(dbFName); + pMsgSendInfo->target.dbFName = taosStrdup(dbFName); } else { pMsgSendInfo->target.type = TARGET_TYPE_MNODE; } @@ -1228,16 +1269,20 @@ static void* ctgCloneDbVgroup(void* pSrc) { return taosArrayDup((const SArray*)p static void ctgFreeDbVgroup(void* p) { taosArrayDestroy((SArray*)((SMetaRes*)p)->pRes); } -static void* ctgCloneDbCfgInfo(void* pSrc) { +void* ctgCloneDbCfgInfo(void* pSrc) { SDbCfgInfo* pDst = taosMemoryMalloc(sizeof(SDbCfgInfo)); if (NULL == pDst) { return NULL; } memcpy(pDst, pSrc, sizeof(SDbCfgInfo)); + pDst->pRetensions = taosArrayDup(((SDbCfgInfo *)pSrc)->pRetensions, NULL); return pDst; } -static void ctgFreeDbCfgInfo(void* p) { taosMemoryFree(((SMetaRes*)p)->pRes); } +static void ctgFreeDbCfgInfo(void* p) { + SDbCfgInfo* pDst = (SDbCfgInfo *)((SMetaRes*)p)->pRes; + freeDbCfgInfo(pDst); +} static void* ctgCloneDbInfo(void* pSrc) { SDbInfo* pDst = taosMemoryMalloc(sizeof(SDbInfo)); @@ -1330,6 +1375,162 @@ static void* ctgCloneDnodeList(void* pSrc) { return taosArrayDup((const SArray*) static void ctgFreeDnodeList(void* p) { taosArrayDestroy((SArray*)((SMetaRes*)p)->pRes); } +int32_t ctgChkSetTbAuthRes(SCatalog* pCtg, SCtgAuthReq* req, SCtgAuthRsp* res) { + int32_t code = 0; + STableMeta* pMeta = NULL; + SGetUserAuthRsp* pInfo = &req->authInfo; + SHashObj* pTbs = (AUTH_TYPE_READ == req->singleType) ? pInfo->readTbs : pInfo->writeTbs; + char* stbName = NULL; + + char tbFName[TSDB_TABLE_FNAME_LEN]; + char dbFName[TSDB_DB_FNAME_LEN]; + tNameExtractFullName(&req->pRawReq->tbName, tbFName); + tNameGetFullDbName(&req->pRawReq->tbName, dbFName); + + while (true) { + taosMemoryFreeClear(pMeta); + + char* pCond = taosHashGet(pTbs, tbFName, strlen(tbFName)); + if (pCond) { + if (strlen(pCond) > 1) { + CTG_ERR_JRET(nodesStringToNode(pCond, &res->pRawRes->pCond)); + } + + res->pRawRes->pass = true; + goto _return; + } + + if (stbName) { + res->pRawRes->pass = false; + goto _return; + } + + CTG_ERR_JRET(catalogGetCachedTableMeta(pCtg, &req->pRawReq->tbName, &pMeta)); + if (NULL == pMeta) { + if (req->onlyCache) { + res->metaNotExists = true; + ctgDebug("db %s tb %s meta not in cache for auth", req->pRawReq->tbName.dbname, req->pRawReq->tbName.tname); + goto _return; + } + + SCtgTbMetaCtx ctx = {0}; + ctx.pName = (SName*)&req->pRawReq->tbName; + ctx.flag = CTG_FLAG_UNKNOWN_STB | CTG_FLAG_SYNC_OP; + + CTG_ERR_JRET(ctgGetTbMeta(pCtg, req->pConn, &ctx, &pMeta)); + } + + if (TSDB_SUPER_TABLE == pMeta->tableType || TSDB_NORMAL_TABLE == pMeta->tableType) { + res->pRawRes->pass = false; + goto _return; + } + + if (TSDB_CHILD_TABLE == pMeta->tableType) { + CTG_ERR_JRET(ctgGetCachedStbNameFromSuid(pCtg, dbFName, pMeta->suid, &stbName)); + if (NULL == stbName) { + if (req->onlyCache) { + res->metaNotExists = true; + ctgDebug("suid %" PRIu64 " name not in cache for auth", pMeta->suid); + goto _return; + } + + continue; + } + + sprintf(tbFName, "%s.%s", dbFName, stbName); + continue; + } + + ctgError("Invalid table type %d for %s", pMeta->tableType, tbFName); + CTG_ERR_JRET(TSDB_CODE_INVALID_PARA); + } + +_return: + + taosMemoryFree(pMeta); + taosMemoryFree(stbName); + + CTG_RET(code); +} + +int32_t ctgChkSetAuthRes(SCatalog* pCtg, SCtgAuthReq* req, SCtgAuthRsp* res) { + int32_t code = 0; + SUserAuthInfo* pReq = req->pRawReq; + SUserAuthRes* pRes = res->pRawRes; + SGetUserAuthRsp* pInfo = &req->authInfo; + + pRes->pass = false; + pRes->pCond = NULL; + + if (!pInfo->enable) { + pRes->pass = false; + return TSDB_CODE_SUCCESS; + } + + if (pInfo->superAuth) { + pRes->pass = true; + return TSDB_CODE_SUCCESS; + } + + char dbFName[TSDB_DB_FNAME_LEN]; + tNameGetFullDbName(&pReq->tbName, dbFName); + + if (pInfo->createdDbs && taosHashGet(pInfo->createdDbs, dbFName, strlen(dbFName))) { + pRes->pass = true; + return TSDB_CODE_SUCCESS; + } + + switch (pReq->type) { + case AUTH_TYPE_READ: { + if (pInfo->readTbs && taosHashGetSize(pInfo->readTbs) > 0) { + req->singleType = AUTH_TYPE_READ; + CTG_ERR_RET(ctgChkSetTbAuthRes(pCtg, req, res)); + if (pRes->pass || res->metaNotExists) { + return TSDB_CODE_SUCCESS; + } + } + + if (pInfo->readDbs && taosHashGet(pInfo->readDbs, dbFName, strlen(dbFName))) { + pRes->pass = true; + return TSDB_CODE_SUCCESS; + } + + break; + } + case AUTH_TYPE_WRITE: { + if (pInfo->writeTbs && taosHashGetSize(pInfo->writeTbs) > 0) { + req->singleType = AUTH_TYPE_WRITE; + CTG_ERR_RET(ctgChkSetTbAuthRes(pCtg, req, res)); + if (pRes->pass || res->metaNotExists) { + return TSDB_CODE_SUCCESS; + } + } + + if (pInfo->writeDbs && taosHashGet(pInfo->writeDbs, dbFName, strlen(dbFName))) { + pRes->pass = true; + return TSDB_CODE_SUCCESS; + } + + break; + } + case AUTH_TYPE_READ_OR_WRITE: { + if ((pInfo->readDbs && taosHashGet(pInfo->readDbs, dbFName, strlen(dbFName))) || + (pInfo->writeDbs && taosHashGet(pInfo->writeDbs, dbFName, strlen(dbFName))) || + (pInfo->useDbs && taosHashGet(pInfo->useDbs, dbFName, strlen(dbFName)))) { + pRes->pass = true; + return TSDB_CODE_SUCCESS; + } + + break; + } + default: + break; + } + + return TSDB_CODE_SUCCESS; +} + +#if 0 static int32_t ctgCloneMetaDataArray(SArray* pSrc, __array_item_dup_fn_t copyFunc, SArray** pDst) { if (NULL == pSrc) { return TSDB_CODE_SUCCESS; @@ -1421,3 +1622,69 @@ void catalogFreeMetaData(SMetaData* pData) { taosMemoryFreeClear(pData->pSvrVer); taosMemoryFree(pData); } +#endif + +void ctgGetClusterCacheStat(SCatalog* pCtg) { + for (int32_t i = 0; i < CTG_CI_MAX_VALUE; ++i) { + if (0 == (gCtgStatItem[i].flag & CTG_CI_FLAG_LEVEL_DB)) { + continue; + } + + pCtg->cacheStat.cacheNum[i] = 0; + } + + SCtgDBCache* dbCache = NULL; + void* pIter = taosHashIterate(pCtg->dbCache, NULL); + while (pIter) { + dbCache = (SCtgDBCache*)pIter; + + for (int32_t i = 0; i < CTG_CI_MAX_VALUE; ++i) { + if (0 == (gCtgStatItem[i].flag & CTG_CI_FLAG_LEVEL_DB)) { + continue; + } + + pCtg->cacheStat.cacheNum[i] += dbCache->dbCacheNum[i]; + } + + pIter = taosHashIterate(pCtg->dbCache, pIter); + } +} + +void ctgSummaryClusterCacheStat(SCatalog* pCtg) { + for (int32_t i = 0; i < CTG_CI_MAX_VALUE; ++i) { + if (gCtgStatItem[i].flag & CTG_CI_FLAG_LEVEL_GLOBAL) { + continue; + } + + gCtgMgmt.statInfo.cache.cacheNum[i] += pCtg->cacheStat.cacheNum[i]; + gCtgMgmt.statInfo.cache.cacheHit[i] += pCtg->cacheStat.cacheHit[i]; + gCtgMgmt.statInfo.cache.cacheNHit[i] += pCtg->cacheStat.cacheNHit[i]; + } +} + +void ctgGetGlobalCacheStat(SCtgCacheStat* pStat) { + for (int32_t i = 0; i < CTG_CI_MAX_VALUE; ++i) { + if (gCtgStatItem[i].flag & CTG_CI_FLAG_LEVEL_GLOBAL) { + continue; + } + + gCtgMgmt.statInfo.cache.cacheNum[i] = 0; + gCtgMgmt.statInfo.cache.cacheHit[i] = 0; + gCtgMgmt.statInfo.cache.cacheNHit[i] = 0; + } + + SCatalog* pCtg = NULL; + void* pIter = taosHashIterate(gCtgMgmt.pCluster, NULL); + while (pIter) { + pCtg = *(SCatalog**)pIter; + + if (pCtg) { + ctgGetClusterCacheStat(pCtg); + ctgSummaryClusterCacheStat(pCtg); + } + + pIter = taosHashIterate(gCtgMgmt.pCluster, pIter); + } + + memcpy(pStat, &gCtgMgmt.statInfo.cache, sizeof(gCtgMgmt.statInfo.cache)); +} diff --git a/source/libs/catalog/test/CMakeLists.txt b/source/libs/catalog/test/CMakeLists.txt index dbbb24ce0b5e8b3ac37b212d88b49d2766bf78ca..de4d08835cf0ebd149e36f252330dfb73940f8df 100644 --- a/source/libs/catalog/test/CMakeLists.txt +++ b/source/libs/catalog/test/CMakeLists.txt @@ -9,7 +9,7 @@ IF(NOT TD_DARWIN) ADD_EXECUTABLE(catalogTest ${SOURCE_LIST}) TARGET_LINK_LIBRARIES( catalogTest - PUBLIC os util common catalog transport gtest qcom taos_static + PUBLIC os util common nodes catalog transport gtest qcom taos_static ) TARGET_INCLUDE_DIRECTORIES( diff --git a/source/libs/catalog/test/catalogTests.cpp b/source/libs/catalog/test/catalogTests.cpp index 5e543384ac2747005ddb40602ca778253ea1eacd..66d2de083b54e25d691c5b1cfd65c691b9dd6157 100644 --- a/source/libs/catalog/test/catalogTests.cpp +++ b/source/libs/catalog/test/catalogTests.cpp @@ -27,8 +27,8 @@ #ifdef WINDOWS #define TD_USE_WINSOCK #endif -#include "catalogInt.h" #include "catalog.h" +#include "catalogInt.h" #include "os.h" #include "stub.h" #include "taos.h" @@ -48,7 +48,7 @@ void ctgTestSetRspCTableMeta(); void ctgTestSetRspSTableMeta(); void ctgTestSetRspMultiSTableMeta(); -extern int32_t clientConnRefPool; +extern int32_t clientConnRefPool; enum { CTGT_RSP_VGINFO = 1, @@ -298,7 +298,7 @@ void ctgTestBuildSTableMetaRsp(STableMetaRsp *rspMsg) { void ctgTestRspDbVgroups(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + SUseDbRsp usedbRsp = {0}; strcpy(usedbRsp.db, ctgTestDbname); usedbRsp.vgVersion = ctgTestVgVersion; @@ -343,7 +343,7 @@ void ctgTestRspDbVgroups(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg * void ctgTestRspTableMeta(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + STableMetaRsp metaRsp = {0}; strcpy(metaRsp.dbFName, ctgTestDbname); strcpy(metaRsp.tbName, ctgTestTablename); @@ -384,13 +384,13 @@ void ctgTestRspTableMeta(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg * void ctgTestRspTableMetaNotExist(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + pRsp->code = CTG_ERR_CODE_TABLE_NOT_EXIST; } void ctgTestRspCTableMeta(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + STableMetaRsp metaRsp = {0}; strcpy(metaRsp.dbFName, ctgTestDbname); strcpy(metaRsp.tbName, ctgTestCurrentCTableName ? ctgTestCurrentCTableName : ctgTestCTablename); @@ -438,7 +438,7 @@ void ctgTestRspCTableMeta(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg void ctgTestRspSTableMeta(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + STableMetaRsp metaRsp = {0}; strcpy(metaRsp.dbFName, ctgTestDbname); strcpy(metaRsp.tbName, ctgTestCurrentSTableName ? ctgTestCurrentSTableName : ctgTestSTablename); @@ -450,7 +450,7 @@ void ctgTestRspSTableMeta(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg metaRsp.sversion = ctgTestSVersion; metaRsp.tversion = ctgTestTVersion; metaRsp.suid = ctgTestSuid; - metaRsp.tuid = ctgTestSuid+1; + metaRsp.tuid = ctgTestSuid + 1; metaRsp.vgId = 0; metaRsp.pSchemas = (SSchema *)taosMemoryMalloc((metaRsp.numOfTags + metaRsp.numOfColumns) * sizeof(SSchema)); @@ -486,7 +486,7 @@ void ctgTestRspSTableMeta(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg void ctgTestRspMultiSTableMeta(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + static int32_t idx = 1; STableMetaRsp metaRsp = {0}; @@ -536,16 +536,14 @@ void ctgTestRspMultiSTableMeta(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRp tFreeSTableMetaRsp(&metaRsp); } - void ctgTestRspErrIndexInfo(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + pRsp->code = TSDB_CODE_MND_DB_INDEX_NOT_EXIST; pRsp->contLen = 0; pRsp->pCont = NULL; } - void ctgTestRspUserAuth(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); @@ -553,6 +551,7 @@ void ctgTestRspUserAuth(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *p strcpy(userRsp.user, ctgTestUsername); userRsp.version = 1; userRsp.superAuth = 1; + userRsp.enable = 1; int32_t contLen = tSerializeSGetUserAuthRsp(NULL, 0, &userRsp); void *pReq = rpcMallocCont(contLen); @@ -565,7 +564,7 @@ void ctgTestRspUserAuth(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *p void ctgTestRspTableCfg(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + static int32_t idx = 1; STableCfgRsp tblRsp = {0}; @@ -600,7 +599,7 @@ void ctgTestRspTableCfg(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *p void ctgTestRspTableIndex(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + static int32_t idx = 1; STableIndexRsp tblRsp = {0}; @@ -611,10 +610,10 @@ void ctgTestRspTableIndex(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg STableIndexInfo info = {0}; for (int32_t i = 0; i < ctgTestIndexNum; ++i) { info.interval = 1 + i; - info.expr = (char*)taosMemoryCalloc(1, 10); + info.expr = (char *)taosMemoryCalloc(1, 10); taosArrayPush(tblRsp.pIndex, &info); } - + int32_t contLen = tSerializeSTableIndexRsp(NULL, 0, &tblRsp); void *pReq = rpcMallocCont(contLen); tSerializeSTableIndexRsp(pReq, contLen, &tblRsp); @@ -628,12 +627,12 @@ void ctgTestRspTableIndex(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg void ctgTestRspDBCfg(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { rpcFreeCont(pMsg->pCont); - + static int32_t idx = 1; SDbCfgRsp dbRsp = {0}; dbRsp.numOfVgroups = ctgTestVgNum; - + int32_t contLen = tSerializeSDbCfgRsp(NULL, 0, &dbRsp); void *pReq = rpcMallocCont(contLen); tSerializeSDbCfgRsp(pReq, contLen, &dbRsp); @@ -651,7 +650,7 @@ void ctgTestRspQnodeList(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg * for (int32_t i = 0; i < ctgTestQnodeNum; ++i) { SQueryNodeLoad nodeLoad = {0}; nodeLoad.addr.nodeId = i; - + (void)taosArrayPush(qlistRsp.qnodeList, &nodeLoad); } @@ -672,12 +671,17 @@ void ctgTestRspUdfInfo(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pR SRetrieveFuncRsp funcRsp = {0}; funcRsp.numOfFuncs = 1; funcRsp.pFuncInfos = taosArrayInit(1, sizeof(SFuncInfo)); + funcRsp.pFuncExtraInfos = taosArrayInit(1, sizeof(SFuncExtraInfo)); SFuncInfo funcInfo = {0}; strcpy(funcInfo.name, "func1"); funcInfo.funcType = ctgTestFuncType; - - (void)taosArrayPush(funcRsp.pFuncInfos, &funcInfo); + (void)taosArrayPush(funcRsp.pFuncInfos, &funcInfo); + SFuncExtraInfo extraInfo = {0}; + extraInfo.funcVersion = 0; + extraInfo.funcCreatedTime = taosGetTimestampMs(); + (void)taosArrayPush(funcRsp.pFuncExtraInfos, &extraInfo); + int32_t rspLen = tSerializeSRetrieveFuncRsp(NULL, 0, &funcRsp); void *pReq = rpcMallocCont(rspLen); tSerializeSRetrieveFuncRsp(pReq, rspLen, &funcRsp); @@ -694,7 +698,7 @@ void ctgTestRspSvrVer(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRs SServerVerRsp verRsp = {0}; strcpy(verRsp.ver, "1.0"); - + int32_t rspLen = tSerializeSServerVerRsp(NULL, 0, &verRsp); void *pReq = rpcMallocCont(rspLen); tSerializeSServerVerRsp(pReq, rspLen, &verRsp); @@ -713,9 +717,9 @@ void ctgTestRspDndeList(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *p epSet.numOfEps = 1; tstrncpy(epSet.eps[0].fqdn, "localhost", TSDB_FQDN_LEN); epSet.eps[0].port = 6030; - + (void)taosArrayPush(dRsp.dnodeList, &epSet); - + int32_t rspLen = tSerializeSDnodeListRsp(NULL, 0, &dRsp); void *pReq = rpcMallocCont(rspLen); tSerializeSDnodeListRsp(pReq, rspLen, &dRsp); @@ -727,8 +731,6 @@ void ctgTestRspDndeList(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *p tFreeSDnodeListRsp(&dRsp); } - - void ctgTestRspAuto(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { switch (pMsg->msgType) { case TDMT_MND_USE_DB: @@ -745,7 +747,7 @@ void ctgTestRspAuto(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) ctgTestRspDBCfg(shandle, pEpSet, pMsg, pRsp); break; case TDMT_MND_QNODE_LIST: - ctgTestRspQnodeList(shandle, pEpSet, pMsg, pRsp); + ctgTestRspQnodeList(shandle, pEpSet, pMsg, pRsp); break; case TDMT_MND_RETRIEVE_FUNC: ctgTestRspUdfInfo(shandle, pEpSet, pMsg, pRsp); @@ -763,7 +765,6 @@ void ctgTestRspAuto(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) return; } - void ctgTestRspByIdx(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp) { switch (ctgTestRspFunc[ctgTestRspIdx]) { case CTGT_RSP_VGINFO: @@ -1058,7 +1059,7 @@ void ctgTestSetRspDbVgroupsAndMultiSuperMeta() { void *ctgTestGetDbVgroupThread(void *param) { struct SCatalog *pCtg = (struct SCatalog *)param; int32_t code = 0; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SArray *vgList = NULL; int32_t n = 0; @@ -1204,7 +1205,6 @@ void *ctgTestSetCtableMetaThread(void *param) { return NULL; } - void ctgTestFetchRows(TAOS_RES *result, int32_t *rows) { TAOS_ROW row; int num_fields = taos_num_fields(result); @@ -1220,23 +1220,22 @@ void ctgTestFetchRows(TAOS_RES *result, int32_t *rows) { } } -void ctgTestExecQuery(TAOS * taos, char* sql, bool fetch, int32_t *rows) { +void ctgTestExecQuery(TAOS *taos, char *sql, bool fetch, int32_t *rows) { TAOS_RES *result = taos_query(taos, sql); - int code = taos_errno(result); + int code = taos_errno(result); ASSERT_EQ(code, 0); if (fetch) { ctgTestFetchRows(result, rows); } - + taos_free_result(result); } - TEST(tableMeta, normalTable) { struct SCatalog *pCtg = NULL; SVgroupInfo vgInfo = {0}; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -1332,7 +1331,7 @@ TEST(tableMeta, normalTable) { ASSERT_EQ(tableMeta->tableInfo.precision, 1); ASSERT_EQ(tableMeta->tableInfo.rowSize, 12); - SDbVgVersion *dbs = NULL; + SDbCacheInfo *dbs = NULL; SSTableVersion *stb = NULL; uint32_t dbNum = 0, stbNum = 0, allDbNum = 0, allStbNum = 0; int32_t i = 0; @@ -1372,7 +1371,7 @@ TEST(tableMeta, normalTable) { TEST(tableMeta, childTableCase) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; @@ -1444,7 +1443,7 @@ TEST(tableMeta, childTableCase) { taosMemoryFree(tableMeta); - SDbVgVersion *dbs = NULL; + SDbCacheInfo *dbs = NULL; SSTableVersion *stb = NULL; uint32_t dbNum = 0, stbNum = 0, allDbNum = 0, allStbNum = 0; int32_t i = 0; @@ -1484,7 +1483,7 @@ TEST(tableMeta, childTableCase) { TEST(tableMeta, superTableCase) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; @@ -1585,7 +1584,7 @@ TEST(tableMeta, superTableCase) { taosMemoryFree(tableMeta); - SDbVgVersion *dbs = NULL; + SDbCacheInfo *dbs = NULL; SSTableVersion *stb = NULL; uint32_t dbNum = 0, stbNum = 0, allDbNum = 0, allStbNum = 0; int32_t i = 0; @@ -1626,7 +1625,7 @@ TEST(tableMeta, superTableCase) { TEST(tableMeta, rmStbMeta) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; @@ -1696,7 +1695,7 @@ TEST(tableMeta, rmStbMeta) { TEST(tableMeta, updateStbMeta) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; @@ -1785,7 +1784,7 @@ TEST(tableMeta, updateStbMeta) { TEST(getIndexInfo, notExists) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SArray *vgList = NULL; @@ -1809,13 +1808,13 @@ TEST(getIndexInfo, notExists) { SIndexInfo info; code = catalogGetIndexMeta(pCtg, mockPointer, "index1", &info); ASSERT_TRUE(code != 0); - + catalogDestroy(); } TEST(refreshGetMeta, normal2normal) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SArray *vgList = NULL; @@ -1894,7 +1893,7 @@ TEST(refreshGetMeta, normal2normal) { TEST(refreshGetMeta, normal2notexist) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SArray *vgList = NULL; @@ -1964,7 +1963,7 @@ TEST(refreshGetMeta, normal2notexist) { TEST(refreshGetMeta, normal2child) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SArray *vgList = NULL; @@ -2045,10 +2044,9 @@ TEST(refreshGetMeta, normal2child) { ctgTestCurrentSTableName = NULL; } - TEST(refreshGetMeta, stable2child) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SArray *vgList = NULL; @@ -2134,7 +2132,7 @@ TEST(refreshGetMeta, stable2child) { TEST(refreshGetMeta, stable2stable) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SArray *vgList = NULL; @@ -2220,7 +2218,7 @@ TEST(refreshGetMeta, stable2stable) { TEST(refreshGetMeta, child2stable) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SArray *vgList = NULL; @@ -2306,7 +2304,7 @@ TEST(refreshGetMeta, child2stable) { TEST(tableDistVgroup, normalTable) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo *vgInfo = NULL; SArray *vgList = NULL; @@ -2343,7 +2341,7 @@ TEST(tableDistVgroup, normalTable) { TEST(tableDistVgroup, childTableCase) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo *vgInfo = NULL; SArray *vgList = NULL; @@ -2381,7 +2379,7 @@ TEST(tableDistVgroup, childTableCase) { TEST(tableDistVgroup, superTableCase) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo *vgInfo = NULL; SArray *vgList = NULL; @@ -2430,7 +2428,7 @@ TEST(tableDistVgroup, superTableCase) { TEST(dbVgroup, getSetDbVgroupCase) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SVgroupInfo *pvgInfo = NULL; @@ -2520,7 +2518,7 @@ TEST(dbVgroup, getSetDbVgroupCase) { TEST(multiThread, getSetRmSameDbVgroup) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SVgroupInfo *pvgInfo = NULL; @@ -2572,7 +2570,7 @@ TEST(multiThread, getSetRmSameDbVgroup) { TEST(multiThread, getSetRmDiffDbVgroup) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SVgroupInfo *pvgInfo = NULL; @@ -2624,7 +2622,7 @@ TEST(multiThread, getSetRmDiffDbVgroup) { TEST(multiThread, ctableMeta) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SVgroupInfo *pvgInfo = NULL; @@ -2675,14 +2673,14 @@ TEST(multiThread, ctableMeta) { TEST(rentTest, allRent) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; SVgroupInfo vgInfo = {0}; SVgroupInfo *pvgInfo = NULL; SDBVgInfo dbVgroup = {0}; SArray *vgList = NULL; ctgTestStop = false; - SDbVgVersion *dbs = NULL; + SDbCacheInfo *dbs = NULL; SSTableVersion *stable = NULL; uint32_t num = 0; @@ -2754,7 +2752,7 @@ TEST(rentTest, allRent) { TEST(apiTest, catalogRefreshDBVgInfo_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -2781,7 +2779,7 @@ TEST(apiTest, catalogRefreshDBVgInfo_test) { TEST(apiTest, catalogChkAuth_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -2800,15 +2798,19 @@ TEST(apiTest, catalogChkAuth_test) { code = catalogGetHandle(ctgTestClusterId, &pCtg); ASSERT_EQ(code, 0); - bool pass = false; + SUserAuthInfo authInfo = {0}; + SUserAuthRes authRes = {0}; + strcpy(authInfo.user, ctgTestUsername); + toName(1, ctgTestDbname, ctgTestSTablename, &authInfo.tbName); + authInfo.type = AUTH_TYPE_READ; bool exists = false; - code = catalogChkAuthFromCache(pCtg, ctgTestUsername, ctgTestDbname, AUTH_TYPE_READ, &pass, &exists); + code = catalogChkAuthFromCache(pCtg, &authInfo, &authRes, &exists); ASSERT_EQ(code, 0); ASSERT_EQ(exists, false); - - code = catalogChkAuth(pCtg, mockPointer, ctgTestUsername, ctgTestDbname, AUTH_TYPE_READ, &pass); + + code = catalogChkAuth(pCtg, mockPointer, &authInfo, &authRes); ASSERT_EQ(code, 0); - ASSERT_EQ(pass, true); + ASSERT_EQ(authRes.pass, true); while (true) { uint64_t n = 0; @@ -2820,9 +2822,9 @@ TEST(apiTest, catalogChkAuth_test) { } } - code = catalogChkAuthFromCache(pCtg, ctgTestUsername, ctgTestDbname, AUTH_TYPE_READ, &pass, &exists); + code = catalogChkAuthFromCache(pCtg, &authInfo, &authRes, &exists); ASSERT_EQ(code, 0); - ASSERT_EQ(pass, true); + ASSERT_EQ(authRes.pass, true); ASSERT_EQ(exists, true); catalogDestroy(); @@ -2830,7 +2832,7 @@ TEST(apiTest, catalogChkAuth_test) { TEST(apiTest, catalogRefreshGetTableCfg_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -2868,7 +2870,7 @@ TEST(apiTest, catalogRefreshGetTableCfg_test) { TEST(apiTest, catalogGetTableIndex_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -2904,7 +2906,7 @@ TEST(apiTest, catalogGetTableIndex_test) { TEST(apiTest, catalogGetDBCfg_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -2937,7 +2939,7 @@ TEST(apiTest, catalogGetDBCfg_test) { TEST(apiTest, catalogGetQnodeList_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -2962,17 +2964,16 @@ TEST(apiTest, catalogGetQnodeList_test) { ASSERT_EQ(taosArrayGetSize(qnodeList), ctgTestQnodeNum); for (int32_t i = 0; i < ctgTestQnodeNum; ++i) { - SQueryNodeLoad * pLoad = (SQueryNodeLoad *)taosArrayGet(qnodeList, i); + SQueryNodeLoad *pLoad = (SQueryNodeLoad *)taosArrayGet(qnodeList, i); ASSERT_EQ(pLoad->addr.nodeId, i); } catalogDestroy(); } - TEST(apiTest, catalogGetUdfInfo_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -2999,10 +3000,9 @@ TEST(apiTest, catalogGetUdfInfo_test) { catalogDestroy(); } - TEST(apiTest, catalogGetServerVersion_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -3021,7 +3021,7 @@ TEST(apiTest, catalogGetServerVersion_test) { code = catalogGetHandle(ctgTestClusterId, &pCtg); ASSERT_EQ(code, 0); - char* ver = NULL; + char *ver = NULL; code = catalogGetServerVersion(pCtg, mockPointer, &ver); ASSERT_EQ(code, 0); ASSERT_TRUE(0 == strcmp(ver, "1.0")); @@ -3031,7 +3031,7 @@ TEST(apiTest, catalogGetServerVersion_test) { TEST(apiTest, catalogUpdateTableIndex_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -3061,10 +3061,9 @@ TEST(apiTest, catalogUpdateTableIndex_test) { catalogDestroy(); } - TEST(apiTest, catalogGetDnodeList_test) { struct SCatalog *pCtg = NULL; - SRequestConnInfo connInfo = {0}; + SRequestConnInfo connInfo = {0}; SRequestConnInfo *mockPointer = (SRequestConnInfo *)&connInfo; ctgTestInitLogFile(); @@ -3083,7 +3082,7 @@ TEST(apiTest, catalogGetDnodeList_test) { code = catalogGetHandle(ctgTestClusterId, &pCtg); ASSERT_EQ(code, 0); - SArray* pList = NULL; + SArray *pList = NULL; code = catalogGetDnodeList(pCtg, mockPointer, &pList); ASSERT_EQ(code, 0); ASSERT_EQ(taosArrayGetSize(pList), 1); @@ -3095,23 +3094,23 @@ TEST(apiTest, catalogGetDnodeList_test) { #ifdef INTEGRATION_TEST TEST(intTest, autoCreateTableTest) { - struct SCatalog *pCtg = NULL; + struct SCatalog *pCtg = NULL; - TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); - ASSERT_TRUE(NULL != taos); + TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); + ASSERT_TRUE(NULL != taos); ctgdEnableDebug("api", true); ctgdEnableDebug("meta", true); ctgdEnableDebug("cache", true); ctgdEnableDebug("lock", true); - + ctgTestExecQuery(taos, "drop database if exists db1", false, NULL); ctgTestExecQuery(taos, "create database db1", false, NULL); ctgTestExecQuery(taos, "create stable db1.st1 (ts timestamp, f1 int) tags(tg1 int)", false, NULL); ctgTestExecQuery(taos, "insert into db1.tb1 using db1.st1 tags(1) values(now, 1)", false, NULL); ctgdGetOneHandle(&pCtg); - + while (true) { uint32_t n = ctgdGetClusterCacheNum(pCtg, CTG_DBG_META_NUM); if (2 != n) { @@ -3137,15 +3136,14 @@ TEST(intTest, autoCreateTableTest) { ctgTestExecQuery(taos, "alter table db1.st1 add column f2 double", false, NULL); ctgdEnableDebug("stopUpdate", false); - + ctgTestExecQuery(taos, "insert into db1.tb1 (ts, f1) values(now, 4)", false, NULL); - + taos_close(taos); } #endif - int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/source/libs/command/inc/commandInt.h b/source/libs/command/inc/commandInt.h index 6acf19218d893a9962853e1fe7b0c73c8dddf7bc..2a435b43e8bd645c18a3122d6ab042ac57ec9077 100644 --- a/source/libs/command/inc/commandInt.h +++ b/source/libs/command/inc/commandInt.h @@ -64,6 +64,9 @@ extern "C" { #define EXPLAIN_IGNORE_GROUPID_FORMAT "Ignore Group Id: %s" #define EXPLAIN_PARTITION_KETS_FORMAT "Partition Key: " #define EXPLAIN_INTERP_FORMAT "Interp" +#define EXPLAIN_EVENT_FORMAT "Event" +#define EXPLAIN_EVENT_START_FORMAT "Start Cond: " +#define EXPLAIN_EVENT_END_FORMAT "End Cond: " #define EXPLAIN_PLANNING_TIME_FORMAT "Planning Time: %.3f ms" #define EXPLAIN_EXEC_TIME_FORMAT "Execution Time: %.3f ms" @@ -98,6 +101,8 @@ extern "C" { #define COMMAND_SCHEDULE_POLICY "schedulePolicy" #define COMMAND_ENABLE_RESCHEDULE "enableReSchedule" #define COMMAND_CATALOG_DEBUG "catalogDebug" +#define COMMAND_ENABLE_MEM_DEBUG "enableMemDebug" +#define COMMAND_DISABLE_MEM_DEBUG "disableMemDebug" typedef struct SExplainGroup { int32_t nodeNum; diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c index 3f10ed73883c25fb7f4a2e134f22bc823a54c746..6efdd8d8ebddbaea1032de9c583ff37147587b1a 100644 --- a/source/libs/command/src/command.c +++ b/source/libs/command/src/command.c @@ -21,6 +21,7 @@ #include "tdatablock.h" #include "tglobal.h" #include "tgrant.h" +#include "taosdef.h" extern SConfig* tsCfg; @@ -40,7 +41,6 @@ static int32_t buildRetrieveTableRsp(SSDataBlock* pBlock, int32_t numOfCols, SRe (*pRsp)->numOfCols = htonl(numOfCols); int32_t len = blockEncode(pBlock, (*pRsp)->data, numOfCols); - ASSERT(len == rspSize - sizeof(SRetrieveTableRsp)); return TSDB_CODE_SUCCESS; } @@ -104,13 +104,13 @@ static void setDescResultIntoDataBlock(bool sysInfoUser, SSDataBlock* pBlock, in continue; } STR_TO_VARSTR(buf, pMeta->schema[i].name); - colDataAppend(pCol1, pBlock->info.rows, buf, false); + colDataSetVal(pCol1, pBlock->info.rows, buf, false); STR_TO_VARSTR(buf, tDataTypes[pMeta->schema[i].type].name); - colDataAppend(pCol2, pBlock->info.rows, buf, false); + colDataSetVal(pCol2, pBlock->info.rows, buf, false); int32_t bytes = getSchemaBytes(pMeta->schema + i); - colDataAppend(pCol3, pBlock->info.rows, (const char*)&bytes, false); + colDataSetVal(pCol3, pBlock->info.rows, (const char*)&bytes, false); STR_TO_VARSTR(buf, i >= pMeta->tableInfo.numOfColumns ? "TAG" : ""); - colDataAppend(pCol4, pBlock->info.rows, buf, false); + colDataSetVal(pCol4, pBlock->info.rows, buf, false); ++(pBlock->info.rows); } } @@ -154,6 +154,23 @@ static int32_t buildCreateDBResultDataBlock(SSDataBlock** pOutput) { return code; } +static int32_t buildAliveResultDataBlock(SSDataBlock** pOutput) { + SSDataBlock* pBlock = createDataBlock(); + if (NULL == pBlock) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_INT, sizeof(int32_t), 1); + int32_t code = blockDataAppendColInfo(pBlock, &infoData); + + if (TSDB_CODE_SUCCESS == code) { + *pOutput = pBlock; + } else { + blockDataDestroy(pBlock); + } + return code; +} + int64_t getValOfDiffPrecision(int8_t unit, int64_t val) { int64_t v = 0; switch (unit) { @@ -231,14 +248,14 @@ static const char* cacheModelStr(int8_t cacheModel) { return TSDB_CACHE_MODEL_NONE_STR; } -static void setCreateDBResultIntoDataBlock(SSDataBlock* pBlock, char* dbFName, SDbCfgInfo* pCfg) { +static void setCreateDBResultIntoDataBlock(SSDataBlock* pBlock, char* dbName, char* dbFName, SDbCfgInfo* pCfg) { blockDataEnsureCapacity(pBlock, 1); pBlock->info.rows = 1; SColumnInfoData* pCol1 = taosArrayGet(pBlock->pDataBlock, 0); char buf1[SHOW_CREATE_DB_RESULT_FIELD1_LEN] = {0}; - STR_TO_VARSTR(buf1, dbFName); - colDataAppend(pCol1, 0, buf1, false); + STR_TO_VARSTR(buf1, dbName); + colDataSetVal(pCol1, 0, buf1, false); SColumnInfoData* pCol2 = taosArrayGet(pBlock->pDataBlock, 1); char buf2[SHOW_CREATE_DB_RESULT_FIELD2_LEN] = {0}; @@ -260,16 +277,25 @@ static void setCreateDBResultIntoDataBlock(SSDataBlock* pBlock, char* dbFName, S } char* retentions = buildRetension(pCfg->pRetensions); + int32_t dbFNameLen = strlen(dbFName); + int32_t hashPrefix = 0; + if (pCfg->hashPrefix > 0) { + hashPrefix = pCfg->hashPrefix - dbFNameLen - 1; + } else if (pCfg->hashPrefix < 0) { + hashPrefix = pCfg->hashPrefix + dbFNameLen + 1; + } len += sprintf( buf2 + VARSTR_HEADER_SIZE, "CREATE DATABASE `%s` BUFFER %d CACHESIZE %d CACHEMODEL '%s' COMP %d DURATION %dm " "WAL_FSYNC_PERIOD %d MAXROWS %d MINROWS %d STT_TRIGGER %d KEEP %dm,%dm,%dm PAGES %d PAGESIZE %d PRECISION '%s' REPLICA %d " - "WAL_LEVEL %d VGROUPS %d SINGLE_STABLE %d", - dbFName, pCfg->buffer, pCfg->cacheSize, cacheModelStr(pCfg->cacheLast), pCfg->compression, pCfg->daysPerFile, + "WAL_LEVEL %d VGROUPS %d SINGLE_STABLE %d TABLE_PREFIX %d TABLE_SUFFIX %d TSDB_PAGESIZE %d " + "WAL_RETENTION_PERIOD %d WAL_RETENTION_SIZE %" PRId64 " WAL_ROLL_PERIOD %d WAL_SEGMENT_SIZE %" PRId64, + dbName, pCfg->buffer, pCfg->cacheSize, cacheModelStr(pCfg->cacheLast), pCfg->compression, pCfg->daysPerFile, pCfg->walFsyncPeriod, pCfg->maxRows, pCfg->minRows, pCfg->sstTrigger, pCfg->daysToKeep0, pCfg->daysToKeep1, pCfg->daysToKeep2, pCfg->pages, pCfg->pageSize, prec, pCfg->replications, pCfg->walLevel, pCfg->numOfVgroups, - 1 == pCfg->numOfStables); + 1 == pCfg->numOfStables, hashPrefix, pCfg->hashSuffix, pCfg->tsdbPageSize, pCfg->walRetentionPeriod, + pCfg->walRetentionSize, pCfg->walRollPeriod, pCfg->walSegmentSize); if (retentions) { len += sprintf(buf2 + VARSTR_HEADER_SIZE + len, " RETENTIONS %s", retentions); @@ -278,14 +304,116 @@ static void setCreateDBResultIntoDataBlock(SSDataBlock* pBlock, char* dbFName, S (varDataLen(buf2)) = len; - colDataAppend(pCol2, 0, buf2, false); + colDataSetVal(pCol2, 0, buf2, false); +} + +#define CHECK_LEADER(n) (row[n] && (fields[n].type == TSDB_DATA_TYPE_VARCHAR && strncasecmp(row[n], "leader", varDataLen((char *)row[n] - VARSTR_HEADER_SIZE)) == 0)) +// on this row, if have leader return true else return false +bool existLeaderRole(TAOS_ROW row, TAOS_FIELD* fields, int nFields) { + // vgroup_id | db_name | tables | v1_dnode | v1_status | v2_dnode | v2_status | v3_dnode | v3_status | v4_dnode | + // v4_status | cacheload | tsma | + if (nFields != 14) { + return false; + } + + // check have leader on cloumn v*_status on 4 6 8 10 + if (CHECK_LEADER(4) || CHECK_LEADER(6) || CHECK_LEADER(8) || CHECK_LEADER(10)) { + return true; + } + + return false; +} + +// get db alive status, return 1 is alive else return 0 +int32_t getAliveStatusFromApi(int64_t* pConnId, char* dbName, int32_t* pStatus) { + char sql[128 + TSDB_DB_NAME_LEN] = "select * from information_schema.ins_vgroups"; + int32_t code; + + // filter with db name + if (dbName && dbName[0] != 0) { + char str[64 + TSDB_DB_NAME_LEN] = ""; + // test db name exist + sprintf(str, "show create database %s ;", dbName); + TAOS_RES* dbRes = taos_query(pConnId, str); + code = taos_errno(dbRes); + if (code != TSDB_CODE_SUCCESS) { + taos_free_result(dbRes); + return code; + } + taos_free_result(dbRes); + + sprintf(str, " where db_name='%s' ;", dbName); + strcat(sql, str); + } + + TAOS_RES* res = taos_query(pConnId, sql); + code = taos_errno(res); + if (code != TSDB_CODE_SUCCESS) { + taos_free_result(res); + return code; + } + + TAOS_ROW row = NULL; + TAOS_FIELD* fields = taos_fetch_fields(res); + int32_t nFields = taos_num_fields(res); + int32_t nAvailble = 0; + int32_t nUnAvailble = 0; + + while ((row = taos_fetch_row(res)) != NULL) { + if (existLeaderRole(row, fields, nFields)) { + nAvailble++; + } else { + nUnAvailble++; + } + } + taos_free_result(res); + + int32_t status = 0; + if (nAvailble + nUnAvailble == 0 || nUnAvailble == 0) { + status = SHOW_STATUS_AVAILABLE; + } else if (nAvailble > 0 && nUnAvailble > 0) { + status = SHOW_STATUS_HALF_AVAILABLE; + } else { + status = SHOW_STATUS_NOT_AVAILABLE; + } + + if (pStatus) { + *pStatus = status; + } + return TSDB_CODE_SUCCESS; +} + +static int32_t setAliveResultIntoDataBlock(int64_t* pConnId, SSDataBlock* pBlock, char* dbName) { + blockDataEnsureCapacity(pBlock, 1); + pBlock->info.rows = 1; + + SColumnInfoData* pCol1 = taosArrayGet(pBlock->pDataBlock, 0); + int32_t status = 0; + int32_t code = getAliveStatusFromApi(pConnId, dbName, &status); + if (code == TSDB_CODE_SUCCESS) { + colDataAppend(pCol1, 0, (const char*)&status, false); + } + return code; +} + +static int32_t execShowAliveStatus(int64_t* pConnId, SShowAliveStmt* pStmt, SRetrieveTableRsp** pRsp) { + SSDataBlock* pBlock = NULL; + int32_t code = buildAliveResultDataBlock(&pBlock); + if (TSDB_CODE_SUCCESS == code) { + code = setAliveResultIntoDataBlock(pConnId, pBlock, pStmt->dbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = buildRetrieveTableRsp(pBlock, SHOW_ALIVE_RESULT_COLS, pRsp); + } + blockDataDestroy(pBlock); + return code; } static int32_t execShowCreateDatabase(SShowCreateDatabaseStmt* pStmt, SRetrieveTableRsp** pRsp) { SSDataBlock* pBlock = NULL; int32_t code = buildCreateDBResultDataBlock(&pBlock); if (TSDB_CODE_SUCCESS == code) { - setCreateDBResultIntoDataBlock(pBlock, pStmt->dbName, pStmt->pCfg); + setCreateDBResultIntoDataBlock(pBlock, pStmt->dbName, pStmt->dbFName, pStmt->pCfg); } if (TSDB_CODE_SUCCESS == code) { code = buildRetrieveTableRsp(pBlock, SHOW_CREATE_DB_RESULT_COLS, pRsp); @@ -488,7 +616,7 @@ static int32_t setCreateTBResultIntoDataBlock(SSDataBlock* pBlock, SDbCfgInfo* p SColumnInfoData* pCol1 = taosArrayGet(pBlock->pDataBlock, 0); char buf1[SHOW_CREATE_TB_RESULT_FIELD1_LEN] = {0}; STR_TO_VARSTR(buf1, tbName); - colDataAppend(pCol1, 0, buf1, false); + colDataSetVal(pCol1, 0, buf1, false); SColumnInfoData* pCol2 = taosArrayGet(pBlock->pDataBlock, 1); char* buf2 = taosMemoryMalloc(SHOW_CREATE_TB_RESULT_FIELD2_LEN); @@ -526,7 +654,7 @@ static int32_t setCreateTBResultIntoDataBlock(SSDataBlock* pBlock, SDbCfgInfo* p varDataLen(buf2) = (len > 65535) ? 65535 : len; - colDataAppend(pCol2, 0, buf2, false); + colDataSetVal(pCol2, 0, buf2, false); taosMemoryFree(buf2); @@ -568,6 +696,21 @@ static int32_t execAlterCmd(char* cmd, char* value, bool* processed) { code = schedulerEnableReSchedule(atoi(value)); } else if (0 == strcasecmp(cmd, COMMAND_CATALOG_DEBUG)) { code = ctgdHandleDbgCommand(value); + } else if (0 == strcasecmp(cmd, COMMAND_ENABLE_MEM_DEBUG)) { + code = taosMemoryDbgInit(); + if (code) { + qError("failed to init memory dbg, error:%s", tstrerror(code)); + return code; + } + tsAsyncLog = false; + qInfo("memory dbg enabled"); + } else if (0 == strcasecmp(cmd, COMMAND_DISABLE_MEM_DEBUG)) { + code = taosMemoryDbgInitRestore(); + if (code) { + qError("failed to restore from memory dbg, error:%s", tstrerror(code)); + return code; + } + qInfo("memory dbg disabled"); } else { goto _return; } @@ -649,14 +792,14 @@ int32_t setLocalVariablesResultIntoDataBlock(SSDataBlock* pBlock) { char name[TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE] = {0}; STR_WITH_MAXSIZE_TO_VARSTR(name, pItem->name, TSDB_CONFIG_OPTION_LEN + VARSTR_HEADER_SIZE); SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, c++); - colDataAppend(pColInfo, i, name, false); + colDataSetVal(pColInfo, i, name, false); char value[TSDB_CONFIG_VALUE_LEN + VARSTR_HEADER_SIZE] = {0}; int32_t valueLen = 0; cfgDumpItemValue(pItem, &value[VARSTR_HEADER_SIZE], TSDB_CONFIG_VALUE_LEN, &valueLen); varDataSetLen(value, valueLen); pColInfo = taosArrayGet(pBlock->pDataBlock, c++); - colDataAppend(pColInfo, i, value, false); + colDataSetVal(pColInfo, i, value, false); numOfRows++; } @@ -712,9 +855,9 @@ int32_t buildSelectResultDataBlock(SNodeList* pProjects, SSDataBlock* pBlock) { return TSDB_CODE_PAR_INVALID_SELECTED_EXPR; } else { if (((SValueNode*)pProj)->isNull) { - colDataAppend(taosArrayGet(pBlock->pDataBlock, index++), 0, NULL, true); + colDataSetVal(taosArrayGet(pBlock->pDataBlock, index++), 0, NULL, true); } else { - colDataAppend(taosArrayGet(pBlock->pDataBlock, index++), 0, nodesGetValueFromNode((SValueNode*)pProj), false); + colDataSetVal(taosArrayGet(pBlock->pDataBlock, index++), 0, nodesGetValueFromNode((SValueNode*)pProj), false); } } } @@ -736,7 +879,7 @@ static int32_t execSelectWithoutFrom(SSelectStmt* pSelect, SRetrieveTableRsp** p return code; } -int32_t qExecCommand(bool sysInfoUser, SNode* pStmt, SRetrieveTableRsp** pRsp) { +int32_t qExecCommand(int64_t* pConnId, bool sysInfoUser, SNode* pStmt, SRetrieveTableRsp** pRsp) { switch (nodeType(pStmt)) { case QUERY_NODE_DESCRIBE_STMT: return execDescribe(sysInfoUser, pStmt, pRsp); @@ -754,6 +897,9 @@ int32_t qExecCommand(bool sysInfoUser, SNode* pStmt, SRetrieveTableRsp** pRsp) { return execShowLocalVariables(pRsp); case QUERY_NODE_SELECT_STMT: return execSelectWithoutFrom((SSelectStmt*)pStmt, pRsp); + case QUERY_NODE_SHOW_DB_ALIVE_STMT: + case QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT: + return execShowAliveStatus(pConnId, (SShowAliveStmt*)pStmt, pRsp); default: break; } diff --git a/source/libs/command/src/explain.c b/source/libs/command/src/explain.c index 253718048dcebb71b64ca4d4b48b3004c6d9ea3a..4302302d7ab6226f2eda506500c9ba0c3bb706fd 100644 --- a/source/libs/command/src/explain.c +++ b/source/libs/command/src/explain.c @@ -114,129 +114,7 @@ _return: int32_t qExplainGenerateResChildren(SPhysiNode *pNode, SExplainGroup *group, SNodeList **pChildren) { int32_t tlen = 0; - SNodeList *pPhysiChildren = NULL; - - switch (pNode->type) { - case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: { - STagScanPhysiNode *pTagScanNode = (STagScanPhysiNode *)pNode; - pPhysiChildren = pTagScanNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN: - case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: { - STableScanPhysiNode *pTblScanNode = (STableScanPhysiNode *)pNode; - pPhysiChildren = pTblScanNode->scan.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN: { - SSystemTableScanPhysiNode *pSTblScanNode = (SSystemTableScanPhysiNode *)pNode; - pPhysiChildren = pSTblScanNode->scan.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_PROJECT: { - SProjectPhysiNode *pPrjNode = (SProjectPhysiNode *)pNode; - pPhysiChildren = pPrjNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN: { - SSortMergeJoinPhysiNode *pJoinNode = (SSortMergeJoinPhysiNode *)pNode; - pPhysiChildren = pJoinNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_HASH_AGG: { - SAggPhysiNode *pAggNode = (SAggPhysiNode *)pNode; - pPhysiChildren = pAggNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: { - SExchangePhysiNode *pExchNode = (SExchangePhysiNode *)pNode; - pPhysiChildren = pExchNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_SORT: { - SSortPhysiNode *pSortNode = (SSortPhysiNode *)pNode; - pPhysiChildren = pSortNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL: { - SIntervalPhysiNode *pIntNode = (SIntervalPhysiNode *)pNode; - pPhysiChildren = pIntNode->window.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION: { - SSessionWinodwPhysiNode *pSessNode = (SSessionWinodwPhysiNode *)pNode; - pPhysiChildren = pSessNode->window.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE: { - SStateWinodwPhysiNode *pStateNode = (SStateWinodwPhysiNode *)pNode; - pPhysiChildren = pStateNode->window.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_PARTITION: { - SPartitionPhysiNode *partitionPhysiNode = (SPartitionPhysiNode *)pNode; - pPhysiChildren = partitionPhysiNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_MERGE: { - SMergePhysiNode *mergePhysiNode = (SMergePhysiNode *)pNode; - pPhysiChildren = mergePhysiNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_INDEF_ROWS_FUNC: { - SIndefRowsFuncPhysiNode *indefPhysiNode = (SIndefRowsFuncPhysiNode *)pNode; - pPhysiChildren = indefPhysiNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL: { - SMergeAlignedIntervalPhysiNode *intPhysiNode = (SMergeAlignedIntervalPhysiNode *)pNode; - pPhysiChildren = intPhysiNode->window.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_FILL: { - SFillPhysiNode *fillPhysiNode = (SFillPhysiNode *)pNode; - pPhysiChildren = fillPhysiNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN: { - STableMergeScanPhysiNode *mergePhysiNode = (STableMergeScanPhysiNode *)pNode; - pPhysiChildren = mergePhysiNode->scan.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN: { - SBlockDistScanPhysiNode *distPhysiNode = (SBlockDistScanPhysiNode *)pNode; - pPhysiChildren = distPhysiNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN: { - SLastRowScanPhysiNode *lastRowPhysiNode = (SLastRowScanPhysiNode *)pNode; - pPhysiChildren = lastRowPhysiNode->scan.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN: { - STableCountScanPhysiNode *tableCountPhysiNode = (STableCountScanPhysiNode *)pNode; - pPhysiChildren = tableCountPhysiNode->scan.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: { - SGroupSortPhysiNode *groupSortPhysiNode = (SGroupSortPhysiNode *)pNode; - pPhysiChildren = groupSortPhysiNode->node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: { - SMergeIntervalPhysiNode *mergeIntPhysiNode = (SMergeIntervalPhysiNode *)pNode; - pPhysiChildren = mergeIntPhysiNode->window.node.pChildren; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC: { - SInterpFuncPhysiNode *interpPhysiNode = (SInterpFuncPhysiNode *)pNode; - pPhysiChildren = interpPhysiNode->node.pChildren; - break; - } - default: - qError("not supported physical node type %d", pNode->type); - QRY_ERR_RET(TSDB_CODE_APP_ERROR); - } + SNodeList *pPhysiChildren = pNode->pChildren; if (pPhysiChildren) { *pChildren = nodesMakeList(); @@ -1583,6 +1461,36 @@ int32_t qExplainResNodeToRowsImpl(SExplainResNode *pResNode, SExplainCtx *ctx, i } break; } + case QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT: { + SEventWinodwPhysiNode *pEventNode = (SEventWinodwPhysiNode *)pNode; + EXPLAIN_ROW_NEW(level, EXPLAIN_EVENT_FORMAT); + EXPLAIN_ROW_APPEND(EXPLAIN_LEFT_PARENTHESIS_FORMAT); + if (pResNode->pExecInfo) { + QRY_ERR_RET(qExplainBufAppendExecInfo(pResNode->pExecInfo, tbuf, &tlen)); + EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT); + } + EXPLAIN_ROW_APPEND(EXPLAIN_FUNCTIONS_FORMAT, pEventNode->window.pFuncs->length); + EXPLAIN_ROW_APPEND(EXPLAIN_BLANK_FORMAT); + EXPLAIN_ROW_APPEND(EXPLAIN_WIDTH_FORMAT, pEventNode->window.node.pOutputDataBlockDesc->totalRowSize); + EXPLAIN_ROW_APPEND(EXPLAIN_RIGHT_PARENTHESIS_FORMAT); + EXPLAIN_ROW_END(); + QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level)); + + if (verbose) { + EXPLAIN_ROW_NEW(level + 1, EXPLAIN_EVENT_START_FORMAT); + QRY_ERR_RET(nodesNodeToSQL(pEventNode->pStartCond, tbuf + VARSTR_HEADER_SIZE, + TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen)); + EXPLAIN_ROW_END(); + QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1)); + + EXPLAIN_ROW_NEW(level + 1, EXPLAIN_EVENT_END_FORMAT); + QRY_ERR_RET(nodesNodeToSQL(pEventNode->pEndCond, tbuf + VARSTR_HEADER_SIZE, + TSDB_EXPLAIN_RESULT_ROW_SIZE, &tlen)); + EXPLAIN_ROW_END(); + QRY_ERR_RET(qExplainResAppendRow(ctx, tbuf, tlen, level + 1)); + } + break; + } default: qError("not supported physical node type %d", pNode->type); return TSDB_CODE_APP_ERROR; @@ -1648,7 +1556,7 @@ int32_t qExplainGetRspFromCtx(void *ctx, SRetrieveTableRsp **pRsp) { for (int32_t i = 0; i < rowNum; ++i) { SQueryExplainRowInfo *row = taosArrayGet(pCtx->rows, i); - colDataAppend(pInfoData, i, row->buf, false); + colDataSetVal(pInfoData, i, row->buf, false); } pBlock->info.rows = rowNum; @@ -1666,7 +1574,6 @@ int32_t qExplainGetRspFromCtx(void *ctx, SRetrieveTableRsp **pRsp) { rsp->numOfRows = htobe64((int64_t)rowNum); int32_t len = blockEncode(pBlock, rsp->data, taosArrayGetSize(pBlock->pDataBlock)); - ASSERT(len == rspSize - sizeof(SRetrieveTableRsp)); rsp->compLen = htonl(len); diff --git a/source/libs/executor/inc/dataSinkInt.h b/source/libs/executor/inc/dataSinkInt.h index 220e9c0b6ced01edce3a36a4297f2c76151a4092..57a771b275b219b776dbee34193e2ba644e73a1f 100644 --- a/source/libs/executor/inc/dataSinkInt.h +++ b/source/libs/executor/inc/dataSinkInt.h @@ -29,7 +29,6 @@ struct SDataSinkHandle; typedef struct SDataSinkManager { SDataSinkMgtCfg cfg; - TdThreadMutex mutex; } SDataSinkManager; typedef int32_t (*FPutDataBlock)(struct SDataSinkHandle* pHandle, const SInputData* pInput, bool* pContinue); diff --git a/source/libs/executor/inc/executil.h b/source/libs/executor/inc/executil.h index 20f43deaa3bd46a9f6d71c9ef35a655e386f3eb3..5b248f9a90d8000fe7f3bf7f3b15cf0d46ca83da 100644 --- a/source/libs/executor/inc/executil.h +++ b/source/libs/executor/inc/executil.h @@ -39,8 +39,6 @@ #define GET_RES_WINDOW_KEY_LEN(_l) ((_l) + sizeof(uint64_t)) -#define GET_TASKID(_t) (((SExecTaskInfo*)(_t))->id.str) - typedef struct SGroupResInfo { int32_t index; SArray* pRows; // SArray @@ -89,7 +87,25 @@ typedef struct SColMatchInfo { } SColMatchInfo; typedef struct SExecTaskInfo SExecTaskInfo; -typedef struct STableListInfo STableListInfo; + + +typedef struct STableListIdInfo { + uint64_t suid; + uint64_t uid; + int32_t tableType; +} STableListIdInfo; + +// If the numOfOutputGroups is 1, the data blocks that belongs to different groups will be provided randomly +// The numOfOutputGroups is specified by physical plan. and will not be affect by numOfGroups +typedef struct STableListInfo { + bool oneTableForEachGroup; + int32_t numOfOuputGroups; // the data block will be generated one by one + int32_t* groupOffset; // keep the offset value for each group in the tableList + SArray* pTableList; + SHashObj* map; // speedup acquire the tableQueryInfo by table uid + STableListIdInfo idInfo; // this maybe the super table or ordinary table +} STableListInfo; + struct SqlFunctionCtx; int32_t createScanTableListInfo(SScanPhysiNode* pScanNode, SNodeList* pGroupTags, bool groupSort, SReadHandle* pHandle, @@ -107,6 +123,8 @@ int32_t tableListGetGroupList(const STableListInfo* pTableList, int32_t uint64_t tableListGetSize(const STableListInfo* pTableList); uint64_t tableListGetSuid(const STableListInfo* pTableList); STableKeyInfo* tableListGetInfo(const STableListInfo* pTableList, int32_t index); +int32_t tableListFind(const STableListInfo* pTableList, uint64_t uid, int32_t startIndex); +void tableListGetSourceTableInfo(const STableListInfo* pTableList, uint64_t* psuid, uint64_t* uid, int32_t* type); size_t getResultRowSize(struct SqlFunctionCtx* pCtx, int32_t numOfOutput); void initResultRowInfo(SResultRowInfo* pResultRowInfo); diff --git a/source/libs/executor/inc/executorInt.h b/source/libs/executor/inc/executorInt.h index d22a7460bb17f53e77c56ec33c177ab466919b47..5db79bba8bf35cc8f1e1a24ccf91f9e896e6c974 100644 --- a/source/libs/executor/inc/executorInt.h +++ b/source/libs/executor/inc/executorInt.h @@ -12,14 +12,75 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ - -#ifndef _TD_EXECUTOR_INT_H -#define _TD_EXECUTOR_INT_H +#ifndef TDENGINE_EXECUTORINT_H +#define TDENGINE_EXECUTORINT_H #ifdef __cplusplus extern "C" { #endif +#include "os.h" +#include "tcommon.h" +#include "tlosertree.h" +#include "tsort.h" +#include "ttszip.h" +#include "tvariant.h" + +#include "dataSinkMgt.h" +#include "executil.h" +#include "executor.h" +#include "planner.h" +#include "scalar.h" +#include "taosdef.h" +#include "tarray.h" +#include "tfill.h" +#include "thash.h" +#include "tlockfree.h" +#include "tmsg.h" +#include "tpagedbuf.h" +#include "tstream.h" +#include "tstreamUpdate.h" + +#include "vnode.h" + +typedef int32_t (*__block_search_fn_t)(char* data, int32_t num, int64_t key, int32_t order); + +#define IS_VALID_SESSION_WIN(winInfo) ((winInfo).sessionWin.win.skey > 0) +#define SET_SESSION_WIN_INVALID(winInfo) ((winInfo).sessionWin.win.skey = INT64_MIN) +#define IS_INVALID_SESSION_WIN_KEY(winKey) ((winKey).win.skey <= 0) +#define SET_SESSION_WIN_KEY_INVALID(pWinKey) ((pWinKey)->win.skey = INT64_MIN) + +/** + * If the number of generated results is greater than this value, + * query query will be halt and return results to client immediate. + */ +typedef struct SResultInfo { // TODO refactor + int64_t totalRows; // total generated result size in rows + int64_t totalBytes; // total results in bytes. + int32_t capacity; // capacity of current result output buffer + int32_t threshold; // result size threshold in rows. +} SResultInfo; + +typedef struct STableQueryInfo { + TSKEY lastKey; // last check ts, todo remove it later + SResultRowPosition pos; // current active time window +} STableQueryInfo; + +typedef struct SLimit { + int64_t limit; + int64_t offset; +} SLimit; + +typedef struct STableScanAnalyzeInfo SFileBlockLoadRecorder; + +enum { + STREAM_RECOVER_STEP__NONE = 0, + STREAM_RECOVER_STEP__PREPARE1, + STREAM_RECOVER_STEP__PREPARE2, + STREAM_RECOVER_STEP__SCAN1, + STREAM_RECOVER_STEP__SCAN2, +}; + extern int32_t exchangeObjRefPool; typedef struct { @@ -29,9 +90,585 @@ typedef struct { int32_t bytes; } SGroupKeys, SStateKeys; +typedef struct { + char* tablename; + char* dbname; + int32_t tversion; + SSchemaWrapper* sw; + SSchemaWrapper* qsw; +} SSchemaInfo; + +typedef struct SExchangeOpStopInfo { + int32_t operatorType; + int64_t refId; +} SExchangeOpStopInfo; + +typedef struct SExprSupp { + SExprInfo* pExprInfo; + int32_t numOfExprs; // the number of scalar expression in group operator + SqlFunctionCtx* pCtx; + int32_t* rowEntryInfoOffset; // offset value for each row result cell info + SFilterInfo* pFilterInfo; +} SExprSupp; + +typedef enum { + EX_SOURCE_DATA_NOT_READY = 0x1, + EX_SOURCE_DATA_READY = 0x2, + EX_SOURCE_DATA_EXHAUSTED = 0x3, +} EX_SOURCE_STATUS; + +#define COL_MATCH_FROM_COL_ID 0x1 +#define COL_MATCH_FROM_SLOT_ID 0x2 + +typedef struct SLoadRemoteDataInfo { + uint64_t totalSize; // total load bytes from remote + uint64_t totalRows; // total number of rows + uint64_t totalElapsed; // total elapsed time +} SLoadRemoteDataInfo; + +typedef struct SLimitInfo { + SLimit limit; + SLimit slimit; + uint64_t currentGroupId; + int64_t remainGroupOffset; + int64_t numOfOutputGroups; + int64_t remainOffset; + int64_t numOfOutputRows; +} SLimitInfo; + +typedef struct SExchangeInfo { + SArray* pSources; + SArray* pSourceDataInfo; + tsem_t ready; + void* pTransporter; + + // SArray, result block list, used to keep the multi-block that + // passed by downstream operator + SArray* pResultBlockList; + SArray* pRecycledBlocks; // build a pool for small data block to avoid to repeatly create and then destroy. + SSDataBlock* pDummyBlock; // dummy block, not keep data + bool seqLoadData; // sequential load data or not, false by default + int32_t current; + SLoadRemoteDataInfo loadInfo; + uint64_t self; + SLimitInfo limitInfo; + int64_t openedTs; // start exec time stamp, todo: move to SLoadRemoteDataInfo +} SExchangeInfo; + +typedef struct SScanInfo { + int32_t numOfAsc; + int32_t numOfDesc; +} SScanInfo; + +typedef struct SSampleExecInfo { + double sampleRatio; // data block sample ratio, 1 by default + uint32_t seed; // random seed value +} SSampleExecInfo; + +enum { + TABLE_SCAN__TABLE_ORDER = 1, + TABLE_SCAN__BLOCK_ORDER = 2, +}; + +typedef struct SAggSupporter { + SSHashObj* pResultRowHashTable; // quick locate the window object for each result + char* keyBuf; // window key buffer + SDiskbasedBuf* pResultBuf; // query result buffer based on blocked-wised disk file + int32_t resultRowSize; // the result buffer size for each result row, with the meta data size for each row + int32_t currentPageId; // current write page id +} SAggSupporter; + +typedef struct { + // if the upstream is an interval operator, the interval info is also kept here to get the time window to check if + // current data block needs to be loaded. + SInterval interval; + SAggSupporter* pAggSup; + SExprSupp* pExprSup; // expr supporter of aggregate operator +} SAggOptrPushDownInfo; + +typedef struct STableMetaCacheInfo { + SLRUCache* pTableMetaEntryCache; // 100 by default + uint64_t metaFetch; + uint64_t cacheHit; +} STableMetaCacheInfo; + +typedef struct STableScanBase { + STsdbReader* dataReader; + SFileBlockLoadRecorder readRecorder; + SQueryTableDataCond cond; + SAggOptrPushDownInfo pdInfo; + SColMatchInfo matchInfo; + SReadHandle readHandle; + SExprSupp pseudoSup; + STableMetaCacheInfo metaCache; + int32_t scanFlag; // table scan flag to denote if it is a repeat/reverse/main scan + int32_t dataBlockLoadFlag; + SLimitInfo limitInfo; + // there are more than one table list exists in one task, if only one vnode exists. + STableListInfo* pTableListInfo; +} STableScanBase; + +typedef struct STableScanInfo { + STableScanBase base; + SScanInfo scanInfo; + int32_t scanTimes; + SSDataBlock* pResBlock; + SHashObj* pIgnoreTables; + SSampleExecInfo sample; // sample execution info + int32_t currentGroupId; + int32_t currentTable; + int8_t scanMode; + int8_t assignBlockUid; + bool hasGroupByTag; + bool countOnly; +} STableScanInfo; + +typedef struct STableMergeScanInfo { + int32_t tableStartIndex; + int32_t tableEndIndex; + bool hasGroupId; + uint64_t groupId; + SArray* queryConds; // array of queryTableDataCond + STableScanBase base; + int32_t bufPageSize; + uint32_t sortBufSize; // max buffer size for in-memory sort + SArray* pSortInfo; + SSortHandle* pSortHandle; + SSDataBlock* pSortInputBlock; + int64_t startTs; // sort start time + SArray* sortSourceParams; + SLimitInfo limitInfo; + int64_t numOfRows; + SScanInfo scanInfo; + int32_t scanTimes; + SSDataBlock* pResBlock; + SSampleExecInfo sample; // sample execution info + SSortExecInfo sortExecInfo; +} STableMergeScanInfo; + +typedef struct STagScanInfo { + SColumnInfo* pCols; + SSDataBlock* pRes; + SColMatchInfo matchInfo; + int32_t curPos; + SReadHandle readHandle; + STableListInfo* pTableListInfo; +} STagScanInfo; + +typedef enum EStreamScanMode { + STREAM_SCAN_FROM_READERHANDLE = 1, + STREAM_SCAN_FROM_RES, + STREAM_SCAN_FROM_UPDATERES, + STREAM_SCAN_FROM_DELETE_DATA, + STREAM_SCAN_FROM_DATAREADER_RETRIEVE, + STREAM_SCAN_FROM_DATAREADER_RANGE, +} EStreamScanMode; + +enum { + PROJECT_RETRIEVE_CONTINUE = 0x1, + PROJECT_RETRIEVE_DONE = 0x2, +}; + +typedef struct SStreamAggSupporter { + int32_t resultRowSize; // the result buffer size for each result row, with the meta data size for each row + SSDataBlock* pScanBlock; + SStreamState* pState; + int64_t gap; // stream session window gap + SqlFunctionCtx* pDummyCtx; // for combine + SSHashObj* pResultRows; + int32_t stateKeySize; + int16_t stateKeyType; + SDiskbasedBuf* pResultBuf; +} SStreamAggSupporter; + +typedef struct SWindowSupporter { + SStreamAggSupporter* pStreamAggSup; + int64_t gap; + uint16_t parentType; + SAggSupporter* pIntervalAggSup; +} SWindowSupporter; + +typedef struct SPartitionBySupporter { + SArray* pGroupCols; // group by columns, SArray + SArray* pGroupColVals; // current group column values, SArray + char* keyBuf; // group by keys for hash + bool needCalc; // partition by column +} SPartitionBySupporter; + +typedef struct SPartitionDataInfo { + uint64_t groupId; + char* tbname; + SArray* tags; + SArray* rowIds; +} SPartitionDataInfo; + +typedef struct STimeWindowAggSupp { + int8_t calTrigger; + int8_t calTriggerSaved; + int64_t deleteMark; + int64_t deleteMarkSaved; + int64_t waterMark; + TSKEY maxTs; + TSKEY minTs; + SColumnInfoData timeWindowData; // query time window info for scalar function execution. +} STimeWindowAggSupp; + +typedef struct SStreamScanInfo { + SExprInfo* pPseudoExpr; + int32_t numOfPseudoExpr; + SExprSupp tbnameCalSup; + SExprSupp tagCalSup; + int32_t primaryTsIndex; // primary time stamp slot id + SReadHandle readHandle; + SInterval interval; // if the upstream is an interval operator, the interval info is also kept here. + SColMatchInfo matchInfo; + + SArray* pBlockLists; // multiple SSDatablock. + SSDataBlock* pRes; // result SSDataBlock + SSDataBlock* pUpdateRes; // update SSDataBlock + int32_t updateResIndex; + int32_t blockType; // current block type + int32_t validBlockIndex; // Is current data has returned? + uint64_t numOfExec; // execution times + STqReader* tqReader; + + uint64_t groupId; + SUpdateInfo* pUpdateInfo; + + EStreamScanMode scanMode; + struct SOperatorInfo* pStreamScanOp; + struct SOperatorInfo* pTableScanOp; + SArray* childIds; + SWindowSupporter windowSup; + SPartitionBySupporter partitionSup; + SExprSupp* pPartScalarSup; + bool assignBlockUid; // assign block uid to groupId, temporarily used for generating rollup SMA. + int32_t scanWinIndex; // for state operator + int32_t pullDataResIndex; + SSDataBlock* pPullDataRes; // pull data SSDataBlock + SSDataBlock* pDeleteDataRes; // delete data SSDataBlock + int32_t deleteDataIndex; + STimeWindow updateWin; + STimeWindowAggSupp twAggSup; + SSDataBlock* pUpdateDataRes; + // status for tmq + SNodeList* pGroupTags; + SNode* pTagCond; + SNode* pTagIndexCond; + + // recover + int32_t blockRecoverContiCnt; + int32_t blockRecoverTotCnt; + SSDataBlock* pRecoverRes; + + SSDataBlock* pCreateTbRes; + int8_t igCheckUpdate; + int8_t igExpired; +} SStreamScanInfo; + +typedef struct { + SVnode* vnode; + SSDataBlock pRes; // result SSDataBlock + STsdbReader* dataReader; + SSnapContext* sContext; + STableListInfo* pTableListInfo; +} SStreamRawScanInfo; + +typedef struct STableCountScanSupp { + int16_t dbNameSlotId; + int16_t stbNameSlotId; + int16_t tbCountSlotId; + bool groupByDbName; + bool groupByStbName; + char dbNameFilter[TSDB_DB_NAME_LEN]; + char stbNameFilter[TSDB_TABLE_NAME_LEN]; +} STableCountScanSupp; + +typedef struct SOptrBasicInfo { + SResultRowInfo resultRowInfo; + SSDataBlock* pRes; + bool mergeResultBlock; +} SOptrBasicInfo; + +typedef struct SIntervalAggOperatorInfo { + SOptrBasicInfo binfo; // basic info + SAggSupporter aggSup; // aggregate supporter + SExprSupp scalarSupp; // supporter for perform scalar function + SGroupResInfo groupResInfo; // multiple results build supporter + SInterval interval; // interval info + int32_t primaryTsIndex; // primary time stamp slot id from result of downstream operator. + STimeWindow win; // query time range + bool timeWindowInterpo; // interpolation needed or not + SArray* pInterpCols; // interpolation columns + int32_t resultTsOrder; // result timestamp order + int32_t inputOrder; // input data ts order + EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model] + STimeWindowAggSupp twAggSup; + SArray* pPrevValues; // SArray used to keep the previous not null value for interpolation. +} SIntervalAggOperatorInfo; + +typedef struct SMergeAlignedIntervalAggOperatorInfo { + SIntervalAggOperatorInfo* intervalAggOperatorInfo; + + uint64_t groupId; // current groupId + int64_t curTs; // current ts + SSDataBlock* prefetchedBlock; + SResultRow* pResultRow; +} SMergeAlignedIntervalAggOperatorInfo; + +typedef struct SStreamIntervalOperatorInfo { + SOptrBasicInfo binfo; // basic info + SAggSupporter aggSup; // aggregate supporter + SExprSupp scalarSupp; // supporter for perform scalar function + SGroupResInfo groupResInfo; // multiple results build supporter + SInterval interval; // interval info + int32_t primaryTsIndex; // primary time stamp slot id from result of downstream operator. + STimeWindowAggSupp twAggSup; + bool invertible; + bool ignoreExpiredData; + bool ignoreExpiredDataSaved; + SArray* pDelWins; // SWinRes + int32_t delIndex; + SSDataBlock* pDelRes; + SPhysiNode* pPhyNode; // create new child + SHashObj* pPullDataMap; + SArray* pPullWins; // SPullWindowInfo + int32_t pullIndex; + SSDataBlock* pPullDataRes; + bool isFinal; + SArray* pChildren; + SStreamState* pState; + SWinKey delKey; + uint64_t numOfDatapack; + SArray* pUpdated; + SSHashObj* pUpdatedMap; + int64_t dataVersion; +} SStreamIntervalOperatorInfo; + +typedef struct SDataGroupInfo { + uint64_t groupId; + int64_t numOfRows; + SArray* pPageList; +} SDataGroupInfo; + +typedef struct SWindowRowsSup { + STimeWindow win; + TSKEY prevTs; + int32_t startRowIndex; + int32_t numOfRows; + uint64_t groupId; +} SWindowRowsSup; + +typedef struct SResultWindowInfo { + void* pOutputBuf; + SSessionKey sessionWin; + bool isOutput; +} SResultWindowInfo; + +typedef struct SStreamSessionAggOperatorInfo { + SOptrBasicInfo binfo; + SStreamAggSupporter streamAggSup; + SExprSupp scalarSupp; // supporter for perform scalar function + SGroupResInfo groupResInfo; + int32_t primaryTsIndex; // primary timestamp slot id + int32_t endTsIndex; // window end timestamp slot id + int32_t order; // current SSDataBlock scan order + STimeWindowAggSupp twAggSup; + SSDataBlock* pWinBlock; // window result + SSDataBlock* pDelRes; // delete result + SSDataBlock* pUpdateRes; // update window + bool returnUpdate; + SSHashObj* pStDeleted; + void* pDelIterator; + SArray* pChildren; // cache for children's result; final stream operator + SPhysiNode* pPhyNode; // create new child + bool isFinal; + bool ignoreExpiredData; + bool ignoreExpiredDataSaved; + SArray* pUpdated; + SSHashObj* pStUpdated; + int64_t dataVersion; +} SStreamSessionAggOperatorInfo; + +typedef struct SStreamStateAggOperatorInfo { + SOptrBasicInfo binfo; + SStreamAggSupporter streamAggSup; + SExprSupp scalarSupp; // supporter for perform scalar function + SGroupResInfo groupResInfo; + int32_t primaryTsIndex; // primary timestamp slot id + STimeWindowAggSupp twAggSup; + SColumn stateCol; + SSDataBlock* pDelRes; + SSHashObj* pSeDeleted; + void* pDelIterator; + SArray* pChildren; // cache for children's result; + bool ignoreExpiredData; + bool ignoreExpiredDataSaved; + SArray* pUpdated; + SSHashObj* pSeUpdated; + int64_t dataVersion; +} SStreamStateAggOperatorInfo; + +typedef struct SStreamPartitionOperatorInfo { + SOptrBasicInfo binfo; + SPartitionBySupporter partitionSup; + SExprSupp scalarSup; + SExprSupp tbnameCalSup; + SExprSupp tagCalSup; + SHashObj* pPartitions; + void* parIte; + void* pTbNameIte; + SSDataBlock* pInputDataBlock; + int32_t tsColIndex; + SSDataBlock* pDelRes; + SSDataBlock* pCreateTbRes; +} SStreamPartitionOperatorInfo; + +typedef struct SStreamFillSupporter { + int32_t type; // fill type + SInterval interval; + SResultRowData prev; + SResultRowData cur; + SResultRowData next; + SResultRowData nextNext; + SFillColInfo* pAllColInfo; // fill exprs and not fill exprs + SExprSupp notFillExprSup; + int32_t numOfAllCols; // number of all exprs, including the tags columns + int32_t numOfFillCols; + int32_t numOfNotFillCols; + int32_t rowSize; + SSHashObj* pResMap; + bool hasDelete; +} SStreamFillSupporter; + +typedef struct SStreamFillOperatorInfo { + SStreamFillSupporter* pFillSup; + SSDataBlock* pRes; + SSDataBlock* pSrcBlock; + int32_t srcRowIndex; + SSDataBlock* pSrcDelBlock; + int32_t srcDelRowIndex; + SSDataBlock* pDelRes; + SColMatchInfo matchInfo; + int32_t primaryTsCol; + int32_t primarySrcSlotId; + SStreamFillInfo* pFillInfo; +} SStreamFillOperatorInfo; + +#define OPTR_IS_OPENED(_optr) (((_optr)->status & OP_OPENED) == OP_OPENED) +#define OPTR_SET_OPENED(_optr) ((_optr)->status |= OP_OPENED) + +SSchemaWrapper* extractQueriedColumnSchema(SScanPhysiNode* pScanNode); +int32_t initQueriedTableSchemaInfo(SReadHandle* pHandle, SScanPhysiNode* pScanNode, const char* dbName, SExecTaskInfo* pTaskInfo); +void cleanupQueriedTableScanInfo(SSchemaInfo* pSchemaInfo); + +void initBasicInfo(SOptrBasicInfo* pInfo, SSDataBlock* pBlock); +void cleanupBasicInfo(SOptrBasicInfo* pInfo); + +int32_t initExprSupp(SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfExpr); +void cleanupExprSupp(SExprSupp* pSup); + +void destroyExprInfo(SExprInfo* pExpr, int32_t numOfExprs); + +int32_t initAggSup(SExprSupp* pSup, SAggSupporter* pAggSup, SExprInfo* pExprInfo, int32_t numOfCols, size_t keyBufSize, + const char* pkey, void* pState); +void cleanupAggSup(SAggSupporter* pAggSup); + +void initResultSizeInfo(SResultInfo* pResultInfo, int32_t numOfRows); + +void doBuildStreamResBlock(struct SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, + SDiskbasedBuf* pBuf); +void doBuildResultDatablock(struct SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, + SDiskbasedBuf* pBuf); + +bool hasLimitOffsetInfo(SLimitInfo* pLimitInfo); +bool hasSlimitOffsetInfo(SLimitInfo* pLimitInfo); +void initLimitInfo(const SNode* pLimit, const SNode* pSLimit, SLimitInfo* pLimitInfo); +void resetLimitInfoForNextGroup(SLimitInfo* pLimitInfo); +bool applyLimitOffset(SLimitInfo* pLimitInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo); + +void applyAggFunctionOnPartialTuples(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, SColumnInfoData* pTimeWindowData, + int32_t offset, int32_t forwardStep, int32_t numOfTotal, int32_t numOfOutput); + +int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, char* pData, SArray* pColList, char** pNextStart); +void updateLoadRemoteInfo(SLoadRemoteDataInfo* pInfo, int64_t numOfRows, int32_t dataLen, int64_t startTs, + struct SOperatorInfo* pOperator); + +STimeWindow getFirstQualifiedTimeWindow(int64_t ts, STimeWindow* pWindow, SInterval* pInterval, int32_t order); +int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, uint32_t* defaultBufsz); + +extern void doDestroyExchangeOperatorInfo(void* param); + +void doFilter(SSDataBlock* pBlock, SFilterInfo* pFilterInfo, SColMatchInfo* pColMatchInfo); +int32_t addTagPseudoColumnData(SReadHandle* pHandle, const SExprInfo* pExpr, int32_t numOfExpr, SSDataBlock* pBlock, + int32_t rows, const char* idStr, STableMetaCacheInfo* pCache); + +void appendOneRowToDataBlock(SSDataBlock* pBlock, STupleHandle* pTupleHandle); +void setTbNameColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId, const char* name); + +void setResultRowInitCtx(SResultRow* pResult, SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset); +void clearResultRowInitFlag(SqlFunctionCtx* pCtx, int32_t numOfOutput); + +SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pResultRowInfo, char* pData, + int16_t bytes, bool masterscan, uint64_t groupId, SExecTaskInfo* pTaskInfo, + bool isIntervalQuery, SAggSupporter* pSup, bool keepGroup); + +int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBlock* pSrcBlock, SqlFunctionCtx* pCtx, + int32_t numOfOutput, SArray* pPseudoList); + +void setInputDataBlock(SExprSupp* pExprSupp, SSDataBlock* pBlock, int32_t order, int32_t scanFlag, bool createDummyCol); + +int32_t checkForQueryBuf(size_t numOfTables); + +int32_t createDataSinkParam(SDataSinkNode* pNode, void** pParam, SExecTaskInfo* pTask, SReadHandle* readHandle); + +STimeWindow getActiveTimeWindow(SDiskbasedBuf* pBuf, SResultRowInfo* pResultRowInfo, int64_t ts, SInterval* pInterval, + int32_t order); +int32_t getNumOfRowsInTimeWindow(SDataBlockInfo* pDataBlockInfo, TSKEY* pPrimaryColumn, int32_t startPos, TSKEY ekey, + __block_search_fn_t searchFn, STableQueryInfo* item, int32_t order); +int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order); +SResultRow* getNewResultRow(SDiskbasedBuf* pResultBuf, int32_t* currentPageId, int32_t interBufSize); +void getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId, SSessionKey* pKey); +bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap); +bool functionNeedToExecute(SqlFunctionCtx* pCtx); +bool isOverdue(TSKEY ts, STimeWindowAggSupp* pSup); +bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pSup); +bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, SStreamState* pState, STimeWindowAggSupp* pTwSup); +void appendOneRowToStreamSpecialBlock(SSDataBlock* pBlock, TSKEY* pStartTs, TSKEY* pEndTs, uint64_t* pUid, + uint64_t* pGp, void* pTbName); +uint64_t calGroupIdByData(SPartitionBySupporter* pParSup, SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t rowId); + +int32_t finalizeResultRows(SDiskbasedBuf* pBuf, SResultRowPosition* resultRowPosition, SExprSupp* pSup, + SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo); + +bool groupbyTbname(SNodeList* pGroupList); +int32_t buildDataBlockFromGroupRes(struct SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, SExprSupp* pSup, + SGroupResInfo* pGroupResInfo); +int32_t saveSessionDiscBuf(SStreamState* pState, SSessionKey* key, void* buf, int32_t size); +int32_t buildSessionResultDataBlock(struct SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, + SExprSupp* pSup, SGroupResInfo* pGroupResInfo); +int32_t setOutputBuf(SStreamState* pState, STimeWindow* win, SResultRow** pResult, int64_t tableGroupId, + SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset, SAggSupporter* pAggSup); +int32_t releaseOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult); +int32_t saveOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult, int32_t resSize); +void getNextIntervalWindow(SInterval* pInterval, STimeWindow* tw, int32_t order); +int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int32_t pos, int32_t order, + int64_t* pData); +void appendCreateTableRow(SStreamState* pState, SExprSupp* pTableSup, SExprSupp* pTagSup, uint64_t groupId, + SSDataBlock* pSrcBlock, int32_t rowId, SSDataBlock* pDestBlock); + +SSDataBlock* buildCreateTableBlock(SExprSupp* tbName, SExprSupp* tag); +SExprInfo* createExpr(SNodeList* pNodeList, int32_t* numOfExprs); + +void copyResultrowToDataBlock(SExprInfo* pExprInfo, int32_t numOfExprs, SResultRow* pRow, SqlFunctionCtx* pCtx, + SSDataBlock* pBlock, const int32_t* rowEntryOffset, SExecTaskInfo* pTaskInfo); +void doUpdateNumOfRows(SqlFunctionCtx* pCtx, SResultRow* pRow, int32_t numOfExprs, const int32_t* rowEntryOffset); +void doClearBufferedBlocks(SStreamScanInfo* pInfo); + uint64_t calcGroupId(char* pData, int32_t len); + #ifdef __cplusplus } #endif -#endif /*_TD_EXECUTOR_INT_H*/ \ No newline at end of file +#endif // TDENGINE_EXECUTORINT_H diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index 1850cd007f3437e4154931044fcea5e2799ce333..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -1,865 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#ifndef TDENGINE_EXECUTORIMPL_H -#define TDENGINE_EXECUTORIMPL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "os.h" -#include "tcommon.h" -#include "tlosertree.h" -#include "tsort.h" -#include "ttszip.h" -#include "tvariant.h" - -#include "dataSinkMgt.h" -#include "executil.h" -#include "executor.h" -#include "planner.h" -#include "scalar.h" -#include "taosdef.h" -#include "tarray.h" -#include "tfill.h" -#include "thash.h" -#include "tlockfree.h" -#include "tmsg.h" -#include "tpagedbuf.h" -#include "tstream.h" -#include "tstreamUpdate.h" - -#include "executorInt.h" -#include "vnode.h" - -typedef int32_t (*__block_search_fn_t)(char* data, int32_t num, int64_t key, int32_t order); - -#define IS_VALID_SESSION_WIN(winInfo) ((winInfo).sessionWin.win.skey > 0) -#define SET_SESSION_WIN_INVALID(winInfo) ((winInfo).sessionWin.win.skey = INT64_MIN) -#define IS_INVALID_SESSION_WIN_KEY(winKey) ((winKey).win.skey <= 0) -#define SET_SESSION_WIN_KEY_INVALID(pWinKey) ((pWinKey)->win.skey = INT64_MIN) - -enum { - // when this task starts to execute, this status will set - TASK_NOT_COMPLETED = 0x1u, - - /* Task is over - * 1. this status is used in one row result query process, e.g., count/sum/first/last/ avg...etc. - * 2. when all data within queried time window, it is also denoted as query_completed - */ - TASK_COMPLETED = 0x2u, -}; - -/** - * If the number of generated results is greater than this value, - * query query will be halt and return results to client immediate. - */ -typedef struct SResultInfo { // TODO refactor - int64_t totalRows; // total generated result size in rows - int64_t totalBytes; // total results in bytes. - int32_t capacity; // capacity of current result output buffer - int32_t threshold; // result size threshold in rows. -} SResultInfo; - -typedef struct STableQueryInfo { - TSKEY lastKey; // last check ts, todo remove it later - SResultRowPosition pos; // current active time window -} STableQueryInfo; - -typedef struct SLimit { - int64_t limit; - int64_t offset; -} SLimit; - -typedef struct STableScanAnalyzeInfo SFileBlockLoadRecorder; - -typedef struct STaskCostInfo { - int64_t created; - int64_t start; - uint64_t elapsedTime; - double extractListTime; - double groupIdMapTime; - SFileBlockLoadRecorder* pRecoder; -} STaskCostInfo; - -typedef struct SOperatorCostInfo { - double openCost; - double totalCost; -} SOperatorCostInfo; - -struct SOperatorInfo; - -typedef int32_t (*__optr_encode_fn_t)(struct SOperatorInfo* pOperator, char** result, int32_t* length); -typedef int32_t (*__optr_decode_fn_t)(struct SOperatorInfo* pOperator, char* result); - -typedef int32_t (*__optr_open_fn_t)(struct SOperatorInfo* pOptr); -typedef SSDataBlock* (*__optr_fn_t)(struct SOperatorInfo* pOptr); -typedef void (*__optr_close_fn_t)(void* param); -typedef int32_t (*__optr_explain_fn_t)(struct SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len); -typedef int32_t (*__optr_reqBuf_fn_t)(struct SOperatorInfo* pOptr); - -typedef struct STaskIdInfo { - uint64_t queryId; // this is also a request id - uint64_t subplanId; - uint64_t templateId; - char* str; -} STaskIdInfo; - -enum { - STREAM_RECOVER_STEP__NONE = 0, - STREAM_RECOVER_STEP__PREPARE1, - STREAM_RECOVER_STEP__PREPARE2, - STREAM_RECOVER_STEP__SCAN, -}; - -typedef struct { - // TODO remove prepareStatus - STqOffsetVal prepareStatus; // for tmq - STqOffsetVal lastStatus; // for tmq - SMqMetaRsp metaRsp; // for tmq fetching meta - int8_t returned; - int64_t snapshotVer; - const SSubmitReq* pReq; - - SSchemaWrapper* schema; - char tbName[TSDB_TABLE_NAME_LEN]; - int8_t recoverStep; - int8_t recoverScanFinished; - SQueryTableDataCond tableCond; - int64_t fillHistoryVer1; - int64_t fillHistoryVer2; - - // int8_t triggerSaved; - // int64_t deleteMarkSaved; - SStreamState* pState; -} SStreamTaskInfo; - -typedef struct { - char* tablename; - char* dbname; - int32_t tversion; - SSchemaWrapper* sw; - SSchemaWrapper* qsw; -} SSchemaInfo; - -typedef struct SExchangeOpStopInfo { - int32_t operatorType; - int64_t refId; -} SExchangeOpStopInfo; - -typedef struct STaskStopInfo { - SRWLatch lock; - SArray* pStopInfo; -} STaskStopInfo; - -struct SExecTaskInfo { - STaskIdInfo id; - uint32_t status; - STimeWindow window; - STaskCostInfo cost; - int64_t owner; // if it is in execution - int32_t code; - int32_t qbufQuota; // total available buffer (in KB) during execution query - - int64_t version; // used for stream to record wal version, why not move to sschemainfo - SStreamTaskInfo streamInfo; - SSchemaInfo schemaInfo; - STableListInfo* pTableInfoList; // this is a table list - const char* sql; // query sql string - jmp_buf env; // jump to this position when error happens. - EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model] - SSubplan* pSubplan; - struct SOperatorInfo* pRoot; - SLocalFetch localFetch; - SArray* pResultBlockList; // result block list - STaskStopInfo stopInfo; -}; - -enum { - OP_NOT_OPENED = 0x0, - OP_OPENED = 0x1, - OP_RES_TO_RETURN = 0x5, - OP_EXEC_DONE = 0x9, - OP_EXEC_RECV = 0x11, -}; - -typedef struct SOperatorFpSet { - __optr_open_fn_t _openFn; // DO NOT invoke this function directly - __optr_fn_t getNextFn; - __optr_fn_t cleanupFn; // call this function to release the allocated resources ASAP - __optr_close_fn_t closeFn; - __optr_reqBuf_fn_t reqBufFn; // total used buffer for blocking operator - __optr_encode_fn_t encodeResultRow; - __optr_decode_fn_t decodeResultRow; - __optr_explain_fn_t getExplainFn; -} SOperatorFpSet; - -typedef struct SExprSupp { - SExprInfo* pExprInfo; - int32_t numOfExprs; // the number of scalar expression in group operator - SqlFunctionCtx* pCtx; - int32_t* rowEntryInfoOffset; // offset value for each row result cell info - SFilterInfo* pFilterInfo; -} SExprSupp; - -typedef struct SOperatorInfo { - uint16_t operatorType; - int16_t resultDataBlockId; - bool blocking; // block operator or not - uint8_t status; // denote if current operator is completed - char* name; // name, for debug purpose - void* info; // extension attribution - SExprSupp exprSupp; - SExecTaskInfo* pTaskInfo; - SOperatorCostInfo cost; - SResultInfo resultInfo; - struct SOperatorInfo** pDownstream; // downstram pointer list - int32_t numOfDownstream; // number of downstream. The value is always ONE expect for join operator - SOperatorFpSet fpSet; -} SOperatorInfo; - -typedef enum { - EX_SOURCE_DATA_NOT_READY = 0x1, - EX_SOURCE_DATA_READY = 0x2, - EX_SOURCE_DATA_EXHAUSTED = 0x3, -} EX_SOURCE_STATUS; - -#define COL_MATCH_FROM_COL_ID 0x1 -#define COL_MATCH_FROM_SLOT_ID 0x2 - -typedef struct SLoadRemoteDataInfo { - uint64_t totalSize; // total load bytes from remote - uint64_t totalRows; // total number of rows - uint64_t totalElapsed; // total elapsed time -} SLoadRemoteDataInfo; - -typedef struct SLimitInfo { - SLimit limit; - SLimit slimit; - uint64_t currentGroupId; - int64_t remainGroupOffset; - int64_t numOfOutputGroups; - int64_t remainOffset; - int64_t numOfOutputRows; -} SLimitInfo; - -typedef struct SExchangeInfo { - SArray* pSources; - SArray* pSourceDataInfo; - tsem_t ready; - void* pTransporter; - - // SArray, result block list, used to keep the multi-block that - // passed by downstream operator - SArray* pResultBlockList; - SArray* pRecycledBlocks; // build a pool for small data block to avoid to repeatly create and then destroy. - SSDataBlock* pDummyBlock; // dummy block, not keep data - bool seqLoadData; // sequential load data or not, false by default - int32_t current; - SLoadRemoteDataInfo loadInfo; - uint64_t self; - SLimitInfo limitInfo; - int64_t openedTs; // start exec time stamp, todo: move to SLoadRemoteDataInfo -} SExchangeInfo; - -typedef struct SScanInfo { - int32_t numOfAsc; - int32_t numOfDesc; -} SScanInfo; - -typedef struct SSampleExecInfo { - double sampleRatio; // data block sample ratio, 1 by default - uint32_t seed; // random seed value -} SSampleExecInfo; - -enum { - TABLE_SCAN__TABLE_ORDER = 1, - TABLE_SCAN__BLOCK_ORDER = 2, -}; - -typedef struct SAggSupporter { - SSHashObj* pResultRowHashTable; // quick locate the window object for each result - char* keyBuf; // window key buffer - SDiskbasedBuf* pResultBuf; // query result buffer based on blocked-wised disk file - int32_t resultRowSize; // the result buffer size for each result row, with the meta data size for each row - int32_t currentPageId; // current write page id -} SAggSupporter; - -typedef struct { - // if the upstream is an interval operator, the interval info is also kept here to get the time window to check if - // current data block needs to be loaded. - SInterval interval; - SAggSupporter* pAggSup; - SExprSupp* pExprSup; // expr supporter of aggregate operator -} SAggOptrPushDownInfo; - -typedef struct STableMetaCacheInfo { - SLRUCache* pTableMetaEntryCache; // 100 by default - uint64_t metaFetch; - uint64_t cacheHit; -} STableMetaCacheInfo; - -typedef struct STableScanBase { - STsdbReader* dataReader; - SFileBlockLoadRecorder readRecorder; - SQueryTableDataCond cond; - SAggOptrPushDownInfo pdInfo; - SColMatchInfo matchInfo; - SReadHandle readHandle; - SExprSupp pseudoSup; - STableMetaCacheInfo metaCache; - int32_t scanFlag; // table scan flag to denote if it is a repeat/reverse/main scan - int32_t dataBlockLoadFlag; - SLimitInfo limitInfo; -} STableScanBase; - -typedef struct STableScanInfo { - STableScanBase base; - SScanInfo scanInfo; - int32_t scanTimes; - SSDataBlock* pResBlock; - SSampleExecInfo sample; // sample execution info - int32_t currentGroupId; - int32_t currentTable; - int8_t scanMode; - int8_t assignBlockUid; - bool hasGroupByTag; -} STableScanInfo; - -typedef struct STableMergeScanInfo { - int32_t tableStartIndex; - int32_t tableEndIndex; - bool hasGroupId; - uint64_t groupId; - SArray* queryConds; // array of queryTableDataCond - STableScanBase base; - int32_t bufPageSize; - uint32_t sortBufSize; // max buffer size for in-memory sort - SArray* pSortInfo; - SSortHandle* pSortHandle; - SSDataBlock* pSortInputBlock; - int64_t startTs; // sort start time - SArray* sortSourceParams; - SLimitInfo limitInfo; - int64_t numOfRows; - SScanInfo scanInfo; - SSDataBlock* pResBlock; - SSampleExecInfo sample; // sample execution info - SSortExecInfo sortExecInfo; -} STableMergeScanInfo; - -typedef struct STagScanInfo { - SColumnInfo* pCols; - SSDataBlock* pRes; - SColMatchInfo matchInfo; - int32_t curPos; - SReadHandle readHandle; -} STagScanInfo; - -typedef enum EStreamScanMode { - STREAM_SCAN_FROM_READERHANDLE = 1, - STREAM_SCAN_FROM_RES, - STREAM_SCAN_FROM_UPDATERES, - STREAM_SCAN_FROM_DELETE_DATA, - STREAM_SCAN_FROM_DATAREADER_RETRIEVE, - STREAM_SCAN_FROM_DATAREADER_RANGE, -} EStreamScanMode; - -enum { - PROJECT_RETRIEVE_CONTINUE = 0x1, - PROJECT_RETRIEVE_DONE = 0x2, -}; - -typedef struct SStreamAggSupporter { - int32_t resultRowSize; // the result buffer size for each result row, with the meta data size for each row - SSDataBlock* pScanBlock; - SStreamState* pState; - int64_t gap; // stream session window gap - SqlFunctionCtx* pDummyCtx; // for combine - SSHashObj* pResultRows; - int32_t stateKeySize; - int16_t stateKeyType; - SDiskbasedBuf* pResultBuf; -} SStreamAggSupporter; - -typedef struct SWindowSupporter { - SStreamAggSupporter* pStreamAggSup; - int64_t gap; - uint16_t parentType; - SAggSupporter* pIntervalAggSup; -} SWindowSupporter; - -typedef struct SPartitionBySupporter { - SArray* pGroupCols; // group by columns, SArray - SArray* pGroupColVals; // current group column values, SArray - char* keyBuf; // group by keys for hash - bool needCalc; // partition by column -} SPartitionBySupporter; - -typedef struct SPartitionDataInfo { - uint64_t groupId; - char* tbname; - SArray* tags; - SArray* rowIds; -} SPartitionDataInfo; - -typedef struct STimeWindowAggSupp { - int8_t calTrigger; - int8_t calTriggerSaved; - int64_t deleteMark; - int64_t deleteMarkSaved; - int64_t waterMark; - TSKEY maxTs; - TSKEY minTs; - SColumnInfoData timeWindowData; // query time window info for scalar function execution. -} STimeWindowAggSupp; - -typedef struct SStreamScanInfo { - uint64_t tableUid; // queried super table uid - SExprInfo* pPseudoExpr; - int32_t numOfPseudoExpr; - SExprSupp tbnameCalSup; - SExprSupp tagCalSup; - int32_t primaryTsIndex; // primary time stamp slot id - SReadHandle readHandle; - SInterval interval; // if the upstream is an interval operator, the interval info is also kept here. - SColMatchInfo matchInfo; - - SArray* pBlockLists; // multiple SSDatablock. - SSDataBlock* pRes; // result SSDataBlock - SSDataBlock* pUpdateRes; // update SSDataBlock - int32_t updateResIndex; - int32_t blockType; // current block type - int32_t validBlockIndex; // Is current data has returned? - uint64_t numOfExec; // execution times - STqReader* tqReader; - - uint64_t groupId; - SUpdateInfo* pUpdateInfo; - - EStreamScanMode scanMode; - SOperatorInfo* pStreamScanOp; - SOperatorInfo* pTableScanOp; - SArray* childIds; - SWindowSupporter windowSup; - SPartitionBySupporter partitionSup; - SExprSupp* pPartScalarSup; - bool assignBlockUid; // assign block uid to groupId, temporarily used for generating rollup SMA. - int32_t scanWinIndex; // for state operator - int32_t pullDataResIndex; - SSDataBlock* pPullDataRes; // pull data SSDataBlock - SSDataBlock* pDeleteDataRes; // delete data SSDataBlock - int32_t deleteDataIndex; - STimeWindow updateWin; - STimeWindowAggSupp twAggSup; - SSDataBlock* pUpdateDataRes; - // status for tmq - SNodeList* pGroupTags; - SNode* pTagCond; - SNode* pTagIndexCond; - - // recover - int32_t blockRecoverContiCnt; - int32_t blockRecoverTotCnt; - - int8_t igCheckUpdate; - int8_t igExpired; -} SStreamScanInfo; - -typedef struct { - // int8_t subType; - // bool withMeta; - // int64_t suid; - // int64_t snapVersion; - // void *metaInfo; - // void *dataInfo; - SVnode* vnode; - SSDataBlock pRes; // result SSDataBlock - STsdbReader* dataReader; - SSnapContext* sContext; -} SStreamRawScanInfo; - -typedef struct STableCountScanSupp { - int16_t dbNameSlotId; - int16_t stbNameSlotId; - int16_t tbCountSlotId; - bool groupByDbName; - bool groupByStbName; - char dbNameFilter[TSDB_DB_NAME_LEN]; - char stbNameFilter[TSDB_TABLE_NAME_LEN]; -} STableCountScanSupp; - -typedef struct STableCountScanOperatorInfo { - SReadHandle readHandle; - SSDataBlock* pRes; - - STableCountScanSupp supp; - - int32_t currGrpIdx; - SArray* stbUidList; // when group by db_name and/or stable_name -} STableCountScanOperatorInfo; - -typedef struct SOptrBasicInfo { - SResultRowInfo resultRowInfo; - SSDataBlock* pRes; - bool mergeResultBlock; -} SOptrBasicInfo; - -typedef struct SIntervalAggOperatorInfo { - SOptrBasicInfo binfo; // basic info - SAggSupporter aggSup; // aggregate supporter - SExprSupp scalarSupp; // supporter for perform scalar function - SGroupResInfo groupResInfo; // multiple results build supporter - SInterval interval; // interval info - int32_t primaryTsIndex; // primary time stamp slot id from result of downstream operator. - STimeWindow win; // query time range - bool timeWindowInterpo; // interpolation needed or not - SArray* pInterpCols; // interpolation columns - int32_t resultTsOrder; // result timestamp order - int32_t inputOrder; // input data ts order - EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model] - STimeWindowAggSupp twAggSup; - SArray* pPrevValues; // SArray used to keep the previous not null value for interpolation. -} SIntervalAggOperatorInfo; - -typedef struct SMergeAlignedIntervalAggOperatorInfo { - SIntervalAggOperatorInfo* intervalAggOperatorInfo; - - uint64_t groupId; // current groupId - int64_t curTs; // current ts - SSDataBlock* prefetchedBlock; - SResultRow* pResultRow; -} SMergeAlignedIntervalAggOperatorInfo; - -typedef struct SStreamIntervalOperatorInfo { - SOptrBasicInfo binfo; // basic info - SAggSupporter aggSup; // aggregate supporter - SExprSupp scalarSupp; // supporter for perform scalar function - SGroupResInfo groupResInfo; // multiple results build supporter - SInterval interval; // interval info - int32_t primaryTsIndex; // primary time stamp slot id from result of downstream operator. - STimeWindowAggSupp twAggSup; - bool invertible; - bool ignoreExpiredData; - SArray* pDelWins; // SWinRes - int32_t delIndex; - SSDataBlock* pDelRes; - SPhysiNode* pPhyNode; // create new child - SHashObj* pPullDataMap; - SArray* pPullWins; // SPullWindowInfo - int32_t pullIndex; - SSDataBlock* pPullDataRes; - bool isFinal; - SArray* pChildren; - SStreamState* pState; - SWinKey delKey; - uint64_t numOfDatapack; -} SStreamIntervalOperatorInfo; - -typedef struct SDataGroupInfo { - uint64_t groupId; - int64_t numOfRows; - SArray* pPageList; -} SDataGroupInfo; - -typedef struct SWindowRowsSup { - STimeWindow win; - TSKEY prevTs; - int32_t startRowIndex; - int32_t numOfRows; - uint64_t groupId; -} SWindowRowsSup; - -typedef struct SResultWindowInfo { - void* pOutputBuf; - SSessionKey sessionWin; - bool isOutput; -} SResultWindowInfo; - -typedef struct SStateWindowInfo { - SResultWindowInfo winInfo; - SStateKeys* pStateKey; -} SStateWindowInfo; - -typedef struct SStreamSessionAggOperatorInfo { - SOptrBasicInfo binfo; - SStreamAggSupporter streamAggSup; - SExprSupp scalarSupp; // supporter for perform scalar function - SGroupResInfo groupResInfo; - int32_t primaryTsIndex; // primary timestamp slot id - int32_t endTsIndex; // window end timestamp slot id - int32_t order; // current SSDataBlock scan order - STimeWindowAggSupp twAggSup; - SSDataBlock* pWinBlock; // window result - SSDataBlock* pDelRes; // delete result - SSDataBlock* pUpdateRes; // update window - bool returnUpdate; - SSHashObj* pStDeleted; - void* pDelIterator; - SArray* pChildren; // cache for children's result; final stream operator - SPhysiNode* pPhyNode; // create new child - bool isFinal; - bool ignoreExpiredData; -} SStreamSessionAggOperatorInfo; - -typedef struct SStreamStateAggOperatorInfo { - SOptrBasicInfo binfo; - SStreamAggSupporter streamAggSup; - SExprSupp scalarSupp; // supporter for perform scalar function - SGroupResInfo groupResInfo; - int32_t primaryTsIndex; // primary timestamp slot id - STimeWindowAggSupp twAggSup; - SColumn stateCol; - SSDataBlock* pDelRes; - SSHashObj* pSeDeleted; - void* pDelIterator; - SArray* pChildren; // cache for children's result; - bool ignoreExpiredData; -} SStreamStateAggOperatorInfo; - -typedef struct SStreamPartitionOperatorInfo { - SOptrBasicInfo binfo; - SPartitionBySupporter partitionSup; - SExprSupp scalarSup; - SExprSupp tbnameCalSup; - SExprSupp tagCalSup; - SHashObj* pPartitions; - void* parIte; - SSDataBlock* pInputDataBlock; - int32_t tsColIndex; - SSDataBlock* pDelRes; -} SStreamPartitionOperatorInfo; - -typedef struct SStreamFillSupporter { - int32_t type; // fill type - SInterval interval; - SResultRowData prev; - SResultRowData cur; - SResultRowData next; - SResultRowData nextNext; - SFillColInfo* pAllColInfo; // fill exprs and not fill exprs - SExprSupp notFillExprSup; - int32_t numOfAllCols; // number of all exprs, including the tags columns - int32_t numOfFillCols; - int32_t numOfNotFillCols; - int32_t rowSize; - SSHashObj* pResMap; - bool hasDelete; -} SStreamFillSupporter; - -typedef struct SStreamFillOperatorInfo { - SStreamFillSupporter* pFillSup; - SSDataBlock* pRes; - SSDataBlock* pSrcBlock; - int32_t srcRowIndex; - SSDataBlock* pSrcDelBlock; - int32_t srcDelRowIndex; - SSDataBlock* pDelRes; - SColMatchInfo matchInfo; - int32_t primaryTsCol; - int32_t primarySrcSlotId; - SStreamFillInfo* pFillInfo; -} SStreamFillOperatorInfo; - -#define OPTR_IS_OPENED(_optr) (((_optr)->status & OP_OPENED) == OP_OPENED) -#define OPTR_SET_OPENED(_optr) ((_optr)->status |= OP_OPENED) - -SOperatorFpSet createOperatorFpSet(__optr_open_fn_t openFn, __optr_fn_t nextFn, __optr_fn_t cleanup, - __optr_close_fn_t closeFn, __optr_reqBuf_fn_t reqBufFn, __optr_explain_fn_t explain); -int32_t optrDummyOpenFn(SOperatorInfo* pOperator); -int32_t appendDownstream(SOperatorInfo* p, SOperatorInfo** pDownstream, int32_t num); -void setOperatorCompleted(SOperatorInfo* pOperator); -void setOperatorInfo(SOperatorInfo* pOperator, const char* name, int32_t type, bool blocking, int32_t status, - void* pInfo, SExecTaskInfo* pTaskInfo); -void destroyOperatorInfo(SOperatorInfo* pOperator); -int32_t optrDefaultBufFn(SOperatorInfo* pOperator); - -void initBasicInfo(SOptrBasicInfo* pInfo, SSDataBlock* pBlock); -void cleanupBasicInfo(SOptrBasicInfo* pInfo); - -int32_t initExprSupp(SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfExpr); -void cleanupExprSupp(SExprSupp* pSup); - -void destroyExprInfo(SExprInfo* pExpr, int32_t numOfExprs); - -int32_t initAggSup(SExprSupp* pSup, SAggSupporter* pAggSup, SExprInfo* pExprInfo, int32_t numOfCols, size_t keyBufSize, - const char* pkey, void* pState); -void cleanupAggSup(SAggSupporter* pAggSup); - -void initResultSizeInfo(SResultInfo* pResultInfo, int32_t numOfRows); - -void doBuildStreamResBlock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, - SDiskbasedBuf* pBuf); -void doBuildResultDatablock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, - SDiskbasedBuf* pBuf); - -bool hasLimitOffsetInfo(SLimitInfo* pLimitInfo); -bool hasSlimitOffsetInfo(SLimitInfo* pLimitInfo); -void initLimitInfo(const SNode* pLimit, const SNode* pSLimit, SLimitInfo* pLimitInfo); -void resetLimitInfoForNextGroup(SLimitInfo* pLimitInfo); -bool applyLimitOffset(SLimitInfo* pLimitInfo, SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo); - -void applyAggFunctionOnPartialTuples(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, SColumnInfoData* pTimeWindowData, - int32_t offset, int32_t forwardStep, int32_t numOfTotal, int32_t numOfOutput); - -int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, char* pData, SArray* pColList, char** pNextStart); -void updateLoadRemoteInfo(SLoadRemoteDataInfo* pInfo, int64_t numOfRows, int32_t dataLen, int64_t startTs, - SOperatorInfo* pOperator); - -STimeWindow getFirstQualifiedTimeWindow(int64_t ts, STimeWindow* pWindow, SInterval* pInterval, int32_t order); - -int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scanFlag); -int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, uint32_t* defaultBufsz); - -extern void doDestroyExchangeOperatorInfo(void* param); - -void doFilter(SSDataBlock* pBlock, SFilterInfo* pFilterInfo, SColMatchInfo* pColMatchInfo); -int32_t addTagPseudoColumnData(SReadHandle* pHandle, const SExprInfo* pExpr, int32_t numOfExpr, SSDataBlock* pBlock, - int32_t rows, const char* idStr, STableMetaCacheInfo* pCache); - -void appendOneRowToDataBlock(SSDataBlock* pBlock, STupleHandle* pTupleHandle); -void setTbNameColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, int32_t functionId, const char* name); - -void setResultRowInitCtx(SResultRow* pResult, SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset); - -SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pResultRowInfo, char* pData, - int16_t bytes, bool masterscan, uint64_t groupId, SExecTaskInfo* pTaskInfo, - bool isIntervalQuery, SAggSupporter* pSup); -// operator creater functions -// clang-format off -SOperatorInfo* createExchangeOperatorInfo(void* pTransporter, SExchangePhysiNode* pExNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNode* pScanPhyNode, const char* pUser, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createTableCountScanOperatorInfo(SReadHandle* handle, STableCountScanPhysiNode* pNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* pNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SProjectPhysiNode* pProjPhyNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createMultiwayMergeOperatorInfo(SOperatorInfo** dowStreams, size_t numStreams, SMergePhysiNode* pMergePhysiNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createCacherowsScanOperator(SLastRowScanPhysiNode* pTableScanNode, SReadHandle* readHandle, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, bool isStream); - -SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SMergeIntervalPhysiNode* pIntervalPhyNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SMergeAlignedIntervalPhysiNode* pNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, int32_t numOfChild); - -SOperatorInfo* createSessionAggOperatorInfo(SOperatorInfo* downstream, SSessionWinodwPhysiNode* pSessionNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* pAggNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createDataBlockInfoScanOperator(SReadHandle* readHandle, SBlockDistScanPhysiNode* pBlockScanNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* pTableScanNode, SNode* pTagCond, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createRawScanOperatorInfo(SReadHandle* pHandle, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SFillPhysiNode* pPhyFillNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createStatewindowOperatorInfo(SOperatorInfo* downstream, SStateWinodwPhysiNode* pStateNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createPartitionOperatorInfo(SOperatorInfo* downstream, SPartitionPhysiNode* pPartNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStreamPartitionPhysiNode* pPartNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDownstream, SSortMergeJoinPhysiNode* pJoinNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, int32_t numOfChild); - -SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createStreamFillOperatorInfo(SOperatorInfo* downstream, SStreamFillPhysiNode* pPhyFillNode, SExecTaskInfo* pTaskInfo); - -SOperatorInfo* createGroupSortOperatorInfo(SOperatorInfo* downstream, SGroupSortPhysiNode* pSortPhyNode, SExecTaskInfo* pTaskInfo); -// clang-format on - -int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBlock* pSrcBlock, SqlFunctionCtx* pCtx, - int32_t numOfOutput, SArray* pPseudoList); - -void setInputDataBlock(SExprSupp* pExprSupp, SSDataBlock* pBlock, int32_t order, int32_t scanFlag, bool createDummyCol); - -int32_t checkForQueryBuf(size_t numOfTables); - -bool isTaskKilled(SExecTaskInfo* pTaskInfo); -void setTaskKilled(SExecTaskInfo* pTaskInfo, int32_t rspCode); -void doDestroyTask(SExecTaskInfo* pTaskInfo); -void setTaskStatus(SExecTaskInfo* pTaskInfo, int8_t status); - -int32_t createExecTaskInfoImpl(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SReadHandle* pHandle, uint64_t taskId, - char* sql, EOPTR_EXEC_MODEL model); -int32_t createDataSinkParam(SDataSinkNode* pNode, void** pParam, qTaskInfo_t* pTaskInfo, SReadHandle* readHandle); -int32_t getOperatorExplainExecInfo(SOperatorInfo* operatorInfo, SArray* pExecInfoList); - -STimeWindow getActiveTimeWindow(SDiskbasedBuf* pBuf, SResultRowInfo* pResultRowInfo, int64_t ts, SInterval* pInterval, - int32_t order); -int32_t getNumOfRowsInTimeWindow(SDataBlockInfo* pDataBlockInfo, TSKEY* pPrimaryColumn, int32_t startPos, TSKEY ekey, - __block_search_fn_t searchFn, STableQueryInfo* item, int32_t order); -int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order); -SResultRow* getNewResultRow(SDiskbasedBuf* pResultBuf, int32_t* currentPageId, int32_t interBufSize); -void getCurSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId, SSessionKey* pKey); -bool isInTimeWindow(STimeWindow* pWin, TSKEY ts, int64_t gap); -bool functionNeedToExecute(SqlFunctionCtx* pCtx); -bool isOverdue(TSKEY ts, STimeWindowAggSupp* pSup); -bool isCloseWindow(STimeWindow* pWin, STimeWindowAggSupp* pSup); -bool isDeletedWindow(STimeWindow* pWin, uint64_t groupId, SAggSupporter* pSup); -bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, SStreamState* pState, STimeWindowAggSupp* pTwSup); -void appendOneRowToStreamSpecialBlock(SSDataBlock* pBlock, TSKEY* pStartTs, TSKEY* pEndTs, uint64_t* pUid, - uint64_t* pGp, void* pTbName); -uint64_t calGroupIdByData(SPartitionBySupporter* pParSup, SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t rowId); -void calBlockTbName(SStreamScanInfo* pInfo, SSDataBlock* pBlock); - -int32_t finalizeResultRows(SDiskbasedBuf* pBuf, SResultRowPosition* resultRowPosition, SExprSupp* pSup, - SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo); - -bool groupbyTbname(SNodeList* pGroupList); -int32_t buildDataBlockFromGroupRes(SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, SExprSupp* pSup, - SGroupResInfo* pGroupResInfo); -int32_t saveSessionDiscBuf(SStreamState* pState, SSessionKey* key, void* buf, int32_t size); -int32_t buildSessionResultDataBlock(SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, - SExprSupp* pSup, SGroupResInfo* pGroupResInfo); -int32_t setOutputBuf(SStreamState* pState, STimeWindow* win, SResultRow** pResult, int64_t tableGroupId, - SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset, SAggSupporter* pAggSup); -int32_t releaseOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult); -int32_t saveOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult, int32_t resSize); -int32_t qAppendTaskStopInfo(SExecTaskInfo* pTaskInfo, SExchangeOpStopInfo* pInfo); -int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn_t searchFn, TSKEY ekey, int32_t pos, - int32_t order, int64_t* pData); - -#ifdef __cplusplus -} -#endif - -#endif // TDENGINE_EXECUTORIMPL_H diff --git a/source/libs/executor/inc/operator.h b/source/libs/executor/inc/operator.h new file mode 100644 index 0000000000000000000000000000000000000000..632b817a0754d2d8d4482200df5ac28e18bcf02c --- /dev/null +++ b/source/libs/executor/inc/operator.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_OPERATOR_H +#define TDENGINE_OPERATOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SOperatorCostInfo { + double openCost; + double totalCost; +} SOperatorCostInfo; + +struct SOperatorInfo; + +typedef int32_t (*__optr_encode_fn_t)(struct SOperatorInfo* pOperator, char** result, int32_t* length); +typedef int32_t (*__optr_decode_fn_t)(struct SOperatorInfo* pOperator, char* result); + +typedef int32_t (*__optr_open_fn_t)(struct SOperatorInfo* pOptr); +typedef SSDataBlock* (*__optr_fn_t)(struct SOperatorInfo* pOptr); +typedef void (*__optr_close_fn_t)(void* param); +typedef int32_t (*__optr_explain_fn_t)(struct SOperatorInfo* pOptr, void** pOptrExplain, uint32_t* len); +typedef int32_t (*__optr_reqBuf_fn_t)(struct SOperatorInfo* pOptr); + +typedef struct SOperatorFpSet { + __optr_open_fn_t _openFn; // DO NOT invoke this function directly + __optr_fn_t getNextFn; + __optr_fn_t cleanupFn; // call this function to release the allocated resources ASAP + __optr_close_fn_t closeFn; + __optr_reqBuf_fn_t reqBufFn; // total used buffer for blocking operator + __optr_encode_fn_t encodeResultRow; + __optr_decode_fn_t decodeResultRow; + __optr_explain_fn_t getExplainFn; +} SOperatorFpSet; + +enum { + OP_NOT_OPENED = 0x0, + OP_OPENED = 0x1, + OP_RES_TO_RETURN = 0x5, + OP_EXEC_DONE = 0x9, +}; + +typedef struct SOperatorInfo { + uint16_t operatorType; + int16_t resultDataBlockId; + bool blocking; // block operator or not + uint8_t status; // denote if current operator is completed + char* name; // name, for debug purpose + void* info; // extension attribution + SExprSupp exprSupp; + SExecTaskInfo* pTaskInfo; + SOperatorCostInfo cost; + SResultInfo resultInfo; + struct SOperatorInfo** pDownstream; // downstram pointer list + int32_t numOfDownstream; // number of downstream. The value is always ONE expect for join operator + SOperatorFpSet fpSet; +} SOperatorInfo; + +// operator creater functions +// clang-format off +SOperatorInfo* createExchangeOperatorInfo(void* pTransporter, SExchangePhysiNode* pExNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle, STableListInfo* pTableList, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle, STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* pPhyNode, STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNode* pScanPhyNode, const char* pUser, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createTableCountScanOperatorInfo(SReadHandle* handle, STableCountScanPhysiNode* pNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* pNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createIndefinitOutputOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createProjectOperatorInfo(SOperatorInfo* downstream, SProjectPhysiNode* pProjPhyNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pSortNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createMultiwayMergeOperatorInfo(SOperatorInfo** dowStreams, size_t numStreams, SMergePhysiNode* pMergePhysiNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createCacherowsScanOperator(SLastRowScanPhysiNode* pTableScanNode, SReadHandle* readHandle, STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createMergeIntervalOperatorInfo(SOperatorInfo* downstream, SMergeIntervalPhysiNode* pIntervalPhyNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createMergeAlignedIntervalOperatorInfo(SOperatorInfo* downstream, SMergeAlignedIntervalPhysiNode* pNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, int32_t numOfChild); + +SOperatorInfo* createSessionAggOperatorInfo(SOperatorInfo* downstream, SSessionWinodwPhysiNode* pSessionNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* pAggNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createDataBlockInfoScanOperator(SReadHandle* readHandle, SBlockDistScanPhysiNode* pBlockScanNode, STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* pTableScanNode, SNode* pTagCond, STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createRawScanOperatorInfo(SReadHandle* pHandle, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createFillOperatorInfo(SOperatorInfo* downstream, SFillPhysiNode* pPhyFillNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createStatewindowOperatorInfo(SOperatorInfo* downstream, SStateWinodwPhysiNode* pStateNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createPartitionOperatorInfo(SOperatorInfo* downstream, SPartitionPhysiNode* pPartNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStreamPartitionPhysiNode* pPartNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDownstream, SSortMergeJoinPhysiNode* pJoinNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createStreamFinalSessionAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, int32_t numOfChild); + +SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createStreamFillOperatorInfo(SOperatorInfo* downstream, SStreamFillPhysiNode* pPhyFillNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createGroupSortOperatorInfo(SOperatorInfo* downstream, SGroupSortPhysiNode* pSortPhyNode, SExecTaskInfo* pTaskInfo); + +SOperatorInfo* createEventwindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* physiNode, SExecTaskInfo* pTaskInfo); +// clang-format on + +SOperatorFpSet createOperatorFpSet(__optr_open_fn_t openFn, __optr_fn_t nextFn, __optr_fn_t cleanup, + __optr_close_fn_t closeFn, __optr_reqBuf_fn_t reqBufFn, __optr_explain_fn_t explain); +int32_t optrDummyOpenFn(SOperatorInfo* pOperator); +int32_t appendDownstream(SOperatorInfo* p, SOperatorInfo** pDownstream, int32_t num); +void setOperatorCompleted(SOperatorInfo* pOperator); +void setOperatorInfo(SOperatorInfo* pOperator, const char* name, int32_t type, bool blocking, int32_t status, + void* pInfo, SExecTaskInfo* pTaskInfo); +int32_t optrDefaultBufFn(SOperatorInfo* pOperator); + +SOperatorInfo* createOperator(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle, SNode* pTagCond, + SNode* pTagIndexCond, const char* pUser, const char* dbname); +void destroyOperator(SOperatorInfo* pOperator); + +SOperatorInfo* extractOperatorInTree(SOperatorInfo* pOperator, int32_t type, const char* id); +int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scanFlag, bool inheritUsOrder); +int32_t stopTableScanOperator(SOperatorInfo* pOperator, const char* pIdStr); +int32_t getOperatorExplainExecInfo(struct SOperatorInfo* operatorInfo, SArray* pExecInfoList); + +#ifdef __cplusplus +} +#endif + +#endif // TDENGINE_OPERATOR_H \ No newline at end of file diff --git a/source/libs/executor/inc/querytask.h b/source/libs/executor/inc/querytask.h new file mode 100644 index 0000000000000000000000000000000000000000..37c93fef5c3fdad15ac2d6855e3d0b7ca323274c --- /dev/null +++ b/source/libs/executor/inc/querytask.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_QUERYTASK_H +#define TDENGINE_QUERYTASK_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define GET_TASKID(_t) (((SExecTaskInfo*)(_t))->id.str) + +enum { + // when this task starts to execute, this status will set + TASK_NOT_COMPLETED = 0x1u, + + /* Task is over + * 1. this status is used in one row result query process, e.g., count/sum/first/last/ avg...etc. + * 2. when all data within queried time window, it is also denoted as query_completed + */ + TASK_COMPLETED = 0x2u, +}; + +typedef struct STaskIdInfo { + uint64_t queryId; // this is also a request id + uint64_t subplanId; + uint64_t templateId; + char* str; + int32_t vgId; +} STaskIdInfo; + +typedef struct STaskCostInfo { + int64_t created; + int64_t start; + uint64_t elapsedTime; + double extractListTime; + double groupIdMapTime; + SFileBlockLoadRecorder* pRecoder; +} STaskCostInfo; + +typedef struct STaskStopInfo { + SRWLatch lock; + SArray* pStopInfo; +} STaskStopInfo; + +typedef struct { + STqOffsetVal currentOffset; // for tmq + SMqMetaRsp metaRsp; // for tmq fetching meta + int64_t snapshotVer; +// SPackedData submit; // todo remove it + SSchemaWrapper* schema; + char tbName[TSDB_TABLE_NAME_LEN]; // this is the current scan table: todo refactor + int8_t recoverStep; + int8_t recoverScanFinished; + SQueryTableDataCond tableCond; + int64_t fillHistoryVer1; + int64_t fillHistoryVer2; + SStreamState* pState; + int64_t dataVersion; + int64_t checkPointId; +} SStreamTaskInfo; + +struct SExecTaskInfo { + STaskIdInfo id; + uint32_t status; + STimeWindow window; + STaskCostInfo cost; + int64_t owner; // if it is in execution + int32_t code; + int32_t qbufQuota; // total available buffer (in KB) during execution query + int64_t version; // used for stream to record wal version, why not move to sschemainfo + SStreamTaskInfo streamInfo; + SSchemaInfo schemaInfo; + const char* sql; // query sql string + jmp_buf env; // jump to this position when error happens. + EOPTR_EXEC_MODEL execModel; // operator execution model [batch model|stream model] + SSubplan* pSubplan; + struct SOperatorInfo* pRoot; + SLocalFetch localFetch; + SArray* pResultBlockList; // result block list + STaskStopInfo stopInfo; + SRWLatch lock; // secure the access of STableListInfo +}; + +void buildTaskId(uint64_t taskId, uint64_t queryId, char* dst); +SExecTaskInfo* doCreateTask(uint64_t queryId, uint64_t taskId, int32_t vgId, EOPTR_EXEC_MODEL model); +void doDestroyTask(SExecTaskInfo* pTaskInfo); +bool isTaskKilled(SExecTaskInfo* pTaskInfo); +void setTaskKilled(SExecTaskInfo* pTaskInfo, int32_t rspCode); +void setTaskStatus(SExecTaskInfo* pTaskInfo, int8_t status); +int32_t createExecTaskInfo(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SReadHandle* pHandle, uint64_t taskId, + int32_t vgId, char* sql, EOPTR_EXEC_MODEL model); +int32_t qAppendTaskStopInfo(SExecTaskInfo* pTaskInfo, SExchangeOpStopInfo* pInfo); +SArray* getTableListInfo(const SExecTaskInfo* pTaskInfo); + +#ifdef __cplusplus +} +#endif + +#endif // TDENGINE_QUERYTASK_H diff --git a/source/libs/executor/inc/tfill.h b/source/libs/executor/inc/tfill.h index fad4059515f386ca94ce2c97985184ff4b95f744..5fd75f9b99d004be68b369172668697bfa6fa9a6 100644 --- a/source/libs/executor/inc/tfill.h +++ b/source/libs/executor/inc/tfill.h @@ -30,6 +30,7 @@ extern "C" { struct SSDataBlock; typedef struct SFillColInfo { + int32_t numOfFillExpr; SExprInfo* pExpr; bool notFillCol; // denote if this column needs fill operation SVariant fillVal; @@ -92,8 +93,8 @@ typedef struct SResultRowData { typedef struct SStreamFillLinearInfo { TSKEY nextEnd; - SArray* pDeltaVal; // double. value for Fill(linear). - SArray* pNextDeltaVal; // double. value for Fill(linear). + SArray* pEndPoints; + SArray* pNextEndPoints; int64_t winIndex; bool hasNext; } SStreamFillLinearInfo; diff --git a/source/libs/executor/inc/tsort.h b/source/libs/executor/inc/tsort.h index cff568aebc0c26fb2e9c22c7a027fa9edb4dd81a..d51a24bb43253e09d6ab21e6a1785d6ef6b5e5ff 100644 --- a/source/libs/executor/inc/tsort.h +++ b/source/libs/executor/inc/tsort.h @@ -44,7 +44,8 @@ typedef struct SSortSource { void* param; bool onlyRef; }; - + int64_t fetchUs; + int64_t fetchNum; } SSortSource; typedef struct SMsortComparParam { diff --git a/source/libs/executor/src/aggregateoperator.c b/source/libs/executor/src/aggregateoperator.c new file mode 100644 index 0000000000000000000000000000000000000000..9b463a3dee630d089750f424c572163f532d500e --- /dev/null +++ b/source/libs/executor/src/aggregateoperator.c @@ -0,0 +1,570 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "filter.h" +#include "function.h" +#include "os.h" +#include "querynodes.h" +#include "tfill.h" +#include "tname.h" + +#include "executorInt.h" +#include "index.h" +#include "operator.h" +#include "query.h" +#include "querytask.h" +#include "tcompare.h" +#include "tdatablock.h" +#include "tglobal.h" +#include "thash.h" +#include "ttypes.h" + +typedef struct { + bool hasAgg; + int32_t numOfRows; + int32_t startOffset; +} SFunctionCtxStatus; + +typedef struct SAggOperatorInfo { + SOptrBasicInfo binfo; + SAggSupporter aggSup; + STableQueryInfo* current; + uint64_t groupId; + SGroupResInfo groupResInfo; + SExprSupp scalarExprSup; + bool groupKeyOptimized; +} SAggOperatorInfo; + +static void destroyAggOperatorInfo(void* param); +static void setExecutionContext(SOperatorInfo* pOperator, int32_t numOfOutput, uint64_t groupId); + +static int32_t createDataBlockForEmptyInput(SOperatorInfo* pOperator, SSDataBlock** ppBlock); +static void destroyDataBlockForEmptyInput(bool blockAllocated, SSDataBlock** ppBlock); + +static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator); +static int32_t doAggregateImpl(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx); +static SSDataBlock* getAggregateResult(SOperatorInfo* pOperator); + +static int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, size_t keyBufSize, + const char* pKey); + +static int32_t addNewResultRowBuf(SResultRow* pWindowRes, SDiskbasedBuf* pResultBuf, uint32_t size); + +static void doSetTableGroupOutputBuf(SOperatorInfo* pOperator, int32_t numOfOutput, uint64_t groupId); + +static void functionCtxSave(SqlFunctionCtx* pCtx, SFunctionCtxStatus* pStatus); +static void functionCtxRestore(SqlFunctionCtx* pCtx, SFunctionCtxStatus* pStatus); + +SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* pAggNode, + SExecTaskInfo* pTaskInfo) { + SAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SAggOperatorInfo)); + SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); + if (pInfo == NULL || pOperator == NULL) { + goto _error; + } + + SSDataBlock* pResBlock = createDataBlockFromDescNode(pAggNode->node.pOutputDataBlockDesc); + initBasicInfo(&pInfo->binfo, pResBlock); + + size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES; + initResultSizeInfo(&pOperator->resultInfo, 4096); + + int32_t num = 0; + SExprInfo* pExprInfo = createExprInfo(pAggNode->pAggFuncs, pAggNode->pGroupKeys, &num); + int32_t code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str, + pTaskInfo->streamInfo.pState); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + int32_t numOfScalarExpr = 0; + SExprInfo* pScalarExprInfo = NULL; + if (pAggNode->pExprs != NULL) { + pScalarExprInfo = createExprInfo(pAggNode->pExprs, NULL, &numOfScalarExpr); + } + + code = initExprSupp(&pInfo->scalarExprSup, pScalarExprInfo, numOfScalarExpr); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + code = filterInitFromNode((SNode*)pAggNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + pInfo->binfo.mergeResultBlock = pAggNode->mergeDataBlock; + pInfo->groupKeyOptimized = pAggNode->groupKeyOptimized; + pInfo->groupId = UINT64_MAX; + + setOperatorInfo(pOperator, "TableAggregate", QUERY_NODE_PHYSICAL_PLAN_HASH_AGG, true, OP_NOT_OPENED, pInfo, + pTaskInfo); + pOperator->fpSet = createOperatorFpSet(doOpenAggregateOptr, getAggregateResult, NULL, destroyAggOperatorInfo, + optrDefaultBufFn, NULL); + + if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) { + STableScanInfo* pTableScanInfo = downstream->info; + pTableScanInfo->base.pdInfo.pExprSup = &pOperator->exprSupp; + pTableScanInfo->base.pdInfo.pAggSup = &pInfo->aggSup; + } + + code = appendDownstream(pOperator, &downstream, 1); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + return pOperator; + + _error: + if (pInfo != NULL) { + destroyAggOperatorInfo(pInfo); + } + + if (pOperator != NULL) { + cleanupExprSupp(&pOperator->exprSupp); + } + + taosMemoryFreeClear(pOperator); + pTaskInfo->code = code; + return NULL; +} + +void destroyAggOperatorInfo(void* param) { + SAggOperatorInfo* pInfo = (SAggOperatorInfo*)param; + cleanupBasicInfo(&pInfo->binfo); + + cleanupAggSup(&pInfo->aggSup); + cleanupExprSupp(&pInfo->scalarExprSup); + cleanupGroupResInfo(&pInfo->groupResInfo); + taosMemoryFreeClear(param); +} + +// this is a blocking operator +int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) { + if (OPTR_IS_OPENED(pOperator)) { + return TSDB_CODE_SUCCESS; + } + + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + SAggOperatorInfo* pAggInfo = pOperator->info; + + SExprSupp* pSup = &pOperator->exprSupp; + SOperatorInfo* downstream = pOperator->pDownstream[0]; + + int64_t st = taosGetTimestampUs(); + + int32_t order = TSDB_ORDER_ASC; + int32_t scanFlag = MAIN_SCAN; + + bool hasValidBlock = false; + + while (1) { + bool blockAllocated = false; + SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); + if (pBlock == NULL) { + if (!hasValidBlock) { + createDataBlockForEmptyInput(pOperator, &pBlock); + if (pBlock == NULL) { + break; + } + blockAllocated = true; + } else { + break; + } + } + hasValidBlock = true; + + int32_t code = getTableScanInfo(pOperator, &order, &scanFlag, false); + if (code != TSDB_CODE_SUCCESS) { + destroyDataBlockForEmptyInput(blockAllocated, &pBlock); + T_LONG_JMP(pTaskInfo->env, code); + } + + // there is an scalar expression that needs to be calculated before apply the group aggregation. + if (pAggInfo->scalarExprSup.pExprInfo != NULL && !blockAllocated) { + SExprSupp* pSup1 = &pAggInfo->scalarExprSup; + code = projectApplyFunctions(pSup1->pExprInfo, pBlock, pBlock, pSup1->pCtx, pSup1->numOfExprs, NULL); + if (code != TSDB_CODE_SUCCESS) { + destroyDataBlockForEmptyInput(blockAllocated, &pBlock); + T_LONG_JMP(pTaskInfo->env, code); + } + } + + // the pDataBlock are always the same one, no need to call this again + setExecutionContext(pOperator, pOperator->exprSupp.numOfExprs, pBlock->info.id.groupId); + setInputDataBlock(pSup, pBlock, order, scanFlag, true); + code = doAggregateImpl(pOperator, pSup->pCtx); + if (code != 0) { + destroyDataBlockForEmptyInput(blockAllocated, &pBlock); + T_LONG_JMP(pTaskInfo->env, code); + } + + destroyDataBlockForEmptyInput(blockAllocated, &pBlock); + } + + // the downstream operator may return with error code, so let's check the code before generating results. + if (pTaskInfo->code != TSDB_CODE_SUCCESS) { + T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); + } + + initGroupedResultInfo(&pAggInfo->groupResInfo, pAggInfo->aggSup.pResultRowHashTable, 0); + OPTR_SET_OPENED(pOperator); + + pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0; + return pTaskInfo->code; +} + +SSDataBlock* getAggregateResult(SOperatorInfo* pOperator) { + SAggOperatorInfo* pAggInfo = pOperator->info; + SOptrBasicInfo* pInfo = &pAggInfo->binfo; + + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } + + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + pTaskInfo->code = pOperator->fpSet._openFn(pOperator); + if (pTaskInfo->code != TSDB_CODE_SUCCESS) { + setOperatorCompleted(pOperator); + return NULL; + } + + blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity); + while (1) { + doBuildResultDatablock(pOperator, pInfo, &pAggInfo->groupResInfo, pAggInfo->aggSup.pResultBuf); + doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); + + if (!hasRemainResults(&pAggInfo->groupResInfo)) { + setOperatorCompleted(pOperator); + break; + } + + if (pInfo->pRes->info.rows > 0) { + break; + } + } + + size_t rows = blockDataGetNumOfRows(pInfo->pRes); + pOperator->resultInfo.totalRows += rows; + + return (rows == 0) ? NULL : pInfo->pRes; +} + +int32_t doAggregateImpl(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx) { + for (int32_t k = 0; k < pOperator->exprSupp.numOfExprs; ++k) { + if (functionNeedToExecute(&pCtx[k])) { + // todo add a dummy funtion to avoid process check + if (pCtx[k].fpSet.process == NULL) { + continue; + } + + int32_t code = pCtx[k].fpSet.process(&pCtx[k]); + if (code != TSDB_CODE_SUCCESS) { + qError("%s aggregate function error happens, code: %s", GET_TASKID(pOperator->pTaskInfo), tstrerror(code)); + return code; + } + } + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t createDataBlockForEmptyInput(SOperatorInfo* pOperator, SSDataBlock** ppBlock) { + if (!tsCountAlwaysReturnValue) { + return TSDB_CODE_SUCCESS; + } + + SAggOperatorInfo* pAggInfo = pOperator->info; + if (pAggInfo->groupKeyOptimized) { + return TSDB_CODE_SUCCESS; + } + + SOperatorInfo* downstream = pOperator->pDownstream[0]; + if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_PARTITION || + (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN && + ((STableScanInfo*)downstream->info)->hasGroupByTag == true)) { + return TSDB_CODE_SUCCESS; + } + + SqlFunctionCtx* pCtx = pOperator->exprSupp.pCtx; + bool hasCountFunc = false; + + for (int32_t i = 0; i < pOperator->exprSupp.numOfExprs; ++i) { + const char* pName = pCtx[i].pExpr->pExpr->_function.functionName; + if ((strcmp(pName, "count") == 0) || (strcmp(pName, "hyperloglog") == 0) || + (strcmp(pName, "_hyperloglog_partial") == 0) || (strcmp(pName, "_hyperloglog_merge") == 0)) { + hasCountFunc = true; + break; + } + } + + if (!hasCountFunc) { + return TSDB_CODE_SUCCESS; + } + + SSDataBlock* pBlock = createDataBlock(); + pBlock->info.rows = 1; + pBlock->info.capacity = 0; + + for (int32_t i = 0; i < pOperator->exprSupp.numOfExprs; ++i) { + SColumnInfoData colInfo = {0}; + colInfo.hasNull = true; + colInfo.info.type = TSDB_DATA_TYPE_NULL; + colInfo.info.bytes = 1; + + SExprInfo* pOneExpr = &pOperator->exprSupp.pExprInfo[i]; + for (int32_t j = 0; j < pOneExpr->base.numOfParams; ++j) { + SFunctParam* pFuncParam = &pOneExpr->base.pParam[j]; + if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) { + int32_t slotId = pFuncParam->pCol->slotId; + int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock); + if (slotId >= numOfCols) { + taosArrayEnsureCap(pBlock->pDataBlock, slotId + 1); + for (int32_t k = numOfCols; k < slotId + 1; ++k) { + taosArrayPush(pBlock->pDataBlock, &colInfo); + } + } + } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) { + // do nothing + } + } + } + + blockDataEnsureCapacity(pBlock, pBlock->info.rows); + *ppBlock = pBlock; + + return TSDB_CODE_SUCCESS; +} + +void destroyDataBlockForEmptyInput(bool blockAllocated, SSDataBlock** ppBlock) { + if (!blockAllocated) { + return; + } + + blockDataDestroy(*ppBlock); + *ppBlock = NULL; +} + +void setExecutionContext(SOperatorInfo* pOperator, int32_t numOfOutput, uint64_t groupId) { + SAggOperatorInfo* pAggInfo = pOperator->info; + if (pAggInfo->groupId != UINT64_MAX && pAggInfo->groupId == groupId) { + return; + } + + doSetTableGroupOutputBuf(pOperator, numOfOutput, groupId); + + // record the current active group id + pAggInfo->groupId = groupId; +} + +void doSetTableGroupOutputBuf(SOperatorInfo* pOperator, int32_t numOfOutput, uint64_t groupId) { + // for simple group by query without interval, all the tables belong to one group result. + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + SAggOperatorInfo* pAggInfo = pOperator->info; + + SResultRowInfo* pResultRowInfo = &pAggInfo->binfo.resultRowInfo; + SqlFunctionCtx* pCtx = pOperator->exprSupp.pCtx; + int32_t* rowEntryInfoOffset = pOperator->exprSupp.rowEntryInfoOffset; + + SResultRow* pResultRow = doSetResultOutBufByKey(pAggInfo->aggSup.pResultBuf, pResultRowInfo, (char*)&groupId, + sizeof(groupId), true, groupId, pTaskInfo, false, &pAggInfo->aggSup, true); + /* + * not assign result buffer yet, add new result buffer + * all group belong to one result set, and each group result has different group id so set the id to be one + */ + if (pResultRow->pageId == -1) { + int32_t ret = addNewResultRowBuf(pResultRow, pAggInfo->aggSup.pResultBuf, pAggInfo->binfo.pRes->info.rowSize); + if (ret != TSDB_CODE_SUCCESS) { + T_LONG_JMP(pTaskInfo->env, terrno); + } + } + + setResultRowInitCtx(pResultRow, pCtx, numOfOutput, rowEntryInfoOffset); +} + +// a new buffer page for each table. Needs to opt this design +int32_t addNewResultRowBuf(SResultRow* pWindowRes, SDiskbasedBuf* pResultBuf, uint32_t size) { + if (pWindowRes->pageId != -1) { + return 0; + } + + SFilePage* pData = NULL; + + // in the first scan, new space needed for results + int32_t pageId = -1; + SArray* list = getDataBufPagesIdList(pResultBuf); + + if (taosArrayGetSize(list) == 0) { + pData = getNewBufPage(pResultBuf, &pageId); + pData->num = sizeof(SFilePage); + } else { + SPageInfo* pi = getLastPageInfo(list); + pData = getBufPage(pResultBuf, getPageId(pi)); + if (pData == NULL) { + qError("failed to get buffer, code:%s", tstrerror(terrno)); + return terrno; + } + + pageId = getPageId(pi); + + if (pData->num + size > getBufPageSize(pResultBuf)) { + // release current page first, and prepare the next one + releaseBufPageInfo(pResultBuf, pi); + + pData = getNewBufPage(pResultBuf, &pageId); + if (pData != NULL) { + pData->num = sizeof(SFilePage); + } + } + } + + if (pData == NULL) { + return -1; + } + + // set the number of rows in current disk page + if (pWindowRes->pageId == -1) { // not allocated yet, allocate new buffer + pWindowRes->pageId = pageId; + pWindowRes->offset = (int32_t)pData->num; + + pData->num += size; + } + + return 0; +} + +int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, size_t keyBufSize, + const char* pKey) { + int32_t code = 0; + // _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); + + pAggSup->currentPageId = -1; + pAggSup->resultRowSize = getResultRowSize(pCtx, numOfOutput); + pAggSup->keyBuf = taosMemoryCalloc(1, keyBufSize + POINTER_BYTES + sizeof(int64_t)); + pAggSup->pResultRowHashTable = tSimpleHashInit(100, taosFastHash); + + if (pAggSup->keyBuf == NULL || pAggSup->pResultRowHashTable == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + uint32_t defaultPgsz = 0; + uint32_t defaultBufsz = 0; + getBufferPgSize(pAggSup->resultRowSize, &defaultPgsz, &defaultBufsz); + + if (!osTempSpaceAvailable()) { + code = TSDB_CODE_NO_AVAIL_DISK; + qError("Init stream agg supporter failed since %s, %s", terrstr(code), pKey); + return code; + } + + code = createDiskbasedBuf(&pAggSup->pResultBuf, defaultPgsz, defaultBufsz, pKey, tsTempDir); + if (code != TSDB_CODE_SUCCESS) { + qError("Create agg result buf failed since %s, %s", tstrerror(code), pKey); + return code; + } + + return code; +} + +void cleanupAggSup(SAggSupporter* pAggSup) { + taosMemoryFreeClear(pAggSup->keyBuf); + tSimpleHashCleanup(pAggSup->pResultRowHashTable); + destroyDiskbasedBuf(pAggSup->pResultBuf); +} + +int32_t initAggSup(SExprSupp* pSup, SAggSupporter* pAggSup, SExprInfo* pExprInfo, int32_t numOfCols, size_t keyBufSize, + const char* pkey, void* pState) { + int32_t code = initExprSupp(pSup, pExprInfo, numOfCols); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + code = doInitAggInfoSup(pAggSup, pSup->pCtx, numOfCols, keyBufSize, pkey); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + for (int32_t i = 0; i < numOfCols; ++i) { + if (pState) { + pSup->pCtx[i].saveHandle.pBuf = NULL; + pSup->pCtx[i].saveHandle.pState = pState; + pSup->pCtx[i].exprIdx = i; + } else { + pSup->pCtx[i].saveHandle.pBuf = pAggSup->pResultBuf; + } + } + + return TSDB_CODE_SUCCESS; +} + +void applyAggFunctionOnPartialTuples(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, SColumnInfoData* pTimeWindowData, + int32_t offset, int32_t forwardStep, int32_t numOfTotal, int32_t numOfOutput) { + for (int32_t k = 0; k < numOfOutput; ++k) { + // keep it temporarily + SFunctionCtxStatus status = {0}; + functionCtxSave(&pCtx[k], &status); + + pCtx[k].input.startRowIndex = offset; + pCtx[k].input.numOfRows = forwardStep; + + // not a whole block involved in query processing, statistics data can not be used + // NOTE: the original value of isSet have been changed here + if (pCtx[k].input.colDataSMAIsSet && forwardStep < numOfTotal) { + pCtx[k].input.colDataSMAIsSet = false; + } + + if (pCtx[k].isPseudoFunc) { + SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pCtx[k]); + + char* p = GET_ROWCELL_INTERBUF(pEntryInfo); + + SColumnInfoData idata = {0}; + idata.info.type = TSDB_DATA_TYPE_BIGINT; + idata.info.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; + idata.pData = p; + + SScalarParam out = {.columnData = &idata}; + SScalarParam tw = {.numOfRows = 5, .columnData = pTimeWindowData}; + pCtx[k].sfp.process(&tw, 1, &out); + pEntryInfo->numOfRes = 1; + } else { + int32_t code = TSDB_CODE_SUCCESS; + if (functionNeedToExecute(&pCtx[k]) && pCtx[k].fpSet.process != NULL) { + code = pCtx[k].fpSet.process(&pCtx[k]); + + if (code != TSDB_CODE_SUCCESS) { + qError("%s apply functions error, code: %s", GET_TASKID(taskInfo), tstrerror(code)); + taskInfo->code = code; + T_LONG_JMP(taskInfo->env, code); + } + } + + // restore it + functionCtxRestore(&pCtx[k], &status); + } + } +} + +void functionCtxSave(SqlFunctionCtx* pCtx, SFunctionCtxStatus* pStatus) { + pStatus->hasAgg = pCtx->input.colDataSMAIsSet; + pStatus->numOfRows = pCtx->input.numOfRows; + pStatus->startOffset = pCtx->input.startRowIndex; +} + +void functionCtxRestore(SqlFunctionCtx* pCtx, SFunctionCtxStatus* pStatus) { + pCtx->input.colDataSMAIsSet = pStatus->hasAgg; + pCtx->input.numOfRows = pStatus->numOfRows; + pCtx->input.startRowIndex = pStatus->startOffset; +} diff --git a/source/libs/executor/src/cachescanoperator.c b/source/libs/executor/src/cachescanoperator.c index 60e4e85fb8a79ae280875484a1875a6f77bddf36..fad1c55b3dd4b9681c6ee7fd387e01fa54bd954a 100644 --- a/source/libs/executor/src/cachescanoperator.c +++ b/source/libs/executor/src/cachescanoperator.c @@ -20,7 +20,9 @@ #include "tdatablock.h" #include "tmsg.h" -#include "executorimpl.h" +#include "executorInt.h" +#include "operator.h" +#include "querytask.h" #include "tcompare.h" #include "thash.h" #include "ttypes.h" @@ -37,6 +39,7 @@ typedef struct SCacheRowsScanInfo { SSDataBlock* pBufferredRes; SArray* pUidList; int32_t indexOfBufferedRes; + STableListInfo* pTableList; } SCacheRowsScanInfo; static SSDataBlock* doScanCache(SOperatorInfo* pOperator); @@ -47,15 +50,17 @@ static int32_t removeRedundantTsCol(SLastRowScanPhysiNode* pScanNode, SColM #define SCAN_ROW_TYPE(_t) ((_t)? CACHESCAN_RETRIEVE_LAST : CACHESCAN_RETRIEVE_LAST_ROW) SOperatorInfo* createCacherowsScanOperator(SLastRowScanPhysiNode* pScanNode, SReadHandle* readHandle, - SExecTaskInfo* pTaskInfo) { + STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo) { int32_t code = TSDB_CODE_SUCCESS; SCacheRowsScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SCacheRowsScanInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { code = TSDB_CODE_OUT_OF_MEMORY; + tableListDestroy(pTableListInfo); goto _error; } + pInfo->pTableList = pTableListInfo; pInfo->readHandle = *readHandle; SDataBlockDescNode* pDescNode = pScanNode->scan.node.pOutputDataBlockDesc; @@ -75,20 +80,18 @@ SOperatorInfo* createCacherowsScanOperator(SLastRowScanPhysiNode* pScanNode, SRe goto _error; } - STableListInfo* pTableList = pTaskInfo->pTableInfoList; - - int32_t totalTables = tableListGetSize(pTableList); + int32_t totalTables = tableListGetSize(pTableListInfo); int32_t capacity = 0; pInfo->pUidList = taosArrayInit(4, sizeof(int64_t)); // partition by tbname - if (oneTableForEachGroup(pTableList) || (totalTables == 1)) { + if (oneTableForEachGroup(pTableListInfo) || (totalTables == 1)) { pInfo->retrieveType = CACHESCAN_RETRIEVE_TYPE_ALL | SCAN_ROW_TYPE(pScanNode->ignoreNull); - STableKeyInfo* pList = tableListGetInfo(pTableList, 0); + STableKeyInfo* pList = tableListGetInfo(pTableListInfo, 0); - uint64_t suid = tableListGetSuid(pTableList); + uint64_t suid = tableListGetSuid(pTableListInfo); code = tsdbCacherowsReaderOpen(pInfo->readHandle.vnode, pInfo->retrieveType, pList, totalTables, taosArrayGetSize(pInfo->matchInfo.pList), suid, &pInfo->pLastrowReader, pTaskInfo->id.str); if (code != TSDB_CODE_SUCCESS) { @@ -136,7 +139,7 @@ SSDataBlock* doScanCache(SOperatorInfo* pOperator) { SCacheRowsScanInfo* pInfo = pOperator->info; SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - STableListInfo* pTableList = pTaskInfo->pTableInfoList; + STableListInfo* pTableList = pInfo->pTableList; uint64_t suid = tableListGetSuid(pTableList); int32_t size = tableListGetSize(pTableList); @@ -182,10 +185,10 @@ SSDataBlock* doScanCache(SOperatorInfo* pOperator) { SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, slotId); if (colDataIsNull_s(pSrc, pInfo->indexOfBufferedRes)) { - colDataAppendNULL(pDst, 0); + colDataSetNULL(pDst, 0); } else { char* p = colDataGetData(pSrc, pInfo->indexOfBufferedRes); - colDataAppend(pDst, 0, p, false); + colDataSetVal(pDst, 0, p, false); } } @@ -223,13 +226,17 @@ SSDataBlock* doScanCache(SOperatorInfo* pOperator) { T_LONG_JMP(pTaskInfo->env, code); } - code = tsdbCacherowsReaderOpen(pInfo->readHandle.vnode, pInfo->retrieveType, pList, num, - taosArrayGetSize(pInfo->matchInfo.pList), suid, &pInfo->pLastrowReader, - pTaskInfo->id.str); - if (code != TSDB_CODE_SUCCESS) { - pInfo->currentGroupIndex += 1; - taosArrayClear(pInfo->pUidList); - continue; + if (NULL == pInfo->pLastrowReader) { + code = tsdbCacherowsReaderOpen(pInfo->readHandle.vnode, pInfo->retrieveType, pList, num, + taosArrayGetSize(pInfo->matchInfo.pList), suid, &pInfo->pLastrowReader, + pTaskInfo->id.str); + if (code != TSDB_CODE_SUCCESS) { + pInfo->currentGroupIndex += 1; + taosArrayClear(pInfo->pUidList); + continue; + } + } else { + tsdbReuseCacherowsReader(pInfo->pLastrowReader, pList, num); } taosArrayClear(pInfo->pUidList); @@ -262,13 +269,14 @@ SSDataBlock* doScanCache(SOperatorInfo* pOperator) { } } - pInfo->pLastrowReader = tsdbCacherowsReaderClose(pInfo->pLastrowReader); + //pInfo->pLastrowReader = tsdbCacherowsReaderClose(pInfo->pLastrowReader); return pInfo->pRes; } else { - pInfo->pLastrowReader = tsdbCacherowsReaderClose(pInfo->pLastrowReader); + //pInfo->pLastrowReader = tsdbCacherowsReaderClose(pInfo->pLastrowReader); } } + pInfo->pLastrowReader = tsdbCacherowsReaderClose(pInfo->pLastrowReader); setOperatorCompleted(pOperator); return NULL; } @@ -281,6 +289,7 @@ void destroyCacheScanOperator(void* param) { taosMemoryFree(pInfo->pSlotIds); taosArrayDestroy(pInfo->pUidList); taosArrayDestroy(pInfo->matchInfo.pList); + tableListDestroy(pInfo->pTableList); if (pInfo->pLastrowReader != NULL) { pInfo->pLastrowReader = tsdbCacherowsReaderClose(pInfo->pLastrowReader); diff --git a/source/libs/executor/src/dataDeleter.c b/source/libs/executor/src/dataDeleter.c index a8051ea7c3eb294e7beb9ce6b5a23be601e635ef..11074b0e94b183612ec58004581ed696d5febf05 100644 --- a/source/libs/executor/src/dataDeleter.c +++ b/source/libs/executor/src/dataDeleter.c @@ -15,7 +15,7 @@ #include "dataSinkInt.h" #include "dataSinkMgt.h" -#include "executorimpl.h" +#include "executorInt.h" #include "planner.h" #include "tcompression.h" #include "tdatablock.h" @@ -62,9 +62,6 @@ static void toDataCacheEntry(SDataDeleterHandle* pHandle, const SInputData* pInp pEntry->numOfCols = taosArrayGetSize(pInput->pData->pDataBlock); pEntry->dataLen = sizeof(SDeleterRes); -// ASSERT(1 == pEntry->numOfRows); -// ASSERT(3 == pEntry->numOfCols); - pBuf->useSize = sizeof(SDataCacheEntry); SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pInput->pData->pDataBlock, 0); @@ -142,7 +139,7 @@ static int32_t putDataBlock(SDataSinkHandle* pHandle, const SInputData* pInput, taosFreeQitem(pBuf); return TSDB_CODE_OUT_OF_MEMORY; } - + toDataCacheEntry(pDeleter, pInput, pBuf); taosWriteQitem(pDeleter->pDataBlocks, pBuf); *pContinue = (DS_BUF_LOW == updateStatus(pDeleter) ? true : false); @@ -167,8 +164,10 @@ static void getDataLength(SDataSinkHandle* pHandle, int64_t* pLen, bool* pQueryE SDataDeleterBuf* pBuf = NULL; taosReadQitem(pDeleter->pDataBlocks, (void**)&pBuf); - memcpy(&pDeleter->nextOutput, pBuf, sizeof(SDataDeleterBuf)); - taosFreeQitem(pBuf); + if (pBuf != NULL) { + memcpy(&pDeleter->nextOutput, pBuf, sizeof(SDataDeleterBuf)); + taosFreeQitem(pBuf); + } SDataCacheEntry* pEntry = (SDataCacheEntry*)pDeleter->nextOutput.pData; *pLen = pEntry->dataLen; @@ -180,7 +179,7 @@ static void getDataLength(SDataSinkHandle* pHandle, int64_t* pLen, bool* pQueryE static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { SDataDeleterHandle* pDeleter = (SDataDeleterHandle*)pHandle; if (NULL == pDeleter->nextOutput.pData) { - assert(pDeleter->queryEnd); + ASSERT(pDeleter->queryEnd); pOutput->useconds = pDeleter->useconds; pOutput->precision = pDeleter->pSchema->precision; pOutput->bufStatus = DS_BUF_EMPTY; @@ -241,6 +240,7 @@ int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pData SDataDeleterHandle* deleter = taosMemoryCalloc(1, sizeof(SDataDeleterHandle)); if (NULL == deleter) { + taosMemoryFree(pParam); code = TSDB_CODE_OUT_OF_MEMORY; goto _end; } @@ -256,7 +256,7 @@ int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pData deleter->pDeleter = pDeleterNode; deleter->pSchema = pDataSink->pInputDataBlockDesc; - if(pParam == NULL) { + if (pParam == NULL) { code = TSDB_CODE_QRY_INVALID_INPUT; qError("invalid input param in creating data deleter, code%s", tstrerror(code)); goto _end; @@ -275,7 +275,7 @@ int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pData *pHandle = deleter; return code; - _end: +_end: if (deleter != NULL) { destroyDataSinker((SDataSinkHandle*)deleter); taosMemoryFree(deleter); diff --git a/source/libs/executor/src/dataDispatcher.c b/source/libs/executor/src/dataDispatcher.c index a603bffba5f37b79ee9f4a42546b8bbb3a0c32ea..49e5bfdd192aae2f952d1b5408ddd4cdaea37fcc 100644 --- a/source/libs/executor/src/dataDispatcher.c +++ b/source/libs/executor/src/dataDispatcher.c @@ -15,7 +15,7 @@ #include "dataSinkInt.h" #include "dataSinkMgt.h" -#include "executorimpl.h" +#include "executorInt.h" #include "planner.h" #include "tcompression.h" #include "tdatablock.h" @@ -77,8 +77,8 @@ static void toDataCacheEntry(SDataDispatchHandle* pHandle, const SInputData* pIn pBuf->useSize = sizeof(SDataCacheEntry); pEntry->dataLen = blockEncode(pInput->pData, pEntry->data, numOfCols); -// ASSERT(pEntry->numOfRows == *(int32_t*)(pEntry->data + 8)); -// ASSERT(pEntry->numOfCols == *(int32_t*)(pEntry->data + 8 + 4)); + // ASSERT(pEntry->numOfRows == *(int32_t*)(pEntry->data + 8)); + // ASSERT(pEntry->numOfCols == *(int32_t*)(pEntry->data + 8 + 4)); pBuf->useSize += pEntry->dataLen; @@ -135,7 +135,7 @@ static int32_t putDataBlock(SDataSinkHandle* pHandle, const SInputData* pInput, taosFreeQitem(pBuf); return TSDB_CODE_OUT_OF_MEMORY; } - + toDataCacheEntry(pDispatcher, pInput, pBuf); taosWriteQitem(pDispatcher->pDataBlocks, pBuf); @@ -162,14 +162,16 @@ static void getDataLength(SDataSinkHandle* pHandle, int64_t* pLen, bool* pQueryE SDataDispatchBuf* pBuf = NULL; taosReadQitem(pDispatcher->pDataBlocks, (void**)&pBuf); - memcpy(&pDispatcher->nextOutput, pBuf, sizeof(SDataDispatchBuf)); - taosFreeQitem(pBuf); + if (pBuf != NULL) { + memcpy(&pDispatcher->nextOutput, pBuf, sizeof(SDataDispatchBuf)); + taosFreeQitem(pBuf); + } SDataCacheEntry* pEntry = (SDataCacheEntry*)pDispatcher->nextOutput.pData; *pLen = pEntry->dataLen; -// ASSERT(pEntry->numOfRows == *(int32_t*)(pEntry->data + 8)); -// ASSERT(pEntry->numOfCols == *(int32_t*)(pEntry->data + 8 + 4)); + // ASSERT(pEntry->numOfRows == *(int32_t*)(pEntry->data + 8)); + // ASSERT(pEntry->numOfCols == *(int32_t*)(pEntry->data + 8 + 4)); *pQueryEnd = pDispatcher->queryEnd; qDebug("got data len %" PRId64 ", row num %d in sink", *pLen, @@ -179,7 +181,7 @@ static void getDataLength(SDataSinkHandle* pHandle, int64_t* pLen, bool* pQueryE static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { SDataDispatchHandle* pDispatcher = (SDataDispatchHandle*)pHandle; if (NULL == pDispatcher->nextOutput.pData) { - assert(pDispatcher->queryEnd); + ASSERT(pDispatcher->queryEnd); pOutput->useconds = pDispatcher->useconds; pOutput->precision = pDispatcher->pSchema->precision; pOutput->bufStatus = DS_BUF_EMPTY; @@ -192,9 +194,6 @@ static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { pOutput->numOfCols = pEntry->numOfCols; pOutput->compressed = pEntry->compressed; -// ASSERT(pEntry->numOfRows == *(int32_t*)(pEntry->data + 8)); -// ASSERT(pEntry->numOfCols == *(int32_t*)(pEntry->data + 8 + 4)); - atomic_sub_fetch_64(&pDispatcher->cachedSize, pEntry->dataLen); atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen); diff --git a/source/libs/executor/src/dataInserter.c b/source/libs/executor/src/dataInserter.c index 99d1968a5de525c4f1f44c2b3ebd89dbabbe4c0d..d31ac0bc517f810732fc868a6371a97d356d78a7 100644 --- a/source/libs/executor/src/dataInserter.c +++ b/source/libs/executor/src/dataInserter.c @@ -15,7 +15,7 @@ #include "dataSinkInt.h" #include "dataSinkMgt.h" -#include "executorimpl.h" +#include "executorInt.h" #include "planner.h" #include "tcompression.h" #include "tdatablock.h" @@ -25,9 +25,9 @@ extern SDataSinkStat gDataSinkStat; typedef struct SSubmitRes { - int64_t affectedRows; - int32_t code; - SSubmitRsp* pRsp; + int64_t affectedRows; + int32_t code; + SSubmitRsp2* pRsp; } SSubmitRes; typedef struct SDataInserterHandle { @@ -46,6 +46,7 @@ typedef struct SDataInserterHandle { uint64_t cachedSize; TdThreadMutex mutex; tsem_t ready; + bool explain; } SDataInserterHandle; typedef struct SSubmitRspParam { @@ -59,22 +60,25 @@ int32_t inserterCallback(void* param, SDataBuf* pMsg, int32_t code) { pInserter->submitRes.code = code; if (code == TSDB_CODE_SUCCESS) { - pInserter->submitRes.pRsp = taosMemoryCalloc(1, sizeof(SSubmitRsp)); + pInserter->submitRes.pRsp = taosMemoryCalloc(1, sizeof(SSubmitRsp2)); SDecoder coder = {0}; tDecoderInit(&coder, pMsg->pData, pMsg->len); - code = tDecodeSSubmitRsp(&coder, pInserter->submitRes.pRsp); + code = tDecodeSSubmitRsp2(&coder, pInserter->submitRes.pRsp); if (code) { - tFreeSSubmitRsp(pInserter->submitRes.pRsp); + taosMemoryFree(pInserter->submitRes.pRsp); pInserter->submitRes.code = code; goto _return; } - if (pInserter->submitRes.pRsp->nBlocks > 0) { - for (int32_t i = 0; i < pInserter->submitRes.pRsp->nBlocks; ++i) { - SSubmitBlkRsp* blk = pInserter->submitRes.pRsp->pBlocks + i; - if (TSDB_CODE_SUCCESS != blk->code) { - code = blk->code; - tFreeSSubmitRsp(pInserter->submitRes.pRsp); + if (pInserter->submitRes.pRsp->affectedRows > 0) { + SArray* pCreateTbList = pInserter->submitRes.pRsp->aCreateTbRsp; + int32_t numOfTables = taosArrayGetSize(pCreateTbList); + + for (int32_t i = 0; i < numOfTables; ++i) { + SVCreateTbRsp* pRsp = taosArrayGet(pCreateTbList, i); + if (TSDB_CODE_SUCCESS != pRsp->code) { + code = pRsp->code; + taosMemoryFree(pInserter->submitRes.pRsp); pInserter->submitRes.code = code; goto _return; } @@ -82,22 +86,20 @@ int32_t inserterCallback(void* param, SDataBuf* pMsg, int32_t code) { } pInserter->submitRes.affectedRows += pInserter->submitRes.pRsp->affectedRows; - qDebug("submit rsp received, affectedRows:%d, total:%"PRId64, pInserter->submitRes.pRsp->affectedRows, + qDebug("submit rsp received, affectedRows:%d, total:%" PRId64, pInserter->submitRes.pRsp->affectedRows, pInserter->submitRes.affectedRows); - - tFreeSSubmitRsp(pInserter->submitRes.pRsp); + tDecoderClear(&coder); + taosMemoryFree(pInserter->submitRes.pRsp); } _return: - tsem_post(&pInserter->ready); - taosMemoryFree(pMsg->pData); - return TSDB_CODE_SUCCESS; } -static int32_t sendSubmitRequest(SDataInserterHandle* pInserter, SSubmitReq* pMsg, void* pTransporter, SEpSet* pEpset) { +static int32_t sendSubmitRequest(SDataInserterHandle* pInserter, void* pMsg, int32_t msgLen, void* pTransporter, + SEpSet* pEpset) { // send the fetch remote task result reques SMsgSendInfo* pMsgSendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo)); if (NULL == pMsgSendInfo) { @@ -112,7 +114,7 @@ static int32_t sendSubmitRequest(SDataInserterHandle* pInserter, SSubmitReq* pMs pMsgSendInfo->param = pParam; pMsgSendInfo->paramFreeFp = taosMemoryFree; pMsgSendInfo->msgInfo.pData = pMsg; - pMsgSendInfo->msgInfo.len = ntohl(pMsg->length); + pMsgSendInfo->msgInfo.len = msgLen; pMsgSendInfo->msgType = TDMT_VND_SUBMIT; pMsgSendInfo->fp = inserterCallback; @@ -120,147 +122,249 @@ static int32_t sendSubmitRequest(SDataInserterHandle* pInserter, SSubmitReq* pMs return asyncSendMsgToServer(pTransporter, pEpset, &transporterId, pMsgSendInfo); } -int32_t dataBlockToSubmit(SDataInserterHandle* pInserter, SSubmitReq** pReq) { - const SArray* pBlocks = pInserter->pDataBlocks; - const STSchema* pTSchema = pInserter->pSchema; - int64_t uid = pInserter->pNode->tableId; - int64_t suid = pInserter->pNode->stableId; - int32_t vgId = pInserter->pNode->vgId; +static int32_t submitReqToMsg(int32_t vgId, SSubmitReq2* pReq, void** pData, int32_t* pLen) { + int32_t code = TSDB_CODE_SUCCESS; + int32_t len = 0; + void* pBuf = NULL; + tEncodeSize(tEncodeSubmitReq, pReq, len, code); + if (TSDB_CODE_SUCCESS == code) { + SEncoder encoder; + len += sizeof(SSubmitReq2Msg); + pBuf = taosMemoryMalloc(len); + if (NULL == pBuf) { + return TSDB_CODE_OUT_OF_MEMORY; + } + ((SSubmitReq2Msg*)pBuf)->header.vgId = htonl(vgId); + ((SSubmitReq2Msg*)pBuf)->header.contLen = htonl(len); + ((SSubmitReq2Msg*)pBuf)->version = htobe64(1); + tEncoderInit(&encoder, POINTER_SHIFT(pBuf, sizeof(SSubmitReq2Msg)), len - sizeof(SSubmitReq2Msg)); + code = tEncodeSubmitReq(&encoder, pReq); + tEncoderClear(&encoder); + } - SSubmitReq* ret = NULL; - int32_t sz = taosArrayGetSize(pBlocks); + if (TSDB_CODE_SUCCESS == code) { + *pData = pBuf; + *pLen = len; + } else { + taosMemoryFree(pBuf); + } + return code; +} - // cal size - int32_t cap = sizeof(SSubmitReq); - for (int32_t i = 0; i < sz; i++) { - SSDataBlock* pDataBlock = taosArrayGetP(pBlocks, i); - int32_t rows = pDataBlock->info.rows; - // TODO min - int32_t rowSize = pDataBlock->info.rowSize; - int32_t maxLen = TD_ROW_MAX_BYTES_FROM_SCHEMA(pTSchema); +int32_t buildSubmitReqFromBlock(SDataInserterHandle* pInserter, SSubmitReq2** ppReq, const SSDataBlock* pDataBlock, + const STSchema* pTSchema, int64_t uid, int32_t vgId, tb_uid_t suid) { + SSubmitReq2* pReq = *ppReq; + SArray* pVals = NULL; + int32_t numOfBlks = 0; + + terrno = TSDB_CODE_SUCCESS; + + if (NULL == pReq) { + if (!(pReq = taosMemoryMalloc(sizeof(SSubmitReq2)))) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _end; + } - cap += sizeof(SSubmitBlk) + rows * maxLen; + if (!(pReq->aSubmitTbData = taosArrayInit(1, sizeof(SSubmitTbData)))) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _end; + } } - // assign data - // TODO - ret = taosMemoryCalloc(1, cap); - ret->header.vgId = htonl(vgId); - ret->version = htonl(pTSchema->version); - ret->length = sizeof(SSubmitReq); - ret->numOfBlocks = htonl(sz); + int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock); + int32_t rows = pDataBlock->info.rows; - SSubmitBlk* blkHead = POINTER_SHIFT(ret, sizeof(SSubmitReq)); - for (int32_t i = 0; i < sz; i++) { - SSDataBlock* pDataBlock = taosArrayGetP(pBlocks, i); + SSubmitTbData tbData = {0}; + if (!(tbData.aRowP = taosArrayInit(rows, sizeof(SRow*)))) { + goto _end; + } + tbData.suid = suid; + tbData.uid = uid; + tbData.sver = pTSchema->version; - blkHead->sversion = htonl(pTSchema->version); - // TODO - blkHead->suid = htobe64(suid); - blkHead->uid = htobe64(uid); - blkHead->schemaLen = htonl(0); - - int32_t rows = 0; - int32_t dataLen = 0; - STSRow* rowData = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk)); - int64_t lastTs = TSKEY_MIN; - bool ignoreRow = false; - for (int32_t j = 0; j < pDataBlock->info.rows; j++) { - SRowBuilder rb = {0}; - tdSRowInit(&rb, pTSchema->version); - tdSRowSetTpInfo(&rb, pTSchema->numOfCols, pTSchema->flen); - tdSRowResetBuf(&rb, rowData); + if (!pVals && !(pVals = taosArrayInit(colNum, sizeof(SColVal)))) { + taosArrayDestroy(tbData.aRowP); + goto _end; + } - ignoreRow = false; - for (int32_t k = 0; k < pTSchema->numOfCols; k++) { - const STColumn* pColumn = &pTSchema->columns[k]; - SColumnInfoData* pColData = NULL; - int16_t colIdx = k; - if (!pInserter->fullOrderColList) { - int16_t* slotId = taosHashGet(pInserter->pCols, &pColumn->colId, sizeof(pColumn->colId)); - if (NULL == slotId) { - continue; - } + int64_t lastTs = TSKEY_MIN; + bool ignoreRow = false; + bool disorderTs = false; - colIdx = *slotId; - } + for (int32_t j = 0; j < rows; ++j) { // iterate by row + taosArrayClear(pVals); - pColData = taosArrayGet(pDataBlock->pDataBlock, colIdx); - if (pColData->info.type != pColumn->type) { - qError("col type mis-match, schema type:%d, type in block:%d", pColumn->type, pColData->info.type); - terrno = TSDB_CODE_APP_ERROR; - return TSDB_CODE_APP_ERROR; + int32_t offset = 0; + for (int32_t k = 0; k < pTSchema->numOfCols; ++k) { // iterate by column + int16_t colIdx = k; + const STColumn* pCol = &pTSchema->columns[k]; + if (!pInserter->fullOrderColList) { + int16_t* slotId = taosHashGet(pInserter->pCols, &pCol->colId, sizeof(pCol->colId)); + if (NULL == slotId) { + continue; } - if (colDataIsNull_s(pColData, j)) { - if (0 == k && TSDB_DATA_TYPE_TIMESTAMP == pColumn->type) { - ignoreRow = true; - break; - } + colIdx = *slotId; + } - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NULL, NULL, false, pColumn->offset, k); - } else { - void* data = colDataGetData(pColData, j); - if (0 == k && TSDB_DATA_TYPE_TIMESTAMP == pColumn->type) { - if (*(int64_t*)data == lastTs) { - ignoreRow = true; - break; + SColumnInfoData* pColInfoData = taosArrayGet(pDataBlock->pDataBlock, colIdx); + void* var = POINTER_SHIFT(pColInfoData->pData, j * pColInfoData->info.bytes); + + switch (pColInfoData->info.type) { + case TSDB_DATA_TYPE_NCHAR: + case TSDB_DATA_TYPE_VARCHAR: { // TSDB_DATA_TYPE_BINARY + ASSERT(pColInfoData->info.type == pCol->type); + if (colDataIsNull_s(pColInfoData, j)) { + SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type); + taosArrayPush(pVals, &cv); + } else { + void* data = colDataGetVarData(pColInfoData, j); + SValue sv = (SValue){.nData = varDataLen(data), .pData = varDataVal(data)}; // address copy, no value + SColVal cv = COL_VAL_VALUE(pCol->colId, pCol->type, sv); + taosArrayPush(pVals, &cv); + } + break; + } + case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_MEDIUMBLOB: + qError("the column type %" PRIi16 " is defined but not implemented yet", pColInfoData->info.type); + terrno = TSDB_CODE_APP_ERROR; + goto _end; + break; + default: + if (pColInfoData->info.type < TSDB_DATA_TYPE_MAX && pColInfoData->info.type > TSDB_DATA_TYPE_NULL) { + if (colDataIsNull_s(pColInfoData, j)) { + if (PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId) { + qError("NULL value for primary key"); + terrno = TSDB_CODE_PAR_INCORRECT_TIMESTAMP_VAL; + goto _end; + } + + SColVal cv = COL_VAL_NULL(pCol->colId, pCol->type); // should use pCol->type + taosArrayPush(pVals, &cv); } else { - lastTs = *(int64_t*)data; + if (PRIMARYKEY_TIMESTAMP_COL_ID == pCol->colId) { + if (*(int64_t*)var == lastTs) { + ignoreRow = true; + } else if (*(int64_t*)var < lastTs) { + disorderTs = true; + } else { + lastTs = *(int64_t*)var; + } + } + + SValue sv; + memcpy(&sv.val, var, tDataTypes[pCol->type].bytes); + SColVal cv = COL_VAL_VALUE(pCol->colId, pCol->type, sv); + taosArrayPush(pVals, &cv); } + } else { + uError("the column type %" PRIi16 " is undefined\n", pColInfoData->info.type); + terrno = TSDB_CODE_APP_ERROR; + goto _end; } - tdAppendColValToRow(&rb, pColumn->colId, pColumn->type, TD_VTYPE_NORM, data, true, pColumn->offset, k); - } - } - if (!pInserter->fullOrderColList) { - rb.hasNone = true; + break; } - tdSRowEnd(&rb); if (ignoreRow) { - continue; + break; } - - rows++; - int32_t rowLen = TD_ROW_LEN(rowData); - rowData = POINTER_SHIFT(rowData, rowLen); - dataLen += rowLen; } - blkHead->dataLen = htonl(dataLen); - blkHead->numOfRows = htonl(rows); + if (ignoreRow) { + ignoreRow = false; + continue; + } - ret->length += sizeof(SSubmitBlk) + dataLen; - blkHead = POINTER_SHIFT(blkHead, sizeof(SSubmitBlk) + dataLen); + SRow* pRow = NULL; + if ((terrno = tRowBuild(pVals, pTSchema, &pRow)) < 0) { + tDestroySubmitTbData(&tbData, TSDB_MSG_FLG_ENCODE); + goto _end; + } + taosArrayPush(tbData.aRowP, &pRow); } - ret->length = htonl(ret->length); + if (disorderTs) { + tRowSort(tbData.aRowP); + if ((terrno = tRowMerge(tbData.aRowP, (STSchema*)pTSchema, 0)) != 0) { + goto _end; + } + } - *pReq = ret; + taosArrayPush(pReq->aSubmitTbData, &tbData); +_end: + taosArrayDestroy(pVals); + if (terrno != 0) { + *ppReq = NULL; + if (pReq) { + tDestroySubmitReq(pReq, TSDB_MSG_FLG_ENCODE); + taosMemoryFree(pReq); + } + return terrno; + } + *ppReq = pReq; return TSDB_CODE_SUCCESS; } +int32_t dataBlocksToSubmitReq(SDataInserterHandle* pInserter, void** pMsg, int32_t* msgLen) { + const SArray* pBlocks = pInserter->pDataBlocks; + const STSchema* pTSchema = pInserter->pSchema; + int64_t uid = pInserter->pNode->tableId; + int64_t suid = pInserter->pNode->stableId; + int32_t vgId = pInserter->pNode->vgId; + int32_t sz = taosArrayGetSize(pBlocks); + int32_t code = 0; + SSubmitReq2* pReq = NULL; + + for (int32_t i = 0; i < sz; i++) { + SSDataBlock* pDataBlock = taosArrayGetP(pBlocks, i); + + code = buildSubmitReqFromBlock(pInserter, &pReq, pDataBlock, pTSchema, uid, vgId, suid); + if (code) { + if (pReq) { + tDestroySubmitReq(pReq, TSDB_MSG_FLG_ENCODE); + taosMemoryFree(pReq); + } + + return code; + } + } + + code = submitReqToMsg(vgId, pReq, pMsg, msgLen); + tDestroySubmitReq(pReq, TSDB_MSG_FLG_ENCODE); + taosMemoryFree(pReq); + + return code; +} + static int32_t putDataBlock(SDataSinkHandle* pHandle, const SInputData* pInput, bool* pContinue) { SDataInserterHandle* pInserter = (SDataInserterHandle*)pHandle; - taosArrayPush(pInserter->pDataBlocks, &pInput->pData); - SSubmitReq* pMsg = NULL; - int32_t code = dataBlockToSubmit(pInserter, &pMsg); - if (code) { - return code; - } + if (!pInserter->explain) { + taosArrayPush(pInserter->pDataBlocks, &pInput->pData); + void* pMsg = NULL; + int32_t msgLen = 0; + int32_t code = dataBlocksToSubmitReq(pInserter, &pMsg, &msgLen); + if (code) { + return code; + } - taosArrayClear(pInserter->pDataBlocks); - - code = sendSubmitRequest(pInserter, pMsg, pInserter->pParam->readHandle->pMsgCb->clientRpc, &pInserter->pNode->epSet); - if (code) { - return code; - } + taosArrayClear(pInserter->pDataBlocks); - tsem_wait(&pInserter->ready); + code = sendSubmitRequest(pInserter, pMsg, msgLen, pInserter->pParam->readHandle->pMsgCb->clientRpc, + &pInserter->pNode->epSet); + if (code) { + return code; + } - if (pInserter->submitRes.code) { - return pInserter->submitRes.code; + tsem_wait(&pInserter->ready); + + if (pInserter->submitRes.code) { + return pInserter->submitRes.code; + } } *pContinue = true; @@ -304,6 +408,7 @@ int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDat void* pParam) { SDataInserterHandle* inserter = taosMemoryCalloc(1, sizeof(SDataInserterHandle)); if (NULL == inserter) { + taosMemoryFree(pParam); terrno = TSDB_CODE_OUT_OF_MEMORY; return TSDB_CODE_OUT_OF_MEMORY; } @@ -320,6 +425,7 @@ int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDat inserter->pParam = pParam; inserter->status = DS_BUF_EMPTY; inserter->queryEnd = false; + inserter->explain = pInserterNode->explain; int64_t suid = 0; int32_t code = @@ -350,7 +456,7 @@ int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDat inserter->pCols = taosHashInit(pInserterNode->pCols->length, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK); - SNode* pNode = NULL; + SNode* pNode = NULL; int32_t i = 0; FOREACH(pNode, pInserterNode->pCols) { SColumnNode* pCol = (SColumnNode*)pNode; diff --git a/source/libs/executor/src/dataSinkMgt.c b/source/libs/executor/src/dataSinkMgt.c index 2b50be33ad29d4cb11d764dd090d2126c1fb13a0..b3cb57325ba5dee1d2d2f3b0d07304a1d1ea5ae2 100644 --- a/source/libs/executor/src/dataSinkMgt.c +++ b/source/libs/executor/src/dataSinkMgt.c @@ -23,7 +23,6 @@ SDataSinkStat gDataSinkStat = {0}; int32_t dsDataSinkMgtInit(SDataSinkMgtCfg* cfg) { gDataSinkManager.cfg = *cfg; - taosThreadMutexInit(&gDataSinkManager.mutex, NULL); return 0; // to avoid compiler eror } @@ -37,10 +36,12 @@ int32_t dsCreateDataSinker(const SDataSinkNode* pDataSink, DataSinkHandle* pHand switch ((int)nodeType(pDataSink)) { case QUERY_NODE_PHYSICAL_PLAN_DISPATCH: return createDataDispatcher(&gDataSinkManager, pDataSink, pHandle); - case QUERY_NODE_PHYSICAL_PLAN_DELETE: + case QUERY_NODE_PHYSICAL_PLAN_DELETE: { return createDataDeleter(&gDataSinkManager, pDataSink, pHandle, pParam); - case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: + } + case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: { return createDataInserter(&gDataSinkManager, pDataSink, pHandle, pParam); + } } qError("invalid input node type:%d, %s", nodeType(pDataSink), id); diff --git a/source/libs/executor/src/eventwindowoperator.c b/source/libs/executor/src/eventwindowoperator.c new file mode 100644 index 0000000000000000000000000000000000000000..956d5b714d1fbf98f7aec024605befc31621eeef --- /dev/null +++ b/source/libs/executor/src/eventwindowoperator.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "executorInt.h" +#include "filter.h" +#include "function.h" +#include "functionMgt.h" +#include "operator.h" +#include "querytask.h" +#include "tcommon.h" +#include "tcompare.h" +#include "tdatablock.h" +#include "ttime.h" + +typedef struct SEventWindowOperatorInfo { + SOptrBasicInfo binfo; + SAggSupporter aggSup; + SExprSupp scalarSup; + SWindowRowsSup winSup; + int32_t tsSlotId; // primary timestamp column slot id + STimeWindowAggSupp twAggSup; + uint64_t groupId; // current group id, used to identify the data block from different groups + SFilterInfo* pStartCondInfo; + SFilterInfo* pEndCondInfo; + bool inWindow; + SResultRow* pRow; +} SEventWindowOperatorInfo; + +static SSDataBlock* eventWindowAggregate(SOperatorInfo* pOperator); +static void destroyEWindowOperatorInfo(void* param); +static int32_t eventWindowAggImpl(SOperatorInfo* pOperator, SEventWindowOperatorInfo* pInfo, SSDataBlock* pBlock); + +// todo : move to util +static void doKeepNewWindowStartInfo(SWindowRowsSup* pRowSup, const int64_t* tsList, int32_t rowIndex, + uint64_t groupId) { + pRowSup->startRowIndex = rowIndex; + pRowSup->numOfRows = 0; + pRowSup->win.skey = tsList[rowIndex]; + pRowSup->groupId = groupId; +} + +static void doKeepTuple(SWindowRowsSup* pRowSup, int64_t ts, uint64_t groupId) { + pRowSup->win.ekey = ts; + pRowSup->prevTs = ts; + pRowSup->numOfRows += 1; + pRowSup->groupId = groupId; +} + +static void updateTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pWin, bool includeEndpoint) { + int64_t* ts = (int64_t*)pColData->pData; + int32_t delta = includeEndpoint ? 1 : 0; + + int64_t duration = pWin->ekey - pWin->skey + delta; + ts[2] = duration; // set the duration + ts[3] = pWin->skey; // window start key + ts[4] = pWin->ekey + delta; // window end key +} + +SOperatorInfo* createEventwindowOperatorInfo(SOperatorInfo* downstream, SPhysiNode* physiNode, + SExecTaskInfo* pTaskInfo) { + SEventWindowOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SEventWindowOperatorInfo)); + SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); + if (pInfo == NULL || pOperator == NULL) { + goto _error; + } + + SEventWinodwPhysiNode* pEventWindowNode = (SEventWinodwPhysiNode*)physiNode; + + int32_t tsSlotId = ((SColumnNode*)pEventWindowNode->window.pTspk)->slotId; + int32_t code = filterInitFromNode((SNode*)pEventWindowNode->pStartCond, &pInfo->pStartCondInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + code = filterInitFromNode((SNode*)pEventWindowNode->pEndCond, &pInfo->pEndCondInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + if (pEventWindowNode->window.pExprs != NULL) { + int32_t numOfScalarExpr = 0; + SExprInfo* pScalarExprInfo = createExprInfo(pEventWindowNode->window.pExprs, NULL, &numOfScalarExpr); + code = initExprSupp(&pInfo->scalarSup, pScalarExprInfo, numOfScalarExpr); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + } + + code = filterInitFromNode((SNode*)pEventWindowNode->window.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES; + + int32_t num = 0; + SExprInfo* pExprInfo = createExprInfo(pEventWindowNode->window.pFuncs, NULL, &num); + initResultSizeInfo(&pOperator->resultInfo, 4096); + + code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str, + pTaskInfo->streamInfo.pState); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + SSDataBlock* pResBlock = createDataBlockFromDescNode(pEventWindowNode->window.node.pOutputDataBlockDesc); + blockDataEnsureCapacity(pResBlock, pOperator->resultInfo.capacity); + + initBasicInfo(&pInfo->binfo, pResBlock); + initResultRowInfo(&pInfo->binfo.resultRowInfo); + + pInfo->twAggSup = (STimeWindowAggSupp){.waterMark = pEventWindowNode->window.watermark, + .calTrigger = pEventWindowNode->window.triggerType}; + + initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window); + + pInfo->tsSlotId = tsSlotId; + + setOperatorInfo(pOperator, "EventWindowOperator", QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE, true, OP_NOT_OPENED, pInfo, + pTaskInfo); + pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, eventWindowAggregate, NULL, destroyEWindowOperatorInfo, + optrDefaultBufFn, NULL); + + code = appendDownstream(pOperator, &downstream, 1); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + + return pOperator; + +_error: + if (pInfo != NULL) { + destroyEWindowOperatorInfo(pInfo); + } + + taosMemoryFreeClear(pOperator); + pTaskInfo->code = code; + return NULL; +} + +void destroyEWindowOperatorInfo(void* param) { + SEventWindowOperatorInfo* pInfo = (SEventWindowOperatorInfo*)param; + if (pInfo == NULL) { + return; + } + + if (pInfo->pRow != NULL) { + taosMemoryFree(pInfo->pRow); + } + + if (pInfo->pStartCondInfo != NULL) { + filterFreeInfo(pInfo->pStartCondInfo); + pInfo->pStartCondInfo = NULL; + } + + if (pInfo->pEndCondInfo != NULL) { + filterFreeInfo(pInfo->pEndCondInfo); + pInfo->pEndCondInfo = NULL; + } + + cleanupBasicInfo(&pInfo->binfo); + colDataDestroy(&pInfo->twAggSup.timeWindowData); + + cleanupAggSup(&pInfo->aggSup); + taosMemoryFreeClear(param); +} + +static SSDataBlock* eventWindowAggregate(SOperatorInfo* pOperator) { + SEventWindowOperatorInfo* pInfo = pOperator->info; + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + + SExprSupp* pSup = &pOperator->exprSupp; + int32_t order = TSDB_ORDER_ASC; + + SSDataBlock* pRes = pInfo->binfo.pRes; + + blockDataCleanup(pRes); + + SOperatorInfo* downstream = pOperator->pDownstream[0]; + while (1) { + SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); + if (pBlock == NULL) { + break; + } + + setInputDataBlock(pSup, pBlock, order, MAIN_SCAN, true); + blockDataUpdateTsWindow(pBlock, pInfo->tsSlotId); + + // there is an scalar expression that needs to be calculated right before apply the group aggregation. + if (pInfo->scalarSup.pExprInfo != NULL) { + pTaskInfo->code = projectApplyFunctions(pInfo->scalarSup.pExprInfo, pBlock, pBlock, pInfo->scalarSup.pCtx, + pInfo->scalarSup.numOfExprs, NULL); + if (pTaskInfo->code != TSDB_CODE_SUCCESS) { + T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); + } + } + + eventWindowAggImpl(pOperator, pInfo, pBlock); + if (pRes->info.rows >= pOperator->resultInfo.threshold) { + return pRes; + } + } + + return pRes->info.rows == 0 ? NULL : pRes; +} + +static int32_t setSingleOutputTupleBufv1(SResultRowInfo* pResultRowInfo, STimeWindow* win, SResultRow** pResult, + SExprSupp* pExprSup, SAggSupporter* pAggSup) { + if (*pResult == NULL) { + SResultRow* p = taosMemoryCalloc(1, pAggSup->resultRowSize); + pResultRowInfo->cur = (SResultRowPosition){.pageId = p->pageId, .offset = p->offset}; + *pResult = p; + } + + (*pResult)->win = *win; + + clearResultRowInitFlag(pExprSup->pCtx, pExprSup->numOfExprs); + setResultRowInitCtx(*pResult, pExprSup->pCtx, pExprSup->numOfExprs, pExprSup->rowEntryInfoOffset); + return TSDB_CODE_SUCCESS; +} + +static void doEventWindowAggImpl(SEventWindowOperatorInfo* pInfo, SExprSupp* pSup, int32_t startIndex, int32_t endIndex, + const SSDataBlock* pBlock, int64_t* tsList, SExecTaskInfo* pTaskInfo) { + SWindowRowsSup* pRowSup = &pInfo->winSup; + + int32_t numOfOutput = pSup->numOfExprs; + int32_t numOfRows = endIndex - startIndex + 1; + + doKeepTuple(pRowSup, tsList[endIndex], pBlock->info.id.groupId); + + int32_t ret = + setSingleOutputTupleBufv1(&pInfo->binfo.resultRowInfo, &pRowSup->win, &pInfo->pRow, pSup, &pInfo->aggSup); + if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code + T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR); + } + + updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pRowSup->win, false); + applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startIndex, numOfRows, + pBlock->info.rows, numOfOutput); +} + +int32_t eventWindowAggImpl(SOperatorInfo* pOperator, SEventWindowOperatorInfo* pInfo, SSDataBlock* pBlock) { + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + SExprSupp* pSup = &pOperator->exprSupp; + SSDataBlock* pRes = pInfo->binfo.pRes; + int64_t gid = pBlock->info.id.groupId; + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->tsSlotId); + TSKEY* tsList = (TSKEY*)pColInfoData->pData; + SWindowRowsSup* pRowSup = &pInfo->winSup; + SColumnInfoData *ps = NULL, *pe = NULL; + int32_t rowIndex = 0; + + pRowSup->numOfRows = 0; + if (pInfo->groupId == 0) { + pInfo->groupId = gid; + } else if (pInfo->groupId != gid) { + // this is a new group, reset the info + pInfo->inWindow = false; + } + + SFilterColumnParam param1 = {.numOfCols = taosArrayGetSize(pBlock->pDataBlock), .pDataBlock = pBlock->pDataBlock}; + + int32_t code = filterSetDataFromSlotId(pInfo->pStartCondInfo, ¶m1); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + int32_t status1 = 0; + filterExecute(pInfo->pStartCondInfo, pBlock, &ps, NULL, param1.numOfCols, &status1); + + SFilterColumnParam param2 = {.numOfCols = taosArrayGetSize(pBlock->pDataBlock), .pDataBlock = pBlock->pDataBlock}; + code = filterSetDataFromSlotId(pInfo->pEndCondInfo, ¶m2); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + + int32_t status2 = 0; + filterExecute(pInfo->pEndCondInfo, pBlock, &pe, NULL, param2.numOfCols, &status2); + + int32_t startIndex = pInfo->inWindow ? 0 : -1; + while (rowIndex < pBlock->info.rows) { + if (pInfo->inWindow) { // let's find the first end value + for (rowIndex = startIndex; rowIndex < pBlock->info.rows; ++rowIndex) { + if (((bool*)pe->pData)[rowIndex]) { + break; + } + } + + if (rowIndex < pBlock->info.rows) { + doEventWindowAggImpl(pInfo, pSup, startIndex, rowIndex, pBlock, tsList, pTaskInfo); + doUpdateNumOfRows(pSup->pCtx, pInfo->pRow, pSup->numOfExprs, pSup->rowEntryInfoOffset); + + // check buffer size + if (pRes->info.rows + pInfo->pRow->numOfRows >= pRes->info.capacity) { + int32_t newSize = pRes->info.rows + pInfo->pRow->numOfRows; + blockDataEnsureCapacity(pRes, newSize); + } + + copyResultrowToDataBlock(pSup->pExprInfo, pSup->numOfExprs, pInfo->pRow, pSup->pCtx, pRes, + pSup->rowEntryInfoOffset, pTaskInfo); + + pRes->info.rows += pInfo->pRow->numOfRows; + pInfo->pRow->numOfRows = 0; + + pInfo->inWindow = false; + rowIndex += 1; + } else { + doEventWindowAggImpl(pInfo, pSup, startIndex, pBlock->info.rows - 1, pBlock, tsList, pTaskInfo); + } + } else { // find the first start value that is fulfill for the start condition + for (; rowIndex < pBlock->info.rows; ++rowIndex) { + if (((bool*)ps->pData)[rowIndex]) { + doKeepNewWindowStartInfo(pRowSup, tsList, rowIndex, gid); + pInfo->inWindow = true; + startIndex = rowIndex; + break; + } + } + + if (pInfo->inWindow) { + continue; // try to find the end position + } else { + break; // no valid start position, quit + } + } + } + + colDataDestroy(ps); + taosMemoryFree(ps); + colDataDestroy(pe); + taosMemoryFree(pe); + + return TSDB_CODE_SUCCESS; +} diff --git a/source/libs/executor/src/exchangeoperator.c b/source/libs/executor/src/exchangeoperator.c index e5089ab4a9b6a6486d86bebbf82bf54c4abd543e..94041140d4e60030a4b93a1d6a6b7b4df9eacd85 100644 --- a/source/libs/executor/src/exchangeoperator.c +++ b/source/libs/executor/src/exchangeoperator.c @@ -13,17 +13,19 @@ * along with this program. If not, see . */ +#include "executorInt.h" #include "filter.h" #include "function.h" -#include "os.h" -#include "tname.h" -#include "tref.h" -#include "tdatablock.h" -#include "tmsg.h" -#include "executorimpl.h" #include "index.h" +#include "operator.h" +#include "os.h" #include "query.h" +#include "querytask.h" +#include "tdatablock.h" #include "thash.h" +#include "tmsg.h" +#include "tname.h" +#include "tref.h" typedef struct SFetchRspHandleWrapper { uint32_t exchangeId; @@ -70,7 +72,7 @@ static void concurrentlyLoadRemoteDataImpl(SOperatorInfo* pOperator, SExchangeIn tsem_wait(&pExchangeInfo->ready); if (isTaskKilled(pTaskInfo)) { - longjmp(pTaskInfo->env, pTaskInfo->code); + T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); } for (int32_t i = 0; i < totalSources; ++i) { @@ -212,6 +214,11 @@ static SSDataBlock* loadRemoteData(SOperatorInfo* pOperator) { return NULL; } + doFilter(pBlock, pOperator->exprSupp.pFilterInfo, NULL); + if (blockDataGetNumOfRows(pBlock) == 0) { + continue; + } + SLimitInfo* pLimitInfo = &pExchangeInfo->limitInfo; if (hasLimitOffsetInfo(pLimitInfo)) { int32_t status = handleLimitOffset(pOperator, pLimitInfo, pBlock, false); @@ -303,6 +310,11 @@ SOperatorInfo* createExchangeOperatorInfo(void* pTransporter, SExchangePhysiNode pTaskInfo); pOperator->exprSupp.numOfExprs = taosArrayGetSize(pInfo->pDummyBlock->pDataBlock); + code = filterInitFromNode((SNode*)pExNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); + if (code != TSDB_CODE_SUCCESS) { + goto _error; + } + pOperator->fpSet = createOperatorFpSet(prepareLoadRemoteData, loadRemoteData, NULL, destroyExchangeOperatorInfo, optrDefaultBufFn, NULL); return pOperator; @@ -512,8 +524,6 @@ int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, char* pData, SArray* pCo blockDataDestroy(pBlock); } - // todo move this to time window aggregator, since the primary timestamp may not be known by exchange operator. - blockDataUpdateTsWindow(pRes, 0); return TSDB_CODE_SUCCESS; } @@ -568,7 +578,7 @@ int32_t prepareConcurrentlyLoad(SOperatorInfo* pOperator) { pOperator->status = OP_RES_TO_RETURN; pOperator->cost.openCost = taosGetTimestampUs() - startTs; if (isTaskKilled(pTaskInfo)) { - longjmp(pTaskInfo->env, pTaskInfo->code); + T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); } return TSDB_CODE_SUCCESS; @@ -621,7 +631,7 @@ int32_t seqLoadRemoteData(SOperatorInfo* pOperator) { doSendFetchDataRequest(pExchangeInfo, pTaskInfo, pExchangeInfo->current); tsem_wait(&pExchangeInfo->ready); if (isTaskKilled(pTaskInfo)) { - longjmp(pTaskInfo->env, pTaskInfo->code); + T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); } SDownstreamSourceNode* pSource = taosArrayGet(pExchangeInfo->pSources, pExchangeInfo->current); diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index b4c5a90be3584d7a42819951a8e686f2b3e42af3..34ead810f23b98e78ae92e79e8809e961ee8fdb8 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -17,38 +17,37 @@ #include "functionMgt.h" #include "index.h" #include "os.h" +#include "query.h" #include "tdatablock.h" #include "thash.h" #include "tmsg.h" #include "ttime.h" #include "executil.h" -#include "executorimpl.h" +#include "executorInt.h" +#include "querytask.h" #include "tcompression.h" -// If the numOfOutputGroups is 1, the data blocks that belongs to different groups will be provided randomly -// The numOfOutputGroups is specified by physical plan. and will not be affect by numOfGroups -struct STableListInfo { - bool oneTableForEachGroup; - int32_t numOfOuputGroups; // the data block will be generated one by one - int32_t* groupOffset; // keep the offset value for each group in the tableList - SArray* pTableList; - SHashObj* map; // speedup acquire the tableQueryInfo by table uid - uint64_t suid; -}; - typedef struct tagFilterAssist { SHashObj* colHash; int32_t index; SArray* cInfoList; } tagFilterAssist; -static int32_t removeInvalidUid(SArray* uids, SHashObj* tags); -static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* pRes, SNode* pTagCond); -static int32_t optimizeTbnameInCondImpl(void* metaHandle, SArray* pExistedUidList, SNode* pTagCond); -static int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode, SNode* pTagCond, - SNode* pTagIndexCond, STableListInfo* pListInfo, const char* idstr); -static SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTables, SArray* pUidTagList, void* metaHandle); +typedef enum { + FILTER_NO_LOGIC = 1, + FILTER_AND, + FILTER_OTHER, +} FilterCondType; + +static FilterCondType checkTagCond(SNode* cond); +static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* list, SNode* pTagCond); +static int32_t optimizeTbnameInCondImpl(void* metaHandle, SArray* list, SNode* pTagCond); + +static int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode, SNode* pTagCond, + SNode* pTagIndexCond, STableListInfo* pListInfo, uint8_t* digest, const char* idstr); +static SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTables, SArray* pUidTagList, + void* metaHandle); static int64_t getLimit(const SNode* pLimit) { return NULL == pLimit ? -1 : ((SLimitNode*)pLimit)->limit; } static int64_t getOffset(const SNode* pLimit) { return NULL == pLimit ? -1 : ((SLimitNode*)pLimit)->offset; } @@ -73,7 +72,6 @@ void resetResultRow(SResultRow* pResultRow, size_t entrySize) { // TODO refactor: use macro SResultRowEntryInfo* getResultEntryInfo(const SResultRow* pRow, int32_t index, const int32_t* offset) { - assert(index >= 0 && offset != NULL); return (SResultRowEntryInfo*)((char*)pRow->pEntryInfo + offset[index]); } @@ -89,14 +87,12 @@ size_t getResultRowSize(SqlFunctionCtx* pCtx, int32_t numOfOutput) { return rowSize; } -static void freeEx(void* p) { - taosMemoryFree(*(void**)p); -} +static void freeEx(void* p) { taosMemoryFree(*(void**)p); } void cleanupGroupResInfo(SGroupResInfo* pGroupResInfo) { taosMemoryFreeClear(pGroupResInfo->pBuf); if (pGroupResInfo->freeItem) { -// taosArrayDestroy(pGroupResInfo->pRows); + // taosArrayDestroy(pGroupResInfo->pRows); taosArrayDestroyEx(pGroupResInfo->pRows, freeEx); pGroupResInfo->freeItem = false; pGroupResInfo->pRows = NULL; @@ -139,11 +135,11 @@ void initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SSHashObj* pHashmap, in size_t keyLen = 0; int32_t iter = 0; - int32_t bufLen = 0, offset = 0; + int64_t bufLen = 0, offset = 0; // todo move away and record this during create window while ((pData = tSimpleHashIterate(pHashmap, pData, &iter)) != NULL) { - /*void* key = */tSimpleHashGetKey(pData, &keyLen); + /*void* key = */ tSimpleHashGetKey(pData, &keyLen); bufLen += keyLen + sizeof(SResultRowPosition); } @@ -153,7 +149,7 @@ void initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SSHashObj* pHashmap, in while ((pData = tSimpleHashIterate(pHashmap, pData, &iter)) != NULL) { void* key = tSimpleHashGetKey(pData, &keyLen); - SResKeyPos* p = (SResKeyPos*) (pGroupResInfo->pBuf + offset); + SResKeyPos* p = (SResKeyPos*)(pGroupResInfo->pBuf + offset); p->groupId = *(uint64_t*)key; p->pos = *(SResultRowPosition*)pData; @@ -170,12 +166,11 @@ void initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SSHashObj* pHashmap, in } pGroupResInfo->index = 0; - assert(pGroupResInfo->index <= getNumOfTotalRes(pGroupResInfo)); } void initMultiResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) { if (pGroupResInfo->pRows != NULL) { - taosArrayDestroyP(pGroupResInfo->pRows, taosMemoryFree); + taosArrayDestroy(pGroupResInfo->pRows); } pGroupResInfo->freeItem = true; @@ -334,10 +329,7 @@ int32_t isQualifiedTable(STableKeyInfo* info, SNode* pTagCond, void* metaHandle, return code; } - ASSERT(nodeType(pNew) == QUERY_NODE_VALUE); SValueNode* pValue = (SValueNode*)pNew; - - ASSERT(pValue->node.resType.type == TSDB_DATA_TYPE_BOOL); *pQualified = pValue->datum.b; nodesDestroyNode(pNew); @@ -421,18 +413,55 @@ static void releaseColInfoData(void* pCol) { } void freeItem(void* p) { - STUidTagInfo *pInfo = p; + STUidTagInfo* pInfo = p; if (pInfo->pTagVal != NULL) { taosMemoryFree(pInfo->pTagVal); } } -int32_t getColInfoResultForGroupby(void* metaHandle, SNodeList* group, STableListInfo* pTableListInfo) { +static void genTagFilterDigest(const SNode* pTagCond, T_MD5_CTX* pContext) { + if (pTagCond == NULL) { + return; + } + + char* payload = NULL; + int32_t len = 0; + nodesNodeToMsg(pTagCond, &payload, &len); + + tMD5Init(pContext); + tMD5Update(pContext, (uint8_t*)payload, (uint32_t)len); + tMD5Final(pContext); + + taosMemoryFree(payload); +} + + +static void genTbGroupDigest(const SNode* pGroup, uint8_t* filterDigest, T_MD5_CTX* pContext) { + char* payload = NULL; + int32_t len = 0; + nodesNodeToMsg(pGroup, &payload, &len); + if (filterDigest[0]) { + payload = taosMemoryRealloc(payload, len + tListLen(pContext->digest)); + memcpy(payload + len, filterDigest + 1, tListLen(pContext->digest)); + len += tListLen(pContext->digest); + } + + tMD5Init(pContext); + tMD5Update(pContext, (uint8_t*)payload, (uint32_t)len); + tMD5Final(pContext); + + taosMemoryFree(payload); +} + + +int32_t getColInfoResultForGroupby(void* metaHandle, SNodeList* group, STableListInfo* pTableListInfo, uint8_t *digest) { int32_t code = TSDB_CODE_SUCCESS; SArray* pBlockList = NULL; SSDataBlock* pResBlock = NULL; void* keyBuf = NULL; SArray* groupData = NULL; + SArray* pUidTagList = NULL; + SArray* tableList = NULL; int32_t rows = taosArrayGetSize(pTableListInfo->pTableList); if (rows == 0) { @@ -459,15 +488,31 @@ int32_t getColInfoResultForGroupby(void* metaHandle, SNodeList* group, STableLis REPLACE_NODE(pNode); } - SArray* pUidTagList = taosArrayInit(8, sizeof(STUidTagInfo)); + T_MD5_CTX context = {0}; + if (tsTagFilterCache) { + SNodeListNode* listNode = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST); + listNode->pNodeList = group; + genTbGroupDigest((SNode *)listNode, digest, &context); + nodesFree(listNode); + + metaGetCachedTbGroup(metaHandle, pTableListInfo->idInfo.suid, context.digest, tListLen(context.digest), &tableList); + if (tableList) { + taosArrayDestroy(pTableListInfo->pTableList); + pTableListInfo->pTableList = tableList; + qDebug("retrieve tb group list from cache, numOfTables:%d", (int32_t)taosArrayGetSize(pTableListInfo->pTableList)); + goto end; + } + } + + pUidTagList = taosArrayInit(8, sizeof(STUidTagInfo)); for (int32_t i = 0; i < rows; ++i) { STableKeyInfo* pkeyInfo = taosArrayGet(pTableListInfo->pTableList, i); - STUidTagInfo info = {.uid = pkeyInfo->uid}; + STUidTagInfo info = {.uid = pkeyInfo->uid}; taosArrayPush(pUidTagList, &info); } // int64_t stt = taosGetTimestampUs(); - code = metaGetTableTags(metaHandle, pTableListInfo->suid, pUidTagList); + code = metaGetTableTags(metaHandle, pTableListInfo->idInfo.suid, pUidTagList); if (code != TSDB_CODE_SUCCESS) { goto end; } @@ -568,6 +613,10 @@ int32_t getColInfoResultForGroupby(void* metaHandle, SNodeList* group, STableLis memcpy(pStart, data, len); pStart += len; } else if (IS_VAR_DATA_TYPE(pValue->info.type)) { + if (varDataTLen(data) > pValue->info.bytes) { + code = TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER; + goto end; + } memcpy(pStart, data, varDataTLen(data)); pStart += varDataTLen(data); } else { @@ -581,6 +630,11 @@ int32_t getColInfoResultForGroupby(void* metaHandle, SNodeList* group, STableLis info->groupId = calcGroupId(keyBuf, len); } + if (tsTagFilterCache) { + tableList = taosArrayDup(pTableListInfo->pTableList, NULL); + metaPutTbGroupToCache(metaHandle, pTableListInfo->idInfo.suid, context.digest, tListLen(context.digest), tableList, taosArrayGetSize(tableList) * sizeof(STableKeyInfo)); + } + // int64_t st2 = taosGetTimestampUs(); // qDebug("calculate tag block rows:%d, cost:%ld us", rows, st2-st1); @@ -660,22 +714,32 @@ static int tableUidCompare(const void* a, const void* b) { } static int32_t filterTableInfoCompare(const void* a, const void* b) { - STUidTagInfo* p1 = (STUidTagInfo*) a; - STUidTagInfo* p2 = (STUidTagInfo*) b; + STUidTagInfo* p1 = (STUidTagInfo*)a; + STUidTagInfo* p2 = (STUidTagInfo*)b; if (p1->uid == p2->uid) { return 0; } - return p1->uid < p2->uid? -1:1; + return p1->uid < p2->uid ? -1 : 1; +} + +static FilterCondType checkTagCond(SNode* cond) { + if (nodeType(cond) == QUERY_NODE_OPERATOR) { + return FILTER_NO_LOGIC; + } + if (nodeType(cond) != QUERY_NODE_LOGIC_CONDITION || ((SLogicConditionNode*)cond)->condType != LOGIC_COND_TYPE_AND) { + return FILTER_AND; + } + return FILTER_OTHER; } -static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* pRes, SNode* cond) { +static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* list, SNode* cond) { int32_t ret = -1; int32_t ntype = nodeType(cond); if (ntype == QUERY_NODE_OPERATOR) { - ret = optimizeTbnameInCondImpl(metaHandle, pRes, cond); + ret = optimizeTbnameInCondImpl(metaHandle, list, cond); } if (ntype != QUERY_NODE_LOGIC_CONDITION || ((SLogicConditionNode*)cond)->condType != LOGIC_COND_TYPE_AND) { @@ -694,50 +758,23 @@ static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* pRes SListCell* cell = pList->pHead; for (int i = 0; i < len; i++) { if (cell == NULL) break; - if (optimizeTbnameInCondImpl(metaHandle, pRes, cell->pNode) == 0) { + if (optimizeTbnameInCondImpl(metaHandle, list, cell->pNode) == 0) { hasTbnameCond = true; break; } cell = cell->pNext; } - taosArraySort(pRes, filterTableInfoCompare); - taosArrayRemoveDuplicate(pRes, filterTableInfoCompare, NULL); + taosArraySort(list, filterTableInfoCompare); + taosArrayRemoveDuplicate(list, filterTableInfoCompare, NULL); if (hasTbnameCond) { - ret = metaGetTableTagsByUids(metaHandle, suid, pRes); -// removeInvalidUid(pRes, tags); + ret = metaGetTableTagsByUids(metaHandle, suid, list); } return ret; } -#if 0 -/* - * handle invalid uid - */ -static int32_t removeInvalidUid(SArray* uids, SHashObj* tags) { - int32_t size = taosArrayGetSize(uids); - if (size <= 0) { - return 0; - } - - SArray* validUid = taosArrayInit(size, sizeof(STUidTagInfo)); - - for (int32_t i = 0; i < size; i++) { - STUidTagInfo* p = taosArrayGet(uids, i); - if (taosHashGet(tags, &p->uid, sizeof(int64_t)) != NULL) { - taosArrayPush(validUid, p); - } - } - - taosArraySwap(uids, validUid); - taosArrayDestroy(validUid); - return 0; -} - -#endif - // only return uid that does not contained in pExistedUidList static int32_t optimizeTbnameInCondImpl(void* metaHandle, SArray* pExistedUidList, SNode* pTagCond) { if (nodeType(pTagCond) != QUERY_NODE_OPERATOR) { @@ -763,7 +800,7 @@ static int32_t optimizeTbnameInCondImpl(void* metaHandle, SArray* pExistedUidLis int32_t numOfTables = taosArrayGetSize(pTbList); SHashObj* uHash = NULL; - size_t numOfExisted = taosArrayGetSize(pExistedUidList); // len > 0 means there already have uids + size_t numOfExisted = taosArrayGetSize(pExistedUidList); // len > 0 means there already have uids if (numOfExisted > 0) { uHash = taosHashInit(numOfExisted / 0.7, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); for (int i = 0; i < numOfExisted; i++) { @@ -789,7 +826,7 @@ static int32_t optimizeTbnameInCondImpl(void* metaHandle, SArray* pExistedUidLis return -1; } } else { -// qWarn("failed to get tableIds from by table name: %s, reason: %s", name, tstrerror(terrno)); + // qWarn("failed to get tableIds from by table name: %s, reason: %s", name, tstrerror(terrno)); terrno = 0; } } @@ -802,23 +839,9 @@ static int32_t optimizeTbnameInCondImpl(void* metaHandle, SArray* pExistedUidLis return -1; } -static void genTagFilterDigest(const SNode* pTagCond, T_MD5_CTX* pContext) { - if (pTagCond == NULL) { - return; - } - - char* payload = NULL; - int32_t len = 0; - nodesNodeToMsg(pTagCond, &payload, &len); - - tMD5Init(pContext); - tMD5Update(pContext, (uint8_t*)payload, (uint32_t)len); - tMD5Final(pContext); - - taosMemoryFree(payload); -} -static SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTables, SArray* pUidTagList, void* metaHandle) { +static SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTables, SArray* pUidTagList, + void* metaHandle) { SSDataBlock* pResBlock = createDataBlock(); if (pResBlock == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -834,6 +857,7 @@ static SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTa int32_t code = blockDataEnsureCapacity(pResBlock, numOfTables); if (code != TSDB_CODE_SUCCESS) { terrno = code; + taosMemoryFree(pResBlock); return NULL; } @@ -851,11 +875,11 @@ static SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTa char str[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; if (p1->name != NULL) { STR_TO_VARSTR(str, p1->name); - } else { // name is not retrieved during filter + } else { // name is not retrieved during filter metaGetTableNameByUid(metaHandle, p1->uid, str); } - colDataAppend(pColInfo, i, str, false); + colDataSetVal(pColInfo, i, str, false); #if TAG_FILTER_DEBUG qDebug("tagfilter uid:%ld, tbname:%s", *uid, str + 2); #endif @@ -863,32 +887,33 @@ static SSDataBlock* createTagValBlockForFilter(SArray* pColList, int32_t numOfTa STagVal tagVal = {0}; tagVal.cid = pColInfo->info.colId; if (p1->pTagVal == NULL) { - colDataAppendNULL(pColInfo, i); - } - - const char* p = metaGetTableTagVal(p1->pTagVal, pColInfo->info.type, &tagVal); - - if (p == NULL || (pColInfo->info.type == TSDB_DATA_TYPE_JSON && ((STag*)p)->nTag == 0)) { - colDataAppendNULL(pColInfo, i); - } else if (pColInfo->info.type == TSDB_DATA_TYPE_JSON) { - colDataAppend(pColInfo, i, p, false); - } else if (IS_VAR_DATA_TYPE(pColInfo->info.type)) { - char* tmp = alloca(tagVal.nData + VARSTR_HEADER_SIZE + 1); - varDataSetLen(tmp, tagVal.nData); - memcpy(tmp + VARSTR_HEADER_SIZE, tagVal.pData, tagVal.nData); - colDataAppend(pColInfo, i, tmp, false); + colDataSetNULL(pColInfo, i); + } else { + const char* p = metaGetTableTagVal(p1->pTagVal, pColInfo->info.type, &tagVal); + + if (p == NULL || (pColInfo->info.type == TSDB_DATA_TYPE_JSON && ((STag*)p)->nTag == 0)) { + colDataSetNULL(pColInfo, i); + } else if (pColInfo->info.type == TSDB_DATA_TYPE_JSON) { + colDataSetVal(pColInfo, i, p, false); + } else if (IS_VAR_DATA_TYPE(pColInfo->info.type)) { + char* tmp = taosMemoryMalloc(tagVal.nData + VARSTR_HEADER_SIZE + 1); + varDataSetLen(tmp, tagVal.nData); + memcpy(tmp + VARSTR_HEADER_SIZE, tagVal.pData, tagVal.nData); + colDataSetVal(pColInfo, i, tmp, false); #if TAG_FILTER_DEBUG - qDebug("tagfilter varch:%s", tmp + 2); + qDebug("tagfilter varch:%s", tmp + 2); #endif - } else { - colDataAppend(pColInfo, i, (const char*)&tagVal.i64, false); + taosMemoryFree(tmp); + } else { + colDataSetVal(pColInfo, i, (const char*)&tagVal.i64, false); #if TAG_FILTER_DEBUG - if (pColInfo->info.type == TSDB_DATA_TYPE_INT) { - qDebug("tagfilter int:%d", *(int*)(&tagVal.i64)); - } else if (pColInfo->info.type == TSDB_DATA_TYPE_DOUBLE) { - qDebug("tagfilter double:%f", *(double*)(&tagVal.i64)); - } + if (pColInfo->info.type == TSDB_DATA_TYPE_INT) { + qDebug("tagfilter int:%d", *(int*)(&tagVal.i64)); + } else if (pColInfo->info.type == TSDB_DATA_TYPE_DOUBLE) { + qDebug("tagfilter double:%f", *(double*)(&tagVal.i64)); + } #endif + } } } } @@ -901,7 +926,7 @@ static void doSetQualifiedUid(SArray* pUidList, const SArray* pUidTagList, bool* taosArrayClear(pUidList); int32_t numOfTables = taosArrayGetSize(pUidTagList); - for(int32_t i = 0; i < numOfTables; ++i) { + for (int32_t i = 0; i < numOfTables; ++i) { uint64_t uid = ((STUidTagInfo*)taosArrayGet(pUidTagList, i))->uid; qDebug("tagfilter get uid:%" PRId64 ", res:%d", uid, pResultList[i]); @@ -917,14 +942,15 @@ static void copyExistedUids(SArray* pUidTagList, const SArray* pUidList) { return; } - for(int32_t i = 0; i < numOfExisted; ++i) { - uint64_t* uid = taosArrayGet(pUidList, i); + for (int32_t i = 0; i < numOfExisted; ++i) { + uint64_t* uid = taosArrayGet(pUidList, i); STUidTagInfo info = {.uid = *uid}; taosArrayPush(pUidTagList, &info); } } -static int32_t doFilterByTagCond(STableListInfo* pListInfo, SArray* pUidList, SNode* pTagCond, void* metaHandle) { +static int32_t doFilterByTagCond(STableListInfo* pListInfo, SArray* pUidList, SNode* pTagCond, void* metaHandle, + SIdxFltStatus status) { if (pTagCond == NULL) { return TSDB_CODE_SUCCESS; } @@ -957,24 +983,27 @@ static int32_t doFilterByTagCond(STableListInfo* pListInfo, SArray* pUidList, SN SArray* pUidTagList = taosArrayInit(10, sizeof(STUidTagInfo)); copyExistedUids(pUidTagList, pUidList); - int32_t filter = optimizeTbnameInCond(metaHandle, pListInfo->suid, pUidTagList, pTagCond); + FilterCondType condType = checkTagCond(pTagCond); + + int32_t filter = optimizeTbnameInCond(metaHandle, pListInfo->idInfo.suid, pUidTagList, pTagCond); if (filter == 0) { // tbname in filter is activated, do nothing and return taosArrayClear(pUidList); int32_t numOfRows = taosArrayGetSize(pUidTagList); taosArrayEnsureCap(pUidList, numOfRows); - for(int32_t i = 0; i < numOfRows; ++i) { + for (int32_t i = 0; i < numOfRows; ++i) { STUidTagInfo* pInfo = taosArrayGet(pUidTagList, i); taosArrayPush(pUidList, &pInfo->uid); } - terrno = 0; - goto end; } else { - // here we retrieve all tags from the vnode table-meta store - code = metaGetTableTags(metaHandle, pListInfo->suid, pUidTagList); + if ((condType == FILTER_NO_LOGIC || condType == FILTER_AND) && status != SFLT_NOT_INDEX) { + code = metaGetTableTagsByUids(metaHandle, pListInfo->idInfo.suid, pUidTagList); + } else { + code = metaGetTableTags(metaHandle, pListInfo->idInfo.suid, pUidTagList); + } if (code != TSDB_CODE_SUCCESS) { - qError("failed to get table tags from meta, reason:%s, suid:%" PRIu64, tstrerror(code), pListInfo->suid); + qError("failed to get table tags from meta, reason:%s, suid:%" PRIu64, tstrerror(code), pListInfo->idInfo.suid); terrno = code; goto end; } @@ -1009,9 +1038,9 @@ static int32_t doFilterByTagCond(STableListInfo* pListInfo, SArray* pUidList, SN goto end; } - doSetQualifiedUid(pUidList, pUidTagList, (bool*) output.columnData->pData); + doSetQualifiedUid(pUidList, pUidTagList, (bool*)output.columnData->pData); - end: +end: taosHashCleanup(ctx.colHash); taosArrayDestroy(ctx.cInfoList); blockDataDestroy(pResBlock); @@ -1024,19 +1053,22 @@ static int32_t doFilterByTagCond(STableListInfo* pListInfo, SArray* pUidList, SN } int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode, SNode* pTagCond, SNode* pTagIndexCond, - STableListInfo* pListInfo, const char* idstr) { + STableListInfo* pListInfo, uint8_t* digest, const char* idstr) { int32_t code = TSDB_CODE_SUCCESS; size_t numOfTables = 0; - pListInfo->suid = pScanNode->suid; + pListInfo->idInfo.suid = pScanNode->suid; + pListInfo->idInfo.tableType = pScanNode->tableType; + SArray* pUidList = taosArrayInit(8, sizeof(uint64_t)); + SIdxFltStatus status = SFLT_NOT_INDEX; if (pScanNode->tableType != TSDB_SUPER_TABLE) { + pListInfo->idInfo.uid = pScanNode->uid; if (metaIsTableExist(metaHandle, pScanNode->uid)) { taosArrayPush(pUidList, &pScanNode->uid); } - - code = doFilterByTagCond(pListInfo, pUidList, pTagCond, metaHandle); + code = doFilterByTagCond(pListInfo, pUidList, pTagCond, metaHandle, status); if (code != TSDB_CODE_SUCCESS) { goto _end; } @@ -1048,33 +1080,37 @@ int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode, genTagFilterDigest(pTagCond, &context); bool acquired = false; - metaGetCachedTableUidList(metaHandle, pScanNode->suid, context.digest, tListLen(context.digest), pUidList, &acquired); + metaGetCachedTableUidList(metaHandle, pScanNode->suid, context.digest, tListLen(context.digest), pUidList, + &acquired); if (acquired) { + digest[0] = 1; + memcpy(digest + 1, context.digest, tListLen(context.digest)); qDebug("retrieve table uid list from cache, numOfTables:%d", (int32_t)taosArrayGetSize(pUidList)); goto _end; } } if (!pTagCond) { // no tag filter condition exists, let's fetch all tables of this super table - ASSERT(pTagIndexCond == NULL); vnodeGetCtbIdList(pVnode, pScanNode->suid, pUidList); } else { // failed to find the result in the cache, let try to calculate the results if (pTagIndexCond) { - void* pIndex = tsdbGetIvtIdx(metaHandle); + void* pIndex = tsdbGetIvtIdx(metaHandle); SIndexMetaArg metaArg = { .metaEx = metaHandle, .idx = tsdbGetIdx(metaHandle), .ivtIdx = pIndex, .suid = pScanNode->uid}; - SIdxFltStatus status = SFLT_NOT_INDEX; + status = SFLT_NOT_INDEX; code = doFilterTag(pTagIndexCond, &metaArg, pUidList, &status); if (code != 0 || status == SFLT_NOT_INDEX) { // temporarily disable it for performance sake -// qError("failed to get tableIds from index, reason:%s, suid:%" PRIu64, tstrerror(code), tableUid); + qWarn("failed to get tableIds from index, suid:%" PRIu64, pScanNode->uid); code = TDB_CODE_SUCCESS; + } else { + qInfo("succ to get filter result, table num: %d", (int)taosArrayGetSize(pUidList)); } } } - code = doFilterByTagCond(pListInfo, pUidList, pTagCond, metaHandle); + code = doFilterByTagCond(pListInfo, pUidList, pTagCond, metaHandle, status); if (code != TSDB_CODE_SUCCESS) { goto _end; } @@ -1092,6 +1128,8 @@ int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode, } metaUidFilterCachePut(metaHandle, pScanNode->suid, context.digest, tListLen(context.digest), pPayload, size, 1); + digest[0] = 1; + memcpy(digest + 1, context.digest, tListLen(context.digest)); } } @@ -1106,7 +1144,7 @@ _end: return TSDB_CODE_OUT_OF_MEMORY; } - qTrace("tagfilter get uid:%" PRIu64", %s", info.uid, idstr); + qTrace("tagfilter get uid:%" PRIu64 ", %s", info.uid, idstr); } taosArrayDestroy(pUidList); @@ -1148,7 +1186,6 @@ int32_t getGroupIdFromTagsVal(void* pMeta, uint64_t uid, SNodeList* pGroupNode, if (TSDB_CODE_SUCCESS == code) { REPLACE_NODE(pNew); } else { - taosMemoryFree(keyBuf); nodesDestroyList(groupNew); metaReaderClear(&mr); return code; @@ -1166,7 +1203,6 @@ int32_t getGroupIdFromTagsVal(void* pMeta, uint64_t uid, SNodeList* pGroupNode, if (pValue->node.resType.type == TSDB_DATA_TYPE_JSON) { if (tTagIsJson(data)) { terrno = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR; - taosMemoryFree(keyBuf); nodesDestroyList(groupNew); metaReaderClear(&mr); return terrno; @@ -1368,7 +1404,6 @@ void createExprFromOneNode(SExprInfo* pExp, SNode* pNode, int16_t slotId) { if (!pFuncNode->pParameterList && (memcmp(pExprNode->_function.functionName, name, len) == 0) && pExprNode->_function.functionName[len] == 0) { pFuncNode->pParameterList = nodesMakeList(); - ASSERT(LIST_LENGTH(pFuncNode->pParameterList) == 0); SValueNode* res = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); if (NULL == res) { // todo handle error } else { @@ -1428,6 +1463,18 @@ void createExprFromTargetNode(SExprInfo* pExp, STargetNode* pTargetNode) { createExprFromOneNode(pExp, pTargetNode->pExpr, pTargetNode->slotId); } +SExprInfo* createExpr(SNodeList* pNodeList, int32_t* numOfExprs) { + *numOfExprs = LIST_LENGTH(pNodeList); + SExprInfo* pExprs = taosMemoryCalloc(*numOfExprs, sizeof(SExprInfo)); + + for (int32_t i = 0; i < (*numOfExprs); ++i) { + SExprInfo* pExp = &pExprs[i]; + createExprFromOneNode(pExp, nodesListGetNode(pNodeList, i), i + UD_TAG_COLUMN_INDEX); + } + + return pExprs; +} + SExprInfo* createExprInfo(SNodeList* pNodeList, SNodeList* pGroupKeys, int32_t* numOfExprs) { int32_t numOfFuncs = LIST_LENGTH(pNodeList); int32_t numOfGroupKeys = 0; @@ -1467,14 +1514,23 @@ static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutpu return TSDB_CODE_OUT_OF_MEMORY; } + SHashObj *pSelectFuncs = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); for (int32_t i = 0; i < numOfOutput; ++i) { const char* pName = pCtx[i].pExpr->pExpr->_function.functionName; if ((strcmp(pName, "_select_value") == 0) || (strcmp(pName, "_group_key") == 0)) { pValCtx[num++] = &pCtx[i]; } else if (fmIsSelectFunc(pCtx[i].functionId)) { - p = &pCtx[i]; + void* data = taosHashGet(pSelectFuncs, pName, strlen(pName)); + if (taosHashGetSize(pSelectFuncs) != 0 && data == NULL) { + p = NULL; + break; + } else { + taosHashPut(pSelectFuncs, pName, strlen(pName), &num, sizeof(num)); + p = &pCtx[i]; + } } } + taosHashCleanup(pSelectFuncs); if (p != NULL) { p->subsidiaries.pCtx = pValCtx; @@ -1519,7 +1575,7 @@ SqlFunctionCtx* createSqlFunctionCtx(SExprInfo* pExprInfo, int32_t numOfOutput, fmGetFuncExecFuncs(pCtx->functionId, &pCtx->fpSet); } else { char* udfName = pExpr->pExpr->_function.pFunctNode->functionName; - pCtx->udfName = strdup(udfName); + pCtx->udfName = taosStrdup(udfName); fmGetUdafExecFuncs(pCtx->functionId, &pCtx->fpSet); } pCtx->fpSet.getEnv(pExpr->pExpr->_function.pFunctNode, &env); @@ -1696,7 +1752,7 @@ void getInitialStartTimeWindow(SInterval* pInterval, TSKEY ts, STimeWindow* w, b int64_t key = w->skey; while (key < ts) { // moving towards end key = taosTimeAdd(key, pInterval->sliding, pInterval->slidingUnit, pInterval->precision); - if (key >= ts) { + if (key > ts) { break; } @@ -1775,7 +1831,7 @@ void getNextTimeWindow(const SInterval* pInterval, STimeWindow* tw, int32_t orde struct tm tm; time_t t = (time_t) key; - taosLocalTime(&t, &tm); + taosLocalTime(&t, &tm, NULL); int mon = (int)(tm.tm_year * 12 + tm.tm_mon + duration * factor); tm.tm_year = mon / 12; @@ -1814,7 +1870,9 @@ uint64_t tableListGetSize(const STableListInfo* pTableList) { return taosArrayGetSize(pTableList->pTableList); } -uint64_t tableListGetSuid(const STableListInfo* pTableList) { return pTableList->suid; } +uint64_t tableListGetSuid(const STableListInfo* pTableList) { + return pTableList->idInfo.suid; +} STableKeyInfo* tableListGetInfo(const STableListInfo* pTableList, int32_t index) { if (taosArrayGetSize(pTableList->pTableList) == 0) { @@ -1824,6 +1882,27 @@ STableKeyInfo* tableListGetInfo(const STableListInfo* pTableList, int32_t index) return taosArrayGet(pTableList->pTableList, index); } +int32_t tableListFind(const STableListInfo* pTableList, uint64_t uid, int32_t startIndex) { + int32_t numOfTables = taosArrayGetSize(pTableList->pTableList); + if (startIndex >= numOfTables) { + return -1; + } + + for (int32_t i = startIndex; i < numOfTables; ++i) { + STableKeyInfo* p = taosArrayGet(pTableList->pTableList, i); + if (p->uid == uid) { + return i; + } + } + return -1; +} + +void tableListGetSourceTableInfo(const STableListInfo* pTableList, uint64_t* psuid, uint64_t* uid, int32_t* type) { + *psuid = pTableList->idInfo.suid; + *uid = pTableList->idInfo.uid; + *type = pTableList->idInfo.tableType; +} + uint64_t getTableGroupId(const STableListInfo* pTableList, uint64_t tableUid) { int32_t* slot = taosHashGet(pTableList->map, &tableUid, sizeof(tableUid)); ASSERT(pTableList->map != NULL && slot != NULL); @@ -1837,7 +1916,6 @@ uint64_t getTableGroupId(const STableListInfo* pTableList, uint64_t tableUid) { // TODO handle the group offset info, fix it, the rule of group output will be broken by this function int32_t tableListAddTableInfo(STableListInfo* pTableList, uint64_t uid, uint64_t gid) { if (pTableList->map == NULL) { - ASSERT(taosArrayGetSize(pTableList->pTableList) == 0); pTableList->map = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK); } @@ -1854,7 +1932,7 @@ int32_t tableListAddTableInfo(STableListInfo* pTableList, uint64_t uid, uint64_t int32_t tableListGetGroupList(const STableListInfo* pTableList, int32_t ordinalGroupIndex, STableKeyInfo** pKeyInfo, int32_t* size) { int32_t totalGroups = tableListGetOutputGroups(pTableList); - int32_t numOfTables = tableListGetSize(pTableList); + int32_t numOfTables = tableListGetSize(pTableList); if (ordinalGroupIndex < 0 || ordinalGroupIndex >= totalGroups) { return TSDB_CODE_INVALID_PARA; @@ -1984,10 +2062,9 @@ static int32_t sortTableGroup(STableListInfo* pTableListInfo) { return TDB_CODE_SUCCESS; } -int32_t buildGroupIdMapForAllTables(STableListInfo* pTableListInfo, SReadHandle* pHandle, SNodeList* group, - bool groupSort) { +int32_t buildGroupIdMapForAllTables(STableListInfo* pTableListInfo, SReadHandle* pHandle, SScanPhysiNode* pScanNode, SNodeList* group, + bool groupSort, uint8_t *digest) { int32_t code = TSDB_CODE_SUCCESS; - ASSERT(pTableListInfo->map != NULL); bool groupByTbname = groupbyTbname(group); size_t numOfTables = taosArrayGetSize(pTableListInfo->pTableList); @@ -2006,7 +2083,7 @@ int32_t buildGroupIdMapForAllTables(STableListInfo* pTableListInfo, SReadHandle* pTableListInfo->numOfOuputGroups = 1; } } else { - code = getColInfoResultForGroupby(pHandle->meta, group, pTableListInfo); + code = getColInfoResultForGroupby(pHandle->meta, group, pTableListInfo, digest); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -2037,14 +2114,14 @@ int32_t createScanTableListInfo(SScanPhysiNode* pScanNode, SNodeList* pGroupTags return TSDB_CODE_INVALID_PARA; } - int32_t code = getTableList(pHandle->meta, pHandle->vnode, pScanNode, pTagCond, pTagIndexCond, pTableListInfo, idStr); + uint8_t digest[17] = {0}; + int32_t code = getTableList(pHandle->meta, pHandle->vnode, pScanNode, pTagCond, pTagIndexCond, pTableListInfo, digest, idStr); if (code != TSDB_CODE_SUCCESS) { qError("failed to getTableList, code: %s", tstrerror(code)); return code; } int32_t numOfTables = taosArrayGetSize(pTableListInfo->pTableList); - ASSERT(pTableListInfo->numOfOuputGroups == 1); int64_t st1 = taosGetTimestampUs(); pTaskInfo->cost.extractListTime = (st1 - st) / 1000.0; @@ -2056,7 +2133,7 @@ int32_t createScanTableListInfo(SScanPhysiNode* pScanNode, SNodeList* pGroupTags return TSDB_CODE_SUCCESS; } - code = buildGroupIdMapForAllTables(pTableListInfo, pHandle, pGroupTags, groupSort); + code = buildGroupIdMapForAllTables(pTableListInfo, pHandle, pScanNode, pGroupTags, groupSort, digest); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -2069,7 +2146,7 @@ int32_t createScanTableListInfo(SScanPhysiNode* pScanNode, SNodeList* pGroupTags void printDataBlock(SSDataBlock* pBlock, const char* flag) { if (!pBlock || pBlock->info.rows == 0) { - qDebug("===stream===printDataBlock: Block is Null or Empty"); + qDebug("===stream===%s: Block is Null or Empty", flag); return; } char* pBuf = NULL; diff --git a/source/libs/executor/src/executor.c b/source/libs/executor/src/executor.c index 6c354c3d6161aa0ec8fe63b4d99edabbf75030d5..c4a56d78aebbe0f6a89e77473ba6791ed61c0212 100644 --- a/source/libs/executor/src/executor.c +++ b/source/libs/executor/src/executor.c @@ -14,8 +14,10 @@ */ #include "executor.h" -#include "executorimpl.h" +#include "executorInt.h" +#include "operator.h" #include "planner.h" +#include "querytask.h" #include "tdatablock.h" #include "tref.h" #include "tudf.h" @@ -29,13 +31,12 @@ static void cleanupRefPool() { taosCloseRef(ref); } -static void initRefPool() { - exchangeObjRefPool = taosOpenRef(1024, doDestroyExchangeOperatorInfo); +static void initRefPool() { + exchangeObjRefPool = taosOpenRef(1024, doDestroyExchangeOperatorInfo); atexit(cleanupRefPool); } static int32_t doSetSMABlock(SOperatorInfo* pOperator, void* input, size_t numOfBlocks, int32_t type, char* id) { - ASSERT(pOperator != NULL); if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { if (pOperator->numOfDownstream == 0) { qError("failed to find stream scan operator to set the input data block, %s" PRIx64, id); @@ -55,8 +56,8 @@ static int32_t doSetSMABlock(SOperatorInfo* pOperator, void* input, size_t numOf if (type == STREAM_INPUT__MERGED_SUBMIT) { for (int32_t i = 0; i < numOfBlocks; i++) { - SSubmitReq* pReq = *(void**)POINTER_SHIFT(input, i * sizeof(void*)); - taosArrayPush(pInfo->pBlockLists, &pReq); + SPackedData* pReq = POINTER_SHIFT(input, i * sizeof(SPackedData)); + taosArrayPush(pInfo->pBlockLists, pReq); } pInfo->blockType = STREAM_INPUT__DATA_SUBMIT; } else if (type == STREAM_INPUT__DATA_SUBMIT) { @@ -65,7 +66,10 @@ static int32_t doSetSMABlock(SOperatorInfo* pOperator, void* input, size_t numOf } else if (type == STREAM_INPUT__DATA_BLOCK) { for (int32_t i = 0; i < numOfBlocks; ++i) { SSDataBlock* pDataBlock = &((SSDataBlock*)input)[i]; - taosArrayPush(pInfo->pBlockLists, &pDataBlock); + SPackedData tmp = { + .pDataBlock = pDataBlock, + }; + taosArrayPush(pInfo->pBlockLists, &tmp); } pInfo->blockType = STREAM_INPUT__DATA_BLOCK; } @@ -75,27 +79,40 @@ static int32_t doSetSMABlock(SOperatorInfo* pOperator, void* input, size_t numOf } static int32_t doSetStreamOpOpen(SOperatorInfo* pOperator, char* id) { - { - ASSERT(pOperator != NULL); - if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { - if (pOperator->numOfDownstream == 0) { - qError("failed to find stream scan operator to set the input data block, %s" PRIx64, id); - return TSDB_CODE_APP_ERROR; - } + if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { + if (pOperator->numOfDownstream == 0) { + qError("failed to find stream scan operator to set the input data block, %s" PRIx64, id); + return TSDB_CODE_APP_ERROR; + } - if (pOperator->numOfDownstream > 1) { // not handle this in join query - qError("join not supported for stream block scan, %s" PRIx64, id); - return TSDB_CODE_APP_ERROR; - } - pOperator->status = OP_NOT_OPENED; - return doSetStreamOpOpen(pOperator->pDownstream[0], id); + if (pOperator->numOfDownstream > 1) { // not handle this in join query + qError("join not supported for stream block scan, %s" PRIx64, id); + return TSDB_CODE_APP_ERROR; } + pOperator->status = OP_NOT_OPENED; + return doSetStreamOpOpen(pOperator->pDownstream[0], id); } return 0; } +static void clearStreamBlock(SOperatorInfo* pOperator) { + if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { + if (pOperator->numOfDownstream == 1) { + return clearStreamBlock(pOperator->pDownstream[0]); + } + } else { + SStreamScanInfo* pInfo = pOperator->info; + doClearBufferedBlocks(pInfo); + } +} + +void resetTaskInfo(qTaskInfo_t tinfo) { + SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; + pTaskInfo->code = 0; + clearStreamBlock(pTaskInfo->pRoot); +} + static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, size_t numOfBlocks, int32_t type, char* id) { - ASSERT(pOperator != NULL); if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { if (pOperator->numOfDownstream == 0) { qError("failed to find stream scan operator to set the input data block, %s" PRIx64, id); @@ -112,25 +129,25 @@ static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, size_t nu pOperator->status = OP_NOT_OPENED; SStreamScanInfo* pInfo = pOperator->info; - - ASSERT(pInfo->validBlockIndex == 0); - ASSERT(taosArrayGetSize(pInfo->pBlockLists) == 0); + qDebug("s-task set source blocks:%d %s", (int32_t)numOfBlocks, id); + ASSERT(pInfo->validBlockIndex == 0 && taosArrayGetSize(pInfo->pBlockLists) == 0); if (type == STREAM_INPUT__MERGED_SUBMIT) { - // ASSERT(numOfBlocks > 1); for (int32_t i = 0; i < numOfBlocks; i++) { - SSubmitReq* pReq = *(void**)POINTER_SHIFT(input, i * sizeof(void*)); - taosArrayPush(pInfo->pBlockLists, &pReq); + SPackedData* pReq = POINTER_SHIFT(input, i * sizeof(SPackedData)); + taosArrayPush(pInfo->pBlockLists, pReq); } pInfo->blockType = STREAM_INPUT__DATA_SUBMIT; } else if (type == STREAM_INPUT__DATA_SUBMIT) { - ASSERT(numOfBlocks == 1); - taosArrayPush(pInfo->pBlockLists, &input); + taosArrayPush(pInfo->pBlockLists, input); pInfo->blockType = STREAM_INPUT__DATA_SUBMIT; } else if (type == STREAM_INPUT__DATA_BLOCK) { for (int32_t i = 0; i < numOfBlocks; ++i) { SSDataBlock* pDataBlock = &((SSDataBlock*)input)[i]; - taosArrayPush(pInfo->pBlockLists, &pDataBlock); + SPackedData tmp = { + .pDataBlock = pDataBlock, + }; + taosArrayPush(pInfo->pBlockLists, &tmp); } pInfo->blockType = STREAM_INPUT__DATA_BLOCK; } else { @@ -141,6 +158,28 @@ static int32_t doSetStreamBlock(SOperatorInfo* pOperator, void* input, size_t nu } } +void doSetTaskId(SOperatorInfo* pOperator) { + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { + SStreamScanInfo* pStreamScanInfo = pOperator->info; + STableScanInfo* pScanInfo = pStreamScanInfo->pTableScanOp->info; + if (pScanInfo->base.dataReader != NULL) { + tsdbReaderSetId(pScanInfo->base.dataReader, pTaskInfo->id.str); + } + } else { + doSetTaskId(pOperator->pDownstream[0]); + } +} + +void qSetTaskId(qTaskInfo_t tinfo, uint64_t taskId, uint64_t queryId) { + SExecTaskInfo* pTaskInfo = tinfo; + pTaskInfo->id.queryId = queryId; + buildTaskId(taskId, queryId, pTaskInfo->id.str); + + // set the idstr for tsdbReader + doSetTaskId(pTaskInfo->pRoot); +} + int32_t qSetStreamOpOpen(qTaskInfo_t tinfo) { if (tinfo == NULL) { return TSDB_CODE_APP_ERROR; @@ -158,6 +197,13 @@ int32_t qSetStreamOpOpen(qTaskInfo_t tinfo) { return code; } +void qGetCheckpointVersion(qTaskInfo_t tinfo, int64_t* dataVer, int64_t* ckId) { + SExecTaskInfo* pTaskInfo = tinfo; + *dataVer = pTaskInfo->streamInfo.dataVersion; + *ckId = pTaskInfo->streamInfo.checkPointId; +} + + int32_t qSetMultiStreamInput(qTaskInfo_t tinfo, const void* pBlocks, size_t numOfBlocks, int32_t type) { if (tinfo == NULL) { return TSDB_CODE_APP_ERROR; @@ -200,37 +246,35 @@ int32_t qSetSMAInput(qTaskInfo_t tinfo, const void* pBlocks, size_t numOfBlocks, return code; } -qTaskInfo_t qCreateQueueExecTaskInfo(void* msg, SReadHandle* readers, int32_t* numOfCols, SSchemaWrapper** pSchema) { - if (msg == NULL) { - // create raw scan - - SExecTaskInfo* pTaskInfo = taosMemoryCalloc(1, sizeof(SExecTaskInfo)); +qTaskInfo_t qCreateQueueExecTaskInfo(void* msg, SReadHandle* pReaderHandle, int32_t vgId, int32_t* numOfCols, + uint64_t id) { + if (msg == NULL) { // create raw scan + SExecTaskInfo* pTaskInfo = doCreateTask(0, id, vgId, OPTR_EXEC_MODEL_QUEUE); if (NULL == pTaskInfo) { terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } - setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED); - - pTaskInfo->cost.created = taosGetTimestampUs(); - pTaskInfo->execModel = OPTR_EXEC_MODEL_QUEUE; - pTaskInfo->pRoot = createRawScanOperatorInfo(readers, pTaskInfo); + pTaskInfo->pRoot = createRawScanOperatorInfo(pReaderHandle, pTaskInfo); if (NULL == pTaskInfo->pRoot) { terrno = TSDB_CODE_OUT_OF_MEMORY; taosMemoryFree(pTaskInfo); return NULL; } + + qDebug("create raw scan task info completed, vgId:%d, %s", vgId, GET_TASKID(pTaskInfo)); return pTaskInfo; } struct SSubplan* pPlan = NULL; - int32_t code = qStringToSubplan(msg, &pPlan); + + int32_t code = qStringToSubplan(msg, &pPlan); if (code != TSDB_CODE_SUCCESS) { terrno = code; return NULL; } qTaskInfo_t pTaskInfo = NULL; - code = qCreateExecTask(readers, 0, 0, pPlan, &pTaskInfo, NULL, NULL, OPTR_EXEC_MODEL_QUEUE); + code = qCreateExecTask(pReaderHandle, vgId, 0, pPlan, &pTaskInfo, NULL, NULL, OPTR_EXEC_MODEL_QUEUE); if (code != TSDB_CODE_SUCCESS) { nodesDestroyNode((SNode*)pPlan); qDestroyTask(pTaskInfo); @@ -250,19 +294,14 @@ qTaskInfo_t qCreateQueueExecTaskInfo(void* msg, SReadHandle* readers, int32_t* n } } - if (pSchema) { - *pSchema = tCloneSSchemaWrapper(((SExecTaskInfo*)pTaskInfo)->schemaInfo.qsw); - } return pTaskInfo; } -qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, SReadHandle* readers) { +qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, SReadHandle* readers, int32_t vgId) { if (msg == NULL) { return NULL; } - /*qDebugL("stream task string %s", (const char*)msg);*/ - struct SSubplan* pPlan = NULL; int32_t code = qStringToSubplan(msg, &pPlan); if (code != TSDB_CODE_SUCCESS) { @@ -271,9 +310,8 @@ qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, SReadHandle* readers) { } qTaskInfo_t pTaskInfo = NULL; - code = qCreateExecTask(readers, 0, 0, pPlan, &pTaskInfo, NULL, NULL, OPTR_EXEC_MODEL_STREAM); + code = qCreateExecTask(readers, vgId, 0, pPlan, &pTaskInfo, NULL, NULL, OPTR_EXEC_MODEL_STREAM); if (code != TSDB_CODE_SUCCESS) { - nodesDestroyNode((SNode*)pPlan); qDestroyTask(pTaskInfo); terrno = code; return NULL; @@ -284,11 +322,22 @@ qTaskInfo_t qCreateStreamExecTaskInfo(void* msg, SReadHandle* readers) { static SArray* filterUnqualifiedTables(const SStreamScanInfo* pScanInfo, const SArray* tableIdList, const char* idstr) { SArray* qa = taosArrayInit(4, sizeof(tb_uid_t)); + int32_t numOfUids = taosArrayGetSize(tableIdList); + if (numOfUids == 0) { + return qa; + } + + STableScanInfo* pTableScanInfo = pScanInfo->pTableScanOp->info; + + uint64_t suid = 0; + uint64_t uid = 0; + int32_t type = 0; + tableListGetSourceTableInfo(pTableScanInfo->base.pTableListInfo, &suid, &uid, &type); // let's discard the tables those are not created according to the queried super table. SMetaReader mr = {0}; metaReaderInit(&mr, pScanInfo->readHandle.meta, 0); - for (int32_t i = 0; i < taosArrayGetSize(tableIdList); ++i) { + for (int32_t i = 0; i < numOfUids; ++i) { uint64_t* id = (uint64_t*)taosArrayGet(tableIdList, i); int32_t code = metaGetTableEntryByUid(&mr, *id); @@ -299,9 +348,21 @@ static SArray* filterUnqualifiedTables(const SStreamScanInfo* pScanInfo, const S tDecoderClear(&mr.coder); - // TODO handle ntb case - if (mr.me.type != TSDB_CHILD_TABLE || mr.me.ctbEntry.suid != pScanInfo->tableUid) { + if (mr.me.type == TSDB_SUPER_TABLE) { continue; + } else { + if (type == TSDB_SUPER_TABLE) { + // this new created child table does not belong to the scanned super table. + if (mr.me.type != TSDB_CHILD_TABLE || mr.me.ctbEntry.suid != suid) { + continue; + } + } else { // ordinary table + // In case that the scanned target table is an ordinary table. When replay the WAL during restore the vnode, we + // should check all newly created ordinary table to make sure that this table isn't the destination table. + if (mr.me.uid != uid) { + continue; + } + } } if (pScanInfo->pTagCond != NULL) { @@ -326,34 +387,29 @@ static SArray* filterUnqualifiedTables(const SStreamScanInfo* pScanInfo, const S return qa; } -int32_t qUpdateQualifiedTableId(qTaskInfo_t tinfo, const SArray* tableIdList, bool isAdd) { +int32_t qUpdateTableListForStreamScanner(qTaskInfo_t tinfo, const SArray* tableIdList, bool isAdd) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; + const char* id = GET_TASKID(pTaskInfo); + int32_t code = 0; if (isAdd) { - qDebug("add %d tables id into query list, %s", (int32_t)taosArrayGetSize(tableIdList), pTaskInfo->id.str); + qDebug("add %d tables id into query list, %s", (int32_t)taosArrayGetSize(tableIdList), id); } // traverse to the stream scanner node to add this table id - SOperatorInfo* pInfo = pTaskInfo->pRoot; - while (pInfo->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { - pInfo = pInfo->pDownstream[0]; - } - - int32_t code = 0; + SOperatorInfo* pInfo = extractOperatorInTree(pTaskInfo->pRoot, QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, id); SStreamScanInfo* pScanInfo = pInfo->info; + if (isAdd) { // add new table id - SArray* qa = filterUnqualifiedTables(pScanInfo, tableIdList, GET_TASKID(pTaskInfo)); + SArray* qa = filterUnqualifiedTables(pScanInfo, tableIdList, id); int32_t numOfQualifiedTables = taosArrayGetSize(qa); - - qDebug(" %d qualified child tables added into stream scanner", numOfQualifiedTables); - + qDebug("%d qualified child tables added into stream scanner, %s", numOfQualifiedTables, id); code = tqReaderAddTbUidList(pScanInfo->tqReader, qa); if (code != TSDB_CODE_SUCCESS) { taosArrayDestroy(qa); return code; } - // todo refactor STableList bool assignUid = false; size_t bufLen = (pScanInfo->pGroupTags != NULL) ? getTableTagsBufLen(pScanInfo->pGroupTags) : 0; char* keyBuf = NULL; @@ -366,7 +422,8 @@ int32_t qUpdateQualifiedTableId(qTaskInfo_t tinfo, const SArray* tableIdList, bo } } - STableListInfo* pTableListInfo = pTaskInfo->pTableInfoList; + STableListInfo* pTableListInfo = ((STableScanInfo*)pScanInfo->pTableScanOp->info)->base.pTableListInfo; + taosWLockLatch(&pTaskInfo->lock); for (int32_t i = 0; i < numOfQualifiedTables; ++i) { uint64_t* uid = taosArrayGet(qa, i); @@ -381,35 +438,26 @@ int32_t qUpdateQualifiedTableId(qTaskInfo_t tinfo, const SArray* tableIdList, bo if (code != TSDB_CODE_SUCCESS) { taosMemoryFree(keyBuf); taosArrayDestroy(qa); + taosWUnLockLatch(&pTaskInfo->lock); return code; } } } -#if 0 - bool exists = false; - for (int32_t k = 0; k < taosArrayGetSize(pListInfo->pTableList); ++k) { - STableKeyInfo* pKeyInfo = taosArrayGet(pListInfo->pTableList, k); - if (pKeyInfo->uid == keyInfo.uid) { - qWarn("ignore duplicated query table uid:%" PRIu64 " added, %s", pKeyInfo->uid, pTaskInfo->id.str); - exists = true; - } - } - - if (!exists) { -#endif - tableListAddTableInfo(pTableListInfo, keyInfo.uid, keyInfo.groupId); } + taosWUnLockLatch(&pTaskInfo->lock); if (keyBuf != NULL) { taosMemoryFree(keyBuf); } taosArrayDestroy(qa); } else { // remove the table id in current list - qDebug(" %d remove child tables from the stream scanner", (int32_t)taosArrayGetSize(tableIdList)); + qDebug("%d remove child tables from the stream scanner, %s", (int32_t)taosArrayGetSize(tableIdList), id); + taosWLockLatch(&pTaskInfo->lock); code = tqReaderRemoveTbUidList(pScanInfo->tqReader, tableIdList); + taosWUnLockLatch(&pTaskInfo->lock); } return code; @@ -442,16 +490,14 @@ int32_t qGetQueryTableSchemaVersion(qTaskInfo_t tinfo, char* dbName, char* table int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId, SSubplan* pSubplan, qTaskInfo_t* pTaskInfo, DataSinkHandle* handle, char* sql, EOPTR_EXEC_MODEL model) { - assert(pSubplan != NULL); SExecTaskInfo** pTask = (SExecTaskInfo**)pTaskInfo; - taosThreadOnce(&initPoolOnce, initRefPool); - qDebug("start to create subplan task, TID:0x%" PRIx64 " QID:0x%" PRIx64, taskId, pSubplan->id.queryId); + qDebug("start to create task, TID:0x%" PRIx64 " QID:0x%" PRIx64 ", vgId:%d", taskId, pSubplan->id.queryId, vgId); - int32_t code = createExecTaskInfoImpl(pSubplan, pTask, readHandle, taskId, sql, model); + int32_t code = createExecTaskInfo(pSubplan, pTask, readHandle, taskId, vgId, sql, model); if (code != TSDB_CODE_SUCCESS) { - qError("failed to createExecTaskInfoImpl, code: %s", tstrerror(code)); + qError("failed to createExecTaskInfo, code: %s", tstrerror(code)); goto _error; } @@ -464,16 +510,14 @@ int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId, if (handle) { void* pSinkParam = NULL; - code = createDataSinkParam(pSubplan->pDataSink, &pSinkParam, pTaskInfo, readHandle); + code = createDataSinkParam(pSubplan->pDataSink, &pSinkParam, (*pTask), readHandle); if (code != TSDB_CODE_SUCCESS) { qError("failed to createDataSinkParam, vgId:%d, code:%s, %s", vgId, tstrerror(code), (*pTask)->id.str); goto _error; } + // pSinkParam has been freed during create sinker. code = dsCreateDataSinker(pSubplan->pDataSink, handle, pSinkParam, (*pTask)->id.str); - if (code != TSDB_CODE_SUCCESS) { - taosMemoryFreeClear(pSinkParam); - } } qDebug("subplan task create completed, TID:0x%" PRIx64 " QID:0x%" PRIx64, taskId, pSubplan->id.queryId); @@ -604,6 +648,7 @@ int32_t qExecTask(qTaskInfo_t tinfo, SSDataBlock** pRes, uint64_t* useconds) { } if (isTaskKilled(pTaskInfo)) { + clearStreamBlock(pTaskInfo->pRoot); atomic_store_64(&pTaskInfo->owner, 0); qDebug("%s already killed, abort", GET_TASKID(pTaskInfo)); return TSDB_CODE_SUCCESS; @@ -671,8 +716,6 @@ void qRemoveTaskStopInfo(SExecTaskInfo* pTaskInfo, SExchangeOpStopInfo* pInfo) { taosArrayRemove(pTaskInfo->stopInfo.pStopInfo, idx); } taosWUnLockLatch(&pTaskInfo->stopInfo.lock); - - return; } void qStopTaskOperators(SExecTaskInfo* pTaskInfo) { @@ -693,7 +736,6 @@ void qStopTaskOperators(SExecTaskInfo* pTaskInfo) { int32_t qAsyncKillTask(qTaskInfo_t qinfo, int32_t rspCode) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)qinfo; - if (pTaskInfo == NULL) { return TSDB_CODE_QRY_INVALID_QHANDLE; } @@ -701,12 +743,28 @@ int32_t qAsyncKillTask(qTaskInfo_t qinfo, int32_t rspCode) { qDebug("%s execTask async killed", GET_TASKID(pTaskInfo)); setTaskKilled(pTaskInfo, rspCode); - qStopTaskOperators(pTaskInfo); return TSDB_CODE_SUCCESS; } +int32_t qKillTask(qTaskInfo_t tinfo, int32_t rspCode) { + SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; + if (pTaskInfo == NULL) { + return TSDB_CODE_QRY_INVALID_QHANDLE; + } + + qDebug("%s sync killed execTask", GET_TASKID(pTaskInfo)); + setTaskKilled(pTaskInfo, TSDB_CODE_TSC_QUERY_KILLED); + + while (qTaskIsExecuting(pTaskInfo)) { + taosMsleep(10); + } + + pTaskInfo->code = rspCode; + return TSDB_CODE_SUCCESS; +} + bool qTaskIsExecuting(qTaskInfo_t qinfo) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)qinfo; if (NULL == pTaskInfo) { @@ -741,7 +799,11 @@ void qDestroyTask(qTaskInfo_t qTaskHandle) { return; } - qDebug("%s execTask completed, numOfRows:%" PRId64, GET_TASKID(pTaskInfo), pTaskInfo->pRoot->resultInfo.totalRows); + if (pTaskInfo->pRoot != NULL) { + qDebug("%s execTask completed, numOfRows:%" PRId64, GET_TASKID(pTaskInfo), pTaskInfo->pRoot->resultInfo.totalRows); + } else { + qDebug("%s execTask completed", GET_TASKID(pTaskInfo)); + } printTaskExecCostInLog(pTaskInfo); // print the query cost summary doDestroyTask(pTaskInfo); @@ -794,15 +856,6 @@ int32_t qExtractStreamScanner(qTaskInfo_t tinfo, void** scanner) { } } -#if 0 -int32_t qStreamInput(qTaskInfo_t tinfo, void* pItem) { - SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; - ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_STREAM); - taosWriteQitem(pTaskInfo->streamInfo.inputQueue->queue, pItem); - return 0; -} -#endif - int32_t qStreamSourceRecoverStep1(qTaskInfo_t tinfo, int64_t ver) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_STREAM); @@ -837,8 +890,7 @@ int32_t qStreamSetParamForRecover(qTaskInfo_t tinfo) { SStreamIntervalOperatorInfo* pInfo = pOperator->info; ASSERT(pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE || pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE); - ASSERT(pInfo->twAggSup.calTriggerSaved == 0); - ASSERT(pInfo->twAggSup.deleteMarkSaved == 0); + ASSERT(pInfo->twAggSup.calTriggerSaved == 0 && pInfo->twAggSup.deleteMarkSaved == 0); qInfo("save stream param for interval: %d, %" PRId64, pInfo->twAggSup.calTrigger, pInfo->twAggSup.deleteMark); @@ -846,28 +898,29 @@ int32_t qStreamSetParamForRecover(qTaskInfo_t tinfo) { pInfo->twAggSup.deleteMarkSaved = pInfo->twAggSup.deleteMark; pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE; pInfo->twAggSup.deleteMark = INT64_MAX; - + pInfo->ignoreExpiredDataSaved = pInfo->ignoreExpiredData; + pInfo->ignoreExpiredData = false; } else if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION || pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION || pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) { SStreamSessionAggOperatorInfo* pInfo = pOperator->info; ASSERT(pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE || pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE); - ASSERT(pInfo->twAggSup.calTriggerSaved == 0); - ASSERT(pInfo->twAggSup.deleteMarkSaved == 0); + ASSERT(pInfo->twAggSup.calTriggerSaved == 0 && pInfo->twAggSup.deleteMarkSaved == 0); qInfo("save stream param for session: %d, %" PRId64, pInfo->twAggSup.calTrigger, pInfo->twAggSup.deleteMark); pInfo->twAggSup.calTriggerSaved = pInfo->twAggSup.calTrigger; pInfo->twAggSup.deleteMarkSaved = pInfo->twAggSup.deleteMark; pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE; pInfo->twAggSup.deleteMark = INT64_MAX; + pInfo->ignoreExpiredDataSaved = pInfo->ignoreExpiredData; + pInfo->ignoreExpiredData = false; } else if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE) { SStreamStateAggOperatorInfo* pInfo = pOperator->info; ASSERT(pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE || pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE); - ASSERT(pInfo->twAggSup.calTriggerSaved == 0); - ASSERT(pInfo->twAggSup.deleteMarkSaved == 0); + ASSERT(pInfo->twAggSup.calTriggerSaved == 0 && pInfo->twAggSup.deleteMarkSaved == 0); qInfo("save stream param for state: %d, %" PRId64, pInfo->twAggSup.calTrigger, pInfo->twAggSup.deleteMark); @@ -875,6 +928,8 @@ int32_t qStreamSetParamForRecover(qTaskInfo_t tinfo) { pInfo->twAggSup.deleteMarkSaved = pInfo->twAggSup.deleteMark; pInfo->twAggSup.calTrigger = STREAM_TRIGGER_AT_ONCE; pInfo->twAggSup.deleteMark = INT64_MAX; + pInfo->ignoreExpiredDataSaved = pInfo->ignoreExpiredData; + pInfo->ignoreExpiredData = false; } // iterate operator tree @@ -902,35 +957,23 @@ int32_t qStreamRestoreParam(qTaskInfo_t tinfo) { pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL || pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL) { SStreamIntervalOperatorInfo* pInfo = pOperator->info; - /*ASSERT(pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE);*/ - /*ASSERT(pInfo->twAggSup.deleteMark == INT64_MAX);*/ - pInfo->twAggSup.calTrigger = pInfo->twAggSup.calTriggerSaved; pInfo->twAggSup.deleteMark = pInfo->twAggSup.deleteMarkSaved; - /*ASSERT(pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE ||*/ - /*pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE);*/ + pInfo->ignoreExpiredData = pInfo->ignoreExpiredDataSaved; qInfo("restore stream param for interval: %d, %" PRId64, pInfo->twAggSup.calTrigger, pInfo->twAggSup.deleteMark); } else if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION || pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION || pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION) { SStreamSessionAggOperatorInfo* pInfo = pOperator->info; - /*ASSERT(pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE);*/ - /*ASSERT(pInfo->twAggSup.deleteMark == INT64_MAX);*/ - pInfo->twAggSup.calTrigger = pInfo->twAggSup.calTriggerSaved; pInfo->twAggSup.deleteMark = pInfo->twAggSup.deleteMarkSaved; - /*ASSERT(pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE ||*/ - /*pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE);*/ + pInfo->ignoreExpiredData = pInfo->ignoreExpiredDataSaved; qInfo("restore stream param for session: %d, %" PRId64, pInfo->twAggSup.calTrigger, pInfo->twAggSup.deleteMark); } else if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE) { SStreamStateAggOperatorInfo* pInfo = pOperator->info; - /*ASSERT(pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE);*/ - /*ASSERT(pInfo->twAggSup.deleteMark == INT64_MAX);*/ - pInfo->twAggSup.calTrigger = pInfo->twAggSup.calTriggerSaved; pInfo->twAggSup.deleteMark = pInfo->twAggSup.deleteMarkSaved; - /*ASSERT(pInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE ||*/ - /*pInfo->twAggSup.calTrigger == STREAM_TRIGGER_WINDOW_CLOSE);*/ + pInfo->ignoreExpiredData = pInfo->ignoreExpiredDataSaved; qInfo("restore stream param for state: %d, %" PRId64, pInfo->twAggSup.calTrigger, pInfo->twAggSup.deleteMark); } @@ -938,7 +981,6 @@ int32_t qStreamRestoreParam(qTaskInfo_t tinfo) { if (pOperator->numOfDownstream != 1 || pOperator->pDownstream[0] == NULL) { if (pOperator->numOfDownstream > 1) { qError("unexpected stream, multiple downstream"); - /*ASSERT(0);*/ return -1; } return 0; @@ -948,6 +990,7 @@ int32_t qStreamRestoreParam(qTaskInfo_t tinfo) { } return 0; } + bool qStreamRecoverScanFinished(qTaskInfo_t tinfo) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; return pTaskInfo->streamInfo.recoverScanFinished; @@ -970,21 +1013,12 @@ const char* qExtractTbnameFromTask(qTaskInfo_t tinfo) { SMqMetaRsp* qStreamExtractMetaMsg(qTaskInfo_t tinfo) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; - ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE); return &pTaskInfo->streamInfo.metaRsp; } -int64_t qStreamExtractPrepareUid(qTaskInfo_t tinfo) { +void qStreamExtractOffset(qTaskInfo_t tinfo, STqOffsetVal* pOffset) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; - ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE); - return pTaskInfo->streamInfo.prepareStatus.uid; -} - -int32_t qStreamExtractOffset(qTaskInfo_t tinfo, STqOffsetVal* pOffset) { - SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; - ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE); - memcpy(pOffset, &pTaskInfo->streamInfo.lastStatus, sizeof(STqOffsetVal)); - return 0; + memcpy(pOffset, &pTaskInfo->streamInfo.currentOffset, sizeof(STqOffsetVal)); } int32_t initQueryTableDataCondForTmq(SQueryTableDataCond* pCond, SSnapContext* sContext, SMetaTableInfo* pMtInfo) { @@ -1018,173 +1052,204 @@ int32_t initQueryTableDataCondForTmq(SQueryTableDataCond* pCond, SSnapContext* s return TSDB_CODE_SUCCESS; } -int32_t qStreamScanMemData(qTaskInfo_t tinfo, const SSubmitReq* pReq) { +void qStreamSetOpen(qTaskInfo_t tinfo) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; - ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE); - ASSERT(pTaskInfo->streamInfo.pReq == NULL); - pTaskInfo->streamInfo.pReq = pReq; - return 0; + SOperatorInfo* pOperator = pTaskInfo->pRoot; + pOperator->status = OP_NOT_OPENED; +} + +void verifyOffset(void *pWalReader, STqOffsetVal* pOffset){ + // if offset version is small than first version , let's seek to first version + taosThreadMutexLock(&((SWalReader*)pWalReader)->pWal->mutex); + int64_t firstVer = walGetFirstVer(((SWalReader*)pWalReader)->pWal); + taosThreadMutexUnlock(&((SWalReader*)pWalReader)->pWal->mutex); + + if (pOffset->version + 1 < firstVer){ + pOffset->version = firstVer - 1; + } } int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subType) { SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)tinfo; SOperatorInfo* pOperator = pTaskInfo->pRoot; - ASSERT(pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE); - pTaskInfo->streamInfo.prepareStatus = *pOffset; - pTaskInfo->streamInfo.returned = 0; - if (tOffsetEqual(pOffset, &pTaskInfo->streamInfo.lastStatus)) { + const char* id = GET_TASKID(pTaskInfo); + + // if pOffset equal to current offset, means continue consume + if (tOffsetEqual(pOffset, &pTaskInfo->streamInfo.currentOffset)) { return 0; } + if (subType == TOPIC_SUB_TYPE__COLUMN) { - uint16_t type = pOperator->operatorType; - pOperator->status = OP_OPENED; - // TODO add more check - if (type != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { - ASSERT(pOperator->numOfDownstream == 1); - pOperator = pOperator->pDownstream[0]; + pOperator = extractOperatorInTree(pOperator, QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, id); + if (pOperator == NULL) { + return -1; } SStreamScanInfo* pInfo = pOperator->info; + STableScanInfo* pScanInfo = pInfo->pTableScanOp->info; + STableScanBase* pScanBaseInfo = &pScanInfo->base; + STableListInfo* pTableListInfo = pScanBaseInfo->pTableListInfo; + if (pOffset->type == TMQ_OFFSET__LOG) { - STableScanInfo* pTSInfo = pInfo->pTableScanOp->info; - tsdbReaderClose(pTSInfo->base.dataReader); - pTSInfo->base.dataReader = NULL; -#if 0 - if (tOffsetEqual(pOffset, &pTaskInfo->streamInfo.lastStatus) && - pInfo->tqReader->pWalReader->curVersion != pOffset->version) { - qError("prepare scan ver %" PRId64 " actual ver %" PRId64 ", last %" PRId64, pOffset->version, - pInfo->tqReader->pWalReader->curVersion, pTaskInfo->streamInfo.lastStatus.version); - ASSERT(0); - } -#endif - if (tqSeekVer(pInfo->tqReader, pOffset->version + 1) < 0) { + // todo refactor: move away + tsdbReaderClose(pScanBaseInfo->dataReader); + pScanBaseInfo->dataReader = NULL; + + verifyOffset(pInfo->tqReader->pWalReader, pOffset); + if (tqSeekVer(pInfo->tqReader, pOffset->version + 1, id) < 0) { + qError("tqSeekVer failed ver:%" PRId64 ", %s", pOffset->version + 1, id); return -1; } - ASSERT(pInfo->tqReader->pWalReader->curVersion == pOffset->version + 1); } else if (pOffset->type == TMQ_OFFSET__SNAPSHOT_DATA) { - /*pInfo->blockType = STREAM_INPUT__TABLE_SCAN;*/ + // iterate all tables from tableInfoList, and retrieve rows from each table one-by-one + // those data are from the snapshot in tsdb, besides the data in the wal file. int64_t uid = pOffset->uid; int64_t ts = pOffset->ts; + int32_t index = 0; + + // this value may be changed if new tables are created + taosRLockLatch(&pTaskInfo->lock); + int32_t numOfTables = tableListGetSize(pTableListInfo); if (uid == 0) { - if (tableListGetSize(pTaskInfo->pTableInfoList) != 0) { - STableKeyInfo* pTableInfo = tableListGetInfo(pTaskInfo->pTableInfoList, 0); + if (numOfTables != 0) { + STableKeyInfo* pTableInfo = tableListGetInfo(pTableListInfo, 0); uid = pTableInfo->uid; ts = INT64_MIN; + pScanInfo->currentTable = 0; } else { + taosRUnLockLatch(&pTaskInfo->lock); + qError("no table in table list, %s", id); + terrno = TSDB_CODE_PAR_INTERNAL_ERROR; return -1; } } - /*if (pTaskInfo->streamInfo.lastStatus.type != TMQ_OFFSET__SNAPSHOT_DATA ||*/ - /*pTaskInfo->streamInfo.lastStatus.uid != uid || pTaskInfo->streamInfo.lastStatus.ts != ts) {*/ - STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info; - int32_t numOfTables = tableListGetSize(pTaskInfo->pTableInfoList); - -#ifndef NDEBUG - qDebug("switch to next table %" PRId64 " (cursor %d), %" PRId64 " rows returned", uid, - pTableScanInfo->currentTable, pInfo->pTableScanOp->resultInfo.totalRows); + qDebug("switch to table uid:%" PRId64 " ts:%" PRId64 "% " PRId64 " rows returned", uid, ts, + pInfo->pTableScanOp->resultInfo.totalRows); pInfo->pTableScanOp->resultInfo.totalRows = 0; -#endif - - bool found = false; - for (int32_t i = 0; i < numOfTables; i++) { - STableKeyInfo* pTableInfo = tableListGetInfo(pTaskInfo->pTableInfoList, i); - if (pTableInfo->uid == uid) { - found = true; - pTableScanInfo->currentTable = i; - break; - } + + // start from current accessed position + // we cannot start from the pScanInfo->currentTable, since the commit offset may cause the rollback of the start + // position, let's find it from the beginning. + index = tableListFind(pTableListInfo, uid, 0); + taosRUnLockLatch(&pTaskInfo->lock); + + if (index >= 0) { + pScanInfo->currentTable = index; + } else { + qError("vgId:%d uid:%" PRIu64 " not found in table list, total:%d, index:%d %s", pTaskInfo->id.vgId, uid, + numOfTables, pScanInfo->currentTable, id); + terrno = TSDB_CODE_PAR_INTERNAL_ERROR; + return -1; } - // TODO after dropping table, table may not found - ASSERT(found); + STableKeyInfo keyInfo = {.uid = uid}; + int64_t oldSkey = pScanBaseInfo->cond.twindows.skey; - if (pTableScanInfo->base.dataReader == NULL) { - STableKeyInfo* pList = tableListGetInfo(pTaskInfo->pTableInfoList, 0); - int32_t num = tableListGetSize(pTaskInfo->pTableInfoList); + // let's start from the next ts that returned to consumer. + pScanBaseInfo->cond.twindows.skey = ts + 1; + pScanInfo->scanTimes = 0; - if (tsdbReaderOpen(pTableScanInfo->base.readHandle.vnode, &pTableScanInfo->base.cond, pList, num, - pTableScanInfo->pResBlock, &pTableScanInfo->base.dataReader, NULL) < 0 || - pTableScanInfo->base.dataReader == NULL) { - ASSERT(0); + if (pScanBaseInfo->dataReader == NULL) { + int32_t code = tsdbReaderOpen(pScanBaseInfo->readHandle.vnode, &pScanBaseInfo->cond, &keyInfo, 1, + pScanInfo->pResBlock, &pScanBaseInfo->dataReader, id, false, NULL); + if (code != TSDB_CODE_SUCCESS) { + qError("prepare read tsdb snapshot failed, uid:%" PRId64 ", code:%s %s", pOffset->uid, tstrerror(code), id); + terrno = code; + return -1; } + + qDebug("tsdb reader created with offset(snapshot) uid:%" PRId64 " ts:%" PRId64 " table index:%d, total:%d, %s", + uid, pScanBaseInfo->cond.twindows.skey, pScanInfo->currentTable, numOfTables, id); + } else { + tsdbSetTableList(pScanBaseInfo->dataReader, &keyInfo, 1); + tsdbReaderReset(pScanBaseInfo->dataReader, &pScanBaseInfo->cond); + qDebug("tsdb reader offset seek snapshot to uid:%" PRId64 " ts %" PRId64 " table index:%d numOfTable:%d, %s", + uid, pScanBaseInfo->cond.twindows.skey, pScanInfo->currentTable, numOfTables, id); } - STableKeyInfo tki = {.uid = uid}; - tsdbSetTableList(pTableScanInfo->base.dataReader, &tki, 1); - int64_t oldSkey = pTableScanInfo->base.cond.twindows.skey; - pTableScanInfo->base.cond.twindows.skey = ts + 1; - tsdbReaderReset(pTableScanInfo->base.dataReader, &pTableScanInfo->base.cond); - pTableScanInfo->base.cond.twindows.skey = oldSkey; - pTableScanInfo->scanTimes = 0; - - qDebug("tsdb reader offset seek to uid %" PRId64 " ts %" PRId64 ", table cur set to %d , all table num %d", uid, - ts, pTableScanInfo->currentTable, numOfTables); - /*}*/ + // restore the key value + pScanBaseInfo->cond.twindows.skey = oldSkey; } else { - ASSERT(0); - } - } else if (pOffset->type == TMQ_OFFSET__SNAPSHOT_DATA) { - SStreamRawScanInfo* pInfo = pOperator->info; - SSnapContext* sContext = pInfo->sContext; - if (setForSnapShot(sContext, pOffset->uid) != 0) { - qError("setDataForSnapShot error. uid:%" PRIi64, pOffset->uid); + qError("invalid pOffset->type:%d, %s", pOffset->type, id); + terrno = TSDB_CODE_PAR_INTERNAL_ERROR; return -1; } - SMetaTableInfo mtInfo = getUidfromSnapShot(sContext); - tsdbReaderClose(pInfo->dataReader); - pInfo->dataReader = NULL; + } else { // subType == TOPIC_SUB_TYPE__TABLE/TOPIC_SUB_TYPE__DB - cleanupQueryTableDataCond(&pTaskInfo->streamInfo.tableCond); - tableListClear(pTaskInfo->pTableInfoList); + if (pOffset->type == TMQ_OFFSET__SNAPSHOT_DATA) { + SStreamRawScanInfo* pInfo = pOperator->info; + SSnapContext* sContext = pInfo->sContext; - if (mtInfo.uid == 0) { - return 0; // no data - } + SOperatorInfo* p = extractOperatorInTree(pOperator, QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, id); + STableListInfo* pTableListInfo = ((SStreamRawScanInfo*)(p->info))->pTableListInfo; + + if (setForSnapShot(sContext, pOffset->uid) != 0) { + qError("setDataForSnapShot error. uid:%" PRId64 " , %s", pOffset->uid, id); + terrno = TSDB_CODE_PAR_INTERNAL_ERROR; + return -1; + } - initQueryTableDataCondForTmq(&pTaskInfo->streamInfo.tableCond, sContext, &mtInfo); - pTaskInfo->streamInfo.tableCond.twindows.skey = pOffset->ts; + SMetaTableInfo mtInfo = getUidfromSnapShot(sContext); + tsdbReaderClose(pInfo->dataReader); + pInfo->dataReader = NULL; - if (pTaskInfo->pTableInfoList == NULL) { - pTaskInfo->pTableInfoList = tableListCreate(); - } + cleanupQueryTableDataCond(&pTaskInfo->streamInfo.tableCond); + tableListClear(pTableListInfo); - tableListAddTableInfo(pTaskInfo->pTableInfoList, mtInfo.uid, 0); + if (mtInfo.uid == 0) { + goto end; // no data + } - STableKeyInfo* pList = tableListGetInfo(pTaskInfo->pTableInfoList, 0); - int32_t size = tableListGetSize(pTaskInfo->pTableInfoList); - ASSERT(size == 1); + initQueryTableDataCondForTmq(&pTaskInfo->streamInfo.tableCond, sContext, &mtInfo); + pTaskInfo->streamInfo.tableCond.twindows.skey = pOffset->ts; - tsdbReaderOpen(pInfo->vnode, &pTaskInfo->streamInfo.tableCond, pList, size, NULL, &pInfo->dataReader, NULL); + tableListAddTableInfo(pTableListInfo, mtInfo.uid, 0); - cleanupQueryTableDataCond(&pTaskInfo->streamInfo.tableCond); - strcpy(pTaskInfo->streamInfo.tbName, mtInfo.tbName); - tDeleteSSchemaWrapper(pTaskInfo->streamInfo.schema); - pTaskInfo->streamInfo.schema = mtInfo.schema; + STableKeyInfo* pList = tableListGetInfo(pTableListInfo, 0); + int32_t size = tableListGetSize(pTableListInfo); - qDebug("tmqsnap qStreamPrepareScan snapshot data uid %" PRId64 " ts %" PRId64, mtInfo.uid, pOffset->ts); - } else if (pOffset->type == TMQ_OFFSET__SNAPSHOT_META) { - SStreamRawScanInfo* pInfo = pOperator->info; - SSnapContext* sContext = pInfo->sContext; - if (setForSnapShot(sContext, pOffset->uid) != 0) { - qError("setForSnapShot error. uid:%" PRIu64 " ,version:%" PRId64, pOffset->uid, pOffset->version); - return -1; + tsdbReaderOpen(pInfo->vnode, &pTaskInfo->streamInfo.tableCond, pList, size, NULL, &pInfo->dataReader, NULL, + false, NULL); + + cleanupQueryTableDataCond(&pTaskInfo->streamInfo.tableCond); + strcpy(pTaskInfo->streamInfo.tbName, mtInfo.tbName); + tDeleteSchemaWrapper(pTaskInfo->streamInfo.schema); + pTaskInfo->streamInfo.schema = mtInfo.schema; + + qDebug("tmqsnap qStreamPrepareScan snapshot data uid:%" PRId64 " ts %" PRId64 " %s", mtInfo.uid, pOffset->ts, id); + } else if (pOffset->type == TMQ_OFFSET__SNAPSHOT_META) { + SStreamRawScanInfo* pInfo = pOperator->info; + SSnapContext* sContext = pInfo->sContext; + if (setForSnapShot(sContext, pOffset->uid) != 0) { + qError("setForSnapShot error. uid:%" PRIu64 " ,version:%" PRId64, pOffset->uid, pOffset->version); + terrno = TSDB_CODE_PAR_INTERNAL_ERROR; + return -1; + } + qDebug("tmqsnap qStreamPrepareScan snapshot meta uid:%" PRId64 " ts %" PRId64 " %s", pOffset->uid, pOffset->ts, + id); + } else if (pOffset->type == TMQ_OFFSET__LOG) { + SStreamRawScanInfo* pInfo = pOperator->info; + tsdbReaderClose(pInfo->dataReader); + pInfo->dataReader = NULL; + qDebug("tmqsnap qStreamPrepareScan snapshot log, %s", id); } - qDebug("tmqsnap qStreamPrepareScan snapshot meta uid %" PRId64 " ts %" PRId64, pOffset->uid, pOffset->ts); - } else if (pOffset->type == TMQ_OFFSET__LOG) { - SStreamRawScanInfo* pInfo = pOperator->info; - tsdbReaderClose(pInfo->dataReader); - pInfo->dataReader = NULL; - qDebug("tmqsnap qStreamPrepareScan snapshot log"); } + +end: + pTaskInfo->streamInfo.currentOffset = *pOffset; + return 0; } void qProcessRspMsg(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) { SMsgSendInfo* pSendInfo = (SMsgSendInfo*)pMsg->info.ahandle; - assert(pMsg->info.ahandle != NULL); + if (pMsg->info.ahandle == NULL) { + qError("pMsg->info.ahandle is NULL"); + return; + } SDataBuf buf = {.len = pMsg->contLen, .pData = NULL}; @@ -1202,3 +1267,44 @@ void qProcessRspMsg(void* parent, SRpcMsg* pMsg, SEpSet* pEpSet) { rpcFreeCont(pMsg->pCont); destroySendMsgInfo(pSendInfo); } + +SArray* qGetQueriedTableListInfo(qTaskInfo_t tinfo) { + SExecTaskInfo* pTaskInfo = tinfo; + SArray* plist = getTableListInfo(pTaskInfo); + + // only extract table in the first elements + STableListInfo* pTableListInfo = taosArrayGetP(plist, 0); + + SArray* pUidList = taosArrayInit(10, sizeof(uint64_t)); + + int32_t numOfTables = tableListGetSize(pTableListInfo); + for(int32_t i = 0; i < numOfTables; ++i) { + STableKeyInfo* pKeyInfo = tableListGetInfo(pTableListInfo, i); + taosArrayPush(pUidList, &pKeyInfo->uid); + } + + taosArrayDestroy(plist); + return pUidList; +} + +static void extractTableList(SArray* pList, const SOperatorInfo* pOperator) { + if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { + SStreamScanInfo* pScanInfo = pOperator->info; + STableScanInfo* pTableScanInfo = pScanInfo->pTableScanOp->info; + taosArrayPush(pList, &pTableScanInfo->base.pTableListInfo); + } else if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) { + STableScanInfo* pScanInfo = pOperator->info; + taosArrayPush(pList, &pScanInfo->base.pTableListInfo); + } else { + if (pOperator->pDownstream != NULL && pOperator->pDownstream[0] != NULL) { + extractTableList(pList, pOperator->pDownstream[0]); + } + } +} + +SArray* getTableListInfo(const SExecTaskInfo* pTaskInfo) { + SArray* pArray = taosArrayInit(0, POINTER_BYTES); + SOperatorInfo* pOperator = pTaskInfo->pRoot; + extractTableList(pArray, pOperator); + return pArray; +} \ No newline at end of file diff --git a/source/libs/executor/src/executorInt.c b/source/libs/executor/src/executorInt.c new file mode 100644 index 0000000000000000000000000000000000000000..89fa10b704c8b4a5a5917931ed61e37aed9a8c9e --- /dev/null +++ b/source/libs/executor/src/executorInt.c @@ -0,0 +1,1308 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "filter.h" +#include "function.h" +#include "functionMgt.h" +#include "os.h" +#include "querynodes.h" +#include "tfill.h" +#include "tname.h" + +#include "tdatablock.h" +#include "tmsg.h" +#include "ttime.h" + +#include "executorInt.h" +#include "index.h" +#include "operator.h" +#include "query.h" +#include "querytask.h" +#include "tcompare.h" +#include "thash.h" +#include "ttypes.h" +#include "vnode.h" + +#define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN) +#define GET_FORWARD_DIRECTION_FACTOR(ord) (((ord) == TSDB_ORDER_ASC) ? QUERY_ASC_FORWARD_STEP : QUERY_DESC_FORWARD_STEP) + +#if 0 +static UNUSED_FUNC void *u_malloc (size_t __size) { + uint32_t v = taosRand(); + + if (v % 1000 <= 0) { + return NULL; + } else { + return taosMemoryMalloc(__size); + } +} + +static UNUSED_FUNC void* u_calloc(size_t num, size_t __size) { + uint32_t v = taosRand(); + if (v % 1000 <= 0) { + return NULL; + } else { + return taosMemoryCalloc(num, __size); + } +} + +static UNUSED_FUNC void* u_realloc(void* p, size_t __size) { + uint32_t v = taosRand(); + if (v % 5 <= 1) { + return NULL; + } else { + return taosMemoryRealloc(p, __size); + } +} + +#define calloc u_calloc +#define malloc u_malloc +#define realloc u_realloc +#endif + +static void setBlockSMAInfo(SqlFunctionCtx* pCtx, SExprInfo* pExpr, SSDataBlock* pBlock); + +static void initCtxOutputBuffer(SqlFunctionCtx* pCtx, int32_t size); +static void doApplyScalarCalculation(SOperatorInfo* pOperator, SSDataBlock* pBlock, int32_t order, int32_t scanFlag); + +static void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const SColumnInfoData* p, bool keep, + int32_t status); +static int32_t doSetInputDataBlock(SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t order, int32_t scanFlag, + bool createDummyCol); +static int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprSupp* pSup, SDiskbasedBuf* pBuf, + SGroupResInfo* pGroupResInfo, int32_t threshold, bool ignoreGroup); + +SResultRow* getNewResultRow(SDiskbasedBuf* pResultBuf, int32_t* currentPageId, int32_t interBufSize) { + SFilePage* pData = NULL; + + // in the first scan, new space needed for results + int32_t pageId = -1; + if (*currentPageId == -1) { + pData = getNewBufPage(pResultBuf, &pageId); + pData->num = sizeof(SFilePage); + } else { + pData = getBufPage(pResultBuf, *currentPageId); + if (pData == NULL) { + qError("failed to get buffer, code:%s", tstrerror(terrno)); + return NULL; + } + + pageId = *currentPageId; + + if (pData->num + interBufSize > getBufPageSize(pResultBuf)) { + // release current page first, and prepare the next one + releaseBufPage(pResultBuf, pData); + + pData = getNewBufPage(pResultBuf, &pageId); + if (pData != NULL) { + pData->num = sizeof(SFilePage); + } + } + } + + if (pData == NULL) { + return NULL; + } + + setBufPageDirty(pData, true); + + // set the number of rows in current disk page + SResultRow* pResultRow = (SResultRow*)((char*)pData + pData->num); + + memset((char*)pResultRow, 0, interBufSize); + pResultRow->pageId = pageId; + pResultRow->offset = (int32_t)pData->num; + + *currentPageId = pageId; + pData->num += interBufSize; + return pResultRow; +} + +/** + * the struct of key in hash table + * +----------+---------------+ + * | group id | key data | + * | 8 bytes | actual length | + * +----------+---------------+ + */ +SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pResultRowInfo, char* pData, + int16_t bytes, bool masterscan, uint64_t groupId, SExecTaskInfo* pTaskInfo, + bool isIntervalQuery, SAggSupporter* pSup, bool keepGroup) { + SET_RES_WINDOW_KEY(pSup->keyBuf, pData, bytes, groupId); + if (!keepGroup) { + *(uint64_t*)pSup->keyBuf = calcGroupId(pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes)); + } + + SResultRowPosition* p1 = + (SResultRowPosition*)tSimpleHashGet(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes)); + + SResultRow* pResult = NULL; + + // in case of repeat scan/reverse scan, no new time window added. + if (isIntervalQuery) { + if (p1 != NULL) { // the *p1 may be NULL in case of sliding+offset exists. + pResult = getResultRowByPos(pResultBuf, p1, true); + if (NULL == pResult) { + T_LONG_JMP(pTaskInfo->env, terrno); + } + + ASSERT(pResult->pageId == p1->pageId && pResult->offset == p1->offset); + } + } else { + // In case of group by column query, the required SResultRow object must be existInCurrentResusltRowInfo in the + // pResultRowInfo object. + if (p1 != NULL) { + // todo + pResult = getResultRowByPos(pResultBuf, p1, true); + if (NULL == pResult) { + T_LONG_JMP(pTaskInfo->env, terrno); + } + + ASSERT(pResult->pageId == p1->pageId && pResult->offset == p1->offset); + } + } + + // 1. close current opened time window + if (pResultRowInfo->cur.pageId != -1 && ((pResult == NULL) || (pResult->pageId != pResultRowInfo->cur.pageId))) { + SResultRowPosition pos = pResultRowInfo->cur; + SFilePage* pPage = getBufPage(pResultBuf, pos.pageId); + if (pPage == NULL) { + qError("failed to get buffer, code:%s, %s", tstrerror(terrno), GET_TASKID(pTaskInfo)); + T_LONG_JMP(pTaskInfo->env, terrno); + } + releaseBufPage(pResultBuf, pPage); + } + + // allocate a new buffer page + if (pResult == NULL) { + pResult = getNewResultRow(pResultBuf, &pSup->currentPageId, pSup->resultRowSize); + if (pResult == NULL) { + T_LONG_JMP(pTaskInfo->env, terrno); + } + + // add a new result set for a new group + SResultRowPosition pos = {.pageId = pResult->pageId, .offset = pResult->offset}; + tSimpleHashPut(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes), &pos, + sizeof(SResultRowPosition)); + } + + // 2. set the new time window to be the new active time window + pResultRowInfo->cur = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset}; + + // too many time window in query + if (pTaskInfo->execModel == OPTR_EXEC_MODEL_BATCH && + tSimpleHashGetSize(pSup->pResultRowHashTable) > MAX_INTERVAL_TIME_WINDOW) { + T_LONG_JMP(pTaskInfo->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW); + } + + return pResult; +} + +// query_range_start, query_range_end, window_duration, window_start, window_end +void initExecTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pQueryWindow) { + pColData->info.type = TSDB_DATA_TYPE_TIMESTAMP; + pColData->info.bytes = sizeof(int64_t); + + colInfoDataEnsureCapacity(pColData, 5, false); + colDataSetInt64(pColData, 0, &pQueryWindow->skey); + colDataSetInt64(pColData, 1, &pQueryWindow->ekey); + + int64_t interval = 0; + colDataSetInt64(pColData, 2, &interval); // this value may be variable in case of 'n' and 'y'. + colDataSetInt64(pColData, 3, &pQueryWindow->skey); + colDataSetInt64(pColData, 4, &pQueryWindow->ekey); +} + +static void doSetInputDataBlockInfo(SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t order, int32_t scanFlag) { + SqlFunctionCtx* pCtx = pExprSup->pCtx; + for (int32_t i = 0; i < pExprSup->numOfExprs; ++i) { + pCtx[i].order = order; + pCtx[i].input.numOfRows = pBlock->info.rows; + setBlockSMAInfo(&pCtx[i], &pExprSup->pExprInfo[i], pBlock); + pCtx[i].pSrcBlock = pBlock; + pCtx[i].scanFlag = scanFlag; + } +} + +void setInputDataBlock(SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t order, int32_t scanFlag, bool createDummyCol) { + if (pBlock->pBlockAgg != NULL) { + doSetInputDataBlockInfo(pExprSup, pBlock, order, scanFlag); + } else { + doSetInputDataBlock(pExprSup, pBlock, order, scanFlag, createDummyCol); + } +} + +static int32_t doCreateConstantValColumnInfo(SInputColumnInfoData* pInput, SFunctParam* pFuncParam, int32_t paramIndex, + int32_t numOfRows) { + SColumnInfoData* pColInfo = NULL; + if (pInput->pData[paramIndex] == NULL) { + pColInfo = taosMemoryCalloc(1, sizeof(SColumnInfoData)); + if (pColInfo == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + // Set the correct column info (data type and bytes) + pColInfo->info.type = pFuncParam->param.nType; + pColInfo->info.bytes = pFuncParam->param.nLen; + + pInput->pData[paramIndex] = pColInfo; + } else { + pColInfo = pInput->pData[paramIndex]; + } + + colInfoDataEnsureCapacity(pColInfo, numOfRows, false); + + int8_t type = pFuncParam->param.nType; + if (type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_UBIGINT) { + int64_t v = pFuncParam->param.i; + for (int32_t i = 0; i < numOfRows; ++i) { + colDataSetInt64(pColInfo, i, &v); + } + } else if (type == TSDB_DATA_TYPE_DOUBLE) { + double v = pFuncParam->param.d; + for (int32_t i = 0; i < numOfRows; ++i) { + colDataSetDouble(pColInfo, i, &v); + } + } else if (type == TSDB_DATA_TYPE_VARCHAR) { + char* tmp = taosMemoryMalloc(pFuncParam->param.nLen + VARSTR_HEADER_SIZE); + STR_WITH_SIZE_TO_VARSTR(tmp, pFuncParam->param.pz, pFuncParam->param.nLen); + for (int32_t i = 0; i < numOfRows; ++i) { + colDataSetVal(pColInfo, i, tmp, false); + } + taosMemoryFree(tmp); + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t doSetInputDataBlock(SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t order, int32_t scanFlag, + bool createDummyCol) { + int32_t code = TSDB_CODE_SUCCESS; + SqlFunctionCtx* pCtx = pExprSup->pCtx; + + for (int32_t i = 0; i < pExprSup->numOfExprs; ++i) { + pCtx[i].order = order; + pCtx[i].input.numOfRows = pBlock->info.rows; + + pCtx[i].pSrcBlock = pBlock; + pCtx[i].scanFlag = scanFlag; + + SInputColumnInfoData* pInput = &pCtx[i].input; + pInput->uid = pBlock->info.id.uid; + pInput->colDataSMAIsSet = false; + + SExprInfo* pOneExpr = &pExprSup->pExprInfo[i]; + for (int32_t j = 0; j < pOneExpr->base.numOfParams; ++j) { + SFunctParam* pFuncParam = &pOneExpr->base.pParam[j]; + if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) { + int32_t slotId = pFuncParam->pCol->slotId; + pInput->pData[j] = taosArrayGet(pBlock->pDataBlock, slotId); + pInput->totalRows = pBlock->info.rows; + pInput->numOfRows = pBlock->info.rows; + pInput->startRowIndex = 0; + + // NOTE: the last parameter is the primary timestamp column + // todo: refactor this + if (fmIsImplicitTsFunc(pCtx[i].functionId) && (j == pOneExpr->base.numOfParams - 1)) { + pInput->pPTS = pInput->pData[j]; // in case of merge function, this is not always the ts column data. + } + ASSERT(pInput->pData[j] != NULL); + } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) { + // todo avoid case: top(k, 12), 12 is the value parameter. + // sum(11), 11 is also the value parameter. + if (createDummyCol && pOneExpr->base.numOfParams == 1) { + pInput->totalRows = pBlock->info.rows; + pInput->numOfRows = pBlock->info.rows; + pInput->startRowIndex = 0; + + code = doCreateConstantValColumnInfo(pInput, pFuncParam, j, pBlock->info.rows); + if (code != TSDB_CODE_SUCCESS) { + return code; + } + } + } + } + } + + return code; +} + +bool functionNeedToExecute(SqlFunctionCtx* pCtx) { + struct SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); + + // in case of timestamp column, always generated results. + int32_t functionId = pCtx->functionId; + if (functionId == -1) { + return false; + } + + if (pCtx->scanFlag == PRE_SCAN) { + return fmIsRepeatScanFunc(pCtx->functionId); + } + + if (isRowEntryCompleted(pResInfo)) { + return false; + } + + return true; +} + +static int32_t doCreateConstantValColumnSMAInfo(SInputColumnInfoData* pInput, SFunctParam* pFuncParam, int32_t type, + int32_t paramIndex, int32_t numOfRows) { + if (pInput->pData[paramIndex] == NULL) { + pInput->pData[paramIndex] = taosMemoryCalloc(1, sizeof(SColumnInfoData)); + if (pInput->pData[paramIndex] == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + // Set the correct column info (data type and bytes) + pInput->pData[paramIndex]->info.type = type; + pInput->pData[paramIndex]->info.bytes = tDataTypes[type].bytes; + } + + SColumnDataAgg* da = NULL; + if (pInput->pColumnDataAgg[paramIndex] == NULL) { + da = taosMemoryCalloc(1, sizeof(SColumnDataAgg)); + pInput->pColumnDataAgg[paramIndex] = da; + if (da == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } else { + da = pInput->pColumnDataAgg[paramIndex]; + } + + if (type == TSDB_DATA_TYPE_BIGINT) { + int64_t v = pFuncParam->param.i; + *da = (SColumnDataAgg){.numOfNull = 0, .min = v, .max = v, .sum = v * numOfRows}; + } else if (type == TSDB_DATA_TYPE_DOUBLE) { + double v = pFuncParam->param.d; + *da = (SColumnDataAgg){.numOfNull = 0}; + + *(double*)&da->min = v; + *(double*)&da->max = v; + *(double*)&da->sum = v * numOfRows; + } else if (type == TSDB_DATA_TYPE_BOOL) { // todo validate this data type + bool v = pFuncParam->param.i; + + *da = (SColumnDataAgg){.numOfNull = 0}; + *(bool*)&da->min = 0; + *(bool*)&da->max = v; + *(bool*)&da->sum = v * numOfRows; + } else if (type == TSDB_DATA_TYPE_TIMESTAMP) { + // do nothing + } else { + qError("invalid constant type for sma info"); + } + + return TSDB_CODE_SUCCESS; +} + +void setBlockSMAInfo(SqlFunctionCtx* pCtx, SExprInfo* pExprInfo, SSDataBlock* pBlock) { + int32_t numOfRows = pBlock->info.rows; + + SInputColumnInfoData* pInput = &pCtx->input; + pInput->numOfRows = numOfRows; + pInput->totalRows = numOfRows; + + if (pBlock->pBlockAgg != NULL) { + pInput->colDataSMAIsSet = true; + + for (int32_t j = 0; j < pExprInfo->base.numOfParams; ++j) { + SFunctParam* pFuncParam = &pExprInfo->base.pParam[j]; + + if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) { + int32_t slotId = pFuncParam->pCol->slotId; + pInput->pColumnDataAgg[j] = pBlock->pBlockAgg[slotId]; + if (pInput->pColumnDataAgg[j] == NULL) { + pInput->colDataSMAIsSet = false; + } + + // Here we set the column info data since the data type for each column data is required, but + // the data in the corresponding SColumnInfoData will not be used. + pInput->pData[j] = taosArrayGet(pBlock->pDataBlock, slotId); + } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) { + doCreateConstantValColumnSMAInfo(pInput, pFuncParam, pFuncParam->param.nType, j, pBlock->info.rows); + } + } + } else { + pInput->colDataSMAIsSet = false; + } +} + +///////////////////////////////////////////////////////////////////////////////////////////// +STimeWindow getAlignQueryTimeWindow(const SInterval* pInterval, int64_t key) { + STimeWindow win = {0}; + win.skey = taosTimeTruncate(key, pInterval); + + /* + * if the realSkey > INT64_MAX - pInterval->interval, the query duration between + * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges. + */ + win.ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1; + if (win.ekey < win.skey) { + win.ekey = INT64_MAX; + } + + return win; +} + +void setResultRowInitCtx(SResultRow* pResult, SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset) { + bool init = false; + for (int32_t i = 0; i < numOfOutput; ++i) { + pCtx[i].resultInfo = getResultEntryInfo(pResult, i, rowEntryInfoOffset); + if (init) { + continue; + } + + struct SResultRowEntryInfo* pResInfo = pCtx[i].resultInfo; + if (isRowEntryCompleted(pResInfo) && isRowEntryInitialized(pResInfo)) { + continue; + } + + if (pCtx[i].isPseudoFunc) { + continue; + } + + if (!pResInfo->initialized) { + if (pCtx[i].functionId != -1) { + pCtx[i].fpSet.init(&pCtx[i], pResInfo); + } else { + pResInfo->initialized = true; + } + } else { + init = true; + } + } +} + +void clearResultRowInitFlag(SqlFunctionCtx* pCtx, int32_t numOfOutput) { + for (int32_t i = 0; i < numOfOutput; ++i) { + SResultRowEntryInfo* pResInfo = pCtx[i].resultInfo; + if (pResInfo == NULL) { + continue; + } + + pResInfo->initialized = false; + pResInfo->numOfRes = 0; + pResInfo->isNullRes = 0; + pResInfo->complete = false; + } +} + +void doFilter(SSDataBlock* pBlock, SFilterInfo* pFilterInfo, SColMatchInfo* pColMatchInfo) { + if (pFilterInfo == NULL || pBlock->info.rows == 0) { + return; + } + + SFilterColumnParam param1 = {.numOfCols = taosArrayGetSize(pBlock->pDataBlock), .pDataBlock = pBlock->pDataBlock}; + int32_t code = filterSetDataFromSlotId(pFilterInfo, ¶m1); + + SColumnInfoData* p = NULL; + int32_t status = 0; + + // todo the keep seems never to be True?? + bool keep = filterExecute(pFilterInfo, pBlock, &p, NULL, param1.numOfCols, &status); + extractQualifiedTupleByFilterResult(pBlock, p, keep, status); + + if (pColMatchInfo != NULL) { + size_t size = taosArrayGetSize(pColMatchInfo->pList); + for (int32_t i = 0; i < size; ++i) { + SColMatchItem* pInfo = taosArrayGet(pColMatchInfo->pList, i); + if (pInfo->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { + SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, pInfo->dstSlotId); + if (pColData->info.type == TSDB_DATA_TYPE_TIMESTAMP) { + blockDataUpdateTsWindow(pBlock, pInfo->dstSlotId); + break; + } + } + } + } + + colDataDestroy(p); + taosMemoryFree(p); +} + +void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const SColumnInfoData* p, bool keep, int32_t status) { + if (keep) { + return; + } + + int8_t* pIndicator = (int8_t*)p->pData; + int32_t totalRows = pBlock->info.rows; + + if (status == FILTER_RESULT_ALL_QUALIFIED) { + // here nothing needs to be done + } else if (status == FILTER_RESULT_NONE_QUALIFIED) { + pBlock->info.rows = 0; + } else { + int32_t bmLen = BitmapLen(totalRows); + char* pBitmap = NULL; + int32_t maxRows = 0; + + size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock); + for (int32_t i = 0; i < numOfCols; ++i) { + SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i); + // it is a reserved column for scalar function, and no data in this column yet. + if (pDst->pData == NULL) { + continue; + } + + int32_t numOfRows = 0; + if (IS_VAR_DATA_TYPE(pDst->info.type)) { + int32_t j = 0; + pDst->varmeta.length = 0; + + while (j < totalRows) { + if (pIndicator[j] == 0) { + j += 1; + continue; + } + + if (colDataIsNull_var(pDst, j)) { + colDataSetNull_var(pDst, numOfRows); + } else { + char* p1 = colDataGetVarData(pDst, j); + colDataSetVal(pDst, numOfRows, p1, false); + } + numOfRows += 1; + j += 1; + } + + if (maxRows < numOfRows) { + maxRows = numOfRows; + } + } else { + if (pBitmap == NULL) { + pBitmap = taosMemoryCalloc(1, bmLen); + } + + memcpy(pBitmap, pDst->nullbitmap, bmLen); + memset(pDst->nullbitmap, 0, bmLen); + + int32_t j = 0; + + switch (pDst->info.type) { + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_UBIGINT: + case TSDB_DATA_TYPE_DOUBLE: + case TSDB_DATA_TYPE_TIMESTAMP: + while (j < totalRows) { + if (pIndicator[j] == 0) { + j += 1; + continue; + } + + if (colDataIsNull_f(pBitmap, j)) { + colDataSetNull_f(pDst->nullbitmap, numOfRows); + } else { + ((int64_t*)pDst->pData)[numOfRows] = ((int64_t*)pDst->pData)[j]; + } + numOfRows += 1; + j += 1; + } + break; + case TSDB_DATA_TYPE_FLOAT: + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_UINT: + while (j < totalRows) { + if (pIndicator[j] == 0) { + j += 1; + continue; + } + if (colDataIsNull_f(pBitmap, j)) { + colDataSetNull_f(pDst->nullbitmap, numOfRows); + } else { + ((int32_t*)pDst->pData)[numOfRows] = ((int32_t*)pDst->pData)[j]; + } + numOfRows += 1; + j += 1; + } + break; + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_USMALLINT: + while (j < totalRows) { + if (pIndicator[j] == 0) { + j += 1; + continue; + } + if (colDataIsNull_f(pBitmap, j)) { + colDataSetNull_f(pDst->nullbitmap, numOfRows); + } else { + ((int16_t*)pDst->pData)[numOfRows] = ((int16_t*)pDst->pData)[j]; + } + numOfRows += 1; + j += 1; + } + break; + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_UTINYINT: + while (j < totalRows) { + if (pIndicator[j] == 0) { + j += 1; + continue; + } + if (colDataIsNull_f(pBitmap, j)) { + colDataSetNull_f(pDst->nullbitmap, numOfRows); + } else { + ((int8_t*)pDst->pData)[numOfRows] = ((int8_t*)pDst->pData)[j]; + } + numOfRows += 1; + j += 1; + } + break; + } + } + + if (maxRows < numOfRows) { + maxRows = numOfRows; + } + } + + pBlock->info.rows = maxRows; + if (pBitmap != NULL) { + taosMemoryFree(pBitmap); + } + } +} + +void doUpdateNumOfRows(SqlFunctionCtx* pCtx, SResultRow* pRow, int32_t numOfExprs, const int32_t* rowEntryOffset) { + bool returnNotNull = false; + for (int32_t j = 0; j < numOfExprs; ++j) { + SResultRowEntryInfo* pResInfo = getResultEntryInfo(pRow, j, rowEntryOffset); + if (!isRowEntryInitialized(pResInfo)) { + continue; + } + + if (pRow->numOfRows < pResInfo->numOfRes) { + pRow->numOfRows = pResInfo->numOfRes; + } + + if (pCtx[j].isNotNullFunc) { + returnNotNull = true; + } + } + // if all expr skips all blocks, e.g. all null inputs for max function, output one row in final result. + // except for first/last, which require not null output, output no rows + if (pRow->numOfRows == 0 && !returnNotNull) { + pRow->numOfRows = 1; + } +} + +void copyResultrowToDataBlock(SExprInfo* pExprInfo, int32_t numOfExprs, SResultRow* pRow, SqlFunctionCtx* pCtx, + SSDataBlock* pBlock, const int32_t* rowEntryOffset, SExecTaskInfo* pTaskInfo) { + for (int32_t j = 0; j < numOfExprs; ++j) { + int32_t slotId = pExprInfo[j].base.resSchema.slotId; + + pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset); + if (pCtx[j].fpSet.finalize) { + if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_group_key") == 0) { + // for groupkey along with functions that output multiple lines(e.g. Histogram) + // need to match groupkey result for each output row of that function. + if (pCtx[j].resultInfo->numOfRes != 0) { + pCtx[j].resultInfo->numOfRes = pRow->numOfRows; + } + } + + int32_t code = pCtx[j].fpSet.finalize(&pCtx[j], pBlock); + if (TAOS_FAILED(code)) { + qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(code)); + T_LONG_JMP(pTaskInfo->env, code); + } + } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) { + // do nothing + } else { + // expand the result into multiple rows. E.g., _wstart, top(k, 20) + // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows. + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId); + char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo); + for (int32_t k = 0; k < pRow->numOfRows; ++k) { + colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes); + } + } + } +} + +// todo refactor. SResultRow has direct pointer in miainfo +int32_t finalizeResultRows(SDiskbasedBuf* pBuf, SResultRowPosition* resultRowPosition, SExprSupp* pSup, + SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo) { + SFilePage* page = getBufPage(pBuf, resultRowPosition->pageId); + if (page == NULL) { + qError("failed to get buffer, code:%s, %s", tstrerror(terrno), GET_TASKID(pTaskInfo)); + T_LONG_JMP(pTaskInfo->env, terrno); + } + + SResultRow* pRow = (SResultRow*)((char*)page + resultRowPosition->offset); + + SqlFunctionCtx* pCtx = pSup->pCtx; + SExprInfo* pExprInfo = pSup->pExprInfo; + const int32_t* rowEntryOffset = pSup->rowEntryInfoOffset; + + doUpdateNumOfRows(pCtx, pRow, pSup->numOfExprs, rowEntryOffset); + if (pRow->numOfRows == 0) { + releaseBufPage(pBuf, page); + return 0; + } + + int32_t size = pBlock->info.capacity; + while (pBlock->info.rows + pRow->numOfRows > size) { + size = size * 1.25; + } + + int32_t code = blockDataEnsureCapacity(pBlock, size); + if (TAOS_FAILED(code)) { + releaseBufPage(pBuf, page); + qError("%s ensure result data capacity failed, code %s", GET_TASKID(pTaskInfo), tstrerror(code)); + T_LONG_JMP(pTaskInfo->env, code); + } + + copyResultrowToDataBlock(pExprInfo, pSup->numOfExprs, pRow, pCtx, pBlock, rowEntryOffset, pTaskInfo); + + releaseBufPage(pBuf, page); + pBlock->info.rows += pRow->numOfRows; + return 0; +} + +int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprSupp* pSup, SDiskbasedBuf* pBuf, + SGroupResInfo* pGroupResInfo, int32_t threshold, bool ignoreGroup) { + SExprInfo* pExprInfo = pSup->pExprInfo; + int32_t numOfExprs = pSup->numOfExprs; + int32_t* rowEntryOffset = pSup->rowEntryInfoOffset; + SqlFunctionCtx* pCtx = pSup->pCtx; + + int32_t numOfRows = getNumOfTotalRes(pGroupResInfo); + + for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) { + SResKeyPos* pPos = taosArrayGetP(pGroupResInfo->pRows, i); + SFilePage* page = getBufPage(pBuf, pPos->pos.pageId); + if (page == NULL) { + qError("failed to get buffer, code:%s, %s", tstrerror(terrno), GET_TASKID(pTaskInfo)); + T_LONG_JMP(pTaskInfo->env, terrno); + } + + SResultRow* pRow = (SResultRow*)((char*)page + pPos->pos.offset); + + doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset); + + // no results, continue to check the next one + if (pRow->numOfRows == 0) { + pGroupResInfo->index += 1; + releaseBufPage(pBuf, page); + continue; + } + + if (!ignoreGroup) { + if (pBlock->info.id.groupId == 0) { + pBlock->info.id.groupId = pPos->groupId; + } else { + // current value belongs to different group, it can't be packed into one datablock + if (pBlock->info.id.groupId != pPos->groupId) { + releaseBufPage(pBuf, page); + break; + } + } + } + + if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) { + uint32_t newSize = pBlock->info.rows + pRow->numOfRows + (numOfRows - i) > 1 ? 1 : 0; + blockDataEnsureCapacity(pBlock, newSize); + qDebug("datablock capacity not sufficient, expand to required:%d, current capacity:%d, %s", + newSize, pBlock->info.capacity, GET_TASKID(pTaskInfo)); + // todo set the pOperator->resultInfo size + } + + pGroupResInfo->index += 1; + copyResultrowToDataBlock(pExprInfo, numOfExprs, pRow, pCtx, pBlock, rowEntryOffset, pTaskInfo); + + releaseBufPage(pBuf, page); + pBlock->info.rows += pRow->numOfRows; + if (pBlock->info.rows >= threshold) { + break; + } + } + + qDebug("%s result generated, rows:%" PRId64 ", groupId:%" PRIu64, GET_TASKID(pTaskInfo), pBlock->info.rows, + pBlock->info.id.groupId); + pBlock->info.dataLoad = 1; + blockDataUpdateTsWindow(pBlock, 0); + return 0; +} + +void doBuildStreamResBlock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, + SDiskbasedBuf* pBuf) { + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + SSDataBlock* pBlock = pbInfo->pRes; + + // set output datablock version + pBlock->info.version = pTaskInfo->version; + + blockDataCleanup(pBlock); + if (!hasRemainResults(pGroupResInfo)) { + return; + } + + // clear the existed group id + pBlock->info.id.groupId = 0; + ASSERT(!pbInfo->mergeResultBlock); + doCopyToSDataBlock(pTaskInfo, pBlock, &pOperator->exprSupp, pBuf, pGroupResInfo, pOperator->resultInfo.threshold, false); + + void* tbname = NULL; + if (streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) < 0) { + pBlock->info.parTbName[0] = 0; + } else { + memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN); + } + tdbFree(tbname); +} + +void doBuildResultDatablock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, + SDiskbasedBuf* pBuf) { + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + SSDataBlock* pBlock = pbInfo->pRes; + + // set output datablock version + pBlock->info.version = pTaskInfo->version; + + blockDataCleanup(pBlock); + if (!hasRemainResults(pGroupResInfo)) { + return; + } + + // clear the existed group id + pBlock->info.id.groupId = 0; + if (!pbInfo->mergeResultBlock) { + doCopyToSDataBlock(pTaskInfo, pBlock, &pOperator->exprSupp, pBuf, pGroupResInfo, pOperator->resultInfo.threshold, false); + } else { + while (hasRemainResults(pGroupResInfo)) { + doCopyToSDataBlock(pTaskInfo, pBlock, &pOperator->exprSupp, pBuf, pGroupResInfo, pOperator->resultInfo.threshold, true); + if (pBlock->info.rows >= pOperator->resultInfo.threshold) { + break; + } + + // clearing group id to continue to merge data that belong to different groups + pBlock->info.id.groupId = 0; + } + + // clear the group id info in SSDataBlock, since the client does not need it + pBlock->info.id.groupId = 0; + } +} + +void destroyExprInfo(SExprInfo* pExpr, int32_t numOfExprs) { + for (int32_t i = 0; i < numOfExprs; ++i) { + SExprInfo* pExprInfo = &pExpr[i]; + for (int32_t j = 0; j < pExprInfo->base.numOfParams; ++j) { + if (pExprInfo->base.pParam[j].type == FUNC_PARAM_TYPE_COLUMN) { + taosMemoryFreeClear(pExprInfo->base.pParam[j].pCol); + } else if (pExprInfo->base.pParam[j].type == FUNC_PARAM_TYPE_VALUE) { + taosVariantDestroy(&pExprInfo->base.pParam[j].param); + } + } + + taosMemoryFree(pExprInfo->base.pParam); + taosMemoryFree(pExprInfo->pExpr); + } +} + +int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, uint32_t* defaultBufsz) { + *defaultPgsz = 4096; + while (*defaultPgsz < rowSize * 4) { + *defaultPgsz <<= 1u; + } + + // The default buffer for each operator in query is 10MB. + // at least four pages need to be in buffer + // TODO: make this variable to be configurable. + *defaultBufsz = 4096 * 2560; + if ((*defaultBufsz) <= (*defaultPgsz)) { + (*defaultBufsz) = (*defaultPgsz) * 4; + } + + return 0; +} + +void initResultSizeInfo(SResultInfo* pResultInfo, int32_t numOfRows) { + if (numOfRows == 0) { + numOfRows = 4096; + } + + pResultInfo->capacity = numOfRows; + pResultInfo->threshold = numOfRows * 0.75; + + if (pResultInfo->threshold == 0) { + pResultInfo->threshold = numOfRows; + } +} + +void initBasicInfo(SOptrBasicInfo* pInfo, SSDataBlock* pBlock) { + pInfo->pRes = pBlock; + initResultRowInfo(&pInfo->resultRowInfo); +} + +static void* destroySqlFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) { + if (pCtx == NULL) { + return NULL; + } + + for (int32_t i = 0; i < numOfOutput; ++i) { + for (int32_t j = 0; j < pCtx[i].numOfParams; ++j) { + taosVariantDestroy(&pCtx[i].param[j].param); + } + + taosMemoryFreeClear(pCtx[i].subsidiaries.pCtx); + taosMemoryFreeClear(pCtx[i].subsidiaries.buf); + taosMemoryFree(pCtx[i].input.pData); + taosMemoryFree(pCtx[i].input.pColumnDataAgg); + + if (pCtx[i].udfName != NULL) { + taosMemoryFree(pCtx[i].udfName); + } + } + + taosMemoryFreeClear(pCtx); + return NULL; +} + +int32_t initExprSupp(SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfExpr) { + pSup->pExprInfo = pExprInfo; + pSup->numOfExprs = numOfExpr; + if (pSup->pExprInfo != NULL) { + pSup->pCtx = createSqlFunctionCtx(pExprInfo, numOfExpr, &pSup->rowEntryInfoOffset); + if (pSup->pCtx == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } + + return TSDB_CODE_SUCCESS; +} + +void cleanupExprSupp(SExprSupp* pSupp) { + destroySqlFunctionCtx(pSupp->pCtx, pSupp->numOfExprs); + if (pSupp->pExprInfo != NULL) { + destroyExprInfo(pSupp->pExprInfo, pSupp->numOfExprs); + taosMemoryFreeClear(pSupp->pExprInfo); + } + + if (pSupp->pFilterInfo != NULL) { + filterFreeInfo(pSupp->pFilterInfo); + pSupp->pFilterInfo = NULL; + } + + taosMemoryFree(pSupp->rowEntryInfoOffset); +} + +void cleanupBasicInfo(SOptrBasicInfo* pInfo) { pInfo->pRes = blockDataDestroy(pInfo->pRes); } + +bool groupbyTbname(SNodeList* pGroupList) { + bool bytbname = false; + if (LIST_LENGTH(pGroupList) == 1) { + SNode* p = nodesListGetNode(pGroupList, 0); + if (p->type == QUERY_NODE_FUNCTION) { + // partition by tbname/group by tbname + bytbname = (strcmp(((struct SFunctionNode*)p)->functionName, "tbname") == 0); + } + } + + return bytbname; +} + +int32_t createDataSinkParam(SDataSinkNode* pNode, void** pParam, SExecTaskInfo* pTask, SReadHandle* readHandle) { + switch (pNode->type) { + case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: { + SInserterParam* pInserterParam = taosMemoryCalloc(1, sizeof(SInserterParam)); + if (NULL == pInserterParam) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pInserterParam->readHandle = readHandle; + + *pParam = pInserterParam; + break; + } + case QUERY_NODE_PHYSICAL_PLAN_DELETE: { + SDeleterParam* pDeleterParam = taosMemoryCalloc(1, sizeof(SDeleterParam)); + if (NULL == pDeleterParam) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + SArray* pInfoList = getTableListInfo(pTask); + STableListInfo* pTableListInfo = taosArrayGetP(pInfoList, 0); + taosArrayDestroy(pInfoList); + + pDeleterParam->suid = tableListGetSuid(pTableListInfo); + + // TODO extract uid list + int32_t numOfTables = tableListGetSize(pTableListInfo); + pDeleterParam->pUidList = taosArrayInit(numOfTables, sizeof(uint64_t)); + if (NULL == pDeleterParam->pUidList) { + taosMemoryFree(pDeleterParam); + return TSDB_CODE_OUT_OF_MEMORY; + } + + for (int32_t i = 0; i < numOfTables; ++i) { + STableKeyInfo* pTable = tableListGetInfo(pTableListInfo, i); + taosArrayPush(pDeleterParam->pUidList, &pTable->uid); + } + + *pParam = pDeleterParam; + break; + } + default: + break; + } + + return TSDB_CODE_SUCCESS; +} + +int32_t setOutputBuf(SStreamState* pState, STimeWindow* win, SResultRow** pResult, int64_t tableGroupId, + SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset, SAggSupporter* pAggSup) { + SWinKey key = { + .ts = win->skey, + .groupId = tableGroupId, + }; + char* value = NULL; + int32_t size = pAggSup->resultRowSize; + + if (streamStateAddIfNotExist(pState, &key, (void**)&value, &size) < 0) { + return TSDB_CODE_OUT_OF_MEMORY; + } + *pResult = (SResultRow*)value; + // set time window for current result + (*pResult)->win = (*win); + setResultRowInitCtx(*pResult, pCtx, numOfOutput, rowEntryInfoOffset); + return TSDB_CODE_SUCCESS; +} + +int32_t releaseOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult) { + streamStateReleaseBuf(pState, pKey, pResult); + return TSDB_CODE_SUCCESS; +} + +int32_t saveOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult, int32_t resSize) { + streamStatePut(pState, pKey, pResult, resSize); + return TSDB_CODE_SUCCESS; +} + +int32_t buildDataBlockFromGroupRes(SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, SExprSupp* pSup, + SGroupResInfo* pGroupResInfo) { + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + SExprInfo* pExprInfo = pSup->pExprInfo; + int32_t numOfExprs = pSup->numOfExprs; + int32_t* rowEntryOffset = pSup->rowEntryInfoOffset; + SqlFunctionCtx* pCtx = pSup->pCtx; + + int32_t numOfRows = getNumOfTotalRes(pGroupResInfo); + + for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) { + SWinKey* pKey = taosArrayGet(pGroupResInfo->pRows, i); + int32_t size = 0; + void* pVal = NULL; + int32_t code = streamStateGet(pState, pKey, &pVal, &size); + ASSERT(code == 0); + SResultRow* pRow = (SResultRow*)pVal; + doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset); + // no results, continue to check the next one + if (pRow->numOfRows == 0) { + pGroupResInfo->index += 1; + releaseOutputBuf(pState, pKey, pRow); + continue; + } + + if (pBlock->info.id.groupId == 0) { + pBlock->info.id.groupId = pKey->groupId; + void* tbname = NULL; + if (streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) < 0) { + pBlock->info.parTbName[0] = 0; + } else { + memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN); + } + tdbFree(tbname); + } else { + // current value belongs to different group, it can't be packed into one datablock + if (pBlock->info.id.groupId != pKey->groupId) { + releaseOutputBuf(pState, pKey, pRow); + break; + } + } + + if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) { + ASSERT(pBlock->info.rows > 0); + releaseOutputBuf(pState, pKey, pRow); + break; + } + + pGroupResInfo->index += 1; + + for (int32_t j = 0; j < numOfExprs; ++j) { + int32_t slotId = pExprInfo[j].base.resSchema.slotId; + + pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset); + if (pCtx[j].fpSet.finalize) { + int32_t code1 = pCtx[j].fpSet.finalize(&pCtx[j], pBlock); + if (TAOS_FAILED(code1)) { + qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(code1)); + T_LONG_JMP(pTaskInfo->env, code1); + } + } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) { + // do nothing, todo refactor + } else { + // expand the result into multiple rows. E.g., _wstart, top(k, 20) + // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows. + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId); + char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo); + for (int32_t k = 0; k < pRow->numOfRows; ++k) { + colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes); + } + } + } + + pBlock->info.rows += pRow->numOfRows; + releaseOutputBuf(pState, pKey, pRow); + } + pBlock->info.dataLoad = 1; + blockDataUpdateTsWindow(pBlock, 0); + return TSDB_CODE_SUCCESS; +} + +int32_t saveSessionDiscBuf(SStreamState* pState, SSessionKey* key, void* buf, int32_t size) { + streamStateSessionPut(pState, key, (const void*)buf, size); + releaseOutputBuf(pState, NULL, (SResultRow*)buf); + return TSDB_CODE_SUCCESS; +} + +int32_t buildSessionResultDataBlock(SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, + SExprSupp* pSup, SGroupResInfo* pGroupResInfo) { + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + SExprInfo* pExprInfo = pSup->pExprInfo; + int32_t numOfExprs = pSup->numOfExprs; + int32_t* rowEntryOffset = pSup->rowEntryInfoOffset; + SqlFunctionCtx* pCtx = pSup->pCtx; + + int32_t numOfRows = getNumOfTotalRes(pGroupResInfo); + + for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) { + SSessionKey* pKey = taosArrayGet(pGroupResInfo->pRows, i); + int32_t size = 0; + void* pVal = NULL; + int32_t code = streamStateSessionGet(pState, pKey, &pVal, &size); + ASSERT(code == 0); + if (code == -1) { + // coverity scan + pGroupResInfo->index += 1; + continue; + } + SResultRow* pRow = (SResultRow*)pVal; + doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset); + // no results, continue to check the next one + if (pRow->numOfRows == 0) { + pGroupResInfo->index += 1; + releaseOutputBuf(pState, NULL, pRow); + continue; + } + + if (pBlock->info.id.groupId == 0) { + pBlock->info.id.groupId = pKey->groupId; + + void* tbname = NULL; + if (streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) < 0) { + pBlock->info.parTbName[0] = 0; + } else { + memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN); + } + tdbFree(tbname); + } else { + // current value belongs to different group, it can't be packed into one datablock + if (pBlock->info.id.groupId != pKey->groupId) { + releaseOutputBuf(pState, NULL, pRow); + break; + } + } + + if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) { + ASSERT(pBlock->info.rows > 0); + releaseOutputBuf(pState, NULL, pRow); + break; + } + + pGroupResInfo->index += 1; + + for (int32_t j = 0; j < numOfExprs; ++j) { + int32_t slotId = pExprInfo[j].base.resSchema.slotId; + + pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset); + if (pCtx[j].fpSet.finalize) { + int32_t code1 = pCtx[j].fpSet.finalize(&pCtx[j], pBlock); + if (TAOS_FAILED(code1)) { + qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(code1)); + T_LONG_JMP(pTaskInfo->env, code1); + } + } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) { + // do nothing, todo refactor + } else { + // expand the result into multiple rows. E.g., _wstart, top(k, 20) + // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows. + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId); + char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo); + for (int32_t k = 0; k < pRow->numOfRows; ++k) { + colDataSetVal(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes); + } + } + } + + pBlock->info.dataLoad = 1; + pBlock->info.rows += pRow->numOfRows; + // saveSessionDiscBuf(pState, pKey, pVal, size); + releaseOutputBuf(pState, NULL, pRow); + } + blockDataUpdateTsWindow(pBlock, 0); + return TSDB_CODE_SUCCESS; +} + +void qStreamCloseTsdbReader(void* task) { + if (task == NULL) { + return; + } + + SExecTaskInfo* pTaskInfo = (SExecTaskInfo*)task; + SOperatorInfo* pOp = pTaskInfo->pRoot; + + qDebug("stream close tsdb reader, reset status uid:%" PRId64 " ts:%" PRId64, pTaskInfo->streamInfo.currentOffset.uid, + pTaskInfo->streamInfo.currentOffset.ts); + + // todo refactor, other thread may already use this read to extract data. + pTaskInfo->streamInfo.currentOffset = (STqOffsetVal){0}; + while (pOp->numOfDownstream == 1 && pOp->pDownstream[0]) { + SOperatorInfo* pDownstreamOp = pOp->pDownstream[0]; + if (pDownstreamOp->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { + SStreamScanInfo* pInfo = pDownstreamOp->info; + if (pInfo->pTableScanOp) { + STableScanInfo* pTSInfo = pInfo->pTableScanOp->info; + + setOperatorCompleted(pInfo->pTableScanOp); + while (pTaskInfo->owner != 0) { + taosMsleep(100); + qDebug("wait for the reader stopping"); + } + + tsdbReaderClose(pTSInfo->base.dataReader); + pTSInfo->base.dataReader = NULL; + + // restore the status, todo refactor. + pInfo->pTableScanOp->status = OP_OPENED; + pTaskInfo->status = TASK_NOT_COMPLETED; + return; + } + } + } +} diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c index 464282613d599a903e0c72ac6ef658ac2fedf43e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -1,2775 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "filter.h" -#include "function.h" -#include "functionMgt.h" -#include "os.h" -#include "querynodes.h" -#include "tfill.h" -#include "tname.h" - -#include "tdatablock.h" -#include "tglobal.h" -#include "tmsg.h" -#include "ttime.h" - -#include "executorimpl.h" -#include "index.h" -#include "query.h" -#include "tcompare.h" -#include "thash.h" -#include "ttypes.h" -#include "vnode.h" - -#define IS_MAIN_SCAN(runtime) ((runtime)->scanFlag == MAIN_SCAN) -#define SET_REVERSE_SCAN_FLAG(runtime) ((runtime)->scanFlag = REVERSE_SCAN) - -#define GET_FORWARD_DIRECTION_FACTOR(ord) (((ord) == TSDB_ORDER_ASC) ? QUERY_ASC_FORWARD_STEP : QUERY_DESC_FORWARD_STEP) - -#if 0 -static UNUSED_FUNC void *u_malloc (size_t __size) { - uint32_t v = taosRand(); - - if (v % 1000 <= 0) { - return NULL; - } else { - return taosMemoryMalloc(__size); - } -} - -static UNUSED_FUNC void* u_calloc(size_t num, size_t __size) { - uint32_t v = taosRand(); - if (v % 1000 <= 0) { - return NULL; - } else { - return taosMemoryCalloc(num, __size); - } -} - -static UNUSED_FUNC void* u_realloc(void* p, size_t __size) { - uint32_t v = taosRand(); - if (v % 5 <= 1) { - return NULL; - } else { - return taosMemoryRealloc(p, __size); - } -} - -#define calloc u_calloc -#define malloc u_malloc -#define realloc u_realloc -#endif - -#define CLEAR_QUERY_STATUS(q, st) ((q)->status &= (~(st))) -#define QUERY_IS_INTERVAL_QUERY(_q) ((_q)->interval.interval > 0) - -typedef struct SAggOperatorInfo { - SOptrBasicInfo binfo; - SAggSupporter aggSup; - STableQueryInfo* current; - uint64_t groupId; - SGroupResInfo groupResInfo; - SExprSupp scalarExprSup; - bool groupKeyOptimized; -} SAggOperatorInfo; - -static void setBlockSMAInfo(SqlFunctionCtx* pCtx, SExprInfo* pExpr, SSDataBlock* pBlock); - -static void releaseQueryBuf(size_t numOfTables); - -static void destroyAggOperatorInfo(void* param); -static void initCtxOutputBuffer(SqlFunctionCtx* pCtx, int32_t size); -static void doSetTableGroupOutputBuf(SOperatorInfo* pOperator, int32_t numOfOutput, uint64_t groupId); -static void doApplyScalarCalculation(SOperatorInfo* pOperator, SSDataBlock* pBlock, int32_t order, int32_t scanFlag); -static int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, size_t keyBufSize, - const char* pKey); -static void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const SColumnInfoData* p, bool keep, - int32_t status); -static int32_t doSetInputDataBlock(SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t order, int32_t scanFlag, - bool createDummyCol); -static int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprSupp* pSup, SDiskbasedBuf* pBuf, - SGroupResInfo* pGroupResInfo); - -void setOperatorCompleted(SOperatorInfo* pOperator) { - pOperator->status = OP_EXEC_DONE; - pOperator->cost.totalCost = (taosGetTimestampUs() - pOperator->pTaskInfo->cost.start) / 1000.0; - setTaskStatus(pOperator->pTaskInfo, TASK_COMPLETED); -} - -void setOperatorInfo(SOperatorInfo* pOperator, const char* name, int32_t type, bool blocking, int32_t status, - void* pInfo, SExecTaskInfo* pTaskInfo) { - pOperator->name = (char*)name; - pOperator->operatorType = type; - pOperator->blocking = blocking; - pOperator->status = status; - pOperator->info = pInfo; - pOperator->pTaskInfo = pTaskInfo; -} - -int32_t optrDummyOpenFn(SOperatorInfo* pOperator) { - OPTR_SET_OPENED(pOperator); - pOperator->cost.openCost = 0; - return TSDB_CODE_SUCCESS; -} - -SOperatorFpSet createOperatorFpSet(__optr_open_fn_t openFn, __optr_fn_t nextFn, __optr_fn_t cleanup, - __optr_close_fn_t closeFn, __optr_reqBuf_fn_t reqBufFn, - __optr_explain_fn_t explain) { - SOperatorFpSet fpSet = { - ._openFn = openFn, - .getNextFn = nextFn, - .cleanupFn = cleanup, - .closeFn = closeFn, - .reqBufFn = reqBufFn, - .getExplainFn = explain, - }; - - return fpSet; -} - -SResultRow* getNewResultRow(SDiskbasedBuf* pResultBuf, int32_t* currentPageId, int32_t interBufSize) { - SFilePage* pData = NULL; - - // in the first scan, new space needed for results - int32_t pageId = -1; - if (*currentPageId == -1) { - pData = getNewBufPage(pResultBuf, &pageId); - pData->num = sizeof(SFilePage); - } else { - pData = getBufPage(pResultBuf, *currentPageId); - if (pData == NULL) { - qError("failed to get buffer, code:%s", tstrerror(terrno)); - return NULL; - } - - pageId = *currentPageId; - - if (pData->num + interBufSize > getBufPageSize(pResultBuf)) { - // release current page first, and prepare the next one - releaseBufPage(pResultBuf, pData); - - pData = getNewBufPage(pResultBuf, &pageId); - if (pData != NULL) { - pData->num = sizeof(SFilePage); - } - } - } - - if (pData == NULL) { - return NULL; - } - - setBufPageDirty(pData, true); - - // set the number of rows in current disk page - SResultRow* pResultRow = (SResultRow*)((char*)pData + pData->num); - - memset((char*) pResultRow, 0, interBufSize); - pResultRow->pageId = pageId; - pResultRow->offset = (int32_t)pData->num; - - *currentPageId = pageId; - pData->num += interBufSize; - return pResultRow; -} - -/** - * the struct of key in hash table - * +----------+---------------+ - * | group id | key data | - * | 8 bytes | actual length | - * +----------+---------------+ - */ -SResultRow* doSetResultOutBufByKey(SDiskbasedBuf* pResultBuf, SResultRowInfo* pResultRowInfo, char* pData, - int16_t bytes, bool masterscan, uint64_t groupId, SExecTaskInfo* pTaskInfo, - bool isIntervalQuery, SAggSupporter* pSup) { - SET_RES_WINDOW_KEY(pSup->keyBuf, pData, bytes, groupId); - - SResultRowPosition* p1 = - (SResultRowPosition*)tSimpleHashGet(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes)); - - SResultRow* pResult = NULL; - - // in case of repeat scan/reverse scan, no new time window added. - if (isIntervalQuery) { - if (p1 != NULL) { // the *p1 may be NULL in case of sliding+offset exists. - pResult = getResultRowByPos(pResultBuf, p1, true); - if (NULL == pResult) { - T_LONG_JMP(pTaskInfo->env, terrno); - } - - ASSERT(pResult->pageId == p1->pageId && pResult->offset == p1->offset); - } - } else { - // In case of group by column query, the required SResultRow object must be existInCurrentResusltRowInfo in the - // pResultRowInfo object. - if (p1 != NULL) { - // todo - pResult = getResultRowByPos(pResultBuf, p1, true); - if (NULL == pResult) { - T_LONG_JMP(pTaskInfo->env, terrno); - } - - ASSERT(pResult->pageId == p1->pageId && pResult->offset == p1->offset); - } - } - - // 1. close current opened time window - if (pResultRowInfo->cur.pageId != -1 && ((pResult == NULL) || (pResult->pageId != pResultRowInfo->cur.pageId))) { - SResultRowPosition pos = pResultRowInfo->cur; - SFilePage* pPage = getBufPage(pResultBuf, pos.pageId); - if (pPage == NULL) { - qError("failed to get buffer, code:%s, %s", tstrerror(terrno), GET_TASKID(pTaskInfo)); - T_LONG_JMP(pTaskInfo->env, terrno); - } - releaseBufPage(pResultBuf, pPage); - } - - // allocate a new buffer page - if (pResult == NULL) { - ASSERT(pSup->resultRowSize > 0); - pResult = getNewResultRow(pResultBuf, &pSup->currentPageId, pSup->resultRowSize); - if (pResult == NULL) { - T_LONG_JMP(pTaskInfo->env, terrno); - } - - // add a new result set for a new group - SResultRowPosition pos = {.pageId = pResult->pageId, .offset = pResult->offset}; - tSimpleHashPut(pSup->pResultRowHashTable, pSup->keyBuf, GET_RES_WINDOW_KEY_LEN(bytes), &pos, - sizeof(SResultRowPosition)); - } - - // 2. set the new time window to be the new active time window - pResultRowInfo->cur = (SResultRowPosition){.pageId = pResult->pageId, .offset = pResult->offset}; - - // too many time window in query - if (pTaskInfo->execModel == OPTR_EXEC_MODEL_BATCH && - tSimpleHashGetSize(pSup->pResultRowHashTable) > MAX_INTERVAL_TIME_WINDOW) { - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW); - } - - return pResult; -} - -// a new buffer page for each table. Needs to opt this design -static int32_t addNewWindowResultBuf(SResultRow* pWindowRes, SDiskbasedBuf* pResultBuf, uint32_t size) { - if (pWindowRes->pageId != -1) { - return 0; - } - - SFilePage* pData = NULL; - - // in the first scan, new space needed for results - int32_t pageId = -1; - SArray* list = getDataBufPagesIdList(pResultBuf); - - if (taosArrayGetSize(list) == 0) { - pData = getNewBufPage(pResultBuf, &pageId); - pData->num = sizeof(SFilePage); - } else { - SPageInfo* pi = getLastPageInfo(list); - pData = getBufPage(pResultBuf, getPageId(pi)); - if (pData == NULL) { - qError("failed to get buffer, code:%s", tstrerror(terrno)); - return terrno; - } - - pageId = getPageId(pi); - - if (pData->num + size > getBufPageSize(pResultBuf)) { - // release current page first, and prepare the next one - releaseBufPageInfo(pResultBuf, pi); - - pData = getNewBufPage(pResultBuf, &pageId); - if (pData != NULL) { - pData->num = sizeof(SFilePage); - } - } - } - - if (pData == NULL) { - return -1; - } - - // set the number of rows in current disk page - if (pWindowRes->pageId == -1) { // not allocated yet, allocate new buffer - pWindowRes->pageId = pageId; - pWindowRes->offset = (int32_t)pData->num; - - pData->num += size; - assert(pWindowRes->pageId >= 0); - } - - return 0; -} - -// query_range_start, query_range_end, window_duration, window_start, window_end -void initExecTimeWindowInfo(SColumnInfoData* pColData, STimeWindow* pQueryWindow) { - pColData->info.type = TSDB_DATA_TYPE_TIMESTAMP; - pColData->info.bytes = sizeof(int64_t); - - colInfoDataEnsureCapacity(pColData, 5, false); - colDataAppendInt64(pColData, 0, &pQueryWindow->skey); - colDataAppendInt64(pColData, 1, &pQueryWindow->ekey); - - int64_t interval = 0; - colDataAppendInt64(pColData, 2, &interval); // this value may be variable in case of 'n' and 'y'. - colDataAppendInt64(pColData, 3, &pQueryWindow->skey); - colDataAppendInt64(pColData, 4, &pQueryWindow->ekey); -} - -typedef struct { - bool hasAgg; - int32_t numOfRows; - int32_t startOffset; -} SFunctionCtxStatus; - -static void functionCtxSave(SqlFunctionCtx* pCtx, SFunctionCtxStatus* pStatus) { - pStatus->hasAgg = pCtx->input.colDataSMAIsSet; - pStatus->numOfRows = pCtx->input.numOfRows; - pStatus->startOffset = pCtx->input.startRowIndex; -} - -static void functionCtxRestore(SqlFunctionCtx* pCtx, SFunctionCtxStatus* pStatus) { - pCtx->input.colDataSMAIsSet = pStatus->hasAgg; - pCtx->input.numOfRows = pStatus->numOfRows; - pCtx->input.startRowIndex = pStatus->startOffset; -} - -void applyAggFunctionOnPartialTuples(SExecTaskInfo* taskInfo, SqlFunctionCtx* pCtx, SColumnInfoData* pTimeWindowData, - int32_t offset, int32_t forwardStep, int32_t numOfTotal, int32_t numOfOutput) { - for (int32_t k = 0; k < numOfOutput; ++k) { - // keep it temporarily - SFunctionCtxStatus status = {0}; - functionCtxSave(&pCtx[k], &status); - - pCtx[k].input.startRowIndex = offset; - pCtx[k].input.numOfRows = forwardStep; - - // not a whole block involved in query processing, statistics data can not be used - // NOTE: the original value of isSet have been changed here - if (pCtx[k].input.colDataSMAIsSet && forwardStep < numOfTotal) { - pCtx[k].input.colDataSMAIsSet = false; - } - - if (pCtx[k].isPseudoFunc) { - SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(&pCtx[k]); - - char* p = GET_ROWCELL_INTERBUF(pEntryInfo); - - SColumnInfoData idata = {0}; - idata.info.type = TSDB_DATA_TYPE_BIGINT; - idata.info.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes; - idata.pData = p; - - SScalarParam out = {.columnData = &idata}; - SScalarParam tw = {.numOfRows = 5, .columnData = pTimeWindowData}; - pCtx[k].sfp.process(&tw, 1, &out); - pEntryInfo->numOfRes = 1; - } else { - int32_t code = TSDB_CODE_SUCCESS; - if (functionNeedToExecute(&pCtx[k]) && pCtx[k].fpSet.process != NULL) { - code = pCtx[k].fpSet.process(&pCtx[k]); - - if (code != TSDB_CODE_SUCCESS) { - qError("%s apply functions error, code: %s", GET_TASKID(taskInfo), tstrerror(code)); - taskInfo->code = code; - T_LONG_JMP(taskInfo->env, code); - } - } - - // restore it - functionCtxRestore(&pCtx[k], &status); - } - } -} - -static void doSetInputDataBlockInfo(SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t order) { - SqlFunctionCtx* pCtx = pExprSup->pCtx; - for (int32_t i = 0; i < pExprSup->numOfExprs; ++i) { - pCtx[i].order = order; - pCtx[i].input.numOfRows = pBlock->info.rows; - setBlockSMAInfo(&pCtx[i], &pExprSup->pExprInfo[i], pBlock); - pCtx[i].pSrcBlock = pBlock; - } -} - -void setInputDataBlock(SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t order, int32_t scanFlag, bool createDummyCol) { - if (pBlock->pBlockAgg != NULL) { - doSetInputDataBlockInfo(pExprSup, pBlock, order); - } else { - doSetInputDataBlock(pExprSup, pBlock, order, scanFlag, createDummyCol); - } -} - -static int32_t doCreateConstantValColumnInfo(SInputColumnInfoData* pInput, SFunctParam* pFuncParam, int32_t paramIndex, - int32_t numOfRows) { - SColumnInfoData* pColInfo = NULL; - if (pInput->pData[paramIndex] == NULL) { - pColInfo = taosMemoryCalloc(1, sizeof(SColumnInfoData)); - if (pColInfo == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - // Set the correct column info (data type and bytes) - pColInfo->info.type = pFuncParam->param.nType; - pColInfo->info.bytes = pFuncParam->param.nLen; - - pInput->pData[paramIndex] = pColInfo; - } else { - pColInfo = pInput->pData[paramIndex]; - } - - colInfoDataEnsureCapacity(pColInfo, numOfRows, false); - - int8_t type = pFuncParam->param.nType; - if (type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_UBIGINT) { - int64_t v = pFuncParam->param.i; - for (int32_t i = 0; i < numOfRows; ++i) { - colDataAppendInt64(pColInfo, i, &v); - } - } else if (type == TSDB_DATA_TYPE_DOUBLE) { - double v = pFuncParam->param.d; - for (int32_t i = 0; i < numOfRows; ++i) { - colDataAppendDouble(pColInfo, i, &v); - } - } else if (type == TSDB_DATA_TYPE_VARCHAR) { - char* tmp = taosMemoryMalloc(pFuncParam->param.nLen + VARSTR_HEADER_SIZE); - STR_WITH_SIZE_TO_VARSTR(tmp, pFuncParam->param.pz, pFuncParam->param.nLen); - for (int32_t i = 0; i < numOfRows; ++i) { - colDataAppend(pColInfo, i, tmp, false); - } - taosMemoryFree(tmp); - } - - return TSDB_CODE_SUCCESS; -} - -static int32_t doSetInputDataBlock(SExprSupp* pExprSup, SSDataBlock* pBlock, int32_t order, int32_t scanFlag, - bool createDummyCol) { - int32_t code = TSDB_CODE_SUCCESS; - SqlFunctionCtx* pCtx = pExprSup->pCtx; - - for (int32_t i = 0; i < pExprSup->numOfExprs; ++i) { - pCtx[i].order = order; - pCtx[i].input.numOfRows = pBlock->info.rows; - - pCtx[i].pSrcBlock = pBlock; - pCtx[i].scanFlag = scanFlag; - - SInputColumnInfoData* pInput = &pCtx[i].input; - pInput->uid = pBlock->info.id.uid; - pInput->colDataSMAIsSet = false; - - SExprInfo* pOneExpr = &pExprSup->pExprInfo[i]; - for (int32_t j = 0; j < pOneExpr->base.numOfParams; ++j) { - SFunctParam* pFuncParam = &pOneExpr->base.pParam[j]; - if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) { - int32_t slotId = pFuncParam->pCol->slotId; - pInput->pData[j] = taosArrayGet(pBlock->pDataBlock, slotId); - pInput->totalRows = pBlock->info.rows; - pInput->numOfRows = pBlock->info.rows; - pInput->startRowIndex = 0; - - // NOTE: the last parameter is the primary timestamp column - // todo: refactor this - if (fmIsImplicitTsFunc(pCtx[i].functionId) && (j == pOneExpr->base.numOfParams - 1)) { - pInput->pPTS = pInput->pData[j]; // in case of merge function, this is not always the ts column data. - // ASSERT(pInput->pPTS->info.type == TSDB_DATA_TYPE_TIMESTAMP); - } - ASSERT(pInput->pData[j] != NULL); - } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) { - // todo avoid case: top(k, 12), 12 is the value parameter. - // sum(11), 11 is also the value parameter. - if (createDummyCol && pOneExpr->base.numOfParams == 1) { - pInput->totalRows = pBlock->info.rows; - pInput->numOfRows = pBlock->info.rows; - pInput->startRowIndex = 0; - - code = doCreateConstantValColumnInfo(pInput, pFuncParam, j, pBlock->info.rows); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - } - } - } - } - - return code; -} - -static int32_t doAggregateImpl(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx) { - for (int32_t k = 0; k < pOperator->exprSupp.numOfExprs; ++k) { - if (functionNeedToExecute(&pCtx[k])) { - // todo add a dummy funtion to avoid process check - if (pCtx[k].fpSet.process == NULL) { - continue; - } - - int32_t code = pCtx[k].fpSet.process(&pCtx[k]); - if (code != TSDB_CODE_SUCCESS) { - qError("%s aggregate function error happens, code: %s", GET_TASKID(pOperator->pTaskInfo), tstrerror(code)); - return code; - } - } - } - - return TSDB_CODE_SUCCESS; -} - -bool functionNeedToExecute(SqlFunctionCtx* pCtx) { - struct SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); - - // in case of timestamp column, always generated results. - int32_t functionId = pCtx->functionId; - if (functionId == -1) { - return false; - } - - if (pCtx->scanFlag == REPEAT_SCAN) { - return fmIsRepeatScanFunc(pCtx->functionId); - } - - if (isRowEntryCompleted(pResInfo)) { - return false; - } - - return true; -} - -static int32_t doCreateConstantValColumnSMAInfo(SInputColumnInfoData* pInput, SFunctParam* pFuncParam, int32_t type, - int32_t paramIndex, int32_t numOfRows) { - if (pInput->pData[paramIndex] == NULL) { - pInput->pData[paramIndex] = taosMemoryCalloc(1, sizeof(SColumnInfoData)); - if (pInput->pData[paramIndex] == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - // Set the correct column info (data type and bytes) - pInput->pData[paramIndex]->info.type = type; - pInput->pData[paramIndex]->info.bytes = tDataTypes[type].bytes; - } - - SColumnDataAgg* da = NULL; - if (pInput->pColumnDataAgg[paramIndex] == NULL) { - da = taosMemoryCalloc(1, sizeof(SColumnDataAgg)); - pInput->pColumnDataAgg[paramIndex] = da; - if (da == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - } else { - da = pInput->pColumnDataAgg[paramIndex]; - } - - if (type == TSDB_DATA_TYPE_BIGINT) { - int64_t v = pFuncParam->param.i; - *da = (SColumnDataAgg){.numOfNull = 0, .min = v, .max = v, .sum = v * numOfRows}; - } else if (type == TSDB_DATA_TYPE_DOUBLE) { - double v = pFuncParam->param.d; - *da = (SColumnDataAgg){.numOfNull = 0}; - - *(double*)&da->min = v; - *(double*)&da->max = v; - *(double*)&da->sum = v * numOfRows; - } else if (type == TSDB_DATA_TYPE_BOOL) { // todo validate this data type - bool v = pFuncParam->param.i; - - *da = (SColumnDataAgg){.numOfNull = 0}; - *(bool*)&da->min = 0; - *(bool*)&da->max = v; - *(bool*)&da->sum = v * numOfRows; - } else if (type == TSDB_DATA_TYPE_TIMESTAMP) { - // do nothing - } else { - qError("invalid constant type for sma info"); - } - - return TSDB_CODE_SUCCESS; -} - -void setBlockSMAInfo(SqlFunctionCtx* pCtx, SExprInfo* pExprInfo, SSDataBlock* pBlock) { - int32_t numOfRows = pBlock->info.rows; - - SInputColumnInfoData* pInput = &pCtx->input; - pInput->numOfRows = numOfRows; - pInput->totalRows = numOfRows; - - if (pBlock->pBlockAgg != NULL) { - pInput->colDataSMAIsSet = true; - - for (int32_t j = 0; j < pExprInfo->base.numOfParams; ++j) { - SFunctParam* pFuncParam = &pExprInfo->base.pParam[j]; - - if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) { - int32_t slotId = pFuncParam->pCol->slotId; - pInput->pColumnDataAgg[j] = pBlock->pBlockAgg[slotId]; - if (pInput->pColumnDataAgg[j] == NULL) { - pInput->colDataSMAIsSet = false; - } - - // Here we set the column info data since the data type for each column data is required, but - // the data in the corresponding SColumnInfoData will not be used. - pInput->pData[j] = taosArrayGet(pBlock->pDataBlock, slotId); - } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) { - doCreateConstantValColumnSMAInfo(pInput, pFuncParam, pFuncParam->param.nType, j, pBlock->info.rows); - } - } - } else { - pInput->colDataSMAIsSet = false; - } -} - -bool isTaskKilled(SExecTaskInfo* pTaskInfo) { return (0 != pTaskInfo->code) ? true : false; } - -void setTaskKilled(SExecTaskInfo* pTaskInfo, int32_t rspCode) { pTaskInfo->code = rspCode; } - -///////////////////////////////////////////////////////////////////////////////////////////// -STimeWindow getAlignQueryTimeWindow(const SInterval* pInterval, int64_t key) { - STimeWindow win = {0}; - win.skey = taosTimeTruncate(key, pInterval); - - /* - * if the realSkey > INT64_MAX - pInterval->interval, the query duration between - * realSkey and realEkey must be less than one interval.Therefore, no need to adjust the query ranges. - */ - win.ekey = taosTimeAdd(win.skey, pInterval->interval, pInterval->intervalUnit, pInterval->precision) - 1; - if (win.ekey < win.skey) { - win.ekey = INT64_MAX; - } - - return win; -} - -int32_t loadDataBlockOnDemand(SExecTaskInfo* pTaskInfo, STableScanInfo* pTableScanInfo, SSDataBlock* pBlock, - uint32_t* status) { - *status = BLK_DATA_NOT_LOAD; - - pBlock->pDataBlock = NULL; - pBlock->pBlockAgg = NULL; - - // int64_t groupId = pRuntimeEnv->current->groupIndex; - // bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr); - - STaskCostInfo* pCost = &pTaskInfo->cost; - -// pCost->totalBlocks += 1; -// pCost->totalRows += pBlock->info.rows; -#if 0 - // Calculate all time windows that are overlapping or contain current data block. - // If current data block is contained by all possible time window, do not load current data block. - if (/*pQueryAttr->pFilters || */pQueryAttr->groupbyColumn || pQueryAttr->sw.gap > 0 || - (QUERY_IS_INTERVAL_QUERY(pQueryAttr) && overlapWithTimeWindow(pTaskInfo, &pBlock->info))) { - (*status) = BLK_DATA_DATA_LOAD; - } - - // check if this data block is required to load - if ((*status) != BLK_DATA_DATA_LOAD) { - bool needFilter = true; - - // the pCtx[i] result is belonged to previous time window since the outputBuf has not been set yet, - // the filter result may be incorrect. So in case of interval query, we need to set the correct time output buffer - if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) { - SResultRow* pResult = NULL; - - bool masterScan = IS_MAIN_SCAN(pRuntimeEnv); - TSKEY k = ascQuery? pBlock->info.window.skey : pBlock->info.window.ekey; - - STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr); - if (pQueryAttr->pointInterpQuery) { - needFilter = chkWindowOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, &win, masterScan, &pResult, groupId, - pTableScanInfo->pCtx, pTableScanInfo->numOfOutput, - pTableScanInfo->rowEntryInfoOffset); - } else { - if (setResultOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pBlock->info.id.uid, &win, masterScan, &pResult, groupId, - pTableScanInfo->pCtx, pTableScanInfo->numOfOutput, - pTableScanInfo->rowEntryInfoOffset) != TSDB_CODE_SUCCESS) { - T_LONG_JMP(pRuntimeEnv->env, TSDB_CODE_OUT_OF_MEMORY); - } - } - } else if (pQueryAttr->stableQuery && (!pQueryAttr->tsCompQuery) && (!pQueryAttr->diffQuery)) { // stable aggregate, not interval aggregate or normal column aggregate - doSetTableGroupOutputBuf(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pTableScanInfo->pCtx, - pTableScanInfo->rowEntryInfoOffset, pTableScanInfo->numOfOutput, - pRuntimeEnv->current->groupIndex); - } - - if (needFilter) { - (*status) = doFilterByBlockTimeWindow(pTableScanInfo, pBlock); - } else { - (*status) = BLK_DATA_DATA_LOAD; - } - } - - SDataBlockInfo* pBlockInfo = &pBlock->info; -// *status = updateBlockLoadStatus(pRuntimeEnv->pQueryAttr, *status); - - if ((*status) == BLK_DATA_NOT_LOAD || (*status) == BLK_DATA_FILTEROUT) { - //qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey, -// pBlockInfo->window.ekey, pBlockInfo->rows); - pCost->skipBlocks += 1; - } else if ((*status) == BLK_DATA_SMA_LOAD) { - // this function never returns error? - pCost->loadBlockStatis += 1; -// tsdbRetrieveDatablockSMA(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg); - - if (pBlock->pBlockAgg == NULL) { // data block statistics does not exist, load data block -// pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pTsdbReadHandle, NULL); - pCost->totalCheckedRows += pBlock->info.rows; - } - } else { - assert((*status) == BLK_DATA_DATA_LOAD); - - // load the data block statistics to perform further filter - pCost->loadBlockStatis += 1; -// tsdbRetrieveDatablockSMA(pTableScanInfo->pTsdbReadHandle, &pBlock->pBlockAgg); - - if (pQueryAttr->topBotQuery && pBlock->pBlockAgg != NULL) { - { // set previous window - if (QUERY_IS_INTERVAL_QUERY(pQueryAttr)) { - SResultRow* pResult = NULL; - - bool masterScan = IS_MAIN_SCAN(pRuntimeEnv); - TSKEY k = ascQuery? pBlock->info.window.skey : pBlock->info.window.ekey; - - STimeWindow win = getActiveTimeWindow(pTableScanInfo->pResultRowInfo, k, pQueryAttr); - if (setResultOutputBufByKey(pRuntimeEnv, pTableScanInfo->pResultRowInfo, pBlock->info.id.uid, &win, masterScan, &pResult, groupId, - pTableScanInfo->pCtx, pTableScanInfo->numOfOutput, - pTableScanInfo->rowEntryInfoOffset) != TSDB_CODE_SUCCESS) { - T_LONG_JMP(pRuntimeEnv->env, TSDB_CODE_OUT_OF_MEMORY); - } - } - } - bool load = false; - for (int32_t i = 0; i < pQueryAttr->numOfOutput; ++i) { - int32_t functionId = pTableScanInfo->pCtx[i].functionId; - if (functionId == FUNCTION_TOP || functionId == FUNCTION_BOTTOM) { -// load = topbot_datablock_filter(&pTableScanInfo->pCtx[i], (char*)&(pBlock->pBlockAgg[i].min), -// (char*)&(pBlock->pBlockAgg[i].max)); - if (!load) { // current block has been discard due to filter applied - pCost->skipBlocks += 1; - //qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, -// pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); - (*status) = BLK_DATA_FILTEROUT; - return TSDB_CODE_SUCCESS; - } - } - } - } - - // current block has been discard due to filter applied -// if (!doFilterByBlockSMA(pRuntimeEnv, pBlock->pBlockAgg, pTableScanInfo->pCtx, pBlockInfo->rows)) { -// pCost->skipBlocks += 1; -// qDebug("QInfo:0x%"PRIx64" data block discard, brange:%" PRId64 "-%" PRId64 ", rows:%d", pQInfo->qId, pBlockInfo->window.skey, -// pBlockInfo->window.ekey, pBlockInfo->rows); -// (*status) = BLK_DATA_FILTEROUT; -// return TSDB_CODE_SUCCESS; -// } - - pCost->totalCheckedRows += pBlockInfo->rows; - pCost->loadBlocks += 1; -// pBlock->pDataBlock = tsdbRetrieveDataBlock(pTableScanInfo->pTsdbReadHandle, NULL); -// if (pBlock->pDataBlock == NULL) { -// return terrno; -// } - -// if (pQueryAttr->pFilters != NULL) { -// filterSetColFieldData(pQueryAttr->pFilters, taosArrayGetSize(pBlock->pDataBlock), pBlock->pDataBlock); -// } - -// if (pQueryAttr->pFilters != NULL || pRuntimeEnv->pTsBuf != NULL) { -// filterColRowsInDataBlock(pRuntimeEnv, pBlock, ascQuery); -// } - } -#endif - return TSDB_CODE_SUCCESS; -} - -void setTaskStatus(SExecTaskInfo* pTaskInfo, int8_t status) { - if (status == TASK_NOT_COMPLETED) { - pTaskInfo->status = status; - } else { - // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first - CLEAR_QUERY_STATUS(pTaskInfo, TASK_NOT_COMPLETED); - pTaskInfo->status |= status; - } -} - -void setResultRowInitCtx(SResultRow* pResult, SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset) { - bool init = false; - for (int32_t i = 0; i < numOfOutput; ++i) { - pCtx[i].resultInfo = getResultEntryInfo(pResult, i, rowEntryInfoOffset); - if (init) { - continue; - } - - struct SResultRowEntryInfo* pResInfo = pCtx[i].resultInfo; - if (isRowEntryCompleted(pResInfo) && isRowEntryInitialized(pResInfo)) { - continue; - } - - if (pCtx[i].isPseudoFunc) { - continue; - } - - if (!pResInfo->initialized) { - if (pCtx[i].functionId != -1) { - pCtx[i].fpSet.init(&pCtx[i], pResInfo); - } else { - pResInfo->initialized = true; - } - } else { - init = true; - } - } -} - -void doFilter(SSDataBlock* pBlock, SFilterInfo* pFilterInfo, SColMatchInfo* pColMatchInfo) { - if (pFilterInfo == NULL || pBlock->info.rows == 0) { - return; - } - - SFilterColumnParam param1 = {.numOfCols = taosArrayGetSize(pBlock->pDataBlock), .pDataBlock = pBlock->pDataBlock}; - int32_t code = filterSetDataFromSlotId(pFilterInfo, ¶m1); - - SColumnInfoData* p = NULL; - int32_t status = 0; - - // todo the keep seems never to be True?? - bool keep = filterExecute(pFilterInfo, pBlock, &p, NULL, param1.numOfCols, &status); - extractQualifiedTupleByFilterResult(pBlock, p, keep, status); - - if (pColMatchInfo != NULL) { - size_t size = taosArrayGetSize(pColMatchInfo->pList); - for (int32_t i = 0; i < size; ++i) { - SColMatchItem* pInfo = taosArrayGet(pColMatchInfo->pList, i); - if (pInfo->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { - SColumnInfoData* pColData = taosArrayGet(pBlock->pDataBlock, pInfo->dstSlotId); - if (pColData->info.type == TSDB_DATA_TYPE_TIMESTAMP) { - blockDataUpdateTsWindow(pBlock, pInfo->dstSlotId); - break; - } - } - } - } - - colDataDestroy(p); - taosMemoryFree(p); -} - -void extractQualifiedTupleByFilterResult(SSDataBlock* pBlock, const SColumnInfoData* p, bool keep, int32_t status) { - if (keep) { - return; - } - - int8_t* pIndicator = (int8_t*)p->pData; - int32_t totalRows = pBlock->info.rows; - - if (status == FILTER_RESULT_ALL_QUALIFIED) { - // here nothing needs to be done - } else if (status == FILTER_RESULT_NONE_QUALIFIED) { - pBlock->info.rows = 0; - } else { - int32_t bmLen = BitmapLen(totalRows); - char* pBitmap = NULL; - int32_t maxRows = 0; - - size_t numOfCols = taosArrayGetSize(pBlock->pDataBlock); - for (int32_t i = 0; i < numOfCols; ++i) { - SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, i); - // it is a reserved column for scalar function, and no data in this column yet. - if (pDst->pData == NULL) { - continue; - } - - int32_t numOfRows = 0; - - if (IS_VAR_DATA_TYPE(pDst->info.type)) { - int32_t j = 0; - pDst->varmeta.length = 0; - - while(j < totalRows) { - if (pIndicator[j] == 0) { - j += 1; - continue; - } - - if (colDataIsNull_var(pDst, j)) { - colDataSetNull_var(pDst, numOfRows); - } else { - char* p1 = colDataGetVarData(pDst, j); - colDataAppend(pDst, numOfRows, p1, false); - } - numOfRows += 1; - j += 1; - } - - if (maxRows < numOfRows) { - maxRows = numOfRows; - } - } else { - if (pBitmap == NULL) { - pBitmap = taosMemoryCalloc(1, bmLen); - } - - memcpy(pBitmap, pDst->nullbitmap, bmLen); - memset(pDst->nullbitmap, 0, bmLen); - - int32_t j = 0; - - switch (pDst->info.type) { - case TSDB_DATA_TYPE_BIGINT: - case TSDB_DATA_TYPE_UBIGINT: - case TSDB_DATA_TYPE_DOUBLE: - case TSDB_DATA_TYPE_TIMESTAMP: - while (j < totalRows) { - if (pIndicator[j] == 0) { - j += 1; - continue; - } - - if (colDataIsNull_f(pBitmap, j)) { - colDataSetNull_f(pDst->nullbitmap, numOfRows); - } else { - ((int64_t*)pDst->pData)[numOfRows] = ((int64_t*)pDst->pData)[j]; - } - numOfRows += 1; - j += 1; - } - break; - case TSDB_DATA_TYPE_FLOAT: - case TSDB_DATA_TYPE_INT: - case TSDB_DATA_TYPE_UINT: - while (j < totalRows) { - if (pIndicator[j] == 0) { - j += 1; - continue; - } - if (colDataIsNull_f(pBitmap, j)) { - colDataSetNull_f(pDst->nullbitmap, numOfRows); - } else { - ((int32_t*)pDst->pData)[numOfRows] = ((int32_t*)pDst->pData)[j]; - } - numOfRows += 1; - j += 1; - } - break; - case TSDB_DATA_TYPE_SMALLINT: - case TSDB_DATA_TYPE_USMALLINT: - while (j < totalRows) { - if (pIndicator[j] == 0) { - j += 1; - continue; - } - if (colDataIsNull_f(pBitmap, j)) { - colDataSetNull_f(pDst->nullbitmap, numOfRows); - } else { - ((int16_t*)pDst->pData)[numOfRows] = ((int16_t*)pDst->pData)[j]; - } - numOfRows += 1; - j += 1; - } - break; - case TSDB_DATA_TYPE_BOOL: - case TSDB_DATA_TYPE_TINYINT: - case TSDB_DATA_TYPE_UTINYINT: - while (j < totalRows) { - if (pIndicator[j] == 0) { - j += 1; - continue; - } - if (colDataIsNull_f(pBitmap, j)) { - colDataSetNull_f(pDst->nullbitmap, numOfRows); - } else { - ((int8_t*)pDst->pData)[numOfRows] = ((int8_t*)pDst->pData)[j]; - } - numOfRows += 1; - j += 1; - } - break; - } - } - - if (maxRows < numOfRows) { - maxRows = numOfRows; - } - } - - pBlock->info.rows = maxRows; - if (pBitmap != NULL) { - taosMemoryFree(pBitmap); - } - } -} - -void doSetTableGroupOutputBuf(SOperatorInfo* pOperator, int32_t numOfOutput, uint64_t groupId) { - // for simple group by query without interval, all the tables belong to one group result. - SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - SAggOperatorInfo* pAggInfo = pOperator->info; - - SResultRowInfo* pResultRowInfo = &pAggInfo->binfo.resultRowInfo; - SqlFunctionCtx* pCtx = pOperator->exprSupp.pCtx; - int32_t* rowEntryInfoOffset = pOperator->exprSupp.rowEntryInfoOffset; - - SResultRow* pResultRow = doSetResultOutBufByKey(pAggInfo->aggSup.pResultBuf, pResultRowInfo, (char*)&groupId, - sizeof(groupId), true, groupId, pTaskInfo, false, &pAggInfo->aggSup); - assert(pResultRow != NULL); - - /* - * not assign result buffer yet, add new result buffer - * all group belong to one result set, and each group result has different group id so set the id to be one - */ - if (pResultRow->pageId == -1) { - int32_t ret = addNewWindowResultBuf(pResultRow, pAggInfo->aggSup.pResultBuf, pAggInfo->binfo.pRes->info.rowSize); - if (ret != TSDB_CODE_SUCCESS) { - T_LONG_JMP(pTaskInfo->env, terrno); - } - } - - setResultRowInitCtx(pResultRow, pCtx, numOfOutput, rowEntryInfoOffset); -} - -static void setExecutionContext(SOperatorInfo* pOperator, int32_t numOfOutput, uint64_t groupId) { - SAggOperatorInfo* pAggInfo = pOperator->info; - if (pAggInfo->groupId != UINT64_MAX && pAggInfo->groupId == groupId) { - return; - } - - doSetTableGroupOutputBuf(pOperator, numOfOutput, groupId); - - // record the current active group id - pAggInfo->groupId = groupId; -} - -static void doUpdateNumOfRows(SqlFunctionCtx* pCtx, SResultRow* pRow, int32_t numOfExprs, - const int32_t* rowEntryOffset) { - bool returnNotNull = false; - for (int32_t j = 0; j < numOfExprs; ++j) { - SResultRowEntryInfo* pResInfo = getResultEntryInfo(pRow, j, rowEntryOffset); - if (!isRowEntryInitialized(pResInfo)) { - continue; - } - - if (pRow->numOfRows < pResInfo->numOfRes) { - pRow->numOfRows = pResInfo->numOfRes; - } - - if (pCtx[j].isNotNullFunc) { - returnNotNull = true; - } - } - // if all expr skips all blocks, e.g. all null inputs for max function, output one row in final result. - // except for first/last, which require not null output, output no rows - if (pRow->numOfRows == 0 && !returnNotNull) { - pRow->numOfRows = 1; - } -} - -static void doCopyResultToDataBlock(SExprInfo* pExprInfo, int32_t numOfExprs, SResultRow* pRow, SqlFunctionCtx* pCtx, - SSDataBlock* pBlock, const int32_t* rowEntryOffset, SExecTaskInfo* pTaskInfo) { - for (int32_t j = 0; j < numOfExprs; ++j) { - int32_t slotId = pExprInfo[j].base.resSchema.slotId; - - pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset); - if (pCtx[j].fpSet.finalize) { - if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_group_key") == 0) { - // for groupkey along with functions that output multiple lines(e.g. Histogram) - // need to match groupkey result for each output row of that function. - if (pCtx[j].resultInfo->numOfRes != 0) { - pCtx[j].resultInfo->numOfRes = pRow->numOfRows; - } - } - - int32_t code = pCtx[j].fpSet.finalize(&pCtx[j], pBlock); - if (TAOS_FAILED(code)) { - qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(code)); - T_LONG_JMP(pTaskInfo->env, code); - } - } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) { - // do nothing - } else { - // expand the result into multiple rows. E.g., _wstart, top(k, 20) - // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows. - SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId); - char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo); - for (int32_t k = 0; k < pRow->numOfRows; ++k) { - colDataAppend(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes); - } - } - } -} - -// todo refactor. SResultRow has direct pointer in miainfo -int32_t finalizeResultRows(SDiskbasedBuf* pBuf, SResultRowPosition* resultRowPosition, SExprSupp* pSup, - SSDataBlock* pBlock, SExecTaskInfo* pTaskInfo) { - SFilePage* page = getBufPage(pBuf, resultRowPosition->pageId); - if (page == NULL) { - qError("failed to get buffer, code:%s, %s", tstrerror(terrno), GET_TASKID(pTaskInfo)); - T_LONG_JMP(pTaskInfo->env, terrno); - } - - SResultRow* pRow = (SResultRow*)((char*)page + resultRowPosition->offset); - - SqlFunctionCtx* pCtx = pSup->pCtx; - SExprInfo* pExprInfo = pSup->pExprInfo; - const int32_t* rowEntryOffset = pSup->rowEntryInfoOffset; - - doUpdateNumOfRows(pCtx, pRow, pSup->numOfExprs, rowEntryOffset); - if (pRow->numOfRows == 0) { - releaseBufPage(pBuf, page); - return 0; - } - - int32_t size = pBlock->info.capacity; - while (pBlock->info.rows + pRow->numOfRows > size) { - size = size * 1.25; - } - - int32_t code = blockDataEnsureCapacity(pBlock, size); - if (TAOS_FAILED(code)) { - releaseBufPage(pBuf, page); - qError("%s ensure result data capacity failed, code %s", GET_TASKID(pTaskInfo), tstrerror(code)); - T_LONG_JMP(pTaskInfo->env, code); - } - - doCopyResultToDataBlock(pExprInfo, pSup->numOfExprs, pRow, pCtx, pBlock, rowEntryOffset, pTaskInfo); - - releaseBufPage(pBuf, page); - pBlock->info.rows += pRow->numOfRows; - return 0; -} - -int32_t doCopyToSDataBlock(SExecTaskInfo* pTaskInfo, SSDataBlock* pBlock, SExprSupp* pSup, SDiskbasedBuf* pBuf, - SGroupResInfo* pGroupResInfo) { - SExprInfo* pExprInfo = pSup->pExprInfo; - int32_t numOfExprs = pSup->numOfExprs; - int32_t* rowEntryOffset = pSup->rowEntryInfoOffset; - SqlFunctionCtx* pCtx = pSup->pCtx; - - int32_t numOfRows = getNumOfTotalRes(pGroupResInfo); - - for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) { - SResKeyPos* pPos = taosArrayGetP(pGroupResInfo->pRows, i); - SFilePage* page = getBufPage(pBuf, pPos->pos.pageId); - if (page == NULL) { - qError("failed to get buffer, code:%s, %s", tstrerror(terrno), GET_TASKID(pTaskInfo)); - T_LONG_JMP(pTaskInfo->env, terrno); - } - - SResultRow* pRow = (SResultRow*)((char*)page + pPos->pos.offset); - - doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset); - - // no results, continue to check the next one - if (pRow->numOfRows == 0) { - pGroupResInfo->index += 1; - releaseBufPage(pBuf, page); - continue; - } - - if (pBlock->info.id.groupId == 0) { - pBlock->info.id.groupId = pPos->groupId; - } else { - // current value belongs to different group, it can't be packed into one datablock - if (pBlock->info.id.groupId != pPos->groupId) { - releaseBufPage(pBuf, page); - break; - } - } - - if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) { - releaseBufPage(pBuf, page); - - if (pBlock->info.rows <= 0 || pRow->numOfRows > pBlock->info.capacity) { - qError("error in copy data to ssdatablock, existed rows in block:%d, rows in pRow:%d, capacity:%d, %s", - pBlock->info.rows, pRow->numOfRows, pBlock->info.capacity, GET_TASKID(pTaskInfo)); - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_APP_ERROR); - } else { - break; - } - } - - pGroupResInfo->index += 1; - doCopyResultToDataBlock(pExprInfo, numOfExprs, pRow, pCtx, pBlock, rowEntryOffset, pTaskInfo); - - releaseBufPage(pBuf, page); - pBlock->info.rows += pRow->numOfRows; - } - - qDebug("%s result generated, rows:%d, groupId:%" PRIu64, GET_TASKID(pTaskInfo), pBlock->info.rows, - pBlock->info.id.groupId); - pBlock->info.dataLoad = 1; - blockDataUpdateTsWindow(pBlock, 0); - return 0; -} - -void doBuildStreamResBlock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, - SDiskbasedBuf* pBuf) { - SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - SSDataBlock* pBlock = pbInfo->pRes; - - // set output datablock version - pBlock->info.version = pTaskInfo->version; - - blockDataCleanup(pBlock); - if (!hasRemainResults(pGroupResInfo)) { - return; - } - - // clear the existed group id - pBlock->info.id.groupId = 0; - ASSERT(!pbInfo->mergeResultBlock); - doCopyToSDataBlock(pTaskInfo, pBlock, &pOperator->exprSupp, pBuf, pGroupResInfo); - - void* tbname = NULL; - if (streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) < 0) { - pBlock->info.parTbName[0] = 0; - } else { - memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN); - } - tdbFree(tbname); -} - -void doBuildResultDatablock(SOperatorInfo* pOperator, SOptrBasicInfo* pbInfo, SGroupResInfo* pGroupResInfo, - SDiskbasedBuf* pBuf) { - SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - SSDataBlock* pBlock = pbInfo->pRes; - - // set output datablock version - pBlock->info.version = pTaskInfo->version; - - blockDataCleanup(pBlock); - if (!hasRemainResults(pGroupResInfo)) { - return; - } - - // clear the existed group id - pBlock->info.id.groupId = 0; - if (!pbInfo->mergeResultBlock) { - doCopyToSDataBlock(pTaskInfo, pBlock, &pOperator->exprSupp, pBuf, pGroupResInfo); - } else { - while (hasRemainResults(pGroupResInfo)) { - doCopyToSDataBlock(pTaskInfo, pBlock, &pOperator->exprSupp, pBuf, pGroupResInfo); - if (pBlock->info.rows >= pOperator->resultInfo.threshold) { - break; - } - - // clearing group id to continue to merge data that belong to different groups - pBlock->info.id.groupId = 0; - } - - // clear the group id info in SSDataBlock, since the client does not need it - pBlock->info.id.groupId = 0; - } -} - -// static TSKEY doSkipIntervalProcess(STaskRuntimeEnv* pRuntimeEnv, STimeWindow* win, SDataBlockInfo* pBlockInfo, -// STableQueryInfo* pTableQueryInfo) { -// STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr; -// SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; -// -// assert(pQueryAttr->limit.offset == 0); -// STimeWindow tw = *win; -// getNextTimeWindow(pQueryAttr, &tw); -// -// if ((tw.skey <= pBlockInfo->window.ekey && QUERY_IS_ASC_QUERY(pQueryAttr)) || -// (tw.ekey >= pBlockInfo->window.skey && !QUERY_IS_ASC_QUERY(pQueryAttr))) { -// -// // load the data block and check data remaining in current data block -// // TODO optimize performance -// SArray * pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pTsdbReadHandle, NULL); -// SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); -// -// tw = *win; -// int32_t startPos = -// getNextQualifiedWindow(pQueryAttr, &tw, pBlockInfo, pColInfoData->pData, binarySearchForKey, -1); -// assert(startPos >= 0); -// -// // set the abort info -// pQueryAttr->pos = startPos; -// -// // reset the query start timestamp -// pTableQueryInfo->win.skey = ((TSKEY *)pColInfoData->pData)[startPos]; -// pQueryAttr->window.skey = pTableQueryInfo->win.skey; -// TSKEY key = pTableQueryInfo->win.skey; -// -// pWindowResInfo->prevSKey = tw.skey; -// int32_t index = pRuntimeEnv->resultRowInfo.curIndex; -// -// int32_t numOfRes = tableApplyFunctionsOnBlock(pRuntimeEnv, pBlockInfo, NULL, binarySearchForKey, pDataBlock); -// pRuntimeEnv->resultRowInfo.curIndex = index; // restore the window index -// -// //qDebug("QInfo:0x%"PRIx64" check data block, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, numOfRes:%d, -// lastKey:%" PRId64, -// GET_TASKID(pRuntimeEnv), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, numOfRes, -// pQueryAttr->current->lastKey); -// -// return key; -// } else { // do nothing -// pQueryAttr->window.skey = tw.skey; -// pWindowResInfo->prevSKey = tw.skey; -// pTableQueryInfo->lastKey = tw.skey; -// -// return tw.skey; -// } -// -// return true; -// } - -// static bool skipTimeInterval(STaskRuntimeEnv *pRuntimeEnv, TSKEY* start) { -// STaskAttr *pQueryAttr = pRuntimeEnv->pQueryAttr; -// if (QUERY_IS_ASC_QUERY(pQueryAttr)) { -// assert(*start <= pRuntimeEnv->current->lastKey); -// } else { -// assert(*start >= pRuntimeEnv->current->lastKey); -// } -// -// // if queried with value filter, do NOT forward query start position -// if (pQueryAttr->limit.offset <= 0 || pQueryAttr->numOfFilterCols > 0 || pRuntimeEnv->pTsBuf != NULL || -// pRuntimeEnv->pFillInfo != NULL) { -// return true; -// } -// -// /* -// * 1. for interval without interpolation query we forward pQueryAttr->interval.interval at a time for -// * pQueryAttr->limit.offset times. Since hole exists, pQueryAttr->interval.interval*pQueryAttr->limit.offset -// value is -// * not valid. otherwise, we only forward pQueryAttr->limit.offset number of points -// */ -// assert(pRuntimeEnv->resultRowInfo.prevSKey == TSKEY_INITIAL_VAL); -// -// STimeWindow w = TSWINDOW_INITIALIZER; -// bool ascQuery = QUERY_IS_ASC_QUERY(pQueryAttr); -// -// SResultRowInfo *pWindowResInfo = &pRuntimeEnv->resultRowInfo; -// STableQueryInfo *pTableQueryInfo = pRuntimeEnv->current; -// -// SDataBlockInfo blockInfo = SDATA_BLOCK_INITIALIZER; -// while (tsdbNextDataBlock(pRuntimeEnv->pTsdbReadHandle)) { -// tsdbRetrieveDataBlockInfo(pRuntimeEnv->pTsdbReadHandle, &blockInfo); -// -// if (QUERY_IS_ASC_QUERY(pQueryAttr)) { -// if (pWindowResInfo->prevSKey == TSKEY_INITIAL_VAL) { -// getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.skey, blockInfo.window.skey, pQueryAttr->window.ekey, -// &w); pWindowResInfo->prevSKey = w.skey; -// } -// } else { -// getAlignQueryTimeWindow(pQueryAttr, blockInfo.window.ekey, pQueryAttr->window.ekey, blockInfo.window.ekey, &w); -// pWindowResInfo->prevSKey = w.skey; -// } -// -// // the first time window -// STimeWindow win = getActiveTimeWindow(pWindowResInfo, pWindowResInfo->prevSKey, pQueryAttr); -// -// while (pQueryAttr->limit.offset > 0) { -// STimeWindow tw = win; -// -// if ((win.ekey <= blockInfo.window.ekey && ascQuery) || (win.ekey >= blockInfo.window.skey && !ascQuery)) { -// pQueryAttr->limit.offset -= 1; -// pWindowResInfo->prevSKey = win.skey; -// -// // current time window is aligned with blockInfo.window.ekey -// // restart it from next data block by set prevSKey to be TSKEY_INITIAL_VAL; -// if ((win.ekey == blockInfo.window.ekey && ascQuery) || (win.ekey == blockInfo.window.skey && !ascQuery)) { -// pWindowResInfo->prevSKey = TSKEY_INITIAL_VAL; -// } -// } -// -// if (pQueryAttr->limit.offset == 0) { -// *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo); -// return true; -// } -// -// // current window does not ended in current data block, try next data block -// getNextTimeWindow(pQueryAttr, &tw); -// -// /* -// * If the next time window still starts from current data block, -// * load the primary timestamp column first, and then find the start position for the next queried time window. -// * Note that only the primary timestamp column is required. -// * TODO: Optimize for this cases. All data blocks are not needed to be loaded, only if the first actually -// required -// * time window resides in current data block. -// */ -// if ((tw.skey <= blockInfo.window.ekey && ascQuery) || (tw.ekey >= blockInfo.window.skey && !ascQuery)) { -// -// SArray *pDataBlock = tsdbRetrieveDataBlock(pRuntimeEnv->pTsdbReadHandle, NULL); -// SColumnInfoData *pColInfoData = taosArrayGet(pDataBlock, 0); -// -// if ((win.ekey > blockInfo.window.ekey && ascQuery) || (win.ekey < blockInfo.window.skey && !ascQuery)) { -// pQueryAttr->limit.offset -= 1; -// } -// -// if (pQueryAttr->limit.offset == 0) { -// *start = doSkipIntervalProcess(pRuntimeEnv, &win, &blockInfo, pTableQueryInfo); -// return true; -// } else { -// tw = win; -// int32_t startPos = -// getNextQualifiedWindow(pQueryAttr, &tw, &blockInfo, pColInfoData->pData, binarySearchForKey, -1); -// assert(startPos >= 0); -// -// // set the abort info -// pQueryAttr->pos = startPos; -// pTableQueryInfo->lastKey = ((TSKEY *)pColInfoData->pData)[startPos]; -// pWindowResInfo->prevSKey = tw.skey; -// win = tw; -// } -// } else { -// break; // offset is not 0, and next time window begins or ends in the next block. -// } -// } -// } -// -// // check for error -// if (terrno != TSDB_CODE_SUCCESS) { -// T_LONG_JMP(pRuntimeEnv->env, terrno); -// } -// -// return true; -// } - -int32_t appendDownstream(SOperatorInfo* p, SOperatorInfo** pDownstream, int32_t num) { - if (p->pDownstream == NULL) { - assert(p->numOfDownstream == 0); - } - - p->pDownstream = taosMemoryCalloc(1, num * POINTER_BYTES); - if (p->pDownstream == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - memcpy(p->pDownstream, pDownstream, num * POINTER_BYTES); - p->numOfDownstream = num; - return TSDB_CODE_SUCCESS; -} - -int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scanFlag) { - // todo add more information about exchange operation - int32_t type = pOperator->operatorType; - if (type == QUERY_NODE_PHYSICAL_PLAN_EXCHANGE || type == QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN || - type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN || - type == QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN || - type == QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN) { - *order = TSDB_ORDER_ASC; - *scanFlag = MAIN_SCAN; - return TSDB_CODE_SUCCESS; - } else if (type == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) { - STableScanInfo* pTableScanInfo = pOperator->info; - *order = pTableScanInfo->base.cond.order; - *scanFlag = pTableScanInfo->base.scanFlag; - return TSDB_CODE_SUCCESS; - } else if (type == QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN) { - STableMergeScanInfo* pTableScanInfo = pOperator->info; - *order = pTableScanInfo->base.cond.order; - *scanFlag = pTableScanInfo->base.scanFlag; - return TSDB_CODE_SUCCESS; - } else { - if (pOperator->pDownstream == NULL || pOperator->pDownstream[0] == NULL) { - return TSDB_CODE_INVALID_PARA; - } else { - return getTableScanInfo(pOperator->pDownstream[0], order, scanFlag); - } - } -} - -static int32_t createDataBlockForEmptyInput(SOperatorInfo* pOperator, SSDataBlock** ppBlock) { - if (!tsCountAlwaysReturnValue) { - return TSDB_CODE_SUCCESS; - } - - SAggOperatorInfo* pAggInfo = pOperator->info; - if (pAggInfo->groupKeyOptimized) { - return TSDB_CODE_SUCCESS; - } - - SOperatorInfo* downstream = pOperator->pDownstream[0]; - if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_PARTITION || - (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN && - ((STableScanInfo*)downstream->info)->hasGroupByTag == true)) { - return TSDB_CODE_SUCCESS; - } - - SqlFunctionCtx* pCtx = pOperator->exprSupp.pCtx; - bool hasCountFunc = false; - - for (int32_t i = 0; i < pOperator->exprSupp.numOfExprs; ++i) { - const char* pName = pCtx[i].pExpr->pExpr->_function.functionName; - if ((strcmp(pName, "count") == 0) || (strcmp(pName, "hyperloglog") == 0) || - (strcmp(pName, "_hyperloglog_partial") == 0) || (strcmp(pName, "_hyperloglog_merge") == 0)) { - hasCountFunc = true; - break; - } - } - - if (!hasCountFunc) { - return TSDB_CODE_SUCCESS; - } - - SSDataBlock* pBlock = createDataBlock(); - pBlock->info.rows = 1; - pBlock->info.capacity = 0; - - for (int32_t i = 0; i < pOperator->exprSupp.numOfExprs; ++i) { - SColumnInfoData colInfo = {0}; - colInfo.hasNull = true; - colInfo.info.type = TSDB_DATA_TYPE_NULL; - colInfo.info.bytes = 1; - - SExprInfo* pOneExpr = &pOperator->exprSupp.pExprInfo[i]; - for (int32_t j = 0; j < pOneExpr->base.numOfParams; ++j) { - SFunctParam* pFuncParam = &pOneExpr->base.pParam[j]; - if (pFuncParam->type == FUNC_PARAM_TYPE_COLUMN) { - int32_t slotId = pFuncParam->pCol->slotId; - int32_t numOfCols = taosArrayGetSize(pBlock->pDataBlock); - if (slotId >= numOfCols) { - taosArrayEnsureCap(pBlock->pDataBlock, slotId + 1); - for (int32_t k = numOfCols; k < slotId + 1; ++k) { - taosArrayPush(pBlock->pDataBlock, &colInfo); - } - } - } else if (pFuncParam->type == FUNC_PARAM_TYPE_VALUE) { - // do nothing - } - } - } - - blockDataEnsureCapacity(pBlock, pBlock->info.rows); - *ppBlock = pBlock; - - return TSDB_CODE_SUCCESS; -} - -static void destroyDataBlockForEmptyInput(bool blockAllocated, SSDataBlock** ppBlock) { - if (!blockAllocated) { - return; - } - - blockDataDestroy(*ppBlock); - *ppBlock = NULL; -} - -// this is a blocking operator -static int32_t doOpenAggregateOptr(SOperatorInfo* pOperator) { - if (OPTR_IS_OPENED(pOperator)) { - return TSDB_CODE_SUCCESS; - } - - SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - SAggOperatorInfo* pAggInfo = pOperator->info; - - SExprSupp* pSup = &pOperator->exprSupp; - SOperatorInfo* downstream = pOperator->pDownstream[0]; - - int64_t st = taosGetTimestampUs(); - - int32_t order = TSDB_ORDER_ASC; - int32_t scanFlag = MAIN_SCAN; - - bool hasValidBlock = false; - bool blockAllocated = false; - - while (1) { - SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); - if (pBlock == NULL) { - if (!hasValidBlock) { - createDataBlockForEmptyInput(pOperator, &pBlock); - if (pBlock == NULL) { - break; - } - blockAllocated = true; - } else { - break; - } - } - hasValidBlock = true; - - int32_t code = getTableScanInfo(pOperator, &order, &scanFlag); - if (code != TSDB_CODE_SUCCESS) { - destroyDataBlockForEmptyInput(blockAllocated, &pBlock); - T_LONG_JMP(pTaskInfo->env, code); - } - - // there is an scalar expression that needs to be calculated before apply the group aggregation. - if (pAggInfo->scalarExprSup.pExprInfo != NULL && !blockAllocated) { - SExprSupp* pSup1 = &pAggInfo->scalarExprSup; - code = projectApplyFunctions(pSup1->pExprInfo, pBlock, pBlock, pSup1->pCtx, pSup1->numOfExprs, NULL); - if (code != TSDB_CODE_SUCCESS) { - destroyDataBlockForEmptyInput(blockAllocated, &pBlock); - T_LONG_JMP(pTaskInfo->env, code); - } - } - - // the pDataBlock are always the same one, no need to call this again - setExecutionContext(pOperator, pOperator->exprSupp.numOfExprs, pBlock->info.id.groupId); - setInputDataBlock(pSup, pBlock, order, scanFlag, true); - code = doAggregateImpl(pOperator, pSup->pCtx); - if (code != 0) { - destroyDataBlockForEmptyInput(blockAllocated, &pBlock); - T_LONG_JMP(pTaskInfo->env, code); - } - - destroyDataBlockForEmptyInput(blockAllocated, &pBlock); - } - - // the downstream operator may return with error code, so let's check the code before generating results. - if (pTaskInfo->code != TSDB_CODE_SUCCESS) { - T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); - } - - initGroupedResultInfo(&pAggInfo->groupResInfo, pAggInfo->aggSup.pResultRowHashTable, 0); - OPTR_SET_OPENED(pOperator); - - pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0; - return pTaskInfo->code; -} - -static SSDataBlock* getAggregateResult(SOperatorInfo* pOperator) { - SAggOperatorInfo* pAggInfo = pOperator->info; - SOptrBasicInfo* pInfo = &pAggInfo->binfo; - - if (pOperator->status == OP_EXEC_DONE) { - return NULL; - } - - SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - pTaskInfo->code = pOperator->fpSet._openFn(pOperator); - if (pTaskInfo->code != TSDB_CODE_SUCCESS) { - setOperatorCompleted(pOperator); - return NULL; - } - - blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity); - while (1) { - doBuildResultDatablock(pOperator, pInfo, &pAggInfo->groupResInfo, pAggInfo->aggSup.pResultBuf); - doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); - - if (!hasRemainResults(&pAggInfo->groupResInfo)) { - setOperatorCompleted(pOperator); - break; - } - - if (pInfo->pRes->info.rows > 0) { - break; - } - } - - size_t rows = blockDataGetNumOfRows(pInfo->pRes); - pOperator->resultInfo.totalRows += rows; - - return (rows == 0) ? NULL : pInfo->pRes; -} - -void destroyExprInfo(SExprInfo* pExpr, int32_t numOfExprs) { - for (int32_t i = 0; i < numOfExprs; ++i) { - SExprInfo* pExprInfo = &pExpr[i]; - for (int32_t j = 0; j < pExprInfo->base.numOfParams; ++j) { - if (pExprInfo->base.pParam[j].type == FUNC_PARAM_TYPE_COLUMN) { - taosMemoryFreeClear(pExprInfo->base.pParam[j].pCol); - } else if (pExprInfo->base.pParam[j].type == FUNC_PARAM_TYPE_VALUE) { - taosVariantDestroy(&pExprInfo->base.pParam[j].param); - } - } - - taosMemoryFree(pExprInfo->base.pParam); - taosMemoryFree(pExprInfo->pExpr); - } -} - -void destroyOperatorInfo(SOperatorInfo* pOperator) { - if (pOperator == NULL) { - return; - } - - if (pOperator->fpSet.closeFn != NULL) { - pOperator->fpSet.closeFn(pOperator->info); - } - - if (pOperator->pDownstream != NULL) { - for (int32_t i = 0; i < pOperator->numOfDownstream; ++i) { - destroyOperatorInfo(pOperator->pDownstream[i]); - } - - taosMemoryFreeClear(pOperator->pDownstream); - pOperator->numOfDownstream = 0; - } - - cleanupExprSupp(&pOperator->exprSupp); - taosMemoryFreeClear(pOperator); -} - -// each operator should be set their own function to return total cost buffer -int32_t optrDefaultBufFn(SOperatorInfo* pOperator) { - if (pOperator->blocking) { - return -1; - } else { - return 0; - } -} - -int32_t getBufferPgSize(int32_t rowSize, uint32_t* defaultPgsz, uint32_t* defaultBufsz) { - *defaultPgsz = 4096; - while (*defaultPgsz < rowSize * 4) { - *defaultPgsz <<= 1u; - } - - // The default buffer for each operator in query is 10MB. - // at least four pages need to be in buffer - // TODO: make this variable to be configurable. - *defaultBufsz = 4096 * 2560; - if ((*defaultBufsz) <= (*defaultPgsz)) { - (*defaultBufsz) = (*defaultPgsz) * 4; - } - - return 0; -} - -int32_t doInitAggInfoSup(SAggSupporter* pAggSup, SqlFunctionCtx* pCtx, int32_t numOfOutput, size_t keyBufSize, - const char* pKey) { - int32_t code = 0; -// _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); - - pAggSup->currentPageId = -1; - pAggSup->resultRowSize = getResultRowSize(pCtx, numOfOutput); - pAggSup->keyBuf = taosMemoryCalloc(1, keyBufSize + POINTER_BYTES + sizeof(int64_t)); - pAggSup->pResultRowHashTable = tSimpleHashInit(100, taosFastHash); - - if (pAggSup->keyBuf == NULL || pAggSup->pResultRowHashTable == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - uint32_t defaultPgsz = 0; - uint32_t defaultBufsz = 0; - getBufferPgSize(pAggSup->resultRowSize, &defaultPgsz, &defaultBufsz); - - if (!osTempSpaceAvailable()) { - code = TSDB_CODE_NO_AVAIL_DISK; - qError("Init stream agg supporter failed since %s, %s", terrstr(code), pKey); - return code; - } - - code = createDiskbasedBuf(&pAggSup->pResultBuf, defaultPgsz, defaultBufsz, pKey, tsTempDir); - if (code != TSDB_CODE_SUCCESS) { - qError("Create agg result buf failed since %s, %s", tstrerror(code), pKey); - return code; - } - - return code; -} - -void cleanupAggSup(SAggSupporter* pAggSup) { - taosMemoryFreeClear(pAggSup->keyBuf); - tSimpleHashCleanup(pAggSup->pResultRowHashTable); - destroyDiskbasedBuf(pAggSup->pResultBuf); -} - -int32_t initAggSup(SExprSupp* pSup, SAggSupporter* pAggSup, SExprInfo* pExprInfo, int32_t numOfCols, size_t keyBufSize, - const char* pkey, void* pState) { - int32_t code = initExprSupp(pSup, pExprInfo, numOfCols); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - code = doInitAggInfoSup(pAggSup, pSup->pCtx, numOfCols, keyBufSize, pkey); - if (code != TSDB_CODE_SUCCESS) { - return code; - } - - for (int32_t i = 0; i < numOfCols; ++i) { - if (pState) { - pSup->pCtx[i].saveHandle.pBuf = NULL; - pSup->pCtx[i].saveHandle.pState = pState; - pSup->pCtx[i].exprIdx = i; - } else { - pSup->pCtx[i].saveHandle.pBuf = pAggSup->pResultBuf; - } - } - - return TSDB_CODE_SUCCESS; -} - -void initResultSizeInfo(SResultInfo* pResultInfo, int32_t numOfRows) { - ASSERT(numOfRows != 0); - pResultInfo->capacity = numOfRows; - pResultInfo->threshold = numOfRows * 0.75; - - if (pResultInfo->threshold == 0) { - pResultInfo->threshold = numOfRows; - } -} - -void initBasicInfo(SOptrBasicInfo* pInfo, SSDataBlock* pBlock) { - pInfo->pRes = pBlock; - initResultRowInfo(&pInfo->resultRowInfo); -} - -void* destroySqlFunctionCtx(SqlFunctionCtx* pCtx, int32_t numOfOutput) { - if (pCtx == NULL) { - return NULL; - } - - for (int32_t i = 0; i < numOfOutput; ++i) { - for (int32_t j = 0; j < pCtx[i].numOfParams; ++j) { - taosVariantDestroy(&pCtx[i].param[j].param); - } - - taosMemoryFreeClear(pCtx[i].subsidiaries.pCtx); - taosMemoryFreeClear(pCtx[i].subsidiaries.buf); - taosMemoryFree(pCtx[i].input.pData); - taosMemoryFree(pCtx[i].input.pColumnDataAgg); - - if (pCtx[i].udfName != NULL) { - taosMemoryFree(pCtx[i].udfName); - } - } - - taosMemoryFreeClear(pCtx); - return NULL; -} - -int32_t initExprSupp(SExprSupp* pSup, SExprInfo* pExprInfo, int32_t numOfExpr) { - pSup->pExprInfo = pExprInfo; - pSup->numOfExprs = numOfExpr; - if (pSup->pExprInfo != NULL) { - pSup->pCtx = createSqlFunctionCtx(pExprInfo, numOfExpr, &pSup->rowEntryInfoOffset); - if (pSup->pCtx == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - } - - return TSDB_CODE_SUCCESS; -} - -void cleanupExprSupp(SExprSupp* pSupp) { - destroySqlFunctionCtx(pSupp->pCtx, pSupp->numOfExprs); - if (pSupp->pExprInfo != NULL) { - destroyExprInfo(pSupp->pExprInfo, pSupp->numOfExprs); - taosMemoryFreeClear(pSupp->pExprInfo); - } - - if (pSupp->pFilterInfo != NULL) { - filterFreeInfo(pSupp->pFilterInfo); - pSupp->pFilterInfo = NULL; - } - - taosMemoryFree(pSupp->rowEntryInfoOffset); -} - -SOperatorInfo* createAggregateOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* pAggNode, - SExecTaskInfo* pTaskInfo) { - SAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SAggOperatorInfo)); - SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); - if (pInfo == NULL || pOperator == NULL) { - goto _error; - } - - SSDataBlock* pResBlock = createDataBlockFromDescNode(pAggNode->node.pOutputDataBlockDesc); - initBasicInfo(&pInfo->binfo, pResBlock); - - size_t keyBufSize = sizeof(int64_t) + sizeof(int64_t) + POINTER_BYTES; - initResultSizeInfo(&pOperator->resultInfo, 4096); - - int32_t num = 0; - SExprInfo* pExprInfo = createExprInfo(pAggNode->pAggFuncs, pAggNode->pGroupKeys, &num); - int32_t code = initAggSup(&pOperator->exprSupp, &pInfo->aggSup, pExprInfo, num, keyBufSize, pTaskInfo->id.str, - pTaskInfo->streamInfo.pState); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } - - int32_t numOfScalarExpr = 0; - SExprInfo* pScalarExprInfo = NULL; - if (pAggNode->pExprs != NULL) { - pScalarExprInfo = createExprInfo(pAggNode->pExprs, NULL, &numOfScalarExpr); - } - - code = initExprSupp(&pInfo->scalarExprSup, pScalarExprInfo, numOfScalarExpr); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } - - code = filterInitFromNode((SNode*)pAggNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } - - pInfo->binfo.mergeResultBlock = pAggNode->mergeDataBlock; - pInfo->groupKeyOptimized = pAggNode->groupKeyOptimized; - pInfo->groupId = UINT64_MAX; - - setOperatorInfo(pOperator, "TableAggregate", QUERY_NODE_PHYSICAL_PLAN_HASH_AGG, true, OP_NOT_OPENED, pInfo, - pTaskInfo); - pOperator->fpSet = createOperatorFpSet(doOpenAggregateOptr, getAggregateResult, NULL, destroyAggOperatorInfo, - optrDefaultBufFn, NULL); - - if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) { - STableScanInfo* pTableScanInfo = downstream->info; - pTableScanInfo->base.pdInfo.pExprSup = &pOperator->exprSupp; - pTableScanInfo->base.pdInfo.pAggSup = &pInfo->aggSup; - } - - code = appendDownstream(pOperator, &downstream, 1); - if (code != TSDB_CODE_SUCCESS) { - goto _error; - } - - return pOperator; - -_error: - if (pInfo != NULL) { - destroyAggOperatorInfo(pInfo); - } - - if (pOperator != NULL) { - cleanupExprSupp(&pOperator->exprSupp); - } - - taosMemoryFreeClear(pOperator); - pTaskInfo->code = code; - return NULL; -} - -void cleanupBasicInfo(SOptrBasicInfo* pInfo) { - assert(pInfo != NULL); - pInfo->pRes = blockDataDestroy(pInfo->pRes); -} - -static void freeItem(void* pItem) { - void** p = pItem; - if (*p != NULL) { - taosMemoryFreeClear(*p); - } -} - -void destroyAggOperatorInfo(void* param) { - SAggOperatorInfo* pInfo = (SAggOperatorInfo*)param; - cleanupBasicInfo(&pInfo->binfo); - - cleanupAggSup(&pInfo->aggSup); - cleanupExprSupp(&pInfo->scalarExprSup); - cleanupGroupResInfo(&pInfo->groupResInfo); - taosMemoryFreeClear(param); -} - -static char* buildTaskId(uint64_t taskId, uint64_t queryId) { - char* p = taosMemoryMalloc(64); - - int32_t offset = 6; - memcpy(p, "TID:0x", offset); - offset += tintToHex(taskId, &p[offset]); - - memcpy(&p[offset], " QID:0x", 7); - offset += 7; - offset += tintToHex(queryId, &p[offset]); - - p[offset] = 0; - - return p; -} - -static SExecTaskInfo* createExecTaskInfo(uint64_t queryId, uint64_t taskId, EOPTR_EXEC_MODEL model, char* dbFName) { - SExecTaskInfo* pTaskInfo = taosMemoryCalloc(1, sizeof(SExecTaskInfo)); - if (pTaskInfo == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - - setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED); - - pTaskInfo->schemaInfo.dbname = strdup(dbFName); - pTaskInfo->execModel = model; - pTaskInfo->pTableInfoList = tableListCreate(); - pTaskInfo->stopInfo.pStopInfo = taosArrayInit(4, sizeof(SExchangeOpStopInfo)); - pTaskInfo->pResultBlockList = taosArrayInit(128, POINTER_BYTES); - - pTaskInfo->id.queryId = queryId; - pTaskInfo->id.str = buildTaskId(taskId, queryId); - return pTaskInfo; -} - -SSchemaWrapper* extractQueriedColumnSchema(SScanPhysiNode* pScanNode); - -int32_t extractTableSchemaInfo(SReadHandle* pHandle, SScanPhysiNode* pScanNode, SExecTaskInfo* pTaskInfo) { - SMetaReader mr = {0}; - metaReaderInit(&mr, pHandle->meta, 0); - int32_t code = metaGetTableEntryByUidCache(&mr, pScanNode->uid); - if (code != TSDB_CODE_SUCCESS) { - qError("failed to get the table meta, uid:0x%" PRIx64 ", suid:0x%" PRIx64 ", %s", pScanNode->uid, pScanNode->suid, - GET_TASKID(pTaskInfo)); - - metaReaderClear(&mr); - return terrno; - } - - SSchemaInfo* pSchemaInfo = &pTaskInfo->schemaInfo; - pSchemaInfo->tablename = strdup(mr.me.name); - - if (mr.me.type == TSDB_SUPER_TABLE) { - pSchemaInfo->sw = tCloneSSchemaWrapper(&mr.me.stbEntry.schemaRow); - pSchemaInfo->tversion = mr.me.stbEntry.schemaTag.version; - } else if (mr.me.type == TSDB_CHILD_TABLE) { - tDecoderClear(&mr.coder); - - tb_uid_t suid = mr.me.ctbEntry.suid; - metaGetTableEntryByUidCache(&mr, suid); - pSchemaInfo->sw = tCloneSSchemaWrapper(&mr.me.stbEntry.schemaRow); - pSchemaInfo->tversion = mr.me.stbEntry.schemaTag.version; - } else { - pSchemaInfo->sw = tCloneSSchemaWrapper(&mr.me.ntbEntry.schemaRow); - } - - metaReaderClear(&mr); - - pSchemaInfo->qsw = extractQueriedColumnSchema(pScanNode); - return TSDB_CODE_SUCCESS; -} - -SSchemaWrapper* extractQueriedColumnSchema(SScanPhysiNode* pScanNode) { - int32_t numOfCols = LIST_LENGTH(pScanNode->pScanCols); - int32_t numOfTags = LIST_LENGTH(pScanNode->pScanPseudoCols); - - SSchemaWrapper* pqSw = taosMemoryCalloc(1, sizeof(SSchemaWrapper)); - pqSw->pSchema = taosMemoryCalloc(numOfCols + numOfTags, sizeof(SSchema)); - - for (int32_t i = 0; i < numOfCols; ++i) { - STargetNode* pNode = (STargetNode*)nodesListGetNode(pScanNode->pScanCols, i); - SColumnNode* pColNode = (SColumnNode*)pNode->pExpr; - - SSchema* pSchema = &pqSw->pSchema[pqSw->nCols++]; - pSchema->colId = pColNode->colId; - pSchema->type = pColNode->node.resType.type; - pSchema->bytes = pColNode->node.resType.bytes; - tstrncpy(pSchema->name, pColNode->colName, tListLen(pSchema->name)); - } - - // this the tags and pseudo function columns, we only keep the tag columns - for (int32_t i = 0; i < numOfTags; ++i) { - STargetNode* pNode = (STargetNode*)nodesListGetNode(pScanNode->pScanPseudoCols, i); - - int32_t type = nodeType(pNode->pExpr); - if (type == QUERY_NODE_COLUMN) { - SColumnNode* pColNode = (SColumnNode*)pNode->pExpr; - - SSchema* pSchema = &pqSw->pSchema[pqSw->nCols++]; - pSchema->colId = pColNode->colId; - pSchema->type = pColNode->node.resType.type; - pSchema->bytes = pColNode->node.resType.bytes; - tstrncpy(pSchema->name, pColNode->colName, tListLen(pSchema->name)); - } - } - - return pqSw; -} - -static void cleanupTableSchemaInfo(SSchemaInfo* pSchemaInfo) { - taosMemoryFreeClear(pSchemaInfo->dbname); - taosMemoryFreeClear(pSchemaInfo->tablename); - tDeleteSSchemaWrapper(pSchemaInfo->sw); - tDeleteSSchemaWrapper(pSchemaInfo->qsw); -} - -static void cleanupStreamInfo(SStreamTaskInfo* pStreamInfo) { tDeleteSSchemaWrapper(pStreamInfo->schema); } - -bool groupbyTbname(SNodeList* pGroupList) { - bool bytbname = false; - if (LIST_LENGTH(pGroupList) == 1) { - SNode* p = nodesListGetNode(pGroupList, 0); - if (p->type == QUERY_NODE_FUNCTION) { - // partition by tbname/group by tbname - bytbname = (strcmp(((struct SFunctionNode*)p)->functionName, "tbname") == 0); - } - } - - return bytbname; -} - -SOperatorInfo* createOperatorTree(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle, SNode* pTagCond, - SNode* pTagIndexCond, const char* pUser) { - int32_t type = nodeType(pPhyNode); - STableListInfo* pTableListInfo = pTaskInfo->pTableInfoList; - const char* idstr = GET_TASKID(pTaskInfo); - - if (pPhyNode->pChildren == NULL || LIST_LENGTH(pPhyNode->pChildren) == 0) { - SOperatorInfo* pOperator = NULL; - if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == type) { - STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode; - - // NOTE: this is an patch to fix the physical plan - // TODO remove it later - if (pTableScanNode->scan.node.pLimit != NULL) { - pTableScanNode->groupSort = true; - } - - int32_t code = - createScanTableListInfo(&pTableScanNode->scan, pTableScanNode->pGroupTags, pTableScanNode->groupSort, pHandle, - pTableListInfo, pTagCond, pTagIndexCond, pTaskInfo); - if (code) { - pTaskInfo->code = code; - qError("failed to createScanTableListInfo, code:%s, %s", tstrerror(code), idstr); - return NULL; - } - - code = extractTableSchemaInfo(pHandle, &pTableScanNode->scan, pTaskInfo); - if (code) { - pTaskInfo->code = terrno; - return NULL; - } - - pOperator = createTableScanOperatorInfo(pTableScanNode, pHandle, pTaskInfo); - if (NULL == pOperator) { - pTaskInfo->code = terrno; - return NULL; - } - - STableScanInfo* pScanInfo = pOperator->info; - pTaskInfo->cost.pRecoder = &pScanInfo->base.readRecorder; - } else if (QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN == type) { - STableMergeScanPhysiNode* pTableScanNode = (STableMergeScanPhysiNode*)pPhyNode; - - int32_t code = createScanTableListInfo(&pTableScanNode->scan, pTableScanNode->pGroupTags, true, pHandle, - pTableListInfo, pTagCond, pTagIndexCond, pTaskInfo); - if (code) { - pTaskInfo->code = code; - qError("failed to createScanTableListInfo, code: %s", tstrerror(code)); - return NULL; - } - - code = extractTableSchemaInfo(pHandle, &pTableScanNode->scan, pTaskInfo); - if (code) { - pTaskInfo->code = terrno; - return NULL; - } - - pOperator = createTableMergeScanOperatorInfo(pTableScanNode, pHandle, pTaskInfo); - if (NULL == pOperator) { - pTaskInfo->code = terrno; - return NULL; - } - - STableScanInfo* pScanInfo = pOperator->info; - pTaskInfo->cost.pRecoder = &pScanInfo->base.readRecorder; - } else if (QUERY_NODE_PHYSICAL_PLAN_EXCHANGE == type) { - pOperator = createExchangeOperatorInfo(pHandle ? pHandle->pMsgCb->clientRpc : NULL, (SExchangePhysiNode*)pPhyNode, - pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN == type) { - STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode; - if (pHandle->vnode) { - int32_t code = - createScanTableListInfo(&pTableScanNode->scan, pTableScanNode->pGroupTags, pTableScanNode->groupSort, - pHandle, pTableListInfo, pTagCond, pTagIndexCond, pTaskInfo); - if (code) { - pTaskInfo->code = code; - qError("failed to createScanTableListInfo, code: %s", tstrerror(code)); - return NULL; - } - -#ifndef NDEBUG - int32_t sz = tableListGetSize(pTableListInfo); - qDebug("create stream task, total:%d", sz); - - for (int32_t i = 0; i < sz; i++) { - STableKeyInfo* pKeyInfo = tableListGetInfo(pTableListInfo, i); - qDebug("add table uid:%" PRIu64 ", gid:%" PRIu64, pKeyInfo->uid, pKeyInfo->groupId); - } -#endif - } - - pTaskInfo->schemaInfo.qsw = extractQueriedColumnSchema(&pTableScanNode->scan); - pOperator = createStreamScanOperatorInfo(pHandle, pTableScanNode, pTagCond, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN == type) { - SSystemTableScanPhysiNode* pSysScanPhyNode = (SSystemTableScanPhysiNode*)pPhyNode; - pOperator = createSysTableScanOperatorInfo(pHandle, pSysScanPhyNode, pUser, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN == type) { - STableCountScanPhysiNode* pTblCountScanNode = (STableCountScanPhysiNode*)pPhyNode; - pOperator = createTableCountScanOperatorInfo(pHandle, pTblCountScanNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN == type) { - STagScanPhysiNode* pScanPhyNode = (STagScanPhysiNode*)pPhyNode; - - int32_t code = createScanTableListInfo(pScanPhyNode, NULL, false, pHandle, pTableListInfo, pTagCond, - pTagIndexCond, pTaskInfo); - if (code != TSDB_CODE_SUCCESS) { - pTaskInfo->code = code; - qError("failed to getTableList, code: %s", tstrerror(code)); - return NULL; - } - - pOperator = createTagScanOperatorInfo(pHandle, pScanPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN == type) { - SBlockDistScanPhysiNode* pBlockNode = (SBlockDistScanPhysiNode*)pPhyNode; - - if (pBlockNode->tableType == TSDB_SUPER_TABLE) { - SArray* pList = taosArrayInit(4, sizeof(STableKeyInfo)); - int32_t code = vnodeGetAllTableList(pHandle->vnode, pBlockNode->uid, pList); - if (code != TSDB_CODE_SUCCESS) { - pTaskInfo->code = terrno; - return NULL; - } - - size_t num = taosArrayGetSize(pList); - for (int32_t i = 0; i < num; ++i) { - STableKeyInfo* p = taosArrayGet(pList, i); - tableListAddTableInfo(pTableListInfo, p->uid, 0); - } - - taosArrayDestroy(pList); - } else { // Create group with only one table - tableListAddTableInfo(pTableListInfo, pBlockNode->uid, 0); - } - - pOperator = createDataBlockInfoScanOperator(pHandle, pBlockNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN == type) { - SLastRowScanPhysiNode* pScanNode = (SLastRowScanPhysiNode*)pPhyNode; - - int32_t code = createScanTableListInfo(&pScanNode->scan, pScanNode->pGroupTags, true, pHandle, pTableListInfo, - pTagCond, pTagIndexCond, pTaskInfo); - if (code != TSDB_CODE_SUCCESS) { - pTaskInfo->code = code; - return NULL; - } - - code = extractTableSchemaInfo(pHandle, &pScanNode->scan, pTaskInfo); - if (code != TSDB_CODE_SUCCESS) { - pTaskInfo->code = code; - return NULL; - } - - pOperator = createCacherowsScanOperator(pScanNode, pHandle, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_PROJECT == type) { - pOperator = createProjectOperatorInfo(NULL, (SProjectPhysiNode*)pPhyNode, pTaskInfo); - } else { - ASSERT(0); - } - - if (pOperator != NULL) { - pOperator->resultDataBlockId = pPhyNode->pOutputDataBlockDesc->dataBlockId; - } - - return pOperator; - } - - size_t size = LIST_LENGTH(pPhyNode->pChildren); - SOperatorInfo** ops = taosMemoryCalloc(size, POINTER_BYTES); - if (ops == NULL) { - return NULL; - } - - for (int32_t i = 0; i < size; ++i) { - SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pPhyNode->pChildren, i); - ops[i] = createOperatorTree(pChildNode, pTaskInfo, pHandle, pTagCond, pTagIndexCond, pUser); - if (ops[i] == NULL) { - taosMemoryFree(ops); - return NULL; - } - } - - SOperatorInfo* pOptr = NULL; - if (QUERY_NODE_PHYSICAL_PLAN_PROJECT == type) { - pOptr = createProjectOperatorInfo(ops[0], (SProjectPhysiNode*)pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_HASH_AGG == type) { - SAggPhysiNode* pAggNode = (SAggPhysiNode*)pPhyNode; - if (pAggNode->pGroupKeys != NULL) { - pOptr = createGroupOperatorInfo(ops[0], pAggNode, pTaskInfo); - } else { - pOptr = createAggregateOperatorInfo(ops[0], pAggNode, pTaskInfo); - } - } else if (QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL == type) { - SIntervalPhysiNode* pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode; - - bool isStream = (QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL == type); - pOptr = createIntervalOperatorInfo(ops[0], pIntervalPhyNode, pTaskInfo, isStream); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL == type) { - pOptr = createStreamIntervalOperatorInfo(ops[0], pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL == type) { - SMergeAlignedIntervalPhysiNode* pIntervalPhyNode = (SMergeAlignedIntervalPhysiNode*)pPhyNode; - pOptr = createMergeAlignedIntervalOperatorInfo(ops[0], pIntervalPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL == type) { - SMergeIntervalPhysiNode* pIntervalPhyNode = (SMergeIntervalPhysiNode*)pPhyNode; - pOptr = createMergeIntervalOperatorInfo(ops[0], pIntervalPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL == type) { - int32_t children = 0; - pOptr = createStreamFinalIntervalOperatorInfo(ops[0], pPhyNode, pTaskInfo, children); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL == type) { - int32_t children = pHandle->numOfVgroups; - pOptr = createStreamFinalIntervalOperatorInfo(ops[0], pPhyNode, pTaskInfo, children); - } else if (QUERY_NODE_PHYSICAL_PLAN_SORT == type) { - pOptr = createSortOperatorInfo(ops[0], (SSortPhysiNode*)pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT == type) { - pOptr = createGroupSortOperatorInfo(ops[0], (SGroupSortPhysiNode*)pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE == type) { - SMergePhysiNode* pMergePhyNode = (SMergePhysiNode*)pPhyNode; - pOptr = createMultiwayMergeOperatorInfo(ops, size, pMergePhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION == type) { - SSessionWinodwPhysiNode* pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode; - pOptr = createSessionAggOperatorInfo(ops[0], pSessionNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION == type) { - pOptr = createStreamSessionAggOperatorInfo(ops[0], pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION == type) { - int32_t children = 0; - pOptr = createStreamFinalSessionAggOperatorInfo(ops[0], pPhyNode, pTaskInfo, children); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION == type) { - int32_t children = pHandle->numOfVgroups; - pOptr = createStreamFinalSessionAggOperatorInfo(ops[0], pPhyNode, pTaskInfo, children); - } else if (QUERY_NODE_PHYSICAL_PLAN_PARTITION == type) { - pOptr = createPartitionOperatorInfo(ops[0], (SPartitionPhysiNode*)pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION == type) { - pOptr = createStreamPartitionOperatorInfo(ops[0], (SStreamPartitionPhysiNode*)pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE == type) { - SStateWinodwPhysiNode* pStateNode = (SStateWinodwPhysiNode*)pPhyNode; - pOptr = createStatewindowOperatorInfo(ops[0], pStateNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE == type) { - pOptr = createStreamStateAggOperatorInfo(ops[0], pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN == type) { - pOptr = createMergeJoinOperatorInfo(ops, size, (SSortMergeJoinPhysiNode*)pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_FILL == type) { - pOptr = createFillOperatorInfo(ops[0], (SFillPhysiNode*)pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_FILL == type) { - pOptr = createStreamFillOperatorInfo(ops[0], (SStreamFillPhysiNode*)pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_INDEF_ROWS_FUNC == type) { - pOptr = createIndefinitOutputOperatorInfo(ops[0], pPhyNode, pTaskInfo); - } else if (QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC == type) { - pOptr = createTimeSliceOperatorInfo(ops[0], pPhyNode, pTaskInfo); - } else { - ASSERT(0); - } - - taosMemoryFree(ops); - if (pOptr) { - pOptr->resultDataBlockId = pPhyNode->pOutputDataBlockDesc->dataBlockId; - } - - return pOptr; -} - -static int32_t extractTbscanInStreamOpTree(SOperatorInfo* pOperator, STableScanInfo** ppInfo) { - if (pOperator->operatorType != QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { - if (pOperator->numOfDownstream == 0) { - qError("failed to find stream scan operator"); - return TSDB_CODE_APP_ERROR; - } - - if (pOperator->numOfDownstream > 1) { - qError("join not supported for stream block scan"); - return TSDB_CODE_APP_ERROR; - } - return extractTbscanInStreamOpTree(pOperator->pDownstream[0], ppInfo); - } else { - SStreamScanInfo* pInfo = pOperator->info; - *ppInfo = pInfo->pTableScanOp->info; - return 0; - } -} - -int32_t extractTableScanNode(SPhysiNode* pNode, STableScanPhysiNode** ppNode) { - if (pNode->pChildren == NULL || LIST_LENGTH(pNode->pChildren) == 0) { - if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == pNode->type) { - *ppNode = (STableScanPhysiNode*)pNode; - return 0; - } else { - terrno = TSDB_CODE_APP_ERROR; - return -1; - } - } else { - if (LIST_LENGTH(pNode->pChildren) != 1) { - terrno = TSDB_CODE_APP_ERROR; - return -1; - } - SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pNode->pChildren, 0); - return extractTableScanNode(pChildNode, ppNode); - } - return -1; -} - -int32_t createDataSinkParam(SDataSinkNode* pNode, void** pParam, qTaskInfo_t* pTaskInfo, SReadHandle* readHandle) { - SExecTaskInfo* pTask = *(SExecTaskInfo**)pTaskInfo; - - switch (pNode->type) { - case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: { - SInserterParam* pInserterParam = taosMemoryCalloc(1, sizeof(SInserterParam)); - if (NULL == pInserterParam) { - return TSDB_CODE_OUT_OF_MEMORY; - } - pInserterParam->readHandle = readHandle; - - *pParam = pInserterParam; - break; - } - case QUERY_NODE_PHYSICAL_PLAN_DELETE: { - SDeleterParam* pDeleterParam = taosMemoryCalloc(1, sizeof(SDeleterParam)); - if (NULL == pDeleterParam) { - return TSDB_CODE_OUT_OF_MEMORY; - } - int32_t tbNum = tableListGetSize(pTask->pTableInfoList); - pDeleterParam->suid = tableListGetSuid(pTask->pTableInfoList); - - // TODO extract uid list - pDeleterParam->pUidList = taosArrayInit(tbNum, sizeof(uint64_t)); - if (NULL == pDeleterParam->pUidList) { - taosMemoryFree(pDeleterParam); - return TSDB_CODE_OUT_OF_MEMORY; - } - - for (int32_t i = 0; i < tbNum; ++i) { - STableKeyInfo* pTable = tableListGetInfo(pTask->pTableInfoList, i); - taosArrayPush(pDeleterParam->pUidList, &pTable->uid); - } - - *pParam = pDeleterParam; - break; - } - default: - break; - } - - return TSDB_CODE_SUCCESS; -} - -int32_t createExecTaskInfoImpl(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SReadHandle* pHandle, uint64_t taskId, - char* sql, EOPTR_EXEC_MODEL model) { - uint64_t queryId = pPlan->id.queryId; - - *pTaskInfo = createExecTaskInfo(queryId, taskId, model, pPlan->dbFName); - if (*pTaskInfo == NULL) { - goto _complete; - } - - if (pHandle) { - /*(*pTaskInfo)->streamInfo.fillHistoryVer1 = pHandle->fillHistoryVer1;*/ - if (pHandle->pStateBackend) { - (*pTaskInfo)->streamInfo.pState = pHandle->pStateBackend; - } - } - - (*pTaskInfo)->sql = sql; - sql = NULL; - - (*pTaskInfo)->pSubplan = pPlan; - (*pTaskInfo)->pRoot = - createOperatorTree(pPlan->pNode, *pTaskInfo, pHandle, pPlan->pTagCond, pPlan->pTagIndexCond, pPlan->user); - - if (NULL == (*pTaskInfo)->pRoot) { - terrno = (*pTaskInfo)->code; - goto _complete; - } - - (*pTaskInfo)->cost.created = taosGetTimestampUs(); - return TSDB_CODE_SUCCESS; - -_complete: - taosMemoryFree(sql); - doDestroyTask(*pTaskInfo); - return terrno; -} - -static void freeBlock(void* pParam) { - SSDataBlock* pBlock = *(SSDataBlock**)pParam; - blockDataDestroy(pBlock); -} - -void doDestroyTask(SExecTaskInfo* pTaskInfo) { - qDebug("%s execTask is freed", GET_TASKID(pTaskInfo)); - - pTaskInfo->pTableInfoList = tableListDestroy(pTaskInfo->pTableInfoList); - destroyOperatorInfo(pTaskInfo->pRoot); - cleanupTableSchemaInfo(&pTaskInfo->schemaInfo); - cleanupStreamInfo(&pTaskInfo->streamInfo); - - if (!pTaskInfo->localFetch.localExec) { - nodesDestroyNode((SNode*)pTaskInfo->pSubplan); - } - - taosArrayDestroyEx(pTaskInfo->pResultBlockList, freeBlock); - taosArrayDestroy(pTaskInfo->stopInfo.pStopInfo); - taosMemoryFreeClear(pTaskInfo->sql); - taosMemoryFreeClear(pTaskInfo->id.str); - taosMemoryFreeClear(pTaskInfo); -} - -static int64_t getQuerySupportBufSize(size_t numOfTables) { - size_t s1 = sizeof(STableQueryInfo); - // size_t s3 = sizeof(STableCheckInfo); buffer consumption in tsdb - return (int64_t)(s1 * 1.5 * numOfTables); -} - -int32_t checkForQueryBuf(size_t numOfTables) { - int64_t t = getQuerySupportBufSize(numOfTables); - if (tsQueryBufferSizeBytes < 0) { - return TSDB_CODE_SUCCESS; - } else if (tsQueryBufferSizeBytes > 0) { - while (1) { - int64_t s = tsQueryBufferSizeBytes; - int64_t remain = s - t; - if (remain >= 0) { - if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) { - return TSDB_CODE_SUCCESS; - } - } else { - return TSDB_CODE_QRY_NOT_ENOUGH_BUFFER; - } - } - } - - // disable query processing if the value of tsQueryBufferSize is zero. - return TSDB_CODE_QRY_NOT_ENOUGH_BUFFER; -} - -void releaseQueryBuf(size_t numOfTables) { - if (tsQueryBufferSizeBytes < 0) { - return; - } - - int64_t t = getQuerySupportBufSize(numOfTables); - - // restore value is not enough buffer available - atomic_add_fetch_64(&tsQueryBufferSizeBytes, t); -} - -int32_t getOperatorExplainExecInfo(SOperatorInfo* operatorInfo, SArray* pExecInfoList) { - SExplainExecInfo execInfo = {0}; - SExplainExecInfo* pExplainInfo = taosArrayPush(pExecInfoList, &execInfo); - - pExplainInfo->numOfRows = operatorInfo->resultInfo.totalRows; - pExplainInfo->startupCost = operatorInfo->cost.openCost; - pExplainInfo->totalCost = operatorInfo->cost.totalCost; - pExplainInfo->verboseLen = 0; - pExplainInfo->verboseInfo = NULL; - - if (operatorInfo->fpSet.getExplainFn) { - int32_t code = - operatorInfo->fpSet.getExplainFn(operatorInfo, &pExplainInfo->verboseInfo, &pExplainInfo->verboseLen); - if (code) { - qError("%s operator getExplainFn failed, code:%s", GET_TASKID(operatorInfo->pTaskInfo), tstrerror(code)); - return code; - } - } - - int32_t code = 0; - for (int32_t i = 0; i < operatorInfo->numOfDownstream; ++i) { - code = getOperatorExplainExecInfo(operatorInfo->pDownstream[i], pExecInfoList); - if (code != TSDB_CODE_SUCCESS) { - // taosMemoryFreeClear(*pRes); - return TSDB_CODE_OUT_OF_MEMORY; - } - } - - return TSDB_CODE_SUCCESS; -} - -int32_t setOutputBuf(SStreamState* pState, STimeWindow* win, SResultRow** pResult, int64_t tableGroupId, - SqlFunctionCtx* pCtx, int32_t numOfOutput, int32_t* rowEntryInfoOffset, SAggSupporter* pAggSup) { - SWinKey key = { - .ts = win->skey, - .groupId = tableGroupId, - }; - char* value = NULL; - int32_t size = pAggSup->resultRowSize; - - if (streamStateAddIfNotExist(pState, &key, (void**)&value, &size) < 0) { - return TSDB_CODE_OUT_OF_MEMORY; - } - *pResult = (SResultRow*)value; - ASSERT(*pResult); - // set time window for current result - (*pResult)->win = (*win); - setResultRowInitCtx(*pResult, pCtx, numOfOutput, rowEntryInfoOffset); - return TSDB_CODE_SUCCESS; -} - -int32_t releaseOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult) { - streamStateReleaseBuf(pState, pKey, pResult); - return TSDB_CODE_SUCCESS; -} - -int32_t saveOutputBuf(SStreamState* pState, SWinKey* pKey, SResultRow* pResult, int32_t resSize) { - streamStatePut(pState, pKey, pResult, resSize); - return TSDB_CODE_SUCCESS; -} - -int32_t buildDataBlockFromGroupRes(SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, SExprSupp* pSup, - SGroupResInfo* pGroupResInfo) { - SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - SExprInfo* pExprInfo = pSup->pExprInfo; - int32_t numOfExprs = pSup->numOfExprs; - int32_t* rowEntryOffset = pSup->rowEntryInfoOffset; - SqlFunctionCtx* pCtx = pSup->pCtx; - - int32_t numOfRows = getNumOfTotalRes(pGroupResInfo); - - for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) { - SResKeyPos* pPos = taosArrayGetP(pGroupResInfo->pRows, i); - int32_t size = 0; - void* pVal = NULL; - SWinKey key = { - .ts = *(TSKEY*)pPos->key, - .groupId = pPos->groupId, - }; - int32_t code = streamStateGet(pState, &key, &pVal, &size); - ASSERT(code == 0); - SResultRow* pRow = (SResultRow*)pVal; - doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset); - // no results, continue to check the next one - if (pRow->numOfRows == 0) { - pGroupResInfo->index += 1; - releaseOutputBuf(pState, &key, pRow); - continue; - } - - if (pBlock->info.id.groupId == 0) { - pBlock->info.id.groupId = pPos->groupId; - void* tbname = NULL; - if (streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) < 0) { - pBlock->info.parTbName[0] = 0; - } else { - memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN); - } - tdbFree(tbname); - } else { - // current value belongs to different group, it can't be packed into one datablock - if (pBlock->info.id.groupId != pPos->groupId) { - releaseOutputBuf(pState, &key, pRow); - break; - } - } - - if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) { - ASSERT(pBlock->info.rows > 0); - releaseOutputBuf(pState, &key, pRow); - break; - } - - pGroupResInfo->index += 1; - - for (int32_t j = 0; j < numOfExprs; ++j) { - int32_t slotId = pExprInfo[j].base.resSchema.slotId; - - pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset); - if (pCtx[j].fpSet.finalize) { - int32_t code1 = pCtx[j].fpSet.finalize(&pCtx[j], pBlock); - if (TAOS_FAILED(code1)) { - qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(code1)); - T_LONG_JMP(pTaskInfo->env, code1); - } - } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) { - // do nothing, todo refactor - } else { - // expand the result into multiple rows. E.g., _wstart, top(k, 20) - // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows. - SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId); - char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo); - for (int32_t k = 0; k < pRow->numOfRows; ++k) { - colDataAppend(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes); - } - } - } - - pBlock->info.rows += pRow->numOfRows; - releaseOutputBuf(pState, &key, pRow); - } - pBlock->info.dataLoad = 1; - blockDataUpdateTsWindow(pBlock, 0); - return TSDB_CODE_SUCCESS; -} - -int32_t saveSessionDiscBuf(SStreamState* pState, SSessionKey* key, void* buf, int32_t size) { - streamStateSessionPut(pState, key, (const void*)buf, size); - releaseOutputBuf(pState, NULL, (SResultRow*)buf); - return TSDB_CODE_SUCCESS; -} - -int32_t buildSessionResultDataBlock(SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, - SExprSupp* pSup, SGroupResInfo* pGroupResInfo) { - SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - SExprInfo* pExprInfo = pSup->pExprInfo; - int32_t numOfExprs = pSup->numOfExprs; - int32_t* rowEntryOffset = pSup->rowEntryInfoOffset; - SqlFunctionCtx* pCtx = pSup->pCtx; - - int32_t numOfRows = getNumOfTotalRes(pGroupResInfo); - - for (int32_t i = pGroupResInfo->index; i < numOfRows; i += 1) { - SSessionKey* pKey = taosArrayGet(pGroupResInfo->pRows, i); - int32_t size = 0; - void* pVal = NULL; - int32_t code = streamStateSessionGet(pState, pKey, &pVal, &size); - ASSERT(code == 0); - if (code == -1) { - // coverity scan - pGroupResInfo->index += 1; - continue; - } - SResultRow* pRow = (SResultRow*)pVal; - doUpdateNumOfRows(pCtx, pRow, numOfExprs, rowEntryOffset); - // no results, continue to check the next one - if (pRow->numOfRows == 0) { - pGroupResInfo->index += 1; - releaseOutputBuf(pState, NULL, pRow); - continue; - } - - if (pBlock->info.id.groupId == 0) { - pBlock->info.id.groupId = pKey->groupId; - - void* tbname = NULL; - if (streamStateGetParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) < 0) { - pBlock->info.parTbName[0] = 0; - } else { - memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN); - } - tdbFree(tbname); - } else { - // current value belongs to different group, it can't be packed into one datablock - if (pBlock->info.id.groupId != pKey->groupId) { - releaseOutputBuf(pState, NULL, pRow); - break; - } - } - - if (pBlock->info.rows + pRow->numOfRows > pBlock->info.capacity) { - ASSERT(pBlock->info.rows > 0); - releaseOutputBuf(pState, NULL, pRow); - break; - } - - pGroupResInfo->index += 1; - - for (int32_t j = 0; j < numOfExprs; ++j) { - int32_t slotId = pExprInfo[j].base.resSchema.slotId; - - pCtx[j].resultInfo = getResultEntryInfo(pRow, j, rowEntryOffset); - if (pCtx[j].fpSet.finalize) { - int32_t code1 = pCtx[j].fpSet.finalize(&pCtx[j], pBlock); - if (TAOS_FAILED(code1)) { - qError("%s build result data block error, code %s", GET_TASKID(pTaskInfo), tstrerror(code1)); - T_LONG_JMP(pTaskInfo->env, code1); - } - } else if (strcmp(pCtx[j].pExpr->pExpr->_function.functionName, "_select_value") == 0) { - // do nothing, todo refactor - } else { - // expand the result into multiple rows. E.g., _wstart, top(k, 20) - // the _wstart needs to copy to 20 following rows, since the results of top-k expands to 20 different rows. - SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, slotId); - char* in = GET_ROWCELL_INTERBUF(pCtx[j].resultInfo); - for (int32_t k = 0; k < pRow->numOfRows; ++k) { - colDataAppend(pColInfoData, pBlock->info.rows + k, in, pCtx[j].resultInfo->isNullRes); - } - } - } - - pBlock->info.dataLoad = 1; - pBlock->info.rows += pRow->numOfRows; - // saveSessionDiscBuf(pState, pKey, pVal, size); - releaseOutputBuf(pState, NULL, pRow); - } - blockDataUpdateTsWindow(pBlock, 0); - return TSDB_CODE_SUCCESS; -} diff --git a/source/libs/executor/src/filloperator.c b/source/libs/executor/src/filloperator.c index 3403c202b7938337ef2ce96a79c7dfe5e3032e8a..73222ee3756fdc31c3da675ea52de53e10c9db03 100644 --- a/source/libs/executor/src/filloperator.c +++ b/source/libs/executor/src/filloperator.c @@ -20,16 +20,18 @@ #include "tmsg.h" #include "ttypes.h" -#include "executorimpl.h" +#include "executorInt.h" #include "tcommon.h" #include "thash.h" #include "ttime.h" -#include "executorInt.h" #include "function.h" #include "querynodes.h" #include "tdatablock.h" #include "tfill.h" +#include "operator.h" +#include "querytask.h" + #define FILL_POS_INVALID 0 #define FILL_POS_START 1 @@ -69,7 +71,7 @@ static void doHandleRemainBlockForNewGroupImpl(SOperatorInfo* pOperator, SFillOp int32_t order = TSDB_ORDER_ASC; int32_t scanFlag = MAIN_SCAN; - getTableScanInfo(pOperator, &order, &scanFlag); + getTableScanInfo(pOperator, &order, &scanFlag, false); int64_t ekey = pInfo->existNewGroupBlock->info.window.ekey; taosResetFillInfo(pInfo->pFillInfo, getFillInfoStart(pInfo->pFillInfo)); @@ -128,7 +130,7 @@ static SSDataBlock* doFillImpl(SOperatorInfo* pOperator) { int32_t order = TSDB_ORDER_ASC; int32_t scanFlag = MAIN_SCAN; - getTableScanInfo(pOperator, &order, &scanFlag); + getTableScanInfo(pOperator, &order, &scanFlag, false); doHandleRemainBlockFromNewGroup(pOperator, pInfo, pResultInfo, pTaskInfo); if (pResBlock->info.rows > 0) { @@ -193,8 +195,6 @@ static SSDataBlock* doFillImpl(SOperatorInfo* pOperator) { return pResBlock; } } else if (pInfo->existNewGroupBlock) { // try next group - assert(pBlock != NULL); - blockDataCleanup(pResBlock); doHandleRemainBlockForNewGroupImpl(pOperator, pInfo, pResultInfo, pTaskInfo); @@ -411,7 +411,7 @@ TSKEY getPrevWindowTs(TSKEY ts, SInterval* pInterval) { } void setRowCell(SColumnInfoData* pCol, int32_t rowId, const SResultCellData* pCell) { - colDataAppend(pCol, rowId, pCell->pData, pCell->isNull); + colDataSetVal(pCol, rowId, pCell->pData, pCell->isNull); } SResultCellData* getResultCell(SResultRowData* pRaw, int32_t index) { @@ -449,9 +449,14 @@ void* destroyStreamFillSupporter(SStreamFillSupporter* pFillSup) { return NULL; } +void destroySPoint(void* ptr) { + SPoint* point = (SPoint*) ptr; + taosMemoryFreeClear(point->val); +} + void* destroyStreamFillLinearInfo(SStreamFillLinearInfo* pFillLinear) { - taosArrayDestroy(pFillLinear->pDeltaVal); - taosArrayDestroy(pFillLinear->pNextDeltaVal); + taosArrayDestroyEx(pFillLinear->pEndPoints, destroySPoint); + taosArrayDestroyEx(pFillLinear->pNextEndPoints, destroySPoint); taosMemoryFree(pFillLinear); return NULL; } @@ -613,19 +618,15 @@ static void calcDeltaData(SSDataBlock* pBlock, int32_t rowId, SResultRowData* pR } } -static void calcRowDeltaData(SResultRowData* pStartRow, SResultRowData* pEndRow, SArray* pDelta, SFillColInfo* pFillCol, - int32_t numOfCol, int32_t winCount) { +static void calcRowDeltaData(SResultRowData* pEndRow, SArray* pEndPoins, SFillColInfo* pFillCol, + int32_t numOfCol) { for (int32_t i = 0; i < numOfCol; i++) { if (!pFillCol[i].notFillCol) { int32_t slotId = GET_DEST_SLOT_ID(pFillCol + i); - SResultCellData* pSCell = getResultCell(pStartRow, slotId); - double start = 0.0; - GET_TYPED_DATA(start, double, pSCell->type, pSCell->pData); SResultCellData* pECell = getResultCell(pEndRow, slotId); - double end = 0.0; - GET_TYPED_DATA(end, double, pECell->type, pECell->pData); - double delta = (end - start) / winCount; - taosArraySet(pDelta, slotId, &delta); + SPoint* pPoint = taosArrayGet(pEndPoins, slotId); + pPoint->key = pEndRow->key; + memcpy(pPoint->val, pECell->pData, pECell->bytes); } } } @@ -676,10 +677,8 @@ void setDeleteFillValueInfo(TSKEY start, TSKEY end, SStreamFillSupporter* pFillS setFillKeyInfo(pFillSup->prev.key, pFillSup->next.key, &pFillSup->interval, pFillInfo); pFillInfo->pLinearInfo->hasNext = false; pFillInfo->pLinearInfo->nextEnd = INT64_MIN; - int32_t numOfWins = taosTimeCountInterval(pFillSup->prev.key, pFillSup->next.key, pFillSup->interval.sliding, - pFillSup->interval.slidingUnit, pFillSup->interval.precision); - calcRowDeltaData(&pFillSup->prev, &pFillSup->next, pFillInfo->pLinearInfo->pDeltaVal, pFillSup->pAllColInfo, - pFillSup->numOfAllCols, numOfWins); + calcRowDeltaData(&pFillSup->next, pFillInfo->pLinearInfo->pEndPoints, pFillSup->pAllColInfo, + pFillSup->numOfAllCols); pFillInfo->pResRow = &pFillSup->prev; pFillInfo->pLinearInfo->winIndex = 0; } break; @@ -782,25 +781,19 @@ void setFillValueInfo(SSDataBlock* pBlock, TSKEY ts, int32_t rowId, SStreamFillS setFillKeyInfo(prevWKey, ts, &pFillSup->interval, pFillInfo); pFillInfo->pos = FILL_POS_MID; pFillInfo->pLinearInfo->nextEnd = nextWKey; - int32_t numOfWins = taosTimeCountInterval(prevWKey, ts, pFillSup->interval.sliding, - pFillSup->interval.slidingUnit, pFillSup->interval.precision); - calcRowDeltaData(&pFillSup->prev, &pFillSup->cur, pFillInfo->pLinearInfo->pDeltaVal, pFillSup->pAllColInfo, - pFillSup->numOfAllCols, numOfWins); + calcRowDeltaData(&pFillSup->cur, pFillInfo->pLinearInfo->pEndPoints, pFillSup->pAllColInfo, + pFillSup->numOfAllCols); pFillInfo->pResRow = &pFillSup->prev; - numOfWins = taosTimeCountInterval(ts, nextWKey, pFillSup->interval.sliding, pFillSup->interval.slidingUnit, - pFillSup->interval.precision); - calcRowDeltaData(&pFillSup->cur, &pFillSup->next, pFillInfo->pLinearInfo->pNextDeltaVal, pFillSup->pAllColInfo, - pFillSup->numOfAllCols, numOfWins); + calcRowDeltaData(&pFillSup->next, pFillInfo->pLinearInfo->pNextEndPoints, pFillSup->pAllColInfo, + pFillSup->numOfAllCols); pFillInfo->pLinearInfo->hasNext = true; } else if (hasPrevWindow(pFillSup)) { setFillKeyInfo(prevWKey, ts, &pFillSup->interval, pFillInfo); pFillInfo->pos = FILL_POS_END; pFillInfo->pLinearInfo->nextEnd = INT64_MIN; - int32_t numOfWins = taosTimeCountInterval(prevWKey, ts, pFillSup->interval.sliding, - pFillSup->interval.slidingUnit, pFillSup->interval.precision); - calcRowDeltaData(&pFillSup->prev, &pFillSup->cur, pFillInfo->pLinearInfo->pDeltaVal, pFillSup->pAllColInfo, - pFillSup->numOfAllCols, numOfWins); + calcRowDeltaData(&pFillSup->cur, pFillInfo->pLinearInfo->pEndPoints, pFillSup->pAllColInfo, + pFillSup->numOfAllCols); pFillInfo->pResRow = &pFillSup->prev; pFillInfo->pLinearInfo->hasNext = false; } else { @@ -808,10 +801,8 @@ void setFillValueInfo(SSDataBlock* pBlock, TSKEY ts, int32_t rowId, SStreamFillS setFillKeyInfo(ts, nextWKey, &pFillSup->interval, pFillInfo); pFillInfo->pos = FILL_POS_START; pFillInfo->pLinearInfo->nextEnd = INT64_MIN; - int32_t numOfWins = taosTimeCountInterval(ts, nextWKey, pFillSup->interval.sliding, - pFillSup->interval.slidingUnit, pFillSup->interval.precision); - calcRowDeltaData(&pFillSup->cur, &pFillSup->next, pFillInfo->pLinearInfo->pDeltaVal, pFillSup->pAllColInfo, - pFillSup->numOfAllCols, numOfWins); + calcRowDeltaData(&pFillSup->next, pFillInfo->pLinearInfo->pEndPoints, pFillSup->pAllColInfo, + pFillSup->numOfAllCols); pFillInfo->pResRow = &pFillSup->cur; pFillInfo->pLinearInfo->hasNext = false; } @@ -905,16 +896,21 @@ static void doStreamFillLinear(SStreamFillSupporter* pFillSup, SStreamFillInfo* } } else { if (IS_VAR_DATA_TYPE(type) || type == TSDB_DATA_TYPE_BOOL || pCell->isNull) { - colDataAppendNULL(pColData, index); + colDataSetNULL(pColData, index); continue; } - double* pDelta = taosArrayGet(pFillInfo->pLinearInfo->pDeltaVal, slotId); + SPoint* pEnd = taosArrayGet(pFillInfo->pLinearInfo->pEndPoints, slotId); double vCell = 0; - GET_TYPED_DATA(vCell, double, pCell->type, pCell->pData); - vCell += (*pDelta) * pFillInfo->pLinearInfo->winIndex; - int64_t result = 0; - SET_TYPED_DATA(&result, pCell->type, vCell); - colDataAppend(pColData, index, (const char*)&result, false); + SPoint start = {0}; + start.key = pFillInfo->pResRow->key; + start.val = pCell->pData; + + SPoint cur = {0}; + cur.key = pFillInfo->current; + cur.val = taosMemoryCalloc(1, pCell->bytes); + taosGetLinearInterpolationVal(&cur, pCell->type, &start, pEnd, pCell->type); + colDataSetVal(pColData, index, (const char*)cur.val, false); + destroySPoint(&cur); } } pFillInfo->current = taosTimeAdd(pFillInfo->current, pFillSup->interval.sliding, pFillSup->interval.slidingUnit, @@ -926,6 +922,7 @@ static void doStreamFillLinear(SStreamFillSupporter* pFillSup, SStreamFillInfo* static void keepResultInDiscBuf(SOperatorInfo* pOperator, uint64_t groupId, SResultRowData* pRow, int32_t len) { SWinKey key = {.groupId = groupId, .ts = pRow->key}; int32_t code = streamStateFillPut(pOperator->pTaskInfo->streamInfo.pState, &key, pRow->pRowVal, len); + qDebug("===stream===fill operator save key ts:%" PRId64 " group id:%" PRIu64 " code:%d", key.ts, key.groupId, code); ASSERT(code == TSDB_CODE_SUCCESS); } @@ -954,8 +951,7 @@ static void doStreamFillRange(SStreamFillInfo* pFillInfo, SStreamFillSupporter* if (pFillInfo->current > pFillInfo->end && pFillInfo->pLinearInfo->hasNext) { pFillInfo->pLinearInfo->hasNext = false; pFillInfo->pLinearInfo->winIndex = 0; - taosArrayClear(pFillInfo->pLinearInfo->pDeltaVal); - taosArrayAddAll(pFillInfo->pLinearInfo->pDeltaVal, pFillInfo->pLinearInfo->pNextDeltaVal); + taosArraySwap(pFillInfo->pLinearInfo->pEndPoints, pFillInfo->pLinearInfo->pNextEndPoints); pFillInfo->pResRow = &pFillSup->cur; setFillKeyInfo(pFillSup->cur.key, pFillInfo->pLinearInfo->nextEnd, &pFillSup->interval, pFillInfo); doStreamFillLinear(pFillSup, pFillInfo, pRes); @@ -1033,23 +1029,23 @@ static void buildDeleteRange(SOperatorInfo* pOp, TSKEY start, TSKEY end, uint64_ SColumnInfoData* pCalStartCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX); SColumnInfoData* pCalEndCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX); SColumnInfoData* pTbNameCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX); - colDataAppend(pStartCol, pBlock->info.rows, (const char*)&start, false); - colDataAppend(pEndCol, pBlock->info.rows, (const char*)&end, false); - colDataAppendNULL(pUidCol, pBlock->info.rows); - colDataAppend(pGroupCol, pBlock->info.rows, (const char*)&groupId, false); - colDataAppendNULL(pCalStartCol, pBlock->info.rows); - colDataAppendNULL(pCalEndCol, pBlock->info.rows); + colDataSetVal(pStartCol, pBlock->info.rows, (const char*)&start, false); + colDataSetVal(pEndCol, pBlock->info.rows, (const char*)&end, false); + colDataSetNULL(pUidCol, pBlock->info.rows); + colDataSetVal(pGroupCol, pBlock->info.rows, (const char*)&groupId, false); + colDataSetNULL(pCalStartCol, pBlock->info.rows); + colDataSetNULL(pCalEndCol, pBlock->info.rows); SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX); void* tbname = NULL; streamStateGetParName(pOp->pTaskInfo->streamInfo.pState, groupId, &tbname); if (tbname == NULL) { - colDataAppendNULL(pTableCol, pBlock->info.rows); + colDataSetNULL(pTableCol, pBlock->info.rows); } else { char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN]; STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName)); - colDataAppend(pTableCol, pBlock->info.rows, (const char*)parTbName, false); + colDataSetVal(pTableCol, pBlock->info.rows, (const char*)parTbName, false); tdbFree(tbname); } @@ -1266,9 +1262,11 @@ static SSDataBlock* doStreamFill(SOperatorInfo* pOperator) { memcpy(pInfo->pSrcBlock->info.parTbName, pBlock->info.parTbName, TSDB_TABLE_NAME_LEN); pInfo->srcRowIndex = 0; } break; + case STREAM_CREATE_CHILD_TABLE: { + return pBlock; + } break; default: - ASSERT(0); - break; + ASSERTS(pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type"); } } @@ -1358,15 +1356,19 @@ SStreamFillInfo* initStreamFillInfo(SStreamFillSupporter* pFillSup, SSDataBlock* pFillInfo->pLinearInfo = taosMemoryCalloc(1, sizeof(SStreamFillLinearInfo)); pFillInfo->pLinearInfo->hasNext = false; pFillInfo->pLinearInfo->nextEnd = INT64_MIN; - pFillInfo->pLinearInfo->pDeltaVal = NULL; - pFillInfo->pLinearInfo->pNextDeltaVal = NULL; + pFillInfo->pLinearInfo->pEndPoints = NULL; + pFillInfo->pLinearInfo->pNextEndPoints = NULL; if (pFillSup->type == TSDB_FILL_LINEAR) { - pFillInfo->pLinearInfo->pDeltaVal = taosArrayInit(pFillSup->numOfAllCols, sizeof(double)); - pFillInfo->pLinearInfo->pNextDeltaVal = taosArrayInit(pFillSup->numOfAllCols, sizeof(double)); + pFillInfo->pLinearInfo->pEndPoints = taosArrayInit(pFillSup->numOfAllCols, sizeof(SPoint)); + pFillInfo->pLinearInfo->pNextEndPoints = taosArrayInit(pFillSup->numOfAllCols, sizeof(SPoint)); for (int32_t i = 0; i < pFillSup->numOfAllCols; i++) { - double value = 0.0; - taosArrayPush(pFillInfo->pLinearInfo->pDeltaVal, &value); - taosArrayPush(pFillInfo->pLinearInfo->pNextDeltaVal, &value); + SColumnInfoData* pColData = taosArrayGet(pRes->pDataBlock, i); + SPoint value = {0}; + value.val = taosMemoryCalloc(1, pColData->info.bytes); + taosArrayPush(pFillInfo->pLinearInfo->pEndPoints, &value); + + value.val = taosMemoryCalloc(1, pColData->info.bytes); + taosArrayPush(pFillInfo->pLinearInfo->pNextEndPoints, &value); } } pFillInfo->pLinearInfo->winIndex = 0; diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c index 9d88126220b32e69023f6335628743f9afb43a8c..47338d44696ffca98494ab075a73114fcfc0b8bc 100644 --- a/source/libs/executor/src/groupoperator.c +++ b/source/libs/executor/src/groupoperator.c @@ -22,7 +22,8 @@ #include "tmsg.h" #include "executorInt.h" -#include "executorimpl.h" +#include "operator.h" +#include "querytask.h" #include "tcompare.h" #include "thash.h" #include "ttypes.h" @@ -173,9 +174,14 @@ static void recordNewGroupKeys(SArray* pGroupCols, SArray* pGroupColVals, SSData size_t numOfGroupCols = taosArrayGetSize(pGroupCols); for (int32_t i = 0; i < numOfGroupCols; ++i) { - SColumn* pCol = taosArrayGet(pGroupCols, i); + SColumn* pCol = (SColumn*) taosArrayGet(pGroupCols, i); SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pCol->slotId); + // valid range check. todo: return error code. + if (pCol->slotId > taosArrayGetSize(pBlock->pDataBlock)) { + continue; + } + if (pBlock->pBlockAgg != NULL) { pColAgg = pBlock->pBlockAgg[pCol->slotId]; // TODO is agg data matched? } @@ -204,7 +210,6 @@ static void recordNewGroupKeys(SArray* pGroupCols, SArray* pGroupColVals, SSData } static int32_t buildGroupKeys(void* pKey, const SArray* pGroupColVals) { - ASSERT(pKey != NULL); size_t numOfGroupCols = taosArrayGetSize(pGroupColVals); char* isNull = (char*)pKey; @@ -278,6 +283,7 @@ static void doHashGroupbyAgg(SOperatorInfo* pOperator, SSDataBlock* pBlock) { terrno = TSDB_CODE_SUCCESS; int32_t num = 0; + uint64_t groupId = 0; for (int32_t j = 0; j < pBlock->info.rows; ++j) { // Compare with the previous row of this column, and do not set the output buffer again if they are identical. if (!pInfo->isInit) { @@ -384,7 +390,7 @@ static SSDataBlock* hashGroupbyAggregate(SOperatorInfo* pOperator) { break; } - int32_t code = getTableScanInfo(pOperator, &order, &scanFlag); + int32_t code = getTableScanInfo(pOperator, &order, &scanFlag, false); if (code != TSDB_CODE_SUCCESS) { T_LONG_JMP(pTaskInfo->env, code); } @@ -427,9 +433,11 @@ static SSDataBlock* hashGroupbyAggregate(SOperatorInfo* pOperator) { } SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* pAggNode, SExecTaskInfo* pTaskInfo) { + int32_t code = TSDB_CODE_SUCCESS; SGroupbyOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SGroupbyOperatorInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; goto _error; } @@ -443,7 +451,7 @@ SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* } pInfo->pGroupCols = extractColumnInfo(pAggNode->pGroupKeys); - int32_t code = initExprSupp(&pInfo->scalarSup, pScalarExprInfo, numOfScalarExpr); + code = initExprSupp(&pInfo->scalarSup, pScalarExprInfo, numOfScalarExpr); if (code != TSDB_CODE_SUCCESS) { goto _error; } @@ -472,6 +480,8 @@ SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* initResultRowInfo(&pInfo->binfo.resultRowInfo); setOperatorInfo(pOperator, "GroupbyAggOperator", 0, true, OP_NOT_OPENED, pInfo, pTaskInfo); + pInfo->binfo.mergeResultBlock = pAggNode->mergeDataBlock; + pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, hashGroupbyAggregate, NULL, destroyGroupOperatorInfo, optrDefaultBufFn, NULL); code = appendDownstream(pOperator, &downstream, 1); @@ -482,7 +492,7 @@ SOperatorInfo* createGroupOperatorInfo(SOperatorInfo* downstream, SAggPhysiNode* return pOperator; _error: - pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; + pTaskInfo->code = code; if (pInfo != NULL) { destroyGroupOperatorInfo(pInfo); } @@ -570,7 +580,6 @@ static void doHashPartition(SOperatorInfo* pOperator, SSDataBlock* pBlock) { } (*columnLen) += contentLen; - ASSERT(*columnLen >= 0); } (*rows) += 1; @@ -681,7 +690,6 @@ static int compareDataGroupInfo(const void* group1, const void* group2) { const SDataGroupInfo* pGroupInfo2 = group2; if (pGroupInfo1->groupId == pGroupInfo2->groupId) { - ASSERT(0); return 0; } @@ -918,8 +926,7 @@ int32_t setGroupResultOutputBuf(SOperatorInfo* pOperator, SOptrBasicInfo* binfo, SqlFunctionCtx* pCtx = pOperator->exprSupp.pCtx; SResultRow* pResultRow = - doSetResultOutBufByKey(pBuf, pResultRowInfo, (char*)pData, bytes, true, groupId, pTaskInfo, false, pAggSup); - assert(pResultRow != NULL); + doSetResultOutBufByKey(pBuf, pResultRowInfo, (char*)pData, bytes, true, groupId, pTaskInfo, false, pAggSup, false); setResultRowInitCtx(pResultRow, pCtx, numOfCols, pOperator->exprSupp.rowEntryInfoOffset); return TSDB_CODE_SUCCESS; @@ -940,6 +947,7 @@ uint64_t calGroupIdByData(SPartitionBySupporter* pParSup, SExprSupp* pExprSup, S } static bool hasRemainPartion(SStreamPartitionOperatorInfo* pInfo) { return pInfo->parIte != NULL; } +static bool hasRemainTbName(SStreamPartitionOperatorInfo* pInfo) { return pInfo->pTbNameIte != NULL; } static SSDataBlock* buildStreamPartitionResult(SOperatorInfo* pOperator) { SStreamPartitionOperatorInfo* pInfo = pOperator->info; @@ -957,43 +965,16 @@ static SSDataBlock* buildStreamPartitionResult(SOperatorInfo* pOperator) { SColumnInfoData* pDestCol = taosArrayGet(pDest->pDataBlock, j); bool isNull = colDataIsNull(pSrcCol, pSrc->info.rows, rowIndex, NULL); char* pSrcData = colDataGetData(pSrcCol, rowIndex); - colDataAppend(pDestCol, pDest->info.rows, pSrcData, isNull); + colDataSetVal(pDestCol, pDest->info.rows, pSrcData, isNull); } pDest->info.rows++; - if (pInfo->tbnameCalSup.numOfExprs > 0 && i == 0) { - void* tbname = NULL; - if (streamStateGetParName(pOperator->pTaskInfo->streamInfo.pState, pParInfo->groupId, &tbname) == 0) { - memcpy(pDest->info.parTbName, tbname, TSDB_TABLE_NAME_LEN); - tdbFree(tbname); - } else { - SSDataBlock* pTmpBlock = blockCopyOneRow(pSrc, rowIndex); - SSDataBlock* pResBlock = createDataBlock(); - pResBlock->info.rowSize = TSDB_TABLE_NAME_LEN; - SColumnInfoData data = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, TSDB_TABLE_NAME_LEN, 0); - taosArrayPush(pResBlock->pDataBlock, &data); - blockDataEnsureCapacity(pResBlock, 1); - projectApplyFunctions(pInfo->tbnameCalSup.pExprInfo, pResBlock, pTmpBlock, pInfo->tbnameCalSup.pCtx, 1, NULL); - ASSERT(pResBlock->info.rows == 1); - ASSERT(taosArrayGetSize(pResBlock->pDataBlock) == 1); - SColumnInfoData* pCol = taosArrayGet(pResBlock->pDataBlock, 0); - ASSERT(pCol->info.type == TSDB_DATA_TYPE_VARCHAR); - void* pData = colDataGetVarData(pCol, 0); - // TODO check tbname validity - if (pData != (void*)-1) { - memset(pDest->info.parTbName, 0, TSDB_TABLE_NAME_LEN); - int32_t len = TMIN(varDataLen(pData), TSDB_TABLE_NAME_LEN - 1); - memcpy(pDest->info.parTbName, varDataVal(pData), len); - /*pDest->info.parTbName[len + 1] = 0;*/ - } else { - pDest->info.parTbName[0] = 0; - } - if (pParInfo->groupId && pDest->info.parTbName[0]) { - streamStatePutParName(pOperator->pTaskInfo->streamInfo.pState, pParInfo->groupId, pDest->info.parTbName); - } - /*printf("\n\n set name %s\n\n", pDest->info.parTbName);*/ - blockDataDestroy(pTmpBlock); - blockDataDestroy(pResBlock); - } + } + pDest->info.parTbName[0] = 0; + if (pInfo->tbnameCalSup.numOfExprs > 0) { + void* tbname = NULL; + if (streamStateGetParName(pOperator->pTaskInfo->streamInfo.pState, pParInfo->groupId, &tbname) == 0) { + memcpy(pDest->info.parTbName, tbname, TSDB_TABLE_NAME_LEN); + tdbFree(tbname); } } taosArrayDestroy(pParInfo->rowIds); @@ -1009,6 +990,73 @@ static SSDataBlock* buildStreamPartitionResult(SOperatorInfo* pOperator) { return pDest; } +void appendCreateTableRow(SStreamState* pState, SExprSupp* pTableSup, SExprSupp* pTagSup, uint64_t groupId, + SSDataBlock* pSrcBlock, int32_t rowId, SSDataBlock* pDestBlock) { + void* pValue = NULL; + if (streamStateGetParName(pState, groupId, &pValue) != 0) { + SSDataBlock* pTmpBlock = blockCopyOneRow(pSrcBlock, rowId); + memset(pTmpBlock->info.parTbName, 0, TSDB_TABLE_NAME_LEN); + pTmpBlock->info.id.groupId = groupId; + char* tbName = pSrcBlock->info.parTbName; + if (pTableSup->numOfExprs > 0) { + projectApplyFunctions(pTableSup->pExprInfo, pDestBlock, pTmpBlock, pTableSup->pCtx, pTableSup->numOfExprs, NULL); + SColumnInfoData* pTbCol = taosArrayGet(pDestBlock->pDataBlock, UD_TABLE_NAME_COLUMN_INDEX); + memset(tbName, 0, TSDB_TABLE_NAME_LEN); + int32_t len = 0; + if (colDataIsNull_s(pTbCol, pDestBlock->info.rows - 1)) { + len = 1; + tbName[0] = 0; + } else { + void* pData = colDataGetData(pTbCol, pDestBlock->info.rows - 1); + len = TMIN(varDataLen(pData), TSDB_TABLE_NAME_LEN - 1); + memcpy(tbName, varDataVal(pData), len); + streamStatePutParName(pState, groupId, tbName); + } + memcpy(pTmpBlock->info.parTbName, tbName, len); + pDestBlock->info.rows--; + } else { + void* pTbNameCol = taosArrayGet(pDestBlock->pDataBlock, UD_TABLE_NAME_COLUMN_INDEX); + colDataSetNULL(pTbNameCol, pDestBlock->info.rows); + tbName[0] = 0; + } + + if (pTagSup->numOfExprs > 0) { + projectApplyFunctions(pTagSup->pExprInfo, pDestBlock, pTmpBlock, pTagSup->pCtx, pTagSup->numOfExprs, NULL); + pDestBlock->info.rows--; + } else { + memcpy(pDestBlock->info.parTbName, pTmpBlock->info.parTbName, TSDB_TABLE_NAME_LEN); + } + + void* pGpIdCol = taosArrayGet(pDestBlock->pDataBlock, UD_GROUPID_COLUMN_INDEX); + colDataAppend(pGpIdCol, pDestBlock->info.rows, (const char*)&groupId, false); + pDestBlock->info.rows++; + blockDataDestroy(pTmpBlock); + } else { + memcpy(pSrcBlock->info.parTbName, pValue, TSDB_TABLE_NAME_LEN); + } + streamStateReleaseBuf(pState, NULL, pValue); +} + +static SSDataBlock* buildStreamCreateTableResult(SOperatorInfo* pOperator) { + SStreamPartitionOperatorInfo* pInfo = pOperator->info; + if ((pInfo->tbnameCalSup.numOfExprs == 0 && pInfo->tagCalSup.numOfExprs == 0) || + taosHashGetSize(pInfo->pPartitions) == 0) { + return NULL; + } + blockDataCleanup(pInfo->pCreateTbRes); + blockDataEnsureCapacity(pInfo->pCreateTbRes, taosHashGetSize(pInfo->pPartitions)); + SSDataBlock* pSrc = pInfo->pInputDataBlock; + + if (pInfo->pTbNameIte != NULL) { + SPartitionDataInfo* pParInfo = (SPartitionDataInfo*)pInfo->pTbNameIte; + int32_t rowId = *(int32_t*)taosArrayGet(pParInfo->rowIds, 0); + appendCreateTableRow(pOperator->pTaskInfo->streamInfo.pState, &pInfo->tbnameCalSup, &pInfo->tagCalSup, + pParInfo->groupId, pSrc, rowId, pInfo->pCreateTbRes); + pInfo->pTbNameIte = taosHashIterate(pInfo->pPartitions, pInfo->pTbNameIte); + } + return pInfo->pCreateTbRes->info.rows > 0 ? pInfo->pCreateTbRes : NULL; +} + static void doStreamHashPartitionImpl(SStreamPartitionOperatorInfo* pInfo, SSDataBlock* pBlock) { pInfo->pInputDataBlock = pBlock; for (int32_t i = 0; i < pBlock->info.rows; ++i) { @@ -1035,6 +1083,15 @@ static SSDataBlock* doStreamHashPartition(SOperatorInfo* pOperator) { SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; SStreamPartitionOperatorInfo* pInfo = pOperator->info; + SSDataBlock* pCtRes = NULL; + + if (hasRemainTbName(pInfo)) { + pCtRes = buildStreamCreateTableResult(pOperator); + if (pCtRes != NULL) { + return pCtRes; + } + } + if (hasRemainPartion(pInfo)) { return buildStreamPartitionResult(pOperator); } @@ -1062,16 +1119,14 @@ static SSDataBlock* doStreamHashPartition(SOperatorInfo* pOperator) { return pInfo->pDelRes; } break; default: + ASSERTS(pBlock->info.type == STREAM_CREATE_CHILD_TABLE, "invalid SSDataBlock type"); return pBlock; } // there is an scalar expression that needs to be calculated right before apply the group aggregation. if (pInfo->scalarSup.pExprInfo != NULL) { - pTaskInfo->code = projectApplyFunctions(pInfo->scalarSup.pExprInfo, pBlock, pBlock, pInfo->scalarSup.pCtx, + projectApplyFunctions(pInfo->scalarSup.pExprInfo, pBlock, pBlock, pInfo->scalarSup.pCtx, pInfo->scalarSup.numOfExprs, NULL); - if (pTaskInfo->code != TSDB_CODE_SUCCESS) { - longjmp(pTaskInfo->env, pTaskInfo->code); - } } taosHashClear(pInfo->pPartitions); doStreamHashPartitionImpl(pInfo, pBlock); @@ -1079,6 +1134,11 @@ static SSDataBlock* doStreamHashPartition(SOperatorInfo* pOperator) { pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0; pInfo->parIte = taosHashIterate(pInfo->pPartitions, NULL); + pInfo->pTbNameIte = taosHashIterate(pInfo->pPartitions, NULL); + pCtRes = buildStreamCreateTableResult(pOperator); + if (pCtRes != NULL) { + return pCtRes; + } return buildStreamPartitionResult(pOperator); } @@ -1099,6 +1159,7 @@ static void destroyStreamPartitionOperatorInfo(void* param) { cleanupExprSupp(&pInfo->tagCalSup); blockDataDestroy(pInfo->pDelRes); taosHashCleanup(pInfo->pPartitions); + blockDataDestroy(pInfo->pCreateTbRes); taosMemoryFreeClear(param); } @@ -1114,14 +1175,56 @@ void initParDownStream(SOperatorInfo* downstream, SPartitionBySupporter* pParSup } } +SSDataBlock* buildCreateTableBlock(SExprSupp* tbName, SExprSupp* tag) { + SSDataBlock* pBlock = taosMemoryCalloc(1, sizeof(SSDataBlock)); + pBlock->info.hasVarCol = false; + pBlock->info.id.groupId = 0; + pBlock->info.rows = 0; + pBlock->info.type = STREAM_CREATE_CHILD_TABLE; + pBlock->info.watermark = INT64_MIN; + + pBlock->pDataBlock = taosArrayInit(4, sizeof(SColumnInfoData)); + SColumnInfoData infoData = {0}; + infoData.info.type = TSDB_DATA_TYPE_VARCHAR; + if (tbName->numOfExprs > 0) { + infoData.info.bytes = tbName->pExprInfo->base.resSchema.bytes; + } else { + infoData.info.bytes = 1; + } + pBlock->info.rowSize += infoData.info.bytes; + // sub table name + taosArrayPush(pBlock->pDataBlock, &infoData); + + SColumnInfoData gpIdData = {0}; + gpIdData.info.type = TSDB_DATA_TYPE_UBIGINT; + gpIdData.info.bytes = 8; + pBlock->info.rowSize += gpIdData.info.bytes; + // group id + taosArrayPush(pBlock->pDataBlock, &gpIdData); + + for (int32_t i = 0; i < tag->numOfExprs; i++) { + SColumnInfoData tagCol = {0}; + tagCol.info.type = tag->pExprInfo[i].base.resSchema.type; + tagCol.info.bytes = tag->pExprInfo[i].base.resSchema.bytes; + tagCol.info.precision = tag->pExprInfo[i].base.resSchema.precision; + // tag info + taosArrayPush(pBlock->pDataBlock, &tagCol); + pBlock->info.rowSize += tagCol.info.bytes; + } + + return pBlock; +} + SOperatorInfo* createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStreamPartitionPhysiNode* pPartNode, SExecTaskInfo* pTaskInfo) { + int32_t code = TSDB_CODE_SUCCESS; SStreamPartitionOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamPartitionOperatorInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; goto _error; } - int32_t code = TSDB_CODE_SUCCESS; + pInfo->partitionSup.pGroupCols = extractPartitionColInfo(pPartNode->part.pPartitionKeys); if (pPartNode->part.pExprs != NULL) { @@ -1133,6 +1236,7 @@ SOperatorInfo* createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStr } } + pInfo->tbnameCalSup.numOfExprs = 0; if (pPartNode->pSubtable != NULL) { SExprInfo* pSubTableExpr = taosMemoryCalloc(1, sizeof(SExprInfo)); if (pSubTableExpr == NULL) { @@ -1147,19 +1251,26 @@ SOperatorInfo* createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStr } } + pInfo->tagCalSup.numOfExprs = 0; if (pPartNode->pTags != NULL) { int32_t numOfTags; - SExprInfo* pTagExpr = createExprInfo(pPartNode->pTags, NULL, &numOfTags); + SExprInfo* pTagExpr = createExpr(pPartNode->pTags, &numOfTags); if (pTagExpr == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; + code = TSDB_CODE_OUT_OF_MEMORY; goto _error; } if (initExprSupp(&pInfo->tagCalSup, pTagExpr, numOfTags) != 0) { - terrno = TSDB_CODE_OUT_OF_MEMORY; + code = TSDB_CODE_OUT_OF_MEMORY; goto _error; } } + if (pInfo->tbnameCalSup.numOfExprs != 0 || pInfo->tagCalSup.numOfExprs != 0) { + pInfo->pCreateTbRes = buildCreateTableBlock(&pInfo->tbnameCalSup, &pInfo->tagCalSup); + } else { + pInfo->pCreateTbRes = NULL; + } + int32_t keyLen = 0; code = initGroupOptrInfo(&pInfo->partitionSup.pGroupColVals, &keyLen, &pInfo->partitionSup.keyBuf, pInfo->partitionSup.pGroupCols); @@ -1170,12 +1281,14 @@ SOperatorInfo* createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStr pInfo->binfo.pRes = createDataBlockFromDescNode(pPartNode->part.node.pOutputDataBlockDesc); if (pInfo->binfo.pRes == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; goto _error; } blockDataEnsureCapacity(pInfo->binfo.pRes, 4096); pInfo->parIte = NULL; + pInfo->pTbNameIte = NULL; pInfo->pInputDataBlock = NULL; _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); @@ -1198,7 +1311,7 @@ SOperatorInfo* createStreamPartitionOperatorInfo(SOperatorInfo* downstream, SStr return pOperator; _error: - pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; + pTaskInfo->code = code; destroyStreamPartitionOperatorInfo(pInfo); taosMemoryFreeClear(pOperator); return NULL; diff --git a/source/libs/executor/src/joinoperator.c b/source/libs/executor/src/joinoperator.c index 88ed9eccb323561718a3a7cc1bc8dfd737bef53c..9dee58367cf7023d3a9b685a805cabf48d6f7eda 100644 --- a/source/libs/executor/src/joinoperator.c +++ b/source/libs/executor/src/joinoperator.c @@ -13,17 +13,32 @@ * along with this program. If not, see . */ +#include "executorInt.h" #include "filter.h" -#include "executorimpl.h" #include "function.h" +#include "operator.h" #include "os.h" #include "querynodes.h" +#include "querytask.h" #include "tcompare.h" #include "tdatablock.h" #include "thash.h" #include "tmsg.h" #include "ttypes.h" +typedef struct SJoinRowCtx { + bool rowRemains; + int64_t ts; + SArray* leftRowLocations; + SArray* leftCreatedBlocks; + SArray* rightCreatedBlocks; + int32_t leftRowIdx; + int32_t rightRowIdx; + + bool rightUseBuildTable; + SArray* rightRowLocations; +} SJoinRowCtx; + typedef struct SJoinOperatorInfo { SSDataBlock* pRes; int32_t joinType; @@ -37,6 +52,18 @@ typedef struct SJoinOperatorInfo { int32_t rightPos; SColumnInfo rightCol; SNode* pCondAfterMerge; + SNode* pTagEqualConditions; + + SArray* leftTagCols; + char* leftTagKeyBuf; + int32_t leftTagKeyLen; + + SArray* rightTagCols; + char* rightTagKeyBuf; + int32_t rightTagKeyLen; + + SSHashObj* rightBuildTable; + SJoinRowCtx rowCtx; } SJoinOperatorInfo; static void setJoinColumnInfo(SColumnInfo* pColumn, const SColumnNode* pColumnNode); @@ -77,6 +104,100 @@ static void extractTimeCondition(SJoinOperatorInfo* pInfo, SOperatorInfo** pDown setJoinColumnInfo(&pInfo->rightCol, rightTsCol); } +static void extractTagEqualColsFromOper(SJoinOperatorInfo* pInfo, SOperatorInfo** pDownstreams, SOperatorNode* pOperNode, + SColumn* pLeft, SColumn* pRight) { + SColumnNode* pLeftNode = (SColumnNode*)pOperNode->pLeft; + SColumnNode* pRightNode = (SColumnNode*)pOperNode->pRight; + if (pLeftNode->dataBlockId == pRightNode->dataBlockId || pLeftNode->dataBlockId == pDownstreams[0]->resultDataBlockId) { + *pLeft = extractColumnFromColumnNode((SColumnNode*)pOperNode->pLeft); + *pRight = extractColumnFromColumnNode((SColumnNode*)pOperNode->pRight); + } else { + *pLeft = extractColumnFromColumnNode((SColumnNode*)pOperNode->pRight); + *pRight = extractColumnFromColumnNode((SColumnNode*)pOperNode->pLeft); + } +} + +static void extractTagEqualCondCols(SJoinOperatorInfo* pInfo, SOperatorInfo** pDownStream, SNode* pTagEqualNode, + SArray* leftTagEqCols, SArray* rightTagEqCols) { + SColumn left = {0}; + SColumn right = {0}; + if (nodeType(pTagEqualNode) == QUERY_NODE_LOGIC_CONDITION && ((SLogicConditionNode*)pTagEqualNode)->condType == LOGIC_COND_TYPE_AND) { + SNode* pNode = NULL; + FOREACH(pNode, ((SLogicConditionNode*)pTagEqualNode)->pParameterList) { + SOperatorNode* pOperNode = (SOperatorNode*)pNode; + extractTagEqualColsFromOper(pInfo, pDownStream, pOperNode, &left, &right); + taosArrayPush(leftTagEqCols, &left); + taosArrayPush(rightTagEqCols, &right); + } + return; + } + + if (nodeType(pTagEqualNode) == QUERY_NODE_OPERATOR) { + SOperatorNode* pOperNode = (SOperatorNode*)pTagEqualNode; + extractTagEqualColsFromOper(pInfo, pDownStream, pOperNode, &left, &right); + taosArrayPush(leftTagEqCols, &left); + taosArrayPush(rightTagEqCols, &right); + } +} + +static int32_t initTagColskeyBuf(int32_t* keyLen, char** keyBuf, const SArray* pGroupColList) { + int32_t numOfGroupCols = taosArrayGetSize(pGroupColList); + for (int32_t i = 0; i < numOfGroupCols; ++i) { + SColumn* pCol = (SColumn*)taosArrayGet(pGroupColList, i); + (*keyLen) += pCol->bytes; // actual data + null_flag + } + + int32_t nullFlagSize = sizeof(int8_t) * numOfGroupCols; + (*keyLen) += nullFlagSize; + + (*keyBuf) = taosMemoryCalloc(1, (*keyLen)); + if ((*keyBuf) == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t fillKeyBufFromTagCols(SArray* pCols, SSDataBlock* pBlock, int32_t rowIndex, void* pKey) { + SColumnDataAgg* pColAgg = NULL; + size_t numOfGroupCols = taosArrayGetSize(pCols); + char* isNull = (char*)pKey; + char* pStart = (char*)pKey + sizeof(int8_t) * numOfGroupCols; + + for (int32_t i = 0; i < numOfGroupCols; ++i) { + SColumn* pCol = (SColumn*) taosArrayGet(pCols, i); + SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pCol->slotId); + + // valid range check. todo: return error code. + if (pCol->slotId > taosArrayGetSize(pBlock->pDataBlock)) { + continue; + } + + if (pBlock->pBlockAgg != NULL) { + pColAgg = pBlock->pBlockAgg[pCol->slotId]; // TODO is agg data matched? + } + + if (colDataIsNull(pColInfoData, pBlock->info.rows, rowIndex, pColAgg)) { + isNull[i] = 1; + } else { + isNull[i] = 0; + char* val = colDataGetData(pColInfoData, rowIndex); + if (pCol->type == TSDB_DATA_TYPE_JSON) { + int32_t dataLen = getJsonValueLen(val); + memcpy(pStart, val, dataLen); + pStart += dataLen; + } else if (IS_VAR_DATA_TYPE(pCol->type)) { + varDataCopy(pStart, val); + pStart += varDataTLen(val); + } else { + memcpy(pStart, val, pCol->bytes); + pStart += pCol->bytes; + } + } + } + return (int32_t)(pStart - (char*)pKey); +} + SOperatorInfo* createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t numOfDownstream, SSortMergeJoinPhysiNode* pJoinNode, SExecTaskInfo* pTaskInfo) { SJoinOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SJoinOperatorInfo)); @@ -138,6 +259,16 @@ SOperatorInfo* createMergeJoinOperatorInfo(SOperatorInfo** pDownstream, int32_t pInfo->inputOrder = TSDB_ORDER_DESC; } + pInfo->pTagEqualConditions = pJoinNode->pTagEqualCondtions; + if (pInfo->pTagEqualConditions != NULL) { + pInfo->leftTagCols = taosArrayInit(4, sizeof(SColumn)); + pInfo->rightTagCols = taosArrayInit(4, sizeof(SColumn)); + extractTagEqualCondCols(pInfo, pDownstream, pInfo->pTagEqualConditions, pInfo->leftTagCols, pInfo->rightTagCols); + initTagColskeyBuf(&pInfo->leftTagKeyLen, &pInfo->leftTagKeyBuf, pInfo->leftTagCols); + initTagColskeyBuf(&pInfo->rightTagKeyLen, &pInfo->rightTagKeyBuf, pInfo->rightTagCols); + _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); + pInfo->rightBuildTable = tSimpleHashInit(256, hashFn); + } pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doMergeJoin, NULL, destroyMergeJoinOperator, optrDefaultBufFn, NULL); code = appendDownstream(pOperator, pDownstream, numOfDownstream); if (code != TSDB_CODE_SUCCESS) { @@ -164,8 +295,28 @@ void setJoinColumnInfo(SColumnInfo* pColumn, const SColumnNode* pColumnNode) { pColumn->scale = pColumnNode->node.resType.scale; } +static void mergeJoinDestoryBuildTable(SSHashObj* pBuildTable) { + void* p = NULL; + int32_t iter = 0; + + while ((p = tSimpleHashIterate(pBuildTable, p, &iter)) != NULL) { + SArray* rows = (*(SArray**)p); + taosArrayDestroy(rows); + } + + tSimpleHashCleanup(pBuildTable); +} + void destroyMergeJoinOperator(void* param) { SJoinOperatorInfo* pJoinOperator = (SJoinOperatorInfo*)param; + if (pJoinOperator->pTagEqualConditions != NULL) { + mergeJoinDestoryBuildTable(pJoinOperator->rightBuildTable); + taosMemoryFreeClear(pJoinOperator->rightTagKeyBuf); + taosArrayDestroy(pJoinOperator->rightTagCols); + + taosMemoryFreeClear(pJoinOperator->leftTagKeyBuf); + taosArrayDestroy(pJoinOperator->leftTagCols); + } nodesDestroyNode(pJoinOperator->pCondAfterMerge); pJoinOperator->pRes = blockDataDestroy(pJoinOperator->pRes); @@ -196,10 +347,10 @@ static void mergeJoinJoinLeftRight(struct SOperatorInfo* pOperator, SSDataBlock* } if (colDataIsNull_s(pSrc, rowIndex)) { - colDataAppendNULL(pDst, currRow); + colDataSetNULL(pDst, currRow); } else { char* p = colDataGetData(pSrc, rowIndex); - colDataAppend(pDst, currRow, p, false); + colDataSetVal(pDst, currRow, p, false); } } } @@ -285,51 +436,172 @@ static int32_t mergeJoinGetDownStreamRowsEqualTimeStamp(SOperatorInfo* pOperator return 0; } -static int32_t mergeJoinJoinDownstreamTsRanges(SOperatorInfo* pOperator, int64_t timestamp, SSDataBlock* pRes, - int32_t* nRows) { +static int32_t mergeJoinFillBuildTable(SJoinOperatorInfo* pInfo, SArray* rightRowLocations) { + for (int32_t i = 0; i < taosArrayGetSize(rightRowLocations); ++i) { + SRowLocation* rightRow = taosArrayGet(rightRowLocations, i); + int32_t keyLen = fillKeyBufFromTagCols(pInfo->rightTagCols, rightRow->pDataBlock, rightRow->pos, pInfo->rightTagKeyBuf); + SArray** ppRows = tSimpleHashGet(pInfo->rightBuildTable, pInfo->rightTagKeyBuf, keyLen); + if (!ppRows) { + SArray* rows = taosArrayInit(4, sizeof(SRowLocation)); + taosArrayPush(rows, rightRow); + tSimpleHashPut(pInfo->rightBuildTable, pInfo->rightTagKeyBuf, keyLen, &rows, POINTER_BYTES); + } else { + taosArrayPush(*ppRows, rightRow); + } + } + return TSDB_CODE_SUCCESS; +} + +static int32_t mergeJoinLeftRowsRightRows(SOperatorInfo* pOperator, SSDataBlock* pRes, int32_t* nRows, + const SArray* leftRowLocations, int32_t leftRowIdx, + int32_t rightRowIdx, bool useBuildTableTSRange, SArray* rightRowLocations, bool* pReachThreshold) { + *pReachThreshold = false; + uint32_t limitRowNum = pOperator->resultInfo.threshold; SJoinOperatorInfo* pJoinInfo = pOperator->info; - SArray* leftRowLocations = taosArrayInit(8, sizeof(SRowLocation)); - SArray* leftCreatedBlocks = taosArrayInit(8, POINTER_BYTES); + size_t leftNumJoin = taosArrayGetSize(leftRowLocations); - SArray* rightRowLocations = taosArrayInit(8, sizeof(SRowLocation)); - SArray* rightCreatedBlocks = taosArrayInit(8, POINTER_BYTES); - int32_t code = TSDB_CODE_SUCCESS; - mergeJoinGetDownStreamRowsEqualTimeStamp(pOperator, 0, pJoinInfo->leftCol.slotId, pJoinInfo->pLeft, - pJoinInfo->leftPos, timestamp, leftRowLocations, leftCreatedBlocks); - mergeJoinGetDownStreamRowsEqualTimeStamp(pOperator, 1, pJoinInfo->rightCol.slotId, pJoinInfo->pRight, - pJoinInfo->rightPos, timestamp, rightRowLocations, rightCreatedBlocks); + int32_t i,j; - size_t leftNumJoin = taosArrayGetSize(leftRowLocations); - size_t rightNumJoin = taosArrayGetSize(rightRowLocations); - code = blockDataEnsureCapacity(pRes, *nRows + leftNumJoin * rightNumJoin); - if (code != TSDB_CODE_SUCCESS) { - qError("%s can not ensure block capacity for join. left: %zu, right: %zu", GET_TASKID(pOperator->pTaskInfo), - leftNumJoin, rightNumJoin); - } - if (code == TSDB_CODE_SUCCESS) { - for (int32_t i = 0; i < leftNumJoin; ++i) { - for (int32_t j = 0; j < rightNumJoin; ++j) { - SRowLocation* leftRow = taosArrayGet(leftRowLocations, i); - SRowLocation* rightRow = taosArrayGet(rightRowLocations, j); - mergeJoinJoinLeftRight(pOperator, pRes, *nRows, leftRow->pDataBlock, leftRow->pos, rightRow->pDataBlock, - rightRow->pos); - ++*nRows; + for (i = leftRowIdx; i < leftNumJoin; ++i, rightRowIdx = 0) { + SRowLocation* leftRow = taosArrayGet(leftRowLocations, i); + SArray* pRightRows = NULL; + if (useBuildTableTSRange) { + int32_t keyLen = fillKeyBufFromTagCols(pJoinInfo->leftTagCols, leftRow->pDataBlock, leftRow->pos, pJoinInfo->leftTagKeyBuf); + SArray** ppRightRows = tSimpleHashGet(pJoinInfo->rightBuildTable, pJoinInfo->leftTagKeyBuf, keyLen); + if (!ppRightRows) { + continue; + } + pRightRows = *ppRightRows; + } else { + pRightRows = rightRowLocations; + } + size_t rightRowsSize = taosArrayGetSize(pRightRows); + for (j = rightRowIdx; j < rightRowsSize; ++j) { + if (*nRows >= limitRowNum) { + *pReachThreshold = true; + break; } + + SRowLocation* rightRow = taosArrayGet(pRightRows, j); + mergeJoinJoinLeftRight(pOperator, pRes, *nRows, leftRow->pDataBlock, leftRow->pos, rightRow->pDataBlock, + rightRow->pos); + ++*nRows; + } + if (*pReachThreshold) { + break; } } + if (*pReachThreshold) { + pJoinInfo->rowCtx.rowRemains = true; + pJoinInfo->rowCtx.leftRowIdx = i; + pJoinInfo->rowCtx.rightRowIdx = j; + } + return TSDB_CODE_SUCCESS; +} + +static void mergeJoinDestroyTSRangeCtx(SJoinOperatorInfo* pJoinInfo, SArray* leftRowLocations, SArray* leftCreatedBlocks, + SArray* rightCreatedBlocks, bool rightUseBuildTable, SArray* rightRowLocations) { for (int i = 0; i < taosArrayGetSize(rightCreatedBlocks); ++i) { SSDataBlock* pBlock = taosArrayGetP(rightCreatedBlocks, i); blockDataDestroy(pBlock); } taosArrayDestroy(rightCreatedBlocks); - taosArrayDestroy(rightRowLocations); for (int i = 0; i < taosArrayGetSize(leftCreatedBlocks); ++i) { SSDataBlock* pBlock = taosArrayGetP(leftCreatedBlocks, i); blockDataDestroy(pBlock); } + if (rightRowLocations != NULL) { + taosArrayDestroy(rightRowLocations); + } + if (rightUseBuildTable) { + void* p = NULL; + int32_t iter = 0; + while ((p = tSimpleHashIterate(pJoinInfo->rightBuildTable, p, &iter)) != NULL) { + SArray* rows = (*(SArray**)p); + taosArrayDestroy(rows); + } + tSimpleHashClear(pJoinInfo->rightBuildTable); + } + taosArrayDestroy(leftCreatedBlocks); taosArrayDestroy(leftRowLocations); + + pJoinInfo->rowCtx.rowRemains = false; + pJoinInfo->rowCtx.leftRowLocations = NULL; + pJoinInfo->rowCtx.leftCreatedBlocks = NULL; + pJoinInfo->rowCtx.rightCreatedBlocks = NULL; + pJoinInfo->rowCtx.rightUseBuildTable = false; + pJoinInfo->rowCtx.rightRowLocations = NULL; +} + +static int32_t mergeJoinJoinDownstreamTsRanges(SOperatorInfo* pOperator, int64_t timestamp, SSDataBlock* pRes, + int32_t* nRows) { + int32_t code = TSDB_CODE_SUCCESS; + SJoinOperatorInfo* pJoinInfo = pOperator->info; + SArray* leftRowLocations = NULL; + SArray* rightRowLocations = NULL; + SArray* leftCreatedBlocks = NULL; + SArray* rightCreatedBlocks = NULL; + int32_t leftRowIdx = 0; + int32_t rightRowIdx = 0; + SSHashObj* rightTableHash = NULL; + bool rightUseBuildTable = false; + + if (pJoinInfo->rowCtx.rowRemains) { + leftRowLocations = pJoinInfo->rowCtx.leftRowLocations; + leftCreatedBlocks = pJoinInfo->rowCtx.leftCreatedBlocks; + rightUseBuildTable = pJoinInfo->rowCtx.rightUseBuildTable; + rightRowLocations = pJoinInfo->rowCtx.rightRowLocations; + rightCreatedBlocks = pJoinInfo->rowCtx.rightCreatedBlocks; + leftRowIdx = pJoinInfo->rowCtx.leftRowIdx; + rightRowIdx = pJoinInfo->rowCtx.rightRowIdx; + } else { + leftRowLocations = taosArrayInit(8, sizeof(SRowLocation)); + leftCreatedBlocks = taosArrayInit(8, POINTER_BYTES); + + rightRowLocations = taosArrayInit(8, sizeof(SRowLocation)); + rightCreatedBlocks = taosArrayInit(8, POINTER_BYTES); + + mergeJoinGetDownStreamRowsEqualTimeStamp(pOperator, 0, pJoinInfo->leftCol.slotId, pJoinInfo->pLeft, + pJoinInfo->leftPos, timestamp, leftRowLocations, leftCreatedBlocks); + mergeJoinGetDownStreamRowsEqualTimeStamp(pOperator, 1, pJoinInfo->rightCol.slotId, pJoinInfo->pRight, + pJoinInfo->rightPos, timestamp, rightRowLocations, rightCreatedBlocks); + if (pJoinInfo->pTagEqualConditions != NULL && taosArrayGetSize(rightRowLocations) > 16) { + mergeJoinFillBuildTable(pJoinInfo, rightRowLocations); + rightUseBuildTable = true; + taosArrayDestroy(rightRowLocations); + rightRowLocations = NULL; + } + } + + size_t leftNumJoin = taosArrayGetSize(leftRowLocations); + code = blockDataEnsureCapacity(pRes, pOperator->resultInfo.threshold); + if (code != TSDB_CODE_SUCCESS) { + qError("%s can not ensure block capacity for join. left: %zu", GET_TASKID(pOperator->pTaskInfo), + leftNumJoin); + } + + bool reachThreshold = false; + + if (code == TSDB_CODE_SUCCESS) { + mergeJoinLeftRowsRightRows(pOperator, pRes, nRows, leftRowLocations, leftRowIdx, + rightRowIdx, rightUseBuildTable, rightRowLocations, &reachThreshold); + } + + if (!reachThreshold) { + mergeJoinDestroyTSRangeCtx(pJoinInfo, leftRowLocations, leftCreatedBlocks, rightCreatedBlocks, + rightUseBuildTable, rightRowLocations); + + } else { + pJoinInfo->rowCtx.rowRemains = true; + pJoinInfo->rowCtx.ts = timestamp; + pJoinInfo->rowCtx.leftRowLocations = leftRowLocations; + pJoinInfo->rowCtx.leftCreatedBlocks = leftCreatedBlocks; + pJoinInfo->rowCtx.rightCreatedBlocks = rightCreatedBlocks; + pJoinInfo->rowCtx.rightUseBuildTable = rightUseBuildTable; + pJoinInfo->rowCtx.rightRowLocations = rightRowLocations; + } return TSDB_CODE_SUCCESS; } @@ -379,9 +651,14 @@ static void doMergeJoinImpl(struct SOperatorInfo* pOperator, SSDataBlock* pRes) while (1) { int64_t leftTs = 0; int64_t rightTs = 0; - bool hasNextTs = mergeJoinGetNextTimestamp(pOperator, &leftTs, &rightTs); - if (!hasNextTs) { - break; + if (pJoinInfo->rowCtx.rowRemains) { + leftTs = pJoinInfo->rowCtx.ts; + rightTs = pJoinInfo->rowCtx.ts; + } else { + bool hasNextTs = mergeJoinGetNextTimestamp(pOperator, &leftTs, &rightTs); + if (!hasNextTs) { + break; + } } if (leftTs == rightTs) { @@ -389,12 +666,12 @@ static void doMergeJoinImpl(struct SOperatorInfo* pOperator, SSDataBlock* pRes) } else if ((asc && leftTs < rightTs) || (!asc && leftTs > rightTs)) { pJoinInfo->leftPos += 1; - if (pJoinInfo->leftPos >= pJoinInfo->pLeft->info.rows) { + if (pJoinInfo->leftPos >= pJoinInfo->pLeft->info.rows && pRes->info.rows < pOperator->resultInfo.threshold) { continue; } } else if ((asc && leftTs > rightTs) || (!asc && leftTs < rightTs)) { pJoinInfo->rightPos += 1; - if (pJoinInfo->rightPos >= pJoinInfo->pRight->info.rows) { + if (pJoinInfo->rightPos >= pJoinInfo->pRight->info.rows && pRes->info.rows < pOperator->resultInfo.threshold) { continue; } } diff --git a/source/libs/executor/src/operator.c b/source/libs/executor/src/operator.c new file mode 100644 index 0000000000000000000000000000000000000000..729178dc60b482fc82b0fddba5b78ce5358c216d --- /dev/null +++ b/source/libs/executor/src/operator.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "filter.h" +#include "function.h" +#include "os.h" +#include "tname.h" + +#include "tglobal.h" + +#include "executorInt.h" +#include "index.h" +#include "operator.h" +#include "query.h" +#include "querytask.h" +#include "vnode.h" + +SOperatorFpSet createOperatorFpSet(__optr_open_fn_t openFn, __optr_fn_t nextFn, __optr_fn_t cleanup, + __optr_close_fn_t closeFn, __optr_reqBuf_fn_t reqBufFn, + __optr_explain_fn_t explain) { + SOperatorFpSet fpSet = { + ._openFn = openFn, + .getNextFn = nextFn, + .cleanupFn = cleanup, + .closeFn = closeFn, + .reqBufFn = reqBufFn, + .getExplainFn = explain, + }; + + return fpSet; +} + +int32_t optrDummyOpenFn(SOperatorInfo* pOperator) { + OPTR_SET_OPENED(pOperator); + pOperator->cost.openCost = 0; + return TSDB_CODE_SUCCESS; +} + +int32_t appendDownstream(SOperatorInfo* p, SOperatorInfo** pDownstream, int32_t num) { + p->pDownstream = taosMemoryCalloc(1, num * POINTER_BYTES); + if (p->pDownstream == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + memcpy(p->pDownstream, pDownstream, num * POINTER_BYTES); + p->numOfDownstream = num; + return TSDB_CODE_SUCCESS; +} + +void setOperatorCompleted(SOperatorInfo* pOperator) { + pOperator->status = OP_EXEC_DONE; + pOperator->cost.totalCost = (taosGetTimestampUs() - pOperator->pTaskInfo->cost.start) / 1000.0; + setTaskStatus(pOperator->pTaskInfo, TASK_COMPLETED); +} + +void setOperatorInfo(SOperatorInfo* pOperator, const char* name, int32_t type, bool blocking, int32_t status, + void* pInfo, SExecTaskInfo* pTaskInfo) { + pOperator->name = (char*)name; + pOperator->operatorType = type; + pOperator->blocking = blocking; + pOperator->status = status; + pOperator->info = pInfo; + pOperator->pTaskInfo = pTaskInfo; +} + +// each operator should be set their own function to return total cost buffer +int32_t optrDefaultBufFn(SOperatorInfo* pOperator) { + if (pOperator->blocking) { + return -1; + } else { + return 0; + } +} + +static int64_t getQuerySupportBufSize(size_t numOfTables) { + size_t s1 = sizeof(STableQueryInfo); + // size_t s3 = sizeof(STableCheckInfo); buffer consumption in tsdb + return (int64_t)(s1 * 1.5 * numOfTables); +} + +int32_t checkForQueryBuf(size_t numOfTables) { + int64_t t = getQuerySupportBufSize(numOfTables); + if (tsQueryBufferSizeBytes < 0) { + return TSDB_CODE_SUCCESS; + } else if (tsQueryBufferSizeBytes > 0) { + while (1) { + int64_t s = tsQueryBufferSizeBytes; + int64_t remain = s - t; + if (remain >= 0) { + if (atomic_val_compare_exchange_64(&tsQueryBufferSizeBytes, s, remain) == s) { + return TSDB_CODE_SUCCESS; + } + } else { + return TSDB_CODE_QRY_NOT_ENOUGH_BUFFER; + } + } + } + + // disable query processing if the value of tsQueryBufferSize is zero. + return TSDB_CODE_QRY_NOT_ENOUGH_BUFFER; +} + +void releaseQueryBuf(size_t numOfTables) { + if (tsQueryBufferSizeBytes < 0) { + return; + } + + int64_t t = getQuerySupportBufSize(numOfTables); + + // restore value is not enough buffer available + atomic_add_fetch_64(&tsQueryBufferSizeBytes, t); +} + +typedef enum { + OPTR_FN_RET_CONTINUE = 0x1, + OPTR_FN_RET_ABORT = 0x2, +} ERetType; + +typedef struct STraverParam { + void* pRet; + int32_t code; + void* pParam; +} STraverParam; + +// iterate the operator tree helper +typedef ERetType (*optr_fn_t)(SOperatorInfo *pOperator, STraverParam *pParam, const char* pIdstr); + +void traverseOperatorTree(SOperatorInfo* pOperator, optr_fn_t fn, STraverParam* pParam, const char* id) { + if (pOperator == NULL) { + return; + } + + ERetType ret = fn(pOperator, pParam, id); + if (ret == OPTR_FN_RET_ABORT || pParam->code != TSDB_CODE_SUCCESS) { + return; + } + + for (int32_t i = 0; i < pOperator->numOfDownstream; ++i) { + traverseOperatorTree(pOperator->pDownstream[i], fn, pParam, id); + if (pParam->code != 0) { + break; + } + } +} + +ERetType extractOperatorInfo(SOperatorInfo* pOperator, STraverParam* pParam, const char* pIdStr) { + STraverParam* p = pParam; + if (pOperator->operatorType == *(int32_t*)p->pParam) { + p->pRet = pOperator; + return OPTR_FN_RET_ABORT; + } else { + return OPTR_FN_RET_CONTINUE; + } +} + +// QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN +SOperatorInfo* extractOperatorInTree(SOperatorInfo* pOperator, int32_t type, const char* id) { + if (pOperator == NULL) { + qError("invalid operator, failed to find tableScanOperator %s", id); + terrno = TSDB_CODE_PAR_INTERNAL_ERROR; + return NULL; + } + + STraverParam p = {.pParam = &type, .pRet = NULL}; + traverseOperatorTree(pOperator, extractOperatorInfo, &p, id); + if (p.code != 0) { + terrno = p.code; + return NULL; + } else { + return p.pRet; + } +} + +typedef struct SExtScanInfo { + int32_t order; + int32_t scanFlag; + int32_t inheritUsOrder; +} SExtScanInfo; + +static ERetType extractScanInfo(SOperatorInfo* pOperator, STraverParam* pParam, const char* pIdStr) { + int32_t type = pOperator->operatorType; + SExtScanInfo* pInfo = pParam->pParam; + + if (type == QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN || + type == QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN || + type == QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN || type == QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN) { + pInfo->order = TSDB_ORDER_ASC; + pInfo->scanFlag= MAIN_SCAN; + return OPTR_FN_RET_ABORT; + } else if (type == QUERY_NODE_PHYSICAL_PLAN_EXCHANGE) { + if (!pInfo->inheritUsOrder) { + pInfo->order = TSDB_ORDER_ASC; + } + pInfo->scanFlag= MAIN_SCAN; + return OPTR_FN_RET_ABORT; + } else if (type == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) { + STableScanInfo* pTableScanInfo = pOperator->info; + pInfo->order = pTableScanInfo->base.cond.order; + pInfo->scanFlag= pTableScanInfo->base.scanFlag; + return OPTR_FN_RET_ABORT; + } else if (type == QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN) { + STableMergeScanInfo* pTableScanInfo = pOperator->info; + pInfo->order = pTableScanInfo->base.cond.order; + pInfo->scanFlag= pTableScanInfo->base.scanFlag; + return OPTR_FN_RET_ABORT; + } else { + return OPTR_FN_RET_CONTINUE; + } +} + +int32_t getTableScanInfo(SOperatorInfo* pOperator, int32_t* order, int32_t* scanFlag, bool inheritUsOrder) { + SExtScanInfo info = {.inheritUsOrder = inheritUsOrder, .order = *order}; + STraverParam p = {.pParam = &info}; + + traverseOperatorTree(pOperator, extractScanInfo, &p, NULL); + *order = info.order; + *scanFlag = info.scanFlag; + + ASSERT(*order == TSDB_ORDER_ASC || *order == TSDB_ORDER_DESC); + return p.code; +} + +static ERetType doStopDataReader(SOperatorInfo* pOperator, STraverParam* pParam, const char* pIdStr) { + if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) { + STableScanInfo* pInfo = pOperator->info; + + if (pInfo->base.dataReader != NULL) { + tsdbReaderSetCloseFlag(pInfo->base.dataReader); + } + return OPTR_FN_RET_ABORT; + } else if (pOperator->operatorType == QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN) { + SStreamScanInfo* pInfo = pOperator->info; + + if (pInfo->pTableScanOp != NULL) { + STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info; + if (pTableScanInfo != NULL && pTableScanInfo->base.dataReader != NULL) { + tsdbReaderSetCloseFlag(pTableScanInfo->base.dataReader); + } + } + + return OPTR_FN_RET_ABORT; + } + + return OPTR_FN_RET_CONTINUE; +} + +int32_t stopTableScanOperator(SOperatorInfo* pOperator, const char* pIdStr) { + STraverParam p = {0}; + traverseOperatorTree(pOperator, doStopDataReader, &p, pIdStr); + return p.code; +} + +SOperatorInfo* createOperator(SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo, SReadHandle* pHandle, SNode* pTagCond, + SNode* pTagIndexCond, const char* pUser, const char* dbname) { + int32_t type = nodeType(pPhyNode); + const char* idstr = GET_TASKID(pTaskInfo); + + if (pPhyNode->pChildren == NULL || LIST_LENGTH(pPhyNode->pChildren) == 0) { + SOperatorInfo* pOperator = NULL; + if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == type) { + STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode; + + // NOTE: this is an patch to fix the physical plan + // TODO remove it later + if (pTableScanNode->scan.node.pLimit != NULL) { + pTableScanNode->groupSort = true; + } + + STableListInfo* pTableListInfo = tableListCreate(); + int32_t code = + createScanTableListInfo(&pTableScanNode->scan, pTableScanNode->pGroupTags, pTableScanNode->groupSort, pHandle, + pTableListInfo, pTagCond, pTagIndexCond, pTaskInfo); + if (code) { + pTaskInfo->code = code; + tableListDestroy(pTableListInfo); + qError("failed to createScanTableListInfo, code:%s, %s", tstrerror(code), idstr); + return NULL; + } + + code = initQueriedTableSchemaInfo(pHandle, &pTableScanNode->scan, dbname, pTaskInfo); + if (code) { + pTaskInfo->code = code; + tableListDestroy(pTableListInfo); + return NULL; + } + + pOperator = createTableScanOperatorInfo(pTableScanNode, pHandle, pTableListInfo, pTaskInfo); + if (NULL == pOperator) { + pTaskInfo->code = terrno; + tableListDestroy(pTableListInfo); + return NULL; + } + + STableScanInfo* pScanInfo = pOperator->info; + pTaskInfo->cost.pRecoder = &pScanInfo->base.readRecorder; + } else if (QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN == type) { + STableMergeScanPhysiNode* pTableScanNode = (STableMergeScanPhysiNode*)pPhyNode; + STableListInfo* pTableListInfo = tableListCreate(); + + int32_t code = createScanTableListInfo(&pTableScanNode->scan, pTableScanNode->pGroupTags, true, pHandle, + pTableListInfo, pTagCond, pTagIndexCond, pTaskInfo); + if (code) { + pTaskInfo->code = code; + tableListDestroy(pTableListInfo); + qError("failed to createScanTableListInfo, code: %s", tstrerror(code)); + return NULL; + } + + code = initQueriedTableSchemaInfo(pHandle, &pTableScanNode->scan, dbname, pTaskInfo); + if (code) { + pTaskInfo->code = terrno; + tableListDestroy(pTableListInfo); + return NULL; + } + + pOperator = createTableMergeScanOperatorInfo(pTableScanNode, pHandle, pTableListInfo, pTaskInfo); + if (NULL == pOperator) { + pTaskInfo->code = terrno; + tableListDestroy(pTableListInfo); + return NULL; + } + + STableScanInfo* pScanInfo = pOperator->info; + pTaskInfo->cost.pRecoder = &pScanInfo->base.readRecorder; + } else if (QUERY_NODE_PHYSICAL_PLAN_EXCHANGE == type) { + pOperator = createExchangeOperatorInfo(pHandle ? pHandle->pMsgCb->clientRpc : NULL, (SExchangePhysiNode*)pPhyNode, + pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN == type) { + STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhyNode; + STableListInfo* pTableListInfo = tableListCreate(); + + if (pHandle->vnode) { + int32_t code = + createScanTableListInfo(&pTableScanNode->scan, pTableScanNode->pGroupTags, pTableScanNode->groupSort, + pHandle, pTableListInfo, pTagCond, pTagIndexCond, pTaskInfo); + if (code) { + pTaskInfo->code = code; + tableListDestroy(pTableListInfo); + qError("failed to createScanTableListInfo, code: %s", tstrerror(code)); + return NULL; + } + } + + pTaskInfo->schemaInfo.qsw = extractQueriedColumnSchema(&pTableScanNode->scan); + pOperator = createStreamScanOperatorInfo(pHandle, pTableScanNode, pTagCond, pTableListInfo, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN == type) { + SSystemTableScanPhysiNode* pSysScanPhyNode = (SSystemTableScanPhysiNode*)pPhyNode; + pOperator = createSysTableScanOperatorInfo(pHandle, pSysScanPhyNode, pUser, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN == type) { + STableCountScanPhysiNode* pTblCountScanNode = (STableCountScanPhysiNode*)pPhyNode; + pOperator = createTableCountScanOperatorInfo(pHandle, pTblCountScanNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN == type) { + STagScanPhysiNode* pScanPhyNode = (STagScanPhysiNode*)pPhyNode; + STableListInfo* pTableListInfo = tableListCreate(); + int32_t code = createScanTableListInfo(pScanPhyNode, NULL, false, pHandle, pTableListInfo, pTagCond, + pTagIndexCond, pTaskInfo); + if (code != TSDB_CODE_SUCCESS) { + pTaskInfo->code = code; + qError("failed to getTableList, code: %s", tstrerror(code)); + return NULL; + } + + pOperator = createTagScanOperatorInfo(pHandle, pScanPhyNode, pTableListInfo, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN == type) { + SBlockDistScanPhysiNode* pBlockNode = (SBlockDistScanPhysiNode*)pPhyNode; + STableListInfo* pTableListInfo = tableListCreate(); + + if (pBlockNode->tableType == TSDB_SUPER_TABLE) { + SArray* pList = taosArrayInit(4, sizeof(STableKeyInfo)); + int32_t code = vnodeGetAllTableList(pHandle->vnode, pBlockNode->uid, pList); + if (code != TSDB_CODE_SUCCESS) { + pTaskInfo->code = terrno; + return NULL; + } + + size_t num = taosArrayGetSize(pList); + for (int32_t i = 0; i < num; ++i) { + STableKeyInfo* p = taosArrayGet(pList, i); + tableListAddTableInfo(pTableListInfo, p->uid, 0); + } + + taosArrayDestroy(pList); + } else { // Create group with only one table + tableListAddTableInfo(pTableListInfo, pBlockNode->uid, 0); + } + + pOperator = createDataBlockInfoScanOperator(pHandle, pBlockNode, pTableListInfo, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN == type) { + SLastRowScanPhysiNode* pScanNode = (SLastRowScanPhysiNode*)pPhyNode; + STableListInfo* pTableListInfo = tableListCreate(); + + int32_t code = createScanTableListInfo(&pScanNode->scan, pScanNode->pGroupTags, true, pHandle, pTableListInfo, + pTagCond, pTagIndexCond, pTaskInfo); + if (code != TSDB_CODE_SUCCESS) { + pTaskInfo->code = code; + return NULL; + } + + code = initQueriedTableSchemaInfo(pHandle, &pScanNode->scan, dbname, pTaskInfo); + if (code != TSDB_CODE_SUCCESS) { + pTaskInfo->code = code; + return NULL; + } + + pOperator = createCacherowsScanOperator(pScanNode, pHandle, pTableListInfo, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_PROJECT == type) { + pOperator = createProjectOperatorInfo(NULL, (SProjectPhysiNode*)pPhyNode, pTaskInfo); + } else { + terrno = TSDB_CODE_INVALID_PARA; + return NULL; + } + + if (pOperator != NULL) { // todo moved away + pOperator->resultDataBlockId = pPhyNode->pOutputDataBlockDesc->dataBlockId; + } + + return pOperator; + } + + size_t size = LIST_LENGTH(pPhyNode->pChildren); + SOperatorInfo** ops = taosMemoryCalloc(size, POINTER_BYTES); + if (ops == NULL) { + return NULL; + } + + for (int32_t i = 0; i < size; ++i) { + SPhysiNode* pChildNode = (SPhysiNode*)nodesListGetNode(pPhyNode->pChildren, i); + ops[i] = createOperator(pChildNode, pTaskInfo, pHandle, pTagCond, pTagIndexCond, pUser, dbname); + if (ops[i] == NULL) { + taosMemoryFree(ops); + return NULL; + } + } + + SOperatorInfo* pOptr = NULL; + if (QUERY_NODE_PHYSICAL_PLAN_PROJECT == type) { + pOptr = createProjectOperatorInfo(ops[0], (SProjectPhysiNode*)pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_HASH_AGG == type) { + SAggPhysiNode* pAggNode = (SAggPhysiNode*)pPhyNode; + if (pAggNode->pGroupKeys != NULL) { + pOptr = createGroupOperatorInfo(ops[0], pAggNode, pTaskInfo); + } else { + pOptr = createAggregateOperatorInfo(ops[0], pAggNode, pTaskInfo); + } + } else if (QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL == type) { + SIntervalPhysiNode* pIntervalPhyNode = (SIntervalPhysiNode*)pPhyNode; + pOptr = createIntervalOperatorInfo(ops[0], pIntervalPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL == type) { + pOptr = createStreamIntervalOperatorInfo(ops[0], pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL == type) { + SMergeAlignedIntervalPhysiNode* pIntervalPhyNode = (SMergeAlignedIntervalPhysiNode*)pPhyNode; + pOptr = createMergeAlignedIntervalOperatorInfo(ops[0], pIntervalPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL == type) { + SMergeIntervalPhysiNode* pIntervalPhyNode = (SMergeIntervalPhysiNode*)pPhyNode; + pOptr = createMergeIntervalOperatorInfo(ops[0], pIntervalPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL == type) { + int32_t children = 0; + pOptr = createStreamFinalIntervalOperatorInfo(ops[0], pPhyNode, pTaskInfo, children); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL == type) { + int32_t children = pHandle->numOfVgroups; + pOptr = createStreamFinalIntervalOperatorInfo(ops[0], pPhyNode, pTaskInfo, children); + } else if (QUERY_NODE_PHYSICAL_PLAN_SORT == type) { + pOptr = createSortOperatorInfo(ops[0], (SSortPhysiNode*)pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT == type) { + pOptr = createGroupSortOperatorInfo(ops[0], (SGroupSortPhysiNode*)pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE == type) { + SMergePhysiNode* pMergePhyNode = (SMergePhysiNode*)pPhyNode; + pOptr = createMultiwayMergeOperatorInfo(ops, size, pMergePhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION == type) { + SSessionWinodwPhysiNode* pSessionNode = (SSessionWinodwPhysiNode*)pPhyNode; + pOptr = createSessionAggOperatorInfo(ops[0], pSessionNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION == type) { + pOptr = createStreamSessionAggOperatorInfo(ops[0], pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION == type) { + int32_t children = 0; + pOptr = createStreamFinalSessionAggOperatorInfo(ops[0], pPhyNode, pTaskInfo, children); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION == type) { + int32_t children = pHandle->numOfVgroups; + pOptr = createStreamFinalSessionAggOperatorInfo(ops[0], pPhyNode, pTaskInfo, children); + } else if (QUERY_NODE_PHYSICAL_PLAN_PARTITION == type) { + pOptr = createPartitionOperatorInfo(ops[0], (SPartitionPhysiNode*)pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION == type) { + pOptr = createStreamPartitionOperatorInfo(ops[0], (SStreamPartitionPhysiNode*)pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE == type) { + SStateWinodwPhysiNode* pStateNode = (SStateWinodwPhysiNode*)pPhyNode; + pOptr = createStatewindowOperatorInfo(ops[0], pStateNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE == type) { + pOptr = createStreamStateAggOperatorInfo(ops[0], pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN == type) { + pOptr = createMergeJoinOperatorInfo(ops, size, (SSortMergeJoinPhysiNode*)pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_FILL == type) { + pOptr = createFillOperatorInfo(ops[0], (SFillPhysiNode*)pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_STREAM_FILL == type) { + pOptr = createStreamFillOperatorInfo(ops[0], (SStreamFillPhysiNode*)pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_INDEF_ROWS_FUNC == type) { + pOptr = createIndefinitOutputOperatorInfo(ops[0], pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC == type) { + pOptr = createTimeSliceOperatorInfo(ops[0], pPhyNode, pTaskInfo); + } else if (QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT == type) { + pOptr = createEventwindowOperatorInfo(ops[0], pPhyNode, pTaskInfo); + } else { + terrno = TSDB_CODE_INVALID_PARA; + taosMemoryFree(ops); + return NULL; + } + + taosMemoryFree(ops); + if (pOptr) { + pOptr->resultDataBlockId = pPhyNode->pOutputDataBlockDesc->dataBlockId; + } + + return pOptr; +} + +void destroyOperator(SOperatorInfo* pOperator) { + if (pOperator == NULL) { + return; + } + + if (pOperator->fpSet.closeFn != NULL) { + pOperator->fpSet.closeFn(pOperator->info); + } + + if (pOperator->pDownstream != NULL) { + for (int32_t i = 0; i < pOperator->numOfDownstream; ++i) { + destroyOperator(pOperator->pDownstream[i]); + } + + taosMemoryFreeClear(pOperator->pDownstream); + pOperator->numOfDownstream = 0; + } + + cleanupExprSupp(&pOperator->exprSupp); + taosMemoryFreeClear(pOperator); +} + +int32_t getOperatorExplainExecInfo(SOperatorInfo* operatorInfo, SArray* pExecInfoList) { + SExplainExecInfo execInfo = {0}; + SExplainExecInfo* pExplainInfo = taosArrayPush(pExecInfoList, &execInfo); + + pExplainInfo->numOfRows = operatorInfo->resultInfo.totalRows; + pExplainInfo->startupCost = operatorInfo->cost.openCost; + pExplainInfo->totalCost = operatorInfo->cost.totalCost; + pExplainInfo->verboseLen = 0; + pExplainInfo->verboseInfo = NULL; + + if (operatorInfo->fpSet.getExplainFn) { + int32_t code = + operatorInfo->fpSet.getExplainFn(operatorInfo, &pExplainInfo->verboseInfo, &pExplainInfo->verboseLen); + if (code) { + qError("%s operator getExplainFn failed, code:%s", GET_TASKID(operatorInfo->pTaskInfo), tstrerror(code)); + return code; + } + } + + int32_t code = 0; + for (int32_t i = 0; i < operatorInfo->numOfDownstream; ++i) { + code = getOperatorExplainExecInfo(operatorInfo->pDownstream[i], pExecInfoList); + if (code != TSDB_CODE_SUCCESS) { + // taosMemoryFreeClear(*pRes); + return TSDB_CODE_OUT_OF_MEMORY; + } + } + + return TSDB_CODE_SUCCESS; +} diff --git a/source/libs/executor/src/projectoperator.c b/source/libs/executor/src/projectoperator.c index 4a3a3f4de41a756f972547583bbb1ea186067c15..02f504bef03aaf4cff5d1193a2c23fd66b0b6146 100644 --- a/source/libs/executor/src/projectoperator.c +++ b/source/libs/executor/src/projectoperator.c @@ -13,9 +13,11 @@ * along with this program. If not, see . */ -#include "executorimpl.h" +#include "executorInt.h" #include "filter.h" #include "functionMgt.h" +#include "operator.h" +#include "querytask.h" typedef struct SProjectOperatorInfo { SOptrBasicInfo binfo; @@ -161,10 +163,9 @@ static int32_t discardGroupDataBlock(SSDataBlock* pBlock, SLimitInfo* pLimitInfo if (pLimitInfo->remainGroupOffset > 0) { return PROJECT_RETRIEVE_CONTINUE; } - } - // set current group id of the project operator - pLimitInfo->currentGroupId = pBlock->info.id.groupId; + pLimitInfo->currentGroupId = 0; + } } return PROJECT_RETRIEVE_DONE; @@ -175,19 +176,29 @@ static int32_t setInfoForNewGroup(SSDataBlock* pBlock, SLimitInfo* pLimitInfo, S // here check for a new group data, we need to handle the data of the previous group. ASSERT(pLimitInfo->remainGroupOffset == 0 || pLimitInfo->remainGroupOffset == -1); - if (pLimitInfo->currentGroupId != 0 && pLimitInfo->currentGroupId != pBlock->info.id.groupId) { + bool newGroup = false; + if (0 == pBlock->info.id.groupId) { + pLimitInfo->numOfOutputGroups = 1; + } else if (pLimitInfo->currentGroupId != pBlock->info.id.groupId) { + pLimitInfo->currentGroupId = pBlock->info.id.groupId; pLimitInfo->numOfOutputGroups += 1; - if ((pLimitInfo->slimit.limit > 0) && (pLimitInfo->slimit.limit <= pLimitInfo->numOfOutputGroups)) { - setOperatorCompleted(pOperator); - return PROJECT_RETRIEVE_DONE; - } + newGroup = true; + } else { + return PROJECT_RETRIEVE_CONTINUE; + } - // reset the value for a new group data - // existing rows that belongs to previous group. - resetLimitInfoForNextGroup(pLimitInfo); + if ((pLimitInfo->slimit.limit >= 0) && (pLimitInfo->slimit.limit < pLimitInfo->numOfOutputGroups)) { + setOperatorCompleted(pOperator); + return PROJECT_RETRIEVE_DONE; } - return PROJECT_RETRIEVE_DONE; + // reset the value for a new group data + // existing rows that belongs to previous group. + if (newGroup) { + resetLimitInfoForNextGroup(pLimitInfo); + } + + return PROJECT_RETRIEVE_CONTINUE; } // todo refactor @@ -199,7 +210,7 @@ static int32_t doIngroupLimitOffset(SLimitInfo* pLimitInfo, uint64_t groupId, SS if (pBlock->info.rows == 0) { return PROJECT_RETRIEVE_CONTINUE; } else { - if (limitReached && (pLimitInfo->slimit.limit > 0 && pLimitInfo->slimit.limit <= pLimitInfo->numOfOutputGroups)) { + if (limitReached && (pLimitInfo->slimit.limit >= 0 && pLimitInfo->slimit.limit <= pLimitInfo->numOfOutputGroups)) { setOperatorCompleted(pOperator); } } @@ -218,17 +229,8 @@ SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) { blockDataCleanup(pFinalRes); SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - if (pTaskInfo->streamInfo.pReq) { - pOperator->status = OP_OPENED; - } if (pOperator->status == OP_EXEC_DONE) { - if (pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE) { - pOperator->status = OP_OPENED; - qDebug("projection in queue model, set status open and return null"); - return NULL; - } - return NULL; } @@ -254,27 +256,18 @@ SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) { // The downstream exec may change the value of the newgroup, so use a local variable instead. SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); if (pBlock == NULL) { - if (pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE && pFinalRes->info.rows == 0) { - pOperator->status = OP_OPENED; - if (pOperator->status == OP_EXEC_RECV) { - continue; - } else { - return NULL; - } - } - qDebug("set op close, exec %d, status %d rows %d", pTaskInfo->execModel, pOperator->status, - pFinalRes->info.rows); + qDebug("set op close, exec %d, status %d rows %" PRId64 , pTaskInfo->execModel, pOperator->status, pFinalRes->info.rows); setOperatorCompleted(pOperator); break; } - if (pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE) { - qDebug("set status recv"); - pOperator->status = OP_EXEC_RECV; - } +// if (pTaskInfo->execModel == OPTR_EXEC_MODEL_QUEUE) { +// qDebug("set status recv"); +// pOperator->status = OP_EXEC_RECV; +// } // for stream interval if (pBlock->info.type == STREAM_RETRIEVE || pBlock->info.type == STREAM_DELETE_RESULT || - pBlock->info.type == STREAM_DELETE_DATA) { + pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_CREATE_CHILD_TABLE) { return pBlock; } @@ -289,7 +282,7 @@ SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) { } // the pDataBlock are always the same one, no need to call this again - int32_t code = getTableScanInfo(downstream, &order, &scanFlag); + int32_t code = getTableScanInfo(downstream, &order, &scanFlag, false); if (code != TSDB_CODE_SUCCESS) { T_LONG_JMP(pTaskInfo->env, code); } @@ -328,7 +321,7 @@ SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) { // when apply the limit/offset for each group, pRes->info.rows may be 0, due to limit constraint. if (pFinalRes->info.rows > 0 || (pOperator->status == OP_EXEC_DONE)) { - qDebug("project return %d rows, status %d", pFinalRes->info.rows, pOperator->status); + qDebug("project return %" PRId64 " rows, status %d", pFinalRes->info.rows, pOperator->status); break; } } else { @@ -441,7 +434,7 @@ static void doHandleDataBlock(SOperatorInfo* pOperator, SSDataBlock* pBlock, SOp SExprSupp* pSup = &pOperator->exprSupp; // the pDataBlock are always the same one, no need to call this again - int32_t code = getTableScanInfo(downstream, &order, &scanFlag); + int32_t code = getTableScanInfo(downstream, &order, &scanFlag, false); if (code != TSDB_CODE_SUCCESS) { T_LONG_JMP(pTaskInfo->env, code); } @@ -580,7 +573,7 @@ void setFunctionResultOutput(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo, SA int64_t tid = 0; int64_t groupId = 0; SResultRow* pRow = doSetResultOutBufByKey(pSup->pResultBuf, pResultRowInfo, (char*)&tid, sizeof(tid), true, groupId, - pTaskInfo, false, pSup); + pTaskInfo, false, pSup, true); for (int32_t i = 0; i < numOfExprs; ++i) { struct SResultRowEntryInfo* pEntry = getResultEntryInfo(pRow, i, rowEntryInfoOffset); @@ -623,9 +616,9 @@ SSDataBlock* doGenerateSourceData(SOperatorInfo* pOperator) { int32_t type = pExpr[k].base.pParam[0].param.nType; if (TSDB_DATA_TYPE_NULL == type) { - colDataAppendNNULL(pColInfoData, 0, 1); + colDataSetNNULL(pColInfoData, 0, 1); } else { - colDataAppend(pColInfoData, 0, taosVariantGet(&pExpr[k].base.pParam[0].param, type), false); + colDataSetVal(pColInfoData, 0, taosVariantGet(&pExpr[k].base.pParam[0].param, type), false); } } @@ -665,9 +658,9 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc int32_t type = pExpr[k].base.pParam[0].param.nType; if (TSDB_DATA_TYPE_NULL == type) { - colDataAppendNNULL(pColInfoData, 0, 1); + colDataSetNNULL(pColInfoData, 0, 1); } else { - colDataAppend(pColInfoData, 0, taosVariantGet(&pExpr[k].base.pParam[0].param, type), false); + colDataSetVal(pColInfoData, 0, taosVariantGet(&pExpr[k].base.pParam[0].param, type), false); } } @@ -728,11 +721,11 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc int32_t type = pExpr[k].base.pParam[0].param.nType; if (TSDB_DATA_TYPE_NULL == type) { - colDataAppendNNULL(pColInfoData, offset, pSrcBlock->info.rows); + colDataSetNNULL(pColInfoData, offset, pSrcBlock->info.rows); } else { char* p = taosVariantGet(&pExpr[k].base.pParam[0].param, type); for (int32_t i = 0; i < pSrcBlock->info.rows; ++i) { - colDataAppend(pColInfoData, i + offset, p, false); + colDataSetVal(pColInfoData, i + offset, p, false); } } @@ -800,10 +793,10 @@ int32_t projectApplyFunctions(SExprInfo* pExpr, SSDataBlock* pResult, SSDataBloc for (int32_t f = 0; f < pSrcBlock->info.rows; ++f) { bool isNull = colDataIsNull_s(pInput, f); if (isNull) { - colDataAppendNULL(pOutput, pResult->info.rows + f); + colDataSetNULL(pOutput, pResult->info.rows + f); } else { char* data = colDataGetData(pInput, f); - colDataAppend(pOutput, pResult->info.rows + f, data, isNull); + colDataSetVal(pOutput, pResult->info.rows + f, data, isNull); } } diff --git a/source/libs/executor/src/querytask.c b/source/libs/executor/src/querytask.c new file mode 100644 index 0000000000000000000000000000000000000000..7716b5976b2fd37fd3486abc2fd9fc125e5a87c7 --- /dev/null +++ b/source/libs/executor/src/querytask.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "filter.h" +#include "function.h" +#include "functionMgt.h" +#include "os.h" +#include "querynodes.h" +#include "tfill.h" +#include "tname.h" + +#include "tdatablock.h" +#include "tmsg.h" + +#include "executorInt.h" +#include "index.h" +#include "operator.h" +#include "query.h" +#include "querytask.h" +#include "thash.h" +#include "ttypes.h" +#include "vnode.h" + +#define CLEAR_QUERY_STATUS(q, st) ((q)->status &= (~(st))) + +SExecTaskInfo* doCreateTask(uint64_t queryId, uint64_t taskId, int32_t vgId, EOPTR_EXEC_MODEL model) { + SExecTaskInfo* pTaskInfo = taosMemoryCalloc(1, sizeof(SExecTaskInfo)); + if (pTaskInfo == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } + + setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED); + pTaskInfo->cost.created = taosGetTimestampUs(); + + pTaskInfo->execModel = model; + pTaskInfo->stopInfo.pStopInfo = taosArrayInit(4, sizeof(SExchangeOpStopInfo)); + pTaskInfo->pResultBlockList = taosArrayInit(128, POINTER_BYTES); + + taosInitRWLatch(&pTaskInfo->lock); + + pTaskInfo->id.vgId = vgId; + pTaskInfo->id.queryId = queryId; + pTaskInfo->id.str = taosMemoryMalloc(64); + buildTaskId(taskId, queryId, pTaskInfo->id.str); + + return pTaskInfo; +} + +bool isTaskKilled(SExecTaskInfo* pTaskInfo) { return (0 != pTaskInfo->code); } + +void setTaskKilled(SExecTaskInfo* pTaskInfo, int32_t rspCode) { + pTaskInfo->code = rspCode; + stopTableScanOperator(pTaskInfo->pRoot, pTaskInfo->id.str); +} + +void setTaskStatus(SExecTaskInfo* pTaskInfo, int8_t status) { + if (status == TASK_NOT_COMPLETED) { + pTaskInfo->status = status; + } else { + // QUERY_NOT_COMPLETED is not compatible with any other status, so clear its position first + CLEAR_QUERY_STATUS(pTaskInfo, TASK_NOT_COMPLETED); + pTaskInfo->status |= status; + } +} + +int32_t createExecTaskInfo(SSubplan* pPlan, SExecTaskInfo** pTaskInfo, SReadHandle* pHandle, uint64_t taskId, + int32_t vgId, char* sql, EOPTR_EXEC_MODEL model) { + *pTaskInfo = doCreateTask(pPlan->id.queryId, taskId, vgId, model); + if (*pTaskInfo == NULL) { + taosMemoryFree(sql); + return terrno; + } + + if (pHandle) { + if (pHandle->pStateBackend) { + (*pTaskInfo)->streamInfo.pState = pHandle->pStateBackend; + } + } + + TSWAP((*pTaskInfo)->sql, sql); + + (*pTaskInfo)->pSubplan = pPlan; + (*pTaskInfo)->pRoot = createOperator(pPlan->pNode, *pTaskInfo, pHandle, pPlan->pTagCond, pPlan->pTagIndexCond, + pPlan->user, pPlan->dbFName); + + if (NULL == (*pTaskInfo)->pRoot) { + int32_t code = (*pTaskInfo)->code; + doDestroyTask(*pTaskInfo); + (*pTaskInfo) = NULL; + return code; + } else { + return TSDB_CODE_SUCCESS; + } +} + +void cleanupQueriedTableScanInfo(SSchemaInfo* pSchemaInfo) { + taosMemoryFreeClear(pSchemaInfo->dbname); + taosMemoryFreeClear(pSchemaInfo->tablename); + tDeleteSchemaWrapper(pSchemaInfo->sw); + tDeleteSchemaWrapper(pSchemaInfo->qsw); +} + +int32_t initQueriedTableSchemaInfo(SReadHandle* pHandle, SScanPhysiNode* pScanNode, const char* dbName, SExecTaskInfo* pTaskInfo) { + SMetaReader mr = {0}; + if (pHandle == NULL) { + terrno = TSDB_CODE_INVALID_PARA; + return terrno; + } + + metaReaderInit(&mr, pHandle->meta, 0); + int32_t code = metaGetTableEntryByUidCache(&mr, pScanNode->uid); + if (code != TSDB_CODE_SUCCESS) { + qError("failed to get the table meta, uid:0x%" PRIx64 ", suid:0x%" PRIx64 ", %s", pScanNode->uid, pScanNode->suid, + GET_TASKID(pTaskInfo)); + + metaReaderClear(&mr); + return terrno; + } + + SSchemaInfo* pSchemaInfo = &pTaskInfo->schemaInfo; + + pSchemaInfo->tablename = taosStrdup(mr.me.name); + pSchemaInfo->dbname = taosStrdup(dbName); + + if (mr.me.type == TSDB_SUPER_TABLE) { + pSchemaInfo->sw = tCloneSSchemaWrapper(&mr.me.stbEntry.schemaRow); + pSchemaInfo->tversion = mr.me.stbEntry.schemaTag.version; + } else if (mr.me.type == TSDB_CHILD_TABLE) { + tDecoderClear(&mr.coder); + + tb_uid_t suid = mr.me.ctbEntry.suid; + code = metaGetTableEntryByUidCache(&mr, suid); + if (code != TSDB_CODE_SUCCESS) { + metaReaderClear(&mr); + return terrno; + } + + pSchemaInfo->sw = tCloneSSchemaWrapper(&mr.me.stbEntry.schemaRow); + pSchemaInfo->tversion = mr.me.stbEntry.schemaTag.version; + } else { + pSchemaInfo->sw = tCloneSSchemaWrapper(&mr.me.ntbEntry.schemaRow); + } + + metaReaderClear(&mr); + + pSchemaInfo->qsw = extractQueriedColumnSchema(pScanNode); + return TSDB_CODE_SUCCESS; +} + +SSchemaWrapper* extractQueriedColumnSchema(SScanPhysiNode* pScanNode) { + int32_t numOfCols = LIST_LENGTH(pScanNode->pScanCols); + int32_t numOfTags = LIST_LENGTH(pScanNode->pScanPseudoCols); + + SSchemaWrapper* pqSw = taosMemoryCalloc(1, sizeof(SSchemaWrapper)); + pqSw->pSchema = taosMemoryCalloc(numOfCols + numOfTags, sizeof(SSchema)); + + for (int32_t i = 0; i < numOfCols; ++i) { + STargetNode* pNode = (STargetNode*)nodesListGetNode(pScanNode->pScanCols, i); + SColumnNode* pColNode = (SColumnNode*)pNode->pExpr; + + SSchema* pSchema = &pqSw->pSchema[pqSw->nCols++]; + pSchema->colId = pColNode->colId; + pSchema->type = pColNode->node.resType.type; + pSchema->bytes = pColNode->node.resType.bytes; + tstrncpy(pSchema->name, pColNode->colName, tListLen(pSchema->name)); + } + + // this the tags and pseudo function columns, we only keep the tag columns + for (int32_t i = 0; i < numOfTags; ++i) { + STargetNode* pNode = (STargetNode*)nodesListGetNode(pScanNode->pScanPseudoCols, i); + + int32_t type = nodeType(pNode->pExpr); + if (type == QUERY_NODE_COLUMN) { + SColumnNode* pColNode = (SColumnNode*)pNode->pExpr; + + SSchema* pSchema = &pqSw->pSchema[pqSw->nCols++]; + pSchema->colId = pColNode->colId; + pSchema->type = pColNode->node.resType.type; + pSchema->bytes = pColNode->node.resType.bytes; + tstrncpy(pSchema->name, pColNode->colName, tListLen(pSchema->name)); + } + } + + return pqSw; +} + +static void cleanupStreamInfo(SStreamTaskInfo* pStreamInfo) { tDeleteSchemaWrapper(pStreamInfo->schema); } + +static void freeBlock(void* pParam) { + SSDataBlock* pBlock = *(SSDataBlock**)pParam; + blockDataDestroy(pBlock); +} + +void doDestroyTask(SExecTaskInfo* pTaskInfo) { + qDebug("%s execTask is freed", GET_TASKID(pTaskInfo)); + destroyOperator(pTaskInfo->pRoot); + pTaskInfo->pRoot = NULL; + + cleanupQueriedTableScanInfo(&pTaskInfo->schemaInfo); + cleanupStreamInfo(&pTaskInfo->streamInfo); + + if (!pTaskInfo->localFetch.localExec) { + nodesDestroyNode((SNode*)pTaskInfo->pSubplan); + pTaskInfo->pSubplan = NULL; + } + + taosArrayDestroyEx(pTaskInfo->pResultBlockList, freeBlock); + taosArrayDestroy(pTaskInfo->stopInfo.pStopInfo); + taosMemoryFreeClear(pTaskInfo->sql); + taosMemoryFreeClear(pTaskInfo->id.str); + taosMemoryFreeClear(pTaskInfo); +} + +void buildTaskId(uint64_t taskId, uint64_t queryId, char* dst) { + char* p = dst; + + int32_t offset = 6; + memcpy(p, "TID:0x", offset); + offset += tintToHex(taskId, &p[offset]); + + memcpy(&p[offset], " QID:0x", 7); + offset += 7; + offset += tintToHex(queryId, &p[offset]); + + p[offset] = 0; +} diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c index c83c161326fe881c66ccdcb07c3ac5001456a6e5..f98419f768a8b4d29e8ee94d06630337cff37b9b 100644 --- a/source/libs/executor/src/scanoperator.c +++ b/source/libs/executor/src/scanoperator.c @@ -13,7 +13,7 @@ * along with this program. If not, see . */ -#include "executorimpl.h" +#include "executorInt.h" #include "filter.h" #include "function.h" #include "functionMgt.h" @@ -30,7 +30,12 @@ #include "tcompare.h" #include "thash.h" #include "ttypes.h" +#include "operator.h" +#include "querytask.h" +int32_t scanDebug = 0; + +#define MULTI_READER_MAX_TABLE_NUM 5000 #define SET_REVERSE_SCAN_FLAG(_info) ((_info)->scanFlag = REVERSE_SCAN) #define SWITCH_ORDER(n) (((n) = ((n) == TSDB_ORDER_ASC) ? TSDB_ORDER_DESC : TSDB_ORDER_ASC)) @@ -44,8 +49,20 @@ typedef struct STableMergeScanSortSourceParam { int32_t readerIdx; uint64_t uid; SSDataBlock* inputBlock; + bool multiReader; + STsdbReader* dataReader; } STableMergeScanSortSourceParam; +typedef struct STableCountScanOperatorInfo { + SReadHandle readHandle; + SSDataBlock* pRes; + + STableCountScanSupp supp; + + int32_t currGrpIdx; + SArray* stbUidList; // when group by db_name and/or stable_name +} STableCountScanOperatorInfo; + static bool processBlockWithProbability(const SSampleExecInfo* pInfo); bool processBlockWithProbability(const SSampleExecInfo* pInfo) { @@ -108,7 +125,7 @@ static bool overlapWithTimeWindow(SInterval* pInterval, SDataBlockInfo* pBlockIn break; } - assert(w.skey < pBlockInfo->window.skey); + ASSERT(w.skey < pBlockInfo->window.skey); if (pBlockInfo->window.skey <= TMIN(w.ekey, pBlockInfo->window.ekey)) { return true; } @@ -144,8 +161,23 @@ static SResultRow* getTableGroupOutputBuf(SOperatorInfo* pOperator, uint64_t gro return (SResultRow*)((char*)(*pPage) + p1->offset); } +static int32_t insertTableToScanIgnoreList(STableScanInfo* pTableScanInfo, uint64_t uid) { + if (NULL == pTableScanInfo->pIgnoreTables) { + int32_t tableNum = taosArrayGetSize(pTableScanInfo->base.pTableListInfo->pTableList); + pTableScanInfo->pIgnoreTables = taosHashInit(tableNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK); + if (NULL == pTableScanInfo->pIgnoreTables) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } + + taosHashPut(pTableScanInfo->pIgnoreTables, &uid, sizeof(uid), &pTableScanInfo->scanTimes, sizeof(pTableScanInfo->scanTimes)); + + return TSDB_CODE_SUCCESS; +} + static int32_t doDynamicPruneDataBlock(SOperatorInfo* pOperator, SDataBlockInfo* pBlockInfo, uint32_t* status) { STableScanInfo* pTableScanInfo = pOperator->info; + int32_t code = TSDB_CODE_SUCCESS; if (pTableScanInfo->base.pdInfo.pExprSup == NULL) { return TSDB_CODE_SUCCESS; @@ -178,9 +210,10 @@ static int32_t doDynamicPruneDataBlock(SOperatorInfo* pOperator, SDataBlockInfo* if (notLoadBlock) { *status = FUNC_DATA_REQUIRED_NOT_LOAD; + code = insertTableToScanIgnoreList(pTableScanInfo, pBlockInfo->id.uid); } - return TSDB_CODE_SUCCESS; + return code; } static bool doFilterByBlockSMA(SFilterInfo* pFilterInfo, SColumnDataAgg** pColsAgg, int32_t numOfCols, @@ -234,7 +267,7 @@ bool applyLimitOffset(SLimitInfo* pLimitInfo, SSDataBlock* pBlock, SExecTaskInfo qDebug("current block ignore due to offset, current:%" PRId64 ", %s", pLimitInfo->remainOffset, id); return false; } else { - blockDataTrimFirstNRows(pBlock, pLimitInfo->remainOffset); + blockDataTrimFirstRows(pBlock, pLimitInfo->remainOffset); pLimitInfo->remainOffset = 0; } } @@ -272,25 +305,29 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableSca taosMemoryFreeClear(pBlock->pBlockAgg); if (*status == FUNC_DATA_REQUIRED_FILTEROUT) { - qDebug("%s data block filter out, brange:%" PRId64 "-%" PRId64 ", rows:%d", GET_TASKID(pTaskInfo), + qDebug("%s data block filter out, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64, GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); pCost->filterOutBlocks += 1; pCost->totalRows += pBlock->info.rows; + tsdbReleaseDataBlock(pTableScanInfo->dataReader); return TSDB_CODE_SUCCESS; } else if (*status == FUNC_DATA_REQUIRED_NOT_LOAD) { - qDebug("%s data block skipped, brange:%" PRId64 "-%" PRId64 ", rows:%d, uid:%"PRIu64, GET_TASKID(pTaskInfo), - pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, pBlockInfo->id.uid); - doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, 1); + qDebug("%s data block skipped, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64 ", uid:%" PRIu64, + GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, + pBlockInfo->id.uid); + doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, pBlock->info.rows); pCost->skipBlocks += 1; + tsdbReleaseDataBlock(pTableScanInfo->dataReader); return TSDB_CODE_SUCCESS; } else if (*status == FUNC_DATA_REQUIRED_SMA_LOAD) { pCost->loadBlockStatis += 1; loadSMA = true; // mark the operation of load sma; bool success = doLoadBlockSMA(pTableScanInfo, pBlock, pTaskInfo); if (success) { // failed to load the block sma data, data block statistics does not exist, load data block instead - qDebug("%s data block SMA loaded, brange:%" PRId64 "-%" PRId64 ", rows:%d", GET_TASKID(pTaskInfo), + qDebug("%s data block SMA loaded, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64, GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); - doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, 1); + doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, pBlock->info.rows); + tsdbReleaseDataBlock(pTableScanInfo->dataReader); return TSDB_CODE_SUCCESS; } else { qDebug("%s failed to load SMA, since not all columns have SMA", GET_TASKID(pTaskInfo)); @@ -307,11 +344,12 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableSca size_t size = taosArrayGetSize(pBlock->pDataBlock); bool keep = doFilterByBlockSMA(pOperator->exprSupp.pFilterInfo, pBlock->pBlockAgg, size, pBlockInfo->rows); if (!keep) { - qDebug("%s data block filter out by block SMA, brange:%" PRId64 "-%" PRId64 ", rows:%d", GET_TASKID(pTaskInfo), - pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); + qDebug("%s data block filter out by block SMA, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64, + GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); pCost->filterOutBlocks += 1; (*status) = FUNC_DATA_REQUIRED_FILTEROUT; + tsdbReleaseDataBlock(pTableScanInfo->dataReader); return TSDB_CODE_SUCCESS; } } @@ -323,11 +361,17 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableSca // try to filter data block according to current results doDynamicPruneDataBlock(pOperator, pBlockInfo, status); if (*status == FUNC_DATA_REQUIRED_NOT_LOAD) { - qDebug("%s data block skipped due to dynamic prune, brange:%" PRId64 "-%" PRId64 ", rows:%d", GET_TASKID(pTaskInfo), - pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); + qDebug("%s data block skipped due to dynamic prune, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64, + GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows); pCost->skipBlocks += 1; + tsdbReleaseDataBlock(pTableScanInfo->dataReader); - *status = FUNC_DATA_REQUIRED_FILTEROUT; + STableScanInfo* pTableScanInfo = pOperator->info; + if (taosHashGetSize(pTableScanInfo->pIgnoreTables) == taosArrayGetSize(pTableScanInfo->base.pTableListInfo->pTableList)) { + *status = FUNC_DATA_REQUIRED_ALL_FILTEROUT; + } else { + *status = FUNC_DATA_REQUIRED_FILTEROUT; + } return TSDB_CODE_SUCCESS; } @@ -354,7 +398,7 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableSca if (pBlock->info.rows == 0) { pCost->filterOutBlocks += 1; - qDebug("%s data block filter out, brange:%" PRId64 "-%" PRId64 ", rows:%d, elapsed time:%.2f ms", + qDebug("%s data block filter out, brange:%" PRId64 "-%" PRId64 ", rows:%" PRId64 ", elapsed time:%.2f ms", GET_TASKID(pTaskInfo), pBlockInfo->window.skey, pBlockInfo->window.ekey, pBlockInfo->rows, el); } else { qDebug("%s data block filter applied, elapsed time:%.2f ms", GET_TASKID(pTaskInfo), el); @@ -362,7 +406,7 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableSca } bool limitReached = applyLimitOffset(&pTableScanInfo->limitInfo, pBlock, pTaskInfo); - if (limitReached) { // set operator flag is done + if (limitReached) { // set operator flag is done setOperatorCompleted(pOperator); } @@ -397,7 +441,7 @@ static void freeTableCachedVal(void* param) { static STableCachedVal* createTableCacheVal(const SMetaReader* pMetaReader) { STableCachedVal* pVal = taosMemoryMalloc(sizeof(STableCachedVal)); - pVal->pName = strdup(pMetaReader->me.name); + pVal->pName = taosStrdup(pMetaReader->me.name); pVal->pTags = NULL; // only child table has tag value @@ -413,13 +457,12 @@ static STableCachedVal* createTableCacheVal(const SMetaReader* pMetaReader) { // const void *key, size_t keyLen, void *value static void freeCachedMetaItem(const void* key, size_t keyLen, void* value) { freeTableCachedVal(value); } - static void doSetNullValue(SSDataBlock* pBlock, const SExprInfo* pExpr, int32_t numOfExpr) { for (int32_t j = 0; j < numOfExpr; ++j) { int32_t dstSlotId = pExpr[j].base.resSchema.slotId; SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, dstSlotId); - colDataAppendNNULL(pColInfoData, 0, pBlock->info.rows); + colDataSetNNULL(pColInfoData, 0, pBlock->info.rows); } } @@ -450,7 +493,6 @@ int32_t addTagPseudoColumnData(SReadHandle* pHandle, const SExprInfo* pExpr, int metaReaderInit(&mr, pHandle->meta, 0); code = metaGetTableEntryByUidCache(&mr, pBlock->info.id.uid); if (code != TSDB_CODE_SUCCESS) { - // when encounter the TSDB_CODE_PAR_TABLE_NOT_EXIST error, we proceed. if (terrno == TSDB_CODE_PAR_TABLE_NOT_EXIST) { qWarn("failed to get table meta, table may have been dropped, uid:0x%" PRIx64 ", code:%s, %s", @@ -544,15 +586,21 @@ int32_t addTagPseudoColumnData(SReadHandle* pHandle, const SExprInfo* pExpr, int bool isNullVal = (data == NULL) || (pColInfoData->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data)); if (isNullVal) { - colDataAppendNNULL(pColInfoData, 0, pBlock->info.rows); + colDataSetNNULL(pColInfoData, 0, pBlock->info.rows); } else if (pColInfoData->info.type != TSDB_DATA_TYPE_JSON) { - colDataAppendNItems(pColInfoData, 0, data, pBlock->info.rows); + code = colDataSetNItems(pColInfoData, 0, data, pBlock->info.rows, false); if (IS_VAR_DATA_TYPE(((const STagVal*)p)->type)) { taosMemoryFree(data); } + if (code) { + if (freeReader) { + metaReaderClear(&mr); + } + return code; + } } else { // todo opt for json tag for (int32_t i = 0; i < pBlock->info.rows; ++i) { - colDataAppend(pColInfoData, i, data, false); + colDataSetVal(pColInfoData, i, data, false); } } } @@ -578,7 +626,7 @@ void setTbNameColData(const SSDataBlock* pBlock, SColumnInfoData* pColInfoData, SColumnInfoData infoData = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, len, 1); colInfoDataEnsureCapacity(&infoData, 1, false); - colDataAppend(&infoData, 0, buf, false); + colDataSetVal(&infoData, 0, buf, false); SScalarParam srcParam = {.numOfRows = pBlock->info.rows, .columnData = &infoData}; SScalarParam param = {.columnData = pColInfoData}; @@ -596,15 +644,29 @@ static SSDataBlock* doTableScanImpl(SOperatorInfo* pOperator) { STableScanInfo* pTableScanInfo = pOperator->info; SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; SSDataBlock* pBlock = pTableScanInfo->pResBlock; + bool hasNext = false; + int32_t code = TSDB_CODE_SUCCESS; int64_t st = taosGetTimestampUs(); - while (tsdbNextDataBlock(pTableScanInfo->base.dataReader)) { + while (true) { + code = tsdbNextDataBlock(pTableScanInfo->base.dataReader, &hasNext); + if (code) { + tsdbReleaseDataBlock(pTableScanInfo->base.dataReader); + T_LONG_JMP(pTaskInfo->env, code); + } + + if (!hasNext) { + break; + } + if (isTaskKilled(pTaskInfo)) { + tsdbReleaseDataBlock(pTableScanInfo->base.dataReader); T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); } if (pOperator->status == OP_EXEC_DONE) { + tsdbReleaseDataBlock(pTableScanInfo->base.dataReader); break; } @@ -614,15 +676,20 @@ static SSDataBlock* doTableScanImpl(SOperatorInfo* pOperator) { continue; } - ASSERT(pBlock->info.id.uid != 0); - pBlock->info.id.groupId = getTableGroupId(pTaskInfo->pTableInfoList, pBlock->info.id.uid); + if (pBlock->info.id.uid) { + pBlock->info.id.groupId = getTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid); + } uint32_t status = 0; - int32_t code = loadDataBlock(pOperator, &pTableScanInfo->base, pBlock, &status); + code = loadDataBlock(pOperator, &pTableScanInfo->base, pBlock, &status); if (code != TSDB_CODE_SUCCESS) { T_LONG_JMP(pTaskInfo->env, code); } + if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) { + break; + } + // current block is filter out according to filter condition, continue load the next block if (status == FUNC_DATA_REQUIRED_FILTEROUT || pBlock->info.rows == 0) { continue; @@ -636,11 +703,10 @@ static SSDataBlock* doTableScanImpl(SOperatorInfo* pOperator) { // todo refactor /*pTableScanInfo->lastStatus.uid = pBlock->info.id.uid;*/ /*pTableScanInfo->lastStatus.ts = pBlock->info.window.ekey;*/ - pTaskInfo->streamInfo.lastStatus.type = TMQ_OFFSET__SNAPSHOT_DATA; - pTaskInfo->streamInfo.lastStatus.uid = pBlock->info.id.uid; - pTaskInfo->streamInfo.lastStatus.ts = pBlock->info.window.ekey; + // pTaskInfo->streamInfo.lastStatus.type = TMQ_OFFSET__SNAPSHOT_DATA; + // pTaskInfo->streamInfo.lastStatus.uid = pBlock->info.id.uid; + // pTaskInfo->streamInfo.lastStatus.ts = pBlock->info.window.ekey; - ASSERT(pBlock->info.id.uid != 0); return pBlock; } return NULL; @@ -663,10 +729,12 @@ static SSDataBlock* doGroupedTableScan(SOperatorInfo* pOperator) { } pTableScanInfo->scanTimes += 1; + taosHashClear(pTableScanInfo->pIgnoreTables); if (pTableScanInfo->scanTimes < pTableScanInfo->scanInfo.numOfAsc) { setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED); - pTableScanInfo->base.scanFlag = REPEAT_SCAN; + pTableScanInfo->base.scanFlag = MAIN_SCAN; + pTableScanInfo->base.dataBlockLoadFlag = FUNC_DATA_REQUIRED_DATA_LOAD; qDebug("start to repeat ascending order scan data blocks due to query func required, %s", GET_TASKID(pTaskInfo)); // do prepare for the next round table scan operation @@ -689,10 +757,11 @@ static SSDataBlock* doGroupedTableScan(SOperatorInfo* pOperator) { } pTableScanInfo->scanTimes += 1; + taosHashClear(pTableScanInfo->pIgnoreTables); if (pTableScanInfo->scanTimes < total) { setTaskStatus(pTaskInfo, TASK_NOT_COMPLETED); - pTableScanInfo->base.scanFlag = REPEAT_SCAN; + pTableScanInfo->base.scanFlag = MAIN_SCAN; qDebug("%s start to repeat descending order scan data blocks", GET_TASKID(pTaskInfo)); tsdbReaderReset(pTableScanInfo->base.dataReader, &pTableScanInfo->base.cond); @@ -709,42 +778,51 @@ static SSDataBlock* doTableScan(SOperatorInfo* pOperator) { // scan table one by one sequentially if (pInfo->scanMode == TABLE_SCAN__TABLE_ORDER) { - int32_t numOfTables = tableListGetSize(pTaskInfo->pTableInfoList); + int32_t numOfTables = 0; // tableListGetSize(pTaskInfo->pTableListInfo); + STableKeyInfo tInfo = {0}; while (1) { SSDataBlock* result = doGroupedTableScan(pOperator); - if (result) { + if (result || (pOperator->status == OP_EXEC_DONE) || isTaskKilled(pTaskInfo)) { return result; } // if no data, switch to next table and continue scan pInfo->currentTable++; + + taosRLockLatch(&pTaskInfo->lock); + numOfTables = tableListGetSize(pInfo->base.pTableListInfo); + if (pInfo->currentTable >= numOfTables) { + qDebug("all table checked in table list, total:%d, return NULL, %s", numOfTables, GET_TASKID(pTaskInfo)); + taosRUnLockLatch(&pTaskInfo->lock); return NULL; } - STableKeyInfo* pTableInfo = tableListGetInfo(pTaskInfo->pTableInfoList, pInfo->currentTable); - tsdbSetTableList(pInfo->base.dataReader, pTableInfo, 1); - qDebug("set uid:%" PRIu64 " into scanner, total tables:%d, index:%d %s", pTableInfo->uid, numOfTables, - pInfo->currentTable, pTaskInfo->id.str); + tInfo = *(STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->currentTable); + taosRUnLockLatch(&pTaskInfo->lock); + + tsdbSetTableList(pInfo->base.dataReader, &tInfo, 1); + qDebug("set uid:%" PRIu64 " into scanner, total tables:%d, index:%d/%d %s", tInfo.uid, numOfTables, + pInfo->currentTable, numOfTables, GET_TASKID(pTaskInfo)); tsdbReaderReset(pInfo->base.dataReader, &pInfo->base.cond); pInfo->scanTimes = 0; } } else { // scan table group by group sequentially if (pInfo->currentGroupId == -1) { - if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pTaskInfo->pTableInfoList)) { + if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pInfo->base.pTableListInfo)) { setOperatorCompleted(pOperator); return NULL; } int32_t num = 0; STableKeyInfo* pList = NULL; - tableListGetGroupList(pTaskInfo->pTableInfoList, pInfo->currentGroupId, &pList, &num); + tableListGetGroupList(pInfo->base.pTableListInfo, pInfo->currentGroupId, &pList, &num); ASSERT(pInfo->base.dataReader == NULL); int32_t code = tsdbReaderOpen(pInfo->base.readHandle.vnode, &pInfo->base.cond, pList, num, pInfo->pResBlock, - (STsdbReader**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo)); + (STsdbReader**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), pInfo->countOnly, &pInfo->pIgnoreTables); if (code != TSDB_CODE_SUCCESS) { T_LONG_JMP(pTaskInfo->env, code); } @@ -756,11 +834,10 @@ static SSDataBlock* doTableScan(SOperatorInfo* pOperator) { SSDataBlock* result = doGroupedTableScan(pOperator); if (result != NULL) { - ASSERT(result->info.id.uid != 0); return result; } - if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pTaskInfo->pTableInfoList)) { + if ((++pInfo->currentGroupId) >= tableListGetOutputGroups(pInfo->base.pTableListInfo)) { setOperatorCompleted(pOperator); return NULL; } @@ -771,7 +848,7 @@ static SSDataBlock* doTableScan(SOperatorInfo* pOperator) { int32_t num = 0; STableKeyInfo* pList = NULL; - tableListGetGroupList(pTaskInfo->pTableInfoList, pInfo->currentGroupId, &pList, &num); + tableListGetGroupList(pInfo->base.pTableListInfo, pInfo->currentGroupId, &pList, &num); tsdbSetTableList(pInfo->base.dataReader, pList, num); tsdbReaderReset(pInfo->base.dataReader, &pInfo->base.cond); @@ -796,28 +873,36 @@ static int32_t getTableScannerExecInfo(struct SOperatorInfo* pOptr, void** pOptr return 0; } -static void destroyTableScanOperatorInfo(void* param) { - STableScanInfo* pTableScanInfo = (STableScanInfo*)param; - blockDataDestroy(pTableScanInfo->pResBlock); - cleanupQueryTableDataCond(&pTableScanInfo->base.cond); +static void destroyTableScanBase(STableScanBase* pBase) { + cleanupQueryTableDataCond(&pBase->cond); - tsdbReaderClose(pTableScanInfo->base.dataReader); - pTableScanInfo->base.dataReader = NULL; + tsdbReaderClose(pBase->dataReader); + pBase->dataReader = NULL; - if (pTableScanInfo->base.matchInfo.pList != NULL) { - taosArrayDestroy(pTableScanInfo->base.matchInfo.pList); + if (pBase->matchInfo.pList != NULL) { + taosArrayDestroy(pBase->matchInfo.pList); } - taosLRUCacheCleanup(pTableScanInfo->base.metaCache.pTableMetaEntryCache); - cleanupExprSupp(&pTableScanInfo->base.pseudoSup); + tableListDestroy(pBase->pTableListInfo); + taosLRUCacheCleanup(pBase->metaCache.pTableMetaEntryCache); + cleanupExprSupp(&pBase->pseudoSup); +} + +static void destroyTableScanOperatorInfo(void* param) { + STableScanInfo* pTableScanInfo = (STableScanInfo*)param; + blockDataDestroy(pTableScanInfo->pResBlock); + taosHashCleanup(pTableScanInfo->pIgnoreTables); + destroyTableScanBase(&pTableScanInfo->base); taosMemoryFreeClear(param); } SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle, - SExecTaskInfo* pTaskInfo) { + STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo) { + int32_t code = 0; STableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableScanInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { + code = TSDB_CODE_OUT_OF_MEMORY; goto _error; } @@ -825,7 +910,7 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc; int32_t numOfCols = 0; - int32_t code = + code = extractColMatchInfo(pScanNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID, &pInfo->base.matchInfo); if (code != TSDB_CODE_SUCCESS) { goto _error; @@ -844,8 +929,8 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, } pInfo->scanInfo = (SScanInfo){.numOfAsc = pTableScanNode->scanSeq[0], .numOfDesc = pTableScanNode->scanSeq[1]}; + pInfo->base.scanFlag = (pInfo->scanInfo.numOfAsc > 1) ? PRE_SCAN : MAIN_SCAN; - pInfo->base.scanFlag = MAIN_SCAN; pInfo->base.pdInfo.interval = extractIntervalInfo(pTableScanNode); pInfo->base.readHandle = *readHandle; pInfo->base.dataBlockLoadFlag = pTableScanNode->dataRequired; @@ -855,7 +940,7 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, initResultSizeInfo(&pOperator->resultInfo, 4096); pInfo->pResBlock = createDataBlockFromDescNode(pDescNode); -// blockDataEnsureCapacity(pInfo->pResBlock, pOperator->resultInfo.capacity); + // blockDataEnsureCapacity(pInfo->pResBlock, pOperator->resultInfo.capacity); code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); if (code != TSDB_CODE_SUCCESS) { @@ -870,12 +955,17 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, pTaskInfo); pOperator->exprSupp.numOfExprs = numOfCols; + pInfo->base.pTableListInfo = pTableListInfo; pInfo->base.metaCache.pTableMetaEntryCache = taosLRUCacheInit(1024 * 128, -1, .5); if (pInfo->base.metaCache.pTableMetaEntryCache == NULL) { code = terrno; goto _error; } + if (scanDebug) { + pInfo->countOnly = true; + } + taosLRUCacheSetStrictCapacity(pInfo->base.metaCache.pTableMetaEntryCache, false); pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableScan, NULL, destroyTableScanOperatorInfo, optrDefaultBufFn, getTableScannerExecInfo); @@ -907,7 +997,8 @@ SOperatorInfo* createTableSeqScanOperatorInfo(void* pReadHandle, SExecTaskInfo* return pOperator; } -static FORCE_INLINE void doClearBufferedBlocks(SStreamScanInfo* pInfo) { +FORCE_INLINE void doClearBufferedBlocks(SStreamScanInfo* pInfo) { + qDebug("clear buff blocks:%d", (int32_t)taosArrayGetSize(pInfo->pBlockLists)); taosArrayClear(pInfo->pBlockLists); pInfo->validBlockIndex = 0; } @@ -946,6 +1037,7 @@ void resetTableScanInfo(STableScanInfo* pTableScanInfo, STimeWindow* pWin) { pTableScanInfo->scanTimes = 0; pTableScanInfo->currentGroupId = -1; tsdbReaderClose(pTableScanInfo->base.dataReader); + qDebug("1"); pTableScanInfo->base.dataReader = NULL; } @@ -965,21 +1057,29 @@ static SSDataBlock* readPreVersionData(SOperatorInfo* pTableScanOp, uint64_t tbU SSDataBlock* pBlock = pTableScanInfo->pResBlock; STsdbReader* pReader = NULL; int32_t code = tsdbReaderOpen(pTableScanInfo->base.readHandle.vnode, &cond, &tblInfo, 1, pBlock, - (STsdbReader**)&pReader, GET_TASKID(pTaskInfo)); + (STsdbReader**)&pReader, GET_TASKID(pTaskInfo), false, NULL); + if (code != TSDB_CODE_SUCCESS) { + terrno = code; + T_LONG_JMP(pTaskInfo->env, code); + return NULL; + } + + bool hasNext = false; + code = tsdbNextDataBlock(pReader, &hasNext); if (code != TSDB_CODE_SUCCESS) { terrno = code; T_LONG_JMP(pTaskInfo->env, code); return NULL; } - if (tsdbNextDataBlock(pReader)) { + if (hasNext) { /*SSDataBlock* p = */ tsdbRetrieveDataBlock(pReader, NULL); doSetTagColumnData(&pTableScanInfo->base, pBlock, pTaskInfo, pBlock->info.rows); - pBlock->info.id.groupId = getTableGroupId(pTaskInfo->pTableInfoList, pBlock->info.id.uid); + pBlock->info.id.groupId = getTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid); } tsdbReaderClose(pReader); - qDebug("retrieve prev rows:%d, skey:%" PRId64 ", ekey:%" PRId64 " uid:%" PRIu64 ", max ver:%" PRId64 + qDebug("retrieve prev rows:%" PRId64 ", skey:%" PRId64 ", ekey:%" PRId64 " uid:%" PRIu64 ", max ver:%" PRId64 ", suid:%" PRIu64, pBlock->info.rows, startTs, endTs, tbUid, maxVersion, cond.suid); @@ -996,7 +1096,8 @@ static uint64_t getGroupIdByCol(SStreamScanInfo* pInfo, uint64_t uid, TSKEY ts, } static uint64_t getGroupIdByUid(SStreamScanInfo* pInfo, uint64_t uid) { - return getTableGroupId(pInfo->pTableScanOp->pTaskInfo->pTableInfoList, uid); + STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info; + return getTableGroupId(pTableScanInfo->base.pTableListInfo, uid); } static uint64_t getGroupIdByData(SStreamScanInfo* pInfo, uint64_t uid, TSKEY ts, int64_t maxVersion) { @@ -1104,6 +1205,7 @@ static SSDataBlock* doRangeScan(SStreamScanInfo* pInfo, SSDataBlock* pSDB, int32 pInfo->updateWin = (STimeWindow){.skey = INT64_MIN, .ekey = INT64_MAX}; STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info; tsdbReaderClose(pTableScanInfo->base.dataReader); + qDebug("2"); pTableScanInfo->base.dataReader = NULL; return NULL; } @@ -1123,7 +1225,7 @@ static SSDataBlock* doRangeScan(SStreamScanInfo* pInfo, SSDataBlock* pSDB, int32 SColumnInfoData* pDestCol = taosArrayGet(pResult->pDataBlock, j); bool isNull = colDataIsNull(pSrcCol, tmpBlock->info.rows, i, NULL); char* pSrcData = colDataGetData(pSrcCol, i); - colDataAppend(pDestCol, pResult->info.rows, pSrcData, isNull); + colDataSetVal(pDestCol, pResult->info.rows, pSrcData, isNull); } pResult->info.rows++; } @@ -1143,16 +1245,18 @@ static SSDataBlock* doRangeScan(SStreamScanInfo* pInfo, SSDataBlock* pSDB, int32 } static int32_t getPreSessionWindow(SStreamAggSupporter* pAggSup, TSKEY startTs, TSKEY endTs, uint64_t groupId, - SSessionKey* pKey) { + SSessionKey* pKey) { pKey->win.skey = startTs; pKey->win.ekey = endTs; pKey->groupId = groupId; - + SStreamStateCur* pCur = streamStateSessionSeekKeyCurrentPrev(pAggSup->pState, pKey); int32_t code = streamStateSessionGetKVByCur(pCur, pKey, NULL, 0); if (code != TSDB_CODE_SUCCESS) { SET_SESSION_WIN_KEY_INVALID(pKey); } + + taosMemoryFree(pCur); return code; } @@ -1191,21 +1295,21 @@ static int32_t generateSessionScanRange(SStreamScanInfo* pInfo, SSDataBlock* pSr } SSessionKey endWin = {0}; getCurSessionWindow(pInfo->windowSup.pStreamAggSup, endData[i], endData[i], groupId, &endWin); - if(IS_INVALID_SESSION_WIN_KEY(endWin)) { + if (IS_INVALID_SESSION_WIN_KEY(endWin)) { getPreSessionWindow(pInfo->windowSup.pStreamAggSup, endData[i], endData[i], groupId, &endWin); } if (IS_INVALID_SESSION_WIN_KEY(startWin)) { // window has been closed. - qError("generate session scan range failed. rang start:%" PRIx64 ", end:%" PRIx64 , startData[i], endData[i]); + qError("generate session scan range failed. rang start:%" PRIx64 ", end:%" PRIx64, startData[i], endData[i]); continue; } - colDataAppend(pDestStartCol, i, (const char*)&startWin.win.skey, false); - colDataAppend(pDestEndCol, i, (const char*)&endWin.win.ekey, false); + colDataSetVal(pDestStartCol, i, (const char*)&startWin.win.skey, false); + colDataSetVal(pDestEndCol, i, (const char*)&endWin.win.ekey, false); - colDataAppendNULL(pDestUidCol, i); - colDataAppend(pDestGpCol, i, (const char*)&groupId, false); - colDataAppendNULL(pDestCalStartTsCol, i); - colDataAppendNULL(pDestCalEndTsCol, i); + colDataSetNULL(pDestUidCol, i); + colDataSetVal(pDestGpCol, i, (const char*)&groupId, false); + colDataSetNULL(pDestCalStartTsCol, i); + colDataSetNULL(pDestCalEndTsCol, i); pDestBlock->info.rows++; } return TSDB_CODE_SUCCESS; @@ -1274,15 +1378,15 @@ static int32_t generateIntervalScanRange(SStreamScanInfo* pInfo, SSDataBlock* pS groupId = getGroupIdByData(pInfo, srcUid, srcStartTsCol[i], version); } TSKEY calStartTs = srcStartTsCol[i]; - colDataAppend(pCalStartTsCol, pDestBlock->info.rows, (const char*)(&calStartTs), false); + colDataSetVal(pCalStartTsCol, pDestBlock->info.rows, (const char*)(&calStartTs), false); STimeWindow win = getSlidingWindow(srcStartTsCol, srcEndTsCol, srcGp, &pInfo->interval, &pSrcBlock->info, &i, pInfo->partitionSup.needCalc); TSKEY calEndTs = srcStartTsCol[i - 1]; - colDataAppend(pCalEndTsCol, pDestBlock->info.rows, (const char*)(&calEndTs), false); - colDataAppend(pDeUidCol, pDestBlock->info.rows, (const char*)(&srcUid), false); - colDataAppend(pStartTsCol, pDestBlock->info.rows, (const char*)(&win.skey), false); - colDataAppend(pEndTsCol, pDestBlock->info.rows, (const char*)(&win.ekey), false); - colDataAppend(pGpCol, pDestBlock->info.rows, (const char*)(&groupId), false); + colDataSetVal(pCalEndTsCol, pDestBlock->info.rows, (const char*)(&calEndTs), false); + colDataSetVal(pDeUidCol, pDestBlock->info.rows, (const char*)(&srcUid), false); + colDataSetVal(pStartTsCol, pDestBlock->info.rows, (const char*)(&win.skey), false); + colDataSetVal(pEndTsCol, pDestBlock->info.rows, (const char*)(&win.ekey), false); + colDataSetVal(pGpCol, pDestBlock->info.rows, (const char*)(&groupId), false); pDestBlock->info.rows++; } return TSDB_CODE_SUCCESS; @@ -1346,52 +1450,46 @@ static int32_t generateScanRange(SStreamScanInfo* pInfo, SSDataBlock* pSrcBlock, return code; } -void calBlockTbName(SStreamScanInfo* pInfo, SSDataBlock* pBlock) { - SExprSupp* pTbNameCalSup = &pInfo->tbnameCalSup; +#if 0 +void calBlockTag(SStreamScanInfo* pInfo, SSDataBlock* pBlock) { + SExprSupp* pTagCalSup = &pInfo->tagCalSup; SStreamState* pState = pInfo->pStreamScanOp->pTaskInfo->streamInfo.pState; - if (pTbNameCalSup == NULL || pTbNameCalSup->numOfExprs == 0) return; + if (pTagCalSup == NULL || pTagCalSup->numOfExprs == 0) return; if (pBlock == NULL || pBlock->info.rows == 0) return; - void* tbname = NULL; - if (streamStateGetParName(pInfo->pStreamScanOp->pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, &tbname) < 0) { - pBlock->info.parTbName[0] = 0; - } else { - memcpy(pBlock->info.parTbName, tbname, TSDB_TABLE_NAME_LEN); - } - tdbFree(tbname); - - SSDataBlock* pSrcBlock = blockCopyOneRow(pBlock, 0); - ASSERT(pSrcBlock->info.rows == 1); - - SSDataBlock* pResBlock = createDataBlock(); - pResBlock->info.rowSize = VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN; - SColumnInfoData data = createColumnInfoData(TSDB_DATA_TYPE_VARCHAR, TSDB_TABLE_NAME_LEN, 0); - taosArrayPush(pResBlock->pDataBlock, &data); - blockDataEnsureCapacity(pResBlock, 1); - - projectApplyFunctions(pTbNameCalSup->pExprInfo, pResBlock, pSrcBlock, pTbNameCalSup->pCtx, 1, NULL); - ASSERT(pResBlock->info.rows == 1); - ASSERT(taosArrayGetSize(pResBlock->pDataBlock) == 1); - SColumnInfoData* pCol = taosArrayGet(pResBlock->pDataBlock, 0); - ASSERT(pCol->info.type == TSDB_DATA_TYPE_VARCHAR); - - void* pData = colDataGetData(pCol, 0); - // TODO check tbname validation - if (pData != (void*)-1 && pData != NULL) { - memset(pBlock->info.parTbName, 0, TSDB_TABLE_NAME_LEN); - int32_t len = TMIN(varDataLen(pData), TSDB_TABLE_NAME_LEN - 1); - memcpy(pBlock->info.parTbName, varDataVal(pData), len); - /*pBlock->info.parTbName[len + 1] = 0;*/ + void* tag = NULL; + int32_t tagLen = 0; + if (streamStateGetParTag(pState, pBlock->info.id.groupId, &tag, &tagLen) == 0) { + pBlock->info.tagLen = tagLen; + void* pTag = taosMemoryRealloc(pBlock->info.pTag, tagLen); + if (pTag == NULL) { + tdbFree(tag); + taosMemoryFree(pBlock->info.pTag); + pBlock->info.pTag = NULL; + pBlock->info.tagLen = 0; + return; + } + pBlock->info.pTag = pTag; + memcpy(pBlock->info.pTag, tag, tagLen); + tdbFree(tag); + return; } else { - pBlock->info.parTbName[0] = 0; + pBlock->info.pTag = NULL; } + tdbFree(tag); +} +#endif - if (pBlock->info.id.groupId && pBlock->info.parTbName[0]) { - streamStatePutParName(pState, pBlock->info.id.groupId, pBlock->info.parTbName); +static void calBlockTbName(SStreamScanInfo* pInfo, SSDataBlock* pBlock) { + SExprSupp* pTbNameCalSup = &pInfo->tbnameCalSup; + SStreamState* pState = pInfo->pStreamScanOp->pTaskInfo->streamInfo.pState; + blockDataCleanup(pInfo->pCreateTbRes); + if (pInfo->tbnameCalSup.numOfExprs == 0 && pInfo->tagCalSup.numOfExprs == 0) { + pBlock->info.parTbName[0] = 0; + } else { + appendCreateTableRow(pInfo->pStreamScanOp->pTaskInfo->streamInfo.pState, &pInfo->tbnameCalSup, &pInfo->tagCalSup, + pBlock->info.id.groupId, pBlock, 0, pInfo->pCreateTbRes); } - - blockDataDestroy(pSrcBlock); - blockDataDestroy(pResBlock); } void appendOneRowToStreamSpecialBlock(SSDataBlock* pBlock, TSKEY* pStartTs, TSKEY* pEndTs, uint64_t* pUid, @@ -1403,13 +1501,13 @@ void appendOneRowToStreamSpecialBlock(SSDataBlock* pBlock, TSKEY* pStartTs, TSKE SColumnInfoData* pCalStartCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX); SColumnInfoData* pCalEndCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX); SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX); - colDataAppend(pStartTsCol, pBlock->info.rows, (const char*)pStartTs, false); - colDataAppend(pEndTsCol, pBlock->info.rows, (const char*)pEndTs, false); - colDataAppend(pUidCol, pBlock->info.rows, (const char*)pUid, false); - colDataAppend(pGpCol, pBlock->info.rows, (const char*)pGp, false); - colDataAppend(pCalStartCol, pBlock->info.rows, (const char*)pStartTs, false); - colDataAppend(pCalEndCol, pBlock->info.rows, (const char*)pEndTs, false); - colDataAppend(pTableCol, pBlock->info.rows, (const char*)pTbName, pTbName == NULL); + colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)pStartTs, false); + colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)pEndTs, false); + colDataSetVal(pUidCol, pBlock->info.rows, (const char*)pUid, false); + colDataSetVal(pGpCol, pBlock->info.rows, (const char*)pGp, false); + colDataSetVal(pCalStartCol, pBlock->info.rows, (const char*)pStartTs, false); + colDataSetVal(pCalEndCol, pBlock->info.rows, (const char*)pEndTs, false); + colDataSetVal(pTableCol, pBlock->info.rows, (const char*)pTbName, pTbName == NULL); pBlock->info.rows++; } @@ -1427,7 +1525,7 @@ static void checkUpdateData(SStreamScanInfo* pInfo, bool invertible, SSDataBlock dumyInfo.cur.pageId = -1; bool isClosed = false; STimeWindow win = {.skey = INT64_MIN, .ekey = INT64_MAX}; - bool overDue = isOverdue(tsCol[rowId], &pInfo->twAggSup); + bool overDue = isOverdue(tsCol[rowId], &pInfo->twAggSup); if (pInfo->igExpired && overDue) { continue; } @@ -1473,7 +1571,8 @@ static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock pInfo->pRes->info.type = STREAM_NORMAL; pInfo->pRes->info.version = pBlock->info.version; - pInfo->pRes->info.id.groupId = getTableGroupId(pTaskInfo->pTableInfoList, pBlock->info.id.uid); + STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info; + pInfo->pRes->info.id.groupId = getTableGroupId(pTableScanInfo->base.pTableListInfo, pBlock->info.id.uid); // todo extract method for (int32_t i = 0; i < taosArrayGetSize(pInfo->matchInfo.pList); ++i) { @@ -1496,7 +1595,7 @@ static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock // the required column does not exists in submit block, let's set it to be all null value if (!colExists) { SColumnInfoData* pDst = taosArrayGet(pInfo->pRes->pDataBlock, pColMatchInfo->dstSlotId); - colDataAppendNNULL(pDst, 0, pBlockInfo->rows); + colDataSetNNULL(pDst, 0, pBlockInfo->rows); } } @@ -1520,7 +1619,7 @@ static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock pInfo->pRes->info.dataLoad = 1; blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex); - blockDataFreeRes((SSDataBlock*)pBlock); +// blockDataFreeRes((SSDataBlock*)pBlock); calBlockTbName(pInfo, pInfo->pRes); return 0; @@ -1529,112 +1628,86 @@ static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock static SSDataBlock* doQueueScan(SOperatorInfo* pOperator) { SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; SStreamScanInfo* pInfo = pOperator->info; + const char* id = GET_TASKID(pTaskInfo); - qDebug("queue scan called"); - - if (pTaskInfo->streamInfo.pReq != NULL) { - if (pInfo->tqReader->pMsg == NULL) { - pInfo->tqReader->pMsg = pTaskInfo->streamInfo.pReq; - const SSubmitReq* pSubmit = pInfo->tqReader->pMsg; - if (tqReaderSetDataMsg(pInfo->tqReader, pSubmit, 0) < 0) { - qError("submit msg messed up when initing stream submit block %p", pSubmit); - pInfo->tqReader->pMsg = NULL; - pTaskInfo->streamInfo.pReq = NULL; - ASSERT(0); + qDebug("start to exec queue scan, %s", id); + +#if 0 + if (pTaskInfo->streamInfo.submit.msgStr != NULL) { + if (pInfo->tqReader->msg.msgStr == NULL) { + SPackedData submit = pTaskInfo->streamInfo.submit; + if (tqReaderSetSubmitMsg(pInfo->tqReader, submit.msgStr, submit.msgLen, submit.ver) < 0) { + qError("submit msg messed up when initing stream submit block %p", submit.msgStr); + return NULL; } } blockDataCleanup(pInfo->pRes); SDataBlockInfo* pBlockInfo = &pInfo->pRes->info; - while (tqNextDataBlock(pInfo->tqReader)) { - SSDataBlock block = {0}; - - int32_t code = tqRetrieveDataBlock(&block, pInfo->tqReader); - - if (code != TSDB_CODE_SUCCESS || block.info.rows == 0) { + while (tqNextBlockImpl(pInfo->tqReader)) { + int32_t code = tqRetrieveDataBlock(pInfo->tqReader, NULL); + if (code != TSDB_CODE_SUCCESS || pInfo->tqReader->pResBlock->info.rows == 0) { continue; } - setBlockIntoRes(pInfo, &block, true); + setBlockIntoRes(pInfo, pInfo->tqReader->pResBlock, true); if (pBlockInfo->rows > 0) { return pInfo->pRes; } } - pInfo->tqReader->pMsg = NULL; - pTaskInfo->streamInfo.pReq = NULL; + pInfo->tqReader->msg = (SPackedData){0}; + pTaskInfo->streamInfo.submit = (SPackedData){0}; return NULL; } +#endif - if (pTaskInfo->streamInfo.prepareStatus.type == TMQ_OFFSET__SNAPSHOT_DATA) { + if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_DATA) { SSDataBlock* pResult = doTableScan(pInfo->pTableScanOp); if (pResult && pResult->info.rows > 0) { - qDebug("queue scan tsdb return %d rows", pResult->info.rows); - pTaskInfo->streamInfo.returned = 1; + qDebug("queue scan tsdb return %" PRId64 " rows min:%" PRId64 " max:%" PRId64 " wal curVersion:%" PRId64, + pResult->info.rows, pResult->info.window.skey, pResult->info.window.ekey, + pInfo->tqReader->pWalReader->curVersion); + tqOffsetResetToData(&pTaskInfo->streamInfo.currentOffset, pResult->info.id.uid, pResult->info.window.ekey); return pResult; - } else { - if (!pTaskInfo->streamInfo.returned) { - STableScanInfo* pTSInfo = pInfo->pTableScanOp->info; - tsdbReaderClose(pTSInfo->base.dataReader); - pTSInfo->base.dataReader = NULL; - tqOffsetResetToLog(&pTaskInfo->streamInfo.prepareStatus, pTaskInfo->streamInfo.snapshotVer); - qDebug("queue scan tsdb over, switch to wal ver %" PRId64 "", pTaskInfo->streamInfo.snapshotVer + 1); - if (tqSeekVer(pInfo->tqReader, pTaskInfo->streamInfo.snapshotVer + 1) < 0) { - tqOffsetResetToLog(&pTaskInfo->streamInfo.lastStatus, pTaskInfo->streamInfo.snapshotVer); - return NULL; - } - ASSERT(pInfo->tqReader->pWalReader->curVersion == pTaskInfo->streamInfo.snapshotVer + 1); - } else { - return NULL; - } } + STableScanInfo* pTSInfo = pInfo->pTableScanOp->info; + tsdbReaderClose(pTSInfo->base.dataReader); + pTSInfo->base.dataReader = NULL; + qDebug("queue scan tsdb over, switch to wal ver %" PRId64 "", pTaskInfo->streamInfo.snapshotVer + 1); + if (tqSeekVer(pInfo->tqReader, pTaskInfo->streamInfo.snapshotVer + 1, pTaskInfo->id.str) < 0) { + return NULL; + } + + tqOffsetResetToLog(&pTaskInfo->streamInfo.currentOffset, pTaskInfo->streamInfo.snapshotVer); } - if (pTaskInfo->streamInfo.prepareStatus.type == TMQ_OFFSET__LOG) { + if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__LOG) { + while (1) { - SFetchRet ret = {0}; - tqNextBlock(pInfo->tqReader, &ret); - if (ret.fetchType == FETCH_TYPE__DATA) { + int32_t type = tqNextBlockInWal(pInfo->tqReader); + SSDataBlock* pRes = pInfo->tqReader->pResBlock; + + // curVersion move to next, so currentOffset = curVersion - 1 + tqOffsetResetToLog(&pTaskInfo->streamInfo.currentOffset, pInfo->tqReader->pWalReader->curVersion - 1); + + if (type == FETCH_TYPE__DATA) { + qDebug("doQueueScan get data from log %" PRId64 " rows, version:%" PRId64, pRes->info.rows, + pTaskInfo->streamInfo.currentOffset.version); blockDataCleanup(pInfo->pRes); - if (setBlockIntoRes(pInfo, &ret.data, true) < 0) { - ASSERT(0); - } + setBlockIntoRes(pInfo, pRes, true); if (pInfo->pRes->info.rows > 0) { - pOperator->status = OP_EXEC_RECV; - qDebug("queue scan log return %d rows", pInfo->pRes->info.rows); return pInfo->pRes; } - } else if (ret.fetchType == FETCH_TYPE__META) { - ASSERT(0); - // pTaskInfo->streamInfo.lastStatus = ret.offset; - // pTaskInfo->streamInfo.metaBlk = ret.meta; - // return NULL; - } else if (ret.fetchType == FETCH_TYPE__NONE || - (ret.fetchType == FETCH_TYPE__SEP && pOperator->status == OP_EXEC_RECV)) { - pTaskInfo->streamInfo.lastStatus = ret.offset; - ASSERT(pTaskInfo->streamInfo.lastStatus.version >= pTaskInfo->streamInfo.prepareStatus.version); - ASSERT(pTaskInfo->streamInfo.lastStatus.version + 1 == pInfo->tqReader->pWalReader->curVersion); - char formatBuf[80]; - tFormatOffset(formatBuf, 80, &ret.offset); - qDebug("queue scan log return null, offset %s", formatBuf); - pOperator->status = OP_OPENED; + } else if (type == FETCH_TYPE__NONE) { + qDebug("doQueueScan get none from log, return, version:%" PRId64, pTaskInfo->streamInfo.currentOffset.version); return NULL; } } -#if 0 - } else if (pTaskInfo->streamInfo.prepareStatus.type == TMQ_OFFSET__SNAPSHOT_DATA) { - SSDataBlock* pResult = doTableScan(pInfo->pTableScanOp); - if (pResult && pResult->info.rows > 0) { - qDebug("stream scan tsdb return %d rows", pResult->info.rows); - return pResult; - } - qDebug("stream scan tsdb return null"); - return NULL; -#endif } else { - ASSERT(0); + qError("unexpected streamInfo prepare type: %d", pTaskInfo->streamInfo.currentOffset.type); return NULL; } } @@ -1657,13 +1730,13 @@ static int32_t filterDelBlockByUid(SSDataBlock* pDst, const SSDataBlock* pSrc, S int32_t j = 0; for (int32_t i = 0; i < rows; i++) { if (taosHashGet(pReader->tbIdHash, &uidCol[i], sizeof(uint64_t))) { - colDataAppend(pDstStartCol, j, (const char*)&startCol[i], false); - colDataAppend(pDstEndCol, j, (const char*)&endCol[i], false); - colDataAppend(pDstUidCol, j, (const char*)&uidCol[i], false); + colDataSetVal(pDstStartCol, j, (const char*)&startCol[i], false); + colDataSetVal(pDstEndCol, j, (const char*)&endCol[i], false); + colDataSetVal(pDstUidCol, j, (const char*)&uidCol[i], false); - colDataAppendNULL(taosArrayGet(pDst->pDataBlock, GROUPID_COLUMN_INDEX), j); - colDataAppendNULL(taosArrayGet(pDst->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX), j); - colDataAppendNULL(taosArrayGet(pDst->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX), j); + colDataSetNULL(taosArrayGet(pDst->pDataBlock, GROUPID_COLUMN_INDEX), j); + colDataSetNULL(taosArrayGet(pDst->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX), j); + colDataSetNULL(taosArrayGet(pDst->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX), j); j++; } } @@ -1687,7 +1760,25 @@ static void setBlockGroupIdByUid(SStreamScanInfo* pInfo, SSDataBlock* pBlock) { if (!pInfo->partitionSup.needCalc) { for (int32_t i = 0; i < rows; i++) { uint64_t groupId = getGroupIdByUid(pInfo, uidCol[i]); - colDataAppend(pGpCol, i, (const char*)&groupId, false); + colDataSetVal(pGpCol, i, (const char*)&groupId, false); + } + } +} + +static void doCheckUpdate(SStreamScanInfo* pInfo, TSKEY endKey, SSDataBlock* pBlock) { + if (pInfo->pUpdateInfo) { + checkUpdateData(pInfo, true, pBlock, true); + pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, endKey); + if (pInfo->pUpdateDataRes->info.rows > 0) { + pInfo->updateResIndex = 0; + if (pInfo->pUpdateDataRes->info.type == STREAM_CLEAR) { + pInfo->scanMode = STREAM_SCAN_FROM_UPDATERES; + } else if (pInfo->pUpdateDataRes->info.type == STREAM_INVERT) { + pInfo->scanMode = STREAM_SCAN_FROM_RES; + // return pInfo->pUpdateDataRes; + } else if (pInfo->pUpdateDataRes->info.type == STREAM_DELETE_DATA) { + pInfo->scanMode = STREAM_SCAN_FROM_DELETE_DATA; + } } } } @@ -1697,7 +1788,7 @@ static SSDataBlock* doStreamScan(SOperatorInfo* pOperator) { SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; SStreamScanInfo* pInfo = pOperator->info; - qDebug("stream scan called"); + qDebug("stream scan started, %s", GET_TASKID(pTaskInfo)); if (pTaskInfo->streamInfo.recoverStep == STREAM_RECOVER_STEP__PREPARE1 || pTaskInfo->streamInfo.recoverStep == STREAM_RECOVER_STEP__PREPARE2) { @@ -1706,47 +1797,102 @@ static SSDataBlock* doStreamScan(SOperatorInfo* pOperator) { if (pTaskInfo->streamInfo.recoverStep == STREAM_RECOVER_STEP__PREPARE1) { pTSInfo->base.cond.startVersion = 0; pTSInfo->base.cond.endVersion = pTaskInfo->streamInfo.fillHistoryVer1; - qDebug("stream recover step 1, from %" PRId64 " to %" PRId64, pTSInfo->base.cond.startVersion, + qDebug("stream recover step1, verRange:%" PRId64 " - %" PRId64, pTSInfo->base.cond.startVersion, pTSInfo->base.cond.endVersion); + pTaskInfo->streamInfo.recoverStep = STREAM_RECOVER_STEP__SCAN1; } else { pTSInfo->base.cond.startVersion = pTaskInfo->streamInfo.fillHistoryVer1 + 1; pTSInfo->base.cond.endVersion = pTaskInfo->streamInfo.fillHistoryVer2; - qDebug("stream recover step 2, from %" PRId64 " to %" PRId64, pTSInfo->base.cond.startVersion, + qDebug("stream recover step2, verRange:%" PRId64 " - %" PRId64, pTSInfo->base.cond.startVersion, pTSInfo->base.cond.endVersion); + pTaskInfo->streamInfo.recoverStep = STREAM_RECOVER_STEP__SCAN2; } /*resetTableScanInfo(pTSInfo, pWin);*/ tsdbReaderClose(pTSInfo->base.dataReader); + pTSInfo->base.dataReader = NULL; pInfo->pTableScanOp->status = OP_OPENED; pTSInfo->scanTimes = 0; pTSInfo->currentGroupId = -1; - pTaskInfo->streamInfo.recoverStep = STREAM_RECOVER_STEP__SCAN; pTaskInfo->streamInfo.recoverScanFinished = false; } - if (pTaskInfo->streamInfo.recoverStep == STREAM_RECOVER_STEP__SCAN) { + if (pTaskInfo->streamInfo.recoverStep == STREAM_RECOVER_STEP__SCAN1 || + pTaskInfo->streamInfo.recoverStep == STREAM_RECOVER_STEP__SCAN2) { if (pInfo->blockRecoverContiCnt > 100) { pInfo->blockRecoverTotCnt += pInfo->blockRecoverContiCnt; pInfo->blockRecoverContiCnt = 0; return NULL; } - SSDataBlock* pBlock = doTableScan(pInfo->pTableScanOp); - if (pBlock != NULL) { + + switch (pInfo->scanMode) { + case STREAM_SCAN_FROM_RES: { + pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE; + printDataBlock(pInfo->pRecoverRes, "scan recover"); + return pInfo->pRecoverRes; + } break; + case STREAM_SCAN_FROM_UPDATERES: { + generateScanRange(pInfo, pInfo->pUpdateDataRes, pInfo->pUpdateRes); + prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex); + pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RANGE; + printDataBlock(pInfo->pUpdateRes, "recover update"); + return pInfo->pUpdateRes; + } break; + case STREAM_SCAN_FROM_DELETE_DATA: { + generateScanRange(pInfo, pInfo->pUpdateDataRes, pInfo->pUpdateRes); + prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex); + pInfo->scanMode = STREAM_SCAN_FROM_DATAREADER_RANGE; + copyDataBlock(pInfo->pDeleteDataRes, pInfo->pUpdateRes); + pInfo->pDeleteDataRes->info.type = STREAM_DELETE_DATA; + printDataBlock(pInfo->pDeleteDataRes, "recover delete"); + return pInfo->pDeleteDataRes; + } break; + case STREAM_SCAN_FROM_DATAREADER_RANGE: { + SSDataBlock* pSDB = doRangeScan(pInfo, pInfo->pUpdateRes, pInfo->primaryTsIndex, &pInfo->updateResIndex); + if (pSDB) { + STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info; + uint64_t version = tsdbGetReaderMaxVersion(pTableScanInfo->base.dataReader); + updateInfoSetScanRange(pInfo->pUpdateInfo, &pTableScanInfo->base.cond.twindows, pInfo->groupId, version); + pSDB->info.type = pInfo->scanMode == STREAM_SCAN_FROM_DATAREADER_RANGE ? STREAM_NORMAL : STREAM_PULL_DATA; + checkUpdateData(pInfo, true, pSDB, false); + printDataBlock(pSDB, "scan recover update"); + calBlockTbName(pInfo, pSDB); + return pSDB; + } + blockDataCleanup(pInfo->pUpdateDataRes); + pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE; + } break; + default: + break; + } + + pInfo->pRecoverRes = doTableScan(pInfo->pTableScanOp); + if (pInfo->pRecoverRes != NULL) { pInfo->blockRecoverContiCnt++; - calBlockTbName(pInfo, pBlock); + calBlockTbName(pInfo, pInfo->pRecoverRes); if (pInfo->pUpdateInfo) { - TSKEY maxTs = updateInfoFillBlockData(pInfo->pUpdateInfo, pBlock, pInfo->primaryTsIndex); - pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs); + if (pTaskInfo->streamInfo.recoverStep == STREAM_RECOVER_STEP__SCAN1) { + TSKEY maxTs = updateInfoFillBlockData(pInfo->pUpdateInfo, pInfo->pRecoverRes, pInfo->primaryTsIndex); + pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs); + } else { + doCheckUpdate(pInfo, pInfo->pRecoverRes->info.window.ekey, pInfo->pRecoverRes); + } } - qDebug("stream recover scan get block, rows %d", pBlock->info.rows); - printDataBlock(pBlock, "scan recover"); - return pBlock; + if (pInfo->pCreateTbRes->info.rows > 0) { + pInfo->scanMode = STREAM_SCAN_FROM_RES; + printDataBlock(pInfo->pCreateTbRes, "recover createTbl"); + return pInfo->pCreateTbRes; + } + qDebug("stream recover scan get block, rows %" PRId64, pInfo->pRecoverRes->info.rows); + printDataBlock(pInfo->pRecoverRes, "scan recover"); + return pInfo->pRecoverRes; } pTaskInfo->streamInfo.recoverStep = STREAM_RECOVER_STEP__NONE; STableScanInfo* pTSInfo = pInfo->pTableScanOp->info; tsdbReaderClose(pTSInfo->base.dataReader); + pTSInfo->base.dataReader = NULL; pTSInfo->base.cond.startVersion = -1; @@ -1762,15 +1908,16 @@ FETCH_NEXT_BLOCK: if (pInfo->blockType == STREAM_INPUT__DATA_BLOCK) { if (pInfo->validBlockIndex >= total) { doClearBufferedBlocks(pInfo); - /*pOperator->status = OP_EXEC_DONE;*/ return NULL; } int32_t current = pInfo->validBlockIndex++; - SSDataBlock* pBlock = taosArrayGetP(pInfo->pBlockLists, current); - if (pBlock->info.id.groupId && pBlock->info.parTbName[0]) { + SPackedData* pPacked = taosArrayGet(pInfo->pBlockLists, current); + SSDataBlock* pBlock = pPacked->pDataBlock; + if (pBlock->info.parTbName[0]) { streamStatePutParName(pTaskInfo->streamInfo.pState, pBlock->info.id.groupId, pBlock->info.parTbName); } + // TODO move into scan pBlock->info.calWin.skey = INT64_MIN; pBlock->info.calWin.ekey = INT64_MAX; @@ -1843,9 +1990,14 @@ FETCH_NEXT_BLOCK: qDebug("scan mode %d", pInfo->scanMode); switch (pInfo->scanMode) { case STREAM_SCAN_FROM_RES: { - blockDataDestroy(pInfo->pUpdateRes); pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE; - return pInfo->pRes; + doCheckUpdate(pInfo, pInfo->pRes->info.window.ekey, pInfo->pRes); + doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); + pInfo->pRes->info.dataLoad = 1; + blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex); + if (pInfo->pRes->info.rows > 0) { + return pInfo->pRes; + } } break; case STREAM_SCAN_FROM_DELETE_DATA: { generateScanRange(pInfo, pInfo->pUpdateDataRes, pInfo->pUpdateRes); @@ -1866,7 +2018,7 @@ FETCH_NEXT_BLOCK: SSDataBlock* pSDB = doRangeScan(pInfo, pInfo->pUpdateRes, pInfo->primaryTsIndex, &pInfo->updateResIndex); if (pSDB) { STableScanInfo* pTableScanInfo = pInfo->pTableScanOp->info; - uint64_t version = getReaderMaxVersion(pTableScanInfo->base.dataReader); + uint64_t version = tsdbGetReaderMaxVersion(pTableScanInfo->base.dataReader); updateInfoSetScanRange(pInfo->pUpdateInfo, &pTableScanInfo->base.cond.twindows, pInfo->groupId, version); pSDB->info.type = pInfo->scanMode == STREAM_SCAN_FROM_DATAREADER_RANGE ? STREAM_NORMAL : STREAM_PULL_DATA; checkUpdateData(pInfo, true, pSDB, false); @@ -1888,6 +2040,7 @@ FETCH_NEXT_BLOCK: copyDataBlock(pInfo->pUpdateRes, pSup->pScanBlock); blockDataCleanup(pSup->pScanBlock); prepareRangeScan(pInfo, pInfo->pUpdateRes, &pInfo->updateResIndex); + pInfo->pUpdateRes->info.type = STREAM_DELETE_DATA; return pInfo->pUpdateRes; } @@ -1897,7 +2050,7 @@ FETCH_NEXT_BLOCK: NEXT_SUBMIT_BLK: while (1) { - if (pInfo->tqReader->pMsg == NULL) { + if (pInfo->tqReader->msg.msgStr == NULL) { if (pInfo->validBlockIndex >= totBlockNum) { updateInfoDestoryColseWinSBF(pInfo->pUpdateInfo); doClearBufferedBlocks(pInfo); @@ -1905,28 +2058,24 @@ FETCH_NEXT_BLOCK: return NULL; } - int32_t current = pInfo->validBlockIndex++; - SSubmitReq* pSubmit = taosArrayGetP(pInfo->pBlockLists, current); - if (tqReaderSetDataMsg(pInfo->tqReader, pSubmit, 0) < 0) { + int32_t current = pInfo->validBlockIndex++; + SPackedData* pSubmit = taosArrayGet(pInfo->pBlockLists, current); + if (tqReaderSetSubmitMsg(pInfo->tqReader, pSubmit->msgStr, pSubmit->msgLen, pSubmit->ver) < 0) { qError("submit msg messed up when initing stream submit block %p, current %d, total %d", pSubmit, current, totBlockNum); - pInfo->tqReader->pMsg = NULL; continue; } } blockDataCleanup(pInfo->pRes); - while (tqNextDataBlock(pInfo->tqReader)) { - SSDataBlock block = {0}; - - int32_t code = tqRetrieveDataBlock(&block, pInfo->tqReader); - - if (code != TSDB_CODE_SUCCESS || block.info.rows == 0) { + while (tqNextBlockImpl(pInfo->tqReader)) { + int32_t code = tqRetrieveDataBlock(pInfo->tqReader, NULL); + if (code != TSDB_CODE_SUCCESS || pInfo->tqReader->pResBlock->info.rows == 0) { continue; } - setBlockIntoRes(pInfo, &block, false); + setBlockIntoRes(pInfo, pInfo->tqReader->pResBlock, false); if (updateInfoIgnore(pInfo->pUpdateInfo, &pInfo->pRes->info.window, pInfo->pRes->info.id.groupId, pInfo->pRes->info.version)) { @@ -1935,22 +2084,12 @@ FETCH_NEXT_BLOCK: continue; } - if (pInfo->pUpdateInfo) { - checkUpdateData(pInfo, true, pInfo->pRes, true); - pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlockInfo->window.ekey); - if (pInfo->pUpdateDataRes->info.rows > 0) { - pInfo->updateResIndex = 0; - if (pInfo->pUpdateDataRes->info.type == STREAM_CLEAR) { - pInfo->scanMode = STREAM_SCAN_FROM_UPDATERES; - } else if (pInfo->pUpdateDataRes->info.type == STREAM_INVERT) { - pInfo->scanMode = STREAM_SCAN_FROM_RES; - return pInfo->pUpdateDataRes; - } else if (pInfo->pUpdateDataRes->info.type == STREAM_DELETE_DATA) { - pInfo->scanMode = STREAM_SCAN_FROM_DELETE_DATA; - } - } + if (pInfo->pCreateTbRes->info.rows > 0) { + pInfo->scanMode = STREAM_SCAN_FROM_RES; + return pInfo->pCreateTbRes; } + doCheckUpdate(pInfo, pBlockInfo->window.ekey, pInfo->pRes); doFilter(pInfo->pRes, pOperator->exprSupp.pFilterInfo, NULL); pInfo->pRes->info.dataLoad = 1; blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex); @@ -1962,18 +2101,15 @@ FETCH_NEXT_BLOCK: if (pBlockInfo->rows > 0 || pInfo->pUpdateDataRes->info.rows > 0) { break; } else { - pInfo->tqReader->pMsg = NULL; continue; } - /*blockDataCleanup(pInfo->pRes);*/ } // record the scan action. pInfo->numOfExec++; pOperator->resultInfo.totalRows += pBlockInfo->rows; - // printDataBlock(pInfo->pRes, "stream scan"); - qDebug("scan rows: %d", pBlockInfo->rows); + qDebug("scan rows: %" PRId64, pBlockInfo->rows); if (pBlockInfo->rows > 0) { return pInfo->pRes; } @@ -2006,44 +2142,50 @@ static SSDataBlock* doRawScan(SOperatorInfo* pOperator) { // NOTE: this operator does never check if current status is done or not SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; SStreamRawScanInfo* pInfo = pOperator->info; + int32_t code = TSDB_CODE_SUCCESS; pTaskInfo->streamInfo.metaRsp.metaRspLen = 0; // use metaRspLen !=0 to judge if data is meta pTaskInfo->streamInfo.metaRsp.metaRsp = NULL; qDebug("tmqsnap doRawScan called"); - if (pTaskInfo->streamInfo.prepareStatus.type == TMQ_OFFSET__SNAPSHOT_DATA) { - if (pInfo->dataReader && tsdbNextDataBlock(pInfo->dataReader)) { + if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_DATA) { + bool hasNext = false; + if (pInfo->dataReader) { + code = tsdbNextDataBlock(pInfo->dataReader, &hasNext); + if (code) { + tsdbReleaseDataBlock(pInfo->dataReader); + T_LONG_JMP(pTaskInfo->env, code); + } + } + + if (pInfo->dataReader && hasNext) { if (isTaskKilled(pTaskInfo)) { - longjmp(pTaskInfo->env, pTaskInfo->code); + tsdbReleaseDataBlock(pInfo->dataReader); + T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); } SSDataBlock* pBlock = tsdbRetrieveDataBlock(pInfo->dataReader, NULL); if (pBlock == NULL) { - longjmp(pTaskInfo->env, terrno); + T_LONG_JMP(pTaskInfo->env, terrno); } qDebug("tmqsnap doRawScan get data uid:%" PRId64 "", pBlock->info.id.uid); - pTaskInfo->streamInfo.lastStatus.type = TMQ_OFFSET__SNAPSHOT_DATA; - pTaskInfo->streamInfo.lastStatus.uid = pBlock->info.id.uid; - pTaskInfo->streamInfo.lastStatus.ts = pBlock->info.window.ekey; + tqOffsetResetToData(&pTaskInfo->streamInfo.currentOffset, pBlock->info.id.uid, pBlock->info.window.ekey); return pBlock; } SMetaTableInfo mtInfo = getUidfromSnapShot(pInfo->sContext); + STqOffsetVal offset = {0}; if (mtInfo.uid == 0) { // read snapshot done, change to get data from wal qDebug("tmqsnap read snapshot done, change to get data from wal"); - pTaskInfo->streamInfo.prepareStatus.uid = mtInfo.uid; - pTaskInfo->streamInfo.lastStatus.type = TMQ_OFFSET__LOG; - pTaskInfo->streamInfo.lastStatus.version = pInfo->sContext->snapVersion; + tqOffsetResetToLog(&offset, pInfo->sContext->snapVersion); } else { - pTaskInfo->streamInfo.prepareStatus.uid = mtInfo.uid; - pTaskInfo->streamInfo.prepareStatus.ts = INT64_MIN; + tqOffsetResetToData(&offset, mtInfo.uid, INT64_MIN); qDebug("tmqsnap change get data uid:%" PRId64 "", mtInfo.uid); - qStreamPrepareScan(pTaskInfo, &pTaskInfo->streamInfo.prepareStatus, pInfo->sContext->subType); } - tDeleteSSchemaWrapper(mtInfo.schema); - qDebug("tmqsnap stream scan tsdb return null"); + qStreamPrepareScan(pTaskInfo, &offset, pInfo->sContext->subType); + tDeleteSchemaWrapper(mtInfo.schema); return NULL; - } else if (pTaskInfo->streamInfo.prepareStatus.type == TMQ_OFFSET__SNAPSHOT_META) { + } else if (pTaskInfo->streamInfo.currentOffset.type == TMQ_OFFSET__SNAPSHOT_META) { SSnapContext* sContext = pInfo->sContext; void* data = NULL; int32_t dataLen = 0; @@ -2055,16 +2197,12 @@ static SSDataBlock* doRawScan(SOperatorInfo* pOperator) { return NULL; } - if (!sContext->queryMetaOrData) { // change to get data next poll request - pTaskInfo->streamInfo.lastStatus.type = TMQ_OFFSET__SNAPSHOT_META; - pTaskInfo->streamInfo.lastStatus.uid = uid; - pTaskInfo->streamInfo.metaRsp.rspOffset.type = TMQ_OFFSET__SNAPSHOT_DATA; - pTaskInfo->streamInfo.metaRsp.rspOffset.uid = 0; - pTaskInfo->streamInfo.metaRsp.rspOffset.ts = INT64_MIN; + if (!sContext->queryMeta) { // change to get data next poll request + STqOffsetVal offset = {0}; + tqOffsetResetToData(&offset, 0, INT64_MIN); + qStreamPrepareScan(pTaskInfo, &offset, pInfo->sContext->subType); } else { - pTaskInfo->streamInfo.lastStatus.type = TMQ_OFFSET__SNAPSHOT_META; - pTaskInfo->streamInfo.lastStatus.uid = uid; - pTaskInfo->streamInfo.metaRsp.rspOffset = pTaskInfo->streamInfo.lastStatus; + tqOffsetResetToMeta(&pTaskInfo->streamInfo.currentOffset, uid); pTaskInfo->streamInfo.metaRsp.resMsgType = type; pTaskInfo->streamInfo.metaRsp.metaRspLen = dataLen; pTaskInfo->streamInfo.metaRsp.metaRsp = data; @@ -2117,6 +2255,7 @@ static void destroyRawScanOperatorInfo(void* param) { SStreamRawScanInfo* pRawScan = (SStreamRawScanInfo*)param; tsdbReaderClose(pRawScan->dataReader); destroySnapContext(pRawScan->sContext); + tableListDestroy(pRawScan->pTableListInfo); taosMemoryFree(pRawScan); } @@ -2138,6 +2277,7 @@ SOperatorInfo* createRawScanOperatorInfo(SReadHandle* pHandle, SExecTaskInfo* pT goto _end; } + pInfo->pTableListInfo = tableListCreate(); pInfo->vnode = pHandle->vnode; pInfo->sContext = pHandle->sContext; @@ -2156,9 +2296,11 @@ _end: static void destroyStreamScanOperatorInfo(void* param) { SStreamScanInfo* pStreamScan = (SStreamScanInfo*)param; + if (pStreamScan->pTableScanOp && pStreamScan->pTableScanOp->info) { - destroyOperatorInfo(pStreamScan->pTableScanOp); + destroyOperator(pStreamScan->pTableScanOp); } + if (pStreamScan->tqReader) { tqCloseReader(pStreamScan->tqReader); } @@ -2171,6 +2313,7 @@ static void destroyStreamScanOperatorInfo(void* param) { } cleanupExprSupp(&pStreamScan->tbnameCalSup); + cleanupExprSupp(&pStreamScan->tagCalSup); updateInfoDestroy(pStreamScan->pUpdateInfo); blockDataDestroy(pStreamScan->pRes); @@ -2178,18 +2321,20 @@ static void destroyStreamScanOperatorInfo(void* param) { blockDataDestroy(pStreamScan->pPullDataRes); blockDataDestroy(pStreamScan->pDeleteDataRes); blockDataDestroy(pStreamScan->pUpdateDataRes); + blockDataDestroy(pStreamScan->pCreateTbRes); taosArrayDestroy(pStreamScan->pBlockLists); taosMemoryFree(pStreamScan); } SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhysiNode* pTableScanNode, SNode* pTagCond, - SExecTaskInfo* pTaskInfo) { + STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo) { SArray* pColIds = NULL; SStreamScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SStreamScanInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; + tableListDestroy(pTableListInfo); goto _error; } @@ -2203,6 +2348,7 @@ SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhys int32_t code = extractColMatchInfo(pScanPhyNode->pScanCols, pDescNode, &numOfCols, COL_MATCH_FROM_COL_ID, &pInfo->matchInfo); if (code != TSDB_CODE_SUCCESS) { + tableListDestroy(pTableListInfo); goto _error; } @@ -2222,36 +2368,42 @@ SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhys SExprInfo* pSubTableExpr = taosMemoryCalloc(1, sizeof(SExprInfo)); if (pSubTableExpr == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; + tableListDestroy(pTableListInfo); goto _error; } + pInfo->tbnameCalSup.pExprInfo = pSubTableExpr; createExprFromOneNode(pSubTableExpr, pTableScanNode->pSubtable, 0); if (initExprSupp(&pInfo->tbnameCalSup, pSubTableExpr, 1) != 0) { + tableListDestroy(pTableListInfo); goto _error; } } if (pTableScanNode->pTags != NULL) { int32_t numOfTags; - SExprInfo* pTagExpr = createExprInfo(pTableScanNode->pTags, NULL, &numOfTags); + SExprInfo* pTagExpr = createExpr(pTableScanNode->pTags, &numOfTags); if (pTagExpr == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; + tableListDestroy(pTableListInfo); goto _error; } if (initExprSupp(&pInfo->tagCalSup, pTagExpr, numOfTags) != 0) { terrno = TSDB_CODE_OUT_OF_MEMORY; + tableListDestroy(pTableListInfo); goto _error; } } - pInfo->pBlockLists = taosArrayInit(4, POINTER_BYTES); + pInfo->pBlockLists = taosArrayInit(4, sizeof(SPackedData)); if (pInfo->pBlockLists == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; + tableListDestroy(pTableListInfo); goto _error; } if (pHandle->vnode) { - SOperatorInfo* pTableScanOp = createTableScanOperatorInfo(pTableScanNode, pHandle, pTaskInfo); + SOperatorInfo* pTableScanOp = createTableScanOperatorInfo(pTableScanNode, pHandle, pTableListInfo, pTaskInfo); STableScanInfo* pTSInfo = (STableScanInfo*)pTableScanOp->info; if (pHandle->version > 0) { pTSInfo->base.cond.endVersion = pHandle->version; @@ -2259,24 +2411,16 @@ SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhys STableKeyInfo* pList = NULL; int32_t num = 0; - tableListGetGroupList(pTaskInfo->pTableInfoList, 0, &pList, &num); + tableListGetGroupList(pTableListInfo, 0, &pList, &num); if (pHandle->initTableReader) { pTSInfo->scanMode = TABLE_SCAN__TABLE_ORDER; pTSInfo->base.dataReader = NULL; - pTaskInfo->streamInfo.lastStatus.uid = -1; -// code = tsdbReaderOpen(pHandle->vnode, &pTSInfo->base.cond, pList, num, pTSInfo->pResBlock, -// &pTSInfo->base.dataReader, NULL); -// if (code != 0) { -// terrno = code; -// destroyTableScanOperatorInfo(pTableScanOp); -// goto _error; -// } } if (pHandle->initTqReader) { ASSERT(pHandle->tqReader == NULL); - pInfo->tqReader = tqOpenReader(pHandle->vnode); + pInfo->tqReader = tqReaderOpen(pHandle->vnode); ASSERT(pInfo->tqReader); } else { ASSERT(pHandle->tqReader); @@ -2290,21 +2434,24 @@ SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhys } pInfo->readHandle = *pHandle; - pInfo->tableUid = pScanPhyNode->uid; pTaskInfo->streamInfo.snapshotVer = pHandle->version; + pInfo->pCreateTbRes = buildCreateTableBlock(&pInfo->tbnameCalSup, &pInfo->tagCalSup); + blockDataEnsureCapacity(pInfo->pCreateTbRes, 8); // set the extract column id to streamHandle tqReaderSetColIdList(pInfo->tqReader, pColIds); - SArray* tableIdList = extractTableIdList(pTaskInfo->pTableInfoList); + SArray* tableIdList = extractTableIdList(((STableScanInfo*)(pInfo->pTableScanOp->info))->base.pTableListInfo); code = tqReaderSetTbUidList(pInfo->tqReader, tableIdList); if (code != 0) { taosArrayDestroy(tableIdList); goto _error; } + taosArrayDestroy(tableIdList); memcpy(&pTaskInfo->streamInfo.tableCond, &pTSInfo->base.cond, sizeof(SQueryTableDataCond)); } else { taosArrayDestroy(pColIds); + tableListDestroy(pTableListInfo); pColIds = NULL; } @@ -2339,7 +2486,7 @@ SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhys pTaskInfo); pOperator->exprSupp.numOfExprs = taosArrayGetSize(pInfo->pRes->pDataBlock); - __optr_fn_t nextFn = pTaskInfo->execModel == OPTR_EXEC_MODEL_STREAM ? doStreamScan : doQueueScan; + __optr_fn_t nextFn = (pTaskInfo->execModel == OPTR_EXEC_MODEL_STREAM) ? doStreamScan : doQueueScan; pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, nextFn, NULL, destroyStreamScanOperatorInfo, optrDefaultBufFn, NULL); @@ -2370,7 +2517,7 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) { SSDataBlock* pRes = pInfo->pRes; blockDataCleanup(pRes); - int32_t size = tableListGetSize(pTaskInfo->pTableInfoList); + int32_t size = tableListGetSize(pInfo->pTableListInfo); if (size == 0) { setTaskStatus(pTaskInfo, TASK_COMPLETED); return NULL; @@ -2382,7 +2529,7 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) { metaReaderInit(&mr, pInfo->readHandle.meta, 0); while (pInfo->curPos < size && count < pOperator->resultInfo.capacity) { - STableKeyInfo* item = tableListGetInfo(pTaskInfo->pTableInfoList, pInfo->curPos); + STableKeyInfo* item = tableListGetInfo(pInfo->pTableListInfo, pInfo->curPos); int32_t code = metaGetTableEntryByUid(&mr, item->uid); tDecoderClear(&mr.coder); if (code != TSDB_CODE_SUCCESS) { @@ -2398,7 +2545,7 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) { // refactor later if (fmIsScanPseudoColumnFunc(pExprInfo[j].pExpr->_function.functionId)) { STR_TO_VARSTR(str, mr.me.name); - colDataAppend(pDst, count, str, false); + colDataSetVal(pDst, count, str, false); } else { // it is a tag value STagVal val = {0}; val.cid = pExprInfo[j].base.pParam[0].pCol->colId; @@ -2410,7 +2557,7 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) { } else { data = (char*)p; } - colDataAppend(pDst, count, data, + colDataSetVal(pDst, count, data, (data == NULL) || (pDst->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data))); if (pDst->info.type != TSDB_DATA_TYPE_JSON && p != NULL && IS_VAR_DATA_TYPE(((const STagVal*)p)->type) && @@ -2443,11 +2590,12 @@ static void destroyTagScanOperatorInfo(void* param) { STagScanInfo* pInfo = (STagScanInfo*)param; pInfo->pRes = blockDataDestroy(pInfo->pRes); taosArrayDestroy(pInfo->matchInfo.pList); + pInfo->pTableListInfo = tableListDestroy(pInfo->pTableListInfo); taosMemoryFreeClear(param); } SOperatorInfo* createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* pPhyNode, - SExecTaskInfo* pTaskInfo) { + STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo) { STagScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STagScanInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { @@ -2469,6 +2617,7 @@ SOperatorInfo* createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysi goto _error; } + pInfo->pTableListInfo = pTableListInfo; pInfo->pRes = createDataBlockFromDescNode(pDescNode); pInfo->readHandle = *pReadHandle; pInfo->curPos = 0; @@ -2497,22 +2646,41 @@ static SSDataBlock* getTableDataBlockImpl(void* param) { SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; int32_t readIdx = source->readerIdx; SSDataBlock* pBlock = source->inputBlock; + int32_t code = 0; SQueryTableDataCond* pQueryCond = taosArrayGet(pInfo->queryConds, readIdx); int64_t st = taosGetTimestampUs(); - void* p = tableListGetInfo(pTaskInfo->pTableInfoList, readIdx + pInfo->tableStartIndex); + void* p = tableListGetInfo(pInfo->base.pTableListInfo, readIdx + pInfo->tableStartIndex); SReadHandle* pHandle = &pInfo->base.readHandle; - int32_t code = - tsdbReaderOpen(pHandle->vnode, pQueryCond, p, 1, pBlock, &pInfo->base.dataReader, GET_TASKID(pTaskInfo)); - if (code != 0) { - T_LONG_JMP(pTaskInfo->env, code); + if (NULL == source->dataReader || !source->multiReader) { + code = tsdbReaderOpen(pHandle->vnode, pQueryCond, p, 1, pBlock, &source->dataReader, GET_TASKID(pTaskInfo), false, NULL); + if (code != 0) { + T_LONG_JMP(pTaskInfo->env, code); + } } + pInfo->base.dataReader = source->dataReader; STsdbReader* reader = pInfo->base.dataReader; - while (tsdbNextDataBlock(reader)) { + bool hasNext = false; + qTrace("tsdb/read-table-data: %p, enter next reader", reader); + + while (true) { + code = tsdbNextDataBlock(reader, &hasNext); + if (code != 0) { + tsdbReleaseDataBlock(reader); + pInfo->base.dataReader = NULL; + T_LONG_JMP(pTaskInfo->env, code); + } + + if (!hasNext) { + break; + } + if (isTaskKilled(pTaskInfo)) { + tsdbReleaseDataBlock(reader); + pInfo->base.dataReader = NULL; T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); } @@ -2535,22 +2703,33 @@ static SSDataBlock* getTableDataBlockImpl(void* param) { T_LONG_JMP(pTaskInfo->env, code); } + if (status == FUNC_DATA_REQUIRED_ALL_FILTEROUT) { + break; + } + // current block is filter out according to filter condition, continue load the next block if (status == FUNC_DATA_REQUIRED_FILTEROUT || pBlock->info.rows == 0) { continue; } - pBlock->info.id.groupId = getTableGroupId(pTaskInfo->pTableInfoList, pBlock->info.id.uid); + pBlock->info.id.groupId = getTableGroupId(pInfo->base.pTableListInfo, pBlock->info.id.uid); pOperator->resultInfo.totalRows += pBlock->info.rows; pInfo->base.readRecorder.elapsedTime += (taosGetTimestampUs() - st) / 1000.0; - tsdbReaderClose(pInfo->base.dataReader); + qTrace("tsdb/read-table-data: %p, close reader", reader); + if (!source->multiReader) { + tsdbReaderClose(pInfo->base.dataReader); + source->dataReader = NULL; + } pInfo->base.dataReader = NULL; return pBlock; } - tsdbReaderClose(pInfo->base.dataReader); + if (!source->multiReader) { + tsdbReaderClose(pInfo->base.dataReader); + source->dataReader = NULL; + } pInfo->base.dataReader = NULL; return NULL; } @@ -2589,10 +2768,10 @@ int32_t startGroupTableMergeScan(SOperatorInfo* pOperator) { SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; { - size_t numOfTables = tableListGetSize(pTaskInfo->pTableInfoList); + size_t numOfTables = tableListGetSize(pInfo->base.pTableListInfo); int32_t i = pInfo->tableStartIndex + 1; for (; i < numOfTables; ++i) { - STableKeyInfo* tableKeyInfo = tableListGetInfo(pTaskInfo->pTableInfoList, i); + STableKeyInfo* tableKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, i); if (tableKeyInfo->groupId != pInfo->groupId) { break; } @@ -2622,6 +2801,7 @@ int32_t startGroupTableMergeScan(SOperatorInfo* pOperator) { STableMergeScanSortSourceParam param = {0}; param.readerIdx = i; param.pOperator = pOperator; + param.multiReader = (numOfTable <= MULTI_READER_MAX_TABLE_NUM) ? true : false; param.inputBlock = createOneDataBlock(pInfo->pResBlock, false); blockDataEnsureCapacity(param.inputBlock, pOperator->resultInfo.capacity); @@ -2665,6 +2845,8 @@ int32_t stopGroupTableMergeScan(SOperatorInfo* pOperator) { for (int32_t i = 0; i < numOfTable; ++i) { STableMergeScanSortSourceParam* param = taosArrayGet(pInfo->sortSourceParams, i); blockDataDestroy(param->inputBlock); + tsdbReaderClose(param->dataReader); + param->dataReader = NULL; } taosArrayClear(pInfo->sortSourceParams); @@ -2704,12 +2886,9 @@ SSDataBlock* getSortedTableMergeScanBlockData(SSortHandle* pHandle, SSDataBlock* } bool limitReached = applyLimitOffset(&pInfo->limitInfo, pResBlock, pTaskInfo); - qDebug("%s get sorted row block, rows:%d, limit:%"PRId64, GET_TASKID(pTaskInfo), pResBlock->info.rows, + qDebug("%s get sorted row block, rows:%" PRId64 ", limit:%" PRId64, GET_TASKID(pTaskInfo), pResBlock->info.rows, pInfo->limitInfo.numOfOutputRows); - if (limitReached) { - resetLimitInfoForNextGroup(&pInfo->limitInfo); - } return (pResBlock->info.rows > 0) ? pResBlock : NULL; } @@ -2726,7 +2905,7 @@ SSDataBlock* doTableMergeScan(SOperatorInfo* pOperator) { T_LONG_JMP(pTaskInfo->env, code); } - size_t tableListSize = tableListGetSize(pTaskInfo->pTableInfoList); + size_t tableListSize = tableListGetSize(pInfo->base.pTableListInfo); if (!pInfo->hasGroupId) { pInfo->hasGroupId = true; @@ -2735,7 +2914,7 @@ SSDataBlock* doTableMergeScan(SOperatorInfo* pOperator) { return NULL; } pInfo->tableStartIndex = 0; - pInfo->groupId = ((STableKeyInfo*)tableListGetInfo(pTaskInfo->pTableInfoList, pInfo->tableStartIndex))->groupId; + pInfo->groupId = ((STableKeyInfo*)tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex))->groupId; startGroupTableMergeScan(pOperator); } @@ -2760,8 +2939,9 @@ SSDataBlock* doTableMergeScan(SOperatorInfo* pOperator) { } pInfo->tableStartIndex = pInfo->tableEndIndex + 1; - pInfo->groupId = tableListGetInfo(pTaskInfo->pTableInfoList, pInfo->tableStartIndex)->groupId; + pInfo->groupId = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex)->groupId; startGroupTableMergeScan(pOperator); + resetLimitInfoForNextGroup(&pInfo->limitInfo); } } @@ -2777,35 +2957,29 @@ void destroyTableMergeScanOperatorInfo(void* param) { for (int32_t i = 0; i < numOfTable; i++) { STableMergeScanSortSourceParam* p = taosArrayGet(pTableScanInfo->sortSourceParams, i); blockDataDestroy(p->inputBlock); + tsdbReaderClose(p->dataReader); + p->dataReader = NULL; } + tsdbReaderClose(pTableScanInfo->base.dataReader); + pTableScanInfo->base.dataReader = NULL; + taosArrayDestroy(pTableScanInfo->sortSourceParams); tsortDestroySortHandle(pTableScanInfo->pSortHandle); pTableScanInfo->pSortHandle = NULL; - tsdbReaderClose(pTableScanInfo->base.dataReader); - pTableScanInfo->base.dataReader = NULL; - for (int i = 0; i < taosArrayGetSize(pTableScanInfo->queryConds); i++) { SQueryTableDataCond* pCond = taosArrayGet(pTableScanInfo->queryConds, i); taosMemoryFree(pCond->colList); } - taosArrayDestroy(pTableScanInfo->queryConds); - if (pTableScanInfo->base.matchInfo.pList != NULL) { - taosArrayDestroy(pTableScanInfo->base.matchInfo.pList); - } + taosArrayDestroy(pTableScanInfo->queryConds); + destroyTableScanBase(&pTableScanInfo->base); pTableScanInfo->pResBlock = blockDataDestroy(pTableScanInfo->pResBlock); pTableScanInfo->pSortInputBlock = blockDataDestroy(pTableScanInfo->pSortInputBlock); taosArrayDestroy(pTableScanInfo->pSortInfo); - cleanupExprSupp(&pTableScanInfo->base.pseudoSup); - - tsdbReaderClose(pTableScanInfo->base.dataReader); - pTableScanInfo->base.dataReader = NULL; - taosLRUCacheCleanup(pTableScanInfo->base.metaCache.pTableMetaEntryCache); - taosMemoryFreeClear(param); } @@ -2824,7 +2998,7 @@ int32_t getTableMergeScanExplainExecInfo(SOperatorInfo* pOptr, void** pOptrExpla } SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle, - SExecTaskInfo* pTaskInfo) { + STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo) { STableMergeScanInfo* pInfo = taosMemoryCalloc(1, sizeof(STableMergeScanInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { @@ -2866,6 +3040,7 @@ SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanN pInfo->base.limitInfo.limit.limit = -1; pInfo->base.limitInfo.slimit.limit = -1; + pInfo->base.pTableListInfo = pTableListInfo; pInfo->sample.sampleRatio = pTableScanNode->ratio; pInfo->sample.seed = taosGetTimestampSec(); @@ -2985,8 +3160,8 @@ int32_t tblCountScanGetInputs(SNodeList* groupTags, SName* tableName, STableCoun } } } else { - strncpy(supp->dbNameFilter, tNameGetDbNameP(tableName), TSDB_DB_NAME_LEN); - strncpy(supp->stbNameFilter, tNameGetTableName(tableName), TSDB_TABLE_NAME_LEN); + tstrncpy(supp->dbNameFilter, tNameGetDbNameP(tableName), TSDB_DB_NAME_LEN); + tstrncpy(supp->stbNameFilter, tNameGetTableName(tableName), TSDB_TABLE_NAME_LEN); } return TSDB_CODE_SUCCESS; } @@ -3064,7 +3239,7 @@ void fillTableCountScanDataBlock(STableCountScanSupp* pSupp, char* dbName, char* tstrncpy(varDataVal(varDbName), dbName, TSDB_DB_NAME_LEN); varDataSetLen(varDbName, strlen(dbName)); - colDataAppend(colInfoData, 0, varDbName, false); + colDataSetVal(colInfoData, 0, varDbName, false); } if (pSupp->stbNameSlotId != -1) { @@ -3073,15 +3248,15 @@ void fillTableCountScanDataBlock(STableCountScanSupp* pSupp, char* dbName, char* char varStbName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; strncpy(varDataVal(varStbName), stbName, TSDB_TABLE_NAME_LEN); varDataSetLen(varStbName, strlen(stbName)); - colDataAppend(colInfoData, 0, varStbName, false); + colDataSetVal(colInfoData, 0, varStbName, false); } else { - colDataAppendNULL(colInfoData, 0); + colDataSetNULL(colInfoData, 0); } } if (pSupp->tbCountSlotId != -1) { SColumnInfoData* colInfoData = taosArrayGet(pRes->pDataBlock, pSupp->tbCountSlotId); - colDataAppend(colInfoData, 0, (char*)&count, false); + colDataSetVal(colInfoData, 0, (char*)&count, false); } pRes->info.rows = 1; } @@ -3095,7 +3270,7 @@ static SSDataBlock* buildSysDbTableCount(SOperatorInfo* pOperator, STableCountSc size_t perfdbTableNum; getPerfDbMeta(NULL, &perfdbTableNum); - if (pSupp->groupByDbName) { + if (pSupp->groupByDbName || pSupp->groupByStbName) { buildSysDbGroupedTableCount(pOperator, pInfo, pSupp, pRes, infodbTableNum, perfdbTableNum); return (pRes->info.rows > 0) ? pRes : NULL; } else { @@ -3120,11 +3295,23 @@ static void buildSysDbGroupedTableCount(SOperatorInfo* pOperator, STableCountSca STableCountScanSupp* pSupp, SSDataBlock* pRes, size_t infodbTableNum, size_t perfdbTableNum) { if (pInfo->currGrpIdx == 0) { - uint64_t groupId = calcGroupId(TSDB_INFORMATION_SCHEMA_DB, strlen(TSDB_INFORMATION_SCHEMA_DB)); + uint64_t groupId = 0; + if (pSupp->groupByDbName) { + groupId = calcGroupId(TSDB_INFORMATION_SCHEMA_DB, strlen(TSDB_INFORMATION_SCHEMA_DB)); + } else { + groupId = calcGroupId("", 0); + } + pRes->info.id.groupId = groupId; fillTableCountScanDataBlock(pSupp, TSDB_INFORMATION_SCHEMA_DB, "", infodbTableNum, pRes); } else if (pInfo->currGrpIdx == 1) { - uint64_t groupId = calcGroupId(TSDB_PERFORMANCE_SCHEMA_DB, strlen(TSDB_PERFORMANCE_SCHEMA_DB)); + uint64_t groupId = 0; + if (pSupp->groupByDbName) { + groupId = calcGroupId(TSDB_PERFORMANCE_SCHEMA_DB, strlen(TSDB_PERFORMANCE_SCHEMA_DB)); + } else { + groupId = calcGroupId("", 0); + } + pRes->info.id.groupId = groupId; fillTableCountScanDataBlock(pSupp, TSDB_PERFORMANCE_SCHEMA_DB, "", perfdbTableNum, pRes); } else { @@ -3162,7 +3349,7 @@ static SSDataBlock* buildVnodeDbTableCount(SOperatorInfo* pOperator, STableCount tNameFromString(&sn, db, T_NAME_ACCT | T_NAME_DB); tNameGetDbName(&sn, dbName); - if (pSupp->groupByDbName) { + if (pSupp->groupByDbName || pSupp->groupByStbName) { buildVnodeGroupedTableCount(pOperator, pInfo, pSupp, pRes, vgId, dbName); } else { buildVnodeFilteredTbCount(pOperator, pInfo, pSupp, pRes, dbName); @@ -3223,7 +3410,10 @@ static void buildVnodeFilteredTbCount(SOperatorInfo* pOperator, STableCountScanO static void buildVnodeGroupedNtbTableCount(STableCountScanOperatorInfo* pInfo, STableCountScanSupp* pSupp, SSDataBlock* pRes, char* dbName) { char fullStbName[TSDB_TABLE_FNAME_LEN] = {0}; - snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, ""); + if (pSupp->groupByDbName) { + snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, ""); + } + uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName)); pRes->info.id.groupId = groupId; int64_t ntbNum = metaGetNtbNum(pInfo->readHandle.meta); @@ -3238,7 +3428,12 @@ static void buildVnodeGroupedStbTableCount(STableCountScanOperatorInfo* pInfo, S metaGetTableSzNameByUid(pInfo->readHandle.meta, stbUid, stbName); char fullStbName[TSDB_TABLE_FNAME_LEN] = {0}; - snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, stbName); + if (pSupp->groupByDbName) { + snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s.%s", dbName, stbName); + } else { + snprintf(fullStbName, TSDB_TABLE_FNAME_LEN, "%s", stbName); + } + uint64_t groupId = calcGroupId(fullStbName, strlen(fullStbName)); pRes->info.id.groupId = groupId; diff --git a/source/libs/executor/src/sortoperator.c b/source/libs/executor/src/sortoperator.c index 98ef6b8a3621abb1560d9f04924f92cff84b4935..10933f285c6d93fafdc86b6e0e30aca3a5e22289 100644 --- a/source/libs/executor/src/sortoperator.c +++ b/source/libs/executor/src/sortoperator.c @@ -13,8 +13,10 @@ * along with this program. If not, see . */ +#include "executorInt.h" #include "filter.h" -#include "executorimpl.h" +#include "operator.h" +#include "querytask.h" #include "tdatablock.h" typedef struct SSortOperatorInfo { @@ -46,8 +48,9 @@ SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* pOperator->pTaskInfo = pTaskInfo; SDataBlockDescNode* pDescNode = pSortNode->node.pOutputDataBlockDesc; - int32_t numOfCols = 0; - SExprInfo* pExprInfo = createExprInfo(pSortNode->pExprs, NULL, &numOfCols); + int32_t numOfCols = 0; + pOperator->exprSupp.pExprInfo = createExprInfo(pSortNode->pExprs, NULL, &numOfCols); + pOperator->exprSupp.numOfExprs = numOfCols; int32_t numOfOutputCols = 0; int32_t code = @@ -56,7 +59,8 @@ SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* goto _error; } - pOperator->exprSupp.pCtx = createSqlFunctionCtx(pExprInfo, numOfCols, &pOperator->exprSupp.rowEntryInfoOffset); + pOperator->exprSupp.pCtx = + createSqlFunctionCtx(pOperator->exprSupp.pExprInfo, numOfCols, &pOperator->exprSupp.rowEntryInfoOffset); initResultSizeInfo(&pOperator->resultInfo, 1024); code = filterInitFromNode((SNode*)pSortNode->node.pConditions, &pOperator->exprSupp.pFilterInfo, 0); if (code != TSDB_CODE_SUCCESS) { @@ -68,8 +72,7 @@ SOperatorInfo* createSortOperatorInfo(SOperatorInfo* downstream, SSortPhysiNode* initLimitInfo(pSortNode->node.pLimit, pSortNode->node.pSlimit, &pInfo->limitInfo); setOperatorInfo(pOperator, "SortOperator", QUERY_NODE_PHYSICAL_PLAN_SORT, true, OP_NOT_OPENED, pInfo, pTaskInfo); - pOperator->exprSupp.pExprInfo = pExprInfo; - pOperator->exprSupp.numOfExprs = numOfCols; + // lazy evaluation for the following parameter since the input datablock is not known till now. // pInfo->bufPageSize = rowSize < 1024 ? 1024 * 2 : rowSize * 2; @@ -101,11 +104,11 @@ void appendOneRowToDataBlock(SSDataBlock* pBlock, STupleHandle* pTupleHandle) { SColumnInfoData* pColInfo = taosArrayGet(pBlock->pDataBlock, i); bool isNull = tsortIsNullVal(pTupleHandle, i); if (isNull) { - colDataAppendNULL(pColInfo, pBlock->info.rows); + colDataSetNULL(pColInfo, pBlock->info.rows); } else { char* pData = tsortGetValue(pTupleHandle, i); if (pData != NULL) { - colDataAppend(pColInfo, pBlock->info.rows, pData, false); + colDataSetVal(pColInfo, pBlock->info.rows, pData, false); } } } @@ -671,7 +674,9 @@ SSDataBlock* getMultiwaySortedBlockData(SSortHandle* pHandle, SSDataBlock* pData } bool limitReached = applyLimitOffset(&pInfo->limitInfo, p, pTaskInfo); - if (limitReached) { + // if limit is reached within a group, do not clear limiInfo otherwise the next block + // will be processed. + if (newgroup && limitReached) { resetLimitInfoForNextGroup(&pInfo->limitInfo); } @@ -695,7 +700,7 @@ SSDataBlock* getMultiwaySortedBlockData(SSortHandle* pHandle, SSDataBlock* pData pDataBlock->info.dataLoad = 1; } - qDebug("%s get sorted block, groupId:0x%" PRIx64 " rows:%d", GET_TASKID(pTaskInfo), pDataBlock->info.id.groupId, + qDebug("%s get sorted block, groupId:0x%" PRIx64 " rows:%" PRId64 , GET_TASKID(pTaskInfo), pDataBlock->info.id.groupId, pDataBlock->info.rows); return (pDataBlock->info.rows > 0) ? pDataBlock : NULL; @@ -768,8 +773,6 @@ SOperatorInfo* createMultiwayMergeOperatorInfo(SOperatorInfo** downStreams, size pInfo->binfo.pRes = createDataBlockFromDescNode(pDescNode); int32_t rowSize = pInfo->binfo.pRes->info.rowSize; - ASSERT(rowSize < 100 * 1024 * 1024); - int32_t numOfOutputCols = 0; code = extractColMatchInfo(pMergePhyNode->pTargets, pDescNode, &numOfOutputCols, COL_MATCH_FROM_SLOT_ID, &pInfo->matchInfo); diff --git a/source/libs/executor/src/sysscanoperator.c b/source/libs/executor/src/sysscanoperator.c index 88d9fb1a1f5b4a4f52fead820c4b00981d64e01e..04c6c619aadec594c459ad223be1f7117a4dbe67 100644 --- a/source/libs/executor/src/sysscanoperator.c +++ b/source/libs/executor/src/sysscanoperator.c @@ -13,7 +13,7 @@ * along with this program. If not, see . */ -#include "executorimpl.h" +#include "executorInt.h" #include "filter.h" #include "function.h" #include "functionMgt.h" @@ -31,6 +31,9 @@ #include "thash.h" #include "ttypes.h" #include "vnode.h" +#include "operator.h" +#include "querytask.h" + typedef int (*__optSysFilter)(void* a, void* b, int16_t dtype); typedef int32_t (*__sys_filte)(void* pMeta, SNode* cond, SArray* result); @@ -57,9 +60,11 @@ typedef struct SSysTableScanInfo { const char* pUser; bool sysInfo; bool showRewrite; + bool restore; SNode* pCondition; // db_name filter condition, to discard data that are not in current database SMTbCursor* pCur; // cursor for iterate the local table meta store. SSysTableIndex* pIdx; // idx for local table meta + SHashObj* pSchema; SColMatchInfo matchInfo; SName name; SSDataBlock* pRes; @@ -81,10 +86,11 @@ typedef struct MergeIndex { } MergeIndex; typedef struct SBlockDistInfo { - SSDataBlock* pResBlock; - STsdbReader* pHandle; - SReadHandle readHandle; - uint64_t uid; // table uid + SSDataBlock* pResBlock; + STsdbReader* pHandle; + SReadHandle readHandle; + STableListInfo* pTableListInfo; + uint64_t uid; // table uid } SBlockDistInfo; static int32_t sysChkFilter__Comm(SNode* pNode); @@ -129,16 +135,20 @@ static char* SYSTABLE_IDX_COLUMN[] = {"table_name", "db_name", "create_time" static char* SYSTABLE_SPECIAL_COL[] = {"db_name", "vgroup_id"}; -static int32_t buildSysDbTableInfo(const SSysTableScanInfo* pInfo, int32_t capacity); -static SSDataBlock* buildInfoSchemaTableMetaBlock(char* tableName); -static void destroySysScanOperator(void* param); -static int32_t loadSysTableCallback(void* param, SDataBuf* pMsg, int32_t code); -static __optSysFilter optSysGetFilterFunc(int32_t ctype, bool* reverse); +static int32_t buildSysDbTableInfo(const SSysTableScanInfo* pInfo, int32_t capacity); +static SSDataBlock* buildInfoSchemaTableMetaBlock(char* tableName); +static void destroySysScanOperator(void* param); +static int32_t loadSysTableCallback(void* param, SDataBuf* pMsg, int32_t code); +static __optSysFilter optSysGetFilterFunc(int32_t ctype, bool* reverse, bool* equal); static int32_t sysTableUserTagsFillOneTableTags(const SSysTableScanInfo* pInfo, SMetaReader* smrSuperTable, SMetaReader* smrChildTable, const char* dbname, const char* tableName, int32_t* pNumOfRows, const SSDataBlock* dataBlock); +static int32_t sysTableUserColsFillOneTableCols(const SSysTableScanInfo* pInfo, const char* dbname, int32_t* pNumOfRows, + const SSDataBlock* dataBlock, char* tName, SSchemaWrapper* schemaRow, + char* tableType); + static void relocateAndFilterSysTagsScanResult(SSysTableScanInfo* pInfo, int32_t numOfRows, SSDataBlock* dataBlock, SFilterInfo* pFilterInfo); @@ -159,7 +169,8 @@ int32_t sysFilte__DbName(void* arg, SNode* pNode, SArray* result) { SValueNode* pVal = (SValueNode*)pOper->pRight; bool reverse = false; - __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse); + bool equal = false; + __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse, &equal); if (func == NULL) return -1; int ret = func(dbname, pVal->datum.p, TSDB_DATA_TYPE_VARCHAR); @@ -177,9 +188,9 @@ int32_t sysFilte__VgroupId(void* arg, SNode* pNode, SArray* result) { SOperatorNode* pOper = (SOperatorNode*)pNode; SValueNode* pVal = (SValueNode*)pOper->pRight; - bool reverse = false; - - __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse); + bool reverse = false; + bool equal = false; + __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse, &equal); if (func == NULL) return -1; int ret = func(&vgId, &pVal->datum.i, TSDB_DATA_TYPE_BIGINT); @@ -193,17 +204,18 @@ int32_t sysFilte__TableName(void* arg, SNode* pNode, SArray* result) { SOperatorNode* pOper = (SOperatorNode*)pNode; SValueNode* pVal = (SValueNode*)pOper->pRight; - bool reverse = false; - __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse); + bool reverse = false, equal = false; + __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse, &equal); if (func == NULL) return -1; SMetaFltParam param = {.suid = 0, - .cid = 0, - .type = TSDB_DATA_TYPE_VARCHAR, - .val = pVal->datum.p, - .reverse = reverse, - .filterFunc = func}; + .cid = 0, + .type = TSDB_DATA_TYPE_VARCHAR, + .val = pVal->datum.p, + .reverse = reverse, + .equal = equal, + .filterFunc = func}; return -1; } @@ -212,17 +224,18 @@ int32_t sysFilte__CreateTime(void* arg, SNode* pNode, SArray* result) { SOperatorNode* pOper = (SOperatorNode*)pNode; SValueNode* pVal = (SValueNode*)pOper->pRight; - bool reverse = false; - __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse); + bool reverse = false, equal = false; + __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse, &equal); if (func == NULL) return -1; SMetaFltParam param = {.suid = 0, - .cid = 0, - .type = TSDB_DATA_TYPE_BIGINT, - .val = &pVal->datum.i, - .reverse = reverse, - .filterFunc = func}; + .cid = 0, + .type = TSDB_DATA_TYPE_BIGINT, + .val = &pVal->datum.i, + .reverse = reverse, + .equal = equal, + .filterFunc = func}; int32_t ret = metaFilterCreateTime(pMeta, ¶m, result); return ret; @@ -234,8 +247,8 @@ int32_t sysFilte__Ncolumn(void* arg, SNode* pNode, SArray* result) { SOperatorNode* pOper = (SOperatorNode*)pNode; SValueNode* pVal = (SValueNode*)pOper->pRight; bool reverse = false; - - __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse); + bool equal = false; + __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse, &equal); if (func == NULL) return -1; return -1; } @@ -246,8 +259,8 @@ int32_t sysFilte__Ttl(void* arg, SNode* pNode, SArray* result) { SOperatorNode* pOper = (SOperatorNode*)pNode; SValueNode* pVal = (SValueNode*)pOper->pRight; bool reverse = false; - - __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse); + bool equal = false; + __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse, &equal); if (func == NULL) return -1; return -1; } @@ -258,8 +271,8 @@ int32_t sysFilte__STableName(void* arg, SNode* pNode, SArray* result) { SOperatorNode* pOper = (SOperatorNode*)pNode; SValueNode* pVal = (SValueNode*)pOper->pRight; bool reverse = false; - - __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse); + bool equal = false; + __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse, &equal); if (func == NULL) return -1; return -1; } @@ -270,8 +283,8 @@ int32_t sysFilte__Uid(void* arg, SNode* pNode, SArray* result) { SOperatorNode* pOper = (SOperatorNode*)pNode; SValueNode* pVal = (SValueNode*)pOper->pRight; bool reverse = false; - - __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse); + bool equal = false; + __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse, &equal); if (func == NULL) return -1; return -1; } @@ -282,8 +295,8 @@ int32_t sysFilte__Type(void* arg, SNode* pNode, SArray* result) { SOperatorNode* pOper = (SOperatorNode*)pNode; SValueNode* pVal = (SValueNode*)pOper->pRight; bool reverse = false; - - __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse); + bool equal = false; + __optSysFilter func = optSysGetFilterFunc(pOper->opType, &reverse, &equal); if (func == NULL) return -1; return -1; } @@ -350,12 +363,17 @@ static int32_t optSysMergeRslt(SArray* mRslt, SArray* rslt); static SSDataBlock* sysTableScanFromMNode(SOperatorInfo* pOperator, SSysTableScanInfo* pInfo, const char* name, SExecTaskInfo* pTaskInfo); void extractTbnameSlotId(SSysTableScanInfo* pInfo, const SScanPhysiNode* pScanNode); -static void sysTableScanFillTbName(SOperatorInfo* pOperator, const SSysTableScanInfo* pInfo, - const char* name, SSDataBlock* pBlock); -__optSysFilter optSysGetFilterFunc(int32_t ctype, bool* reverse) { + +static void sysTableScanFillTbName(SOperatorInfo* pOperator, const SSysTableScanInfo* pInfo, const char* name, + SSDataBlock* pBlock); + +__optSysFilter optSysGetFilterFunc(int32_t ctype, bool* reverse, bool* equal) { if (ctype == OP_TYPE_LOWER_EQUAL || ctype == OP_TYPE_LOWER_THAN) { *reverse = true; } + if (ctype == OP_TYPE_EQUAL) { + *equal = true; + } if (ctype == OP_TYPE_LOWER_THAN) return optSysFilterFuncImpl__LowerThan; else if (ctype == OP_TYPE_LOWER_EQUAL) @@ -412,6 +430,192 @@ static bool sysTableIsCondOnOneTable(SNode* pCond, char* condTable) { return false; } +static SSDataBlock* sysTableScanUserCols(SOperatorInfo* pOperator) { + qDebug("sysTableScanUserCols get cols start"); + SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; + SSysTableScanInfo* pInfo = pOperator->info; + if (pOperator->status == OP_EXEC_DONE) { + return NULL; + } + + blockDataCleanup(pInfo->pRes); + int32_t numOfRows = 0; + + SSDataBlock* dataBlock = buildInfoSchemaTableMetaBlock(TSDB_INS_TABLE_COLS); + blockDataEnsureCapacity(dataBlock, pOperator->resultInfo.capacity); + + const char* db = NULL; + int32_t vgId = 0; + vnodeGetInfo(pInfo->readHandle.vnode, &db, &vgId); + + SName sn = {0}; + char dbname[TSDB_DB_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + tNameFromString(&sn, db, T_NAME_ACCT | T_NAME_DB); + + tNameGetDbName(&sn, varDataVal(dbname)); + varDataSetLen(dbname, strlen(varDataVal(dbname))); + + // optimize when sql like where table_name='tablename' and xxx. + if (pInfo->req.filterTb[0]) { + char tableName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(tableName, pInfo->req.filterTb); + + SMetaReader smrTable = {0}; + metaReaderInit(&smrTable, pInfo->readHandle.meta, 0); + int32_t code = metaGetTableEntryByName(&smrTable, pInfo->req.filterTb); + if (code != TSDB_CODE_SUCCESS) { + // terrno has been set by metaGetTableEntryByName, therefore, return directly + metaReaderClear(&smrTable); + blockDataDestroy(dataBlock); + pInfo->loadInfo.totalRows = 0; + return NULL; + } + + if (smrTable.me.type == TSDB_SUPER_TABLE) { + metaReaderClear(&smrTable); + blockDataDestroy(dataBlock); + pInfo->loadInfo.totalRows = 0; + return NULL; + } + + if (smrTable.me.type == TSDB_CHILD_TABLE) { + int64_t suid = smrTable.me.ctbEntry.suid; + metaReaderClear(&smrTable); + metaReaderInit(&smrTable, pInfo->readHandle.meta, 0); + code = metaGetTableEntryByUid(&smrTable, suid); + if (code != TSDB_CODE_SUCCESS) { + // terrno has been set by metaGetTableEntryByName, therefore, return directly + metaReaderClear(&smrTable); + blockDataDestroy(dataBlock); + pInfo->loadInfo.totalRows = 0; + return NULL; + } + } + + char typeName[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + SSchemaWrapper* schemaRow = NULL; + if (smrTable.me.type == TSDB_SUPER_TABLE) { + schemaRow = &smrTable.me.stbEntry.schemaRow; + STR_TO_VARSTR(typeName, "CHILD_TABLE"); + } else if (smrTable.me.type == TSDB_NORMAL_TABLE) { + schemaRow = &smrTable.me.ntbEntry.schemaRow; + STR_TO_VARSTR(typeName, "NORMAL_TABLE"); + } + + sysTableUserColsFillOneTableCols(pInfo, dbname, &numOfRows, dataBlock, tableName, schemaRow, typeName); + metaReaderClear(&smrTable); + + if (numOfRows > 0) { + relocateAndFilterSysTagsScanResult(pInfo, numOfRows, dataBlock, pOperator->exprSupp.pFilterInfo); + numOfRows = 0; + } + blockDataDestroy(dataBlock); + pInfo->loadInfo.totalRows += pInfo->pRes->info.rows; + setOperatorCompleted(pOperator); + return (pInfo->pRes->info.rows == 0) ? NULL : pInfo->pRes; + } + + int32_t ret = 0; + if (pInfo->pCur == NULL) { + pInfo->pCur = metaOpenTbCursor(pInfo->readHandle.meta); + } + + if (pInfo->pSchema == NULL) { + pInfo->pSchema = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK); + taosHashSetFreeFp(pInfo->pSchema, tDeleteSSchemaWrapperForHash); + } + + if (!pInfo->pCur || !pInfo->pSchema) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + qError("sysTableScanUserCols failed since %s", terrstr(terrno)); + blockDataDestroy(dataBlock); + pInfo->loadInfo.totalRows = 0; + return NULL; + } + + int32_t restore = pInfo->restore; + pInfo->restore = false; + while (restore || ((ret = metaTbCursorNext(pInfo->pCur, TSDB_TABLE_MAX)) == 0)) { + if (restore) restore = false; + char typeName[TSDB_TABLE_FNAME_LEN + VARSTR_HEADER_SIZE] = {0}; + char tableName[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + + SSchemaWrapper* schemaRow = NULL; + + if (pInfo->pCur->mr.me.type == TSDB_SUPER_TABLE) { + qDebug("sysTableScanUserCols cursor get super table"); + void* schema = taosHashGet(pInfo->pSchema, &pInfo->pCur->mr.me.uid, sizeof(int64_t)); + if (schema == NULL) { + SSchemaWrapper* schemaWrapper = tCloneSSchemaWrapper(&pInfo->pCur->mr.me.stbEntry.schemaRow); + taosHashPut(pInfo->pSchema, &pInfo->pCur->mr.me.uid, sizeof(int64_t), &schemaWrapper, POINTER_BYTES); + } + continue; + } else if (pInfo->pCur->mr.me.type == TSDB_CHILD_TABLE) { + qDebug("sysTableScanUserCols cursor get child table"); + STR_TO_VARSTR(typeName, "CHILD_TABLE"); + STR_TO_VARSTR(tableName, pInfo->pCur->mr.me.name); + int64_t suid = pInfo->pCur->mr.me.ctbEntry.suid; + void* schema = taosHashGet(pInfo->pSchema, &pInfo->pCur->mr.me.ctbEntry.suid, sizeof(int64_t)); + if (schema != NULL) { + schemaRow = *(SSchemaWrapper**)schema; + } else { + SMetaReader smrSuperTable = {0}; + metaReaderInit(&smrSuperTable, pInfo->readHandle.meta, 0); + int code = metaGetTableEntryByUid(&smrSuperTable, suid); + if (code != TSDB_CODE_SUCCESS) { + // terrno has been set by metaGetTableEntryByName, therefore, return directly + qError("sysTableScanUserCols get meta by suid:%" PRId64 " error, code:%d", suid, code); + metaReaderClear(&smrSuperTable); + blockDataDestroy(dataBlock); + pInfo->loadInfo.totalRows = 0; + return NULL; + } + SSchemaWrapper* schemaWrapper = tCloneSSchemaWrapper(&smrSuperTable.me.stbEntry.schemaRow); + taosHashPut(pInfo->pSchema, &suid, sizeof(int64_t), &schemaWrapper, POINTER_BYTES); + schemaRow = schemaWrapper; + metaReaderClear(&smrSuperTable); + } + } else if (pInfo->pCur->mr.me.type == TSDB_NORMAL_TABLE) { + qDebug("sysTableScanUserCols cursor get normal table"); + schemaRow = &pInfo->pCur->mr.me.ntbEntry.schemaRow; + STR_TO_VARSTR(typeName, "NORMAL_TABLE"); + STR_TO_VARSTR(tableName, pInfo->pCur->mr.me.name); + } else { + qDebug("sysTableScanUserCols cursor get invalid table"); + continue; + } + + if ((numOfRows + schemaRow->nCols) > pOperator->resultInfo.capacity) { + relocateAndFilterSysTagsScanResult(pInfo, numOfRows, dataBlock, pOperator->exprSupp.pFilterInfo); + numOfRows = 0; + pInfo->restore = true; + + if (pInfo->pRes->info.rows > 0) { + break; + } + } else { + sysTableUserColsFillOneTableCols(pInfo, dbname, &numOfRows, dataBlock, tableName, schemaRow, typeName); + } + } + + if (numOfRows > 0) { + relocateAndFilterSysTagsScanResult(pInfo, numOfRows, dataBlock, pOperator->exprSupp.pFilterInfo); + numOfRows = 0; + } + + blockDataDestroy(dataBlock); + if (ret != 0) { + metaCloseTbCursor(pInfo->pCur); + pInfo->pCur = NULL; + setOperatorCompleted(pOperator); + } + + pInfo->loadInfo.totalRows += pInfo->pRes->info.rows; + qDebug("sysTableScanUserCols get cols success, rows:%" PRIu64, pInfo->loadInfo.totalRows); + + return (pInfo->pRes->info.rows == 0) ? NULL : pInfo->pRes; +} + static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) { SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; SSysTableScanInfo* pInfo = pOperator->info; @@ -491,7 +695,7 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) { } bool blockFull = false; - while ((ret = metaTbCursorNext(pInfo->pCur)) == 0) { + while ((ret = metaTbCursorNext(pInfo->pCur, TSDB_SUPER_TABLE)) == 0) { if (pInfo->pCur->mr.me.type != TSDB_CHILD_TABLE) { continue; } @@ -513,12 +717,13 @@ static SSDataBlock* sysTableScanUserTags(SOperatorInfo* pOperator) { } if ((smrSuperTable.me.stbEntry.schemaTag.nCols + numOfRows) > pOperator->resultInfo.capacity) { - metaTbCursorPrev(pInfo->pCur); + metaTbCursorPrev(pInfo->pCur, TSDB_TABLE_MAX); blockFull = true; } else { - sysTableUserTagsFillOneTableTags(pInfo, &smrSuperTable, &pInfo->pCur->mr, dbname, tableName, &numOfRows, dataBlock); + sysTableUserTagsFillOneTableTags(pInfo, &smrSuperTable, &pInfo->pCur->mr, dbname, tableName, &numOfRows, + dataBlock); } - + metaReaderClear(&smrSuperTable); if (blockFull || numOfRows >= pOperator->resultInfo.capacity) { @@ -654,21 +859,21 @@ static int32_t sysTableUserTagsFillOneTableTags(const SSysTableScanInfo* pInfo, // table name pColInfoData = taosArrayGet(dataBlock->pDataBlock, 0); - colDataAppend(pColInfoData, numOfRows, tableName, false); + colDataSetVal(pColInfoData, numOfRows, tableName, false); // database name pColInfoData = taosArrayGet(dataBlock->pDataBlock, 1); - colDataAppend(pColInfoData, numOfRows, dbname, false); + colDataSetVal(pColInfoData, numOfRows, dbname, false); // super table name pColInfoData = taosArrayGet(dataBlock->pDataBlock, 2); - colDataAppend(pColInfoData, numOfRows, stableName, false); + colDataSetVal(pColInfoData, numOfRows, stableName, false); // tag name char tagName[TSDB_COL_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(tagName, (*smrSuperTable).me.stbEntry.schemaTag.pSchema[i].name); pColInfoData = taosArrayGet(dataBlock->pDataBlock, 3); - colDataAppend(pColInfoData, numOfRows, tagName, false); + colDataSetVal(pColInfoData, numOfRows, tagName, false); // tag type int8_t tagType = (*smrSuperTable).me.stbEntry.schemaTag.pSchema[i].type; @@ -684,7 +889,7 @@ static int32_t sysTableUserTagsFillOneTableTags(const SSysTableScanInfo* pInfo, (int32_t)(((*smrSuperTable).me.stbEntry.schemaTag.pSchema[i].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)); } varDataSetLen(tagTypeStr, tagTypeLen); - colDataAppend(pColInfoData, numOfRows, (char*)tagTypeStr, false); + colDataSetVal(pColInfoData, numOfRows, (char*)tagTypeStr, false); STagVal tagVal = {0}; tagVal.cid = (*smrSuperTable).me.stbEntry.schemaTag.pSchema[i].colId; @@ -724,7 +929,7 @@ static int32_t sysTableUserTagsFillOneTableTags(const SSysTableScanInfo* pInfo, } } pColInfoData = taosArrayGet(dataBlock->pDataBlock, 5); - colDataAppend(pColInfoData, numOfRows, tagVarChar, + colDataSetVal(pColInfoData, numOfRows, tagVarChar, (tagData == NULL) || (tagType == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(tagData))); taosMemoryFree(tagVarChar); ++numOfRows; @@ -735,6 +940,66 @@ static int32_t sysTableUserTagsFillOneTableTags(const SSysTableScanInfo* pInfo, return TSDB_CODE_SUCCESS; } +static int32_t sysTableUserColsFillOneTableCols(const SSysTableScanInfo* pInfo, const char* dbname, int32_t* pNumOfRows, + const SSDataBlock* dataBlock, char* tName, SSchemaWrapper* schemaRow, + char* tableType) { + if (schemaRow == NULL) { + qError("sysTableUserColsFillOneTableCols schemaRow is NULL"); + return TSDB_CODE_SUCCESS; + } + int32_t numOfRows = *pNumOfRows; + + int32_t numOfCols = schemaRow->nCols; + for (int32_t i = 0; i < numOfCols; ++i) { + SColumnInfoData* pColInfoData = NULL; + + // table name + pColInfoData = taosArrayGet(dataBlock->pDataBlock, 0); + colDataAppend(pColInfoData, numOfRows, tName, false); + + // database name + pColInfoData = taosArrayGet(dataBlock->pDataBlock, 1); + colDataAppend(pColInfoData, numOfRows, dbname, false); + + pColInfoData = taosArrayGet(dataBlock->pDataBlock, 2); + colDataAppend(pColInfoData, numOfRows, tableType, false); + + // col name + char colName[TSDB_COL_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(colName, schemaRow->pSchema[i].name); + pColInfoData = taosArrayGet(dataBlock->pDataBlock, 3); + colDataAppend(pColInfoData, numOfRows, colName, false); + + // col type + int8_t colType = schemaRow->pSchema[i].type; + pColInfoData = taosArrayGet(dataBlock->pDataBlock, 4); + char colTypeStr[VARSTR_HEADER_SIZE + 32]; + int colTypeLen = sprintf(varDataVal(colTypeStr), "%s", tDataTypes[colType].name); + if (colType == TSDB_DATA_TYPE_VARCHAR) { + colTypeLen += sprintf(varDataVal(colTypeStr) + colTypeLen, "(%d)", + (int32_t)(schemaRow->pSchema[i].bytes - VARSTR_HEADER_SIZE)); + } else if (colType == TSDB_DATA_TYPE_NCHAR) { + colTypeLen += sprintf(varDataVal(colTypeStr) + colTypeLen, "(%d)", + (int32_t)((schemaRow->pSchema[i].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)); + } + varDataSetLen(colTypeStr, colTypeLen); + colDataAppend(pColInfoData, numOfRows, (char*)colTypeStr, false); + + pColInfoData = taosArrayGet(dataBlock->pDataBlock, 5); + colDataAppend(pColInfoData, numOfRows, (const char*)&schemaRow->pSchema[i].bytes, false); + + for (int32_t j = 6; j <= 8; ++j) { + pColInfoData = taosArrayGet(dataBlock->pDataBlock, j); + colDataSetNULL(pColInfoData, numOfRows); + } + ++numOfRows; + } + + *pNumOfRows = numOfRows; + + return TSDB_CODE_SUCCESS; +} + static SSDataBlock* buildInfoSchemaTableMetaBlock(char* tableName) { size_t size = 0; const SSysTableMeta* pMeta = NULL; @@ -772,30 +1037,30 @@ int32_t buildDbTableInfoBlock(bool sysInfo, const SSDataBlock* p, const SSysTabl SColumnInfoData* pColInfoData = taosArrayGet(p->pDataBlock, 0); STR_TO_VARSTR(n, pm->name); - colDataAppend(pColInfoData, numOfRows, n, false); + colDataSetVal(pColInfoData, numOfRows, n, false); // database name STR_TO_VARSTR(n, dbName); pColInfoData = taosArrayGet(p->pDataBlock, 1); - colDataAppend(pColInfoData, numOfRows, n, false); + colDataSetVal(pColInfoData, numOfRows, n, false); // create time pColInfoData = taosArrayGet(p->pDataBlock, 2); - colDataAppendNULL(pColInfoData, numOfRows); + colDataSetNULL(pColInfoData, numOfRows); // number of columns pColInfoData = taosArrayGet(p->pDataBlock, 3); - colDataAppend(pColInfoData, numOfRows, (char*)&pm->colNum, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&pm->colNum, false); for (int32_t j = 4; j <= 8; ++j) { pColInfoData = taosArrayGet(p->pDataBlock, j); - colDataAppendNULL(pColInfoData, numOfRows); + colDataSetNULL(pColInfoData, numOfRows); } STR_TO_VARSTR(n, "SYSTEM_TABLE"); pColInfoData = taosArrayGet(p->pDataBlock, 9); - colDataAppend(pColInfoData, numOfRows, n, false); + colDataSetVal(pColInfoData, numOfRows, n, false); numOfRows += 1; } @@ -863,22 +1128,22 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) { // table name SColumnInfoData* pColInfoData = taosArrayGet(p->pDataBlock, 0); - colDataAppend(pColInfoData, numOfRows, n, false); + colDataSetVal(pColInfoData, numOfRows, n, false); // database name pColInfoData = taosArrayGet(p->pDataBlock, 1); - colDataAppend(pColInfoData, numOfRows, dbname, false); + colDataSetVal(pColInfoData, numOfRows, dbname, false); // vgId pColInfoData = taosArrayGet(p->pDataBlock, 6); - colDataAppend(pColInfoData, numOfRows, (char*)&vgId, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&vgId, false); int32_t tableType = mr.me.type; if (tableType == TSDB_CHILD_TABLE) { // create time int64_t ts = mr.me.ctbEntry.ctime; pColInfoData = taosArrayGet(p->pDataBlock, 2); - colDataAppend(pColInfoData, numOfRows, (char*)&ts, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&ts, false); SMetaReader mr1 = {0}; metaReaderInit(&mr1, pInfo->readHandle.meta, META_READER_NOLOCK); @@ -893,12 +1158,12 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) { T_LONG_JMP(pTaskInfo->env, terrno); } pColInfoData = taosArrayGet(p->pDataBlock, 3); - colDataAppend(pColInfoData, numOfRows, (char*)&mr1.me.stbEntry.schemaRow.nCols, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&mr1.me.stbEntry.schemaRow.nCols, false); // super table name STR_TO_VARSTR(n, mr1.me.name); pColInfoData = taosArrayGet(p->pDataBlock, 4); - colDataAppend(pColInfoData, numOfRows, n, false); + colDataSetVal(pColInfoData, numOfRows, n, false); metaReaderClear(&mr1); // table comment @@ -906,59 +1171,59 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) { if (mr.me.ctbEntry.commentLen > 0) { char comment[TSDB_TB_COMMENT_LEN + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, mr.me.ctbEntry.comment); - colDataAppend(pColInfoData, numOfRows, comment, false); + colDataSetVal(pColInfoData, numOfRows, comment, false); } else if (mr.me.ctbEntry.commentLen == 0) { char comment[VARSTR_HEADER_SIZE + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, ""); - colDataAppend(pColInfoData, numOfRows, comment, false); + colDataSetVal(pColInfoData, numOfRows, comment, false); } else { - colDataAppendNULL(pColInfoData, numOfRows); + colDataSetNULL(pColInfoData, numOfRows); } // uid pColInfoData = taosArrayGet(p->pDataBlock, 5); - colDataAppend(pColInfoData, numOfRows, (char*)&mr.me.uid, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&mr.me.uid, false); // ttl pColInfoData = taosArrayGet(p->pDataBlock, 7); - colDataAppend(pColInfoData, numOfRows, (char*)&mr.me.ctbEntry.ttlDays, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&mr.me.ctbEntry.ttlDays, false); STR_TO_VARSTR(n, "CHILD_TABLE"); } else if (tableType == TSDB_NORMAL_TABLE) { // create time pColInfoData = taosArrayGet(p->pDataBlock, 2); - colDataAppend(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.ctime, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.ctime, false); // number of columns pColInfoData = taosArrayGet(p->pDataBlock, 3); - colDataAppend(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.schemaRow.nCols, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.schemaRow.nCols, false); // super table name pColInfoData = taosArrayGet(p->pDataBlock, 4); - colDataAppendNULL(pColInfoData, numOfRows); + colDataSetNULL(pColInfoData, numOfRows); // table comment pColInfoData = taosArrayGet(p->pDataBlock, 8); if (mr.me.ntbEntry.commentLen > 0) { char comment[TSDB_TB_COMMENT_LEN + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, mr.me.ntbEntry.comment); - colDataAppend(pColInfoData, numOfRows, comment, false); + colDataSetVal(pColInfoData, numOfRows, comment, false); } else if (mr.me.ntbEntry.commentLen == 0) { char comment[VARSTR_HEADER_SIZE + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, ""); - colDataAppend(pColInfoData, numOfRows, comment, false); + colDataSetVal(pColInfoData, numOfRows, comment, false); } else { - colDataAppendNULL(pColInfoData, numOfRows); + colDataSetNULL(pColInfoData, numOfRows); } // uid pColInfoData = taosArrayGet(p->pDataBlock, 5); - colDataAppend(pColInfoData, numOfRows, (char*)&mr.me.uid, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&mr.me.uid, false); // ttl pColInfoData = taosArrayGet(p->pDataBlock, 7); - colDataAppend(pColInfoData, numOfRows, (char*)&mr.me.ntbEntry.ttlDays, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&mr.me.ntbEntry.ttlDays, false); STR_TO_VARSTR(n, "NORMAL_TABLE"); // impl later @@ -967,7 +1232,7 @@ static SSDataBlock* sysTableBuildUserTablesByUids(SOperatorInfo* pOperator) { metaReaderClear(&mr); pColInfoData = taosArrayGet(p->pDataBlock, 9); - colDataAppend(pColInfoData, numOfRows, n, false); + colDataSetVal(pColInfoData, numOfRows, n, false); if (++numOfRows >= pOperator->resultInfo.capacity) { p->info.rows = numOfRows; @@ -1036,27 +1301,27 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) { char n[TSDB_TABLE_NAME_LEN + VARSTR_HEADER_SIZE] = {0}; int32_t ret = 0; - while ((ret = metaTbCursorNext(pInfo->pCur)) == 0) { + while ((ret = metaTbCursorNext(pInfo->pCur, TSDB_SUPER_TABLE)) == 0) { STR_TO_VARSTR(n, pInfo->pCur->mr.me.name); // table name SColumnInfoData* pColInfoData = taosArrayGet(p->pDataBlock, 0); - colDataAppend(pColInfoData, numOfRows, n, false); + colDataSetVal(pColInfoData, numOfRows, n, false); // database name pColInfoData = taosArrayGet(p->pDataBlock, 1); - colDataAppend(pColInfoData, numOfRows, dbname, false); + colDataSetVal(pColInfoData, numOfRows, dbname, false); // vgId pColInfoData = taosArrayGet(p->pDataBlock, 6); - colDataAppend(pColInfoData, numOfRows, (char*)&vgId, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&vgId, false); int32_t tableType = pInfo->pCur->mr.me.type; if (tableType == TSDB_CHILD_TABLE) { // create time int64_t ts = pInfo->pCur->mr.me.ctbEntry.ctime; pColInfoData = taosArrayGet(p->pDataBlock, 2); - colDataAppend(pColInfoData, numOfRows, (char*)&ts, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&ts, false); SMetaReader mr = {0}; metaReaderInit(&mr, pInfo->readHandle.meta, META_READER_NOLOCK); @@ -1074,12 +1339,12 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) { // number of columns pColInfoData = taosArrayGet(p->pDataBlock, 3); - colDataAppend(pColInfoData, numOfRows, (char*)&mr.me.stbEntry.schemaRow.nCols, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&mr.me.stbEntry.schemaRow.nCols, false); // super table name STR_TO_VARSTR(n, mr.me.name); pColInfoData = taosArrayGet(p->pDataBlock, 4); - colDataAppend(pColInfoData, numOfRows, n, false); + colDataSetVal(pColInfoData, numOfRows, n, false); metaReaderClear(&mr); // table comment @@ -1087,64 +1352,64 @@ static SSDataBlock* sysTableBuildUserTables(SOperatorInfo* pOperator) { if (pInfo->pCur->mr.me.ctbEntry.commentLen > 0) { char comment[TSDB_TB_COMMENT_LEN + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, pInfo->pCur->mr.me.ctbEntry.comment); - colDataAppend(pColInfoData, numOfRows, comment, false); + colDataSetVal(pColInfoData, numOfRows, comment, false); } else if (pInfo->pCur->mr.me.ctbEntry.commentLen == 0) { char comment[VARSTR_HEADER_SIZE + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, ""); - colDataAppend(pColInfoData, numOfRows, comment, false); + colDataSetVal(pColInfoData, numOfRows, comment, false); } else { - colDataAppendNULL(pColInfoData, numOfRows); + colDataSetNULL(pColInfoData, numOfRows); } // uid pColInfoData = taosArrayGet(p->pDataBlock, 5); - colDataAppend(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.uid, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.uid, false); // ttl pColInfoData = taosArrayGet(p->pDataBlock, 7); - colDataAppend(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ctbEntry.ttlDays, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ctbEntry.ttlDays, false); STR_TO_VARSTR(n, "CHILD_TABLE"); } else if (tableType == TSDB_NORMAL_TABLE) { // create time pColInfoData = taosArrayGet(p->pDataBlock, 2); - colDataAppend(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.ctime, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.ctime, false); // number of columns pColInfoData = taosArrayGet(p->pDataBlock, 3); - colDataAppend(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.schemaRow.nCols, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.schemaRow.nCols, false); // super table name pColInfoData = taosArrayGet(p->pDataBlock, 4); - colDataAppendNULL(pColInfoData, numOfRows); + colDataSetNULL(pColInfoData, numOfRows); // table comment pColInfoData = taosArrayGet(p->pDataBlock, 8); if (pInfo->pCur->mr.me.ntbEntry.commentLen > 0) { char comment[TSDB_TB_COMMENT_LEN + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, pInfo->pCur->mr.me.ntbEntry.comment); - colDataAppend(pColInfoData, numOfRows, comment, false); + colDataSetVal(pColInfoData, numOfRows, comment, false); } else if (pInfo->pCur->mr.me.ntbEntry.commentLen == 0) { char comment[VARSTR_HEADER_SIZE + VARSTR_HEADER_SIZE] = {0}; STR_TO_VARSTR(comment, ""); - colDataAppend(pColInfoData, numOfRows, comment, false); + colDataSetVal(pColInfoData, numOfRows, comment, false); } else { - colDataAppendNULL(pColInfoData, numOfRows); + colDataSetNULL(pColInfoData, numOfRows); } // uid pColInfoData = taosArrayGet(p->pDataBlock, 5); - colDataAppend(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.uid, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.uid, false); // ttl pColInfoData = taosArrayGet(p->pDataBlock, 7); - colDataAppend(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.ttlDays, false); + colDataSetVal(pColInfoData, numOfRows, (char*)&pInfo->pCur->mr.me.ntbEntry.ttlDays, false); STR_TO_VARSTR(n, "NORMAL_TABLE"); } pColInfoData = taosArrayGet(p->pDataBlock, 9); - colDataAppend(pColInfoData, numOfRows, n, false); + colDataSetVal(pColInfoData, numOfRows, n, false); if (++numOfRows >= pOperator->resultInfo.capacity) { p->info.rows = numOfRows; @@ -1220,11 +1485,7 @@ static SSDataBlock* sysTableScanUserTables(SOperatorInfo* pOperator) { pInfo->pIdx->init = 1; SSDataBlock* blk = sysTableBuildUserTablesByUids(pOperator); return blk; - } else if (flt == -2) { - qDebug("%s failed to get sys table info by idx, empty result", GET_TASKID(pTaskInfo)); - return NULL; - } else if (flt == -1) { - // not idx + } else if ((flt == -1) || (flt == -2)) { qDebug("%s failed to get sys table info by idx, scan sys table one by one", GET_TASKID(pTaskInfo)); } } else if (pCondition != NULL && (pInfo->pIdx != NULL && pInfo->pIdx->init == 1)) { @@ -1322,6 +1583,10 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) { if (pInfo->showRewrite) { getDBNameFromCondition(pInfo->pCondition, dbName); sprintf(pInfo->req.db, "%d.%s", pInfo->accountId, dbName); + } else if (strncasecmp(name, TSDB_INS_TABLE_COLS, TSDB_TABLE_FNAME_LEN) == 0) { + getDBNameFromCondition(pInfo->pCondition, dbName); + if (dbName[0]) sprintf(pInfo->req.db, "%d.%s", pInfo->accountId, dbName); + sysTableIsCondOnOneTable(pInfo->pCondition, pInfo->req.filterTb); } SSDataBlock* pBlock = NULL; @@ -1329,6 +1594,8 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) { pBlock = sysTableScanUserTables(pOperator); } else if (strncasecmp(name, TSDB_INS_TABLE_TAGS, TSDB_TABLE_FNAME_LEN) == 0) { pBlock = sysTableScanUserTags(pOperator); + } else if (strncasecmp(name, TSDB_INS_TABLE_COLS, TSDB_TABLE_FNAME_LEN) == 0 && pInfo->readHandle.mnd == NULL) { + pBlock = sysTableScanUserCols(pOperator); } else if (strncasecmp(name, TSDB_INS_TABLE_STABLES, TSDB_TABLE_FNAME_LEN) == 0 && pInfo->showRewrite && IS_SYS_DBNAME(dbName)) { pBlock = sysTableScanUserSTables(pOperator); @@ -1343,7 +1610,7 @@ static SSDataBlock* doSysTableScan(SOperatorInfo* pOperator) { setOperatorCompleted(pOperator); } - return pBlock->info.rows > 0? pBlock:NULL; + return pBlock->info.rows > 0 ? pBlock : NULL; } else { return NULL; } @@ -1357,11 +1624,10 @@ static void sysTableScanFillTbName(SOperatorInfo* pOperator, const SSysTableScan if (pInfo->tbnameSlotId != -1) { SColumnInfoData* pColumnInfoData = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, pInfo->tbnameSlotId); - char varTbName[TSDB_TABLE_FNAME_LEN - 1 + VARSTR_HEADER_SIZE] = {0}; - memcpy(varDataVal(varTbName), name, strlen(name)); - varDataSetLen(varTbName, strlen(name)); + char varTbName[TSDB_TABLE_FNAME_LEN - 1 + VARSTR_HEADER_SIZE] = {0}; + STR_TO_VARSTR(varTbName, name); - colDataAppendNItems(pColumnInfoData, 0, varTbName, pBlock->info.rows); + colDataSetNItems(pColumnInfoData, 0, varTbName, pBlock->info.rows, true); } doFilter(pBlock, pOperator->exprSupp.pFilterInfo, NULL); @@ -1406,7 +1672,7 @@ static SSDataBlock* sysTableScanFromMNode(SOperatorInfo* pOperator, SSysTableSca tsem_wait(&pInfo->ready); if (pTaskInfo->code) { - qDebug("%s load meta data from mnode failed, totalRows:%" PRIu64 ", code:%s", GET_TASKID(pTaskInfo), + qError("%s load meta data from mnode failed, totalRows:%" PRIu64 ", code:%s", GET_TASKID(pTaskInfo), pInfo->loadInfo.totalRows, tstrerror(pTaskInfo->code)); return NULL; } @@ -1442,6 +1708,7 @@ static SSDataBlock* sysTableScanFromMNode(SOperatorInfo* pOperator, SSysTableSca SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScanPhysiNode* pScanPhyNode, const char* pUser, SExecTaskInfo* pTaskInfo) { + int32_t code = TDB_CODE_SUCCESS; SSysTableScanInfo* pInfo = taosMemoryCalloc(1, sizeof(SSysTableScanInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { @@ -1452,7 +1719,7 @@ SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScan SDataBlockDescNode* pDescNode = pScanNode->node.pOutputDataBlockDesc; int32_t num = 0; - int32_t code = extractColMatchInfo(pScanNode->pScanCols, pDescNode, &num, COL_MATCH_FROM_COL_ID, &pInfo->matchInfo); + code = extractColMatchInfo(pScanNode->pScanCols, pDescNode, &num, COL_MATCH_FROM_COL_ID, &pInfo->matchInfo); if (code != TSDB_CODE_SUCCESS) { goto _error; } @@ -1460,7 +1727,7 @@ SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScan extractTbnameSlotId(pInfo, pScanNode); pInfo->accountId = pScanPhyNode->accountId; - pInfo->pUser = taosMemoryStrDup((void*)pUser); + pInfo->pUser = taosStrdup((void*)pUser); pInfo->sysInfo = pScanPhyNode->sysInfo; pInfo->showRewrite = pScanPhyNode->showRewrite; pInfo->pRes = createDataBlockFromDescNode(pDescNode); @@ -1489,10 +1756,11 @@ SOperatorInfo* createSysTableScanOperatorInfo(void* readHandle, SSystemTableScan setOperatorInfo(pOperator, "SysTableScanOperator", QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN, false, OP_NOT_OPENED, pInfo, pTaskInfo); pOperator->exprSupp.numOfExprs = taosArrayGetSize(pInfo->pRes->pDataBlock); - pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doSysTableScan, NULL, destroySysScanOperator, optrDefaultBufFn, NULL); + pOperator->fpSet = + createOperatorFpSet(optrDummyOpenFn, doSysTableScan, NULL, destroySysScanOperator, optrDefaultBufFn, NULL); return pOperator; - _error: +_error: if (pInfo != NULL) { destroySysScanOperator(pInfo); } @@ -1528,7 +1796,8 @@ void destroySysScanOperator(void* param) { const char* name = tNameGetTableName(&pInfo->name); if (strncasecmp(name, TSDB_INS_TABLE_TABLES, TSDB_TABLE_FNAME_LEN) == 0 || - strncasecmp(name, TSDB_INS_TABLE_TAGS, TSDB_TABLE_FNAME_LEN) == 0 || pInfo->pCur != NULL) { + strncasecmp(name, TSDB_INS_TABLE_TAGS, TSDB_TABLE_FNAME_LEN) == 0 || + strncasecmp(name, TSDB_INS_TABLE_COLS, TSDB_TABLE_FNAME_LEN) == 0 || pInfo->pCur != NULL) { metaCloseTbCursor(pInfo->pCur); pInfo->pCur = NULL; } @@ -1538,6 +1807,11 @@ void destroySysScanOperator(void* param) { pInfo->pIdx = NULL; } + if(pInfo->pSchema) { + taosHashCleanup(pInfo->pSchema); + pInfo->pSchema = NULL; + } + taosArrayDestroy(pInfo->matchInfo.pList); taosMemoryFreeClear(pInfo->pUser); @@ -1921,14 +2195,14 @@ static SSDataBlock* doBlockInfoScan(SOperatorInfo* pOperator) { tSerializeBlockDistInfo(varDataVal(p), len, &blockDistInfo); varDataSetLen(p, len); - colDataAppend(pColInfo, 0, p, false); + colDataSetVal(pColInfo, 0, p, false); taosMemoryFree(p); // make the valgrind happy that all memory buffer has been initialized already. if (slotId != 0) { SColumnInfoData* p1 = taosArrayGet(pBlock->pDataBlock, 0); - int64_t v = 0; - colDataAppendInt64(p1, 0, &v); + int64_t v = 0; + colDataSetInt64(p1, 0, &v); } pBlock->info.rows = 1; @@ -1937,10 +2211,11 @@ static SSDataBlock* doBlockInfoScan(SOperatorInfo* pOperator) { } static void destroyBlockDistScanOperatorInfo(void* param) { - SBlockDistInfo* pDistInfo = (SBlockDistInfo*)param; - blockDataDestroy(pDistInfo->pResBlock); - tsdbReaderClose(pDistInfo->pHandle); - taosMemoryFreeClear(param); + SBlockDistInfo* pDistInfo = (SBlockDistInfo*)param; + blockDataDestroy(pDistInfo->pResBlock); + tsdbReaderClose(pDistInfo->pHandle); + tableListDestroy(pDistInfo->pTableListInfo); + taosMemoryFreeClear(param); } static int32_t initTableblockDistQueryCond(uint64_t uid, SQueryTableDataCond* pCond) { @@ -1971,7 +2246,7 @@ static int32_t initTableblockDistQueryCond(uint64_t uid, SQueryTableDataCond* pC } SOperatorInfo* createDataBlockInfoScanOperator(SReadHandle* readHandle, SBlockDistScanPhysiNode* pBlockScanNode, - SExecTaskInfo* pTaskInfo) { + STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo) { SBlockDistInfo* pInfo = taosMemoryCalloc(1, sizeof(SBlockDistInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { @@ -1989,11 +2264,11 @@ SOperatorInfo* createDataBlockInfoScanOperator(SReadHandle* readHandle, SBlockDi goto _error; } - STableListInfo* pTableListInfo = pTaskInfo->pTableInfoList; - size_t num = tableListGetSize(pTableListInfo); - void* pList = tableListGetInfo(pTableListInfo, 0); + pInfo->pTableListInfo = pTableListInfo; + size_t num = tableListGetSize(pTableListInfo); + void* pList = tableListGetInfo(pTableListInfo, 0); - code = tsdbReaderOpen(readHandle->vnode, &cond, pList, num, pInfo->pResBlock, &pInfo->pHandle, pTaskInfo->id.str); + code = tsdbReaderOpen(readHandle->vnode, &cond, pList, num, pInfo->pResBlock, &pInfo->pHandle, pTaskInfo->id.str, false, NULL); cleanupQueryTableDataCond(&cond); if (code != 0) { goto _error; @@ -2001,7 +2276,7 @@ SOperatorInfo* createDataBlockInfoScanOperator(SReadHandle* readHandle, SBlockDi } pInfo->readHandle = *readHandle; - pInfo->uid = (pBlockScanNode->suid != 0)? pBlockScanNode->suid:pBlockScanNode->uid; + pInfo->uid = (pBlockScanNode->suid != 0) ? pBlockScanNode->suid : pBlockScanNode->uid; int32_t numOfCols = 0; SExprInfo* pExprInfo = createExprInfo(pBlockScanNode->pScanPseudoCols, NULL, &numOfCols); @@ -2012,8 +2287,8 @@ SOperatorInfo* createDataBlockInfoScanOperator(SReadHandle* readHandle, SBlockDi setOperatorInfo(pOperator, "DataBlockDistScanOperator", QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN, false, OP_NOT_OPENED, pInfo, pTaskInfo); - pOperator->fpSet = - createOperatorFpSet(optrDummyOpenFn, doBlockInfoScan, NULL, destroyBlockDistScanOperatorInfo, optrDefaultBufFn, NULL); + pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doBlockInfoScan, NULL, destroyBlockDistScanOperatorInfo, + optrDefaultBufFn, NULL); return pOperator; _error: diff --git a/source/libs/executor/src/tfill.c b/source/libs/executor/src/tfill.c index ed786003d52eba6fdd1feb3178beec6bfd698ed6..c98746c241b63c036e3a37b352d6523a0efe4530 100644 --- a/source/libs/executor/src/tfill.c +++ b/source/libs/executor/src/tfill.c @@ -20,7 +20,7 @@ #include "tmsg.h" #include "ttypes.h" -#include "executorimpl.h" +#include "executorInt.h" #include "tcommon.h" #include "thash.h" #include "ttime.h" @@ -44,7 +44,7 @@ static void setNotFillColumn(SFillInfo* pFillInfo, SColumnInfoData* pDstColInfo, } else { p = FILL_IS_ASC_FILL(pFillInfo) ? &pFillInfo->prev : &pFillInfo->next; } - + SGroupKeys* pKey = taosArrayGet(p->pRowVal, colIdx); doSetVal(pDstColInfo, rowIndex, pKey); } @@ -60,7 +60,7 @@ static void setNullRow(SSDataBlock* pBlock, SFillInfo* pFillInfo, int32_t rowInd setNotFillColumn(pFillInfo, pDstColInfo, rowIndex, i); } } else { - colDataAppendNULL(pDstColInfo, rowIndex); + colDataSetNULL(pDstColInfo, rowIndex); } } } @@ -69,19 +69,19 @@ static void doSetUserSpecifiedValue(SColumnInfoData* pDst, SVariant* pVar, int32 if (pDst->info.type == TSDB_DATA_TYPE_FLOAT) { float v = 0; GET_TYPED_DATA(v, float, pVar->nType, &pVar->i); - colDataAppend(pDst, rowIndex, (char*)&v, false); + colDataSetVal(pDst, rowIndex, (char*)&v, false); } else if (pDst->info.type == TSDB_DATA_TYPE_DOUBLE) { double v = 0; GET_TYPED_DATA(v, double, pVar->nType, &pVar->i); - colDataAppend(pDst, rowIndex, (char*)&v, false); + colDataSetVal(pDst, rowIndex, (char*)&v, false); } else if (IS_SIGNED_NUMERIC_TYPE(pDst->info.type)) { int64_t v = 0; GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i); - colDataAppend(pDst, rowIndex, (char*)&v, false); + colDataSetVal(pDst, rowIndex, (char*)&v, false); } else if (pDst->info.type == TSDB_DATA_TYPE_TIMESTAMP) { - colDataAppend(pDst, rowIndex, (const char*)¤tKey, false); + colDataSetVal(pDst, rowIndex, (const char*)¤tKey, false); } else { // varchar/nchar data - colDataAppendNULL(pDst, rowIndex); + colDataSetNULL(pDst, rowIndex); } } @@ -96,18 +96,18 @@ bool fillIfWindowPseudoColumn(SFillInfo* pFillInfo, SFillColInfo* pCol, SColumnI return false; } if (pCol->pExpr->base.pParam[0].pCol->colType == COLUMN_TYPE_WINDOW_START) { - colDataAppend(pDstColInfoData, rowIndex, (const char*)&pFillInfo->currentKey, false); + colDataSetVal(pDstColInfoData, rowIndex, (const char*)&pFillInfo->currentKey, false); return true; } else if (pCol->pExpr->base.pParam[0].pCol->colType == COLUMN_TYPE_WINDOW_END) { // TODO: include endpoint SInterval* pInterval = &pFillInfo->interval; int64_t windowEnd = taosTimeAdd(pFillInfo->currentKey, pInterval->interval, pInterval->intervalUnit, pInterval->precision); - colDataAppend(pDstColInfoData, rowIndex, (const char*)&windowEnd, false); + colDataSetVal(pDstColInfoData, rowIndex, (const char*)&windowEnd, false); return true; } else if (pCol->pExpr->base.pParam[0].pCol->colType == COLUMN_TYPE_WINDOW_DURATION) { // TODO: include endpoint - colDataAppend(pDstColInfoData, rowIndex, (const char*)&pFillInfo->interval.sliding, false); + colDataSetVal(pDstColInfoData, rowIndex, (const char*)&pFillInfo->interval.sliding, false); return true; } } @@ -163,7 +163,7 @@ static void doFillOneRow(SFillInfo* pFillInfo, SSDataBlock* pBlock, SSDataBlock* } else { SGroupKeys* pKey = taosArrayGet(pFillInfo->prev.pRowVal, i); if (IS_VAR_DATA_TYPE(type) || type == TSDB_DATA_TYPE_BOOL || pKey->isNull) { - colDataAppendNULL(pDstCol, index); + colDataSetNULL(pDstCol, index); continue; } @@ -182,7 +182,7 @@ static void doFillOneRow(SFillInfo* pFillInfo, SSDataBlock* pBlock, SSDataBlock* point = (SPoint){.key = pFillInfo->currentKey, .val = &out}; taosGetLinearInterpolationVal(&point, type, &point1, &point2, type); - colDataAppend(pDstCol, index, (const char*)&out, false); + colDataSetVal(pDstCol, index, (const char*)&out, false); } } } @@ -217,9 +217,9 @@ static void doFillOneRow(SFillInfo* pFillInfo, SSDataBlock* pBlock, SSDataBlock* void doSetVal(SColumnInfoData* pDstCol, int32_t rowIndex, const SGroupKeys* pKey) { if (pKey->isNull) { - colDataAppendNULL(pDstCol, rowIndex); + colDataSetNULL(pDstCol, rowIndex); } else { - colDataAppend(pDstCol, rowIndex, pKey->pData, false); + colDataSetVal(pDstCol, rowIndex, pKey->pData, false); } } @@ -332,14 +332,14 @@ static int32_t fillResultImpl(SFillInfo* pFillInfo, SSDataBlock* pBlock, int32_t char* src = colDataGetData(pSrc, pFillInfo->index); if (!colDataIsNull_s(pSrc, pFillInfo->index)) { - colDataAppend(pDst, index, src, false); + colDataSetVal(pDst, index, src, false); saveColData(pFillInfo->prev.pRowVal, i, src, false); if (pFillInfo->srcTsSlotId == dstSlotId) { pFillInfo->prev.key = *(int64_t*)src; } } else { // the value is null if (pDst->info.type == TSDB_DATA_TYPE_TIMESTAMP) { - colDataAppend(pDst, index, (const char*)&pFillInfo->currentKey, false); + colDataSetVal(pDst, index, (const char*)&pFillInfo->currentKey, false); } else { // i > 0 and data is null , do interpolation if (pFillInfo->type == TSDB_FILL_PREV) { SArray* p = FILL_IS_ASC_FILL(pFillInfo) ? pFillInfo->prev.pRowVal : pFillInfo->next.pRowVal; @@ -347,10 +347,10 @@ static int32_t fillResultImpl(SFillInfo* pFillInfo, SSDataBlock* pBlock, int32_t doSetVal(pDst, index, pKey); } else if (pFillInfo->type == TSDB_FILL_LINEAR) { bool isNull = colDataIsNull_s(pSrc, pFillInfo->index); - colDataAppend(pDst, index, src, isNull); + colDataSetVal(pDst, index, src, isNull); saveColData(pFillInfo->prev.pRowVal, i, src, isNull); // todo: } else if (pFillInfo->type == TSDB_FILL_NULL || pFillInfo->type == TSDB_FILL_NULL_F) { - colDataAppendNULL(pDst, index); + colDataSetNULL(pDst, index); } else if (pFillInfo->type == TSDB_FILL_NEXT) { SArray* p = FILL_IS_ASC_FILL(pFillInfo) ? pFillInfo->next.pRowVal : pFillInfo->prev.pRowVal; SGroupKeys* pKey = taosArrayGet(p, i); @@ -408,7 +408,7 @@ static int64_t appendFilledResult(SFillInfo* pFillInfo, SSDataBlock* pBlock, int pFillInfo->numOfTotal += pFillInfo->numOfCurrent; - assert(pFillInfo->numOfCurrent == resultCapacity); + ASSERT(pFillInfo->numOfCurrent == resultCapacity); return resultCapacity; } @@ -558,7 +558,7 @@ int64_t getNumOfResultsAfterFillGap(SFillInfo* pFillInfo, TSKEY ekey, int32_t ma numOfRes = taosTimeCountInterval(lastKey, pFillInfo->currentKey, pFillInfo->interval.sliding, pFillInfo->interval.slidingUnit, pFillInfo->interval.precision); numOfRes += 1; - assert(numOfRes >= numOfRows); + ASSERT(numOfRes >= numOfRows); } else { // reach the end of data if ((ekey1 < pFillInfo->currentKey && FILL_IS_ASC_FILL(pFillInfo)) || (ekey1 >= pFillInfo->currentKey && !FILL_IS_ASC_FILL(pFillInfo))) { @@ -578,7 +578,12 @@ int32_t taosGetLinearInterpolationVal(SPoint* point, int32_t outputType, SPoint* GET_TYPED_DATA(v1, double, inputType, point1->val); GET_TYPED_DATA(v2, double, inputType, point2->val); - double r = DO_INTERPOLATION(v1, v2, point1->key, point2->key, point->key); + double r = 0; + if (!IS_BOOLEAN_TYPE(inputType)) { + r = DO_INTERPOLATION(v1, v2, point1->key, point2->key, point->key); + } else { + r = (v1 < 1 || v2 < 1) ? 0 : 1; + } SET_TYPED_DATA(point->val, outputType, r); return TSDB_CODE_SUCCESS; @@ -588,14 +593,14 @@ int64_t taosFillResultDataBlock(SFillInfo* pFillInfo, SSDataBlock* p, int32_t ca int32_t remain = taosNumOfRemainRows(pFillInfo); int64_t numOfRes = getNumOfResultsAfterFillGap(pFillInfo, pFillInfo->end, capacity); - assert(numOfRes <= capacity); + ASSERT(numOfRes <= capacity); // no data existed for fill operation now, append result according to the fill strategy if (remain == 0) { appendFilledResult(pFillInfo, p, numOfRes); } else { fillResultImpl(pFillInfo, p, (int32_t)numOfRes); - assert(numOfRes == pFillInfo->numOfCurrent); + ASSERT(numOfRes == pFillInfo->numOfCurrent); } qDebug("fill:%p, generated fill result, src block:%d, index:%d, brange:%" PRId64 "-%" PRId64 ", currentKey:%" PRId64 @@ -630,6 +635,7 @@ SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfFillExpr, SExprIn nodesValueNodeToVariant(pv, &pFillCol[i].fillVal); } } + pFillCol->numOfFillExpr = numOfFillExpr; for (int32_t i = 0; i < numOfNoFillExpr; ++i) { SExprInfo* pExprInfo = &pNotFillExpr[i]; diff --git a/source/libs/executor/src/timesliceoperator.c b/source/libs/executor/src/timesliceoperator.c index 3bf597f3b398c972233ff3edb307ac25cc7201ce..168bdf3f7c63e9efbc416b10b246987c4284273d 100644 --- a/source/libs/executor/src/timesliceoperator.c +++ b/source/libs/executor/src/timesliceoperator.c @@ -12,10 +12,12 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include "executorimpl.h" +#include "executorInt.h" #include "filter.h" #include "function.h" #include "functionMgt.h" +#include "operator.h" +#include "querytask.h" #include "tcommon.h" #include "tcompare.h" #include "tdatablock.h" @@ -91,7 +93,6 @@ static void doKeepLinearInfo(STimeSliceOperatorInfo* pSliceInfo, const SSDataBlo SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, pSliceInfo->tsCol.slotId); SFillLinearInfo* pLinearInfo = taosArrayGet(pSliceInfo->pLinearInfo, i); - if (!IS_MATHABLE_TYPE(pColInfoData->info.type)) { continue; } @@ -100,7 +101,6 @@ static void doKeepLinearInfo(STimeSliceOperatorInfo* pSliceInfo, const SSDataBlo // TODO: optimize to ignore null values for linear interpolation. if (!pLinearInfo->isStartSet) { if (!colDataIsNull_s(pColInfoData, rowIndex)) { - pLinearInfo->start.key = *(int64_t*)colDataGetData(pTsCol, rowIndex); char* p = colDataGetData(pColInfoData, rowIndex); if (IS_VAR_DATA_TYPE(pColInfoData->info.type)) { @@ -144,10 +144,8 @@ static void doKeepLinearInfo(STimeSliceOperatorInfo* pSliceInfo, const SSDataBlo } } } - } - static FORCE_INLINE int32_t timeSliceEnsureBlockCapacity(STimeSliceOperatorInfo* pSliceInfo, SSDataBlock* pBlock) { if (pBlock->info.rows < pBlock->info.capacity) { return TSDB_CODE_SUCCESS; @@ -160,8 +158,18 @@ static FORCE_INLINE int32_t timeSliceEnsureBlockCapacity(STimeSliceOperatorInfo* return TSDB_CODE_SUCCESS; } +static bool isIrowtsPseudoColumn(SExprInfo* pExprInfo) { + char *name = pExprInfo->pExpr->_function.functionName; + return (IS_TIMESTAMP_TYPE(pExprInfo->base.resSchema.type) && strcasecmp(name, "_irowts") == 0); +} + +static bool isIsfilledPseudoColumn(SExprInfo* pExprInfo) { + char *name = pExprInfo->pExpr->_function.functionName; + return (IS_BOOLEAN_TYPE(pExprInfo->base.resSchema.type) && strcasecmp(name, "_isfilled") == 0); +} -static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp* pExprSup, SSDataBlock* pResBlock, bool beforeTs) { +static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp* pExprSup, SSDataBlock* pResBlock, + bool beforeTs) { int32_t rows = pResBlock->info.rows; timeSliceEnsureBlockCapacity(pSliceInfo, pResBlock); // todo set the correct primary timestamp column @@ -174,8 +182,12 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp int32_t dstSlot = pExprInfo->base.resSchema.slotId; SColumnInfoData* pDst = taosArrayGet(pResBlock->pDataBlock, dstSlot); - if (IS_TIMESTAMP_TYPE(pExprInfo->base.resSchema.type)) { - colDataAppend(pDst, rows, (char*)&pSliceInfo->current, false); + if (isIrowtsPseudoColumn(pExprInfo)) { + colDataSetVal(pDst, rows, (char*)&pSliceInfo->current, false); + continue; + } else if (isIsfilledPseudoColumn(pExprInfo)) { + bool isFilled = true; + colDataAppend(pDst, pResBlock->info.rows, (char*)&isFilled, false); continue; } @@ -183,7 +195,7 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp switch (pSliceInfo->fillType) { case TSDB_FILL_NULL: case TSDB_FILL_NULL_F: { - colDataAppendNULL(pDst, rows); + colDataSetNULL(pDst, rows); break; } @@ -194,15 +206,23 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp if (pDst->info.type == TSDB_DATA_TYPE_FLOAT) { float v = 0; GET_TYPED_DATA(v, float, pVar->nType, &pVar->i); - colDataAppend(pDst, rows, (char*)&v, false); + colDataSetVal(pDst, rows, (char*)&v, false); } else if (pDst->info.type == TSDB_DATA_TYPE_DOUBLE) { double v = 0; GET_TYPED_DATA(v, double, pVar->nType, &pVar->i); - colDataAppend(pDst, rows, (char*)&v, false); + colDataSetVal(pDst, rows, (char*)&v, false); } else if (IS_SIGNED_NUMERIC_TYPE(pDst->info.type)) { int64_t v = 0; GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i); - colDataAppend(pDst, rows, (char*)&v, false); + colDataSetVal(pDst, rows, (char*)&v, false); + } else if (IS_BOOLEAN_TYPE(pDst->info.type)) { + bool v = false; + if (!IS_VAR_DATA_TYPE(pVar->nType)) { + GET_TYPED_DATA(v, bool, pVar->nType, &pVar->i); + } else { + v = taosStr2Int8(varDataVal(pVar->pz), NULL, 10); + } + colDataSetVal(pDst, rows, (char*)&v, false); } break; } @@ -224,14 +244,19 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp break; } + if (end.key != INT64_MIN && end.key < pSliceInfo->current) { + hasInterp = false; + break; + } + if (start.key == INT64_MIN || end.key == INT64_MIN) { - colDataAppendNULL(pDst, rows); + colDataSetNULL(pDst, rows); break; } current.val = taosMemoryCalloc(pLinearInfo->bytes, 1); taosGetLinearInterpolationVal(¤t, pLinearInfo->type, &start, &end, pLinearInfo->type); - colDataAppend(pDst, rows, (char*)current.val, false); + colDataSetVal(pDst, rows, (char*)current.val, false); taosMemoryFree(current.val); break; @@ -244,9 +269,9 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp SGroupKeys* pkey = taosArrayGet(pSliceInfo->pPrevRow, srcSlot); if (pkey->isNull == false) { - colDataAppend(pDst, rows, pkey->pData, false); + colDataSetVal(pDst, rows, pkey->pData, false); } else { - colDataAppendNULL(pDst, rows); + colDataSetNULL(pDst, rows); } break; } @@ -259,9 +284,9 @@ static bool genInterpolationResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp SGroupKeys* pkey = taosArrayGet(pSliceInfo->pNextRow, srcSlot); if (pkey->isNull == false) { - colDataAppend(pDst, rows, pkey->pData, false); + colDataSetVal(pDst, rows, pkey->pData, false); } else { - colDataAppendNULL(pDst, rows); + colDataSetNULL(pDst, rows); } break; } @@ -288,19 +313,22 @@ static void addCurrentRowToResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp* int32_t dstSlot = pExprInfo->base.resSchema.slotId; SColumnInfoData* pDst = taosArrayGet(pResBlock->pDataBlock, dstSlot); - if (IS_TIMESTAMP_TYPE(pExprInfo->base.resSchema.type)) { - colDataAppend(pDst, pResBlock->info.rows, (char*)&pSliceInfo->current, false); + if (isIrowtsPseudoColumn(pExprInfo)) { + colDataSetVal(pDst, pResBlock->info.rows, (char*)&pSliceInfo->current, false); + } else if (isIsfilledPseudoColumn(pExprInfo)) { + bool isFilled = false; + colDataSetVal(pDst, pResBlock->info.rows, (char*)&isFilled, false); } else { int32_t srcSlot = pExprInfo->base.pParam[0].pCol->slotId; SColumnInfoData* pSrc = taosArrayGet(pSrcBlock->pDataBlock, srcSlot); if (colDataIsNull_s(pSrc, index)) { - colDataAppendNULL(pDst, pResBlock->info.rows); + colDataSetNULL(pDst, pResBlock->info.rows); continue; } char* v = colDataGetData(pSrc, index); - colDataAppend(pDst, pResBlock->info.rows, v, false); + colDataSetVal(pDst, pResBlock->info.rows, v, false); } } @@ -308,7 +336,6 @@ static void addCurrentRowToResult(STimeSliceOperatorInfo* pSliceInfo, SExprSupp* return; } - static int32_t initPrevRowsKeeper(STimeSliceOperatorInfo* pInfo, SSDataBlock* pBlock) { if (pInfo->pPrevRow != NULL) { return TSDB_CODE_SUCCESS; @@ -480,11 +507,12 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) { int64_t nextTs = *(int64_t*)colDataGetData(pTsCol, i + 1); if (nextTs > pSliceInfo->current) { while (pSliceInfo->current < nextTs && pSliceInfo->current <= pSliceInfo->win.ekey) { - if (!genInterpolationResult(pSliceInfo, &pOperator->exprSupp, pResBlock, false) && pSliceInfo->fillType == TSDB_FILL_LINEAR) { + if (!genInterpolationResult(pSliceInfo, &pOperator->exprSupp, pResBlock, false) && + pSliceInfo->fillType == TSDB_FILL_LINEAR) { break; } else { - pSliceInfo->current = - taosTimeAdd(pSliceInfo->current, pInterval->interval, pInterval->intervalUnit, pInterval->precision); + pSliceInfo->current = taosTimeAdd(pSliceInfo->current, pInterval->interval, pInterval->intervalUnit, + pInterval->precision); } } @@ -504,7 +532,8 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) { doKeepLinearInfo(pSliceInfo, pBlock, i); while (pSliceInfo->current < ts && pSliceInfo->current <= pSliceInfo->win.ekey) { - if (!genInterpolationResult(pSliceInfo, &pOperator->exprSupp, pResBlock, true) && pSliceInfo->fillType == TSDB_FILL_LINEAR) { + if (!genInterpolationResult(pSliceInfo, &pOperator->exprSupp, pResBlock, true) && + pSliceInfo->fillType == TSDB_FILL_LINEAR) { break; } else { pSliceInfo->current = @@ -599,14 +628,15 @@ SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode setOperatorInfo(pOperator, "TimeSliceOperator", QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC, false, OP_NOT_OPENED, pInfo, pTaskInfo); - pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTimeslice, NULL, destroyTimeSliceOperatorInfo, optrDefaultBufFn, NULL); + pOperator->fpSet = + createOperatorFpSet(optrDummyOpenFn, doTimeslice, NULL, destroyTimeSliceOperatorInfo, optrDefaultBufFn, NULL); blockDataEnsureCapacity(pInfo->pRes, pOperator->resultInfo.capacity); code = appendDownstream(pOperator, &downstream, 1); return pOperator; - _error: +_error: taosMemoryFree(pInfo); taosMemoryFree(pOperator); pTaskInfo->code = TSDB_CODE_OUT_OF_MEMORY; @@ -638,6 +668,9 @@ void destroyTimeSliceOperatorInfo(void* param) { taosArrayDestroy(pInfo->pLinearInfo); cleanupExprSupp(&pInfo->scalarSup); + for (int32_t i = 0; i < pInfo->pFillColInfo->numOfFillExpr; ++i) { + taosVariantDestroy(&pInfo->pFillColInfo[i].fillVal); + } taosMemoryFree(pInfo->pFillColInfo); taosMemoryFreeClear(param); } diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c index 15f803125c043bf23e6bde5e77fa5dff4d25c534..8cf5813ad55e40b945765817490823f73dc5a187 100644 --- a/source/libs/executor/src/timewindowoperator.c +++ b/source/libs/executor/src/timewindowoperator.c @@ -12,10 +12,12 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include "executorimpl.h" +#include "executorInt.h" #include "filter.h" #include "function.h" #include "functionMgt.h" +#include "operator.h" +#include "querytask.h" #include "tcommon.h" #include "tcompare.h" #include "tdatablock.h" @@ -25,6 +27,12 @@ #define IS_FINAL_OP(op) ((op)->isFinal) #define DEAULT_DELETE_MARK (1000LL * 60LL * 60LL * 24LL * 365LL * 10LL); +typedef struct SStateWindowInfo { + SResultWindowInfo winInfo; + SStateKeys* pStateKey; +} SStateWindowInfo; + + typedef struct SSessionAggOperatorInfo { SOptrBasicInfo binfo; SAggSupporter aggSup; @@ -78,7 +86,7 @@ static int32_t setTimeWindowOutputBuf(SResultRowInfo* pResultRowInfo, STimeWindo int32_t numOfOutput, int32_t* rowEntryInfoOffset, SAggSupporter* pAggSup, SExecTaskInfo* pTaskInfo) { SResultRow* pResultRow = doSetResultOutBufByKey(pAggSup->pResultBuf, pResultRowInfo, (char*)&win->skey, TSDB_KEYSIZE, - masterscan, tableGroupId, pTaskInfo, true, pAggSup); + masterscan, tableGroupId, pTaskInfo, true, pAggSup, true); if (pResultRow == NULL) { *pResult = NULL; @@ -128,8 +136,9 @@ FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn if (end >= 0) { forwardRows = end; - if (pData[end + pos] == ekey) { + while (pData[end + pos] == ekey) { forwardRows += 1; + ++pos; } } } else { @@ -137,8 +146,9 @@ FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn if (end >= 0) { forwardRows = end; - if (pData[end + pos] == ekey) { + while (pData[end + pos] == ekey) { forwardRows += 1; + ++pos; } } // int32_t end = searchFn((char*)pData, pos + 1, ekey, order); @@ -151,7 +161,7 @@ FORCE_INLINE int32_t getForwardStepsInBlock(int32_t numOfRows, __block_search_fn // } } - assert(forwardRows >= 0); + ASSERT(forwardRows >= 0); return forwardRows; } @@ -163,8 +173,6 @@ int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order) { return -1; } - assert(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC); - TSKEY* keyList = (TSKEY*)pValue; int32_t firstPos = 0; int32_t lastPos = num - 1; @@ -228,7 +236,7 @@ int32_t binarySearchForKey(char* pValue, int num, TSKEY key, int order) { int32_t getNumOfRowsInTimeWindow(SDataBlockInfo* pDataBlockInfo, TSKEY* pPrimaryColumn, int32_t startPos, TSKEY ekey, __block_search_fn_t searchFn, STableQueryInfo* item, int32_t order) { - assert(startPos >= 0 && startPos < pDataBlockInfo->rows); + ASSERT(startPos >= 0 && startPos < pDataBlockInfo->rows); int32_t num = -1; int32_t step = GET_FORWARD_DIRECTION_FACTOR(order); @@ -259,7 +267,6 @@ int32_t getNumOfRowsInTimeWindow(SDataBlockInfo* pDataBlockInfo, TSKEY* pPrimary } } - assert(num >= 0); return num; } @@ -394,7 +401,7 @@ static bool setTimeWindowInterpolationEndTs(SIntervalAggOperatorInfo* pInfo, SEx } int32_t nextRowIndex = endRowIndex + 1; - assert(nextRowIndex >= 0); + ASSERT(nextRowIndex >= 0); TSKEY nextKey = tsCols[nextRowIndex]; doTimeWindowInterpolation(pInfo->pPrevValues, pDataBlock, actualEndKey, endRowIndex, nextKey, nextRowIndex, key, @@ -455,9 +462,9 @@ static int32_t getNextQualifiedWindow(SInterval* pInterval, STimeWindow* pNext, */ if (primaryKeys == NULL) { if (ascQuery) { - assert(pDataBlockInfo->window.skey <= pNext->ekey); + ASSERT(pDataBlockInfo->window.skey <= pNext->ekey); } else { - assert(pDataBlockInfo->window.ekey >= pNext->skey); + ASSERT(pDataBlockInfo->window.ekey >= pNext->skey); } } else { if (ascQuery && primaryKeys[startPos] > pNext->ekey) { @@ -494,7 +501,6 @@ static bool isResultRowInterpolated(SResultRow* pResult, SResultTsInterpType typ } static void setResultRowInterpo(SResultRow* pResult, SResultTsInterpType type) { - assert(pResult != NULL && (type == RESULT_ROW_START_INTERP || type == RESULT_ROW_END_INTERP)); if (type == RESULT_ROW_START_INTERP) { pResult->startInterp = true; } else { @@ -805,70 +811,61 @@ static int32_t saveResult(SResultWindowInfo winInfo, SSHashObj* pStUpdated) { return tSimpleHashPut(pStUpdated, &winInfo.sessionWin, sizeof(SSessionKey), &winInfo, sizeof(SResultWindowInfo)); } -static int32_t saveWinResult(int64_t ts, int32_t pageId, int32_t offset, uint64_t groupId, SHashObj* pUpdatedMap) { - SResKeyPos* newPos = taosMemoryMalloc(sizeof(SResKeyPos) + sizeof(uint64_t)); - if (newPos == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - newPos->groupId = groupId; - newPos->pos = (SResultRowPosition){.pageId = pageId, .offset = offset}; - *(int64_t*)newPos->key = ts; +static int32_t saveWinResult(int64_t ts, uint64_t groupId, SSHashObj* pUpdatedMap) { SWinKey key = {.ts = ts, .groupId = groupId}; - if (taosHashPut(pUpdatedMap, &key, sizeof(SWinKey), &newPos, sizeof(void*)) != TSDB_CODE_SUCCESS) { - taosMemoryFree(newPos); - } - + tSimpleHashPut(pUpdatedMap, &key, sizeof(SWinKey), NULL, 0); return TSDB_CODE_SUCCESS; } -static int32_t saveWinResultInfo(TSKEY ts, uint64_t groupId, SHashObj* pUpdatedMap) { - return saveWinResult(ts, -1, -1, groupId, pUpdatedMap); +static int32_t saveWinResultInfo(TSKEY ts, uint64_t groupId, SSHashObj* pUpdatedMap) { + return saveWinResult(ts, groupId, pUpdatedMap); } -static void removeResults(SArray* pWins, SHashObj* pUpdatedMap) { +static void removeResults(SArray* pWins, SSHashObj* pUpdatedMap) { int32_t size = taosArrayGetSize(pWins); for (int32_t i = 0; i < size; i++) { SWinKey* pW = taosArrayGet(pWins, i); - void* tmp = taosHashGet(pUpdatedMap, pW, sizeof(SWinKey)); + void* tmp = tSimpleHashGet(pUpdatedMap, pW, sizeof(SWinKey)); if (tmp) { void* value = *(void**)tmp; taosMemoryFree(value); - taosHashRemove(pUpdatedMap, pW, sizeof(SWinKey)); + tSimpleHashRemove(pUpdatedMap, pW, sizeof(SWinKey)); } } } -int32_t compareWinRes(void* pKey, void* data, int32_t index) { - SArray* res = (SArray*)data; - SWinKey* pDataPos = taosArrayGet(res, index); - SResKeyPos* pRKey = (SResKeyPos*)pKey; - if (pRKey->groupId > pDataPos->groupId) { +int32_t compareWinKey(void* pKey, void* data, int32_t index) { + SArray* res = (SArray*)data; + SWinKey* pDataPos = taosArrayGet(res, index); + SWinKey* pWKey = (SWinKey*)pKey; + + if (pWKey->groupId > pDataPos->groupId) { return 1; - } else if (pRKey->groupId < pDataPos->groupId) { + } else if (pWKey->groupId < pDataPos->groupId) { return -1; } - if (*(int64_t*)pRKey->key > pDataPos->ts) { + if (pWKey->ts > pDataPos->ts) { return 1; - } else if (*(int64_t*)pRKey->key < pDataPos->ts) { + } else if (pWKey->ts < pDataPos->ts) { return -1; } return 0; } -static void removeDeleteResults(SHashObj* pUpdatedMap, SArray* pDelWins) { +static void removeDeleteResults(SSHashObj* pUpdatedMap, SArray* pDelWins) { taosArraySort(pDelWins, winKeyCmprImpl); taosArrayRemoveDuplicate(pDelWins, winKeyCmprImpl, NULL); int32_t delSize = taosArrayGetSize(pDelWins); - if (taosHashGetSize(pUpdatedMap) == 0 || delSize == 0) { + if (tSimpleHashGetSize(pUpdatedMap) == 0 || delSize == 0) { return; } - void* pIte = NULL; - while ((pIte = taosHashIterate(pUpdatedMap, pIte)) != NULL) { - SResKeyPos* pResKey = *(SResKeyPos**)pIte; - int32_t index = binarySearchCom(pDelWins, delSize, pResKey, TSDB_ORDER_DESC, compareWinRes); - if (index >= 0 && 0 == compareWinRes(pResKey, pDelWins, index)) { + void* pIte = NULL; + int32_t iter = 0; + while ((pIte = tSimpleHashIterate(pUpdatedMap, pIte, &iter)) != NULL) { + SWinKey* pResKey = tSimpleHashGetKey(pIte, NULL); + int32_t index = binarySearchCom(pDelWins, delSize, pResKey, TSDB_ORDER_DESC, compareWinKey); + if (index >= 0 && 0 == compareWinKey(pResKey, pDelWins, index)) { taosArrayRemove(pDelWins, index); delSize = taosArrayGetSize(pDelWins); } @@ -908,10 +905,10 @@ static void hashIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pResul if (ret != TSDB_CODE_SUCCESS || pResult == NULL) { T_LONG_JMP(pTaskInfo->env, TSDB_CODE_OUT_OF_MEMORY); } + TSKEY ekey = ascScan ? win.ekey : win.skey; int32_t forwardRows = getNumOfRowsInTimeWindow(&pBlock->info, tsCols, startPos, ekey, binarySearchForKey, NULL, pInfo->inputOrder); - ASSERT(forwardRows > 0); // prev time window not interpolation yet. if (pInfo->timeWindowInterpo) { @@ -1044,7 +1041,7 @@ static int32_t doOpenIntervalAgg(SOperatorInfo* pOperator) { break; } - getTableScanInfo(pOperator, &pInfo->inputOrder, &scanFlag); + getTableScanInfo(pOperator, &pInfo->inputOrder, &scanFlag, true); if (pInfo->scalarSupp.pExprInfo != NULL) { SExprSupp* pExprSup = &pInfo->scalarSupp; @@ -1317,7 +1314,7 @@ static bool doDeleteWindow(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId) } static void doDeleteWindows(SOperatorInfo* pOperator, SInterval* pInterval, SSDataBlock* pBlock, SArray* pUpWins, - SHashObj* pUpdatedMap) { + SSHashObj* pUpdatedMap) { SStreamIntervalOperatorInfo* pInfo = pOperator->info; SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX); TSKEY* startTsCols = (TSKEY*)pStartTsCol->pData; @@ -1353,28 +1350,21 @@ static void doDeleteWindows(SOperatorInfo* pOperator, SInterval* pInterval, SSDa taosArrayPush(pUpWins, &winRes); } if (pUpdatedMap) { - void* tmp = taosHashGet(pUpdatedMap, &winRes, sizeof(SWinKey)); - if (tmp) { - void* value = *(void**)tmp; - taosMemoryFree(value); - taosHashRemove(pUpdatedMap, &winRes, sizeof(SWinKey)); - } + tSimpleHashRemove(pUpdatedMap, &winRes, sizeof(SWinKey)); } getNextTimeWindow(pInterval, &win, TSDB_ORDER_ASC); } while (win.ekey <= endTsCols[i]); } } -static int32_t getAllIntervalWindow(SSHashObj* pHashMap, SHashObj* resWins) { +static int32_t getAllIntervalWindow(SSHashObj* pHashMap, SSHashObj* resWins) { void* pIte = NULL; - size_t keyLen = 0; int32_t iter = 0; while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) { - void* key = tSimpleHashGetKey(pIte, &keyLen); - uint64_t groupId = *(uint64_t*)key; - TSKEY ts = *(int64_t*)((char*)key + sizeof(uint64_t)); - SResultRowPosition* pPos = (SResultRowPosition*)pIte; - int32_t code = saveWinResult(ts, pPos->pageId, pPos->offset, groupId, resWins); + SWinKey* pKey = tSimpleHashGetKey(pIte, NULL); + uint64_t groupId = pKey->groupId; + TSKEY ts = pKey->ts; + int32_t code = saveWinResult(ts, groupId, resWins); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -1382,36 +1372,16 @@ static int32_t getAllIntervalWindow(SSHashObj* pHashMap, SHashObj* resWins) { return TSDB_CODE_SUCCESS; } -int32_t compareWinKey(void* pKey, void* data, int32_t index) { - SArray* res = (SArray*)data; - SWinKey* pDataPos = taosArrayGet(res, index); - SWinKey* pWKey = (SWinKey*)pKey; - - if (pWKey->groupId > pDataPos->groupId) { - return 1; - } else if (pWKey->groupId < pDataPos->groupId) { - return -1; - } - - if (pWKey->ts > pDataPos->ts) { - return 1; - } else if (pWKey->ts < pDataPos->ts) { - return -1; - } - return 0; -} - static int32_t closeStreamIntervalWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SInterval* pInterval, - SHashObj* pPullDataMap, SHashObj* closeWins, SArray* pDelWins, + SHashObj* pPullDataMap, SSHashObj* closeWins, SArray* pDelWins, SOperatorInfo* pOperator) { qDebug("===stream===close interval window"); void* pIte = NULL; - size_t keyLen = 0; int32_t iter = 0; SStreamIntervalOperatorInfo* pInfo = pOperator->info; int32_t delSize = taosArrayGetSize(pDelWins); while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) { - void* key = tSimpleHashGetKey(pIte, &keyLen); + void* key = tSimpleHashGetKey(pIte, NULL); SWinKey* pWinKey = (SWinKey*)key; if (delSize > 0) { int32_t index = binarySearchCom(pDelWins, delSize, pWinKey, TSDB_ORDER_DESC, compareWinKey); @@ -1501,16 +1471,16 @@ static void deleteIntervalDiscBuf(SStreamState* pState, SHashObj* pPullDataMap, code = streamStateGetKVByCur(pCur, &tmpKey, NULL, 0); if (code == TSDB_CODE_SUCCESS) { STimeWindow tw = getFinalTimeWindow(tmpKey.ts, pInterval); - qDebug("===stream===error stream state first key:%" PRId64 "-%" PRId64 ",%" PRId64 ",mark %" PRId64, tw.skey, + qDebug("===stream===error stream state first key:%" PRId64 "-%" PRId64 ",%" PRIu64 ",mark %" PRId64, tw.skey, tw.ekey, tmpKey.groupId, mark); } else { STimeWindow tw = getFinalTimeWindow(key->ts, pInterval); - qDebug("===stream===stream state first key:%" PRId64 "-%" PRId64 ",%" PRId64 ",mark %" PRId64, tw.skey, tw.ekey, + qDebug("===stream===stream state first key:%" PRId64 "-%" PRId64 ",%" PRIu64 ",mark %" PRId64, tw.skey, tw.ekey, key->groupId, mark); } } else { STimeWindow tw = getFinalTimeWindow(key->ts, pInterval); - qDebug("===stream===stream state first key:%" PRId64 "-%" PRId64 ",%" PRId64 ",mark %" PRId64, tw.skey, tw.ekey, + qDebug("===stream===stream state first key:%" PRId64 "-%" PRId64 ",%" PRIu64 ",mark %" PRId64, tw.skey, tw.ekey, key->groupId, mark); } streamStateFreeCur(pCur); @@ -1607,13 +1577,13 @@ void destroyStreamFinalIntervalOperatorInfo(void* param) { int32_t size = taosArrayGetSize(pInfo->pChildren); for (int32_t i = 0; i < size; i++) { SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, i); - destroyOperatorInfo(pChildOp); + destroyOperator(pChildOp); } taosArrayDestroy(pInfo->pChildren); } nodesDestroyNode((SNode*)pInfo->pPhyNode); colDataDestroy(&pInfo->twAggSup.timeWindowData); - cleanupGroupResInfo(&pInfo->groupResInfo); + pInfo->groupResInfo.pRows = taosArrayDestroy(pInfo->groupResInfo.pRows); cleanupExprSupp(&pInfo->scalarSupp); taosMemoryFreeClear(param); @@ -1705,7 +1675,7 @@ void initStreamFunciton(SqlFunctionCtx* pCtx, int32_t numOfExpr) { } SOperatorInfo* createIntervalOperatorInfo(SOperatorInfo* downstream, SIntervalPhysiNode* pPhyNode, - SExecTaskInfo* pTaskInfo, bool isStream) { + SExecTaskInfo* pTaskInfo) { SIntervalAggOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SIntervalAggOperatorInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); if (pInfo == NULL || pOperator == NULL) { @@ -1938,6 +1908,7 @@ static SSDataBlock* doSessionWindowAgg(SOperatorInfo* pOperator) { return (pBInfo->pRes->info.rows == 0) ? NULL : pBInfo->pRes; } +// todo make this as an non-blocking operator SOperatorInfo* createStatewindowOperatorInfo(SOperatorInfo* downstream, SStateWinodwPhysiNode* pStateNode, SExecTaskInfo* pTaskInfo) { SStateWindowOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(SStateWindowOperatorInfo)); @@ -2109,10 +2080,12 @@ void compactFunctions(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int3 } else if (functionNeedToExecute(&pDestCtx[k]) && pDestCtx[k].fpSet.combine != NULL) { int32_t code = pDestCtx[k].fpSet.combine(&pDestCtx[k], &pSourceCtx[k]); if (code != TSDB_CODE_SUCCESS) { - qError("%s apply functions error, code: %s", GET_TASKID(pTaskInfo), tstrerror(code)); - pTaskInfo->code = code; - T_LONG_JMP(pTaskInfo->env, code); + qError("%s apply combine functions error, code: %s", GET_TASKID(pTaskInfo), tstrerror(code)); } + } else if (pDestCtx[k].fpSet.combine == NULL) { + char* funName = fmGetFuncName(pDestCtx[k].functionId); + qError("%s error, combine funcion for %s is not implemented", GET_TASKID(pTaskInfo), funName); + taosMemoryFreeClear(funName); } } } @@ -2121,7 +2094,7 @@ bool hasIntervalWindow(SStreamState* pState, SWinKey* pKey) { return TSDB_CODE_SUCCESS == streamStateGet(pState, pKey, NULL, 0); } -static void rebuildIntervalWindow(SOperatorInfo* pOperator, SArray* pWinArray, SHashObj* pUpdatedMap) { +static void rebuildIntervalWindow(SOperatorInfo* pOperator, SArray* pWinArray, SSHashObj* pUpdatedMap) { SStreamIntervalOperatorInfo* pInfo = pOperator->info; SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; int32_t size = taosArrayGetSize(pWinArray); @@ -2170,13 +2143,6 @@ static void rebuildIntervalWindow(SOperatorInfo* pOperator, SArray* pWinArray, S } } -bool isDeletedWindow(STimeWindow* pWin, uint64_t groupId, SAggSupporter* pSup) { - SET_RES_WINDOW_KEY(pSup->keyBuf, &pWin->skey, sizeof(int64_t), groupId); - SResultRowPosition* p1 = (SResultRowPosition*)tSimpleHashGet(pSup->pResultRowHashTable, pSup->keyBuf, - GET_RES_WINDOW_KEY_LEN(sizeof(int64_t))); - return p1 == NULL; -} - bool isDeletedStreamWindow(STimeWindow* pWin, uint64_t groupId, SStreamState* pState, STimeWindowAggSupp* pTwSup) { if (pWin->ekey < pTwSup->maxTs - pTwSup->deleteMark) { SWinKey key = {.ts = pWin->skey, .groupId = groupId}; @@ -2235,11 +2201,11 @@ static void doBuildPullDataBlock(SArray* array, int32_t* pIndex, SSDataBlock* pB SColumnInfoData* pCalEndTs = (SColumnInfoData*)taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX); for (; (*pIndex) < size; (*pIndex)++) { SPullWindowInfo* pWin = taosArrayGet(array, (*pIndex)); - colDataAppend(pStartTs, pBlock->info.rows, (const char*)&pWin->window.skey, false); - colDataAppend(pEndTs, pBlock->info.rows, (const char*)&pWin->window.ekey, false); - colDataAppend(pGroupId, pBlock->info.rows, (const char*)&pWin->groupId, false); - colDataAppend(pCalStartTs, pBlock->info.rows, (const char*)&pWin->calWin.skey, false); - colDataAppend(pCalEndTs, pBlock->info.rows, (const char*)&pWin->calWin.ekey, false); + colDataSetVal(pStartTs, pBlock->info.rows, (const char*)&pWin->window.skey, false); + colDataSetVal(pEndTs, pBlock->info.rows, (const char*)&pWin->window.ekey, false); + colDataSetVal(pGroupId, pBlock->info.rows, (const char*)&pWin->groupId, false); + colDataSetVal(pCalStartTs, pBlock->info.rows, (const char*)&pWin->calWin.skey, false); + colDataSetVal(pCalEndTs, pBlock->info.rows, (const char*)&pWin->calWin.ekey, false); pBlock->info.rows++; } if ((*pIndex) == size) { @@ -2307,7 +2273,8 @@ static void clearFunctionContext(SExprSupp* pSup) { } } -void doBuildResult(SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, SGroupResInfo* pGroupResInfo) { +void doBuildStreamIntervalResult(SOperatorInfo* pOperator, SStreamState* pState, SSDataBlock* pBlock, + SGroupResInfo* pGroupResInfo) { SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; // set output datablock version pBlock->info.version = pTaskInfo->version; @@ -2333,9 +2300,15 @@ static int32_t getNextQualifiedFinalWindow(SInterval* pInterval, STimeWindow* pN return startPos; } +static void setStreamDataVersion(SExecTaskInfo* pTaskInfo, int64_t version, int64_t ckId) { + pTaskInfo->streamInfo.dataVersion = version; + pTaskInfo->streamInfo.checkPointId = ckId; +} + static void doStreamIntervalAggImpl(SOperatorInfo* pOperatorInfo, SSDataBlock* pSDataBlock, uint64_t groupId, - SHashObj* pUpdatedMap) { + SSHashObj* pUpdatedMap) { SStreamIntervalOperatorInfo* pInfo = (SStreamIntervalOperatorInfo*)pOperatorInfo->info; + pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version); SResultRowInfo* pResultRowInfo = &(pInfo->binfo.resultRowInfo); SExecTaskInfo* pTaskInfo = pOperatorInfo->pTaskInfo; @@ -2432,10 +2405,8 @@ static void doStreamIntervalAggImpl(SOperatorInfo* pOperatorInfo, SSDataBlock* p updateTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &nextWin, true); applyAggFunctionOnPartialTuples(pTaskInfo, pSup->pCtx, &pInfo->twAggSup.timeWindowData, startPos, forwardRows, pSDataBlock->info.rows, numOfOutput); - SWinKey key = { - .ts = nextWin.skey, - .groupId = groupId, - }; + + SWinKey key = { .ts = nextWin.skey, .groupId = groupId }; saveOutputBuf(pInfo->pState, &key, pResult, pInfo->aggSup.resultRowSize); releaseOutputBuf(pInfo->pState, &key, pResult); if (pInfo->delKey.ts > key.ts) { @@ -2470,12 +2441,8 @@ static void doStreamIntervalAggImpl(SOperatorInfo* pOperatorInfo, SSDataBlock* p static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { SStreamIntervalOperatorInfo* pInfo = pOperator->info; SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - - SOperatorInfo* downstream = pOperator->pDownstream[0]; - TSKEY maxTs = INT64_MIN; - TSKEY minTs = INT64_MAX; - - SExprSupp* pSup = &pOperator->exprSupp; + SOperatorInfo* downstream = pOperator->pDownstream[0]; + SExprSupp* pSup = &pOperator->exprSupp; qDebug("interval status %d %s", pOperator->status, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi"); @@ -2496,7 +2463,7 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { return pInfo->pDelRes; } - doBuildResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); + doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); if (pInfo->binfo.pRes->info.rows != 0) { printDataBlock(pInfo->binfo.pRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi"); return pInfo->binfo.pRes; @@ -2507,6 +2474,7 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { clearFunctionContext(&pOperator->exprSupp); // semi interval operator clear disk buffer clearStreamIntervalOperator(pInfo); + setStreamDataVersion(pTaskInfo, pInfo->dataVersion, pInfo->pState->checkPointId); qDebug("===stream===clear semi operator"); } else { deleteIntervalDiscBuf(pInfo->pState, pInfo->pPullDataMap, pInfo->twAggSup.maxTs - pInfo->twAggSup.deleteMark, @@ -2523,7 +2491,7 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { return pInfo->pDelRes; } - doBuildResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); + doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); if (pInfo->binfo.pRes->info.rows != 0) { printDataBlock(pInfo->binfo.pRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi"); return pInfo->binfo.pRes; @@ -2531,11 +2499,29 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { } } - SArray* pUpdated = taosArrayInit(4, POINTER_BYTES); + if (!pInfo->pUpdated) { + pInfo->pUpdated = taosArrayInit(4, sizeof(SWinKey)); + } + if (!pInfo->pUpdatedMap) { + _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); + pInfo->pUpdatedMap = tSimpleHashInit(1024, hashFn); + } - _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); - SHashObj* pUpdatedMap = taosHashInit(1024, hashFn, false, HASH_NO_LOCK); while (1) { + if (isTaskKilled(pTaskInfo)) { + + if (pInfo->pUpdated != NULL) { + pInfo->pUpdated = taosArrayDestroy(pInfo->pUpdated); + } + + if (pInfo->pUpdatedMap != NULL) { + tSimpleHashCleanup(pInfo->pUpdatedMap); + pInfo->pUpdatedMap = NULL; + } + + T_LONG_JMP(pTaskInfo->env, pTaskInfo->code); + } + SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); if (pBlock == NULL) { pOperator->status = OP_RES_TO_RETURN; @@ -2552,35 +2538,39 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT || pBlock->info.type == STREAM_CLEAR) { SArray* delWins = taosArrayInit(8, sizeof(SWinKey)); - doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pUpdatedMap); + doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, pInfo->pUpdatedMap); if (IS_FINAL_OP(pInfo)) { int32_t childIndex = getChildIndex(pBlock); SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, childIndex); SStreamIntervalOperatorInfo* pChildInfo = pChildOp->info; SExprSupp* pChildSup = &pChildOp->exprSupp; doDeleteWindows(pChildOp, &pChildInfo->interval, pBlock, NULL, NULL); - rebuildIntervalWindow(pOperator, delWins, pUpdatedMap); + rebuildIntervalWindow(pOperator, delWins, pInfo->pUpdatedMap); addRetriveWindow(delWins, pInfo); taosArrayAddAll(pInfo->pDelWins, delWins); taosArrayDestroy(delWins); continue; } - removeResults(delWins, pUpdatedMap); + removeResults(delWins, pInfo->pUpdatedMap); taosArrayAddAll(pInfo->pDelWins, delWins); taosArrayDestroy(delWins); break; } else if (pBlock->info.type == STREAM_GET_ALL && IS_FINAL_OP(pInfo)) { - getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pUpdatedMap); + getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap); continue; } else if (pBlock->info.type == STREAM_RETRIEVE && !IS_FINAL_OP(pInfo)) { - doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pUpdatedMap); - if (taosArrayGetSize(pUpdated) > 0) { + doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pInfo->pUpdatedMap); + if (taosArrayGetSize(pInfo->pUpdated) > 0) { break; } continue; } else if (pBlock->info.type == STREAM_PULL_OVER && IS_FINAL_OP(pInfo)) { processPullOver(pBlock, pInfo->pPullDataMap, &pInfo->interval); continue; + } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) { + return pBlock; + } else { + ASSERTS(pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type"); } if (pInfo->scalarSupp.pExprInfo != NULL) { @@ -2588,7 +2578,7 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { projectApplyFunctions(pExprSup->pExprInfo, pBlock, pBlock, pExprSup->pCtx, pExprSup->numOfExprs, NULL); } setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true); - doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pUpdatedMap); + doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap); if (IS_FINAL_OP(pInfo)) { int32_t chIndex = getChildIndex(pBlock); int32_t size = taosArrayGetSize(pInfo->pChildren); @@ -2608,29 +2598,31 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true); doStreamIntervalAggImpl(pChildOp, pBlock, pBlock->info.id.groupId, NULL); } - maxTs = TMAX(maxTs, pBlock->info.window.ekey); - maxTs = TMAX(maxTs, pBlock->info.watermark); - minTs = TMIN(minTs, pBlock->info.window.skey); + pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey); + pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark); + pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey); } - removeDeleteResults(pUpdatedMap, pInfo->pDelWins); - pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs); - pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, minTs); + removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins); if (IS_FINAL_OP(pInfo)) { closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, - pInfo->pPullDataMap, pUpdatedMap, pInfo->pDelWins, pOperator); + pInfo->pPullDataMap, pInfo->pUpdatedMap, pInfo->pDelWins, pOperator); closeChildIntervalWindow(pOperator, pInfo->pChildren, pInfo->twAggSup.maxTs); } pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs; - void* pIte = NULL; - while ((pIte = taosHashIterate(pUpdatedMap, pIte)) != NULL) { - taosArrayPush(pUpdated, pIte); + void* pIte = NULL; + int32_t iter = 0; + while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) { + taosArrayPush(pInfo->pUpdated, pIte); } - taosHashCleanup(pUpdatedMap); - taosArraySort(pUpdated, resultrowComparAsc); - initMultiResInfoFromArrayList(&pInfo->groupResInfo, pUpdated); + tSimpleHashCleanup(pInfo->pUpdatedMap); + pInfo->pUpdatedMap = NULL; + taosArraySort(pInfo->pUpdated, winKeyCmprImpl); + + initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated); + pInfo->pUpdated = NULL; blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity); doBuildPullDataBlock(pInfo->pPullWins, &pInfo->pullIndex, pInfo->pPullDataRes); @@ -2647,7 +2639,7 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { return pInfo->pDelRes; } - doBuildResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); + doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); if (pInfo->binfo.pRes->info.rows != 0) { printDataBlock(pInfo->binfo.pRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi"); return pInfo->binfo.pRes; @@ -2762,12 +2754,16 @@ SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, pInfo->pPullDataMap = taosHashInit(64, hashFn, false, HASH_NO_LOCK); pInfo->pPullDataRes = createSpecialDataBlock(STREAM_RETRIEVE); pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired; + pInfo->ignoreExpiredDataSaved = false; pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT); pInfo->delIndex = 0; pInfo->pDelWins = taosArrayInit(4, sizeof(SWinKey)); pInfo->delKey.ts = INT64_MAX; pInfo->delKey.groupId = 0; pInfo->numOfDatapack = 0; + pInfo->pUpdated = NULL; + pInfo->pUpdatedMap = NULL; + pInfo->dataVersion = 0; pOperator->operatorType = pPhyNode->type; pOperator->blocking = true; @@ -2810,7 +2806,7 @@ void destroyStreamSessionAggOperatorInfo(void* param) { int32_t size = taosArrayGetSize(pInfo->pChildren); for (int32_t i = 0; i < size; i++) { SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i); - destroyOperatorInfo(pChild); + destroyOperator(pChild); } taosArrayDestroy(pInfo->pChildren); } @@ -3118,6 +3114,8 @@ static void doStreamSessionAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSData int32_t rows = pSDataBlock->info.rows; int32_t winRows = 0; + pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version); + SColumnInfoData* pStartTsCol = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex); TSKEY* startTsCols = (int64_t*)pStartTsCol->pData; SColumnInfoData* pEndTsCol = NULL; @@ -3211,10 +3209,9 @@ static inline int32_t sessionKeyCompareAsc(const void* pKey1, const void* pKey2) static int32_t copyUpdateResult(SSHashObj* pStUpdated, SArray* pUpdated) { void* pIte = NULL; - size_t keyLen = 0; int32_t iter = 0; while ((pIte = tSimpleHashIterate(pStUpdated, pIte, &iter)) != NULL) { - void* key = tSimpleHashGetKey(pIte, &keyLen); + void* key = tSimpleHashGetKey(pIte, NULL); taosArrayPush(pUpdated, key); } taosArraySort(pUpdated, sessionKeyCompareAsc); @@ -3228,36 +3225,35 @@ void doBuildDeleteDataBlock(SOperatorInfo* pOp, SSHashObj* pStDeleted, SSDataBlo return; } blockDataEnsureCapacity(pBlock, size); - size_t keyLen = 0; int32_t iter = 0; while (((*Ite) = tSimpleHashIterate(pStDeleted, *Ite, &iter)) != NULL) { if (pBlock->info.rows + 1 > pBlock->info.capacity) { break; } - SSessionKey* res = tSimpleHashGetKey(*Ite, &keyLen); + SSessionKey* res = tSimpleHashGetKey(*Ite, NULL); SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX); - colDataAppend(pStartTsCol, pBlock->info.rows, (const char*)&res->win.skey, false); + colDataSetVal(pStartTsCol, pBlock->info.rows, (const char*)&res->win.skey, false); SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX); - colDataAppend(pEndTsCol, pBlock->info.rows, (const char*)&res->win.skey, false); + colDataSetVal(pEndTsCol, pBlock->info.rows, (const char*)&res->win.skey, false); SColumnInfoData* pUidCol = taosArrayGet(pBlock->pDataBlock, UID_COLUMN_INDEX); - colDataAppendNULL(pUidCol, pBlock->info.rows); + colDataSetNULL(pUidCol, pBlock->info.rows); SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX); - colDataAppend(pGpCol, pBlock->info.rows, (const char*)&res->groupId, false); + colDataSetVal(pGpCol, pBlock->info.rows, (const char*)&res->groupId, false); SColumnInfoData* pCalStCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX); - colDataAppendNULL(pCalStCol, pBlock->info.rows); + colDataSetNULL(pCalStCol, pBlock->info.rows); SColumnInfoData* pCalEdCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX); - colDataAppendNULL(pCalEdCol, pBlock->info.rows); + colDataSetNULL(pCalEdCol, pBlock->info.rows); SColumnInfoData* pTableCol = taosArrayGet(pBlock->pDataBlock, TABLE_NAME_COLUMN_INDEX); void* tbname = NULL; streamStateGetParName(pOp->pTaskInfo->streamInfo.pState, res->groupId, &tbname); if (tbname == NULL) { - colDataAppendNULL(pTableCol, pBlock->info.rows); + colDataSetNULL(pTableCol, pBlock->info.rows); } else { char parTbName[VARSTR_HEADER_SIZE + TSDB_TABLE_NAME_LEN]; STR_WITH_MAXSIZE_TO_VARSTR(parTbName, tbname, sizeof(parTbName)); - colDataAppend(pTableCol, pBlock->info.rows, (const char*)parTbName, false); + colDataSetVal(pTableCol, pBlock->info.rows, (const char*)parTbName, false); tdbFree(tbname); } pBlock->info.rows += 1; @@ -3323,7 +3319,6 @@ static void rebuildSessionWindow(SOperatorInfo* pOperator, SArray* pWinArray, SS int32_t closeSessionWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SSHashObj* pClosed) { void* pIte = NULL; - size_t keyLen = 0; int32_t iter = 0; while ((pIte = tSimpleHashIterate(pHashMap, pIte, &iter)) != NULL) { SResultWindowInfo* pWinInfo = pIte; @@ -3334,7 +3329,7 @@ int32_t closeSessionWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SSHa return code; } } - SSessionKey* pKey = tSimpleHashGetKey(pIte, &keyLen); + SSessionKey* pKey = tSimpleHashGetKey(pIte, NULL); tSimpleHashIterateRemove(pHashMap, pKey, sizeof(SSessionKey), &pIte, &iter); } } @@ -3400,7 +3395,6 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) { SExprSupp* pSup = &pOperator->exprSupp; SStreamSessionAggOperatorInfo* pInfo = pOperator->info; SOptrBasicInfo* pBInfo = &pInfo->binfo; - TSKEY maxTs = INT64_MIN; SStreamAggSupporter* pAggSup = &pInfo->streamAggSup; if (pOperator->status == OP_EXEC_DONE) { return NULL; @@ -3420,10 +3414,14 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) { return NULL; } - _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); - SSHashObj* pStUpdated = tSimpleHashInit(64, hashFn); SOperatorInfo* downstream = pOperator->pDownstream[0]; - SArray* pUpdated = taosArrayInit(16, sizeof(SSessionKey)); // SResKeyPos + if (!pInfo->pUpdated) { + pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey)); + } + if (!pInfo->pStUpdated) { + _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); + pInfo->pStUpdated = tSimpleHashInit(64, hashFn); + } while (1) { SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); if (pBlock == NULL) { @@ -3436,21 +3434,25 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) { SArray* pWins = taosArrayInit(16, sizeof(SSessionKey)); // gap must be 0 doDeleteTimeWindows(pAggSup, pBlock, pWins); - removeSessionResults(pStUpdated, pWins); + removeSessionResults(pInfo->pStUpdated, pWins); if (IS_FINAL_OP(pInfo)) { int32_t childIndex = getChildIndex(pBlock); SOperatorInfo* pChildOp = taosArrayGetP(pInfo->pChildren, childIndex); SStreamSessionAggOperatorInfo* pChildInfo = pChildOp->info; // gap must be 0 doDeleteTimeWindows(&pChildInfo->streamAggSup, pBlock, NULL); - rebuildSessionWindow(pOperator, pWins, pStUpdated); + rebuildSessionWindow(pOperator, pWins, pInfo->pStUpdated); } copyDeleteWindowInfo(pWins, pInfo->pStDeleted); taosArrayDestroy(pWins); continue; } else if (pBlock->info.type == STREAM_GET_ALL) { - getAllSessionWindow(pAggSup->pResultRows, pStUpdated); + getAllSessionWindow(pAggSup->pResultRows, pInfo->pStUpdated); continue; + } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) { + return pBlock; + } else { + ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type"); } if (pInfo->scalarSupp.pExprInfo != NULL) { @@ -3459,7 +3461,7 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) { } // the pDataBlock are always the same one, no need to call this again setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true); - doStreamSessionAggImpl(pOperator, pBlock, pStUpdated, pInfo->pStDeleted, IS_FINAL_OP(pInfo)); + doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, pInfo->pStDeleted, IS_FINAL_OP(pInfo)); if (IS_FINAL_OP(pInfo)) { int32_t chIndex = getChildIndex(pBlock); int32_t size = taosArrayGetSize(pInfo->pChildren); @@ -3476,20 +3478,20 @@ static SSDataBlock* doStreamSessionAgg(SOperatorInfo* pOperator) { setInputDataBlock(&pChildOp->exprSupp, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true); doStreamSessionAggImpl(pChildOp, pBlock, NULL, NULL, true); } - maxTs = TMAX(maxTs, pBlock->info.window.ekey); - maxTs = TMAX(maxTs, pBlock->info.watermark); + pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey); + pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.watermark); } - - pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs); // restore the value pOperator->status = OP_RES_TO_RETURN; - closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pStUpdated); + closeSessionWindow(pAggSup->pResultRows, &pInfo->twAggSup, pInfo->pStUpdated); closeChildSessionWindow(pInfo->pChildren, pInfo->twAggSup.maxTs); - copyUpdateResult(pStUpdated, pUpdated); - removeSessionResults(pInfo->pStDeleted, pUpdated); - tSimpleHashCleanup(pStUpdated); - initGroupResInfoFromArrayList(&pInfo->groupResInfo, pUpdated); + copyUpdateResult(pInfo->pStUpdated, pInfo->pUpdated); + removeSessionResults(pInfo->pStDeleted, pInfo->pUpdated); + tSimpleHashCleanup(pInfo->pStUpdated); + pInfo->pStUpdated = NULL; + initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated); + pInfo->pUpdated = NULL; blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity); #if 0 @@ -3574,6 +3576,10 @@ SOperatorInfo* createStreamSessionAggOperatorInfo(SOperatorInfo* downstream, SPh pInfo->isFinal = false; pInfo->pPhyNode = pPhyNode; pInfo->ignoreExpiredData = pSessionNode->window.igExpired; + pInfo->ignoreExpiredDataSaved = false; + pInfo->pUpdated = NULL; + pInfo->pStUpdated = NULL; + pInfo->dataVersion = 0; setOperatorInfo(pOperator, "StreamSessionWindowAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION, true, OP_NOT_OPENED, pInfo, pTaskInfo); @@ -3634,10 +3640,14 @@ static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) { } } - _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); - SSHashObj* pStUpdated = tSimpleHashInit(64, hashFn); SOperatorInfo* downstream = pOperator->pDownstream[0]; - SArray* pUpdated = taosArrayInit(16, sizeof(SSessionKey)); + if (!pInfo->pUpdated) { + pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey)); + } + if (!pInfo->pStUpdated) { + _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); + pInfo->pStUpdated = tSimpleHashInit(64, hashFn); + } while (1) { SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); if (pBlock == NULL) { @@ -3652,13 +3662,17 @@ static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) { // gap must be 0 SArray* pWins = taosArrayInit(16, sizeof(SSessionKey)); doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, pWins); - removeSessionResults(pStUpdated, pWins); + removeSessionResults(pInfo->pStUpdated, pWins); copyDeleteWindowInfo(pWins, pInfo->pStDeleted); taosArrayDestroy(pWins); break; } else if (pBlock->info.type == STREAM_GET_ALL) { - getAllSessionWindow(pInfo->streamAggSup.pResultRows, pStUpdated); + getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pStUpdated); continue; + } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) { + return pBlock; + } else { + ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type"); } if (pInfo->scalarSupp.pExprInfo != NULL) { @@ -3667,18 +3681,20 @@ static SSDataBlock* doStreamSessionSemiAgg(SOperatorInfo* pOperator) { } // the pDataBlock are always the same one, no need to call this again setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true); - doStreamSessionAggImpl(pOperator, pBlock, pStUpdated, NULL, false); + doStreamSessionAggImpl(pOperator, pBlock, pInfo->pStUpdated, NULL, false); maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey); } pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs); pBInfo->pRes->info.watermark = pInfo->twAggSup.maxTs; - copyUpdateResult(pStUpdated, pUpdated); - removeSessionResults(pInfo->pStDeleted, pUpdated); - tSimpleHashCleanup(pStUpdated); + copyUpdateResult(pInfo->pStUpdated, pInfo->pUpdated); + removeSessionResults(pInfo->pStDeleted, pInfo->pUpdated); + tSimpleHashCleanup(pInfo->pStUpdated); + pInfo->pStUpdated = NULL; - initGroupResInfoFromArrayList(&pInfo->groupResInfo, pUpdated); + initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated); + pInfo->pUpdated = NULL; blockDataEnsureCapacity(pBInfo->pRes, pOperator->resultInfo.capacity); #if 0 @@ -3767,7 +3783,7 @@ void destroyStreamStateOperatorInfo(void* param) { int32_t size = taosArrayGetSize(pInfo->pChildren); for (int32_t i = 0; i < size; i++) { SOperatorInfo* pChild = taosArrayGetP(pInfo->pChildren, i); - destroyOperatorInfo(pChild); + destroyOperator(pChild); } taosArrayDestroy(pInfo->pChildren); } @@ -3874,6 +3890,9 @@ static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBl TSKEY* tsCols = NULL; SResultRow* pResult = NULL; int32_t winRows = 0; + + pInfo->dataVersion = TMAX(pInfo->dataVersion, pSDataBlock->info.version); + if (pSDataBlock->pDataBlock != NULL) { SColumnInfoData* pColDataInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->primaryTsIndex); tsCols = (int64_t*)pColDataInfo->pData; @@ -3886,7 +3905,7 @@ static void doStreamStateAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBl blockDataEnsureCapacity(pAggSup->pScanBlock, rows); SColumnInfoData* pKeyColInfo = taosArrayGet(pSDataBlock->pDataBlock, pInfo->stateCol.slotId); for (int32_t i = 0; i < rows; i += winRows) { - if (pInfo->ignoreExpiredData && isOverdue(tsCols[i], &pInfo->twAggSup)) { + if (pInfo->ignoreExpiredData && isOverdue(tsCols[i], &pInfo->twAggSup) || colDataIsNull_s(pKeyColInfo, i)) { i++; continue; } @@ -3938,7 +3957,6 @@ static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) { SExprSupp* pSup = &pOperator->exprSupp; SStreamStateAggOperatorInfo* pInfo = pOperator->info; SOptrBasicInfo* pBInfo = &pInfo->binfo; - int64_t maxTs = INT64_MIN; if (pOperator->status == OP_RES_TO_RETURN) { doBuildDeleteDataBlock(pOperator, pInfo->pSeDeleted, pInfo->pDelRes, &pInfo->pDelIterator); if (pInfo->pDelRes->info.rows > 0) { @@ -3956,10 +3974,14 @@ static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) { return NULL; } - _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); - SSHashObj* pSeUpdated = tSimpleHashInit(64, hashFn); SOperatorInfo* downstream = pOperator->pDownstream[0]; - SArray* pUpdated = taosArrayInit(16, sizeof(SSessionKey)); + if (!pInfo->pUpdated) { + pInfo->pUpdated = taosArrayInit(16, sizeof(SSessionKey)); + } + if (!pInfo->pSeUpdated) { + _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); + pInfo->pSeUpdated = tSimpleHashInit(64, hashFn); + } while (1) { SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); if (pBlock == NULL) { @@ -3971,13 +3993,17 @@ static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) { pBlock->info.type == STREAM_CLEAR) { SArray* pWins = taosArrayInit(16, sizeof(SSessionKey)); doDeleteTimeWindows(&pInfo->streamAggSup, pBlock, pWins); - removeSessionResults(pSeUpdated, pWins); + removeSessionResults(pInfo->pSeUpdated, pWins); copyDeleteWindowInfo(pWins, pInfo->pSeDeleted); taosArrayDestroy(pWins); continue; } else if (pBlock->info.type == STREAM_GET_ALL) { - getAllSessionWindow(pInfo->streamAggSup.pResultRows, pSeUpdated); + getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated); continue; + } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) { + return pBlock; + } else { + ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type"); } if (pInfo->scalarSupp.pExprInfo != NULL) { @@ -3986,19 +4012,20 @@ static SSDataBlock* doStreamStateAgg(SOperatorInfo* pOperator) { } // the pDataBlock are always the same one, no need to call this again setInputDataBlock(pSup, pBlock, TSDB_ORDER_ASC, MAIN_SCAN, true); - doStreamStateAggImpl(pOperator, pBlock, pSeUpdated, pInfo->pSeDeleted); - maxTs = TMAX(maxTs, pBlock->info.window.ekey); + doStreamStateAggImpl(pOperator, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted); + pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey); } - pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs); // restore the value pOperator->status = OP_RES_TO_RETURN; - closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pSeUpdated); - copyUpdateResult(pSeUpdated, pUpdated); - removeSessionResults(pInfo->pSeDeleted, pUpdated); - tSimpleHashCleanup(pSeUpdated); + closeSessionWindow(pInfo->streamAggSup.pResultRows, &pInfo->twAggSup, pInfo->pSeUpdated); + copyUpdateResult(pInfo->pSeUpdated, pInfo->pUpdated); + removeSessionResults(pInfo->pSeDeleted, pInfo->pUpdated); + tSimpleHashCleanup(pInfo->pSeUpdated); + pInfo->pSeUpdated = NULL; - initGroupResInfoFromArrayList(&pInfo->groupResInfo, pUpdated); + initGroupResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated); + pInfo->pUpdated = NULL; blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity); #if 0 @@ -4079,6 +4106,10 @@ SOperatorInfo* createStreamStateAggOperatorInfo(SOperatorInfo* downstream, SPhys pInfo->pDelRes = createSpecialDataBlock(STREAM_DELETE_RESULT); pInfo->pChildren = NULL; pInfo->ignoreExpiredData = pStateNode->window.igExpired; + pInfo->ignoreExpiredDataSaved = false; + pInfo->pUpdated = NULL; + pInfo->pSeUpdated = NULL; + pInfo->dataVersion = 0; setOperatorInfo(pOperator, "StreamStateAggOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE, true, OP_NOT_OPENED, pInfo, pTaskInfo); @@ -4258,7 +4289,7 @@ static void doMergeAlignedIntervalAgg(SOperatorInfo* pOperator) { } } - getTableScanInfo(pOperator, &pIaInfo->inputOrder, &scanFlag); + getTableScanInfo(pOperator, &pIaInfo->inputOrder, &scanFlag, false); setInputDataBlock(pSup, pBlock, pIaInfo->inputOrder, scanFlag, true); doMergeAlignedIntervalAggImpl(pOperator, &pIaInfo->binfo.resultRowInfo, pBlock, pRes); @@ -4585,7 +4616,7 @@ static SSDataBlock* doMergeIntervalAgg(SOperatorInfo* pOperator) { break; } - getTableScanInfo(pOperator, &iaInfo->inputOrder, &scanFlag); + getTableScanInfo(pOperator, &iaInfo->inputOrder, &scanFlag, false); setInputDataBlock(pExpSupp, pBlock, iaInfo->inputOrder, scanFlag, true); doMergeIntervalAggImpl(pOperator, &iaInfo->binfo.resultRowInfo, pBlock, scanFlag, pRes); @@ -4692,8 +4723,6 @@ _error: static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) { SStreamIntervalOperatorInfo* pInfo = pOperator->info; SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; - int64_t maxTs = INT64_MIN; - int64_t minTs = INT64_MAX; SExprSupp* pSup = &pOperator->exprSupp; if (pOperator->status == OP_EXEC_DONE) { @@ -4707,7 +4736,7 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) { return pInfo->pDelRes; } - doBuildResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); + doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); if (pInfo->binfo.pRes->info.rows > 0) { printDataBlock(pInfo->binfo.pRes, "single interval"); return pInfo->binfo.pRes; @@ -4716,15 +4745,20 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) { &pInfo->delKey); setOperatorCompleted(pOperator); streamStateCommit(pTaskInfo->streamInfo.pState); + setStreamDataVersion(pTaskInfo, pInfo->dataVersion, pInfo->pState->checkPointId); return NULL; } SOperatorInfo* downstream = pOperator->pDownstream[0]; - SArray* pUpdated = taosArrayInit(4, POINTER_BYTES); // SResKeyPos + if (!pInfo->pUpdated) { + pInfo->pUpdated = taosArrayInit(4, sizeof(SWinKey)); + } - _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); - SHashObj* pUpdatedMap = taosHashInit(1024, hashFn, false, HASH_NO_LOCK); + if (!pInfo->pUpdatedMap) { + _hash_fn_t hashFn = taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY); + pInfo->pUpdatedMap = tSimpleHashInit(1024, hashFn); + } while (1) { SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); @@ -4733,16 +4767,22 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) { pInfo->numOfDatapack = 0; break; } + pInfo->numOfDatapack++; printDataBlock(pBlock, "single interval recv"); if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT || pBlock->info.type == STREAM_CLEAR) { - doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pUpdatedMap); + doDeleteWindows(pOperator, &pInfo->interval, pBlock, pInfo->pDelWins, pInfo->pUpdatedMap); continue; } else if (pBlock->info.type == STREAM_GET_ALL) { - getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pUpdatedMap); + getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pInfo->pUpdatedMap); continue; + } else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) { + printDataBlock(pBlock, "single interval"); + return pBlock; + } else { + ASSERTS(pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_INVALID, "invalid SSDataBlock type"); } if (pBlock->info.type == STREAM_NORMAL && pBlock->info.version != 0) { @@ -4763,28 +4803,28 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) { setInverFunction(pSup->pCtx, pOperator->exprSupp.numOfExprs, pBlock->info.type); } - maxTs = TMAX(maxTs, pBlock->info.window.ekey); - minTs = TMIN(minTs, pBlock->info.window.skey); - - doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pUpdatedMap); + doStreamIntervalAggImpl(pOperator, pBlock, pBlock->info.id.groupId, pInfo->pUpdatedMap); + pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, pBlock->info.window.ekey); + pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, pBlock->info.window.skey); } - pInfo->twAggSup.maxTs = TMAX(pInfo->twAggSup.maxTs, maxTs); - pInfo->twAggSup.minTs = TMIN(pInfo->twAggSup.minTs, minTs); pOperator->status = OP_RES_TO_RETURN; - removeDeleteResults(pUpdatedMap, pInfo->pDelWins); - closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL, pUpdatedMap, - pInfo->pDelWins, pOperator); + removeDeleteResults(pInfo->pUpdatedMap, pInfo->pDelWins); + closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, NULL, + pInfo->pUpdatedMap, pInfo->pDelWins, pOperator); - void* pIte = NULL; - while ((pIte = taosHashIterate(pUpdatedMap, pIte)) != NULL) { - taosArrayPush(pUpdated, pIte); + void* pIte = NULL; + int32_t iter = 0; + while ((pIte = tSimpleHashIterate(pInfo->pUpdatedMap, pIte, &iter)) != NULL) { + SWinKey* pKey = tSimpleHashGetKey(pIte, NULL); + taosArrayPush(pInfo->pUpdated, pKey); } - taosArraySort(pUpdated, resultrowComparAsc); - - initMultiResInfoFromArrayList(&pInfo->groupResInfo, pUpdated); + taosArraySort(pInfo->pUpdated, winKeyCmprImpl); + initMultiResInfoFromArrayList(&pInfo->groupResInfo, pInfo->pUpdated); + pInfo->pUpdated = NULL; blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity); - taosHashCleanup(pUpdatedMap); + tSimpleHashCleanup(pInfo->pUpdatedMap); + pInfo->pUpdatedMap = NULL; #if 0 char* pBuf = streamStateIntervalDump(pInfo->pState); @@ -4798,7 +4838,7 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) { return pInfo->pDelRes; } - doBuildResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); + doBuildStreamIntervalResult(pOperator, pInfo->pState, pInfo->binfo.pRes, &pInfo->groupResInfo); if (pInfo->binfo.pRes->info.rows > 0) { printDataBlock(pInfo->binfo.pRes, "single interval"); return pInfo->binfo.pRes; @@ -4844,6 +4884,7 @@ SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhys pInfo->interval = interval; pInfo->twAggSup = twAggSupp; pInfo->ignoreExpiredData = pIntervalPhyNode->window.igExpired; + pInfo->ignoreExpiredDataSaved = false; pInfo->isFinal = false; SExprSupp* pSup = &pOperator->exprSupp; @@ -4891,6 +4932,8 @@ SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhys pInfo->delKey.ts = INT64_MAX; pInfo->delKey.groupId = 0; pInfo->numOfDatapack = 0; + pInfo->pUpdated = NULL; + pInfo->pUpdatedMap = NULL; setOperatorInfo(pOperator, "StreamIntervalOperator", QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, true, OP_NOT_OPENED, pInfo, pTaskInfo); @@ -4911,4 +4954,3 @@ _error: pTaskInfo->code = code; return NULL; } - diff --git a/source/libs/executor/src/tsort.c b/source/libs/executor/src/tsort.c index 90f20f40b820c9503eeb13be1e52de8eb4c4a66b..36e41b0c5d5437ec3ed9b60eafe6af47e00fec65 100644 --- a/source/libs/executor/src/tsort.c +++ b/source/libs/executor/src/tsort.c @@ -90,7 +90,7 @@ SSortHandle* tsortCreateSortHandle(SArray* pSortInfo, int32_t type, int32_t page tsortSetComparFp(pSortHandle, msortComparFn); if (idstr != NULL) { - pSortHandle->idStr = strdup(idstr); + pSortHandle->idStr = taosStrdup(idstr); } return pSortHandle; @@ -108,12 +108,18 @@ static int32_t sortComparCleanup(SMsortComparParam* cmpParam) { return TSDB_CODE_SUCCESS; } -void tsortClearOrderdSource(SArray* pOrderedSource) { +void tsortClearOrderdSource(SArray* pOrderedSource, int64_t *fetchUs, int64_t *fetchNum) { for (size_t i = 0; i < taosArrayGetSize(pOrderedSource); i++) { SSortSource** pSource = taosArrayGet(pOrderedSource, i); if (NULL == *pSource) { continue; } + + if (fetchUs) { + *fetchUs += (*pSource)->fetchUs; + *fetchNum += (*pSource)->fetchNum; + } + // release pageIdList if ((*pSource)->pageIdList) { taosArrayDestroy((*pSource)->pageIdList); @@ -147,7 +153,10 @@ void tsortDestroySortHandle(SSortHandle* pSortHandle) { taosMemoryFreeClear(pSortHandle->idStr); blockDataDestroy(pSortHandle->pDataBlock); - tsortClearOrderdSource(pSortHandle->pOrderedSource); + int64_t fetchUs = 0, fetchNum = 0; + tsortClearOrderdSource(pSortHandle->pOrderedSource, &fetchUs, &fetchNum); + qDebug("all source fetch time: %" PRId64 "us num:%" PRId64 " %s", fetchUs, fetchNum, pSortHandle->idStr); + taosArrayDestroy(pSortHandle->pOrderedSource); taosMemoryFreeClear(pSortHandle); } @@ -212,6 +221,7 @@ static int32_t doAddToBuf(SSDataBlock* pDataBlock, SSortHandle* pHandle) { int32_t pageId = -1; void* pPage = getNewBufPage(pHandle->pBuf, &pageId); if (pPage == NULL) { + taosArrayDestroy(pPageIdList); blockDataDestroy(p); return terrno; } @@ -219,7 +229,7 @@ static int32_t doAddToBuf(SSDataBlock* pDataBlock, SSortHandle* pHandle) { taosArrayPush(pPageIdList, &pageId); int32_t size = blockDataGetSize(p) + sizeof(int32_t) + taosArrayGetSize(p->pDataBlock) * sizeof(int32_t); - assert(size <= getBufPageSize(pHandle->pBuf)); + ASSERT(size <= getBufPageSize(pHandle->pBuf)); blockDataToBuf(pPage, p); @@ -320,10 +330,10 @@ static void appendOneRowToDataBlock(SSDataBlock* pBlock, const SSDataBlock* pSou bool isNull = colDataIsNull(pSrcColInfo, pSource->info.rows, *rowIndex, NULL); if (isNull) { - colDataAppend(pColInfo, pBlock->info.rows, NULL, true); + colDataSetVal(pColInfo, pBlock->info.rows, NULL, true); } else { char* pData = colDataGetData(pSrcColInfo, *rowIndex); - colDataAppend(pColInfo, pBlock->info.rows, pData, false); + colDataSetVal(pColInfo, pBlock->info.rows, pData, false); } } @@ -364,7 +374,10 @@ static int32_t adjustMergeTreeForNextTuple(SSortSource* pSource, SMultiwayMergeT releaseBufPage(pHandle->pBuf, pPage); } } else { + int64_t st = taosGetTimestampUs(); pSource->src.pBlock = pHandle->fetchfp(((SSortSource*)pSource)->param); + pSource->fetchUs += taosGetTimestampUs() - st; + pSource->fetchNum++; if (pSource->src.pBlock == NULL) { (*numOfCompleted) += 1; pSource->src.rowIndex = -1; @@ -579,7 +592,7 @@ static int32_t doInternalMergeSort(SSortHandle* pHandle) { int32_t size = blockDataGetSize(pDataBlock) + sizeof(int32_t) + taosArrayGetSize(pDataBlock->pDataBlock) * sizeof(int32_t); - assert(size <= getBufPageSize(pHandle->pBuf)); + ASSERT(size <= getBufPageSize(pHandle->pBuf)); blockDataToBuf(pPage, pDataBlock); @@ -601,7 +614,7 @@ static int32_t doInternalMergeSort(SSortHandle* pHandle) { } } - tsortClearOrderdSource(pHandle->pOrderedSource); + tsortClearOrderdSource(pHandle->pOrderedSource, NULL, NULL); taosArrayAddAll(pHandle->pOrderedSource, pResList); taosArrayDestroy(pResList); @@ -643,7 +656,7 @@ static int32_t createInitialSources(SSortHandle* pHandle) { SSortSource* source = *pSource; *pSource = NULL; - tsortClearOrderdSource(pHandle->pOrderedSource); + tsortClearOrderdSource(pHandle->pOrderedSource, NULL, NULL); while (1) { SSDataBlock* pBlock = pHandle->fetchfp(source->param); diff --git a/source/libs/executor/test/executorTests.cpp b/source/libs/executor/test/executorTests.cpp index 913aae6cc3ae489aa725ea255ce9ecce4482a13d..cefe12990d53ade95ba48c3f9e380dbdb2e1f62a 100644 --- a/source/libs/executor/test/executorTests.cpp +++ b/source/libs/executor/test/executorTests.cpp @@ -24,15 +24,12 @@ #include "os.h" #include "executor.h" -#include "executorimpl.h" +#include "executorInt.h" #include "function.h" +#include "operator.h" #include "taos.h" #include "tdatablock.h" #include "tdef.h" -#include "tglobal.h" -#include "tmsg.h" -#include "tname.h" -#include "trpc.h" #include "tvariant.h" namespace { @@ -110,13 +107,13 @@ SSDataBlock* getDummyBlock(SOperatorInfo* pOperator) { v = taosRand(); } - colDataAppend(pColInfo, i, reinterpret_cast(&v), false); + colDataSetVal(pColInfo, i, reinterpret_cast(&v), false); // sprintf(buf, "this is %d row", i); // STR_TO_VARSTR(b1, buf); // // SColumnInfoData* pColInfo2 = static_cast(TARRAY_GET_ELEM(pBlock->pDataBlock, 1)); - // colDataAppend(pColInfo2, i, b1, false); + // colDataSetVal(pColInfo2, i, b1, false); } pBlock->info.rows = pInfo->numOfRowsPerPage; @@ -155,7 +152,7 @@ SSDataBlock* get2ColsDummyBlock(SOperatorInfo* pOperator) { SColumnInfoData* pColInfo = static_cast(TARRAY_GET_ELEM(pBlock->pDataBlock, 0)); ts = (++pInfo->tsStart); - colDataAppend(pColInfo, i, reinterpret_cast(&ts), false); + colDataSetVal(pColInfo, i, reinterpret_cast(&ts), false); SColumnInfoData* pColInfo1 = static_cast(TARRAY_GET_ELEM(pBlock->pDataBlock, 1)); if (pInfo->type == data_desc) { @@ -166,13 +163,13 @@ SSDataBlock* get2ColsDummyBlock(SOperatorInfo* pOperator) { v = taosRand(); } - colDataAppend(pColInfo1, i, reinterpret_cast(&v), false); + colDataSetVal(pColInfo1, i, reinterpret_cast(&v), false); // sprintf(buf, "this is %d row", i); // STR_TO_VARSTR(b1, buf); // // SColumnInfoData* pColInfo2 = static_cast(TARRAY_GET_ELEM(pBlock->pDataBlock, 1)); - // colDataAppend(pColInfo2, i, b1, false); + // colDataSetVal(pColInfo2, i, b1, false); } pBlock->info.rows = pInfo->numOfRowsPerPage; diff --git a/source/libs/executor/test/lhashTests.cpp b/source/libs/executor/test/lhashTests.cpp index 24570ff7889aa09dcd160a8703be88e57bbc35c9..92f7652d8df01c8ed8cfa74ef77a5d6d84048d3a 100644 --- a/source/libs/executor/test/lhashTests.cpp +++ b/source/libs/executor/test/lhashTests.cpp @@ -15,7 +15,7 @@ #include #include -#include "executorimpl.h" +#include "executorInt.h" #include "tlinearhash.h" #pragma GCC diagnostic push diff --git a/source/libs/executor/test/sortTests.cpp b/source/libs/executor/test/sortTests.cpp index 62813453a1398f51bc2667879e9b7cf07194b449..8122d7d6a91fed15eddce1fa74150600475043c0 100644 --- a/source/libs/executor/test/sortTests.cpp +++ b/source/libs/executor/test/sortTests.cpp @@ -26,7 +26,7 @@ #include "os.h" #include "executor.h" -#include "executorimpl.h" +#include "executorInt.h" #include "taos.h" #include "tcompare.h" #include "tdatablock.h" @@ -91,7 +91,7 @@ SSDataBlock* getSingleColDummyBlock(void* param) { return NULL; } varDataSetLen(str, len); - colDataAppend(pColInfo, i, reinterpret_cast(str), false); + colDataSetVal(pColInfo, i, reinterpret_cast(str), false); pBlock->info.hasVarCol = true; printf("nchar: %s\n", strOri); } else if (pInfo->type == TSDB_DATA_TYPE_BINARY) { @@ -99,12 +99,12 @@ SSDataBlock* getSingleColDummyBlock(void* param) { char str[64] = {0}; taosRandStr(varDataVal(str), size); varDataSetLen(str, size); - colDataAppend(pColInfo, i, reinterpret_cast(str), false); + colDataSetVal(pColInfo, i, reinterpret_cast(str), false); pBlock->info.hasVarCol = true; printf("binary: %s\n", varDataVal(str)); } else if (pInfo->type == TSDB_DATA_TYPE_DOUBLE || pInfo->type == TSDB_DATA_TYPE_FLOAT) { double v = rand_f2(); - colDataAppend(pColInfo, i, reinterpret_cast(&v), false); + colDataSetVal(pColInfo, i, reinterpret_cast(&v), false); printf("float: %f\n", v); } else { int64_t v = ++pInfo->startVal; @@ -115,7 +115,7 @@ SSDataBlock* getSingleColDummyBlock(void* param) { memcpy(result, (char*)(&v) + sizeof(int64_t) - tDataTypes[pInfo->type].bytes, tDataTypes[pInfo->type].bytes); } - colDataAppend(pColInfo, i, result, false); + colDataSetVal(pColInfo, i, result, false); printf("int: %" PRId64 "\n", v); taosMemoryFree(result); } diff --git a/source/libs/function/CMakeLists.txt b/source/libs/function/CMakeLists.txt index 9d11d7b376b0de0e3f8b8fb5ad533cab72c90c19..f23b4d3e8762951a791529930781f657294c7d13 100644 --- a/source/libs/function/CMakeLists.txt +++ b/source/libs/function/CMakeLists.txt @@ -79,6 +79,26 @@ ENDIF () target_link_libraries( udf1 PUBLIC os ${LINK_JEMALLOC}) + +add_library(udf1_dup STATIC MODULE test/udf1_dup.c) +target_include_directories( + udf1_dup + PUBLIC + "${TD_SOURCE_DIR}/include/libs/function" + "${TD_SOURCE_DIR}/include/util" + "${TD_SOURCE_DIR}/include/common" + "${TD_SOURCE_DIR}/include/client" + "${TD_SOURCE_DIR}/include/os" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" +) + +IF (TD_LINUX_64 AND JEMALLOC_ENABLED) + ADD_DEPENDENCIES(udf1_dup jemalloc) +ENDIF () + +target_link_libraries( + udf1_dup PUBLIC os ${LINK_JEMALLOC}) + add_library(udf2 STATIC MODULE test/udf2.c) target_include_directories( udf2 @@ -99,6 +119,26 @@ target_link_libraries( udf2 PUBLIC os ${LINK_JEMALLOC} ) +add_library(udf2_dup STATIC MODULE test/udf2_dup.c) +target_include_directories( + udf2_dup + PUBLIC + "${TD_SOURCE_DIR}/include/libs/function" + "${TD_SOURCE_DIR}/include/util" + "${TD_SOURCE_DIR}/include/common" + "${TD_SOURCE_DIR}/include/client" + "${TD_SOURCE_DIR}/include/os" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" +) + +IF (TD_LINUX_64 AND JEMALLOC_ENABLED) + ADD_DEPENDENCIES(udf2_dup jemalloc) +ENDIF () + +target_link_libraries( + udf2_dup PUBLIC os ${LINK_JEMALLOC} +) + #SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/build/bin) add_executable(udfd src/udfd.c) target_include_directories( diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h index dc884a058193e0abbefa04cff086788733f59a87..c3afc30a7b203469b0da23244dc281e64f32bd69 100644 --- a/source/libs/function/inc/builtinsimpl.h +++ b/source/libs/function/inc/builtinsimpl.h @@ -235,6 +235,7 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock); bool getGroupKeyFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv); int32_t groupKeyFunction(SqlFunctionCtx* pCtx); int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock); +int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx); #ifdef __cplusplus } diff --git a/source/libs/function/inc/tudfInt.h b/source/libs/function/inc/tudfInt.h index c69d19b8a6187ad1d6817a6b5f8793b0905817e4..27d3b7930f80905f76704250765dc63040d33353 100644 --- a/source/libs/function/inc/tudfInt.h +++ b/source/libs/function/inc/tudfInt.h @@ -41,7 +41,7 @@ typedef struct SUdfSetupRequest { typedef struct SUdfSetupResponse { int64_t udfHandle; int8_t outputType; - int32_t outputLen; + int32_t bytes; int32_t bufSize; } SUdfSetupResponse; diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index faf7a29dd0aa34031325dc9c0b49cf46e403e78a..a293f452383505de201c147744da7dcc2e1ec8ff 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -213,8 +213,9 @@ static int32_t addTimezoneParam(SNodeList* pList) { char buf[6] = {0}; time_t t = taosTime(NULL); struct tm tmInfo; - taosLocalTime(&t, &tmInfo); - strftime(buf, sizeof(buf), "%z", &tmInfo); + if (taosLocalTime(&t, &tmInfo, buf) != NULL) { + strftime(buf, sizeof(buf), "%z", &tmInfo); + } int32_t len = (int32_t)strlen(buf); SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); @@ -466,7 +467,7 @@ static int32_t translateStddevMerge(SFunctionNode* pFunc, char* pErrBuf, int32_t static int32_t translateWduration(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { // pseudo column do not need to check parameters - pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT}; + pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT}; return TSDB_CODE_SUCCESS; } @@ -480,14 +481,23 @@ static int32_t translateNowToday(SFunctionNode* pFunc, char* pErrBuf, int32_t le return code; } - pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_TIMESTAMP}; + pFunc->node.resType = + (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes, .type = TSDB_DATA_TYPE_TIMESTAMP}; return TSDB_CODE_SUCCESS; } static int32_t translateTimePseudoColumn(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { // pseudo column do not need to check parameters - pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_TIMESTAMP}; + pFunc->node.resType = + (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes, .type = TSDB_DATA_TYPE_TIMESTAMP}; + return TSDB_CODE_SUCCESS; +} + +static int32_t translateIsFilledPseudoColumn(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + // pseudo column do not need to check parameters + + pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes, .type = TSDB_DATA_TYPE_BOOL}; return TSDB_CODE_SUCCESS; } @@ -497,27 +507,43 @@ static int32_t translateTimezone(SFunctionNode* pFunc, char* pErrBuf, int32_t le } static int32_t translatePercentile(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { - if (2 != LIST_LENGTH(pFunc->pParameterList)) { + int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); + if (numOfParams < 2 || numOfParams > 11) { return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); } - // param1 - SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1); - - if (pValue->datum.i < 0 || pValue->datum.i > 100) { - return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName); + uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; + if (!IS_NUMERIC_TYPE(para1Type)) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } - pValue->notReserved = true; + for (int32_t i = 1; i < numOfParams; ++i) { + SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, i); + pValue->notReserved = true; - uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; - uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type; - if (!IS_NUMERIC_TYPE(para1Type) || (!IS_SIGNED_NUMERIC_TYPE(para2Type) && !IS_UNSIGNED_NUMERIC_TYPE(para2Type))) { - return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); + uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, i))->resType.type; + if (!IS_NUMERIC_TYPE(paraType)) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); + } + + double v = 0; + if (IS_INTEGER_TYPE(paraType)) { + v = (double)pValue->datum.i; + } else { + v = pValue->datum.d; + } + + if (v < 0 || v > 100) { + return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName); + } } // set result type - pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE}; + if (numOfParams > 2) { + pFunc->node.resType = (SDataType){.bytes = 512, .type = TSDB_DATA_TYPE_VARCHAR}; + } else { + pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE}; + } return TSDB_CODE_SUCCESS; } @@ -1549,7 +1575,7 @@ static int32_t translateInterp(SFunctionNode* pFunc, char* pErrBuf, int32_t len) uint8_t nodeType = nodeType(nodesListGetNode(pFunc->pParameterList, 0)); uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; - if (!IS_NUMERIC_TYPE(paraType) || QUERY_NODE_VALUE == nodeType) { + if ((!IS_NUMERIC_TYPE(paraType) && !IS_BOOLEAN_TYPE(paraType))|| QUERY_NODE_VALUE == nodeType) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } @@ -2266,8 +2292,9 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "percentile", .type = FUNCTION_TYPE_PERCENTILE, - .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_REPEAT_SCAN_FUNC | FUNC_MGT_FORBID_STREAM_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_REPEAT_SCAN_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED | FUNC_MGT_FORBID_STREAM_FUNC, .translateFunc = translatePercentile, + .dataRequiredFunc = statisDataRequired, .getEnvFunc = getPercentileFuncEnv, .initFunc = percentileFunctionSetup, .processFunc = percentileFunction, @@ -2349,7 +2376,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "spread", .type = FUNCTION_TYPE_SPREAD, - .classification = FUNC_MGT_AGG_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED, .translateFunc = translateSpread, .dataRequiredFunc = statisDataRequired, .getEnvFunc = getSpreadFuncEnv, @@ -2391,7 +2418,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "elapsed", .type = FUNCTION_TYPE_ELAPSED, - .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_FORBID_STREAM_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED, .dataRequiredFunc = statisDataRequired, .translateFunc = translateElapsed, .getEnvFunc = getElapsedFuncEnv, @@ -2431,7 +2458,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .name = "interp", .type = FUNCTION_TYPE_INTERP, .classification = FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | - FUNC_MGT_FORBID_STREAM_FUNC, + FUNC_MGT_FORBID_STREAM_FUNC|FUNC_MGT_KEEP_ORDER_FUNC, .translateFunc = translateInterp, .getEnvFunc = getSelectivityFuncEnv, .initFunc = functionSetup, @@ -2454,7 +2481,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "irate", .type = FUNCTION_TYPE_IRATE, - .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | FUNC_MGT_FORBID_STREAM_FUNC, .translateFunc = translateIrate, .getEnvFunc = getIrateFuncEnv, .initFunc = irateFuncSetup, @@ -2465,7 +2492,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "last_row", .type = FUNCTION_TYPE_LAST_ROW, - .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_MULTI_RES_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, .translateFunc = translateFirstLast, .dynDataRequiredFunc = lastDynDataReq, .getEnvFunc = getFirstLastFuncEnv, @@ -2474,7 +2501,8 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .sprocessFunc = firstLastScalarFunction, .pPartialFunc = "_last_row_partial", .pMergeFunc = "_last_row_merge", - .finalizeFunc = firstLastFinalize + .finalizeFunc = firstLastFinalize, + .combineFunc = lastCombine }, { .name = "_cache_last_row", @@ -2783,7 +2811,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "mode", .type = FUNCTION_TYPE_MODE, - .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC | FUNC_MGT_FORBID_STREAM_FUNC, .translateFunc = translateMode, .getEnvFunc = getModeFuncEnv, .initFunc = modeFunctionSetup, @@ -3186,7 +3214,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "_block_dist", .type = FUNCTION_TYPE_BLOCK_DIST, - .classification = FUNC_MGT_AGG_FUNC, + .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_FORBID_STREAM_FUNC, .translateFunc = translateBlockDistFunc, .getEnvFunc = getBlockDistFuncEnv, .initFunc = blockDistSetup, @@ -3208,6 +3236,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .initFunc = functionSetup, .processFunc = groupKeyFunction, .finalizeFunc = groupKeyFinalize, + .combineFunc = groupKeyCombine, .pPartialFunc = "_group_key", .pMergeFunc = "_group_key" }, @@ -3250,13 +3279,23 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { { .name = "_irowts", .type = FUNCTION_TYPE_IROWTS, - .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_INTERP_PC_FUNC, + .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_INTERP_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, .translateFunc = translateTimePseudoColumn, .getEnvFunc = getTimePseudoFuncEnv, .initFunc = NULL, .sprocessFunc = NULL, .finalizeFunc = NULL }, + { + .name = "_isfilled", + .type = FUNCTION_TYPE_ISFILLED, + .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_INTERP_PC_FUNC, + .translateFunc = translateIsFilledPseudoColumn, + .getEnvFunc = NULL, + .initFunc = NULL, + .sprocessFunc = NULL, + .finalizeFunc = NULL + }, { .name = "_tags", .type = FUNCTION_TYPE_TAGS, diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 50ceda4605393b224eac68553091c3bc320f166e..4c019b3e710961065e0f4439f2f4f4baeb9de990 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -32,9 +32,6 @@ #define TAIL_MAX_POINTS_NUM 100 #define TAIL_MAX_OFFSET 100 -#define UNIQUE_MAX_RESULT_SIZE (1024 * 1024 * 10) -#define MODE_MAX_RESULT_SIZE UNIQUE_MAX_RESULT_SIZE - #define HLL_BUCKET_BITS 14 // The bits of the bucket #define HLL_DATA_BITS (64 - HLL_BUCKET_BITS) #define HLL_BUCKETS (1 << HLL_BUCKET_BITS) @@ -244,12 +241,11 @@ typedef struct SUniqueInfo { typedef struct SModeItem { int64_t count; + STuplePos dataPos; STuplePos tuplePos; - char data[]; } SModeItem; typedef struct SModeInfo { - int32_t numOfPoints; uint8_t colType; int16_t colBytes; SHashObj* pHash; @@ -257,7 +253,7 @@ typedef struct SModeInfo { STuplePos nullTuplePos; bool nullTupleSaved; - char pItems[]; + char* buf; // serialize data buffer } SModeInfo; typedef struct SDerivInfo { @@ -446,7 +442,7 @@ int32_t functionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0; char* in = GET_ROWCELL_INTERBUF(pResInfo); - colDataAppend(pCol, pBlock->info.rows, in, pResInfo->isNullRes); + colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes); return pResInfo->numOfRes; } @@ -476,7 +472,7 @@ int32_t functionFinalizeWithResultBuf(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0; char* in = finalResult; - colDataAppend(pCol, pBlock->info.rows, in, pResInfo->isNullRes); + colDataSetVal(pCol, pBlock->info.rows, in, pResInfo->isNullRes); return pResInfo->numOfRes; } @@ -494,8 +490,8 @@ bool getCountFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) { return true; } -static int32_t getNumOfElems(SqlFunctionCtx* pCtx) { - int32_t numOfElem = 0; +static int64_t getNumOfElems(SqlFunctionCtx* pCtx) { + int64_t numOfElem = 0; /* * 1. column data missing (schema modified) causes pInputCol->hasNull == true. pInput->colDataSMAIsSet == true; @@ -528,7 +524,7 @@ static int32_t getNumOfElems(SqlFunctionCtx* pCtx) { * count function does not use the pCtx->interResBuf to keep the intermediate buffer */ int32_t countFunction(SqlFunctionCtx* pCtx) { - int32_t numOfElem = 0; + int64_t numOfElem = 0; SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); SInputColumnInfoData* pInput = &pCtx->input; @@ -555,7 +551,7 @@ int32_t countFunction(SqlFunctionCtx* pCtx) { } int32_t countInvertFunction(SqlFunctionCtx* pCtx) { - int32_t numOfElem = getNumOfElems(pCtx); + int64_t numOfElem = getNumOfElems(pCtx); SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); char* buf = GET_ROWCELL_INTERBUF(pResInfo); @@ -775,13 +771,13 @@ int32_t maxFunction(SqlFunctionCtx* pCtx) { static int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32_t rowIndex); static int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STuplePos* pTuplePos, - int32_t rowIndex); + int32_t rowIndex); int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t code = TSDB_CODE_SUCCESS; SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx); - SMinmaxResInfo* pRes = GET_ROWCELL_INTERBUF(pEntryInfo); + SMinmaxResInfo* pRes = GET_ROWCELL_INTERBUF(pEntryInfo); int32_t slotId = pCtx->pExpr->base.resSchema.slotId; int32_t currentRow = pBlock->info.rows; @@ -795,32 +791,31 @@ int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { case TSDB_DATA_TYPE_UBIGINT: case TSDB_DATA_TYPE_BIGINT: ((int64_t*)pCol->pData)[currentRow] = pRes->v; -// colDataAppendInt64(pCol, currentRow, &pRes->v); break; case TSDB_DATA_TYPE_UINT: case TSDB_DATA_TYPE_INT: - colDataAppendInt32(pCol, currentRow, (int32_t*)&pRes->v); + colDataSetInt32(pCol, currentRow, (int32_t*)&pRes->v); break; case TSDB_DATA_TYPE_USMALLINT: case TSDB_DATA_TYPE_SMALLINT: - colDataAppendInt16(pCol, currentRow, (int16_t*)&pRes->v); + colDataSetInt16(pCol, currentRow, (int16_t*)&pRes->v); break; case TSDB_DATA_TYPE_BOOL: case TSDB_DATA_TYPE_UTINYINT: case TSDB_DATA_TYPE_TINYINT: - colDataAppendInt8(pCol, currentRow, (int8_t*)&pRes->v); + colDataSetInt8(pCol, currentRow, (int8_t*)&pRes->v); break; case TSDB_DATA_TYPE_DOUBLE: - colDataAppendDouble(pCol, currentRow, (double*)&pRes->v); + colDataSetDouble(pCol, currentRow, (double*)&pRes->v); break; case TSDB_DATA_TYPE_FLOAT: { float v = GET_FLOAT_VAL(&pRes->v); - colDataAppendFloat(pCol, currentRow, &v); + colDataSetFloat(pCol, currentRow, &v); break; } } } else { - colDataAppendNULL(pCol, currentRow); + colDataSetNULL(pCol, currentRow); } if (pCtx->subsidiaries.num > 0) { @@ -844,7 +839,7 @@ int32_t setNullSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, int32 int32_t dstSlotId = pc->pExpr->base.resSchema.slotId; SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId); - colDataAppendNULL(pDstCol, rowIndex); + colDataSetNULL(pDstCol, rowIndex); } return TSDB_CODE_SUCCESS; @@ -872,11 +867,17 @@ int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STu SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j]; int32_t dstSlotId = pc->pExpr->base.resSchema.slotId; + // group_key function has its own process function + // do not process there + if (fmIsGroupKeyFunc(pc->functionId)) { + continue; + } + SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId); if (nullList[j]) { - colDataAppendNULL(pDstCol, rowIndex); + colDataSetNULL(pDstCol, rowIndex); } else { - colDataAppend(pDstCol, rowIndex, pStart, false); + colDataSetVal(pDstCol, rowIndex, pStart, false); } pStart += pDstCol->info.bytes; } @@ -889,13 +890,6 @@ int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STu return TSDB_CODE_SUCCESS; } -void releaseSource(STuplePos* pPos) { - if (pPos->pageId == -1) { - return; - } - // Todo(liuyao) relase row -} - // This function append the selectivity to subsidiaries function context directly, without fetching data // from intermediate disk based buf page void appendSelectivityValue(SqlFunctionCtx* pCtx, int32_t rowIndex, int32_t pos) { @@ -920,17 +914,14 @@ void appendSelectivityValue(SqlFunctionCtx* pCtx, int32_t rowIndex, int32_t pos) SColumnInfoData* pDstCol = taosArrayGet(pCtx->pDstBlock->pDataBlock, dstSlotId); if (colDataIsNull_s(pSrcCol, rowIndex) == true) { - colDataAppendNULL(pDstCol, pos); + colDataSetNULL(pDstCol, pos); } else { - colDataAppend(pDstCol, pos, pData, false); + colDataSetVal(pDstCol, pos, pData, false); } } } -void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) { - releaseSource(pDestPos); - *pDestPos = *pSourcePos; -} +void replaceTupleData(STuplePos* pDestPos, STuplePos* pSourcePos) { *pDestPos = *pSourcePos; } int32_t minMaxCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx, int32_t isMinFunc) { SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx); @@ -1309,7 +1300,7 @@ int32_t stddevPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t slotId = pCtx->pExpr->base.resSchema.slotId; SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); - colDataAppend(pCol, pBlock->info.rows, res, false); + colDataSetVal(pCol, pBlock->info.rows, res, false); taosMemoryFree(res); return pResInfo->numOfRes; @@ -1516,7 +1507,7 @@ int32_t leastSQRFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t currentRow = pBlock->info.rows; if (0 == pInfo->num) { - colDataAppendNULL(pCol, currentRow); + colDataSetNULL(pCol, currentRow); return 0; } @@ -1529,7 +1520,7 @@ int32_t leastSQRFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { double param02 = param[0][2] - param[1][2] * (param[0][1] / param[1][1]); if (0 == param00) { - colDataAppendNULL(pCol, currentRow); + colDataSetNULL(pCol, currentRow); return 0; } @@ -1545,7 +1536,7 @@ int32_t leastSQRFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%.6lf, intercept:%.6lf}", param02, param12); varDataSetLen(buf, len); - colDataAppend(pCol, currentRow, buf, pResInfo->isNullRes); + colDataSetVal(pCol, currentRow, buf, pResInfo->isNullRes); return pResInfo->numOfRes; } @@ -1607,7 +1598,7 @@ int32_t percentileFunction(SqlFunctionCtx* pCtx) { int32_t type = pCol->info.type; SPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo); - if (pCtx->scanFlag == REPEAT_SCAN && pInfo->stage == 0) { + if (pCtx->scanFlag == MAIN_SCAN && pInfo->stage == 0) { pInfo->stage += 1; // all data are null, set it completed @@ -1690,26 +1681,63 @@ int32_t percentileFunction(SqlFunctionCtx* pCtx) { } int32_t percentileFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { - SVariant* pVal = &pCtx->param[1].param; - int32_t code = 0; - double v = 0; - - GET_TYPED_DATA(v, double, pVal->nType, &pVal->i); - SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); SPercentileInfo* ppInfo = (SPercentileInfo*)GET_ROWCELL_INTERBUF(pResInfo); + int32_t code = 0; + double v = 0; + tMemBucket* pMemBucket = ppInfo->pMemBucket; if (pMemBucket != NULL && pMemBucket->total > 0) { // check for null - code = getPercentile(pMemBucket, v, &ppInfo->result); - } + if (pCtx->numOfParams > 2) { + char buf[512] = {0}; + size_t len = 1; - tMemBucketDestroy(pMemBucket); - if (code != TSDB_CODE_SUCCESS) { - return code; + varDataVal(buf)[0] = '['; + for (int32_t i = 1; i < pCtx->numOfParams; ++i) { + SVariant* pVal = &pCtx->param[i].param; + + GET_TYPED_DATA(v, double, pVal->nType, &pVal->i); + + int32_t code = getPercentile(pMemBucket, v, &ppInfo->result); + if (code != TSDB_CODE_SUCCESS) { + goto _fin_error; + } + + if (i == pCtx->numOfParams - 1) { + len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf]", ppInfo->result); + } else { + len += snprintf(varDataVal(buf) + len, sizeof(buf) - VARSTR_HEADER_SIZE - len, "%.6lf, ", ppInfo->result); + } + } + + int32_t slotId = pCtx->pExpr->base.resSchema.slotId; + SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); + + varDataSetLen(buf, len); + colDataAppend(pCol, pBlock->info.rows, buf, false); + + tMemBucketDestroy(pMemBucket); + return pResInfo->numOfRes; + } else { + SVariant* pVal = &pCtx->param[1].param; + + GET_TYPED_DATA(v, double, pVal->nType, &pVal->i); + + code = getPercentile(pMemBucket, v, &ppInfo->result); + if (code != TSDB_CODE_SUCCESS) { + goto _fin_error; + } + + tMemBucketDestroy(pMemBucket); + return functionFinalize(pCtx, pBlock); + } } - return functionFinalize(pCtx, pBlock); +_fin_error: + + tMemBucketDestroy(pMemBucket); + return code; } bool getApercentileFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) { @@ -1903,7 +1931,7 @@ int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) { SAPercentileInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo); - qDebug("%s total %d rows will merge, %p", __FUNCTION__, pInput->numOfRows, pInfo->pHisto); + qDebug("%s total %" PRId64 " rows will merge, %p", __FUNCTION__, pInput->numOfRows, pInfo->pHisto); int32_t start = pInput->startRowIndex; for (int32_t i = start; i < start + pInput->numOfRows; ++i) { @@ -1914,6 +1942,7 @@ int32_t apercentileFunctionMerge(SqlFunctionCtx* pCtx) { } if (pInfo->algo != APERCT_ALGO_TDIGEST) { + buildHistogramInfo(pInfo); qDebug("%s after merge, total:%" PRId64 ", numOfEntry:%d, %p", __FUNCTION__, pInfo->pHisto->numOfElems, pInfo->pHisto->numOfEntries, pInfo->pHisto); } @@ -1975,7 +2004,7 @@ int32_t apercentilePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t slotId = pCtx->pExpr->base.resSchema.slotId; SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); - colDataAppend(pCol, pBlock->info.rows, res, false); + colDataSetVal(pCol, pBlock->info.rows, res, false); taosMemoryFree(res); return pResInfo->numOfRes; @@ -2070,7 +2099,7 @@ static void prepareBuf(SqlFunctionCtx* pCtx) { } static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SqlFunctionCtx* pCtx, - SFirstLastRes* pInfo) { + SFirstLastRes* pInfo) { int32_t code = TSDB_CODE_SUCCESS; if (pCtx->subsidiaries.num <= 0) { @@ -2123,7 +2152,8 @@ int32_t firstFunction(SqlFunctionCtx* pCtx) { } // All null data column, return directly. - if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) && pInputCol->hasNull == true) { + if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) && + pInputCol->hasNull == true) { // save selectivity value for column consisted of all null values int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo); if (code != TSDB_CODE_SUCCESS) { @@ -2239,7 +2269,8 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) { } // All null data column, return directly. - if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) && pInputCol->hasNull == true) { + if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) && + pInputCol->hasNull == true) { // save selectivity value for column consisted of all null values int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo); if (code != TSDB_CODE_SUCCESS) { @@ -2333,7 +2364,7 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) { } if (pResInfo->numOfRes == 0 || pInfo->ts < cts) { - char* data = colDataGetData(pInputCol, chosen); + char* data = colDataGetData(pInputCol, chosen); int32_t code = doSaveCurrentVal(pCtx, i, cts, type, data); if (code != TSDB_CODE_SUCCESS) { return code; @@ -2344,7 +2375,7 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) { for (int32_t i = pInput->startRowIndex + round * 4; i < pInput->startRowIndex + pInput->numOfRows; ++i) { if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) { - char* data = colDataGetData(pInputCol, i); + char* data = colDataGetData(pInputCol, i); int32_t code = doSaveCurrentVal(pCtx, i, pts[i], type, data); if (code != TSDB_CODE_SUCCESS) { return code; @@ -2361,7 +2392,7 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pResInfo->numOfRes == 0 || pInfo->ts < pts[i]) { - char* data = colDataGetData(pInputCol, i); + char* data = colDataGetData(pInputCol, i); int32_t code = doSaveCurrentVal(pCtx, i, pts[i], type, data); if (code != TSDB_CODE_SUCCESS) { return code; @@ -2408,7 +2439,7 @@ static int32_t firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* p } static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst, - int32_t rowIndex) { + int32_t rowIndex) { if (TSDB_CODE_SUCCESS == firstLastTransferInfoImpl(pInput, pOutput, isFirst)) { int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput); if (code != TSDB_CODE_SUCCESS) { @@ -2433,9 +2464,12 @@ static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuer int32_t numOfElems = 0; for (int32_t i = start; i < start + pInput->numOfRows; ++i) { + if (colDataIsNull_s(pCol, i)) { + continue; + } char* data = colDataGetData(pCol, i); SFirstLastRes* pInputInfo = (SFirstLastRes*)varDataVal(data); - int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i); + int32_t code = firstLastTransferInfo(pCtx, pInputInfo, pInfo, isFirstQuery, i); if (code != TSDB_CODE_SUCCESS) { return code; } @@ -2461,7 +2495,7 @@ int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0; SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo); - colDataAppend(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes); + colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes); // handle selectivity code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows); @@ -2486,7 +2520,7 @@ int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t slotId = pCtx->pExpr->base.resSchema.slotId; SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); - colDataAppend(pCol, pBlock->info.rows, res, false); + colDataSetVal(pCol, pBlock->info.rows, res, false); code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows); taosMemoryFree(res); @@ -2667,7 +2701,7 @@ static int32_t doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv, } static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos, - int32_t order, int64_t ts) { + int32_t order, int64_t ts) { int32_t factor = (order == TSDB_ORDER_ASC) ? 1 : -1; pDiffInfo->prevTs = ts; switch (type) { @@ -2677,7 +2711,7 @@ static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, if (delta < 0 && pDiffInfo->ignoreNegative) { colDataSetNull_f_s(pOutput, pos); } else { - colDataAppendInt64(pOutput, pos, &delta); + colDataSetInt64(pOutput, pos, &delta); } pDiffInfo->prev.i64 = v; @@ -2690,7 +2724,7 @@ static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, if (delta < 0 && pDiffInfo->ignoreNegative) { colDataSetNull_f_s(pOutput, pos); } else { - colDataAppendInt64(pOutput, pos, &delta); + colDataSetInt64(pOutput, pos, &delta); } pDiffInfo->prev.i64 = v; break; @@ -2701,7 +2735,7 @@ static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, if (delta < 0 && pDiffInfo->ignoreNegative) { colDataSetNull_f_s(pOutput, pos); } else { - colDataAppendInt64(pOutput, pos, &delta); + colDataSetInt64(pOutput, pos, &delta); } pDiffInfo->prev.i64 = v; break; @@ -2713,7 +2747,7 @@ static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, if (delta < 0 && pDiffInfo->ignoreNegative) { colDataSetNull_f_s(pOutput, pos); } else { - colDataAppendInt64(pOutput, pos, &delta); + colDataSetInt64(pOutput, pos, &delta); } pDiffInfo->prev.i64 = v; break; @@ -2724,7 +2758,7 @@ static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, if ((delta < 0 && pDiffInfo->ignoreNegative) || isinf(delta) || isnan(delta)) { // check for overflow colDataSetNull_f_s(pOutput, pos); } else { - colDataAppendDouble(pOutput, pos, &delta); + colDataSetDouble(pOutput, pos, &delta); } pDiffInfo->prev.d64 = v; break; @@ -2735,7 +2769,7 @@ static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, if ((delta < 0 && pDiffInfo->ignoreNegative) || isinf(delta) || isnan(delta)) { // check for overflow colDataSetNull_f_s(pOutput, pos); } else { - colDataAppendDouble(pOutput, pos, &delta); + colDataSetDouble(pOutput, pos, &delta); } pDiffInfo->prev.d64 = v; break; @@ -2875,8 +2909,8 @@ static STopBotRes* getTopBotOutputInfo(SqlFunctionCtx* pCtx) { return pRes; } -static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type, - uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery); +static int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, + uint16_t type, uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery); static void addResult(SqlFunctionCtx* pCtx, STopBotResItem* pSourceItem, int16_t type, bool isTopQuery); @@ -2897,7 +2931,7 @@ int32_t topFunction(SqlFunctionCtx* pCtx) { } numOfElems++; - char* data = colDataGetData(pCol, i); + char* data = colDataGetData(pCol, i); int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, true); if (code != TSDB_CODE_SUCCESS) { return code; @@ -2931,7 +2965,7 @@ int32_t bottomFunction(SqlFunctionCtx* pCtx) { } numOfElems++; - char* data = colDataGetData(pCol, i); + char* data = colDataGetData(pCol, i); int32_t code = doAddIntoResult(pCtx, data, i, pCtx->pSrcBlock, pRes->type, pInput->uid, pResInfo, false); if (code != TSDB_CODE_SUCCESS) { return code; @@ -2983,7 +3017,7 @@ static int32_t topBotResComparFn(const void* p1, const void* p2, const void* par } int32_t doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSDataBlock* pSrcBlock, uint16_t type, - uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) { + uint64_t uid, SResultRowEntryInfo* pEntryInfo, bool isTopQuery) { STopBotRes* pRes = getTopBotOutputInfo(pCtx); SVariant val = {0}; @@ -3059,6 +3093,12 @@ void* serializeTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsid for (int32_t i = 0; i < pSubsidiaryies->num; ++i) { SqlFunctionCtx* pc = pSubsidiaryies->pCtx[i]; + // group_key function has its own process function + // do not process there + if (fmIsGroupKeyFunc(pc->functionId)) { + continue; + } + SFunctParam* pFuncParam = &pc->pExpr->base.pParam[0]; int32_t srcSlotId = pFuncParam->pCol->slotId; @@ -3081,7 +3121,7 @@ void* serializeTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsid return buf; } -static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STupleKey key, +static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STupleKey* key, STuplePos* pPos) { STuplePos p = {0}; if (pHandle->pBuf != NULL) { @@ -3117,8 +3157,8 @@ static int32_t doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, releaseBufPage(pHandle->pBuf, pPage); } else { // other tuple save policy - if (streamStateFuncPut(pHandle->pState, &key, pBuf, length) >= 0) { - p.streamTupleKey = key; + if (streamStateFuncPut(pHandle->pState, key, pBuf, length) >= 0) { + p.streamTupleKey = *key; } } @@ -3142,7 +3182,7 @@ int32_t saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* } char* buf = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf); - return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, key, pPos); + return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, &key, pPos); } static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos) { @@ -3174,7 +3214,7 @@ static char* doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPo if (pPage == NULL) { return NULL; } - char* p = pPage->data + pPos->offset; + char* p = pPage->data + pPos->offset; releaseBufPage(pHandle->pBuf, pPage); return p; } else { @@ -3203,13 +3243,13 @@ int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { // todo assign the tag value and the corresponding row data int32_t currentRow = pBlock->info.rows; if (pEntryInfo->numOfRes <= 0) { - colDataAppendNULL(pCol, currentRow); + colDataSetNULL(pCol, currentRow); code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow); return code; } for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) { STopBotResItem* pItem = &pRes->pItems[i]; - colDataAppend(pCol, currentRow, (const char*)&pItem->v.i, false); + colDataSetVal(pCol, currentRow, (const char*)&pItem->v.i, false); #ifdef BUF_PAGE_DEBUG qDebug("page_finalize i:%d,item:%p,pageId:%d, offset:%d\n", i, pItem, pItem->tuplePos.pageId, pItem->tuplePos.offset); @@ -3313,7 +3353,7 @@ int32_t spreadFunction(SqlFunctionCtx* pCtx) { goto _spread_over; } double tmin = 0.0, tmax = 0.0; - if (IS_SIGNED_NUMERIC_TYPE(type)) { + if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) { tmin = (double)GET_INT64_VAL(&pAgg->min); tmax = (double)GET_INT64_VAL(&pAgg->max); } else if (IS_FLOAT_TYPE(type)) { @@ -3426,7 +3466,7 @@ int32_t spreadPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t slotId = pCtx->pExpr->base.resSchema.slotId; SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); - colDataAppend(pCol, pBlock->info.rows, res, false); + colDataSetVal(pCol, pBlock->info.rows, res, false); taosMemoryFree(res); return pResInfo->numOfRes; @@ -3601,7 +3641,7 @@ int32_t elapsedPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t slotId = pCtx->pExpr->base.resSchema.slotId; SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); - colDataAppend(pCol, pBlock->info.rows, res, false); + colDataSetVal(pCol, pBlock->info.rows, res, false); taosMemoryFree(res); return pResInfo->numOfRes; @@ -3927,7 +3967,7 @@ int32_t histogramFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { pInfo->bins[i].upper, pInfo->bins[i].percentage); } varDataSetLen(buf, len); - colDataAppend(pCol, currentRow, buf, false); + colDataSetVal(pCol, currentRow, buf, false); currentRow++; } @@ -3946,7 +3986,7 @@ int32_t histogramPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t slotId = pCtx->pExpr->base.resSchema.slotId; SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); - colDataAppend(pCol, pBlock->info.rows, res, false); + colDataSetVal(pCol, pBlock->info.rows, res, false); taosMemoryFree(res); return pResInfo->numOfRes; @@ -4165,7 +4205,7 @@ int32_t hllPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t slotId = pCtx->pExpr->base.resSchema.slotId; SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); - colDataAppend(pCol, pBlock->info.rows, res, false); + colDataSetVal(pCol, pBlock->info.rows, res, false); taosMemoryFree(res); return pResInfo->numOfRes; @@ -4298,7 +4338,7 @@ int32_t stateCountFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutput, i); + colDataSetNULL(pOutput, i); // handle selectivity if (pCtx->subsidiaries.num > 0) { appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1); @@ -4314,7 +4354,7 @@ int32_t stateCountFunction(SqlFunctionCtx* pCtx) { } else { pInfo->count = 0; } - colDataAppend(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false); + colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false); // handle selectivity if (pCtx->subsidiaries.num > 0) { @@ -4360,7 +4400,7 @@ int32_t stateDurationFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutput, i); + colDataSetNULL(pOutput, i); // handle selectivity if (pCtx->subsidiaries.num > 0) { appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1); @@ -4380,7 +4420,7 @@ int32_t stateDurationFunction(SqlFunctionCtx* pCtx) { } else { pInfo->durationStart = 0; } - colDataAppend(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false); + colDataSetVal(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false); // handle selectivity if (pCtx->subsidiaries.num > 0) { @@ -4420,7 +4460,7 @@ int32_t csumFunction(SqlFunctionCtx* pCtx) { int32_t pos = startOffset + numOfElems; if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - // colDataAppendNULL(pOutput, i); + // colDataSetNULL(pOutput, i); continue; } @@ -4429,21 +4469,21 @@ int32_t csumFunction(SqlFunctionCtx* pCtx) { int64_t v; GET_TYPED_DATA(v, int64_t, type, data); pSumRes->isum += v; - colDataAppend(pOutput, pos, (char*)&pSumRes->isum, false); + colDataSetVal(pOutput, pos, (char*)&pSumRes->isum, false); } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { uint64_t v; GET_TYPED_DATA(v, uint64_t, type, data); pSumRes->usum += v; - colDataAppend(pOutput, pos, (char*)&pSumRes->usum, false); + colDataSetVal(pOutput, pos, (char*)&pSumRes->usum, false); } else if (IS_FLOAT_TYPE(type)) { double v; GET_TYPED_DATA(v, double, type, data); pSumRes->dsum += v; // check for overflow if (isinf(pSumRes->dsum) || isnan(pSumRes->dsum)) { - colDataAppendNULL(pOutput, pos); + colDataSetNULL(pOutput, pos); } else { - colDataAppend(pOutput, pos, (char*)&pSumRes->dsum, false); + colDataSetVal(pOutput, pos, (char*)&pSumRes->dsum, false); } } @@ -4507,7 +4547,7 @@ int32_t mavgFunction(SqlFunctionCtx* pCtx) { int32_t pos = startOffset + numOfElems; if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - // colDataAppendNULL(pOutput, i); + // colDataSetNULL(pOutput, i); continue; } @@ -4530,9 +4570,9 @@ int32_t mavgFunction(SqlFunctionCtx* pCtx) { double result = pInfo->sum / pInfo->numOfPoints; // check for overflow if (isinf(result) || isnan(result)) { - colDataAppendNULL(pOutput, pos); + colDataSetNULL(pOutput, pos); } else { - colDataAppend(pOutput, pos, (char*)&result, false); + colDataSetVal(pOutput, pos, (char*)&result, false); } // handle selectivity @@ -4635,7 +4675,7 @@ int32_t sampleFunction(SqlFunctionCtx* pCtx) { continue; } - char* data = colDataGetData(pInputCol, i); + char* data = colDataGetData(pInputCol, i); int32_t code = doReservoirSample(pCtx, pInfo, data, i); if (code != TSDB_CODE_SUCCESS) { return code; @@ -4655,7 +4695,7 @@ int32_t sampleFunction(SqlFunctionCtx* pCtx) { } int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { - int32_t code = TSDB_CODE_SUCCESS; + int32_t code = TSDB_CODE_SUCCESS; SResultRowEntryInfo* pEntryInfo = GET_RES_INFO(pCtx); SSampleInfo* pInfo = getSampleOutputInfo(pCtx); @@ -4666,12 +4706,12 @@ int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t currentRow = pBlock->info.rows; if (pInfo->numSampled == 0) { - colDataAppendNULL(pCol, currentRow); + colDataSetNULL(pCol, currentRow); code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow); return code; } for (int32_t i = 0; i < pInfo->numSampled; ++i) { - colDataAppend(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false); + colDataSetVal(pCol, currentRow + i, pInfo->data + i * pInfo->colBytes, false); code = setSelectivityValue(pCtx, pBlock, &pInfo->tuplePos[i], currentRow + i); } @@ -4782,9 +4822,9 @@ int32_t tailFunction(SqlFunctionCtx* pCtx) { int32_t pos = startOffset + i; STailItem* pItem = pInfo->pItems[i]; if (pItem->isNull) { - colDataAppendNULL(pOutput, pos); + colDataSetNULL(pOutput, pos); } else { - colDataAppend(pOutput, pos, pItem->data, false); + colDataSetVal(pOutput, pos, pItem->data, false); } } @@ -4808,7 +4848,7 @@ int32_t tailFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t currentRow = pBlock->info.rows; for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) { STailItem* pItem = pInfo->pItems[i]; - colDataAppend(pCol, currentRow, pItem->data, false); + colDataSetVal(pCol, currentRow, pItem->data, false); currentRow += 1; } @@ -4902,12 +4942,12 @@ int32_t uniqueFunction(SqlFunctionCtx* pCtx) { for (int32_t i = 0; i < pInfo->numOfPoints; ++i) { SUniqueItem* pItem = (SUniqueItem*)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes)); if (pItem->isNull == true) { - colDataAppendNULL(pOutput, i); + colDataSetNULL(pOutput, i); } else { - colDataAppend(pOutput, i, pItem->data, false); + colDataSetVal(pOutput, i, pItem->data, false); } if (pTsOutput != NULL) { - colDataAppendInt64(pTsOutput, i, &pItem->timestamp); + colDataSetInt64(pTsOutput, i, &pItem->timestamp); } } @@ -4917,7 +4957,7 @@ int32_t uniqueFunction(SqlFunctionCtx* pCtx) { } bool getModeFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) { - pEnv->calcMemSize = sizeof(SModeInfo) + MODE_MAX_RESULT_SIZE; + pEnv->calcMemSize = sizeof(SModeInfo); return true; } @@ -4927,7 +4967,6 @@ bool modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) { } SModeInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo); - pInfo->numOfPoints = 0; pInfo->colType = pCtx->resDataInfo.type; pInfo->colBytes = pCtx->resDataInfo.bytes; if (pInfo->pHash != NULL) { @@ -4938,38 +4977,60 @@ bool modeFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) { pInfo->nullTupleSaved = false; pInfo->nullTuplePos.pageId = -1; + pInfo->buf = taosMemoryMalloc(pInfo->colBytes); + return true; } +static void modeFunctionCleanup(SModeInfo * pInfo) { + taosHashCleanup(pInfo->pHash); + taosMemoryFreeClear(pInfo->buf); +} + +static int32_t saveModeTupleData(SqlFunctionCtx* pCtx, char* data, SModeInfo *pInfo, STuplePos* pPos) { + if (IS_VAR_DATA_TYPE(pInfo->colType)) { + memcpy(pInfo->buf, data, varDataTLen(data)); + } else { + memcpy(pInfo->buf, data, pInfo->colBytes); + } + + return doSaveTupleData(&pCtx->saveHandle, pInfo->buf, pInfo->colBytes, NULL, pPos); +} + static int32_t doModeAdd(SModeInfo* pInfo, int32_t rowIndex, SqlFunctionCtx* pCtx, char* data) { - int32_t hashKeyBytes = IS_STR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes; - SModeItem** pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes); + int32_t code = TSDB_CODE_SUCCESS; + int32_t hashKeyBytes = IS_STR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes; + + SModeItem* pHashItem = (SModeItem *)taosHashGet(pInfo->pHash, data, hashKeyBytes); if (pHashItem == NULL) { - int32_t size = sizeof(SModeItem) + pInfo->colBytes; - SModeItem* pItem = (SModeItem*)(pInfo->pItems + pInfo->numOfPoints * size); - memcpy(pItem->data, data, hashKeyBytes); - pItem->count += 1; + int32_t size = sizeof(SModeItem); + SModeItem item = {0}; + + item.count += 1; + code = saveModeTupleData(pCtx, data, pInfo, &item.dataPos); + if (code != TSDB_CODE_SUCCESS) { + return code; + } if (pCtx->subsidiaries.num > 0) { - int32_t code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pItem->tuplePos); + code = saveTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &item.tuplePos); if (code != TSDB_CODE_SUCCESS) { return code; } } - taosHashPut(pInfo->pHash, data, hashKeyBytes, &pItem, sizeof(SModeItem*)); - pInfo->numOfPoints++; + taosHashPut(pInfo->pHash, data, hashKeyBytes, &item, sizeof(SModeItem)); } else { - (*pHashItem)->count += 1; + pHashItem->count += 1; if (pCtx->subsidiaries.num > 0) { - int32_t code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &((*pHashItem)->tuplePos)); + int32_t code = updateTupleData(pCtx, rowIndex, pCtx->pSrcBlock, &pHashItem->tuplePos); if (code != TSDB_CODE_SUCCESS) { return code; } } } - return TSDB_CODE_SUCCESS; + return code; } int32_t modeFunction(SqlFunctionCtx* pCtx) { @@ -4989,21 +5050,18 @@ int32_t modeFunction(SqlFunctionCtx* pCtx) { } numOfElems++; - char* data = colDataGetData(pInputCol, i); + char* data = colDataGetData(pInputCol, i); int32_t code = doModeAdd(pInfo, i, pCtx, data); if (code != TSDB_CODE_SUCCESS) { + modeFunctionCleanup(pInfo); return code; } - - if (sizeof(SModeInfo) + pInfo->numOfPoints * (sizeof(SModeItem) + pInfo->colBytes) >= MODE_MAX_RESULT_SIZE) { - taosHashCleanup(pInfo->pHash); - return TSDB_CODE_OUT_OF_MEMORY; - } } if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) { int32_t code = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, &pInfo->nullTuplePos); if (code != TSDB_CODE_SUCCESS) { + modeFunctionCleanup(pInfo); return code; } pInfo->nullTupleSaved = true; @@ -5022,26 +5080,37 @@ int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); int32_t currentRow = pBlock->info.rows; - int32_t resIndex = -1; + STuplePos resDataPos, resTuplePos; int32_t maxCount = 0; - for (int32_t i = 0; i < pInfo->numOfPoints; ++i) { - SModeItem* pItem = (SModeItem*)(pInfo->pItems + i * (sizeof(SModeItem) + pInfo->colBytes)); + + void *pIter = taosHashIterate(pInfo->pHash, NULL); + while (pIter != NULL) { + SModeItem *pItem = (SModeItem *)pIter; if (pItem->count >= maxCount) { maxCount = pItem->count; - resIndex = i; + resDataPos = pItem->dataPos; + resTuplePos = pItem->tuplePos; } + + pIter = taosHashIterate(pInfo->pHash, pIter); } if (maxCount != 0) { - SModeItem* pResItem = (SModeItem*)(pInfo->pItems + resIndex * (sizeof(SModeItem) + pInfo->colBytes)); - colDataAppend(pCol, currentRow, pResItem->data, false); - code = setSelectivityValue(pCtx, pBlock, &pResItem->tuplePos, currentRow); + const char* pData = loadTupleData(pCtx, &resDataPos); + if (pData == NULL) { + code = TSDB_CODE_NO_AVAIL_DISK; + modeFunctionCleanup(pInfo); + return code; + } + + colDataSetVal(pCol, currentRow, pData, false); + code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow); } else { - colDataAppendNULL(pCol, currentRow); + colDataSetNULL(pCol, currentRow); code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow); } - taosHashCleanup(pInfo->pHash); + modeFunctionCleanup(pInfo); return code; } @@ -5410,7 +5479,7 @@ int32_t blockDistFunction(SqlFunctionCtx* pCtx) { if (pDistInfo->maxRows < p1.maxRows) { pDistInfo->maxRows = p1.maxRows; } - + pDistInfo->numOfVgroups += (p1.numOfTables != 0 ? 1 : 0); for (int32_t i = 0; i < tListLen(pDistInfo->blockRowsHisto); ++i) { pDistInfo->blockRowsHisto[i] += p1.blockRowsHisto[i]; } @@ -5438,6 +5507,7 @@ int32_t tSerializeBlockDistInfo(void* buf, int32_t bufLen, const STableBlockDist if (tEncodeI32(&encoder, pInfo->defMinRows) < 0) return -1; if (tEncodeU32(&encoder, pInfo->numOfInmemRows) < 0) return -1; if (tEncodeU32(&encoder, pInfo->numOfSmallBlocks) < 0) return -1; + if (tEncodeU32(&encoder, pInfo->numOfVgroups) < 0) return -1; for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) { if (tEncodeI32(&encoder, pInfo->blockRowsHisto[i]) < 0) return -1; @@ -5469,6 +5539,7 @@ int32_t tDeserializeBlockDistInfo(void* buf, int32_t bufLen, STableBlockDistInfo if (tDecodeI32(&decoder, &pInfo->defMinRows) < 0) return -1; if (tDecodeU32(&decoder, &pInfo->numOfInmemRows) < 0) return -1; if (tDecodeU32(&decoder, &pInfo->numOfSmallBlocks) < 0) return -1; + if (tDecodeU32(&decoder, &pInfo->numOfVgroups) < 0) return -1; for (int32_t i = 0; i < tListLen(pInfo->blockRowsHisto); ++i) { if (tDecodeI32(&decoder, &pInfo->blockRowsHisto[i]) < 0) return -1; @@ -5501,11 +5572,11 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { } int32_t len = sprintf(st + VARSTR_HEADER_SIZE, - "Total_Blocks=[%d] Total_Size=[%.2f Kb] Average_size=[%.2f Kb] Compression_Ratio=[%.2f %c]", + "Total_Blocks=[%d] Total_Size=[%.2f KB] Average_size=[%.2f KB] Compression_Ratio=[%.2f %c]", pData->numOfBlocks, pData->totalSize / 1024.0, averageSize / 1024.0, compRatio, '%'); varDataSetLen(st, len); - colDataAppend(pColInfo, row++, st, false); + colDataSetVal(pColInfo, row++, st, false); int64_t avgRows = 0; if (pData->numOfBlocks > 0) { @@ -5517,18 +5588,18 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { pData->totalRows, pData->numOfInmemRows, pData->minRows, pData->maxRows, avgRows); varDataSetLen(st, len); - colDataAppend(pColInfo, row++, st, false); + colDataSetVal(pColInfo, row++, st, false); len = sprintf(st + VARSTR_HEADER_SIZE, "Total_Tables=[%d] Total_Files=[%d] Total_Vgroups=[%d]", pData->numOfTables, - pData->numOfFiles, 0); + pData->numOfFiles, pData->numOfVgroups); varDataSetLen(st, len); - colDataAppend(pColInfo, row++, st, false); + colDataSetVal(pColInfo, row++, st, false); len = sprintf(st + VARSTR_HEADER_SIZE, "--------------------------------------------------------------------------------"); varDataSetLen(st, len); - colDataAppend(pColInfo, row++, st, false); + colDataSetVal(pColInfo, row++, st, false); int32_t maxVal = 0; int32_t minVal = INT32_MAX; @@ -5549,7 +5620,7 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t bucketRange = (pData->defMaxRows - pData->defMinRows) / numOfBuckets; for (int32_t i = 0; i < tListLen(pData->blockRowsHisto); ++i) { - len = sprintf(st + VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * i); + len = sprintf(st + VARSTR_HEADER_SIZE, "%04d |", pData->defMinRows + bucketRange * (i + 1)); int32_t num = 0; if (pData->blockRowsHisto[i] > 0) { @@ -5567,7 +5638,7 @@ int32_t blockDistFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { } varDataSetLen(st, len); - colDataAppend(pColInfo, row++, st, false); + colDataSetVal(pColInfo, row++, st, false); } return TSDB_CODE_SUCCESS; @@ -5628,13 +5699,13 @@ int32_t derivativeFunction(SqlFunctionCtx* pCtx) { if (pDerivInfo->ignoreNegative && r < 0) { } else { if (isinf(r) || isnan(r)) { - colDataAppendNULL(pOutput, pos); + colDataSetNULL(pOutput, pos); } else { - colDataAppend(pOutput, pos, (const char*)&r, false); + colDataSetVal(pOutput, pos, (const char*)&r, false); } if (pTsOutput != NULL) { - colDataAppendInt64(pTsOutput, pos, &tsList[i]); + colDataSetInt64(pTsOutput, pos, &tsList[i]); } // handle selectivity @@ -5669,13 +5740,13 @@ int32_t derivativeFunction(SqlFunctionCtx* pCtx) { if (pDerivInfo->ignoreNegative && r < 0) { } else { if (isinf(r) || isnan(r)) { - colDataAppendNULL(pOutput, pos); + colDataSetNULL(pOutput, pos); } else { - colDataAppend(pOutput, pos, (const char*)&r, false); + colDataSetVal(pOutput, pos, (const char*)&r, false); } if (pTsOutput != NULL) { - colDataAppendInt64(pTsOutput, pos, &pDerivInfo->prevTs); + colDataSetInt64(pTsOutput, pos, &pDerivInfo->prevTs); } // handle selectivity @@ -5806,7 +5877,7 @@ int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { SRateInfo* pInfo = GET_ROWCELL_INTERBUF(pResInfo); double result = doCalcRate(pInfo, (double)TSDB_TICK_PER_SECOND(pCtx->param[1].param.i)); - colDataAppend(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes); + colDataSetVal(pCol, pBlock->info.rows, (const char*)&result, pResInfo->isNullRes); return pResInfo->numOfRes; } @@ -5857,7 +5928,7 @@ int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { if (pInfo->hasResult) { int32_t currentRow = pBlock->info.rows; for (; currentRow < pBlock->info.rows + pResInfo->numOfRes; ++currentRow) { - colDataAppend(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false); + colDataSetVal(pCol, currentRow, pInfo->data, pInfo->isNull ? true : false); } } else { pResInfo->numOfRes = 0; @@ -5866,6 +5937,39 @@ int32_t groupKeyFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { return pResInfo->numOfRes; } +int32_t groupKeyCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) { + SResultRowEntryInfo* pDResInfo = GET_RES_INFO(pDestCtx); + SGroupKeyInfo* pDBuf = GET_ROWCELL_INTERBUF(pDResInfo); + + SResultRowEntryInfo* pSResInfo = GET_RES_INFO(pSourceCtx); + SGroupKeyInfo* pSBuf = GET_ROWCELL_INTERBUF(pSResInfo); + + // escape rest of data blocks to avoid first entry to be overwritten. + if (pDBuf->hasResult) { + goto _group_key_over; + } + + if (pSBuf->isNull) { + pDBuf->isNull = true; + pDBuf->hasResult = true; + goto _group_key_over; + } + + if (IS_VAR_DATA_TYPE(pSourceCtx->resDataInfo.type)) { + memcpy(pDBuf->data, pSBuf->data, + (pSourceCtx->resDataInfo.type == TSDB_DATA_TYPE_JSON) ? getJsonValueLen(pSBuf->data) : varDataTLen(pSBuf->data)); + } else { + memcpy(pDBuf->data, pSBuf->data, pSourceCtx->resDataInfo.bytes); + } + + pDBuf->hasResult = true; + +_group_key_over: + + SET_VAL(pDResInfo, 1, 1); + return TSDB_CODE_SUCCESS; +} + int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx) { int32_t numOfElems = 0; diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index 3a70a65ec4f8d5888f264b3fd9f97a82932554dc..50df1b5067021dc1ef33d9fc7c68fa95029e2adb 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -847,7 +847,7 @@ int32_t avgPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t slotId = pCtx->pExpr->base.resSchema.slotId; SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); - colDataAppend(pCol, pBlock->info.rows, res, false); + colDataSetVal(pCol, pBlock->info.rows, res, false); taosMemoryFree(res); return pResInfo->numOfRes; diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index e3127fcd7ba233d478c58cc16b7543587b5eaf90..18f6e8050b56e1c73a28cf64bb24c1da3844651f 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -174,6 +174,8 @@ bool fmIsSelectFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC bool fmIsTimelineFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_TIMELINE_FUNC); } +bool fmIsDateTimeFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_DATETIME_FUNC); } + bool fmIsPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_PSEUDO_COLUMN_FUNC); } bool fmIsScanPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SCAN_PC_FUNC); } @@ -184,6 +186,7 @@ bool fmIsWindowClauseFunc(int32_t funcId) { return fmIsAggFunc(funcId) || fmIsWi bool fmIsIndefiniteRowsFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_INDEFINITE_ROWS_FUNC); } + bool fmIsSpecialDataRequiredFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SPECIAL_DATA_REQUIRED); } @@ -447,3 +450,10 @@ int32_t fmGetDistMethod(const SFunctionNode* pFunc, SFunctionNode** pPartialFunc return code; } + +char* fmGetFuncName(int32_t funcId) { + if (fmIsUserDefinedFunc(funcId) || funcId < 0 || funcId >= funcMgtBuiltinsNum) { + return taosStrdup("invalid function"); + } + return taosStrdup(funcMgtBuiltins[funcId].name); +} diff --git a/source/libs/function/src/tfunctionInt.c b/source/libs/function/src/tfunctionInt.c index edfd8660106fa8ce1141bb979a78cd4d9a771bbe..e8041d17044d08e46cafdac61b47f59b15ed2c79 100644 --- a/source/libs/function/src/tfunctionInt.c +++ b/source/libs/function/src/tfunctionInt.c @@ -47,11 +47,11 @@ int32_t getNumOfResult(SqlFunctionCtx* pCtx, int32_t num, SSDataBlock* pResBlock SResultRowEntryInfo* pResInfo = GET_RES_INFO(&pCtx[i]); if (pResInfo->numOfRes == 0) { for (int32_t j = 0; j < pResInfo->numOfRes; ++j) { - colDataAppend(pCol, j, NULL, true); // TODO add set null data api + colDataSetVal(pCol, j, NULL, true); // TODO add set null data api } } else { for (int32_t j = 0; j < pResInfo->numOfRes; ++j) { - colDataAppend(pCol, j, GET_ROWCELL_INTERBUF(pResInfo), false); + colDataSetVal(pCol, j, GET_ROWCELL_INTERBUF(pResInfo), false); } } } diff --git a/source/libs/function/src/tpercentile.c b/source/libs/function/src/tpercentile.c index 1734b535f13dfe33f391187efe8ec59e86b94992..de381fadbd6efa25494559c5a9f63ab6a0422cf9 100644 --- a/source/libs/function/src/tpercentile.c +++ b/source/libs/function/src/tpercentile.c @@ -33,7 +33,14 @@ static SFilePage *loadDataFromFilePage(tMemBucket *pMemBucket, int32_t slotIdx) (SFilePage *)taosMemoryCalloc(1, pMemBucket->bytes * pMemBucket->pSlots[slotIdx].info.size + sizeof(SFilePage)); int32_t groupId = getGroupId(pMemBucket->numOfSlots, slotIdx, pMemBucket->times); - SArray *pIdList = *(SArray **)taosHashGet(pMemBucket->groupPagesMap, &groupId, sizeof(groupId)); + + SArray *pIdList; + void *p = taosHashGet(pMemBucket->groupPagesMap, &groupId, sizeof(groupId)); + if (p != NULL) { + pIdList = *(SArray **)p; + } else { + return NULL; + } int32_t offset = 0; for (int32_t i = 0; i < taosArrayGetSize(pIdList); ++i) { @@ -512,8 +519,17 @@ int32_t getPercentileImpl(tMemBucket *pMemBucket, int32_t count, double fraction resetSlotInfo(pMemBucket); int32_t groupId = getGroupId(pMemBucket->numOfSlots, i, pMemBucket->times - 1); - SArray* list = *(SArray **)taosHashGet(pMemBucket->groupPagesMap, &groupId, sizeof(groupId)); - ASSERT(list != NULL && list->size > 0); + + SArray* list; + void *p = taosHashGet(pMemBucket->groupPagesMap, &groupId, sizeof(groupId)); + if (p != NULL) { + list = *(SArray **)p; + if (list == NULL || list->size <= 0) { + return -1; + } + } else { + return -1; + } for (int32_t f = 0; f < list->size; ++f) { int32_t *pageId = taosArrayGet(list, f); diff --git a/source/libs/function/src/tudf.c b/source/libs/function/src/tudf.c index b9e72847a16a5abc5f82e8cce60842254028d759..2269ad7f6a8d5e5d1c67b70be661168907820797 100644 --- a/source/libs/function/src/tudf.c +++ b/source/libs/function/src/tudf.c @@ -376,7 +376,7 @@ typedef struct SUdfcUvSession { uv_pipe_t *udfUvPipe; int8_t outputType; - int32_t outputLen; + int32_t bytes; int32_t bufSize; char udfName[TSDB_FUNC_NAME_LEN + 1]; @@ -614,7 +614,7 @@ int32_t encodeUdfSetupResponse(void **buf, const SUdfSetupResponse *setupRsp) { int32_t len = 0; len += taosEncodeFixedI64(buf, setupRsp->udfHandle); len += taosEncodeFixedI8(buf, setupRsp->outputType); - len += taosEncodeFixedI32(buf, setupRsp->outputLen); + len += taosEncodeFixedI32(buf, setupRsp->bytes); len += taosEncodeFixedI32(buf, setupRsp->bufSize); return len; } @@ -622,7 +622,7 @@ int32_t encodeUdfSetupResponse(void **buf, const SUdfSetupResponse *setupRsp) { void *decodeUdfSetupResponse(const void *buf, SUdfSetupResponse *setupRsp) { buf = taosDecodeFixedI64(buf, &setupRsp->udfHandle); buf = taosDecodeFixedI8(buf, &setupRsp->outputType); - buf = taosDecodeFixedI32(buf, &setupRsp->outputLen); + buf = taosDecodeFixedI32(buf, &setupRsp->bytes); buf = taosDecodeFixedI32(buf, &setupRsp->bufSize); return (void *)buf; } @@ -808,6 +808,26 @@ int32_t convertDataBlockToUdfDataBlock(SSDataBlock *block, SUdfDataBlock *udfBlo } int32_t convertUdfColumnToDataBlock(SUdfColumn *udfCol, SSDataBlock *block) { + SUdfColumnMeta* meta = &udfCol->colMeta; + + SColumnInfoData colInfoData = createColumnInfoData(meta->type, meta->bytes, 1); + blockDataAppendColInfo(block, &colInfoData); + blockDataEnsureCapacity(block, udfCol->colData.numOfRows); + + SColumnInfoData *col = bdGetColumnInfoData(block, 0); + for (int i = 0; i < udfCol->colData.numOfRows; ++i) { + if (udfColDataIsNull(udfCol, i)) { + colDataSetNULL(col, i); + } else { + char* data = udfColDataGetData(udfCol, i); + colDataSetVal(col, i, data, false); + } + } + block->info.rows = udfCol->colData.numOfRows; + return 0; +} + +int32_t convertUdfColumnToDataBlock2(SUdfColumn *udfCol, SSDataBlock *block) { block->info.rows = udfCol->colData.numOfRows; block->info.hasVarCol = IS_VAR_DATA_TYPE(udfCol->colMeta.type); @@ -864,13 +884,13 @@ int32_t convertScalarParamToDataBlock(SScalarParam *input, int32_t numOfCols, SS int expandRows = numOfRows - startRow; bool isNull = colDataIsNull_s(pColInfoData, (input+i)->numOfRows - 1); if (isNull) { - colDataAppendNNULL(pDest, startRow, expandRows); + colDataSetNNULL(pDest, startRow, expandRows); } else { char* src = colDataGetData(pColInfoData, (input + i)->numOfRows - 1); for (int j = 0; j < expandRows; ++j) { - colDataAppend(pDest, startRow+j, src, false); + colDataSetVal(pDest, startRow+j, src, false); } - //colDataAppendNItems(pColInfoData, startRow, data, expandRows); + //colDataSetNItems(pColInfoData, startRow, data, expandRows); } } } @@ -899,9 +919,11 @@ int32_t convertDataBlockToScalarParm(SSDataBlock *input, SScalarParam *output) { typedef struct SUdfAggRes { int8_t finalResNum; int8_t interResNum; + int32_t interResBufLen; char *finalResBuf; char *interResBuf; } SUdfAggRes; + void onUdfcPipeClose(uv_handle_t *handle); int32_t udfcGetUdfTaskResultFromUvTask(SClientUdfTask *task, SClientUvTaskNode *uvTask); void udfcAllocateBuffer(uv_handle_t *handle, size_t suggestedSize, uv_buf_t *buf); @@ -1048,15 +1070,22 @@ int32_t callUdfScalarFunc(char *udfName, SScalarParam *input, int32_t numOfCols, if (code != 0) { return code; } + SUdfcUvSession *session = handle; code = doCallUdfScalarFunc(handle, input, numOfCols, output); + if (code != TSDB_CODE_SUCCESS) { + fnError("udfc scalar function execution failure"); + releaseUdfFuncHandle(udfName); + return code; + } + if (output->columnData == NULL) { fnError("udfc scalar function calculate error. no column data"); code = TSDB_CODE_UDF_INVALID_OUTPUT_TYPE; } else { - if (session->outputType != output->columnData->info.type || session->outputLen != output->columnData->info.bytes) { + if (session->outputType != output->columnData->info.type || session->bytes != output->columnData->info.bytes) { fnError("udfc scalar function calculate error. type mismatch. session type: %d(%d), output type: %d(%d)", - session->outputType, session->outputLen, output->columnData->info.type, output->columnData->info.bytes); + session->outputType, session->bytes, output->columnData->info.type, output->columnData->info.bytes); code = TSDB_CODE_UDF_INVALID_OUTPUT_TYPE; } } @@ -1084,11 +1113,11 @@ bool udfAggInit(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo *pResult } SUdfcUvSession *session = (SUdfcUvSession *)handle; SUdfAggRes *udfRes = (SUdfAggRes *)GET_ROWCELL_INTERBUF(pResultCellInfo); - int32_t envSize = sizeof(SUdfAggRes) + session->outputLen + session->bufSize; + int32_t envSize = sizeof(SUdfAggRes) + session->bytes + session->bufSize; memset(udfRes, 0, envSize); udfRes->finalResBuf = (char *)udfRes + sizeof(SUdfAggRes); - udfRes->interResBuf = (char *)udfRes + sizeof(SUdfAggRes) + session->outputLen; + udfRes->interResBuf = (char *)udfRes + sizeof(SUdfAggRes) + session->bytes; SUdfInterBuf buf = {0}; if ((udfCode = doCallUdfAggInit(handle, &buf)) != 0) { @@ -1096,9 +1125,10 @@ bool udfAggInit(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo *pResult releaseUdfFuncHandle(pCtx->udfName); return false; } - udfRes->interResNum = buf.numOfResult; if (buf.bufLen <= session->bufSize) { memcpy(udfRes->interResBuf, buf.buf, buf.bufLen); + udfRes->interResBufLen = buf.bufLen; + udfRes->interResNum = buf.numOfResult; } else { fnError("udfc inter buf size %d is greater than function bufSize %d", buf.bufLen, session->bufSize); releaseUdfFuncHandle(pCtx->udfName); @@ -1120,7 +1150,7 @@ int32_t udfAggProcess(struct SqlFunctionCtx *pCtx) { SUdfcUvSession *session = handle; SUdfAggRes *udfRes = (SUdfAggRes *)GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); udfRes->finalResBuf = (char *)udfRes + sizeof(SUdfAggRes); - udfRes->interResBuf = (char *)udfRes + sizeof(SUdfAggRes) + session->outputLen; + udfRes->interResBuf = (char *)udfRes + sizeof(SUdfAggRes) + session->bytes; SInputColumnInfoData *pInput = &pCtx->input; int32_t numOfCols = pInput->numOfInputCols; @@ -1136,7 +1166,7 @@ int32_t udfAggProcess(struct SqlFunctionCtx *pCtx) { SSDataBlock *inputBlock = blockDataExtractBlock(pTempBlock, start, numOfRows); - SUdfInterBuf state = {.buf = udfRes->interResBuf, .bufLen = session->bufSize, .numOfResult = udfRes->interResNum}; + SUdfInterBuf state = {.buf = udfRes->interResBuf, .bufLen = udfRes->interResBufLen, .numOfResult = udfRes->interResNum}; SUdfInterBuf newState = {0}; udfCode = doCallUdfAggProcess(session, inputBlock, &state, &newState); @@ -1144,17 +1174,17 @@ int32_t udfAggProcess(struct SqlFunctionCtx *pCtx) { fnError("udfAggProcess error. code: %d", udfCode); newState.numOfResult = 0; } else { - udfRes->interResNum = newState.numOfResult; if (newState.bufLen <= session->bufSize) { memcpy(udfRes->interResBuf, newState.buf, newState.bufLen); + udfRes->interResBufLen = newState.bufLen; + udfRes->interResNum = newState.numOfResult; } else { fnError("udfc inter buf size %d is greater than function bufSize %d", newState.bufLen, session->bufSize); udfCode = TSDB_CODE_UDF_INVALID_BUFSIZE; } } - if (newState.numOfResult == 1 || state.numOfResult == 1) { - GET_RES_INFO(pCtx)->numOfRes = 1; - } + + GET_RES_INFO(pCtx)->numOfRes = udfRes->interResNum; blockDataDestroy(inputBlock); @@ -1177,24 +1207,29 @@ int32_t udfAggFinalize(struct SqlFunctionCtx *pCtx, SSDataBlock *pBlock) { SUdfcUvSession *session = handle; SUdfAggRes *udfRes = (SUdfAggRes *)GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); udfRes->finalResBuf = (char *)udfRes + sizeof(SUdfAggRes); - udfRes->interResBuf = (char *)udfRes + sizeof(SUdfAggRes) + session->outputLen; + udfRes->interResBuf = (char *)udfRes + sizeof(SUdfAggRes) + session->bytes; SUdfInterBuf resultBuf = {0}; - SUdfInterBuf state = {.buf = udfRes->interResBuf, .bufLen = session->bufSize, .numOfResult = udfRes->interResNum}; + SUdfInterBuf state = {.buf = udfRes->interResBuf, .bufLen = udfRes->interResBufLen, .numOfResult = udfRes->interResNum}; int32_t udfCallCode = 0; udfCallCode = doCallUdfAggFinalize(session, &state, &resultBuf); if (udfCallCode != 0) { fnError("udfAggFinalize error. doCallUdfAggFinalize step. udf code:%d", udfCallCode); GET_RES_INFO(pCtx)->numOfRes = 0; } else { - if (resultBuf.bufLen <= session->outputLen) { - memcpy(udfRes->finalResBuf, resultBuf.buf, session->outputLen); - udfRes->finalResNum = resultBuf.numOfResult; - GET_RES_INFO(pCtx)->numOfRes = udfRes->finalResNum; - } else { - fnError("udfc inter buf size %d is greater than function output size %d", resultBuf.bufLen, session->outputLen); + if (resultBuf.numOfResult == 0) { + udfRes->finalResNum = 0; GET_RES_INFO(pCtx)->numOfRes = 0; - udfCallCode = TSDB_CODE_UDF_INVALID_OUTPUT_TYPE; + } else { + if (resultBuf.bufLen <= session->bytes) { + memcpy(udfRes->finalResBuf, resultBuf.buf, resultBuf.bufLen); + udfRes->finalResNum = resultBuf.numOfResult; + GET_RES_INFO(pCtx)->numOfRes = udfRes->finalResNum; + } else { + fnError("udfc inter buf size %d is greater than function output size %d", resultBuf.bufLen, session->bytes); + GET_RES_INFO(pCtx)->numOfRes = 0; + udfCallCode = TSDB_CODE_UDF_INVALID_OUTPUT_TYPE; + } } } @@ -1365,8 +1400,9 @@ void udfcUvHandleError(SClientUvConn *conn) { QUEUE_REMOVE(&task->procTaskQueue); uv_sem_post(&task->taskSem); } - - uv_close((uv_handle_t *)conn->pipe, onUdfcPipeClose); + if (!uv_is_closing((uv_handle_t *)conn->pipe)) { + uv_close((uv_handle_t *)conn->pipe, onUdfcPipeClose); + } } void onUdfcPipeRead(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) { @@ -1518,7 +1554,9 @@ int32_t udfcStartUvTask(SClientUvTaskNode *uvTask) { } else { SClientUvConn *conn = pipe->data; QUEUE_INSERT_TAIL(&conn->taskQueue, &uvTask->connTaskQueue); - uv_close((uv_handle_t *)uvTask->pipe, onUdfcPipeClose); + if (!uv_is_closing((uv_handle_t *)uvTask->pipe)) { + uv_close((uv_handle_t *)uvTask->pipe, onUdfcPipeClose); + } code = 0; } break; @@ -1696,13 +1734,13 @@ int32_t doSetupUdf(char udfName[], UdfcFuncHandle *funcHandle) { SUdfSetupResponse *rsp = &task->_setup.rsp; task->session->severHandle = rsp->udfHandle; task->session->outputType = rsp->outputType; - task->session->outputLen = rsp->outputLen; + task->session->bytes = rsp->bytes; task->session->bufSize = rsp->bufSize; strncpy(task->session->udfName, udfName, TSDB_FUNC_NAME_LEN); if (task->errCode != 0) { fnError("failed to setup udf. udfname: %s, err: %d", udfName, task->errCode) } else { - fnInfo("sucessfully setup udf func handle. udfName: %s, handle: %p", udfName, task->session); + fnInfo("successfully setup udf func handle. udfName: %s, handle: %p", udfName, task->session); *funcHandle = task->session; } int32_t err = task->errCode; diff --git a/source/libs/function/src/udfd.c b/source/libs/function/src/udfd.c index fe6ed7d785c7b6a6d99adbe9f930294bf8b950ef..b1988656965d60bc76447a9b4fce25decdde9dfd 100644 --- a/source/libs/function/src/udfd.c +++ b/source/libs/function/src/udfd.c @@ -21,6 +21,7 @@ #include "tudf.h" #include "tudfInt.h" +#include "version.h" #include "tdatablock.h" #include "tdataformat.h" @@ -30,6 +31,182 @@ #include "tmisce.h" // clang-format on +#define UDFD_MAX_SCRIPT_PLUGINS 64 +#define UDFD_MAX_SCRIPT_TYPE 1 +#define UDFD_MAX_PLUGIN_FUNCS 9 + +typedef struct SUdfCPluginCtx { + uv_lib_t lib; + + TUdfScalarProcFunc scalarProcFunc; + + TUdfAggStartFunc aggStartFunc; + TUdfAggProcessFunc aggProcFunc; + TUdfAggFinishFunc aggFinishFunc; + TUdfAggMergeFunc aggMergeFunc; + + TUdfInitFunc initFunc; + TUdfDestroyFunc destroyFunc; +} SUdfCPluginCtx; + +int32_t udfdCPluginOpen(SScriptUdfEnvItem *items, int numItems) { return 0; } + +int32_t udfdCPluginClose() { return 0; } + +const char *udfdCPluginUdfInitLoadInitDestoryFuncs(SUdfCPluginCtx *udfCtx, const char *udfName) { + char initFuncName[TSDB_FUNC_NAME_LEN + 6] = {0}; + char *initSuffix = "_init"; + snprintf(initFuncName, sizeof(initFuncName), "%s%s", udfName, initSuffix); + uv_dlsym(&udfCtx->lib, initFuncName, (void **)(&udfCtx->initFunc)); + + char destroyFuncName[TSDB_FUNC_NAME_LEN + 9] = {0}; + char *destroySuffix = "_destroy"; + strcpy(destroyFuncName, udfName); + snprintf(destroyFuncName, sizeof(destroyFuncName), "%s%s", udfName, destroySuffix); + uv_dlsym(&udfCtx->lib, destroyFuncName, (void **)(&udfCtx->destroyFunc)); + return udfName; +} + +void udfdCPluginUdfInitLoadAggFuncs(SUdfCPluginCtx *udfCtx, const char *udfName) { + char processFuncName[TSDB_FUNC_NAME_LEN] = {0}; + strcpy(processFuncName, udfName); + uv_dlsym(&udfCtx->lib, processFuncName, (void **)(&udfCtx->aggProcFunc)); + + char startFuncName[TSDB_FUNC_NAME_LEN + 7] = {0}; + char *startSuffix = "_start"; + snprintf(startFuncName, sizeof(startFuncName), "%s%s", processFuncName, startSuffix); + uv_dlsym(&udfCtx->lib, startFuncName, (void **)(&udfCtx->aggStartFunc)); + + char finishFuncName[TSDB_FUNC_NAME_LEN + 8] = {0}; + char *finishSuffix = "_finish"; + snprintf(finishFuncName, sizeof(finishFuncName), "%s%s", processFuncName, finishSuffix); + uv_dlsym(&udfCtx->lib, finishFuncName, (void **)(&udfCtx->aggFinishFunc)); + + char mergeFuncName[TSDB_FUNC_NAME_LEN + 7] = {0}; + char *mergeSuffix = "_merge"; + snprintf(mergeFuncName, sizeof(mergeFuncName), "%s%s", processFuncName, mergeSuffix); + uv_dlsym(&udfCtx->lib, mergeFuncName, (void **)(&udfCtx->aggMergeFunc)); +} + +int32_t udfdCPluginUdfInit(SScriptUdfInfo *udf, void **pUdfCtx) { + int32_t err = 0; + SUdfCPluginCtx *udfCtx = taosMemoryCalloc(1, sizeof(SUdfCPluginCtx)); + err = uv_dlopen(udf->path, &udfCtx->lib); + if (err != 0) { + fnError("can not load library %s. error: %s", udf->path, uv_strerror(err)); + return TSDB_CODE_UDF_LOAD_UDF_FAILURE; + } + const char *udfName = udf->name; + + udfdCPluginUdfInitLoadInitDestoryFuncs(udfCtx, udfName); + + if (udf->funcType == UDF_FUNC_TYPE_SCALAR) { + char processFuncName[TSDB_FUNC_NAME_LEN] = {0}; + strcpy(processFuncName, udfName); + uv_dlsym(&udfCtx->lib, processFuncName, (void **)(&udfCtx->scalarProcFunc)); + } else if (udf->funcType == UDF_FUNC_TYPE_AGG) { + udfdCPluginUdfInitLoadAggFuncs(udfCtx, udfName); + } + + int32_t code = 0; + if (udfCtx->initFunc) { + code = (udfCtx->initFunc)(); + if (code != 0) { + uv_dlclose(&udfCtx->lib); + taosMemoryFree(udfCtx); + return code; + } + } + *pUdfCtx = udfCtx; + return 0; +} + +int32_t udfdCPluginUdfDestroy(void *udfCtx) { + SUdfCPluginCtx *ctx = udfCtx; + int32_t code = 0; + if (ctx->destroyFunc) { + code = (ctx->destroyFunc)(); + } + uv_dlclose(&ctx->lib); + taosMemoryFree(ctx); + return code; +} + +int32_t udfdCPluginUdfScalarProc(SUdfDataBlock *block, SUdfColumn *resultCol, void *udfCtx) { + SUdfCPluginCtx *ctx = udfCtx; + if (ctx->scalarProcFunc) { + return ctx->scalarProcFunc(block, resultCol); + } else { + fnError("udfd c plugin scalar proc not implemented"); + return TSDB_CODE_UDF_FUNC_EXEC_FAILURE; + } +} + +int32_t udfdCPluginUdfAggStart(SUdfInterBuf *buf, void *udfCtx) { + SUdfCPluginCtx *ctx = udfCtx; + if (ctx->aggStartFunc) { + return ctx->aggStartFunc(buf); + } else { + fnError("udfd c plugin aggregation start not implemented"); + return TSDB_CODE_UDF_FUNC_EXEC_FAILURE; + } + return 0; +} + +int32_t udfdCPluginUdfAggProc(SUdfDataBlock *block, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf, void *udfCtx) { + SUdfCPluginCtx *ctx = udfCtx; + if (ctx->aggProcFunc) { + return ctx->aggProcFunc(block, interBuf, newInterBuf); + } else { + fnError("udfd c plugin aggregation process not implemented"); + return TSDB_CODE_UDF_FUNC_EXEC_FAILURE; + } +} + +int32_t udfdCPluginUdfAggMerge(SUdfInterBuf *inputBuf1, SUdfInterBuf *inputBuf2, SUdfInterBuf *outputBuf, + void *udfCtx) { + SUdfCPluginCtx *ctx = udfCtx; + if (ctx->aggMergeFunc) { + return ctx->aggMergeFunc(inputBuf1, inputBuf2, outputBuf); + } else { + fnError("udfd c plugin aggregation merge not implemented"); + return TSDB_CODE_UDF_FUNC_EXEC_FAILURE; + } +} + +int32_t udfdCPluginUdfAggFinish(SUdfInterBuf *buf, SUdfInterBuf *resultData, void *udfCtx) { + SUdfCPluginCtx *ctx = udfCtx; + if (ctx->aggFinishFunc) { + return ctx->aggFinishFunc(buf, resultData); + } else { + fnError("udfd c plugin aggregation finish not implemented"); + return TSDB_CODE_UDF_FUNC_EXEC_FAILURE; + } + return 0; +} + +// for c, the function pointer are filled directly and libloaded = true; +// for others, dlopen/dlsym to find function pointers +typedef struct SUdfScriptPlugin { + int8_t scriptType; + + char libPath[PATH_MAX]; + bool libLoaded; + uv_lib_t lib; + + TScriptUdfScalarProcFunc udfScalarProcFunc; + TScriptUdfAggStartFunc udfAggStartFunc; + TScriptUdfAggProcessFunc udfAggProcFunc; + TScriptUdfAggMergeFunc udfAggMergeFunc; + TScriptUdfAggFinishFunc udfAggFinishFunc; + + TScriptUdfInitFunc udfInitFunc; + TScriptUdfDestoryFunc udfDestroyFunc; + + TScriptOpenFunc openFunc; + TScriptCloseFunc closeFunc; +} SUdfScriptPlugin; + typedef struct SUdfdContext { uv_loop_t *loop; uv_pipe_t ctrlPipe; @@ -37,13 +214,18 @@ typedef struct SUdfdContext { char listenPipeName[PATH_MAX + UDF_LISTEN_PIPE_NAME_LEN + 2]; uv_pipe_t listeningPipe; - void *clientRpc; - SCorEpSet mgmtEp; + void *clientRpc; + SCorEpSet mgmtEp; + uv_mutex_t udfsMutex; SHashObj *udfsHash; + uv_mutex_t scriptPluginsMutex; + SUdfScriptPlugin *scriptPlugins[UDFD_MAX_SCRIPT_PLUGINS]; + SArray *residentFuncs; + char udfDataDir[PATH_MAX]; bool printVersion; } SUdfdContext; @@ -70,16 +252,13 @@ typedef struct SUvUdfWork { struct SUvUdfWork *pWorkNext; } SUvUdfWork; -typedef enum { UDF_STATE_INIT = 0, UDF_STATE_LOADING, UDF_STATE_READY, UDF_STATE_UNLOADING } EUdfState; +typedef enum { UDF_STATE_INIT = 0, UDF_STATE_LOADING, UDF_STATE_READY } EUdfState; typedef struct SUdf { - int32_t refCount; - EUdfState state; - uv_mutex_t lock; - uv_cond_t condReady; - bool resident; - char name[TSDB_FUNC_NAME_LEN + 1]; + int32_t version; + int64_t createdTime; + int8_t funcType; int8_t scriptType; int8_t outputType; @@ -88,20 +267,19 @@ typedef struct SUdf { char path[PATH_MAX]; - uv_lib_t lib; - - TUdfScalarProcFunc scalarProcFunc; + int32_t refCount; + EUdfState state; + uv_mutex_t lock; + uv_cond_t condReady; + bool resident; - TUdfAggStartFunc aggStartFunc; - TUdfAggProcessFunc aggProcFunc; - TUdfAggFinishFunc aggFinishFunc; - TUdfAggMergeFunc aggMergeFunc; + SUdfScriptPlugin *scriptPlugin; + void *scriptUdfCtx; - TUdfInitFunc initFunc; - TUdfDestroyFunc destroyFunc; + int64_t lastFetchTime; // last fetch time in milliseconds + bool expired; } SUdf; -// TODO: add private udf structure. typedef struct SUdfcFuncHandle { SUdf *udf; } SUdfcFuncHandle; @@ -121,7 +299,6 @@ typedef struct SUdfdRpcSendRecvInfo { static void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet); static int32_t udfdFillUdfInfoFromMNode(void *clientRpc, char *udfName, SUdf *udf); static int32_t udfdConnectToMnode(); -static int32_t udfdLoadUdf(char *udfName, SUdf *udf); static bool udfdRpcRfp(int32_t code, tmsg_t msgType); static int initEpSetFromCfg(const char *firstEp, const char *secondEp, SCorEpSet *pEpSet); static int32_t udfdOpenClientRpc(); @@ -155,6 +332,159 @@ static void udfdCloseWalkCb(uv_handle_t *handle, void *arg); static int32_t udfdRun(); static void udfdConnectMnodeThreadFunc(void *args); +SUdf *udfdNewUdf(const char *udfName); +void udfdGetFuncBodyPath(const SUdf *udf, char *path); + +void udfdInitializeCPlugin(SUdfScriptPlugin *plugin) { + plugin->scriptType = TSDB_FUNC_SCRIPT_BIN_LIB; + plugin->openFunc = udfdCPluginOpen; + plugin->closeFunc = udfdCPluginClose; + plugin->udfInitFunc = udfdCPluginUdfInit; + plugin->udfDestroyFunc = udfdCPluginUdfDestroy; + plugin->udfScalarProcFunc = udfdCPluginUdfScalarProc; + plugin->udfAggStartFunc = udfdCPluginUdfAggStart; + plugin->udfAggProcFunc = udfdCPluginUdfAggProc; + plugin->udfAggMergeFunc = udfdCPluginUdfAggMerge; + plugin->udfAggFinishFunc = udfdCPluginUdfAggFinish; + + SScriptUdfEnvItem items[1] = {{"LD_LIBRARY_PATH", tsUdfdLdLibPath}}; + plugin->openFunc(items, 1); + return; +} + +int32_t udfdLoadSharedLib(char *libPath, uv_lib_t *pLib, const char *funcName[], void **func[], int numOfFuncs) { + int err = uv_dlopen(libPath, pLib); + if (err != 0) { + fnError("can not load library %s. error: %s", libPath, uv_strerror(err)); + return TSDB_CODE_UDF_LOAD_UDF_FAILURE; + } + + for (int i = 0; i < numOfFuncs; ++i) { + err = uv_dlsym(pLib, funcName[i], func[i]); + if (err != 0) { + fnError("load library function failed. lib %s function %s", libPath, funcName[i]); + } + } + return 0; +} + +int32_t udfdInitializePythonPlugin(SUdfScriptPlugin *plugin) { + plugin->scriptType = TSDB_FUNC_SCRIPT_PYTHON; + // todo: windows support + sprintf(plugin->libPath, "%s", "libtaospyudf.so"); + plugin->libLoaded = false; + const char *funcName[UDFD_MAX_PLUGIN_FUNCS] = {"pyOpen", "pyClose", "pyUdfInit", + "pyUdfDestroy", "pyUdfScalarProc", "pyUdfAggStart", + "pyUdfAggFinish", "pyUdfAggProc", "pyUdfAggMerge"}; + void **funcs[UDFD_MAX_PLUGIN_FUNCS] = { + (void **)&plugin->openFunc, (void **)&plugin->closeFunc, (void **)&plugin->udfInitFunc, + (void **)&plugin->udfDestroyFunc, (void **)&plugin->udfScalarProcFunc, (void **)&plugin->udfAggStartFunc, + (void **)&plugin->udfAggFinishFunc, (void **)&plugin->udfAggProcFunc, (void **)&plugin->udfAggMergeFunc}; + int32_t err = udfdLoadSharedLib(plugin->libPath, &plugin->lib, funcName, funcs, UDFD_MAX_PLUGIN_FUNCS); + if (err != 0) { + fnError("can not load python plugin. lib path %s", plugin->libPath); + return err; + } + + if (plugin->openFunc) { + int16_t lenPythonPath = + strlen(tsUdfdLdLibPath) + strlen(global.udfDataDir) + 1 + 1; // global.udfDataDir:tsUdfdLdLibPath + char *pythonPath = taosMemoryMalloc(lenPythonPath); +#ifdef WINDOWS + snprintf(pythonPath, lenPythonPath, "%s;%s", global.udfDataDir, tsUdfdLdLibPath); +#else + snprintf(pythonPath, lenPythonPath, "%s:%s", global.udfDataDir, tsUdfdLdLibPath); +#endif + SScriptUdfEnvItem items[] = {{"PYTHONPATH", pythonPath}, {"LOGDIR", tsLogDir}}; + err = plugin->openFunc(items, 2); + taosMemoryFree(pythonPath); + } + if (err != 0) { + fnError("udf script python plugin open func failed. error: %d", err); + uv_dlclose(&plugin->lib); + return err; + } + plugin->libLoaded = true; + + return 0; +} + +void udfdDeinitCPlugin(SUdfScriptPlugin *plugin) { + if (plugin->closeFunc) { + plugin->closeFunc(); + } + plugin->openFunc = NULL; + plugin->closeFunc = NULL; + plugin->udfInitFunc = NULL; + plugin->udfDestroyFunc = NULL; + plugin->udfScalarProcFunc = NULL; + plugin->udfAggStartFunc = NULL; + plugin->udfAggProcFunc = NULL; + plugin->udfAggMergeFunc = NULL; + plugin->udfAggFinishFunc = NULL; + return; +} + +void udfdDeinitPythonPlugin(SUdfScriptPlugin *plugin) { + if (plugin->closeFunc) { + plugin->closeFunc(); + } + uv_dlclose(&plugin->lib); + if (plugin->libLoaded) { + plugin->libLoaded = false; + } + plugin->openFunc = NULL; + plugin->closeFunc = NULL; + plugin->udfInitFunc = NULL; + plugin->udfDestroyFunc = NULL; + plugin->udfScalarProcFunc = NULL; + plugin->udfAggStartFunc = NULL; + plugin->udfAggProcFunc = NULL; + plugin->udfAggMergeFunc = NULL; + plugin->udfAggFinishFunc = NULL; +} + +int32_t udfdInitScriptPlugin(int8_t scriptType) { + SUdfScriptPlugin *plugin = taosMemoryCalloc(1, sizeof(SUdfScriptPlugin)); + + switch (scriptType) { + case TSDB_FUNC_SCRIPT_BIN_LIB: + udfdInitializeCPlugin(plugin); + break; + case TSDB_FUNC_SCRIPT_PYTHON: { + int32_t err = udfdInitializePythonPlugin(plugin); + if (err != 0) { + taosMemoryFree(plugin); + return err; + } + break; + } + default: + fnError("udf script type %d not supported", scriptType); + taosMemoryFree(plugin); + return TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED; + } + + global.scriptPlugins[scriptType] = plugin; + return TSDB_CODE_SUCCESS; +} + +void udfdDeinitScriptPlugins() { + SUdfScriptPlugin *plugin = NULL; + plugin = global.scriptPlugins[TSDB_FUNC_SCRIPT_PYTHON]; + if (plugin != NULL) { + udfdDeinitPythonPlugin(plugin); + taosMemoryFree(plugin); + } + + plugin = global.scriptPlugins[TSDB_FUNC_SCRIPT_BIN_LIB]; + if (plugin != NULL) { + udfdDeinitCPlugin(plugin); + taosMemoryFree(plugin); + } + return; +} + void udfdProcessRequest(uv_work_t *req) { SUvUdfWork *uvUdf = (SUvUdfWork *)(req->data); SUdfRequest request = {0}; @@ -180,51 +510,134 @@ void udfdProcessRequest(uv_work_t *req) { } } +void convertUdf2UdfInfo(SUdf *udf, SScriptUdfInfo *udfInfo) { + udfInfo->bufSize = udf->bufSize; + if (udf->funcType == TSDB_FUNC_TYPE_AGGREGATE) { + udfInfo->funcType = UDF_FUNC_TYPE_AGG; + } else if (udf->funcType == TSDB_FUNC_TYPE_SCALAR) { + udfInfo->funcType = UDF_FUNC_TYPE_SCALAR; + } + udfInfo->name = udf->name; + udfInfo->version = udf->version; + udfInfo->createdTime = udf->createdTime; + udfInfo->outputLen = udf->outputLen; + udfInfo->outputType = udf->outputType; + udfInfo->path = udf->path; + udfInfo->scriptType = udf->scriptType; +} + +int32_t udfdInitUdf(char *udfName, SUdf *udf) { + int32_t err = 0; + err = udfdFillUdfInfoFromMNode(global.clientRpc, udfName, udf); + if (err != 0) { + fnError("can not retrieve udf from mnode. udf name %s", udfName); + return TSDB_CODE_UDF_LOAD_UDF_FAILURE; + } + if (udf->scriptType > UDFD_MAX_SCRIPT_TYPE) { + fnError("udf name %s script type %d not supported", udfName, udf->scriptType); + return TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED; + } + + uv_mutex_lock(&global.scriptPluginsMutex); + SUdfScriptPlugin *scriptPlugin = global.scriptPlugins[udf->scriptType]; + if (scriptPlugin == NULL) { + err = udfdInitScriptPlugin(udf->scriptType); + if (err != 0) { + uv_mutex_unlock(&global.scriptPluginsMutex); + return err; + } + } + uv_mutex_unlock(&global.scriptPluginsMutex); + udf->scriptPlugin = global.scriptPlugins[udf->scriptType]; + + SScriptUdfInfo info = {0}; + convertUdf2UdfInfo(udf, &info); + err = udf->scriptPlugin->udfInitFunc(&info, &udf->scriptUdfCtx); + if (err != 0) { + fnError("udf name %s init failed. error %d", udfName, err); + return err; + } + + fnInfo("udf init succeeded. name %s type %d context %p", udf->name, udf->scriptType, (void *)udf->scriptUdfCtx); + return 0; +} + +SUdf *udfdNewUdf(const char *udfName) { + SUdf *udfNew = taosMemoryCalloc(1, sizeof(SUdf)); + udfNew->refCount = 1; + udfNew->lastFetchTime = taosGetTimestampMs(); + strncpy(udfNew->name, udfName, TSDB_FUNC_NAME_LEN); + + udfNew->state = UDF_STATE_INIT; + uv_mutex_init(&udfNew->lock); + uv_cond_init(&udfNew->condReady); + + udfNew->resident = false; + udfNew->expired = false; + for (int32_t i = 0; i < taosArrayGetSize(global.residentFuncs); ++i) { + char *funcName = taosArrayGet(global.residentFuncs, i); + if (strcmp(udfName, funcName) == 0) { + udfNew->resident = true; + break; + } + } + return udfNew; +} + +SUdf *udfdGetOrCreateUdf(const char *udfName) { + uv_mutex_lock(&global.udfsMutex); + SUdf **pUdfHash = taosHashGet(global.udfsHash, udfName, strlen(udfName)); + int64_t currTime = taosGetTimestampSec(); + bool expired = false; + if (pUdfHash) { + expired = currTime - (*pUdfHash)->lastFetchTime > 10 * 1000; // 10s + if (!expired) { + ++(*pUdfHash)->refCount; + SUdf *udf = *pUdfHash; + uv_mutex_unlock(&global.udfsMutex); + fnInfo("udfd reuse existing udf. udf %s udf version %d, udf created time %" PRIx64, udf->name, udf->version, + udf->createdTime); + return udf; + } else { + (*pUdfHash)->expired = true; + taosHashRemove(global.udfsHash, udfName, strlen(udfName)); + fnInfo("udfd expired, check for new version. existing udf %s udf version %d, udf created time %" PRIx64, + (*pUdfHash)->name, (*pUdfHash)->version, (*pUdfHash)->createdTime); + } + } + + SUdf *udf = udfdNewUdf(udfName); + + SUdf **pUdf = &udf; + taosHashPut(global.udfsHash, udfName, strlen(udfName), pUdf, POINTER_BYTES); + uv_mutex_unlock(&global.udfsMutex); + + return udf; +} + void udfdProcessSetupRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { // TODO: tracable id from client. connect, setup, call, teardown fnInfo("setup request. seq num: %" PRId64 ", udf name: %s", request->seqNum, request->setup.udfName); + SUdfSetupRequest *setup = &request->setup; int32_t code = TSDB_CODE_SUCCESS; SUdf *udf = NULL; - uv_mutex_lock(&global.udfsMutex); - SUdf **udfInHash = taosHashGet(global.udfsHash, request->setup.udfName, strlen(request->setup.udfName)); - if (udfInHash) { - ++(*udfInHash)->refCount; - udf = *udfInHash; - uv_mutex_unlock(&global.udfsMutex); - } else { - SUdf *udfNew = taosMemoryCalloc(1, sizeof(SUdf)); - udfNew->refCount = 1; - udfNew->state = UDF_STATE_INIT; - uv_mutex_init(&udfNew->lock); - uv_cond_init(&udfNew->condReady); - udf = udfNew; - SUdf **pUdf = &udf; - taosHashPut(global.udfsHash, request->setup.udfName, strlen(request->setup.udfName), pUdf, POINTER_BYTES); - uv_mutex_unlock(&global.udfsMutex); - } + udf = udfdGetOrCreateUdf(setup->udfName); uv_mutex_lock(&udf->lock); if (udf->state == UDF_STATE_INIT) { udf->state = UDF_STATE_LOADING; - code = udfdLoadUdf(setup->udfName, udf); - if (udf->initFunc) { - udf->initFunc(); - } - udf->resident = false; - for (int32_t i = 0; i < taosArrayGetSize(global.residentFuncs); ++i) { - char *funcName = taosArrayGet(global.residentFuncs, i); - if (strcmp(setup->udfName, funcName) == 0) { - udf->resident = true; - break; - } + code = udfdInitUdf(setup->udfName, udf); + if (code == 0) { + udf->state = UDF_STATE_READY; + } else { + udf->state = UDF_STATE_INIT; } - udf->state = UDF_STATE_READY; uv_cond_broadcast(&udf->condReady); uv_mutex_unlock(&udf->lock); } else { - while (udf->state != UDF_STATE_READY) { + while (udf->state == UDF_STATE_LOADING) { uv_cond_wait(&udf->condReady, &udf->lock); } uv_mutex_unlock(&udf->lock); @@ -235,10 +648,10 @@ void udfdProcessSetupRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { SUdfResponse rsp; rsp.seqNum = request->seqNum; rsp.type = request->type; - rsp.code = code; + rsp.code = (code != 0) ? TSDB_CODE_UDF_FUNC_EXEC_FAILURE : 0; rsp.setupRsp.udfHandle = (int64_t)(handle); rsp.setupRsp.outputType = udf->outputType; - rsp.setupRsp.outputLen = udf->outputLen; + rsp.setupRsp.bytes = udf->outputLen; rsp.setupRsp.bufSize = udf->bufSize; int32_t len = encodeUdfResponse(NULL, &rsp); @@ -267,10 +680,13 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { switch (call->callType) { case TSDB_UDF_CALL_SCALA_PROC: { SUdfColumn output = {0}; - + output.colMeta.bytes = udf->outputLen; + output.colMeta.type = udf->outputType; + output.colMeta.precision = 0; + output.colMeta.scale = 0; SUdfDataBlock input = {0}; convertDataBlockToUdfDataBlock(&call->block, &input); - code = udf->scalarProcFunc(&input, &output); + code = udf->scriptPlugin->udfScalarProcFunc(&input, &output, udf->scriptUdfCtx); freeUdfDataDataBlock(&input); convertUdfColumnToDataBlock(&output, &response.callRsp.resultData); freeUdfColumn(&output); @@ -278,7 +694,7 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { } case TSDB_UDF_CALL_AGG_INIT: { SUdfInterBuf outBuf = {.buf = taosMemoryMalloc(udf->bufSize), .bufLen = udf->bufSize, .numOfResult = 0}; - udf->aggStartFunc(&outBuf); + code = udf->scriptPlugin->udfAggStartFunc(&outBuf, udf->scriptUdfCtx); subRsp->resultBuf = outBuf; break; } @@ -286,7 +702,7 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { SUdfDataBlock input = {0}; convertDataBlockToUdfDataBlock(&call->block, &input); SUdfInterBuf outBuf = {.buf = taosMemoryMalloc(udf->bufSize), .bufLen = udf->bufSize, .numOfResult = 0}; - code = udf->aggProcFunc(&input, &call->interBuf, &outBuf); + code = udf->scriptPlugin->udfAggProcFunc(&input, &call->interBuf, &outBuf, udf->scriptUdfCtx); freeUdfInterBuf(&call->interBuf); freeUdfDataDataBlock(&input); subRsp->resultBuf = outBuf; @@ -295,7 +711,7 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { } case TSDB_UDF_CALL_AGG_MERGE: { SUdfInterBuf outBuf = {.buf = taosMemoryMalloc(udf->bufSize), .bufLen = udf->bufSize, .numOfResult = 0}; - code = udf->aggMergeFunc(&call->interBuf, &call->interBuf2, &outBuf); + code = udf->scriptPlugin->udfAggMergeFunc(&call->interBuf, &call->interBuf2, &outBuf, udf->scriptUdfCtx); freeUdfInterBuf(&call->interBuf); freeUdfInterBuf(&call->interBuf2); subRsp->resultBuf = outBuf; @@ -304,7 +720,7 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { } case TSDB_UDF_CALL_AGG_FIN: { SUdfInterBuf outBuf = {.buf = taosMemoryMalloc(udf->bufSize), .bufLen = udf->bufSize, .numOfResult = 0}; - code = udf->aggFinishFunc(&call->interBuf, &outBuf); + code = udf->scriptPlugin->udfAggFinishFunc(&call->interBuf, &outBuf, udf->scriptUdfCtx); freeUdfInterBuf(&call->interBuf); subRsp->resultBuf = outBuf; break; @@ -315,7 +731,7 @@ void udfdProcessCallRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { rsp->seqNum = request->seqNum; rsp->type = request->type; - rsp->code = code; + rsp->code = (code != 0) ? TSDB_CODE_UDF_FUNC_EXEC_FAILURE : 0; subRsp->callType = call->callType; int32_t len = encodeUdfResponse(NULL, rsp); @@ -366,18 +782,17 @@ void udfdProcessTeardownRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { uv_mutex_lock(&global.udfsMutex); udf->refCount--; - if (udf->refCount == 0 && !udf->resident) { + if (udf->refCount == 0 && (!udf->resident || udf->expired)) { unloadUdf = true; taosHashRemove(global.udfsHash, udf->name, strlen(udf->name)); } uv_mutex_unlock(&global.udfsMutex); if (unloadUdf) { + fnInfo("udf teardown. udf name: %s type %d: context %p", udf->name, udf->scriptType, (void *)(udf->scriptUdfCtx)); uv_cond_destroy(&udf->condReady); uv_mutex_destroy(&udf->lock); - if (udf->destroyFunc) { - (udf->destroyFunc)(); - } - uv_dlclose(&udf->lib); + code = udf->scriptPlugin->udfDestroyFunc(udf->scriptUdfCtx); + fnDebug("udfd destroy function returns %d", code); taosMemoryFree(udf); } taosMemoryFree(handle); @@ -398,6 +813,61 @@ void udfdProcessTeardownRequest(SUvUdfWork *uvUdf, SUdfRequest *request) { return; } +void udfdGetFuncBodyPath(const SUdf *udf, char *path) { + if (udf->scriptType == TSDB_FUNC_SCRIPT_BIN_LIB) { +#ifdef WINDOWS + snprintf(path, PATH_MAX, "%s%s_%d_%" PRIx64 ".dll", global.udfDataDir, udf->name, udf->version, udf->createdTime); +#else + snprintf(path, PATH_MAX, "%s/lib%s_%d_%" PRIx64 ".so", global.udfDataDir, udf->name, udf->version, + udf->createdTime); +#endif + } else if (udf->scriptType == TSDB_FUNC_SCRIPT_PYTHON) { +#ifdef WINDOWS + snprintf(path, PATH_MAX, "%s%s_%d_%" PRIx64 ".py", global.udfDataDir, udf->name, udf->version, udf->createdTime); +#else + snprintf(path, PATH_MAX, "%s/%s_%d_%" PRIx64 ".py", global.udfDataDir, udf->name, udf->version, udf->createdTime); +#endif + } else { +#ifdef WINDOWS + snprintf(path, PATH_MAX, "%s%s_%d_%" PRIx64, global.udfDataDir, udf->name, udf->version, udf->createdTime); +#else + snprintf(path, PATH_MAX, "%s/lib%s_%d_%" PRIx64, global.udfDataDir, udf->name, udf->version, udf->createdTime); +#endif + } +} + +int32_t udfdSaveFuncBodyToFile(SFuncInfo *pFuncInfo, SUdf *udf) { + if (!osDataSpaceAvailable()) { + terrno = TSDB_CODE_NO_AVAIL_DISK; + fnError("udfd create shared library failed since %s", terrstr(terrno)); + return terrno; + } + + char path[PATH_MAX] = {0}; + udfdGetFuncBodyPath(udf, path); + bool fileExist = !(taosStatFile(path, NULL, NULL) < 0); + if (fileExist) { + strncpy(udf->path, path, PATH_MAX); + fnInfo("udfd func body file. reuse existing file %s", path); + return TSDB_CODE_SUCCESS; + } + + TdFilePtr file = taosOpenFile(path, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_READ | TD_FILE_TRUNC); + if (file == NULL) { + fnError("udfd write udf shared library: %s failed, error: %d %s", path, errno, strerror(errno)); + return TSDB_CODE_FILE_CORRUPTED; + } + int64_t count = taosWriteFile(file, pFuncInfo->pCode, pFuncInfo->codeSize); + if (count != pFuncInfo->codeSize) { + fnError("udfd write udf shared library failed"); + return TSDB_CODE_FILE_CORRUPTED; + } + taosCloseFile(&file); + + strncpy(udf->path, path, PATH_MAX); + return TSDB_CODE_SUCCESS; +} + void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) { SUdfdRpcSendRecvInfo *msgInfo = (SUdfdRpcSendRecvInfo *)pMsg->info.ahandle; @@ -436,9 +906,7 @@ void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) { } else if (msgInfo->rpcType == UDFD_RPC_RETRIVE_FUNC) { SRetrieveFuncRsp retrieveRsp = {0}; tDeserializeSRetrieveFuncRsp(pMsg->pCont, pMsg->contLen, &retrieveRsp); - if (retrieveRsp.pFuncInfos == NULL) { - goto _return; - } + SFuncInfo *pFuncInfo = (SFuncInfo *)taosArrayGet(retrieveRsp.pFuncInfos, 0); SUdf *udf = msgInfo->param; udf->funcType = pFuncInfo->funcType; @@ -447,38 +915,16 @@ void udfdProcessRpcRsp(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) { udf->outputLen = pFuncInfo->outputLen; udf->bufSize = pFuncInfo->bufSize; - if (!osTempSpaceAvailable()) { - terrno = TSDB_CODE_NO_AVAIL_DISK; - msgInfo->code = terrno; - fnError("udfd create shared library failed since %s", terrstr(terrno)); - goto _return; - } - - char path[PATH_MAX] = {0}; -#ifdef WINDOWS - snprintf(path, sizeof(path), "%s%s.dll", tsTempDir, pFuncInfo->name); -#else - snprintf(path, sizeof(path), "%s/lib%s.so", tsTempDir, pFuncInfo->name); -#endif - - TdFilePtr file = taosOpenFile(path, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_READ | TD_FILE_TRUNC); - if (file == NULL) { - fnError("udfd write udf shared library: %s failed, error: %d %s", path, errno, strerror(errno)); - msgInfo->code = TSDB_CODE_FILE_CORRUPTED; - goto _return; + SFuncExtraInfo *pFuncExtraInfo = (SFuncExtraInfo *)taosArrayGet(retrieveRsp.pFuncExtraInfos, 0); + udf->version = pFuncExtraInfo->funcVersion; + udf->createdTime = pFuncExtraInfo->funcCreatedTime; + msgInfo->code = udfdSaveFuncBodyToFile(pFuncInfo, udf); + if (msgInfo->code != 0) { + udf->lastFetchTime = 0; } - - int64_t count = taosWriteFile(file, pFuncInfo->pCode, pFuncInfo->codeSize); - if (count != pFuncInfo->codeSize) { - fnError("udfd write udf shared library failed"); - msgInfo->code = TSDB_CODE_FILE_CORRUPTED; - goto _return; - } - taosCloseFile(&file); - strncpy(udf->path, path, PATH_MAX); tFreeSFuncInfo(pFuncInfo); taosArrayDestroy(retrieveRsp.pFuncInfos); - msgInfo->code = 0; + taosArrayDestroy(retrieveRsp.pFuncExtraInfos); } _return: @@ -527,6 +973,7 @@ int32_t udfdConnectToMnode() { tstrncpy(connReq.passwd, pass, sizeof(connReq.passwd)); connReq.pid = taosGetPId(); connReq.startTime = taosGetTimestampMs(); + strcpy(connReq.sVer, version); int32_t contLen = tSerializeSConnectReq(NULL, 0, &connReq); void *pReq = rpcMallocCont(contLen); @@ -550,65 +997,10 @@ int32_t udfdConnectToMnode() { return code; } -int32_t udfdLoadUdf(char *udfName, SUdf *udf) { - strncpy(udf->name, udfName, TSDB_FUNC_NAME_LEN); - int32_t err = 0; - - err = udfdFillUdfInfoFromMNode(global.clientRpc, udf->name, udf); - if (err != 0) { - fnError("can not retrieve udf from mnode. udf name %s", udfName); - return TSDB_CODE_UDF_LOAD_UDF_FAILURE; - } - - err = uv_dlopen(udf->path, &udf->lib); - if (err != 0) { - fnError("can not load library %s. error: %s", udf->path, uv_strerror(err)); - return TSDB_CODE_UDF_LOAD_UDF_FAILURE; - } - - char initFuncName[TSDB_FUNC_NAME_LEN + 5] = {0}; - char *initSuffix = "_init"; - strcpy(initFuncName, udfName); - strncat(initFuncName, initSuffix, strlen(initSuffix)); - uv_dlsym(&udf->lib, initFuncName, (void **)(&udf->initFunc)); - - char destroyFuncName[TSDB_FUNC_NAME_LEN + 5] = {0}; - char *destroySuffix = "_destroy"; - strcpy(destroyFuncName, udfName); - strncat(destroyFuncName, destroySuffix, strlen(destroySuffix)); - uv_dlsym(&udf->lib, destroyFuncName, (void **)(&udf->destroyFunc)); - - if (udf->funcType == TSDB_FUNC_TYPE_SCALAR) { - char processFuncName[TSDB_FUNC_NAME_LEN] = {0}; - strcpy(processFuncName, udfName); - uv_dlsym(&udf->lib, processFuncName, (void **)(&udf->scalarProcFunc)); - } else if (udf->funcType == TSDB_FUNC_TYPE_AGGREGATE) { - char processFuncName[TSDB_FUNC_NAME_LEN] = {0}; - strcpy(processFuncName, udfName); - uv_dlsym(&udf->lib, processFuncName, (void **)(&udf->aggProcFunc)); - char startFuncName[TSDB_FUNC_NAME_LEN + 6] = {0}; - char *startSuffix = "_start"; - strncpy(startFuncName, processFuncName, sizeof(startFuncName)); - strncat(startFuncName, startSuffix, strlen(startSuffix)); - uv_dlsym(&udf->lib, startFuncName, (void **)(&udf->aggStartFunc)); - char finishFuncName[TSDB_FUNC_NAME_LEN + 7] = {0}; - char *finishSuffix = "_finish"; - strncpy(finishFuncName, processFuncName, sizeof(finishFuncName)); - strncat(finishFuncName, finishSuffix, strlen(finishSuffix)); - uv_dlsym(&udf->lib, finishFuncName, (void **)(&udf->aggFinishFunc)); - char mergeFuncName[TSDB_FUNC_NAME_LEN + 6] = {0}; - char *mergeSuffix = "_merge"; - strncpy(mergeFuncName, processFuncName, sizeof(mergeFuncName)); - strncat(mergeFuncName, mergeSuffix, strlen(mergeSuffix)); - uv_dlsym(&udf->lib, mergeFuncName, (void **)(&udf->aggMergeFunc)); - } - return 0; -} static bool udfdRpcRfp(int32_t code, tmsg_t msgType) { if (code == TSDB_CODE_RPC_NETWORK_UNAVAIL || code == TSDB_CODE_RPC_BROKEN_LINK || code == TSDB_CODE_SYN_NOT_LEADER || - code == TSDB_CODE_RPC_SOMENODE_NOT_CONNECTED || - code == TSDB_CODE_SYN_RESTORING || code == TSDB_CODE_MNODE_NOT_FOUND || code == TSDB_CODE_APP_IS_STARTING || - code == TSDB_CODE_APP_IS_STOPPING) { + code == TSDB_CODE_RPC_SOMENODE_NOT_CONNECTED || code == TSDB_CODE_SYN_RESTORING || + code == TSDB_CODE_MNODE_NOT_FOUND || code == TSDB_CODE_APP_IS_STARTING || code == TSDB_CODE_APP_IS_STOPPING) { if (msgType == TDMT_SCH_QUERY || msgType == TDMT_SCH_MERGE_QUERY || msgType == TDMT_SCH_FETCH || msgType == TDMT_SCH_MERGE_FETCH) { return false; @@ -673,6 +1065,12 @@ int32_t udfdOpenClientRpc() { rpcInit.rfp = udfdRpcRfp; rpcInit.compressSize = tsCompressMsgSize; + int32_t connLimitNum = tsNumOfRpcSessions / (tsNumOfRpcThreads * 3); + connLimitNum = TMAX(connLimitNum, 10); + connLimitNum = TMIN(connLimitNum, 500); + rpcInit.connLimitNum = connLimitNum; + rpcInit.timeToGetConn = tsTimeToGetAvailableConn; + global.clientRpc = rpcOpen(&rpcInit); if (global.clientRpc == NULL) { fnError("failed to init dnode rpc client"); @@ -765,7 +1163,7 @@ bool isUdfdUvMsgComplete(SUdfdUvConn *pipe) { } void udfdHandleRequest(SUdfdUvConn *conn) { - char *inputBuf = conn->inputBuf; + char *inputBuf = conn->inputBuf; int32_t inputLen = conn->inputLen; uv_work_t *work = taosMemoryMalloc(sizeof(uv_work_t)); @@ -784,7 +1182,7 @@ void udfdHandleRequest(SUdfdUvConn *conn) { void udfdPipeCloseCb(uv_handle_t *pipe) { SUdfdUvConn *conn = pipe->data; - SUvUdfWork* pWork = conn->pWorkList; + SUvUdfWork *pWork = conn->pWorkList; while (pWork != NULL) { pWork->conn = NULL; pWork = pWork->pWorkNext; @@ -960,6 +1358,8 @@ static void udfdCloseWalkCb(uv_handle_t *handle, void *arg) { } static int32_t udfdRun() { + uv_mutex_init(&global.scriptPluginsMutex); + global.udfsHash = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); uv_mutex_init(&global.udfsMutex); @@ -1016,13 +1416,11 @@ int32_t udfdDeinitResidentFuncs() { char *funcName = taosArrayGet(global.residentFuncs, i); SUdf **udfInHash = taosHashGet(global.udfsHash, funcName, strlen(funcName)); if (udfInHash) { - SUdf *udf = *udfInHash; - if (udf->destroyFunc) { - (udf->destroyFunc)(); - } - uv_dlclose(&udf->lib); - taosMemoryFree(udf); + SUdf *udf = *udfInHash; + int32_t code = udf->scriptPlugin->udfDestroyFunc(udf->scriptUdfCtx); + fnDebug("udfd destroy function returns %d", code); taosHashRemove(global.udfsHash, funcName, strlen(funcName)); + taosMemoryFree(udf); } } taosArrayDestroy(global.residentFuncs); @@ -1035,6 +1433,24 @@ int32_t udfdCleanup() { return 0; } +int32_t udfdCreateUdfSourceDir() { + snprintf(global.udfDataDir, PATH_MAX, "%s/.udf", tsDataDir); + int32_t code = taosMkDir(global.udfDataDir); + if (code != TSDB_CODE_SUCCESS) { + snprintf(global.udfDataDir, PATH_MAX, "%s/.udf", tsTempDir); + code = taosMkDir(global.udfDataDir); + } + fnInfo("udfd create udf source directory %s. result: %s", global.udfDataDir, tstrerror(code)); + + return code; +} + +int32_t udfdDestroyUdfSourceDir() { + fnInfo("destory udf source directory %s", global.udfDataDir); + taosRemoveDir(global.udfDataDir); + return 0; +} + int main(int argc, char *argv[]) { if (!taosCheckSystemIsLittleEnd()) { printf("failed to start since on non-little-end machines\n"); @@ -1063,10 +1479,15 @@ int main(int argc, char *argv[]) { initEpSetFromCfg(tsFirst, tsSecond, &global.mgmtEp); if (udfdOpenClientRpc() != 0) { - fnError("open rpc connection to mnode failure"); + fnError("open rpc connection to mnode failed"); return -3; } + if (udfdCreateUdfSourceDir() != 0) { + fnError("create udf source directory failed"); + return -4; + } + if (udfdUvInit() != 0) { fnError("uv init failure"); return -5; @@ -1080,9 +1501,13 @@ int main(int argc, char *argv[]) { udfdRun(); removeListeningPipe(); + udfdDestroyUdfSourceDir(); udfdCloseClientRpc(); udfdDeinitResidentFuncs(); + + udfdDeinitScriptPlugins(); + udfdCleanup(); return 0; } diff --git a/source/libs/function/test/runUdf.c b/source/libs/function/test/runUdf.c index b5d1b1576b7b33d3ca6511e2bdf707daa8e78a41..aa8b88b7384cf1140b1c927bf0c9bfeaff0d7dc9 100644 --- a/source/libs/function/test/runUdf.c +++ b/source/libs/function/test/runUdf.c @@ -55,7 +55,7 @@ int scalarFuncTest() { SColumnInfoData *pCol = taosArrayGet(pBlock->pDataBlock, 0); for (int32_t j = 0; j < pBlock->info.rows; ++j) { - colDataAppendInt32(pCol, j, &j); + colDataSetInt32(pCol, j, &j); } SScalarParam input = {0}; @@ -99,7 +99,7 @@ int aggregateFuncTest() { SColumnInfoData *pColInfo = bdGetColumnInfoData(pBlock, 0); for (int32_t j = 0; j < pBlock->info.rows; ++j) { - colDataAppendInt32(pColInfo, j, &j); + colDataSetInt32(pColInfo, j, &j); } SUdfInterBuf buf = {0}; diff --git a/source/libs/function/test/udf1.c b/source/libs/function/test/udf1.c index 71d30b67557847dcdf451cefb20c7b144d214cf8..5b950879962b56dc38a1c26f8665c13cd6c29c9c 100644 --- a/source/libs/function/test/udf1.c +++ b/source/libs/function/test/udf1.c @@ -14,15 +14,8 @@ DLL_EXPORT int32_t udf1_init() { return 0; } DLL_EXPORT int32_t udf1_destroy() { return 0; } DLL_EXPORT int32_t udf1(SUdfDataBlock *block, SUdfColumn *resultCol) { - SUdfColumnMeta *meta = &resultCol->colMeta; - meta->bytes = 4; - meta->type = TSDB_DATA_TYPE_INT; - meta->scale = 0; - meta->precision = 0; - SUdfColumnData *resultData = &resultCol->colData; - resultData->numOfRows = block->numOfRows; - for (int32_t i = 0; i < resultData->numOfRows; ++i) { + for (int32_t i = 0; i < block->numOfRows; ++i) { int j = 0; for (; j < block->numOfCols; ++j) { if (udfColDataIsNull(block->udfCols[j], i)) { @@ -31,7 +24,7 @@ DLL_EXPORT int32_t udf1(SUdfDataBlock *block, SUdfColumn *resultCol) { } } if (j == block->numOfCols) { - int32_t luckyNum = 88; + int32_t luckyNum = 1; udfColDataSet(resultCol, i, (char *)&luckyNum, false); } } @@ -42,5 +35,6 @@ DLL_EXPORT int32_t udf1(SUdfDataBlock *block, SUdfColumn *resultCol) { #ifdef WINDOWS Sleep(1); #endif + resultData->numOfRows = block->numOfRows; return 0; -} \ No newline at end of file +} diff --git a/source/libs/function/test/udf1_dup.c b/source/libs/function/test/udf1_dup.c new file mode 100644 index 0000000000000000000000000000000000000000..c251192da34568741f0058c61999e5aebf1c56d2 --- /dev/null +++ b/source/libs/function/test/udf1_dup.c @@ -0,0 +1,42 @@ +#include +#include +#include +#ifdef LINUX +#include +#endif +#ifdef WINDOWS +#include +#endif +#include "taosudf.h" + + +DLL_EXPORT int32_t udf1_dup_init() { return 0; } + +DLL_EXPORT int32_t udf1_dup_destroy() { return 0; } + +DLL_EXPORT int32_t udf1_dup(SUdfDataBlock *block, SUdfColumn *resultCol) { + SUdfColumnData *resultData = &resultCol->colData; + for (int32_t i = 0; i < block->numOfRows; ++i) { + int j = 0; + for (; j < block->numOfCols; ++j) { + if (udfColDataIsNull(block->udfCols[j], i)) { + udfColDataSetNull(resultCol, i); + break; + } + } + if (j == block->numOfCols) { + int32_t luckyNum = 2; + udfColDataSet(resultCol, i, (char *)&luckyNum, false); + } + } + // to simulate actual processing delay by udf +#ifdef LINUX + usleep(1 * 1000); // usleep takes sleep time in us (1 millionth of a second) +#endif +#ifdef WINDOWS + Sleep(1); +#endif + resultData->numOfRows = block->numOfRows; + return 0; +} + diff --git a/source/libs/function/test/udf2.c b/source/libs/function/test/udf2.c index e24789d0fb4095f2fdc75d8d1ce3e8dc1355e4c6..faf4daa4e53cacd70cbfd4ff319178c2cdbb8a56 100644 --- a/source/libs/function/test/udf2.c +++ b/source/libs/function/test/udf2.c @@ -12,12 +12,15 @@ DLL_EXPORT int32_t udf2_destroy() { return 0; } DLL_EXPORT int32_t udf2_start(SUdfInterBuf* buf) { *(int64_t*)(buf->buf) = 0; buf->bufLen = sizeof(double); - buf->numOfResult = 0; + buf->numOfResult = 1; return 0; } DLL_EXPORT int32_t udf2(SUdfDataBlock* block, SUdfInterBuf* interBuf, SUdfInterBuf* newInterBuf) { - double sumSquares = *(double*)interBuf->buf; + double sumSquares = 0; + if (interBuf->numOfResult == 1) { + sumSquares = *(double*)interBuf->buf; + } int8_t numNotNull = 0; for (int32_t i = 0; i < block->numOfCols; ++i) { SUdfColumn* col = block->udfCols[i]; diff --git a/source/libs/function/test/udf2_dup.c b/source/libs/function/test/udf2_dup.c new file mode 100644 index 0000000000000000000000000000000000000000..1a98190823c4510b24b1bac2d053dc3060973744 --- /dev/null +++ b/source/libs/function/test/udf2_dup.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include "taosudf.h" + +DLL_EXPORT int32_t udf2_dup_init() { return 0; } + +DLL_EXPORT int32_t udf2_dup_destroy() { return 0; } + +DLL_EXPORT int32_t udf2_dup_start(SUdfInterBuf* buf) { + *(int64_t*)(buf->buf) = 0; + buf->bufLen = sizeof(double); + buf->numOfResult = 1; + return 0; +} + +DLL_EXPORT int32_t udf2_dup(SUdfDataBlock* block, SUdfInterBuf* interBuf, SUdfInterBuf* newInterBuf) { + double sumSquares = 0; + if (interBuf->numOfResult == 1) { + sumSquares = *(double*)interBuf->buf; + } + int8_t numNotNull = 0; + for (int32_t i = 0; i < block->numOfCols; ++i) { + SUdfColumn* col = block->udfCols[i]; + if (!(col->colMeta.type == TSDB_DATA_TYPE_INT || col->colMeta.type == TSDB_DATA_TYPE_DOUBLE)) { + return TSDB_CODE_UDF_INVALID_INPUT; + } + } + for (int32_t i = 0; i < block->numOfCols; ++i) { + for (int32_t j = 0; j < block->numOfRows; ++j) { + SUdfColumn* col = block->udfCols[i]; + if (udfColDataIsNull(col, j)) { + continue; + } + switch (col->colMeta.type) { + case TSDB_DATA_TYPE_INT: { + char* cell = udfColDataGetData(col, j); + int32_t num = *(int32_t*)cell; + sumSquares += (double)num * num; + break; + } + case TSDB_DATA_TYPE_DOUBLE: { + char* cell = udfColDataGetData(col, j); + double num = *(double*)cell; + sumSquares += num * num; + break; + } + default: + break; + } + ++numNotNull; + } + } + + *(double*)(newInterBuf->buf) = sumSquares; + newInterBuf->bufLen = sizeof(double); + + if (interBuf->numOfResult == 0 && numNotNull == 0) { + newInterBuf->numOfResult = 0; + } else { + newInterBuf->numOfResult = 1; + } + return 0; +} + +DLL_EXPORT int32_t udf2_dup_finish(SUdfInterBuf* buf, SUdfInterBuf* resultData) { + if (buf->numOfResult == 0) { + resultData->numOfResult = 0; + return 0; + } + double sumSquares = *(double*)(buf->buf); + *(double*)(resultData->buf) = sqrt(sumSquares) + 100; + resultData->bufLen = sizeof(double); + resultData->numOfResult = 1; + return 0; +} diff --git a/source/libs/index/src/index.c b/source/libs/index/src/index.c index a99c87b7f9a5bef05c8e641ab4aa826e7c5e7dfc..3ed66956e841b43d0744cbd2c7aa0ad6614599df 100644 --- a/source/libs/index/src/index.c +++ b/source/libs/index/src/index.c @@ -126,7 +126,7 @@ int indexOpen(SIndexOpts* opts, const char* path, SIndex** index) { idx->colObj = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK); idx->version = 1; - idx->path = tstrdup(path); + idx->path = taosStrdup(path); taosThreadMutexInit(&idx->mtx, NULL); tsem_init(&idx->sem, 0, 0); diff --git a/source/libs/index/src/indexCache.c b/source/libs/index/src/indexCache.c index 0bb454571adebae9695ae07cf7ff6af4efd9e95f..8b0e7125530fd557648d97106fc106132972c71b 100644 --- a/source/libs/index/src/indexCache.c +++ b/source/libs/index/src/indexCache.c @@ -22,8 +22,8 @@ #define MAX_INDEX_KEY_LEN 256 // test only, change later #define MEM_TERM_LIMIT 10 * 10000 -#define MEM_THRESHOLD 8 * 512 * 1024 // 8M -#define MEM_SIGNAL_QUIT MEM_THRESHOLD * 20 +#define MEM_THRESHOLD 128 * 1024 * 1024 // 8M +#define MEM_SIGNAL_QUIT MEM_THRESHOLD * 5 #define MEM_ESTIMATE_RADIO 1.5 static void idxMemRef(MemTable* tbl); @@ -340,7 +340,7 @@ IndexCache* idxCacheCreate(SIndex* idx, uint64_t suid, const char* colName, int8 cache->mem = idxInternalCacheCreate(type); cache->mem->pCache = cache; - cache->colName = IDX_TYPE_CONTAIN_EXTERN_TYPE(type, TSDB_DATA_TYPE_JSON) ? tstrdup(JSON_COLUMN) : tstrdup(colName); + cache->colName = IDX_TYPE_CONTAIN_EXTERN_TYPE(type, TSDB_DATA_TYPE_JSON) ? taosStrdup(JSON_COLUMN) : taosStrdup(colName); cache->type = type; cache->index = idx; cache->version = 0; @@ -767,7 +767,7 @@ static bool idxCacheIteratorNext(Iterate* itera) { iv->type = ct->operaType; iv->ver = ct->version; - iv->colVal = tstrdup(ct->colVal); + iv->colVal = taosStrdup(ct->colVal); taosArrayPush(iv->val, &ct->uid); } return next; diff --git a/source/libs/index/src/indexFilter.c b/source/libs/index/src/indexFilter.c index 5c14424b7ecb56a45405cd48daa018a5f8837da9..02ed0d2d05270511244b329c3e05c1b8a311035a 100644 --- a/source/libs/index/src/indexFilter.c +++ b/source/libs/index/src/indexFilter.c @@ -221,6 +221,71 @@ static FORCE_INLINE int32_t sifInitJsonParam(SNode *node, SIFParam *param, SIFCt param->status = SFLT_COARSE_INDEX; return 0; } +static int32_t sifNeedConvertCond(SNode *l, SNode *r) { + if (nodeType(l) != QUERY_NODE_COLUMN || nodeType(r) != QUERY_NODE_VALUE) { + return 0; + } + SColumnNode *c = (SColumnNode *)l; + SValueNode *v = (SValueNode *)r; + int32_t ctype = c->node.resType.type; + int32_t vtype = v->node.resType.type; + if (!IS_VAR_DATA_TYPE(ctype) && IS_VAR_DATA_TYPE(vtype)) { + return 1; + } + return 0; +} +static int32_t sifInitParamValByCol(SNode *r, SNode *l, SIFParam *param, SIFCtx *ctx) { + param->status = SFLT_COARSE_INDEX; + SColumnNode *cn = (SColumnNode *)r; + SValueNode *vn = (SValueNode *)l; + if (vn->typeData == TSDB_DATA_TYPE_NULL && (vn->literal == NULL || strlen(vn->literal) == 0)) { + param->status = SFLT_NOT_INDEX; + return 0; + } + SDataType *pType = &cn->node.resType; + int32_t type = pType->type; + + SDataType *pVType = &vn->node.resType; + int32_t vtype = pVType->type; + char *pData = nodesGetValueFromNode(vn); + int32_t valLen = 0; + char **value = ¶m->condValue; + + if (IS_VAR_DATA_TYPE(type)) { + int32_t dataLen = varDataTLen(pData); + if (type == TSDB_DATA_TYPE_JSON) { + if (*pData == TSDB_DATA_TYPE_NULL) { + dataLen = 0; + } else if (*pData == TSDB_DATA_TYPE_NCHAR) { + dataLen = varDataTLen(pData); + } else if (*pData == TSDB_DATA_TYPE_DOUBLE) { + dataLen = LONG_BYTES; + } else if (*pData == TSDB_DATA_TYPE_BOOL) { + dataLen = CHAR_BYTES; + } + dataLen += CHAR_BYTES; + } + valLen = dataLen; + } else { + valLen = pType->bytes; + } + char *tv = taosMemoryCalloc(1, valLen + 1); + if (tv == NULL) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + memcpy(tv, pData, valLen); + *value = tv; + + param->colId = -1; + param->colValType = (uint8_t)(vn->node.resType.type); + if (vn->literal != NULL && strlen(vn->literal) <= sizeof(param->colName)) { + memcpy(param->colName, vn->literal, strlen(vn->literal)); + } else { + param->status = SFLT_NOT_INDEX; + } + return 0; +} static int32_t sifInitParam(SNode *node, SIFParam *param, SIFCtx *ctx) { param->status = SFLT_COARSE_INDEX; switch (nodeType(node)) { @@ -317,8 +382,13 @@ static int32_t sifInitOperParams(SIFParam **params, SOperatorNode *node, SIFCtx return TSDB_CODE_SUCCESS; } else { SIF_ERR_JRET(sifInitParam(node->pLeft, ¶mList[0], ctx)); + if (nParam > 1) { + // if (sifNeedConvertCond(node->pLeft, node->pRight)) { + // SIF_ERR_JRET(sifInitParamValByCol(node->pLeft, node->pRight, ¶mList[1], ctx)); + // } else { SIF_ERR_JRET(sifInitParam(node->pRight, ¶mList[1], ctx)); + // } // if (paramList[0].colValType == TSDB_DATA_TYPE_JSON && // ((SOperatorNode *)(node))->opType == OP_TYPE_JSON_CONTAINS) { // return TSDB_CODE_OUT_OF_MEMORY; @@ -383,12 +453,13 @@ static FORCE_INLINE int sifEqual(void *a, void *b, int16_t dtype) { //__compar_fn_t func = idxGetCompar(dtype); return (int)tDoCompare(func, QUERY_TERM, a, b); } -static FORCE_INLINE FilterFunc sifGetFilterFunc(EIndexQueryType type, bool *reverse) { +static FORCE_INLINE FilterFunc sifGetFilterFunc(EIndexQueryType type, bool *reverse, bool *equal) { if (type == QUERY_LESS_EQUAL || type == QUERY_LESS_THAN) { *reverse = true; } else { *reverse = false; } + if (type == QUERY_LESS_EQUAL) return sifLessEqual; else if (type == QUERY_LESS_THAN) @@ -398,64 +469,154 @@ static FORCE_INLINE FilterFunc sifGetFilterFunc(EIndexQueryType type, bool *reve else if (type == QUERY_GREATER_THAN) return sifGreaterThan; else if (type == QUERY_TERM) { + *equal = true; return sifEqual; } return NULL; } +int32_t sifStr2Num(char *buf, int32_t len, int8_t type, void *val) { + // signed/unsigned/float + if (IS_SIGNED_NUMERIC_TYPE(type)) { + int64_t v = 0; + if (0 != toInteger(buf, len, 10, &v)) { + return -1; + } + if (type == TSDB_DATA_TYPE_BIGINT) { + *(int64_t *)val = v; + } else if (type == TSDB_DATA_TYPE_INT) { + *(int32_t *)val = v; + } else if (type == TSDB_DATA_TYPE_TINYINT) { + *(int8_t *)val = v; + } else if (type == TSDB_DATA_TYPE_SMALLINT) { + *(int16_t *)val = v; + } + } else if (IS_FLOAT_TYPE(type)) { + if (type == TSDB_DATA_TYPE_FLOAT) { + *(float *)val = taosStr2Float(buf, NULL); + } else { + *(double *)val = taosStr2Double(buf, NULL); + } + } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { + uint64_t v = 0; + if (0 != toUInteger(buf, len, 10, &v)) { + return -1; + } + if (type == TSDB_DATA_TYPE_UBIGINT) { + *(uint64_t *)val = v; + } else if (type == TSDB_DATA_TYPE_UINT) { + *(uint32_t *)val = v; + } else if (type == TSDB_DATA_TYPE_UTINYINT) { + *(uint8_t *)val = v; + } else if (type == TSDB_DATA_TYPE_USMALLINT) { + *(uint16_t *)val = v; + } + } else { + return -1; + } + return 0; +} -static void sifSetFltParam(SIFParam *left, SIFParam *right, SDataTypeBuf *typedata, SMetaFltParam *param) { - int8_t ltype = left->colValType, rtype = right->colValType; +static int32_t sifSetFltParam(SIFParam *left, SIFParam *right, SDataTypeBuf *typedata, SMetaFltParam *param) { + int32_t code = 0; + int8_t ltype = left->colValType, rtype = right->colValType; + if (!IS_NUMERIC_TYPE(ltype) || !((IS_NUMERIC_TYPE(rtype)) || rtype == TSDB_DATA_TYPE_VARCHAR)) { + return -1; + } if (ltype == TSDB_DATA_TYPE_FLOAT) { float f = 0; - SIF_DATA_CONVERT(rtype, right->condValue, f); + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, f); + } else { + SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_FLOAT, &f)); + } typedata->f = f; param->val = &typedata->f; } else if (ltype == TSDB_DATA_TYPE_DOUBLE) { double d = 0; - SIF_DATA_CONVERT(rtype, right->condValue, d); + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, d); + } else { + SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_DOUBLE, &d)); + } typedata->d = d; param->val = &typedata->d; } else if (ltype == TSDB_DATA_TYPE_BIGINT) { int64_t i64 = 0; - SIF_DATA_CONVERT(rtype, right->condValue, i64); + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, i64); + } else { + SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_BIGINT, &i64)); + } typedata->i64 = i64; param->val = &typedata->i64; } else if (ltype == TSDB_DATA_TYPE_INT) { int32_t i32 = 0; - SIF_DATA_CONVERT(rtype, right->condValue, i32); + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, i32); + } else { + SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_INT, &i32)); + } typedata->i32 = i32; param->val = &typedata->i32; } else if (ltype == TSDB_DATA_TYPE_SMALLINT) { int16_t i16 = 0; - SIF_DATA_CONVERT(rtype, right->condValue, i16); + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, i16); + } else { + SIF_ERR_RET( + sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_SMALLINT, &i16)); + } + typedata->i16 = i16; param->val = &typedata->i16; } else if (ltype == TSDB_DATA_TYPE_TINYINT) { int8_t i8 = 0; - SIF_DATA_CONVERT(rtype, right->condValue, i8) + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, i8); + } else { + SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_TINYINT, &i8)); + } typedata->i8 = i8; param->val = &typedata->i8; } else if (ltype == TSDB_DATA_TYPE_UBIGINT) { uint64_t u64 = 0; - SIF_DATA_CONVERT(rtype, right->condValue, u64); + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, u64); + } else { + SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_UBIGINT, &u64)); + } typedata->u64 = u64; param->val = &typedata->u64; } else if (ltype == TSDB_DATA_TYPE_UINT) { uint32_t u32 = 0; - SIF_DATA_CONVERT(rtype, right->condValue, u32); + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, u32); + } else { + SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_UINT, &u32)); + } typedata->u32 = u32; param->val = &typedata->u32; } else if (ltype == TSDB_DATA_TYPE_USMALLINT) { uint16_t u16 = 0; - SIF_DATA_CONVERT(rtype, right->condValue, u16); + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, u16); + } else { + SIF_ERR_RET( + sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_USMALLINT, &u16)); + } typedata->u16 = u16; param->val = &typedata->u16; } else if (ltype == TSDB_DATA_TYPE_UTINYINT) { uint8_t u8 = 0; - SIF_DATA_CONVERT(rtype, right->condValue, u8); + if (IS_NUMERIC_TYPE(rtype)) { + SIF_DATA_CONVERT(rtype, right->condValue, u8); + } else { + SIF_ERR_RET(sifStr2Num(varDataVal(right->condValue), varDataLen(right->condValue), TSDB_DATA_TYPE_UTINYINT, &u8)); + } typedata->u8 = u8; param->val = &typedata->u8; } + return 0; } static int32_t sifDoIndex(SIFParam *left, SIFParam *right, int8_t operType, SIFParam *output) { int ret = 0; @@ -474,14 +635,15 @@ static int32_t sifDoIndex(SIFParam *left, SIFParam *right, int8_t operType, SIFP ret = indexJsonSearch(arg->ivtIdx, mtm, output->result); indexMultiTermQueryDestroy(mtm); } else { - bool reverse; - FilterFunc filterFunc = sifGetFilterFunc(qtype, &reverse); + bool reverse = false, equal = false; + FilterFunc filterFunc = sifGetFilterFunc(qtype, &reverse, &equal); SMetaFltParam param = {.suid = arg->suid, .cid = left->colId, .type = left->colValType, .val = right->condValue, .reverse = reverse, + .equal = equal, .filterFunc = filterFunc}; char buf[128] = {0}; @@ -495,7 +657,7 @@ static int32_t sifDoIndex(SIFParam *left, SIFParam *right, int8_t operType, SIFP param.val = buf; } } else { - sifSetFltParam(left, right, &typedata, ¶m); + if (sifSetFltParam(left, right, &typedata, ¶m) != 0) return -1; } ret = metaFilterTableIds(arg->metaEx, ¶m, output->result); } @@ -631,7 +793,7 @@ static FORCE_INLINE int32_t sifGetOperFn(int32_t funcId, sif_func_t *func, SIdxF } static int32_t sifExecOper(SOperatorNode *node, SIFCtx *ctx, SIFParam *output) { - int32_t code = 0; + int32_t code = -1; if (sifValidOp(node->opType) < 0) { code = TSDB_CODE_QRY_INVALID_INPUT; ctx->code = code; @@ -651,7 +813,7 @@ static int32_t sifExecOper(SOperatorNode *node, SIFCtx *ctx, SIFParam *output) { SIFParam *params = NULL; SIF_ERR_RET(sifInitOperParams(¶ms, node, ctx)); - if (params[0].status == SFLT_NOT_INDEX && (nParam > 1 && params[1].status == SFLT_NOT_INDEX)) { + if (params[0].status == SFLT_NOT_INDEX || (nParam > 1 && params[1].status == SFLT_NOT_INDEX)) { output->status = SFLT_NOT_INDEX; goto _return; } @@ -661,6 +823,7 @@ static int32_t sifExecOper(SOperatorNode *node, SIFCtx *ctx, SIFParam *output) { sif_func_t operFn = sifNullFunc; if (!ctx->noExec) { + code = 0; SIF_ERR_JRET(sifGetOperFn(node->opType, &operFn, &output->status)); SIF_ERR_JRET(operFn(¶ms[0], nParam > 1 ? ¶ms[1] : NULL, output)); } else { @@ -669,11 +832,17 @@ static int32_t sifExecOper(SOperatorNode *node, SIFCtx *ctx, SIFParam *output) { output->status = SFLT_NOT_INDEX; goto _return; } + code = 0; SIF_ERR_JRET(sifGetOperFn(node->opType, &operFn, &output->status)); } _return: for (int i = 0; i < nParam; i++) sifFreeParam(¶ms[i]); taosMemoryFree(params); + if (code != 0) { + output->status = SFLT_NOT_INDEX; + } else { + output->status = SFLT_COARSE_INDEX; + } return code; } @@ -714,7 +883,7 @@ _return: static EDealRes sifWalkFunction(SNode *pNode, void *context) { SFunctionNode *node = (SFunctionNode *)pNode; - SIFParam output = {.result = taosArrayInit(8, sizeof(uint64_t))}; + SIFParam output = {.result = taosArrayInit(8, sizeof(uint64_t)), .status = SFLT_COARSE_INDEX}; SIFCtx *ctx = context; ctx->code = sifExecFunction(node, ctx, &output); @@ -732,7 +901,7 @@ static EDealRes sifWalkFunction(SNode *pNode, void *context) { static EDealRes sifWalkLogic(SNode *pNode, void *context) { SLogicConditionNode *node = (SLogicConditionNode *)pNode; - SIFParam output = {.result = taosArrayInit(8, sizeof(uint64_t))}; + SIFParam output = {.result = taosArrayInit(8, sizeof(uint64_t)), .status = SFLT_COARSE_INDEX}; SIFCtx *ctx = context; ctx->code = sifExecLogic(node, ctx, &output); @@ -828,6 +997,7 @@ static int32_t sifCalculate(SNode *pNode, SIFParam *pDst) { if (res->result != NULL) { taosArrayAddAll(pDst->result, res->result); } + pDst->status = res->status; sifFreeParam(res); taosHashRemove(ctx.pRes, (void *)&pNode, POINTER_BYTES); @@ -884,16 +1054,20 @@ int32_t doFilterTag(SNode *pFilterNode, SIndexMetaArg *metaArg, SArray *result, SFilterInfo *filter = NULL; SArray *output = taosArrayInit(8, sizeof(uint64_t)); - SIFParam param = {.arg = *metaArg, .result = output}; + SIFParam param = {.arg = *metaArg, .result = output, .status = SFLT_NOT_INDEX}; int32_t code = sifCalculate((SNode *)pFilterNode, ¶m); if (code != 0) { sifFreeParam(¶m); return code; } + if (param.status == SFLT_NOT_INDEX) { + *status = param.status; + } else { + *status = st; + } taosArrayAddAll(result, param.result); sifFreeParam(¶m); - *status = st; return TSDB_CODE_SUCCESS; } diff --git a/source/libs/index/src/indexFstAutomation.c b/source/libs/index/src/indexFstAutomation.c index 385e832763228494af2b1562f915da14b6500a25..0c96d1aa0a9a62c351b1b7419b387a763daddfbc 100644 --- a/source/libs/index/src/indexFstAutomation.c +++ b/source/libs/index/src/indexFstAutomation.c @@ -164,7 +164,7 @@ FAutoCtx* automCtxCreate(void* data, AutomationType atype) { // add more search type } - ctx->data = (data != NULL ? strdup((char*)data) : NULL); + ctx->data = (data != NULL ? taosStrdup((char*)data) : NULL); ctx->type = atype; ctx->stdata = (void*)sv; return ctx; diff --git a/source/libs/index/src/indexFstDfa.c b/source/libs/index/src/indexFstDfa.c index 4d348e76f25eb9ec4575b536f2b5de73f1fabe6a..a3e26d8518cfa934eaa6e9163a92c1043cd8e841 100644 --- a/source/libs/index/src/indexFstDfa.c +++ b/source/libs/index/src/indexFstDfa.c @@ -188,7 +188,6 @@ void dfaAdd(FstDfa *dfa, FstSparseSet *set, uint32_t ip) { return; } bool succ = sparSetAdd(set, ip, NULL); - // assert(succ == true); Inst *inst = taosArrayGet(dfa->insts, ip); if (inst->ty == MATCH || inst->ty == RANGE) { // do nothing diff --git a/source/libs/index/src/indexFstFile.c b/source/libs/index/src/indexFstFile.c index 5a9c8dfe3d3906bd452111bf885e62b65638f6e5..9e7ed5210425520f7b7c02a7f9b2edc6d98756ed 100644 --- a/source/libs/index/src/indexFstFile.c +++ b/source/libs/index/src/indexFstFile.c @@ -18,6 +18,7 @@ #include "indexInt.h" #include "indexUtil.h" #include "os.h" +#include "osDef.h" #include "tutil.h" static int32_t kBlockSize = 4096; @@ -126,8 +127,6 @@ static int idxFileCtxDoReadFrom(IFileCtx* ctx, uint8_t* buf, int len, int32_t of blk->blockId = blkId; blk->nread = taosPReadFile(ctx->file.pFile, blk->buf, kBlockSize, blkId * kBlockSize); ASSERTS(blk->nread <= kBlockSize, "index read incomplete data"); - if (blk->nread > kBlockSize) break; - if (blk->nread < kBlockSize && blk->nread < len) { taosMemoryFree(blk); break; @@ -172,7 +171,8 @@ static FORCE_INLINE int idxFileCtxDoFlush(IFileCtx* ctx) { int32_t nw = taosWriteFile(ctx->file.pFile, ctx->file.wBuf, ctx->file.wBufOffset); ctx->file.wBufOffset = 0; } - taosFsyncFile(ctx->file.pFile); + int ret = taosFsyncFile(ctx->file.pFile); + UNUSED(ret); } else { // do nothing } @@ -180,11 +180,11 @@ static FORCE_INLINE int idxFileCtxDoFlush(IFileCtx* ctx) { } IFileCtx* idxFileCtxCreate(WriterType type, const char* path, bool readOnly, int32_t capacity) { + int code = 0; IFileCtx* ctx = taosMemoryCalloc(1, sizeof(IFileCtx)); if (ctx == NULL) { return NULL; } - ctx->type = type; if (ctx->type == TFILE) { // ugly code, refactor later @@ -192,15 +192,21 @@ IFileCtx* idxFileCtxCreate(WriterType type, const char* path, bool readOnly, int memcpy(ctx->file.buf, path, strlen(path)); if (readOnly == false) { ctx->file.pFile = taosOpenFile(path, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND); - taosFtruncateFile(ctx->file.pFile, 0); - taosStatFile(path, &ctx->file.size, NULL); + + code = taosFtruncateFile(ctx->file.pFile, 0); + UNUSED(code); + + code = taosStatFile(path, &ctx->file.size, NULL); + UNUSED(code); ctx->file.wBufOffset = 0; ctx->file.wBufCap = kBlockSize * 4; ctx->file.wBuf = taosMemoryCalloc(1, ctx->file.wBufCap); } else { ctx->file.pFile = taosOpenFile(path, TD_FILE_READ); - taosFStatFile(ctx->file.pFile, &ctx->file.size, NULL); + code = taosFStatFile(ctx->file.pFile, &ctx->file.size, NULL); + UNUSED(code); + ctx->file.wBufOffset = 0; #ifdef USE_MMAP diff --git a/source/libs/index/src/indexFstRegex.c b/source/libs/index/src/indexFstRegex.c index e148f211f23a6acbf9bd81eed2dff13761a7800a..8b513bfb2be3245c97fc9041d14f556c86145709 100644 --- a/source/libs/index/src/indexFstRegex.c +++ b/source/libs/index/src/indexFstRegex.c @@ -23,7 +23,7 @@ FstRegex *regexCreate(const char *str) { return NULL; } - regex->orig = tstrdup(str); + regex->orig = taosStrdup(str); // construct insts based on str SArray *insts = taosArrayInit(256, sizeof(uint8_t)); diff --git a/source/libs/index/src/indexTfile.c b/source/libs/index/src/indexTfile.c index d921ca7103c55d51421a10818b2b23964854869c..cdd1cc738693bf6dcc9c87b99b153370838a44be 100644 --- a/source/libs/index/src/indexTfile.c +++ b/source/libs/index/src/indexTfile.c @@ -804,7 +804,7 @@ TFileValue* tfileValueCreate(char* val) { if (tf == NULL) { return NULL; } - tf->colVal = tstrdup(val); + tf->colVal = taosStrdup(val); tf->tableId = taosArrayInit(32, sizeof(uint64_t)); return tf; } diff --git a/source/libs/index/test/fstTest.cc b/source/libs/index/test/fstTest.cc index 4e9a85330299fb3689969335eb96b613b3a40c36..b889a2209a76fe1ebff7f73cd81fa4b841c63fd9 100644 --- a/source/libs/index/test/fstTest.cc +++ b/source/libs/index/test/fstTest.cc @@ -599,7 +599,7 @@ void validateTFile(char* arg) { std::thread threads[NUM_OF_THREAD]; // std::vector threads; SIndex* index = (SIndex*)taosMemoryCalloc(1, sizeof(SIndex)); - index->path = strdup(arg); + index->path = taosStrdup(arg); TFileReader* reader = tfileReaderOpen(index, 0, 20000000, "tag1"); for (int i = 0; i < NUM_OF_THREAD; i++) { diff --git a/source/libs/monitor/src/monMain.c b/source/libs/monitor/src/monMain.c index b23a36d4df3acaef40116b2fd66559a661e3f8c1..949e91198adcb69301fbc177b721289d6d736651 100644 --- a/source/libs/monitor/src/monMain.c +++ b/source/libs/monitor/src/monMain.c @@ -210,6 +210,8 @@ static void monGenClusterJson(SMonInfo *pMonitor) { tjsonAddDoubleToObject(pJson, "vnodes_total", pInfo->vnodes_total); tjsonAddDoubleToObject(pJson, "vnodes_alive", pInfo->vnodes_alive); tjsonAddDoubleToObject(pJson, "connections_total", pInfo->connections_total); + tjsonAddDoubleToObject(pJson, "topics_total", pInfo->topics_toal); + tjsonAddDoubleToObject(pJson, "streams_total", pInfo->streams_total); SJson *pDnodesJson = tjsonAddArrayToObject(pJson, "dnodes"); if (pDnodesJson == NULL) return; diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index 2b1819d5c0d8cd27dc70e0adfe8e44192835608d..91db527a02a98ab7d34775ef74eb826b8265db4d 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -35,15 +35,15 @@ memcpy(&((pDst)->fldname), &((pSrc)->fldname), size); \ } while (0) -#define COPY_CHAR_POINT_FIELD(fldname) \ - do { \ - if (NULL == (pSrc)->fldname) { \ - break; \ - } \ - (pDst)->fldname = strdup((pSrc)->fldname); \ - if (NULL == (pDst)->fldname) { \ - return TSDB_CODE_OUT_OF_MEMORY; \ - } \ +#define COPY_CHAR_POINT_FIELD(fldname) \ + do { \ + if (NULL == (pSrc)->fldname) { \ + break; \ + } \ + (pDst)->fldname = taosStrdup((pSrc)->fldname); \ + if (NULL == (pDst)->fldname) { \ + return TSDB_CODE_OUT_OF_MEMORY; \ + } \ } while (0) #define CLONE_NODE_FIELD(fldname) \ @@ -158,7 +158,7 @@ static int32_t valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) { case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: { - int32_t len = varDataTLen(pSrc->datum.p) + 1; + int32_t len = pSrc->node.resType.bytes + 1; pDst->datum.p = taosMemoryCalloc(1, len); if (NULL == pDst->datum.p) { return TSDB_CODE_OUT_OF_MEMORY; @@ -295,6 +295,13 @@ static int32_t stateWindowNodeCopy(const SStateWindowNode* pSrc, SStateWindowNod return TSDB_CODE_SUCCESS; } +static int32_t eventWindowNodeCopy(const SEventWindowNode* pSrc, SEventWindowNode* pDst) { + CLONE_NODE_FIELD(pCol); + CLONE_NODE_FIELD(pStartCond); + CLONE_NODE_FIELD(pEndCond); + return TSDB_CODE_SUCCESS; +} + static int32_t sessionWindowNodeCopy(const SSessionWindowNode* pSrc, SSessionWindowNode* pDst) { CLONE_NODE_FIELD_EX(pCol, SColumnNode*); CLONE_NODE_FIELD_EX(pGap, SValueNode*); @@ -394,6 +401,7 @@ static int32_t logicJoinCopy(const SJoinLogicNode* pSrc, SJoinLogicNode* pDst) { COPY_SCALAR_FIELD(joinType); CLONE_NODE_FIELD(pMergeCondition); CLONE_NODE_FIELD(pOnConditions); + CLONE_NODE_FIELD(pTagEqualConditions); COPY_SCALAR_FIELD(isSingleTableJoin); COPY_SCALAR_FIELD(inputTsOrder); return TSDB_CODE_SUCCESS; @@ -464,6 +472,8 @@ static int32_t logicWindowCopy(const SWindowLogicNode* pSrc, SWindowLogicNode* p CLONE_NODE_FIELD(pTspk); CLONE_NODE_FIELD(pTsEnd); CLONE_NODE_FIELD(pStateExpr); + CLONE_NODE_FIELD(pStartCond); + CLONE_NODE_FIELD(pEndCond); COPY_SCALAR_FIELD(triggerType); COPY_SCALAR_FIELD(watermark); COPY_SCALAR_FIELD(deleteMark); @@ -712,6 +722,9 @@ SNode* nodesCloneNode(const SNode* pNode) { case QUERY_NODE_STATE_WINDOW: code = stateWindowNodeCopy((const SStateWindowNode*)pNode, (SStateWindowNode*)pDst); break; + case QUERY_NODE_EVENT_WINDOW: + code = eventWindowNodeCopy((const SEventWindowNode*)pNode, (SEventWindowNode*)pDst); + break; case QUERY_NODE_SESSION_WINDOW: code = sessionWindowNodeCopy((const SSessionWindowNode*)pNode, (SSessionWindowNode*)pDst); break; diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index c19f64bb3a0051afc72d8e821c2c0962b363148d..b4e2d95e2629386bd82ca51d63f9d6488eb1bac0 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -79,17 +79,23 @@ const char* nodesNodeName(ENodeType type) { return "TableOptions"; case QUERY_NODE_INDEX_OPTIONS: return "IndexOptions"; + case QUERY_NODE_EXPLAIN_OPTIONS: + return "ExplainOptions"; + case QUERY_NODE_STREAM_OPTIONS: + return "StreamOptions"; case QUERY_NODE_LEFT_VALUE: return "LeftValue"; case QUERY_NODE_WHEN_THEN: return "WhenThen"; case QUERY_NODE_CASE_WHEN: return "CaseWhen"; + case QUERY_NODE_EVENT_WINDOW: + return "EventWindow"; case QUERY_NODE_SET_OPERATOR: return "SetOperator"; case QUERY_NODE_SELECT_STMT: return "SelectStmt"; - case QUERY_NODE_VNODE_MODIF_STMT: + case QUERY_NODE_VNODE_MODIFY_STMT: return "VnodeModifStmt"; case QUERY_NODE_CREATE_DATABASE_STMT: return "CreateDatabaseStmt"; @@ -97,11 +103,15 @@ const char* nodesNodeName(ENodeType type) { return "DropDatabaseStmt"; case QUERY_NODE_ALTER_DATABASE_STMT: return "AlterDatabaseStmt"; + case QUERY_NODE_FLUSH_DATABASE_STMT: + return "FlushDatabaseStmt"; + case QUERY_NODE_TRIM_DATABASE_STMT: + return "TrimDatabaseStmt"; case QUERY_NODE_CREATE_TABLE_STMT: return "CreateTableStmt"; case QUERY_NODE_CREATE_SUBTABLE_CLAUSE: return "CreateSubtableClause"; - case QUERY_NODE_CREATE_MULTI_TABLE_STMT: + case QUERY_NODE_CREATE_MULTI_TABLES_STMT: return "CreateMultiTableStmt"; case QUERY_NODE_DROP_TABLE_CLAUSE: return "DropTableClause"; @@ -135,12 +145,50 @@ const char* nodesNodeName(ENodeType type) { return "CreateQnodeStmt"; case QUERY_NODE_DROP_QNODE_STMT: return "DropQnodeStmt"; + case QUERY_NODE_CREATE_SNODE_STMT: + return "CreateSnodeStmt"; + case QUERY_NODE_DROP_SNODE_STMT: + return "DropSnodeStmt"; + case QUERY_NODE_CREATE_MNODE_STMT: + return "CreateMnodeStmt"; + case QUERY_NODE_DROP_MNODE_STMT: + return "DropMnodeStmt"; case QUERY_NODE_CREATE_TOPIC_STMT: return "CreateTopicStmt"; case QUERY_NODE_DROP_TOPIC_STMT: return "DropTopicStmt"; + case QUERY_NODE_DROP_CGROUP_STMT: + return "DropConsumerGroupStmt"; case QUERY_NODE_ALTER_LOCAL_STMT: return "AlterLocalStmt"; + case QUERY_NODE_EXPLAIN_STMT: + return "ExplainStmt"; + case QUERY_NODE_DESCRIBE_STMT: + return "DescribeStmt"; + case QUERY_NODE_COMPACT_DATABASE_STMT: + return "CompactDatabaseStmt"; + case QUERY_NODE_CREATE_STREAM_STMT: + return "CreateStreamStmt"; + case QUERY_NODE_DROP_STREAM_STMT: + return "DropStreamStmt"; + case QUERY_NODE_BALANCE_VGROUP_STMT: + return "BalanceVgroupStmt"; + case QUERY_NODE_BALANCE_VGROUP_LEADER_STMT: + return "BalanceVgroupLeaderStmt"; + case QUERY_NODE_MERGE_VGROUP_STMT: + return "MergeVgroupStmt"; + case QUERY_NODE_SHOW_DB_ALIVE_STMT: + return "ShowDbAliveStmt"; + case QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT: + return "ShowClusterAliveStmt"; + case QUERY_NODE_REDISTRIBUTE_VGROUP_STMT: + return "RedistributeVgroupStmt"; + case QUERY_NODE_SPLIT_VGROUP_STMT: + return "SplitVgroupStmt"; + case QUERY_NODE_GRANT_STMT: + return "GrantStmt"; + case QUERY_NODE_REVOKE_STMT: + return "RevokeStmt"; case QUERY_NODE_SHOW_DNODES_STMT: return "ShowDnodesStmt"; case QUERY_NODE_SHOW_MNODES_STMT: @@ -153,6 +201,8 @@ const char* nodesNodeName(ENodeType type) { return "ShowSnodesStmt"; case QUERY_NODE_SHOW_BNODES_STMT: return "ShowBnodesStmt"; + case QUERY_NODE_SHOW_CLUSTER_STMT: + return "ShowClusterStmt"; case QUERY_NODE_SHOW_DATABASES_STMT: return "ShowDatabaseStmt"; case QUERY_NODE_SHOW_FUNCTIONS_STMT: @@ -179,8 +229,30 @@ const char* nodesNodeName(ENodeType type) { return "ShowConsumersStmt"; case QUERY_NODE_SHOW_QUERIES_STMT: return "ShowQueriesStmt"; + case QUERY_NODE_SHOW_VARIABLES_STMT: + return "ShowVariablesStmt"; + case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT: + return "ShowDnodeVariablesStmt"; + case QUERY_NODE_SHOW_TRANSACTIONS_STMT: + return "ShowTransactionsStmt"; + case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT: + return "ShowSubscriptionsStmt"; case QUERY_NODE_SHOW_VNODES_STMT: return "ShowVnodeStmt"; + case QUERY_NODE_SHOW_USER_PRIVILEGES_STMT: + return "ShowUserPrivilegesStmt"; + case QUERY_NODE_SHOW_CREATE_DATABASE_STMT: + return "ShowCreateDatabasesStmt"; + case QUERY_NODE_SHOW_CREATE_TABLE_STMT: + return "ShowCreateTablesStmt"; + case QUERY_NODE_SHOW_CREATE_STABLE_STMT: + return "ShowCreateStablesStmt"; + case QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT: + return "ShowTableDistributedStmt"; + case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT: + return "ShowLocalVariablesStmt"; + case QUERY_NODE_SHOW_TABLE_TAGS_STMT: + return "ShowTableTagsStmt"; case QUERY_NODE_DELETE_STMT: return "DeleteStmt"; case QUERY_NODE_INSERT_STMT: @@ -233,6 +305,10 @@ const char* nodesNodeName(ENodeType type) { return "PhysiLastRowScan"; case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN: return "PhysiTableCountScan"; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT: + return "PhysiMergeEventWindow"; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT: + return "PhysiStreamEventWindow"; case QUERY_NODE_PHYSICAL_PLAN_PROJECT: return "PhysiProject"; case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN: @@ -1340,6 +1416,7 @@ static int32_t jsonToLogicPlan(const SJson* pJson, void* pObj) { static const char* jkJoinLogicPlanJoinType = "JoinType"; static const char* jkJoinLogicPlanOnConditions = "OnConditions"; static const char* jkJoinLogicPlanMergeCondition = "MergeConditions"; +static const char* jkJoinLogicPlanTagEqualConditions = "TagEqualConditions"; static int32_t logicJoinNodeToJson(const void* pObj, SJson* pJson) { const SJoinLogicNode* pNode = (const SJoinLogicNode*)pObj; @@ -1354,7 +1431,28 @@ static int32_t logicJoinNodeToJson(const void* pObj, SJson* pJson) { if (TSDB_CODE_SUCCESS == code) { code = tjsonAddObject(pJson, jkJoinLogicPlanOnConditions, nodeToJson, pNode->pOnConditions); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkJoinLogicPlanTagEqualConditions, nodeToJson, pNode->pTagEqualConditions); + } + return code; +} +static int32_t jsonToLogicJoinNode(const SJson* pJson, void* pObj) { + SJoinLogicNode* pNode = (SJoinLogicNode*)pObj; + + int32_t code = jsonToLogicPlanNode(pJson, pObj); + if (TSDB_CODE_SUCCESS == code) { + tjsonGetNumberValue(pJson, jkJoinLogicPlanJoinType, pNode->joinType, code); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkJoinLogicPlanMergeCondition, &pNode->pMergeCondition); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkJoinLogicPlanOnConditions, &pNode->pOnConditions); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkJoinLogicPlanTagEqualConditions, &pNode->pTagEqualConditions); + } return code; } @@ -1785,6 +1883,7 @@ static const char* jkJoinPhysiPlanInputTsOrder = "InputTsOrder"; static const char* jkJoinPhysiPlanMergeCondition = "MergeCondition"; static const char* jkJoinPhysiPlanOnConditions = "OnConditions"; static const char* jkJoinPhysiPlanTargets = "Targets"; +static const char* jkJoinPhysiPlanTagEqualConditions = "TagEqualConditions"; static int32_t physiJoinNodeToJson(const void* pObj, SJson* pJson) { const SSortMergeJoinPhysiNode* pNode = (const SSortMergeJoinPhysiNode*)pObj; @@ -1805,7 +1904,9 @@ static int32_t physiJoinNodeToJson(const void* pObj, SJson* pJson) { if (TSDB_CODE_SUCCESS == code) { code = nodeListToJson(pJson, jkJoinPhysiPlanTargets, pNode->pTargets); } - + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkJoinPhysiPlanTagEqualConditions, nodeToJson, pNode->pTagEqualCondtions); + } return code; } @@ -1828,7 +1929,9 @@ static int32_t jsonToPhysiJoinNode(const SJson* pJson, void* pObj) { if (TSDB_CODE_SUCCESS == code) { code = jsonToNodeList(pJson, jkJoinPhysiPlanTargets, &pNode->pTargets); } - + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkJoinPhysiPlanTagEqualConditions, &pNode->pTagEqualCondtions); + } return code; } @@ -2286,6 +2389,37 @@ static int32_t jsonToPhysiStateWindowNode(const SJson* pJson, void* pObj) { return code; } +static const char* jkEventWindowPhysiPlanStartCond = "StartCond"; +static const char* jkEventWindowPhysiPlanEndCond = "EndCond"; + +static int32_t physiEventWindowNodeToJson(const void* pObj, SJson* pJson) { + const SEventWinodwPhysiNode* pNode = (const SEventWinodwPhysiNode*)pObj; + + int32_t code = physiWindowNodeToJson(pObj, pJson); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkEventWindowPhysiPlanStartCond, nodeToJson, pNode->pStartCond); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkEventWindowPhysiPlanEndCond, nodeToJson, pNode->pEndCond); + } + + return code; +} + +static int32_t jsonToPhysiEventWindowNode(const SJson* pJson, void* pObj) { + SEventWinodwPhysiNode* pNode = (SEventWinodwPhysiNode*)pObj; + + int32_t code = jsonToPhysiWindowNode(pJson, pObj); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkEventWindowPhysiPlanStartCond, &pNode->pStartCond); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkEventWindowPhysiPlanEndCond, &pNode->pEndCond); + } + + return code; +} + static const char* jkPartitionPhysiPlanExprs = "Exprs"; static const char* jkPartitionPhysiPlanPartitionKeys = "PartitionKeys"; static const char* jkPartitionPhysiPlanTargets = "Targets"; @@ -2482,6 +2616,7 @@ static const char* jkQueryInsertPhysiPlanTableType = "TableType"; static const char* jkQueryInsertPhysiPlanTableFName = "TableFName"; static const char* jkQueryInsertPhysiPlanVgId = "VgId"; static const char* jkQueryInsertPhysiPlanEpSet = "EpSet"; +static const char* jkQueryInsertPhysiPlanExplain = "Explain"; static int32_t physiQueryInsertNodeToJson(const void* pObj, SJson* pJson) { const SQueryInserterNode* pNode = (const SQueryInserterNode*)pObj; @@ -2508,6 +2643,9 @@ static int32_t physiQueryInsertNodeToJson(const void* pObj, SJson* pJson) { if (TSDB_CODE_SUCCESS == code) { code = tjsonAddObject(pJson, jkQueryInsertPhysiPlanEpSet, epSetToJson, &pNode->epSet); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkQueryInsertPhysiPlanExplain, pNode->explain); + } return code; } @@ -2537,6 +2675,9 @@ static int32_t jsonToPhysiQueryInsertNode(const SJson* pJson, void* pObj) { if (TSDB_CODE_SUCCESS == code) { code = tjsonToObject(pJson, jkQueryInsertPhysiPlanEpSet, jsonToEpSet, &pNode->epSet); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkQueryInsertPhysiPlanExplain, &pNode->explain); + } return code; } @@ -3140,7 +3281,7 @@ static int32_t jsonToDatum(const SJson* pJson, void* pObj) { case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: { - pNode->datum.p = taosMemoryCalloc(1, pNode->node.resType.bytes + VARSTR_HEADER_SIZE + 1); + pNode->datum.p = taosMemoryCalloc(1, pNode->node.resType.bytes + 1); if (NULL == pNode->datum.p) { code = TSDB_CODE_OUT_OF_MEMORY; break; @@ -3546,6 +3687,51 @@ static int32_t jsonToTempTableNode(const SJson* pJson, void* pObj) { return code; } +static const char* jkJoinTableJoinType = "JoinType"; +static const char* jkJoinTableLeft = "Left"; +static const char* jkJoinTableRight = "Right"; +static const char* jkJoinTableOnCond = "OnCond"; + +static int32_t joinTableNodeToJson(const void* pObj, SJson* pJson) { + const SJoinTableNode* pNode = (const SJoinTableNode*)pObj; + + int32_t code = tableNodeToJson(pObj, pJson); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkJoinTableJoinType, pNode->joinType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkJoinTableLeft, nodeToJson, pNode->pLeft); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkJoinTableRight, nodeToJson, pNode->pRight); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkJoinTableOnCond, nodeToJson, pNode->pOnCond); + } + + return code; +} + +static int32_t jsonToJoinTableNode(const SJson* pJson, void* pObj) { + SJoinTableNode* pNode = (SJoinTableNode*)pObj; + + int32_t code = jsonToTableNode(pJson, pObj); + if (TSDB_CODE_SUCCESS == code) { + tjsonGetNumberValue(pJson, jkJoinTableJoinType, pNode->joinType, code); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkJoinTableLeft, &pNode->pLeft); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkJoinTableRight, &pNode->pRight); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkJoinTableOnCond, &pNode->pOnCond); + } + + return code; +} + static const char* jkGroupingSetType = "GroupingSetType"; static const char* jkGroupingSetParameter = "Parameters"; @@ -3674,6 +3860,36 @@ static int32_t jsonToSessionWindowNode(const SJson* pJson, void* pObj) { return code; } +static const char* jkEventWindowTsPrimaryKey = "TsPrimaryKey"; +static const char* jkEventWindowStartCond = "StartCond"; +static const char* jkEventWindowEndCond = "EndCond"; + +static int32_t eventWindowNodeToJson(const void* pObj, SJson* pJson) { + const SEventWindowNode* pNode = (const SEventWindowNode*)pObj; + + int32_t code = tjsonAddObject(pJson, jkEventWindowTsPrimaryKey, nodeToJson, pNode->pCol); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkEventWindowStartCond, nodeToJson, pNode->pStartCond); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkEventWindowEndCond, nodeToJson, pNode->pEndCond); + } + return code; +} + +static int32_t jsonToEventWindowNode(const SJson* pJson, void* pObj) { + SEventWindowNode* pNode = (SEventWindowNode*)pObj; + + int32_t code = jsonToNodeObject(pJson, jkEventWindowTsPrimaryKey, &pNode->pCol); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkEventWindowStartCond, &pNode->pStartCond); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkEventWindowEndCond, &pNode->pEndCond); + } + return code; +} + static const char* jkIntervalWindowInterval = "Interval"; static const char* jkIntervalWindowOffset = "Offset"; static const char* jkIntervalWindowSliding = "Sliding"; @@ -3870,6 +4086,45 @@ static int32_t jsonToSlotDescNode(const SJson* pJson, void* pObj) { return code; } +static const char* jkColumnDefColName = "ColName"; +static const char* jkColumnDefDataType = "DataType"; +static const char* jkColumnDefComments = "Comments"; +static const char* jkColumnDefSma = "Sma"; + +static int32_t columnDefNodeToJson(const void* pObj, SJson* pJson) { + const SColumnDefNode* pNode = (const SColumnDefNode*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkColumnDefColName, pNode->colName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkColumnDefDataType, dataTypeToJson, &pNode->dataType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkColumnDefComments, pNode->comments); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkColumnDefSma, pNode->sma); + } + + return code; +} + +static int32_t jsonToColumnDefNode(const SJson* pJson, void* pObj) { + SColumnDefNode* pNode = (SColumnDefNode*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkColumnDefColName, pNode->colName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonToObject(pJson, jkColumnDefDataType, jsonToDataType, &pNode->dataType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkColumnDefComments, pNode->comments); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkColumnDefSma, &pNode->sma); + } + + return code; +} + static const char* jkDownstreamSourceAddr = "Addr"; static const char* jkDownstreamSourceTaskId = "TaskId"; static const char* jkDownstreamSourceSchedId = "SchedId"; @@ -4060,6 +4315,190 @@ static int32_t jsonToDatabaseOptions(const SJson* pJson, void* pObj) { return code; } +static const char* jkTableOptionsComment = "Comment"; +static const char* jkTableOptionsMaxDelay = "MaxDelay"; +static const char* jkTableOptionsWatermark = "Watermark"; +static const char* jkTableOptionsDeleteMark = "DeleteMark"; +static const char* jkTableOptionsRollupFuncs = "RollupFuncs"; +static const char* jkTableOptionsTtl = "Ttl"; +static const char* jkTableOptionsSma = "Sma"; + +static int32_t tableOptionsToJson(const void* pObj, SJson* pJson) { + const STableOptions* pNode = (const STableOptions*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkTableOptionsComment, pNode->comment); + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkTableOptionsMaxDelay, pNode->pMaxDelay); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkTableOptionsWatermark, pNode->pWatermark); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkTableOptionsDeleteMark, pNode->pDeleteMark); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkTableOptionsRollupFuncs, pNode->pRollupFuncs); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkTableOptionsTtl, pNode->ttl); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkTableOptionsSma, pNode->pSma); + } + + return code; +} + +static int32_t jsonToTableOptions(const SJson* pJson, void* pObj) { + STableOptions* pNode = (STableOptions*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkTableOptionsComment, pNode->comment); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkTableOptionsMaxDelay, &pNode->pMaxDelay); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkTableOptionsWatermark, &pNode->pWatermark); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkTableOptionsDeleteMark, &pNode->pDeleteMark); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkTableOptionsRollupFuncs, &pNode->pRollupFuncs); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkTableOptionsTtl, &pNode->ttl); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkTableOptionsSma, &pNode->pSma); + } + + return code; +} + +static const char* jkIndexOptionsFuncs = "Funcs"; +static const char* jkIndexOptionsInterval = "Interval"; +static const char* jkIndexOptionsOffset = "Offset"; +static const char* jkIndexOptionsSliding = "Sliding"; +static const char* jkIndexOptionsStreamOptions = "StreamOptions"; + +static int32_t indexOptionsToJson(const void* pObj, SJson* pJson) { + const SIndexOptions* pNode = (const SIndexOptions*)pObj; + + int32_t code = nodeListToJson(pJson, jkIndexOptionsFuncs, pNode->pFuncs); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkIndexOptionsInterval, nodeToJson, pNode->pInterval); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkIndexOptionsOffset, nodeToJson, pNode->pOffset); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkIndexOptionsSliding, nodeToJson, pNode->pSliding); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkIndexOptionsStreamOptions, nodeToJson, pNode->pStreamOptions); + } + + return code; +} + +static int32_t jsonToIndexOptions(const SJson* pJson, void* pObj) { + SIndexOptions* pNode = (SIndexOptions*)pObj; + + int32_t code = jsonToNodeList(pJson, jkIndexOptionsFuncs, &pNode->pFuncs); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkIndexOptionsInterval, &pNode->pInterval); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkIndexOptionsOffset, &pNode->pOffset); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkIndexOptionsSliding, &pNode->pSliding); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkIndexOptionsStreamOptions, &pNode->pStreamOptions); + } + + return code; +} + +static const char* jkExplainOptionsVerbose = "Verbose"; +static const char* jkExplainOptionsRatio = "Ratio"; + +static int32_t explainOptionsToJson(const void* pObj, SJson* pJson) { + const SExplainOptions* pNode = (const SExplainOptions*)pObj; + + int32_t code = tjsonAddBoolToObject(pJson, jkExplainOptionsVerbose, pNode->verbose); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddDoubleToObject(pJson, jkExplainOptionsRatio, pNode->ratio); + } + + return code; +} + +static int32_t jsonToExplainOptions(const SJson* pJson, void* pObj) { + SExplainOptions* pNode = (SExplainOptions*)pObj; + + int32_t code = tjsonGetBoolValue(pJson, jkExplainOptionsVerbose, &pNode->verbose); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetDoubleValue(pJson, jkExplainOptionsRatio, &pNode->ratio); + } + + return code; +} + +static const char* jkStreamOptionsTriggerType = "TriggerType"; +static const char* jkStreamOptionsDelay = "Delay"; +static const char* jkStreamOptionsWatermark = "Watermark"; +static const char* jkStreamOptionsDeleteMark = "DeleteMark"; +static const char* jkStreamOptionsFillHistory = "FillHistory"; +static const char* jkStreamOptionsIgnoreExpired = "IgnoreExpired"; + +static int32_t streamOptionsToJson(const void* pObj, SJson* pJson) { + const SStreamOptions* pNode = (const SStreamOptions*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkStreamOptionsTriggerType, pNode->triggerType); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkStreamOptionsDelay, nodeToJson, pNode->pDelay); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkStreamOptionsWatermark, nodeToJson, pNode->pWatermark); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkStreamOptionsDeleteMark, nodeToJson, pNode->pDeleteMark); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkStreamOptionsFillHistory, pNode->fillHistory); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkStreamOptionsIgnoreExpired, pNode->ignoreExpired); + } + + return code; +} + +static int32_t jsonToStreamOptions(const SJson* pJson, void* pObj) { + SStreamOptions* pNode = (SStreamOptions*)pObj; + + int32_t code = tjsonGetTinyIntValue(pJson, jkStreamOptionsTriggerType, &pNode->triggerType); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkStreamOptionsDelay, &pNode->pDelay); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkStreamOptionsWatermark, &pNode->pWatermark); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkStreamOptionsDeleteMark, &pNode->pDeleteMark); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetTinyIntValue(pJson, jkStreamOptionsFillHistory, &pNode->fillHistory); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetTinyIntValue(pJson, jkStreamOptionsIgnoreExpired, &pNode->ignoreExpired); + } + + return code; +} + static const char* jkWhenThenWhen = "When"; static const char* jkWhenThenThen = "Then"; @@ -4345,164 +4784,1414 @@ static int32_t jsonToSelectStmt(const SJson* pJson, void* pObj) { return code; } -static const char* jkAlterDatabaseStmtDbName = "DbName"; -static const char* jkAlterDatabaseStmtOptions = "Options"; +static const char* jkVnodeModifyOpStmtSqlNodeType = "SqlNodeType"; +static const char* jkVnodeModifyOpStmtTotalRowsNum = "TotalRowsNum"; +static const char* jkVnodeModifyOpStmtTotalTbNum = "TotalTbNum"; -static int32_t alterDatabaseStmtToJson(const void* pObj, SJson* pJson) { - const SAlterDatabaseStmt* pNode = (const SAlterDatabaseStmt*)pObj; +static int32_t vnodeModifyStmtToJson(const void* pObj, SJson* pJson) { + const SVnodeModifyOpStmt* pNode = (const SVnodeModifyOpStmt*)pObj; - int32_t code = tjsonAddStringToObject(pJson, jkAlterDatabaseStmtDbName, pNode->dbName); + int32_t code = tjsonAddIntegerToObject(pJson, jkVnodeModifyOpStmtSqlNodeType, pNode->sqlNodeType); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddObject(pJson, jkAlterDatabaseStmtOptions, nodeToJson, pNode->pOptions); + code = tjsonAddIntegerToObject(pJson, jkVnodeModifyOpStmtTotalRowsNum, pNode->totalRowsNum); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkVnodeModifyOpStmtTotalTbNum, pNode->totalTbNum); } return code; } -static int32_t jsonToAlterDatabaseStmt(const SJson* pJson, void* pObj) { - SAlterDatabaseStmt* pNode = (SAlterDatabaseStmt*)pObj; +static int32_t jsonToVnodeModifyStmt(const SJson* pJson, void* pObj) { + SVnodeModifyOpStmt* pNode = (SVnodeModifyOpStmt*)pObj; - int32_t code = tjsonGetStringValue(pJson, jkAlterDatabaseStmtDbName, pNode->dbName); + int32_t code = TSDB_CODE_SUCCESS; + tjsonGetNumberValue(pJson, jkVnodeModifyOpStmtSqlNodeType, pNode->sqlNodeType, code); if (TSDB_CODE_SUCCESS == code) { - code = jsonToNodeObject(pJson, jkAlterDatabaseStmtOptions, (SNode**)&pNode->pOptions); + code = tjsonGetIntValue(pJson, jkVnodeModifyOpStmtTotalRowsNum, &pNode->totalRowsNum); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkVnodeModifyOpStmtTotalTbNum, &pNode->totalTbNum); } return code; } -static const char* jkAlterTableStmtDbName = "DbName"; -static const char* jkAlterTableStmtTableName = "TableName"; -static const char* jkAlterTableStmtAlterType = "AlterType"; -static const char* jkAlterTableStmtColName = "ColName"; -static const char* jkAlterTableStmtNewColName = "NewColName"; -static const char* jkAlterTableStmtOptions = "Options"; -static const char* jkAlterTableStmtNewDataType = "NewDataType"; -static const char* jkAlterTableStmtNewTagVal = "NewTagVal"; +static const char* jkCreateDatabaseStmtDbName = "DbName"; +static const char* jkCreateDatabaseStmtIgnoreExists = "IgnoreExists"; +static const char* jkCreateDatabaseStmtOptions = "Options"; -static int32_t alterTableStmtToJson(const void* pObj, SJson* pJson) { - const SAlterTableStmt* pNode = (const SAlterTableStmt*)pObj; +static int32_t createDatabaseStmtToJson(const void* pObj, SJson* pJson) { + const SCreateDatabaseStmt* pNode = (const SCreateDatabaseStmt*)pObj; - int32_t code = tjsonAddStringToObject(pJson, jkAlterTableStmtDbName, pNode->dbName); + int32_t code = tjsonAddStringToObject(pJson, jkCreateDatabaseStmtDbName, pNode->dbName); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddStringToObject(pJson, jkAlterTableStmtTableName, pNode->tableName); + code = tjsonAddBoolToObject(pJson, jkCreateDatabaseStmtIgnoreExists, pNode->ignoreExists); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddIntegerToObject(pJson, jkAlterTableStmtAlterType, pNode->alterType); + code = tjsonAddObject(pJson, jkCreateDatabaseStmtOptions, nodeToJson, pNode->pOptions); } + + return code; +} + +static int32_t jsonToCreateDatabaseStmt(const SJson* pJson, void* pObj) { + SCreateDatabaseStmt* pNode = (SCreateDatabaseStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkCreateDatabaseStmtDbName, pNode->dbName); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddStringToObject(pJson, jkAlterTableStmtColName, pNode->colName); + code = tjsonGetBoolValue(pJson, jkCreateDatabaseStmtIgnoreExists, &pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkCreateDatabaseStmtOptions, (SNode**)&pNode->pOptions); + } + + return code; +} + +static const char* jkAlterDatabaseStmtDbName = "DbName"; +static const char* jkAlterDatabaseStmtOptions = "Options"; + +static int32_t alterDatabaseStmtToJson(const void* pObj, SJson* pJson) { + const SAlterDatabaseStmt* pNode = (const SAlterDatabaseStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkAlterDatabaseStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkAlterDatabaseStmtOptions, nodeToJson, pNode->pOptions); + } + + return code; +} + +static int32_t jsonToAlterDatabaseStmt(const SJson* pJson, void* pObj) { + SAlterDatabaseStmt* pNode = (SAlterDatabaseStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkAlterDatabaseStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkAlterDatabaseStmtOptions, (SNode**)&pNode->pOptions); + } + + return code; +} + +static const char* jkTrimDatabaseStmtDbName = "DbName"; +static const char* jkTrimDatabaseStmtMaxSpeed = "MaxSpeed"; + +static int32_t trimDatabaseStmtToJson(const void* pObj, SJson* pJson) { + const STrimDatabaseStmt* pNode = (const STrimDatabaseStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkTrimDatabaseStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkTrimDatabaseStmtMaxSpeed, pNode->maxSpeed); + } + + return code; +} + +static int32_t jsonToTrimDatabaseStmt(const SJson* pJson, void* pObj) { + STrimDatabaseStmt* pNode = (STrimDatabaseStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkTrimDatabaseStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkTrimDatabaseStmtMaxSpeed, &pNode->maxSpeed); + } + + return code; +} + +static const char* jkCreateTableStmtDbName = "DbName"; +static const char* jkCreateTableStmtTableName = "TableName"; +static const char* jkCreateTableStmtIgnoreExists = "IgnoreExists"; +static const char* jkCreateTableStmtCols = "Cols"; +static const char* jkCreateTableStmtTags = "Tags"; +static const char* jkCreateTableStmtOptions = "Options"; + +static int32_t createTableStmtToJson(const void* pObj, SJson* pJson) { + const SCreateTableStmt* pNode = (const SCreateTableStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkCreateTableStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateTableStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkCreateTableStmtIgnoreExists, pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkCreateTableStmtCols, pNode->pCols); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkCreateTableStmtTags, pNode->pTags); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkCreateTableStmtOptions, nodeToJson, pNode->pOptions); + } + + return code; +} + +static int32_t jsonToCreateTableStmt(const SJson* pJson, void* pObj) { + SCreateTableStmt* pNode = (SCreateTableStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkCreateTableStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateTableStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkCreateTableStmtIgnoreExists, &pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkCreateTableStmtCols, &pNode->pCols); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkCreateTableStmtTags, &pNode->pTags); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkCreateTableStmtOptions, (SNode**)&pNode->pOptions); + } + + return code; +} + +static const char* jkCreateSubTableClauseDbName = "DbName"; +static const char* jkCreateSubTableClauseTableName = "TableName"; +static const char* jkCreateSubTableClauseUseDbName = "UseDbName"; +static const char* jkCreateSubTableClauseUseTableName = "UseTableName"; +static const char* jkCreateSubTableClauseIgnoreExists = "IgnoreExists"; +static const char* jkCreateSubTableClauseSpecificTags = "SpecificTags"; +static const char* jkCreateSubTableClauseValsOfTags = "ValsOfTags"; +static const char* jkCreateSubTableClauseOptions = "Options"; + +static int32_t createSubTableClauseToJson(const void* pObj, SJson* pJson) { + const SCreateSubTableClause* pNode = (const SCreateSubTableClause*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkCreateSubTableClauseDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateSubTableClauseTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateSubTableClauseUseDbName, pNode->useDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateSubTableClauseUseTableName, pNode->useTableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkCreateSubTableClauseIgnoreExists, pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkCreateSubTableClauseSpecificTags, pNode->pSpecificTags); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkCreateSubTableClauseValsOfTags, pNode->pValsOfTags); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkCreateSubTableClauseOptions, nodeToJson, pNode->pOptions); + } + + return code; +} + +static int32_t jsonToCreateSubTableClause(const SJson* pJson, void* pObj) { + SCreateSubTableClause* pNode = (SCreateSubTableClause*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkCreateSubTableClauseDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateSubTableClauseTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateSubTableClauseUseDbName, pNode->useDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateSubTableClauseUseTableName, pNode->useTableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkCreateSubTableClauseIgnoreExists, &pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkCreateSubTableClauseSpecificTags, &pNode->pSpecificTags); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkCreateSubTableClauseValsOfTags, &pNode->pValsOfTags); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkCreateSubTableClauseOptions, (SNode**)&pNode->pOptions); + } + + return code; +} + +static const char* jkCreateMultiTablesStmtSubTables = "SubTables"; + +static int32_t createMultiTablesStmtToJson(const void* pObj, SJson* pJson) { + const SCreateMultiTablesStmt* pNode = (const SCreateMultiTablesStmt*)pObj; + return nodeListToJson(pJson, jkCreateMultiTablesStmtSubTables, pNode->pSubTables); +} + +static int32_t jsonToCreateMultiTablesStmt(const SJson* pJson, void* pObj) { + SCreateMultiTablesStmt* pNode = (SCreateMultiTablesStmt*)pObj; + return jsonToNodeList(pJson, jkCreateMultiTablesStmtSubTables, &pNode->pSubTables); +} + +static const char* jkDropTableClauseDbName = "DbName"; +static const char* jkDropTableClauseTableName = "TableName"; +static const char* jkDropTableClauseIgnoreNotExists = "IgnoreNotExists"; + +static int32_t dropTableClauseToJson(const void* pObj, SJson* pJson) { + const SDropTableClause* pNode = (const SDropTableClause*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkDropTableClauseDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkDropTableClauseTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkDropTableClauseIgnoreNotExists, pNode->ignoreNotExists); + } + + return code; +} + +static int32_t jsonToDropTableClause(const SJson* pJson, void* pObj) { + SDropTableClause* pNode = (SDropTableClause*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkDropTableClauseDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkDropTableClauseTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkDropTableClauseIgnoreNotExists, &pNode->ignoreNotExists); + } + + return code; +} + +static const char* jkDropTableStmtTables = "Tables"; + +static int32_t dropTableStmtToJson(const void* pObj, SJson* pJson) { + const SDropTableStmt* pNode = (const SDropTableStmt*)pObj; + return nodeListToJson(pJson, jkDropTableStmtTables, pNode->pTables); +} + +static int32_t jsonToDropTableStmt(const SJson* pJson, void* pObj) { + SDropTableStmt* pNode = (SDropTableStmt*)pObj; + return jsonToNodeList(pJson, jkDropTableStmtTables, &pNode->pTables); +} + +static const char* jkDropSuperTableStmtDbName = "DbName"; +static const char* jkDropSuperTableStmtTableName = "TableName"; +static const char* jkDropSuperTableStmtIgnoreNotExists = "IgnoreNotExists"; + +static int32_t dropStableStmtToJson(const void* pObj, SJson* pJson) { + const SDropSuperTableStmt* pNode = (const SDropSuperTableStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkDropSuperTableStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkDropSuperTableStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkDropSuperTableStmtIgnoreNotExists, pNode->ignoreNotExists); + } + + return code; +} + +static int32_t jsonToDropStableStmt(const SJson* pJson, void* pObj) { + SDropSuperTableStmt* pNode = (SDropSuperTableStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkDropSuperTableStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkDropSuperTableStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkDropSuperTableStmtIgnoreNotExists, &pNode->ignoreNotExists); + } + + return code; +} + +static const char* jkAlterTableStmtDbName = "DbName"; +static const char* jkAlterTableStmtTableName = "TableName"; +static const char* jkAlterTableStmtAlterType = "AlterType"; +static const char* jkAlterTableStmtColName = "ColName"; +static const char* jkAlterTableStmtNewColName = "NewColName"; +static const char* jkAlterTableStmtOptions = "Options"; +static const char* jkAlterTableStmtNewDataType = "NewDataType"; +static const char* jkAlterTableStmtNewTagVal = "NewTagVal"; + +static int32_t alterTableStmtToJson(const void* pObj, SJson* pJson) { + const SAlterTableStmt* pNode = (const SAlterTableStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkAlterTableStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkAlterTableStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkAlterTableStmtAlterType, pNode->alterType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkAlterTableStmtColName, pNode->colName); } if (TSDB_CODE_SUCCESS == code) { code = tjsonAddStringToObject(pJson, jkAlterTableStmtNewColName, pNode->newColName); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddObject(pJson, jkAlterTableStmtOptions, nodeToJson, pNode->pOptions); + code = tjsonAddObject(pJson, jkAlterTableStmtOptions, nodeToJson, pNode->pOptions); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkAlterTableStmtNewDataType, dataTypeToJson, &pNode->dataType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkAlterTableStmtOptions, nodeToJson, pNode->pVal); + } + + return code; +} + +static int32_t jsonToAlterTableStmt(const SJson* pJson, void* pObj) { + SAlterTableStmt* pNode = (SAlterTableStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkAlterTableStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkAlterTableStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetTinyIntValue(pJson, jkAlterTableStmtAlterType, &pNode->alterType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkAlterTableStmtColName, pNode->colName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkAlterTableStmtNewColName, pNode->newColName); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkAlterTableStmtOptions, (SNode**)&pNode->pOptions); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonToObject(pJson, jkAlterTableStmtNewDataType, jsonToDataType, &pNode->dataType); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkAlterTableStmtOptions, (SNode**)&pNode->pVal); + } + + return code; +} + +static int32_t alterStableStmtToJson(const void* pObj, SJson* pJson) { return alterTableStmtToJson(pObj, pJson); } + +static int32_t jsonToAlterStableStmt(const SJson* pJson, void* pObj) { return jsonToAlterTableStmt(pJson, pObj); } + +static const char* jkCreateUserStmtUserName = "UserName"; +static const char* jkCreateUserStmtPassword = "Password"; +static const char* jkCreateUserStmtSysinfo = "Sysinfo"; + +static int32_t createUserStmtToJson(const void* pObj, SJson* pJson) { + const SCreateUserStmt* pNode = (const SCreateUserStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkCreateUserStmtUserName, pNode->userName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateUserStmtPassword, pNode->password); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkCreateUserStmtSysinfo, pNode->sysinfo); + } + + return code; +} + +static int32_t jsonToCreateUserStmt(const SJson* pJson, void* pObj) { + SCreateUserStmt* pNode = (SCreateUserStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkCreateUserStmtUserName, pNode->userName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateUserStmtPassword, pNode->password); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetTinyIntValue(pJson, jkCreateUserStmtSysinfo, &pNode->sysinfo); + } + + return code; +} + +static const char* jkAlterUserStmtUserName = "UserName"; +static const char* jkAlterUserStmtAlterType = "AlterType"; +static const char* jkAlterUserStmtPassword = "Password"; +static const char* jkAlterUserStmtEnable = "Enable"; +static const char* jkAlterUserStmtSysinfo = "Sysinfo"; + +static int32_t alterUserStmtToJson(const void* pObj, SJson* pJson) { + const SAlterUserStmt* pNode = (const SAlterUserStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkAlterUserStmtUserName, pNode->userName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkAlterUserStmtAlterType, pNode->alterType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkAlterUserStmtPassword, pNode->password); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkAlterUserStmtEnable, pNode->enable); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkAlterUserStmtSysinfo, pNode->sysinfo); + } + + return code; +} + +static int32_t jsonToAlterUserStmt(const SJson* pJson, void* pObj) { + SAlterUserStmt* pNode = (SAlterUserStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkAlterUserStmtUserName, pNode->userName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetTinyIntValue(pJson, jkAlterUserStmtAlterType, &pNode->alterType); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkAlterUserStmtPassword, pNode->password); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetTinyIntValue(pJson, jkAlterUserStmtEnable, &pNode->enable); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetTinyIntValue(pJson, jkAlterUserStmtSysinfo, &pNode->sysinfo); + } + + return code; +} + +static const char* jkDropUserStmtUserName = "UserName"; + +static int32_t dropUserStmtToJson(const void* pObj, SJson* pJson) { + const SDropUserStmt* pNode = (const SDropUserStmt*)pObj; + return tjsonAddStringToObject(pJson, jkDropUserStmtUserName, pNode->userName); +} + +static int32_t jsonToDropUserStmt(const SJson* pJson, void* pObj) { + SDropUserStmt* pNode = (SDropUserStmt*)pObj; + return tjsonGetStringValue(pJson, jkDropUserStmtUserName, pNode->userName); +} + +static const char* jkUseDatabaseStmtDbName = "DbName"; + +static int32_t useDatabaseStmtToJson(const void* pObj, SJson* pJson) { + const SUseDatabaseStmt* pNode = (const SUseDatabaseStmt*)pObj; + return tjsonAddStringToObject(pJson, jkUseDatabaseStmtDbName, pNode->dbName); +} + +static int32_t jsonToUseDatabaseStmt(const SJson* pJson, void* pObj) { + SUseDatabaseStmt* pNode = (SUseDatabaseStmt*)pObj; + return tjsonGetStringValue(pJson, jkUseDatabaseStmtDbName, pNode->dbName); +} + +static const char* jkCreateDnodeStmtFqdn = "Fqdn"; +static const char* jkCreateDnodeStmtPort = "Port"; + +static int32_t createDnodeStmtToJson(const void* pObj, SJson* pJson) { + const SCreateDnodeStmt* pNode = (const SCreateDnodeStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkCreateDnodeStmtFqdn, pNode->fqdn); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkCreateDnodeStmtPort, pNode->port); + } + + return code; +} + +static int32_t jsonToCreateDnodeStmt(const SJson* pJson, void* pObj) { + SCreateDnodeStmt* pNode = (SCreateDnodeStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkCreateDnodeStmtFqdn, pNode->fqdn); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkCreateDnodeStmtPort, &pNode->port); + } + + return code; +} + +static const char* jkAlterDnodeStmtDnodeId = "DnodeId"; +static const char* jkAlterDnodeStmtConfig = "Config"; +static const char* jkAlterDnodeStmtValue = "Value"; + +static int32_t alterDnodeStmtToJson(const void* pObj, SJson* pJson) { + const SAlterDnodeStmt* pNode = (const SAlterDnodeStmt*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkAlterDnodeStmtDnodeId, pNode->dnodeId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkAlterDnodeStmtConfig, pNode->config); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkAlterDnodeStmtValue, pNode->value); + } + + return code; +} + +static int32_t jsonToAlterDnodeStmt(const SJson* pJson, void* pObj) { + SAlterDnodeStmt* pNode = (SAlterDnodeStmt*)pObj; + + int32_t code = tjsonGetIntValue(pJson, jkAlterDnodeStmtDnodeId, &pNode->dnodeId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkAlterDnodeStmtConfig, pNode->config); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkAlterDnodeStmtValue, pNode->value); + } + + return code; +} + +static const char* jkCreateIndexStmtIndexType = "IndexType"; +static const char* jkCreateIndexStmtIgnoreExists = "IgnoreExists"; +static const char* jkCreateIndexStmtIndexDbName = "IndexDbName"; +static const char* jkCreateIndexStmtIndexName = "indexName"; +static const char* jkCreateIndexStmtDbName = "DbName"; +static const char* jkCreateIndexStmtTableName = "TableName"; +static const char* jkCreateIndexStmtCols = "Cols"; +static const char* jkCreateIndexStmtOptions = "Options"; + +static int32_t createIndexStmtToJson(const void* pObj, SJson* pJson) { + const SCreateIndexStmt* pNode = (const SCreateIndexStmt*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkCreateIndexStmtIndexType, pNode->indexType); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkCreateIndexStmtIgnoreExists, pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateIndexStmtIndexDbName, pNode->indexDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateIndexStmtIndexName, pNode->indexName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateIndexStmtDbName, pNode->dbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateIndexStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkCreateIndexStmtCols, pNode->pCols); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkCreateIndexStmtOptions, nodeToJson, pNode->pOptions); + } + + return code; +} + +static int32_t jsonToCreateIndexStmt(const SJson* pJson, void* pObj) { + SCreateIndexStmt* pNode = (SCreateIndexStmt*)pObj; + + int32_t code = TSDB_CODE_SUCCESS; + tjsonGetNumberValue(pJson, jkCreateIndexStmtIndexType, pNode->indexType, code); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkCreateIndexStmtIgnoreExists, &pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateIndexStmtIndexDbName, pNode->indexDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateIndexStmtIndexName, pNode->indexName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateIndexStmtDbName, pNode->dbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateIndexStmtTableName, pNode->tableName); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkCreateIndexStmtCols, &pNode->pCols); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkCreateIndexStmtOptions, (SNode**)&pNode->pOptions); + } + + return code; +} + +static const char* jkDropIndexStmtIgnoreNotExists = "IgnoreNotExists"; +static const char* jkDropIndexStmtIndexDbName = "IndexDbName"; +static const char* jkDropIndexStmtIndexName = "IndexName"; + +static int32_t dropIndexStmtToJson(const void* pObj, SJson* pJson) { + const SDropIndexStmt* pNode = (const SDropIndexStmt*)pObj; + + int32_t code = tjsonAddBoolToObject(pJson, jkDropIndexStmtIgnoreNotExists, pNode->ignoreNotExists); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkDropIndexStmtIndexDbName, pNode->indexDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkDropIndexStmtIndexName, pNode->indexName); + } + + return code; +} + +static int32_t jsonToDropIndexStmt(const SJson* pJson, void* pObj) { + SDropIndexStmt* pNode = (SDropIndexStmt*)pObj; + + int32_t code = tjsonGetBoolValue(pJson, jkDropIndexStmtIgnoreNotExists, &pNode->ignoreNotExists); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkDropIndexStmtIndexDbName, pNode->indexDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkDropIndexStmtIndexName, pNode->indexName); + } + + return code; +} + +static const char* jkCreateComponentNodeStmtDnodeId = "DnodeId"; + +static int32_t createComponentNodeStmtToJson(const void* pObj, SJson* pJson) { + const SCreateComponentNodeStmt* pNode = (const SCreateComponentNodeStmt*)pObj; + return tjsonAddIntegerToObject(pJson, jkCreateComponentNodeStmtDnodeId, pNode->dnodeId); +} + +static int32_t jsonToCreateComponentNodeStmt(const SJson* pJson, void* pObj) { + SCreateComponentNodeStmt* pNode = (SCreateComponentNodeStmt*)pObj; + return tjsonGetIntValue(pJson, jkCreateComponentNodeStmtDnodeId, &pNode->dnodeId); +} + +static const char* jkDropComponentNodeStmtDnodeId = "DnodeId"; + +static int32_t dropComponentNodeStmtToJson(const void* pObj, SJson* pJson) { + const SDropComponentNodeStmt* pNode = (const SDropComponentNodeStmt*)pObj; + return tjsonAddIntegerToObject(pJson, jkDropComponentNodeStmtDnodeId, pNode->dnodeId); +} + +static int32_t jsonToDropComponentNodeStmt(const SJson* pJson, void* pObj) { + SDropComponentNodeStmt* pNode = (SDropComponentNodeStmt*)pObj; + return tjsonGetIntValue(pJson, jkDropComponentNodeStmtDnodeId, &pNode->dnodeId); +} + +static int32_t createQnodeStmtToJson(const void* pObj, SJson* pJson) { + return createComponentNodeStmtToJson(pObj, pJson); +} + +static int32_t jsonToCreateQnodeStmt(const SJson* pJson, void* pObj) { + return jsonToCreateComponentNodeStmt(pJson, pObj); +} + +static int32_t dropQnodeStmtToJson(const void* pObj, SJson* pJson) { return dropComponentNodeStmtToJson(pObj, pJson); } + +static int32_t jsonToDropQnodeStmt(const SJson* pJson, void* pObj) { return jsonToDropComponentNodeStmt(pJson, pObj); } + +static int32_t createSnodeStmtToJson(const void* pObj, SJson* pJson) { + return createComponentNodeStmtToJson(pObj, pJson); +} + +static int32_t jsonToCreateSnodeStmt(const SJson* pJson, void* pObj) { + return jsonToCreateComponentNodeStmt(pJson, pObj); +} + +static int32_t dropSnodeStmtToJson(const void* pObj, SJson* pJson) { return dropComponentNodeStmtToJson(pObj, pJson); } + +static int32_t jsonToDropSnodeStmt(const SJson* pJson, void* pObj) { return jsonToDropComponentNodeStmt(pJson, pObj); } + +static int32_t createMnodeStmtToJson(const void* pObj, SJson* pJson) { + return createComponentNodeStmtToJson(pObj, pJson); +} + +static int32_t jsonToCreateMnodeStmt(const SJson* pJson, void* pObj) { + return jsonToCreateComponentNodeStmt(pJson, pObj); +} + +static int32_t dropMnodeStmtToJson(const void* pObj, SJson* pJson) { return dropComponentNodeStmtToJson(pObj, pJson); } + +static int32_t jsonToDropMnodeStmt(const SJson* pJson, void* pObj) { return jsonToDropComponentNodeStmt(pJson, pObj); } + +static const char* jkDropDnodeStmtDnodeId = "DnodeId"; +static const char* jkDropDnodeStmtFqdn = "Fqdn"; +static const char* jkDropDnodeStmtPort = "Port"; +static const char* jkDropDnodeStmtForce = "Force"; + +static int32_t dropDnodeStmtToJson(const void* pObj, SJson* pJson) { + const SDropDnodeStmt* pNode = (const SDropDnodeStmt*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkDropDnodeStmtDnodeId, pNode->dnodeId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkDropDnodeStmtFqdn, pNode->fqdn); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkDropDnodeStmtPort, pNode->port); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkDropDnodeStmtForce, pNode->force); + } + + return code; +} + +static int32_t jsonToDropDnodeStmt(const SJson* pJson, void* pObj) { + SDropDnodeStmt* pNode = (SDropDnodeStmt*)pObj; + + int32_t code = tjsonGetIntValue(pJson, jkDropDnodeStmtDnodeId, &pNode->dnodeId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkDropDnodeStmtFqdn, pNode->fqdn); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkDropDnodeStmtPort, &pNode->port); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkDropDnodeStmtForce, &pNode->force); + } + + return code; +} + +static const char* jkCreateTopicStmtTopicName = "TopicName"; +static const char* jkCreateTopicStmtSubscribeDbName = "SubscribeDbName"; +static const char* jkCreateTopicStmtIgnoreExists = "IgnoreExists"; +static const char* jkCreateTopicStmtQuery = "Query"; + +static int32_t createTopicStmtToJson(const void* pObj, SJson* pJson) { + const SCreateTopicStmt* pNode = (const SCreateTopicStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkCreateTopicStmtTopicName, pNode->topicName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateTopicStmtSubscribeDbName, pNode->subDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkCreateTopicStmtIgnoreExists, pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkCreateTopicStmtQuery, nodeToJson, pNode->pQuery); + } + + return code; +} + +static int32_t jsonToCreateTopicStmt(const SJson* pJson, void* pObj) { + SCreateTopicStmt* pNode = (SCreateTopicStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkCreateTopicStmtTopicName, pNode->topicName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateTopicStmtSubscribeDbName, pNode->subDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkCreateTopicStmtIgnoreExists, &pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkCreateTopicStmtQuery, &pNode->pQuery); + } + + return code; +} + +static const char* jkDropTopicStmtTopicName = "TopicName"; +static const char* jkDropTopicStmtIgnoreNotExists = "IgnoreNotExists"; + +static int32_t dropTopicStmtToJson(const void* pObj, SJson* pJson) { + const SDropTopicStmt* pNode = (const SDropTopicStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkDropTopicStmtTopicName, pNode->topicName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkDropTopicStmtIgnoreNotExists, pNode->ignoreNotExists); + } + + return code; +} + +static int32_t jsonToDropTopicStmt(const SJson* pJson, void* pObj) { + SDropTopicStmt* pNode = (SDropTopicStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkDropTopicStmtTopicName, pNode->topicName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkDropTopicStmtIgnoreNotExists, &pNode->ignoreNotExists); + } + + return code; +} + +static const char* jkDropCGroupStmtTopicName = "TopicName"; +static const char* jkDropCGroupStmtConsumerGroup = "ConsumerGroup"; +static const char* jkDropCGroupStmtIgnoreNotExists = "IgnoreNotExists"; + +static int32_t dropConsumerGroupStmtToJson(const void* pObj, SJson* pJson) { + const SDropCGroupStmt* pNode = (const SDropCGroupStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkDropCGroupStmtTopicName, pNode->topicName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkDropCGroupStmtConsumerGroup, pNode->cgroup); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkDropCGroupStmtIgnoreNotExists, pNode->ignoreNotExists); + } + + return code; +} + +static int32_t jsonToDropConsumerGroupStmt(const SJson* pJson, void* pObj) { + SDropCGroupStmt* pNode = (SDropCGroupStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkDropCGroupStmtTopicName, pNode->topicName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkDropCGroupStmtConsumerGroup, pNode->cgroup); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkDropCGroupStmtIgnoreNotExists, &pNode->ignoreNotExists); + } + + return code; +} + +static const char* jkAlterLocalStmtConfig = "Config"; +static const char* jkAlterLocalStmtValue = "Value"; + +static int32_t alterLocalStmtToJson(const void* pObj, SJson* pJson) { + const SAlterLocalStmt* pNode = (const SAlterLocalStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkAlterLocalStmtConfig, pNode->config); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkAlterLocalStmtValue, pNode->value); + } + + return code; +} + +static int32_t jsonToAlterLocalStmt(const SJson* pJson, void* pObj) { + SAlterLocalStmt* pNode = (SAlterLocalStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkAlterLocalStmtConfig, pNode->config); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkAlterLocalStmtValue, pNode->value); + } + + return code; +} + +static const char* jkExplainStmtAnalyze = "Analyze"; +static const char* jkExplainStmtOptions = "Options"; +static const char* jkExplainStmtQuery = "Query"; + +static int32_t explainStmtToJson(const void* pObj, SJson* pJson) { + const SExplainStmt* pNode = (const SExplainStmt*)pObj; + + int32_t code = tjsonAddBoolToObject(pJson, jkExplainStmtAnalyze, pNode->analyze); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkExplainStmtOptions, nodeToJson, pNode->pOptions); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkExplainStmtQuery, nodeToJson, pNode->pQuery); + } + + return code; +} + +static int32_t jsonToExplainStmt(const SJson* pJson, void* pObj) { + SExplainStmt* pNode = (SExplainStmt*)pObj; + + int32_t code = tjsonGetBoolValue(pJson, jkExplainStmtAnalyze, &pNode->analyze); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkExplainStmtOptions, (SNode**)&pNode->pOptions); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkExplainStmtQuery, &pNode->pQuery); + } + + return code; +} + +static const char* jkDescribeStmtDbName = "DbName"; +static const char* jkDescribeStmtTableName = "TableName"; + +static int32_t describeStmtToJson(const void* pObj, SJson* pJson) { + const SDescribeStmt* pNode = (const SDescribeStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkDescribeStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkDescribeStmtTableName, pNode->tableName); + } + + return code; +} + +static int32_t jsonToDescribeStmt(const SJson* pJson, void* pObj) { + SDescribeStmt* pNode = (SDescribeStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkDescribeStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkDescribeStmtTableName, pNode->tableName); + } + + return code; +} + +static const char* jkCompactDatabaseStmtDbName = "DbName"; + +static int32_t compactDatabaseStmtToJson(const void* pObj, SJson* pJson) { + const SCompactDatabaseStmt* pNode = (const SCompactDatabaseStmt*)pObj; + return tjsonAddStringToObject(pJson, jkCompactDatabaseStmtDbName, pNode->dbName); +} + +static int32_t jsonToCompactDatabaseStmt(const SJson* pJson, void* pObj) { + SCompactDatabaseStmt* pNode = (SCompactDatabaseStmt*)pObj; + return tjsonGetStringValue(pJson, jkCompactDatabaseStmtDbName, pNode->dbName); +} + +static const char* jkCreateStreamStmtStreamName = "StreamName"; +static const char* jkCreateStreamStmtTargetDbName = "TargetDbName"; +static const char* jkCreateStreamStmtTargetTabName = "TargetTabName"; +static const char* jkCreateStreamStmtIgnoreExists = "IgnoreExists"; +static const char* jkCreateStreamStmtOptions = "Options"; +static const char* jkCreateStreamStmtQuery = "Query"; +static const char* jkCreateStreamStmtTags = "Tags"; +static const char* jkCreateStreamStmtSubtable = "Subtable"; + +static int32_t createStreamStmtToJson(const void* pObj, SJson* pJson) { + const SCreateStreamStmt* pNode = (const SCreateStreamStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkCreateStreamStmtStreamName, pNode->streamName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateStreamStmtTargetDbName, pNode->targetDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkCreateStreamStmtTargetTabName, pNode->targetTabName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkCreateStreamStmtIgnoreExists, pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkCreateStreamStmtOptions, nodeToJson, pNode->pOptions); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkCreateStreamStmtQuery, nodeToJson, pNode->pQuery); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkCreateStreamStmtTags, pNode->pTags); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkCreateStreamStmtSubtable, nodeToJson, pNode->pSubtable); + } + + return code; +} + +static int32_t jsonToCreateStreamStmt(const SJson* pJson, void* pObj) { + SCreateStreamStmt* pNode = (SCreateStreamStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkCreateStreamStmtStreamName, pNode->streamName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateStreamStmtTargetDbName, pNode->targetDbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetStringValue(pJson, jkCreateStreamStmtTargetTabName, pNode->targetTabName); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkCreateStreamStmtIgnoreExists, &pNode->ignoreExists); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkCreateStreamStmtOptions, (SNode**)&pNode->pOptions); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkCreateStreamStmtQuery, &pNode->pQuery); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkCreateStreamStmtTags, &pNode->pTags); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkCreateStreamStmtSubtable, &pNode->pSubtable); + } + + return code; +} + +static const char* jkDropStreamStmtStreamName = "StreamName"; +static const char* jkDropStreamStmtIgnoreNotExists = "IgnoreNotExists"; + +static int32_t dropStreamStmtToJson(const void* pObj, SJson* pJson) { + const SDropStreamStmt* pNode = (const SDropStreamStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkDropStreamStmtStreamName, pNode->streamName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddBoolToObject(pJson, jkDropStreamStmtIgnoreNotExists, pNode->ignoreNotExists); + } + + return code; +} + +static int32_t jsonToDropStreamStmt(const SJson* pJson, void* pObj) { + SDropStreamStmt* pNode = (SDropStreamStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkDropStreamStmtStreamName, pNode->streamName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBoolValue(pJson, jkDropStreamStmtIgnoreNotExists, &pNode->ignoreNotExists); + } + + return code; +} + +static const char* jkMergeVgroupStmtVgroupId1 = "VgroupId1"; +static const char* jkMergeVgroupStmtVgroupId2 = "VgroupId2"; + +static int32_t mergeVgroupStmtToJson(const void* pObj, SJson* pJson) { + const SMergeVgroupStmt* pNode = (const SMergeVgroupStmt*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkMergeVgroupStmtVgroupId1, pNode->vgId1); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkMergeVgroupStmtVgroupId2, pNode->vgId2); + } + + return code; +} + +static int32_t jsonToMergeVgroupStmt(const SJson* pJson, void* pObj) { + SMergeVgroupStmt* pNode = (SMergeVgroupStmt*)pObj; + + int32_t code = tjsonGetIntValue(pJson, jkMergeVgroupStmtVgroupId1, &pNode->vgId1); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkMergeVgroupStmtVgroupId2, &pNode->vgId2); + } + + return code; +} + +static const char* jkRedistributeVgroupStmtVgroupId = "VgroupId"; +static const char* jkRedistributeVgroupStmtDnodeId1 = "DnodeId1"; +static const char* jkRedistributeVgroupStmtDnodeId2 = "DnodeId2"; +static const char* jkRedistributeVgroupStmtDnodeId3 = "DnodeId3"; +static const char* jkRedistributeVgroupStmtDnodes = "Dnodes"; + +static int32_t redistributeVgroupStmtToJson(const void* pObj, SJson* pJson) { + const SRedistributeVgroupStmt* pNode = (const SRedistributeVgroupStmt*)pObj; + + int32_t code = tjsonAddIntegerToObject(pJson, jkRedistributeVgroupStmtVgroupId, pNode->vgId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkRedistributeVgroupStmtDnodeId1, pNode->dnodeId1); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkRedistributeVgroupStmtDnodeId2, pNode->dnodeId2); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkRedistributeVgroupStmtDnodeId3, pNode->dnodeId3); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkRedistributeVgroupStmtDnodes, pNode->pDnodes); + } + + return code; +} + +static int32_t jsonToRedistributeVgroupStmt(const SJson* pJson, void* pObj) { + SRedistributeVgroupStmt* pNode = (SRedistributeVgroupStmt*)pObj; + + int32_t code = tjsonGetIntValue(pJson, jkRedistributeVgroupStmtVgroupId, &pNode->vgId); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkRedistributeVgroupStmtDnodeId1, &pNode->dnodeId1); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkRedistributeVgroupStmtDnodeId2, &pNode->dnodeId2); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddObject(pJson, jkAlterTableStmtNewDataType, dataTypeToJson, &pNode->dataType); + code = tjsonGetIntValue(pJson, jkRedistributeVgroupStmtDnodeId3, &pNode->dnodeId3); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddObject(pJson, jkAlterTableStmtOptions, nodeToJson, pNode->pVal); + code = jsonToNodeList(pJson, jkRedistributeVgroupStmtDnodes, &pNode->pDnodes); } return code; } -static int32_t jsonToAlterTableStmt(const SJson* pJson, void* pObj) { - SAlterTableStmt* pNode = (SAlterTableStmt*)pObj; +static const char* jkSplitVgroupStmtVgroupId = "VgroupId"; - int32_t code = tjsonGetStringValue(pJson, jkAlterTableStmtDbName, pNode->dbName); +static int32_t splitVgroupStmtToJson(const void* pObj, SJson* pJson) { + const SSplitVgroupStmt* pNode = (const SSplitVgroupStmt*)pObj; + return tjsonAddIntegerToObject(pJson, jkSplitVgroupStmtVgroupId, pNode->vgId); +} + +static int32_t jsonToSplitVgroupStmt(const SJson* pJson, void* pObj) { + SSplitVgroupStmt* pNode = (SSplitVgroupStmt*)pObj; + return tjsonGetIntValue(pJson, jkSplitVgroupStmtVgroupId, &pNode->vgId); +} + +static const char* jkGrantStmtUserName = "UserName"; +static const char* jkGrantStmtObjName = "ObjName"; +static const char* jkGrantStmtPrivileges = "Privileges"; + +static int32_t grantStmtToJson(const void* pObj, SJson* pJson) { + const SGrantStmt* pNode = (const SGrantStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkGrantStmtUserName, pNode->userName); if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetStringValue(pJson, jkAlterTableStmtTableName, pNode->tableName); + code = tjsonAddStringToObject(pJson, jkGrantStmtObjName, pNode->objName); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetTinyIntValue(pJson, jkAlterTableStmtAlterType, &pNode->alterType); + code = tjsonAddIntegerToObject(pJson, jkGrantStmtPrivileges, pNode->privileges); } + + return code; +} + +static int32_t jsonToGrantStmt(const SJson* pJson, void* pObj) { + SGrantStmt* pNode = (SGrantStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkGrantStmtUserName, pNode->userName); if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetStringValue(pJson, jkAlterTableStmtColName, pNode->colName); + code = tjsonGetStringValue(pJson, jkGrantStmtObjName, pNode->objName); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetStringValue(pJson, jkAlterTableStmtNewColName, pNode->newColName); + code = tjsonGetBigIntValue(pJson, jkGrantStmtPrivileges, &pNode->privileges); } + + return code; +} + +static int32_t revokeStmtToJson(const void* pObj, SJson* pJson) { return grantStmtToJson(pObj, pJson); } + +static int32_t jsonToRevokeStmt(const SJson* pJson, void* pObj) { return jsonToGrantStmt(pJson, pObj); } + +static const char* jkShowStmtDbName = "DbName"; +static const char* jkShowStmtTbName = "TbName"; +static const char* jkShowStmtTableCondType = "TableCondType"; + +static int32_t showStmtToJson(const void* pObj, SJson* pJson) { + const SShowStmt* pNode = (const SShowStmt*)pObj; + + int32_t code = tjsonAddObject(pJson, jkShowStmtDbName, nodeToJson, pNode->pDbName); if (TSDB_CODE_SUCCESS == code) { - code = jsonToNodeObject(pJson, jkAlterTableStmtOptions, (SNode**)&pNode->pOptions); + code = tjsonAddObject(pJson, jkShowStmtTbName, nodeToJson, pNode->pTbName); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonToObject(pJson, jkAlterTableStmtNewDataType, jsonToDataType, &pNode->dataType); + code = tjsonAddIntegerToObject(pJson, jkShowStmtTableCondType, pNode->tableCondType); } + + return code; +} + +static int32_t jsonToShowStmt(const SJson* pJson, void* pObj) { + SShowStmt* pNode = (SShowStmt*)pObj; + + int32_t code = jsonToNodeObject(pJson, jkShowStmtDbName, &pNode->pDbName); if (TSDB_CODE_SUCCESS == code) { - code = jsonToNodeObject(pJson, jkAlterTableStmtOptions, (SNode**)&pNode->pVal); + code = jsonToNodeObject(pJson, jkShowStmtTbName, &pNode->pTbName); + } + if (TSDB_CODE_SUCCESS == code) { + tjsonGetNumberValue(pJson, jkShowStmtTableCondType, pNode->tableCondType, code); } return code; } -static const char* jkAlterDnodeStmtDnodeId = "DnodeId"; -static const char* jkAlterDnodeStmtConfig = "Config"; -static const char* jkAlterDnodeStmtValue = "Value"; +static int32_t showDnodesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } -static int32_t alterDnodeStmtToJson(const void* pObj, SJson* pJson) { - const SAlterDnodeStmt* pNode = (const SAlterDnodeStmt*)pObj; +static int32_t jsonToShowDnodesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } - int32_t code = tjsonAddIntegerToObject(pJson, jkAlterDnodeStmtDnodeId, pNode->dnodeId); +static int32_t showMnodesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowMnodesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showQnodesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowQnodesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showClusterStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowClusterStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showDatabasesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowDatabasesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showFunctionsStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowFunctionsStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showIndexesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowIndexesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showStablesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowStablesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showStreamsStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowStreamsStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showTablesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowTablesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showTagsStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowTagsStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showUsersStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowUsersStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showVgroupsStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowVgroupsStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showConsumersStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowConsumersStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showVariablesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowVariablesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static const char* jkShowDnodeVariablesStmtDnodeId = "DnodeId"; +static const char* jkShowDnodeVariablesStmtLikePattern = "LikePattern"; + +static int32_t showDnodeVariablesStmtToJson(const void* pObj, SJson* pJson) { + const SShowDnodeVariablesStmt* pNode = (const SShowDnodeVariablesStmt*)pObj; + + int32_t code = tjsonAddObject(pJson, jkShowDnodeVariablesStmtDnodeId, nodeToJson, pNode->pDnodeId); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddStringToObject(pJson, jkAlterDnodeStmtConfig, pNode->config); + code = tjsonAddObject(pJson, jkShowDnodeVariablesStmtLikePattern, nodeToJson, pNode->pLikePattern); } + + return code; +} + +static int32_t jsonToShowDnodeVariablesStmt(const SJson* pJson, void* pObj) { + SShowDnodeVariablesStmt* pNode = (SShowDnodeVariablesStmt*)pObj; + + int32_t code = jsonToNodeObject(pJson, jkShowDnodeVariablesStmtDnodeId, &pNode->pDnodeId); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddStringToObject(pJson, jkAlterDnodeStmtValue, pNode->value); + code = jsonToNodeObject(pJson, jkShowDnodeVariablesStmtLikePattern, &pNode->pLikePattern); } return code; } -static int32_t jsonToAlterDnodeStmt(const SJson* pJson, void* pObj) { - SAlterDnodeStmt* pNode = (SAlterDnodeStmt*)pObj; +static int32_t showTransactionsStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } - int32_t code = tjsonGetIntValue(pJson, jkAlterDnodeStmtDnodeId, &pNode->dnodeId); +static int32_t jsonToShowTransactionsStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static int32_t showSubscriptionsStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } + +static int32_t jsonToShowSubscriptionsStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static const char* jkShowVnodesStmtDnodeId = "DnodeId"; +static const char* jkShowVnodesStmtDnodeEndpoint = "DnodeEndpoint"; + +static int32_t showVnodesStmtToJson(const void* pObj, SJson* pJson) { + const SShowVnodesStmt* pNode = (const SShowVnodesStmt*)pObj; + + int32_t code = tjsonAddObject(pJson, jkShowVnodesStmtDnodeId, nodeToJson, pNode->pDnodeId); if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetStringValue(pJson, jkAlterDnodeStmtConfig, pNode->config); + code = tjsonAddObject(pJson, jkShowVnodesStmtDnodeEndpoint, nodeToJson, pNode->pDnodeEndpoint); } + + return code; +} + +static int32_t jsonToShowVnodesStmt(const SJson* pJson, void* pObj) { + SShowVnodesStmt* pNode = (SShowVnodesStmt*)pObj; + + int32_t code = jsonToNodeObject(pJson, jkShowVnodesStmtDnodeId, &pNode->pDnodeId); if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetStringValue(pJson, jkAlterDnodeStmtValue, pNode->value); + code = jsonToNodeObject(pJson, jkShowVnodesStmtDnodeEndpoint, &pNode->pDnodeEndpoint); } return code; } -static const char* jkCreateTopicStmtTopicName = "TopicName"; -static const char* jkCreateTopicStmtSubscribeDbName = "SubscribeDbName"; -static const char* jkCreateTopicStmtIgnoreExists = "IgnoreExists"; -static const char* jkCreateTopicStmtQuery = "Query"; +static int32_t showUserPrivilegesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } -static int32_t createTopicStmtToJson(const void* pObj, SJson* pJson) { - const SCreateTopicStmt* pNode = (const SCreateTopicStmt*)pObj; +static int32_t jsonToShowUserPrivilegesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } - int32_t code = tjsonAddStringToObject(pJson, jkCreateTopicStmtTopicName, pNode->topicName); +static const char* jkShowCreateDatabaseStmtDbName = "DbName"; + +static int32_t showCreateDatabaseStmtToJson(const void* pObj, SJson* pJson) { + const SShowCreateDatabaseStmt* pNode = (const SShowCreateDatabaseStmt*)pObj; + return tjsonAddStringToObject(pJson, jkShowCreateDatabaseStmtDbName, pNode->dbName); +} + +static int32_t jsonToShowCreateDatabaseStmt(const SJson* pJson, void* pObj) { + SShowCreateDatabaseStmt* pNode = (SShowCreateDatabaseStmt*)pObj; + return tjsonGetStringValue(pJson, jkShowCreateDatabaseStmtDbName, pNode->dbName); +} + +static const char* jkShowCreateTableStmtDbName = "DbName"; +static const char* jkShowCreateTableStmtTableName = "TableName"; + +static int32_t showCreateTableStmtToJson(const void* pObj, SJson* pJson) { + const SShowCreateTableStmt* pNode = (const SShowCreateTableStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkShowCreateTableStmtDbName, pNode->dbName); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddStringToObject(pJson, jkCreateTopicStmtSubscribeDbName, pNode->subDbName); + code = tjsonAddStringToObject(pJson, jkShowCreateTableStmtTableName, pNode->tableName); } + + return code; +} + +static int32_t jsonToShowCreateTableStmt(const SJson* pJson, void* pObj) { + SShowCreateTableStmt* pNode = (SShowCreateTableStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkShowCreateTableStmtDbName, pNode->dbName); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddBoolToObject(pJson, jkCreateTopicStmtIgnoreExists, pNode->ignoreExists); + code = tjsonGetStringValue(pJson, jkShowCreateTableStmtTableName, pNode->tableName); + } + + return code; +} + +static int32_t showCreateStableStmtToJson(const void* pObj, SJson* pJson) { + return showCreateTableStmtToJson(pObj, pJson); +} + +static int32_t jsonToShowCreateStableStmt(const SJson* pJson, void* pObj) { + return jsonToShowCreateTableStmt(pJson, pObj); +} + +static const char* jkShowTableDistributedStmtDbName = "DbName"; +static const char* jkShowTableDistributedStmtTableName = "TableName"; + +static int32_t showTableDistributedStmtToJson(const void* pObj, SJson* pJson) { + const SShowTableDistributedStmt* pNode = (const SShowTableDistributedStmt*)pObj; + + int32_t code = tjsonAddStringToObject(pJson, jkShowTableDistributedStmtDbName, pNode->dbName); + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddStringToObject(pJson, jkShowTableDistributedStmtTableName, pNode->tableName); } + + return code; +} + +static int32_t jsonToShowTableDistributedStmt(const SJson* pJson, void* pObj) { + SShowTableDistributedStmt* pNode = (SShowTableDistributedStmt*)pObj; + + int32_t code = tjsonGetStringValue(pJson, jkShowTableDistributedStmtDbName, pNode->dbName); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddObject(pJson, jkCreateTopicStmtQuery, nodeToJson, pNode->pQuery); + code = tjsonGetStringValue(pJson, jkShowTableDistributedStmtTableName, pNode->tableName); } return code; } -static int32_t jsonToCreateTopicStmt(const SJson* pJson, void* pObj) { - SCreateTopicStmt* pNode = (SCreateTopicStmt*)pObj; +static int32_t showLocalVariablesStmtToJson(const void* pObj, SJson* pJson) { return showStmtToJson(pObj, pJson); } - int32_t code = tjsonGetStringValue(pJson, jkCreateTopicStmtTopicName, pNode->topicName); +static int32_t jsonToShowLocalVariablesStmt(const SJson* pJson, void* pObj) { return jsonToShowStmt(pJson, pObj); } + +static const char* jkShowTableTagsStmtDbName = "DbName"; +static const char* jkShowTableTagsStmtTbName = "TbName"; +static const char* jkShowTableTagsStmtTags = "Tags"; + +static int32_t showTableTagsStmtToJson(const void* pObj, SJson* pJson) { + const SShowTableTagsStmt* pNode = (const SShowTableTagsStmt*)pObj; + + int32_t code = tjsonAddObject(pJson, jkShowTableTagsStmtDbName, nodeToJson, pNode->pDbName); if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetStringValue(pJson, jkCreateTopicStmtSubscribeDbName, pNode->subDbName); + code = tjsonAddObject(pJson, jkShowTableTagsStmtTbName, nodeToJson, pNode->pTbName); } if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetBoolValue(pJson, jkCreateTopicStmtIgnoreExists, &pNode->ignoreExists); + code = nodeListToJson(pJson, jkShowTableTagsStmtTags, pNode->pTags); } + + return code; +} + +static int32_t jsonToShowTableTagsStmt(const SJson* pJson, void* pObj) { + SShowTableTagsStmt* pNode = (SShowTableTagsStmt*)pObj; + + int32_t code = jsonToNodeObject(pJson, jkShowTableTagsStmtDbName, &pNode->pDbName); if (TSDB_CODE_SUCCESS == code) { - code = jsonToNodeObject(pJson, jkCreateTopicStmtQuery, &pNode->pQuery); + code = jsonToNodeObject(pJson, jkShowTableTagsStmtTbName, &pNode->pTbName); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkShowTableTagsStmtTags, &pNode->pTags); } return code; @@ -4575,6 +6264,45 @@ static int32_t jsonToDeleteStmt(const SJson* pJson, void* pObj) { return code; } +static const char* jkInsertStmtTable = "Table"; +static const char* jkInsertStmtCols = "Cols"; +static const char* jkInsertStmtQuery = "Query"; +static const char* jkInsertStmtPrecision = "Precision"; + +static int32_t insertStmtToJson(const void* pObj, SJson* pJson) { + const SInsertStmt* pNode = (const SInsertStmt*)pObj; + + int32_t code = tjsonAddObject(pJson, jkInsertStmtTable, nodeToJson, pNode->pTable); + if (TSDB_CODE_SUCCESS == code) { + code = nodeListToJson(pJson, jkInsertStmtCols, pNode->pCols); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkInsertStmtQuery, nodeToJson, pNode->pQuery); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkInsertStmtPrecision, pNode->precision); + } + + return code; +} + +static int32_t jsonToInsertStmt(const SJson* pJson, void* pObj) { + SInsertStmt* pNode = (SInsertStmt*)pObj; + + int32_t code = jsonToNodeObject(pJson, jkInsertStmtTable, &pNode->pTable); + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeList(pJson, jkInsertStmtCols, &pNode->pCols); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkInsertStmtQuery, &pNode->pQuery); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetUTinyIntValue(pJson, jkInsertStmtPrecision, &pNode->precision); + } + + return code; +} + static int32_t specificNodeToJson(const void* pObj, SJson* pJson) { switch (nodeType(pObj)) { case QUERY_NODE_COLUMN: @@ -4592,7 +6320,7 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) { case QUERY_NODE_TEMP_TABLE: return tempTableNodeToJson(pObj, pJson); case QUERY_NODE_JOIN_TABLE: - break; + return joinTableNodeToJson(pObj, pJson); case QUERY_NODE_GROUPING_SET: return groupingSetNodeToJson(pObj, pJson); case QUERY_NODE_ORDER_BY_EXPR: @@ -4618,42 +6346,173 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) { case QUERY_NODE_SLOT_DESC: return slotDescNodeToJson(pObj, pJson); case QUERY_NODE_COLUMN_DEF: - break; + return columnDefNodeToJson(pObj, pJson); case QUERY_NODE_DOWNSTREAM_SOURCE: return downstreamSourceNodeToJson(pObj, pJson); case QUERY_NODE_DATABASE_OPTIONS: return databaseOptionsToJson(pObj, pJson); + case QUERY_NODE_TABLE_OPTIONS: + return tableOptionsToJson(pObj, pJson); + case QUERY_NODE_INDEX_OPTIONS: + return indexOptionsToJson(pObj, pJson); + case QUERY_NODE_EXPLAIN_OPTIONS: + return explainOptionsToJson(pObj, pJson); + case QUERY_NODE_STREAM_OPTIONS: + return streamOptionsToJson(pObj, pJson); case QUERY_NODE_LEFT_VALUE: return TSDB_CODE_SUCCESS; // SLeftValueNode has no fields to serialize. case QUERY_NODE_WHEN_THEN: return whenThenNodeToJson(pObj, pJson); case QUERY_NODE_CASE_WHEN: return caseWhenNodeToJson(pObj, pJson); + case QUERY_NODE_EVENT_WINDOW: + return eventWindowNodeToJson(pObj, pJson); case QUERY_NODE_SET_OPERATOR: return setOperatorToJson(pObj, pJson); case QUERY_NODE_SELECT_STMT: return selectStmtToJson(pObj, pJson); - case QUERY_NODE_VNODE_MODIF_STMT: + case QUERY_NODE_VNODE_MODIFY_STMT: + return vnodeModifyStmtToJson(pObj, pJson); case QUERY_NODE_CREATE_DATABASE_STMT: - break; + return createDatabaseStmtToJson(pObj, pJson); case QUERY_NODE_ALTER_DATABASE_STMT: return alterDatabaseStmtToJson(pObj, pJson); + case QUERY_NODE_TRIM_DATABASE_STMT: + return trimDatabaseStmtToJson(pObj, pJson); case QUERY_NODE_CREATE_TABLE_STMT: - break; + return createTableStmtToJson(pObj, pJson); + case QUERY_NODE_CREATE_SUBTABLE_CLAUSE: + return createSubTableClauseToJson(pObj, pJson); + case QUERY_NODE_CREATE_MULTI_TABLES_STMT: + return createMultiTablesStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_TABLE_CLAUSE: + return dropTableClauseToJson(pObj, pJson); + case QUERY_NODE_DROP_TABLE_STMT: + return dropTableStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_SUPER_TABLE_STMT: + return dropStableStmtToJson(pObj, pJson); case QUERY_NODE_ALTER_TABLE_STMT: return alterTableStmtToJson(pObj, pJson); + case QUERY_NODE_ALTER_SUPER_TABLE_STMT: + return alterStableStmtToJson(pObj, pJson); + case QUERY_NODE_CREATE_USER_STMT: + return createUserStmtToJson(pObj, pJson); + case QUERY_NODE_ALTER_USER_STMT: + return alterUserStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_USER_STMT: + return dropUserStmtToJson(pObj, pJson); case QUERY_NODE_USE_DATABASE_STMT: - break; + return useDatabaseStmtToJson(pObj, pJson); + case QUERY_NODE_CREATE_DNODE_STMT: + return createDnodeStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_DNODE_STMT: + return dropDnodeStmtToJson(pObj, pJson); case QUERY_NODE_ALTER_DNODE_STMT: return alterDnodeStmtToJson(pObj, pJson); + case QUERY_NODE_CREATE_INDEX_STMT: + return createIndexStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_INDEX_STMT: + return dropIndexStmtToJson(pObj, pJson); + case QUERY_NODE_CREATE_QNODE_STMT: + return createQnodeStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_QNODE_STMT: + return dropQnodeStmtToJson(pObj, pJson); + case QUERY_NODE_CREATE_SNODE_STMT: + return createSnodeStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_SNODE_STMT: + return dropSnodeStmtToJson(pObj, pJson); + case QUERY_NODE_CREATE_MNODE_STMT: + return createMnodeStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_MNODE_STMT: + return dropMnodeStmtToJson(pObj, pJson); + case QUERY_NODE_CREATE_TOPIC_STMT: + return createTopicStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_TOPIC_STMT: + return dropTopicStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_CGROUP_STMT: + return dropConsumerGroupStmtToJson(pObj, pJson); + case QUERY_NODE_ALTER_LOCAL_STMT: + return alterLocalStmtToJson(pObj, pJson); + case QUERY_NODE_EXPLAIN_STMT: + return explainStmtToJson(pObj, pJson); + case QUERY_NODE_DESCRIBE_STMT: + return describeStmtToJson(pObj, pJson); + case QUERY_NODE_COMPACT_DATABASE_STMT: + return compactDatabaseStmtToJson(pObj, pJson); + case QUERY_NODE_CREATE_STREAM_STMT: + return createStreamStmtToJson(pObj, pJson); + case QUERY_NODE_DROP_STREAM_STMT: + return dropStreamStmtToJson(pObj, pJson); + case QUERY_NODE_BALANCE_VGROUP_STMT: + return TSDB_CODE_SUCCESS; // SBalanceVgroupStmt has no fields to serialize. + case QUERY_NODE_BALANCE_VGROUP_LEADER_STMT: + return TSDB_CODE_SUCCESS; // SBalanceVgroupLeaderStmt has no fields to serialize. + case QUERY_NODE_MERGE_VGROUP_STMT: + return mergeVgroupStmtToJson(pObj, pJson); + case QUERY_NODE_REDISTRIBUTE_VGROUP_STMT: + return redistributeVgroupStmtToJson(pObj, pJson); + case QUERY_NODE_SPLIT_VGROUP_STMT: + return splitVgroupStmtToJson(pObj, pJson); + case QUERY_NODE_GRANT_STMT: + return grantStmtToJson(pObj, pJson); + case QUERY_NODE_REVOKE_STMT: + return revokeStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_DNODES_STMT: + return showDnodesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_MNODES_STMT: + return showMnodesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_QNODES_STMT: + return showQnodesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_CLUSTER_STMT: + return showClusterStmtToJson(pObj, pJson); case QUERY_NODE_SHOW_DATABASES_STMT: + return showDatabasesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_FUNCTIONS_STMT: + return showFunctionsStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_INDEXES_STMT: + return showIndexesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_STABLES_STMT: + return showStablesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_STREAMS_STMT: + return showStreamsStmtToJson(pObj, pJson); case QUERY_NODE_SHOW_TABLES_STMT: + return showTablesStmtToJson(pObj, pJson); case QUERY_NODE_SHOW_TAGS_STMT: - break; - case QUERY_NODE_CREATE_TOPIC_STMT: - return createTopicStmtToJson(pObj, pJson); + return showTagsStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_USERS_STMT: + return showUsersStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_VGROUPS_STMT: + return showVgroupsStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_CONSUMERS_STMT: + return showConsumersStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_VARIABLES_STMT: + return showVariablesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT: + return showDnodeVariablesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_TRANSACTIONS_STMT: + return showTransactionsStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT: + return showSubscriptionsStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_VNODES_STMT: + return showVnodesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_USER_PRIVILEGES_STMT: + return showUserPrivilegesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_CREATE_DATABASE_STMT: + return showCreateDatabaseStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_CREATE_TABLE_STMT: + return showCreateTableStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_CREATE_STABLE_STMT: + return showCreateStableStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT: + return showTableDistributedStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT: + return showLocalVariablesStmtToJson(pObj, pJson); + case QUERY_NODE_SHOW_TABLE_TAGS_STMT: + return showTableTagsStmtToJson(pObj, pJson); case QUERY_NODE_DELETE_STMT: return deleteStmtToJson(pObj, pJson); + case QUERY_NODE_INSERT_STMT: + return insertStmtToJson(pObj, pJson); case QUERY_NODE_LOGIC_PLAN_SCAN: return logicScanNodeToJson(pObj, pJson); case QUERY_NODE_LOGIC_PLAN_JOIN: @@ -4726,6 +6585,9 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) { case QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE: case QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE: return physiStateWindowNodeToJson(pObj, pJson); + case QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT: + case QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT: + return physiEventWindowNodeToJson(pObj, pJson); case QUERY_NODE_PHYSICAL_PLAN_PARTITION: return physiPartitionNodeToJson(pObj, pJson); case QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION: @@ -4769,6 +6631,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) { return jsonToRealTableNode(pJson, pObj); case QUERY_NODE_TEMP_TABLE: return jsonToTempTableNode(pJson, pObj); + case QUERY_NODE_JOIN_TABLE: + return jsonToJoinTableNode(pJson, pObj); case QUERY_NODE_GROUPING_SET: return jsonToGroupingSetNode(pJson, pObj); case QUERY_NODE_ORDER_BY_EXPR: @@ -4791,32 +6655,178 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) { return jsonToDataBlockDescNode(pJson, pObj); case QUERY_NODE_SLOT_DESC: return jsonToSlotDescNode(pJson, pObj); + case QUERY_NODE_COLUMN_DEF: + return jsonToColumnDefNode(pJson, pObj); case QUERY_NODE_DOWNSTREAM_SOURCE: return jsonToDownstreamSourceNode(pJson, pObj); case QUERY_NODE_DATABASE_OPTIONS: return jsonToDatabaseOptions(pJson, pObj); + case QUERY_NODE_TABLE_OPTIONS: + return jsonToTableOptions(pJson, pObj); + case QUERY_NODE_INDEX_OPTIONS: + return jsonToIndexOptions(pJson, pObj); + case QUERY_NODE_EXPLAIN_OPTIONS: + return jsonToExplainOptions(pJson, pObj); + case QUERY_NODE_STREAM_OPTIONS: + return jsonToStreamOptions(pJson, pObj); case QUERY_NODE_LEFT_VALUE: return TSDB_CODE_SUCCESS; // SLeftValueNode has no fields to deserialize. case QUERY_NODE_WHEN_THEN: return jsonToWhenThenNode(pJson, pObj); case QUERY_NODE_CASE_WHEN: return jsonToCaseWhenNode(pJson, pObj); + case QUERY_NODE_EVENT_WINDOW: + return jsonToEventWindowNode(pJson, pObj); case QUERY_NODE_SET_OPERATOR: return jsonToSetOperator(pJson, pObj); case QUERY_NODE_SELECT_STMT: return jsonToSelectStmt(pJson, pObj); + case QUERY_NODE_VNODE_MODIFY_STMT: + return jsonToVnodeModifyStmt(pJson, pObj); + case QUERY_NODE_CREATE_DATABASE_STMT: + return jsonToCreateDatabaseStmt(pJson, pObj); case QUERY_NODE_ALTER_DATABASE_STMT: return jsonToAlterDatabaseStmt(pJson, pObj); + case QUERY_NODE_TRIM_DATABASE_STMT: + return jsonToTrimDatabaseStmt(pJson, pObj); + case QUERY_NODE_CREATE_TABLE_STMT: + return jsonToCreateTableStmt(pJson, pObj); + case QUERY_NODE_CREATE_SUBTABLE_CLAUSE: + return jsonToCreateSubTableClause(pJson, pObj); + case QUERY_NODE_CREATE_MULTI_TABLES_STMT: + return jsonToCreateMultiTablesStmt(pJson, pObj); + case QUERY_NODE_DROP_TABLE_CLAUSE: + return jsonToDropTableClause(pJson, pObj); + case QUERY_NODE_DROP_TABLE_STMT: + return jsonToDropTableStmt(pJson, pObj); + case QUERY_NODE_DROP_SUPER_TABLE_STMT: + return jsonToDropStableStmt(pJson, pObj); case QUERY_NODE_ALTER_TABLE_STMT: return jsonToAlterTableStmt(pJson, pObj); + case QUERY_NODE_ALTER_SUPER_TABLE_STMT: + return jsonToAlterStableStmt(pJson, pObj); + case QUERY_NODE_CREATE_USER_STMT: + return jsonToCreateUserStmt(pJson, pObj); + case QUERY_NODE_ALTER_USER_STMT: + return jsonToAlterUserStmt(pJson, pObj); + case QUERY_NODE_DROP_USER_STMT: + return jsonToDropUserStmt(pJson, pObj); + case QUERY_NODE_USE_DATABASE_STMT: + return jsonToUseDatabaseStmt(pJson, pObj); + case QUERY_NODE_CREATE_DNODE_STMT: + return jsonToCreateDnodeStmt(pJson, pObj); + case QUERY_NODE_DROP_DNODE_STMT: + return jsonToDropDnodeStmt(pJson, pObj); case QUERY_NODE_ALTER_DNODE_STMT: return jsonToAlterDnodeStmt(pJson, pObj); + case QUERY_NODE_CREATE_INDEX_STMT: + return jsonToCreateIndexStmt(pJson, pObj); + case QUERY_NODE_DROP_INDEX_STMT: + return jsonToDropIndexStmt(pJson, pObj); + case QUERY_NODE_CREATE_QNODE_STMT: + return jsonToCreateQnodeStmt(pJson, pObj); + case QUERY_NODE_DROP_QNODE_STMT: + return jsonToDropQnodeStmt(pJson, pObj); + case QUERY_NODE_CREATE_SNODE_STMT: + return jsonToCreateSnodeStmt(pJson, pObj); + case QUERY_NODE_DROP_SNODE_STMT: + return jsonToDropSnodeStmt(pJson, pObj); + case QUERY_NODE_CREATE_MNODE_STMT: + return jsonToCreateMnodeStmt(pJson, pObj); + case QUERY_NODE_DROP_MNODE_STMT: + return jsonToDropMnodeStmt(pJson, pObj); case QUERY_NODE_CREATE_TOPIC_STMT: return jsonToCreateTopicStmt(pJson, pObj); + case QUERY_NODE_DROP_TOPIC_STMT: + return jsonToDropTopicStmt(pJson, pObj); + case QUERY_NODE_DROP_CGROUP_STMT: + return jsonToDropConsumerGroupStmt(pJson, pObj); + case QUERY_NODE_ALTER_LOCAL_STMT: + return jsonToAlterLocalStmt(pJson, pObj); + case QUERY_NODE_EXPLAIN_STMT: + return jsonToExplainStmt(pJson, pObj); + case QUERY_NODE_DESCRIBE_STMT: + return jsonToDescribeStmt(pJson, pObj); + case QUERY_NODE_COMPACT_DATABASE_STMT: + return jsonToCompactDatabaseStmt(pJson, pObj); + case QUERY_NODE_CREATE_STREAM_STMT: + return jsonToCreateStreamStmt(pJson, pObj); + case QUERY_NODE_DROP_STREAM_STMT: + return jsonToDropStreamStmt(pJson, pObj); + case QUERY_NODE_BALANCE_VGROUP_STMT: + return TSDB_CODE_SUCCESS; // SBalanceVgroupStmt has no fields to deserialize. + case QUERY_NODE_BALANCE_VGROUP_LEADER_STMT: + return TSDB_CODE_SUCCESS; // SBalanceVgroupLeaderStmt has no fields to deserialize. + case QUERY_NODE_MERGE_VGROUP_STMT: + return jsonToMergeVgroupStmt(pJson, pObj); + case QUERY_NODE_REDISTRIBUTE_VGROUP_STMT: + return jsonToRedistributeVgroupStmt(pJson, pObj); + case QUERY_NODE_SPLIT_VGROUP_STMT: + return jsonToSplitVgroupStmt(pJson, pObj); + case QUERY_NODE_GRANT_STMT: + return jsonToGrantStmt(pJson, pObj); + case QUERY_NODE_REVOKE_STMT: + return jsonToRevokeStmt(pJson, pObj); + case QUERY_NODE_SHOW_DNODES_STMT: + return jsonToShowDnodesStmt(pJson, pObj); + case QUERY_NODE_SHOW_MNODES_STMT: + return jsonToShowMnodesStmt(pJson, pObj); + case QUERY_NODE_SHOW_QNODES_STMT: + return jsonToShowQnodesStmt(pJson, pObj); + case QUERY_NODE_SHOW_CLUSTER_STMT: + return jsonToShowClusterStmt(pJson, pObj); + case QUERY_NODE_SHOW_DATABASES_STMT: + return jsonToShowDatabasesStmt(pJson, pObj); + case QUERY_NODE_SHOW_FUNCTIONS_STMT: + return jsonToShowFunctionsStmt(pJson, pObj); + case QUERY_NODE_SHOW_INDEXES_STMT: + return jsonToShowIndexesStmt(pJson, pObj); + case QUERY_NODE_SHOW_STABLES_STMT: + return jsonToShowStablesStmt(pJson, pObj); + case QUERY_NODE_SHOW_STREAMS_STMT: + return jsonToShowStreamsStmt(pJson, pObj); + case QUERY_NODE_SHOW_TABLES_STMT: + return jsonToShowTablesStmt(pJson, pObj); + case QUERY_NODE_SHOW_TAGS_STMT: + return jsonToShowTagsStmt(pJson, pObj); + case QUERY_NODE_SHOW_USERS_STMT: + return jsonToShowUsersStmt(pJson, pObj); + case QUERY_NODE_SHOW_VGROUPS_STMT: + return jsonToShowVgroupsStmt(pJson, pObj); + case QUERY_NODE_SHOW_CONSUMERS_STMT: + return jsonToShowConsumersStmt(pJson, pObj); + case QUERY_NODE_SHOW_VARIABLES_STMT: + return jsonToShowVariablesStmt(pJson, pObj); + case QUERY_NODE_SHOW_DNODE_VARIABLES_STMT: + return jsonToShowDnodeVariablesStmt(pJson, pObj); + case QUERY_NODE_SHOW_TRANSACTIONS_STMT: + return jsonToShowTransactionsStmt(pJson, pObj); + case QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT: + return jsonToShowSubscriptionsStmt(pJson, pObj); + case QUERY_NODE_SHOW_VNODES_STMT: + return jsonToShowVnodesStmt(pJson, pObj); + case QUERY_NODE_SHOW_USER_PRIVILEGES_STMT: + return jsonToShowUserPrivilegesStmt(pJson, pObj); + case QUERY_NODE_SHOW_CREATE_DATABASE_STMT: + return jsonToShowCreateDatabaseStmt(pJson, pObj); + case QUERY_NODE_SHOW_CREATE_TABLE_STMT: + return jsonToShowCreateTableStmt(pJson, pObj); + case QUERY_NODE_SHOW_CREATE_STABLE_STMT: + return jsonToShowCreateStableStmt(pJson, pObj); + case QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT: + return jsonToShowTableDistributedStmt(pJson, pObj); + case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT: + return jsonToShowLocalVariablesStmt(pJson, pObj); + case QUERY_NODE_SHOW_TABLE_TAGS_STMT: + return jsonToShowTableTagsStmt(pJson, pObj); case QUERY_NODE_DELETE_STMT: return jsonToDeleteStmt(pJson, pObj); + case QUERY_NODE_INSERT_STMT: + return jsonToInsertStmt(pJson, pObj); case QUERY_NODE_LOGIC_PLAN_SCAN: return jsonToLogicScanNode(pJson, pObj); + case QUERY_NODE_LOGIC_PLAN_JOIN: + return jsonToLogicJoinNode(pJson, pObj); case QUERY_NODE_LOGIC_PLAN_AGG: return jsonToLogicAggNode(pJson, pObj); case QUERY_NODE_LOGIC_PLAN_PROJECT: @@ -4885,6 +6895,9 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) { case QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE: case QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE: return jsonToPhysiStateWindowNode(pJson, pObj); + case QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT: + case QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT: + return jsonToPhysiEventWindowNode(pJson, pObj); case QUERY_NODE_PHYSICAL_PLAN_PARTITION: return jsonToPhysiPartitionNode(pJson, pObj); case QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION: diff --git a/source/libs/nodes/src/nodesEqualFuncs.c b/source/libs/nodes/src/nodesEqualFuncs.c index 4e23999ec2c32e2c82a6b0c569b3ff5c60770ef7..477d27d2719386ca2f41ea50fcd0aadf8f215fc8 100644 --- a/source/libs/nodes/src/nodesEqualFuncs.c +++ b/source/libs/nodes/src/nodesEqualFuncs.c @@ -82,9 +82,7 @@ static bool columnNodeEqual(const SColumnNode* a, const SColumnNode* b) { COMPARE_STRING_FIELD(dbName); COMPARE_STRING_FIELD(tableName); COMPARE_STRING_FIELD(colName); - if (0 == a->tableId) { - COMPARE_STRING_FIELD(tableAlias); - } + COMPARE_STRING_FIELD(tableAlias); return true; } @@ -136,6 +134,7 @@ static bool logicConditionNodeEqual(const SLogicConditionNode* a, const SLogicCo static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) { COMPARE_SCALAR_FIELD(funcId); + COMPARE_STRING_FIELD(functionName); COMPARE_NODE_LIST_FIELD(pParameterList); return true; } diff --git a/source/libs/nodes/src/nodesMsgFuncs.c b/source/libs/nodes/src/nodesMsgFuncs.c index 104f066fa945572bdc8add88452d133668a39b3e..45cebb4559d2f319c4098357eec282e309eb5e78 100644 --- a/source/libs/nodes/src/nodesMsgFuncs.c +++ b/source/libs/nodes/src/nodesMsgFuncs.c @@ -928,7 +928,7 @@ static int32_t msgToDatum(STlv* pTlv, void* pObj) { code = TSDB_CODE_FAILED; break; } - pNode->datum.p = taosMemoryCalloc(1, pNode->node.resType.bytes + VARSTR_HEADER_SIZE + 1); + pNode->datum.p = taosMemoryCalloc(1, pNode->node.resType.bytes + 1); if (NULL == pNode->datum.p) { code = TSDB_CODE_OUT_OF_MEMORY; break; @@ -2317,7 +2317,8 @@ enum { PHY_SORT_MERGE_JOIN_CODE_MERGE_CONDITION, PHY_SORT_MERGE_JOIN_CODE_ON_CONDITIONS, PHY_SORT_MERGE_JOIN_CODE_TARGETS, - PHY_SORT_MERGE_JOIN_CODE_INPUT_TS_ORDER + PHY_SORT_MERGE_JOIN_CODE_INPUT_TS_ORDER, + PHY_SORT_MERGE_JOIN_CODE_TAG_EQUAL_CONDITIONS }; static int32_t physiJoinNodeToMsg(const void* pObj, STlvEncoder* pEncoder) { @@ -2339,7 +2340,9 @@ static int32_t physiJoinNodeToMsg(const void* pObj, STlvEncoder* pEncoder) { if (TSDB_CODE_SUCCESS == code) { code = tlvEncodeEnum(pEncoder, PHY_SORT_MERGE_JOIN_CODE_INPUT_TS_ORDER, pNode->inputTsOrder); } - + if (TSDB_CODE_SUCCESS == code) { + code = tlvEncodeObj(pEncoder, PHY_SORT_MERGE_JOIN_CODE_TAG_EQUAL_CONDITIONS, nodeToMsg, pNode->pTagEqualCondtions); + } return code; } @@ -2368,6 +2371,9 @@ static int32_t msgToPhysiJoinNode(STlvDecoder* pDecoder, void* pObj) { case PHY_SORT_MERGE_JOIN_CODE_INPUT_TS_ORDER: code = tlvDecodeEnum(pTlv, &pNode->inputTsOrder, sizeof(pNode->inputTsOrder)); break; + case PHY_SORT_MERGE_JOIN_CODE_TAG_EQUAL_CONDITIONS: + code = msgToNodeFromTlv(pTlv, (void**)&pNode->pTagEqualCondtions); + break; default: break; } @@ -2945,6 +2951,46 @@ static int32_t msgToPhysiStateWindowNode(STlvDecoder* pDecoder, void* pObj) { return code; } +enum { PHY_EVENT_CODE_WINDOW = 1, PHY_EVENT_CODE_START_COND, PHY_EVENT_CODE_END_COND }; + +static int32_t physiEventWindowNodeToMsg(const void* pObj, STlvEncoder* pEncoder) { + const SEventWinodwPhysiNode* pNode = (const SEventWinodwPhysiNode*)pObj; + + int32_t code = tlvEncodeObj(pEncoder, PHY_EVENT_CODE_WINDOW, physiWindowNodeToMsg, &pNode->window); + if (TSDB_CODE_SUCCESS == code) { + code = tlvEncodeObj(pEncoder, PHY_EVENT_CODE_START_COND, nodeToMsg, pNode->pStartCond); + } + if (TSDB_CODE_SUCCESS == code) { + code = tlvEncodeObj(pEncoder, PHY_EVENT_CODE_END_COND, nodeToMsg, pNode->pEndCond); + } + + return code; +} + +static int32_t msgToPhysiEventWindowNode(STlvDecoder* pDecoder, void* pObj) { + SEventWinodwPhysiNode* pNode = (SEventWinodwPhysiNode*)pObj; + + int32_t code = TSDB_CODE_SUCCESS; + STlv* pTlv = NULL; + tlvForEach(pDecoder, pTlv, code) { + switch (pTlv->type) { + case PHY_EVENT_CODE_WINDOW: + code = tlvDecodeObjFromTlv(pTlv, msgToPhysiWindowNode, &pNode->window); + break; + case PHY_EVENT_CODE_START_COND: + code = msgToNodeFromTlv(pTlv, (void**)&pNode->pStartCond); + break; + case PHY_EVENT_CODE_END_COND: + code = msgToNodeFromTlv(pTlv, (void**)&pNode->pEndCond); + break; + default: + break; + } + } + + return code; +} + enum { PHY_PARTITION_CODE_BASE_NODE = 1, PHY_PARTITION_CODE_EXPR, PHY_PARTITION_CODE_KEYS, PHY_PARTITION_CODE_TARGETS }; static int32_t physiPartitionNodeToMsg(const void* pObj, STlvEncoder* pEncoder) { @@ -3215,7 +3261,8 @@ enum { PHY_QUERY_INSERT_CODE_TABLE_TYPE, PHY_QUERY_INSERT_CODE_TABLE_NAME, PHY_QUERY_INSERT_CODE_VG_ID, - PHY_QUERY_INSERT_CODE_EP_SET + PHY_QUERY_INSERT_CODE_EP_SET, + PHY_QUERY_INSERT_CODE_EXPLAIN }; static int32_t physiQueryInsertNodeToMsg(const void* pObj, STlvEncoder* pEncoder) { @@ -3243,6 +3290,9 @@ static int32_t physiQueryInsertNodeToMsg(const void* pObj, STlvEncoder* pEncoder if (TSDB_CODE_SUCCESS == code) { code = tlvEncodeObj(pEncoder, PHY_QUERY_INSERT_CODE_EP_SET, epSetToMsg, &pNode->epSet); } + if (TSDB_CODE_SUCCESS == code) { + code = tlvEncodeBool(pEncoder, PHY_QUERY_INSERT_CODE_EXPLAIN, pNode->explain); + } return code; } @@ -3278,6 +3328,9 @@ static int32_t msgToPhysiQueryInsertNode(STlvDecoder* pDecoder, void* pObj) { case PHY_QUERY_INSERT_CODE_EP_SET: code = tlvDecodeObjFromTlv(pTlv, msgToEpSet, &pNode->epSet); break; + case PHY_QUERY_INSERT_CODE_EXPLAIN: + code = tlvDecodeBool(pTlv, &pNode->explain); + break; default: break; } @@ -3716,6 +3769,10 @@ static int32_t specificNodeToMsg(const void* pObj, STlvEncoder* pEncoder) { case QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE: code = physiStateWindowNodeToMsg(pObj, pEncoder); break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT: + case QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT: + code = physiEventWindowNodeToMsg(pObj, pEncoder); + break; case QUERY_NODE_PHYSICAL_PLAN_PARTITION: code = physiPartitionNodeToMsg(pObj, pEncoder); break; @@ -3855,6 +3912,10 @@ static int32_t msgToSpecificNode(STlvDecoder* pDecoder, void* pObj) { case QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE: code = msgToPhysiStateWindowNode(pDecoder, pObj); break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT: + case QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT: + code = msgToPhysiEventWindowNode(pDecoder, pObj); + break; case QUERY_NODE_PHYSICAL_PLAN_PARTITION: code = msgToPhysiPartitionNode(pDecoder, pObj); break; diff --git a/source/libs/nodes/src/nodesToSQLFuncs.c b/source/libs/nodes/src/nodesToSQLFuncs.c index 0181da92a9e7eeb5387a68ed18b0b20470979101..b57bba0cc9bd510576e611a5f0416ef3d21982d4 100644 --- a/source/libs/nodes/src/nodesToSQLFuncs.c +++ b/source/libs/nodes/src/nodesToSQLFuncs.c @@ -120,9 +120,9 @@ int32_t nodesNodeToSQL(SNode *pNode, char *buf, int32_t bufSize, int32_t *len) { } if (colNode->tableAlias[0]) { - *len += snprintf(buf + *len, bufSize - *len, "`%s`", colNode->colName); + *len += snprintf(buf + *len, bufSize - *len, "`%s`", colNode->node.userAlias); } else { - *len += snprintf(buf + *len, bufSize - *len, "%s", colNode->colName); + *len += snprintf(buf + *len, bufSize - *len, "%s", colNode->node.userAlias); } return TSDB_CODE_SUCCESS; diff --git a/source/libs/nodes/src/nodesTraverseFuncs.c b/source/libs/nodes/src/nodesTraverseFuncs.c index 106812d55f1cdd08120cb100e338b0b82244e752..ce575ede8a5dd2020c6af39394a72d6fa39cc348 100644 --- a/source/libs/nodes/src/nodesTraverseFuncs.c +++ b/source/libs/nodes/src/nodesTraverseFuncs.c @@ -165,6 +165,17 @@ static EDealRes dispatchExpr(SNode* pNode, ETraversalOrder order, FNodeWalker wa } break; } + case QUERY_NODE_EVENT_WINDOW: { + SEventWindowNode* pEvent = (SEventWindowNode*)pNode; + res = walkExpr(pEvent->pCol, order, walker, pContext); + if (DEAL_RES_ERROR != res && DEAL_RES_END != res) { + res = walkExpr(pEvent->pStartCond, order, walker, pContext); + } + if (DEAL_RES_ERROR != res && DEAL_RES_END != res) { + res = walkExpr(pEvent->pEndCond, order, walker, pContext); + } + break; + } default: break; } @@ -329,6 +340,17 @@ static EDealRes rewriteExpr(SNode** pRawNode, ETraversalOrder order, FNodeRewrit } break; } + case QUERY_NODE_EVENT_WINDOW: { + SEventWindowNode* pEvent = (SEventWindowNode*)pNode; + res = rewriteExpr(&pEvent->pCol, order, rewriter, pContext); + if (DEAL_RES_ERROR != res && DEAL_RES_END != res) { + res = rewriteExpr(&pEvent->pStartCond, order, rewriter, pContext); + } + if (DEAL_RES_ERROR != res && DEAL_RES_END != res) { + res = rewriteExpr(&pEvent->pEndCond, order, rewriter, pContext); + } + break; + } default: break; } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index e28486e0b63c9c44e9ea766b5c497b836ba4fdf1..67747497dbd495f982e9dcfc82ddca02c11b8e6a 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -87,7 +87,7 @@ static void* nodesCalloc(int32_t num, int32_t size) { return (char*)p + 1; } -static void nodesFree(void* p) { +void nodesFree(void* p) { char* ptr = (char*)p - 1; if (0 == *ptr) { taosMemoryFree(ptr); @@ -299,12 +299,14 @@ SNode* nodesMakeNode(ENodeType type) { return makeNode(type, sizeof(SWhenThenNode)); case QUERY_NODE_CASE_WHEN: return makeNode(type, sizeof(SCaseWhenNode)); + case QUERY_NODE_EVENT_WINDOW: + return makeNode(type, sizeof(SEventWindowNode)); case QUERY_NODE_SET_OPERATOR: return makeNode(type, sizeof(SSetOperator)); case QUERY_NODE_SELECT_STMT: return makeNode(type, sizeof(SSelectStmt)); - case QUERY_NODE_VNODE_MODIF_STMT: - return makeNode(type, sizeof(SVnodeModifOpStmt)); + case QUERY_NODE_VNODE_MODIFY_STMT: + return makeNode(type, sizeof(SVnodeModifyOpStmt)); case QUERY_NODE_CREATE_DATABASE_STMT: return makeNode(type, sizeof(SCreateDatabaseStmt)); case QUERY_NODE_DROP_DATABASE_STMT: @@ -319,8 +321,8 @@ SNode* nodesMakeNode(ENodeType type) { return makeNode(type, sizeof(SCreateTableStmt)); case QUERY_NODE_CREATE_SUBTABLE_CLAUSE: return makeNode(type, sizeof(SCreateSubTableClause)); - case QUERY_NODE_CREATE_MULTI_TABLE_STMT: - return makeNode(type, sizeof(SCreateMultiTableStmt)); + case QUERY_NODE_CREATE_MULTI_TABLES_STMT: + return makeNode(type, sizeof(SCreateMultiTablesStmt)); case QUERY_NODE_DROP_TABLE_CLAUSE: return makeNode(type, sizeof(SDropTableClause)); case QUERY_NODE_DROP_TABLE_STMT: @@ -372,8 +374,8 @@ SNode* nodesMakeNode(ENodeType type) { return makeNode(type, sizeof(SDescribeStmt)); case QUERY_NODE_RESET_QUERY_CACHE_STMT: return makeNode(type, sizeof(SNode)); - case QUERY_NODE_COMPACT_STMT: - break; + case QUERY_NODE_COMPACT_DATABASE_STMT: + return makeNode(type, sizeof(SCompactDatabaseStmt)); case QUERY_NODE_CREATE_FUNCTION_STMT: return makeNode(type, sizeof(SCreateFunctionStmt)); case QUERY_NODE_DROP_FUNCTION_STMT: @@ -384,6 +386,8 @@ SNode* nodesMakeNode(ENodeType type) { return makeNode(type, sizeof(SDropStreamStmt)); case QUERY_NODE_BALANCE_VGROUP_STMT: return makeNode(type, sizeof(SBalanceVgroupStmt)); + case QUERY_NODE_BALANCE_VGROUP_LEADER_STMT: + return makeNode(type, sizeof(SBalanceVgroupLeaderStmt)); case QUERY_NODE_MERGE_VGROUP_STMT: return makeNode(type, sizeof(SMergeVgroupStmt)); case QUERY_NODE_REDISTRIBUTE_VGROUP_STMT: @@ -432,6 +436,9 @@ SNode* nodesMakeNode(ENodeType type) { return makeNode(type, sizeof(SShowDnodeVariablesStmt)); case QUERY_NODE_SHOW_CREATE_DATABASE_STMT: return makeNode(type, sizeof(SShowCreateDatabaseStmt)); + case QUERY_NODE_SHOW_DB_ALIVE_STMT: + case QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT: + return makeNode(type, sizeof(SShowAliveStmt)); case QUERY_NODE_SHOW_CREATE_TABLE_STMT: case QUERY_NODE_SHOW_CREATE_STABLE_STMT: return makeNode(type, sizeof(SShowCreateTableStmt)); @@ -535,6 +542,10 @@ SNode* nodesMakeNode(ENodeType type) { return makeNode(type, sizeof(SStateWinodwPhysiNode)); case QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE: return makeNode(type, sizeof(SStreamStateWinodwPhysiNode)); + case QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT: + return makeNode(type, sizeof(SEventWinodwPhysiNode)); + case QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT: + return makeNode(type, sizeof(SStreamEventWinodwPhysiNode)); case QUERY_NODE_PHYSICAL_PLAN_PARTITION: return makeNode(type, sizeof(SPartitionPhysiNode)); case QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION: @@ -765,16 +776,23 @@ void nodesDestroyNode(SNode* pNode) { case QUERY_NODE_COLUMN_REF: // no pointer field break; case QUERY_NODE_WHEN_THEN: { - SWhenThenNode* pStmt = (SWhenThenNode*)pNode; - nodesDestroyNode(pStmt->pWhen); - nodesDestroyNode(pStmt->pThen); + SWhenThenNode* pWhenThen = (SWhenThenNode*)pNode; + nodesDestroyNode(pWhenThen->pWhen); + nodesDestroyNode(pWhenThen->pThen); break; } case QUERY_NODE_CASE_WHEN: { - SCaseWhenNode* pStmt = (SCaseWhenNode*)pNode; - nodesDestroyNode(pStmt->pCase); - nodesDestroyNode(pStmt->pElse); - nodesDestroyList(pStmt->pWhenThenList); + SCaseWhenNode* pCaseWhen = (SCaseWhenNode*)pNode; + nodesDestroyNode(pCaseWhen->pCase); + nodesDestroyNode(pCaseWhen->pElse); + nodesDestroyList(pCaseWhen->pWhenThenList); + break; + } + case QUERY_NODE_EVENT_WINDOW: { + SEventWindowNode* pEvent = (SEventWindowNode*)pNode; + nodesDestroyNode(pEvent->pCol); + nodesDestroyNode(pEvent->pStartCond); + nodesDestroyNode(pEvent->pEndCond); break; } case QUERY_NODE_SET_OPERATOR: { @@ -805,10 +823,12 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyNode((SNode*)pStmt->pSlimit); break; } - case QUERY_NODE_VNODE_MODIF_STMT: { - SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)pNode; + case QUERY_NODE_VNODE_MODIFY_STMT: { + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pNode; destroyVgDataBlockArray(pStmt->pDataBlocks); taosMemoryFreeClear(pStmt->pTableMeta); + nodesDestroyNode(pStmt->pTagCond); + taosArrayDestroy(pStmt->pTableTag); taosHashCleanup(pStmt->pVgroupsHashObj); taosHashCleanup(pStmt->pSubTableHashObj); taosHashCleanup(pStmt->pTableNameHashObj); @@ -819,7 +839,8 @@ void nodesDestroyNode(SNode* pNode) { if (pStmt->freeArrayFunc) { pStmt->freeArrayFunc(pStmt->pVgDataBlocks); } - tdDestroySVCreateTbReq(&pStmt->createTblReq); + tdDestroySVCreateTbReq(pStmt->pCreateTblReq); + taosMemoryFreeClear(pStmt->pCreateTblReq); taosCloseFile(&pStmt->fp); break; } @@ -848,8 +869,8 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyNode((SNode*)pStmt->pOptions); break; } - case QUERY_NODE_CREATE_MULTI_TABLE_STMT: - nodesDestroyList(((SCreateMultiTableStmt*)pNode)->pSubTables); + case QUERY_NODE_CREATE_MULTI_TABLES_STMT: + nodesDestroyList(((SCreateMultiTablesStmt*)pNode)->pSubTables); break; case QUERY_NODE_DROP_TABLE_CLAUSE: // no pointer field break; @@ -906,9 +927,15 @@ void nodesDestroyNode(SNode* pNode) { taosMemoryFree(((SDescribeStmt*)pNode)->pMeta); break; case QUERY_NODE_RESET_QUERY_CACHE_STMT: // no pointer field - case QUERY_NODE_COMPACT_STMT: // no pointer field - case QUERY_NODE_CREATE_FUNCTION_STMT: // no pointer field - case QUERY_NODE_DROP_FUNCTION_STMT: // no pointer field + break; + case QUERY_NODE_COMPACT_DATABASE_STMT: { + SCompactDatabaseStmt* pStmt = (SCompactDatabaseStmt*)pNode; + nodesDestroyNode(pStmt->pStart); + nodesDestroyNode(pStmt->pEnd); + break; + } + case QUERY_NODE_CREATE_FUNCTION_STMT: // no pointer field + case QUERY_NODE_DROP_FUNCTION_STMT: // no pointer field break; case QUERY_NODE_CREATE_STREAM_STMT: { SCreateStreamStmt* pStmt = (SCreateStreamStmt*)pNode; @@ -918,17 +945,22 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyNode(pStmt->pSubtable); break; } - case QUERY_NODE_DROP_STREAM_STMT: // no pointer field - case QUERY_NODE_BALANCE_VGROUP_STMT: // no pointer field - case QUERY_NODE_MERGE_VGROUP_STMT: // no pointer field + case QUERY_NODE_DROP_STREAM_STMT: // no pointer field + case QUERY_NODE_BALANCE_VGROUP_STMT: // no pointer field + case QUERY_NODE_BALANCE_VGROUP_LEADER_STMT: // no pointer field + case QUERY_NODE_MERGE_VGROUP_STMT: // no pointer field break; case QUERY_NODE_REDISTRIBUTE_VGROUP_STMT: nodesDestroyList(((SRedistributeVgroupStmt*)pNode)->pDnodes); break; case QUERY_NODE_SPLIT_VGROUP_STMT: // no pointer field case QUERY_NODE_SYNCDB_STMT: // no pointer field - case QUERY_NODE_GRANT_STMT: // no pointer field - case QUERY_NODE_REVOKE_STMT: // no pointer field + break; + case QUERY_NODE_GRANT_STMT: + nodesDestroyNode(((SGrantStmt*)pNode)->pTagCond); + break; + case QUERY_NODE_REVOKE_STMT: + nodesDestroyNode(((SRevokeStmt*)pNode)->pTagCond); break; case QUERY_NODE_SHOW_DNODES_STMT: case QUERY_NODE_SHOW_MNODES_STMT: @@ -1040,6 +1072,7 @@ void nodesDestroyNode(SNode* pNode) { destroyLogicNode((SLogicNode*)pLogicNode); nodesDestroyNode(pLogicNode->pMergeCondition); nodesDestroyNode(pLogicNode->pOnConditions); + nodesDestroyNode(pLogicNode->pTagEqualConditions); break; } case QUERY_NODE_LOGIC_PLAN_AGG: { @@ -1084,6 +1117,8 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyNode(pLogicNode->pTspk); nodesDestroyNode(pLogicNode->pTsEnd); nodesDestroyNode(pLogicNode->pStateExpr); + nodesDestroyNode(pLogicNode->pStartCond); + nodesDestroyNode(pLogicNode->pEndCond); break; } case QUERY_NODE_LOGIC_PLAN_FILL: { @@ -1170,6 +1205,7 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyNode(pPhyNode->pMergeCondition); nodesDestroyNode(pPhyNode->pOnConditions); nodesDestroyList(pPhyNode->pTargets); + nodesDestroyNode(pPhyNode->pTagEqualCondtions); break; } case QUERY_NODE_PHYSICAL_PLAN_HASH_AGG: { @@ -1232,6 +1268,14 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyNode(pPhyNode->pStateKey); break; } + case QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT: + case QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT: { + SEventWinodwPhysiNode* pPhyNode = (SEventWinodwPhysiNode*)pNode; + destroyWinodwPhysiNode((SWinodwPhysiNode*)pPhyNode); + nodesDestroyNode(pPhyNode->pStartCond); + nodesDestroyNode(pPhyNode->pEndCond); + break; + } case QUERY_NODE_PHYSICAL_PLAN_PARTITION: { destroyPartitionPhysiNode((SPartitionPhysiNode*)pNode); break; @@ -1435,7 +1479,7 @@ SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) { } void nodesListInsertList(SNodeList* pTarget, SListCell* pPos, SNodeList* pSrc) { - if (NULL == pTarget || NULL == pPos || NULL == pSrc) { + if (NULL == pTarget || NULL == pPos || NULL == pSrc || NULL == pSrc->pHead) { return; } @@ -2012,7 +2056,7 @@ char* nodesGetNameFromColumnNode(SNode* pNode) { return "NULL"; } - return ((SColumnNode*)pNode)->colName; + return ((SColumnNode*)pNode)->node.userAlias; } int32_t nodesGetOutputNumFromSlotList(SNodeList* pSlots) { @@ -2072,9 +2116,9 @@ void nodesValueNodeToVariant(const SValueNode* pNode, SVariant* pVal) { case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: - pVal->pz = taosMemoryMalloc(pVal->nLen + VARSTR_HEADER_SIZE + 1); - memcpy(pVal->pz, pNode->datum.p, pVal->nLen + VARSTR_HEADER_SIZE); - pVal->pz[pVal->nLen + VARSTR_HEADER_SIZE] = 0; + pVal->pz = taosMemoryMalloc(pVal->nLen + 1); + memcpy(pVal->pz, pNode->datum.p, pVal->nLen); + pVal->pz[pVal->nLen] = 0; break; case TSDB_DATA_TYPE_JSON: pVal->nLen = getJsonValueLen(pNode->datum.p); diff --git a/source/libs/nodes/test/nodesTestMain.cpp b/source/libs/nodes/test/nodesTestMain.cpp index 0515e8bbc0ae1319042f868b4d70315cc1e31b9c..a7f9a06611b3bd6bec2283b483127ab4737d03b9 100644 --- a/source/libs/nodes/test/nodesTestMain.cpp +++ b/source/libs/nodes/test/nodesTestMain.cpp @@ -28,7 +28,7 @@ static EDealRes rewriterTest(SNode** pNode, void* pContext) { } SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); string tmp = to_string(stoi(((SValueNode*)(pOp->pLeft))->literal) + stoi(((SValueNode*)(pOp->pRight))->literal)); - pVal->literal = strdup(tmp.c_str()); + pVal->literal = taosStrdup(tmp.c_str()); nodesDestroyNode(*pNode); *pNode = (SNode*)pVal; } @@ -40,12 +40,12 @@ TEST(NodesTest, traverseTest) { SOperatorNode* pOp = (SOperatorNode*)pRoot; SOperatorNode* pLeft = (SOperatorNode*)nodesMakeNode(QUERY_NODE_OPERATOR); pLeft->pLeft = (SNode*)nodesMakeNode(QUERY_NODE_VALUE); - ((SValueNode*)(pLeft->pLeft))->literal = strdup("10"); + ((SValueNode*)(pLeft->pLeft))->literal = taosStrdup("10"); pLeft->pRight = (SNode*)nodesMakeNode(QUERY_NODE_VALUE); - ((SValueNode*)(pLeft->pRight))->literal = strdup("5"); + ((SValueNode*)(pLeft->pRight))->literal = taosStrdup("5"); pOp->pLeft = (SNode*)pLeft; pOp->pRight = (SNode*)nodesMakeNode(QUERY_NODE_VALUE); - ((SValueNode*)(pOp->pRight))->literal = strdup("3"); + ((SValueNode*)(pOp->pRight))->literal = taosStrdup("3"); EXPECT_EQ(nodeType(pRoot), QUERY_NODE_OPERATOR); EDealRes res = DEAL_RES_CONTINUE; diff --git a/source/libs/parser/inc/parAst.h b/source/libs/parser/inc/parAst.h index 5fecc95f1bbe7f21091803b2fe6d705eda3efd4b..e08b77e681918ee1b00c46120f9c239c62a2fbcd 100644 --- a/source/libs/parser/inc/parAst.h +++ b/source/libs/parser/inc/parAst.h @@ -82,6 +82,11 @@ typedef struct SAlterOption { SNodeList* pList; } SAlterOption; +typedef struct STokenPair { + SToken first; + SToken second; +} STokenPair; + extern SToken nil_token; void initAstCreateContext(SParseContext* pParseCxt, SAstCreateContext* pCxt); @@ -116,6 +121,7 @@ SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const STok SNode* createOrderByExprNode(SAstCreateContext* pCxt, SNode* pExpr, EOrder order, ENullOrder nullOrder); SNode* createSessionWindowNode(SAstCreateContext* pCxt, SNode* pCol, SNode* pGap); SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pExpr); +SNode* createEventWindowNode(SAstCreateContext* pCxt, SNode* pStartCond, SNode* pEndCond); SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding, SNode* pFill); SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues); @@ -150,6 +156,7 @@ SNode* createDropDatabaseStmt(SAstCreateContext* pCxt, bool ignoreNotExists, STo SNode* createAlterDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName, SNode* pOptions); SNode* createFlushDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName); SNode* createTrimDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName, int32_t maxSpeed); +SNode* createCompactStmt(SAstCreateContext* pCxt, SToken* pDbName, SNode* pStart, SNode* pEnd); SNode* createDefaultTableOptions(SAstCreateContext* pCxt); SNode* createAlterTableOptions(SAstCreateContext* pCxt); SNode* setTableOption(SAstCreateContext* pCxt, SNode* pOptions, ETableOptionType type, void* pVal); @@ -175,6 +182,7 @@ SNode* createShowStmt(SAstCreateContext* pCxt, ENodeType type); SNode* createShowStmtWithCond(SAstCreateContext* pCxt, ENodeType type, SNode* pDbName, SNode* pTbName, EOperatorType tableCondType); SNode* createShowCreateDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName); +SNode* createShowAliveStmt(SAstCreateContext* pCxt, SNode* pDbName, ENodeType type); SNode* createShowCreateTableStmt(SAstCreateContext* pCxt, ENodeType type, SNode* pRealTable); SNode* createShowTableDistributedStmt(SAstCreateContext* pCxt, SNode* pRealTable); SNode* createShowDnodeVariablesStmt(SAstCreateContext* pCxt, SNode* pDnodeId, SNode* pLikePattern); @@ -208,23 +216,28 @@ SNode* setExplainRatio(SAstCreateContext* pCxt, SNode* pOptions, const SToken* p SNode* createExplainStmt(SAstCreateContext* pCxt, bool analyze, SNode* pOptions, SNode* pQuery); SNode* createDescribeStmt(SAstCreateContext* pCxt, SNode* pRealTable); SNode* createResetQueryCacheStmt(SAstCreateContext* pCxt); -SNode* createCompactStmt(SAstCreateContext* pCxt, SNodeList* pVgroups); SNode* createCreateFunctionStmt(SAstCreateContext* pCxt, bool ignoreExists, bool aggFunc, const SToken* pFuncName, - const SToken* pLibPath, SDataType dataType, int32_t bufSize); + const SToken* pLibPath, SDataType dataType, int32_t bufSize, const SToken* pLanguage, + bool orReplace); SNode* createDropFunctionStmt(SAstCreateContext* pCxt, bool ignoreNotExists, const SToken* pFuncName); SNode* createStreamOptions(SAstCreateContext* pCxt); +SNode* setStreamOptions(SAstCreateContext* pCxt, SNode* pOptions, EStreamOptionsSetFlag setflag, SToken* pToken, + SNode* pNode); SNode* createCreateStreamStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* pStreamName, SNode* pRealTable, - SNode* pOptions, SNodeList* pTags, SNode* pSubtable, SNode* pQuery); + SNode* pOptions, SNodeList* pTags, SNode* pSubtable, SNode* pQuery, SNodeList* pCols); SNode* createDropStreamStmt(SAstCreateContext* pCxt, bool ignoreNotExists, SToken* pStreamName); SNode* createKillStmt(SAstCreateContext* pCxt, ENodeType type, const SToken* pId); SNode* createKillQueryStmt(SAstCreateContext* pCxt, const SToken* pQueryId); SNode* createBalanceVgroupStmt(SAstCreateContext* pCxt); +SNode* createBalanceVgroupLeaderStmt(SAstCreateContext* pCxt); SNode* createMergeVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId1, const SToken* pVgId2); SNode* createRedistributeVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId, SNodeList* pDnodes); SNode* createSplitVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId); SNode* createSyncdbStmt(SAstCreateContext* pCxt, const SToken* pDbName); -SNode* createGrantStmt(SAstCreateContext* pCxt, int64_t privileges, SToken* pDbName, SToken* pUserName); -SNode* createRevokeStmt(SAstCreateContext* pCxt, int64_t privileges, SToken* pDbName, SToken* pUserName); +SNode* createGrantStmt(SAstCreateContext* pCxt, int64_t privileges, STokenPair* pPrivLevel, SToken* pUserName, + SNode* pTagCond); +SNode* createRevokeStmt(SAstCreateContext* pCxt, int64_t privileges, STokenPair* pPrivLevel, SToken* pUserName, + SNode* pTagCond); SNode* createDeleteStmt(SAstCreateContext* pCxt, SNode* pTable, SNode* pWhere); SNode* createInsertStmt(SAstCreateContext* pCxt, SNode* pTable, SNodeList* pCols, SNode* pQuery); diff --git a/source/libs/parser/inc/parInsertUtil.h b/source/libs/parser/inc/parInsertUtil.h index 9dd4daec3b3905740aa8ee2d25bcbd7751279aec..303d349b34a1d182bd65a839f866a5b70892afad 100644 --- a/source/libs/parser/inc/parInsertUtil.h +++ b/source/libs/parser/inc/parInsertUtil.h @@ -20,8 +20,6 @@ struct SToken; -#define IS_DATA_COL_ORDERED(spd) ((spd->orderStatus) == (int8_t)ORDER_STATUS_ORDERED) - #define NEXT_TOKEN(pSql, sToken) \ do { \ int32_t index = 0; \ @@ -37,108 +35,27 @@ struct SToken; } \ } while (0) -typedef enum EOrderStatus { - ORDER_STATUS_UNKNOWN = 0, - ORDER_STATUS_ORDERED = 1, - ORDER_STATUS_DISORDERED = 2, -} EOrderStatus; - -typedef enum EValStat { - VAL_STAT_HAS = 0x0, // 0 means has val - VAL_STAT_NONE = 0x01, // 1 means no val -} EValStat; - -typedef struct SBoundColumn { - int32_t offset; // all column offset value - int32_t toffset; // first part offset for SDataRow TODO: get offset from STSchema on future - uint8_t valStat; // EValStat. denote if current column bound or not(0 means has val, 1 means no val) -} SBoundColumn; - -typedef struct { - col_id_t schemaColIdx; - col_id_t boundIdx; - col_id_t finalIdx; -} SBoundIdxInfo; - -typedef struct SParsedDataColInfo { - col_id_t numOfCols; - col_id_t numOfBound; - uint16_t flen; // TODO: get from STSchema - uint16_t allNullLen; // TODO: get from STSchema(base on SDataRow) - uint16_t extendedVarLen; - uint16_t boundNullLen; // bound column len with all NULL value(without VarDataOffsetT/SColIdx part) - col_id_t *boundColumns; // bound column idx according to schema - SBoundColumn *cols; - SBoundIdxInfo *colIdxInfo; - int8_t orderStatus; // bound columns -} SParsedDataColInfo; - -typedef struct SInsertParseBaseContext { - SParseContext *pComCxt; - char *pSql; - SMsgBuf msg; -} SInsertParseBaseContext; - -typedef struct SInsertParseSyntaxCxt { - SParseContext *pComCxt; - char *pSql; - SMsgBuf msg; - SParseMetaCache *pMetaCache; -} SInsertParseSyntaxCxt; - -typedef struct SMemParam { - SRowBuilder *rb; - SSchema *schema; - int32_t toffset; - col_id_t colIdx; -} SMemParam; - -typedef struct { - uint8_t rowType; // default is 0, that is SDataRow - int32_t rowSize; -} SMemRowBuilder; - -typedef struct STableDataBlocks { - int8_t tsSource; // where does the UNIX timestamp come from, server or client - bool ordered; // if current rows are ordered or not - int32_t vgId; // virtual group id - int64_t prevTS; // previous timestamp, recorded to decide if the records array is ts ascending - int32_t numOfTables; // number of tables in current submit block - int32_t rowSize; // row size for current table - uint32_t nAllocSize; - uint32_t headerSize; // header for table info (uid, tid, submit metadata) - uint32_t size; - STableMeta *pTableMeta; // the tableMeta of current table, the table meta will be used during submit, keep a ref to - // avoid to be removed from cache - char *pData; - bool cloned; - int32_t createTbReqLen; - SParsedDataColInfo boundColumnInfo; - SRowBuilder rowBuilder; -} STableDataBlocks; +typedef struct SVgroupDataCxt { + int32_t vgId; + SSubmitReq2 *pData; +} SVgroupDataCxt; -int32_t insGetExtendedRowSize(STableDataBlocks *pBlock); -void insGetSTSRowAppendInfo(uint8_t rowType, SParsedDataColInfo *spd, col_id_t idx, int32_t *toffset, col_id_t *colIdx); -int32_t insSetBlockInfo(SSubmitBlk *pBlocks, STableDataBlocks *dataBuf, int32_t numOfRows, SMsgBuf *pMsg); -int32_t insSchemaIdxCompar(const void *lhs, const void *rhs); -int32_t insBoundIdxCompar(const void *lhs, const void *rhs); -void insSetBoundColumnInfo(SParsedDataColInfo *pColList, SSchema *pSchema, col_id_t numOfCols); -void insDestroyBlockArrayList(SArray *pDataBlockList); -void insDestroyBlockHashmap(SHashObj *pDataBlockHash); -int32_t insInitRowBuilder(SRowBuilder *pBuilder, int16_t schemaVer, SParsedDataColInfo *pColInfo); -int32_t insGetDataBlockFromList(SHashObj *pHashList, void *id, int32_t idLen, int32_t size, int32_t startOffset, - int32_t rowSize, STableMeta *pTableMeta, STableDataBlocks **dataBlocks, - SArray *pBlockList, SVCreateTbReq *pCreateTbReq); -int32_t insMergeTableDataBlocks(SHashObj *pHashObj, SArray **pVgDataBlocks); -int32_t insBuildCreateTbMsg(STableDataBlocks *pBlocks, SVCreateTbReq *pCreateTbReq); -int32_t insAllocateMemForSize(STableDataBlocks *pDataBlock, int32_t allSize); int32_t insCreateSName(SName *pName, struct SToken *pTableName, int32_t acctId, const char *dbName, SMsgBuf *pMsgBuf); -int32_t insFindCol(struct SToken *pColname, int32_t start, int32_t end, SSchema *pSchema); +int16_t insFindCol(struct SToken *pColname, int16_t start, int16_t end, SSchema *pSchema); void insBuildCreateTbReq(SVCreateTbReq *pTbReq, const char *tname, STag *pTag, int64_t suid, const char *sname, SArray *tagName, uint8_t tagNum, int32_t ttl); -int32_t insMemRowAppend(SMsgBuf *pMsgBuf, const void *value, int32_t len, void *param); -int32_t insCheckTimestamp(STableDataBlocks *pDataBlocks, const char *start); -int32_t insBuildOutput(SHashObj *pVgroupsHashObj, SArray *pVgDataBlocks, SArray **pDataBlocks); -void insDestroyDataBlock(STableDataBlocks *pDataBlock); +int32_t insInitBoundColsInfo(int32_t numOfBound, SBoundColInfo *pInfo); +void insCheckTableDataOrder(STableDataCxt *pTableCxt, TSKEY tsKey); +int32_t insGetTableDataCxt(SHashObj *pHash, void *id, int32_t idLen, STableMeta *pTableMeta, + SVCreateTbReq **pCreateTbReq, STableDataCxt **pTableCxt, bool colMode); +int32_t initTableColSubmitData(STableDataCxt *pTableCxt); +int32_t insMergeTableDataCxt(SHashObj *pTableHash, SArray **pVgDataBlocks); +int32_t insBuildVgDataBlocks(SHashObj *pVgroupsHashObj, SArray *pVgDataBlocks, SArray **pDataBlocks); +void insDestroyTableDataCxtHashMap(SHashObj *pTableCxtHash); +void insDestroyVgroupDataCxt(SVgroupDataCxt *pVgCxt); +void insDestroyVgroupDataCxtList(SArray *pVgCxtList); +void insDestroyVgroupDataCxtHashMap(SHashObj *pVgCxtHash); +void insDestroyTableDataCxt(STableDataCxt *pTableCxt); +void insDestroyBoundColInfo(SBoundColInfo *pInfo); #endif // TDENGINE_PAR_INSERT_UTIL_H diff --git a/source/libs/parser/inc/parToken.h b/source/libs/parser/inc/parToken.h index d539e8b37bfbab8cd0995f2f77c8228809b07f7e..86bcc18fd5ed91a39c285a6c98357cf04154352c 100644 --- a/source/libs/parser/inc/parToken.h +++ b/source/libs/parser/inc/parToken.h @@ -175,8 +175,6 @@ _end: void taosCleanupKeywordsTable(); -SToken taosTokenDup(SToken *pToken, char *buf, int32_t len); - #ifdef __cplusplus } #endif diff --git a/source/libs/parser/inc/parUtil.h b/source/libs/parser/inc/parUtil.h index ce5a63f5d07d35fb7a432e878d60372b9bab6cf9..850571eea1533541318c4dc57c60b14311fcc5a8 100644 --- a/source/libs/parser/inc/parUtil.h +++ b/source/libs/parser/inc/parUtil.h @@ -97,9 +97,8 @@ int32_t reserveTableVgroupInCache(int32_t acctId, const char* pDb, const char* p int32_t reserveTableVgroupInCacheExt(const SName* pName, SParseMetaCache* pMetaCache); int32_t reserveDbVgVersionInCache(int32_t acctId, const char* pDb, SParseMetaCache* pMetaCache); int32_t reserveDbCfgInCache(int32_t acctId, const char* pDb, SParseMetaCache* pMetaCache); -int32_t reserveUserAuthInCache(int32_t acctId, const char* pUser, const char* pDb, AUTH_TYPE type, +int32_t reserveUserAuthInCache(int32_t acctId, const char* pUser, const char* pDb, const char* pTable, AUTH_TYPE type, SParseMetaCache* pMetaCache); -int32_t reserveUserAuthInCacheExt(const char* pUser, const SName* pName, AUTH_TYPE type, SParseMetaCache* pMetaCache); int32_t reserveUdfInCache(const char* pFunc, SParseMetaCache* pMetaCache); int32_t reserveTableIndexInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache); int32_t reserveTableCfgInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache); @@ -110,8 +109,7 @@ int32_t getTableVgroupFromCache(SParseMetaCache* pMetaCache, const SName* pName, int32_t getDbVgVersionFromCache(SParseMetaCache* pMetaCache, const char* pDbFName, int32_t* pVersion, int64_t* pDbId, int32_t* pTableNum, int64_t* pStateTs); int32_t getDbCfgFromCache(SParseMetaCache* pMetaCache, const char* pDbFName, SDbCfgInfo* pInfo); -int32_t getUserAuthFromCache(SParseMetaCache* pMetaCache, const char* pUser, const char* pDbFName, AUTH_TYPE type, - bool* pPass); +int32_t getUserAuthFromCache(SParseMetaCache* pMetaCache, SUserAuthInfo* pAuthReq, SUserAuthRes* pAuthRes); int32_t getUdfInfoFromCache(SParseMetaCache* pMetaCache, const char* pFunc, SFuncInfo* pInfo); int32_t getTableIndexFromCache(SParseMetaCache* pMetaCache, const SName* pName, SArray** pIndexes); int32_t getTableCfgFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableCfg** pOutput); diff --git a/source/libs/parser/inc/sql.y b/source/libs/parser/inc/sql.y old mode 100644 new mode 100755 index faa908021e0123998362d6e19ded991cf97ead5a..5918b488b432d06f20f6ea07cc74629e1f590b3d --- a/source/libs/parser/inc/sql.y +++ b/source/libs/parser/inc/sql.y @@ -94,8 +94,8 @@ sysinfo_opt(A) ::= . sysinfo_opt(A) ::= SYSINFO NK_INTEGER(B). { A = taosStr2Int8(B.z, NULL, 10); } /************************************************ grant/revoke ********************************************************/ -cmd ::= GRANT privileges(A) ON priv_level(B) TO user_name(C). { pCxt->pRootNode = createGrantStmt(pCxt, A, &B, &C); } -cmd ::= REVOKE privileges(A) ON priv_level(B) FROM user_name(C). { pCxt->pRootNode = createRevokeStmt(pCxt, A, &B, &C); } +cmd ::= GRANT privileges(A) ON priv_level(B) with_opt(D) TO user_name(C). { pCxt->pRootNode = createGrantStmt(pCxt, A, &B, &C, D); } +cmd ::= REVOKE privileges(A) ON priv_level(B) with_opt(D) FROM user_name(C). { pCxt->pRootNode = createRevokeStmt(pCxt, A, &B, &C, D); } %type privileges { int64_t } %destructor privileges { } @@ -113,11 +113,15 @@ priv_type_list(A) ::= priv_type_list(B) NK_COMMA priv_type(C). priv_type(A) ::= READ. { A = PRIVILEGE_TYPE_READ; } priv_type(A) ::= WRITE. { A = PRIVILEGE_TYPE_WRITE; } -%type priv_level { SToken } +%type priv_level { STokenPair } %destructor priv_level { } -priv_level(A) ::= NK_STAR(B) NK_DOT NK_STAR. { A = B; } -priv_level(A) ::= db_name(B) NK_DOT NK_STAR. { A = B; } -priv_level(A) ::= topic_name(B). { A = B; } +priv_level(A) ::= NK_STAR(B) NK_DOT NK_STAR(C). { A.first = B; A.second = C; } +priv_level(A) ::= db_name(B) NK_DOT NK_STAR(C). { A.first = B; A.second = C; } +priv_level(A) ::= db_name(B) NK_DOT table_name(C). { A.first = B; A.second = C; } +priv_level(A) ::= topic_name(B). { A.first = B; A.second = nil_token; } + +with_opt(A) ::= . { A = NULL; } +with_opt(A) ::= WITH search_condition(B). { A = B; } /************************************************ create/drop/alter dnode *********************************************/ cmd ::= CREATE DNODE dnode_endpoint(A). { pCxt->pRootNode = createCreateDnodeStmt(pCxt, &A, NULL); } @@ -167,6 +171,7 @@ cmd ::= USE db_name(A). cmd ::= ALTER DATABASE db_name(A) alter_db_options(B). { pCxt->pRootNode = createAlterDatabaseStmt(pCxt, &A, B); } cmd ::= FLUSH DATABASE db_name(A). { pCxt->pRootNode = createFlushDatabaseStmt(pCxt, &A); } cmd ::= TRIM DATABASE db_name(A) speed_opt(B). { pCxt->pRootNode = createTrimDatabaseStmt(pCxt, &A, B); } +cmd ::= COMPACT DATABASE db_name(A) start_opt(B) end_opt(C). { pCxt->pRootNode = createCompactStmt(pCxt, &A, B, C); } %type not_exists_opt { bool } %destructor not_exists_opt { } @@ -216,8 +221,8 @@ db_options(A) ::= db_options(B) WAL_RETENTION_SIZE NK_MINUS(D) NK_INTEGER(C). db_options(A) ::= db_options(B) WAL_ROLL_PERIOD NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_WAL_ROLL_PERIOD, &C); } db_options(A) ::= db_options(B) WAL_SEGMENT_SIZE NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_WAL_SEGMENT_SIZE, &C); } db_options(A) ::= db_options(B) STT_TRIGGER NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_STT_TRIGGER, &C); } -db_options(A) ::= db_options(B) TABLE_PREFIX NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_TABLE_PREFIX, &C); } -db_options(A) ::= db_options(B) TABLE_SUFFIX NK_INTEGER(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_TABLE_SUFFIX, &C); } +db_options(A) ::= db_options(B) TABLE_PREFIX signed(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_TABLE_PREFIX, C); } +db_options(A) ::= db_options(B) TABLE_SUFFIX signed(C). { A = setDatabaseOption(pCxt, B, DB_OPTION_TABLE_SUFFIX, C); } alter_db_options(A) ::= alter_db_option(B). { A = createAlterDatabaseOptions(pCxt); A = setAlterDatabaseOption(pCxt, A, &B); } alter_db_options(A) ::= alter_db_options(B) alter_db_option(C). { A = setAlterDatabaseOption(pCxt, B, &C); } @@ -235,6 +240,19 @@ alter_db_option(A) ::= REPLICA NK_INTEGER(B). //alter_db_option(A) ::= STRICT NK_STRING(B). { A.type = DB_OPTION_STRICT; A.val = B; } alter_db_option(A) ::= WAL_LEVEL NK_INTEGER(B). { A.type = DB_OPTION_WAL; A.val = B; } alter_db_option(A) ::= STT_TRIGGER NK_INTEGER(B). { A.type = DB_OPTION_STT_TRIGGER; A.val = B; } +alter_db_option(A) ::= MINROWS NK_INTEGER(B). { A.type = DB_OPTION_MINROWS; A.val = B; } +alter_db_option(A) ::= WAL_RETENTION_PERIOD NK_INTEGER(B). { A.type = DB_OPTION_WAL_RETENTION_PERIOD; A.val = B; } +alter_db_option(A) ::= WAL_RETENTION_PERIOD NK_MINUS(B) NK_INTEGER(C). { + SToken t = B; + t.n = (C.z + C.n) - B.z; + A.type = DB_OPTION_WAL_RETENTION_PERIOD; A.val = t; + } +alter_db_option(A) ::= WAL_RETENTION_SIZE NK_INTEGER(B). { A.type = DB_OPTION_WAL_RETENTION_SIZE; A.val = B; } +alter_db_option(A) ::= WAL_RETENTION_SIZE NK_MINUS(B) NK_INTEGER(C). { + SToken t = B; + t.n = (C.z + C.n) - B.z; + A.type = DB_OPTION_WAL_RETENTION_SIZE; A.val = t; + } %type integer_list { SNodeList* } %destructor integer_list { nodesDestroyList($$); } @@ -258,6 +276,16 @@ retention(A) ::= NK_VARIABLE(B) NK_COLON NK_VARIABLE(C). speed_opt(A) ::= . { A = 0; } speed_opt(A) ::= MAX_SPEED NK_INTEGER(B). { A = taosStr2Int32(B.z, NULL, 10); } +start_opt(A) ::= . { A = NULL; } +start_opt(A) ::= START WITH NK_INTEGER(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &B); } +start_opt(A) ::= START WITH NK_STRING(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &B); } +start_opt(A) ::= START WITH TIMESTAMP NK_STRING(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &B); } + +end_opt(A) ::= . { A = NULL; } +end_opt(A) ::= END WITH NK_INTEGER(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &B); } +end_opt(A) ::= END WITH NK_STRING(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &B); } +end_opt(A) ::= END WITH TIMESTAMP NK_STRING(B). { A = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &B); } + /************************************************ create/drop table/stable ********************************************/ cmd ::= CREATE TABLE not_exists_opt(A) full_table_name(B) NK_LP column_def_list(C) NK_RP tags_def_opt(D) table_options(E). { pCxt->pRootNode = createCreateTableStmt(pCxt, A, B, C, D, E); } @@ -300,7 +328,7 @@ create_subtable_clause(A) ::= %type multi_drop_clause { SNodeList* } %destructor multi_drop_clause { nodesDestroyList($$); } multi_drop_clause(A) ::= drop_table_clause(B). { A = createNodeList(pCxt, B); } -multi_drop_clause(A) ::= multi_drop_clause(B) drop_table_clause(C). { A = addNodeToList(pCxt, B, C); } +multi_drop_clause(A) ::= multi_drop_clause(B) NK_COMMA drop_table_clause(C). { A = addNodeToList(pCxt, B, C); } drop_table_clause(A) ::= exists_opt(B) full_table_name(C). { A = createDropTableClause(pCxt, B, C); } @@ -318,7 +346,7 @@ column_def_list(A) ::= column_def(B). column_def_list(A) ::= column_def_list(B) NK_COMMA column_def(C). { A = addNodeToList(pCxt, B, C); } column_def(A) ::= column_name(B) type_name(C). { A = createColumnDefNode(pCxt, &B, C, NULL); } -column_def(A) ::= column_name(B) type_name(C) COMMENT NK_STRING(D). { A = createColumnDefNode(pCxt, &B, C, &D); } +//column_def(A) ::= column_name(B) type_name(C) COMMENT NK_STRING(D). { A = createColumnDefNode(pCxt, &B, C, &D); } %type type_name { SDataType } %destructor type_name { } @@ -433,6 +461,9 @@ cmd ::= SHOW TAGS FROM table_name_cond(A) from_db_opt(B). cmd ::= SHOW TABLE TAGS tag_list_opt(C) FROM table_name_cond(A) from_db_opt(B). { pCxt->pRootNode = createShowTableTagsStmt(pCxt, A, B, C); } cmd ::= SHOW VNODES NK_INTEGER(A). { pCxt->pRootNode = createShowVnodesStmt(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &A), NULL); } cmd ::= SHOW VNODES NK_STRING(A). { pCxt->pRootNode = createShowVnodesStmt(pCxt, NULL, createValueNode(pCxt, TSDB_DATA_TYPE_VARCHAR, &A)); } +// show alive +cmd ::= SHOW db_name_cond_opt(A) ALIVE. { pCxt->pRootNode = createShowAliveStmt(pCxt, A, QUERY_NODE_SHOW_DB_ALIVE_STMT); } +cmd ::= SHOW CLUSTER ALIVE. { pCxt->pRootNode = createShowAliveStmt(pCxt, NULL, QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT); } db_name_cond_opt(A) ::= . { A = createDefaultDatabaseCondValue(pCxt); } db_name_cond_opt(A) ::= db_name(B) NK_DOT. { A = createIdentifierValueNode(pCxt, &B); } @@ -458,17 +489,19 @@ tag_item(A) ::= column_name(B) column_alias(C). tag_item(A) ::= column_name(B) AS column_alias(C). { A = setProjectionAlias(pCxt, createColumnNode(pCxt, NULL, &B), &C); } /************************************************ create index ********************************************************/ -cmd ::= CREATE SMA INDEX not_exists_opt(D) +cmd ::= CREATE SMA INDEX not_exists_opt(D) full_index_name(A) ON full_table_name(B) index_options(C). { pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_SMA, D, A, B, NULL, C); } +cmd ::= CREATE INDEX not_exists_opt(D) + full_index_name(A) ON full_table_name(B) NK_LP col_name_list(C) NK_RP. { pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_NORMAL, D, A, B, C, NULL); } cmd ::= DROP INDEX exists_opt(B) full_index_name(A). { pCxt->pRootNode = createDropIndexStmt(pCxt, B, A); } full_index_name(A) ::= index_name(B). { A = createRealTableNodeForIndexName(pCxt, NULL, &B); } full_index_name(A) ::= db_name(B) NK_DOT index_name(C). { A = createRealTableNodeForIndexName(pCxt, &B, &C); } -index_options(A) ::= FUNCTION NK_LP func_list(B) NK_RP INTERVAL +index_options(A) ::= FUNCTION NK_LP func_list(B) NK_RP INTERVAL NK_LP duration_literal(C) NK_RP sliding_opt(D) sma_stream_opt(E). { A = createIndexOption(pCxt, B, releaseRawExprNode(pCxt, C), NULL, D, E); } -index_options(A) ::= FUNCTION NK_LP func_list(B) NK_RP INTERVAL - NK_LP duration_literal(C) NK_COMMA duration_literal(D) NK_RP sliding_opt(E) +index_options(A) ::= FUNCTION NK_LP func_list(B) NK_RP INTERVAL + NK_LP duration_literal(C) NK_COMMA duration_literal(D) NK_RP sliding_opt(E) sma_stream_opt(F). { A = createIndexOption(pCxt, B, releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, D), E, F); } %type func_list { SNodeList* } @@ -476,7 +509,15 @@ index_options(A) ::= FUNCTION NK_LP func_list(B) NK_RP INTERVAL func_list(A) ::= func(B). { A = createNodeList(pCxt, B); } func_list(A) ::= func_list(B) NK_COMMA func(C). { A = addNodeToList(pCxt, B, C); } -func(A) ::= function_name(B) NK_LP expression_list(C) NK_RP. { A = createFunctionNode(pCxt, &B, C); } +func(A) ::= sma_func_name(B) NK_LP expression_list(C) NK_RP. { A = createFunctionNode(pCxt, &B, C); } + +%type sma_func_name { SToken } +%destructor sma_func_name { } +sma_func_name(A) ::= function_name(B). { A = B; } +sma_func_name(A) ::= COUNT(B). { A = B; } +sma_func_name(A) ::= FIRST(B). { A = B; } +sma_func_name(A) ::= LAST(B). { A = B; } +sma_func_name(A) ::= LAST_ROW(B). { A = B; } sma_stream_opt(A) ::= . { A = createStreamOptions(pCxt); } sma_stream_opt(A) ::= sma_stream_opt(B) WATERMARK duration_literal(C). { ((SStreamOptions*)B)->pWatermark = releaseRawExprNode(pCxt, C); A = B; } @@ -504,6 +545,7 @@ cmd ::= RESET QUERY CACHE. /************************************************ explain *************************************************************/ cmd ::= EXPLAIN analyze_opt(A) explain_options(B) query_or_subquery(C). { pCxt->pRootNode = createExplainStmt(pCxt, A, B, C); } +cmd ::= EXPLAIN analyze_opt(A) explain_options(B) insert_query(C). { pCxt->pRootNode = createExplainStmt(pCxt, A, B, C); } %type analyze_opt { bool } %destructor analyze_opt { } @@ -514,12 +556,10 @@ explain_options(A) ::= . explain_options(A) ::= explain_options(B) VERBOSE NK_BOOL(C). { A = setExplainVerbose(pCxt, B, &C); } explain_options(A) ::= explain_options(B) RATIO NK_FLOAT(C). { A = setExplainRatio(pCxt, B, &C); } -/************************************************ compact *************************************************************/ -//cmd ::= COMPACT VNODES IN NK_LP integer_list NK_RP. { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } - /************************************************ create/drop function ************************************************/ -cmd ::= CREATE agg_func_opt(A) FUNCTION not_exists_opt(F) function_name(B) - AS NK_STRING(C) OUTPUTTYPE type_name(D) bufsize_opt(E). { pCxt->pRootNode = createCreateFunctionStmt(pCxt, F, A, &B, &C, D, E); } +cmd ::= CREATE or_replace_opt(H) agg_func_opt(A) FUNCTION not_exists_opt(F) + function_name(B) AS NK_STRING(C) OUTPUTTYPE type_name(D) bufsize_opt(E) + language_opt(G). { pCxt->pRootNode = createCreateFunctionStmt(pCxt, F, A, &B, &C, D, E, &G, H); } cmd ::= DROP FUNCTION exists_opt(B) function_name(A). { pCxt->pRootNode = createDropFunctionStmt(pCxt, B, &A); } %type agg_func_opt { bool } @@ -532,20 +572,42 @@ agg_func_opt(A) ::= AGGREGATE. bufsize_opt(A) ::= . { A = 0; } bufsize_opt(A) ::= BUFSIZE NK_INTEGER(B). { A = taosStr2Int32(B.z, NULL, 10); } +%type language_opt { SToken } +%destructor language_opt { } +language_opt(A) ::= . { A = nil_token; } +language_opt(A) ::= LANGUAGE NK_STRING(B). { A = B; } + +%type or_replace_opt { bool } +%destructor or_replace_opt { } +or_replace_opt(A) ::= . { A = false; } +or_replace_opt(A) ::= OR REPLACE. { A = true; } + /************************************************ create/drop stream **************************************************/ cmd ::= CREATE STREAM not_exists_opt(E) stream_name(A) stream_options(B) INTO - full_table_name(C) tags_def_opt(F) subtable_opt(G) AS query_or_subquery(D). { pCxt->pRootNode = createCreateStreamStmt(pCxt, E, &A, C, B, F, G, D); } + full_table_name(C) col_list_opt(H) tag_def_or_ref_opt(F) subtable_opt(G) + AS query_or_subquery(D). { pCxt->pRootNode = createCreateStreamStmt(pCxt, E, &A, C, B, F, G, D, H); } cmd ::= DROP STREAM exists_opt(A) stream_name(B). { pCxt->pRootNode = createDropStreamStmt(pCxt, A, &B); } +%type col_list_opt { SNodeList* } +%destructor col_list_opt { nodesDestroyList($$); } +col_list_opt(A) ::= . { A = NULL; } +col_list_opt(A) ::= NK_LP col_name_list(B) NK_RP. { A = B; } + +%type tag_def_or_ref_opt { SNodeList* } +%destructor tag_def_or_ref_opt { nodesDestroyList($$); } +tag_def_or_ref_opt(A) ::= . { A = NULL; } +tag_def_or_ref_opt(A) ::= tags_def(B). { A = B; } +tag_def_or_ref_opt(A) ::= TAGS NK_LP col_name_list(B) NK_RP. { A = B; } + stream_options(A) ::= . { A = createStreamOptions(pCxt); } -stream_options(A) ::= stream_options(B) TRIGGER AT_ONCE. { ((SStreamOptions*)B)->triggerType = STREAM_TRIGGER_AT_ONCE; A = B; } -stream_options(A) ::= stream_options(B) TRIGGER WINDOW_CLOSE. { ((SStreamOptions*)B)->triggerType = STREAM_TRIGGER_WINDOW_CLOSE; A = B; } -stream_options(A) ::= stream_options(B) TRIGGER MAX_DELAY duration_literal(C). { ((SStreamOptions*)B)->triggerType = STREAM_TRIGGER_MAX_DELAY; ((SStreamOptions*)B)->pDelay = releaseRawExprNode(pCxt, C); A = B; } -stream_options(A) ::= stream_options(B) WATERMARK duration_literal(C). { ((SStreamOptions*)B)->pWatermark = releaseRawExprNode(pCxt, C); A = B; } -stream_options(A) ::= stream_options(B) IGNORE EXPIRED NK_INTEGER(C). { ((SStreamOptions*)B)->ignoreExpired = taosStr2Int8(C.z, NULL, 10); A = B; } -stream_options(A) ::= stream_options(B) FILL_HISTORY NK_INTEGER(C). { ((SStreamOptions*)B)->fillHistory = taosStr2Int8(C.z, NULL, 10); A = B; } -stream_options(A) ::= stream_options(B) DELETE_MARK duration_literal(C). { ((SStreamOptions*)B)->pDeleteMark = releaseRawExprNode(pCxt, C); A = B; } -stream_options(A) ::= stream_options(B) IGNORE UPDATE NK_INTEGER(C). { ((SStreamOptions*)B)->ignoreUpdate = taosStr2Int8(C.z, NULL, 10); A = B; } +stream_options(A) ::= stream_options(B) TRIGGER AT_ONCE(C). { A = setStreamOptions(pCxt, B, SOPT_TRIGGER_TYPE_SET, &C, NULL); } +stream_options(A) ::= stream_options(B) TRIGGER WINDOW_CLOSE(C). { A = setStreamOptions(pCxt, B, SOPT_TRIGGER_TYPE_SET, &C, NULL); } +stream_options(A) ::= stream_options(B) TRIGGER MAX_DELAY(C) duration_literal(D). { A = setStreamOptions(pCxt, B, SOPT_TRIGGER_TYPE_SET, &C, releaseRawExprNode(pCxt, D)); } +stream_options(A) ::= stream_options(B) WATERMARK duration_literal(C). { A = setStreamOptions(pCxt, B, SOPT_WATERMARK_SET, NULL, releaseRawExprNode(pCxt, C)); } +stream_options(A) ::= stream_options(B) IGNORE EXPIRED NK_INTEGER(C). { A = setStreamOptions(pCxt, B, SOPT_IGNORE_EXPIRED_SET, &C, NULL); } +stream_options(A) ::= stream_options(B) FILL_HISTORY NK_INTEGER(C). { A = setStreamOptions(pCxt, B, SOPT_FILL_HISTORY_SET, &C, NULL); } +stream_options(A) ::= stream_options(B) DELETE_MARK duration_literal(C). { A = setStreamOptions(pCxt, B, SOPT_DELETE_MARK_SET, NULL, releaseRawExprNode(pCxt, C)); } +stream_options(A) ::= stream_options(B) IGNORE UPDATE NK_INTEGER(C). { A = setStreamOptions(pCxt, B, SOPT_IGNORE_UPDATE_SET, &C, NULL); } subtable_opt(A) ::= . { A = NULL; } subtable_opt(A) ::= SUBTABLE NK_LP expression(B) NK_RP. { A = releaseRawExprNode(pCxt, B); } @@ -557,6 +619,7 @@ cmd ::= KILL TRANSACTION NK_INTEGER(A). /************************************************ merge/redistribute/ vgroup ******************************************/ cmd ::= BALANCE VGROUP. { pCxt->pRootNode = createBalanceVgroupStmt(pCxt); } +cmd ::= BALANCE VGROUP LEADER. { pCxt->pRootNode = createBalanceVgroupLeaderStmt(pCxt); } cmd ::= MERGE VGROUP NK_INTEGER(A) NK_INTEGER(B). { pCxt->pRootNode = createMergeVgroupStmt(pCxt, &A, &B); } cmd ::= REDISTRIBUTE VGROUP NK_INTEGER(A) dnode_list(B). { pCxt->pRootNode = createRedistributeVgroupStmt(pCxt, &A, B); } cmd ::= SPLIT VGROUP NK_INTEGER(A). { pCxt->pRootNode = createSplitVgroupStmt(pCxt, &A); } @@ -576,9 +639,11 @@ cmd ::= DELETE FROM full_table_name(A) where_clause_opt(B). cmd ::= query_or_subquery(A). { pCxt->pRootNode = A; } /************************************************ insert **************************************************************/ -cmd ::= INSERT INTO full_table_name(A) - NK_LP col_name_list(B) NK_RP query_or_subquery(C). { pCxt->pRootNode = createInsertStmt(pCxt, A, B, C); } -cmd ::= INSERT INTO full_table_name(A) query_or_subquery(B). { pCxt->pRootNode = createInsertStmt(pCxt, A, NULL, B); } +cmd ::= insert_query(A). { pCxt->pRootNode = A; } + +insert_query(A) ::= INSERT INTO full_table_name(D) + NK_LP col_name_list(B) NK_RP query_or_subquery(C). { A = createInsertStmt(pCxt, D, B, C); } +insert_query(A) ::= INSERT INTO full_table_name(C) query_or_subquery(B). { A = createInsertStmt(pCxt, C, NULL, B); } /************************************************ literal *************************************************************/ literal(A) ::= NK_INTEGER(B). { A = createRawExprNode(pCxt, &B, createValueNode(pCxt, TSDB_DATA_TYPE_UBIGINT, &B)); } @@ -742,6 +807,7 @@ pseudo_column(A) ::= WSTART(B). pseudo_column(A) ::= WEND(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); } pseudo_column(A) ::= WDURATION(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); } pseudo_column(A) ::= IROWTS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); } +pseudo_column(A) ::= ISFILLED(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); } pseudo_column(A) ::= QTAGS(B). { A = createRawExprNode(pCxt, &B, createFunctionNode(pCxt, &B, NULL)); } function_expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); } @@ -973,6 +1039,8 @@ twindow_clause_opt(A) ::= twindow_clause_opt(A) ::= INTERVAL NK_LP duration_literal(B) NK_COMMA duration_literal(C) NK_RP sliding_opt(D) fill_opt(E). { A = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C), D, E); } +twindow_clause_opt(A) ::= + EVENT_WINDOW START WITH search_condition(B) END WITH search_condition(C). { A = createEventWindowNode(pCxt, B, C); } sliding_opt(A) ::= . { A = NULL; } sliding_opt(A) ::= SLIDING NK_LP duration_literal(B) NK_RP. { A = releaseRawExprNode(pCxt, B); } @@ -1077,6 +1145,6 @@ null_ordering_opt(A) ::= . null_ordering_opt(A) ::= NULLS FIRST. { A = NULL_ORDER_FIRST; } null_ordering_opt(A) ::= NULLS LAST. { A = NULL_ORDER_LAST; } -%fallback ABORT AFTER ATTACH BEFORE BEGIN BITAND BITNOT BITOR BLOCKS CHANGE COMMA COMPACT CONCAT CONFLICT COPY DEFERRED DELIMITERS DETACH DIVIDE DOT EACH END FAIL - FILE FOR GLOB ID IMMEDIATE IMPORT INITIALLY INSTEAD ISNULL KEY MODULES NK_BITNOT NK_SEMI NOTNULL OF PLUS PRIVILEGE RAISE REPLACE RESTRICT ROW SEMI STAR STATEMENT +%fallback ABORT AFTER ATTACH BEFORE BEGIN BITAND BITNOT BITOR BLOCKS CHANGE COMMA CONCAT CONFLICT COPY DEFERRED DELIMITERS DETACH DIVIDE DOT EACH END FAIL + FILE FOR GLOB ID IMMEDIATE IMPORT INITIALLY INSTEAD ISNULL KEY MODULES NK_BITNOT NK_SEMI NOTNULL OF PLUS PRIVILEGE RAISE RESTRICT ROW SEMI STAR STATEMENT STRICT STRING TIMES VALUES VARIABLE VIEW WAL. diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index d1f861a5fc160fa06af8a57b18e26402c91cbecf..6f866c027eae082a6b214b342ad99fbace18dec2 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -259,8 +259,19 @@ SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) { strcpy(pExpr->userAlias, ((SColumnNode*)pExpr)->colName); } else { int32_t len = TMIN(sizeof(pExpr->aliasName) - 1, pRawExpr->n); - strncpy(pExpr->aliasName, pRawExpr->p, len); - pExpr->aliasName[len] = '\0'; + + // See TS-3398. + // Len of pRawExpr->p could be larger than len of aliasName[TSDB_COL_NAME_LEN]. + // If aliasName is truncated, hash value of aliasName could be the same. + T_MD5_CTX ctx; + tMD5Init(&ctx); + tMD5Update(&ctx, (uint8_t*)pRawExpr->p, pRawExpr->n); + tMD5Final(&ctx); + char* p = pExpr->aliasName; + for (uint8_t i = 0; i < tListLen(ctx.digest); ++i) { + sprintf(p, "%02x", ctx.digest[i]); + p += 2; + } strncpy(pExpr->userAlias, pRawExpr->p, len); pExpr->userAlias[len] = '\0'; } @@ -355,7 +366,7 @@ SNode* createDefaultDatabaseCondValue(SAstCreateContext* pCxt) { SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); CHECK_OUT_OF_MEM(val); - val->literal = strdup(pCxt->pQueryCxt->db); + val->literal = taosStrdup(pCxt->pQueryCxt->db); CHECK_OUT_OF_MEM(val->literal); val->isDuration = false; val->translate = false; @@ -623,6 +634,20 @@ SNode* createStateWindowNode(SAstCreateContext* pCxt, SNode* pExpr) { return (SNode*)state; } +SNode* createEventWindowNode(SAstCreateContext* pCxt, SNode* pStartCond, SNode* pEndCond) { + CHECK_PARSER_STATUS(pCxt); + SEventWindowNode* pEvent = (SEventWindowNode*)nodesMakeNode(QUERY_NODE_EVENT_WINDOW); + CHECK_OUT_OF_MEM(pEvent); + pEvent->pCol = createPrimaryKeyCol(pCxt, NULL); + if (NULL == pEvent->pCol) { + nodesDestroyNode((SNode*)pEvent); + CHECK_OUT_OF_MEM(NULL); + } + pEvent->pStartCond = pStartCond; + pEvent->pEndCond = pEndCond; + return (SNode*)pEvent; +} + SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding, SNode* pFill) { CHECK_PARSER_STATUS(pCxt); @@ -911,8 +936,8 @@ SNode* createAlterDatabaseOptions(SAstCreateContext* pCxt) { pOptions->numOfVgroups = -1; pOptions->singleStable = -1; pOptions->schemaless = -1; - pOptions->walRetentionPeriod = -1; - pOptions->walRetentionSize = -1; + pOptions->walRetentionPeriod = -2; // -1 is a valid value + pOptions->walRetentionSize = -2; // -1 is a valid value pOptions->walRollPeriod = -1; pOptions->walSegmentSize = -1; pOptions->sstTrigger = -1; @@ -921,7 +946,8 @@ SNode* createAlterDatabaseOptions(SAstCreateContext* pCxt) { return (SNode*)pOptions; } -SNode* setDatabaseOption(SAstCreateContext* pCxt, SNode* pOptions, EDatabaseOptionType type, void* pVal) { +static SNode* setDatabaseOptionImpl(SAstCreateContext* pCxt, SNode* pOptions, EDatabaseOptionType type, void* pVal, + bool alter) { CHECK_PARSER_STATUS(pCxt); SDatabaseOptions* pDbOptions = (SDatabaseOptions*)pOptions; switch (type) { @@ -972,7 +998,9 @@ SNode* setDatabaseOption(SAstCreateContext* pCxt, SNode* pOptions, EDatabaseOpti break; case DB_OPTION_REPLICA: pDbOptions->replica = taosStr2Int8(((SToken*)pVal)->z, NULL, 10); - updateWalOptionsDefault(pDbOptions); + if (!alter) { + updateWalOptionsDefault(pDbOptions); + } break; case DB_OPTION_STRICT: COPY_STRING_FORM_STR_TOKEN(pDbOptions->strictStr, (SToken*)pVal); @@ -1007,28 +1035,48 @@ SNode* setDatabaseOption(SAstCreateContext* pCxt, SNode* pOptions, EDatabaseOpti case DB_OPTION_STT_TRIGGER: pDbOptions->sstTrigger = taosStr2Int32(((SToken*)pVal)->z, NULL, 10); break; - case DB_OPTION_TABLE_PREFIX: - pDbOptions->tablePrefix = taosStr2Int32(((SToken*)pVal)->z, NULL, 10); + case DB_OPTION_TABLE_PREFIX: { + SValueNode *pNode = (SValueNode *)pVal; + if (TSDB_DATA_TYPE_BIGINT == pNode->node.resType.type || TSDB_DATA_TYPE_UBIGINT == pNode->node.resType.type) { + pDbOptions->tablePrefix = taosStr2Int32(pNode->literal, NULL, 10); + } else { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid table_prefix data type"); + pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR; + } + nodesDestroyNode((SNode*)pNode); break; - case DB_OPTION_TABLE_SUFFIX: - pDbOptions->tableSuffix = taosStr2Int32(((SToken*)pVal)->z, NULL, 10); + } + case DB_OPTION_TABLE_SUFFIX:{ + SValueNode *pNode = (SValueNode *)pVal; + if (TSDB_DATA_TYPE_BIGINT == pNode->node.resType.type || TSDB_DATA_TYPE_UBIGINT == pNode->node.resType.type) { + pDbOptions->tableSuffix = taosStr2Int32(pNode->literal, NULL, 10); + } else { + snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid table_suffix data type"); + pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR; + } + nodesDestroyNode((SNode*)pNode); break; + } default: break; } return pOptions; } +SNode* setDatabaseOption(SAstCreateContext* pCxt, SNode* pOptions, EDatabaseOptionType type, void* pVal) { + return setDatabaseOptionImpl(pCxt, pOptions, type, pVal, false); +} + SNode* setAlterDatabaseOption(SAstCreateContext* pCxt, SNode* pOptions, SAlterOption* pAlterOption) { CHECK_PARSER_STATUS(pCxt); switch (pAlterOption->type) { case DB_OPTION_KEEP: case DB_OPTION_RETENTIONS: - return setDatabaseOption(pCxt, pOptions, pAlterOption->type, pAlterOption->pList); + return setDatabaseOptionImpl(pCxt, pOptions, pAlterOption->type, pAlterOption->pList, true); default: break; } - return setDatabaseOption(pCxt, pOptions, pAlterOption->type, &pAlterOption->val); + return setDatabaseOptionImpl(pCxt, pOptions, pAlterOption->type, &pAlterOption->val, true); } SNode* createCreateDatabaseStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* pDbName, SNode* pOptions) { @@ -1091,6 +1139,19 @@ SNode* createTrimDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName, int32_t return (SNode*)pStmt; } +SNode* createCompactStmt(SAstCreateContext* pCxt, SToken* pDbName, SNode* pStart, SNode* pEnd) { + CHECK_PARSER_STATUS(pCxt); + if (!checkDbName(pCxt, pDbName, false)) { + return NULL; + } + SCompactDatabaseStmt* pStmt = (SCompactDatabaseStmt*)nodesMakeNode(QUERY_NODE_COMPACT_DATABASE_STMT); + CHECK_OUT_OF_MEM(pStmt); + COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbName); + pStmt->pStart = pStart; + pStmt->pEnd = pEnd; + return (SNode*)pStmt; +} + SNode* createDefaultTableOptions(SAstCreateContext* pCxt) { CHECK_PARSER_STATUS(pCxt); STableOptions* pOptions = (STableOptions*)nodesMakeNode(QUERY_NODE_TABLE_OPTIONS); @@ -1213,7 +1274,7 @@ SNode* createCreateSubTableClause(SAstCreateContext* pCxt, bool ignoreExists, SN SNode* createCreateMultiTableStmt(SAstCreateContext* pCxt, SNodeList* pSubTables) { CHECK_PARSER_STATUS(pCxt); - SCreateMultiTableStmt* pStmt = (SCreateMultiTableStmt*)nodesMakeNode(QUERY_NODE_CREATE_MULTI_TABLE_STMT); + SCreateMultiTablesStmt* pStmt = (SCreateMultiTablesStmt*)nodesMakeNode(QUERY_NODE_CREATE_MULTI_TABLES_STMT); CHECK_OUT_OF_MEM(pStmt); pStmt->pSubTables = pSubTables; return (SNode*)pStmt; @@ -1374,6 +1435,38 @@ SNode* createShowCreateDatabaseStmt(SAstCreateContext* pCxt, SToken* pDbName) { return (SNode*)pStmt; } +SNode* createShowAliveStmt(SAstCreateContext* pCxt, SNode* pNode, ENodeType type) { + CHECK_PARSER_STATUS(pCxt); + SToken dbToken = {0}; + SToken* pDbToken = NULL; + + if (pNode) { + SValueNode* pDbName = (SValueNode*)pNode; + if (pDbName->literal) { + dbToken.z = pDbName->literal; + dbToken.n = strlen(pDbName->literal); + pDbToken = &dbToken; + } + } + + if (pDbToken && !checkDbName(pCxt, pDbToken, true)) { + nodesDestroyNode(pNode); + return NULL; + } + + SShowAliveStmt* pStmt = (SShowAliveStmt*)nodesMakeNode(type); + CHECK_OUT_OF_MEM(pStmt); + + if (pDbToken) { + COPY_STRING_FORM_ID_TOKEN(pStmt->dbName, pDbToken); + } + if (pNode) { + nodesDestroyNode(pNode); + } + + return (SNode*)pStmt; +} + SNode* createShowCreateTableStmt(SAstCreateContext* pCxt, ENodeType type, SNode* pRealTable) { CHECK_PARSER_STATUS(pCxt); SShowCreateTableStmt* pStmt = (SShowCreateTableStmt*)nodesMakeNode(type); @@ -1435,7 +1528,7 @@ SNode* createCreateUserStmt(SAstCreateContext* pCxt, SToken* pUserName, const ST } SCreateUserStmt* pStmt = (SCreateUserStmt*)nodesMakeNode(QUERY_NODE_CREATE_USER_STMT); CHECK_OUT_OF_MEM(pStmt); - COPY_STRING_FORM_ID_TOKEN(pStmt->useName, pUserName); + COPY_STRING_FORM_ID_TOKEN(pStmt->userName, pUserName); strcpy(pStmt->password, password); pStmt->sysinfo = sysinfo; return (SNode*)pStmt; @@ -1448,7 +1541,7 @@ SNode* createAlterUserStmt(SAstCreateContext* pCxt, SToken* pUserName, int8_t al } SAlterUserStmt* pStmt = (SAlterUserStmt*)nodesMakeNode(QUERY_NODE_ALTER_USER_STMT); CHECK_OUT_OF_MEM(pStmt); - COPY_STRING_FORM_ID_TOKEN(pStmt->useName, pUserName); + COPY_STRING_FORM_ID_TOKEN(pStmt->userName, pUserName); pStmt->alterType = alterType; switch (alterType) { case TSDB_ALTER_USER_PASSWD: { @@ -1479,7 +1572,7 @@ SNode* createDropUserStmt(SAstCreateContext* pCxt, SToken* pUserName) { } SDropUserStmt* pStmt = (SDropUserStmt*)nodesMakeNode(QUERY_NODE_DROP_USER_STMT); CHECK_OUT_OF_MEM(pStmt); - COPY_STRING_FORM_ID_TOKEN(pStmt->useName, pUserName); + COPY_STRING_FORM_ID_TOKEN(pStmt->userName, pUserName); return (SNode*)pStmt; } @@ -1722,28 +1815,40 @@ SNode* createResetQueryCacheStmt(SAstCreateContext* pCxt) { return pStmt; } -SNode* createCompactStmt(SAstCreateContext* pCxt, SNodeList* pVgroups) { - CHECK_PARSER_STATUS(pCxt); - SNode* pStmt = nodesMakeNode(QUERY_NODE_COMPACT_STMT); - CHECK_OUT_OF_MEM(pStmt); - return pStmt; +static int32_t convertUdfLanguageType(SAstCreateContext* pCxt, const SToken* pLanguageToken, int8_t* pLanguage) { + if (TK_NK_NIL == pLanguageToken->type || 0 == strncasecmp(pLanguageToken->z + 1, "c", pLanguageToken->n - 2)) { + *pLanguage = TSDB_FUNC_SCRIPT_BIN_LIB; + } else if (0 == strncasecmp(pLanguageToken->z + 1, "python", pLanguageToken->n - 2)) { + *pLanguage = TSDB_FUNC_SCRIPT_PYTHON; + } else { + pCxt->errCode = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, + "udf programming language supports c and python"); + } + return pCxt->errCode; } SNode* createCreateFunctionStmt(SAstCreateContext* pCxt, bool ignoreExists, bool aggFunc, const SToken* pFuncName, - const SToken* pLibPath, SDataType dataType, int32_t bufSize) { + const SToken* pLibPath, SDataType dataType, int32_t bufSize, const SToken* pLanguage, + bool orReplace) { CHECK_PARSER_STATUS(pCxt); if (pLibPath->n <= 2) { pCxt->errCode = TSDB_CODE_PAR_SYNTAX_ERROR; return NULL; } + int8_t language = 0; + if (TSDB_CODE_SUCCESS != convertUdfLanguageType(pCxt, pLanguage, &language)) { + return NULL; + } SCreateFunctionStmt* pStmt = (SCreateFunctionStmt*)nodesMakeNode(QUERY_NODE_CREATE_FUNCTION_STMT); CHECK_OUT_OF_MEM(pStmt); + pStmt->orReplace = orReplace; pStmt->ignoreExists = ignoreExists; COPY_STRING_FORM_ID_TOKEN(pStmt->funcName, pFuncName); pStmt->isAgg = aggFunc; COPY_STRING_FORM_STR_TOKEN(pStmt->libraryPath, pLibPath); pStmt->outputDt = dataType; pStmt->bufSize = bufSize; + pStmt->language = language; return (SNode*)pStmt; } @@ -1760,15 +1865,68 @@ SNode* createStreamOptions(SAstCreateContext* pCxt) { CHECK_PARSER_STATUS(pCxt); SStreamOptions* pOptions = (SStreamOptions*)nodesMakeNode(QUERY_NODE_STREAM_OPTIONS); CHECK_OUT_OF_MEM(pOptions); - pOptions->triggerType = STREAM_TRIGGER_AT_ONCE; + pOptions->triggerType = STREAM_TRIGGER_WINDOW_CLOSE; pOptions->fillHistory = STREAM_DEFAULT_FILL_HISTORY; pOptions->ignoreExpired = STREAM_DEFAULT_IGNORE_EXPIRED; pOptions->ignoreUpdate = STREAM_DEFAULT_IGNORE_UPDATE; return (SNode*)pOptions; } +static int8_t getTriggerType(uint32_t tokenType) { + switch (tokenType) { + case TK_AT_ONCE: + return STREAM_TRIGGER_AT_ONCE; + case TK_WINDOW_CLOSE: + return STREAM_TRIGGER_WINDOW_CLOSE; + case TK_MAX_DELAY: + return STREAM_TRIGGER_MAX_DELAY; + default: + break; + } + return STREAM_TRIGGER_WINDOW_CLOSE; +} + +SNode* setStreamOptions(SAstCreateContext* pCxt, SNode* pOptions, EStreamOptionsSetFlag setflag, SToken* pToken, + SNode* pNode) { + SStreamOptions* pStreamOptions = (SStreamOptions*)pOptions; + if (BIT_FLAG_TEST_MASK(setflag, pStreamOptions->setFlag)) { + pCxt->errCode = + generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "stream options each item is only set once"); + return pOptions; + } + + switch (setflag) { + case SOPT_TRIGGER_TYPE_SET: + pStreamOptions->triggerType = getTriggerType(pToken->type); + if (STREAM_TRIGGER_MAX_DELAY == pStreamOptions->triggerType) { + pStreamOptions->pDelay = pNode; + } + break; + case SOPT_WATERMARK_SET: + pStreamOptions->pWatermark = pNode; + break; + case SOPT_DELETE_MARK_SET: + pStreamOptions->pDeleteMark = pNode; + break; + case SOPT_FILL_HISTORY_SET: + pStreamOptions->fillHistory = taosStr2Int8(pToken->z, NULL, 10); + break; + case SOPT_IGNORE_EXPIRED_SET: + pStreamOptions->ignoreExpired = taosStr2Int8(pToken->z, NULL, 10); + break; + case SOPT_IGNORE_UPDATE_SET: + pStreamOptions->ignoreUpdate = taosStr2Int8(pToken->z, NULL, 10); + break; + default: + break; + } + BIT_FLAG_SET_MASK(pStreamOptions->setFlag, setflag); + + return pOptions; +} + SNode* createCreateStreamStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken* pStreamName, SNode* pRealTable, - SNode* pOptions, SNodeList* pTags, SNode* pSubtable, SNode* pQuery) { + SNode* pOptions, SNodeList* pTags, SNode* pSubtable, SNode* pQuery, SNodeList* pCols) { CHECK_PARSER_STATUS(pCxt); if (!checkStreamName(pCxt, pStreamName)) { return NULL; @@ -1776,16 +1934,15 @@ SNode* createCreateStreamStmt(SAstCreateContext* pCxt, bool ignoreExists, SToken SCreateStreamStmt* pStmt = (SCreateStreamStmt*)nodesMakeNode(QUERY_NODE_CREATE_STREAM_STMT); CHECK_OUT_OF_MEM(pStmt); COPY_STRING_FORM_ID_TOKEN(pStmt->streamName, pStreamName); - if (NULL != pRealTable) { - strcpy(pStmt->targetDbName, ((SRealTableNode*)pRealTable)->table.dbName); - strcpy(pStmt->targetTabName, ((SRealTableNode*)pRealTable)->table.tableName); - nodesDestroyNode(pRealTable); - } + strcpy(pStmt->targetDbName, ((SRealTableNode*)pRealTable)->table.dbName); + strcpy(pStmt->targetTabName, ((SRealTableNode*)pRealTable)->table.tableName); + nodesDestroyNode(pRealTable); pStmt->ignoreExists = ignoreExists; pStmt->pOptions = (SStreamOptions*)pOptions; pStmt->pQuery = pQuery; pStmt->pTags = pTags; pStmt->pSubtable = pSubtable; + pStmt->pCols = pCols; return (SNode*)pStmt; } @@ -1824,6 +1981,13 @@ SNode* createBalanceVgroupStmt(SAstCreateContext* pCxt) { return (SNode*)pStmt; } +SNode* createBalanceVgroupLeaderStmt(SAstCreateContext* pCxt) { + CHECK_PARSER_STATUS(pCxt); + SBalanceVgroupLeaderStmt* pStmt = (SBalanceVgroupLeaderStmt*)nodesMakeNode(QUERY_NODE_BALANCE_VGROUP_LEADER_STMT); + CHECK_OUT_OF_MEM(pStmt); + return (SNode*)pStmt; +} + SNode* createMergeVgroupStmt(SAstCreateContext* pCxt, const SToken* pVgId1, const SToken* pVgId2) { CHECK_PARSER_STATUS(pCxt); SMergeVgroupStmt* pStmt = (SMergeVgroupStmt*)nodesMakeNode(QUERY_NODE_MERGE_VGROUP_STMT); @@ -1857,29 +2021,39 @@ SNode* createSyncdbStmt(SAstCreateContext* pCxt, const SToken* pDbName) { return pStmt; } -SNode* createGrantStmt(SAstCreateContext* pCxt, int64_t privileges, SToken* pDbName, SToken* pUserName) { +SNode* createGrantStmt(SAstCreateContext* pCxt, int64_t privileges, STokenPair* pPrivLevel, SToken* pUserName, + SNode* pTagCond) { CHECK_PARSER_STATUS(pCxt); - if (!checkDbName(pCxt, pDbName, false) || !checkUserName(pCxt, pUserName)) { + if (!checkDbName(pCxt, &pPrivLevel->first, false) || !checkUserName(pCxt, pUserName)) { return NULL; } SGrantStmt* pStmt = (SGrantStmt*)nodesMakeNode(QUERY_NODE_GRANT_STMT); CHECK_OUT_OF_MEM(pStmt); pStmt->privileges = privileges; - COPY_STRING_FORM_ID_TOKEN(pStmt->objName, pDbName); + COPY_STRING_FORM_ID_TOKEN(pStmt->objName, &pPrivLevel->first); + if (TK_NK_NIL != pPrivLevel->second.type && TK_NK_STAR != pPrivLevel->second.type) { + COPY_STRING_FORM_ID_TOKEN(pStmt->tabName, &pPrivLevel->second); + } COPY_STRING_FORM_ID_TOKEN(pStmt->userName, pUserName); + pStmt->pTagCond = pTagCond; return (SNode*)pStmt; } -SNode* createRevokeStmt(SAstCreateContext* pCxt, int64_t privileges, SToken* pDbName, SToken* pUserName) { +SNode* createRevokeStmt(SAstCreateContext* pCxt, int64_t privileges, STokenPair* pPrivLevel, SToken* pUserName, + SNode* pTagCond) { CHECK_PARSER_STATUS(pCxt); - if (!checkDbName(pCxt, pDbName, false) || !checkUserName(pCxt, pUserName)) { + if (!checkDbName(pCxt, &pPrivLevel->first, false) || !checkUserName(pCxt, pUserName)) { return NULL; } SRevokeStmt* pStmt = (SRevokeStmt*)nodesMakeNode(QUERY_NODE_REVOKE_STMT); CHECK_OUT_OF_MEM(pStmt); pStmt->privileges = privileges; - COPY_STRING_FORM_ID_TOKEN(pStmt->objName, pDbName); + COPY_STRING_FORM_ID_TOKEN(pStmt->objName, &pPrivLevel->first); + if (TK_NK_NIL != pPrivLevel->second.type && TK_NK_STAR != pPrivLevel->second.type) { + COPY_STRING_FORM_ID_TOKEN(pStmt->tabName, &pPrivLevel->second); + } COPY_STRING_FORM_ID_TOKEN(pStmt->userName, pUserName); + pStmt->pTagCond = pTagCond; return (SNode*)pStmt; } diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c index 8346ab8c05e7dd606b0223ad53663d69386d7927..5db1f5dbdbca70bed529373c3bb2caa76d74efd2 100644 --- a/source/libs/parser/src/parAstParser.c +++ b/source/libs/parser/src/parAstParser.c @@ -154,7 +154,8 @@ static int32_t collectMetaKeyFromRealTableImpl(SCollectMetaKeyCxt* pCxt, const c code = reserveTableVgroupInCache(pCxt->pParseCxt->acctId, pDb, pTable, pCxt->pMetaCache); } if (TSDB_CODE_SUCCESS == code) { - code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pDb, authType, pCxt->pMetaCache); + code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pDb, pTable, authType, + pCxt->pMetaCache); } if (TSDB_CODE_SUCCESS == code) { code = reserveDbVgInfoInCache(pCxt->pParseCxt->acctId, pDb, pCxt->pMetaCache); @@ -166,7 +167,8 @@ static int32_t collectMetaKeyFromRealTableImpl(SCollectMetaKeyCxt* pCxt, const c code = reserveDnodeRequiredInCache(pCxt->pMetaCache); } if (TSDB_CODE_SUCCESS == code && - (0 == strcmp(pTable, TSDB_INS_TABLE_TAGS) || 0 == strcmp(pTable, TSDB_INS_TABLE_TABLES)) && + (0 == strcmp(pTable, TSDB_INS_TABLE_TAGS) || 0 == strcmp(pTable, TSDB_INS_TABLE_TABLES) || + 0 == strcmp(pTable, TSDB_INS_TABLE_COLS)) && QUERY_NODE_SELECT_STMT == nodeType(pCxt->pStmt)) { code = collectMetaKeyFromInsTags(pCxt); } @@ -246,13 +248,13 @@ static int32_t collectMetaKeyFromCreateTable(SCollectMetaKeyCxt* pCxt, SCreateTa code = reserveTableVgroupInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, pCxt->pMetaCache); } if (TSDB_CODE_SUCCESS == code) { - code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pStmt->dbName, AUTH_TYPE_WRITE, + code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pStmt->dbName, NULL, AUTH_TYPE_WRITE, pCxt->pMetaCache); } return code; } -static int32_t collectMetaKeyFromCreateMultiTable(SCollectMetaKeyCxt* pCxt, SCreateMultiTableStmt* pStmt) { +static int32_t collectMetaKeyFromCreateMultiTable(SCollectMetaKeyCxt* pCxt, SCreateMultiTablesStmt* pStmt) { int32_t code = TSDB_CODE_SUCCESS; SNode* pNode = NULL; FOREACH(pNode, pStmt->pSubTables) { @@ -266,8 +268,8 @@ static int32_t collectMetaKeyFromCreateMultiTable(SCollectMetaKeyCxt* pCxt, SCre code = reserveTableVgroupInCache(pCxt->pParseCxt->acctId, pClause->dbName, pClause->tableName, pCxt->pMetaCache); } if (TSDB_CODE_SUCCESS == code) { - code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pClause->dbName, AUTH_TYPE_WRITE, - pCxt->pMetaCache); + code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pClause->dbName, NULL, + AUTH_TYPE_WRITE, pCxt->pMetaCache); } if (TSDB_CODE_SUCCESS != code) { break; @@ -285,6 +287,10 @@ static int32_t collectMetaKeyFromDropTable(SCollectMetaKeyCxt* pCxt, SDropTableS if (TSDB_CODE_SUCCESS == code) { code = reserveTableVgroupInCache(pCxt->pParseCxt->acctId, pClause->dbName, pClause->tableName, pCxt->pMetaCache); } + if (TSDB_CODE_SUCCESS == code) { + code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pClause->dbName, + pClause->tableName, AUTH_TYPE_WRITE, pCxt->pMetaCache); + } if (TSDB_CODE_SUCCESS != code) { break; } @@ -292,6 +298,11 @@ static int32_t collectMetaKeyFromDropTable(SCollectMetaKeyCxt* pCxt, SDropTableS return code; } +static int32_t collectMetaKeyFromDropStable(SCollectMetaKeyCxt* pCxt, SDropSuperTableStmt* pStmt) { + return reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pStmt->dbName, pStmt->tableName, + AUTH_TYPE_WRITE, pCxt->pMetaCache); +} + static int32_t collectMetaKeyFromAlterTable(SCollectMetaKeyCxt* pCxt, SAlterTableStmt* pStmt) { int32_t code = reserveDbCfgInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache); if (TSDB_CODE_SUCCESS == code) { @@ -300,6 +311,10 @@ static int32_t collectMetaKeyFromAlterTable(SCollectMetaKeyCxt* pCxt, SAlterTabl if (TSDB_CODE_SUCCESS == code) { code = reserveTableVgroupInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, pCxt->pMetaCache); } + if (TSDB_CODE_SUCCESS == code) { + code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pStmt->dbName, pStmt->tableName, + AUTH_TYPE_WRITE, pCxt->pMetaCache); + } return code; } @@ -308,6 +323,10 @@ static int32_t collectMetaKeyFromAlterStable(SCollectMetaKeyCxt* pCxt, SAlterTab if (TSDB_CODE_SUCCESS == code) { code = reserveTableMetaInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, pCxt->pMetaCache); } + if (TSDB_CODE_SUCCESS == code) { + code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pStmt->dbName, pStmt->tableName, + AUTH_TYPE_WRITE, pCxt->pMetaCache); + } return code; } @@ -355,7 +374,12 @@ static int32_t collectMetaKeyFromDescribe(SCollectMetaKeyCxt* pCxt, SDescribeStm } static int32_t collectMetaKeyFromCreateStream(SCollectMetaKeyCxt* pCxt, SCreateStreamStmt* pStmt) { - return collectMetaKeyFromQuery(pCxt, pStmt->pQuery); + int32_t code = + reserveTableMetaInCache(pCxt->pParseCxt->acctId, pStmt->targetDbName, pStmt->targetTabName, pCxt->pMetaCache); + if (TSDB_CODE_SUCCESS == code) { + code = collectMetaKeyFromQuery(pCxt, pStmt->pQuery); + } + return code; } static int32_t collectMetaKeyFromShowDnodes(SCollectMetaKeyCxt* pCxt, SShowStmt* pStmt) { @@ -433,8 +457,9 @@ static int32_t collectMetaKeyFromShowStables(SCollectMetaKeyCxt* pCxt, SShowStmt int32_t code = reserveTableMetaInCache(pCxt->pParseCxt->acctId, TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_STABLES, pCxt->pMetaCache); if (TSDB_CODE_SUCCESS == code) { - code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, - ((SValueNode*)pStmt->pDbName)->literal, AUTH_TYPE_READ_OR_WRITE, pCxt->pMetaCache); + code = + reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, ((SValueNode*)pStmt->pDbName)->literal, + NULL, AUTH_TYPE_READ_OR_WRITE, pCxt->pMetaCache); } return code; } @@ -451,8 +476,9 @@ static int32_t collectMetaKeyFromShowTables(SCollectMetaKeyCxt* pCxt, SShowStmt* code = reserveDbVgInfoInCache(pCxt->pParseCxt->acctId, ((SValueNode*)pStmt->pDbName)->literal, pCxt->pMetaCache); } if (TSDB_CODE_SUCCESS == code) { - code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, - ((SValueNode*)pStmt->pDbName)->literal, AUTH_TYPE_READ_OR_WRITE, pCxt->pMetaCache); + code = + reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, ((SValueNode*)pStmt->pDbName)->literal, + NULL, AUTH_TYPE_READ_OR_WRITE, pCxt->pMetaCache); } return code; } @@ -555,7 +581,8 @@ static int32_t collectMetaKeyFromShowCreateTable(SCollectMetaKeyCxt* pCxt, SShow code = reserveDbCfgInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache); } if (TSDB_CODE_SUCCESS == code) { - code = reserveUserAuthInCacheExt(pCxt->pParseCxt->pUser, &name, AUTH_TYPE_READ, pCxt->pMetaCache); + code = reserveUserAuthInCache(pCxt->pParseCxt->acctId, pCxt->pParseCxt->pUser, pStmt->dbName, NULL, AUTH_TYPE_READ, + pCxt->pMetaCache); } return code; } @@ -600,6 +627,17 @@ static int32_t collectMetaKeyFromShowSubscriptions(SCollectMetaKeyCxt* pCxt, SSh pCxt->pMetaCache); } +static int32_t collectMetaKeyFromCompactDatabase(SCollectMetaKeyCxt* pCxt, SCompactDatabaseStmt* pStmt) { + return reserveDbCfgInCache(pCxt->pParseCxt->acctId, pStmt->dbName, pCxt->pMetaCache); +} + +static int32_t collectMetaKeyFromGrant(SCollectMetaKeyCxt* pCxt, SGrantStmt* pStmt) { + if ('\0' == pStmt->tabName[0]) { + return TSDB_CODE_SUCCESS; + } + return reserveTableMetaInCache(pCxt->pParseCxt->acctId, pStmt->objName, pStmt->tabName, pCxt->pMetaCache); +} + static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) { pCxt->pStmt = pStmt; switch (nodeType(pStmt)) { @@ -613,10 +651,12 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) { return collectMetaKeyFromFlushDatabase(pCxt, (SFlushDatabaseStmt*)pStmt); case QUERY_NODE_CREATE_TABLE_STMT: return collectMetaKeyFromCreateTable(pCxt, (SCreateTableStmt*)pStmt); - case QUERY_NODE_CREATE_MULTI_TABLE_STMT: - return collectMetaKeyFromCreateMultiTable(pCxt, (SCreateMultiTableStmt*)pStmt); + case QUERY_NODE_CREATE_MULTI_TABLES_STMT: + return collectMetaKeyFromCreateMultiTable(pCxt, (SCreateMultiTablesStmt*)pStmt); case QUERY_NODE_DROP_TABLE_STMT: return collectMetaKeyFromDropTable(pCxt, (SDropTableStmt*)pStmt); + case QUERY_NODE_DROP_SUPER_TABLE_STMT: + return collectMetaKeyFromDropStable(pCxt, (SDropSuperTableStmt*)pStmt); case QUERY_NODE_ALTER_TABLE_STMT: return collectMetaKeyFromAlterTable(pCxt, (SAlterTableStmt*)pStmt); case QUERY_NODE_ALTER_SUPER_TABLE_STMT: @@ -631,8 +671,12 @@ static int32_t collectMetaKeyFromQuery(SCollectMetaKeyCxt* pCxt, SNode* pStmt) { return collectMetaKeyFromExplain(pCxt, (SExplainStmt*)pStmt); case QUERY_NODE_DESCRIBE_STMT: return collectMetaKeyFromDescribe(pCxt, (SDescribeStmt*)pStmt); + case QUERY_NODE_COMPACT_DATABASE_STMT: + return collectMetaKeyFromCompactDatabase(pCxt, (SCompactDatabaseStmt*)pStmt); case QUERY_NODE_CREATE_STREAM_STMT: return collectMetaKeyFromCreateStream(pCxt, (SCreateStreamStmt*)pStmt); + case QUERY_NODE_GRANT_STMT: + return collectMetaKeyFromGrant(pCxt, (SGrantStmt*)pStmt); case QUERY_NODE_SHOW_DNODES_STMT: return collectMetaKeyFromShowDnodes(pCxt, (SShowStmt*)pStmt); case QUERY_NODE_SHOW_MNODES_STMT: diff --git a/source/libs/parser/src/parAuthenticator.c b/source/libs/parser/src/parAuthenticator.c index 4fd711e0ea43a0f82b09d598dca866d8ef682b04..1586d8128ba8d425575526ecf5567e688408af42 100644 --- a/source/libs/parser/src/parAuthenticator.c +++ b/source/libs/parser/src/parAuthenticator.c @@ -23,49 +23,112 @@ typedef struct SAuthCxt { int32_t errCode; } SAuthCxt; +typedef struct SSelectAuthCxt { + SAuthCxt* pAuthCxt; + SSelectStmt* pSelect; +} SSelectAuthCxt; + static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt); -static int32_t checkAuth(SAuthCxt* pCxt, const char* pDbName, AUTH_TYPE type) { +static void setUserAuthInfo(SParseContext* pCxt, const char* pDbName, const char* pTabName, AUTH_TYPE type, + SUserAuthInfo* pAuth) { + snprintf(pAuth->user, sizeof(pAuth->user), "%s", pCxt->pUser); + if (NULL == pTabName) { + tNameSetDbName(&pAuth->tbName, pCxt->acctId, pDbName, strlen(pDbName)); + } else { + toName(pCxt->acctId, pDbName, pTabName, &pAuth->tbName); + } + pAuth->type = type; +} + +static int32_t checkAuth(SAuthCxt* pCxt, const char* pDbName, const char* pTabName, AUTH_TYPE type, SNode** pCond) { SParseContext* pParseCxt = pCxt->pParseCxt; if (pParseCxt->isSuperUser) { return TSDB_CODE_SUCCESS; } - SName name; - tNameSetDbName(&name, pParseCxt->acctId, pDbName, strlen(pDbName)); - char dbFname[TSDB_DB_FNAME_LEN] = {0}; - tNameGetFullDbName(&name, dbFname); - int32_t code = TSDB_CODE_SUCCESS; - bool pass = false; + + SUserAuthInfo authInfo = {0}; + setUserAuthInfo(pCxt->pParseCxt, pDbName, pTabName, type, &authInfo); + int32_t code = TSDB_CODE_SUCCESS; + SUserAuthRes authRes = {0}; if (NULL != pCxt->pMetaCache) { - code = getUserAuthFromCache(pCxt->pMetaCache, pParseCxt->pUser, dbFname, type, &pass); + code = getUserAuthFromCache(pCxt->pMetaCache, &authInfo, &authRes); } else { SRequestConnInfo conn = {.pTrans = pParseCxt->pTransporter, .requestId = pParseCxt->requestId, .requestObjRefId = pParseCxt->requestRid, .mgmtEps = pParseCxt->mgmtEpSet}; - - code = catalogChkAuth(pParseCxt->pCatalog, &conn, pParseCxt->pUser, dbFname, type, &pass); + code = catalogChkAuth(pParseCxt->pCatalog, &conn, &authInfo, &authRes); + } + if (TSDB_CODE_SUCCESS == code && NULL != pCond) { + *pCond = authRes.pCond; } - return TSDB_CODE_SUCCESS == code ? (pass ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED) : code; + return TSDB_CODE_SUCCESS == code ? (authRes.pass ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED) : code; } static EDealRes authSubquery(SAuthCxt* pCxt, SNode* pStmt) { return TSDB_CODE_SUCCESS == authQuery(pCxt, pStmt) ? DEAL_RES_CONTINUE : DEAL_RES_ERROR; } +static int32_t mergeStableTagCond(SNode** pWhere, SNode* pTagCond) { + SLogicConditionNode* pLogicCond = (SLogicConditionNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); + if (NULL == pLogicCond) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pLogicCond->node.resType.type = TSDB_DATA_TYPE_BOOL; + pLogicCond->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; + pLogicCond->condType = LOGIC_COND_TYPE_AND; + int32_t code = nodesListMakeStrictAppend(&pLogicCond->pParameterList, pTagCond); + if (TSDB_CODE_SUCCESS == code) { + code = nodesListMakeAppend(&pLogicCond->pParameterList, *pWhere); + } + if (TSDB_CODE_SUCCESS == code) { + *pWhere = (SNode*)pLogicCond; + } else { + nodesDestroyNode((SNode*)pLogicCond); + } + return code; +} + +static int32_t appendStableTagCond(SNode** pWhere, SNode* pTagCond) { + SNode* pTagCondCopy = nodesCloneNode(pTagCond); + if (NULL == pTagCondCopy) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + if (NULL == *pWhere) { + *pWhere = pTagCondCopy; + return TSDB_CODE_SUCCESS; + } + + if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pWhere) && + LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)*pWhere)->condType) { + return nodesListStrictAppend(((SLogicConditionNode*)*pWhere)->pParameterList, pTagCondCopy); + } + + return mergeStableTagCond(pWhere, pTagCondCopy); +} + static EDealRes authSelectImpl(SNode* pNode, void* pContext) { - SAuthCxt* pCxt = pContext; + SSelectAuthCxt* pCxt = pContext; + SAuthCxt* pAuthCxt = pCxt->pAuthCxt; if (QUERY_NODE_REAL_TABLE == nodeType(pNode)) { - pCxt->errCode = checkAuth(pCxt, ((SRealTableNode*)pNode)->table.dbName, AUTH_TYPE_READ); - return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR; + SNode* pTagCond = NULL; + STableNode* pTable = (STableNode*)pNode; + pAuthCxt->errCode = checkAuth(pAuthCxt, pTable->dbName, pTable->tableName, AUTH_TYPE_READ, &pTagCond); + if (TSDB_CODE_SUCCESS == pAuthCxt->errCode && NULL != pTagCond) { + pAuthCxt->errCode = appendStableTagCond(&pCxt->pSelect->pWhere, pTagCond); + } + return TSDB_CODE_SUCCESS == pAuthCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR; } else if (QUERY_NODE_TEMP_TABLE == nodeType(pNode)) { - return authSubquery(pCxt, ((STempTableNode*)pNode)->pSubquery); + return authSubquery(pAuthCxt, ((STempTableNode*)pNode)->pSubquery); } return DEAL_RES_CONTINUE; } static int32_t authSelect(SAuthCxt* pCxt, SSelectStmt* pSelect) { - nodesWalkSelectStmt(pSelect, SQL_CLAUSE_FROM, authSelectImpl, pCxt); + SSelectAuthCxt cxt = {.pAuthCxt = pCxt, .pSelect = pSelect}; + nodesWalkSelectStmt(pSelect, SQL_CLAUSE_FROM, authSelectImpl, &cxt); return pCxt->errCode; } @@ -78,18 +141,27 @@ static int32_t authSetOperator(SAuthCxt* pCxt, SSetOperator* pSetOper) { } static int32_t authDropUser(SAuthCxt* pCxt, SDropUserStmt* pStmt) { - if (!pCxt->pParseCxt->isSuperUser || 0 == strcmp(pStmt->useName, TSDB_DEFAULT_USER)) { + if (!pCxt->pParseCxt->isSuperUser || 0 == strcmp(pStmt->userName, TSDB_DEFAULT_USER)) { return TSDB_CODE_PAR_PERMISSION_DENIED; } return TSDB_CODE_SUCCESS; } static int32_t authDelete(SAuthCxt* pCxt, SDeleteStmt* pDelete) { - return checkAuth(pCxt, ((SRealTableNode*)pDelete->pFromTable)->table.dbName, AUTH_TYPE_WRITE); + SNode* pTagCond = NULL; + STableNode* pTable = (STableNode*)pDelete->pFromTable; + int32_t code = checkAuth(pCxt, pTable->dbName, pTable->tableName, AUTH_TYPE_WRITE, &pTagCond); + if (TSDB_CODE_SUCCESS == code && NULL != pTagCond) { + code = appendStableTagCond(&pDelete->pWhere, pTagCond); + } + return code; } static int32_t authInsert(SAuthCxt* pCxt, SInsertStmt* pInsert) { - int32_t code = checkAuth(pCxt, ((SRealTableNode*)pInsert->pTable)->table.dbName, AUTH_TYPE_WRITE); + SNode* pTagCond = NULL; + STableNode* pTable = (STableNode*)pInsert->pTable; + // todo check tag condition for subtable + int32_t code = checkAuth(pCxt, pTable->dbName, pTable->tableName, AUTH_TYPE_WRITE, &pTagCond); if (TSDB_CODE_SUCCESS == code) { code = authQuery(pCxt, pInsert->pQuery); } @@ -97,22 +169,27 @@ static int32_t authInsert(SAuthCxt* pCxt, SInsertStmt* pInsert) { } static int32_t authShowTables(SAuthCxt* pCxt, SShowStmt* pStmt) { - return checkAuth(pCxt, ((SValueNode*)pStmt->pDbName)->literal, AUTH_TYPE_READ_OR_WRITE); + return checkAuth(pCxt, ((SValueNode*)pStmt->pDbName)->literal, NULL, AUTH_TYPE_READ_OR_WRITE, NULL); } static int32_t authShowCreateTable(SAuthCxt* pCxt, SShowCreateTableStmt* pStmt) { - return checkAuth(pCxt, pStmt->dbName, AUTH_TYPE_READ); + SNode* pTagCond = NULL; + // todo check tag condition for subtable + return checkAuth(pCxt, pStmt->dbName, NULL, AUTH_TYPE_READ, &pTagCond); } static int32_t authCreateTable(SAuthCxt* pCxt, SCreateTableStmt* pStmt) { - return checkAuth(pCxt, pStmt->dbName, AUTH_TYPE_WRITE); + SNode* pTagCond = NULL; + // todo check tag condition for subtable + return checkAuth(pCxt, pStmt->dbName, NULL, AUTH_TYPE_WRITE, &pTagCond); } -static int32_t authCreateMultiTable(SAuthCxt* pCxt, SCreateMultiTableStmt* pStmt) { +static int32_t authCreateMultiTable(SAuthCxt* pCxt, SCreateMultiTablesStmt* pStmt) { int32_t code = TSDB_CODE_SUCCESS; SNode* pNode = NULL; FOREACH(pNode, pStmt->pSubTables) { - code = checkAuth(pCxt, ((SCreateSubTableClause*)pNode)->dbName, AUTH_TYPE_WRITE); + SCreateSubTableClause* pClause = (SCreateSubTableClause*)pNode; + code = checkAuth(pCxt, pClause->dbName, NULL, AUTH_TYPE_WRITE, NULL); if (TSDB_CODE_SUCCESS != code) { break; } @@ -120,6 +197,29 @@ static int32_t authCreateMultiTable(SAuthCxt* pCxt, SCreateMultiTableStmt* pStmt return code; } +static int32_t authDropTable(SAuthCxt* pCxt, SDropTableStmt* pStmt) { + int32_t code = TSDB_CODE_SUCCESS; + SNode* pNode = NULL; + FOREACH(pNode, pStmt->pTables) { + SDropTableClause* pClause = (SDropTableClause*)pNode; + code = checkAuth(pCxt, pClause->dbName, pClause->tableName, AUTH_TYPE_WRITE, NULL); + if (TSDB_CODE_SUCCESS != code) { + break; + } + } + return code; +} + +static int32_t authDropStable(SAuthCxt* pCxt, SDropSuperTableStmt* pStmt) { + return checkAuth(pCxt, pStmt->dbName, pStmt->tableName, AUTH_TYPE_WRITE, NULL); +} + +static int32_t authAlterTable(SAuthCxt* pCxt, SAlterTableStmt* pStmt) { + SNode* pTagCond = NULL; + // todo check tag condition for subtable + return checkAuth(pCxt, pStmt->dbName, pStmt->tableName, AUTH_TYPE_WRITE, NULL); +} + static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) { switch (nodeType(pStmt)) { case QUERY_NODE_SET_OPERATOR: @@ -134,8 +234,15 @@ static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) { return authInsert(pCxt, (SInsertStmt*)pStmt); case QUERY_NODE_CREATE_TABLE_STMT: return authCreateTable(pCxt, (SCreateTableStmt*)pStmt); - case QUERY_NODE_CREATE_MULTI_TABLE_STMT: - return authCreateMultiTable(pCxt, (SCreateMultiTableStmt*)pStmt); + case QUERY_NODE_CREATE_MULTI_TABLES_STMT: + return authCreateMultiTable(pCxt, (SCreateMultiTablesStmt*)pStmt); + case QUERY_NODE_DROP_TABLE_STMT: + return authDropTable(pCxt, (SDropTableStmt*)pStmt); + case QUERY_NODE_DROP_SUPER_TABLE_STMT: + return authDropStable(pCxt, (SDropSuperTableStmt*)pStmt); + case QUERY_NODE_ALTER_TABLE_STMT: + case QUERY_NODE_ALTER_SUPER_TABLE_STMT: + return authAlterTable(pCxt, (SAlterTableStmt*)pStmt); case QUERY_NODE_SHOW_DNODES_STMT: case QUERY_NODE_SHOW_MNODES_STMT: case QUERY_NODE_SHOW_MODULES_STMT: @@ -145,6 +252,8 @@ static int32_t authQuery(SAuthCxt* pCxt, SNode* pStmt) { case QUERY_NODE_SHOW_CLUSTER_STMT: case QUERY_NODE_SHOW_LICENCES_STMT: case QUERY_NODE_SHOW_VGROUPS_STMT: + case QUERY_NODE_SHOW_DB_ALIVE_STMT: + case QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT: case QUERY_NODE_SHOW_CREATE_DATABASE_STMT: case QUERY_NODE_SHOW_TABLE_DISTRIBUTED_STMT: case QUERY_NODE_SHOW_VNODES_STMT: diff --git a/source/libs/parser/src/parCalcConst.c b/source/libs/parser/src/parCalcConst.c index d4f4949df06a79d7b67806d2c3bb760a45695d2a..01b62a90511fd933239f806160ca6760299b7f95 100644 --- a/source/libs/parser/src/parCalcConst.c +++ b/source/libs/parser/src/parCalcConst.c @@ -183,16 +183,18 @@ static int32_t calcConstProject(SNode* pProject, bool dual, SNode** pNew) { } else { code = scalarCalculateConstants(pProject, pNew); } - if (TSDB_CODE_SUCCESS == code && QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) { + if (TSDB_CODE_SUCCESS == code) { strcpy(((SExprNode*)*pNew)->aliasName, aliasName); - int32_t size = taosArrayGetSize(pAssociation); - for (int32_t i = 0; i < size; ++i) { - SNode** pCol = taosArrayGetP(pAssociation, i); - nodesDestroyNode(*pCol); - *pCol = nodesCloneNode(*pNew); - if (NULL == *pCol) { - code = TSDB_CODE_OUT_OF_MEMORY; - break; + if (QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) { + int32_t size = taosArrayGetSize(pAssociation); + for (int32_t i = 0; i < size; ++i) { + SNode** pCol = taosArrayGetP(pAssociation, i); + nodesDestroyNode(*pCol); + *pCol = nodesCloneNode(*pNew); + if (NULL == *pCol) { + code = TSDB_CODE_OUT_OF_MEMORY; + break; + } } } } @@ -320,6 +322,107 @@ static int32_t calcConstInsert(SCalcConstContext* pCxt, SInsertStmt* pInsert) { return code; } +static SNodeList* getChildProjection(SNode* pStmt) { + switch (nodeType(pStmt)) { + case QUERY_NODE_SELECT_STMT: + return ((SSelectStmt*)pStmt)->pProjectionList; + case QUERY_NODE_SET_OPERATOR: + return ((SSetOperator*)pStmt)->pProjectionList; + default: + break; + } + return NULL; +} + +static void eraseSetOpChildProjection(SSetOperator* pSetOp, int32_t index) { + SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft); + nodesListErase(pLeftProjs, nodesListGetCell(pLeftProjs, index)); + if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pLeft)) { + eraseSetOpChildProjection((SSetOperator*)pSetOp->pLeft, index); + } + SNodeList* pRightProjs = getChildProjection(pSetOp->pRight); + nodesListErase(pRightProjs, nodesListGetCell(pRightProjs, index)); + if (QUERY_NODE_SET_OPERATOR == nodeType(pSetOp->pRight)) { + eraseSetOpChildProjection((SSetOperator*)pSetOp->pRight, index); + } +} + +typedef struct SNotRefByOrderByCxt { + SColumnNode* pCol; + bool hasThisCol; +} SNotRefByOrderByCxt; + +static EDealRes notRefByOrderByImpl(SNode* pNode, void* pContext) { + if (QUERY_NODE_COLUMN == nodeType(pNode)) { + SNotRefByOrderByCxt* pCxt = (SNotRefByOrderByCxt*)pContext; + if (nodesEqualNode((SNode*)pCxt->pCol, pNode)) { + pCxt->hasThisCol = true; + return DEAL_RES_END; + } + } + return DEAL_RES_CONTINUE; +} + +static bool notRefByOrderBy(SColumnNode* pCol, SNodeList* pOrderByList) { + SNotRefByOrderByCxt cxt = {.pCol = pCol, .hasThisCol = false}; + nodesWalkExprs(pOrderByList, notRefByOrderByImpl, &cxt); + return !cxt.hasThisCol; +} + +static bool isSetUselessCol(SSetOperator* pSetOp, int32_t index, SExprNode* pProj) { + if (!isUselessCol(pProj)) { + return false; + } + + SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft); + if (!isUselessCol((SExprNode*)nodesListGetNode(pLeftProjs, index))) { + return false; + } + + SNodeList* pRightProjs = getChildProjection(pSetOp->pRight); + if (!isUselessCol((SExprNode*)nodesListGetNode(pRightProjs, index))) { + return false; + } + + return true; +} + +static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) { + if (subquery && pSetOp->opType == SET_OP_TYPE_UNION) { + return TSDB_CODE_SUCCESS; + } + int32_t index = 0; + SNode* pProj = NULL; + WHERE_EACH(pProj, pSetOp->pProjectionList) { + if (subquery && notRefByOrderBy((SColumnNode*)pProj, pSetOp->pOrderByList) && + isSetUselessCol(pSetOp, index, (SExprNode*)pProj)) { + ERASE_NODE(pSetOp->pProjectionList); + eraseSetOpChildProjection(pSetOp, index); + continue; + } + ++index; + WHERE_NEXT; + } + if (0 == LIST_LENGTH(pSetOp->pProjectionList)) { + return nodesListStrictAppend(pSetOp->pProjectionList, createConstantValue()); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t calcConstSetOperator(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) { + int32_t code = calcConstSetOpProjections(pCxt, pSetOp, subquery); + if (TSDB_CODE_SUCCESS == code) { + code = calcConstQuery(pCxt, pSetOp->pLeft, false); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstQuery(pCxt, pSetOp->pRight, false); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstList(pSetOp->pOrderByList); + } + return code; +} + static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) { int32_t code = TSDB_CODE_SUCCESS; switch (nodeType(pStmt)) { @@ -330,11 +433,7 @@ static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subque code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery); break; case QUERY_NODE_SET_OPERATOR: { - SSetOperator* pSetOp = (SSetOperator*)pStmt; - code = calcConstQuery(pCxt, pSetOp->pLeft, false); - if (TSDB_CODE_SUCCESS == code) { - code = calcConstQuery(pCxt, pSetOp->pRight, false); - } + code = calcConstSetOperator(pCxt, (SSetOperator*)pStmt, subquery); break; } case QUERY_NODE_DELETE_STMT: diff --git a/source/libs/parser/src/parInsertSml.c b/source/libs/parser/src/parInsertSml.c index 358baa74cb3932887894bda79a6e26e9a888c797..1c921b2d7c2dcfee70200498b3ee10511331251d 100644 --- a/source/libs/parser/src/parInsertSml.c +++ b/source/libs/parser/src/parInsertSml.c @@ -18,6 +18,18 @@ #include "parToken.h" #include "ttime.h" +static void clearColValArray(SArray* pCols) { + int32_t num = taosArrayGetSize(pCols); + for (int32_t i = 0; i < num; ++i) { + SColVal* pCol = taosArrayGet(pCols, i); + if (TSDB_DATA_TYPE_NCHAR == pCol->type) { + taosMemoryFreeClear(pCol->value.pData); + } + pCol->flag = CV_FLAG_NONE; + pCol->value.val = 0; + } +} + int32_t qCreateSName(SName* pName, const char* pTableName, int32_t acctId, char* dbName, char* msgBuf, int32_t msgBufLen) { SMsgBuf msg = {.buf = msgBuf, .len = msgBufLen}; @@ -45,95 +57,46 @@ int32_t qCreateSName(SName* pName, const char* pTableName, int32_t acctId, char* return TSDB_CODE_SUCCESS; } -typedef struct SmlExecTableHandle { - SParsedDataColInfo tags; // each table - SVCreateTbReq createTblReq; // each table -} SmlExecTableHandle; - -typedef struct SmlExecHandle { - SHashObj* pBlockHash; - SmlExecTableHandle tableExecHandle; - SQuery* pQuery; -} SSmlExecHandle; - -static void smlDestroyTableHandle(void* pHandle) { - SmlExecTableHandle* handle = (SmlExecTableHandle*)pHandle; - destroyBoundColumnInfo(&handle->tags); - tdDestroySVCreateTbReq(&handle->createTblReq); -} - -static int32_t smlBoundColumnData(SArray* cols, SParsedDataColInfo* pColList, SSchema* pSchema, bool isTag) { - col_id_t nCols = pColList->numOfCols; - - pColList->numOfBound = 0; - pColList->boundNullLen = 0; - memset(pColList->boundColumns, 0, sizeof(col_id_t) * nCols); - for (col_id_t i = 0; i < nCols; ++i) { - pColList->cols[i].valStat = VAL_STAT_NONE; +static int32_t smlBoundColumnData(SArray* cols, SBoundColInfo* pBoundInfo, SSchema* pSchema, bool isTag) { + bool* pUseCols = taosMemoryCalloc(pBoundInfo->numOfCols, sizeof(bool)); + if (NULL == pUseCols) { + return TSDB_CODE_OUT_OF_MEMORY; } - bool isOrdered = true; - col_id_t lastColIdx = -1; // last column found + pBoundInfo->numOfBound = 0; + int16_t lastColIdx = -1; // last column found + int32_t code = TSDB_CODE_SUCCESS; + for (int i = 0; i < taosArrayGetSize(cols); ++i) { - SSmlKv* kv = taosArrayGetP(cols, i); + SSmlKv* kv = taosArrayGet(cols, i); SToken sToken = {.n = kv->keyLen, .z = (char*)kv->key}; col_id_t t = lastColIdx + 1; - col_id_t index = ((t == 0 && !isTag) ? 0 : insFindCol(&sToken, t, nCols, pSchema)); - uDebug("SML, index:%d, t:%d, ncols:%d", index, t, nCols); + col_id_t index = ((t == 0 && !isTag) ? 0 : insFindCol(&sToken, t, pBoundInfo->numOfCols, pSchema)); + uTrace("SML, index:%d, t:%d, ncols:%d", index, t, pBoundInfo->numOfCols); if (index < 0 && t > 0) { index = insFindCol(&sToken, 0, t, pSchema); - isOrdered = false; } + if (index < 0) { uError("smlBoundColumnData. index:%d", index); - return TSDB_CODE_SML_INVALID_DATA; + code = TSDB_CODE_SML_INVALID_DATA; + goto end; } - if (pColList->cols[index].valStat == VAL_STAT_HAS) { + if (pUseCols[index]) { uError("smlBoundColumnData. already set. index:%d", index); - return TSDB_CODE_SML_INVALID_DATA; + code = TSDB_CODE_SML_INVALID_DATA; + goto end; } lastColIdx = index; - pColList->cols[index].valStat = VAL_STAT_HAS; - pColList->boundColumns[pColList->numOfBound] = index; - ++pColList->numOfBound; - switch (pSchema[t].type) { - case TSDB_DATA_TYPE_BINARY: - pColList->boundNullLen += (sizeof(VarDataOffsetT) + VARSTR_HEADER_SIZE + CHAR_BYTES); - break; - case TSDB_DATA_TYPE_NCHAR: - pColList->boundNullLen += (sizeof(VarDataOffsetT) + VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE); - break; - default: - pColList->boundNullLen += TYPE_BYTES[pSchema[t].type]; - break; - } + pUseCols[index] = true; + pBoundInfo->pColIndex[pBoundInfo->numOfBound] = index; + ++pBoundInfo->numOfBound; } - pColList->orderStatus = isOrdered ? ORDER_STATUS_ORDERED : ORDER_STATUS_DISORDERED; - - if (!isOrdered) { - pColList->colIdxInfo = taosMemoryCalloc(pColList->numOfBound, sizeof(SBoundIdxInfo)); - if (NULL == pColList->colIdxInfo) { - return TSDB_CODE_OUT_OF_MEMORY; - } - SBoundIdxInfo* pColIdx = pColList->colIdxInfo; - for (col_id_t i = 0; i < pColList->numOfBound; ++i) { - pColIdx[i].schemaColIdx = pColList->boundColumns[i]; - pColIdx[i].boundIdx = i; - } - taosSort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), insSchemaIdxCompar); - for (col_id_t i = 0; i < pColList->numOfBound; ++i) { - pColIdx[i].finalIdx = i; - } - taosSort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), insBoundIdxCompar); - } - - if (pColList->numOfCols > pColList->numOfBound) { - memset(&pColList->boundColumns[pColList->numOfBound], 0, - sizeof(col_id_t) * (pColList->numOfCols - pColList->numOfBound)); - } +end: + taosMemoryFree(pUseCols); - return TSDB_CODE_SUCCESS; + return code; } /** @@ -146,7 +109,7 @@ static int32_t smlBoundColumnData(SArray* cols, SParsedDataColInfo* pColList, SS * @param msg * @return int32_t */ -static int32_t smlBuildTagRow(SArray* cols, SParsedDataColInfo* tags, SSchema* pSchema, STag** ppTag, SArray** tagName, +static int32_t smlBuildTagRow(SArray* cols, SBoundColInfo* tags, SSchema* pSchema, STag** ppTag, SArray** tagName, SMsgBuf* msg) { SArray* pTagArray = taosArrayInit(tags->numOfBound, sizeof(STagVal)); if (!pTagArray) { @@ -159,8 +122,14 @@ static int32_t smlBuildTagRow(SArray* cols, SParsedDataColInfo* tags, SSchema* p int32_t code = TSDB_CODE_SUCCESS; for (int i = 0; i < tags->numOfBound; ++i) { - SSchema* pTagSchema = &pSchema[tags->boundColumns[i]]; - SSmlKv* kv = taosArrayGetP(cols, i); + SSchema* pTagSchema = &pSchema[tags->pColIndex[i]]; + SSmlKv* kv = taosArrayGet(cols, i); + + if(kv->keyLen != strlen(pTagSchema->name) || memcmp(kv->key, pTagSchema->name, kv->keyLen) != 0 || kv->type != pTagSchema->type){ + code = TSDB_CODE_SML_INVALID_DATA; + uError("SML smlBuildCol error col not same %s", pTagSchema->name); + goto end; + } taosArrayPush(*tagName, pTagSchema->name); STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type}; @@ -207,153 +176,255 @@ end: return code; } -int32_t smlBindData(void* handle, SArray* tags, SArray* colsSchema, SArray* cols, bool format, STableMeta* pTableMeta, - char* tableName, const char* sTableName, int32_t sTableNameLen, int32_t ttl, char* msgBuf, int16_t msgBufLen) { - SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; +STableDataCxt* smlInitTableDataCtx(SQuery* query, STableMeta* pTableMeta) { + STableDataCxt* pTableCxt = NULL; + SVCreateTbReq* pCreateTbReq = NULL; + int ret = insGetTableDataCxt(((SVnodeModifyOpStmt*)(query->pRoot))->pTableBlockHashObj, &pTableMeta->uid, + sizeof(pTableMeta->uid), pTableMeta, &pCreateTbReq, &pTableCxt, false); + if (ret != TSDB_CODE_SUCCESS) { + return NULL; + } - SSmlExecHandle* smlHandle = (SSmlExecHandle*)handle; - smlDestroyTableHandle(&smlHandle->tableExecHandle); // free for each table - SSchema* pTagsSchema = getTableTagSchema(pTableMeta); - insSetBoundColumnInfo(&smlHandle->tableExecHandle.tags, pTagsSchema, getNumOfTags(pTableMeta)); - int ret = smlBoundColumnData(tags, &smlHandle->tableExecHandle.tags, pTagsSchema, true); + ret = initTableColSubmitData(pTableCxt); if (ret != TSDB_CODE_SUCCESS) { - buildInvalidOperationMsg(&pBuf, "bound tags error"); + return NULL; + } + return pTableCxt; +} + +int32_t smlBuildRow(STableDataCxt* pTableCxt) { + SRow** pRow = taosArrayReserve(pTableCxt->pData->aRowP, 1); + int ret = tRowBuild(pTableCxt->pValues, pTableCxt->pSchema, pRow); + if (TSDB_CODE_SUCCESS != ret) { return ret; } - STag* pTag = NULL; - SArray* tagName = NULL; - ret = smlBuildTagRow(tags, &smlHandle->tableExecHandle.tags, pTagsSchema, &pTag, &tagName, &pBuf); + insCheckTableDataOrder(pTableCxt, TD_ROW_KEY(*pRow)); + return TSDB_CODE_SUCCESS; +} + +int32_t smlBuildCol(STableDataCxt* pTableCxt, SSchema* schema, void* data, int32_t index) { + int ret = TSDB_CODE_SUCCESS; + SSchema* pColSchema = schema + index; + SColVal* pVal = taosArrayGet(pTableCxt->pValues, index); + SSmlKv* kv = (SSmlKv*)data; + if(kv->keyLen != strlen(pColSchema->name) || memcmp(kv->key, pColSchema->name, kv->keyLen) != 0 || kv->type != pColSchema->type){ + ret = TSDB_CODE_SML_INVALID_DATA; + uError("SML smlBuildCol error col not same %s", pColSchema->name); + goto end; + } + if (kv->type == TSDB_DATA_TYPE_NCHAR) { + int32_t len = 0; + int64_t size = pColSchema->bytes - VARSTR_HEADER_SIZE; + if(size <= 0){ + ret = TSDB_CODE_SML_INVALID_DATA; + goto end; + } + char* pUcs4 = taosMemoryCalloc(1, size); + if (NULL == pUcs4) { + ret = TSDB_CODE_OUT_OF_MEMORY; + goto end; + } + if (!taosMbsToUcs4(kv->value, kv->length, (TdUcs4*)pUcs4, size, &len)) { + if (errno == E2BIG) { + taosMemoryFree(pUcs4); + ret = TSDB_CODE_PAR_VALUE_TOO_LONG; + goto end; + } + taosMemoryFree(pUcs4); + ret = TSDB_CODE_TSC_INVALID_VALUE; + goto end; + } + pVal->value.pData = pUcs4; + pVal->value.nData = len; + } else if (kv->type == TSDB_DATA_TYPE_BINARY) { + pVal->value.nData = kv->length; + pVal->value.pData = (uint8_t*)kv->value; + } else { + memcpy(&pVal->value.val, &(kv->value), kv->length); + } + pVal->flag = CV_FLAG_VALUE; + +end: + return ret; +} + +int32_t smlBindData(SQuery* query, bool dataFormat, SArray* tags, SArray* colsSchema, SArray* cols, + STableMeta* pTableMeta, char* tableName, const char* sTableName, int32_t sTableNameLen, int32_t ttl, + char* msgBuf, int16_t msgBufLen) { + SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; + + SSchema* pTagsSchema = getTableTagSchema(pTableMeta); + SBoundColInfo bindTags = {0}; + SVCreateTbReq* pCreateTblReq = NULL; + SArray* tagName = NULL; + + insInitBoundColsInfo(getNumOfTags(pTableMeta), &bindTags); + int ret = smlBoundColumnData(tags, &bindTags, pTagsSchema, true); if (ret != TSDB_CODE_SUCCESS) { - taosArrayDestroy(tagName); - return ret; + buildInvalidOperationMsg(&pBuf, "bound tags error"); + goto end; } - insBuildCreateTbReq(&smlHandle->tableExecHandle.createTblReq, tableName, pTag, pTableMeta->suid, NULL, tagName, - pTableMeta->tableInfo.numOfTags, ttl); - taosArrayDestroy(tagName); + STag* pTag = NULL; + + ret = smlBuildTagRow(tags, &bindTags, pTagsSchema, &pTag, &tagName, &pBuf); + if (ret != TSDB_CODE_SUCCESS) { + goto end; + } - smlHandle->tableExecHandle.createTblReq.ctb.stbName = taosMemoryMalloc(sTableNameLen + 1); - memcpy(smlHandle->tableExecHandle.createTblReq.ctb.stbName, sTableName, sTableNameLen); - smlHandle->tableExecHandle.createTblReq.ctb.stbName[sTableNameLen] = 0; + pCreateTblReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq)); + if (NULL == pCreateTblReq) { + ret = TSDB_CODE_OUT_OF_MEMORY; + goto end; + } + insBuildCreateTbReq(pCreateTblReq, tableName, pTag, pTableMeta->suid, NULL, tagName, pTableMeta->tableInfo.numOfTags, + ttl); + + pCreateTblReq->ctb.stbName = taosMemoryCalloc(1, sTableNameLen + 1); + memcpy(pCreateTblReq->ctb.stbName, sTableName, sTableNameLen); + + if (dataFormat) { + STableDataCxt** pTableCxt = (STableDataCxt**)taosHashGet(((SVnodeModifyOpStmt*)(query->pRoot))->pTableBlockHashObj, + &pTableMeta->uid, sizeof(pTableMeta->uid)); + if (NULL == pTableCxt) { + ret = buildInvalidOperationMsg(&pBuf, "dataformat true. get tableDataCtx error"); + goto end; + } + (*pTableCxt)->pData->flags |= SUBMIT_REQ_AUTO_CREATE_TABLE; + (*pTableCxt)->pData->pCreateTbReq = pCreateTblReq; + (*pTableCxt)->pMeta->uid = pTableMeta->uid; + (*pTableCxt)->pMeta->vgId = pTableMeta->vgId; + pCreateTblReq = NULL; + goto end; + } - STableDataBlocks* pDataBlock = NULL; - ret = insGetDataBlockFromList(smlHandle->pBlockHash, &pTableMeta->uid, sizeof(pTableMeta->uid), - TSDB_DEFAULT_PAYLOAD_SIZE, sizeof(SSubmitBlk), getTableInfo(pTableMeta).rowSize, - pTableMeta, &pDataBlock, NULL, &smlHandle->tableExecHandle.createTblReq); + STableDataCxt* pTableCxt = NULL; + ret = insGetTableDataCxt(((SVnodeModifyOpStmt*)(query->pRoot))->pTableBlockHashObj, &pTableMeta->uid, + sizeof(pTableMeta->uid), pTableMeta, &pCreateTblReq, &pTableCxt, false); if (ret != TSDB_CODE_SUCCESS) { - buildInvalidOperationMsg(&pBuf, "create data block error"); - return ret; + buildInvalidOperationMsg(&pBuf, "insGetTableDataCxt error"); + goto end; } SSchema* pSchema = getTableColumnSchema(pTableMeta); - - ret = smlBoundColumnData(colsSchema, &pDataBlock->boundColumnInfo, pSchema, false); + ret = smlBoundColumnData(colsSchema, &pTableCxt->boundColsInfo, pSchema, false); if (ret != TSDB_CODE_SUCCESS) { buildInvalidOperationMsg(&pBuf, "bound cols error"); - return ret; + goto end; } - int32_t extendedRowSize = insGetExtendedRowSize(pDataBlock); - SParsedDataColInfo* spd = &pDataBlock->boundColumnInfo; - SRowBuilder* pBuilder = &pDataBlock->rowBuilder; - SMemParam param = {.rb = pBuilder}; - insInitRowBuilder(&pDataBlock->rowBuilder, pDataBlock->pTableMeta->sversion, &pDataBlock->boundColumnInfo); + ret = initTableColSubmitData(pTableCxt); + if (ret != TSDB_CODE_SUCCESS) { + buildInvalidOperationMsg(&pBuf, "initTableColSubmitData error"); + goto end; + } int32_t rowNum = taosArrayGetSize(cols); if (rowNum <= 0) { - return buildInvalidOperationMsg(&pBuf, "cols size <= 0"); - } - ret = insAllocateMemForSize(pDataBlock, extendedRowSize * rowNum); - if (ret != TSDB_CODE_SUCCESS) { - buildInvalidOperationMsg(&pBuf, "allocate memory error"); - return ret; + ret = buildInvalidOperationMsg(&pBuf, "cols size <= 0"); + goto end; } + for (int32_t r = 0; r < rowNum; ++r) { - STSRow* row = (STSRow*)(pDataBlock->pData + pDataBlock->size); // skip the SSubmitBlk header - tdSRowResetBuf(pBuilder, row); - void* rowData = taosArrayGetP(cols, r); - size_t rowDataSize = 0; - if (format) { - rowDataSize = taosArrayGetSize(rowData); - } + void* rowData = taosArrayGetP(cols, r); // 1. set the parsed value from sql string - for (int c = 0, j = 0; c < spd->numOfBound; ++c) { - SSchema* pColSchema = &pSchema[spd->boundColumns[c]]; - - param.schema = pColSchema; - insGetSTSRowAppendInfo(pBuilder->rowType, spd, c, ¶m.toffset, ¶m.colIdx); - - SSmlKv* kv = NULL; - if (format) { - if (j < rowDataSize) { - kv = taosArrayGetP(rowData, j); - if (rowDataSize != spd->numOfBound && j != 0 && - (kv->keyLen != strlen(pColSchema->name) || strncmp(kv->key, pColSchema->name, kv->keyLen) != 0)) { - kv = NULL; - } else { - j++; - } - } - } else { - void** p = taosHashGet(rowData, pColSchema->name, strlen(pColSchema->name)); - if (p) kv = *p; + for (int c = 0; c < pTableCxt->boundColsInfo.numOfBound; ++c) { + SSchema* pColSchema = &pSchema[pTableCxt->boundColsInfo.pColIndex[c]]; + SColVal* pVal = taosArrayGet(pTableCxt->pValues, pTableCxt->boundColsInfo.pColIndex[c]); + void** p = taosHashGet(rowData, pColSchema->name, strlen(pColSchema->name)); + if (p == NULL) { + continue; } - - if (kv) { - int32_t colLen = kv->length; - if (pColSchema->type == TSDB_DATA_TYPE_TIMESTAMP) { - uDebug("SML:data before:%" PRId64 ", precision:%d", kv->i, pTableMeta->tableInfo.precision); - kv->i = convertTimePrecision(kv->i, TSDB_TIME_PRECISION_NANO, pTableMeta->tableInfo.precision); - uDebug("SML:data after:%" PRId64 ", precision:%d", kv->i, pTableMeta->tableInfo.precision); + SSmlKv* kv = *(SSmlKv**)p; + if(kv->type != pColSchema->type){ + ret = buildInvalidOperationMsg(&pBuf, "kv type not equal to col type"); + goto end; + } + if (pColSchema->type == TSDB_DATA_TYPE_TIMESTAMP) { + kv->i = convertTimePrecision(kv->i, TSDB_TIME_PRECISION_NANO, pTableMeta->tableInfo.precision); + } + if (kv->type == TSDB_DATA_TYPE_NCHAR) { + int32_t len = 0; + char* pUcs4 = taosMemoryCalloc(1, pColSchema->bytes - VARSTR_HEADER_SIZE); + if (NULL == pUcs4) { + ret = TSDB_CODE_OUT_OF_MEMORY; + goto end; } - - if (IS_VAR_DATA_TYPE(kv->type)) { - insMemRowAppend(&pBuf, kv->value, colLen, ¶m); - } else { - insMemRowAppend(&pBuf, &(kv->value), colLen, ¶m); + if (!taosMbsToUcs4(kv->value, kv->length, (TdUcs4*)pUcs4, pColSchema->bytes - VARSTR_HEADER_SIZE, &len)) { + if (errno == E2BIG) { + uError("sml bind taosMbsToUcs4 error, kv length:%d, bytes:%d, kv->value:%s", (int)kv->length, pColSchema->bytes, kv->value); + buildInvalidOperationMsg(&pBuf, "value too long"); + ret = TSDB_CODE_PAR_VALUE_TOO_LONG; + goto end; + } + ret = buildInvalidOperationMsg(&pBuf, strerror(errno)); + goto end; } + pVal->value.pData = pUcs4; + pVal->value.nData = len; + } else if (kv->type == TSDB_DATA_TYPE_BINARY) { + pVal->value.nData = kv->length; + pVal->value.pData = (uint8_t*)kv->value; } else { - pBuilder->hasNone = true; - } - - if (PRIMARYKEY_TIMESTAMP_COL_ID == pColSchema->colId) { - TSKEY tsKey = TD_ROW_KEY(row); - insCheckTimestamp(pDataBlock, (const char*)&tsKey); + memcpy(&pVal->value.val, &(kv->value), kv->length); } + pVal->flag = CV_FLAG_VALUE; } - // set the null value for the columns that do not assign values - if ((spd->numOfBound < spd->numOfCols) && TD_IS_TP_ROW(row)) { - pBuilder->hasNone = true; + SRow** pRow = taosArrayReserve(pTableCxt->pData->aRowP, 1); + ret = tRowBuild(pTableCxt->pValues, pTableCxt->pSchema, pRow); + if (TSDB_CODE_SUCCESS != ret) { + buildInvalidOperationMsg(&pBuf, "tRowBuild error"); + goto end; } - - tdSRowEnd(pBuilder); - pDataBlock->size += extendedRowSize; + insCheckTableDataOrder(pTableCxt, TD_ROW_KEY(*pRow)); + clearColValArray(pTableCxt->pValues); } - SSubmitBlk* pBlocks = (SSubmitBlk*)(pDataBlock->pData); - return insSetBlockInfo(pBlocks, pDataBlock, rowNum, &pBuf); +end: + insDestroyBoundColInfo(&bindTags); + tdDestroySVCreateTbReq(pCreateTblReq); + taosMemoryFree(pCreateTblReq); + taosArrayDestroy(tagName); + return ret; } -void* smlInitHandle(SQuery* pQuery) { - SSmlExecHandle* handle = taosMemoryCalloc(1, sizeof(SSmlExecHandle)); - if (!handle) return NULL; - handle->pBlockHash = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false); - handle->pQuery = pQuery; - - return handle; -} +SQuery* smlInitHandle() { + SQuery* pQuery = (SQuery*)nodesMakeNode(QUERY_NODE_QUERY); + if (NULL == pQuery) { + uError("create pQuery error"); + return NULL; + } + pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; + pQuery->haveResultSet = false; + pQuery->msgType = TDMT_VND_SUBMIT; + SVnodeModifyOpStmt* stmt = (SVnodeModifyOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIFY_STMT); + if (NULL == stmt) { + uError("create SVnodeModifyOpStmt error"); + qDestroyQuery(pQuery); + return NULL; + } + stmt->pTableBlockHashObj = taosHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK); + stmt->freeHashFunc = insDestroyTableDataCxtHashMap; + stmt->freeArrayFunc = insDestroyVgroupDataCxtList; -void smlDestroyHandle(void* pHandle) { - if (!pHandle) return; - SSmlExecHandle* handle = (SSmlExecHandle*)pHandle; - insDestroyBlockHashmap(handle->pBlockHash); - smlDestroyTableHandle(&handle->tableExecHandle); - taosMemoryFree(handle); + pQuery->pRoot = (SNode*)stmt; + return pQuery; } -int32_t smlBuildOutput(void* handle, SHashObj* pVgHash) { - SSmlExecHandle* smlHandle = (SSmlExecHandle*)handle; - return qBuildStmtOutput(smlHandle->pQuery, pVgHash, smlHandle->pBlockHash); +int32_t smlBuildOutput(SQuery* handle, SHashObj* pVgHash) { + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)(handle)->pRoot; + // merge according to vgId + int32_t code = insMergeTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pVgDataBlocks); + if (code != TSDB_CODE_SUCCESS) { + uError("insMergeTableDataCxt failed"); + return code; + } + code = insBuildVgDataBlocks(pVgHash, pStmt->pVgDataBlocks, &pStmt->pDataBlocks); + if (code != TSDB_CODE_SUCCESS) { + uError("insBuildVgDataBlocks failed"); + return code; + } + return code; } diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index abee9416faf733d437a34f089f74ec1b1f20e7ed..02de9f227d1f4a8afdf8de83e71b1aabd0e78069 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -15,6 +15,7 @@ #include "parInsertUtil.h" #include "parToken.h" +#include "scalar.h" #include "tglobal.h" #include "ttime.h" @@ -45,13 +46,14 @@ } while (TK_NK_SPACE == (token).type) typedef struct SInsertParseContext { - SParseContext* pComCxt; - SMsgBuf msg; - char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW]; - SParsedDataColInfo tags; // for stmt - bool missCache; - bool usingDuplicateTable; - bool forceUpdate; + SParseContext* pComCxt; + SMsgBuf msg; + char tmpTokenBuf[TSDB_MAX_BYTES_PER_ROW]; + SBoundColInfo tags; // for stmt + bool missCache; + bool usingDuplicateTable; + bool forceUpdate; + bool needTableTagVal; } SInsertParseContext; typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param); @@ -162,7 +164,7 @@ static int32_t ignoreUsingClause(SInsertParseContext* pCxt, const char** pSql) { return code; } -static int32_t parseDuplicateUsingClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, bool* pDuplicate) { +static int32_t parseDuplicateUsingClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pDuplicate) { *pDuplicate = false; char tbFName[TSDB_TABLE_FNAME_LEN]; @@ -180,21 +182,19 @@ static int32_t parseDuplicateUsingClause(SInsertParseContext* pCxt, SVnodeModifO } // pStmt->pSql -> field1_name, ...) -static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, bool isTags, - SParsedDataColInfo* pColList, SSchema* pSchema) { - col_id_t nCols = pColList->numOfCols; - - pColList->numOfBound = 0; - pColList->boundNullLen = 0; - memset(pColList->boundColumns, 0, sizeof(col_id_t) * nCols); - for (col_id_t i = 0; i < nCols; ++i) { - pColList->cols[i].valStat = VAL_STAT_NONE; +static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, bool isTags, SSchema* pSchema, + SBoundColInfo* pBoundInfo) { + bool* pUseCols = taosMemoryCalloc(pBoundInfo->numOfCols, sizeof(bool)); + if (NULL == pUseCols) { + return TSDB_CODE_OUT_OF_MEMORY; } - SToken token; - bool isOrdered = true; - col_id_t lastColIdx = -1; // last column found - while (1) { + pBoundInfo->numOfBound = 0; + + int16_t lastColIdx = -1; // last column found + int32_t code = TSDB_CODE_SUCCESS; + while (TSDB_CODE_SUCCESS == code) { + SToken token; NEXT_TOKEN(*pSql, token); if (TK_NK_RP == token.type) { @@ -206,64 +206,30 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, b token.z = tmpTokenBuf; token.n = strdequote(token.z); - col_id_t t = lastColIdx + 1; - col_id_t index = insFindCol(&token, t, nCols, pSchema); + int16_t t = lastColIdx + 1; + int16_t index = insFindCol(&token, t, pBoundInfo->numOfCols, pSchema); if (index < 0 && t > 0) { index = insFindCol(&token, 0, t, pSchema); - isOrdered = false; } if (index < 0) { - return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z); - } - if (pColList->cols[index].valStat == VAL_STAT_HAS) { - return buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", token.z); - } - lastColIdx = index; - pColList->cols[index].valStat = VAL_STAT_HAS; - pColList->boundColumns[pColList->numOfBound] = index; - ++pColList->numOfBound; - switch (pSchema[t].type) { - case TSDB_DATA_TYPE_BINARY: - pColList->boundNullLen += (sizeof(VarDataOffsetT) + VARSTR_HEADER_SIZE + CHAR_BYTES); - break; - case TSDB_DATA_TYPE_NCHAR: - pColList->boundNullLen += (sizeof(VarDataOffsetT) + VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE); - break; - default: - pColList->boundNullLen += TYPE_BYTES[pSchema[t].type]; - break; + code = generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_INVALID_COLUMN, token.z); + } else if (pUseCols[index]) { + code = buildSyntaxErrMsg(&pCxt->msg, "duplicated column name", token.z); + } else { + lastColIdx = index; + pUseCols[index] = true; + pBoundInfo->pColIndex[pBoundInfo->numOfBound] = index; + ++pBoundInfo->numOfBound; } } - if (!isTags && pColList->cols[0].valStat == VAL_STAT_NONE) { - return buildInvalidOperationMsg(&pCxt->msg, "primary timestamp column can not be null"); + if (TSDB_CODE_SUCCESS == code && !isTags && !pUseCols[0]) { + code = buildInvalidOperationMsg(&pCxt->msg, "primary timestamp column can not be null"); } - pColList->orderStatus = isOrdered ? ORDER_STATUS_ORDERED : ORDER_STATUS_DISORDERED; + taosMemoryFree(pUseCols); - if (!isOrdered) { - pColList->colIdxInfo = taosMemoryCalloc(pColList->numOfBound, sizeof(SBoundIdxInfo)); - if (NULL == pColList->colIdxInfo) { - return TSDB_CODE_OUT_OF_MEMORY; - } - SBoundIdxInfo* pColIdx = pColList->colIdxInfo; - for (col_id_t i = 0; i < pColList->numOfBound; ++i) { - pColIdx[i].schemaColIdx = pColList->boundColumns[i]; - pColIdx[i].boundIdx = i; - } - taosSort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), insSchemaIdxCompar); - for (col_id_t i = 0; i < pColList->numOfBound; ++i) { - pColIdx[i].finalIdx = i; - } - taosSort(pColIdx, pColList->numOfBound, sizeof(SBoundIdxInfo), insBoundIdxCompar); - } - - if (pColList->numOfCols > pColList->numOfBound) { - memset(&pColList->boundColumns[pColList->numOfBound], 0, - sizeof(col_id_t) * (pColList->numOfCols - pColList->numOfBound)); - } - - return TSDB_CODE_SUCCESS; + return code; } static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t* time, SMsgBuf* pMsgBuf) { @@ -485,7 +451,7 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); } - val->pData = strdup(pToken->z); + val->pData = taosStrdup(pToken->z); val->nData = pToken->n; break; } @@ -525,9 +491,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, // input pStmt->pSql: [(tag1_name, ...)] TAGS (tag1_value, ...) ... // output pStmt->pSql: TAGS (tag1_value, ...) ... -static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { - SSchema* pTagsSchema = getTableTagSchema(pStmt->pTableMeta); - insSetBoundColumnInfo(&pCxt->tags, pTagsSchema, getNumOfTags(pStmt->pTableMeta)); +static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { + insInitBoundColsInfo(getNumOfTags(pStmt->pTableMeta), &pCxt->tags); SToken token; int32_t index = 0; @@ -537,10 +502,10 @@ static int32_t parseBoundTagsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt } pStmt->pSql += index; - return parseBoundColumns(pCxt, &pStmt->pSql, true, &pCxt->tags, pTagsSchema); + return parseBoundColumns(pCxt, &pStmt->pSql, true, getTableTagSchema(pStmt->pTableMeta), &pCxt->tags); } -static int32_t parseTagValue(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SSchema* pTagSchema, SToken* pToken, +static int32_t parseTagValue(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SSchema* pTagSchema, SToken* pToken, SArray* pTagName, SArray* pTagVals, STag** pTag) { if (!isNullValue(pTagSchema->type, pToken)) { taosArrayPush(pTagName, pTagSchema->name); @@ -568,10 +533,15 @@ static int32_t parseTagValue(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt return code; } -static void buildCreateTbReq(SVnodeModifOpStmt* pStmt, STag* pTag, SArray* pTagName) { - insBuildCreateTbReq(&pStmt->createTblReq, pStmt->targetTableName.tname, pTag, pStmt->pTableMeta->suid, +static int32_t buildCreateTbReq(SVnodeModifyOpStmt* pStmt, STag* pTag, SArray* pTagName) { + pStmt->pCreateTblReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq)); + if (NULL == pStmt->pCreateTblReq) { + return TSDB_CODE_OUT_OF_MEMORY; + } + insBuildCreateTbReq(pStmt->pCreateTblReq, pStmt->targetTableName.tname, pTag, pStmt->pTableMeta->suid, pStmt->usingTableName.tname, pTagName, pStmt->pTableMeta->tableInfo.numOfTags, TSDB_DEFAULT_TABLE_TTL); + return TSDB_CODE_SUCCESS; } static int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf) { @@ -597,8 +567,137 @@ static int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMs return TSDB_CODE_SUCCESS; } +typedef struct SRewriteTagCondCxt { + SArray* pTagVals; + SArray* pTagName; + int32_t code; +} SRewriteTagCondCxt; + +static int32_t rewriteTagCondColumnImpl(STagVal* pVal, SNode** pNode) { + SValueNode* pValue = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); + if (NULL == pValue) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + pValue->node.resType = ((SColumnNode*)*pNode)->node.resType; + nodesDestroyNode(*pNode); + *pNode = (SNode*)pValue; + + switch (pVal->type) { + case TSDB_DATA_TYPE_BOOL: + pValue->datum.b = *(int8_t*)(&pVal->i64); + *(bool*)&pValue->typeData = pValue->datum.b; + break; + case TSDB_DATA_TYPE_TINYINT: + pValue->datum.i = *(int8_t*)(&pVal->i64); + *(int8_t*)&pValue->typeData = pValue->datum.i; + break; + case TSDB_DATA_TYPE_SMALLINT: + pValue->datum.i = *(int16_t*)(&pVal->i64); + *(int16_t*)&pValue->typeData = pValue->datum.i; + break; + case TSDB_DATA_TYPE_INT: + pValue->datum.i = *(int32_t*)(&pVal->i64); + *(int32_t*)&pValue->typeData = pValue->datum.i; + break; + case TSDB_DATA_TYPE_BIGINT: + pValue->datum.i = pVal->i64; + pValue->typeData = pValue->datum.i; + break; + case TSDB_DATA_TYPE_FLOAT: + pValue->datum.d = *(float*)(&pVal->i64); + *(float*)&pValue->typeData = pValue->datum.d; + break; + case TSDB_DATA_TYPE_DOUBLE: + pValue->datum.d = *(double*)(&pVal->i64); + *(double*)&pValue->typeData = pValue->datum.d; + break; + case TSDB_DATA_TYPE_VARCHAR: + case TSDB_DATA_TYPE_NCHAR: + pValue->datum.p = taosMemoryCalloc(1, pVal->nData + VARSTR_HEADER_SIZE); + if (NULL == pValue->datum.p) { + return TSDB_CODE_OUT_OF_MEMORY; + } + varDataSetLen(pValue->datum.p, pVal->nData); + memcpy(varDataVal(pValue->datum.p), pVal->pData, pVal->nData); + break; + case TSDB_DATA_TYPE_TIMESTAMP: + pValue->datum.i = pVal->i64; + pValue->typeData = pValue->datum.i; + break; + case TSDB_DATA_TYPE_UTINYINT: + pValue->datum.i = *(uint8_t*)(&pVal->i64); + *(uint8_t*)&pValue->typeData = pValue->datum.i; + break; + case TSDB_DATA_TYPE_USMALLINT: + pValue->datum.i = *(uint16_t*)(&pVal->i64); + *(uint16_t*)&pValue->typeData = pValue->datum.i; + break; + case TSDB_DATA_TYPE_UINT: + pValue->datum.i = *(uint32_t*)(&pVal->i64); + *(uint32_t*)&pValue->typeData = pValue->datum.i; + break; + case TSDB_DATA_TYPE_UBIGINT: + pValue->datum.i = *(uint64_t*)(&pVal->i64); + *(uint64_t*)&pValue->typeData = pValue->datum.i; + break; + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + case TSDB_DATA_TYPE_MEDIUMBLOB: + default: + return TSDB_CODE_FAILED; + } + return TSDB_CODE_SUCCESS; +} + +static int32_t rewriteTagCondColumn(SArray* pTagVals, SArray* pTagName, SNode** pNode) { + SColumnNode* pCol = (SColumnNode*)*pNode; + int32_t ntags = taosArrayGetSize(pTagName); + for (int32_t i = 0; i < ntags; ++i) { + char* pTagColName = taosArrayGet(pTagName, i); + if (0 == strcmp(pTagColName, pCol->colName)) { + return rewriteTagCondColumnImpl(taosArrayGet(pTagVals, i), pNode); + } + } + return TSDB_CODE_PAR_PERMISSION_DENIED; +} + +static EDealRes rewriteTagCond(SNode** pNode, void* pContext) { + if (QUERY_NODE_COLUMN == nodeType(*pNode)) { + SRewriteTagCondCxt* pCxt = pContext; + pCxt->code = rewriteTagCondColumn(pCxt->pTagVals, pCxt->pTagName, pNode); + return (TSDB_CODE_SUCCESS == pCxt->code ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR); + } + return DEAL_RES_CONTINUE; +} + +static int32_t setTagVal(SArray* pTagVals, SArray* pTagName, SNode* pCond) { + SRewriteTagCondCxt cxt = {.code = TSDB_CODE_SUCCESS, .pTagVals = pTagVals, .pTagName = pTagName}; + nodesRewriteExpr(&pCond, rewriteTagCond, &cxt); + return cxt.code; +} + +static int32_t checkTagCondResult(SNode* pResult) { + return (QUERY_NODE_VALUE == nodeType(pResult) && ((SValueNode*)pResult)->datum.b) ? TSDB_CODE_SUCCESS + : TSDB_CODE_PAR_PERMISSION_DENIED; +} + +static int32_t checkSubtablePrivilege(SArray* pTagVals, SArray* pTagName, SNode** pCond) { + int32_t code = setTagVal(pTagVals, pTagName, *pCond); + if (TSDB_CODE_SUCCESS == code) { + code = scalarCalculateConstants(*pCond, pCond); + } + if (TSDB_CODE_SUCCESS == code) { + code = checkTagCondResult(*pCond); + } + NODES_DESTORY_NODE(*pCond); + return code; +} + // pSql -> tag1_value, ...) -static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { int32_t code = TSDB_CODE_SUCCESS; SSchema* pSchema = getTableTagSchema(pStmt->pTableMeta); SArray* pTagVals = taosArrayInit(pCxt->tags.numOfBound, sizeof(STagVal)); @@ -625,7 +724,7 @@ static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* break; } - SSchema* pTagSchema = &pSchema[pCxt->tags.boundColumns[i]]; + SSchema* pTagSchema = &pSchema[pCxt->tags.pColIndex[i]]; isJson = pTagSchema->type == TSDB_DATA_TYPE_JSON; code = checkAndTrimValue(&token, pCxt->tmpTokenBuf, &pCxt->msg); if (TSDB_CODE_SUCCESS == code) { @@ -633,12 +732,16 @@ static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* } } + if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pTagCond) { + code = checkSubtablePrivilege(pTagVals, pTagName, &pStmt->pTagCond); + } + if (TSDB_CODE_SUCCESS == code && !isParseBindParam && !isJson) { code = tTagNew(pTagVals, 1, false, &pTag); } if (TSDB_CODE_SUCCESS == code && !isParseBindParam) { - buildCreateTbReq(pStmt, pTag, pTagName); + code = buildCreateTbReq(pStmt, pTag, pTagName); pTag = NULL; } @@ -656,7 +759,7 @@ static int32_t parseTagsClauseImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* // input pStmt->pSql: TAGS (tag1_value, ...) [table_options] ... // output pStmt->pSql: [table_options] ... -static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { SToken token; NEXT_TOKEN(pStmt->pSql, token); if (TK_TAGS != token.type) { @@ -680,7 +783,7 @@ static int32_t parseTagsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pSt return code; } -static int32_t storeTableMeta(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t storeTableMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { pStmt->pTableMeta->suid = pStmt->pTableMeta->uid; pStmt->pTableMeta->uid = pStmt->totalTbNum; pStmt->pTableMeta->tableType = TSDB_CHILD_TABLE; @@ -695,7 +798,7 @@ static int32_t storeTableMeta(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStm return taosHashPut(pStmt->pSubTableHashObj, tbFName, strlen(tbFName), &pBackup, POINTER_BYTES); } -static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { do { int32_t index = 0; SToken token; @@ -706,8 +809,8 @@ static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifOpStmt* p if (TK_NK_INTEGER != token.type) { return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z); } - pStmt->createTblReq.ttl = taosStr2Int32(token.z, NULL, 10); - if (pStmt->createTblReq.ttl < 0) { + pStmt->pCreateTblReq->ttl = taosStr2Int32(token.z, NULL, 10); + if (pStmt->pCreateTblReq->ttl < 0) { return buildSyntaxErrMsg(&pCxt->msg, "Invalid option ttl", token.z); } } else if (TK_COMMENT == token.type) { @@ -720,11 +823,11 @@ static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifOpStmt* p return buildSyntaxErrMsg(&pCxt->msg, "comment too long", token.z); } int32_t len = trimString(token.z, token.n, pCxt->tmpTokenBuf, TSDB_TB_COMMENT_LEN); - pStmt->createTblReq.comment = strndup(pCxt->tmpTokenBuf, len); - if (NULL == pStmt->createTblReq.comment) { + pStmt->pCreateTblReq->comment = strndup(pCxt->tmpTokenBuf, len); + if (NULL == pStmt->pCreateTblReq->comment) { return TSDB_CODE_OUT_OF_MEMORY; } - pStmt->createTblReq.commentLen = len; + pStmt->pCreateTblReq->commentLen = len; } else { break; } @@ -738,7 +841,7 @@ static int32_t parseTableOptions(SInsertParseContext* pCxt, SVnodeModifOpStmt* p // output pStmt->pSql: // 1. [(field1_name, ...)] // 2. VALUES ... | FILE ... -static int32_t parseUsingClauseBottom(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseUsingClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { if (!pStmt->usingTableProcessing || pCxt->usingDuplicateTable) { return TSDB_CODE_SUCCESS; } @@ -754,31 +857,54 @@ static int32_t parseUsingClauseBottom(SInsertParseContext* pCxt, SVnodeModifOpSt return code; } -static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool* pMissCache) { - char dbFName[TSDB_DB_FNAME_LEN]; - tNameGetFullDbName(pTbName, dbFName); - int32_t code = TSDB_CODE_SUCCESS; - bool pass = true; - bool exists = true; +static void setUserAuthInfo(SParseContext* pCxt, SName* pTbName, SUserAuthInfo* pInfo) { + snprintf(pInfo->user, sizeof(pInfo->user), "%s", pCxt->pUser); + memcpy(&pInfo->tbName, pTbName, sizeof(SName)); + pInfo->type = AUTH_TYPE_WRITE; +} + +static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool* pMissCache, SNode** pTagCond) { + int32_t code = TSDB_CODE_SUCCESS; + SUserAuthInfo authInfo = {0}; + setUserAuthInfo(pCxt, pTbName, &authInfo); + SUserAuthRes authRes = {0}; + bool exists = true; if (pCxt->async) { - code = catalogChkAuthFromCache(pCxt->pCatalog, pCxt->pUser, dbFName, AUTH_TYPE_WRITE, &pass, &exists); + code = catalogChkAuthFromCache(pCxt->pCatalog, &authInfo, &authRes, &exists); } else { SRequestConnInfo conn = {.pTrans = pCxt->pTransporter, .requestId = pCxt->requestId, .requestObjRefId = pCxt->requestRid, .mgmtEps = pCxt->mgmtEpSet}; - code = catalogChkAuth(pCxt->pCatalog, &conn, pCxt->pUser, dbFName, AUTH_TYPE_WRITE, &pass); + code = catalogChkAuth(pCxt->pCatalog, &conn, &authInfo, &authRes); } if (TSDB_CODE_SUCCESS == code) { if (!exists) { *pMissCache = true; - } else if (!pass) { + } else if (!authRes.pass) { code = TSDB_CODE_PAR_PERMISSION_DENIED; + } else if (NULL != authRes.pCond) { + *pTagCond = authRes.pCond; } } return code; } +static int32_t checkAuthForTable(SParseContext* pCxt, SName* pTbName, bool* pMissCache, bool* pNeedTableTagVal) { + SNode* pTagCond = NULL; + int32_t code = checkAuth(pCxt, pTbName, pMissCache, &pTagCond); + if (TSDB_CODE_SUCCESS == code) { + *pNeedTableTagVal = ((*pMissCache) || (NULL != pTagCond)); + *pMissCache = (NULL != pTagCond); + } + nodesDestroyNode(pTagCond); + return code; +} + +static int32_t checkAuthForStable(SParseContext* pCxt, SName* pTbName, bool* pMissCache, SNode** pTagCond) { + return checkAuth(pCxt, pTbName, pMissCache, pTagCond); +} + static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, bool isStb, STableMeta** pTableMeta, bool* pMissCache) { SParseContext* pComCxt = pCxt->pComCxt; @@ -812,7 +938,7 @@ static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, bool isSt return code; } -static int32_t getTableVgroup(SParseContext* pCxt, SVnodeModifOpStmt* pStmt, bool isStb, bool* pMissCache) { +static int32_t getTableVgroup(SParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool isStb, bool* pMissCache) { int32_t code = TSDB_CODE_SUCCESS; SVgroupInfo vg; bool exists = true; @@ -837,7 +963,7 @@ static int32_t getTableVgroup(SParseContext* pCxt, SVnodeModifOpStmt* pStmt, boo return code; } -static int32_t getTableMetaAndVgroupImpl(SParseContext* pCxt, SVnodeModifOpStmt* pStmt, bool* pMissCache) { +static int32_t getTableMetaAndVgroupImpl(SParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pMissCache) { SVgroupInfo vg; int32_t code = catalogGetCachedTableVgMeta(pCxt->pCatalog, &pStmt->targetTableName, &vg, &pStmt->pTableMeta); if (TSDB_CODE_SUCCESS == code) { @@ -849,7 +975,7 @@ static int32_t getTableMetaAndVgroupImpl(SParseContext* pCxt, SVnodeModifOpStmt* return code; } -static int32_t getTableMetaAndVgroup(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, bool* pMissCache) { +static int32_t getTableMetaAndVgroup(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, bool* pMissCache) { SParseContext* pComCxt = pCxt->pComCxt; int32_t code = TSDB_CODE_SUCCESS; if (pComCxt->async) { @@ -875,13 +1001,13 @@ static int32_t collectUseDatabase(const SName* pName, SHashObj* pDbs) { return taosHashPut(pDbs, dbFName, strlen(dbFName), dbFName, sizeof(dbFName)); } -static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { if (pCxt->forceUpdate) { pCxt->missCache = true; return TSDB_CODE_SUCCESS; } - int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache); + int32_t code = checkAuthForTable(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache, &pCxt->needTableTagVal); if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { code = getTableMetaAndVgroup(pCxt, pStmt, &pCxt->missCache); } @@ -894,17 +1020,17 @@ static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifOpStmt return code; } -static int32_t preParseUsingTableName(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName) { +static int32_t preParseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) { return insCreateSName(&pStmt->usingTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg); } -static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { if (pCxt->forceUpdate) { pCxt->missCache = true; return TSDB_CODE_SUCCESS; } - int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache); + int32_t code = checkAuthForStable(pCxt->pComCxt, &pStmt->usingTableName, &pCxt->missCache, &pStmt->pTagCond); if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { code = getTableMeta(pCxt, &pStmt->usingTableName, true, &pStmt->pTableMeta, &pCxt->missCache); } @@ -920,7 +1046,7 @@ static int32_t getUsingTableSchema(SInsertParseContext* pCxt, SVnodeModifOpStmt* return code; } -static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { SToken token; NEXT_TOKEN(pStmt->pSql, token); int32_t code = preParseUsingTableName(pCxt, pStmt, &token); @@ -939,7 +1065,7 @@ static int32_t parseUsingTableNameImpl(SInsertParseContext* pCxt, SVnodeModifOpS // output pStmt->pSql: // 1. [(tag1_name, ...)] TAGS (tag1_value, ...) [table_options]] ... // 2. VALUES ... | FILE ... -static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { SToken token; int32_t index = 0; NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index); @@ -957,7 +1083,7 @@ static int32_t parseUsingTableName(SInsertParseContext* pCxt, SVnodeModifOpStmt* return code; } -static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName) { +static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) { return insCreateSName(&pStmt->targetTableName, pTbName, pCxt->pComCxt->acctId, pCxt->pComCxt->db, &pCxt->msg); } @@ -968,7 +1094,7 @@ static int32_t preParseTargetTableName(SInsertParseContext* pCxt, SVnodeModifOpS // output pStmt->pSql: // 1. [ USING ... ] ... // 2. VALUES ... | FILE ... -static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { SToken token; int32_t index = 0; NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index); @@ -982,26 +1108,22 @@ static int32_t preParseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModif return skipParentheses(pCxt, &pStmt->pSql); } -static int32_t getTableDataBlocks(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks** pDataBuf) { +static int32_t getTableDataCxt(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt** pTableCxt) { if (pCxt->pComCxt->async) { - uint64_t uid = pStmt->pTableMeta->uid; - if (pStmt->usingTableProcessing) { - pStmt->pTableMeta->uid = 0; - } - - return insGetDataBlockFromList( - pStmt->pTableBlockHashObj, &uid, sizeof(pStmt->pTableMeta->uid), TSDB_DEFAULT_PAYLOAD_SIZE, sizeof(SSubmitBlk), - getTableInfo(pStmt->pTableMeta).rowSize, pStmt->pTableMeta, pDataBuf, NULL, &pStmt->createTblReq); + return insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pTableMeta->uid, sizeof(pStmt->pTableMeta->uid), + pStmt->pTableMeta, &pStmt->pCreateTblReq, pTableCxt, false); } + char tbFName[TSDB_TABLE_FNAME_LEN]; tNameExtractFullName(&pStmt->targetTableName, tbFName); - return insGetDataBlockFromList(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), TSDB_DEFAULT_PAYLOAD_SIZE, - sizeof(SSubmitBlk), getTableInfo(pStmt->pTableMeta).rowSize, pStmt->pTableMeta, - pDataBuf, NULL, &pStmt->createTblReq); + if (pStmt->usingTableProcessing) { + pStmt->pTableMeta->uid = 0; + } + return insGetTableDataCxt(pStmt->pTableBlockHashObj, tbFName, strlen(tbFName), pStmt->pTableMeta, + &pStmt->pCreateTblReq, pTableCxt, NULL != pCxt->pComCxt->pStmtCb); } -static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, - STableDataBlocks* pDataBuf) { +static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) { SToken token; int32_t index = 0; NEXT_TOKEN_KEEP_SQL(pStmt->pSql, token, index); @@ -1011,13 +1133,30 @@ static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifOpS return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z); } // pStmt->pSql -> field1_name, ...) - return parseBoundColumns(pCxt, &pStmt->pSql, false, &pDataBuf->boundColumnInfo, - getTableColumnSchema(pStmt->pTableMeta)); + return parseBoundColumns(pCxt, &pStmt->pSql, false, getTableColumnSchema(pStmt->pTableMeta), + &pTableCxt->boundColsInfo); } if (NULL != pStmt->pBoundCols) { - return parseBoundColumns(pCxt, &pStmt->pBoundCols, false, &pDataBuf->boundColumnInfo, - getTableColumnSchema(pStmt->pTableMeta)); + return parseBoundColumns(pCxt, &pStmt->pBoundCols, false, getTableColumnSchema(pStmt->pTableMeta), + &pTableCxt->boundColsInfo); + } + + return TSDB_CODE_SUCCESS; +} + +int32_t initTableColSubmitData(STableDataCxt* pTableCxt) { + if (0 == (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT)) { + return TSDB_CODE_SUCCESS; + } + + for (int32_t i = 0; i < pTableCxt->boundColsInfo.numOfBound; ++i) { + SSchema* pSchema = &pTableCxt->pMeta->schema[pTableCxt->boundColsInfo.pColIndex[i]]; + SColData* pCol = taosArrayReserve(pTableCxt->pData->aCol, 1); + if (NULL == pCol) { + return TSDB_CODE_OUT_OF_MEMORY; + } + tColDataInit(pCol, pSchema->colId, pSchema->type, 0); } return TSDB_CODE_SUCCESS; @@ -1027,14 +1166,17 @@ static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifOpS // 1. [(tag1_name, ...)] ... // 2. VALUES ... | FILE ... // output pStmt->pSql: VALUES ... | FILE ... -static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, - STableDataBlocks** pDataBuf) { +static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, + STableDataCxt** pTableCxt) { int32_t code = parseUsingClauseBottom(pCxt, pStmt); if (TSDB_CODE_SUCCESS == code) { - code = getTableDataBlocks(pCxt, pStmt, pDataBuf); + code = getTableDataCxt(pCxt, pStmt, pTableCxt); } if (TSDB_CODE_SUCCESS == code) { - code = parseBoundColumnsClause(pCxt, pStmt, *pDataBuf); + code = parseBoundColumnsClause(pCxt, pStmt, *pTableCxt); + } + if (TSDB_CODE_SUCCESS == code) { + code = initTableColSubmitData(*pTableCxt); } return code; } @@ -1043,7 +1185,7 @@ static int32_t parseSchemaClauseBottom(SInsertParseContext* pCxt, SVnodeModifOpS // output pStmt->pSql: // 1. [(tag1_name, ...)] ... // 2. VALUES ... | FILE ... -static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName) { +static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) { int32_t code = preParseTargetTableName(pCxt, pStmt, pTbName); if (TSDB_CODE_SUCCESS == code) { // option: [(field1_name, ...)] @@ -1057,108 +1199,88 @@ static int32_t parseSchemaClauseTop(SInsertParseContext* pCxt, SVnodeModifOpStmt } static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema, - int16_t timePrec, _row_append_fn_t func, void* param) { - int64_t iv; - uint64_t uv; - char* endptr = NULL; - + int16_t timePrec, SColVal* pVal) { switch (pSchema->type) { case TSDB_DATA_TYPE_BOOL: { if ((pToken->type == TK_NK_BOOL || pToken->type == TK_NK_STRING) && (pToken->n != 0)) { if (strncmp(pToken->z, "true", pToken->n) == 0) { - return func(&pCxt->msg, &TRUE_VALUE, pSchema->bytes, param); + pVal->value.val = TRUE_VALUE; } else if (strncmp(pToken->z, "false", pToken->n) == 0) { - return func(&pCxt->msg, &FALSE_VALUE, pSchema->bytes, param); + pVal->value.val = FALSE_VALUE; } else { return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z); } } else if (pToken->type == TK_NK_INTEGER) { - return func(&pCxt->msg, ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? &FALSE_VALUE : &TRUE_VALUE), - pSchema->bytes, param); + pVal->value.val = ((taosStr2Int64(pToken->z, NULL, 10) == 0) ? FALSE_VALUE : TRUE_VALUE); } else if (pToken->type == TK_NK_FLOAT) { - return func(&pCxt->msg, ((taosStr2Double(pToken->z, NULL) == 0) ? &FALSE_VALUE : &TRUE_VALUE), pSchema->bytes, - param); + pVal->value.val = ((taosStr2Double(pToken->z, NULL) == 0) ? FALSE_VALUE : TRUE_VALUE); } else { return buildSyntaxErrMsg(&pCxt->msg, "invalid bool data", pToken->z); } + break; } - case TSDB_DATA_TYPE_TINYINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z); - } else if (!IS_VALID_TINYINT(iv)) { + } else if (!IS_VALID_TINYINT(pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "tinyint data overflow", pToken->z); } - - uint8_t tmpVal = (uint8_t)iv; - return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + break; } - case TSDB_DATA_TYPE_UTINYINT: { - if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { + if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z); - } else if (uv > UINT8_MAX) { + } else if (pVal->value.val > UINT8_MAX) { return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z); } - uint8_t tmpVal = (uint8_t)uv; - return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + break; } - case TSDB_DATA_TYPE_SMALLINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z); - } else if (!IS_VALID_SMALLINT(iv)) { + } else if (!IS_VALID_SMALLINT(pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z); } - int16_t tmpVal = (int16_t)iv; - return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + break; } - case TSDB_DATA_TYPE_USMALLINT: { - if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { + if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z); - } else if (uv > UINT16_MAX) { + } else if (pVal->value.val > UINT16_MAX) { return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z); } - uint16_t tmpVal = (uint16_t)uv; - return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + break; } - case TSDB_DATA_TYPE_INT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z); - } else if (!IS_VALID_INT(iv)) { + } else if (!IS_VALID_INT(pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z); } - int32_t tmpVal = (int32_t)iv; - return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + break; } - case TSDB_DATA_TYPE_UINT: { - if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { + if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z); - } else if (uv > UINT32_MAX) { + } else if (pVal->value.val > UINT32_MAX) { return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z); } - uint32_t tmpVal = (uint32_t)uv; - return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + break; } - case TSDB_DATA_TYPE_BIGINT: { - if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) { + if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z); } - return func(&pCxt->msg, &iv, pSchema->bytes, param); + break; } - case TSDB_DATA_TYPE_UBIGINT: { - if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) { + if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) { return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned bigint data", pToken->z); } - return func(&pCxt->msg, &uv, pSchema->bytes, param); + break; } - case TSDB_DATA_TYPE_FLOAT: { + char* endptr = NULL; double dv; if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z); @@ -1167,11 +1289,12 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, isnan(dv)) { return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z); } - float tmpVal = (float)dv; - return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + float f = dv; + memcpy(&pVal->value.val, &f, sizeof(f)); + break; } - case TSDB_DATA_TYPE_DOUBLE: { + char* endptr = NULL; double dv; if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) { return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z); @@ -1179,49 +1302,77 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql, if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) { return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z); } - return func(&pCxt->msg, &dv, pSchema->bytes, param); + pVal->value.val = *(int64_t*)&dv; + break; } - case TSDB_DATA_TYPE_BINARY: { // Too long values will raise the invalid sql error message if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); } - - return func(&pCxt->msg, pToken->z, pToken->n, param); + pVal->value.pData = taosMemoryMalloc(pToken->n); + if (NULL == pVal->value.pData) { + return TSDB_CODE_OUT_OF_MEMORY; + } + memcpy(pVal->value.pData, pToken->z, pToken->n); + pVal->value.nData = pToken->n; + break; } - case TSDB_DATA_TYPE_NCHAR: { - return func(&pCxt->msg, pToken->z, pToken->n, param); + // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long' + int32_t len = 0; + char* pUcs4 = taosMemoryCalloc(1, pSchema->bytes - VARSTR_HEADER_SIZE); + if (NULL == pUcs4) { + return TSDB_CODE_OUT_OF_MEMORY; + } + if (!taosMbsToUcs4(pToken->z, pToken->n, (TdUcs4*)pUcs4, pSchema->bytes - VARSTR_HEADER_SIZE, &len)) { + taosMemoryFree(pUcs4); + if (errno == E2BIG) { + return generateSyntaxErrMsg(&pCxt->msg, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); + } + char buf[512] = {0}; + snprintf(buf, tListLen(buf), "%s", strerror(errno)); + return buildSyntaxErrMsg(&pCxt->msg, buf, pToken->z); + } + pVal->value.pData = pUcs4; + pVal->value.nData = len; + break; } case TSDB_DATA_TYPE_JSON: { if (pToken->n > (TSDB_MAX_JSON_TAG_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE) { return buildSyntaxErrMsg(&pCxt->msg, "json string too long than 4095", pToken->z); } - return func(&pCxt->msg, pToken->z, pToken->n, param); + pVal->value.pData = taosMemoryMalloc(pToken->n); + if (NULL == pVal->value.pData) { + return TSDB_CODE_OUT_OF_MEMORY; + } + memcpy(pVal->value.pData, pToken->z, pToken->n); + pVal->value.nData = pToken->n; + break; } case TSDB_DATA_TYPE_TIMESTAMP: { - int64_t tmpVal; - if (parseTime(pSql, pToken, timePrec, &tmpVal, &pCxt->msg) != TSDB_CODE_SUCCESS) { + if (parseTime(pSql, pToken, timePrec, &pVal->value.val, &pCxt->msg) != TSDB_CODE_SUCCESS) { return buildSyntaxErrMsg(&pCxt->msg, "invalid timestamp", pToken->z); } - - return func(&pCxt->msg, &tmpVal, pSchema->bytes, param); + break; } + default: + return TSDB_CODE_FAILED; } - return TSDB_CODE_FAILED; + pVal->flag = CV_FLAG_VALUE; + return TSDB_CODE_SUCCESS; } static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, SToken* pToken, SSchema* pSchema, - int16_t timePrec, _row_append_fn_t func, void* param) { + int16_t timePrec, SColVal* pVal) { int32_t code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg); if (TSDB_CODE_SUCCESS == code && isNullValue(pSchema->type, pToken)) { if (TSDB_DATA_TYPE_TIMESTAMP == pSchema->type && PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { return buildSyntaxErrMsg(&pCxt->msg, "primary timestamp should not be null", pToken->z); } - - return func(&pCxt->msg, NULL, 0, param); + pVal->flag = CV_FLAG_NULL; + return TSDB_CODE_SUCCESS; } if (TSDB_CODE_SUCCESS == code && IS_NUMERIC_TYPE(pSchema->type) && pToken->n == 0) { @@ -1229,22 +1380,29 @@ static int32_t parseValueToken(SInsertParseContext* pCxt, const char** pSql, STo } if (TSDB_CODE_SUCCESS == code) { - code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, timePrec, func, param); + code = parseValueTokenImpl(pCxt, pSql, pToken, pSchema, timePrec, pVal); } return code; } -static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataBlocks* pDataBuf, bool* pGotRow, +static void clearColValArray(SArray* pCols) { + int32_t num = taosArrayGetSize(pCols); + for (int32_t i = 0; i < num; ++i) { + SColVal* pCol = taosArrayGet(pCols, i); + if (IS_VAR_DATA_TYPE(pCol->type)) { + taosMemoryFreeClear(pCol->value.pData); + } + } +} + +static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataCxt* pTableCxt, bool* pGotRow, SToken* pToken) { - SRowBuilder* pBuilder = &pDataBuf->rowBuilder; - STSRow* row = (STSRow*)(pDataBuf->pData + pDataBuf->size); // skip the SSubmitBlk header - SParsedDataColInfo* pCols = &pDataBuf->boundColumnInfo; - bool isParseBindParam = false; - SSchema* pSchemas = getTableColumnSchema(pDataBuf->pTableMeta); - SMemParam param = {.rb = pBuilder}; - - int32_t code = tdSRowResetBuf(pBuilder, row); + SBoundColInfo* pCols = &pTableCxt->boundColsInfo; + bool isParseBindParam = false; + SSchema* pSchemas = getTableColumnSchema(pTableCxt->pMeta); + + int32_t code = TSDB_CODE_SUCCESS; // 1. set the parsed value from sql string for (int i = 0; i < pCols->numOfBound && TSDB_CODE_SUCCESS == code; ++i) { const char* pOrigSql = *pSql; @@ -1255,6 +1413,9 @@ static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataB break; } + SSchema* pSchema = &pSchemas[pCols->pColIndex[i]]; + SColVal* pVal = taosArrayGet(pTableCxt->pValues, pCols->pColIndex[i]); + if (pToken->type == TK_NK_QUESTION) { isParseBindParam = true; if (NULL == pCxt->pComCxt->pStmtCb) { @@ -1272,10 +1433,9 @@ static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataB break; } - param.schema = &pSchemas[pCols->boundColumns[i]]; - insGetSTSRowAppendInfo(pBuilder->rowType, pCols, i, ¶m.toffset, ¶m.colIdx); - code = parseValueToken(pCxt, pSql, pToken, param.schema, getTableInfo(pDataBuf->pTableMeta).precision, - insMemRowAppend, ¶m); + if (TSDB_CODE_SUCCESS == code) { + code = parseValueToken(pCxt, pSql, pToken, pSchema, getTableInfo(pTableCxt->pMeta).precision, pVal); + } } if (TSDB_CODE_SUCCESS == code && i < pCols->numOfBound - 1) { @@ -1286,65 +1446,28 @@ static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataB } } - if (TSDB_CODE_SUCCESS == code) { - TSKEY tsKey = TD_ROW_KEY(row); - code = insCheckTimestamp(pDataBuf, (const char*)&tsKey); - } - if (TSDB_CODE_SUCCESS == code && !isParseBindParam) { - // set the null value for the columns that do not assign values - if ((pCols->numOfBound < pCols->numOfCols) && TD_IS_TP_ROW(row)) { - pBuilder->hasNone = true; + SRow** pRow = taosArrayReserve(pTableCxt->pData->aRowP, 1); + code = tRowBuild(pTableCxt->pValues, pTableCxt->pSchema, pRow); + if (TSDB_CODE_SUCCESS == code) { + insCheckTableDataOrder(pTableCxt, TD_ROW_KEY(*pRow)); } + } - tdSRowEnd(pBuilder); - + if (TSDB_CODE_SUCCESS == code && !isParseBindParam) { *pGotRow = true; - -#ifdef TD_DEBUG_PRINT_ROW - STSchema* pSTSchema = tdGetSTSChemaFromSSChema(schema, spd->numOfCols, 1); - tdSRowPrint(row, pSTSchema, __func__); - taosMemoryFree(pSTSchema); -#endif } - return code; -} - -static int32_t allocateMemIfNeed(STableDataBlocks* pDataBlock, int32_t rowSize, int32_t* numOfRows) { - size_t remain = pDataBlock->nAllocSize - pDataBlock->size; - const int factor = 5; - uint32_t nAllocSizeOld = pDataBlock->nAllocSize; - - // expand the allocated size - if (remain < rowSize * factor) { - while (remain < rowSize * factor) { - pDataBlock->nAllocSize = (uint32_t)(pDataBlock->nAllocSize * 1.5); - remain = pDataBlock->nAllocSize - pDataBlock->size; - } + clearColValArray(pTableCxt->pValues); - char* tmp = taosMemoryRealloc(pDataBlock->pData, (size_t)pDataBlock->nAllocSize); - if (tmp != NULL) { - pDataBlock->pData = tmp; - memset(pDataBlock->pData + pDataBlock->size, 0, pDataBlock->nAllocSize - pDataBlock->size); - } else { - // do nothing, if allocate more memory failed - pDataBlock->nAllocSize = nAllocSizeOld; - *numOfRows = (int32_t)(pDataBlock->nAllocSize - pDataBlock->headerSize) / rowSize; - return TSDB_CODE_OUT_OF_MEMORY; - } - } - - *numOfRows = (int32_t)(pDataBlock->nAllocSize - pDataBlock->headerSize) / rowSize; - return TSDB_CODE_SUCCESS; + return code; } // pSql -> (field1_value, ...) [(field1_value2, ...) ...] -static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf, - int32_t maxRows, int32_t* pNumOfRows, SToken* pToken) { - int32_t code = insInitRowBuilder(&pDataBuf->rowBuilder, pDataBuf->pTableMeta->sversion, &pDataBuf->boundColumnInfo); +static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt, + int32_t* pNumOfRows, SToken* pToken) { + int32_t code = TSDB_CODE_SUCCESS; - int32_t extendedRowSize = insGetExtendedRowSize(pDataBuf); (*pNumOfRows) = 0; while (TSDB_CODE_SUCCESS == code) { int32_t index = 0; @@ -1354,13 +1477,9 @@ static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, } pStmt->pSql += index; - if ((*pNumOfRows) >= maxRows || pDataBuf->size + extendedRowSize >= pDataBuf->nAllocSize) { - code = allocateMemIfNeed(pDataBuf, extendedRowSize, &maxRows); - } - bool gotRow = false; if (TSDB_CODE_SUCCESS == code) { - code = parseOneRow(pCxt, &pStmt->pSql, pDataBuf, &gotRow, pToken); + code = parseOneRow(pCxt, &pStmt->pSql, pTableCxt, &gotRow, pToken); } if (TSDB_CODE_SUCCESS == code) { @@ -1373,7 +1492,6 @@ static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, } if (TSDB_CODE_SUCCESS == code && gotRow) { - pDataBuf->size += extendedRowSize; (*pNumOfRows)++; } } @@ -1386,19 +1504,11 @@ static int32_t parseValues(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, } // VALUES (field1_value, ...) [(field1_value2, ...) ...] -static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf, +static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt, SToken* pToken) { - int32_t maxNumOfRows = 0; int32_t numOfRows = 0; - int32_t code = allocateMemIfNeed(pDataBuf, insGetExtendedRowSize(pDataBuf), &maxNumOfRows); + int32_t code = parseValues(pCxt, pStmt, pTableCxt, &numOfRows, pToken); if (TSDB_CODE_SUCCESS == code) { - code = parseValues(pCxt, pStmt, pDataBuf, maxNumOfRows, &numOfRows, pToken); - } - if (TSDB_CODE_SUCCESS == code) { - code = insSetBlockInfo((SSubmitBlk*)(pDataBuf->pData), pDataBuf, numOfRows, &pCxt->msg); - } - if (TSDB_CODE_SUCCESS == code) { - pDataBuf->numOfTables = 1; pStmt->totalRowsNum += numOfRows; pStmt->totalTbNum += 1; TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_INSERT); @@ -1406,11 +1516,9 @@ static int32_t parseValuesClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* p return code; } -static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf, - int maxRows, int32_t* pNumOfRows) { - int32_t code = insInitRowBuilder(&pDataBuf->rowBuilder, pDataBuf->pTableMeta->sversion, &pDataBuf->boundColumnInfo); - - int32_t extendedRowSize = insGetExtendedRowSize(pDataBuf); +static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt, + int32_t* pNumOfRows) { + int32_t code = TSDB_CODE_SUCCESS; (*pNumOfRows) = 0; char* pLine = NULL; int64_t readLen = 0; @@ -1426,16 +1534,13 @@ static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, continue; } - if ((*pNumOfRows) >= maxRows || pDataBuf->size + extendedRowSize >= pDataBuf->nAllocSize) { - code = allocateMemIfNeed(pDataBuf, extendedRowSize, &maxRows); - } - bool gotRow = false; if (TSDB_CODE_SUCCESS == code) { SToken token; strtolower(pLine, pLine); const char* pRow = pLine; - code = parseOneRow(pCxt, (const char**)&pRow, pDataBuf, &gotRow, &token); + + code = parseOneRow(pCxt, (const char**)&pRow, pTableCxt, &gotRow, &token); if (code && firstLine) { firstLine = false; code = 0; @@ -1444,11 +1549,10 @@ static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, } if (TSDB_CODE_SUCCESS == code && gotRow) { - pDataBuf->size += extendedRowSize; (*pNumOfRows)++; } - if (TSDB_CODE_SUCCESS == code && pDataBuf->nAllocSize > tsMaxMemUsedByInsert * 1024 * 1024) { + if (TSDB_CODE_SUCCESS == code && (*pNumOfRows) > tsMaxMemUsedByInsert * 1024 * 1024) { pStmt->fileProcessing = true; break; } @@ -1464,18 +1568,10 @@ static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, return code; } -static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf) { - int32_t maxNumOfRows = 0; +static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) { int32_t numOfRows = 0; - int32_t code = allocateMemIfNeed(pDataBuf, insGetExtendedRowSize(pDataBuf), &maxNumOfRows); - if (TSDB_CODE_SUCCESS == code) { - code = parseCsvFile(pCxt, pStmt, pDataBuf, maxNumOfRows, &numOfRows); - } + int32_t code = parseCsvFile(pCxt, pStmt, pTableCxt, &numOfRows); if (TSDB_CODE_SUCCESS == code) { - code = insSetBlockInfo((SSubmitBlk*)(pDataBuf->pData), pDataBuf, numOfRows, &pCxt->msg); - } - if (TSDB_CODE_SUCCESS == code) { - pDataBuf->numOfTables = 1; pStmt->totalRowsNum += numOfRows; pStmt->totalTbNum += 1; TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_FILE_INSERT); @@ -1488,8 +1584,8 @@ static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifOpStm return code; } -static int32_t parseDataFromFile(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pFilePath, - STableDataBlocks* pDataBuf) { +static int32_t parseDataFromFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pFilePath, + STableDataCxt* pTableCxt) { char filePathStr[TSDB_FILENAME_LEN] = {0}; if (TK_NK_STRING == pFilePath->type) { trimString(pFilePath->z, pFilePath->n, filePathStr, sizeof(filePathStr)); @@ -1501,10 +1597,10 @@ static int32_t parseDataFromFile(SInsertParseContext* pCxt, SVnodeModifOpStmt* p return TAOS_SYSTEM_ERROR(errno); } - return parseDataFromFileImpl(pCxt, pStmt, pDataBuf); + return parseDataFromFileImpl(pCxt, pStmt, pTableCxt); } -static int32_t parseFileClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf, +static int32_t parseFileClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt, SToken* pToken) { if (tsUseAdapter) { return buildInvalidOperationMsg(&pCxt->msg, "proxy mode does not support csv loading"); @@ -1514,18 +1610,18 @@ static int32_t parseFileClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pSt if (0 == pToken->n || (TK_NK_STRING != pToken->type && TK_NK_ID != pToken->type)) { return buildSyntaxErrMsg(&pCxt->msg, "file path is required following keyword FILE", pToken->z); } - return parseDataFromFile(pCxt, pStmt, pToken, pDataBuf); + return parseDataFromFile(pCxt, pStmt, pToken, pTableCxt); } // VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path -static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, STableDataBlocks* pDataBuf) { +static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, STableDataCxt* pTableCxt) { SToken token; NEXT_TOKEN(pStmt->pSql, token); switch (token.type) { case TK_VALUES: - return parseValuesClause(pCxt, pStmt, pDataBuf, &token); + return parseValuesClause(pCxt, pStmt, pTableCxt, &token); case TK_FILE: - return parseFileClause(pCxt, pStmt, pDataBuf, &token); + return parseFileClause(pCxt, pStmt, pTableCxt, &token); default: break; } @@ -1535,28 +1631,32 @@ static int32_t parseDataClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pSt // input pStmt->pSql: // 1. [(tag1_name, ...)] ... // 2. VALUES ... | FILE ... -static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { - STableDataBlocks* pDataBuf = NULL; - int32_t code = parseSchemaClauseBottom(pCxt, pStmt, &pDataBuf); +static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { + STableDataCxt* pTableCxt = NULL; + int32_t code = parseSchemaClauseBottom(pCxt, pStmt, &pTableCxt); if (TSDB_CODE_SUCCESS == code) { - code = parseDataClause(pCxt, pStmt, pDataBuf); + code = parseDataClause(pCxt, pStmt, pTableCxt); } return code; } -static void resetEnvPreTable(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { - destroyBoundColumnInfo(&pCxt->tags); +static void resetEnvPreTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { + insDestroyBoundColInfo(&pCxt->tags); taosMemoryFreeClear(pStmt->pTableMeta); - tdDestroySVCreateTbReq(&pStmt->createTblReq); + nodesDestroyNode(pStmt->pTagCond); + taosArrayDestroy(pStmt->pTableTag); + tdDestroySVCreateTbReq(pStmt->pCreateTblReq); + taosMemoryFreeClear(pStmt->pCreateTblReq); pCxt->missCache = false; pCxt->usingDuplicateTable = false; pStmt->pBoundCols = NULL; pStmt->usingTableProcessing = false; pStmt->fileProcessing = false; + pStmt->usingTableName.type = 0; } // input pStmt->pSql: [(field1_name, ...)] [ USING ... ] VALUES ... | FILE ... -static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName) { +static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName) { resetEnvPreTable(pCxt, pStmt); int32_t code = parseSchemaClauseTop(pCxt, pStmt, pTbName); if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { @@ -1565,7 +1665,7 @@ static int32_t parseInsertTableClause(SInsertParseContext* pCxt, SVnodeModifOpSt return code; } -static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SToken* pTbName, +static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SToken* pTbName, bool* pHasData) { // no data in the sql string anymore. if (0 == pTbName->n) { @@ -1600,12 +1700,16 @@ static int32_t checkTableClauseFirstToken(SInsertParseContext* pCxt, SVnodeModif } } + if (TK_NK_ID != pTbName->type && TK_NK_STRING != pTbName->type && TK_NK_QUESTION != pTbName->type) { + return buildSyntaxErrMsg(&pCxt->msg, "table_name is expected", pTbName->z); + } + *pHasData = true; return TSDB_CODE_SUCCESS; } -static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { - SParsedDataColInfo* tags = taosMemoryMalloc(sizeof(pCxt->tags)); +static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { + SBoundColInfo* tags = taosMemoryMalloc(sizeof(pCxt->tags)); if (NULL == tags) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -1622,19 +1726,17 @@ static int32_t setStmtInfo(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) return code; } -static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { if (TSDB_QUERY_HAS_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT)) { return setStmtInfo(pCxt, pStmt); } // merge according to vgId - int32_t code = TSDB_CODE_SUCCESS; - if (taosHashGetSize(pStmt->pTableBlockHashObj) > 0) { - code = insMergeTableDataBlocks(pStmt->pTableBlockHashObj, &pStmt->pVgDataBlocks); - } + int32_t code = insMergeTableDataCxt(pStmt->pTableBlockHashObj, &pStmt->pVgDataBlocks); if (TSDB_CODE_SUCCESS == code) { - code = insBuildOutput(pStmt->pVgroupsHashObj, pStmt->pVgDataBlocks, &pStmt->pDataBlocks); + code = insBuildVgDataBlocks(pStmt->pVgroupsHashObj, pStmt->pVgDataBlocks, &pStmt->pDataBlocks); } + return code; } @@ -1643,7 +1745,7 @@ static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifOpStm // [(field1_name, ...)] // VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path // [...]; -static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { SToken token; int32_t code = TSDB_CODE_SUCCESS; bool hasData = true; @@ -1666,7 +1768,7 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt, SVnodeModifOpStmt* pSt static void destroySubTableHashElem(void* p) { taosMemoryFree(*(STableMeta**)p); } static int32_t createVnodeModifOpStmt(SInsertParseContext* pCxt, bool reentry, SNode** pOutput) { - SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIFY_STMT); if (NULL == pStmt) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -1675,8 +1777,8 @@ static int32_t createVnodeModifOpStmt(SInsertParseContext* pCxt, bool reentry, S TSDB_QUERY_SET_TYPE(pStmt->insertType, TSDB_QUERY_TYPE_STMT_INSERT); } pStmt->pSql = pCxt->pComCxt->pSql; - pStmt->freeHashFunc = insDestroyBlockHashmap; - pStmt->freeArrayFunc = insDestroyBlockArrayList; + pStmt->freeHashFunc = insDestroyTableDataCxtHashMap; + pStmt->freeArrayFunc = insDestroyVgroupDataCxtList; if (!reentry) { pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); @@ -1717,14 +1819,18 @@ static int32_t createInsertQuery(SInsertParseContext* pCxt, SQuery** pOutput) { return code; } -static int32_t checkAuthFromMetaData(const SArray* pUsers) { +static int32_t checkAuthFromMetaData(const SArray* pUsers, SNode** pTagCond) { if (1 != taosArrayGetSize(pUsers)) { return TSDB_CODE_FAILED; } SMetaRes* pRes = taosArrayGet(pUsers, 0); if (TSDB_CODE_SUCCESS == pRes->code) { - return (*(bool*)pRes->pRes) ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED; + SUserAuthRes* pAuth = pRes->pRes; + if (NULL != pAuth->pCond) { + *pTagCond = nodesCloneNode(pAuth->pCond); + } + return pAuth->pass ? TSDB_CODE_SUCCESS : TSDB_CODE_PAR_PERMISSION_DENIED; } return pRes->code; } @@ -1745,7 +1851,7 @@ static int32_t getTableMetaFromMetaData(const SArray* pTables, STableMeta** pMet return pRes->code; } -static int32_t getTableVgroupFromMetaData(const SArray* pTables, SVnodeModifOpStmt* pStmt, bool isStb) { +static int32_t getTableVgroupFromMetaData(const SArray* pTables, SVnodeModifyOpStmt* pStmt, bool isStb) { if (1 != taosArrayGetSize(pTables)) { return TSDB_CODE_FAILED; } @@ -1763,9 +1869,40 @@ static int32_t getTableVgroupFromMetaData(const SArray* pTables, SVnodeModifOpSt sizeof(SVgroupInfo)); } +static int32_t buildTagNameFromMeta(STableMeta* pMeta, SArray** pTagName) { + *pTagName = taosArrayInit(pMeta->tableInfo.numOfTags, TSDB_COL_NAME_LEN); + if (NULL == *pTagName) { + return TSDB_CODE_OUT_OF_MEMORY; + } + SSchema* pSchema = getTableTagSchema(pMeta); + for (int32_t i = 0; i < pMeta->tableInfo.numOfTags; ++i) { + taosArrayPush(*pTagName, pSchema[i].name); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t checkSubtablePrivilegeForTable(const SArray* pTables, SVnodeModifyOpStmt* pStmt) { + if (1 != taosArrayGetSize(pTables)) { + return TSDB_CODE_FAILED; + } + + SMetaRes* pRes = taosArrayGet(pTables, 0); + if (TSDB_CODE_SUCCESS != pRes->code) { + return pRes->code; + } + + SArray* pTagName = NULL; + int32_t code = buildTagNameFromMeta(pStmt->pTableMeta, &pTagName); + if (TSDB_CODE_SUCCESS == code) { + code = checkSubtablePrivilege((SArray*)pRes->pRes, pTagName, &pStmt->pTagCond); + } + taosArrayDestroy(pTagName); + return code; +} + static int32_t getTableSchemaFromMetaData(SInsertParseContext* pCxt, const SMetaData* pMetaData, - SVnodeModifOpStmt* pStmt, bool isStb) { - int32_t code = checkAuthFromMetaData(pMetaData->pUser); + SVnodeModifyOpStmt* pStmt, bool isStb) { + int32_t code = checkAuthFromMetaData(pMetaData->pUser, &pStmt->pTagCond); if (TSDB_CODE_SUCCESS == code) { code = getTableMetaFromMetaData(pMetaData->pTableMeta, &pStmt->pTableMeta); } @@ -1778,6 +1915,9 @@ static int32_t getTableSchemaFromMetaData(SInsertParseContext* pCxt, const SMeta if (TSDB_CODE_SUCCESS == code) { code = getTableVgroupFromMetaData(pMetaData->pTableHash, pStmt, isStb); } + if (TSDB_CODE_SUCCESS == code && !isStb && NULL != pStmt->pTagCond) { + code = checkSubtablePrivilegeForTable(pMetaData->pTableTag, pStmt); + } return code; } @@ -1797,10 +1937,12 @@ static void clearCatalogReq(SCatalogReq* pCatalogReq) { pCatalogReq->pTableHash = NULL; taosArrayDestroy(pCatalogReq->pUser); pCatalogReq->pUser = NULL; + taosArrayDestroy(pCatalogReq->pTableTag); + pCatalogReq->pTableTag = NULL; } static int32_t setVnodeModifOpStmt(SInsertParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData, - SVnodeModifOpStmt* pStmt) { + SVnodeModifyOpStmt* pStmt) { clearCatalogReq(pCatalogReq); if (pStmt->usingTableProcessing) { @@ -1814,7 +1956,7 @@ static int32_t resetVnodeModifOpStmt(SInsertParseContext* pCxt, SQuery* pQuery) int32_t code = createVnodeModifOpStmt(pCxt, true, &pQuery->pRoot); if (TSDB_CODE_SUCCESS == code) { - SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)pQuery->pRoot; + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot; (*pCxt->pComCxt->pStmtCb->getExecInfoFn)(pCxt->pComCxt->pStmtCb->pStmt, &pStmt->pVgroupsHashObj, &pStmt->pTableBlockHashObj); @@ -1843,7 +1985,7 @@ static int32_t initInsertQuery(SInsertParseContext* pCxt, SCatalogReq* pCatalogR return resetVnodeModifOpStmt(pCxt, *pQuery); } - SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)(*pQuery)->pRoot; + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)(*pQuery)->pRoot; if (!pStmt->fileProcessing) { return setVnodeModifOpStmt(pCxt, pCatalogReq, pMetaData, pStmt); @@ -1853,7 +1995,7 @@ static int32_t initInsertQuery(SInsertParseContext* pCxt, SCatalogReq* pCatalogR } static int32_t setRefreshMate(SQuery* pQuery) { - SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)pQuery->pRoot; + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot; if (taosHashGetSize(pStmt->pTableNameHashObj) > 0) { taosArrayDestroy(pQuery->pTableList); @@ -1884,7 +2026,7 @@ static int32_t setRefreshMate(SQuery* pQuery) { // [(field1_name, ...)] // VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path // [...]; -static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { int32_t code = skipInsertInto(&pStmt->pSql, &pCxt->msg); if (TSDB_CODE_SUCCESS == code) { code = parseInsertBody(pCxt, pStmt); @@ -1892,11 +2034,11 @@ static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifOpS return code; } -static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { - STableDataBlocks* pDataBuf = NULL; - int32_t code = getTableDataBlocks(pCxt, pStmt, &pDataBuf); +static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { + STableDataCxt* pTableCxt = NULL; + int32_t code = getTableDataCxt(pCxt, pStmt, &pTableCxt); if (TSDB_CODE_SUCCESS == code) { - code = parseDataFromFileImpl(pCxt, pStmt, pDataBuf); + code = parseDataFromFileImpl(pCxt, pStmt, pTableCxt); } if (TSDB_CODE_SUCCESS == code) { @@ -1910,7 +2052,7 @@ static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifOpStm return code; } -static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { int32_t code = parseInsertTableClauseBottom(pCxt, pStmt); if (TSDB_CODE_SUCCESS == code) { code = parseInsertBody(pCxt, pStmt); @@ -1918,7 +2060,7 @@ static int32_t parseInsertSqlFromTable(SInsertParseContext* pCxt, SVnodeModifOpS return code; } -static int32_t parseInsertSqlImpl(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt) { +static int32_t parseInsertSqlImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { if (pStmt->pSql == pCxt->pComCxt->pSql || NULL != pCxt->pComCxt->pStmtCb) { return parseInsertSqlFromStart(pCxt, pStmt); } @@ -1964,14 +2106,21 @@ static int32_t buildInsertUserAuthReq(const char* pUser, SName* pName, SArray** SUserAuthInfo userAuth = {.type = AUTH_TYPE_WRITE}; snprintf(userAuth.user, sizeof(userAuth.user), "%s", pUser); - tNameGetFullDbName(pName, userAuth.dbFName); + memcpy(&userAuth.tbName, pName, sizeof(SName)); taosArrayPush(*pUserAuth, &userAuth); return TSDB_CODE_SUCCESS; } -static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifOpStmt* pStmt, SCatalogReq* pCatalogReq) { - int32_t code = buildInsertUserAuthReq(pCxt->pComCxt->pUser, &pStmt->targetTableName, &pCatalogReq->pUser); +static int32_t buildInsertTableTagReq(SName* pName, SArray** pTables) { return buildInsertTableReq(pName, pTables); } + +static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SCatalogReq* pCatalogReq) { + int32_t code = buildInsertUserAuthReq( + pCxt->pComCxt->pUser, (0 == pStmt->usingTableName.type ? &pStmt->targetTableName : &pStmt->usingTableName), + &pCatalogReq->pUser); + if (TSDB_CODE_SUCCESS == code && pCxt->needTableTagVal) { + code = buildInsertTableTagReq(&pStmt->targetTableName, &pCatalogReq->pTableTag); + } if (TSDB_CODE_SUCCESS == code) { if (0 == pStmt->usingTableName.type) { code = buildInsertDbReq(&pStmt->targetTableName, &pCatalogReq->pTableMeta); @@ -1986,7 +2135,7 @@ static int32_t buildInsertCatalogReq(SInsertParseContext* pCxt, SVnodeModifOpStm } static int32_t setNextStageInfo(SInsertParseContext* pCxt, SQuery* pQuery, SCatalogReq* pCatalogReq) { - SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)pQuery->pRoot; + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot; if (pCxt->missCache) { parserDebug("0x%" PRIx64 " %d rows of %d tables have been inserted before cache miss", pCxt->pComCxt->requestId, pStmt->totalRowsNum, pStmt->totalTbNum); @@ -2011,7 +2160,7 @@ int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatal int32_t code = initInsertQuery(&context, pCatalogReq, pMetaData, pQuery); if (TSDB_CODE_SUCCESS == code) { - code = parseInsertSqlImpl(&context, (SVnodeModifOpStmt*)(*pQuery)->pRoot); + code = parseInsertSqlImpl(&context, (SVnodeModifyOpStmt*)(*pQuery)->pRoot); } if (TSDB_CODE_SUCCESS == code) { code = setNextStageInfo(&context, *pQuery, pCatalogReq); @@ -2020,6 +2169,6 @@ int32_t parseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatal QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) { code = setRefreshMate(*pQuery); } - destroyBoundColumnInfo(&context.tags); + insDestroyBoundColInfo(&context.tags); return code; } diff --git a/source/libs/parser/src/parInsertStmt.c b/source/libs/parser/src/parInsertStmt.c index cfdbbbbc3663263af7af8231e3ae863af657d995..922a0f45ff38fba30fc4b766a3b6427026b49b36 100644 --- a/source/libs/parser/src/parInsertStmt.c +++ b/source/libs/parser/src/parInsertStmt.c @@ -29,26 +29,53 @@ typedef struct SKvParam { char buf[TSDB_MAX_TAGS_LEN]; } SKvParam; +int32_t qCloneCurrentTbData(STableDataCxt* pDataBlock, SSubmitTbData** pData) { + *pData = taosMemoryCalloc(1, sizeof(SSubmitTbData)); + if (NULL == *pData) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + SSubmitTbData* pNew = *pData; + + *pNew = *pDataBlock->pData; + + cloneSVreateTbReq(pDataBlock->pData->pCreateTbReq, &pNew->pCreateTbReq); + pNew->aCol = taosArrayDup(pDataBlock->pData->aCol, NULL); + + int32_t colNum = taosArrayGetSize(pNew->aCol); + for (int32_t i = 0; i < colNum; ++i) { + SColData* pCol = (SColData*)taosArrayGet(pNew->aCol, i); + tColDataDeepClear(pCol); + } + + return TSDB_CODE_SUCCESS; +} + int32_t qBuildStmtOutput(SQuery* pQuery, SHashObj* pVgHash, SHashObj* pBlockHash) { - int32_t code = TSDB_CODE_SUCCESS; - SArray* pVgDataBlocks = NULL; + int32_t code = TSDB_CODE_SUCCESS; + SArray* pVgDataBlocks = NULL; + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot; + // merge according to vgId if (taosHashGetSize(pBlockHash) > 0) { - code = insMergeTableDataBlocks(pBlockHash, &pVgDataBlocks); + code = insMergeTableDataCxt(pBlockHash, &pVgDataBlocks); } if (TSDB_CODE_SUCCESS == code) { - code = insBuildOutput(pVgHash, pVgDataBlocks, &((SVnodeModifOpStmt*)pQuery->pRoot)->pDataBlocks); + code = insBuildVgDataBlocks(pVgHash, pVgDataBlocks, &pStmt->pDataBlocks); + } + + if (pStmt->freeArrayFunc) { + pStmt->freeArrayFunc(pVgDataBlocks); } - insDestroyBlockArrayList(pVgDataBlocks); return code; } int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const char* sTableName, char* tName, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen) { - STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock; - SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; - int32_t code = TSDB_CODE_SUCCESS; - SParsedDataColInfo* tags = (SParsedDataColInfo*)boundTags; + STableDataCxt* pDataBlock = (STableDataCxt*)pBlock; + SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; + int32_t code = TSDB_CODE_SUCCESS; + SBoundColInfo* tags = (SBoundColInfo*)boundTags; if (NULL == tags) { return TSDB_CODE_APP_ERROR; } @@ -64,7 +91,7 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const ch goto end; } - SSchema* pSchema = getTableTagSchema(pDataBlock->pTableMeta); + SSchema* pSchema = getTableTagSchema(pDataBlock->pMeta); bool isJson = false; STag* pTag = NULL; @@ -74,7 +101,7 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const ch continue; } - SSchema* pTagSchema = &pSchema[tags->boundColumns[c]]; + SSchema* pTagSchema = &pSchema[tags->pColIndex[c]]; int32_t colLen = pTagSchema->bytes; if (IS_VAR_DATA_TYPE(pTagSchema->type)) { colLen = bind[c].length[0]; @@ -136,11 +163,16 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const ch goto end; } - SVCreateTbReq tbReq = {0}; - insBuildCreateTbReq(&tbReq, tName, pTag, suid, sTableName, tagName, pDataBlock->pTableMeta->tableInfo.numOfTags, - TSDB_DEFAULT_TABLE_TTL); - code = insBuildCreateTbMsg(pDataBlock, &tbReq); - tdDestroySVCreateTbReq(&tbReq); + if (NULL == pDataBlock->pData->pCreateTbReq) { + pDataBlock->pData->pCreateTbReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq)); + if (NULL == pDataBlock->pData->pCreateTbReq) { + code = TSDB_CODE_OUT_OF_MEMORY; + goto end; + } + } + + insBuildCreateTbReq(pDataBlock->pData->pCreateTbReq, tName, pTag, suid, sTableName, tagName, + pDataBlock->pMeta->tableInfo.numOfTags, TSDB_DEFAULT_TABLE_TTL); end: for (int i = 0; i < taosArrayGetSize(pTagArray); ++i) { @@ -155,199 +187,178 @@ end: return code; } -int32_t qBindStmtColsValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen) { - STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock; - SSchema* pSchema = getTableColumnSchema(pDataBlock->pTableMeta); - int32_t extendedRowSize = insGetExtendedRowSize(pDataBlock); - SParsedDataColInfo* spd = &pDataBlock->boundColumnInfo; - SRowBuilder* pBuilder = &pDataBlock->rowBuilder; - SMemParam param = {.rb = pBuilder}; - SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; - int32_t rowNum = bind->num; - - CHECK_CODE( - insInitRowBuilder(&pDataBlock->rowBuilder, pDataBlock->pTableMeta->sversion, &pDataBlock->boundColumnInfo)); +int32_t convertStmtNcharCol(SMsgBuf* pMsgBuf, SSchema* pSchema, TAOS_MULTI_BIND* src, TAOS_MULTI_BIND* dst) { + int32_t output = 0; + int32_t newBuflen = (pSchema->bytes - VARSTR_HEADER_SIZE) * src->num; + if (dst->buffer_length < newBuflen) { + dst->buffer = taosMemoryRealloc(dst->buffer, newBuflen); + if (NULL == dst->buffer) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } - CHECK_CODE(insAllocateMemForSize(pDataBlock, extendedRowSize * bind->num)); + if (NULL == dst->length) { + dst->length = taosMemoryRealloc(dst->length, sizeof(int32_t) * src->num); + if (NULL == dst->buffer) { + taosMemoryFreeClear(dst->buffer); + return TSDB_CODE_OUT_OF_MEMORY; + } + } - for (int32_t r = 0; r < bind->num; ++r) { - STSRow* row = (STSRow*)(pDataBlock->pData + pDataBlock->size); // skip the SSubmitBlk header - tdSRowResetBuf(pBuilder, row); + dst->buffer_length = pSchema->bytes - VARSTR_HEADER_SIZE; - for (int c = 0; c < spd->numOfBound; ++c) { - SSchema* pColSchema = &pSchema[spd->boundColumns[c]]; + for (int32_t i = 0; i < src->num; ++i) { + if (src->is_null && src->is_null[i]) { + continue; + } - if (bind[c].num != rowNum) { - return buildInvalidOperationMsg(&pBuf, "row number in each bind param should be the same"); + if (!taosMbsToUcs4(((char*)src->buffer) + src->buffer_length * i, src->length[i], + (TdUcs4*)(((char*)dst->buffer) + dst->buffer_length * i), dst->buffer_length, &output)) { + if (errno == E2BIG) { + return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pSchema->name); } + char buf[512] = {0}; + snprintf(buf, tListLen(buf), "%s", strerror(errno)); + return buildSyntaxErrMsg(pMsgBuf, buf, NULL); + } - param.schema = pColSchema; - insGetSTSRowAppendInfo(pBuilder->rowType, spd, c, ¶m.toffset, ¶m.colIdx); - - if (bind[c].is_null && bind[c].is_null[r]) { - if (pColSchema->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { - return buildInvalidOperationMsg(&pBuf, "primary timestamp should not be NULL"); - } - - CHECK_CODE(insMemRowAppend(&pBuf, NULL, 0, ¶m)); - } else { - if (bind[c].buffer_type != pColSchema->type) { - return buildInvalidOperationMsg(&pBuf, "column type mis-match with buffer type"); - } + dst->length[i] = output; + } - int32_t colLen = pColSchema->bytes; - if (IS_VAR_DATA_TYPE(pColSchema->type)) { - colLen = bind[c].length[r]; - } + dst->buffer_type = src->buffer_type; + dst->is_null = src->is_null; + dst->num = src->num; - CHECK_CODE(insMemRowAppend(&pBuf, (char*)bind[c].buffer + bind[c].buffer_length * r, colLen, ¶m)); - } + return TSDB_CODE_SUCCESS; +} - if (PRIMARYKEY_TIMESTAMP_COL_ID == pColSchema->colId) { - TSKEY tsKey = TD_ROW_KEY(row); - insCheckTimestamp(pDataBlock, (const char*)&tsKey); - } - } - // set the null value for the columns that do not assign values - if ((spd->numOfBound < spd->numOfCols) && TD_IS_TP_ROW(row)) { - pBuilder->hasNone = true; +int32_t qBindStmtColsValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen) { + STableDataCxt* pDataBlock = (STableDataCxt*)pBlock; + SSchema* pSchema = getTableColumnSchema(pDataBlock->pMeta); + SBoundColInfo* boundInfo = &pDataBlock->boundColsInfo; + SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; + int32_t rowNum = bind->num; + TAOS_MULTI_BIND ncharBind = {0}; + TAOS_MULTI_BIND* pBind = NULL; + int32_t code = 0; + + for (int c = 0; c < boundInfo->numOfBound; ++c) { + SSchema* pColSchema = &pSchema[boundInfo->pColIndex[c]]; + SColData* pCol = taosArrayGet(pDataBlock->pData->aCol, c); + + if (bind[c].num != rowNum) { + code = buildInvalidOperationMsg(&pBuf, "row number in each bind param should be the same"); + goto _return; } - tdSRowEnd(pBuilder); -#ifdef TD_DEBUG_PRINT_ROW - STSchema* pSTSchema = tdGetSTSChemaFromSSChema(pSchema, spd->numOfCols, 1); - tdSRowPrint(row, pSTSchema, __func__); - taosMemoryFree(pSTSchema); -#endif - pDataBlock->size += extendedRowSize; - } - SSubmitBlk* pBlocks = (SSubmitBlk*)(pDataBlock->pData); - return insSetBlockInfo(pBlocks, pDataBlock, bind->num, &pBuf); -} + if ((!(rowNum == 1 && bind[c].is_null && *bind[c].is_null)) && bind[c].buffer_type != pColSchema->type) { // for rowNum ==1 , connector may not set buffer_type + code = buildInvalidOperationMsg(&pBuf, "column type mis-match with buffer type"); + goto _return; + } -int32_t qBindStmtSingleColValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen, int32_t colIdx, - int32_t rowNum) { - STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock; - SSchema* pSchema = getTableColumnSchema(pDataBlock->pTableMeta); - int32_t extendedRowSize = insGetExtendedRowSize(pDataBlock); - SParsedDataColInfo* spd = &pDataBlock->boundColumnInfo; - SRowBuilder* pBuilder = &pDataBlock->rowBuilder; - SMemParam param = {.rb = pBuilder}; - SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; - bool rowStart = (0 == colIdx); - bool rowEnd = ((colIdx + 1) == spd->numOfBound); - - if (rowStart) { - CHECK_CODE( - insInitRowBuilder(&pDataBlock->rowBuilder, pDataBlock->pTableMeta->sversion, &pDataBlock->boundColumnInfo)); - CHECK_CODE(insAllocateMemForSize(pDataBlock, extendedRowSize * bind->num)); - } - - for (int32_t r = 0; r < bind->num; ++r) { - STSRow* row = (STSRow*)(pDataBlock->pData + pDataBlock->size + extendedRowSize * r); // skip the SSubmitBlk header - if (rowStart) { - tdSRowResetBuf(pBuilder, row); + if (TSDB_DATA_TYPE_NCHAR == pColSchema->type) { + code = convertStmtNcharCol(&pBuf, pColSchema, bind + c, &ncharBind); + if (code) { + goto _return; + } + pBind = &ncharBind; } else { - tdSRowGetBuf(pBuilder, row); + pBind = bind + c; } - SSchema* pColSchema = &pSchema[spd->boundColumns[colIdx]]; - - if (bind->num != rowNum) { - return buildInvalidOperationMsg(&pBuf, "row number in each bind param should be the same"); - } + tColDataAddValueByBind(pCol, pBind); + } - param.schema = pColSchema; - insGetSTSRowAppendInfo(pBuilder->rowType, spd, colIdx, ¶m.toffset, ¶m.colIdx); + qDebug("stmt all %d columns bind %d rows data", boundInfo->numOfBound, rowNum); - if (bind->is_null && bind->is_null[r]) { - if (pColSchema->colId == PRIMARYKEY_TIMESTAMP_COL_ID) { - return buildInvalidOperationMsg(&pBuf, "primary timestamp should not be NULL"); - } +_return: - CHECK_CODE(insMemRowAppend(&pBuf, NULL, 0, ¶m)); - } else { - if (bind->buffer_type != pColSchema->type) { - return buildInvalidOperationMsg(&pBuf, "column type mis-match with buffer type"); - } + taosMemoryFree(ncharBind.buffer); + taosMemoryFree(ncharBind.length); - int32_t colLen = pColSchema->bytes; - if (IS_VAR_DATA_TYPE(pColSchema->type)) { - colLen = bind->length[r]; - } + return code; +} - CHECK_CODE(insMemRowAppend(&pBuf, (char*)bind->buffer + bind->buffer_length * r, colLen, ¶m)); - } +int32_t qBindStmtSingleColValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen, int32_t colIdx, + int32_t rowNum) { + STableDataCxt* pDataBlock = (STableDataCxt*)pBlock; + SSchema* pSchema = getTableColumnSchema(pDataBlock->pMeta); + SBoundColInfo* boundInfo = &pDataBlock->boundColsInfo; + SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen}; + SSchema* pColSchema = &pSchema[boundInfo->pColIndex[colIdx]]; + SColData* pCol = taosArrayGet(pDataBlock->pData->aCol, colIdx); + TAOS_MULTI_BIND ncharBind = {0}; + TAOS_MULTI_BIND* pBind = NULL; + int32_t code = 0; + + if (bind->num != rowNum) { + return buildInvalidOperationMsg(&pBuf, "row number in each bind param should be the same"); + } - if (PRIMARYKEY_TIMESTAMP_COL_ID == pColSchema->colId) { - TSKEY tsKey = TD_ROW_KEY(row); - insCheckTimestamp(pDataBlock, (const char*)&tsKey); - } + if (bind->buffer_type != pColSchema->type) { + return buildInvalidOperationMsg(&pBuf, "column type mis-match with buffer type"); + } - // set the null value for the columns that do not assign values - if (rowEnd && (spd->numOfBound < spd->numOfCols) && TD_IS_TP_ROW(row)) { - pBuilder->hasNone = true; + if (TSDB_DATA_TYPE_NCHAR == pColSchema->type) { + code = convertStmtNcharCol(&pBuf, pColSchema, bind, &ncharBind); + if (code) { + goto _return; } - if (rowEnd) { - tdSRowEnd(pBuilder); - } -#ifdef TD_DEBUG_PRINT_ROW - if (rowEnd) { - STSchema* pSTSchema = tdGetSTSChemaFromSSChema(pSchema, spd->numOfCols, 1); - tdSRowPrint(row, pSTSchema, __func__); - taosMemoryFree(pSTSchema); - } -#endif + pBind = &ncharBind; + } else { + pBind = bind; } - if (rowEnd) { - pDataBlock->size += extendedRowSize * bind->num; + tColDataAddValueByBind(pCol, pBind); - SSubmitBlk* pBlocks = (SSubmitBlk*)(pDataBlock->pData); - CHECK_CODE(insSetBlockInfo(pBlocks, pDataBlock, bind->num, &pBuf)); - } + qDebug("stmt col %d bind %d rows data", colIdx, rowNum); - return TSDB_CODE_SUCCESS; +_return: + + taosMemoryFree(ncharBind.buffer); + taosMemoryFree(ncharBind.length); + + return code; } -int32_t buildBoundFields(SParsedDataColInfo* boundInfo, SSchema* pSchema, int32_t* fieldNum, TAOS_FIELD_E** fields, - uint8_t timePrec) { +int32_t buildBoundFields(int32_t numOfBound, int16_t* boundColumns, SSchema* pSchema, int32_t* fieldNum, + TAOS_FIELD_E** fields, uint8_t timePrec) { if (fields) { - *fields = taosMemoryCalloc(boundInfo->numOfBound, sizeof(TAOS_FIELD)); + *fields = taosMemoryCalloc(numOfBound, sizeof(TAOS_FIELD_E)); if (NULL == *fields) { return TSDB_CODE_OUT_OF_MEMORY; } - SSchema* schema = &pSchema[boundInfo->boundColumns[0]]; + SSchema* schema = &pSchema[boundColumns[0]]; if (TSDB_DATA_TYPE_TIMESTAMP == schema->type) { (*fields)[0].precision = timePrec; } - for (int32_t i = 0; i < boundInfo->numOfBound; ++i) { - schema = &pSchema[boundInfo->boundColumns[i]]; + for (int32_t i = 0; i < numOfBound; ++i) { + schema = &pSchema[boundColumns[i]]; strcpy((*fields)[i].name, schema->name); (*fields)[i].type = schema->type; (*fields)[i].bytes = schema->bytes; } } - *fieldNum = boundInfo->numOfBound; + *fieldNum = numOfBound; return TSDB_CODE_SUCCESS; } int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TAOS_FIELD_E** fields) { - STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock; - SParsedDataColInfo* tags = (SParsedDataColInfo*)boundTags; + STableDataCxt* pDataBlock = (STableDataCxt*)pBlock; + SBoundColInfo* tags = (SBoundColInfo*)boundTags; if (NULL == tags) { return TSDB_CODE_APP_ERROR; } - if (pDataBlock->pTableMeta->tableType != TSDB_SUPER_TABLE && pDataBlock->pTableMeta->tableType != TSDB_CHILD_TABLE) { + if (pDataBlock->pMeta->tableType != TSDB_SUPER_TABLE && pDataBlock->pMeta->tableType != TSDB_CHILD_TABLE) { return TSDB_CODE_TSC_STMT_API_ERROR; } - SSchema* pSchema = getTableTagSchema(pDataBlock->pTableMeta); + SSchema* pSchema = getTableTagSchema(pDataBlock->pMeta); if (tags->numOfBound <= 0) { *fieldNum = 0; *fields = NULL; @@ -355,15 +366,15 @@ int32_t qBuildStmtTagFields(void* pBlock, void* boundTags, int32_t* fieldNum, TA return TSDB_CODE_SUCCESS; } - CHECK_CODE(buildBoundFields(tags, pSchema, fieldNum, fields, 0)); + CHECK_CODE(buildBoundFields(tags->numOfBound, tags->pColIndex, pSchema, fieldNum, fields, 0)); return TSDB_CODE_SUCCESS; } int32_t qBuildStmtColFields(void* pBlock, int32_t* fieldNum, TAOS_FIELD_E** fields) { - STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock; - SSchema* pSchema = getTableColumnSchema(pDataBlock->pTableMeta); - if (pDataBlock->boundColumnInfo.numOfBound <= 0) { + STableDataCxt* pDataBlock = (STableDataCxt*)pBlock; + SSchema* pSchema = getTableColumnSchema(pDataBlock->pMeta); + if (pDataBlock->boundColsInfo.numOfBound <= 0) { *fieldNum = 0; if (fields) { *fields = NULL; @@ -372,128 +383,125 @@ int32_t qBuildStmtColFields(void* pBlock, int32_t* fieldNum, TAOS_FIELD_E** fiel return TSDB_CODE_SUCCESS; } - CHECK_CODE(buildBoundFields(&pDataBlock->boundColumnInfo, pSchema, fieldNum, fields, - pDataBlock->pTableMeta->tableInfo.precision)); + CHECK_CODE(buildBoundFields(pDataBlock->boundColsInfo.numOfBound, pDataBlock->boundColsInfo.pColIndex, pSchema, + fieldNum, fields, pDataBlock->pMeta->tableInfo.precision)); return TSDB_CODE_SUCCESS; } -int32_t qResetStmtDataBlock(void* block, bool keepBuf) { - STableDataBlocks* pBlock = (STableDataBlocks*)block; +int32_t qResetStmtDataBlock(STableDataCxt* block, bool deepClear) { + STableDataCxt* pBlock = (STableDataCxt*)block; + int32_t colNum = taosArrayGetSize(pBlock->pData->aCol); - if (keepBuf) { - taosMemoryFreeClear(pBlock->pData); - pBlock->pData = taosMemoryMalloc(TSDB_PAYLOAD_SIZE); - if (NULL == pBlock->pData) { - return TSDB_CODE_OUT_OF_MEMORY; + for (int32_t i = 0; i < colNum; ++i) { + SColData* pCol = (SColData*)taosArrayGet(pBlock->pData->aCol, i); + if (deepClear) { + tColDataDeepClear(pCol); + } else { + tColDataClear(pCol); } - memset(pBlock->pData, 0, sizeof(SSubmitBlk)); - } else { - pBlock->pData = NULL; } - pBlock->ordered = true; - pBlock->prevTS = INT64_MIN; - pBlock->size = sizeof(SSubmitBlk); - pBlock->tsSource = -1; - pBlock->numOfTables = 1; - pBlock->nAllocSize = TSDB_PAYLOAD_SIZE; - pBlock->headerSize = pBlock->size; - pBlock->createTbReqLen = 0; - - memset(&pBlock->rowBuilder, 0, sizeof(pBlock->rowBuilder)); - return TSDB_CODE_SUCCESS; } -int32_t qCloneStmtDataBlock(void** pDst, void* pSrc) { - *pDst = taosMemoryMalloc(sizeof(STableDataBlocks)); +int32_t qCloneStmtDataBlock(STableDataCxt** pDst, STableDataCxt* pSrc, bool reset) { + int32_t code = 0; + + *pDst = taosMemoryCalloc(1, sizeof(STableDataCxt)); if (NULL == *pDst) { return TSDB_CODE_OUT_OF_MEMORY; } - memcpy(*pDst, pSrc, sizeof(STableDataBlocks)); - ((STableDataBlocks*)(*pDst))->cloned = true; + STableDataCxt* pNewCxt = (STableDataCxt*)*pDst; + STableDataCxt* pCxt = (STableDataCxt*)pSrc; + pNewCxt->pSchema = NULL; + pNewCxt->pValues = NULL; - STableDataBlocks* pBlock = (STableDataBlocks*)(*pDst); - if (pBlock->pTableMeta) { - void* pNewMeta = taosMemoryMalloc(TABLE_META_SIZE(pBlock->pTableMeta)); + if (pCxt->pMeta) { + void* pNewMeta = taosMemoryMalloc(TABLE_META_SIZE(pCxt->pMeta)); if (NULL == pNewMeta) { - taosMemoryFreeClear(*pDst); + insDestroyTableDataCxt(*pDst); return TSDB_CODE_OUT_OF_MEMORY; } - memcpy(pNewMeta, pBlock->pTableMeta, TABLE_META_SIZE(pBlock->pTableMeta)); - pBlock->pTableMeta = pNewMeta; + memcpy(pNewMeta, pCxt->pMeta, TABLE_META_SIZE(pCxt->pMeta)); + pNewCxt->pMeta = pNewMeta; } - if (pBlock->boundColumnInfo.boundColumns) { - int32_t size = pBlock->boundColumnInfo.numOfCols * sizeof(col_id_t); - void* tmp = taosMemoryMalloc(size); - memcpy(tmp, pBlock->boundColumnInfo.boundColumns, size); - pBlock->boundColumnInfo.boundColumns = tmp; - } + memcpy(&pNewCxt->boundColsInfo, &pCxt->boundColsInfo, sizeof(pCxt->boundColsInfo)); + pNewCxt->boundColsInfo.pColIndex = NULL; - if (pBlock->boundColumnInfo.cols) { - int32_t size = pBlock->boundColumnInfo.numOfCols * sizeof(SBoundColumn); - void* tmp = taosMemoryMalloc(size); - memcpy(tmp, pBlock->boundColumnInfo.cols, size); - pBlock->boundColumnInfo.cols = tmp; + if (pCxt->boundColsInfo.pColIndex) { + void* pNewColIdx = taosMemoryMalloc(pCxt->boundColsInfo.numOfBound * sizeof(*pCxt->boundColsInfo.pColIndex)); + if (NULL == pNewColIdx) { + insDestroyTableDataCxt(*pDst); + return TSDB_CODE_OUT_OF_MEMORY; + } + memcpy(pNewColIdx, pCxt->boundColsInfo.pColIndex, + pCxt->boundColsInfo.numOfBound * sizeof(*pCxt->boundColsInfo.pColIndex)); + pNewCxt->boundColsInfo.pColIndex = pNewColIdx; } - if (pBlock->boundColumnInfo.colIdxInfo) { - int32_t size = pBlock->boundColumnInfo.numOfBound * sizeof(SBoundIdxInfo); - void* tmp = taosMemoryMalloc(size); - memcpy(tmp, pBlock->boundColumnInfo.colIdxInfo, size); - pBlock->boundColumnInfo.colIdxInfo = tmp; + if (pCxt->pData) { + SSubmitTbData* pNewTb = (SSubmitTbData*)taosMemoryMalloc(sizeof(SSubmitTbData)); + if (NULL == pNewTb) { + insDestroyTableDataCxt(*pDst); + return TSDB_CODE_OUT_OF_MEMORY; + } + + memcpy(pNewTb, pCxt->pData, sizeof(*pCxt->pData)); + pNewTb->pCreateTbReq = NULL; + + pNewTb->aCol = taosArrayDup(pCxt->pData->aCol, NULL); + if (NULL == pNewTb) { + insDestroyTableDataCxt(*pDst); + return TSDB_CODE_OUT_OF_MEMORY; + } + + pNewCxt->pData = pNewTb; + + if (reset) { + code = qResetStmtDataBlock(*pDst, true); + } } - return qResetStmtDataBlock(*pDst, false); + return code; } -int32_t qRebuildStmtDataBlock(void** pDst, void* pSrc, uint64_t uid, int32_t vgId) { - int32_t code = qCloneStmtDataBlock(pDst, pSrc); +int32_t qRebuildStmtDataBlock(STableDataCxt** pDst, STableDataCxt* pSrc, uint64_t uid, uint64_t suid, int32_t vgId, + bool rebuildCreateTb) { + int32_t code = qCloneStmtDataBlock(pDst, pSrc, false); if (code) { return code; } - STableDataBlocks* pBlock = (STableDataBlocks*)*pDst; - pBlock->pData = taosMemoryMalloc(pBlock->nAllocSize); - if (NULL == pBlock->pData) { - qDestroyStmtDataBlock(pBlock); - return TSDB_CODE_OUT_OF_MEMORY; + STableDataCxt* pBlock = (STableDataCxt*)*pDst; + if (pBlock->pMeta) { + pBlock->pMeta->uid = uid; + pBlock->pMeta->vgId = vgId; + pBlock->pMeta->suid = suid; } - pBlock->vgId = vgId; + pBlock->pData->suid = suid; + pBlock->pData->uid = uid; - if (pBlock->pTableMeta) { - pBlock->pTableMeta->uid = uid; - pBlock->pTableMeta->vgId = vgId; + if (rebuildCreateTb && NULL == pBlock->pData->pCreateTbReq) { + pBlock->pData->pCreateTbReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq)); + if (NULL == pBlock->pData->pCreateTbReq) { + return TSDB_CODE_OUT_OF_MEMORY; + } } - memset(pBlock->pData, 0, sizeof(SSubmitBlk)); - return TSDB_CODE_SUCCESS; } -STableMeta* qGetTableMetaInDataBlock(void* pDataBlock) { return ((STableDataBlocks*)pDataBlock)->pTableMeta; } +STableMeta* qGetTableMetaInDataBlock(STableDataCxt* pDataBlock) { return ((STableDataCxt*)pDataBlock)->pMeta; } -void qFreeStmtDataBlock(void* pDataBlock) { - if (pDataBlock == NULL) { - return; - } - - taosMemoryFreeClear(((STableDataBlocks*)pDataBlock)->pTableMeta); - taosMemoryFreeClear(((STableDataBlocks*)pDataBlock)->pData); - taosMemoryFreeClear(pDataBlock); -} - -void qDestroyStmtDataBlock(void* pBlock) { +void qDestroyStmtDataBlock(STableDataCxt* pBlock) { if (pBlock == NULL) { return; } - STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock; - - pDataBlock->cloned = false; - insDestroyDataBlock(pDataBlock); + STableDataCxt* pDataBlock = (STableDataCxt*)pBlock; + insDestroyTableDataCxt(pDataBlock); } diff --git a/source/libs/parser/src/parInsertUtil.c b/source/libs/parser/src/parInsertUtil.c index 73cedfeb3d4109622062477214cd148bdd441391..f921094752f337796b66c24c27db42fd8e54d5eb 100644 --- a/source/libs/parser/src/parInsertUtil.c +++ b/source/libs/parser/src/parInsertUtil.c @@ -20,938 +20,687 @@ #include "parUtil.h" #include "querynodes.h" #include "tRealloc.h" +#include "tdatablock.h" -typedef struct SBlockKeyTuple { - TSKEY skey; - void* payloadAddr; - int16_t index; -} SBlockKeyTuple; - -typedef struct SBlockKeyInfo { - int32_t maxBytesAlloc; - SBlockKeyTuple* pKeyTuple; -} SBlockKeyInfo; +void qDestroyBoundColInfo(void* pInfo) { + if (NULL == pInfo) { + return; + } -typedef struct { - int32_t index; - SArray* rowArray; // array of merged rows(mem allocated by tRealloc/free by tFree) - STSchema* pSchema; - int64_t tbUid; // suid for child table, uid for normal table -} SBlockRowMerger; + SBoundColInfo* pBoundInfo = (SBoundColInfo*)pInfo; -static FORCE_INLINE void tdResetSBlockRowMerger(SBlockRowMerger* pMerger) { - if (pMerger) { - pMerger->index = -1; - } + taosMemoryFreeClear(pBoundInfo->pColIndex); } -static void tdFreeSBlockRowMerger(SBlockRowMerger* pMerger) { - if (pMerger) { - int32_t size = taosArrayGetSize(pMerger->rowArray); - for (int32_t i = 0; i < size; ++i) { - tFree(*(void**)taosArrayGet(pMerger->rowArray, i)); +static char* tableNameGetPosition(SToken* pToken, char target) { + bool inEscape = false; + bool inQuote = false; + char quotaStr = 0; + + for (uint32_t i = 0; i < pToken->n; ++i) { + if (*(pToken->z + i) == target && (!inEscape) && (!inQuote)) { + return pToken->z + i; } - taosArrayDestroy(pMerger->rowArray); - taosMemoryFreeClear(pMerger->pSchema); - taosMemoryFree(pMerger); - } -} + if (*(pToken->z + i) == TS_ESCAPE_CHAR) { + if (!inQuote) { + inEscape = !inEscape; + } + } -static int32_t rowDataCompar(const void* lhs, const void* rhs) { - TSKEY left = *(TSKEY*)lhs; - TSKEY right = *(TSKEY*)rhs; - if (left == right) { - return 0; - } else { - return left > right ? 1 : -1; + if (*(pToken->z + i) == '\'' || *(pToken->z + i) == '"') { + if (!inEscape) { + if (!inQuote) { + quotaStr = *(pToken->z + i); + inQuote = !inQuote; + } else if (quotaStr == *(pToken->z + i)) { + inQuote = !inQuote; + } + } + } } -} -static int32_t rowDataComparStable(const void* lhs, const void* rhs) { - TSKEY left = *(TSKEY*)lhs; - TSKEY right = *(TSKEY*)rhs; - if (left == right) { - return ((SBlockKeyTuple*)lhs)->index - ((SBlockKeyTuple*)rhs)->index; - } else { - return left > right ? 1 : -1; - } + return NULL; } -int32_t insGetExtendedRowSize(STableDataBlocks* pBlock) { - STableComInfo* pTableInfo = &pBlock->pTableMeta->tableInfo; - ASSERT(pBlock->rowSize == pTableInfo->rowSize); - return pBlock->rowSize + TD_ROW_HEAD_LEN - sizeof(TSKEY) + pBlock->boundColumnInfo.extendedVarLen + - (int32_t)TD_BITMAP_BYTES(pTableInfo->numOfColumns - 1); -} +int32_t insCreateSName(SName* pName, SToken* pTableName, int32_t acctId, const char* dbName, SMsgBuf* pMsgBuf) { + const char* msg1 = "name too long"; + const char* msg2 = "invalid database name"; + const char* msg3 = "db is not specified"; + const char* msg4 = "invalid table name"; -void insGetSTSRowAppendInfo(uint8_t rowType, SParsedDataColInfo* spd, col_id_t idx, int32_t* toffset, - col_id_t* colIdx) { - col_id_t schemaIdx = 0; - if (IS_DATA_COL_ORDERED(spd)) { - schemaIdx = spd->boundColumns[idx]; - if (TD_IS_TP_ROW_T(rowType)) { - *toffset = (spd->cols + schemaIdx)->toffset; // the offset of firstPart - *colIdx = schemaIdx; - } else { - *toffset = idx * sizeof(SKvRowIdx); // the offset of SKvRowIdx - *colIdx = idx; + int32_t code = TSDB_CODE_SUCCESS; + char* p = tableNameGetPosition(pTableName, TS_PATH_DELIMITER[0]); + + if (p != NULL) { // db has been specified in sql string so we ignore current db path + int32_t dbLen = p - pTableName->z; + if (dbLen <= 0) { + return buildInvalidOperationMsg(pMsgBuf, msg2); } - } else { - ASSERT(idx == (spd->colIdxInfo + idx)->boundIdx); - schemaIdx = (spd->colIdxInfo + idx)->schemaColIdx; - if (TD_IS_TP_ROW_T(rowType)) { - *toffset = (spd->cols + schemaIdx)->toffset; - *colIdx = schemaIdx; - } else { - *toffset = ((spd->colIdxInfo + idx)->finalIdx) * sizeof(SKvRowIdx); - *colIdx = (spd->colIdxInfo + idx)->finalIdx; + char name[TSDB_DB_FNAME_LEN] = {0}; + strncpy(name, pTableName->z, dbLen); + int32_t actualDbLen = strdequote(name); + + code = tNameSetDbName(pName, acctId, name, actualDbLen); + if (code != TSDB_CODE_SUCCESS) { + return buildInvalidOperationMsg(pMsgBuf, msg1); } - } -} -int32_t insSetBlockInfo(SSubmitBlk* pBlocks, STableDataBlocks* dataBuf, int32_t numOfRows, SMsgBuf* pMsg) { - pBlocks->suid = (TSDB_NORMAL_TABLE == dataBuf->pTableMeta->tableType ? 0 : dataBuf->pTableMeta->suid); - pBlocks->uid = dataBuf->pTableMeta->uid; - pBlocks->sversion = dataBuf->pTableMeta->sversion; - pBlocks->schemaLen = dataBuf->createTbReqLen; + int32_t tbLen = pTableName->n - dbLen - 1; + if (tbLen <= 0) { + return buildInvalidOperationMsg(pMsgBuf, msg4); + } - if (pBlocks->numOfRows + numOfRows >= INT32_MAX) { - return buildInvalidOperationMsg(pMsg, "too many rows in sql, total number of rows should be less than INT32_MAX"); - } - pBlocks->numOfRows += numOfRows; - return TSDB_CODE_SUCCESS; -} + char tbname[TSDB_TABLE_FNAME_LEN] = {0}; + strncpy(tbname, p + 1, tbLen); + /*tbLen = */ strdequote(tbname); -void insSetBoundColumnInfo(SParsedDataColInfo* pColList, SSchema* pSchema, col_id_t numOfCols) { - pColList->numOfCols = numOfCols; - pColList->numOfBound = numOfCols; - pColList->orderStatus = ORDER_STATUS_ORDERED; // default is ORDERED for non-bound mode - pColList->boundColumns = taosMemoryCalloc(pColList->numOfCols, sizeof(col_id_t)); - pColList->cols = taosMemoryCalloc(pColList->numOfCols, sizeof(SBoundColumn)); - pColList->colIdxInfo = NULL; - pColList->flen = 0; - pColList->allNullLen = 0; - - int32_t nVar = 0; - for (int32_t i = 0; i < pColList->numOfCols; ++i) { - uint8_t type = pSchema[i].type; - if (i > 0) { - pColList->cols[i].offset = pColList->cols[i - 1].offset + pSchema[i - 1].bytes; - pColList->cols[i].toffset = pColList->flen; - pColList->flen += TYPE_BYTES[type]; + code = tNameFromString(pName, tbname, T_NAME_TABLE); + if (code != 0) { + return buildInvalidOperationMsg(pMsgBuf, msg1); } - switch (type) { - case TSDB_DATA_TYPE_BINARY: - pColList->allNullLen += (VARSTR_HEADER_SIZE + CHAR_BYTES); - ++nVar; - break; - case TSDB_DATA_TYPE_NCHAR: - pColList->allNullLen += (VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE); - ++nVar; - break; - default: - break; + } else { // get current DB name first, and then set it into path + if (pTableName->n >= TSDB_TABLE_NAME_LEN) { + return buildInvalidOperationMsg(pMsgBuf, msg1); + } + + char name[TSDB_TABLE_FNAME_LEN] = {0}; + strncpy(name, pTableName->z, pTableName->n); + strdequote(name); + + if (dbName == NULL) { + return buildInvalidOperationMsg(pMsgBuf, msg3); + } + + code = tNameSetDbName(pName, acctId, dbName, strlen(dbName)); + if (code != TSDB_CODE_SUCCESS) { + code = buildInvalidOperationMsg(pMsgBuf, msg2); + return code; + } + + code = tNameFromString(pName, name, T_NAME_TABLE); + if (code != 0) { + code = buildInvalidOperationMsg(pMsgBuf, msg1); } - pColList->boundColumns[i] = i; } - pColList->allNullLen += pColList->flen; - pColList->boundNullLen = pColList->allNullLen; // default set allNullLen - pColList->extendedVarLen = (uint16_t)(nVar * sizeof(VarDataOffsetT)); -} -int32_t insSchemaIdxCompar(const void* lhs, const void* rhs) { - uint16_t left = *(uint16_t*)lhs; - uint16_t right = *(uint16_t*)rhs; + if (NULL != strchr(pName->tname, '.')) { + code = generateSyntaxErrMsgExt(pMsgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, "The table name cannot contain '.'"); + } + + return code; +} - if (left == right) { - return 0; - } else { - return left > right ? 1 : -1; +int16_t insFindCol(SToken* pColname, int16_t start, int16_t end, SSchema* pSchema) { + while (start < end) { + if (strlen(pSchema[start].name) == pColname->n && strncmp(pColname->z, pSchema[start].name, pColname->n) == 0) { + return start; + } + ++start; } + return -1; } -int32_t insBoundIdxCompar(const void* lhs, const void* rhs) { - uint16_t left = *(uint16_t*)POINTER_SHIFT(lhs, sizeof(uint16_t)); - uint16_t right = *(uint16_t*)POINTER_SHIFT(rhs, sizeof(uint16_t)); +void insBuildCreateTbReq(SVCreateTbReq* pTbReq, const char* tname, STag* pTag, int64_t suid, const char* sname, + SArray* tagName, uint8_t tagNum, int32_t ttl) { + pTbReq->type = TD_CHILD_TABLE; + pTbReq->name = taosStrdup(tname); + pTbReq->ctb.suid = suid; + pTbReq->ctb.tagNum = tagNum; + if (sname) pTbReq->ctb.stbName = taosStrdup(sname); + pTbReq->ctb.pTag = (uint8_t*)pTag; + pTbReq->ctb.tagName = taosArrayDup(tagName, NULL); + pTbReq->ttl = ttl; + pTbReq->commentLen = -1; + + return; +} - if (left == right) { - return 0; - } else { - return left > right ? 1 : -1; +static void initBoundCols(int32_t ncols, int16_t* pBoundCols) { + for (int32_t i = 0; i < ncols; ++i) { + pBoundCols[i] = i; } } -void destroyBoundColumnInfo(void* pBoundInfo) { - if (NULL == pBoundInfo) { - return; +static void initColValues(STableMeta* pTableMeta, SArray* pValues) { + SSchema* pSchemas = getTableColumnSchema(pTableMeta); + for (int32_t i = 0; i < pTableMeta->tableInfo.numOfColumns; ++i) { + SColVal val = COL_VAL_NONE(pSchemas[i].colId, pSchemas[i].type); + taosArrayPush(pValues, &val); } - - SParsedDataColInfo* pColList = (SParsedDataColInfo*)pBoundInfo; - - taosMemoryFreeClear(pColList->boundColumns); - taosMemoryFreeClear(pColList->cols); - taosMemoryFreeClear(pColList->colIdxInfo); } -static int32_t createDataBlock(size_t defaultSize, int32_t rowSize, int32_t startOffset, STableMeta* pTableMeta, - STableDataBlocks** dataBlocks) { - STableDataBlocks* dataBuf = (STableDataBlocks*)taosMemoryCalloc(1, sizeof(STableDataBlocks)); - if (dataBuf == NULL) { +int32_t insInitBoundColsInfo(int32_t numOfBound, SBoundColInfo* pInfo) { + pInfo->numOfCols = numOfBound; + pInfo->numOfBound = numOfBound; + pInfo->pColIndex = taosMemoryCalloc(numOfBound, sizeof(int16_t)); + if (NULL == pInfo->pColIndex) { return TSDB_CODE_OUT_OF_MEMORY; } + initBoundCols(numOfBound, pInfo->pColIndex); + return TSDB_CODE_SUCCESS; +} - dataBuf->nAllocSize = (uint32_t)defaultSize; - dataBuf->headerSize = startOffset; +void insCheckTableDataOrder(STableDataCxt* pTableCxt, TSKEY tsKey) { + // once the data block is disordered, we do NOT keep last timestamp any more + if (!pTableCxt->ordered) { + return; + } - // the header size will always be the startOffset value, reserved for the subumit block header - if (dataBuf->nAllocSize <= dataBuf->headerSize) { - dataBuf->nAllocSize = dataBuf->headerSize * 2; + if (tsKey < pTableCxt->lastTs) { + pTableCxt->ordered = false; } - dataBuf->pData = taosMemoryMalloc(dataBuf->nAllocSize); - if (dataBuf->pData == NULL) { - taosMemoryFreeClear(dataBuf); - return TSDB_CODE_OUT_OF_MEMORY; + if (tsKey == pTableCxt->lastTs) { + pTableCxt->duplicateTs = true; } - memset(dataBuf->pData, 0, sizeof(SSubmitBlk)); - dataBuf->pTableMeta = tableMetaDup(pTableMeta); + pTableCxt->lastTs = tsKey; + return; +} - SParsedDataColInfo* pColInfo = &dataBuf->boundColumnInfo; - SSchema* pSchema = getTableColumnSchema(dataBuf->pTableMeta); - insSetBoundColumnInfo(pColInfo, pSchema, dataBuf->pTableMeta->tableInfo.numOfColumns); +void insDestroyBoundColInfo(SBoundColInfo* pInfo) { taosMemoryFreeClear(pInfo->pColIndex); } - dataBuf->ordered = true; - dataBuf->prevTS = INT64_MIN; - dataBuf->rowSize = rowSize; - dataBuf->size = startOffset; - dataBuf->vgId = dataBuf->pTableMeta->vgId; +static int32_t createTableDataCxt(STableMeta* pTableMeta, SVCreateTbReq** pCreateTbReq, STableDataCxt** pOutput, + bool colMode) { + STableDataCxt* pTableCxt = taosMemoryCalloc(1, sizeof(STableDataCxt)); + if (NULL == pTableCxt) { + return TSDB_CODE_OUT_OF_MEMORY; + } - assert(defaultSize > 0 && pTableMeta != NULL && dataBuf->pTableMeta != NULL); + int32_t code = TSDB_CODE_SUCCESS; - *dataBlocks = dataBuf; - return TSDB_CODE_SUCCESS; -} + pTableCxt->lastTs = 0; + pTableCxt->ordered = true; + pTableCxt->duplicateTs = false; -int32_t insBuildCreateTbMsg(STableDataBlocks* pBlocks, SVCreateTbReq* pCreateTbReq) { - SEncoder coder = {0}; - char* pBuf; - int32_t len; - - int32_t ret = 0; - tEncodeSize(tEncodeSVCreateTbReq, pCreateTbReq, len, ret); - if (pBlocks->nAllocSize - pBlocks->size < len) { - pBlocks->nAllocSize += len + pBlocks->rowSize; - char* pTmp = taosMemoryRealloc(pBlocks->pData, pBlocks->nAllocSize); - if (pTmp != NULL) { - pBlocks->pData = pTmp; - memset(pBlocks->pData + pBlocks->size, 0, pBlocks->nAllocSize - pBlocks->size); + pTableCxt->pMeta = tableMetaDup(pTableMeta); + if (NULL == pTableCxt->pMeta) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + if (TSDB_CODE_SUCCESS == code) { + pTableCxt->pSchema = + tBuildTSchema(getTableColumnSchema(pTableMeta), pTableMeta->tableInfo.numOfColumns, pTableMeta->sversion); + if (NULL == pTableCxt->pSchema) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + } + if (TSDB_CODE_SUCCESS == code) { + code = insInitBoundColsInfo(pTableMeta->tableInfo.numOfColumns, &pTableCxt->boundColsInfo); + } + if (TSDB_CODE_SUCCESS == code) { + pTableCxt->pValues = taosArrayInit(pTableMeta->tableInfo.numOfColumns, sizeof(SColVal)); + if (NULL == pTableCxt->pValues) { + code = TSDB_CODE_OUT_OF_MEMORY; } else { - pBlocks->nAllocSize -= len + pBlocks->rowSize; - return TSDB_CODE_OUT_OF_MEMORY; + initColValues(pTableMeta, pTableCxt->pValues); + } + } + if (TSDB_CODE_SUCCESS == code) { + pTableCxt->pData = taosMemoryCalloc(1, sizeof(SSubmitTbData)); + if (NULL == pTableCxt->pData) { + code = TSDB_CODE_OUT_OF_MEMORY; + } else { + pTableCxt->pData->flags = NULL != *pCreateTbReq ? SUBMIT_REQ_AUTO_CREATE_TABLE : 0; + pTableCxt->pData->flags |= colMode ? SUBMIT_REQ_COLUMN_DATA_FORMAT : 0; + pTableCxt->pData->suid = pTableMeta->suid; + pTableCxt->pData->uid = pTableMeta->uid; + pTableCxt->pData->sver = pTableMeta->sversion; + pTableCxt->pData->pCreateTbReq = *pCreateTbReq; + *pCreateTbReq = NULL; + if (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { + pTableCxt->pData->aCol = taosArrayInit(128, sizeof(SColData)); + if (NULL == pTableCxt->pData->aCol) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + } else { + pTableCxt->pData->aRowP = taosArrayInit(128, POINTER_BYTES); + if (NULL == pTableCxt->pData->aRowP) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + } } } - pBuf = pBlocks->pData + pBlocks->size; - - tEncoderInit(&coder, pBuf, len); - int32_t code = tEncodeSVCreateTbReq(&coder, pCreateTbReq); - tEncoderClear(&coder); - pBlocks->size += len; - pBlocks->createTbReqLen = len; + if (TSDB_CODE_SUCCESS == code) { + *pOutput = pTableCxt; + qDebug("tableDataCxt created, uid:%" PRId64 ", vgId:%d", pTableMeta->uid, pTableMeta->vgId); + } else { + taosMemoryFree(pTableCxt); + } return code; } -void insDestroyDataBlock(STableDataBlocks* pDataBlock) { - if (pDataBlock == NULL) { - return; +static void resetColValues(SArray* pValues) { + int32_t num = taosArrayGetSize(pValues); + for (int32_t i = 0; i < num; ++i) { + SColVal* pVal = taosArrayGet(pValues, i); + pVal->flag = CV_FLAG_NONE; } +} - taosMemoryFreeClear(pDataBlock->pData); - taosMemoryFreeClear(pDataBlock->pTableMeta); - destroyBoundColumnInfo(&pDataBlock->boundColumnInfo); - taosMemoryFreeClear(pDataBlock); +int32_t insGetTableDataCxt(SHashObj* pHash, void* id, int32_t idLen, STableMeta* pTableMeta, + SVCreateTbReq** pCreateTbReq, STableDataCxt** pTableCxt, bool colMode) { + STableDataCxt** tmp = (STableDataCxt**)taosHashGet(pHash, id, idLen); + if (NULL != tmp) { + *pTableCxt = *tmp; + resetColValues((*pTableCxt)->pValues); + return TSDB_CODE_SUCCESS; + } + int32_t code = createTableDataCxt(pTableMeta, pCreateTbReq, pTableCxt, colMode); + if (TSDB_CODE_SUCCESS == code) { + void* pData = *pTableCxt; // deal scan coverity + code = taosHashPut(pHash, id, idLen, &pData, POINTER_BYTES); + } + return code; } -int32_t insGetDataBlockFromList(SHashObj* pHashList, void* id, int32_t idLen, int32_t size, int32_t startOffset, - int32_t rowSize, STableMeta* pTableMeta, STableDataBlocks** dataBlocks, - SArray* pBlockList, SVCreateTbReq* pCreateTbReq) { - *dataBlocks = NULL; - STableDataBlocks** t1 = (STableDataBlocks**)taosHashGet(pHashList, (const char*)id, idLen); - if (t1 != NULL) { - *dataBlocks = *t1; +static void destroyColVal(void* p) { + SColVal* pVal = p; + if (TSDB_DATA_TYPE_NCHAR == pVal->type) { + taosMemoryFree(pVal->value.pData); } +} - if (*dataBlocks == NULL) { - int32_t ret = createDataBlock((size_t)size, rowSize, startOffset, pTableMeta, dataBlocks); - if (ret != TSDB_CODE_SUCCESS) { - return ret; - } +void insDestroyTableDataCxt(STableDataCxt* pTableCxt) { + if (NULL == pTableCxt) { + return; + } - if (NULL != pCreateTbReq && NULL != pCreateTbReq->ctb.pTag) { - ret = insBuildCreateTbMsg(*dataBlocks, pCreateTbReq); - if (ret != TSDB_CODE_SUCCESS) { - insDestroyDataBlock(*dataBlocks); - return ret; - } - } + taosMemoryFreeClear(pTableCxt->pMeta); + tDestroyTSchema(pTableCxt->pSchema); + insDestroyBoundColInfo(&pTableCxt->boundColsInfo); + taosArrayDestroyEx(pTableCxt->pValues, destroyColVal); + if (pTableCxt->pData) { + tDestroySubmitTbData(pTableCxt->pData, TSDB_MSG_FLG_ENCODE); + taosMemoryFree(pTableCxt->pData); + } + taosMemoryFree(pTableCxt); +} - // converting to 'const char*' is to handle coverity scan errors - taosHashPut(pHashList, (const char*)id, idLen, (const char*)dataBlocks, POINTER_BYTES); - if (pBlockList) { - taosArrayPush(pBlockList, dataBlocks); - } +void insDestroyVgroupDataCxt(SVgroupDataCxt* pVgCxt) { + if (NULL == pVgCxt) { + return; } - return TSDB_CODE_SUCCESS; + tDestroySubmitReq(pVgCxt->pData, TSDB_MSG_FLG_ENCODE); + taosMemoryFree(pVgCxt->pData); + taosMemoryFree(pVgCxt); } -void insDestroyBlockArrayList(SArray* pDataBlockList) { - if (pDataBlockList == NULL) { +void insDestroyVgroupDataCxtList(SArray* pVgCxtList) { + if (NULL == pVgCxtList) { return; } - size_t size = taosArrayGetSize(pDataBlockList); + size_t size = taosArrayGetSize(pVgCxtList); for (int32_t i = 0; i < size; i++) { - void* p = taosArrayGetP(pDataBlockList, i); - insDestroyDataBlock(p); + void* p = taosArrayGetP(pVgCxtList, i); + insDestroyVgroupDataCxt(p); } - taosArrayDestroy(pDataBlockList); + taosArrayDestroy(pVgCxtList); } -void insDestroyBlockHashmap(SHashObj* pDataBlockHash) { - if (pDataBlockHash == NULL) { +void insDestroyVgroupDataCxtHashMap(SHashObj* pVgCxtHash) { + if (NULL == pVgCxtHash) { return; } - void** p1 = taosHashIterate(pDataBlockHash, NULL); - while (p1) { - STableDataBlocks* pBlocks = *p1; - insDestroyDataBlock(pBlocks); + void** p = taosHashIterate(pVgCxtHash, NULL); + while (p) { + insDestroyVgroupDataCxt(*(SVgroupDataCxt**)p); - p1 = taosHashIterate(pDataBlockHash, p1); + p = taosHashIterate(pVgCxtHash, p); } - taosHashCleanup(pDataBlockHash); + taosHashCleanup(pVgCxtHash); } -// data block is disordered, sort it in ascending order -static int sortRemoveDataBlockDupRows(STableDataBlocks* dataBuf, SBlockKeyInfo* pBlkKeyInfo) { - SSubmitBlk* pBlocks = (SSubmitBlk*)dataBuf->pData; - int16_t nRows = pBlocks->numOfRows; - - // size is less than the total size, since duplicated rows may be removed yet. - - // allocate memory - size_t nAlloc = nRows * sizeof(SBlockKeyTuple); - if (pBlkKeyInfo->pKeyTuple == NULL || pBlkKeyInfo->maxBytesAlloc < nAlloc) { - char* tmp = taosMemoryRealloc(pBlkKeyInfo->pKeyTuple, nAlloc); - if (tmp == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - pBlkKeyInfo->pKeyTuple = (SBlockKeyTuple*)tmp; - pBlkKeyInfo->maxBytesAlloc = (int32_t)nAlloc; +void insDestroyTableDataCxtHashMap(SHashObj* pTableCxtHash) { + if (NULL == pTableCxtHash) { + return; } - memset(pBlkKeyInfo->pKeyTuple, 0, nAlloc); - int32_t extendedRowSize = insGetExtendedRowSize(dataBuf); - SBlockKeyTuple* pBlkKeyTuple = pBlkKeyInfo->pKeyTuple; - char* pBlockData = pBlocks->data + pBlocks->schemaLen; - int n = 0; - while (n < nRows) { - pBlkKeyTuple->skey = TD_ROW_KEY((STSRow*)pBlockData); - pBlkKeyTuple->payloadAddr = pBlockData; - pBlkKeyTuple->index = n; + void** p = taosHashIterate(pTableCxtHash, NULL); + while (p) { + insDestroyTableDataCxt(*(STableDataCxt**)p); - // next loop - pBlockData += extendedRowSize; - ++pBlkKeyTuple; - ++n; + p = taosHashIterate(pTableCxtHash, p); } - if (!dataBuf->ordered) { - pBlkKeyTuple = pBlkKeyInfo->pKeyTuple; - - // todo. qsort is unstable, if timestamp is same, should get the last one - taosSort(pBlkKeyTuple, nRows, sizeof(SBlockKeyTuple), rowDataComparStable); - - pBlkKeyTuple = pBlkKeyInfo->pKeyTuple; - int32_t i = 0; - int32_t j = 1; - while (j < nRows) { - TSKEY ti = (pBlkKeyTuple + i)->skey; - TSKEY tj = (pBlkKeyTuple + j)->skey; - - if (ti == tj) { - ++j; - continue; - } + taosHashCleanup(pTableCxtHash); +} - int32_t nextPos = (++i); - if (nextPos != j) { - memmove(pBlkKeyTuple + nextPos, pBlkKeyTuple + j, sizeof(SBlockKeyTuple)); - } - ++j; +static int32_t fillVgroupDataCxt(STableDataCxt* pTableCxt, SVgroupDataCxt* pVgCxt) { + if (NULL == pVgCxt->pData->aSubmitTbData) { + pVgCxt->pData->aSubmitTbData = taosArrayInit(128, sizeof(SSubmitTbData)); + if (NULL == pVgCxt->pData->aSubmitTbData) { + return TSDB_CODE_OUT_OF_MEMORY; } - - dataBuf->ordered = true; - pBlocks->numOfRows = i + 1; } + taosArrayPush(pVgCxt->pData->aSubmitTbData, pTableCxt->pData); + taosMemoryFreeClear(pTableCxt->pData); - dataBuf->size = sizeof(SSubmitBlk) + pBlocks->numOfRows * extendedRowSize; - dataBuf->prevTS = INT64_MIN; - - return 0; -} + qDebug("add tableDataCxt uid:%" PRId64 " to vgId:%d", pTableCxt->pMeta->uid, pVgCxt->vgId); -static void* tdGetCurRowFromBlockMerger(SBlockRowMerger* pBlkRowMerger) { - if (pBlkRowMerger && (pBlkRowMerger->index >= 0)) { - ASSERT(pBlkRowMerger->index < taosArrayGetSize(pBlkRowMerger->rowArray)); - return *(void**)taosArrayGet(pBlkRowMerger->rowArray, pBlkRowMerger->index); - } - return NULL; + return TSDB_CODE_SUCCESS; } -static int32_t tdBlockRowMerge(STableMeta* pTableMeta, SBlockKeyTuple* pEndKeyTp, int32_t nDupRows, - SBlockRowMerger** pBlkRowMerger, int32_t rowSize) { - ASSERT(nDupRows > 1); - SBlockKeyTuple* pStartKeyTp = pEndKeyTp - (nDupRows - 1); - ASSERT(pStartKeyTp->skey == pEndKeyTp->skey); - - // TODO: optimization if end row is all normal -#if 0 - STSRow* pEndRow = (STSRow*)pEndKeyTp->payloadAddr; - if(isNormal(pEndRow)) { // set the end row if it is normal and return directly - pStartKeyTp->payloadAddr = pEndKeyTp->payloadAddr; - return TSDB_CODE_SUCCESS; - } -#endif - - if (!(*pBlkRowMerger)) { - (*pBlkRowMerger) = taosMemoryCalloc(1, sizeof(**pBlkRowMerger)); - if (!(*pBlkRowMerger)) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return TSDB_CODE_FAILED; - } - (*pBlkRowMerger)->index = -1; - if (!(*pBlkRowMerger)->rowArray) { - (*pBlkRowMerger)->rowArray = taosArrayInit(1, sizeof(void*)); - if (!(*pBlkRowMerger)->rowArray) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return TSDB_CODE_FAILED; - } - } - } - - if ((*pBlkRowMerger)->pSchema) { - if ((*pBlkRowMerger)->pSchema->version != pTableMeta->sversion) { - taosMemoryFreeClear((*pBlkRowMerger)->pSchema); - } else { - if ((*pBlkRowMerger)->tbUid != (pTableMeta->suid > 0 ? pTableMeta->suid : pTableMeta->uid)) { - taosMemoryFreeClear((*pBlkRowMerger)->pSchema); - } - } +static int32_t createVgroupDataCxt(STableDataCxt* pTableCxt, SHashObj* pVgroupHash, SArray* pVgroupList, + SVgroupDataCxt** pOutput) { + SVgroupDataCxt* pVgCxt = taosMemoryCalloc(1, sizeof(SVgroupDataCxt)); + if (NULL == pVgCxt) { + return TSDB_CODE_OUT_OF_MEMORY; } - - if (!(*pBlkRowMerger)->pSchema) { - (*pBlkRowMerger)->pSchema = - tdGetSTSChemaFromSSChema(pTableMeta->schema, pTableMeta->tableInfo.numOfColumns, pTableMeta->sversion); - - if (!(*pBlkRowMerger)->pSchema) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return TSDB_CODE_FAILED; - } - (*pBlkRowMerger)->tbUid = pTableMeta->suid > 0 ? pTableMeta->suid : pTableMeta->uid; + pVgCxt->pData = taosMemoryCalloc(1, sizeof(SSubmitReq2)); + if (NULL == pVgCxt->pData) { + insDestroyVgroupDataCxt(pVgCxt); + return TSDB_CODE_OUT_OF_MEMORY; } - void* pDestRow = NULL; - ++((*pBlkRowMerger)->index); - if ((*pBlkRowMerger)->index < taosArrayGetSize((*pBlkRowMerger)->rowArray)) { - void** pAlloc = (void**)taosArrayGet((*pBlkRowMerger)->rowArray, (*pBlkRowMerger)->index); - if (tRealloc((uint8_t**)pAlloc, rowSize) != 0) { - return TSDB_CODE_FAILED; - } - pDestRow = *pAlloc; + pVgCxt->vgId = pTableCxt->pMeta->vgId; + int32_t code = taosHashPut(pVgroupHash, &pVgCxt->vgId, sizeof(pVgCxt->vgId), &pVgCxt, POINTER_BYTES); + if (TSDB_CODE_SUCCESS == code) { + taosArrayPush(pVgroupList, &pVgCxt); +// uDebug("td23101 2vgId:%d, uid:%" PRIu64, pVgCxt->vgId, pTableCxt->pMeta->uid); + *pOutput = pVgCxt; } else { - if (tRealloc((uint8_t**)&pDestRow, rowSize) != 0) { - return TSDB_CODE_FAILED; - } - taosArrayPush((*pBlkRowMerger)->rowArray, &pDestRow); - } - - // merge rows to pDestRow - STSchema* pSchema = (*pBlkRowMerger)->pSchema; - SArray* pArray = taosArrayInit(pSchema->numOfCols, sizeof(SColVal)); - for (int32_t i = 0; i < pSchema->numOfCols; ++i) { - SColVal colVal = {0}; - for (int32_t j = 0; j < nDupRows; ++j) { - tTSRowGetVal((pEndKeyTp - j)->payloadAddr, pSchema, i, &colVal); - if (!COL_VAL_IS_NONE(&colVal)) { - break; - } - } - taosArrayPush(pArray, &colVal); - } - if (tdSTSRowNew(pArray, pSchema, (STSRow**)&pDestRow) < 0) { - taosArrayDestroy(pArray); - return TSDB_CODE_FAILED; + insDestroyVgroupDataCxt(pVgCxt); } - - taosArrayDestroy(pArray); - return TSDB_CODE_SUCCESS; + return code; } -// data block is disordered, sort it in ascending order, and merge dup rows if exists -static int sortMergeDataBlockDupRows(STableDataBlocks* dataBuf, SBlockKeyInfo* pBlkKeyInfo, - SBlockRowMerger** ppBlkRowMerger) { - SSubmitBlk* pBlocks = (SSubmitBlk*)dataBuf->pData; - STableMeta* pTableMeta = dataBuf->pTableMeta; - int32_t nRows = pBlocks->numOfRows; - - // size is less than the total size, since duplicated rows may be removed. - - // allocate memory - size_t nAlloc = nRows * sizeof(SBlockKeyTuple); - if (pBlkKeyInfo->pKeyTuple == NULL || pBlkKeyInfo->maxBytesAlloc < nAlloc) { - char* tmp = taosMemoryRealloc(pBlkKeyInfo->pKeyTuple, nAlloc); - if (tmp == NULL) { - return TSDB_CODE_OUT_OF_MEMORY; - } - pBlkKeyInfo->pKeyTuple = (SBlockKeyTuple*)tmp; - pBlkKeyInfo->maxBytesAlloc = (int32_t)nAlloc; +int insColDataComp(const void* lp, const void* rp) { + SColData* pLeft = (SColData*)lp; + SColData* pRight = (SColData*)rp; + if (pLeft->cid < pRight->cid) { + return -1; + } else if (pLeft->cid > pRight->cid) { + return 1; } - memset(pBlkKeyInfo->pKeyTuple, 0, nAlloc); - tdResetSBlockRowMerger(*ppBlkRowMerger); - - int32_t extendedRowSize = insGetExtendedRowSize(dataBuf); - SBlockKeyTuple* pBlkKeyTuple = pBlkKeyInfo->pKeyTuple; - char* pBlockData = pBlocks->data + pBlocks->schemaLen; - int32_t n = 0; - while (n < nRows) { - pBlkKeyTuple->skey = TD_ROW_KEY((STSRow*)pBlockData); - pBlkKeyTuple->payloadAddr = pBlockData; - pBlkKeyTuple->index = n; + return 0; +} - // next loop - pBlockData += extendedRowSize; - ++pBlkKeyTuple; - ++n; +int32_t insMergeTableDataCxt(SHashObj* pTableHash, SArray** pVgDataBlocks) { + SHashObj* pVgroupHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, false); + SArray* pVgroupList = taosArrayInit(8, POINTER_BYTES); + if (NULL == pVgroupHash || NULL == pVgroupList) { + taosHashCleanup(pVgroupHash); + taosArrayDestroy(pVgroupList); + return TSDB_CODE_OUT_OF_MEMORY; } - if (!dataBuf->ordered) { - pBlkKeyTuple = pBlkKeyInfo->pKeyTuple; - - taosSort(pBlkKeyTuple, nRows, sizeof(SBlockKeyTuple), rowDataComparStable); - - pBlkKeyTuple = pBlkKeyInfo->pKeyTuple; - bool hasDup = false; - int32_t nextPos = 0; - int32_t i = 0; - int32_t j = 1; + int32_t code = TSDB_CODE_SUCCESS; + bool colFormat = false; - while (j < nRows) { - TSKEY ti = (pBlkKeyTuple + i)->skey; - TSKEY tj = (pBlkKeyTuple + j)->skey; + void* p = taosHashIterate(pTableHash, NULL); + if (p) { + STableDataCxt* pTableCxt = *(STableDataCxt**)p; + colFormat = (0 != (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT)); + } - if (ti == tj) { - ++j; + while (TSDB_CODE_SUCCESS == code && NULL != p) { + STableDataCxt* pTableCxt = *(STableDataCxt**)p; + if (colFormat) { + SColData* pCol = taosArrayGet(pTableCxt->pData->aCol, 0); + if (pCol->nVal <= 0) { + p = taosHashIterate(pTableHash, p); continue; } - if ((j - i) > 1) { - if (tdBlockRowMerge(pTableMeta, (pBlkKeyTuple + j - 1), j - i, ppBlkRowMerger, extendedRowSize) < 0) { - return TSDB_CODE_FAILED; - } - (pBlkKeyTuple + nextPos)->payloadAddr = tdGetCurRowFromBlockMerger(*ppBlkRowMerger); - if (!hasDup) { - hasDup = true; - } - i = j; - } else { - if (hasDup) { - memmove(pBlkKeyTuple + nextPos, pBlkKeyTuple + i, sizeof(SBlockKeyTuple)); - } - ++i; + if (pTableCxt->pData->pCreateTbReq) { + pTableCxt->pData->flags |= SUBMIT_REQ_AUTO_CREATE_TABLE; } - ++nextPos; - ++j; - } + taosArraySort(pTableCxt->pData->aCol, insColDataComp); - if ((j - i) > 1) { - ASSERT((pBlkKeyTuple + i)->skey == (pBlkKeyTuple + j - 1)->skey); - if (tdBlockRowMerge(pTableMeta, (pBlkKeyTuple + j - 1), j - i, ppBlkRowMerger, extendedRowSize) < 0) { - return TSDB_CODE_FAILED; + tColDataSortMerge(pTableCxt->pData->aCol); + } else { + if (!pTableCxt->ordered) { + tRowSort(pTableCxt->pData->aRowP); + } + if (!pTableCxt->ordered || pTableCxt->duplicateTs) { + code = tRowMerge(pTableCxt->pData->aRowP, pTableCxt->pSchema, 0); } - (pBlkKeyTuple + nextPos)->payloadAddr = tdGetCurRowFromBlockMerger(*ppBlkRowMerger); - } else if (hasDup) { - memmove(pBlkKeyTuple + nextPos, pBlkKeyTuple + i, sizeof(SBlockKeyTuple)); } - dataBuf->ordered = true; - pBlocks->numOfRows = nextPos + 1; - } - - dataBuf->size = sizeof(SSubmitBlk) + pBlocks->numOfRows * extendedRowSize; - dataBuf->prevTS = INT64_MIN; - - return TSDB_CODE_SUCCESS; -} - -// Erase the empty space reserved for binary data -static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, SBlockKeyTuple* blkKeyTuple) { - // TODO: optimize this function, handle the case while binary is not presented - int32_t nonDataLen = sizeof(SSubmitBlk) + pTableDataBlock->createTbReqLen; - SSubmitBlk* pBlock = pDataBlock; - memcpy(pDataBlock, pTableDataBlock->pData, nonDataLen); - pDataBlock = (char*)pDataBlock + nonDataLen; - - pBlock->schemaLen = pTableDataBlock->createTbReqLen; - pBlock->dataLen = 0; - - int32_t numOfRows = pBlock->numOfRows; - for (int32_t i = 0; i < numOfRows; ++i) { - void* payload = (blkKeyTuple + i)->payloadAddr; - TDRowLenT rowTLen = TD_ROW_LEN((STSRow*)payload); - memcpy(pDataBlock, payload, rowTLen); - pDataBlock = POINTER_SHIFT(pDataBlock, rowTLen); - pBlock->dataLen += rowTLen; - } - - return pBlock->dataLen + pBlock->schemaLen; -} - -int32_t insMergeTableDataBlocks(SHashObj* pHashObj, SArray** pVgDataBlocks) { - const int INSERT_HEAD_SIZE = sizeof(SSubmitReq); - int code = 0; - SHashObj* pVnodeDataBlockHashList = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, false); - SArray* pVnodeDataBlockList = taosArrayInit(8, POINTER_BYTES); - - STableDataBlocks** p = taosHashIterate(pHashObj, NULL); - STableDataBlocks* pOneTableBlock = *p; - SBlockKeyInfo blkKeyInfo = {0}; // share by pOneTableBlock - SBlockRowMerger* pBlkRowMerger = NULL; - - while (pOneTableBlock) { - SSubmitBlk* pBlocks = (SSubmitBlk*)pOneTableBlock->pData; - if (pBlocks->numOfRows > 0) { - STableDataBlocks* dataBuf = NULL; - pOneTableBlock->pTableMeta->vgId = pOneTableBlock->vgId; // for schemaless, restore origin vgId - int32_t ret = insGetDataBlockFromList(pVnodeDataBlockHashList, &pOneTableBlock->vgId, - sizeof(pOneTableBlock->vgId), TSDB_PAYLOAD_SIZE, INSERT_HEAD_SIZE, 0, - pOneTableBlock->pTableMeta, &dataBuf, pVnodeDataBlockList, NULL); - if (ret != TSDB_CODE_SUCCESS) { - tdFreeSBlockRowMerger(pBlkRowMerger); - taosHashCleanup(pVnodeDataBlockHashList); - insDestroyBlockArrayList(pVnodeDataBlockList); - taosMemoryFreeClear(blkKeyInfo.pKeyTuple); - return ret; - } - ASSERT(pOneTableBlock->pTableMeta->tableInfo.rowSize > 0); - // the maximum expanded size in byte when a row-wise data is converted to SDataRow format - int64_t destSize = dataBuf->size + pOneTableBlock->size + - sizeof(STColumn) * getNumOfColumns(pOneTableBlock->pTableMeta) + - pOneTableBlock->createTbReqLen; - - if (dataBuf->nAllocSize < destSize) { - dataBuf->nAllocSize = (uint32_t)(destSize * 1.5); - char* tmp = taosMemoryRealloc(dataBuf->pData, dataBuf->nAllocSize); - if (tmp != NULL) { - dataBuf->pData = tmp; - } else { // failed to allocate memory, free already allocated memory and return error code - tdFreeSBlockRowMerger(pBlkRowMerger); - taosHashCleanup(pVnodeDataBlockHashList); - insDestroyBlockArrayList(pVnodeDataBlockList); - taosMemoryFreeClear(dataBuf->pData); - taosMemoryFreeClear(blkKeyInfo.pKeyTuple); - return TSDB_CODE_OUT_OF_MEMORY; - } + if (TSDB_CODE_SUCCESS == code) { + SVgroupDataCxt* pVgCxt = NULL; + int32_t vgId = pTableCxt->pMeta->vgId; + void** pp = taosHashGet(pVgroupHash, &vgId, sizeof(vgId)); + if (NULL == pp) { + code = createVgroupDataCxt(pTableCxt, pVgroupHash, pVgroupList, &pVgCxt); + } else { + pVgCxt = *(SVgroupDataCxt**)pp; } - - if ((code = sortMergeDataBlockDupRows(pOneTableBlock, &blkKeyInfo, &pBlkRowMerger)) != 0) { - tdFreeSBlockRowMerger(pBlkRowMerger); - taosHashCleanup(pVnodeDataBlockHashList); - insDestroyBlockArrayList(pVnodeDataBlockList); - taosMemoryFreeClear(dataBuf->pData); - taosMemoryFreeClear(blkKeyInfo.pKeyTuple); - return code; + if (TSDB_CODE_SUCCESS == code) { + code = fillVgroupDataCxt(pTableCxt, pVgCxt); } - ASSERT(blkKeyInfo.pKeyTuple != NULL && pBlocks->numOfRows > 0); - - // erase the empty space reserved for binary data - int32_t finalLen = trimDataBlock(dataBuf->pData + dataBuf->size, pOneTableBlock, blkKeyInfo.pKeyTuple); - - dataBuf->size += (finalLen + sizeof(SSubmitBlk)); - assert(dataBuf->size <= dataBuf->nAllocSize); - dataBuf->numOfTables += 1; } - - p = taosHashIterate(pHashObj, p); - if (p == NULL) { - break; + if (TSDB_CODE_SUCCESS == code) { + p = taosHashIterate(pTableHash, p); } + } - pOneTableBlock = *p; + taosHashCleanup(pVgroupHash); + if (TSDB_CODE_SUCCESS == code) { + *pVgDataBlocks = pVgroupList; + } else { + insDestroyVgroupDataCxtList(pVgroupList); } - // free the table data blocks; - tdFreeSBlockRowMerger(pBlkRowMerger); - taosHashCleanup(pVnodeDataBlockHashList); - taosMemoryFreeClear(blkKeyInfo.pKeyTuple); - *pVgDataBlocks = pVnodeDataBlockList; - return TSDB_CODE_SUCCESS; + return code; } -int32_t insAllocateMemForSize(STableDataBlocks* pDataBlock, int32_t allSize) { - size_t remain = pDataBlock->nAllocSize - pDataBlock->size; - uint32_t nAllocSizeOld = pDataBlock->nAllocSize; - - // expand the allocated size - if (remain < allSize) { - pDataBlock->nAllocSize = (pDataBlock->size + allSize) * 1.5; - - char* tmp = taosMemoryRealloc(pDataBlock->pData, (size_t)pDataBlock->nAllocSize); - if (tmp != NULL) { - pDataBlock->pData = tmp; - memset(pDataBlock->pData + pDataBlock->size, 0, pDataBlock->nAllocSize - pDataBlock->size); - } else { - // do nothing, if allocate more memory failed - pDataBlock->nAllocSize = nAllocSizeOld; +static int32_t buildSubmitReq(int32_t vgId, SSubmitReq2* pReq, void** pData, uint32_t* pLen) { + int32_t code = TSDB_CODE_SUCCESS; + uint32_t len = 0; + void* pBuf = NULL; + tEncodeSize(tEncodeSubmitReq, pReq, len, code); + if (TSDB_CODE_SUCCESS == code) { + SEncoder encoder; + len += sizeof(SSubmitReq2Msg); + pBuf = taosMemoryMalloc(len); + if (NULL == pBuf) { return TSDB_CODE_OUT_OF_MEMORY; } + ((SSubmitReq2Msg*)pBuf)->header.vgId = htonl(vgId); + ((SSubmitReq2Msg*)pBuf)->header.contLen = htonl(len); + ((SSubmitReq2Msg*)pBuf)->version = htobe64(1); + tEncoderInit(&encoder, POINTER_SHIFT(pBuf, sizeof(SSubmitReq2Msg)), len - sizeof(SSubmitReq2Msg)); + code = tEncodeSubmitReq(&encoder, pReq); + tEncoderClear(&encoder); } - return TSDB_CODE_SUCCESS; + if (TSDB_CODE_SUCCESS == code) { + *pData = pBuf; + *pLen = len; + } else { + taosMemoryFree(pBuf); + } + return code; } -int32_t insInitRowBuilder(SRowBuilder* pBuilder, int16_t schemaVer, SParsedDataColInfo* pColInfo) { - ASSERT(pColInfo->numOfCols > 0 && (pColInfo->numOfBound <= pColInfo->numOfCols)); - tdSRowInit(pBuilder, schemaVer); - tdSRowSetExtendedInfo(pBuilder, pColInfo->numOfCols, pColInfo->numOfBound, pColInfo->flen, pColInfo->allNullLen, - pColInfo->boundNullLen); - return TSDB_CODE_SUCCESS; +static void destroyVgDataBlocks(void* p) { + SVgDataBlocks* pVg = p; + taosMemoryFree(pVg->pData); + taosMemoryFree(pVg); } -static char* tableNameGetPosition(SToken* pToken, char target) { - bool inEscape = false; - bool inQuote = false; - char quotaStr = 0; - - for (uint32_t i = 0; i < pToken->n; ++i) { - if (*(pToken->z + i) == target && (!inEscape) && (!inQuote)) { - return pToken->z + i; - } - - if (*(pToken->z + i) == TS_ESCAPE_CHAR) { - if (!inQuote) { - inEscape = !inEscape; - } - } - - if (*(pToken->z + i) == '\'' || *(pToken->z + i) == '"') { - if (!inEscape) { - if (!inQuote) { - quotaStr = *(pToken->z + i); - inQuote = !inQuote; - } else if (quotaStr == *(pToken->z + i)) { - inQuote = !inQuote; - } - } - } +int32_t insBuildVgDataBlocks(SHashObj* pVgroupsHashObj, SArray* pVgDataCxtList, SArray** pVgDataBlocks) { + size_t numOfVg = taosArrayGetSize(pVgDataCxtList); + SArray* pDataBlocks = taosArrayInit(numOfVg, POINTER_BYTES); + if (NULL == pDataBlocks) { + return TSDB_CODE_OUT_OF_MEMORY; } - return NULL; -} - -int32_t insCreateSName(SName* pName, SToken* pTableName, int32_t acctId, const char* dbName, SMsgBuf* pMsgBuf) { - const char* msg1 = "name too long"; - const char* msg2 = "invalid database name"; - const char* msg3 = "db is not specified"; - const char* msg4 = "invalid table name"; - int32_t code = TSDB_CODE_SUCCESS; - char* p = tableNameGetPosition(pTableName, TS_PATH_DELIMITER[0]); - - if (p != NULL) { // db has been specified in sql string so we ignore current db path - assert(*p == TS_PATH_DELIMITER[0]); - - int32_t dbLen = p - pTableName->z; - if (dbLen <= 0) { - return buildInvalidOperationMsg(pMsgBuf, msg2); - } - char name[TSDB_DB_FNAME_LEN] = {0}; - strncpy(name, pTableName->z, dbLen); - int32_t actualDbLen = strdequote(name); - - code = tNameSetDbName(pName, acctId, name, actualDbLen); - if (code != TSDB_CODE_SUCCESS) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - - int32_t tbLen = pTableName->n - dbLen - 1; - if (tbLen <= 0) { - return buildInvalidOperationMsg(pMsgBuf, msg4); - } - - char tbname[TSDB_TABLE_FNAME_LEN] = {0}; - strncpy(tbname, p + 1, tbLen); - /*tbLen = */ strdequote(tbname); - - code = tNameFromString(pName, tbname, T_NAME_TABLE); - if (code != 0) { - return buildInvalidOperationMsg(pMsgBuf, msg1); - } - } else { // get current DB name first, and then set it into path - if (pTableName->n >= TSDB_TABLE_NAME_LEN) { - return buildInvalidOperationMsg(pMsgBuf, msg1); + for (size_t i = 0; TSDB_CODE_SUCCESS == code && i < numOfVg; ++i) { + SVgroupDataCxt* src = taosArrayGetP(pVgDataCxtList, i); + SVgDataBlocks* dst = taosMemoryCalloc(1, sizeof(SVgDataBlocks)); + if (NULL == dst) { + code = TSDB_CODE_OUT_OF_MEMORY; } - - assert(pTableName->n < TSDB_TABLE_FNAME_LEN); - - char name[TSDB_TABLE_FNAME_LEN] = {0}; - strncpy(name, pTableName->z, pTableName->n); - strdequote(name); - - if (dbName == NULL) { - return buildInvalidOperationMsg(pMsgBuf, msg3); + if (TSDB_CODE_SUCCESS == code) { + dst->numOfTables = taosArrayGetSize(src->pData->aSubmitTbData); + code = taosHashGetDup(pVgroupsHashObj, (const char*)&src->vgId, sizeof(src->vgId), &dst->vg); +// uError("td23101 3vgId:%d, numEps:%d", src->vgId, dst->vg.epSet.numOfEps); } - - code = tNameSetDbName(pName, acctId, dbName, strlen(dbName)); - if (code != TSDB_CODE_SUCCESS) { - code = buildInvalidOperationMsg(pMsgBuf, msg2); - return code; + if (TSDB_CODE_SUCCESS == code) { + code = buildSubmitReq(src->vgId, src->pData, &dst->pData, &dst->size); } - - code = tNameFromString(pName, name, T_NAME_TABLE); - if (code != 0) { - code = buildInvalidOperationMsg(pMsgBuf, msg1); + if (TSDB_CODE_SUCCESS == code) { + code = (NULL == taosArrayPush(pDataBlocks, &dst) ? TSDB_CODE_OUT_OF_MEMORY : TSDB_CODE_SUCCESS); } } - if (NULL != strchr(pName->tname, '.')) { - code = generateSyntaxErrMsgExt(pMsgBuf, TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME, "The table name cannot contain '.'"); + if (TSDB_CODE_SUCCESS == code) { + *pVgDataBlocks = pDataBlocks; + } else { + taosArrayDestroyP(pDataBlocks, destroyVgDataBlocks); } return code; } -int32_t insFindCol(SToken* pColname, int32_t start, int32_t end, SSchema* pSchema) { - while (start < end) { - if (strlen(pSchema[start].name) == pColname->n && strncmp(pColname->z, pSchema[start].name, pColname->n) == 0) { - return start; +static bool findFileds(SSchema* pSchema, TAOS_FIELD* fields, int numFields) { + for (int i = 0; i < numFields; i++) { + if(strcmp(pSchema->name, fields[i].name) == 0){ + return true; } - ++start; } - return -1; -} -void insBuildCreateTbReq(SVCreateTbReq* pTbReq, const char* tname, STag* pTag, int64_t suid, const char* sname, - SArray* tagName, uint8_t tagNum, int32_t ttl) { - pTbReq->type = TD_CHILD_TABLE; - pTbReq->name = strdup(tname); - pTbReq->ctb.suid = suid; - pTbReq->ctb.tagNum = tagNum; - if (sname) pTbReq->ctb.stbName = strdup(sname); - pTbReq->ctb.pTag = (uint8_t*)pTag; - pTbReq->ctb.tagName = taosArrayDup(tagName, NULL); - pTbReq->ttl = ttl; - pTbReq->commentLen = -1; - - return; + return false; } -int32_t insMemRowAppend(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param) { - SMemParam* pa = (SMemParam*)param; - SRowBuilder* rb = pa->rb; - - if (value == NULL) { // it is a null data - tdAppendColValToRow(rb, pa->schema->colId, pa->schema->type, TD_VTYPE_NULL, value, false, pa->toffset, pa->colIdx); - return TSDB_CODE_SUCCESS; +int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreateTbReq* pCreateTb, TAOS_FIELD* tFields, + int numFields, bool needChangeLength) { + void* tmp = taosHashGet(((SVnodeModifyOpStmt*)(query->pRoot))->pTableBlockHashObj, &pTableMeta->uid, sizeof(pTableMeta->uid)); + STableDataCxt* pTableCxt = NULL; + int ret = insGetTableDataCxt(((SVnodeModifyOpStmt*)(query->pRoot))->pTableBlockHashObj, &pTableMeta->uid, + sizeof(pTableMeta->uid), pTableMeta, &pCreateTb, &pTableCxt, true); + if (ret != TSDB_CODE_SUCCESS) { + uError("insGetTableDataCxt error"); + goto end; } - if (TSDB_DATA_TYPE_BINARY == pa->schema->type) { - const char* rowEnd = tdRowEnd(rb->pBuf); - STR_WITH_SIZE_TO_VARSTR(rowEnd, value, len); - tdAppendColValToRow(rb, pa->schema->colId, pa->schema->type, TD_VTYPE_NORM, rowEnd, false, pa->toffset, pa->colIdx); - } else if (TSDB_DATA_TYPE_NCHAR == pa->schema->type) { - // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long' - int32_t output = 0; - const char* rowEnd = tdRowEnd(rb->pBuf); - if (!taosMbsToUcs4(value, len, (TdUcs4*)varDataVal(rowEnd), pa->schema->bytes - VARSTR_HEADER_SIZE, &output)) { - if (errno == E2BIG) { - return generateSyntaxErrMsg(pMsgBuf, TSDB_CODE_PAR_VALUE_TOO_LONG, pa->schema->name); - } - char buf[512] = {0}; - snprintf(buf, tListLen(buf), "%s", strerror(errno)); - return buildSyntaxErrMsg(pMsgBuf, buf, value); + if(tmp == NULL){ + ret = initTableColSubmitData(pTableCxt); + if (ret != TSDB_CODE_SUCCESS) { + uError("initTableColSubmitData error"); + goto end; } - varDataSetLen(rowEnd, output); - tdAppendColValToRow(rb, pa->schema->colId, pa->schema->type, TD_VTYPE_NORM, rowEnd, false, pa->toffset, pa->colIdx); - } else { - tdAppendColValToRow(rb, pa->schema->colId, pa->schema->type, TD_VTYPE_NORM, value, false, pa->toffset, pa->colIdx); } - return TSDB_CODE_SUCCESS; -} + char* p = (char*)data; + // | version | total length | total rows | total columns | flag seg| block group id | column schema | each column + // length | + p += sizeof(int32_t); + p += sizeof(int32_t); -int32_t insCheckTimestamp(STableDataBlocks* pDataBlocks, const char* start) { - // once the data block is disordered, we do NOT keep previous timestamp any more - if (!pDataBlocks->ordered) { - return TSDB_CODE_SUCCESS; - } + int32_t numOfRows = *(int32_t*)p; + p += sizeof(int32_t); - TSKEY k = *(TSKEY*)start; - if (k <= pDataBlocks->prevTS) { - pDataBlocks->ordered = false; - } + int32_t numOfCols = *(int32_t*)p; + p += sizeof(int32_t); - pDataBlocks->prevTS = k; - return TSDB_CODE_SUCCESS; -} + p += sizeof(int32_t); + p += sizeof(uint64_t); -static void buildMsgHeader(STableDataBlocks* src, SVgDataBlocks* blocks) { - SSubmitReq* submit = (SSubmitReq*)blocks->pData; - submit->header.vgId = htonl(blocks->vg.vgId); - submit->header.contLen = htonl(blocks->size); - submit->length = submit->header.contLen; - submit->numOfBlocks = htonl(blocks->numOfTables); - SSubmitBlk* blk = (SSubmitBlk*)(submit + 1); - int32_t numOfBlocks = blocks->numOfTables; - while (numOfBlocks--) { - int32_t dataLen = blk->dataLen; - int32_t schemaLen = blk->schemaLen; - blk->uid = htobe64(blk->uid); - blk->suid = htobe64(blk->suid); - blk->sversion = htonl(blk->sversion); - blk->dataLen = htonl(blk->dataLen); - blk->schemaLen = htonl(blk->schemaLen); - blk->numOfRows = htonl(blk->numOfRows); - blk = (SSubmitBlk*)(blk->data + schemaLen + dataLen); - } -} + int8_t* fields = p; + p += numOfCols * (sizeof(int8_t) + sizeof(int32_t)); -int32_t insBuildOutput(SHashObj* pVgroupsHashObj, SArray* pVgDataBlocks, SArray** pDataBlocks) { - size_t numOfVg = taosArrayGetSize(pVgDataBlocks); - *pDataBlocks = taosArrayInit(numOfVg, POINTER_BYTES); - if (NULL == *pDataBlocks) { - return TSDB_CODE_OUT_OF_MEMORY; + int32_t* colLength = (int32_t*)p; + p += sizeof(int32_t) * numOfCols; + + char* pStart = p; + + SSchema* pSchema = getTableColumnSchema(pTableCxt->pMeta); + SBoundColInfo* boundInfo = &pTableCxt->boundColsInfo; + + if (tFields != NULL && numFields != numOfCols) { + uError("numFields:%d != numOfCols:%d", numFields, numOfCols); + ret = TSDB_CODE_INVALID_PARA; + goto end; } - for (size_t i = 0; i < numOfVg; ++i) { - STableDataBlocks* src = taosArrayGetP(pVgDataBlocks, i); - SVgDataBlocks* dst = taosMemoryCalloc(1, sizeof(SVgDataBlocks)); - if (NULL == dst) { - return TSDB_CODE_OUT_OF_MEMORY; + if (tFields != NULL && numFields > boundInfo->numOfBound) { + uError("numFields:%d > boundInfo->numOfBound:%d", numFields, boundInfo->numOfBound); + ret = TSDB_CODE_INVALID_PARA; + goto end; + } + if(tFields == NULL){ + for (int j = 0; j < boundInfo->numOfBound; j++){ + SSchema* pColSchema = &pSchema[j]; + SColData* pCol = taosArrayGet(pTableCxt->pData->aCol, j); + if (*fields != pColSchema->type && *(int32_t*)(fields + sizeof(int8_t)) != pColSchema->bytes) { + uError("type or bytes not equal"); + ret = TSDB_CODE_INVALID_PARA; + goto end; + } + + int8_t* offset = pStart; + if (IS_VAR_DATA_TYPE(pColSchema->type)) { + pStart += numOfRows * sizeof(int32_t); + } else { + pStart += BitmapLen(numOfRows); + } + char* pData = pStart; + + tColDataAddValueByDataBlock(pCol, pColSchema->type, pColSchema->bytes, numOfRows, offset, pData); + fields += sizeof(int8_t) + sizeof(int32_t); + if (needChangeLength) { + pStart += htonl(colLength[j]); + } else { + pStart += colLength[j]; + } + } + }else{ + for (int i = 0; i < numFields; i++) { + for (int j = 0; j < boundInfo->numOfBound; j++){ + SSchema* pColSchema = &pSchema[j]; + if(strcmp(pColSchema->name, tFields[i].name) == 0){ + if (*fields != pColSchema->type && *(int32_t*)(fields + sizeof(int8_t)) != pColSchema->bytes) { + uError("type or bytes not equal"); + ret = TSDB_CODE_INVALID_PARA; + goto end; + } + + int8_t* offset = pStart; + if (IS_VAR_DATA_TYPE(pColSchema->type)) { + pStart += numOfRows * sizeof(int32_t); + } else { + pStart += BitmapLen(numOfRows); + } + char* pData = pStart; + + SColData* pCol = taosArrayGet(pTableCxt->pData->aCol, j); + tColDataAddValueByDataBlock(pCol, pColSchema->type, pColSchema->bytes, numOfRows, offset, pData); + fields += sizeof(int8_t) + sizeof(int32_t); + if (needChangeLength) { + pStart += htonl(colLength[i]); + } else { + pStart += colLength[i]; + } + boundInfo->pColIndex[j] = -1; + break; + } + } + + } + + for (int c = 0; c < boundInfo->numOfBound; ++c) { + if( boundInfo->pColIndex[c] != -1){ + SColData* pCol = taosArrayGet(pTableCxt->pData->aCol, c); + tColDataAddValueByDataBlock(pCol, 0, 0, numOfRows, NULL, NULL); + }else{ + boundInfo->pColIndex[c] = c; // restore for next block + } } - taosHashGetDup(pVgroupsHashObj, (const char*)&src->vgId, sizeof(src->vgId), &dst->vg); - dst->numOfTables = src->numOfTables; - dst->size = src->size; - TSWAP(dst->pData, src->pData); - buildMsgHeader(src, dst); - taosArrayPush(*pDataBlocks, &dst); } - return TSDB_CODE_SUCCESS; + +end: + return ret; } diff --git a/source/libs/parser/src/parTokenizer.c b/source/libs/parser/src/parTokenizer.c index b248efee59584156bace88e5dd0f001003216bc0..49da87dc1685f3c9d2d03d861eb3dce8e029fd38 100644 --- a/source/libs/parser/src/parTokenizer.c +++ b/source/libs/parser/src/parTokenizer.c @@ -61,6 +61,7 @@ static SKeyword keywordTable[] = { {"COLUMN", TK_COLUMN}, {"COMMENT", TK_COMMENT}, {"COMP", TK_COMP}, + {"COMPACT", TK_COMPACT}, {"CONNECTION", TK_CONNECTION}, {"CONNECTIONS", TK_CONNECTIONS}, {"CONNS", TK_CONNS}, @@ -90,6 +91,7 @@ static SKeyword keywordTable[] = { {"EXISTS", TK_EXISTS}, {"EXPIRED", TK_EXPIRED}, {"EXPLAIN", TK_EXPLAIN}, + {"EVENT_WINDOW", TK_EVENT_WINDOW}, {"EVERY", TK_EVERY}, {"FILE", TK_FILE}, {"FILL", TK_FILL}, @@ -122,8 +124,10 @@ static SKeyword keywordTable[] = { {"JSON", TK_JSON}, {"KEEP", TK_KEEP}, {"KILL", TK_KILL}, + {"LANGUAGE", TK_LANGUAGE}, {"LAST", TK_LAST}, {"LAST_ROW", TK_LAST_ROW}, + {"LEADER", TK_LEADER}, {"LICENCES", TK_LICENCES}, {"LIKE", TK_LIKE}, {"LIMIT", TK_LIMIT}, @@ -174,6 +178,7 @@ static SKeyword keywordTable[] = { {"READ", TK_READ}, {"REDISTRIBUTE", TK_REDISTRIBUTE}, {"RENAME", TK_RENAME}, + {"REPLACE", TK_REPLACE}, {"REPLICA", TK_REPLICA}, {"RESET", TK_RESET}, {"RETENTIONS", TK_RETENTIONS}, @@ -196,15 +201,16 @@ static SKeyword keywordTable[] = { {"SNODES", TK_SNODES}, {"SOFFSET", TK_SOFFSET}, {"SPLIT", TK_SPLIT}, - {"STT_TRIGGER", TK_STT_TRIGGER}, {"STABLE", TK_STABLE}, {"STABLES", TK_STABLES}, + {"START", TK_START}, {"STATE", TK_STATE}, {"STATE_WINDOW", TK_STATE_WINDOW}, {"STORAGE", TK_STORAGE}, {"STREAM", TK_STREAM}, {"STREAMS", TK_STREAMS}, {"STRICT", TK_STRICT}, + {"STT_TRIGGER", TK_STT_TRIGGER}, {"SUBSCRIBE", TK_SUBSCRIBE}, {"SUBSCRIPTIONS", TK_SUBSCRIPTIONS}, {"SUBTABLE", TK_SUBTABLE}, @@ -233,7 +239,7 @@ static SKeyword keywordTable[] = { {"TTL", TK_TTL}, {"UNION", TK_UNION}, {"UNSIGNED", TK_UNSIGNED}, - {"UPDATE", TK_UPDATE}, + {"UPDATE", TK_UPDATE}, {"USE", TK_USE}, {"USER", TK_USER}, {"USERS", TK_USERS}, @@ -261,6 +267,7 @@ static SKeyword keywordTable[] = { {"WRITE", TK_WRITE}, {"_C0", TK_ROWTS}, {"_IROWTS", TK_IROWTS}, + {"_ISFILLED", TK_ISFILLED}, {"_QDURATION", TK_QDURATION}, {"_QEND", TK_QEND}, {"_QSTART", TK_QSTART}, @@ -269,6 +276,7 @@ static SKeyword keywordTable[] = { {"_WDURATION", TK_WDURATION}, {"_WEND", TK_WEND}, {"_WSTART", TK_WSTART}, + {"ALIVE", TK_ALIVE}, }; // clang-format on @@ -684,7 +692,7 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr, bool* pIgnoreC len = tGetToken(&str[*i + t0.n + 1], &type); // only id and string are valid - if ((TK_NK_STRING != t0.type) && (TK_NK_ID != t0.type)) { + if (((TK_NK_STRING != t0.type) && (TK_NK_ID != t0.type)) || ((TK_NK_STRING != type) && (TK_NK_ID != type))) { t0.type = TK_NK_ILLEGAL; t0.n = 0; @@ -718,14 +726,3 @@ void taosCleanupKeywordsTable() { taosHashCleanup(m); } } - -SToken taosTokenDup(SToken* pToken, char* buf, int32_t len) { - assert(pToken != NULL && buf != NULL && len > pToken->n); - - strncpy(buf, pToken->z, pToken->n); - buf[pToken->n] = 0; - - SToken token = *pToken; - token.z = buf; - return token; -} diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index c61c4fe4d47341decff44b42d5de7ce516708421..e92cdca6b620b970105fae686b0d94c34a12898d 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -30,6 +30,11 @@ #define SYSTABLE_SHOW_TYPE_OFFSET QUERY_NODE_SHOW_DNODES_STMT +typedef struct SRewriteTbNameContext { + int32_t errCode; + char* pTbName; +} SRewriteTbNameContext; + typedef struct STranslateContext { SParseContext* pParseCxt; int32_t errCode; @@ -352,7 +357,7 @@ static int32_t getTableMetaImpl(STranslateContext* pCxt, const SName* pName, STa code = catalogGetTableMeta(pParCxt->pCatalog, &conn, pName, pMeta); } } - if (TSDB_CODE_SUCCESS != code) { + if (TSDB_CODE_SUCCESS != code && TSDB_CODE_PAR_TABLE_NOT_EXIST != code) { parserError("0x%" PRIx64 " catalogGetTableMeta error, code:%s, dbName:%s, tbName:%s", pCxt->pParseCxt->requestId, tstrerror(code), pName->dbname, pName->tname); } @@ -645,6 +650,10 @@ static bool isSelectStmt(SNode* pCurrStmt) { return NULL != pCurrStmt && QUERY_NODE_SELECT_STMT == nodeType(pCurrStmt); } +static bool isDeleteStmt(SNode* pCurrStmt) { + return NULL != pCurrStmt && QUERY_NODE_DELETE_STMT == nodeType(pCurrStmt); +} + static bool isSetOperator(SNode* pCurrStmt) { return NULL != pCurrStmt && QUERY_NODE_SET_OPERATOR == nodeType(pCurrStmt); } @@ -669,6 +678,9 @@ static uint8_t getPrecisionFromCurrStmt(SNode* pCurrStmt, uint8_t defaultVal) { if (NULL != pCurrStmt && QUERY_NODE_CREATE_STREAM_STMT == nodeType(pCurrStmt)) { return getPrecisionFromCurrStmt(((SCreateStreamStmt*)pCurrStmt)->pQuery, defaultVal); } + if (isDeleteStmt(pCurrStmt)) { + return ((SDeleteStmt*)pCurrStmt)->precision; + } return defaultVal; } @@ -688,6 +700,10 @@ static bool isWindowPseudoColumnFunc(const SNode* pNode) { return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsWindowPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)); } +static bool isInterpPseudoColumnFunc(const SNode* pNode) { + return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsInterpPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)); +} + static bool isTimelineFunc(const SNode* pNode) { return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsTimelineFunc(((SFunctionNode*)pNode)->funcId)); } @@ -755,9 +771,11 @@ static bool isPrimaryKeyImpl(SNode* pExpr) { } else if (QUERY_NODE_FUNCTION == nodeType(pExpr)) { SFunctionNode* pFunc = (SFunctionNode*)pExpr; if (FUNCTION_TYPE_SELECT_VALUE == pFunc->funcType || FUNCTION_TYPE_GROUP_KEY == pFunc->funcType || - FUNCTION_TYPE_FIRST == pFunc->funcType || FUNCTION_TYPE_LAST == pFunc->funcType) { + FUNCTION_TYPE_FIRST == pFunc->funcType || FUNCTION_TYPE_LAST == pFunc->funcType || + FUNCTION_TYPE_LAST_ROW == pFunc->funcType) { return isPrimaryKeyImpl(nodesListGetNode(pFunc->pParameterList, 0)); - } else if (FUNCTION_TYPE_WSTART == pFunc->funcType || FUNCTION_TYPE_WEND == pFunc->funcType) { + } else if (FUNCTION_TYPE_WSTART == pFunc->funcType || FUNCTION_TYPE_WEND == pFunc->funcType || + FUNCTION_TYPE_IROWTS == pFunc->funcType) { return true; } } @@ -787,7 +805,7 @@ static void setColumnInfoBySchema(const SRealTableNode* pTable, const SSchema* p pCol->tableType = pTable->pMeta->tableType; pCol->colId = pColSchema->colId; pCol->colType = (tagFlag >= 0 ? COLUMN_TYPE_TAG : COLUMN_TYPE_COLUMN); - pCol->hasIndex = (0 == tagFlag); + pCol->hasIndex = ((0 == tagFlag) || (pColSchema != NULL && IS_IDX_ON(pColSchema))); pCol->node.resType.type = pColSchema->type; pCol->node.resType.bytes = pColSchema->bytes; if (TSDB_DATA_TYPE_TIMESTAMP == pCol->node.resType.type) { @@ -809,7 +827,7 @@ static void setColumnInfoByExpr(STempTableNode* pTable, SExprNode* pExpr, SColum strcpy(pCol->node.aliasName, pCol->colName); } if ('\0' == pCol->node.userAlias[0]) { - strcpy(pCol->node.userAlias, pCol->colName); + strcpy(pCol->node.userAlias, pExpr->userAlias); } pCol->node.resType = pExpr->resType; } @@ -976,7 +994,8 @@ static EDealRes translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** p } static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode** pCol) { - if (NULL == pCxt->pCurrStmt || isSelectStmt(pCxt->pCurrStmt) && NULL == ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable) { + if (NULL == pCxt->pCurrStmt || + (isSelectStmt(pCxt->pCurrStmt) && NULL == ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable)) { return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, (*pCol)->colName); } @@ -1211,7 +1230,8 @@ static EDealRes translateValueImpl(STranslateContext* pCxt, SValueNode* pVal, SD } else { res = translateNormalValue(pCxt, pVal, targetDt, strict); } - pVal->node.resType = targetDt; + pVal->node.resType.type = targetDt.type; + pVal->node.resType.bytes = targetDt.bytes; pVal->node.resType.scale = pVal->unit; pVal->translate = true; if (!strict && TSDB_DATA_TYPE_UBIGINT == pVal->node.resType.type && pVal->datum.u <= INT64_MAX) { @@ -1231,6 +1251,10 @@ static int32_t calcTypeBytes(SDataType dt) { } static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) { + if (pVal->translate) { + return TSDB_CODE_SUCCESS; + } + SDataType dt = pVal->node.resType; dt.bytes = calcTypeBytes(dt); return translateValueImpl(pCxt, pVal, dt, false); @@ -1291,7 +1315,8 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) { } static EDealRes haveVectorFunction(SNode* pNode, void* pContext) { - if (isAggFunc(pNode) || isIndefiniteRowsFunc(pNode) || isWindowPseudoColumnFunc(pNode)) { + if (isAggFunc(pNode) || isIndefiniteRowsFunc(pNode) || isWindowPseudoColumnFunc(pNode) || + isInterpPseudoColumnFunc(pNode)) { *((bool*)pContext) = true; return DEAL_RES_END; } @@ -1330,6 +1355,32 @@ static int32_t rewriteCountStar(STranslateContext* pCxt, SFunctionNode* pCount) return code; } +static bool isCountNotNullValue(SFunctionNode* pFunc) { + if (FUNCTION_TYPE_COUNT != pFunc->funcType || 1 != LIST_LENGTH(pFunc->pParameterList)) { + return false; + } + SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0); + return (QUERY_NODE_VALUE == nodeType(pPara) && !((SValueNode*)pPara)->isNull); +} + +// count(1) is rewritten as count(ts) for scannning optimization +static int32_t rewriteCountNotNullValue(STranslateContext* pCxt, SFunctionNode* pCount) { + SValueNode* pValue = (SValueNode*)nodesListGetNode(pCount->pParameterList, 0); + STableNode* pTable = NULL; + int32_t code = findTable(pCxt, NULL, &pTable); + if (TSDB_CODE_SUCCESS == code && QUERY_NODE_REAL_TABLE == nodeType(pTable)) { + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + code = TSDB_CODE_OUT_OF_MEMORY; + } else { + setColumnInfoBySchema((SRealTableNode*)pTable, ((SRealTableNode*)pTable)->pMeta->schema, -1, pCol); + NODES_DESTORY_LIST(pCount->pParameterList); + code = nodesListMakeAppend(&pCount->pParameterList, (SNode*)pCol); + } + } + return code; +} + static bool isCountTbname(SFunctionNode* pFunc) { if (FUNCTION_TYPE_COUNT != pFunc->funcType || 1 != LIST_LENGTH(pFunc->pParameterList)) { return false; @@ -1395,6 +1446,9 @@ static int32_t translateAggFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { if (isCountStar(pFunc)) { return rewriteCountStar(pCxt, pFunc); } + if (isCountNotNullValue(pFunc)) { + return rewriteCountNotNullValue(pCxt, pFunc); + } if (isCountTbname(pFunc)) { return rewriteCountTbname(pCxt, pFunc); } @@ -1470,8 +1524,8 @@ static int32_t translateInterpFunc(STranslateContext* pCxt, SFunctionNode* pFunc SNode* pTable = pSelect->pFromTable; if ((NULL != pTable && (QUERY_NODE_REAL_TABLE != nodeType(pTable) || - (TSDB_CHILD_TABLE != ((SRealTableNode*)pTable)->pMeta->tableType && - TSDB_NORMAL_TABLE != ((SRealTableNode*)pTable)->pMeta->tableType)))) { + (TSDB_CHILD_TABLE != ((SRealTableNode*)pTable)->pMeta->tableType && + TSDB_NORMAL_TABLE != ((SRealTableNode*)pTable)->pMeta->tableType)))) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_SUPPORT_SINGLE_TABLE, "%s is only supported in single table query", pFunc->functionName); } @@ -1489,6 +1543,21 @@ static int32_t translateInterpFunc(STranslateContext* pCxt, SFunctionNode* pFunc return TSDB_CODE_SUCCESS; } +static int32_t translateInterpPseudoColumnFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { + if (!fmIsInterpPseudoColumnFunc(pFunc->funcId)) { + return TSDB_CODE_SUCCESS; + } + if (!isSelectStmt(pCxt->pCurrStmt)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC, + "%s must be used in select statements", pFunc->functionName); + } + if (pCxt->currClause == SQL_CLAUSE_WHERE) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_INTERP_CLAUSE, + "%s is not allowed in where clause", pFunc->functionName); + } + return TSDB_CODE_SUCCESS; +} + static int32_t translateTimelineFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { if (!fmIsTimelineFunc(pFunc->funcId)) { return TSDB_CODE_SUCCESS; @@ -1506,6 +1575,21 @@ static int32_t translateTimelineFunc(STranslateContext* pCxt, SFunctionNode* pFu return TSDB_CODE_SUCCESS; } +static int32_t translateDateTimeFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { + if (!fmIsDateTimeFunc(pFunc->funcId)) { + return TSDB_CODE_SUCCESS; + } + + if (!isSelectStmt(pCxt->pCurrStmt)) { + return TSDB_CODE_SUCCESS; + } + + SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt; + pFunc->node.resType.precision = pSelect->precision; + + return TSDB_CODE_SUCCESS; +} + static bool hasFillClause(SNode* pCurrStmt) { if (!isSelectStmt(pCurrStmt)) { return false; @@ -1604,13 +1688,15 @@ static bool isTableStar(SNode* pNode) { (0 == strcmp(((SColumnNode*)pNode)->colName, "*")); } +static bool isStarParam(SNode* pNode) { return isStar(pNode) || isTableStar(pNode); } + static int32_t translateMultiResFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { if (!fmIsMultiResFunc(pFunc->funcId)) { return TSDB_CODE_SUCCESS; } if (SQL_CLAUSE_SELECT != pCxt->currClause) { SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0); - if (isStar(pPara) || isTableStar(pPara)) { + if (isStarParam(pPara)) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC, "%s(*) is only supported in SELECTed list", pFunc->functionName); } @@ -1624,7 +1710,7 @@ static int32_t translateMultiResFunc(STranslateContext* pCxt, SFunctionNode* pFu static int32_t getMultiResFuncNum(SNodeList* pParameterList) { if (1 == LIST_LENGTH(pParameterList)) { - return isStar(nodesListGetNode(pParameterList, 0)) ? 2 : 1; + return isStarParam(nodesListGetNode(pParameterList, 0)) ? 2 : 1; } return LIST_LENGTH(pParameterList); } @@ -1643,6 +1729,7 @@ static void setFuncClassification(SNode* pCurrStmt, SFunctionNode* pFunc) { SSelectStmt* pSelect = (SSelectStmt*)pCurrStmt; pSelect->hasAggFuncs = pSelect->hasAggFuncs ? true : fmIsAggFunc(pFunc->funcId); pSelect->hasRepeatScanFuncs = pSelect->hasRepeatScanFuncs ? true : fmIsRepeatScanFunc(pFunc->funcId); + if (fmIsIndefiniteRowsFunc(pFunc->funcId)) { pSelect->hasIndefiniteRowsFunc = true; pSelect->returnRows = fmGetFuncReturnRows(pFunc); @@ -1657,6 +1744,8 @@ static void setFuncClassification(SNode* pCurrStmt, SFunctionNode* pFunc) { pSelect->hasUniqueFunc = pSelect->hasUniqueFunc ? true : (FUNCTION_TYPE_UNIQUE == pFunc->funcType); pSelect->hasTailFunc = pSelect->hasTailFunc ? true : (FUNCTION_TYPE_TAIL == pFunc->funcType); pSelect->hasInterpFunc = pSelect->hasInterpFunc ? true : (FUNCTION_TYPE_INTERP == pFunc->funcType); + pSelect->hasInterpPseudoColFunc = + pSelect->hasInterpPseudoColFunc ? true : fmIsInterpPseudoColumnFunc(pFunc->funcId); pSelect->hasLastRowFunc = pSelect->hasLastRowFunc ? true : (FUNCTION_TYPE_LAST_ROW == pFunc->funcType); pSelect->hasLastFunc = pSelect->hasLastFunc ? true : (FUNCTION_TYPE_LAST == pFunc->funcType); pSelect->hasTimeLineFunc = pSelect->hasTimeLineFunc ? true : fmIsTimelineFunc(pFunc->funcId); @@ -1671,6 +1760,7 @@ static int32_t rewriteFuncToValue(STranslateContext* pCxt, char* pLiteral, SNode return TSDB_CODE_OUT_OF_MEMORY; } strcpy(pVal->node.aliasName, ((SExprNode*)*pNode)->aliasName); + strcpy(pVal->node.userAlias, ((SExprNode*)*pNode)->userAlias); pVal->node.resType = ((SExprNode*)*pNode)->resType; if (NULL == pLiteral) { pVal->isNull = true; @@ -1692,7 +1782,7 @@ static int32_t rewriteFuncToValue(STranslateContext* pCxt, char* pLiteral, SNode static int32_t rewriteDatabaseFunc(STranslateContext* pCxt, SNode** pNode) { char* pCurrDb = NULL; if (NULL != pCxt->pParseCxt->db) { - pCurrDb = taosMemoryStrDup((void*)pCxt->pParseCxt->db); + pCurrDb = taosStrdup((void*)pCxt->pParseCxt->db); if (NULL == pCurrDb) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -1701,7 +1791,7 @@ static int32_t rewriteDatabaseFunc(STranslateContext* pCxt, SNode** pNode) { } static int32_t rewriteClentVersionFunc(STranslateContext* pCxt, SNode** pNode) { - char* pVer = taosMemoryStrDup((void*)version); + char* pVer = taosStrdup((void*)version); if (NULL == pVer) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -1709,7 +1799,7 @@ static int32_t rewriteClentVersionFunc(STranslateContext* pCxt, SNode** pNode) { } static int32_t rewriteServerVersionFunc(STranslateContext* pCxt, SNode** pNode) { - char* pVer = taosMemoryStrDup((void*)pCxt->pParseCxt->svrVer); + char* pVer = taosStrdup((void*)pCxt->pParseCxt->svrVer); if (NULL == pVer) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -1720,7 +1810,7 @@ static int32_t rewriteServerStatusFunc(STranslateContext* pCxt, SNode** pNode) { if (pCxt->pParseCxt->nodeOffline) { return TSDB_CODE_RPC_NETWORK_UNAVAIL; } - char* pStatus = taosMemoryStrDup((void*)"1"); + char* pStatus = taosStrdup((void*)"1"); return rewriteFuncToValue(pCxt, pStatus, pNode); } @@ -1728,7 +1818,7 @@ static int32_t rewriteUserFunc(STranslateContext* pCxt, SNode** pNode) { char userConn[TSDB_USER_LEN + 1 + TSDB_FQDN_LEN] = {0}; // format 'user@host' int32_t len = snprintf(userConn, sizeof(userConn), "%s@", pCxt->pParseCxt->pUser); taosGetFqdn(userConn + len); - char* pUserConn = taosMemoryStrDup((void*)userConn); + char* pUserConn = taosStrdup((void*)userConn); if (NULL == pUserConn) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -1783,9 +1873,15 @@ static int32_t translateNormalFunction(STranslateContext* pCxt, SFunctionNode* p if (TSDB_CODE_SUCCESS == code) { code = translateInterpFunc(pCxt, pFunc); } + if (TSDB_CODE_SUCCESS == code) { + code = translateInterpPseudoColumnFunc(pCxt, pFunc); + } if (TSDB_CODE_SUCCESS == code) { code = translateTimelineFunc(pCxt, pFunc); } + if (TSDB_CODE_SUCCESS == code) { + code = translateDateTimeFunc(pCxt, pFunc); + } if (TSDB_CODE_SUCCESS == code) { code = translateBlockDistFunc(pCxt, pFunc); } @@ -2040,7 +2136,7 @@ static int32_t getGroupByErrorCode(STranslateContext* pCxt) { if (isSelectStmt(pCxt->pCurrStmt) && NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pGroupByList) { return TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION; } - return TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN; + return TSDB_CODE_PAR_INVALID_OPTR_USAGE; } static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode) { @@ -2113,13 +2209,13 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { } if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) { if (pSelect->selectFuncNum > 1 || pSelect->hasOtherVectorFunc || !pSelect->hasSelectFunc) { - return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt)); + return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt), ((SExprNode*)(*pNode))->userAlias); } else { return rewriteColToSelectValFunc(pCxt, pNode); } } if (isVectorFunc(*pNode) && isDistinctOrderBy(pCxt)) { - return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt)); + return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt), ((SExprNode*)(*pNode))->userAlias); } return DEAL_RES_CONTINUE; } @@ -2250,7 +2346,8 @@ static int32_t dnodeToVgroupsInfo(SArray* pDnodes, SVgroupsInfo** pVgsInfo) { } static bool sysTableFromVnode(const char* pTable) { - return ((0 == strcmp(pTable, TSDB_INS_TABLE_TABLES)) || (0 == strcmp(pTable, TSDB_INS_TABLE_TAGS))); + return ((0 == strcmp(pTable, TSDB_INS_TABLE_TABLES)) || (0 == strcmp(pTable, TSDB_INS_TABLE_TAGS)) || + (0 == strcmp(pTable, TSDB_INS_TABLE_COLS))); } static bool sysTableFromDnode(const char* pTable) { return 0 == strcmp(pTable, TSDB_INS_TABLE_DNODE_VARIABLES); } @@ -2318,7 +2415,9 @@ static int32_t setVnodeSysTableVgroupList(STranslateContext* pCxt, SName* pName, ((SSelectStmt*)pCxt->pCurrStmt)->isEmptyResult = true; } - if (TSDB_CODE_SUCCESS == code && 0 == strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TABLES) && !hasUserDbCond) { + if (TSDB_CODE_SUCCESS == code && + (0 == strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TABLES) && !hasUserDbCond) || + 0 == strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_COLS)) { code = addMnodeToVgroupList(&pCxt->pParseCxt->mgmtEpSet, &pVgs); } @@ -2416,7 +2515,8 @@ static bool isSingleTable(SRealTableNode* pRealTable) { int8_t tableType = pRealTable->pMeta->tableType; if (TSDB_SYSTEM_TABLE == tableType) { return 0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TABLES) && - 0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TAGS); + 0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_TAGS) && + 0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_COLS); } return (TSDB_CHILD_TABLE == tableType || TSDB_NORMAL_TABLE == tableType); } @@ -2447,6 +2547,64 @@ static int32_t setTableCacheLastMode(STranslateContext* pCxt, SSelectStmt* pSele return code; } +static EDealRes doTranslateTbName(SNode** pNode, void* pContext) { + switch (nodeType(*pNode)) { + case QUERY_NODE_FUNCTION: { + SFunctionNode *pFunc = (SFunctionNode *)*pNode; + if (FUNCTION_TYPE_TBNAME == pFunc->funcType) { + SRewriteTbNameContext *pCxt = (SRewriteTbNameContext*)pContext; + SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); + if (NULL == pVal) { + pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; + return DEAL_RES_ERROR; + } + + int32_t tbLen = strlen(pCxt->pTbName); + pVal->literal = taosStrdup(pCxt->pTbName); + if (NULL == pVal->literal) { + pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; + return DEAL_RES_ERROR; + } + pVal->isDuration = false; + pVal->translate = true; + pVal->node.resType.type = TSDB_DATA_TYPE_BINARY; + pVal->node.resType.bytes = tbLen + VARSTR_HEADER_SIZE; + pVal->datum.p = taosMemoryCalloc(1, tbLen + VARSTR_HEADER_SIZE + 1); + varDataSetLen(pVal->datum.p, tbLen); + strncpy(varDataVal(pVal->datum.p), pVal->literal, tbLen); + strcpy(pVal->node.userAlias, pFunc->node.userAlias); + strcpy(pVal->node.aliasName, pFunc->node.aliasName); + + nodesDestroyNode(*pNode); + *pNode = (SNode*)pVal; + } + break; + } + default: + break; + } + return DEAL_RES_CONTINUE; +} + +static int32_t replaceTbName(STranslateContext* pCxt, SSelectStmt* pSelect) { + if (QUERY_NODE_REAL_TABLE != nodeType(pSelect->pFromTable)) { + return TSDB_CODE_SUCCESS; + } + + SRealTableNode* pTable = (SRealTableNode*)pSelect->pFromTable; + if (TSDB_CHILD_TABLE != pTable->pMeta->tableType && TSDB_NORMAL_TABLE != pTable->pMeta->tableType && TSDB_SYSTEM_TABLE != pTable->pMeta->tableType) { + return TSDB_CODE_SUCCESS; + } + + SNode** pNode = NULL; + SRewriteTbNameContext pRewriteCxt = {0}; + pRewriteCxt.pTbName = pTable->table.tableName; + + nodesRewriteExprPostOrder(&pSelect->pWhere, doTranslateTbName, &pRewriteCxt); + + return pRewriteCxt.errCode; +} + static int32_t checkJoinTable(STranslateContext* pCxt, SJoinTableNode* pJoinTable) { if ((QUERY_NODE_TEMP_TABLE == nodeType(pJoinTable->pLeft) && !isTimeLineQuery(((STempTableNode*)pJoinTable->pLeft)->pSubquery)) || @@ -2484,8 +2642,13 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) { if (TSDB_SUPER_TABLE == pRealTable->pMeta->tableType) { pCxt->stableQuery = true; } - if (TSDB_SYSTEM_TABLE == pRealTable->pMeta->tableType && isSelectStmt(pCxt->pCurrStmt)) { - ((SSelectStmt*)pCxt->pCurrStmt)->isTimeLineResult = false; + if (TSDB_SYSTEM_TABLE == pRealTable->pMeta->tableType) { + if (isSelectStmt(pCxt->pCurrStmt)) { + ((SSelectStmt*)pCxt->pCurrStmt)->isTimeLineResult = false; + } else if (isDeleteStmt(pCxt->pCurrStmt)) { + code = TSDB_CODE_TSC_INVALID_OPERATION; + break; + } } code = addNamespace(pCxt, pRealTable); } @@ -2495,6 +2658,11 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) { STempTableNode* pTempTable = (STempTableNode*)pTable; code = translateSubquery(pCxt, pTempTable->pSubquery); if (TSDB_CODE_SUCCESS == code) { + if (QUERY_NODE_SELECT_STMT == nodeType(pTempTable->pSubquery) && + ((SSelectStmt*)pTempTable->pSubquery)->isEmptyResult && isSelectStmt(pCxt->pCurrStmt)) { + ((SSelectStmt*)pCxt->pCurrStmt)->isEmptyResult = true; + } + pTempTable->table.precision = getStmtPrecision(pTempTable->pSubquery); pTempTable->table.singleTable = stmtIsSingleTable(pTempTable->pSubquery); code = addNamespace(pCxt, pTempTable); @@ -2572,6 +2740,7 @@ static SNode* createMultiResFunc(SFunctionNode* pSrcFunc, SExprNode* pExpr) { } else { len = snprintf(buf, sizeof(buf), "%s(%s)", pSrcFunc->functionName, pExpr->aliasName); strncpy(pFunc->node.aliasName, buf, TMIN(len, sizeof(pFunc->node.aliasName) - 1)); + len = snprintf(buf, sizeof(buf), "%s(%s)", pSrcFunc->functionName, pExpr->userAlias); strncpy(pFunc->node.userAlias, buf, TMIN(len, sizeof(pFunc->node.userAlias) - 1)); } @@ -2792,6 +2961,10 @@ static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) { bool other; int32_t code = translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other); if (TSDB_CODE_SUCCESS == code) { + if (0 == LIST_LENGTH(pSelect->pOrderByList)) { + NODES_DESTORY_LIST(pSelect->pOrderByList); + return TSDB_CODE_SUCCESS; + } if (!other) { return TSDB_CODE_SUCCESS; } @@ -2920,6 +3093,9 @@ static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect if (TSDB_CODE_SUCCESS == code) { code = translateFillValues(pCxt, pSelect); } + if (NULL == pSelect->pProjectionList || 0 >= pSelect->pProjectionList->length) { + code = TSDB_CODE_PAR_INVALID_SELECTED_EXPR; + } return code; } @@ -2992,11 +3168,14 @@ static int32_t checkFill(STranslateContext* pCxt, SFillNode* pFill, SValueNode* return TSDB_CODE_SUCCESS; } - if (!pCxt->createStream && (TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_INITIALIZER) || - TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_DESC_INITIALIZER))) { + if (!pCxt->createStream && TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_INITIALIZER)) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE); } + if (TSWINDOW_IS_EQUAL(pFill->timeRange, TSWINDOW_DESC_INITIALIZER)) { + return TSDB_CODE_SUCCESS; + } + // interp FILL clause if (NULL == pInterval) { return TSDB_CODE_SUCCESS; @@ -3068,6 +3247,19 @@ static const char* getPrecisionStr(uint8_t precision) { return "unknown"; } +static void convertVarDuration(SValueNode* pOffset, uint8_t precision) { + const int64_t factors[3] = {NANOSECOND_PER_MSEC, NANOSECOND_PER_USEC, 1}; + const int8_t units[3] = {TIME_UNIT_MILLISECOND, TIME_UNIT_MICROSECOND, TIME_UNIT_NANOSECOND}; + + if (pOffset->unit == 'n') { + pOffset->datum.i = pOffset->datum.i * 31 * (NANOSECOND_PER_DAY / factors[precision]); + } else { + pOffset->datum.i = pOffset->datum.i * 365 * (NANOSECOND_PER_DAY / factors[precision]); + } + + pOffset->unit = units[precision]; +} + static int32_t checkIntervalWindow(STranslateContext* pCxt, SIntervalWindowNode* pInterval) { uint8_t precision = ((SColumnNode*)pInterval->pCol)->node.resType.precision; @@ -3092,6 +3284,10 @@ static int32_t checkIntervalWindow(STranslateContext* pCxt, SIntervalWindowNode* getMonthsFromTimeVal(pInter->datum.i, precision, pInter->unit))) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INTER_OFFSET_TOO_BIG); } + + if (pOffset->unit == 'n' || pOffset->unit == 'y') { + convertVarDuration(pOffset, precision); + } } if (NULL != pInterval->pSliding) { @@ -3188,6 +3384,15 @@ static int32_t translateSessionWindow(STranslateContext* pCxt, SSelectStmt* pSel return TSDB_CODE_SUCCESS; } +static int32_t translateEventWindow(STranslateContext* pCxt, SSelectStmt* pSelect) { + if (QUERY_NODE_TEMP_TABLE == nodeType(pSelect->pFromTable) && + !isGlobalTimeLineQuery(((STempTableNode*)pSelect->pFromTable)->pSubquery)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TIMELINE_QUERY, + "EVENT_WINDOW requires valid time series input"); + } + return TSDB_CODE_SUCCESS; +} + static int32_t translateSpecificWindow(STranslateContext* pCxt, SSelectStmt* pSelect) { switch (nodeType(pSelect->pWindow)) { case QUERY_NODE_STATE_WINDOW: @@ -3196,6 +3401,8 @@ static int32_t translateSpecificWindow(STranslateContext* pCxt, SSelectStmt* pSe return translateSessionWindow(pCxt, pSelect); case QUERY_NODE_INTERVAL_WINDOW: return translateIntervalWindow(pCxt, pSelect); + case QUERY_NODE_EVENT_WINDOW: + return translateEventWindow(pCxt, pSelect); default: break; } @@ -3288,6 +3495,10 @@ static int32_t translateInterp(STranslateContext* pCxt, SSelectStmt* pSelect) { if (NULL != pSelect->pRange || NULL != pSelect->pEvery || NULL != pSelect->pFill) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_INTERP_CLAUSE); } + if (pSelect->hasInterpPseudoColFunc) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC, + "Has Interp pseudo column(s) but missing interp function"); + } return TSDB_CODE_SUCCESS; } @@ -3307,9 +3518,6 @@ static int32_t translateInterp(STranslateContext* pCxt, SSelectStmt* pSelect) { } static int32_t translatePartitionBy(STranslateContext* pCxt, SSelectStmt* pSelect) { - if (NULL == pSelect->pPartitionByList) { - return TSDB_CODE_SUCCESS; - } pCxt->currClause = SQL_CLAUSE_PARTITION_BY; int32_t code = translateExprList(pCxt, pSelect->pPartitionByList); if (TSDB_CODE_SUCCESS == code) { @@ -3327,6 +3535,9 @@ static int32_t translateWhere(STranslateContext* pCxt, SSelectStmt* pSelect) { if (TSDB_CODE_SUCCESS == code) { code = getQueryTimeRange(pCxt, pSelect->pWhere, &pSelect->timeRange); } + if (TSDB_CODE_SUCCESS == code && pSelect->timeRange.skey > pSelect->timeRange.ekey) { + pSelect->isEmptyResult = true; + } return code; } @@ -3341,8 +3552,8 @@ static int32_t checkLimit(STranslateContext* pCxt, SSelectStmt* pSelect) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_OFFSET_LESS_ZERO); } - if (NULL != pSelect->pSlimit && NULL == pSelect->pPartitionByList) { - return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_BY); + if (NULL != pSelect->pSlimit && (NULL == pSelect->pPartitionByList && NULL == pSelect->pGroupByList)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_GROUP_BY); } return TSDB_CODE_SUCCESS; @@ -3503,6 +3714,10 @@ static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect if (TSDB_CODE_SUCCESS == code) { code = setTableCacheLastMode(pCxt, pSelect); } + if (TSDB_CODE_SUCCESS == code) { + code = replaceTbName(pCxt, pSelect); + } + return code; } @@ -3543,7 +3758,7 @@ static int32_t translateSetOperProject(STranslateContext* pCxt, SSetOperator* pS if (comp > 0) { SNode* pRightFunc = NULL; int32_t code = createCastFunc(pCxt, pRight, pLeftExpr->resType, &pRightFunc); - if (TSDB_CODE_SUCCESS != code) { + if (TSDB_CODE_SUCCESS != code || NULL == pRightFunc) { // deal scan coverity return code; } REPLACE_LIST2_NODE(pRightFunc); @@ -3551,7 +3766,7 @@ static int32_t translateSetOperProject(STranslateContext* pCxt, SSetOperator* pS } else if (comp < 0) { SNode* pLeftFunc = NULL; int32_t code = createCastFunc(pCxt, pLeft, pRightExpr->resType, &pLeftFunc); - if (TSDB_CODE_SUCCESS != code) { + if (TSDB_CODE_SUCCESS != code || NULL == pLeftFunc) { // deal scan coverity return code; } REPLACE_LIST1_NODE(pLeftFunc); @@ -3655,6 +3870,7 @@ static int32_t translateDelete(STranslateContext* pCxt, SDeleteStmt* pDelete) { pCxt->pCurrStmt = (SNode*)pDelete; int32_t code = translateFrom(pCxt, pDelete->pFromTable); if (TSDB_CODE_SUCCESS == code) { + pDelete->precision = ((STableNode*)pDelete->pFromTable)->precision; code = translateDeleteWhere(pCxt, pDelete); } pCxt->currClause = SQL_CLAUSE_SELECT; @@ -3932,7 +4148,8 @@ static int32_t checkDbKeepOption(STranslateContext* pCxt, SDatabaseOptions* pOpt if (pOptions->keep[0] < TSDB_MIN_KEEP || pOptions->keep[1] < TSDB_MIN_KEEP || pOptions->keep[2] < TSDB_MIN_KEEP || pOptions->keep[0] > tsdbMaxKeep || pOptions->keep[1] > tsdbMaxKeep || pOptions->keep[2] > tsdbMaxKeep) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DB_OPTION, - "Invalid option keep: %" PRId64 ", %" PRId64 ", %" PRId64 " valid range: [%dm, %dm]", + "Invalid option keep: %" PRId64 ", %" PRId64 ", %" PRId64 + " valid range: [%dm, %" PRId64 "m]", pOptions->keep[0], pOptions->keep[1], pOptions->keep[2], TSDB_MIN_KEEP, tsdbMaxKeep); } @@ -4035,6 +4252,34 @@ static int32_t checkDbRetentionsOption(STranslateContext* pCxt, SNodeList* pRete return TSDB_CODE_SUCCESS; } + +static int32_t checkDbTbPrefixSuffixOptions(STranslateContext* pCxt, int32_t tbPrefix, int32_t tbSuffix) { + if (tbPrefix < TSDB_MIN_HASH_PREFIX || tbPrefix > TSDB_MAX_HASH_PREFIX) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DB_OPTION, + "Invalid option table_prefix: %d valid range: [%d, %d]", tbPrefix, + TSDB_MIN_HASH_PREFIX, TSDB_MAX_HASH_PREFIX); + } + + if (tbSuffix < TSDB_MIN_HASH_SUFFIX || tbSuffix > TSDB_MAX_HASH_SUFFIX) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DB_OPTION, + "Invalid option table_suffix: %d valid range: [%d, %d]", tbSuffix, + TSDB_MIN_HASH_SUFFIX, TSDB_MAX_HASH_SUFFIX); + } + + if ((tbPrefix * tbSuffix) < 0) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DB_OPTION, + "Invalid option table_prefix & table_suffix: mixed usage not allowed"); + } + + if ((tbPrefix + tbSuffix) >= (TSDB_TABLE_NAME_LEN - 1)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DB_OPTION, + "Invalid option table_prefix & table_suffix: exceed max table name length"); + } + + return TSDB_CODE_SUCCESS; +} + + static int32_t checkOptionsDependency(STranslateContext* pCxt, const char* pDbName, SDatabaseOptions* pOptions) { int32_t daysPerFile = pOptions->daysPerFile; int64_t daysToKeep0 = pOptions->keep[0]; @@ -4142,10 +4387,7 @@ static int32_t checkDatabaseOptions(STranslateContext* pCxt, const char* pDbName code = checkDbRangeOption(pCxt, "sstTrigger", pOptions->sstTrigger, TSDB_MIN_STT_TRIGGER, TSDB_MAX_STT_TRIGGER); } if (TSDB_CODE_SUCCESS == code) { - code = checkDbRangeOption(pCxt, "tablePrefix", pOptions->tablePrefix, TSDB_MIN_HASH_PREFIX, TSDB_MAX_HASH_PREFIX); - } - if (TSDB_CODE_SUCCESS == code) { - code = checkDbRangeOption(pCxt, "tableSuffix", pOptions->tableSuffix, TSDB_MIN_HASH_SUFFIX, TSDB_MAX_HASH_SUFFIX); + code = checkDbTbPrefixSuffixOptions(pCxt, pOptions->tablePrefix, pOptions->tableSuffix); } if (TSDB_CODE_SUCCESS == code) { code = checkOptionsDependency(pCxt, pDbName, pOptions); @@ -4221,6 +4463,9 @@ static void buildAlterDbReq(STranslateContext* pCxt, SAlterDatabaseStmt* pStmt, pReq->cacheLastSize = pStmt->pOptions->cacheLastSize; pReq->replications = pStmt->pOptions->replica; pReq->sstTrigger = pStmt->pOptions->sstTrigger; + pReq->minRows = pStmt->pOptions->minRowsPerBlock; + pReq->walRetentionPeriod = pStmt->pOptions->walRetentionPeriod; + pReq->walRetentionSize = pStmt->pOptions->walRetentionSize; return; } @@ -4599,58 +4844,109 @@ typedef struct SSampleAstInfo { SNode* pSliding; SNodeList* pPartitionByList; STableMeta* pRollupTableMeta; + bool createSmaIndex; } SSampleAstInfo; -static int32_t buildSampleAst(STranslateContext* pCxt, SSampleAstInfo* pInfo, char** pAst, int32_t* pLen, char** pExpr, - int32_t* pExprLen) { - SSelectStmt* pSelect = (SSelectStmt*)nodesMakeNode(QUERY_NODE_SELECT_STMT); - if (NULL == pSelect) { - return TSDB_CODE_OUT_OF_MEMORY; - } - sprintf(pSelect->stmtName, "%p", pSelect); - +static int32_t buildTableForSampleAst(SSampleAstInfo* pInfo, SNode** pOutput) { SRealTableNode* pTable = (SRealTableNode*)nodesMakeNode(QUERY_NODE_REAL_TABLE); if (NULL == pTable) { - nodesDestroyNode((SNode*)pSelect); return TSDB_CODE_OUT_OF_MEMORY; } snprintf(pTable->table.dbName, sizeof(pTable->table.dbName), "%s", pInfo->pDbName); snprintf(pTable->table.tableName, sizeof(pTable->table.tableName), "%s", pInfo->pTableName); TSWAP(pTable->pMeta, pInfo->pRollupTableMeta); - pSelect->pFromTable = (SNode*)pTable; + *pOutput = (SNode*)pTable; + return TSDB_CODE_SUCCESS; +} - TSWAP(pSelect->pProjectionList, pInfo->pFuncs); +static int32_t addWstartToSampleProjects(SNodeList* pProjectionList) { SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION); - if (NULL == pSelect->pProjectionList || NULL == pFunc) { - nodesDestroyNode((SNode*)pSelect); + if (NULL == pFunc) { return TSDB_CODE_OUT_OF_MEMORY; } strcpy(pFunc->functionName, "_wstart"); - nodesListPushFront(pSelect->pProjectionList, (SNode*)pFunc); - SNode* pProject = NULL; - FOREACH(pProject, pSelect->pProjectionList) { sprintf(((SExprNode*)pProject)->aliasName, "#%p", pProject); } + return nodesListPushFront(pProjectionList, (SNode*)pFunc); +} + +static int32_t addWendToSampleProjects(SNodeList* pProjectionList) { + SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION); + if (NULL == pFunc) { + return TSDB_CODE_OUT_OF_MEMORY; + } + strcpy(pFunc->functionName, "_wend"); + return nodesListAppend(pProjectionList, (SNode*)pFunc); +} + +static int32_t addWdurationToSampleProjects(SNodeList* pProjectionList) { + SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION); + if (NULL == pFunc) { + return TSDB_CODE_OUT_OF_MEMORY; + } + strcpy(pFunc->functionName, "_wduration"); + return nodesListAppend(pProjectionList, (SNode*)pFunc); +} + +static int32_t buildProjectsForSampleAst(SSampleAstInfo* pInfo, SNodeList** pList) { + SNodeList* pProjectionList = pInfo->pFuncs; + pInfo->pFuncs = NULL; + + int32_t code = addWstartToSampleProjects(pProjectionList); + if (TSDB_CODE_SUCCESS == code && pInfo->createSmaIndex) { + code = addWendToSampleProjects(pProjectionList); + if (TSDB_CODE_SUCCESS == code) { + code = addWdurationToSampleProjects(pProjectionList); + } + } - TSWAP(pSelect->pPartitionByList, pInfo->pPartitionByList); + if (TSDB_CODE_SUCCESS == code) { + SNode* pProject = NULL; + FOREACH(pProject, pProjectionList) { sprintf(((SExprNode*)pProject)->aliasName, "#%p", pProject); } + *pList = pProjectionList; + } else { + nodesDestroyList(pProjectionList); + } + return code; +} +static int32_t buildIntervalForSampleAst(SSampleAstInfo* pInfo, SNode** pOutput) { SIntervalWindowNode* pInterval = (SIntervalWindowNode*)nodesMakeNode(QUERY_NODE_INTERVAL_WINDOW); if (NULL == pInterval) { - nodesDestroyNode((SNode*)pSelect); return TSDB_CODE_OUT_OF_MEMORY; } - pSelect->pWindow = (SNode*)pInterval; TSWAP(pInterval->pInterval, pInfo->pInterval); TSWAP(pInterval->pOffset, pInfo->pOffset); TSWAP(pInterval->pSliding, pInfo->pSliding); pInterval->pCol = nodesMakeNode(QUERY_NODE_COLUMN); if (NULL == pInterval->pCol) { - nodesDestroyNode((SNode*)pSelect); + nodesDestroyNode((SNode*)pInterval); return TSDB_CODE_OUT_OF_MEMORY; } ((SColumnNode*)pInterval->pCol)->colId = PRIMARYKEY_TIMESTAMP_COL_ID; strcpy(((SColumnNode*)pInterval->pCol)->colName, ROWTS_PSEUDO_COLUMN_NAME); + *pOutput = (SNode*)pInterval; + return TSDB_CODE_SUCCESS; +} - pCxt->createStream = true; - int32_t code = translateQuery(pCxt, (SNode*)pSelect); +static int32_t buildSampleAst(STranslateContext* pCxt, SSampleAstInfo* pInfo, char** pAst, int32_t* pLen, char** pExpr, + int32_t* pExprLen) { + SSelectStmt* pSelect = (SSelectStmt*)nodesMakeNode(QUERY_NODE_SELECT_STMT); + if (NULL == pSelect) { + return TSDB_CODE_OUT_OF_MEMORY; + } + sprintf(pSelect->stmtName, "%p", pSelect); + + int32_t code = buildTableForSampleAst(pInfo, &pSelect->pFromTable); + if (TSDB_CODE_SUCCESS == code) { + code = buildProjectsForSampleAst(pInfo, &pSelect->pProjectionList); + } + if (TSDB_CODE_SUCCESS == code) { + TSWAP(pSelect->pPartitionByList, pInfo->pPartitionByList); + code = buildIntervalForSampleAst(pInfo, &pSelect->pWindow); + } + if (TSDB_CODE_SUCCESS == code) { + pCxt->createStream = true; + code = translateQuery(pCxt, (SNode*)pSelect); + } if (TSDB_CODE_SUCCESS == code) { code = nodesNodeToString((SNode*)pSelect, false, pAst, pLen); } @@ -4843,7 +5139,7 @@ static int32_t buildCreateStbReq(STranslateContext* pCxt, SCreateTableStmt* pStm pReq->numOfColumns = LIST_LENGTH(pStmt->pCols); pReq->numOfTags = LIST_LENGTH(pStmt->pTags); if (pStmt->pOptions->commentNull == false) { - pReq->pComment = strdup(pStmt->pOptions->comment); + pReq->pComment = taosStrdup(pStmt->pOptions->comment); if (NULL == pReq->pComment) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -4911,7 +5207,7 @@ static int32_t buildAlterSuperTableReq(STranslateContext* pCxt, SAlterTableStmt* if (TSDB_ALTER_TABLE_UPDATE_OPTIONS == pStmt->alterType) { // pAlterReq->ttl = pStmt->pOptions->ttl; if (pStmt->pOptions->commentNull == false) { - pAlterReq->comment = strdup(pStmt->pOptions->comment); + pAlterReq->comment = taosStrdup(pStmt->pOptions->comment); if (NULL == pAlterReq->comment) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -4958,10 +5254,10 @@ static int32_t buildAlterSuperTableReq(STranslateContext* pCxt, SAlterTableStmt* return TSDB_CODE_SUCCESS; } -static SSchema* getColSchema(STableMeta* pTableMeta, const char* pColName) { +static const SSchema* getColSchema(const STableMeta* pTableMeta, const char* pColName) { int32_t numOfFields = getNumOfTags(pTableMeta) + getNumOfColumns(pTableMeta); for (int32_t i = 0; i < numOfFields; ++i) { - SSchema* pSchema = pTableMeta->schema + i; + const SSchema* pSchema = pTableMeta->schema + i; if (0 == strcmp(pColName, pSchema->name)) { return pSchema; } @@ -4969,7 +5265,19 @@ static SSchema* getColSchema(STableMeta* pTableMeta, const char* pColName) { return NULL; } -static SSchema* getTagSchema(STableMeta* pTableMeta, const char* pTagName) { +static const SSchema* getNormalColSchema(const STableMeta* pTableMeta, const char* pColName) { + int32_t numOfCols = getNumOfColumns(pTableMeta); + SSchema* pColsSchema = getTableColumnSchema(pTableMeta); + for (int32_t i = 0; i < numOfCols; ++i) { + const SSchema* pSchema = pColsSchema + i; + if (0 == strcmp(pColName, pSchema->name)) { + return pSchema; + } + } + return NULL; +} + +static SSchema* getTagSchema(const STableMeta* pTableMeta, const char* pTagName) { int32_t numOfTags = getNumOfTags(pTableMeta); SSchema* pTagsSchema = getTableTagSchema(pTableMeta); for (int32_t i = 0; i < numOfTags; ++i) { @@ -4981,7 +5289,8 @@ static SSchema* getTagSchema(STableMeta* pTableMeta, const char* pTagName) { return NULL; } -static int32_t checkAlterSuperTableBySchema(STranslateContext* pCxt, SAlterTableStmt* pStmt, STableMeta* pTableMeta) { +static int32_t checkAlterSuperTableBySchema(STranslateContext* pCxt, SAlterTableStmt* pStmt, + const STableMeta* pTableMeta) { SSchema* pTagsSchema = getTableTagSchema(pTableMeta); if (getNumOfTags(pTableMeta) == 1 && pTagsSchema->type == TSDB_DATA_TYPE_JSON && (pStmt->alterType == TSDB_ALTER_TABLE_ADD_TAG || pStmt->alterType == TSDB_ALTER_TABLE_DROP_TAG || @@ -4989,37 +5298,54 @@ static int32_t checkAlterSuperTableBySchema(STranslateContext* pCxt, SAlterTable return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_ONLY_ONE_JSON_TAG); } - if (getNumOfTags(pTableMeta) == 1 && pStmt->alterType == TSDB_ALTER_TABLE_DROP_TAG) { - return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE, "the only tag cannot be dropped"); - } - int32_t tagsLen = 0; for (int32_t i = 0; i < pTableMeta->tableInfo.numOfTags; ++i) { tagsLen += pTagsSchema[i].bytes; } if (TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES == pStmt->alterType || - TSDB_ALTER_TABLE_UPDATE_TAG_BYTES == pStmt->alterType) { + TSDB_ALTER_TABLE_UPDATE_TAG_BYTES == pStmt->alterType || TSDB_ALTER_TABLE_DROP_COLUMN == pStmt->alterType || + TSDB_ALTER_TABLE_DROP_TAG == pStmt->alterType) { if (TSDB_SUPER_TABLE != pTableMeta->tableType) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE, "Table is not super table"); } - SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName); + const SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName); if (NULL == pSchema) { - return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, pStmt->colName); - } else if (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->type != pStmt->dataType.type || - pSchema->bytes >= calcTypeBytes(pStmt->dataType)) { + return generateSyntaxErrMsg( + &pCxt->msgBuf, + (TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES == pStmt->alterType || TSDB_ALTER_TABLE_DROP_COLUMN == pStmt->alterType) + ? TSDB_CODE_PAR_INVALID_COLUMN + : TSDB_CODE_PAR_INVALID_TAG_NAME, + pStmt->colName); + } + + if ((TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES == pStmt->alterType || + TSDB_ALTER_TABLE_UPDATE_TAG_BYTES == pStmt->alterType) && + (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->type != pStmt->dataType.type || + pSchema->bytes >= calcTypeBytes(pStmt->dataType))) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_MODIFY_COL); } - if (TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES == pStmt->alterType && - pTableMeta->tableInfo.rowSize + calcTypeBytes(pStmt->dataType) - pSchema->bytes > TSDB_MAX_BYTES_PER_ROW) { - return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROW_LENGTH, TSDB_MAX_BYTES_PER_ROW); + if (TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES == pStmt->alterType) { + if ((TSDB_DATA_TYPE_VARCHAR == pStmt->dataType.type && calcTypeBytes(pStmt->dataType) > TSDB_MAX_BINARY_LEN) || + (TSDB_DATA_TYPE_NCHAR == pStmt->dataType.type && calcTypeBytes(pStmt->dataType) > TSDB_MAX_NCHAR_LEN)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN); + } + + if (pTableMeta->tableInfo.rowSize + calcTypeBytes(pStmt->dataType) - pSchema->bytes > TSDB_MAX_BYTES_PER_ROW) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROW_LENGTH, TSDB_MAX_BYTES_PER_ROW); + } } - if (TSDB_ALTER_TABLE_UPDATE_TAG_BYTES == pStmt->alterType && - tagsLen + calcTypeBytes(pStmt->dataType) - pSchema->bytes > TSDB_MAX_TAGS_LEN) { - return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TAGS_LENGTH, TSDB_MAX_TAGS_LEN); + if (TSDB_ALTER_TABLE_UPDATE_TAG_BYTES == pStmt->alterType) { + if (calcTypeBytes(pStmt->dataType) > TSDB_MAX_FIELD_LEN) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN); + } + + if (tagsLen + calcTypeBytes(pStmt->dataType) - pSchema->bytes > TSDB_MAX_TAGS_LEN) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TAGS_LENGTH, TSDB_MAX_TAGS_LEN); + } } } @@ -5028,6 +5354,11 @@ static int32_t checkAlterSuperTableBySchema(STranslateContext* pCxt, SAlterTable return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TOO_MANY_COLUMNS); } + if ((TSDB_DATA_TYPE_VARCHAR == pStmt->dataType.type && calcTypeBytes(pStmt->dataType) > TSDB_MAX_BINARY_LEN) || + (TSDB_DATA_TYPE_NCHAR == pStmt->dataType.type && calcTypeBytes(pStmt->dataType) > TSDB_MAX_NCHAR_LEN)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN); + } + if (pTableMeta->tableInfo.rowSize + calcTypeBytes(pStmt->dataType) > TSDB_MAX_BYTES_PER_ROW) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROW_LENGTH, TSDB_MAX_BYTES_PER_ROW); } @@ -5043,6 +5374,10 @@ static int32_t checkAlterSuperTableBySchema(STranslateContext* pCxt, SAlterTable } } + if (getNumOfTags(pTableMeta) == 1 && pStmt->alterType == TSDB_ALTER_TABLE_DROP_TAG) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE, "the only tag cannot be dropped"); + } + return TSDB_CODE_SUCCESS; } @@ -5117,7 +5452,7 @@ static int32_t translateUseDatabase(STranslateContext* pCxt, SUseDatabaseStmt* p static int32_t translateCreateUser(STranslateContext* pCxt, SCreateUserStmt* pStmt) { SCreateUserReq createReq = {0}; - strcpy(createReq.user, pStmt->useName); + strcpy(createReq.user, pStmt->userName); createReq.createType = 0; createReq.superUser = 0; createReq.sysInfo = pStmt->sysinfo; @@ -5129,7 +5464,7 @@ static int32_t translateCreateUser(STranslateContext* pCxt, SCreateUserStmt* pSt static int32_t translateAlterUser(STranslateContext* pCxt, SAlterUserStmt* pStmt) { SAlterUserReq alterReq = {0}; - strcpy(alterReq.user, pStmt->useName); + strcpy(alterReq.user, pStmt->userName); alterReq.alterType = pStmt->alterType; alterReq.superUser = 0; alterReq.enable = pStmt->enable; @@ -5144,7 +5479,7 @@ static int32_t translateAlterUser(STranslateContext* pCxt, SAlterUserStmt* pStmt static int32_t translateDropUser(STranslateContext* pCxt, SDropUserStmt* pStmt) { SDropUserReq dropReq = {0}; - strcpy(dropReq.user, pStmt->useName); + strcpy(dropReq.user, pStmt->userName); return buildCmdMsg(pCxt, TDMT_MND_DROP_USER, (FSerializeFunc)tSerializeSDropUserReq, &dropReq); } @@ -5187,7 +5522,7 @@ static int32_t getSmaIndexDstVgId(STranslateContext* pCxt, const char* pDbName, } static int32_t getSmaIndexSql(STranslateContext* pCxt, char** pSql, int32_t* pLen) { - *pSql = strdup(pCxt->pParseCxt->pSql); + *pSql = taosStrdup(pCxt->pParseCxt->pSql); if (NULL == *pSql) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -5196,6 +5531,7 @@ static int32_t getSmaIndexSql(STranslateContext* pCxt, char** pSql, int32_t* pLe } static int32_t buildSampleAstInfoByIndex(STranslateContext* pCxt, SCreateIndexStmt* pStmt, SSampleAstInfo* pInfo) { + pInfo->createSmaIndex = true; pInfo->pDbName = pStmt->dbName; pInfo->pTableName = pStmt->tableName; pInfo->pFuncs = nodesCloneList(pStmt->pOptions->pFuncs); @@ -5310,6 +5646,28 @@ static int32_t buildCreateFullTextReq(STranslateContext* pCxt, SCreateIndexStmt* return TSDB_CODE_SUCCESS; } +static int32_t buildCreateTagIndexReq(STranslateContext* pCxt, SCreateIndexStmt* pStmt, SCreateTagIndexReq* pReq) { + SName name; + tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->indexDbName, pStmt->indexName, &name), pReq->idxName); + memset(&name, 0, sizeof(SName)); + + tNameExtractFullName(toName(pCxt->pParseCxt->acctId, pStmt->dbName, pStmt->tableName, &name), pReq->stbName); + memset(&name, 0, sizeof(SName)); + + tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName)); + tNameGetFullDbName(&name, pReq->dbFName); + + SNode* pNode = NULL; + ASSERT(LIST_LENGTH(pStmt->pCols) == 1); + FOREACH(pNode, pStmt->pCols) { + SColumnNode* p = (SColumnNode*)pNode; + memcpy(pReq->colName, p->colName, sizeof(p->colName)); + } + + // impl later + return TSDB_CODE_SUCCESS; +} + static int32_t translateCreateFullTextIndex(STranslateContext* pCxt, SCreateIndexStmt* pStmt) { SMCreateFullTextReq createFTReq = {0}; int32_t code = buildCreateFullTextReq(pCxt, pStmt, &createFTReq); @@ -5320,9 +5678,20 @@ static int32_t translateCreateFullTextIndex(STranslateContext* pCxt, SCreateInde return code; } +static int32_t translateCreateNormalIndex(STranslateContext* pCxt, SCreateIndexStmt* pStmt) { + SCreateTagIndexReq createTagIdxReq = {0}; + int32_t code = buildCreateTagIndexReq(pCxt, pStmt, &createTagIdxReq); + if (TSDB_CODE_SUCCESS == code) { + code = buildCmdMsg(pCxt, TDMT_MND_CREATE_INDEX, (FSerializeFunc)tSerializeSCreateTagIdxReq, &createTagIdxReq); + } + return code; +} + static int32_t translateCreateIndex(STranslateContext* pCxt, SCreateIndexStmt* pStmt) { if (INDEX_TYPE_FULLTEXT == pStmt->indexType) { return translateCreateFullTextIndex(pCxt, pStmt); + } else if (INDEX_TYPE_NORMAL == pStmt->indexType) { + return translateCreateNormalIndex(pCxt, pStmt); } return translateCreateSmaIndex(pCxt, pStmt); } @@ -5391,7 +5760,7 @@ static int32_t buildCreateTopicReq(STranslateContext* pCxt, SCreateTopicStmt* pS pReq->igExists = pStmt->ignoreExists; pReq->withMeta = pStmt->withMeta; - pReq->sql = strdup(pCxt->pParseCxt->pSql); + pReq->sql = taosStrdup(pCxt->pParseCxt->pSql); if (NULL == pReq->sql) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -5432,7 +5801,8 @@ static int32_t checkCreateTopic(STranslateContext* pCxt, SCreateTopicStmt* pStmt if (QUERY_NODE_SELECT_STMT == nodeType(pStmt->pQuery)) { SSelectStmt* pSelect = (SSelectStmt*)pStmt->pQuery; - if (!pSelect->isDistinct && QUERY_NODE_REAL_TABLE == nodeType(pSelect->pFromTable) && + if (!pSelect->isDistinct && + (NULL != pSelect->pFromTable && QUERY_NODE_REAL_TABLE == nodeType(pSelect->pFromTable)) && NULL == pSelect->pGroupByList && NULL == pSelect->pLimit && NULL == pSelect->pSlimit && NULL == pSelect->pOrderByList && NULL == pSelect->pPartitionByList) { return TSDB_CODE_SUCCESS; @@ -5479,7 +5849,7 @@ static int32_t translateDropCGroup(STranslateContext* pCxt, SDropCGroupStmt* pSt } static int32_t translateAlterLocal(STranslateContext* pCxt, SAlterLocalStmt* pStmt) { - // todo + // The statement is executed directly on the client without constructing a message. return TSDB_CODE_SUCCESS; } @@ -5494,13 +5864,45 @@ static int32_t translateDescribe(STranslateContext* pCxt, SDescribeStmt* pStmt) return refreshGetTableMeta(pCxt, pStmt->dbName, pStmt->tableName, &pStmt->pMeta); } -static int32_t translateKillConnection(STranslateContext* pCxt, SKillStmt* pStmt) { - SKillConnReq killReq = {0}; - killReq.connId = pStmt->targetId; - return buildCmdMsg(pCxt, TDMT_MND_KILL_CONN, (FSerializeFunc)tSerializeSKillConnReq, &killReq); +static int32_t translateCompactRange(STranslateContext* pCxt, SCompactDatabaseStmt* pStmt, SCompactDbReq* pReq) { + SDbCfgInfo dbCfg = {0}; + int32_t code = getDBCfg(pCxt, pStmt->dbName, &dbCfg); + if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pStart) { + ((SValueNode*)pStmt->pStart)->node.resType.precision = dbCfg.precision; + ((SValueNode*)pStmt->pStart)->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP; + code = doTranslateValue(pCxt, (SValueNode*)pStmt->pStart); + } + if (TSDB_CODE_SUCCESS == code && NULL != pStmt->pEnd) { + ((SValueNode*)pStmt->pEnd)->node.resType.precision = dbCfg.precision; + ((SValueNode*)pStmt->pEnd)->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP; + code = doTranslateValue(pCxt, (SValueNode*)pStmt->pEnd); + } + if (TSDB_CODE_SUCCESS == code) { + pReq->timeRange.skey = NULL != pStmt->pStart ? ((SValueNode*)pStmt->pStart)->datum.i : INT64_MIN; + pReq->timeRange.ekey = NULL != pStmt->pEnd ? ((SValueNode*)pStmt->pEnd)->datum.i : INT64_MAX; + } + return code; } -static int32_t translateKillQuery(STranslateContext* pCxt, SKillQueryStmt* pStmt) { +static int32_t translateCompact(STranslateContext* pCxt, SCompactDatabaseStmt* pStmt) { + SCompactDbReq compactReq = {0}; + SName name; + tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName)); + tNameGetFullDbName(&name, compactReq.db); + int32_t code = translateCompactRange(pCxt, pStmt, &compactReq); + if (TSDB_CODE_SUCCESS == code) { + code = buildCmdMsg(pCxt, TDMT_MND_COMPACT_DB, (FSerializeFunc)tSerializeSCompactDbReq, &compactReq); + } + return code; +} + +static int32_t translateKillConnection(STranslateContext* pCxt, SKillStmt* pStmt) { + SKillConnReq killReq = {0}; + killReq.connId = pStmt->targetId; + return buildCmdMsg(pCxt, TDMT_MND_KILL_CONN, (FSerializeFunc)tSerializeSKillConnReq, &killReq); +} + +static int32_t translateKillQuery(STranslateContext* pCxt, SKillQueryStmt* pStmt) { SKillQueryReq killReq = {0}; strcpy(killReq.queryStrId, pStmt->queryId); return buildCmdMsg(pCxt, TDMT_MND_KILL_QUERY, (FSerializeFunc)tSerializeSKillQueryReq, &killReq); @@ -5592,6 +5994,13 @@ static int32_t addWstartTsToCreateStreamQuery(STranslateContext* pCxt, SNode* pS return code; } +static const char* getTagNameForCreateStreamTag(SNode* pTag) { + if (QUERY_NODE_COLUMN_DEF == nodeType(pTag)) { + return ((SColumnDefNode*)pTag)->colName; + } + return ((SColumnNode*)pTag)->colName; +} + static int32_t addTagsToCreateStreamQuery(STranslateContext* pCxt, SCreateStreamStmt* pStmt, SSelectStmt* pSelect) { if (NULL == pStmt->pTags) { return TSDB_CODE_SUCCESS; @@ -5602,7 +6011,7 @@ static int32_t addTagsToCreateStreamQuery(STranslateContext* pCxt, SCreateStream bool found = false; SNode* pPart = NULL; FOREACH(pPart, pSelect->pPartitionByList) { - if (0 == strcmp(((SColumnDefNode*)pTag)->colName, ((SExprNode*)pPart)->userAlias)) { + if (0 == strcmp(getTagNameForCreateStreamTag(pTag), ((SExprNode*)pPart)->userAlias)) { if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pSelect->pTags, nodesCloneNode(pPart))) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -5611,12 +6020,32 @@ static int32_t addTagsToCreateStreamQuery(STranslateContext* pCxt, SCreateStream } } if (!found) { - return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, ((SColumnDefNode*)pTag)->colName); + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, ((SColumnDefNode*)pTag)->colName); } } return TSDB_CODE_SUCCESS; } +static SNode* createNullValue() { + SValueNode* pValue = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); + if (NULL == pValue) { + return NULL; + } + pValue->isNull = true; + pValue->node.resType.type = TSDB_DATA_TYPE_NULL; + pValue->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_NULL].bytes; + return (SNode*)pValue; +} + +static int32_t addNullTagsForExistTable(STranslateContext* pCxt, STableMeta* pMeta, SSelectStmt* pSelect) { + int32_t numOfTags = getNumOfTags(pMeta); + int32_t code = TSDB_CODE_SUCCESS; + for (int32_t i = 0; TSDB_CODE_SUCCESS == code && i < numOfTags; ++i) { + code = nodesListMakeStrictAppend(&pSelect->pTags, createNullValue()); + } + return code; +} + typedef struct SRewriteSubtableCxt { STranslateContext* pCxt; SNodeList* pPartitionList; @@ -5662,16 +6091,30 @@ static int32_t addSubtableNameToCreateStreamQuery(STranslateContext* pCxt, SCrea return pCxt->errCode; } -static int32_t addSubtableInfoToCreateStreamQuery(STranslateContext* pCxt, SCreateStreamStmt* pStmt) { +static int32_t addNullTagsForCreateTable(STranslateContext* pCxt, SCreateStreamStmt* pStmt) { + int32_t code = TSDB_CODE_SUCCESS; + for (int32_t i = 0; TSDB_CODE_SUCCESS == code && i < LIST_LENGTH(pStmt->pTags); ++i) { + code = nodesListMakeStrictAppend(&((SSelectStmt*)pStmt->pQuery)->pTags, createNullValue()); + } + return code; +} + +static int32_t addNullTagsToCreateStreamQuery(STranslateContext* pCxt, STableMeta* pMeta, SCreateStreamStmt* pStmt) { + if (NULL == pMeta) { + return addNullTagsForCreateTable(pCxt, pStmt); + } + return addNullTagsForExistTable(pCxt, pMeta, (SSelectStmt*)pStmt->pQuery); +} + +static int32_t addSubtableInfoToCreateStreamQuery(STranslateContext* pCxt, STableMeta* pMeta, + SCreateStreamStmt* pStmt) { + int32_t code = TSDB_CODE_SUCCESS; SSelectStmt* pSelect = (SSelectStmt*)pStmt->pQuery; if (NULL == pSelect->pPartitionByList) { - if (NULL != pStmt->pTags || NULL != pStmt->pSubtable) { - return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, "Unsupported stream query"); - } - return TSDB_CODE_SUCCESS; + code = addNullTagsToCreateStreamQuery(pCxt, pMeta, pStmt); + } else { + code = addTagsToCreateStreamQuery(pCxt, pStmt, pSelect); } - - int32_t code = addTagsToCreateStreamQuery(pCxt, pStmt, pSelect); if (TSDB_CODE_SUCCESS == code) { code = addSubtableNameToCreateStreamQuery(pCxt, pStmt, pSelect); } @@ -5679,17 +6122,54 @@ static int32_t addSubtableInfoToCreateStreamQuery(STranslateContext* pCxt, SCrea return code; } +static bool isEventWindowQuery(SSelectStmt* pSelect) { + return NULL != pSelect->pWindow && QUERY_NODE_EVENT_WINDOW == nodeType(pSelect->pWindow); +} + +static bool hasJsonTypeProjection(SSelectStmt* pSelect) { + SNode* pProj = NULL; + FOREACH(pProj, pSelect->pProjectionList) { + if (TSDB_DATA_TYPE_JSON == ((SExprNode*)pProj)->resType.type) { + return true; + } + } + return false; +} + +static EDealRes hasColumnOrPseudoColumn(SNode* pNode, void* pContext) { + if (QUERY_NODE_COLUMN == nodeType(pNode)) { + *(bool*)pContext = true; + return DEAL_RES_END; + } + if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)) { + *(bool*)pContext = true; + return DEAL_RES_END; + } + return DEAL_RES_CONTINUE; +} + +static int32_t subtableExprHasColumnOrPseudoColumn(SNode* pNode) { + bool hasColumn = false; + nodesWalkExprPostOrder(pNode, hasColumnOrPseudoColumn, &hasColumn); + return hasColumn; +} + static int32_t checkStreamQuery(STranslateContext* pCxt, SCreateStreamStmt* pStmt) { SSelectStmt* pSelect = (SSelectStmt*)pStmt->pQuery; if (TSDB_DATA_TYPE_TIMESTAMP != ((SExprNode*)nodesListGetNode(pSelect->pProjectionList, 0))->resType.type || !pSelect->isTimeLineResult || crossTableWithoutAggOper(pSelect) || NULL != pSelect->pOrderByList || - crossTableWithUdaf(pSelect)) { + crossTableWithUdaf(pSelect) || isEventWindowQuery(pSelect) || hasJsonTypeProjection(pSelect)) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, "Unsupported stream query"); } if (NULL != pSelect->pSubtable && TSDB_DATA_TYPE_VARCHAR != ((SExprNode*)pSelect->pSubtable)->resType.type) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, "SUBTABLE expression must be of VARCHAR type"); } + if (NULL != pSelect->pSubtable && 0 == LIST_LENGTH(pSelect->pPartitionByList) && subtableExprHasColumnOrPseudoColumn(pSelect->pSubtable)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, + "SUBTABLE expression must not has column when no partition by clause"); + } + if (NULL == pSelect->pWindow && STREAM_TRIGGER_AT_ONCE != pStmt->pOptions->triggerType) { return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, "The trigger mode of non window query can only be AT_ONCE"); @@ -5697,9 +6177,349 @@ static int32_t checkStreamQuery(STranslateContext* pCxt, SCreateStreamStmt* pStm return TSDB_CODE_SUCCESS; } +static int32_t adjustDataTypeOfProjections(STranslateContext* pCxt, const STableMeta* pMeta, SNodeList* pProjections) { + if (getNumOfColumns(pMeta) != LIST_LENGTH(pProjections)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMNS_NUM, "Illegal number of columns"); + } + + SSchema* pSchemas = getTableColumnSchema(pMeta); + int32_t index = 0; + SNode* pProj = NULL; + FOREACH(pProj, pProjections) { + SSchema* pSchema = pSchemas + index++; + SDataType dt = {.type = pSchema->type, .bytes = pSchema->bytes}; + if (!dataTypeEqual(&dt, &((SExprNode*)pProj)->resType)) { + SNode* pFunc = NULL; + int32_t code = createCastFunc(pCxt, pProj, dt, &pFunc); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + REPLACE_NODE(pFunc); + } + } + + return TSDB_CODE_SUCCESS; +} + +typedef struct SProjColPos { + int32_t colId; + SNode* pProj; +} SProjColPos; + +static int32_t projColPosCompar(const void* l, const void* r) { + return ((SProjColPos*)l)->colId > ((SProjColPos*)r)->colId; +} + +static void projColPosDelete(void* p) { nodesDestroyNode(((SProjColPos*)p)->pProj); } + +static int32_t addProjToProjColPos(STranslateContext* pCxt, const SSchema* pSchema, SNode* pProj, SArray* pProjColPos) { + SNode* pNewProj = nodesCloneNode(pProj); + if (NULL == pNewProj) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + int32_t code = TSDB_CODE_SUCCESS; + SDataType dt = {.type = pSchema->type, .bytes = pSchema->bytes}; + if (!dataTypeEqual(&dt, &((SExprNode*)pNewProj)->resType)) { + SNode* pFunc = NULL; + code = createCastFunc(pCxt, pNewProj, dt, &pFunc); + pNewProj = pFunc; + } + if (TSDB_CODE_SUCCESS == code) { + SProjColPos pos = {.colId = pSchema->colId, .pProj = pNewProj}; + code = (NULL == taosArrayPush(pProjColPos, &pos) ? TSDB_CODE_OUT_OF_MEMORY : TSDB_CODE_SUCCESS); + } + if (TSDB_CODE_SUCCESS != code) { + nodesDestroyNode(pNewProj); + } + return code; +} + +static int32_t setFillNullCols(SArray* pProjColPos, const STableMeta* pMeta, SCMCreateStreamReq* pReq) { + int32_t numOfBoundCols = taosArrayGetSize(pProjColPos); + pReq->fillNullCols = taosArrayInit(pMeta->tableInfo.numOfColumns - numOfBoundCols, sizeof(SColLocation)); + if (NULL == pReq->fillNullCols) { + return TSDB_CODE_OUT_OF_MEMORY; + } + const SSchema* pSchemas = getTableColumnSchema(pMeta); + int32_t indexOfBoundCols = 0; + for (int32_t i = 0; i < pMeta->tableInfo.numOfColumns; ++i) { + const SSchema* pSchema = pSchemas + i; + if (indexOfBoundCols < numOfBoundCols) { + SProjColPos* pPos = taosArrayGet(pProjColPos, indexOfBoundCols); + if (pSchema->colId == pPos->colId) { + ++indexOfBoundCols; + continue; + } + } + SColLocation colLoc = {.colId = pSchema->colId, .slotId = i, .type = pSchema->type}; + taosArrayPush(pReq->fillNullCols, &colLoc); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t adjustOrderOfProjections(STranslateContext* pCxt, SNodeList* pCols, const STableMeta* pMeta, + SNodeList** pProjections, SCMCreateStreamReq* pReq) { + if (LIST_LENGTH(pCols) != LIST_LENGTH(*pProjections)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMNS_NUM, "Illegal number of columns"); + } + + SArray* pProjColPos = taosArrayInit(LIST_LENGTH(pCols), sizeof(SProjColPos)); + if (NULL == pProjColPos) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + int32_t code = TSDB_CODE_SUCCESS; + bool hasPrimaryKey = false; + SNode* pCol = NULL; + SNode* pProj = NULL; + FORBOTH(pCol, pCols, pProj, *pProjections) { + const SSchema* pSchema = getNormalColSchema(pMeta, ((SColumnNode*)pCol)->colName); + if (NULL == pSchema) { + code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, ((SColumnNode*)pCol)->colName); + } + if (TSDB_CODE_SUCCESS == code) { + code = addProjToProjColPos(pCxt, pSchema, pProj, pProjColPos); + } + if (TSDB_CODE_SUCCESS != code) { + break; + } + if (PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { + hasPrimaryKey = true; + } + } + + if (TSDB_CODE_SUCCESS == code && !hasPrimaryKey) { + code = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMNS_NUM, + "primary timestamp column can not be null"); + } + + SNodeList* pNewProjections = NULL; + if (TSDB_CODE_SUCCESS == code) { + taosArraySort(pProjColPos, projColPosCompar); + int32_t num = taosArrayGetSize(pProjColPos); + pNewProjections = nodesMakeList(); + if (NULL == pNewProjections) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + for (int32_t i = 0; TSDB_CODE_SUCCESS == code && i < num; ++i) { + SProjColPos* pPos = taosArrayGet(pProjColPos, i); + code = nodesListStrictAppend(pNewProjections, pPos->pProj); + pPos->pProj = NULL; + } + } + + if (TSDB_CODE_SUCCESS == code && pMeta->tableInfo.numOfColumns > LIST_LENGTH(pCols)) { + code = setFillNullCols(pProjColPos, pMeta, pReq); + } + + if (TSDB_CODE_SUCCESS == code) { + taosArrayDestroy(pProjColPos); + nodesDestroyList(*pProjections); + *pProjections = pNewProjections; + } else { + taosArrayDestroyEx(pProjColPos, projColPosDelete); + nodesDestroyList(pNewProjections); + } + + return code; +} + +static int32_t adjustProjectionsForExistTable(STranslateContext* pCxt, SCreateStreamStmt* pStmt, + const STableMeta* pMeta, SCMCreateStreamReq* pReq) { + SSelectStmt* pSelect = (SSelectStmt*)pStmt->pQuery; + if (NULL == pStmt->pCols) { + return adjustDataTypeOfProjections(pCxt, pMeta, pSelect->pProjectionList); + } + return adjustOrderOfProjections(pCxt, pStmt->pCols, pMeta, &pSelect->pProjectionList, pReq); +} + +static bool isGroupIdTagStream(const STableMeta* pMeta, SNodeList* pTags) { + return (NULL == pTags && 1 == pMeta->tableInfo.numOfTags && TSDB_DATA_TYPE_UBIGINT == getTableTagSchema(pMeta)->type); +} + +static int32_t adjustDataTypeOfTags(STranslateContext* pCxt, const STableMeta* pMeta, SNodeList* pTags) { + if (isGroupIdTagStream(pMeta, pTags)) { + return TSDB_CODE_SUCCESS; + } + + if (getNumOfTags(pMeta) != LIST_LENGTH(pTags)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMNS_NUM, "Illegal number of tags"); + } + + SSchema* pSchemas = getTableTagSchema(pMeta); + int32_t index = 0; + SNode* pTag = NULL; + FOREACH(pTag, pTags) { + SSchema* pSchema = pSchemas + index++; + SDataType dt = {.type = pSchema->type, .bytes = pSchema->bytes}; + if (!dataTypeEqual(&dt, &((SExprNode*)pTag)->resType)) { + SNode* pFunc = NULL; + int32_t code = createCastFunc(pCxt, pTag, dt, &pFunc); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + REPLACE_NODE(pFunc); + } + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t adjustOrderOfTags(STranslateContext* pCxt, SNodeList* pTags, const STableMeta* pMeta, + SNodeList** pTagExprs, SCMCreateStreamReq* pReq) { + if (LIST_LENGTH(pTags) != LIST_LENGTH(*pTagExprs)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMNS_NUM, "Illegal number of tags"); + } + + SArray* pTagPos = taosArrayInit(LIST_LENGTH(pTags), sizeof(SProjColPos)); + if (NULL == pTagPos) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + int32_t code = TSDB_CODE_SUCCESS; + SNode* pTag = NULL; + SNode* pTagExpr = NULL; + FORBOTH(pTag, pTags, pTagExpr, *pTagExprs) { + const SSchema* pSchema = getTagSchema(pMeta, ((SColumnNode*)pTag)->colName); + if (NULL == pSchema) { + code = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TAG_NAME, ((SColumnNode*)pTag)->colName); + } + if (TSDB_CODE_SUCCESS == code) { + code = addProjToProjColPos(pCxt, pSchema, pTagExpr, pTagPos); + } + if (TSDB_CODE_SUCCESS != code) { + break; + } + } + + SNodeList* pNewTagExprs = NULL; + if (TSDB_CODE_SUCCESS == code) { + taosArraySort(pTagPos, projColPosCompar); + int32_t indexOfBoundTags = 0; + int32_t numOfBoundTags = taosArrayGetSize(pTagPos); + int32_t numOfTags = getNumOfTags(pMeta); + const SSchema* pTagsSchema = getTableTagSchema(pMeta); + pNewTagExprs = nodesMakeList(); + if (NULL == pNewTagExprs) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + for (int32_t i = 0; TSDB_CODE_SUCCESS == code && i < numOfTags; ++i) { + const SSchema* pTagSchema = pTagsSchema + i; + if (indexOfBoundTags < numOfBoundTags) { + SProjColPos* pPos = taosArrayGet(pTagPos, indexOfBoundTags); + if (pPos->colId == pTagSchema->colId) { + ++indexOfBoundTags; + code = nodesListStrictAppend(pNewTagExprs, pPos->pProj); + pPos->pProj = NULL; + continue; + } + } + code = nodesListStrictAppend(pNewTagExprs, createNullValue()); + } + } + + if (TSDB_CODE_SUCCESS == code) { + taosArrayDestroy(pTagPos); + nodesDestroyList(*pTagExprs); + *pTagExprs = pNewTagExprs; + } else { + taosArrayDestroyEx(pTagPos, projColPosDelete); + nodesDestroyList(pNewTagExprs); + } + + return code; +} + +static int32_t adjustTagsForExistTable(STranslateContext* pCxt, SCreateStreamStmt* pStmt, const STableMeta* pMeta, + SCMCreateStreamReq* pReq) { + SSelectStmt* pSelect = (SSelectStmt*)pStmt->pQuery; + if (NULL == pSelect->pPartitionByList) { + return TSDB_CODE_SUCCESS; + } + if (NULL == pStmt->pTags) { + return adjustDataTypeOfTags(pCxt, pMeta, pSelect->pTags); + } + return adjustOrderOfTags(pCxt, pStmt->pTags, pMeta, &pSelect->pTags, pReq); +} + +static int32_t adjustTagsForCreateTable(STranslateContext* pCxt, SCreateStreamStmt* pStmt, SCMCreateStreamReq* pReq) { + SSelectStmt* pSelect = (SSelectStmt*)pStmt->pQuery; + if (NULL == pSelect->pPartitionByList || NULL == pSelect->pTags) { + return TSDB_CODE_SUCCESS; + } + + SNode* pTagDef = NULL; + SNode* pTagExpr = NULL; + FORBOTH(pTagDef, pStmt->pTags, pTagExpr, pSelect->pTags) { + SColumnDefNode* pDef = (SColumnDefNode*)pTagDef; + if (!dataTypeEqual(&pDef->dataType, &((SExprNode*)pTagExpr)->resType)) { + SNode* pFunc = NULL; + int32_t code = createCastFunc(pCxt, pTagExpr, pDef->dataType, &pFunc); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + REPLACE_LIST2_NODE(pFunc); + } + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t adjustTags(STranslateContext* pCxt, SCreateStreamStmt* pStmt, const STableMeta* pMeta, + SCMCreateStreamReq* pReq) { + if (NULL == pMeta) { + return adjustTagsForCreateTable(pCxt, pStmt, pReq); + } + return adjustTagsForExistTable(pCxt, pStmt, pMeta, pReq); +} + +static bool isTagDef(SNodeList* pTags) { + if (NULL == pTags) { + return false; + } + return QUERY_NODE_COLUMN_DEF == nodeType(nodesListGetNode(pTags, 0)); +} + +static bool isTagBound(SNodeList* pTags) { + if (NULL == pTags) { + return false; + } + return QUERY_NODE_COLUMN == nodeType(nodesListGetNode(pTags, 0)); +} + +static int32_t translateStreamTargetTable(STranslateContext* pCxt, SCreateStreamStmt* pStmt, SCMCreateStreamReq* pReq, + STableMeta** pMeta) { + int32_t code = getTableMeta(pCxt, pStmt->targetDbName, pStmt->targetTabName, pMeta); + if (TSDB_CODE_PAR_TABLE_NOT_EXIST == code) { + if (NULL != pStmt->pCols || isTagBound(pStmt->pTags)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TABLE_NOT_EXIST, pStmt->targetTabName); + } + pReq->createStb = STREAM_CREATE_STABLE_TRUE; + pReq->targetStbUid = 0; + return TSDB_CODE_SUCCESS; + } else if (TSDB_CODE_SUCCESS == code) { + if (isTagDef(pStmt->pTags)) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, "Table already exist: %s", + pStmt->targetTabName); + } + if (TSDB_SUPER_TABLE != (*pMeta)->tableType) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_STREAM_QUERY, + "Stream can only be written to super table"); + } + pReq->createStb = STREAM_CREATE_STABLE_FALSE; + pReq->targetStbUid = (*pMeta)->suid; + } + return code; +} + static int32_t buildCreateStreamQuery(STranslateContext* pCxt, SCreateStreamStmt* pStmt, SCMCreateStreamReq* pReq) { pCxt->createStream = true; - int32_t code = addSubtableInfoToCreateStreamQuery(pCxt, pStmt); + STableMeta* pMeta = NULL; + int32_t code = translateStreamTargetTable(pCxt, pStmt, pReq, &pMeta); + if (TSDB_CODE_SUCCESS == code) { + code = addSubtableInfoToCreateStreamQuery(pCxt, pMeta, pStmt); + } if (TSDB_CODE_SUCCESS == code) { code = translateQuery(pCxt, pStmt->pQuery); } @@ -5709,10 +6529,17 @@ static int32_t buildCreateStreamQuery(STranslateContext* pCxt, SCreateStreamStmt if (TSDB_CODE_SUCCESS == code) { code = checkStreamQuery(pCxt, pStmt); } + if (TSDB_CODE_SUCCESS == code && NULL != pMeta) { + code = adjustProjectionsForExistTable(pCxt, pStmt, pMeta, pReq); + } + if (TSDB_CODE_SUCCESS == code) { + code = adjustTags(pCxt, pStmt, pMeta, pReq); + } if (TSDB_CODE_SUCCESS == code) { getSourceDatabase(pStmt->pQuery, pCxt->pParseCxt->acctId, pReq->sourceDB); code = nodesNodeToString(pStmt->pQuery, false, &pReq->ast, NULL); } + taosMemoryFree(pMeta); return code; } @@ -5742,7 +6569,7 @@ static int32_t buildCreateStreamReq(STranslateContext* pCxt, SCreateStreamStmt* int32_t code = buildCreateStreamQuery(pCxt, pStmt, pReq); if (TSDB_CODE_SUCCESS == code) { - pReq->sql = strdup(pCxt->pParseCxt->pSql); + pReq->sql = taosStrdup(pCxt->pParseCxt->pSql); if (NULL == pReq->sql) { code = TSDB_CODE_OUT_OF_MEMORY; } @@ -5760,9 +6587,11 @@ static int32_t buildCreateStreamReq(STranslateContext* pCxt, SCreateStreamStmt* (NULL != pStmt->pOptions->pDeleteMark ? ((SValueNode*)pStmt->pOptions->pDeleteMark)->datum.i : 0); pReq->fillHistory = pStmt->pOptions->fillHistory; pReq->igExpired = pStmt->pOptions->ignoreExpired; + if (pReq->createStb) { + columnDefNodeToField(pStmt->pTags, &pReq->pTags); + pReq->numOfTags = LIST_LENGTH(pStmt->pTags); + } pReq->igUpdate = pStmt->pOptions->ignoreUpdate; - columnDefNodeToField(pStmt->pTags, &pReq->pTags); - pReq->numOfTags = LIST_LENGTH(pStmt->pTags); } return code; @@ -5829,12 +6658,25 @@ static int32_t translateCreateFunction(STranslateContext* pCxt, SCreateFunctionS if (fmIsBuiltinFunc(pStmt->funcName)) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_FUNCTION_NAME); } + + if (TSDB_DATA_TYPE_JSON == pStmt->outputDt.type || TSDB_DATA_TYPE_VARBINARY == pStmt->outputDt.type || + TSDB_DATA_TYPE_DECIMAL == pStmt->outputDt.type || TSDB_DATA_TYPE_BLOB == pStmt->outputDt.type || + TSDB_DATA_TYPE_MEDIUMBLOB == pStmt->outputDt.type) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "Unsupported output type for UDF"); + } + + if (!pStmt->isAgg && pStmt->bufSize > 0) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, "BUFSIZE can only be used with UDAF"); + } + SCreateFuncReq req = {0}; strcpy(req.name, pStmt->funcName); + req.orReplace = pStmt->orReplace; req.igExists = pStmt->ignoreExists; req.funcType = pStmt->isAgg ? TSDB_FUNC_TYPE_AGGREGATE : TSDB_FUNC_TYPE_SCALAR; - req.scriptType = TSDB_FUNC_SCRIPT_BIN_LIB; + req.scriptType = pStmt->language; req.outputType = pStmt->outputDt.type; + pStmt->outputDt.bytes = calcTypeBytes(pStmt->outputDt); req.outputLen = pStmt->outputDt.bytes; req.bufSize = pStmt->bufSize; int32_t code = readFromFile(pStmt->libraryPath, &req.codeLen, &req.pCode); @@ -5852,39 +6694,106 @@ static int32_t translateDropFunction(STranslateContext* pCxt, SDropFunctionStmt* return buildCmdMsg(pCxt, TDMT_MND_DROP_FUNC, (FSerializeFunc)tSerializeSDropFuncReq, &req); } +static int32_t createRealTableForGrantTable(SGrantStmt* pStmt, SRealTableNode** pTable) { + SRealTableNode* pRealTable = (SRealTableNode*)nodesMakeNode(QUERY_NODE_REAL_TABLE); + if (NULL == pRealTable) { + return TSDB_CODE_OUT_OF_MEMORY; + } + strcpy(pRealTable->table.dbName, pStmt->objName); + strcpy(pRealTable->table.tableName, pStmt->tabName); + strcpy(pRealTable->table.tableAlias, pStmt->tabName); + *pTable = pRealTable; + return TSDB_CODE_SUCCESS; +} + +static int32_t translateGrantTagCond(STranslateContext* pCxt, SGrantStmt* pStmt, SAlterUserReq* pReq) { + SRealTableNode* pTable = NULL; + if ('\0' == pStmt->tabName[0] || '*' == pStmt->tabName[0]) { + if (pStmt->pTagCond) { + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, + "The With clause can only be used for table level privilege"); + } else { + return TSDB_CODE_SUCCESS; + } + } + + int32_t code = createRealTableForGrantTable(pStmt, &pTable); + if (TSDB_CODE_SUCCESS == code) { + SName name; + code = getTableMetaImpl(pCxt, toName(pCxt->pParseCxt->acctId, pTable->table.dbName, pTable->table.tableName, &name), + &(pTable->pMeta)); + if (code) { + nodesDestroyNode((SNode*)pTable); + return code; + } + + if (TSDB_SUPER_TABLE != pTable->pMeta->tableType && TSDB_NORMAL_TABLE != pTable->pMeta->tableType) { + nodesDestroyNode((SNode*)pTable); + return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_SYNTAX_ERROR, + "Only supertable and normal table can be granted"); + } + } + + if (TSDB_CODE_SUCCESS == code && NULL == pStmt->pTagCond) { + nodesDestroyNode((SNode*)pTable); + return TSDB_CODE_SUCCESS; + } + + pCxt->pCurrStmt = (SNode*)pStmt; + + if (TSDB_CODE_SUCCESS == code) { + code = addNamespace(pCxt, pTable); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateExpr(pCxt, &pStmt->pTagCond); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodesNodeToString(pStmt->pTagCond, false, &pReq->tagCond, &pReq->tagCondLen); + } + nodesDestroyNode((SNode*)pTable); + return code; +} + static int32_t translateGrant(STranslateContext* pCxt, SGrantStmt* pStmt) { SAlterUserReq req = {0}; - if (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_ALL) || - (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_READ) && - PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_WRITE))) { - req.alterType = TSDB_ALTER_USER_ADD_ALL_DB; - } else if (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_READ)) { - req.alterType = TSDB_ALTER_USER_ADD_READ_DB; - } else if (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_WRITE)) { - req.alterType = TSDB_ALTER_USER_ADD_WRITE_DB; - } else if (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_SUBSCRIBE)) { + if (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_ALL) || + (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_READ) && + BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_WRITE))) { + req.alterType = ('\0' == pStmt->tabName[0] ? TSDB_ALTER_USER_ADD_ALL_DB : TSDB_ALTER_USER_ADD_ALL_TABLE); + } else if (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_READ)) { + req.alterType = ('\0' == pStmt->tabName[0] ? TSDB_ALTER_USER_ADD_READ_DB : TSDB_ALTER_USER_ADD_READ_TABLE); + } else if (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_WRITE)) { + req.alterType = ('\0' == pStmt->tabName[0] ? TSDB_ALTER_USER_ADD_WRITE_DB : TSDB_ALTER_USER_ADD_WRITE_TABLE); + } else if (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_SUBSCRIBE)) { req.alterType = TSDB_ALTER_USER_ADD_SUBSCRIBE_TOPIC; } strcpy(req.user, pStmt->userName); sprintf(req.objname, "%d.%s", pCxt->pParseCxt->acctId, pStmt->objName); - return buildCmdMsg(pCxt, TDMT_MND_ALTER_USER, (FSerializeFunc)tSerializeSAlterUserReq, &req); + sprintf(req.tabName, "%s", pStmt->tabName); + int32_t code = translateGrantTagCond(pCxt, pStmt, &req); + if (TSDB_CODE_SUCCESS == code) { + code = buildCmdMsg(pCxt, TDMT_MND_ALTER_USER, (FSerializeFunc)tSerializeSAlterUserReq, &req); + } + tFreeSAlterUserReq(&req); + return code; } static int32_t translateRevoke(STranslateContext* pCxt, SRevokeStmt* pStmt) { SAlterUserReq req = {0}; - if (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_ALL) || - (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_READ) && - PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_WRITE))) { - req.alterType = TSDB_ALTER_USER_REMOVE_ALL_DB; - } else if (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_READ)) { - req.alterType = TSDB_ALTER_USER_REMOVE_READ_DB; - } else if (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_WRITE)) { - req.alterType = TSDB_ALTER_USER_REMOVE_WRITE_DB; - } else if (PRIVILEGE_TYPE_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_SUBSCRIBE)) { + if (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_ALL) || + (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_READ) && + BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_WRITE))) { + req.alterType = ('\0' == pStmt->tabName[0] ? TSDB_ALTER_USER_REMOVE_ALL_DB : TSDB_ALTER_USER_REMOVE_ALL_TABLE); + } else if (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_READ)) { + req.alterType = ('\0' == pStmt->tabName[0] ? TSDB_ALTER_USER_REMOVE_READ_DB : TSDB_ALTER_USER_REMOVE_READ_TABLE); + } else if (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_WRITE)) { + req.alterType = ('\0' == pStmt->tabName[0] ? TSDB_ALTER_USER_REMOVE_WRITE_DB : TSDB_ALTER_USER_REMOVE_WRITE_TABLE); + } else if (BIT_FLAG_TEST_MASK(pStmt->privileges, PRIVILEGE_TYPE_SUBSCRIBE)) { req.alterType = TSDB_ALTER_USER_REMOVE_SUBSCRIBE_TOPIC; } strcpy(req.user, pStmt->userName); sprintf(req.objname, "%d.%s", pCxt->pParseCxt->acctId, pStmt->objName); + sprintf(req.tabName, "%s", pStmt->tabName); return buildCmdMsg(pCxt, TDMT_MND_ALTER_USER, (FSerializeFunc)tSerializeSAlterUserReq, &req); } @@ -5893,6 +6802,11 @@ static int32_t translateBalanceVgroup(STranslateContext* pCxt, SBalanceVgroupStm return buildCmdMsg(pCxt, TDMT_MND_BALANCE_VGROUP, (FSerializeFunc)tSerializeSBalanceVgroupReq, &req); } +static int32_t translateBalanceVgroupLeader(STranslateContext* pCxt, SBalanceVgroupLeaderStmt* pStmt) { + SBalanceVgroupLeaderReq req = {0}; + return buildCmdMsg(pCxt, TDMT_MND_BALANCE_VGROUP_LEADER, (FSerializeFunc)tSerializeSBalanceVgroupLeaderReq, &req); +} + static int32_t translateMergeVgroup(STranslateContext* pCxt, SMergeVgroupStmt* pStmt) { SMergeVgroupReq req = {.vgId1 = pStmt->vgId1, .vgId2 = pStmt->vgId2}; return buildCmdMsg(pCxt, TDMT_MND_MERGE_VGROUP, (FSerializeFunc)tSerializeSMergeVgroupReq, &req); @@ -5952,6 +6866,11 @@ static int32_t translateShowCreateDatabase(STranslateContext* pCxt, SShowCreateD if (NULL == pStmt->pCfg) { return TSDB_CODE_OUT_OF_MEMORY; } + + SName name; + tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName)); + tNameGetFullDbName(&name, pStmt->dbFName); + return getDBCfg(pCxt, pStmt->dbName, (SDbCfgInfo*)pStmt->pCfg); } @@ -6066,6 +6985,9 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) { case QUERY_NODE_DESCRIBE_STMT: code = translateDescribe(pCxt, (SDescribeStmt*)pNode); break; + case QUERY_NODE_COMPACT_DATABASE_STMT: + code = translateCompact(pCxt, (SCompactDatabaseStmt*)pNode); + break; case QUERY_NODE_KILL_CONNECTION_STMT: code = translateKillConnection(pCxt, (SKillStmt*)pNode); break; @@ -6096,6 +7018,9 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) { case QUERY_NODE_BALANCE_VGROUP_STMT: code = translateBalanceVgroup(pCxt, (SBalanceVgroupStmt*)pNode); break; + case QUERY_NODE_BALANCE_VGROUP_LEADER_STMT: + code = translateBalanceVgroupLeader(pCxt, (SBalanceVgroupLeaderStmt*)pNode); + break; case QUERY_NODE_MERGE_VGROUP_STMT: code = translateMergeVgroup(pCxt, (SMergeVgroupStmt*)pNode); break; @@ -6221,6 +7146,20 @@ static int32_t extractShowCreateDatabaseResultSchema(int32_t* numOfCols, SSchema return TSDB_CODE_SUCCESS; } +static int32_t extractShowAliveResultSchema(int32_t* numOfCols, SSchema** pSchema) { + *numOfCols = 1; + *pSchema = taosMemoryCalloc((*numOfCols), sizeof(SSchema)); + if (NULL == (*pSchema)) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + (*pSchema)[0].type = TSDB_DATA_TYPE_INT; + (*pSchema)[0].bytes = sizeof(int32_t); + strcpy((*pSchema)[0].name, "status"); + + return TSDB_CODE_SUCCESS; +} + static int32_t extractShowCreateTableResultSchema(int32_t* numOfCols, SSchema** pSchema) { *numOfCols = 2; *pSchema = taosMemoryCalloc((*numOfCols), sizeof(SSchema)); @@ -6272,6 +7211,9 @@ int32_t extractResultSchema(const SNode* pRoot, int32_t* numOfCols, SSchema** pS return extractDescribeResultSchema(numOfCols, pSchema); case QUERY_NODE_SHOW_CREATE_DATABASE_STMT: return extractShowCreateDatabaseResultSchema(numOfCols, pSchema); + case QUERY_NODE_SHOW_DB_ALIVE_STMT: + case QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT: + return extractShowAliveResultSchema(numOfCols, pSchema); case QUERY_NODE_SHOW_CREATE_TABLE_STMT: case QUERY_NODE_SHOW_CREATE_STABLE_STMT: return extractShowCreateTableResultSchema(numOfCols, pSchema); @@ -6376,7 +7318,7 @@ static int32_t createOperatorNode(EOperatorType opType, const char* pColName, SN nodesDestroyNode((SNode*)pOper); return TSDB_CODE_OUT_OF_MEMORY; } - strcpy(((SColumnNode*)pOper->pLeft)->colName, pColName); + snprintf(((SColumnNode*)pOper->pLeft)->colName, sizeof(((SColumnNode*)pOper->pLeft)->colName), "%s", pColName); *pOp = (SNode*)pOper; return TSDB_CODE_SUCCESS; @@ -6612,10 +7554,10 @@ static int32_t buildNormalTableBatchReq(int32_t acctId, const SCreateTableStmt* SVCreateTbReq req = {0}; req.type = TD_NORMAL_TABLE; - req.name = strdup(pStmt->tableName); + req.name = taosStrdup(pStmt->tableName); req.ttl = pStmt->pOptions->ttl; if (pStmt->pOptions->commentNull == false) { - req.comment = strdup(pStmt->pOptions->comment); + req.comment = taosStrdup(pStmt->pOptions->comment); if (NULL == req.comment) { tdDestroySVCreateTbReq(&req); return TSDB_CODE_OUT_OF_MEMORY; @@ -6696,7 +7638,7 @@ static void destroyCreateTbReqBatch(void* data) { } int32_t rewriteToVnodeModifyOpStmt(SQuery* pQuery, SArray* pBufArray) { - SVnodeModifOpStmt* pNewStmt = (SVnodeModifOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT); + SVnodeModifyOpStmt* pNewStmt = (SVnodeModifyOpStmt*)nodesMakeNode(QUERY_NODE_VNODE_MODIFY_STMT); if (pNewStmt == NULL) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -6774,17 +7716,17 @@ static void addCreateTbReqIntoVgroup(int32_t acctId, SHashObj* pVgroupHashmap, S struct SVCreateTbReq req = {0}; req.type = TD_CHILD_TABLE; - req.name = strdup(pStmt->tableName); + req.name = taosStrdup(pStmt->tableName); req.ttl = pStmt->pOptions->ttl; if (pStmt->pOptions->commentNull == false) { - req.comment = strdup(pStmt->pOptions->comment); + req.comment = taosStrdup(pStmt->pOptions->comment); req.commentLen = strlen(pStmt->pOptions->comment); } else { req.commentLen = -1; } req.ctb.suid = suid; req.ctb.tagNum = tagNum; - req.ctb.stbName = strdup(sTableNmae); + req.ctb.stbName = taosStrdup(sTableNmae); req.ctb.pTag = (uint8_t*)pTag; req.ctb.tagName = taosArrayDup(tagName, NULL); if (pStmt->ignoreExists) { @@ -7080,7 +8022,7 @@ SArray* serializeVgroupsCreateTableBatch(SHashObj* pVgroupHashmap) { } static int32_t rewriteCreateMultiTable(STranslateContext* pCxt, SQuery* pQuery) { - SCreateMultiTableStmt* pStmt = (SCreateMultiTableStmt*)pQuery->pRoot; + SCreateMultiTablesStmt* pStmt = (SCreateMultiTablesStmt*)pQuery->pRoot; SHashObj* pVgroupHashmap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); if (NULL == pVgroupHashmap) { @@ -7266,7 +8208,7 @@ static int32_t buildUpdateTagValReq(STranslateContext* pCxt, SAlterTableStmt* pS pStmt->colName); } - pReq->tagName = strdup(pStmt->colName); + pReq->tagName = taosStrdup(pStmt->colName); if (NULL == pReq->tagName) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -7331,6 +8273,11 @@ static int32_t buildAddColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, S return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DUPLICATED_COLUMN); } + if ((TSDB_DATA_TYPE_VARCHAR == pStmt->dataType.type && calcTypeBytes(pStmt->dataType) > TSDB_MAX_BINARY_LEN) || + (TSDB_DATA_TYPE_NCHAR == pStmt->dataType.type && calcTypeBytes(pStmt->dataType) > TSDB_MAX_NCHAR_LEN)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN); + } + if (TSDB_MAX_COLUMNS == pTableMeta->tableInfo.numOfColumns) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_TOO_MANY_COLUMNS); } @@ -7339,7 +8286,7 @@ static int32_t buildAddColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, S return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROW_LENGTH, TSDB_MAX_BYTES_PER_ROW); } - pReq->colName = strdup(pStmt->colName); + pReq->colName = taosStrdup(pStmt->colName); if (NULL == pReq->colName) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -7350,19 +8297,19 @@ static int32_t buildAddColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, S return TSDB_CODE_SUCCESS; } -static int32_t buildDropColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, STableMeta* pTableMeta, +static int32_t buildDropColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, const STableMeta* pTableMeta, SVAlterTbReq* pReq) { if (2 == getNumOfColumns(pTableMeta)) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_DROP_COL); } - SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName); + const SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName); if (NULL == pSchema) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, pStmt->colName); } else if (PRIMARYKEY_TIMESTAMP_COL_ID == pSchema->colId) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_CANNOT_DROP_PRIMARY_KEY); } - pReq->colName = strdup(pStmt->colName); + pReq->colName = taosStrdup(pStmt->colName); if (NULL == pReq->colName) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -7371,11 +8318,11 @@ static int32_t buildDropColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, return TSDB_CODE_SUCCESS; } -static int32_t buildUpdateColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, STableMeta* pTableMeta, +static int32_t buildUpdateColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, const STableMeta* pTableMeta, SVAlterTbReq* pReq) { pReq->colModBytes = calcTypeBytes(pStmt->dataType); pReq->colModType = pStmt->dataType.type; - SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName); + const SSchema* pSchema = getColSchema(pTableMeta, pStmt->colName); if (NULL == pSchema) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_COLUMN, pStmt->colName); } else if (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->type != pStmt->dataType.type || @@ -7383,11 +8330,16 @@ static int32_t buildUpdateColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_MODIFY_COL); } + if ((TSDB_DATA_TYPE_VARCHAR == pStmt->dataType.type && calcTypeBytes(pStmt->dataType) > TSDB_MAX_BINARY_LEN) || + (TSDB_DATA_TYPE_NCHAR == pStmt->dataType.type && calcTypeBytes(pStmt->dataType) > TSDB_MAX_NCHAR_LEN)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN); + } + if (pTableMeta->tableInfo.rowSize + pReq->colModBytes - pSchema->bytes > TSDB_MAX_BYTES_PER_ROW) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ROW_LENGTH, TSDB_MAX_BYTES_PER_ROW); } - pReq->colName = strdup(pStmt->colName); + pReq->colName = taosStrdup(pStmt->colName); if (NULL == pReq->colName) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -7405,8 +8357,8 @@ static int32_t buildRenameColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_DUPLICATED_COLUMN); } - pReq->colName = strdup(pStmt->colName); - pReq->colNewName = strdup(pStmt->newColName); + pReq->colName = taosStrdup(pStmt->colName); + pReq->colNewName = taosStrdup(pStmt->newColName); if (NULL == pReq->colName || NULL == pReq->colNewName) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -7423,7 +8375,7 @@ static int32_t buildUpdateOptionsReq(STranslateContext* pCxt, SAlterTableStmt* p if (TSDB_CODE_SUCCESS == code) { if (pStmt->pOptions->commentNull == false) { - pReq->newComment = strdup(pStmt->pOptions->comment); + pReq->newComment = taosStrdup(pStmt->pOptions->comment); if (NULL == pReq->newComment) { code = TSDB_CODE_OUT_OF_MEMORY; } else { @@ -7439,7 +8391,7 @@ static int32_t buildUpdateOptionsReq(STranslateContext* pCxt, SAlterTableStmt* p static int32_t buildAlterTbReq(STranslateContext* pCxt, SAlterTableStmt* pStmt, STableMeta* pTableMeta, SVAlterTbReq* pReq) { - pReq->tbName = strdup(pStmt->tableName); + pReq->tbName = taosStrdup(pStmt->tableName); if (NULL == pReq->tbName) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -7538,10 +8490,6 @@ static void destoryAlterTbReq(SVAlterTbReq* pReq) { static int32_t rewriteAlterTableImpl(STranslateContext* pCxt, SAlterTableStmt* pStmt, STableMeta* pTableMeta, SQuery* pQuery) { - if (getNumOfTags(pTableMeta) == 1 && pStmt->alterType == TSDB_ALTER_TABLE_DROP_TAG) { - return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE, "the only tag cannot be dropped"); - } - if (TSDB_SUPER_TABLE == pTableMeta->tableType) { return TSDB_CODE_SUCCESS; } else if (TSDB_CHILD_TABLE != pTableMeta->tableType && TSDB_NORMAL_TABLE != pTableMeta->tableType) { @@ -7688,7 +8636,7 @@ static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) { code = rewriteCreateTable(pCxt, pQuery); } break; - case QUERY_NODE_CREATE_MULTI_TABLE_STMT: + case QUERY_NODE_CREATE_MULTI_TABLES_STMT: code = rewriteCreateMultiTable(pCxt, pQuery); break; case QUERY_NODE_DROP_TABLE_STMT: @@ -7785,12 +8733,14 @@ static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) { pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; pQuery->msgType = TDMT_VND_SUBMIT; break; - case QUERY_NODE_VNODE_MODIF_STMT: + case QUERY_NODE_VNODE_MODIFY_STMT: pQuery->execMode = QUERY_EXEC_MODE_SCHEDULE; - pQuery->msgType = toMsgType(((SVnodeModifOpStmt*)pQuery->pRoot)->sqlNodeType); + pQuery->msgType = toMsgType(((SVnodeModifyOpStmt*)pQuery->pRoot)->sqlNodeType); break; case QUERY_NODE_DESCRIBE_STMT: case QUERY_NODE_SHOW_CREATE_DATABASE_STMT: + case QUERY_NODE_SHOW_DB_ALIVE_STMT: + case QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT: case QUERY_NODE_SHOW_CREATE_TABLE_STMT: case QUERY_NODE_SHOW_CREATE_STABLE_STMT: case QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT: diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index fa091901b680041721936f7501fe23bb53b36305..14da6f8aabcfba0cfdc3a71a731b1c34acdb32d5 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -17,7 +17,7 @@ #include "cJSON.h" #include "querynodes.h" -#define USER_AUTH_KEY_MAX_LEN TSDB_USER_LEN + TSDB_DB_FNAME_LEN + 2 +#define USER_AUTH_KEY_MAX_LEN TSDB_USER_LEN + TSDB_TABLE_FNAME_LEN + 2 const void* nullPointer = NULL; @@ -103,8 +103,8 @@ static char* getSyntaxErrFormat(int32_t errCode) { return "Incorrect TIMESTAMP value: %s"; case TSDB_CODE_PAR_OFFSET_LESS_ZERO: return "soffset/offset can not be less than 0"; - case TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_BY: - return "slimit/soffset only available for PARTITION BY query"; + case TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_GROUP_BY: + return "slimit/soffset only available for PARTITION/GROUP BY query"; case TSDB_CODE_PAR_INVALID_TOPIC_QUERY: return "Invalid topic query"; case TSDB_CODE_PAR_INVALID_DROP_STABLE: @@ -174,6 +174,8 @@ static char* getSyntaxErrFormat(int32_t errCode) { return "Invalid usage of RANGE clause, EVERY clause or FILL clause"; case TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN: return "No valid function in window query"; + case TSDB_CODE_PAR_INVALID_OPTR_USAGE: + return "Invalid usage of expr: %s"; case TSDB_CODE_OUT_OF_MEMORY: return "Out of memory"; default: @@ -442,7 +444,7 @@ static int32_t getInsTagsTableTargetNameFromOp(int32_t acctId, SOperatorNode* pO } else if (QUERY_NODE_VALUE == nodeType(pOper->pRight)) { pVal = (SValueNode*)pOper->pRight; } - if (NULL == pCol || NULL == pVal) { + if (NULL == pCol || NULL == pVal || NULL == pVal->literal || 0 == strcmp(pVal->literal, "")) { return TSDB_CODE_SUCCESS; } @@ -494,24 +496,44 @@ int32_t getVnodeSysTableTargetName(int32_t acctId, SNode* pWhere, SName* pName) return TSDB_CODE_SUCCESS; } -static int32_t userAuthToString(int32_t acctId, const char* pUser, const char* pDb, AUTH_TYPE type, char* pStr) { - return sprintf(pStr, "%s*%d.%s*%d", pUser, acctId, pDb, type); +static int32_t userAuthToString(int32_t acctId, const char* pUser, const char* pDb, const char* pTable, AUTH_TYPE type, + char* pStr) { + return sprintf(pStr, "%s*%d*%s*%s*%d", pUser, acctId, pDb, (NULL != pTable && '\0' == pTable[0]) ? NULL : pTable, + type); } -static int32_t userAuthToStringExt(const char* pUser, const char* pDbFName, AUTH_TYPE type, char* pStr) { - return sprintf(pStr, "%s*%s*%d", pUser, pDbFName, type); +static int32_t getIntegerFromAuthStr(const char* pStart, char** pNext) { + char* p = strchr(pStart, '*'); + char buf[10] = {0}; + if (NULL == p) { + strcpy(buf, pStart); + *pNext = NULL; + } else { + strncpy(buf, pStart, p - pStart); + *pNext = ++p; + } + return taosStr2Int32(buf, NULL, 10); +} + +static void getStringFromAuthStr(const char* pStart, char* pStr, char** pNext) { + char* p = strchr(pStart, '*'); + if (NULL == p) { + strcpy(pStr, pStart); + *pNext = NULL; + } else { + strncpy(pStr, pStart, p - pStart); + *pNext = ++p; + } } static void stringToUserAuth(const char* pStr, int32_t len, SUserAuthInfo* pUserAuth) { - char* p1 = strchr(pStr, '*'); - strncpy(pUserAuth->user, pStr, p1 - pStr); - ++p1; - char* p2 = strchr(p1, '*'); - strncpy(pUserAuth->dbFName, p1, p2 - p1); - ++p2; - char buf[10] = {0}; - strncpy(buf, p2, len - (p2 - pStr)); - pUserAuth->type = taosStr2Int32(buf, NULL, 10); + char* p = NULL; + getStringFromAuthStr(pStr, pUserAuth->user, &p); + pUserAuth->tbName.acctId = getIntegerFromAuthStr(p, &p); + getStringFromAuthStr(p, pUserAuth->tbName.dbname, &p); + getStringFromAuthStr(p, pUserAuth->tbName.tname, &p); + pUserAuth->tbName.type = TSDB_TABLE_NAME_T; + pUserAuth->type = getIntegerFromAuthStr(p, &p); } static int32_t buildTableReq(SHashObj* pTablesHash, SArray** pTables) { @@ -582,10 +604,12 @@ static int32_t buildUserAuthReq(SHashObj* pUserAuthHash, SArray** pUserAuth) { } void* p = taosHashIterate(pUserAuthHash, NULL); while (NULL != p) { - size_t len = 0; - char* pKey = taosHashGetKey(p, &len); + size_t len = 0; + char* pKey = taosHashGetKey(p, &len); + char key[USER_AUTH_KEY_MAX_LEN] = {0}; + strncpy(key, pKey, len); SUserAuthInfo userAuth = {0}; - stringToUserAuth(pKey, len, &userAuth); + stringToUserAuth(key, len, &userAuth); taosArrayPush(*pUserAuth, &userAuth); p = taosHashIterate(pUserAuthHash, p); } @@ -710,7 +734,8 @@ static int32_t putUserAuthToCache(const SArray* pUserAuthReq, const SArray* pUse for (int32_t i = 0; i < nvgs; ++i) { SUserAuthInfo* pUser = taosArrayGet(pUserAuthReq, i); char key[USER_AUTH_KEY_MAX_LEN] = {0}; - int32_t len = userAuthToStringExt(pUser->user, pUser->dbFName, pUser->type, key); + int32_t len = userAuthToString(pUser->tbName.acctId, pUser->user, pUser->tbName.dbname, pUser->tbName.tname, + pUser->type, key); if (TSDB_CODE_SUCCESS != putMetaDataToHash(key, len, pUserAuthData, i, pUserAuth)) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -908,33 +933,24 @@ static int32_t reserveUserAuthInCacheImpl(const char* pKey, int32_t len, SParseM return TSDB_CODE_OUT_OF_MEMORY; } } - bool pass = false; - return taosHashPut(pMetaCache->pUserAuth, pKey, len, &pass, sizeof(pass)); + return taosHashPut(pMetaCache->pUserAuth, pKey, len, &nullPointer, POINTER_BYTES); } -int32_t reserveUserAuthInCache(int32_t acctId, const char* pUser, const char* pDb, AUTH_TYPE type, +int32_t reserveUserAuthInCache(int32_t acctId, const char* pUser, const char* pDb, const char* pTable, AUTH_TYPE type, SParseMetaCache* pMetaCache) { char key[USER_AUTH_KEY_MAX_LEN] = {0}; - int32_t len = userAuthToString(acctId, pUser, pDb, type, key); - return reserveUserAuthInCacheImpl(key, len, pMetaCache); -} - -int32_t reserveUserAuthInCacheExt(const char* pUser, const SName* pName, AUTH_TYPE type, SParseMetaCache* pMetaCache) { - char dbFName[TSDB_DB_FNAME_LEN] = {0}; - tNameGetFullDbName(pName, dbFName); - char key[USER_AUTH_KEY_MAX_LEN] = {0}; - int32_t len = userAuthToStringExt(pUser, dbFName, type, key); + int32_t len = userAuthToString(acctId, pUser, pDb, pTable, type, key); return reserveUserAuthInCacheImpl(key, len, pMetaCache); } -int32_t getUserAuthFromCache(SParseMetaCache* pMetaCache, const char* pUser, const char* pDbFName, AUTH_TYPE type, - bool* pPass) { - char key[USER_AUTH_KEY_MAX_LEN] = {0}; - int32_t len = userAuthToStringExt(pUser, pDbFName, type, key); - bool* pRes = NULL; - int32_t code = getMetaDataFromHash(key, len, pMetaCache->pUserAuth, (void**)&pRes); +int32_t getUserAuthFromCache(SParseMetaCache* pMetaCache, SUserAuthInfo* pAuthReq, SUserAuthRes* pAuthRes) { + char key[USER_AUTH_KEY_MAX_LEN] = {0}; + int32_t len = userAuthToString(pAuthReq->tbName.acctId, pAuthReq->user, pAuthReq->tbName.dbname, + pAuthReq->tbName.tname, pAuthReq->type, key); + SUserAuthRes* pAuth = NULL; + int32_t code = getMetaDataFromHash(key, len, pMetaCache->pUserAuth, (void**)&pAuth); if (TSDB_CODE_SUCCESS == code) { - *pPass = *pRes; + memcpy(pAuthRes, pAuth, sizeof(SUserAuthRes)); } return code; } @@ -971,7 +987,7 @@ static SArray* smaIndexesDup(SArray* pSrc) { } for (int32_t i = 0; i < size; ++i) { STableIndexInfo* pIndex = taosArrayGet(pDst, i); - pIndex->expr = taosMemoryStrDup(((STableIndexInfo*)taosArrayGet(pSrc, i))->expr); + pIndex->expr = taosStrdup(((STableIndexInfo*)taosArrayGet(pSrc, i))->expr); if (NULL == pIndex->expr) { taosArrayDestroyEx(pDst, destroySmaIndex); return NULL; diff --git a/source/libs/parser/src/sql.c b/source/libs/parser/src/sql.c index 98368d38063671eb741b2183dd1daea4c601aa4a..2e473455e40abbf768d44c5bec841ee42d40e598 100644 --- a/source/libs/parser/src/sql.c +++ b/source/libs/parser/src/sql.c @@ -104,26 +104,27 @@ #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 461 +#define YYNOCODE 476 #define YYACTIONTYPE unsigned short int #define ParseTOKENTYPE SToken typedef union { int yyinit; ParseTOKENTYPE yy0; - EOrder yy32; - SToken yy77; - int32_t yy248; - int8_t yy287; - ENullOrder yy385; - EJoinType yy560; - SNode* yy600; - SNodeList* yy601; - SAlterOption yy661; - EOperatorType yy666; - int64_t yy717; - EFillMode yy798; - bool yy841; - SDataType yy888; + EFillMode yy46; + SAlterOption yy53; + SToken yy113; + EOperatorType yy156; + bool yy369; + SNodeList* yy432; + SNode* yy448; + int8_t yy551; + ENullOrder yy585; + EJoinType yy596; + EOrder yy666; + SDataType yy728; + STokenPair yy777; + int32_t yy788; + int64_t yy837; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -139,17 +140,18 @@ typedef union { #define ParseCTX_FETCH #define ParseCTX_STORE #define YYFALLBACK 1 -#define YYNSTATE 716 -#define YYNRULE 545 -#define YYNTOKEN 324 -#define YY_MAX_SHIFT 715 -#define YY_MIN_SHIFTREDUCE 1063 -#define YY_MAX_SHIFTREDUCE 1607 -#define YY_ERROR_ACTION 1608 -#define YY_ACCEPT_ACTION 1609 -#define YY_NO_ACTION 1610 -#define YY_MIN_REDUCE 1611 -#define YY_MAX_REDUCE 2155 +#define YYNSTATE 762 +#define YYNRULE 583 +#define YYNRULE_WITH_ACTION 583 +#define YYNTOKEN 330 +#define YY_MAX_SHIFT 761 +#define YY_MIN_SHIFTREDUCE 1136 +#define YY_MAX_SHIFTREDUCE 1718 +#define YY_ERROR_ACTION 1719 +#define YY_ACCEPT_ACTION 1720 +#define YY_NO_ACTION 1721 +#define YY_MIN_REDUCE 1722 +#define YY_MAX_REDUCE 2304 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -216,744 +218,823 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (2733) +#define YY_ACTTAB_COUNT (2904) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 463, 370, 464, 1647, 1810, 1812, 404, 1969, 1755, 33, - /* 10 */ 277, 170, 43, 41, 1536, 1634, 1753, 571, 168, 1951, - /* 20 */ 365, 2126, 1386, 1955, 1804, 42, 40, 39, 38, 37, - /* 30 */ 1969, 605, 1609, 1466, 1951, 1384, 570, 174, 1987, 335, - /* 40 */ 1864, 2127, 572, 1811, 1812, 52, 622, 591, 550, 1947, - /* 50 */ 1953, 1937, 2126, 621, 11, 10, 1411, 589, 1461, 1937, - /* 60 */ 615, 1987, 1764, 16, 1947, 1953, 347, 2132, 174, 586, - /* 70 */ 1392, 1412, 2127, 572, 1937, 615, 621, 462, 1968, 604, - /* 80 */ 467, 1653, 2003, 43, 41, 161, 1970, 625, 1972, 1973, - /* 90 */ 620, 365, 615, 1386, 479, 12, 1873, 380, 604, 550, - /* 100 */ 605, 1968, 159, 2126, 1466, 2003, 1384, 1718, 101, 1970, - /* 110 */ 625, 1972, 1973, 620, 124, 615, 260, 712, 2132, 174, - /* 120 */ 171, 502, 2056, 2127, 572, 229, 359, 2052, 1794, 1461, - /* 130 */ 604, 1764, 1468, 1469, 16, 97, 605, 573, 2147, 550, - /* 140 */ 176, 1392, 583, 2126, 472, 94, 464, 1647, 2082, 1509, - /* 150 */ 124, 157, 1182, 59, 46, 86, 297, 507, 2132, 174, - /* 160 */ 592, 1442, 1451, 2127, 572, 471, 12, 1764, 467, 1653, - /* 170 */ 295, 67, 356, 132, 66, 1877, 2071, 517, 516, 515, - /* 180 */ 1387, 1680, 1385, 1265, 1266, 129, 511, 1184, 712, 1956, - /* 190 */ 510, 357, 194, 459, 457, 509, 514, 1318, 1319, 156, - /* 200 */ 1951, 508, 2068, 1468, 1469, 46, 1390, 1391, 1766, 1441, - /* 210 */ 1444, 1445, 1446, 1447, 1448, 1449, 1450, 617, 613, 1459, - /* 220 */ 1460, 1462, 1463, 1464, 1465, 1467, 1470, 2, 59, 605, - /* 230 */ 1947, 1953, 1442, 1451, 257, 2064, 582, 590, 125, 581, - /* 240 */ 1413, 615, 2126, 179, 469, 1411, 517, 516, 515, 168, - /* 250 */ 465, 1387, 227, 1385, 129, 511, 226, 570, 174, 510, - /* 260 */ 1764, 50, 2127, 572, 509, 514, 549, 100, 36, 35, - /* 270 */ 508, 1865, 42, 40, 39, 38, 37, 1390, 1391, 378, - /* 280 */ 1441, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 617, 613, - /* 290 */ 1459, 1460, 1462, 1463, 1464, 1465, 1467, 1470, 2, 522, - /* 300 */ 9, 43, 41, 177, 177, 75, 74, 407, 92, 365, - /* 310 */ 181, 1386, 83, 323, 532, 1987, 345, 98, 533, 1969, - /* 320 */ 59, 550, 1466, 565, 1384, 2126, 1817, 145, 225, 319, - /* 330 */ 1757, 133, 395, 358, 393, 389, 385, 382, 379, 1756, - /* 340 */ 2132, 174, 1815, 525, 1955, 2127, 572, 1461, 519, 368, - /* 350 */ 1987, 63, 16, 224, 371, 1951, 1574, 156, 622, 1392, - /* 360 */ 2131, 481, 156, 1937, 564, 621, 1766, 39, 38, 37, - /* 370 */ 591, 1766, 43, 41, 1471, 566, 59, 1413, 177, 51, - /* 380 */ 365, 1969, 1386, 259, 12, 1947, 1953, 348, 59, 65, - /* 390 */ 1968, 81, 64, 1466, 2003, 1384, 615, 101, 1970, 625, - /* 400 */ 1972, 1973, 620, 9, 615, 128, 712, 135, 1497, 142, - /* 410 */ 2027, 2056, 1987, 1742, 1759, 359, 2052, 600, 1461, 1873, - /* 420 */ 622, 1468, 1469, 268, 269, 1937, 1096, 621, 267, 1740, - /* 430 */ 1392, 1222, 647, 646, 645, 1226, 644, 1228, 1229, 643, - /* 440 */ 1231, 640, 59, 1237, 637, 1239, 1240, 634, 631, 650, - /* 450 */ 1442, 1451, 1968, 1597, 1412, 44, 2003, 1611, 186, 102, - /* 460 */ 1970, 625, 1972, 1973, 620, 1098, 615, 1101, 1102, 1387, - /* 470 */ 177, 1385, 403, 2056, 402, 481, 1411, 712, 2053, 410, - /* 480 */ 30, 123, 122, 121, 120, 119, 118, 117, 116, 115, - /* 490 */ 1502, 659, 1468, 1469, 78, 1390, 1391, 77, 1441, 1444, - /* 500 */ 1445, 1446, 1447, 1448, 1449, 1450, 617, 613, 1459, 1460, - /* 510 */ 1462, 1463, 1464, 1465, 1467, 1470, 2, 513, 512, 321, - /* 520 */ 259, 1442, 1451, 1612, 114, 605, 177, 113, 112, 111, - /* 530 */ 110, 109, 108, 107, 106, 105, 81, 659, 177, 408, - /* 540 */ 1387, 158, 1385, 1623, 114, 1410, 1633, 113, 112, 111, - /* 550 */ 110, 109, 108, 107, 106, 105, 1764, 36, 35, 1760, - /* 560 */ 1969, 42, 40, 39, 38, 37, 1390, 1391, 47, 1441, - /* 570 */ 1444, 1445, 1446, 1447, 1448, 1449, 1450, 617, 613, 1459, - /* 580 */ 1460, 1462, 1463, 1464, 1465, 1467, 1470, 2, 43, 41, - /* 590 */ 1937, 1987, 177, 25, 411, 446, 365, 592, 1386, 586, - /* 600 */ 340, 1115, 1392, 1114, 1937, 561, 621, 412, 9, 1466, - /* 610 */ 7, 1384, 1878, 1817, 1817, 607, 211, 2028, 36, 35, - /* 620 */ 369, 332, 42, 40, 39, 38, 37, 6, 1632, 1815, - /* 630 */ 1815, 1968, 1116, 1955, 1461, 2003, 531, 583, 101, 1970, - /* 640 */ 625, 1972, 1973, 620, 1951, 615, 1392, 1563, 605, 529, - /* 650 */ 171, 527, 2056, 190, 189, 583, 359, 2052, 2071, 43, - /* 660 */ 41, 341, 409, 339, 338, 671, 504, 365, 132, 1386, - /* 670 */ 506, 44, 1937, 328, 1947, 1953, 360, 1749, 2083, 1764, - /* 680 */ 1466, 399, 1384, 1414, 2067, 615, 132, 571, 1540, 567, - /* 690 */ 562, 2126, 505, 712, 1411, 558, 557, 1561, 1562, 1564, - /* 700 */ 1565, 1566, 545, 401, 397, 1461, 570, 174, 1468, 1469, - /* 710 */ 1631, 2127, 572, 228, 1495, 2131, 1630, 1392, 177, 2126, - /* 720 */ 36, 35, 605, 1751, 42, 40, 39, 38, 37, 173, - /* 730 */ 2064, 2065, 1414, 130, 2069, 2130, 418, 1442, 1451, 2127, - /* 740 */ 2129, 2131, 12, 2071, 1476, 2126, 585, 172, 2064, 2065, - /* 750 */ 1411, 130, 2069, 1764, 1937, 1747, 1387, 609, 1385, 2028, - /* 760 */ 1937, 2130, 506, 1629, 712, 2127, 2128, 36, 35, 2066, - /* 770 */ 1496, 42, 40, 39, 38, 37, 1361, 1362, 134, 1468, - /* 780 */ 1469, 2027, 1390, 1391, 505, 1441, 1444, 1445, 1446, 1447, - /* 790 */ 1448, 1449, 1450, 617, 613, 1459, 1460, 1462, 1463, 1464, - /* 800 */ 1465, 1467, 1470, 2, 320, 2130, 1409, 1937, 1442, 1451, - /* 810 */ 1115, 232, 1114, 440, 683, 681, 453, 36, 35, 452, - /* 820 */ 1860, 42, 40, 39, 38, 37, 183, 1387, 1677, 1385, - /* 830 */ 651, 182, 1529, 1808, 424, 1443, 454, 1628, 1533, 426, - /* 840 */ 1627, 1116, 32, 363, 1490, 1491, 1492, 1493, 1494, 1498, - /* 850 */ 1499, 1500, 1501, 1390, 1391, 1552, 1441, 1444, 1445, 1446, - /* 860 */ 1447, 1448, 1449, 1450, 617, 613, 1459, 1460, 1462, 1463, - /* 870 */ 1464, 1465, 1467, 1470, 2, 237, 29, 1626, 616, 1625, - /* 880 */ 336, 1937, 36, 35, 1937, 649, 42, 40, 39, 38, - /* 890 */ 37, 1443, 414, 689, 688, 687, 686, 375, 1622, 685, - /* 900 */ 684, 136, 679, 678, 677, 676, 675, 674, 673, 149, - /* 910 */ 669, 668, 667, 374, 373, 664, 663, 662, 661, 660, - /* 920 */ 1621, 1937, 450, 1937, 1969, 445, 444, 443, 442, 439, - /* 930 */ 438, 437, 436, 435, 431, 430, 429, 428, 337, 421, - /* 940 */ 420, 419, 1937, 416, 415, 334, 1620, 1969, 1619, 1860, - /* 950 */ 1860, 291, 362, 361, 1794, 1987, 1618, 605, 605, 1414, - /* 960 */ 184, 188, 1400, 622, 1937, 605, 605, 1617, 1937, 1741, - /* 970 */ 621, 432, 433, 1466, 156, 1393, 1411, 583, 1987, 372, - /* 980 */ 480, 1604, 672, 1767, 1734, 1817, 622, 1624, 1764, 1764, - /* 990 */ 1937, 1937, 1937, 621, 377, 1968, 1764, 1764, 1461, 2003, - /* 1000 */ 1937, 1816, 101, 1970, 625, 1972, 1973, 620, 132, 615, - /* 1010 */ 1392, 1937, 1101, 1102, 2146, 1616, 2056, 1719, 1968, 1615, - /* 1020 */ 359, 2052, 2003, 1847, 1614, 101, 1970, 625, 1972, 1973, - /* 1030 */ 620, 2090, 615, 1969, 575, 31, 550, 2146, 2096, 2056, - /* 1040 */ 2126, 36, 35, 359, 2052, 42, 40, 39, 38, 37, - /* 1050 */ 655, 2076, 1529, 1808, 2120, 2132, 174, 611, 1924, 1937, - /* 1060 */ 2127, 572, 656, 1937, 1987, 1808, 574, 212, 1937, 175, - /* 1070 */ 2064, 2065, 622, 130, 2069, 210, 657, 1937, 1603, 621, - /* 1080 */ 1532, 1667, 163, 1660, 48, 138, 3, 126, 498, 494, - /* 1090 */ 490, 486, 209, 68, 254, 147, 146, 654, 653, 652, - /* 1100 */ 144, 578, 236, 518, 1968, 520, 387, 535, 2003, 534, - /* 1110 */ 1969, 101, 1970, 625, 1972, 1973, 620, 1443, 615, 605, - /* 1120 */ 1401, 217, 1396, 2146, 215, 2056, 1606, 1607, 82, 359, - /* 1130 */ 2052, 207, 1395, 1761, 1969, 665, 219, 235, 1386, 218, - /* 1140 */ 2075, 1987, 61, 76, 61, 241, 1404, 1406, 657, 622, - /* 1150 */ 1764, 1384, 605, 1658, 1937, 1394, 621, 1163, 613, 1459, - /* 1160 */ 1460, 1462, 1463, 1464, 1465, 1987, 140, 147, 146, 654, - /* 1170 */ 653, 652, 144, 622, 427, 523, 84, 612, 1937, 1969, - /* 1180 */ 621, 1968, 559, 1764, 221, 2003, 1392, 220, 101, 1970, - /* 1190 */ 625, 1972, 1973, 620, 1560, 615, 1559, 243, 206, 200, - /* 1200 */ 2031, 205, 2056, 45, 477, 1968, 359, 2052, 248, 2003, - /* 1210 */ 1987, 1739, 101, 1970, 625, 1972, 1973, 620, 622, 615, - /* 1220 */ 198, 11, 10, 1937, 2029, 621, 2056, 1988, 376, 265, - /* 1230 */ 359, 2052, 605, 712, 1969, 36, 35, 605, 1869, 42, - /* 1240 */ 40, 39, 38, 37, 1648, 141, 546, 143, 145, 61, - /* 1250 */ 1968, 587, 605, 605, 2003, 1331, 576, 101, 1970, 625, - /* 1260 */ 1972, 1973, 620, 1764, 615, 1987, 272, 602, 1764, 608, - /* 1270 */ 1805, 2056, 605, 622, 223, 359, 2052, 222, 1937, 1398, - /* 1280 */ 621, 270, 538, 1764, 1764, 2086, 603, 36, 35, 584, - /* 1290 */ 1969, 42, 40, 39, 38, 37, 1387, 597, 1385, 274, - /* 1300 */ 1215, 1503, 1397, 1764, 45, 1968, 1958, 45, 629, 2003, - /* 1310 */ 143, 145, 102, 1970, 625, 1972, 1973, 620, 657, 615, - /* 1320 */ 1487, 1987, 1390, 1391, 550, 579, 2056, 1654, 2126, 622, - /* 1330 */ 2055, 2052, 127, 605, 1937, 1969, 621, 147, 146, 654, - /* 1340 */ 653, 652, 144, 2132, 174, 666, 143, 278, 2127, 572, - /* 1350 */ 1144, 256, 253, 4, 1960, 1, 1452, 381, 1969, 290, - /* 1360 */ 1243, 1968, 1247, 1254, 1764, 2003, 1987, 1161, 102, 1970, - /* 1370 */ 625, 1972, 1973, 620, 622, 615, 707, 386, 333, 1937, - /* 1380 */ 1348, 621, 2056, 285, 1252, 1145, 610, 2052, 187, 1987, - /* 1390 */ 155, 413, 1414, 1870, 417, 448, 422, 619, 148, 1409, - /* 1400 */ 434, 1862, 1937, 441, 621, 447, 623, 455, 449, 191, - /* 1410 */ 2003, 456, 458, 102, 1970, 625, 1972, 1973, 620, 460, - /* 1420 */ 615, 1415, 461, 470, 1417, 473, 474, 2056, 197, 1968, - /* 1430 */ 199, 327, 2052, 2003, 1416, 475, 313, 1970, 625, 1972, - /* 1440 */ 1973, 620, 618, 615, 606, 2021, 1969, 1418, 202, 476, - /* 1450 */ 204, 478, 79, 80, 208, 1118, 482, 501, 539, 1915, - /* 1460 */ 503, 499, 1969, 500, 537, 322, 1754, 104, 214, 540, - /* 1470 */ 286, 2087, 541, 230, 1912, 1750, 216, 1987, 544, 233, - /* 1480 */ 547, 560, 150, 595, 151, 622, 2102, 1752, 1748, 152, - /* 1490 */ 1937, 153, 621, 1987, 5, 2101, 2078, 569, 1911, 247, - /* 1500 */ 555, 622, 553, 164, 249, 552, 1937, 251, 621, 250, - /* 1510 */ 554, 350, 556, 349, 563, 2149, 580, 1968, 1969, 2097, - /* 1520 */ 577, 2003, 1529, 239, 160, 1970, 625, 1972, 1973, 620, - /* 1530 */ 242, 615, 131, 1968, 2125, 255, 1413, 2003, 261, 1419, - /* 1540 */ 160, 1970, 625, 1972, 1973, 620, 1969, 615, 252, 1987, - /* 1550 */ 2072, 588, 1874, 353, 593, 287, 288, 622, 594, 1883, - /* 1560 */ 1882, 1881, 1937, 355, 621, 551, 2093, 598, 89, 599, - /* 1570 */ 58, 91, 289, 1765, 2037, 93, 627, 1987, 1735, 1809, - /* 1580 */ 292, 281, 2094, 709, 708, 622, 49, 711, 301, 1968, - /* 1590 */ 1937, 316, 621, 2003, 294, 315, 307, 1970, 625, 1972, - /* 1600 */ 1973, 620, 324, 615, 305, 296, 1931, 1930, 1969, 325, - /* 1610 */ 72, 1929, 1928, 73, 1925, 383, 384, 1968, 1378, 1379, - /* 1620 */ 715, 2003, 180, 1923, 161, 1970, 625, 1972, 1973, 620, - /* 1630 */ 388, 615, 390, 391, 284, 392, 1922, 394, 1921, 1987, - /* 1640 */ 568, 1920, 398, 396, 354, 1919, 1351, 622, 400, 167, - /* 1650 */ 1350, 1894, 1937, 1893, 621, 705, 701, 697, 693, 282, - /* 1660 */ 405, 1892, 406, 1969, 1309, 1855, 1854, 1852, 137, 1851, - /* 1670 */ 1850, 1853, 1849, 1848, 1846, 1845, 1844, 2148, 1891, 1968, - /* 1680 */ 185, 423, 1843, 2003, 425, 1842, 314, 1970, 625, 1972, - /* 1690 */ 1973, 620, 1841, 615, 1987, 99, 1840, 1839, 275, 1838, - /* 1700 */ 1837, 1836, 619, 1835, 1834, 1833, 1832, 1937, 1831, 621, - /* 1710 */ 1830, 1829, 1828, 1827, 1826, 1825, 1824, 1823, 1822, 139, - /* 1720 */ 1311, 1821, 1820, 451, 1819, 1969, 1190, 1682, 1681, 1679, - /* 1730 */ 1643, 601, 1818, 70, 1968, 195, 1957, 192, 2003, 193, - /* 1740 */ 1642, 313, 1970, 625, 1972, 1973, 620, 1104, 615, 466, - /* 1750 */ 2022, 169, 1103, 1907, 1901, 1969, 1987, 1890, 1889, 1872, - /* 1760 */ 196, 364, 71, 203, 622, 1743, 468, 1678, 262, 1937, - /* 1770 */ 201, 621, 1676, 1137, 483, 485, 1674, 487, 1672, 491, - /* 1780 */ 489, 1670, 484, 488, 1657, 1355, 1987, 231, 493, 497, - /* 1790 */ 495, 366, 1656, 492, 622, 496, 1968, 1639, 1745, 1937, - /* 1800 */ 2003, 621, 1258, 314, 1970, 625, 1972, 1973, 620, 1259, - /* 1810 */ 615, 1744, 1181, 1969, 1180, 680, 1173, 1179, 1178, 682, - /* 1820 */ 1175, 1174, 1172, 1668, 342, 1661, 1968, 213, 343, 1969, - /* 1830 */ 2003, 1659, 344, 314, 1970, 625, 1972, 1973, 620, 521, - /* 1840 */ 615, 60, 524, 1638, 1987, 1637, 1636, 526, 528, 530, - /* 1850 */ 1366, 1368, 622, 103, 1365, 1906, 1370, 1937, 24, 621, - /* 1860 */ 1987, 1357, 1900, 154, 542, 1888, 1886, 2131, 622, 1576, - /* 1870 */ 14, 18, 17, 1937, 1969, 621, 56, 62, 57, 245, - /* 1880 */ 15, 28, 19, 26, 536, 238, 246, 240, 2003, 1558, - /* 1890 */ 1969, 309, 1970, 625, 1972, 1973, 620, 1551, 615, 162, - /* 1900 */ 1968, 1958, 1591, 244, 2003, 1987, 53, 298, 1970, 625, - /* 1910 */ 1972, 1973, 620, 622, 615, 543, 234, 548, 1937, 27, - /* 1920 */ 621, 1987, 1590, 351, 346, 1596, 258, 1595, 1594, 622, - /* 1930 */ 352, 85, 165, 54, 1937, 1887, 621, 1597, 55, 1885, - /* 1940 */ 1526, 1884, 1871, 1525, 263, 1968, 20, 88, 264, 2003, - /* 1950 */ 276, 266, 299, 1970, 625, 1972, 1973, 620, 271, 615, - /* 1960 */ 21, 1968, 596, 273, 1556, 2003, 87, 1969, 300, 1970, - /* 1970 */ 625, 1972, 1973, 620, 94, 615, 90, 10, 1402, 2006, - /* 1980 */ 166, 178, 1456, 1434, 614, 628, 1454, 367, 626, 632, - /* 1990 */ 1478, 1969, 1453, 34, 8, 13, 1477, 22, 1987, 635, - /* 2000 */ 1426, 1488, 23, 1221, 638, 1244, 622, 630, 624, 1241, - /* 2010 */ 633, 1937, 636, 621, 1238, 1232, 639, 641, 1230, 642, - /* 2020 */ 1236, 648, 1987, 95, 1235, 1234, 96, 279, 1253, 1233, - /* 2030 */ 622, 69, 1249, 1169, 1135, 1937, 658, 621, 1968, 1168, - /* 2040 */ 1167, 1166, 2003, 1165, 1164, 306, 1970, 625, 1972, 1973, - /* 2050 */ 620, 1162, 615, 1969, 1160, 1159, 1158, 1188, 670, 280, - /* 2060 */ 1156, 1155, 1968, 1154, 1153, 1152, 2003, 1151, 1150, 310, - /* 2070 */ 1970, 625, 1972, 1973, 620, 1183, 615, 1185, 1147, 1146, - /* 2080 */ 1143, 1142, 1141, 1969, 1987, 1140, 1675, 690, 692, 691, - /* 2090 */ 1673, 694, 622, 1671, 696, 695, 698, 1937, 700, 621, - /* 2100 */ 1669, 699, 702, 704, 1655, 703, 706, 1093, 1635, 283, - /* 2110 */ 710, 1610, 714, 1388, 1987, 1610, 293, 713, 1610, 1610, - /* 2120 */ 1610, 1610, 622, 1610, 1968, 1610, 1610, 1937, 2003, 621, - /* 2130 */ 1610, 302, 1970, 625, 1972, 1973, 620, 1610, 615, 1610, - /* 2140 */ 1610, 1969, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2150 */ 1610, 1610, 1610, 1610, 1968, 1610, 1610, 1969, 2003, 1610, - /* 2160 */ 1610, 311, 1970, 625, 1972, 1973, 620, 1610, 615, 1610, - /* 2170 */ 1610, 1610, 1987, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2180 */ 622, 1610, 1610, 1610, 1610, 1937, 1610, 621, 1987, 1610, - /* 2190 */ 1610, 1610, 1610, 1610, 1610, 1610, 622, 1610, 1610, 1610, - /* 2200 */ 1610, 1937, 1969, 621, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2210 */ 1610, 1610, 1968, 1610, 1610, 1610, 2003, 1610, 1969, 303, - /* 2220 */ 1970, 625, 1972, 1973, 620, 1610, 615, 1610, 1968, 1610, - /* 2230 */ 1610, 1610, 2003, 1987, 1610, 312, 1970, 625, 1972, 1973, - /* 2240 */ 620, 622, 615, 1610, 1610, 1610, 1937, 1610, 621, 1987, - /* 2250 */ 1610, 1610, 1610, 1610, 1610, 1610, 1610, 622, 1610, 1610, - /* 2260 */ 1610, 1610, 1937, 1610, 621, 1610, 1610, 1610, 1610, 1610, - /* 2270 */ 1610, 1610, 1610, 1968, 1610, 1610, 1610, 2003, 1610, 1610, - /* 2280 */ 304, 1970, 625, 1972, 1973, 620, 1610, 615, 1610, 1968, - /* 2290 */ 1610, 1610, 1610, 2003, 1610, 1969, 317, 1970, 625, 1972, - /* 2300 */ 1973, 620, 1610, 615, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2310 */ 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1969, - /* 2320 */ 1610, 1610, 1610, 1610, 1610, 1610, 1987, 1610, 1610, 1610, - /* 2330 */ 1610, 1610, 1610, 1610, 622, 1610, 1610, 1610, 1610, 1937, - /* 2340 */ 1610, 621, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2350 */ 1987, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 622, 1610, - /* 2360 */ 1610, 1610, 1610, 1937, 1610, 621, 1968, 1610, 1610, 1610, - /* 2370 */ 2003, 1610, 1610, 318, 1970, 625, 1972, 1973, 620, 1610, - /* 2380 */ 615, 1969, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2390 */ 1968, 1610, 1610, 1610, 2003, 1610, 1610, 1981, 1970, 625, - /* 2400 */ 1972, 1973, 620, 1610, 615, 1610, 1610, 1610, 1610, 1610, - /* 2410 */ 1610, 1969, 1987, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2420 */ 622, 1610, 1610, 1610, 1610, 1937, 1610, 621, 1610, 1610, - /* 2430 */ 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2440 */ 1610, 1610, 1987, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2450 */ 622, 1610, 1968, 1610, 1610, 1937, 2003, 621, 1610, 1980, - /* 2460 */ 1970, 625, 1972, 1973, 620, 1610, 615, 1610, 1610, 1969, - /* 2470 */ 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2480 */ 1610, 1610, 1968, 1610, 1610, 1969, 2003, 1610, 1610, 1979, - /* 2490 */ 1970, 625, 1972, 1973, 620, 1610, 615, 1610, 1610, 1610, - /* 2500 */ 1987, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 622, 1610, - /* 2510 */ 1610, 1610, 1610, 1937, 1610, 621, 1987, 1610, 1610, 1610, - /* 2520 */ 1610, 1610, 1610, 1610, 622, 1610, 1610, 1610, 1610, 1937, - /* 2530 */ 1969, 621, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2540 */ 1968, 1610, 1610, 1610, 2003, 1610, 1969, 329, 1970, 625, - /* 2550 */ 1972, 1973, 620, 1610, 615, 1610, 1968, 1610, 1610, 1610, - /* 2560 */ 2003, 1987, 1610, 330, 1970, 625, 1972, 1973, 620, 622, - /* 2570 */ 615, 1610, 1610, 1610, 1937, 1610, 621, 1987, 1610, 1610, - /* 2580 */ 1610, 1610, 1610, 1610, 1610, 622, 1610, 1610, 1610, 1610, - /* 2590 */ 1937, 1610, 621, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2600 */ 1610, 1968, 1610, 1610, 1610, 2003, 1610, 1610, 326, 1970, - /* 2610 */ 625, 1972, 1973, 620, 1610, 615, 1610, 1968, 1610, 1610, - /* 2620 */ 1610, 2003, 1610, 1969, 331, 1970, 625, 1972, 1973, 620, - /* 2630 */ 1610, 615, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, - /* 2640 */ 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1969, 1610, 1610, - /* 2650 */ 1610, 1610, 1610, 1610, 1987, 1610, 1610, 1610, 1610, 1610, - /* 2660 */ 1610, 1610, 622, 1610, 1610, 1610, 1610, 1937, 1610, 621, - /* 2670 */ 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1987, 1610, - /* 2680 */ 1610, 1610, 1610, 1610, 1610, 1610, 622, 1610, 1610, 1610, - /* 2690 */ 1610, 1937, 1610, 621, 623, 1610, 1610, 1610, 2003, 1610, - /* 2700 */ 1610, 309, 1970, 625, 1972, 1973, 620, 1610, 615, 1610, - /* 2710 */ 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1610, 1968, 1610, - /* 2720 */ 1610, 1610, 2003, 1610, 1610, 308, 1970, 625, 1972, 1973, - /* 2730 */ 620, 1610, 615, + /* 0 */ 2116, 2010, 1881, 396, 434, 168, 636, 1734, 433, 1989, + /* 10 */ 672, 162, 46, 44, 1646, 1723, 2008, 642, 374, 1894, + /* 20 */ 393, 506, 1495, 440, 39, 38, 1942, 503, 45, 43, + /* 30 */ 42, 41, 40, 1576, 1791, 1493, 123, 2134, 1520, 122, + /* 40 */ 121, 120, 119, 118, 117, 116, 115, 114, 2279, 2084, + /* 50 */ 593, 671, 593, 2275, 194, 2275, 39, 38, 167, 1571, + /* 60 */ 45, 43, 42, 41, 40, 19, 1833, 340, 2281, 186, + /* 70 */ 2281, 186, 1501, 2276, 619, 2276, 619, 45, 43, 42, + /* 80 */ 41, 40, 2115, 501, 654, 2151, 502, 1758, 169, 2117, + /* 90 */ 675, 2119, 2120, 670, 182, 665, 1520, 758, 36, 298, + /* 100 */ 15, 735, 734, 733, 732, 405, 1931, 731, 730, 144, + /* 110 */ 725, 724, 723, 722, 721, 720, 719, 157, 715, 714, + /* 120 */ 713, 404, 403, 710, 709, 708, 175, 174, 594, 2241, + /* 130 */ 509, 654, 1320, 502, 1758, 123, 1578, 1579, 122, 121, + /* 140 */ 120, 119, 118, 117, 116, 115, 114, 1311, 697, 696, + /* 150 */ 695, 1315, 694, 1317, 1318, 693, 690, 179, 1326, 687, + /* 160 */ 1328, 1329, 684, 681, 49, 640, 1551, 1561, 654, 2219, + /* 170 */ 655, 1892, 1577, 1580, 1720, 39, 38, 360, 1993, 45, + /* 180 */ 43, 42, 41, 40, 1409, 1410, 1496, 1523, 1494, 133, + /* 190 */ 655, 1892, 387, 62, 1715, 2216, 539, 39, 38, 280, + /* 200 */ 165, 45, 43, 42, 41, 40, 39, 38, 1894, 191, + /* 210 */ 45, 43, 42, 41, 40, 1499, 1500, 1868, 1550, 1553, + /* 220 */ 1554, 1555, 1556, 1557, 1558, 1559, 1560, 667, 663, 1569, + /* 230 */ 1570, 1572, 1573, 1574, 1575, 2, 46, 44, 1722, 179, + /* 240 */ 62, 343, 93, 1518, 393, 408, 1495, 62, 49, 407, + /* 250 */ 471, 2116, 2280, 485, 352, 2275, 484, 1576, 1989, 1493, + /* 260 */ 1994, 672, 132, 131, 130, 129, 128, 127, 126, 125, + /* 270 */ 124, 2279, 454, 1522, 486, 2276, 2278, 456, 432, 396, + /* 280 */ 431, 707, 2280, 1571, 1275, 2275, 211, 165, 2134, 19, + /* 290 */ 504, 593, 1765, 1714, 2275, 1894, 1501, 1274, 1605, 1685, + /* 300 */ 2084, 2279, 671, 196, 2010, 2276, 2277, 430, 618, 2281, + /* 310 */ 186, 2275, 518, 2116, 2276, 619, 386, 621, 66, 2007, + /* 320 */ 642, 758, 361, 672, 15, 1767, 617, 186, 1264, 655, + /* 330 */ 1892, 2276, 619, 2115, 444, 257, 2151, 655, 1892, 110, + /* 340 */ 2117, 675, 2119, 2120, 670, 189, 665, 1521, 133, 143, + /* 350 */ 2134, 150, 2175, 2204, 1606, 544, 55, 389, 2200, 487, + /* 360 */ 1578, 1579, 2084, 482, 671, 1266, 476, 475, 474, 473, + /* 370 */ 470, 469, 468, 467, 466, 462, 461, 460, 459, 342, + /* 380 */ 451, 450, 449, 613, 446, 445, 359, 1650, 1520, 1521, + /* 390 */ 1551, 1561, 189, 1520, 545, 2115, 1577, 1580, 2151, 189, + /* 400 */ 189, 110, 2117, 675, 2119, 2120, 670, 707, 665, 1191, + /* 410 */ 1496, 1190, 1494, 2295, 62, 2204, 1262, 630, 140, 389, + /* 420 */ 2200, 279, 50, 608, 641, 630, 140, 1745, 35, 391, + /* 430 */ 1600, 1601, 1602, 1603, 1604, 1608, 1609, 1610, 1611, 1499, + /* 440 */ 1500, 1192, 1550, 1553, 1554, 1555, 1556, 1557, 1558, 1559, + /* 450 */ 1560, 667, 663, 1569, 1570, 1572, 1573, 1574, 1575, 2, + /* 460 */ 12, 46, 44, 1354, 1355, 1495, 402, 401, 62, 393, + /* 470 */ 1279, 1495, 557, 556, 555, 516, 2084, 2003, 1493, 547, + /* 480 */ 137, 551, 1576, 1278, 1493, 550, 2280, 2116, 32, 1502, + /* 490 */ 549, 554, 368, 367, 39, 38, 548, 672, 45, 43, + /* 500 */ 42, 41, 40, 1522, 1523, 1426, 1427, 2116, 1571, 614, + /* 510 */ 609, 602, 1674, 699, 19, 1501, 1935, 669, 185, 2212, + /* 520 */ 2213, 1501, 138, 2217, 2134, 632, 184, 2212, 2213, 398, + /* 530 */ 138, 2217, 1937, 1939, 2051, 1191, 2084, 1190, 671, 1552, + /* 540 */ 758, 1425, 1428, 1519, 2134, 489, 758, 39, 38, 15, + /* 550 */ 228, 45, 43, 42, 41, 40, 2084, 153, 671, 605, + /* 560 */ 604, 1672, 1673, 1675, 1676, 1677, 189, 1192, 166, 2115, + /* 570 */ 1744, 580, 2151, 318, 189, 170, 2117, 675, 2119, 2120, + /* 580 */ 670, 246, 665, 28, 1708, 1578, 1579, 316, 73, 2115, + /* 590 */ 12, 72, 2151, 2094, 562, 334, 2117, 675, 2119, 2120, + /* 600 */ 670, 668, 665, 656, 2169, 655, 1892, 2102, 107, 572, + /* 610 */ 209, 497, 495, 492, 54, 1551, 1561, 2098, 612, 2084, + /* 620 */ 189, 1577, 1580, 242, 438, 141, 620, 2296, 213, 1496, + /* 630 */ 478, 1494, 504, 1884, 1765, 1496, 1794, 1494, 165, 565, + /* 640 */ 1944, 1944, 1505, 641, 559, 2134, 1895, 358, 373, 241, + /* 650 */ 62, 279, 195, 2100, 376, 1942, 1942, 1501, 1499, 1500, + /* 660 */ 1169, 289, 290, 665, 1499, 1500, 288, 1550, 1553, 1554, + /* 670 */ 1555, 1556, 1557, 1558, 1559, 1560, 667, 663, 1569, 1570, + /* 680 */ 1572, 1573, 1574, 1575, 2, 46, 44, 1581, 109, 70, + /* 690 */ 202, 201, 69, 393, 639, 1495, 2003, 2116, 611, 1171, + /* 700 */ 1974, 1174, 1175, 557, 556, 555, 1576, 633, 1493, 365, + /* 710 */ 547, 137, 551, 477, 641, 698, 550, 618, 655, 1892, + /* 720 */ 2275, 549, 554, 368, 367, 630, 140, 548, 81, 80, + /* 730 */ 437, 1643, 1571, 193, 2134, 617, 186, 439, 1938, 1939, + /* 740 */ 2276, 619, 717, 244, 1944, 1501, 2084, 243, 671, 655, + /* 750 */ 1892, 383, 14, 13, 341, 655, 1892, 423, 1877, 1942, + /* 760 */ 421, 417, 413, 410, 430, 650, 1743, 2003, 448, 1944, + /* 770 */ 758, 106, 2077, 47, 463, 366, 388, 364, 363, 2115, + /* 780 */ 541, 103, 2151, 2116, 1942, 110, 2117, 675, 2119, 2120, + /* 790 */ 670, 1944, 665, 672, 1869, 655, 1892, 183, 397, 2204, + /* 800 */ 101, 543, 189, 389, 2200, 542, 1942, 90, 347, 1578, + /* 810 */ 1579, 372, 87, 573, 464, 2084, 188, 2078, 593, 1735, + /* 820 */ 2134, 2275, 553, 552, 2230, 1885, 277, 2212, 629, 362, + /* 830 */ 134, 628, 2084, 2275, 671, 1742, 2281, 186, 1887, 1551, + /* 840 */ 1561, 2276, 619, 630, 140, 1577, 1580, 245, 617, 186, + /* 850 */ 655, 1892, 1619, 2276, 619, 458, 1586, 2219, 12, 1496, + /* 860 */ 10, 1494, 1520, 593, 457, 2115, 2275, 1741, 2151, 517, + /* 870 */ 1879, 111, 2117, 675, 2119, 2120, 670, 657, 665, 2176, + /* 880 */ 622, 2281, 186, 2215, 2084, 2204, 2276, 619, 1499, 1500, + /* 890 */ 2201, 1550, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, + /* 900 */ 667, 663, 1569, 1570, 1572, 1573, 1574, 1575, 2, 46, + /* 910 */ 44, 659, 1523, 2176, 1468, 1469, 2084, 393, 427, 1495, + /* 920 */ 52, 2116, 3, 705, 155, 154, 702, 701, 700, 152, + /* 930 */ 1576, 633, 1493, 39, 38, 655, 1892, 45, 43, 42, + /* 940 */ 41, 40, 429, 425, 187, 2212, 2213, 2116, 138, 2217, + /* 950 */ 198, 1875, 655, 1892, 1889, 578, 1571, 672, 2134, 2238, + /* 960 */ 705, 155, 154, 702, 701, 700, 152, 399, 1520, 1501, + /* 970 */ 2084, 247, 671, 655, 1892, 165, 42, 41, 40, 2219, + /* 980 */ 1642, 39, 38, 1894, 2134, 45, 43, 42, 41, 40, + /* 990 */ 84, 543, 589, 83, 758, 542, 2084, 47, 671, 655, + /* 1000 */ 1892, 593, 1740, 2115, 2275, 2214, 2151, 2116, 1552, 110, + /* 1010 */ 2117, 675, 2119, 2120, 670, 2067, 665, 672, 634, 2281, + /* 1020 */ 186, 183, 9, 2204, 2276, 619, 1739, 389, 2200, 2115, + /* 1030 */ 1867, 87, 2151, 1578, 1579, 110, 2117, 675, 2119, 2120, + /* 1040 */ 670, 2094, 665, 254, 2134, 1738, 571, 2295, 2231, 2204, + /* 1050 */ 146, 2084, 135, 389, 2200, 1883, 2084, 1888, 671, 569, + /* 1060 */ 256, 567, 1989, 1551, 1561, 2098, 34, 655, 1892, 1577, + /* 1070 */ 1580, 1607, 39, 38, 1662, 2084, 45, 43, 42, 41, + /* 1080 */ 40, 729, 727, 1496, 1896, 1494, 638, 655, 1892, 2115, + /* 1090 */ 655, 1892, 2151, 164, 2084, 169, 2117, 675, 2119, 2120, + /* 1100 */ 670, 2100, 665, 1174, 1175, 312, 293, 200, 1921, 652, + /* 1110 */ 623, 665, 1499, 1500, 1552, 1550, 1553, 1554, 1555, 1556, + /* 1120 */ 1557, 1558, 1559, 1560, 667, 663, 1569, 1570, 1572, 1573, + /* 1130 */ 1574, 1575, 2, 46, 44, 1737, 2242, 2116, 655, 1892, + /* 1140 */ 1736, 393, 1733, 1495, 2094, 33, 1732, 672, 1731, 2251, + /* 1150 */ 655, 1892, 655, 1892, 1576, 1612, 1493, 653, 2102, 705, + /* 1160 */ 155, 154, 702, 701, 700, 152, 1730, 142, 2098, 299, + /* 1170 */ 2175, 400, 2224, 1639, 2134, 1944, 703, 1177, 704, 1935, + /* 1180 */ 1571, 1935, 1729, 1519, 2084, 2094, 2084, 1728, 671, 2084, + /* 1190 */ 1943, 2084, 2094, 1501, 1870, 2084, 625, 2084, 1727, 2102, + /* 1200 */ 1726, 1725, 2070, 251, 2100, 377, 2103, 718, 234, 2098, + /* 1210 */ 1854, 232, 74, 592, 665, 2084, 2098, 236, 758, 2115, + /* 1220 */ 235, 15, 2151, 2116, 422, 110, 2117, 675, 2119, 2120, + /* 1230 */ 670, 2084, 665, 672, 1639, 600, 2084, 2295, 148, 2204, + /* 1240 */ 153, 441, 546, 389, 2200, 2100, 390, 2084, 1781, 2084, + /* 1250 */ 2084, 415, 2100, 238, 442, 665, 237, 1578, 1579, 1774, + /* 1260 */ 2134, 82, 665, 240, 1260, 153, 239, 1772, 711, 575, + /* 1270 */ 558, 574, 2084, 662, 671, 64, 255, 64, 261, 1717, + /* 1280 */ 1718, 560, 14, 13, 666, 2105, 1834, 1551, 1561, 563, + /* 1290 */ 1240, 2244, 274, 1577, 1580, 227, 268, 1463, 606, 1832, + /* 1300 */ 1504, 1503, 712, 1831, 153, 2115, 48, 1496, 2151, 1494, + /* 1310 */ 2135, 110, 2117, 675, 2119, 2120, 670, 286, 665, 91, + /* 1320 */ 71, 151, 1466, 2295, 1238, 2204, 406, 64, 48, 389, + /* 1330 */ 2200, 1998, 1671, 53, 1670, 263, 1499, 1500, 2107, 1550, + /* 1340 */ 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 667, 663, + /* 1350 */ 1569, 1570, 1572, 1573, 1574, 1575, 2, 2116, 402, 401, + /* 1360 */ 1221, 637, 153, 1423, 48, 679, 1768, 672, 1509, 2269, + /* 1370 */ 151, 1764, 153, 1759, 291, 1932, 2234, 647, 295, 1576, + /* 1380 */ 136, 1502, 631, 2116, 1613, 1562, 276, 151, 273, 1, + /* 1390 */ 5, 409, 356, 672, 2134, 2223, 414, 1222, 1446, 306, + /* 1400 */ 199, 443, 1523, 1999, 480, 1571, 2084, 447, 671, 452, + /* 1410 */ 1518, 490, 465, 1991, 479, 472, 753, 491, 1501, 1305, + /* 1420 */ 2134, 311, 1332, 1597, 481, 488, 203, 1336, 626, 1343, + /* 1430 */ 2116, 204, 2084, 493, 671, 494, 206, 1341, 496, 2115, + /* 1440 */ 672, 498, 2151, 661, 156, 110, 2117, 675, 2119, 2120, + /* 1450 */ 670, 2116, 665, 1507, 1506, 1524, 4, 2295, 499, 2204, + /* 1460 */ 507, 672, 1526, 389, 2200, 2115, 500, 2134, 2151, 508, + /* 1470 */ 510, 110, 2117, 675, 2119, 2120, 670, 1521, 665, 2084, + /* 1480 */ 1525, 671, 214, 2295, 511, 2204, 512, 216, 2134, 389, + /* 1490 */ 2200, 1527, 513, 1194, 219, 515, 221, 85, 86, 519, + /* 1500 */ 2084, 536, 671, 225, 538, 537, 112, 346, 540, 1882, + /* 1510 */ 231, 1878, 2115, 2060, 577, 2151, 2057, 2056, 170, 2117, + /* 1520 */ 675, 2119, 2120, 670, 579, 665, 233, 89, 149, 307, + /* 1530 */ 158, 159, 1510, 2115, 1505, 248, 2151, 1880, 1876, 110, + /* 1540 */ 2117, 675, 2119, 2120, 670, 160, 665, 161, 583, 252, + /* 1550 */ 582, 2179, 1453, 2204, 584, 2116, 597, 389, 2200, 607, + /* 1560 */ 587, 1513, 1515, 250, 2250, 672, 590, 645, 259, 588, + /* 1570 */ 2297, 2235, 2245, 603, 663, 1569, 1570, 1572, 1573, 1574, + /* 1580 */ 1575, 262, 2249, 8, 616, 378, 610, 2226, 598, 596, + /* 1590 */ 595, 267, 2134, 379, 139, 272, 1639, 2298, 627, 1522, + /* 1600 */ 624, 2220, 382, 635, 2084, 269, 671, 1528, 2004, 308, + /* 1610 */ 643, 281, 96, 309, 644, 648, 98, 2018, 2017, 2016, + /* 1620 */ 649, 2116, 173, 385, 270, 1893, 271, 100, 61, 102, + /* 1630 */ 2185, 672, 1936, 313, 1855, 310, 754, 2115, 302, 755, + /* 1640 */ 2151, 757, 348, 110, 2117, 675, 2119, 2120, 670, 2116, + /* 1650 */ 665, 2274, 677, 275, 337, 2177, 51, 2204, 2134, 672, + /* 1660 */ 322, 389, 2200, 336, 326, 317, 2076, 2075, 349, 2074, + /* 1670 */ 2084, 315, 671, 78, 2071, 411, 412, 1486, 1487, 192, + /* 1680 */ 416, 2116, 2069, 418, 419, 420, 2134, 2068, 357, 2066, + /* 1690 */ 424, 672, 426, 2064, 428, 79, 1449, 1448, 2084, 2065, + /* 1700 */ 671, 2030, 2029, 2115, 2028, 435, 2151, 436, 2027, 110, + /* 1710 */ 2117, 675, 2119, 2120, 670, 2026, 665, 1982, 2134, 1400, + /* 1720 */ 1981, 658, 1979, 2204, 1978, 145, 1977, 389, 2200, 1980, + /* 1730 */ 2084, 2115, 671, 1976, 2151, 1975, 1973, 111, 2117, 675, + /* 1740 */ 2119, 2120, 670, 1972, 665, 1971, 197, 453, 1970, 455, + /* 1750 */ 1984, 2204, 2116, 1969, 1968, 2203, 2200, 483, 147, 1954, + /* 1760 */ 1953, 1952, 672, 2115, 1967, 1966, 2151, 1965, 1964, 111, + /* 1770 */ 2117, 675, 2119, 2120, 670, 1963, 665, 1962, 1961, 1960, + /* 1780 */ 2116, 1959, 1958, 2204, 1957, 1956, 1955, 660, 2200, 2134, + /* 1790 */ 672, 1983, 1951, 1950, 1402, 1949, 1948, 1947, 1946, 2116, + /* 1800 */ 1945, 2084, 1276, 671, 344, 1280, 345, 1797, 205, 669, + /* 1810 */ 1796, 1272, 1795, 1793, 207, 2116, 1754, 2134, 180, 1176, + /* 1820 */ 2104, 208, 1753, 2047, 2037, 672, 76, 2025, 77, 2084, + /* 1830 */ 210, 671, 2024, 218, 673, 220, 2134, 2151, 2002, 1871, + /* 1840 */ 111, 2117, 675, 2119, 2120, 670, 181, 665, 2084, 505, + /* 1850 */ 671, 212, 2134, 1792, 2204, 1790, 1214, 384, 351, 2200, + /* 1860 */ 520, 1788, 2115, 521, 2084, 2151, 671, 522, 328, 2117, + /* 1870 */ 675, 2119, 2120, 670, 526, 665, 2116, 524, 525, 1786, + /* 1880 */ 528, 2115, 529, 530, 2151, 1784, 672, 334, 2117, 675, + /* 1890 */ 2119, 2120, 670, 532, 665, 533, 2170, 2115, 581, 2116, + /* 1900 */ 2151, 534, 1771, 335, 2117, 675, 2119, 2120, 670, 672, + /* 1910 */ 665, 615, 1770, 2134, 1750, 1873, 761, 63, 392, 1348, + /* 1920 */ 1347, 1872, 230, 1263, 1261, 2084, 1259, 671, 1258, 1257, + /* 1930 */ 305, 1256, 1250, 1782, 1255, 369, 2134, 561, 1252, 726, + /* 1940 */ 1251, 394, 1249, 1775, 728, 370, 178, 1773, 2084, 371, + /* 1950 */ 671, 564, 751, 747, 743, 739, 303, 566, 2115, 1749, + /* 1960 */ 1748, 2151, 1747, 568, 335, 2117, 675, 2119, 2120, 670, + /* 1970 */ 570, 665, 113, 1473, 1475, 1472, 1477, 27, 2046, 1455, + /* 1980 */ 67, 2115, 2036, 1457, 2151, 56, 585, 335, 2117, 675, + /* 1990 */ 2119, 2120, 670, 2116, 665, 163, 108, 2023, 586, 296, + /* 2000 */ 2021, 253, 1459, 672, 375, 2280, 29, 20, 17, 591, + /* 2010 */ 1687, 258, 59, 6, 7, 599, 601, 60, 265, 260, + /* 2020 */ 1669, 31, 266, 2105, 171, 2116, 264, 21, 65, 30, + /* 2030 */ 2134, 651, 1661, 1707, 92, 672, 1708, 22, 1702, 278, + /* 2040 */ 1701, 380, 2084, 2116, 671, 1706, 1705, 381, 176, 2022, + /* 2050 */ 1636, 1635, 58, 672, 2020, 2019, 2001, 18, 94, 95, + /* 2060 */ 284, 646, 2134, 2000, 103, 97, 283, 23, 57, 297, + /* 2070 */ 285, 282, 1667, 294, 2084, 576, 671, 24, 2151, 287, + /* 2080 */ 2134, 330, 2117, 675, 2119, 2120, 670, 292, 665, 68, + /* 2090 */ 2116, 249, 2084, 11, 671, 99, 1588, 1587, 13, 1511, + /* 2100 */ 672, 1543, 1598, 678, 177, 190, 395, 2115, 1566, 2154, + /* 2110 */ 2151, 682, 1325, 319, 2117, 675, 2119, 2120, 670, 664, + /* 2120 */ 665, 685, 1564, 37, 16, 2115, 676, 2134, 2151, 1563, + /* 2130 */ 25, 320, 2117, 675, 2119, 2120, 670, 2116, 665, 2084, + /* 2140 */ 1535, 671, 674, 26, 688, 1333, 680, 672, 1330, 1327, + /* 2150 */ 683, 686, 691, 1321, 1319, 300, 1324, 1323, 1322, 2116, + /* 2160 */ 689, 692, 104, 1342, 105, 75, 1338, 1212, 706, 672, + /* 2170 */ 1244, 1243, 2115, 301, 2134, 2151, 1242, 1241, 321, 2117, + /* 2180 */ 675, 2119, 2120, 670, 2116, 665, 2084, 1239, 671, 1237, + /* 2190 */ 1236, 1235, 1270, 716, 672, 1233, 2134, 1232, 1231, 1230, + /* 2200 */ 1229, 1228, 1227, 1267, 1265, 1224, 2116, 1223, 2084, 1220, + /* 2210 */ 671, 1219, 1218, 1217, 1789, 736, 672, 737, 738, 2115, + /* 2220 */ 1787, 2134, 2151, 740, 741, 327, 2117, 675, 2119, 2120, + /* 2230 */ 670, 742, 665, 2084, 1785, 671, 744, 746, 745, 1783, + /* 2240 */ 748, 2115, 749, 2134, 2151, 750, 1769, 331, 2117, 675, + /* 2250 */ 2119, 2120, 670, 752, 665, 2084, 1166, 671, 304, 756, + /* 2260 */ 1721, 1721, 1497, 314, 759, 760, 2115, 1746, 1721, 2151, + /* 2270 */ 2116, 1721, 323, 2117, 675, 2119, 2120, 670, 1721, 665, + /* 2280 */ 672, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 2115, 1721, + /* 2290 */ 2116, 2151, 1721, 1721, 332, 2117, 675, 2119, 2120, 670, + /* 2300 */ 672, 665, 1721, 1721, 1721, 2116, 1721, 2134, 1721, 1721, + /* 2310 */ 1721, 1721, 1721, 1721, 1721, 672, 1721, 1721, 1721, 2084, + /* 2320 */ 1721, 671, 1721, 1721, 1721, 1721, 1721, 2134, 1721, 1721, + /* 2330 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 2116, 1721, 2084, + /* 2340 */ 1721, 671, 2134, 1721, 1721, 1721, 1721, 672, 1721, 1721, + /* 2350 */ 1721, 1721, 2115, 1721, 2084, 2151, 671, 1721, 324, 2117, + /* 2360 */ 675, 2119, 2120, 670, 1721, 665, 1721, 1721, 1721, 1721, + /* 2370 */ 1721, 1721, 2115, 1721, 2134, 2151, 1721, 1721, 333, 2117, + /* 2380 */ 675, 2119, 2120, 670, 1721, 665, 2084, 2115, 671, 1721, + /* 2390 */ 2151, 1721, 1721, 325, 2117, 675, 2119, 2120, 670, 1721, + /* 2400 */ 665, 1721, 1721, 1721, 1721, 2116, 1721, 1721, 1721, 1721, + /* 2410 */ 1721, 1721, 1721, 1721, 1721, 672, 1721, 1721, 1721, 2115, + /* 2420 */ 1721, 1721, 2151, 1721, 2116, 338, 2117, 675, 2119, 2120, + /* 2430 */ 670, 1721, 665, 1721, 672, 1721, 1721, 1721, 1721, 1721, + /* 2440 */ 1721, 1721, 2134, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2450 */ 1721, 1721, 2116, 1721, 2084, 1721, 671, 1721, 1721, 1721, + /* 2460 */ 1721, 2134, 672, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2470 */ 1721, 2116, 1721, 2084, 1721, 671, 1721, 1721, 1721, 1721, + /* 2480 */ 1721, 672, 1721, 1721, 1721, 1721, 1721, 2115, 1721, 2134, + /* 2490 */ 2151, 1721, 1721, 339, 2117, 675, 2119, 2120, 670, 1721, + /* 2500 */ 665, 2084, 1721, 671, 1721, 1721, 2115, 1721, 2134, 2151, + /* 2510 */ 1721, 1721, 2128, 2117, 675, 2119, 2120, 670, 2116, 665, + /* 2520 */ 2084, 1721, 671, 1721, 1721, 1721, 1721, 1721, 672, 1721, + /* 2530 */ 1721, 1721, 1721, 1721, 2115, 1721, 1721, 2151, 1721, 1721, + /* 2540 */ 2127, 2117, 675, 2119, 2120, 670, 1721, 665, 1721, 1721, + /* 2550 */ 1721, 1721, 1721, 2115, 1721, 2134, 2151, 1721, 1721, 2126, + /* 2560 */ 2117, 675, 2119, 2120, 670, 1721, 665, 2084, 1721, 671, + /* 2570 */ 1721, 1721, 1721, 1721, 1721, 2116, 1721, 1721, 1721, 1721, + /* 2580 */ 1721, 1721, 1721, 1721, 1721, 672, 1721, 1721, 1721, 1721, + /* 2590 */ 1721, 2116, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2600 */ 2115, 672, 1721, 2151, 1721, 1721, 353, 2117, 675, 2119, + /* 2610 */ 2120, 670, 2134, 665, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2620 */ 1721, 1721, 1721, 1721, 2084, 1721, 671, 1721, 2134, 1721, + /* 2630 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2640 */ 2084, 2116, 671, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2650 */ 1721, 672, 1721, 1721, 1721, 1721, 1721, 2115, 1721, 1721, + /* 2660 */ 2151, 2116, 1721, 354, 2117, 675, 2119, 2120, 670, 1721, + /* 2670 */ 665, 672, 1721, 2115, 1721, 1721, 2151, 1721, 2134, 350, + /* 2680 */ 2117, 675, 2119, 2120, 670, 1721, 665, 1721, 1721, 1721, + /* 2690 */ 2084, 1721, 671, 1721, 1721, 1721, 1721, 1721, 2134, 1721, + /* 2700 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 2116, 1721, + /* 2710 */ 2084, 1721, 671, 1721, 1721, 1721, 1721, 1721, 672, 1721, + /* 2720 */ 1721, 1721, 1721, 2115, 1721, 1721, 2151, 1721, 1721, 355, + /* 2730 */ 2117, 675, 2119, 2120, 670, 1721, 665, 1721, 1721, 1721, + /* 2740 */ 1721, 1721, 229, 673, 1721, 2134, 2151, 1721, 1721, 330, + /* 2750 */ 2117, 675, 2119, 2120, 670, 1721, 665, 2084, 172, 671, + /* 2760 */ 1721, 1721, 1721, 1721, 535, 531, 527, 523, 226, 1721, + /* 2770 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2780 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2790 */ 2115, 1721, 1721, 2151, 1721, 1721, 329, 2117, 675, 2119, + /* 2800 */ 2120, 670, 1721, 665, 1721, 1721, 1721, 1721, 88, 1721, + /* 2810 */ 1721, 224, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2820 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2830 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2840 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2850 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2860 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2870 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 223, 217, + /* 2880 */ 1721, 1721, 1721, 222, 1721, 514, 1721, 1721, 1721, 1721, + /* 2890 */ 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, 1721, + /* 2900 */ 1721, 1721, 1721, 215, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 331, 369, 333, 334, 372, 373, 389, 327, 360, 420, - /* 10 */ 421, 357, 12, 13, 14, 327, 359, 431, 358, 371, - /* 20 */ 20, 435, 22, 360, 370, 12, 13, 14, 15, 16, - /* 30 */ 327, 335, 324, 33, 371, 35, 450, 451, 358, 379, - /* 40 */ 380, 455, 456, 372, 373, 349, 366, 335, 431, 401, - /* 50 */ 402, 371, 435, 373, 1, 2, 20, 389, 58, 371, - /* 60 */ 412, 358, 366, 63, 401, 402, 403, 450, 451, 366, - /* 70 */ 70, 20, 455, 456, 371, 412, 373, 332, 398, 20, - /* 80 */ 335, 336, 402, 12, 13, 405, 406, 407, 408, 409, - /* 90 */ 410, 20, 412, 22, 382, 95, 384, 389, 20, 431, - /* 100 */ 335, 398, 342, 435, 33, 402, 35, 347, 405, 406, - /* 110 */ 407, 408, 409, 410, 349, 412, 58, 117, 450, 451, - /* 120 */ 417, 356, 419, 455, 456, 351, 423, 424, 354, 58, - /* 130 */ 20, 366, 132, 133, 63, 95, 335, 457, 458, 431, - /* 140 */ 437, 70, 335, 435, 331, 105, 333, 334, 445, 96, - /* 150 */ 349, 18, 35, 95, 95, 97, 23, 356, 450, 451, - /* 160 */ 373, 161, 162, 455, 456, 332, 95, 366, 335, 336, - /* 170 */ 37, 38, 385, 366, 41, 388, 404, 65, 66, 67, - /* 180 */ 180, 0, 182, 132, 133, 73, 74, 70, 117, 360, - /* 190 */ 78, 350, 59, 60, 61, 83, 84, 161, 162, 358, - /* 200 */ 371, 89, 430, 132, 133, 95, 206, 207, 367, 209, - /* 210 */ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - /* 220 */ 220, 221, 222, 223, 224, 225, 226, 227, 95, 335, - /* 230 */ 401, 402, 161, 162, 427, 428, 429, 20, 431, 432, - /* 240 */ 20, 412, 435, 349, 14, 20, 65, 66, 67, 358, - /* 250 */ 20, 180, 127, 182, 73, 74, 131, 450, 451, 78, - /* 260 */ 366, 163, 455, 456, 83, 84, 168, 134, 8, 9, - /* 270 */ 89, 380, 12, 13, 14, 15, 16, 206, 207, 389, - /* 280 */ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, - /* 290 */ 219, 220, 221, 222, 223, 224, 225, 226, 227, 4, - /* 300 */ 229, 12, 13, 245, 245, 172, 173, 174, 339, 20, - /* 310 */ 177, 22, 187, 188, 19, 358, 191, 339, 193, 327, - /* 320 */ 95, 431, 33, 366, 35, 435, 358, 44, 33, 196, - /* 330 */ 361, 353, 199, 365, 201, 202, 203, 204, 205, 361, - /* 340 */ 450, 451, 374, 48, 360, 455, 456, 58, 53, 350, - /* 350 */ 358, 4, 63, 58, 350, 371, 96, 358, 366, 70, - /* 360 */ 3, 62, 358, 371, 407, 373, 367, 14, 15, 16, - /* 370 */ 335, 367, 12, 13, 14, 20, 95, 20, 245, 96, - /* 380 */ 20, 327, 22, 163, 95, 401, 402, 403, 95, 94, - /* 390 */ 398, 341, 97, 33, 402, 35, 412, 405, 406, 407, - /* 400 */ 408, 409, 410, 229, 412, 355, 117, 415, 160, 417, - /* 410 */ 418, 419, 358, 0, 364, 423, 424, 382, 58, 384, - /* 420 */ 366, 132, 133, 126, 127, 371, 4, 373, 131, 0, - /* 430 */ 70, 108, 109, 110, 111, 112, 113, 114, 115, 116, - /* 440 */ 117, 118, 95, 120, 121, 122, 123, 124, 125, 106, - /* 450 */ 161, 162, 398, 96, 20, 95, 402, 0, 58, 405, - /* 460 */ 406, 407, 408, 409, 410, 43, 412, 45, 46, 180, - /* 470 */ 245, 182, 179, 419, 181, 62, 20, 117, 424, 335, - /* 480 */ 232, 24, 25, 26, 27, 28, 29, 30, 31, 32, - /* 490 */ 242, 62, 132, 133, 94, 206, 207, 97, 209, 210, - /* 500 */ 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - /* 510 */ 221, 222, 223, 224, 225, 226, 227, 344, 345, 375, - /* 520 */ 163, 161, 162, 0, 21, 335, 245, 24, 25, 26, - /* 530 */ 27, 28, 29, 30, 31, 32, 341, 62, 245, 349, - /* 540 */ 180, 326, 182, 328, 21, 20, 327, 24, 25, 26, - /* 550 */ 27, 28, 29, 30, 31, 32, 366, 8, 9, 364, - /* 560 */ 327, 12, 13, 14, 15, 16, 206, 207, 95, 209, - /* 570 */ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - /* 580 */ 220, 221, 222, 223, 224, 225, 226, 227, 12, 13, - /* 590 */ 371, 358, 245, 44, 22, 79, 20, 373, 22, 366, - /* 600 */ 37, 20, 70, 22, 371, 166, 373, 35, 229, 33, - /* 610 */ 231, 35, 388, 358, 358, 416, 35, 418, 8, 9, - /* 620 */ 365, 365, 12, 13, 14, 15, 16, 39, 327, 374, - /* 630 */ 374, 398, 51, 360, 58, 402, 21, 335, 405, 406, - /* 640 */ 407, 408, 409, 410, 371, 412, 70, 206, 335, 34, - /* 650 */ 417, 36, 419, 137, 138, 335, 423, 424, 404, 12, - /* 660 */ 13, 98, 349, 100, 101, 70, 103, 20, 366, 22, - /* 670 */ 107, 95, 371, 63, 401, 402, 403, 359, 445, 366, - /* 680 */ 33, 175, 35, 20, 430, 412, 366, 431, 14, 250, - /* 690 */ 251, 435, 129, 117, 20, 254, 255, 256, 257, 258, - /* 700 */ 259, 260, 393, 197, 198, 58, 450, 451, 132, 133, - /* 710 */ 327, 455, 456, 126, 104, 431, 327, 70, 245, 435, - /* 720 */ 8, 9, 335, 359, 12, 13, 14, 15, 16, 427, - /* 730 */ 428, 429, 20, 431, 432, 451, 349, 161, 162, 455, - /* 740 */ 456, 431, 95, 404, 14, 435, 426, 427, 428, 429, - /* 750 */ 20, 431, 432, 366, 371, 359, 180, 416, 182, 418, - /* 760 */ 371, 451, 107, 327, 117, 455, 456, 8, 9, 430, - /* 770 */ 160, 12, 13, 14, 15, 16, 189, 190, 415, 132, - /* 780 */ 133, 418, 206, 207, 129, 209, 210, 211, 212, 213, - /* 790 */ 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - /* 800 */ 224, 225, 226, 227, 18, 3, 20, 371, 161, 162, - /* 810 */ 20, 359, 22, 27, 344, 345, 30, 8, 9, 33, - /* 820 */ 366, 12, 13, 14, 15, 16, 163, 180, 0, 182, - /* 830 */ 368, 377, 244, 371, 48, 161, 50, 327, 4, 53, - /* 840 */ 327, 51, 232, 233, 234, 235, 236, 237, 238, 239, - /* 850 */ 240, 241, 242, 206, 207, 96, 209, 210, 211, 212, - /* 860 */ 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, - /* 870 */ 223, 224, 225, 226, 227, 163, 2, 327, 359, 327, - /* 880 */ 94, 371, 8, 9, 371, 359, 12, 13, 14, 15, - /* 890 */ 16, 161, 106, 65, 66, 67, 68, 69, 327, 71, - /* 900 */ 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - /* 910 */ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - /* 920 */ 327, 371, 136, 371, 327, 139, 140, 141, 142, 143, - /* 930 */ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - /* 940 */ 154, 155, 371, 157, 158, 159, 327, 327, 327, 366, - /* 950 */ 366, 351, 12, 13, 354, 358, 327, 335, 335, 20, - /* 960 */ 377, 377, 22, 366, 371, 335, 335, 327, 371, 0, - /* 970 */ 373, 349, 349, 33, 358, 35, 20, 335, 358, 349, - /* 980 */ 349, 172, 346, 367, 348, 358, 366, 328, 366, 366, - /* 990 */ 371, 371, 371, 373, 389, 398, 366, 366, 58, 402, - /* 1000 */ 371, 374, 405, 406, 407, 408, 409, 410, 366, 412, - /* 1010 */ 70, 371, 45, 46, 417, 327, 419, 347, 398, 327, - /* 1020 */ 423, 424, 402, 0, 327, 405, 406, 407, 408, 409, - /* 1030 */ 410, 434, 412, 327, 44, 2, 431, 417, 381, 419, - /* 1040 */ 435, 8, 9, 423, 424, 12, 13, 14, 15, 16, - /* 1050 */ 368, 243, 244, 371, 434, 450, 451, 117, 0, 371, - /* 1060 */ 455, 456, 368, 371, 358, 371, 264, 33, 371, 427, - /* 1070 */ 428, 429, 366, 431, 432, 337, 107, 371, 269, 373, - /* 1080 */ 246, 0, 48, 0, 42, 42, 44, 44, 54, 55, - /* 1090 */ 56, 57, 58, 106, 459, 126, 127, 128, 129, 130, - /* 1100 */ 131, 44, 163, 22, 398, 22, 48, 192, 402, 194, - /* 1110 */ 327, 405, 406, 407, 408, 409, 410, 161, 412, 335, - /* 1120 */ 180, 99, 182, 417, 102, 419, 132, 133, 94, 423, - /* 1130 */ 424, 97, 35, 349, 327, 13, 99, 58, 22, 102, - /* 1140 */ 434, 358, 44, 156, 44, 44, 206, 207, 107, 366, - /* 1150 */ 366, 35, 335, 0, 371, 35, 373, 35, 218, 219, - /* 1160 */ 220, 221, 222, 223, 224, 358, 349, 126, 127, 128, - /* 1170 */ 129, 130, 131, 366, 151, 22, 97, 63, 371, 327, - /* 1180 */ 373, 398, 448, 366, 99, 402, 70, 102, 405, 406, - /* 1190 */ 407, 408, 409, 410, 96, 412, 96, 96, 164, 165, - /* 1200 */ 417, 167, 419, 44, 170, 398, 423, 424, 442, 402, - /* 1210 */ 358, 0, 405, 406, 407, 408, 409, 410, 366, 412, - /* 1220 */ 186, 1, 2, 371, 417, 373, 419, 358, 337, 44, - /* 1230 */ 423, 424, 335, 117, 327, 8, 9, 335, 381, 12, - /* 1240 */ 13, 14, 15, 16, 334, 44, 349, 44, 44, 44, - /* 1250 */ 398, 349, 335, 335, 402, 96, 266, 405, 406, 407, - /* 1260 */ 408, 409, 410, 366, 412, 358, 349, 349, 366, 417, - /* 1270 */ 370, 419, 335, 366, 99, 423, 424, 102, 371, 182, - /* 1280 */ 373, 96, 389, 366, 366, 381, 349, 8, 9, 433, - /* 1290 */ 327, 12, 13, 14, 15, 16, 180, 96, 182, 96, - /* 1300 */ 96, 96, 182, 366, 44, 398, 47, 44, 44, 402, - /* 1310 */ 44, 44, 405, 406, 407, 408, 409, 410, 107, 412, - /* 1320 */ 206, 358, 206, 207, 431, 268, 419, 0, 435, 366, - /* 1330 */ 423, 424, 44, 335, 371, 327, 373, 126, 127, 128, - /* 1340 */ 129, 130, 131, 450, 451, 13, 44, 349, 455, 456, - /* 1350 */ 35, 452, 425, 247, 95, 436, 96, 400, 327, 96, - /* 1360 */ 96, 398, 96, 96, 366, 402, 358, 35, 405, 406, - /* 1370 */ 407, 408, 409, 410, 366, 412, 49, 48, 399, 371, - /* 1380 */ 178, 373, 419, 391, 96, 70, 423, 424, 42, 358, - /* 1390 */ 163, 378, 20, 381, 378, 160, 376, 366, 96, 20, - /* 1400 */ 335, 335, 371, 378, 373, 376, 398, 93, 376, 335, - /* 1410 */ 402, 343, 335, 405, 406, 407, 408, 409, 410, 335, - /* 1420 */ 412, 20, 329, 329, 20, 395, 373, 419, 341, 398, - /* 1430 */ 341, 423, 424, 402, 20, 336, 405, 406, 407, 408, - /* 1440 */ 409, 410, 411, 412, 413, 414, 327, 20, 341, 390, - /* 1450 */ 341, 336, 341, 341, 341, 52, 335, 329, 397, 371, - /* 1460 */ 358, 338, 327, 338, 195, 329, 358, 335, 358, 185, - /* 1470 */ 395, 381, 394, 339, 371, 358, 358, 358, 373, 339, - /* 1480 */ 335, 253, 358, 252, 358, 366, 441, 358, 358, 358, - /* 1490 */ 371, 358, 373, 358, 261, 441, 444, 171, 371, 443, - /* 1500 */ 263, 366, 262, 441, 440, 248, 371, 438, 373, 439, - /* 1510 */ 371, 270, 371, 371, 371, 460, 267, 398, 327, 381, - /* 1520 */ 265, 402, 244, 386, 405, 406, 407, 408, 409, 410, - /* 1530 */ 386, 412, 366, 398, 454, 453, 20, 402, 339, 20, - /* 1540 */ 405, 406, 407, 408, 409, 410, 327, 412, 400, 358, - /* 1550 */ 404, 335, 384, 336, 371, 386, 386, 366, 371, 371, - /* 1560 */ 371, 371, 371, 371, 373, 446, 447, 165, 339, 383, - /* 1570 */ 95, 339, 354, 366, 422, 95, 362, 358, 348, 371, - /* 1580 */ 335, 339, 447, 330, 36, 366, 392, 329, 352, 398, - /* 1590 */ 371, 396, 373, 402, 340, 352, 405, 406, 407, 408, - /* 1600 */ 409, 410, 387, 412, 352, 325, 0, 0, 327, 387, - /* 1610 */ 187, 0, 0, 42, 0, 35, 200, 398, 35, 35, - /* 1620 */ 19, 402, 35, 0, 405, 406, 407, 408, 409, 410, - /* 1630 */ 200, 412, 35, 35, 33, 200, 0, 200, 0, 358, - /* 1640 */ 449, 0, 22, 35, 363, 0, 182, 366, 35, 48, - /* 1650 */ 180, 0, 371, 0, 373, 54, 55, 56, 57, 58, - /* 1660 */ 176, 0, 175, 327, 47, 0, 0, 0, 42, 0, - /* 1670 */ 0, 0, 0, 0, 0, 0, 0, 458, 0, 398, - /* 1680 */ 151, 35, 0, 402, 151, 0, 405, 406, 407, 408, - /* 1690 */ 409, 410, 0, 412, 358, 94, 0, 0, 97, 0, - /* 1700 */ 0, 0, 366, 0, 0, 0, 0, 371, 0, 373, - /* 1710 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, - /* 1720 */ 22, 0, 0, 135, 0, 327, 35, 0, 0, 0, - /* 1730 */ 0, 130, 0, 39, 398, 42, 47, 58, 402, 58, - /* 1740 */ 0, 405, 406, 407, 408, 409, 410, 14, 412, 47, - /* 1750 */ 414, 44, 14, 0, 0, 327, 358, 0, 0, 0, - /* 1760 */ 40, 363, 39, 171, 366, 0, 47, 0, 167, 371, - /* 1770 */ 39, 373, 0, 64, 35, 39, 0, 35, 0, 35, - /* 1780 */ 39, 0, 48, 48, 0, 184, 358, 186, 39, 39, - /* 1790 */ 35, 363, 0, 48, 366, 48, 398, 0, 0, 371, - /* 1800 */ 402, 373, 22, 405, 406, 407, 408, 409, 410, 35, - /* 1810 */ 412, 0, 35, 327, 35, 44, 22, 35, 35, 44, - /* 1820 */ 35, 35, 35, 0, 22, 0, 398, 102, 22, 327, - /* 1830 */ 402, 0, 22, 405, 406, 407, 408, 409, 410, 50, - /* 1840 */ 412, 104, 35, 0, 358, 0, 0, 35, 35, 22, - /* 1850 */ 35, 35, 366, 20, 35, 0, 96, 371, 95, 373, - /* 1860 */ 358, 35, 0, 183, 22, 0, 0, 3, 366, 96, - /* 1870 */ 249, 249, 44, 371, 327, 373, 44, 3, 44, 44, - /* 1880 */ 249, 44, 44, 95, 398, 95, 47, 96, 402, 96, - /* 1890 */ 327, 405, 406, 407, 408, 409, 410, 96, 412, 95, - /* 1900 */ 398, 47, 35, 95, 402, 358, 163, 405, 406, 407, - /* 1910 */ 408, 409, 410, 366, 412, 163, 165, 169, 371, 95, - /* 1920 */ 373, 358, 35, 35, 163, 96, 47, 35, 35, 366, - /* 1930 */ 35, 95, 47, 243, 371, 0, 373, 96, 44, 0, - /* 1940 */ 96, 0, 0, 96, 47, 398, 95, 39, 96, 402, - /* 1950 */ 47, 95, 405, 406, 407, 408, 409, 410, 95, 412, - /* 1960 */ 44, 398, 166, 164, 96, 402, 95, 327, 405, 406, - /* 1970 */ 407, 408, 409, 410, 105, 412, 95, 2, 22, 95, - /* 1980 */ 47, 47, 96, 22, 95, 35, 96, 35, 106, 35, - /* 1990 */ 228, 327, 96, 95, 230, 95, 228, 95, 358, 35, - /* 2000 */ 96, 206, 95, 22, 35, 96, 366, 95, 208, 96, - /* 2010 */ 95, 371, 95, 373, 96, 96, 95, 35, 96, 95, - /* 2020 */ 119, 107, 358, 95, 119, 119, 95, 44, 35, 119, - /* 2030 */ 366, 95, 22, 35, 64, 371, 63, 373, 398, 35, - /* 2040 */ 35, 35, 402, 35, 35, 405, 406, 407, 408, 409, - /* 2050 */ 410, 35, 412, 327, 35, 35, 35, 70, 92, 44, - /* 2060 */ 35, 35, 398, 35, 22, 35, 402, 35, 35, 405, - /* 2070 */ 406, 407, 408, 409, 410, 35, 412, 70, 35, 35, - /* 2080 */ 35, 35, 22, 327, 358, 35, 0, 35, 39, 48, - /* 2090 */ 0, 35, 366, 0, 39, 48, 35, 371, 39, 373, - /* 2100 */ 0, 48, 35, 39, 0, 48, 35, 35, 0, 22, - /* 2110 */ 21, 461, 20, 22, 358, 461, 22, 21, 461, 461, - /* 2120 */ 461, 461, 366, 461, 398, 461, 461, 371, 402, 373, - /* 2130 */ 461, 405, 406, 407, 408, 409, 410, 461, 412, 461, - /* 2140 */ 461, 327, 461, 461, 461, 461, 461, 461, 461, 461, - /* 2150 */ 461, 461, 461, 461, 398, 461, 461, 327, 402, 461, - /* 2160 */ 461, 405, 406, 407, 408, 409, 410, 461, 412, 461, - /* 2170 */ 461, 461, 358, 461, 461, 461, 461, 461, 461, 461, - /* 2180 */ 366, 461, 461, 461, 461, 371, 461, 373, 358, 461, - /* 2190 */ 461, 461, 461, 461, 461, 461, 366, 461, 461, 461, - /* 2200 */ 461, 371, 327, 373, 461, 461, 461, 461, 461, 461, - /* 2210 */ 461, 461, 398, 461, 461, 461, 402, 461, 327, 405, - /* 2220 */ 406, 407, 408, 409, 410, 461, 412, 461, 398, 461, - /* 2230 */ 461, 461, 402, 358, 461, 405, 406, 407, 408, 409, - /* 2240 */ 410, 366, 412, 461, 461, 461, 371, 461, 373, 358, - /* 2250 */ 461, 461, 461, 461, 461, 461, 461, 366, 461, 461, - /* 2260 */ 461, 461, 371, 461, 373, 461, 461, 461, 461, 461, - /* 2270 */ 461, 461, 461, 398, 461, 461, 461, 402, 461, 461, - /* 2280 */ 405, 406, 407, 408, 409, 410, 461, 412, 461, 398, - /* 2290 */ 461, 461, 461, 402, 461, 327, 405, 406, 407, 408, - /* 2300 */ 409, 410, 461, 412, 461, 461, 461, 461, 461, 461, - /* 2310 */ 461, 461, 461, 461, 461, 461, 461, 461, 461, 327, - /* 2320 */ 461, 461, 461, 461, 461, 461, 358, 461, 461, 461, - /* 2330 */ 461, 461, 461, 461, 366, 461, 461, 461, 461, 371, - /* 2340 */ 461, 373, 461, 461, 461, 461, 461, 461, 461, 461, - /* 2350 */ 358, 461, 461, 461, 461, 461, 461, 461, 366, 461, - /* 2360 */ 461, 461, 461, 371, 461, 373, 398, 461, 461, 461, - /* 2370 */ 402, 461, 461, 405, 406, 407, 408, 409, 410, 461, - /* 2380 */ 412, 327, 461, 461, 461, 461, 461, 461, 461, 461, - /* 2390 */ 398, 461, 461, 461, 402, 461, 461, 405, 406, 407, - /* 2400 */ 408, 409, 410, 461, 412, 461, 461, 461, 461, 461, - /* 2410 */ 461, 327, 358, 461, 461, 461, 461, 461, 461, 461, - /* 2420 */ 366, 461, 461, 461, 461, 371, 461, 373, 461, 461, - /* 2430 */ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, - /* 2440 */ 461, 461, 358, 461, 461, 461, 461, 461, 461, 461, - /* 2450 */ 366, 461, 398, 461, 461, 371, 402, 373, 461, 405, - /* 2460 */ 406, 407, 408, 409, 410, 461, 412, 461, 461, 327, - /* 2470 */ 461, 461, 461, 461, 461, 461, 461, 461, 461, 461, - /* 2480 */ 461, 461, 398, 461, 461, 327, 402, 461, 461, 405, - /* 2490 */ 406, 407, 408, 409, 410, 461, 412, 461, 461, 461, - /* 2500 */ 358, 461, 461, 461, 461, 461, 461, 461, 366, 461, - /* 2510 */ 461, 461, 461, 371, 461, 373, 358, 461, 461, 461, - /* 2520 */ 461, 461, 461, 461, 366, 461, 461, 461, 461, 371, - /* 2530 */ 327, 373, 461, 461, 461, 461, 461, 461, 461, 461, - /* 2540 */ 398, 461, 461, 461, 402, 461, 327, 405, 406, 407, - /* 2550 */ 408, 409, 410, 461, 412, 461, 398, 461, 461, 461, - /* 2560 */ 402, 358, 461, 405, 406, 407, 408, 409, 410, 366, - /* 2570 */ 412, 461, 461, 461, 371, 461, 373, 358, 461, 461, - /* 2580 */ 461, 461, 461, 461, 461, 366, 461, 461, 461, 461, - /* 2590 */ 371, 461, 373, 461, 461, 461, 461, 461, 461, 461, - /* 2600 */ 461, 398, 461, 461, 461, 402, 461, 461, 405, 406, - /* 2610 */ 407, 408, 409, 410, 461, 412, 461, 398, 461, 461, - /* 2620 */ 461, 402, 461, 327, 405, 406, 407, 408, 409, 410, - /* 2630 */ 461, 412, 461, 461, 461, 461, 461, 461, 461, 461, - /* 2640 */ 461, 461, 461, 461, 461, 461, 461, 327, 461, 461, - /* 2650 */ 461, 461, 461, 461, 358, 461, 461, 461, 461, 461, - /* 2660 */ 461, 461, 366, 461, 461, 461, 461, 371, 461, 373, - /* 2670 */ 461, 461, 461, 461, 461, 461, 461, 461, 358, 461, - /* 2680 */ 461, 461, 461, 461, 461, 461, 366, 461, 461, 461, - /* 2690 */ 461, 371, 461, 373, 398, 461, 461, 461, 402, 461, - /* 2700 */ 461, 405, 406, 407, 408, 409, 410, 461, 412, 461, - /* 2710 */ 461, 461, 461, 461, 461, 461, 461, 461, 398, 461, - /* 2720 */ 461, 461, 402, 461, 461, 405, 406, 407, 408, 409, - /* 2730 */ 410, 461, 412, + /* 0 */ 333, 384, 371, 362, 401, 332, 401, 334, 405, 343, + /* 10 */ 343, 370, 12, 13, 14, 0, 399, 400, 377, 378, + /* 20 */ 20, 14, 22, 342, 8, 9, 385, 20, 12, 13, + /* 30 */ 14, 15, 16, 33, 0, 35, 21, 370, 20, 24, + /* 40 */ 25, 26, 27, 28, 29, 30, 31, 32, 3, 382, + /* 50 */ 447, 384, 447, 450, 388, 450, 8, 9, 351, 59, + /* 60 */ 12, 13, 14, 15, 16, 65, 359, 386, 465, 466, + /* 70 */ 465, 466, 72, 470, 471, 470, 471, 12, 13, 14, + /* 80 */ 15, 16, 415, 337, 20, 418, 340, 341, 421, 422, + /* 90 */ 423, 424, 425, 426, 369, 428, 20, 97, 436, 437, + /* 100 */ 100, 67, 68, 69, 70, 71, 381, 73, 74, 75, + /* 110 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, + /* 120 */ 86, 87, 88, 89, 90, 91, 92, 93, 461, 462, + /* 130 */ 337, 20, 97, 340, 341, 21, 136, 137, 24, 25, + /* 140 */ 26, 27, 28, 29, 30, 31, 32, 112, 113, 114, + /* 150 */ 115, 116, 117, 118, 119, 120, 121, 370, 123, 124, + /* 160 */ 125, 126, 127, 128, 100, 20, 166, 167, 20, 420, + /* 170 */ 342, 343, 172, 173, 330, 8, 9, 390, 391, 12, + /* 180 */ 13, 14, 15, 16, 166, 167, 186, 20, 188, 361, + /* 190 */ 342, 343, 362, 100, 178, 446, 368, 8, 9, 59, + /* 200 */ 370, 12, 13, 14, 15, 16, 8, 9, 378, 361, + /* 210 */ 12, 13, 14, 15, 16, 215, 216, 0, 218, 219, + /* 220 */ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, + /* 230 */ 230, 231, 232, 233, 234, 235, 12, 13, 0, 370, + /* 240 */ 100, 18, 102, 20, 20, 401, 22, 100, 100, 405, + /* 250 */ 27, 333, 447, 30, 65, 450, 33, 33, 343, 35, + /* 260 */ 391, 343, 24, 25, 26, 27, 28, 29, 30, 31, + /* 270 */ 32, 466, 49, 20, 51, 470, 471, 54, 185, 362, + /* 280 */ 187, 64, 447, 59, 22, 450, 338, 370, 370, 65, + /* 290 */ 342, 447, 344, 277, 450, 378, 72, 35, 109, 101, + /* 300 */ 382, 466, 384, 388, 384, 470, 471, 214, 447, 465, + /* 310 */ 466, 450, 64, 333, 470, 471, 396, 272, 4, 399, + /* 320 */ 400, 97, 99, 343, 100, 345, 465, 466, 35, 342, + /* 330 */ 343, 470, 471, 415, 111, 168, 418, 342, 343, 421, + /* 340 */ 422, 423, 424, 425, 426, 252, 428, 20, 361, 431, + /* 350 */ 370, 433, 434, 435, 165, 368, 361, 439, 440, 97, + /* 360 */ 136, 137, 382, 140, 384, 72, 143, 144, 145, 146, + /* 370 */ 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, + /* 380 */ 157, 158, 159, 20, 161, 162, 163, 14, 20, 20, + /* 390 */ 166, 167, 252, 20, 13, 415, 172, 173, 418, 252, + /* 400 */ 252, 421, 422, 423, 424, 425, 426, 64, 428, 20, + /* 410 */ 186, 22, 188, 433, 100, 435, 35, 342, 343, 439, + /* 420 */ 440, 168, 100, 171, 342, 342, 343, 333, 239, 240, + /* 430 */ 241, 242, 243, 244, 245, 246, 247, 248, 249, 215, + /* 440 */ 216, 52, 218, 219, 220, 221, 222, 223, 224, 225, + /* 450 */ 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, + /* 460 */ 236, 12, 13, 136, 137, 22, 12, 13, 100, 20, + /* 470 */ 22, 22, 67, 68, 69, 393, 382, 395, 35, 74, + /* 480 */ 75, 76, 33, 35, 35, 80, 3, 333, 2, 35, + /* 490 */ 85, 86, 87, 88, 8, 9, 91, 343, 12, 13, + /* 500 */ 14, 15, 16, 20, 20, 136, 137, 333, 59, 257, + /* 510 */ 258, 259, 215, 379, 65, 72, 382, 343, 443, 444, + /* 520 */ 445, 72, 447, 448, 370, 442, 443, 444, 445, 380, + /* 530 */ 447, 448, 383, 384, 366, 20, 382, 22, 384, 166, + /* 540 */ 97, 172, 173, 20, 370, 97, 97, 8, 9, 100, + /* 550 */ 35, 12, 13, 14, 15, 16, 382, 44, 384, 262, + /* 560 */ 263, 264, 265, 266, 267, 268, 252, 52, 18, 415, + /* 570 */ 333, 111, 418, 23, 252, 421, 422, 423, 424, 425, + /* 580 */ 426, 413, 428, 44, 101, 136, 137, 37, 38, 415, + /* 590 */ 236, 41, 418, 358, 4, 421, 422, 423, 424, 425, + /* 600 */ 426, 427, 428, 429, 430, 342, 343, 372, 348, 19, + /* 610 */ 60, 61, 62, 63, 101, 166, 167, 382, 343, 382, + /* 620 */ 252, 172, 173, 33, 361, 365, 472, 473, 338, 186, + /* 630 */ 81, 188, 342, 373, 344, 186, 0, 188, 370, 49, + /* 640 */ 370, 370, 188, 342, 54, 370, 378, 377, 377, 59, + /* 650 */ 100, 168, 168, 418, 419, 385, 385, 72, 215, 216, + /* 660 */ 4, 130, 131, 428, 215, 216, 135, 218, 219, 220, + /* 670 */ 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + /* 680 */ 231, 232, 233, 234, 235, 12, 13, 14, 138, 99, + /* 690 */ 141, 142, 102, 20, 393, 22, 395, 333, 423, 43, + /* 700 */ 0, 45, 46, 67, 68, 69, 33, 343, 35, 37, + /* 710 */ 74, 75, 76, 164, 342, 111, 80, 447, 342, 343, + /* 720 */ 450, 85, 86, 87, 88, 342, 343, 91, 178, 179, + /* 730 */ 180, 4, 59, 183, 370, 465, 466, 361, 383, 384, + /* 740 */ 470, 471, 72, 131, 370, 72, 382, 135, 384, 342, + /* 750 */ 343, 377, 1, 2, 204, 342, 343, 207, 371, 385, + /* 760 */ 210, 211, 212, 213, 214, 393, 333, 395, 361, 370, + /* 770 */ 97, 100, 401, 100, 361, 103, 377, 105, 106, 415, + /* 780 */ 108, 110, 418, 333, 385, 421, 422, 423, 424, 425, + /* 790 */ 426, 370, 428, 343, 0, 342, 343, 433, 377, 435, + /* 800 */ 348, 129, 252, 439, 440, 133, 385, 195, 196, 136, + /* 810 */ 137, 199, 350, 201, 361, 382, 452, 401, 447, 334, + /* 820 */ 370, 450, 355, 356, 460, 373, 443, 444, 445, 367, + /* 830 */ 447, 448, 382, 450, 384, 333, 465, 466, 376, 166, + /* 840 */ 167, 470, 471, 342, 343, 172, 173, 130, 465, 466, + /* 850 */ 342, 343, 101, 470, 471, 155, 14, 420, 236, 186, + /* 860 */ 238, 188, 20, 447, 164, 415, 450, 333, 418, 361, + /* 870 */ 371, 421, 422, 423, 424, 425, 426, 432, 428, 434, + /* 880 */ 44, 465, 466, 446, 382, 435, 470, 471, 215, 216, + /* 890 */ 440, 218, 219, 220, 221, 222, 223, 224, 225, 226, + /* 900 */ 227, 228, 229, 230, 231, 232, 233, 234, 235, 12, + /* 910 */ 13, 432, 20, 434, 197, 198, 382, 20, 181, 22, + /* 920 */ 42, 333, 44, 129, 130, 131, 132, 133, 134, 135, + /* 930 */ 33, 343, 35, 8, 9, 342, 343, 12, 13, 14, + /* 940 */ 15, 16, 205, 206, 443, 444, 445, 333, 447, 448, + /* 950 */ 59, 371, 342, 343, 361, 401, 59, 343, 370, 345, + /* 960 */ 129, 130, 131, 132, 133, 134, 135, 362, 20, 72, + /* 970 */ 382, 361, 384, 342, 343, 370, 14, 15, 16, 420, + /* 980 */ 253, 8, 9, 378, 370, 12, 13, 14, 15, 16, + /* 990 */ 99, 129, 361, 102, 97, 133, 382, 100, 384, 342, + /* 1000 */ 343, 447, 333, 415, 450, 446, 418, 333, 166, 421, + /* 1010 */ 422, 423, 424, 425, 426, 0, 428, 343, 361, 465, + /* 1020 */ 466, 433, 39, 435, 470, 471, 333, 439, 440, 415, + /* 1030 */ 0, 350, 418, 136, 137, 421, 422, 423, 424, 425, + /* 1040 */ 426, 358, 428, 406, 370, 333, 21, 433, 460, 435, + /* 1050 */ 42, 382, 44, 439, 440, 372, 382, 376, 384, 34, + /* 1060 */ 168, 36, 343, 166, 167, 382, 2, 342, 343, 172, + /* 1070 */ 173, 165, 8, 9, 101, 382, 12, 13, 14, 15, + /* 1080 */ 16, 355, 356, 186, 371, 188, 361, 342, 343, 415, + /* 1090 */ 342, 343, 418, 168, 382, 421, 422, 423, 424, 425, + /* 1100 */ 426, 418, 428, 45, 46, 363, 361, 388, 366, 361, + /* 1110 */ 274, 428, 215, 216, 166, 218, 219, 220, 221, 222, + /* 1120 */ 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, + /* 1130 */ 233, 234, 235, 12, 13, 333, 462, 333, 342, 343, + /* 1140 */ 333, 20, 333, 22, 358, 239, 333, 343, 333, 345, + /* 1150 */ 342, 343, 342, 343, 33, 249, 35, 361, 372, 129, + /* 1160 */ 130, 131, 132, 133, 134, 135, 333, 431, 382, 361, + /* 1170 */ 434, 361, 250, 251, 370, 370, 379, 14, 379, 382, + /* 1180 */ 59, 382, 333, 20, 382, 358, 382, 333, 384, 382, + /* 1190 */ 385, 382, 358, 72, 0, 382, 44, 382, 333, 372, + /* 1200 */ 333, 333, 0, 371, 418, 419, 372, 357, 104, 382, + /* 1210 */ 360, 107, 111, 48, 428, 382, 382, 104, 97, 415, + /* 1220 */ 107, 100, 418, 333, 209, 421, 422, 423, 424, 425, + /* 1230 */ 426, 382, 428, 343, 251, 345, 382, 433, 44, 435, + /* 1240 */ 44, 22, 13, 439, 440, 418, 419, 382, 0, 382, + /* 1250 */ 382, 49, 418, 104, 35, 428, 107, 136, 137, 0, + /* 1260 */ 370, 160, 428, 104, 35, 44, 107, 0, 13, 200, + /* 1270 */ 22, 202, 382, 65, 384, 44, 59, 44, 44, 136, + /* 1280 */ 137, 22, 1, 2, 371, 47, 359, 166, 167, 22, + /* 1290 */ 35, 392, 474, 172, 173, 346, 457, 101, 463, 358, + /* 1300 */ 35, 35, 13, 358, 44, 415, 44, 186, 418, 188, + /* 1310 */ 370, 421, 422, 423, 424, 425, 426, 44, 428, 102, + /* 1320 */ 44, 44, 101, 433, 35, 435, 346, 44, 44, 439, + /* 1330 */ 440, 392, 101, 168, 101, 101, 215, 216, 100, 218, + /* 1340 */ 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, + /* 1350 */ 229, 230, 231, 232, 233, 234, 235, 333, 12, 13, + /* 1360 */ 35, 101, 44, 101, 44, 44, 0, 343, 22, 345, + /* 1370 */ 44, 343, 44, 341, 101, 381, 392, 101, 101, 33, + /* 1380 */ 44, 35, 449, 333, 101, 101, 467, 44, 441, 451, + /* 1390 */ 254, 417, 416, 343, 370, 345, 49, 72, 184, 403, + /* 1400 */ 42, 389, 20, 392, 165, 59, 382, 389, 384, 387, + /* 1410 */ 20, 98, 342, 342, 387, 389, 50, 354, 72, 101, + /* 1420 */ 370, 101, 101, 215, 387, 96, 353, 101, 276, 101, + /* 1430 */ 333, 342, 382, 95, 384, 352, 342, 101, 342, 415, + /* 1440 */ 343, 342, 418, 97, 101, 421, 422, 423, 424, 425, + /* 1450 */ 426, 333, 428, 188, 188, 20, 48, 433, 335, 435, + /* 1460 */ 335, 343, 20, 439, 440, 415, 339, 370, 418, 339, + /* 1470 */ 410, 421, 422, 423, 424, 425, 426, 20, 428, 382, + /* 1480 */ 20, 384, 350, 433, 384, 435, 344, 350, 370, 439, + /* 1490 */ 440, 20, 402, 53, 350, 344, 350, 350, 350, 342, + /* 1500 */ 382, 347, 384, 350, 335, 347, 342, 335, 370, 370, + /* 1510 */ 370, 370, 415, 382, 203, 418, 382, 382, 421, 422, + /* 1520 */ 423, 424, 425, 426, 414, 428, 370, 100, 412, 410, + /* 1530 */ 370, 370, 186, 415, 188, 348, 418, 370, 370, 421, + /* 1540 */ 422, 423, 424, 425, 426, 370, 428, 370, 192, 348, + /* 1550 */ 191, 433, 190, 435, 409, 333, 382, 439, 440, 261, + /* 1560 */ 384, 215, 216, 408, 456, 343, 342, 260, 397, 407, + /* 1570 */ 473, 392, 392, 382, 228, 229, 230, 231, 232, 233, + /* 1580 */ 234, 397, 456, 269, 177, 382, 382, 459, 271, 270, + /* 1590 */ 255, 458, 370, 278, 343, 417, 251, 475, 275, 20, + /* 1600 */ 273, 420, 344, 342, 382, 455, 384, 20, 395, 397, + /* 1610 */ 382, 348, 348, 397, 382, 170, 348, 382, 382, 382, + /* 1620 */ 394, 333, 456, 382, 454, 343, 453, 348, 100, 100, + /* 1630 */ 438, 343, 382, 342, 360, 366, 36, 415, 348, 336, + /* 1640 */ 418, 335, 398, 421, 422, 423, 424, 425, 426, 333, + /* 1650 */ 428, 469, 374, 468, 411, 433, 404, 435, 370, 343, + /* 1660 */ 364, 439, 440, 364, 364, 331, 0, 0, 398, 0, + /* 1670 */ 382, 349, 384, 42, 0, 35, 208, 35, 35, 35, + /* 1680 */ 208, 333, 0, 35, 35, 208, 370, 0, 208, 0, + /* 1690 */ 35, 343, 22, 0, 35, 195, 188, 186, 382, 0, + /* 1700 */ 384, 0, 0, 415, 0, 182, 418, 181, 0, 421, + /* 1710 */ 422, 423, 424, 425, 426, 0, 428, 0, 370, 47, + /* 1720 */ 0, 433, 0, 435, 0, 42, 0, 439, 440, 0, + /* 1730 */ 382, 415, 384, 0, 418, 0, 0, 421, 422, 423, + /* 1740 */ 424, 425, 426, 0, 428, 0, 155, 35, 0, 155, + /* 1750 */ 0, 435, 333, 0, 0, 439, 440, 139, 42, 0, + /* 1760 */ 0, 0, 343, 415, 0, 0, 418, 0, 0, 421, + /* 1770 */ 422, 423, 424, 425, 426, 0, 428, 0, 0, 0, + /* 1780 */ 333, 0, 0, 435, 0, 0, 0, 439, 440, 370, + /* 1790 */ 343, 0, 0, 0, 22, 0, 0, 0, 0, 333, + /* 1800 */ 0, 382, 22, 384, 48, 22, 48, 0, 59, 343, + /* 1810 */ 0, 35, 0, 0, 59, 333, 0, 370, 44, 14, + /* 1820 */ 47, 59, 0, 0, 0, 343, 39, 0, 39, 382, + /* 1830 */ 42, 384, 0, 39, 415, 177, 370, 418, 0, 0, + /* 1840 */ 421, 422, 423, 424, 425, 426, 47, 428, 382, 47, + /* 1850 */ 384, 40, 370, 0, 435, 0, 66, 375, 439, 440, + /* 1860 */ 35, 0, 415, 49, 382, 418, 384, 39, 421, 422, + /* 1870 */ 423, 424, 425, 426, 39, 428, 333, 35, 49, 0, + /* 1880 */ 35, 415, 49, 39, 418, 0, 343, 421, 422, 423, + /* 1890 */ 424, 425, 426, 35, 428, 49, 430, 415, 1, 333, + /* 1900 */ 418, 39, 0, 421, 422, 423, 424, 425, 426, 343, + /* 1910 */ 428, 464, 0, 370, 0, 0, 19, 109, 375, 35, + /* 1920 */ 22, 0, 107, 35, 35, 382, 35, 384, 35, 35, + /* 1930 */ 33, 35, 22, 0, 35, 22, 370, 51, 35, 44, + /* 1940 */ 35, 375, 35, 0, 44, 22, 49, 0, 382, 22, + /* 1950 */ 384, 35, 55, 56, 57, 58, 59, 35, 415, 0, + /* 1960 */ 0, 418, 0, 35, 421, 422, 423, 424, 425, 426, + /* 1970 */ 22, 428, 20, 35, 35, 35, 101, 100, 0, 35, + /* 1980 */ 100, 415, 0, 22, 418, 168, 22, 421, 422, 423, + /* 1990 */ 424, 425, 426, 333, 428, 189, 99, 0, 168, 102, + /* 2000 */ 0, 170, 193, 343, 168, 3, 100, 44, 256, 175, + /* 2010 */ 101, 100, 44, 48, 48, 98, 96, 44, 44, 101, + /* 2020 */ 101, 44, 47, 47, 100, 333, 100, 256, 3, 100, + /* 2030 */ 370, 134, 101, 101, 100, 343, 101, 44, 35, 47, + /* 2040 */ 35, 35, 382, 333, 384, 35, 35, 35, 47, 0, + /* 2050 */ 101, 101, 44, 343, 0, 0, 0, 256, 100, 39, + /* 2060 */ 47, 171, 370, 0, 110, 39, 169, 100, 250, 47, + /* 2070 */ 101, 174, 101, 169, 382, 415, 384, 44, 418, 100, + /* 2080 */ 370, 421, 422, 423, 424, 425, 426, 100, 428, 100, + /* 2090 */ 333, 194, 382, 237, 384, 100, 98, 98, 2, 22, + /* 2100 */ 343, 22, 215, 35, 47, 47, 35, 415, 101, 100, + /* 2110 */ 418, 35, 122, 421, 422, 423, 424, 425, 426, 100, + /* 2120 */ 428, 35, 101, 100, 100, 415, 111, 370, 418, 101, + /* 2130 */ 100, 421, 422, 423, 424, 425, 426, 333, 428, 382, + /* 2140 */ 101, 384, 217, 100, 35, 101, 100, 343, 101, 101, + /* 2150 */ 100, 100, 35, 101, 101, 44, 122, 122, 122, 333, + /* 2160 */ 100, 100, 100, 35, 100, 100, 22, 66, 65, 343, + /* 2170 */ 35, 35, 415, 44, 370, 418, 35, 35, 421, 422, + /* 2180 */ 423, 424, 425, 426, 333, 428, 382, 35, 384, 35, + /* 2190 */ 35, 35, 72, 94, 343, 35, 370, 35, 35, 22, + /* 2200 */ 35, 35, 35, 72, 35, 35, 333, 35, 382, 35, + /* 2210 */ 384, 35, 22, 35, 0, 35, 343, 49, 39, 415, + /* 2220 */ 0, 370, 418, 35, 49, 421, 422, 423, 424, 425, + /* 2230 */ 426, 39, 428, 382, 0, 384, 35, 39, 49, 0, + /* 2240 */ 35, 415, 49, 370, 418, 39, 0, 421, 422, 423, + /* 2250 */ 424, 425, 426, 35, 428, 382, 35, 384, 22, 21, + /* 2260 */ 476, 476, 22, 22, 21, 20, 415, 0, 476, 418, + /* 2270 */ 333, 476, 421, 422, 423, 424, 425, 426, 476, 428, + /* 2280 */ 343, 476, 476, 476, 476, 476, 476, 476, 415, 476, + /* 2290 */ 333, 418, 476, 476, 421, 422, 423, 424, 425, 426, + /* 2300 */ 343, 428, 476, 476, 476, 333, 476, 370, 476, 476, + /* 2310 */ 476, 476, 476, 476, 476, 343, 476, 476, 476, 382, + /* 2320 */ 476, 384, 476, 476, 476, 476, 476, 370, 476, 476, + /* 2330 */ 476, 476, 476, 476, 476, 476, 476, 333, 476, 382, + /* 2340 */ 476, 384, 370, 476, 476, 476, 476, 343, 476, 476, + /* 2350 */ 476, 476, 415, 476, 382, 418, 384, 476, 421, 422, + /* 2360 */ 423, 424, 425, 426, 476, 428, 476, 476, 476, 476, + /* 2370 */ 476, 476, 415, 476, 370, 418, 476, 476, 421, 422, + /* 2380 */ 423, 424, 425, 426, 476, 428, 382, 415, 384, 476, + /* 2390 */ 418, 476, 476, 421, 422, 423, 424, 425, 426, 476, + /* 2400 */ 428, 476, 476, 476, 476, 333, 476, 476, 476, 476, + /* 2410 */ 476, 476, 476, 476, 476, 343, 476, 476, 476, 415, + /* 2420 */ 476, 476, 418, 476, 333, 421, 422, 423, 424, 425, + /* 2430 */ 426, 476, 428, 476, 343, 476, 476, 476, 476, 476, + /* 2440 */ 476, 476, 370, 476, 476, 476, 476, 476, 476, 476, + /* 2450 */ 476, 476, 333, 476, 382, 476, 384, 476, 476, 476, + /* 2460 */ 476, 370, 343, 476, 476, 476, 476, 476, 476, 476, + /* 2470 */ 476, 333, 476, 382, 476, 384, 476, 476, 476, 476, + /* 2480 */ 476, 343, 476, 476, 476, 476, 476, 415, 476, 370, + /* 2490 */ 418, 476, 476, 421, 422, 423, 424, 425, 426, 476, + /* 2500 */ 428, 382, 476, 384, 476, 476, 415, 476, 370, 418, + /* 2510 */ 476, 476, 421, 422, 423, 424, 425, 426, 333, 428, + /* 2520 */ 382, 476, 384, 476, 476, 476, 476, 476, 343, 476, + /* 2530 */ 476, 476, 476, 476, 415, 476, 476, 418, 476, 476, + /* 2540 */ 421, 422, 423, 424, 425, 426, 476, 428, 476, 476, + /* 2550 */ 476, 476, 476, 415, 476, 370, 418, 476, 476, 421, + /* 2560 */ 422, 423, 424, 425, 426, 476, 428, 382, 476, 384, + /* 2570 */ 476, 476, 476, 476, 476, 333, 476, 476, 476, 476, + /* 2580 */ 476, 476, 476, 476, 476, 343, 476, 476, 476, 476, + /* 2590 */ 476, 333, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2600 */ 415, 343, 476, 418, 476, 476, 421, 422, 423, 424, + /* 2610 */ 425, 426, 370, 428, 476, 476, 476, 476, 476, 476, + /* 2620 */ 476, 476, 476, 476, 382, 476, 384, 476, 370, 476, + /* 2630 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2640 */ 382, 333, 384, 476, 476, 476, 476, 476, 476, 476, + /* 2650 */ 476, 343, 476, 476, 476, 476, 476, 415, 476, 476, + /* 2660 */ 418, 333, 476, 421, 422, 423, 424, 425, 426, 476, + /* 2670 */ 428, 343, 476, 415, 476, 476, 418, 476, 370, 421, + /* 2680 */ 422, 423, 424, 425, 426, 476, 428, 476, 476, 476, + /* 2690 */ 382, 476, 384, 476, 476, 476, 476, 476, 370, 476, + /* 2700 */ 476, 476, 476, 476, 476, 476, 476, 476, 333, 476, + /* 2710 */ 382, 476, 384, 476, 476, 476, 476, 476, 343, 476, + /* 2720 */ 476, 476, 476, 415, 476, 476, 418, 476, 476, 421, + /* 2730 */ 422, 423, 424, 425, 426, 476, 428, 476, 476, 476, + /* 2740 */ 476, 476, 33, 415, 476, 370, 418, 476, 476, 421, + /* 2750 */ 422, 423, 424, 425, 426, 476, 428, 382, 49, 384, + /* 2760 */ 476, 476, 476, 476, 55, 56, 57, 58, 59, 476, + /* 2770 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2780 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2790 */ 415, 476, 476, 418, 476, 476, 421, 422, 423, 424, + /* 2800 */ 425, 426, 476, 428, 476, 476, 476, 476, 99, 476, + /* 2810 */ 476, 102, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2820 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2830 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2840 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2850 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2860 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2870 */ 476, 476, 476, 476, 476, 476, 476, 476, 169, 170, + /* 2880 */ 476, 476, 476, 174, 476, 176, 476, 476, 476, 476, + /* 2890 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2900 */ 476, 476, 476, 194, 476, 476, 476, 476, 476, 476, + /* 2910 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2920 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2930 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2940 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2950 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2960 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2970 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2980 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 2990 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 3000 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 3010 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 3020 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 3030 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 3040 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 3050 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 3060 */ 476, 476, 476, 476, 476, 476, 476, 476, 476, 476, + /* 3070 */ 476, 476, 476, 330, 330, 330, 330, 330, 330, 330, + /* 3080 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3090 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3100 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3110 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3120 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3130 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3140 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3150 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3160 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3170 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3180 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3190 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3200 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3210 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3220 */ 330, 330, 330, 330, 330, 330, 330, 330, 330, 330, + /* 3230 */ 330, 330, 330, 330, }; -#define YY_SHIFT_COUNT (715) +#define YY_SHIFT_COUNT (761) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (2108) +#define YY_SHIFT_MAX (2709) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 133, 0, 71, 0, 289, 289, 289, 289, 289, 289, - /* 10 */ 289, 289, 289, 360, 576, 576, 647, 576, 576, 576, - /* 20 */ 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, - /* 30 */ 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, - /* 40 */ 576, 576, 576, 576, 576, 576, 59, 225, 110, 293, - /* 50 */ 58, 281, 473, 281, 110, 110, 940, 940, 940, 281, - /* 60 */ 940, 940, 347, 281, 78, 78, 422, 422, 36, 51, - /* 70 */ 230, 230, 78, 78, 78, 78, 78, 78, 78, 217, - /* 80 */ 78, 78, 299, 78, 78, 355, 78, 434, 78, 217, - /* 90 */ 456, 78, 78, 456, 78, 456, 456, 456, 78, 475, - /* 100 */ 786, 610, 610, 503, 112, 1116, 1116, 1116, 1116, 1116, - /* 110 */ 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, 1116, - /* 120 */ 1116, 1116, 1116, 1116, 563, 357, 36, 51, 413, 117, - /* 130 */ 220, 220, 220, 429, 379, 379, 117, 525, 525, 525, - /* 140 */ 343, 434, 174, 456, 532, 456, 532, 532, 343, 595, - /* 150 */ 323, 323, 323, 323, 323, 323, 323, 1601, 523, 181, - /* 160 */ 712, 809, 441, 581, 439, 674, 730, 790, 663, 967, - /* 170 */ 655, 939, 808, 588, 802, 808, 1042, 834, 956, 1106, - /* 180 */ 1329, 1202, 1346, 1372, 1346, 1235, 1379, 1379, 1346, 1235, - /* 190 */ 1235, 1314, 1379, 1379, 1379, 1401, 1401, 1404, 299, 434, - /* 200 */ 299, 1414, 1427, 299, 1414, 299, 299, 299, 1379, 299, - /* 210 */ 1403, 1403, 1401, 456, 456, 456, 456, 456, 456, 456, - /* 220 */ 456, 456, 456, 456, 1379, 1401, 532, 532, 532, 1269, - /* 230 */ 1404, 475, 1284, 434, 475, 1379, 1372, 1372, 532, 1228, - /* 240 */ 1231, 532, 1228, 1231, 532, 532, 456, 1233, 1326, 1228, - /* 250 */ 1237, 1240, 1257, 1106, 1241, 1249, 1255, 1278, 525, 1516, - /* 260 */ 1379, 1414, 475, 1519, 1231, 532, 532, 532, 532, 532, - /* 270 */ 1231, 532, 1402, 475, 343, 475, 525, 1475, 1480, 532, - /* 280 */ 595, 1379, 475, 1548, 1401, 2733, 2733, 2733, 2733, 2733, - /* 290 */ 2733, 2733, 2733, 2733, 828, 1034, 457, 295, 260, 549, - /* 300 */ 759, 969, 874, 1033, 1227, 1211, 1279, 1279, 1279, 1279, - /* 310 */ 1279, 1279, 1279, 1279, 1279, 1041, 125, 13, 13, 506, - /* 320 */ 400, 516, 615, 587, 297, 297, 353, 53, 248, 353, - /* 330 */ 353, 353, 283, 1058, 572, 1043, 987, 1023, 1022, 1037, - /* 340 */ 1085, 1175, 1081, 1083, 1153, 915, 1079, 1098, 1100, 1101, - /* 350 */ 994, 990, 1057, 98, 1159, 1185, 1201, 1203, 1204, 1220, - /* 360 */ 1205, 1097, 1120, 1114, 1260, 1259, 1263, 1264, 1266, 1267, - /* 370 */ 1288, 1302, 40, 1122, 1332, 1315, 1327, 1606, 1607, 1423, - /* 380 */ 1611, 1612, 1571, 1614, 1580, 1416, 1583, 1584, 1587, 1430, - /* 390 */ 1623, 1597, 1598, 1435, 1636, 1437, 1638, 1608, 1641, 1620, - /* 400 */ 1645, 1613, 1464, 1470, 1651, 1653, 1484, 1487, 1661, 1678, - /* 410 */ 1617, 1665, 1666, 1667, 1626, 1669, 1670, 1671, 1672, 1673, - /* 420 */ 1674, 1675, 1676, 1529, 1646, 1682, 1533, 1685, 1692, 1696, - /* 430 */ 1697, 1699, 1700, 1701, 1703, 1704, 1705, 1706, 1708, 1710, - /* 440 */ 1711, 1712, 1677, 1713, 1714, 1715, 1716, 1717, 1698, 1718, - /* 450 */ 1721, 1722, 1588, 1724, 1732, 1691, 1727, 1679, 1728, 1681, - /* 460 */ 1729, 1730, 1693, 1694, 1707, 1689, 1733, 1702, 1738, 1719, - /* 470 */ 1740, 1720, 1723, 1753, 1754, 1757, 1731, 1592, 1758, 1759, - /* 480 */ 1765, 1709, 1767, 1772, 1739, 1734, 1736, 1776, 1742, 1735, - /* 490 */ 1741, 1778, 1744, 1745, 1749, 1781, 1755, 1747, 1750, 1784, - /* 500 */ 1792, 1797, 1798, 1737, 1725, 1774, 1780, 1811, 1777, 1779, - /* 510 */ 1782, 1783, 1771, 1775, 1785, 1786, 1794, 1787, 1823, 1802, - /* 520 */ 1825, 1806, 1789, 1831, 1810, 1807, 1843, 1812, 1845, 1813, - /* 530 */ 1846, 1827, 1833, 1815, 1816, 1819, 1760, 1763, 1855, 1743, - /* 540 */ 1826, 1862, 1680, 1842, 1752, 1751, 1865, 1866, 1761, 1748, - /* 550 */ 1864, 1828, 1621, 1788, 1773, 1790, 1791, 1832, 1834, 1793, - /* 560 */ 1804, 1808, 1824, 1801, 1835, 1839, 1854, 1836, 1837, 1622, - /* 570 */ 1829, 1841, 1874, 1838, 1631, 1867, 1887, 1888, 1892, 1893, - /* 580 */ 1895, 1844, 1847, 1879, 1690, 1894, 1885, 1935, 1939, 1941, - /* 590 */ 1689, 1897, 1851, 1852, 1868, 1856, 1863, 1796, 1871, 1942, - /* 600 */ 1908, 1799, 1881, 1869, 1689, 1903, 1916, 1762, 1764, 1768, - /* 610 */ 1975, 1956, 1795, 1884, 1886, 1889, 1890, 1898, 1896, 1933, - /* 620 */ 1900, 1902, 1934, 1904, 1961, 1800, 1907, 1882, 1909, 1950, - /* 630 */ 1952, 1912, 1913, 1954, 1915, 1918, 1964, 1917, 1919, 1969, - /* 640 */ 1921, 1922, 1982, 1924, 1901, 1905, 1906, 1910, 1981, 1914, - /* 650 */ 1928, 1983, 1931, 1993, 1936, 1983, 1983, 2010, 1970, 1973, - /* 660 */ 1998, 2004, 2005, 2006, 2008, 2009, 2016, 2019, 2020, 2021, - /* 670 */ 1987, 1966, 2015, 2025, 2026, 2028, 2042, 2030, 2032, 2033, - /* 680 */ 2007, 1771, 2040, 1775, 2043, 2044, 2045, 2046, 2060, 2050, - /* 690 */ 2086, 2052, 2041, 2049, 2090, 2056, 2047, 2055, 2093, 2061, - /* 700 */ 2053, 2059, 2100, 2067, 2057, 2064, 2104, 2071, 2072, 2108, - /* 710 */ 2087, 2089, 2091, 2094, 2096, 2092, + /* 0 */ 550, 0, 224, 0, 449, 449, 449, 449, 449, 449, + /* 10 */ 449, 449, 449, 449, 449, 449, 673, 897, 897, 1121, + /* 20 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 30 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 40 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 148, + /* 50 */ 368, 93, 64, 140, 147, 322, 147, 64, 64, 1346, + /* 60 */ 1346, 1346, 147, 1346, 1346, 314, 147, 76, 369, 111, + /* 70 */ 111, 369, 656, 656, 18, 327, 7, 7, 111, 111, + /* 80 */ 111, 111, 111, 111, 111, 145, 111, 111, 248, 76, + /* 90 */ 111, 111, 363, 111, 76, 111, 145, 111, 145, 76, + /* 100 */ 111, 111, 76, 111, 76, 76, 76, 111, 343, 223, + /* 110 */ 189, 189, 405, 114, 443, 443, 443, 443, 443, 443, + /* 120 */ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443, + /* 130 */ 443, 443, 443, 672, 483, 18, 327, 293, 253, 253, + /* 140 */ 253, 217, 622, 622, 293, 523, 523, 523, 248, 460, + /* 150 */ 354, 76, 585, 76, 585, 585, 604, 670, 35, 35, + /* 160 */ 35, 35, 35, 35, 35, 35, 1897, 636, 15, 167, + /* 170 */ 16, 297, 515, 252, 454, 454, 373, 842, 389, 484, + /* 180 */ 1058, 1163, 862, 892, 922, 983, 45, 922, 878, 727, + /* 190 */ 948, 1136, 1347, 1214, 1358, 1382, 1358, 1239, 1390, 1390, + /* 200 */ 1358, 1239, 1239, 1313, 1329, 1390, 1338, 1390, 1390, 1390, + /* 210 */ 1435, 1408, 1435, 1408, 1442, 248, 1457, 248, 1460, 1471, + /* 220 */ 248, 1460, 248, 248, 248, 1390, 248, 1440, 1440, 1435, + /* 230 */ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, + /* 240 */ 76, 1390, 1435, 585, 585, 585, 1311, 1427, 1442, 343, + /* 250 */ 1356, 1359, 1457, 343, 1362, 1390, 1382, 1382, 585, 1298, + /* 260 */ 1307, 585, 1298, 1307, 585, 585, 76, 1314, 1407, 1298, + /* 270 */ 1317, 1319, 1335, 1136, 1315, 1323, 1327, 1345, 523, 1579, + /* 280 */ 1390, 1460, 343, 343, 1587, 1307, 585, 585, 585, 585, + /* 290 */ 585, 1307, 585, 1445, 343, 604, 343, 523, 1528, 1529, + /* 300 */ 585, 670, 1390, 343, 1600, 1435, 2904, 2904, 2904, 2904, + /* 310 */ 2904, 2904, 2904, 2904, 2904, 34, 2709, 238, 590, 198, + /* 320 */ 539, 973, 794, 486, 1064, 925, 1030, 48, 48, 48, + /* 330 */ 48, 48, 48, 48, 48, 48, 831, 612, 65, 65, + /* 340 */ 549, 737, 700, 891, 262, 448, 1025, 717, 531, 531, + /* 350 */ 962, 751, 906, 962, 962, 962, 1202, 1015, 513, 1219, + /* 360 */ 1008, 1101, 1194, 1104, 1113, 1149, 1159, 381, 1229, 1248, + /* 370 */ 1259, 1267, 1069, 1196, 1221, 1217, 1231, 1233, 1234, 1143, + /* 380 */ 836, 1152, 1165, 1260, 1262, 1273, 1276, 1277, 1318, 1281, + /* 390 */ 1283, 1208, 1284, 1238, 1320, 1321, 1326, 1328, 1336, 1343, + /* 400 */ 671, 1265, 1266, 1255, 1289, 1325, 1366, 1666, 1667, 1669, + /* 410 */ 1631, 1674, 1640, 1468, 1642, 1643, 1644, 1472, 1682, 1648, + /* 420 */ 1649, 1477, 1687, 1480, 1689, 1655, 1699, 1670, 1693, 1659, + /* 430 */ 1500, 1508, 1511, 1701, 1702, 1704, 1523, 1526, 1708, 1715, + /* 440 */ 1672, 1717, 1720, 1722, 1683, 1724, 1726, 1729, 1733, 1735, + /* 450 */ 1736, 1743, 1745, 1591, 1712, 1748, 1594, 1750, 1753, 1754, + /* 460 */ 1764, 1765, 1767, 1768, 1775, 1777, 1778, 1779, 1781, 1782, + /* 470 */ 1784, 1785, 1786, 1716, 1759, 1760, 1761, 1791, 1792, 1793, + /* 480 */ 1772, 1795, 1796, 1797, 1618, 1798, 1800, 1780, 1756, 1783, + /* 490 */ 1758, 1807, 1749, 1776, 1810, 1755, 1812, 1762, 1813, 1816, + /* 500 */ 1788, 1787, 1774, 1773, 1799, 1805, 1802, 1822, 1811, 1789, + /* 510 */ 1823, 1824, 1827, 1794, 1658, 1832, 1838, 1839, 1790, 1853, + /* 520 */ 1855, 1825, 1814, 1828, 1861, 1842, 1829, 1835, 1879, 1845, + /* 530 */ 1833, 1844, 1885, 1858, 1846, 1862, 1902, 1912, 1914, 1915, + /* 540 */ 1808, 1815, 1884, 1898, 1921, 1888, 1889, 1891, 1893, 1894, + /* 550 */ 1896, 1899, 1895, 1900, 1903, 1905, 1910, 1907, 1933, 1913, + /* 560 */ 1943, 1923, 1886, 1947, 1927, 1916, 1959, 1922, 1960, 1928, + /* 570 */ 1962, 1948, 1952, 1938, 1939, 1940, 1875, 1877, 1978, 1817, + /* 580 */ 1880, 1809, 1944, 1961, 1982, 1806, 1964, 1830, 1831, 1997, + /* 590 */ 2000, 1836, 1834, 2002, 1963, 1752, 1906, 1909, 1911, 1965, + /* 600 */ 1917, 1966, 1920, 1918, 1968, 1973, 1919, 1924, 1926, 1929, + /* 610 */ 1931, 1974, 1975, 1976, 1934, 1977, 1771, 1932, 1935, 2025, + /* 620 */ 1993, 1801, 2003, 2005, 2006, 2010, 2011, 2012, 1949, 1950, + /* 630 */ 1992, 1818, 2008, 2001, 2049, 2054, 2055, 2056, 1958, 2020, + /* 640 */ 1773, 2013, 1967, 1969, 1971, 1979, 1987, 1890, 1989, 2063, + /* 650 */ 2026, 1904, 1995, 1954, 1773, 2022, 2033, 1998, 1856, 1999, + /* 660 */ 2096, 2077, 1887, 2009, 2007, 2019, 2021, 2023, 2028, 2057, + /* 670 */ 2024, 2030, 2058, 2039, 2079, 1925, 2043, 2015, 2044, 2068, + /* 680 */ 2071, 2046, 2047, 2076, 2050, 2048, 2086, 2051, 2052, 2109, + /* 690 */ 2060, 2053, 2117, 2061, 1990, 2034, 2035, 2036, 2062, 2111, + /* 700 */ 2064, 2128, 2065, 2111, 2111, 2144, 2101, 2103, 2135, 2136, + /* 710 */ 2141, 2142, 2152, 2154, 2155, 2156, 2120, 2099, 2129, 2160, + /* 720 */ 2162, 2163, 2177, 2165, 2166, 2167, 2131, 1895, 2169, 1900, + /* 730 */ 2170, 2172, 2174, 2176, 2190, 2178, 2214, 2180, 2168, 2179, + /* 740 */ 2220, 2188, 2175, 2192, 2234, 2201, 2189, 2198, 2239, 2205, + /* 750 */ 2193, 2206, 2246, 2218, 2221, 2267, 2236, 2238, 2240, 2241, + /* 760 */ 2243, 2245, }; -#define YY_REDUCE_COUNT (293) -#define YY_REDUCE_MIN (-414) -#define YY_REDUCE_MAX (2320) +#define YY_REDUCE_COUNT (314) +#define YY_REDUCE_MIN (-397) +#define YY_REDUCE_MAX (2375) static const short yy_reduce_ofst[] = { - /* 0 */ -292, -297, -8, 233, 597, 620, 706, 783, 807, 852, - /* 10 */ 907, 963, 1008, 1031, 1119, -320, 54, 1135, 1191, 1219, - /* 20 */ 1281, 1336, 1398, 1428, 1486, 1502, 1547, 1563, 1640, 1664, - /* 30 */ 1726, 1756, 1814, 1830, 1875, 1891, 1968, 1992, 2054, 2084, - /* 40 */ 2142, 2158, 2203, 2219, 2296, 2320, -193, 256, 320, -383, - /* 50 */ -332, -110, 605, 893, 302, 642, -337, -16, 273, -414, - /* 60 */ -352, -171, 284, 310, -235, -199, -331, -187, -340, -368, - /* 70 */ -255, -167, -304, -106, 190, 313, 387, 622, 623, -288, - /* 80 */ 631, 784, 50, 817, 897, -43, 902, -213, 917, 35, - /* 90 */ -159, 918, 937, -32, 998, -1, 255, 4, 630, -22, - /* 100 */ 144, -411, -411, 215, -240, -312, 219, 301, 383, 389, - /* 110 */ 436, 510, 513, 550, 552, 571, 593, 619, 621, 629, - /* 120 */ 640, 688, 692, 697, -346, -228, -109, -329, 195, 173, - /* 130 */ -228, 254, 339, -31, 199, 341, 470, 454, 583, 584, - /* 140 */ -226, 224, 363, 616, 462, 627, 682, 694, 600, 636, - /* 150 */ -343, 318, 364, 396, 452, 519, 526, 309, 659, 670, - /* 160 */ 657, 635, 734, 738, 766, 869, 869, 891, 857, 910, - /* 170 */ 900, 904, 856, 856, 899, 856, 927, 919, 869, 957, - /* 180 */ 979, 992, 1013, 1012, 1016, 1020, 1065, 1066, 1025, 1029, - /* 190 */ 1032, 1068, 1074, 1077, 1084, 1093, 1094, 1030, 1087, 1053, - /* 200 */ 1089, 1099, 1059, 1107, 1115, 1109, 1111, 1112, 1121, 1113, - /* 210 */ 1123, 1125, 1128, 1102, 1108, 1110, 1117, 1118, 1124, 1126, - /* 220 */ 1129, 1130, 1131, 1133, 1132, 1136, 1088, 1103, 1127, 1061, - /* 230 */ 1075, 1134, 1078, 1105, 1140, 1145, 1090, 1138, 1139, 1045, - /* 240 */ 1137, 1141, 1054, 1144, 1142, 1143, 869, 1052, 1056, 1062, - /* 250 */ 1064, 1070, 1069, 1148, 1055, 1080, 1082, 856, 1166, 1146, - /* 260 */ 1216, 1217, 1199, 1168, 1169, 1183, 1187, 1188, 1189, 1190, - /* 270 */ 1170, 1192, 1186, 1229, 1218, 1232, 1207, 1152, 1214, 1208, - /* 280 */ 1230, 1245, 1242, 1253, 1258, 1194, 1195, 1215, 1222, 1236, - /* 290 */ 1243, 1252, 1254, 1280, + /* 0 */ -156, 364, -82, 588, -20, 614, 804, 890, 1024, 1050, + /* 10 */ 1118, 1222, 1288, 1316, 1348, 1419, 174, -333, 154, 450, + /* 20 */ 674, 1447, 1097, 1482, 1466, 1543, 1566, 1660, 1692, 1710, + /* 30 */ 1757, 1804, 1826, 1851, 1873, 1937, 1957, 1972, 2004, 2072, + /* 40 */ 2091, 2119, 2138, 2185, 2242, 2258, 2308, 2328, 2375, 383, + /* 50 */ 270, -397, 83, -395, 371, 416, 554, 75, 501, 235, + /* 60 */ 786, 827, -139, 683, 834, -195, -165, -359, -80, -172, + /* 70 */ -13, -383, -254, -207, -213, 149, -52, 290, -152, -5, + /* 80 */ 263, 376, 407, 413, 453, 82, 508, 593, 462, 271, + /* 90 */ 610, 631, 275, 657, 374, 725, 301, 745, 372, -170, + /* 100 */ 748, 796, 399, 808, -83, 421, 605, 810, 260, -319, + /* 110 */ -338, -338, -293, -327, 94, 237, 433, 502, 534, 669, + /* 120 */ 693, 712, 802, 807, 809, 813, 815, 833, 849, 854, + /* 130 */ 865, 867, 868, -275, -251, -131, 355, 467, -251, 437, + /* 140 */ 559, 452, 445, 479, 726, -334, -85, 719, 681, 168, + /* 150 */ 736, 268, 134, 805, 797, 799, 742, 850, -369, 387, + /* 160 */ 499, 580, 713, 832, 913, 713, 637, 927, 485, 899, + /* 170 */ 818, 835, 949, 839, 941, 945, 940, 940, 980, 939, + /* 180 */ 1032, 1028, 994, 984, 933, 933, 919, 933, 947, 938, + /* 190 */ 940, 974, 976, 996, 1012, 1011, 1018, 1022, 1070, 1071, + /* 200 */ 1026, 1027, 1037, 1063, 1073, 1089, 1083, 1094, 1096, 1099, + /* 210 */ 1123, 1127, 1125, 1130, 1060, 1132, 1100, 1137, 1142, 1090, + /* 220 */ 1144, 1151, 1146, 1147, 1148, 1157, 1153, 1154, 1158, 1169, + /* 230 */ 1138, 1139, 1140, 1141, 1156, 1160, 1161, 1167, 1168, 1175, + /* 240 */ 1177, 1164, 1172, 1131, 1134, 1135, 1110, 1116, 1119, 1187, + /* 250 */ 1145, 1155, 1176, 1201, 1162, 1224, 1179, 1180, 1174, 1108, + /* 260 */ 1171, 1191, 1126, 1184, 1203, 1204, 940, 1128, 1133, 1166, + /* 270 */ 1150, 1170, 1173, 1178, 1122, 1182, 1185, 933, 1251, 1181, + /* 280 */ 1261, 1258, 1263, 1264, 1213, 1212, 1228, 1232, 1235, 1236, + /* 290 */ 1237, 1216, 1241, 1226, 1268, 1269, 1279, 1282, 1192, 1278, + /* 300 */ 1250, 1274, 1291, 1290, 1303, 1306, 1252, 1243, 1244, 1270, + /* 310 */ 1296, 1299, 1300, 1322, 1334, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 10 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 20 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 30 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 40 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 50 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 60 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1863, 1608, - /* 70 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 80 */ 1608, 1608, 1686, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 90 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1684, - /* 100 */ 1856, 2058, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 110 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 120 */ 1608, 1608, 1608, 1608, 1608, 2070, 1608, 1608, 1686, 1608, - /* 130 */ 2070, 2070, 2070, 1684, 2030, 2030, 1608, 1608, 1608, 1608, - /* 140 */ 1793, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1793, 1608, - /* 150 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1902, 1608, 1608, - /* 160 */ 2095, 2150, 1608, 1608, 2098, 1608, 1608, 1608, 1868, 1608, - /* 170 */ 1746, 2085, 2062, 2076, 2134, 2063, 2060, 2079, 1608, 2089, - /* 180 */ 1608, 1895, 1861, 1608, 1861, 1858, 1608, 1608, 1861, 1858, - /* 190 */ 1858, 1737, 1608, 1608, 1608, 1608, 1608, 1608, 1686, 1608, - /* 200 */ 1686, 1608, 1608, 1686, 1608, 1686, 1686, 1686, 1608, 1686, - /* 210 */ 1665, 1665, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 220 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1917, - /* 230 */ 1608, 1684, 1904, 1608, 1684, 1608, 1608, 1608, 1608, 2105, - /* 240 */ 2103, 1608, 2105, 2103, 1608, 1608, 1608, 2119, 2115, 2105, - /* 250 */ 2123, 2121, 2091, 2089, 2153, 2140, 2136, 2076, 1608, 1608, - /* 260 */ 1608, 1608, 1684, 1608, 2103, 1608, 1608, 1608, 1608, 1608, - /* 270 */ 2103, 1608, 1608, 1684, 1608, 1684, 1608, 1608, 1762, 1608, - /* 280 */ 1608, 1608, 1684, 1640, 1608, 1897, 1908, 1880, 1880, 1796, - /* 290 */ 1796, 1796, 1687, 1613, 1608, 1608, 1608, 1608, 1608, 1608, - /* 300 */ 1608, 1608, 1608, 1608, 1608, 1608, 2118, 2117, 1986, 1608, - /* 310 */ 2034, 2033, 2032, 2023, 1985, 1758, 1608, 1984, 1983, 1608, - /* 320 */ 1608, 1608, 1608, 1608, 1876, 1875, 1977, 1608, 1608, 1978, - /* 330 */ 1976, 1975, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 340 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 350 */ 1608, 2137, 2141, 1608, 1608, 1608, 1608, 1608, 1608, 2059, - /* 360 */ 1608, 1608, 1608, 1608, 1608, 1959, 1608, 1608, 1608, 1608, - /* 370 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 380 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 390 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 400 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 410 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 420 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 430 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 440 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 450 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 460 */ 1608, 1608, 1608, 1608, 1645, 1964, 1608, 1608, 1608, 1608, - /* 470 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 480 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 490 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 500 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 510 */ 1608, 1608, 1725, 1724, 1608, 1608, 1608, 1608, 1608, 1608, - /* 520 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 530 */ 1608, 1608, 1608, 1608, 1608, 1608, 1968, 1608, 1608, 1608, - /* 540 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 550 */ 2133, 2092, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 560 */ 1608, 1608, 1608, 1608, 1608, 1608, 1959, 1608, 2116, 1608, - /* 570 */ 1608, 2131, 1608, 2135, 1608, 1608, 1608, 1608, 1608, 1608, - /* 580 */ 1608, 2069, 2065, 1608, 1608, 2061, 1608, 1608, 1608, 1608, - /* 590 */ 1967, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 600 */ 1608, 1608, 1608, 1608, 1958, 1608, 2020, 1608, 1608, 1608, - /* 610 */ 2054, 1608, 1608, 2005, 1608, 1608, 1608, 1608, 1608, 1608, - /* 620 */ 1608, 1608, 1608, 1968, 1608, 1971, 1608, 1608, 1608, 1608, - /* 630 */ 1608, 1790, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 640 */ 1608, 1608, 1608, 1608, 1775, 1773, 1772, 1771, 1608, 1768, - /* 650 */ 1608, 1803, 1608, 1608, 1608, 1799, 1798, 1608, 1608, 1608, - /* 660 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 670 */ 1608, 1608, 1705, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 680 */ 1608, 1697, 1608, 1696, 1608, 1608, 1608, 1608, 1608, 1608, - /* 690 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 700 */ 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, 1608, - /* 710 */ 1608, 1608, 1608, 1608, 1608, 1608, + /* 0 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 10 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 20 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 30 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 40 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 50 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 60 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 70 */ 1719, 1719, 1719, 1719, 1992, 1719, 1719, 1719, 1719, 1719, + /* 80 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1801, 1719, + /* 90 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 100 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1799, 1985, + /* 110 */ 2206, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 120 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 130 */ 1719, 1719, 1719, 1719, 2218, 1719, 1719, 1719, 2218, 2218, + /* 140 */ 2218, 1799, 2178, 2178, 1719, 1719, 1719, 1719, 1801, 2050, + /* 150 */ 1719, 1719, 1719, 1719, 1719, 1719, 1920, 1719, 1719, 1719, + /* 160 */ 1719, 1719, 1944, 1719, 1719, 1719, 2044, 1719, 1719, 2243, + /* 170 */ 2299, 1719, 1719, 2246, 1719, 1719, 1719, 1719, 1719, 1997, + /* 180 */ 1719, 1719, 1874, 2233, 2210, 2224, 2283, 2211, 2208, 2227, + /* 190 */ 1719, 2237, 1719, 2031, 1990, 1719, 1990, 1987, 1719, 1719, + /* 200 */ 1990, 1987, 1987, 1863, 1859, 1719, 1857, 1719, 1719, 1719, + /* 210 */ 1719, 1766, 1719, 1766, 1719, 1801, 1719, 1801, 1719, 1719, + /* 220 */ 1801, 1719, 1801, 1801, 1801, 1719, 1801, 1779, 1779, 1719, + /* 230 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 240 */ 1719, 1719, 1719, 1719, 1719, 1719, 2062, 2048, 1719, 1799, + /* 250 */ 2042, 2040, 1719, 1799, 2038, 1719, 1719, 1719, 1719, 2254, + /* 260 */ 2252, 1719, 2254, 2252, 1719, 1719, 1719, 2268, 2264, 2254, + /* 270 */ 2272, 2270, 2239, 2237, 2302, 2289, 2285, 2224, 1719, 1719, + /* 280 */ 1719, 1719, 1799, 1799, 1719, 2252, 1719, 1719, 1719, 1719, + /* 290 */ 1719, 2252, 1719, 1719, 1799, 1719, 1799, 1719, 1719, 1890, + /* 300 */ 1719, 1719, 1719, 1799, 1751, 1719, 2033, 2053, 2015, 2015, + /* 310 */ 1923, 1923, 1923, 1802, 1724, 1719, 1719, 1719, 1719, 1719, + /* 320 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 2267, 2266, 2133, + /* 330 */ 1719, 2182, 2181, 2180, 2171, 2132, 1886, 1719, 2131, 2130, + /* 340 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 2006, 2005, + /* 350 */ 2124, 1719, 1719, 2125, 2123, 2122, 1719, 1719, 1719, 1719, + /* 360 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 370 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 380 */ 2286, 2290, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 2207, + /* 390 */ 1719, 1719, 1719, 2106, 1719, 1719, 1719, 1719, 1719, 1719, + /* 400 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 410 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 420 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 430 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 440 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 450 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 460 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 470 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 480 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 490 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 500 */ 1719, 1719, 1756, 2111, 1719, 1719, 1719, 1719, 1719, 1719, + /* 510 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 520 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 530 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 540 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 550 */ 1719, 1719, 1840, 1839, 1719, 1719, 1719, 1719, 1719, 1719, + /* 560 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 570 */ 1719, 1719, 1719, 1719, 1719, 1719, 2115, 1719, 1719, 1719, + /* 580 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 590 */ 1719, 1719, 1719, 2282, 2240, 1719, 1719, 1719, 1719, 1719, + /* 600 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 610 */ 1719, 1719, 1719, 2106, 1719, 2265, 1719, 1719, 2280, 1719, + /* 620 */ 2284, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 2217, 2213, + /* 630 */ 1719, 1719, 2209, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 640 */ 2114, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 650 */ 1719, 1719, 1719, 1719, 2105, 1719, 2168, 1719, 1719, 1719, + /* 660 */ 2202, 1719, 1719, 2153, 1719, 1719, 1719, 1719, 1719, 1719, + /* 670 */ 1719, 1719, 1719, 2115, 1719, 2118, 1719, 1719, 1719, 1719, + /* 680 */ 1719, 1917, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 690 */ 1719, 1719, 1719, 1719, 1902, 1900, 1899, 1898, 1719, 1930, + /* 700 */ 1719, 1719, 1719, 1926, 1925, 1719, 1719, 1719, 1719, 1719, + /* 710 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1820, 1719, + /* 720 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1812, 1719, 1811, + /* 730 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 740 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 750 */ 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, 1719, + /* 760 */ 1719, 1719, }; /********** End of lemon-generated parsing tables *****************************/ @@ -1021,6 +1102,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* READ => nothing */ 0, /* WRITE => nothing */ 0, /* NK_DOT => nothing */ + 0, /* WITH => nothing */ 0, /* DNODE => nothing */ 0, /* PORT => nothing */ 0, /* DNODES => nothing */ @@ -1035,6 +1117,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* USE => nothing */ 0, /* FLUSH => nothing */ 0, /* TRIM => nothing */ + 0, /* COMPACT => nothing */ 0, /* IF => nothing */ 0, /* NOT => nothing */ 0, /* EXISTS => nothing */ @@ -1067,6 +1150,9 @@ static const YYCODETYPE yyFallback[] = { 0, /* TABLE_SUFFIX => nothing */ 0, /* NK_COLON => nothing */ 0, /* MAX_SPEED => nothing */ + 0, /* START => nothing */ + 0, /* TIMESTAMP => nothing */ + 279, /* END => ABORT */ 0, /* TABLE => nothing */ 0, /* NK_LP => nothing */ 0, /* NK_RP => nothing */ @@ -1080,7 +1166,6 @@ static const YYCODETYPE yyFallback[] = { 0, /* NK_EQ => nothing */ 0, /* USING => nothing */ 0, /* TAGS => nothing */ - 0, /* COMMENT => nothing */ 0, /* BOOL => nothing */ 0, /* TINYINT => nothing */ 0, /* SMALLINT => nothing */ @@ -1090,7 +1175,6 @@ static const YYCODETYPE yyFallback[] = { 0, /* FLOAT => nothing */ 0, /* DOUBLE => nothing */ 0, /* BINARY => nothing */ - 0, /* TIMESTAMP => nothing */ 0, /* NCHAR => nothing */ 0, /* UNSIGNED => nothing */ 0, /* JSON => nothing */ @@ -1099,6 +1183,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* BLOB => nothing */ 0, /* VARBINARY => nothing */ 0, /* DECIMAL => nothing */ + 0, /* COMMENT => nothing */ 0, /* MAX_DELAY => nothing */ 0, /* WATERMARK => nothing */ 0, /* ROLLUP => nothing */ @@ -1133,6 +1218,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* CONSUMERS => nothing */ 0, /* SUBSCRIPTIONS => nothing */ 0, /* VNODES => nothing */ + 0, /* ALIVE => nothing */ 0, /* LIKE => nothing */ 0, /* TBNAME => nothing */ 0, /* QTAGS => nothing */ @@ -1140,8 +1226,9 @@ static const YYCODETYPE yyFallback[] = { 0, /* INDEX => nothing */ 0, /* FUNCTION => nothing */ 0, /* INTERVAL => nothing */ + 0, /* COUNT => nothing */ + 0, /* LAST_ROW => nothing */ 0, /* TOPIC => nothing */ - 0, /* WITH => nothing */ 0, /* META => nothing */ 0, /* CONSUMER => nothing */ 0, /* GROUP => nothing */ @@ -1159,6 +1246,8 @@ static const YYCODETYPE yyFallback[] = { 0, /* OUTPUTTYPE => nothing */ 0, /* AGGREGATE => nothing */ 0, /* BUFSIZE => nothing */ + 0, /* LANGUAGE => nothing */ + 0, /* REPLACE => nothing */ 0, /* STREAM => nothing */ 0, /* INTO => nothing */ 0, /* TRIGGER => nothing */ @@ -1174,6 +1263,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* TRANSACTION => nothing */ 0, /* BALANCE => nothing */ 0, /* VGROUP => nothing */ + 0, /* LEADER => nothing */ 0, /* MERGE => nothing */ 0, /* REDISTRIBUTE => nothing */ 0, /* SPLIT => nothing */ @@ -1190,6 +1280,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* WEND => nothing */ 0, /* WDURATION => nothing */ 0, /* IROWTS => nothing */ + 0, /* ISFILLED => nothing */ 0, /* CAST => nothing */ 0, /* NOW => nothing */ 0, /* TODAY => nothing */ @@ -1198,10 +1289,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* SERVER_VERSION => nothing */ 0, /* SERVER_STATUS => nothing */ 0, /* CURRENT_USER => nothing */ - 0, /* COUNT => nothing */ - 0, /* LAST_ROW => nothing */ 0, /* CASE => nothing */ - 271, /* END => ABORT */ 0, /* WHEN => nothing */ 0, /* THEN => nothing */ 0, /* ELSE => nothing */ @@ -1225,6 +1313,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* BY => nothing */ 0, /* SESSION => nothing */ 0, /* STATE_WINDOW => nothing */ + 0, /* EVENT_WINDOW => nothing */ 0, /* SLIDING => nothing */ 0, /* FILL => nothing */ 0, /* VALUE => nothing */ @@ -1245,58 +1334,56 @@ static const YYCODETYPE yyFallback[] = { 0, /* ASC => nothing */ 0, /* NULLS => nothing */ 0, /* ABORT => nothing */ - 271, /* AFTER => ABORT */ - 271, /* ATTACH => ABORT */ - 271, /* BEFORE => ABORT */ - 271, /* BEGIN => ABORT */ - 271, /* BITAND => ABORT */ - 271, /* BITNOT => ABORT */ - 271, /* BITOR => ABORT */ - 271, /* BLOCKS => ABORT */ - 271, /* CHANGE => ABORT */ - 271, /* COMMA => ABORT */ - 271, /* COMPACT => ABORT */ - 271, /* CONCAT => ABORT */ - 271, /* CONFLICT => ABORT */ - 271, /* COPY => ABORT */ - 271, /* DEFERRED => ABORT */ - 271, /* DELIMITERS => ABORT */ - 271, /* DETACH => ABORT */ - 271, /* DIVIDE => ABORT */ - 271, /* DOT => ABORT */ - 271, /* EACH => ABORT */ - 271, /* FAIL => ABORT */ - 271, /* FILE => ABORT */ - 271, /* FOR => ABORT */ - 271, /* GLOB => ABORT */ - 271, /* ID => ABORT */ - 271, /* IMMEDIATE => ABORT */ - 271, /* IMPORT => ABORT */ - 271, /* INITIALLY => ABORT */ - 271, /* INSTEAD => ABORT */ - 271, /* ISNULL => ABORT */ - 271, /* KEY => ABORT */ - 271, /* MODULES => ABORT */ - 271, /* NK_BITNOT => ABORT */ - 271, /* NK_SEMI => ABORT */ - 271, /* NOTNULL => ABORT */ - 271, /* OF => ABORT */ - 271, /* PLUS => ABORT */ - 271, /* PRIVILEGE => ABORT */ - 271, /* RAISE => ABORT */ - 271, /* REPLACE => ABORT */ - 271, /* RESTRICT => ABORT */ - 271, /* ROW => ABORT */ - 271, /* SEMI => ABORT */ - 271, /* STAR => ABORT */ - 271, /* STATEMENT => ABORT */ - 271, /* STRICT => ABORT */ - 271, /* STRING => ABORT */ - 271, /* TIMES => ABORT */ - 271, /* VALUES => ABORT */ - 271, /* VARIABLE => ABORT */ - 271, /* VIEW => ABORT */ - 271, /* WAL => ABORT */ + 279, /* AFTER => ABORT */ + 279, /* ATTACH => ABORT */ + 279, /* BEFORE => ABORT */ + 279, /* BEGIN => ABORT */ + 279, /* BITAND => ABORT */ + 279, /* BITNOT => ABORT */ + 279, /* BITOR => ABORT */ + 279, /* BLOCKS => ABORT */ + 279, /* CHANGE => ABORT */ + 279, /* COMMA => ABORT */ + 279, /* CONCAT => ABORT */ + 279, /* CONFLICT => ABORT */ + 279, /* COPY => ABORT */ + 279, /* DEFERRED => ABORT */ + 279, /* DELIMITERS => ABORT */ + 279, /* DETACH => ABORT */ + 279, /* DIVIDE => ABORT */ + 279, /* DOT => ABORT */ + 279, /* EACH => ABORT */ + 279, /* FAIL => ABORT */ + 279, /* FILE => ABORT */ + 279, /* FOR => ABORT */ + 279, /* GLOB => ABORT */ + 279, /* ID => ABORT */ + 279, /* IMMEDIATE => ABORT */ + 279, /* IMPORT => ABORT */ + 279, /* INITIALLY => ABORT */ + 279, /* INSTEAD => ABORT */ + 279, /* ISNULL => ABORT */ + 279, /* KEY => ABORT */ + 279, /* MODULES => ABORT */ + 279, /* NK_BITNOT => ABORT */ + 279, /* NK_SEMI => ABORT */ + 279, /* NOTNULL => ABORT */ + 279, /* OF => ABORT */ + 279, /* PLUS => ABORT */ + 279, /* PRIVILEGE => ABORT */ + 279, /* RAISE => ABORT */ + 279, /* RESTRICT => ABORT */ + 279, /* ROW => ABORT */ + 279, /* SEMI => ABORT */ + 279, /* STAR => ABORT */ + 279, /* STATEMENT => ABORT */ + 279, /* STRICT => ABORT */ + 279, /* STRING => ABORT */ + 279, /* TIMES => ABORT */ + 279, /* VALUES => ABORT */ + 279, /* VARIABLE => ABORT */ + 279, /* VIEW => ABORT */ + 279, /* WAL => ABORT */ }; #endif /* YYFALLBACK */ @@ -1432,419 +1519,434 @@ static const char *const yyTokenName[] = { /* 45 */ "READ", /* 46 */ "WRITE", /* 47 */ "NK_DOT", - /* 48 */ "DNODE", - /* 49 */ "PORT", - /* 50 */ "DNODES", - /* 51 */ "NK_IPTOKEN", - /* 52 */ "FORCE", - /* 53 */ "LOCAL", - /* 54 */ "QNODE", - /* 55 */ "BNODE", - /* 56 */ "SNODE", - /* 57 */ "MNODE", - /* 58 */ "DATABASE", - /* 59 */ "USE", - /* 60 */ "FLUSH", - /* 61 */ "TRIM", - /* 62 */ "IF", - /* 63 */ "NOT", - /* 64 */ "EXISTS", - /* 65 */ "BUFFER", - /* 66 */ "CACHEMODEL", - /* 67 */ "CACHESIZE", - /* 68 */ "COMP", - /* 69 */ "DURATION", - /* 70 */ "NK_VARIABLE", - /* 71 */ "MAXROWS", - /* 72 */ "MINROWS", - /* 73 */ "KEEP", - /* 74 */ "PAGES", - /* 75 */ "PAGESIZE", - /* 76 */ "TSDB_PAGESIZE", - /* 77 */ "PRECISION", - /* 78 */ "REPLICA", - /* 79 */ "VGROUPS", - /* 80 */ "SINGLE_STABLE", - /* 81 */ "RETENTIONS", - /* 82 */ "SCHEMALESS", - /* 83 */ "WAL_LEVEL", - /* 84 */ "WAL_FSYNC_PERIOD", - /* 85 */ "WAL_RETENTION_PERIOD", - /* 86 */ "WAL_RETENTION_SIZE", - /* 87 */ "WAL_ROLL_PERIOD", - /* 88 */ "WAL_SEGMENT_SIZE", - /* 89 */ "STT_TRIGGER", - /* 90 */ "TABLE_PREFIX", - /* 91 */ "TABLE_SUFFIX", - /* 92 */ "NK_COLON", - /* 93 */ "MAX_SPEED", - /* 94 */ "TABLE", - /* 95 */ "NK_LP", - /* 96 */ "NK_RP", - /* 97 */ "STABLE", - /* 98 */ "ADD", - /* 99 */ "COLUMN", - /* 100 */ "MODIFY", - /* 101 */ "RENAME", - /* 102 */ "TAG", - /* 103 */ "SET", - /* 104 */ "NK_EQ", - /* 105 */ "USING", - /* 106 */ "TAGS", - /* 107 */ "COMMENT", - /* 108 */ "BOOL", - /* 109 */ "TINYINT", - /* 110 */ "SMALLINT", - /* 111 */ "INT", - /* 112 */ "INTEGER", - /* 113 */ "BIGINT", - /* 114 */ "FLOAT", - /* 115 */ "DOUBLE", - /* 116 */ "BINARY", - /* 117 */ "TIMESTAMP", - /* 118 */ "NCHAR", - /* 119 */ "UNSIGNED", - /* 120 */ "JSON", - /* 121 */ "VARCHAR", - /* 122 */ "MEDIUMBLOB", - /* 123 */ "BLOB", - /* 124 */ "VARBINARY", - /* 125 */ "DECIMAL", - /* 126 */ "MAX_DELAY", - /* 127 */ "WATERMARK", - /* 128 */ "ROLLUP", - /* 129 */ "TTL", - /* 130 */ "SMA", - /* 131 */ "DELETE_MARK", - /* 132 */ "FIRST", - /* 133 */ "LAST", - /* 134 */ "SHOW", - /* 135 */ "PRIVILEGES", - /* 136 */ "DATABASES", - /* 137 */ "TABLES", - /* 138 */ "STABLES", - /* 139 */ "MNODES", - /* 140 */ "QNODES", - /* 141 */ "FUNCTIONS", - /* 142 */ "INDEXES", - /* 143 */ "ACCOUNTS", - /* 144 */ "APPS", - /* 145 */ "CONNECTIONS", - /* 146 */ "LICENCES", - /* 147 */ "GRANTS", - /* 148 */ "QUERIES", - /* 149 */ "SCORES", - /* 150 */ "TOPICS", - /* 151 */ "VARIABLES", - /* 152 */ "CLUSTER", - /* 153 */ "BNODES", - /* 154 */ "SNODES", - /* 155 */ "TRANSACTIONS", - /* 156 */ "DISTRIBUTED", - /* 157 */ "CONSUMERS", - /* 158 */ "SUBSCRIPTIONS", - /* 159 */ "VNODES", - /* 160 */ "LIKE", - /* 161 */ "TBNAME", - /* 162 */ "QTAGS", - /* 163 */ "AS", - /* 164 */ "INDEX", - /* 165 */ "FUNCTION", - /* 166 */ "INTERVAL", - /* 167 */ "TOPIC", - /* 168 */ "WITH", - /* 169 */ "META", - /* 170 */ "CONSUMER", - /* 171 */ "GROUP", - /* 172 */ "DESC", - /* 173 */ "DESCRIBE", - /* 174 */ "RESET", - /* 175 */ "QUERY", - /* 176 */ "CACHE", - /* 177 */ "EXPLAIN", - /* 178 */ "ANALYZE", - /* 179 */ "VERBOSE", - /* 180 */ "NK_BOOL", - /* 181 */ "RATIO", - /* 182 */ "NK_FLOAT", - /* 183 */ "OUTPUTTYPE", - /* 184 */ "AGGREGATE", - /* 185 */ "BUFSIZE", - /* 186 */ "STREAM", - /* 187 */ "INTO", - /* 188 */ "TRIGGER", - /* 189 */ "AT_ONCE", - /* 190 */ "WINDOW_CLOSE", - /* 191 */ "IGNORE", - /* 192 */ "EXPIRED", - /* 193 */ "FILL_HISTORY", - /* 194 */ "UPDATE", - /* 195 */ "SUBTABLE", - /* 196 */ "KILL", - /* 197 */ "CONNECTION", - /* 198 */ "TRANSACTION", - /* 199 */ "BALANCE", - /* 200 */ "VGROUP", - /* 201 */ "MERGE", - /* 202 */ "REDISTRIBUTE", - /* 203 */ "SPLIT", - /* 204 */ "DELETE", - /* 205 */ "INSERT", - /* 206 */ "NULL", - /* 207 */ "NK_QUESTION", - /* 208 */ "NK_ARROW", - /* 209 */ "ROWTS", - /* 210 */ "QSTART", - /* 211 */ "QEND", - /* 212 */ "QDURATION", - /* 213 */ "WSTART", - /* 214 */ "WEND", - /* 215 */ "WDURATION", - /* 216 */ "IROWTS", - /* 217 */ "CAST", - /* 218 */ "NOW", - /* 219 */ "TODAY", - /* 220 */ "TIMEZONE", - /* 221 */ "CLIENT_VERSION", - /* 222 */ "SERVER_VERSION", - /* 223 */ "SERVER_STATUS", - /* 224 */ "CURRENT_USER", - /* 225 */ "COUNT", - /* 226 */ "LAST_ROW", - /* 227 */ "CASE", - /* 228 */ "END", - /* 229 */ "WHEN", - /* 230 */ "THEN", - /* 231 */ "ELSE", - /* 232 */ "BETWEEN", - /* 233 */ "IS", - /* 234 */ "NK_LT", - /* 235 */ "NK_GT", - /* 236 */ "NK_LE", - /* 237 */ "NK_GE", - /* 238 */ "NK_NE", - /* 239 */ "MATCH", - /* 240 */ "NMATCH", - /* 241 */ "CONTAINS", - /* 242 */ "IN", - /* 243 */ "JOIN", - /* 244 */ "INNER", - /* 245 */ "SELECT", - /* 246 */ "DISTINCT", - /* 247 */ "WHERE", - /* 248 */ "PARTITION", - /* 249 */ "BY", - /* 250 */ "SESSION", - /* 251 */ "STATE_WINDOW", - /* 252 */ "SLIDING", - /* 253 */ "FILL", - /* 254 */ "VALUE", - /* 255 */ "VALUE_F", - /* 256 */ "NONE", - /* 257 */ "PREV", - /* 258 */ "NULL_F", - /* 259 */ "LINEAR", - /* 260 */ "NEXT", - /* 261 */ "HAVING", - /* 262 */ "RANGE", - /* 263 */ "EVERY", - /* 264 */ "ORDER", - /* 265 */ "SLIMIT", - /* 266 */ "SOFFSET", - /* 267 */ "LIMIT", - /* 268 */ "OFFSET", - /* 269 */ "ASC", - /* 270 */ "NULLS", - /* 271 */ "ABORT", - /* 272 */ "AFTER", - /* 273 */ "ATTACH", - /* 274 */ "BEFORE", - /* 275 */ "BEGIN", - /* 276 */ "BITAND", - /* 277 */ "BITNOT", - /* 278 */ "BITOR", - /* 279 */ "BLOCKS", - /* 280 */ "CHANGE", - /* 281 */ "COMMA", - /* 282 */ "COMPACT", - /* 283 */ "CONCAT", - /* 284 */ "CONFLICT", - /* 285 */ "COPY", - /* 286 */ "DEFERRED", - /* 287 */ "DELIMITERS", - /* 288 */ "DETACH", - /* 289 */ "DIVIDE", - /* 290 */ "DOT", - /* 291 */ "EACH", - /* 292 */ "FAIL", - /* 293 */ "FILE", - /* 294 */ "FOR", - /* 295 */ "GLOB", - /* 296 */ "ID", - /* 297 */ "IMMEDIATE", - /* 298 */ "IMPORT", - /* 299 */ "INITIALLY", - /* 300 */ "INSTEAD", - /* 301 */ "ISNULL", - /* 302 */ "KEY", - /* 303 */ "MODULES", - /* 304 */ "NK_BITNOT", - /* 305 */ "NK_SEMI", - /* 306 */ "NOTNULL", - /* 307 */ "OF", - /* 308 */ "PLUS", - /* 309 */ "PRIVILEGE", - /* 310 */ "RAISE", - /* 311 */ "REPLACE", - /* 312 */ "RESTRICT", - /* 313 */ "ROW", - /* 314 */ "SEMI", - /* 315 */ "STAR", - /* 316 */ "STATEMENT", - /* 317 */ "STRICT", - /* 318 */ "STRING", - /* 319 */ "TIMES", - /* 320 */ "VALUES", - /* 321 */ "VARIABLE", - /* 322 */ "VIEW", - /* 323 */ "WAL", - /* 324 */ "cmd", - /* 325 */ "account_options", - /* 326 */ "alter_account_options", - /* 327 */ "literal", - /* 328 */ "alter_account_option", - /* 329 */ "user_name", - /* 330 */ "sysinfo_opt", - /* 331 */ "privileges", - /* 332 */ "priv_level", - /* 333 */ "priv_type_list", - /* 334 */ "priv_type", - /* 335 */ "db_name", - /* 336 */ "topic_name", - /* 337 */ "dnode_endpoint", - /* 338 */ "force_opt", - /* 339 */ "not_exists_opt", - /* 340 */ "db_options", - /* 341 */ "exists_opt", - /* 342 */ "alter_db_options", - /* 343 */ "speed_opt", - /* 344 */ "integer_list", - /* 345 */ "variable_list", - /* 346 */ "retention_list", - /* 347 */ "alter_db_option", - /* 348 */ "retention", - /* 349 */ "full_table_name", - /* 350 */ "column_def_list", - /* 351 */ "tags_def_opt", - /* 352 */ "table_options", - /* 353 */ "multi_create_clause", - /* 354 */ "tags_def", - /* 355 */ "multi_drop_clause", - /* 356 */ "alter_table_clause", - /* 357 */ "alter_table_options", - /* 358 */ "column_name", - /* 359 */ "type_name", - /* 360 */ "signed_literal", - /* 361 */ "create_subtable_clause", - /* 362 */ "specific_cols_opt", - /* 363 */ "expression_list", - /* 364 */ "drop_table_clause", - /* 365 */ "col_name_list", - /* 366 */ "table_name", - /* 367 */ "column_def", - /* 368 */ "duration_list", - /* 369 */ "rollup_func_list", - /* 370 */ "alter_table_option", - /* 371 */ "duration_literal", - /* 372 */ "rollup_func_name", - /* 373 */ "function_name", - /* 374 */ "col_name", - /* 375 */ "db_name_cond_opt", - /* 376 */ "like_pattern_opt", - /* 377 */ "table_name_cond", - /* 378 */ "from_db_opt", - /* 379 */ "tag_list_opt", - /* 380 */ "tag_item", - /* 381 */ "column_alias", - /* 382 */ "full_index_name", - /* 383 */ "index_options", - /* 384 */ "index_name", - /* 385 */ "func_list", - /* 386 */ "sliding_opt", - /* 387 */ "sma_stream_opt", - /* 388 */ "func", - /* 389 */ "query_or_subquery", - /* 390 */ "cgroup_name", - /* 391 */ "analyze_opt", - /* 392 */ "explain_options", - /* 393 */ "agg_func_opt", - /* 394 */ "bufsize_opt", - /* 395 */ "stream_name", - /* 396 */ "stream_options", - /* 397 */ "subtable_opt", - /* 398 */ "expression", - /* 399 */ "dnode_list", - /* 400 */ "where_clause_opt", - /* 401 */ "signed", - /* 402 */ "literal_func", - /* 403 */ "literal_list", - /* 404 */ "table_alias", - /* 405 */ "expr_or_subquery", - /* 406 */ "pseudo_column", - /* 407 */ "column_reference", - /* 408 */ "function_expression", - /* 409 */ "case_when_expression", - /* 410 */ "star_func", - /* 411 */ "star_func_para_list", - /* 412 */ "noarg_func", - /* 413 */ "other_para_list", - /* 414 */ "star_func_para", - /* 415 */ "when_then_list", - /* 416 */ "case_when_else_opt", - /* 417 */ "common_expression", - /* 418 */ "when_then_expr", - /* 419 */ "predicate", - /* 420 */ "compare_op", - /* 421 */ "in_op", - /* 422 */ "in_predicate_value", - /* 423 */ "boolean_value_expression", - /* 424 */ "boolean_primary", - /* 425 */ "from_clause_opt", - /* 426 */ "table_reference_list", - /* 427 */ "table_reference", - /* 428 */ "table_primary", - /* 429 */ "joined_table", - /* 430 */ "alias_opt", - /* 431 */ "subquery", - /* 432 */ "parenthesized_joined_table", - /* 433 */ "join_type", - /* 434 */ "search_condition", - /* 435 */ "query_specification", - /* 436 */ "set_quantifier_opt", - /* 437 */ "select_list", - /* 438 */ "partition_by_clause_opt", - /* 439 */ "range_opt", - /* 440 */ "every_opt", - /* 441 */ "fill_opt", - /* 442 */ "twindow_clause_opt", - /* 443 */ "group_by_clause_opt", - /* 444 */ "having_clause_opt", - /* 445 */ "select_item", - /* 446 */ "partition_list", - /* 447 */ "partition_item", - /* 448 */ "fill_mode", - /* 449 */ "group_by_list", - /* 450 */ "query_expression", - /* 451 */ "query_simple", - /* 452 */ "order_by_clause_opt", - /* 453 */ "slimit_clause_opt", - /* 454 */ "limit_clause_opt", - /* 455 */ "union_query_expression", - /* 456 */ "query_simple_or_subquery", - /* 457 */ "sort_specification_list", - /* 458 */ "sort_specification", - /* 459 */ "ordering_specification_opt", - /* 460 */ "null_ordering_opt", + /* 48 */ "WITH", + /* 49 */ "DNODE", + /* 50 */ "PORT", + /* 51 */ "DNODES", + /* 52 */ "NK_IPTOKEN", + /* 53 */ "FORCE", + /* 54 */ "LOCAL", + /* 55 */ "QNODE", + /* 56 */ "BNODE", + /* 57 */ "SNODE", + /* 58 */ "MNODE", + /* 59 */ "DATABASE", + /* 60 */ "USE", + /* 61 */ "FLUSH", + /* 62 */ "TRIM", + /* 63 */ "COMPACT", + /* 64 */ "IF", + /* 65 */ "NOT", + /* 66 */ "EXISTS", + /* 67 */ "BUFFER", + /* 68 */ "CACHEMODEL", + /* 69 */ "CACHESIZE", + /* 70 */ "COMP", + /* 71 */ "DURATION", + /* 72 */ "NK_VARIABLE", + /* 73 */ "MAXROWS", + /* 74 */ "MINROWS", + /* 75 */ "KEEP", + /* 76 */ "PAGES", + /* 77 */ "PAGESIZE", + /* 78 */ "TSDB_PAGESIZE", + /* 79 */ "PRECISION", + /* 80 */ "REPLICA", + /* 81 */ "VGROUPS", + /* 82 */ "SINGLE_STABLE", + /* 83 */ "RETENTIONS", + /* 84 */ "SCHEMALESS", + /* 85 */ "WAL_LEVEL", + /* 86 */ "WAL_FSYNC_PERIOD", + /* 87 */ "WAL_RETENTION_PERIOD", + /* 88 */ "WAL_RETENTION_SIZE", + /* 89 */ "WAL_ROLL_PERIOD", + /* 90 */ "WAL_SEGMENT_SIZE", + /* 91 */ "STT_TRIGGER", + /* 92 */ "TABLE_PREFIX", + /* 93 */ "TABLE_SUFFIX", + /* 94 */ "NK_COLON", + /* 95 */ "MAX_SPEED", + /* 96 */ "START", + /* 97 */ "TIMESTAMP", + /* 98 */ "END", + /* 99 */ "TABLE", + /* 100 */ "NK_LP", + /* 101 */ "NK_RP", + /* 102 */ "STABLE", + /* 103 */ "ADD", + /* 104 */ "COLUMN", + /* 105 */ "MODIFY", + /* 106 */ "RENAME", + /* 107 */ "TAG", + /* 108 */ "SET", + /* 109 */ "NK_EQ", + /* 110 */ "USING", + /* 111 */ "TAGS", + /* 112 */ "BOOL", + /* 113 */ "TINYINT", + /* 114 */ "SMALLINT", + /* 115 */ "INT", + /* 116 */ "INTEGER", + /* 117 */ "BIGINT", + /* 118 */ "FLOAT", + /* 119 */ "DOUBLE", + /* 120 */ "BINARY", + /* 121 */ "NCHAR", + /* 122 */ "UNSIGNED", + /* 123 */ "JSON", + /* 124 */ "VARCHAR", + /* 125 */ "MEDIUMBLOB", + /* 126 */ "BLOB", + /* 127 */ "VARBINARY", + /* 128 */ "DECIMAL", + /* 129 */ "COMMENT", + /* 130 */ "MAX_DELAY", + /* 131 */ "WATERMARK", + /* 132 */ "ROLLUP", + /* 133 */ "TTL", + /* 134 */ "SMA", + /* 135 */ "DELETE_MARK", + /* 136 */ "FIRST", + /* 137 */ "LAST", + /* 138 */ "SHOW", + /* 139 */ "PRIVILEGES", + /* 140 */ "DATABASES", + /* 141 */ "TABLES", + /* 142 */ "STABLES", + /* 143 */ "MNODES", + /* 144 */ "QNODES", + /* 145 */ "FUNCTIONS", + /* 146 */ "INDEXES", + /* 147 */ "ACCOUNTS", + /* 148 */ "APPS", + /* 149 */ "CONNECTIONS", + /* 150 */ "LICENCES", + /* 151 */ "GRANTS", + /* 152 */ "QUERIES", + /* 153 */ "SCORES", + /* 154 */ "TOPICS", + /* 155 */ "VARIABLES", + /* 156 */ "CLUSTER", + /* 157 */ "BNODES", + /* 158 */ "SNODES", + /* 159 */ "TRANSACTIONS", + /* 160 */ "DISTRIBUTED", + /* 161 */ "CONSUMERS", + /* 162 */ "SUBSCRIPTIONS", + /* 163 */ "VNODES", + /* 164 */ "ALIVE", + /* 165 */ "LIKE", + /* 166 */ "TBNAME", + /* 167 */ "QTAGS", + /* 168 */ "AS", + /* 169 */ "INDEX", + /* 170 */ "FUNCTION", + /* 171 */ "INTERVAL", + /* 172 */ "COUNT", + /* 173 */ "LAST_ROW", + /* 174 */ "TOPIC", + /* 175 */ "META", + /* 176 */ "CONSUMER", + /* 177 */ "GROUP", + /* 178 */ "DESC", + /* 179 */ "DESCRIBE", + /* 180 */ "RESET", + /* 181 */ "QUERY", + /* 182 */ "CACHE", + /* 183 */ "EXPLAIN", + /* 184 */ "ANALYZE", + /* 185 */ "VERBOSE", + /* 186 */ "NK_BOOL", + /* 187 */ "RATIO", + /* 188 */ "NK_FLOAT", + /* 189 */ "OUTPUTTYPE", + /* 190 */ "AGGREGATE", + /* 191 */ "BUFSIZE", + /* 192 */ "LANGUAGE", + /* 193 */ "REPLACE", + /* 194 */ "STREAM", + /* 195 */ "INTO", + /* 196 */ "TRIGGER", + /* 197 */ "AT_ONCE", + /* 198 */ "WINDOW_CLOSE", + /* 199 */ "IGNORE", + /* 200 */ "EXPIRED", + /* 201 */ "FILL_HISTORY", + /* 202 */ "UPDATE", + /* 203 */ "SUBTABLE", + /* 204 */ "KILL", + /* 205 */ "CONNECTION", + /* 206 */ "TRANSACTION", + /* 207 */ "BALANCE", + /* 208 */ "VGROUP", + /* 209 */ "LEADER", + /* 210 */ "MERGE", + /* 211 */ "REDISTRIBUTE", + /* 212 */ "SPLIT", + /* 213 */ "DELETE", + /* 214 */ "INSERT", + /* 215 */ "NULL", + /* 216 */ "NK_QUESTION", + /* 217 */ "NK_ARROW", + /* 218 */ "ROWTS", + /* 219 */ "QSTART", + /* 220 */ "QEND", + /* 221 */ "QDURATION", + /* 222 */ "WSTART", + /* 223 */ "WEND", + /* 224 */ "WDURATION", + /* 225 */ "IROWTS", + /* 226 */ "ISFILLED", + /* 227 */ "CAST", + /* 228 */ "NOW", + /* 229 */ "TODAY", + /* 230 */ "TIMEZONE", + /* 231 */ "CLIENT_VERSION", + /* 232 */ "SERVER_VERSION", + /* 233 */ "SERVER_STATUS", + /* 234 */ "CURRENT_USER", + /* 235 */ "CASE", + /* 236 */ "WHEN", + /* 237 */ "THEN", + /* 238 */ "ELSE", + /* 239 */ "BETWEEN", + /* 240 */ "IS", + /* 241 */ "NK_LT", + /* 242 */ "NK_GT", + /* 243 */ "NK_LE", + /* 244 */ "NK_GE", + /* 245 */ "NK_NE", + /* 246 */ "MATCH", + /* 247 */ "NMATCH", + /* 248 */ "CONTAINS", + /* 249 */ "IN", + /* 250 */ "JOIN", + /* 251 */ "INNER", + /* 252 */ "SELECT", + /* 253 */ "DISTINCT", + /* 254 */ "WHERE", + /* 255 */ "PARTITION", + /* 256 */ "BY", + /* 257 */ "SESSION", + /* 258 */ "STATE_WINDOW", + /* 259 */ "EVENT_WINDOW", + /* 260 */ "SLIDING", + /* 261 */ "FILL", + /* 262 */ "VALUE", + /* 263 */ "VALUE_F", + /* 264 */ "NONE", + /* 265 */ "PREV", + /* 266 */ "NULL_F", + /* 267 */ "LINEAR", + /* 268 */ "NEXT", + /* 269 */ "HAVING", + /* 270 */ "RANGE", + /* 271 */ "EVERY", + /* 272 */ "ORDER", + /* 273 */ "SLIMIT", + /* 274 */ "SOFFSET", + /* 275 */ "LIMIT", + /* 276 */ "OFFSET", + /* 277 */ "ASC", + /* 278 */ "NULLS", + /* 279 */ "ABORT", + /* 280 */ "AFTER", + /* 281 */ "ATTACH", + /* 282 */ "BEFORE", + /* 283 */ "BEGIN", + /* 284 */ "BITAND", + /* 285 */ "BITNOT", + /* 286 */ "BITOR", + /* 287 */ "BLOCKS", + /* 288 */ "CHANGE", + /* 289 */ "COMMA", + /* 290 */ "CONCAT", + /* 291 */ "CONFLICT", + /* 292 */ "COPY", + /* 293 */ "DEFERRED", + /* 294 */ "DELIMITERS", + /* 295 */ "DETACH", + /* 296 */ "DIVIDE", + /* 297 */ "DOT", + /* 298 */ "EACH", + /* 299 */ "FAIL", + /* 300 */ "FILE", + /* 301 */ "FOR", + /* 302 */ "GLOB", + /* 303 */ "ID", + /* 304 */ "IMMEDIATE", + /* 305 */ "IMPORT", + /* 306 */ "INITIALLY", + /* 307 */ "INSTEAD", + /* 308 */ "ISNULL", + /* 309 */ "KEY", + /* 310 */ "MODULES", + /* 311 */ "NK_BITNOT", + /* 312 */ "NK_SEMI", + /* 313 */ "NOTNULL", + /* 314 */ "OF", + /* 315 */ "PLUS", + /* 316 */ "PRIVILEGE", + /* 317 */ "RAISE", + /* 318 */ "RESTRICT", + /* 319 */ "ROW", + /* 320 */ "SEMI", + /* 321 */ "STAR", + /* 322 */ "STATEMENT", + /* 323 */ "STRICT", + /* 324 */ "STRING", + /* 325 */ "TIMES", + /* 326 */ "VALUES", + /* 327 */ "VARIABLE", + /* 328 */ "VIEW", + /* 329 */ "WAL", + /* 330 */ "cmd", + /* 331 */ "account_options", + /* 332 */ "alter_account_options", + /* 333 */ "literal", + /* 334 */ "alter_account_option", + /* 335 */ "user_name", + /* 336 */ "sysinfo_opt", + /* 337 */ "privileges", + /* 338 */ "priv_level", + /* 339 */ "with_opt", + /* 340 */ "priv_type_list", + /* 341 */ "priv_type", + /* 342 */ "db_name", + /* 343 */ "table_name", + /* 344 */ "topic_name", + /* 345 */ "search_condition", + /* 346 */ "dnode_endpoint", + /* 347 */ "force_opt", + /* 348 */ "not_exists_opt", + /* 349 */ "db_options", + /* 350 */ "exists_opt", + /* 351 */ "alter_db_options", + /* 352 */ "speed_opt", + /* 353 */ "start_opt", + /* 354 */ "end_opt", + /* 355 */ "integer_list", + /* 356 */ "variable_list", + /* 357 */ "retention_list", + /* 358 */ "signed", + /* 359 */ "alter_db_option", + /* 360 */ "retention", + /* 361 */ "full_table_name", + /* 362 */ "column_def_list", + /* 363 */ "tags_def_opt", + /* 364 */ "table_options", + /* 365 */ "multi_create_clause", + /* 366 */ "tags_def", + /* 367 */ "multi_drop_clause", + /* 368 */ "alter_table_clause", + /* 369 */ "alter_table_options", + /* 370 */ "column_name", + /* 371 */ "type_name", + /* 372 */ "signed_literal", + /* 373 */ "create_subtable_clause", + /* 374 */ "specific_cols_opt", + /* 375 */ "expression_list", + /* 376 */ "drop_table_clause", + /* 377 */ "col_name_list", + /* 378 */ "column_def", + /* 379 */ "duration_list", + /* 380 */ "rollup_func_list", + /* 381 */ "alter_table_option", + /* 382 */ "duration_literal", + /* 383 */ "rollup_func_name", + /* 384 */ "function_name", + /* 385 */ "col_name", + /* 386 */ "db_name_cond_opt", + /* 387 */ "like_pattern_opt", + /* 388 */ "table_name_cond", + /* 389 */ "from_db_opt", + /* 390 */ "tag_list_opt", + /* 391 */ "tag_item", + /* 392 */ "column_alias", + /* 393 */ "full_index_name", + /* 394 */ "index_options", + /* 395 */ "index_name", + /* 396 */ "func_list", + /* 397 */ "sliding_opt", + /* 398 */ "sma_stream_opt", + /* 399 */ "func", + /* 400 */ "sma_func_name", + /* 401 */ "query_or_subquery", + /* 402 */ "cgroup_name", + /* 403 */ "analyze_opt", + /* 404 */ "explain_options", + /* 405 */ "insert_query", + /* 406 */ "or_replace_opt", + /* 407 */ "agg_func_opt", + /* 408 */ "bufsize_opt", + /* 409 */ "language_opt", + /* 410 */ "stream_name", + /* 411 */ "stream_options", + /* 412 */ "col_list_opt", + /* 413 */ "tag_def_or_ref_opt", + /* 414 */ "subtable_opt", + /* 415 */ "expression", + /* 416 */ "dnode_list", + /* 417 */ "where_clause_opt", + /* 418 */ "literal_func", + /* 419 */ "literal_list", + /* 420 */ "table_alias", + /* 421 */ "expr_or_subquery", + /* 422 */ "pseudo_column", + /* 423 */ "column_reference", + /* 424 */ "function_expression", + /* 425 */ "case_when_expression", + /* 426 */ "star_func", + /* 427 */ "star_func_para_list", + /* 428 */ "noarg_func", + /* 429 */ "other_para_list", + /* 430 */ "star_func_para", + /* 431 */ "when_then_list", + /* 432 */ "case_when_else_opt", + /* 433 */ "common_expression", + /* 434 */ "when_then_expr", + /* 435 */ "predicate", + /* 436 */ "compare_op", + /* 437 */ "in_op", + /* 438 */ "in_predicate_value", + /* 439 */ "boolean_value_expression", + /* 440 */ "boolean_primary", + /* 441 */ "from_clause_opt", + /* 442 */ "table_reference_list", + /* 443 */ "table_reference", + /* 444 */ "table_primary", + /* 445 */ "joined_table", + /* 446 */ "alias_opt", + /* 447 */ "subquery", + /* 448 */ "parenthesized_joined_table", + /* 449 */ "join_type", + /* 450 */ "query_specification", + /* 451 */ "set_quantifier_opt", + /* 452 */ "select_list", + /* 453 */ "partition_by_clause_opt", + /* 454 */ "range_opt", + /* 455 */ "every_opt", + /* 456 */ "fill_opt", + /* 457 */ "twindow_clause_opt", + /* 458 */ "group_by_clause_opt", + /* 459 */ "having_clause_opt", + /* 460 */ "select_item", + /* 461 */ "partition_list", + /* 462 */ "partition_item", + /* 463 */ "fill_mode", + /* 464 */ "group_by_list", + /* 465 */ "query_expression", + /* 466 */ "query_simple", + /* 467 */ "order_by_clause_opt", + /* 468 */ "slimit_clause_opt", + /* 469 */ "limit_clause_opt", + /* 470 */ "union_query_expression", + /* 471 */ "query_simple_or_subquery", + /* 472 */ "sort_specification_list", + /* 473 */ "sort_specification", + /* 474 */ "ordering_specification_opt", + /* 475 */ "null_ordering_opt", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -1883,8 +1985,8 @@ static const char *const yyRuleName[] = { /* 28 */ "cmd ::= DROP USER user_name", /* 29 */ "sysinfo_opt ::=", /* 30 */ "sysinfo_opt ::= SYSINFO NK_INTEGER", - /* 31 */ "cmd ::= GRANT privileges ON priv_level TO user_name", - /* 32 */ "cmd ::= REVOKE privileges ON priv_level FROM user_name", + /* 31 */ "cmd ::= GRANT privileges ON priv_level with_opt TO user_name", + /* 32 */ "cmd ::= REVOKE privileges ON priv_level with_opt FROM user_name", /* 33 */ "privileges ::= ALL", /* 34 */ "privileges ::= priv_type_list", /* 35 */ "privileges ::= SUBSCRIBE", @@ -1894,509 +1996,547 @@ static const char *const yyRuleName[] = { /* 39 */ "priv_type ::= WRITE", /* 40 */ "priv_level ::= NK_STAR NK_DOT NK_STAR", /* 41 */ "priv_level ::= db_name NK_DOT NK_STAR", - /* 42 */ "priv_level ::= topic_name", - /* 43 */ "cmd ::= CREATE DNODE dnode_endpoint", - /* 44 */ "cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER", - /* 45 */ "cmd ::= DROP DNODE NK_INTEGER force_opt", - /* 46 */ "cmd ::= DROP DNODE dnode_endpoint force_opt", - /* 47 */ "cmd ::= ALTER DNODE NK_INTEGER NK_STRING", - /* 48 */ "cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING", - /* 49 */ "cmd ::= ALTER ALL DNODES NK_STRING", - /* 50 */ "cmd ::= ALTER ALL DNODES NK_STRING NK_STRING", - /* 51 */ "dnode_endpoint ::= NK_STRING", - /* 52 */ "dnode_endpoint ::= NK_ID", - /* 53 */ "dnode_endpoint ::= NK_IPTOKEN", - /* 54 */ "force_opt ::=", - /* 55 */ "force_opt ::= FORCE", - /* 56 */ "cmd ::= ALTER LOCAL NK_STRING", - /* 57 */ "cmd ::= ALTER LOCAL NK_STRING NK_STRING", - /* 58 */ "cmd ::= CREATE QNODE ON DNODE NK_INTEGER", - /* 59 */ "cmd ::= DROP QNODE ON DNODE NK_INTEGER", - /* 60 */ "cmd ::= CREATE BNODE ON DNODE NK_INTEGER", - /* 61 */ "cmd ::= DROP BNODE ON DNODE NK_INTEGER", - /* 62 */ "cmd ::= CREATE SNODE ON DNODE NK_INTEGER", - /* 63 */ "cmd ::= DROP SNODE ON DNODE NK_INTEGER", - /* 64 */ "cmd ::= CREATE MNODE ON DNODE NK_INTEGER", - /* 65 */ "cmd ::= DROP MNODE ON DNODE NK_INTEGER", - /* 66 */ "cmd ::= CREATE DATABASE not_exists_opt db_name db_options", - /* 67 */ "cmd ::= DROP DATABASE exists_opt db_name", - /* 68 */ "cmd ::= USE db_name", - /* 69 */ "cmd ::= ALTER DATABASE db_name alter_db_options", - /* 70 */ "cmd ::= FLUSH DATABASE db_name", - /* 71 */ "cmd ::= TRIM DATABASE db_name speed_opt", - /* 72 */ "not_exists_opt ::= IF NOT EXISTS", - /* 73 */ "not_exists_opt ::=", - /* 74 */ "exists_opt ::= IF EXISTS", - /* 75 */ "exists_opt ::=", - /* 76 */ "db_options ::=", - /* 77 */ "db_options ::= db_options BUFFER NK_INTEGER", - /* 78 */ "db_options ::= db_options CACHEMODEL NK_STRING", - /* 79 */ "db_options ::= db_options CACHESIZE NK_INTEGER", - /* 80 */ "db_options ::= db_options COMP NK_INTEGER", - /* 81 */ "db_options ::= db_options DURATION NK_INTEGER", - /* 82 */ "db_options ::= db_options DURATION NK_VARIABLE", - /* 83 */ "db_options ::= db_options MAXROWS NK_INTEGER", - /* 84 */ "db_options ::= db_options MINROWS NK_INTEGER", - /* 85 */ "db_options ::= db_options KEEP integer_list", - /* 86 */ "db_options ::= db_options KEEP variable_list", - /* 87 */ "db_options ::= db_options PAGES NK_INTEGER", - /* 88 */ "db_options ::= db_options PAGESIZE NK_INTEGER", - /* 89 */ "db_options ::= db_options TSDB_PAGESIZE NK_INTEGER", - /* 90 */ "db_options ::= db_options PRECISION NK_STRING", - /* 91 */ "db_options ::= db_options REPLICA NK_INTEGER", - /* 92 */ "db_options ::= db_options VGROUPS NK_INTEGER", - /* 93 */ "db_options ::= db_options SINGLE_STABLE NK_INTEGER", - /* 94 */ "db_options ::= db_options RETENTIONS retention_list", - /* 95 */ "db_options ::= db_options SCHEMALESS NK_INTEGER", - /* 96 */ "db_options ::= db_options WAL_LEVEL NK_INTEGER", - /* 97 */ "db_options ::= db_options WAL_FSYNC_PERIOD NK_INTEGER", - /* 98 */ "db_options ::= db_options WAL_RETENTION_PERIOD NK_INTEGER", - /* 99 */ "db_options ::= db_options WAL_RETENTION_PERIOD NK_MINUS NK_INTEGER", - /* 100 */ "db_options ::= db_options WAL_RETENTION_SIZE NK_INTEGER", - /* 101 */ "db_options ::= db_options WAL_RETENTION_SIZE NK_MINUS NK_INTEGER", - /* 102 */ "db_options ::= db_options WAL_ROLL_PERIOD NK_INTEGER", - /* 103 */ "db_options ::= db_options WAL_SEGMENT_SIZE NK_INTEGER", - /* 104 */ "db_options ::= db_options STT_TRIGGER NK_INTEGER", - /* 105 */ "db_options ::= db_options TABLE_PREFIX NK_INTEGER", - /* 106 */ "db_options ::= db_options TABLE_SUFFIX NK_INTEGER", - /* 107 */ "alter_db_options ::= alter_db_option", - /* 108 */ "alter_db_options ::= alter_db_options alter_db_option", - /* 109 */ "alter_db_option ::= BUFFER NK_INTEGER", - /* 110 */ "alter_db_option ::= CACHEMODEL NK_STRING", - /* 111 */ "alter_db_option ::= CACHESIZE NK_INTEGER", - /* 112 */ "alter_db_option ::= WAL_FSYNC_PERIOD NK_INTEGER", - /* 113 */ "alter_db_option ::= KEEP integer_list", - /* 114 */ "alter_db_option ::= KEEP variable_list", - /* 115 */ "alter_db_option ::= PAGES NK_INTEGER", - /* 116 */ "alter_db_option ::= REPLICA NK_INTEGER", - /* 117 */ "alter_db_option ::= WAL_LEVEL NK_INTEGER", - /* 118 */ "alter_db_option ::= STT_TRIGGER NK_INTEGER", - /* 119 */ "integer_list ::= NK_INTEGER", - /* 120 */ "integer_list ::= integer_list NK_COMMA NK_INTEGER", - /* 121 */ "variable_list ::= NK_VARIABLE", - /* 122 */ "variable_list ::= variable_list NK_COMMA NK_VARIABLE", - /* 123 */ "retention_list ::= retention", - /* 124 */ "retention_list ::= retention_list NK_COMMA retention", - /* 125 */ "retention ::= NK_VARIABLE NK_COLON NK_VARIABLE", - /* 126 */ "speed_opt ::=", - /* 127 */ "speed_opt ::= MAX_SPEED NK_INTEGER", - /* 128 */ "cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options", - /* 129 */ "cmd ::= CREATE TABLE multi_create_clause", - /* 130 */ "cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options", - /* 131 */ "cmd ::= DROP TABLE multi_drop_clause", - /* 132 */ "cmd ::= DROP STABLE exists_opt full_table_name", - /* 133 */ "cmd ::= ALTER TABLE alter_table_clause", - /* 134 */ "cmd ::= ALTER STABLE alter_table_clause", - /* 135 */ "alter_table_clause ::= full_table_name alter_table_options", - /* 136 */ "alter_table_clause ::= full_table_name ADD COLUMN column_name type_name", - /* 137 */ "alter_table_clause ::= full_table_name DROP COLUMN column_name", - /* 138 */ "alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name", - /* 139 */ "alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name", - /* 140 */ "alter_table_clause ::= full_table_name ADD TAG column_name type_name", - /* 141 */ "alter_table_clause ::= full_table_name DROP TAG column_name", - /* 142 */ "alter_table_clause ::= full_table_name MODIFY TAG column_name type_name", - /* 143 */ "alter_table_clause ::= full_table_name RENAME TAG column_name column_name", - /* 144 */ "alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal", - /* 145 */ "multi_create_clause ::= create_subtable_clause", - /* 146 */ "multi_create_clause ::= multi_create_clause create_subtable_clause", - /* 147 */ "create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_cols_opt TAGS NK_LP expression_list NK_RP table_options", - /* 148 */ "multi_drop_clause ::= drop_table_clause", - /* 149 */ "multi_drop_clause ::= multi_drop_clause drop_table_clause", - /* 150 */ "drop_table_clause ::= exists_opt full_table_name", - /* 151 */ "specific_cols_opt ::=", - /* 152 */ "specific_cols_opt ::= NK_LP col_name_list NK_RP", - /* 153 */ "full_table_name ::= table_name", - /* 154 */ "full_table_name ::= db_name NK_DOT table_name", - /* 155 */ "column_def_list ::= column_def", - /* 156 */ "column_def_list ::= column_def_list NK_COMMA column_def", - /* 157 */ "column_def ::= column_name type_name", - /* 158 */ "column_def ::= column_name type_name COMMENT NK_STRING", - /* 159 */ "type_name ::= BOOL", - /* 160 */ "type_name ::= TINYINT", - /* 161 */ "type_name ::= SMALLINT", - /* 162 */ "type_name ::= INT", - /* 163 */ "type_name ::= INTEGER", - /* 164 */ "type_name ::= BIGINT", - /* 165 */ "type_name ::= FLOAT", - /* 166 */ "type_name ::= DOUBLE", - /* 167 */ "type_name ::= BINARY NK_LP NK_INTEGER NK_RP", - /* 168 */ "type_name ::= TIMESTAMP", - /* 169 */ "type_name ::= NCHAR NK_LP NK_INTEGER NK_RP", - /* 170 */ "type_name ::= TINYINT UNSIGNED", - /* 171 */ "type_name ::= SMALLINT UNSIGNED", - /* 172 */ "type_name ::= INT UNSIGNED", - /* 173 */ "type_name ::= BIGINT UNSIGNED", - /* 174 */ "type_name ::= JSON", - /* 175 */ "type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP", - /* 176 */ "type_name ::= MEDIUMBLOB", - /* 177 */ "type_name ::= BLOB", - /* 178 */ "type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP", - /* 179 */ "type_name ::= DECIMAL", - /* 180 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP", - /* 181 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP", - /* 182 */ "tags_def_opt ::=", - /* 183 */ "tags_def_opt ::= tags_def", - /* 184 */ "tags_def ::= TAGS NK_LP column_def_list NK_RP", - /* 185 */ "table_options ::=", - /* 186 */ "table_options ::= table_options COMMENT NK_STRING", - /* 187 */ "table_options ::= table_options MAX_DELAY duration_list", - /* 188 */ "table_options ::= table_options WATERMARK duration_list", - /* 189 */ "table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP", - /* 190 */ "table_options ::= table_options TTL NK_INTEGER", - /* 191 */ "table_options ::= table_options SMA NK_LP col_name_list NK_RP", - /* 192 */ "table_options ::= table_options DELETE_MARK duration_list", - /* 193 */ "alter_table_options ::= alter_table_option", - /* 194 */ "alter_table_options ::= alter_table_options alter_table_option", - /* 195 */ "alter_table_option ::= COMMENT NK_STRING", - /* 196 */ "alter_table_option ::= TTL NK_INTEGER", - /* 197 */ "duration_list ::= duration_literal", - /* 198 */ "duration_list ::= duration_list NK_COMMA duration_literal", - /* 199 */ "rollup_func_list ::= rollup_func_name", - /* 200 */ "rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name", - /* 201 */ "rollup_func_name ::= function_name", - /* 202 */ "rollup_func_name ::= FIRST", - /* 203 */ "rollup_func_name ::= LAST", - /* 204 */ "col_name_list ::= col_name", - /* 205 */ "col_name_list ::= col_name_list NK_COMMA col_name", - /* 206 */ "col_name ::= column_name", - /* 207 */ "cmd ::= SHOW DNODES", - /* 208 */ "cmd ::= SHOW USERS", - /* 209 */ "cmd ::= SHOW USER PRIVILEGES", - /* 210 */ "cmd ::= SHOW DATABASES", - /* 211 */ "cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt", - /* 212 */ "cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt", - /* 213 */ "cmd ::= SHOW db_name_cond_opt VGROUPS", - /* 214 */ "cmd ::= SHOW MNODES", - /* 215 */ "cmd ::= SHOW QNODES", - /* 216 */ "cmd ::= SHOW FUNCTIONS", - /* 217 */ "cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt", - /* 218 */ "cmd ::= SHOW STREAMS", - /* 219 */ "cmd ::= SHOW ACCOUNTS", - /* 220 */ "cmd ::= SHOW APPS", - /* 221 */ "cmd ::= SHOW CONNECTIONS", - /* 222 */ "cmd ::= SHOW LICENCES", - /* 223 */ "cmd ::= SHOW GRANTS", - /* 224 */ "cmd ::= SHOW CREATE DATABASE db_name", - /* 225 */ "cmd ::= SHOW CREATE TABLE full_table_name", - /* 226 */ "cmd ::= SHOW CREATE STABLE full_table_name", - /* 227 */ "cmd ::= SHOW QUERIES", - /* 228 */ "cmd ::= SHOW SCORES", - /* 229 */ "cmd ::= SHOW TOPICS", - /* 230 */ "cmd ::= SHOW VARIABLES", - /* 231 */ "cmd ::= SHOW CLUSTER VARIABLES", - /* 232 */ "cmd ::= SHOW LOCAL VARIABLES", - /* 233 */ "cmd ::= SHOW DNODE NK_INTEGER VARIABLES like_pattern_opt", - /* 234 */ "cmd ::= SHOW BNODES", - /* 235 */ "cmd ::= SHOW SNODES", - /* 236 */ "cmd ::= SHOW CLUSTER", - /* 237 */ "cmd ::= SHOW TRANSACTIONS", - /* 238 */ "cmd ::= SHOW TABLE DISTRIBUTED full_table_name", - /* 239 */ "cmd ::= SHOW CONSUMERS", - /* 240 */ "cmd ::= SHOW SUBSCRIPTIONS", - /* 241 */ "cmd ::= SHOW TAGS FROM table_name_cond from_db_opt", - /* 242 */ "cmd ::= SHOW TABLE TAGS tag_list_opt FROM table_name_cond from_db_opt", - /* 243 */ "cmd ::= SHOW VNODES NK_INTEGER", - /* 244 */ "cmd ::= SHOW VNODES NK_STRING", - /* 245 */ "db_name_cond_opt ::=", - /* 246 */ "db_name_cond_opt ::= db_name NK_DOT", - /* 247 */ "like_pattern_opt ::=", - /* 248 */ "like_pattern_opt ::= LIKE NK_STRING", - /* 249 */ "table_name_cond ::= table_name", - /* 250 */ "from_db_opt ::=", - /* 251 */ "from_db_opt ::= FROM db_name", - /* 252 */ "tag_list_opt ::=", - /* 253 */ "tag_list_opt ::= tag_item", - /* 254 */ "tag_list_opt ::= tag_list_opt NK_COMMA tag_item", - /* 255 */ "tag_item ::= TBNAME", - /* 256 */ "tag_item ::= QTAGS", - /* 257 */ "tag_item ::= column_name", - /* 258 */ "tag_item ::= column_name column_alias", - /* 259 */ "tag_item ::= column_name AS column_alias", - /* 260 */ "cmd ::= CREATE SMA INDEX not_exists_opt full_index_name ON full_table_name index_options", - /* 261 */ "cmd ::= DROP INDEX exists_opt full_index_name", - /* 262 */ "full_index_name ::= index_name", - /* 263 */ "full_index_name ::= db_name NK_DOT index_name", - /* 264 */ "index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt sma_stream_opt", - /* 265 */ "index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt sma_stream_opt", - /* 266 */ "func_list ::= func", - /* 267 */ "func_list ::= func_list NK_COMMA func", - /* 268 */ "func ::= function_name NK_LP expression_list NK_RP", - /* 269 */ "sma_stream_opt ::=", - /* 270 */ "sma_stream_opt ::= sma_stream_opt WATERMARK duration_literal", - /* 271 */ "sma_stream_opt ::= sma_stream_opt MAX_DELAY duration_literal", - /* 272 */ "sma_stream_opt ::= sma_stream_opt DELETE_MARK duration_literal", - /* 273 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_or_subquery", - /* 274 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name", - /* 275 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS DATABASE db_name", - /* 276 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name", - /* 277 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS STABLE full_table_name", - /* 278 */ "cmd ::= DROP TOPIC exists_opt topic_name", - /* 279 */ "cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name", - /* 280 */ "cmd ::= DESC full_table_name", - /* 281 */ "cmd ::= DESCRIBE full_table_name", - /* 282 */ "cmd ::= RESET QUERY CACHE", - /* 283 */ "cmd ::= EXPLAIN analyze_opt explain_options query_or_subquery", - /* 284 */ "analyze_opt ::=", - /* 285 */ "analyze_opt ::= ANALYZE", - /* 286 */ "explain_options ::=", - /* 287 */ "explain_options ::= explain_options VERBOSE NK_BOOL", - /* 288 */ "explain_options ::= explain_options RATIO NK_FLOAT", - /* 289 */ "cmd ::= CREATE agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt", - /* 290 */ "cmd ::= DROP FUNCTION exists_opt function_name", - /* 291 */ "agg_func_opt ::=", - /* 292 */ "agg_func_opt ::= AGGREGATE", - /* 293 */ "bufsize_opt ::=", - /* 294 */ "bufsize_opt ::= BUFSIZE NK_INTEGER", - /* 295 */ "cmd ::= CREATE STREAM not_exists_opt stream_name stream_options INTO full_table_name tags_def_opt subtable_opt AS query_or_subquery", - /* 296 */ "cmd ::= DROP STREAM exists_opt stream_name", - /* 297 */ "stream_options ::=", - /* 298 */ "stream_options ::= stream_options TRIGGER AT_ONCE", - /* 299 */ "stream_options ::= stream_options TRIGGER WINDOW_CLOSE", - /* 300 */ "stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal", - /* 301 */ "stream_options ::= stream_options WATERMARK duration_literal", - /* 302 */ "stream_options ::= stream_options IGNORE EXPIRED NK_INTEGER", - /* 303 */ "stream_options ::= stream_options FILL_HISTORY NK_INTEGER", - /* 304 */ "stream_options ::= stream_options DELETE_MARK duration_literal", - /* 305 */ "stream_options ::= stream_options IGNORE UPDATE NK_INTEGER", - /* 306 */ "subtable_opt ::=", - /* 307 */ "subtable_opt ::= SUBTABLE NK_LP expression NK_RP", - /* 308 */ "cmd ::= KILL CONNECTION NK_INTEGER", - /* 309 */ "cmd ::= KILL QUERY NK_STRING", - /* 310 */ "cmd ::= KILL TRANSACTION NK_INTEGER", - /* 311 */ "cmd ::= BALANCE VGROUP", - /* 312 */ "cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER", - /* 313 */ "cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list", - /* 314 */ "cmd ::= SPLIT VGROUP NK_INTEGER", - /* 315 */ "dnode_list ::= DNODE NK_INTEGER", - /* 316 */ "dnode_list ::= dnode_list DNODE NK_INTEGER", - /* 317 */ "cmd ::= DELETE FROM full_table_name where_clause_opt", - /* 318 */ "cmd ::= query_or_subquery", - /* 319 */ "cmd ::= INSERT INTO full_table_name NK_LP col_name_list NK_RP query_or_subquery", - /* 320 */ "cmd ::= INSERT INTO full_table_name query_or_subquery", - /* 321 */ "literal ::= NK_INTEGER", - /* 322 */ "literal ::= NK_FLOAT", - /* 323 */ "literal ::= NK_STRING", - /* 324 */ "literal ::= NK_BOOL", - /* 325 */ "literal ::= TIMESTAMP NK_STRING", - /* 326 */ "literal ::= duration_literal", - /* 327 */ "literal ::= NULL", - /* 328 */ "literal ::= NK_QUESTION", - /* 329 */ "duration_literal ::= NK_VARIABLE", - /* 330 */ "signed ::= NK_INTEGER", - /* 331 */ "signed ::= NK_PLUS NK_INTEGER", - /* 332 */ "signed ::= NK_MINUS NK_INTEGER", - /* 333 */ "signed ::= NK_FLOAT", - /* 334 */ "signed ::= NK_PLUS NK_FLOAT", - /* 335 */ "signed ::= NK_MINUS NK_FLOAT", - /* 336 */ "signed_literal ::= signed", - /* 337 */ "signed_literal ::= NK_STRING", - /* 338 */ "signed_literal ::= NK_BOOL", - /* 339 */ "signed_literal ::= TIMESTAMP NK_STRING", - /* 340 */ "signed_literal ::= duration_literal", - /* 341 */ "signed_literal ::= NULL", - /* 342 */ "signed_literal ::= literal_func", - /* 343 */ "signed_literal ::= NK_QUESTION", - /* 344 */ "literal_list ::= signed_literal", - /* 345 */ "literal_list ::= literal_list NK_COMMA signed_literal", - /* 346 */ "db_name ::= NK_ID", - /* 347 */ "table_name ::= NK_ID", - /* 348 */ "column_name ::= NK_ID", - /* 349 */ "function_name ::= NK_ID", - /* 350 */ "table_alias ::= NK_ID", - /* 351 */ "column_alias ::= NK_ID", - /* 352 */ "user_name ::= NK_ID", - /* 353 */ "topic_name ::= NK_ID", - /* 354 */ "stream_name ::= NK_ID", - /* 355 */ "cgroup_name ::= NK_ID", - /* 356 */ "index_name ::= NK_ID", - /* 357 */ "expr_or_subquery ::= expression", - /* 358 */ "expression ::= literal", - /* 359 */ "expression ::= pseudo_column", - /* 360 */ "expression ::= column_reference", - /* 361 */ "expression ::= function_expression", - /* 362 */ "expression ::= case_when_expression", - /* 363 */ "expression ::= NK_LP expression NK_RP", - /* 364 */ "expression ::= NK_PLUS expr_or_subquery", - /* 365 */ "expression ::= NK_MINUS expr_or_subquery", - /* 366 */ "expression ::= expr_or_subquery NK_PLUS expr_or_subquery", - /* 367 */ "expression ::= expr_or_subquery NK_MINUS expr_or_subquery", - /* 368 */ "expression ::= expr_or_subquery NK_STAR expr_or_subquery", - /* 369 */ "expression ::= expr_or_subquery NK_SLASH expr_or_subquery", - /* 370 */ "expression ::= expr_or_subquery NK_REM expr_or_subquery", - /* 371 */ "expression ::= column_reference NK_ARROW NK_STRING", - /* 372 */ "expression ::= expr_or_subquery NK_BITAND expr_or_subquery", - /* 373 */ "expression ::= expr_or_subquery NK_BITOR expr_or_subquery", - /* 374 */ "expression_list ::= expr_or_subquery", - /* 375 */ "expression_list ::= expression_list NK_COMMA expr_or_subquery", - /* 376 */ "column_reference ::= column_name", - /* 377 */ "column_reference ::= table_name NK_DOT column_name", - /* 378 */ "pseudo_column ::= ROWTS", - /* 379 */ "pseudo_column ::= TBNAME", - /* 380 */ "pseudo_column ::= table_name NK_DOT TBNAME", - /* 381 */ "pseudo_column ::= QSTART", - /* 382 */ "pseudo_column ::= QEND", - /* 383 */ "pseudo_column ::= QDURATION", - /* 384 */ "pseudo_column ::= WSTART", - /* 385 */ "pseudo_column ::= WEND", - /* 386 */ "pseudo_column ::= WDURATION", - /* 387 */ "pseudo_column ::= IROWTS", - /* 388 */ "pseudo_column ::= QTAGS", - /* 389 */ "function_expression ::= function_name NK_LP expression_list NK_RP", - /* 390 */ "function_expression ::= star_func NK_LP star_func_para_list NK_RP", - /* 391 */ "function_expression ::= CAST NK_LP expr_or_subquery AS type_name NK_RP", - /* 392 */ "function_expression ::= literal_func", - /* 393 */ "literal_func ::= noarg_func NK_LP NK_RP", - /* 394 */ "literal_func ::= NOW", - /* 395 */ "noarg_func ::= NOW", - /* 396 */ "noarg_func ::= TODAY", - /* 397 */ "noarg_func ::= TIMEZONE", - /* 398 */ "noarg_func ::= DATABASE", - /* 399 */ "noarg_func ::= CLIENT_VERSION", - /* 400 */ "noarg_func ::= SERVER_VERSION", - /* 401 */ "noarg_func ::= SERVER_STATUS", - /* 402 */ "noarg_func ::= CURRENT_USER", - /* 403 */ "noarg_func ::= USER", - /* 404 */ "star_func ::= COUNT", - /* 405 */ "star_func ::= FIRST", - /* 406 */ "star_func ::= LAST", - /* 407 */ "star_func ::= LAST_ROW", - /* 408 */ "star_func_para_list ::= NK_STAR", - /* 409 */ "star_func_para_list ::= other_para_list", - /* 410 */ "other_para_list ::= star_func_para", - /* 411 */ "other_para_list ::= other_para_list NK_COMMA star_func_para", - /* 412 */ "star_func_para ::= expr_or_subquery", - /* 413 */ "star_func_para ::= table_name NK_DOT NK_STAR", - /* 414 */ "case_when_expression ::= CASE when_then_list case_when_else_opt END", - /* 415 */ "case_when_expression ::= CASE common_expression when_then_list case_when_else_opt END", - /* 416 */ "when_then_list ::= when_then_expr", - /* 417 */ "when_then_list ::= when_then_list when_then_expr", - /* 418 */ "when_then_expr ::= WHEN common_expression THEN common_expression", - /* 419 */ "case_when_else_opt ::=", - /* 420 */ "case_when_else_opt ::= ELSE common_expression", - /* 421 */ "predicate ::= expr_or_subquery compare_op expr_or_subquery", - /* 422 */ "predicate ::= expr_or_subquery BETWEEN expr_or_subquery AND expr_or_subquery", - /* 423 */ "predicate ::= expr_or_subquery NOT BETWEEN expr_or_subquery AND expr_or_subquery", - /* 424 */ "predicate ::= expr_or_subquery IS NULL", - /* 425 */ "predicate ::= expr_or_subquery IS NOT NULL", - /* 426 */ "predicate ::= expr_or_subquery in_op in_predicate_value", - /* 427 */ "compare_op ::= NK_LT", - /* 428 */ "compare_op ::= NK_GT", - /* 429 */ "compare_op ::= NK_LE", - /* 430 */ "compare_op ::= NK_GE", - /* 431 */ "compare_op ::= NK_NE", - /* 432 */ "compare_op ::= NK_EQ", - /* 433 */ "compare_op ::= LIKE", - /* 434 */ "compare_op ::= NOT LIKE", - /* 435 */ "compare_op ::= MATCH", - /* 436 */ "compare_op ::= NMATCH", - /* 437 */ "compare_op ::= CONTAINS", - /* 438 */ "in_op ::= IN", - /* 439 */ "in_op ::= NOT IN", - /* 440 */ "in_predicate_value ::= NK_LP literal_list NK_RP", - /* 441 */ "boolean_value_expression ::= boolean_primary", - /* 442 */ "boolean_value_expression ::= NOT boolean_primary", - /* 443 */ "boolean_value_expression ::= boolean_value_expression OR boolean_value_expression", - /* 444 */ "boolean_value_expression ::= boolean_value_expression AND boolean_value_expression", - /* 445 */ "boolean_primary ::= predicate", - /* 446 */ "boolean_primary ::= NK_LP boolean_value_expression NK_RP", - /* 447 */ "common_expression ::= expr_or_subquery", - /* 448 */ "common_expression ::= boolean_value_expression", - /* 449 */ "from_clause_opt ::=", - /* 450 */ "from_clause_opt ::= FROM table_reference_list", - /* 451 */ "table_reference_list ::= table_reference", - /* 452 */ "table_reference_list ::= table_reference_list NK_COMMA table_reference", - /* 453 */ "table_reference ::= table_primary", - /* 454 */ "table_reference ::= joined_table", - /* 455 */ "table_primary ::= table_name alias_opt", - /* 456 */ "table_primary ::= db_name NK_DOT table_name alias_opt", - /* 457 */ "table_primary ::= subquery alias_opt", - /* 458 */ "table_primary ::= parenthesized_joined_table", - /* 459 */ "alias_opt ::=", - /* 460 */ "alias_opt ::= table_alias", - /* 461 */ "alias_opt ::= AS table_alias", - /* 462 */ "parenthesized_joined_table ::= NK_LP joined_table NK_RP", - /* 463 */ "parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP", - /* 464 */ "joined_table ::= table_reference join_type JOIN table_reference ON search_condition", - /* 465 */ "join_type ::=", - /* 466 */ "join_type ::= INNER", - /* 467 */ "query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt", - /* 468 */ "set_quantifier_opt ::=", - /* 469 */ "set_quantifier_opt ::= DISTINCT", - /* 470 */ "set_quantifier_opt ::= ALL", - /* 471 */ "select_list ::= select_item", - /* 472 */ "select_list ::= select_list NK_COMMA select_item", - /* 473 */ "select_item ::= NK_STAR", - /* 474 */ "select_item ::= common_expression", - /* 475 */ "select_item ::= common_expression column_alias", - /* 476 */ "select_item ::= common_expression AS column_alias", - /* 477 */ "select_item ::= table_name NK_DOT NK_STAR", - /* 478 */ "where_clause_opt ::=", - /* 479 */ "where_clause_opt ::= WHERE search_condition", - /* 480 */ "partition_by_clause_opt ::=", - /* 481 */ "partition_by_clause_opt ::= PARTITION BY partition_list", - /* 482 */ "partition_list ::= partition_item", - /* 483 */ "partition_list ::= partition_list NK_COMMA partition_item", - /* 484 */ "partition_item ::= expr_or_subquery", - /* 485 */ "partition_item ::= expr_or_subquery column_alias", - /* 486 */ "partition_item ::= expr_or_subquery AS column_alias", - /* 487 */ "twindow_clause_opt ::=", - /* 488 */ "twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP", - /* 489 */ "twindow_clause_opt ::= STATE_WINDOW NK_LP expr_or_subquery NK_RP", - /* 490 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt", - /* 491 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt", - /* 492 */ "sliding_opt ::=", - /* 493 */ "sliding_opt ::= SLIDING NK_LP duration_literal NK_RP", - /* 494 */ "fill_opt ::=", - /* 495 */ "fill_opt ::= FILL NK_LP fill_mode NK_RP", - /* 496 */ "fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP", - /* 497 */ "fill_opt ::= FILL NK_LP VALUE_F NK_COMMA literal_list NK_RP", - /* 498 */ "fill_mode ::= NONE", - /* 499 */ "fill_mode ::= PREV", - /* 500 */ "fill_mode ::= NULL", - /* 501 */ "fill_mode ::= NULL_F", - /* 502 */ "fill_mode ::= LINEAR", - /* 503 */ "fill_mode ::= NEXT", - /* 504 */ "group_by_clause_opt ::=", - /* 505 */ "group_by_clause_opt ::= GROUP BY group_by_list", - /* 506 */ "group_by_list ::= expr_or_subquery", - /* 507 */ "group_by_list ::= group_by_list NK_COMMA expr_or_subquery", - /* 508 */ "having_clause_opt ::=", - /* 509 */ "having_clause_opt ::= HAVING search_condition", - /* 510 */ "range_opt ::=", - /* 511 */ "range_opt ::= RANGE NK_LP expr_or_subquery NK_COMMA expr_or_subquery NK_RP", - /* 512 */ "every_opt ::=", - /* 513 */ "every_opt ::= EVERY NK_LP duration_literal NK_RP", - /* 514 */ "query_expression ::= query_simple order_by_clause_opt slimit_clause_opt limit_clause_opt", - /* 515 */ "query_simple ::= query_specification", - /* 516 */ "query_simple ::= union_query_expression", - /* 517 */ "union_query_expression ::= query_simple_or_subquery UNION ALL query_simple_or_subquery", - /* 518 */ "union_query_expression ::= query_simple_or_subquery UNION query_simple_or_subquery", - /* 519 */ "query_simple_or_subquery ::= query_simple", - /* 520 */ "query_simple_or_subquery ::= subquery", - /* 521 */ "query_or_subquery ::= query_expression", - /* 522 */ "query_or_subquery ::= subquery", - /* 523 */ "order_by_clause_opt ::=", - /* 524 */ "order_by_clause_opt ::= ORDER BY sort_specification_list", - /* 525 */ "slimit_clause_opt ::=", - /* 526 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER", - /* 527 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER", - /* 528 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER", - /* 529 */ "limit_clause_opt ::=", - /* 530 */ "limit_clause_opt ::= LIMIT NK_INTEGER", - /* 531 */ "limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER", - /* 532 */ "limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER", - /* 533 */ "subquery ::= NK_LP query_expression NK_RP", - /* 534 */ "subquery ::= NK_LP subquery NK_RP", - /* 535 */ "search_condition ::= common_expression", - /* 536 */ "sort_specification_list ::= sort_specification", - /* 537 */ "sort_specification_list ::= sort_specification_list NK_COMMA sort_specification", - /* 538 */ "sort_specification ::= expr_or_subquery ordering_specification_opt null_ordering_opt", - /* 539 */ "ordering_specification_opt ::=", - /* 540 */ "ordering_specification_opt ::= ASC", - /* 541 */ "ordering_specification_opt ::= DESC", - /* 542 */ "null_ordering_opt ::=", - /* 543 */ "null_ordering_opt ::= NULLS FIRST", - /* 544 */ "null_ordering_opt ::= NULLS LAST", + /* 42 */ "priv_level ::= db_name NK_DOT table_name", + /* 43 */ "priv_level ::= topic_name", + /* 44 */ "with_opt ::=", + /* 45 */ "with_opt ::= WITH search_condition", + /* 46 */ "cmd ::= CREATE DNODE dnode_endpoint", + /* 47 */ "cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER", + /* 48 */ "cmd ::= DROP DNODE NK_INTEGER force_opt", + /* 49 */ "cmd ::= DROP DNODE dnode_endpoint force_opt", + /* 50 */ "cmd ::= ALTER DNODE NK_INTEGER NK_STRING", + /* 51 */ "cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING", + /* 52 */ "cmd ::= ALTER ALL DNODES NK_STRING", + /* 53 */ "cmd ::= ALTER ALL DNODES NK_STRING NK_STRING", + /* 54 */ "dnode_endpoint ::= NK_STRING", + /* 55 */ "dnode_endpoint ::= NK_ID", + /* 56 */ "dnode_endpoint ::= NK_IPTOKEN", + /* 57 */ "force_opt ::=", + /* 58 */ "force_opt ::= FORCE", + /* 59 */ "cmd ::= ALTER LOCAL NK_STRING", + /* 60 */ "cmd ::= ALTER LOCAL NK_STRING NK_STRING", + /* 61 */ "cmd ::= CREATE QNODE ON DNODE NK_INTEGER", + /* 62 */ "cmd ::= DROP QNODE ON DNODE NK_INTEGER", + /* 63 */ "cmd ::= CREATE BNODE ON DNODE NK_INTEGER", + /* 64 */ "cmd ::= DROP BNODE ON DNODE NK_INTEGER", + /* 65 */ "cmd ::= CREATE SNODE ON DNODE NK_INTEGER", + /* 66 */ "cmd ::= DROP SNODE ON DNODE NK_INTEGER", + /* 67 */ "cmd ::= CREATE MNODE ON DNODE NK_INTEGER", + /* 68 */ "cmd ::= DROP MNODE ON DNODE NK_INTEGER", + /* 69 */ "cmd ::= CREATE DATABASE not_exists_opt db_name db_options", + /* 70 */ "cmd ::= DROP DATABASE exists_opt db_name", + /* 71 */ "cmd ::= USE db_name", + /* 72 */ "cmd ::= ALTER DATABASE db_name alter_db_options", + /* 73 */ "cmd ::= FLUSH DATABASE db_name", + /* 74 */ "cmd ::= TRIM DATABASE db_name speed_opt", + /* 75 */ "cmd ::= COMPACT DATABASE db_name start_opt end_opt", + /* 76 */ "not_exists_opt ::= IF NOT EXISTS", + /* 77 */ "not_exists_opt ::=", + /* 78 */ "exists_opt ::= IF EXISTS", + /* 79 */ "exists_opt ::=", + /* 80 */ "db_options ::=", + /* 81 */ "db_options ::= db_options BUFFER NK_INTEGER", + /* 82 */ "db_options ::= db_options CACHEMODEL NK_STRING", + /* 83 */ "db_options ::= db_options CACHESIZE NK_INTEGER", + /* 84 */ "db_options ::= db_options COMP NK_INTEGER", + /* 85 */ "db_options ::= db_options DURATION NK_INTEGER", + /* 86 */ "db_options ::= db_options DURATION NK_VARIABLE", + /* 87 */ "db_options ::= db_options MAXROWS NK_INTEGER", + /* 88 */ "db_options ::= db_options MINROWS NK_INTEGER", + /* 89 */ "db_options ::= db_options KEEP integer_list", + /* 90 */ "db_options ::= db_options KEEP variable_list", + /* 91 */ "db_options ::= db_options PAGES NK_INTEGER", + /* 92 */ "db_options ::= db_options PAGESIZE NK_INTEGER", + /* 93 */ "db_options ::= db_options TSDB_PAGESIZE NK_INTEGER", + /* 94 */ "db_options ::= db_options PRECISION NK_STRING", + /* 95 */ "db_options ::= db_options REPLICA NK_INTEGER", + /* 96 */ "db_options ::= db_options VGROUPS NK_INTEGER", + /* 97 */ "db_options ::= db_options SINGLE_STABLE NK_INTEGER", + /* 98 */ "db_options ::= db_options RETENTIONS retention_list", + /* 99 */ "db_options ::= db_options SCHEMALESS NK_INTEGER", + /* 100 */ "db_options ::= db_options WAL_LEVEL NK_INTEGER", + /* 101 */ "db_options ::= db_options WAL_FSYNC_PERIOD NK_INTEGER", + /* 102 */ "db_options ::= db_options WAL_RETENTION_PERIOD NK_INTEGER", + /* 103 */ "db_options ::= db_options WAL_RETENTION_PERIOD NK_MINUS NK_INTEGER", + /* 104 */ "db_options ::= db_options WAL_RETENTION_SIZE NK_INTEGER", + /* 105 */ "db_options ::= db_options WAL_RETENTION_SIZE NK_MINUS NK_INTEGER", + /* 106 */ "db_options ::= db_options WAL_ROLL_PERIOD NK_INTEGER", + /* 107 */ "db_options ::= db_options WAL_SEGMENT_SIZE NK_INTEGER", + /* 108 */ "db_options ::= db_options STT_TRIGGER NK_INTEGER", + /* 109 */ "db_options ::= db_options TABLE_PREFIX signed", + /* 110 */ "db_options ::= db_options TABLE_SUFFIX signed", + /* 111 */ "alter_db_options ::= alter_db_option", + /* 112 */ "alter_db_options ::= alter_db_options alter_db_option", + /* 113 */ "alter_db_option ::= BUFFER NK_INTEGER", + /* 114 */ "alter_db_option ::= CACHEMODEL NK_STRING", + /* 115 */ "alter_db_option ::= CACHESIZE NK_INTEGER", + /* 116 */ "alter_db_option ::= WAL_FSYNC_PERIOD NK_INTEGER", + /* 117 */ "alter_db_option ::= KEEP integer_list", + /* 118 */ "alter_db_option ::= KEEP variable_list", + /* 119 */ "alter_db_option ::= PAGES NK_INTEGER", + /* 120 */ "alter_db_option ::= REPLICA NK_INTEGER", + /* 121 */ "alter_db_option ::= WAL_LEVEL NK_INTEGER", + /* 122 */ "alter_db_option ::= STT_TRIGGER NK_INTEGER", + /* 123 */ "alter_db_option ::= MINROWS NK_INTEGER", + /* 124 */ "alter_db_option ::= WAL_RETENTION_PERIOD NK_INTEGER", + /* 125 */ "alter_db_option ::= WAL_RETENTION_PERIOD NK_MINUS NK_INTEGER", + /* 126 */ "alter_db_option ::= WAL_RETENTION_SIZE NK_INTEGER", + /* 127 */ "alter_db_option ::= WAL_RETENTION_SIZE NK_MINUS NK_INTEGER", + /* 128 */ "integer_list ::= NK_INTEGER", + /* 129 */ "integer_list ::= integer_list NK_COMMA NK_INTEGER", + /* 130 */ "variable_list ::= NK_VARIABLE", + /* 131 */ "variable_list ::= variable_list NK_COMMA NK_VARIABLE", + /* 132 */ "retention_list ::= retention", + /* 133 */ "retention_list ::= retention_list NK_COMMA retention", + /* 134 */ "retention ::= NK_VARIABLE NK_COLON NK_VARIABLE", + /* 135 */ "speed_opt ::=", + /* 136 */ "speed_opt ::= MAX_SPEED NK_INTEGER", + /* 137 */ "start_opt ::=", + /* 138 */ "start_opt ::= START WITH NK_INTEGER", + /* 139 */ "start_opt ::= START WITH NK_STRING", + /* 140 */ "start_opt ::= START WITH TIMESTAMP NK_STRING", + /* 141 */ "end_opt ::=", + /* 142 */ "end_opt ::= END WITH NK_INTEGER", + /* 143 */ "end_opt ::= END WITH NK_STRING", + /* 144 */ "end_opt ::= END WITH TIMESTAMP NK_STRING", + /* 145 */ "cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options", + /* 146 */ "cmd ::= CREATE TABLE multi_create_clause", + /* 147 */ "cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options", + /* 148 */ "cmd ::= DROP TABLE multi_drop_clause", + /* 149 */ "cmd ::= DROP STABLE exists_opt full_table_name", + /* 150 */ "cmd ::= ALTER TABLE alter_table_clause", + /* 151 */ "cmd ::= ALTER STABLE alter_table_clause", + /* 152 */ "alter_table_clause ::= full_table_name alter_table_options", + /* 153 */ "alter_table_clause ::= full_table_name ADD COLUMN column_name type_name", + /* 154 */ "alter_table_clause ::= full_table_name DROP COLUMN column_name", + /* 155 */ "alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name", + /* 156 */ "alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name", + /* 157 */ "alter_table_clause ::= full_table_name ADD TAG column_name type_name", + /* 158 */ "alter_table_clause ::= full_table_name DROP TAG column_name", + /* 159 */ "alter_table_clause ::= full_table_name MODIFY TAG column_name type_name", + /* 160 */ "alter_table_clause ::= full_table_name RENAME TAG column_name column_name", + /* 161 */ "alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal", + /* 162 */ "multi_create_clause ::= create_subtable_clause", + /* 163 */ "multi_create_clause ::= multi_create_clause create_subtable_clause", + /* 164 */ "create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_cols_opt TAGS NK_LP expression_list NK_RP table_options", + /* 165 */ "multi_drop_clause ::= drop_table_clause", + /* 166 */ "multi_drop_clause ::= multi_drop_clause NK_COMMA drop_table_clause", + /* 167 */ "drop_table_clause ::= exists_opt full_table_name", + /* 168 */ "specific_cols_opt ::=", + /* 169 */ "specific_cols_opt ::= NK_LP col_name_list NK_RP", + /* 170 */ "full_table_name ::= table_name", + /* 171 */ "full_table_name ::= db_name NK_DOT table_name", + /* 172 */ "column_def_list ::= column_def", + /* 173 */ "column_def_list ::= column_def_list NK_COMMA column_def", + /* 174 */ "column_def ::= column_name type_name", + /* 175 */ "type_name ::= BOOL", + /* 176 */ "type_name ::= TINYINT", + /* 177 */ "type_name ::= SMALLINT", + /* 178 */ "type_name ::= INT", + /* 179 */ "type_name ::= INTEGER", + /* 180 */ "type_name ::= BIGINT", + /* 181 */ "type_name ::= FLOAT", + /* 182 */ "type_name ::= DOUBLE", + /* 183 */ "type_name ::= BINARY NK_LP NK_INTEGER NK_RP", + /* 184 */ "type_name ::= TIMESTAMP", + /* 185 */ "type_name ::= NCHAR NK_LP NK_INTEGER NK_RP", + /* 186 */ "type_name ::= TINYINT UNSIGNED", + /* 187 */ "type_name ::= SMALLINT UNSIGNED", + /* 188 */ "type_name ::= INT UNSIGNED", + /* 189 */ "type_name ::= BIGINT UNSIGNED", + /* 190 */ "type_name ::= JSON", + /* 191 */ "type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP", + /* 192 */ "type_name ::= MEDIUMBLOB", + /* 193 */ "type_name ::= BLOB", + /* 194 */ "type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP", + /* 195 */ "type_name ::= DECIMAL", + /* 196 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP", + /* 197 */ "type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP", + /* 198 */ "tags_def_opt ::=", + /* 199 */ "tags_def_opt ::= tags_def", + /* 200 */ "tags_def ::= TAGS NK_LP column_def_list NK_RP", + /* 201 */ "table_options ::=", + /* 202 */ "table_options ::= table_options COMMENT NK_STRING", + /* 203 */ "table_options ::= table_options MAX_DELAY duration_list", + /* 204 */ "table_options ::= table_options WATERMARK duration_list", + /* 205 */ "table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP", + /* 206 */ "table_options ::= table_options TTL NK_INTEGER", + /* 207 */ "table_options ::= table_options SMA NK_LP col_name_list NK_RP", + /* 208 */ "table_options ::= table_options DELETE_MARK duration_list", + /* 209 */ "alter_table_options ::= alter_table_option", + /* 210 */ "alter_table_options ::= alter_table_options alter_table_option", + /* 211 */ "alter_table_option ::= COMMENT NK_STRING", + /* 212 */ "alter_table_option ::= TTL NK_INTEGER", + /* 213 */ "duration_list ::= duration_literal", + /* 214 */ "duration_list ::= duration_list NK_COMMA duration_literal", + /* 215 */ "rollup_func_list ::= rollup_func_name", + /* 216 */ "rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name", + /* 217 */ "rollup_func_name ::= function_name", + /* 218 */ "rollup_func_name ::= FIRST", + /* 219 */ "rollup_func_name ::= LAST", + /* 220 */ "col_name_list ::= col_name", + /* 221 */ "col_name_list ::= col_name_list NK_COMMA col_name", + /* 222 */ "col_name ::= column_name", + /* 223 */ "cmd ::= SHOW DNODES", + /* 224 */ "cmd ::= SHOW USERS", + /* 225 */ "cmd ::= SHOW USER PRIVILEGES", + /* 226 */ "cmd ::= SHOW DATABASES", + /* 227 */ "cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt", + /* 228 */ "cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt", + /* 229 */ "cmd ::= SHOW db_name_cond_opt VGROUPS", + /* 230 */ "cmd ::= SHOW MNODES", + /* 231 */ "cmd ::= SHOW QNODES", + /* 232 */ "cmd ::= SHOW FUNCTIONS", + /* 233 */ "cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt", + /* 234 */ "cmd ::= SHOW STREAMS", + /* 235 */ "cmd ::= SHOW ACCOUNTS", + /* 236 */ "cmd ::= SHOW APPS", + /* 237 */ "cmd ::= SHOW CONNECTIONS", + /* 238 */ "cmd ::= SHOW LICENCES", + /* 239 */ "cmd ::= SHOW GRANTS", + /* 240 */ "cmd ::= SHOW CREATE DATABASE db_name", + /* 241 */ "cmd ::= SHOW CREATE TABLE full_table_name", + /* 242 */ "cmd ::= SHOW CREATE STABLE full_table_name", + /* 243 */ "cmd ::= SHOW QUERIES", + /* 244 */ "cmd ::= SHOW SCORES", + /* 245 */ "cmd ::= SHOW TOPICS", + /* 246 */ "cmd ::= SHOW VARIABLES", + /* 247 */ "cmd ::= SHOW CLUSTER VARIABLES", + /* 248 */ "cmd ::= SHOW LOCAL VARIABLES", + /* 249 */ "cmd ::= SHOW DNODE NK_INTEGER VARIABLES like_pattern_opt", + /* 250 */ "cmd ::= SHOW BNODES", + /* 251 */ "cmd ::= SHOW SNODES", + /* 252 */ "cmd ::= SHOW CLUSTER", + /* 253 */ "cmd ::= SHOW TRANSACTIONS", + /* 254 */ "cmd ::= SHOW TABLE DISTRIBUTED full_table_name", + /* 255 */ "cmd ::= SHOW CONSUMERS", + /* 256 */ "cmd ::= SHOW SUBSCRIPTIONS", + /* 257 */ "cmd ::= SHOW TAGS FROM table_name_cond from_db_opt", + /* 258 */ "cmd ::= SHOW TABLE TAGS tag_list_opt FROM table_name_cond from_db_opt", + /* 259 */ "cmd ::= SHOW VNODES NK_INTEGER", + /* 260 */ "cmd ::= SHOW VNODES NK_STRING", + /* 261 */ "cmd ::= SHOW db_name_cond_opt ALIVE", + /* 262 */ "cmd ::= SHOW CLUSTER ALIVE", + /* 263 */ "db_name_cond_opt ::=", + /* 264 */ "db_name_cond_opt ::= db_name NK_DOT", + /* 265 */ "like_pattern_opt ::=", + /* 266 */ "like_pattern_opt ::= LIKE NK_STRING", + /* 267 */ "table_name_cond ::= table_name", + /* 268 */ "from_db_opt ::=", + /* 269 */ "from_db_opt ::= FROM db_name", + /* 270 */ "tag_list_opt ::=", + /* 271 */ "tag_list_opt ::= tag_item", + /* 272 */ "tag_list_opt ::= tag_list_opt NK_COMMA tag_item", + /* 273 */ "tag_item ::= TBNAME", + /* 274 */ "tag_item ::= QTAGS", + /* 275 */ "tag_item ::= column_name", + /* 276 */ "tag_item ::= column_name column_alias", + /* 277 */ "tag_item ::= column_name AS column_alias", + /* 278 */ "cmd ::= CREATE SMA INDEX not_exists_opt full_index_name ON full_table_name index_options", + /* 279 */ "cmd ::= CREATE INDEX not_exists_opt full_index_name ON full_table_name NK_LP col_name_list NK_RP", + /* 280 */ "cmd ::= DROP INDEX exists_opt full_index_name", + /* 281 */ "full_index_name ::= index_name", + /* 282 */ "full_index_name ::= db_name NK_DOT index_name", + /* 283 */ "index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt sma_stream_opt", + /* 284 */ "index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt sma_stream_opt", + /* 285 */ "func_list ::= func", + /* 286 */ "func_list ::= func_list NK_COMMA func", + /* 287 */ "func ::= sma_func_name NK_LP expression_list NK_RP", + /* 288 */ "sma_func_name ::= function_name", + /* 289 */ "sma_func_name ::= COUNT", + /* 290 */ "sma_func_name ::= FIRST", + /* 291 */ "sma_func_name ::= LAST", + /* 292 */ "sma_func_name ::= LAST_ROW", + /* 293 */ "sma_stream_opt ::=", + /* 294 */ "sma_stream_opt ::= sma_stream_opt WATERMARK duration_literal", + /* 295 */ "sma_stream_opt ::= sma_stream_opt MAX_DELAY duration_literal", + /* 296 */ "sma_stream_opt ::= sma_stream_opt DELETE_MARK duration_literal", + /* 297 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_or_subquery", + /* 298 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name", + /* 299 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS DATABASE db_name", + /* 300 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name", + /* 301 */ "cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS STABLE full_table_name", + /* 302 */ "cmd ::= DROP TOPIC exists_opt topic_name", + /* 303 */ "cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name", + /* 304 */ "cmd ::= DESC full_table_name", + /* 305 */ "cmd ::= DESCRIBE full_table_name", + /* 306 */ "cmd ::= RESET QUERY CACHE", + /* 307 */ "cmd ::= EXPLAIN analyze_opt explain_options query_or_subquery", + /* 308 */ "cmd ::= EXPLAIN analyze_opt explain_options insert_query", + /* 309 */ "analyze_opt ::=", + /* 310 */ "analyze_opt ::= ANALYZE", + /* 311 */ "explain_options ::=", + /* 312 */ "explain_options ::= explain_options VERBOSE NK_BOOL", + /* 313 */ "explain_options ::= explain_options RATIO NK_FLOAT", + /* 314 */ "cmd ::= CREATE or_replace_opt agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt language_opt", + /* 315 */ "cmd ::= DROP FUNCTION exists_opt function_name", + /* 316 */ "agg_func_opt ::=", + /* 317 */ "agg_func_opt ::= AGGREGATE", + /* 318 */ "bufsize_opt ::=", + /* 319 */ "bufsize_opt ::= BUFSIZE NK_INTEGER", + /* 320 */ "language_opt ::=", + /* 321 */ "language_opt ::= LANGUAGE NK_STRING", + /* 322 */ "or_replace_opt ::=", + /* 323 */ "or_replace_opt ::= OR REPLACE", + /* 324 */ "cmd ::= CREATE STREAM not_exists_opt stream_name stream_options INTO full_table_name col_list_opt tag_def_or_ref_opt subtable_opt AS query_or_subquery", + /* 325 */ "cmd ::= DROP STREAM exists_opt stream_name", + /* 326 */ "col_list_opt ::=", + /* 327 */ "col_list_opt ::= NK_LP col_name_list NK_RP", + /* 328 */ "tag_def_or_ref_opt ::=", + /* 329 */ "tag_def_or_ref_opt ::= tags_def", + /* 330 */ "tag_def_or_ref_opt ::= TAGS NK_LP col_name_list NK_RP", + /* 331 */ "stream_options ::=", + /* 332 */ "stream_options ::= stream_options TRIGGER AT_ONCE", + /* 333 */ "stream_options ::= stream_options TRIGGER WINDOW_CLOSE", + /* 334 */ "stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal", + /* 335 */ "stream_options ::= stream_options WATERMARK duration_literal", + /* 336 */ "stream_options ::= stream_options IGNORE EXPIRED NK_INTEGER", + /* 337 */ "stream_options ::= stream_options FILL_HISTORY NK_INTEGER", + /* 338 */ "stream_options ::= stream_options DELETE_MARK duration_literal", + /* 339 */ "stream_options ::= stream_options IGNORE UPDATE NK_INTEGER", + /* 340 */ "subtable_opt ::=", + /* 341 */ "subtable_opt ::= SUBTABLE NK_LP expression NK_RP", + /* 342 */ "cmd ::= KILL CONNECTION NK_INTEGER", + /* 343 */ "cmd ::= KILL QUERY NK_STRING", + /* 344 */ "cmd ::= KILL TRANSACTION NK_INTEGER", + /* 345 */ "cmd ::= BALANCE VGROUP", + /* 346 */ "cmd ::= BALANCE VGROUP LEADER", + /* 347 */ "cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER", + /* 348 */ "cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list", + /* 349 */ "cmd ::= SPLIT VGROUP NK_INTEGER", + /* 350 */ "dnode_list ::= DNODE NK_INTEGER", + /* 351 */ "dnode_list ::= dnode_list DNODE NK_INTEGER", + /* 352 */ "cmd ::= DELETE FROM full_table_name where_clause_opt", + /* 353 */ "cmd ::= query_or_subquery", + /* 354 */ "cmd ::= insert_query", + /* 355 */ "insert_query ::= INSERT INTO full_table_name NK_LP col_name_list NK_RP query_or_subquery", + /* 356 */ "insert_query ::= INSERT INTO full_table_name query_or_subquery", + /* 357 */ "literal ::= NK_INTEGER", + /* 358 */ "literal ::= NK_FLOAT", + /* 359 */ "literal ::= NK_STRING", + /* 360 */ "literal ::= NK_BOOL", + /* 361 */ "literal ::= TIMESTAMP NK_STRING", + /* 362 */ "literal ::= duration_literal", + /* 363 */ "literal ::= NULL", + /* 364 */ "literal ::= NK_QUESTION", + /* 365 */ "duration_literal ::= NK_VARIABLE", + /* 366 */ "signed ::= NK_INTEGER", + /* 367 */ "signed ::= NK_PLUS NK_INTEGER", + /* 368 */ "signed ::= NK_MINUS NK_INTEGER", + /* 369 */ "signed ::= NK_FLOAT", + /* 370 */ "signed ::= NK_PLUS NK_FLOAT", + /* 371 */ "signed ::= NK_MINUS NK_FLOAT", + /* 372 */ "signed_literal ::= signed", + /* 373 */ "signed_literal ::= NK_STRING", + /* 374 */ "signed_literal ::= NK_BOOL", + /* 375 */ "signed_literal ::= TIMESTAMP NK_STRING", + /* 376 */ "signed_literal ::= duration_literal", + /* 377 */ "signed_literal ::= NULL", + /* 378 */ "signed_literal ::= literal_func", + /* 379 */ "signed_literal ::= NK_QUESTION", + /* 380 */ "literal_list ::= signed_literal", + /* 381 */ "literal_list ::= literal_list NK_COMMA signed_literal", + /* 382 */ "db_name ::= NK_ID", + /* 383 */ "table_name ::= NK_ID", + /* 384 */ "column_name ::= NK_ID", + /* 385 */ "function_name ::= NK_ID", + /* 386 */ "table_alias ::= NK_ID", + /* 387 */ "column_alias ::= NK_ID", + /* 388 */ "user_name ::= NK_ID", + /* 389 */ "topic_name ::= NK_ID", + /* 390 */ "stream_name ::= NK_ID", + /* 391 */ "cgroup_name ::= NK_ID", + /* 392 */ "index_name ::= NK_ID", + /* 393 */ "expr_or_subquery ::= expression", + /* 394 */ "expression ::= literal", + /* 395 */ "expression ::= pseudo_column", + /* 396 */ "expression ::= column_reference", + /* 397 */ "expression ::= function_expression", + /* 398 */ "expression ::= case_when_expression", + /* 399 */ "expression ::= NK_LP expression NK_RP", + /* 400 */ "expression ::= NK_PLUS expr_or_subquery", + /* 401 */ "expression ::= NK_MINUS expr_or_subquery", + /* 402 */ "expression ::= expr_or_subquery NK_PLUS expr_or_subquery", + /* 403 */ "expression ::= expr_or_subquery NK_MINUS expr_or_subquery", + /* 404 */ "expression ::= expr_or_subquery NK_STAR expr_or_subquery", + /* 405 */ "expression ::= expr_or_subquery NK_SLASH expr_or_subquery", + /* 406 */ "expression ::= expr_or_subquery NK_REM expr_or_subquery", + /* 407 */ "expression ::= column_reference NK_ARROW NK_STRING", + /* 408 */ "expression ::= expr_or_subquery NK_BITAND expr_or_subquery", + /* 409 */ "expression ::= expr_or_subquery NK_BITOR expr_or_subquery", + /* 410 */ "expression_list ::= expr_or_subquery", + /* 411 */ "expression_list ::= expression_list NK_COMMA expr_or_subquery", + /* 412 */ "column_reference ::= column_name", + /* 413 */ "column_reference ::= table_name NK_DOT column_name", + /* 414 */ "pseudo_column ::= ROWTS", + /* 415 */ "pseudo_column ::= TBNAME", + /* 416 */ "pseudo_column ::= table_name NK_DOT TBNAME", + /* 417 */ "pseudo_column ::= QSTART", + /* 418 */ "pseudo_column ::= QEND", + /* 419 */ "pseudo_column ::= QDURATION", + /* 420 */ "pseudo_column ::= WSTART", + /* 421 */ "pseudo_column ::= WEND", + /* 422 */ "pseudo_column ::= WDURATION", + /* 423 */ "pseudo_column ::= IROWTS", + /* 424 */ "pseudo_column ::= ISFILLED", + /* 425 */ "pseudo_column ::= QTAGS", + /* 426 */ "function_expression ::= function_name NK_LP expression_list NK_RP", + /* 427 */ "function_expression ::= star_func NK_LP star_func_para_list NK_RP", + /* 428 */ "function_expression ::= CAST NK_LP expr_or_subquery AS type_name NK_RP", + /* 429 */ "function_expression ::= literal_func", + /* 430 */ "literal_func ::= noarg_func NK_LP NK_RP", + /* 431 */ "literal_func ::= NOW", + /* 432 */ "noarg_func ::= NOW", + /* 433 */ "noarg_func ::= TODAY", + /* 434 */ "noarg_func ::= TIMEZONE", + /* 435 */ "noarg_func ::= DATABASE", + /* 436 */ "noarg_func ::= CLIENT_VERSION", + /* 437 */ "noarg_func ::= SERVER_VERSION", + /* 438 */ "noarg_func ::= SERVER_STATUS", + /* 439 */ "noarg_func ::= CURRENT_USER", + /* 440 */ "noarg_func ::= USER", + /* 441 */ "star_func ::= COUNT", + /* 442 */ "star_func ::= FIRST", + /* 443 */ "star_func ::= LAST", + /* 444 */ "star_func ::= LAST_ROW", + /* 445 */ "star_func_para_list ::= NK_STAR", + /* 446 */ "star_func_para_list ::= other_para_list", + /* 447 */ "other_para_list ::= star_func_para", + /* 448 */ "other_para_list ::= other_para_list NK_COMMA star_func_para", + /* 449 */ "star_func_para ::= expr_or_subquery", + /* 450 */ "star_func_para ::= table_name NK_DOT NK_STAR", + /* 451 */ "case_when_expression ::= CASE when_then_list case_when_else_opt END", + /* 452 */ "case_when_expression ::= CASE common_expression when_then_list case_when_else_opt END", + /* 453 */ "when_then_list ::= when_then_expr", + /* 454 */ "when_then_list ::= when_then_list when_then_expr", + /* 455 */ "when_then_expr ::= WHEN common_expression THEN common_expression", + /* 456 */ "case_when_else_opt ::=", + /* 457 */ "case_when_else_opt ::= ELSE common_expression", + /* 458 */ "predicate ::= expr_or_subquery compare_op expr_or_subquery", + /* 459 */ "predicate ::= expr_or_subquery BETWEEN expr_or_subquery AND expr_or_subquery", + /* 460 */ "predicate ::= expr_or_subquery NOT BETWEEN expr_or_subquery AND expr_or_subquery", + /* 461 */ "predicate ::= expr_or_subquery IS NULL", + /* 462 */ "predicate ::= expr_or_subquery IS NOT NULL", + /* 463 */ "predicate ::= expr_or_subquery in_op in_predicate_value", + /* 464 */ "compare_op ::= NK_LT", + /* 465 */ "compare_op ::= NK_GT", + /* 466 */ "compare_op ::= NK_LE", + /* 467 */ "compare_op ::= NK_GE", + /* 468 */ "compare_op ::= NK_NE", + /* 469 */ "compare_op ::= NK_EQ", + /* 470 */ "compare_op ::= LIKE", + /* 471 */ "compare_op ::= NOT LIKE", + /* 472 */ "compare_op ::= MATCH", + /* 473 */ "compare_op ::= NMATCH", + /* 474 */ "compare_op ::= CONTAINS", + /* 475 */ "in_op ::= IN", + /* 476 */ "in_op ::= NOT IN", + /* 477 */ "in_predicate_value ::= NK_LP literal_list NK_RP", + /* 478 */ "boolean_value_expression ::= boolean_primary", + /* 479 */ "boolean_value_expression ::= NOT boolean_primary", + /* 480 */ "boolean_value_expression ::= boolean_value_expression OR boolean_value_expression", + /* 481 */ "boolean_value_expression ::= boolean_value_expression AND boolean_value_expression", + /* 482 */ "boolean_primary ::= predicate", + /* 483 */ "boolean_primary ::= NK_LP boolean_value_expression NK_RP", + /* 484 */ "common_expression ::= expr_or_subquery", + /* 485 */ "common_expression ::= boolean_value_expression", + /* 486 */ "from_clause_opt ::=", + /* 487 */ "from_clause_opt ::= FROM table_reference_list", + /* 488 */ "table_reference_list ::= table_reference", + /* 489 */ "table_reference_list ::= table_reference_list NK_COMMA table_reference", + /* 490 */ "table_reference ::= table_primary", + /* 491 */ "table_reference ::= joined_table", + /* 492 */ "table_primary ::= table_name alias_opt", + /* 493 */ "table_primary ::= db_name NK_DOT table_name alias_opt", + /* 494 */ "table_primary ::= subquery alias_opt", + /* 495 */ "table_primary ::= parenthesized_joined_table", + /* 496 */ "alias_opt ::=", + /* 497 */ "alias_opt ::= table_alias", + /* 498 */ "alias_opt ::= AS table_alias", + /* 499 */ "parenthesized_joined_table ::= NK_LP joined_table NK_RP", + /* 500 */ "parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP", + /* 501 */ "joined_table ::= table_reference join_type JOIN table_reference ON search_condition", + /* 502 */ "join_type ::=", + /* 503 */ "join_type ::= INNER", + /* 504 */ "query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt", + /* 505 */ "set_quantifier_opt ::=", + /* 506 */ "set_quantifier_opt ::= DISTINCT", + /* 507 */ "set_quantifier_opt ::= ALL", + /* 508 */ "select_list ::= select_item", + /* 509 */ "select_list ::= select_list NK_COMMA select_item", + /* 510 */ "select_item ::= NK_STAR", + /* 511 */ "select_item ::= common_expression", + /* 512 */ "select_item ::= common_expression column_alias", + /* 513 */ "select_item ::= common_expression AS column_alias", + /* 514 */ "select_item ::= table_name NK_DOT NK_STAR", + /* 515 */ "where_clause_opt ::=", + /* 516 */ "where_clause_opt ::= WHERE search_condition", + /* 517 */ "partition_by_clause_opt ::=", + /* 518 */ "partition_by_clause_opt ::= PARTITION BY partition_list", + /* 519 */ "partition_list ::= partition_item", + /* 520 */ "partition_list ::= partition_list NK_COMMA partition_item", + /* 521 */ "partition_item ::= expr_or_subquery", + /* 522 */ "partition_item ::= expr_or_subquery column_alias", + /* 523 */ "partition_item ::= expr_or_subquery AS column_alias", + /* 524 */ "twindow_clause_opt ::=", + /* 525 */ "twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP", + /* 526 */ "twindow_clause_opt ::= STATE_WINDOW NK_LP expr_or_subquery NK_RP", + /* 527 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt", + /* 528 */ "twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt", + /* 529 */ "twindow_clause_opt ::= EVENT_WINDOW START WITH search_condition END WITH search_condition", + /* 530 */ "sliding_opt ::=", + /* 531 */ "sliding_opt ::= SLIDING NK_LP duration_literal NK_RP", + /* 532 */ "fill_opt ::=", + /* 533 */ "fill_opt ::= FILL NK_LP fill_mode NK_RP", + /* 534 */ "fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP", + /* 535 */ "fill_opt ::= FILL NK_LP VALUE_F NK_COMMA literal_list NK_RP", + /* 536 */ "fill_mode ::= NONE", + /* 537 */ "fill_mode ::= PREV", + /* 538 */ "fill_mode ::= NULL", + /* 539 */ "fill_mode ::= NULL_F", + /* 540 */ "fill_mode ::= LINEAR", + /* 541 */ "fill_mode ::= NEXT", + /* 542 */ "group_by_clause_opt ::=", + /* 543 */ "group_by_clause_opt ::= GROUP BY group_by_list", + /* 544 */ "group_by_list ::= expr_or_subquery", + /* 545 */ "group_by_list ::= group_by_list NK_COMMA expr_or_subquery", + /* 546 */ "having_clause_opt ::=", + /* 547 */ "having_clause_opt ::= HAVING search_condition", + /* 548 */ "range_opt ::=", + /* 549 */ "range_opt ::= RANGE NK_LP expr_or_subquery NK_COMMA expr_or_subquery NK_RP", + /* 550 */ "every_opt ::=", + /* 551 */ "every_opt ::= EVERY NK_LP duration_literal NK_RP", + /* 552 */ "query_expression ::= query_simple order_by_clause_opt slimit_clause_opt limit_clause_opt", + /* 553 */ "query_simple ::= query_specification", + /* 554 */ "query_simple ::= union_query_expression", + /* 555 */ "union_query_expression ::= query_simple_or_subquery UNION ALL query_simple_or_subquery", + /* 556 */ "union_query_expression ::= query_simple_or_subquery UNION query_simple_or_subquery", + /* 557 */ "query_simple_or_subquery ::= query_simple", + /* 558 */ "query_simple_or_subquery ::= subquery", + /* 559 */ "query_or_subquery ::= query_expression", + /* 560 */ "query_or_subquery ::= subquery", + /* 561 */ "order_by_clause_opt ::=", + /* 562 */ "order_by_clause_opt ::= ORDER BY sort_specification_list", + /* 563 */ "slimit_clause_opt ::=", + /* 564 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER", + /* 565 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER", + /* 566 */ "slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER", + /* 567 */ "limit_clause_opt ::=", + /* 568 */ "limit_clause_opt ::= LIMIT NK_INTEGER", + /* 569 */ "limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER", + /* 570 */ "limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER", + /* 571 */ "subquery ::= NK_LP query_expression NK_RP", + /* 572 */ "subquery ::= NK_LP subquery NK_RP", + /* 573 */ "search_condition ::= common_expression", + /* 574 */ "sort_specification_list ::= sort_specification", + /* 575 */ "sort_specification_list ::= sort_specification_list NK_COMMA sort_specification", + /* 576 */ "sort_specification ::= expr_or_subquery ordering_specification_opt null_ordering_opt", + /* 577 */ "ordering_specification_opt ::=", + /* 578 */ "ordering_specification_opt ::= ASC", + /* 579 */ "ordering_specification_opt ::= DESC", + /* 580 */ "null_ordering_opt ::=", + /* 581 */ "null_ordering_opt ::= NULLS FIRST", + /* 582 */ "null_ordering_opt ::= NULLS LAST", }; #endif /* NDEBUG */ @@ -2523,195 +2663,208 @@ static void yy_destructor( */ /********* Begin destructor definitions ***************************************/ /* Default NON-TERMINAL Destructor */ - case 324: /* cmd */ - case 327: /* literal */ - case 340: /* db_options */ - case 342: /* alter_db_options */ - case 348: /* retention */ - case 349: /* full_table_name */ - case 352: /* table_options */ - case 356: /* alter_table_clause */ - case 357: /* alter_table_options */ - case 360: /* signed_literal */ - case 361: /* create_subtable_clause */ - case 364: /* drop_table_clause */ - case 367: /* column_def */ - case 371: /* duration_literal */ - case 372: /* rollup_func_name */ - case 374: /* col_name */ - case 375: /* db_name_cond_opt */ - case 376: /* like_pattern_opt */ - case 377: /* table_name_cond */ - case 378: /* from_db_opt */ - case 380: /* tag_item */ - case 382: /* full_index_name */ - case 383: /* index_options */ - case 386: /* sliding_opt */ - case 387: /* sma_stream_opt */ - case 388: /* func */ - case 389: /* query_or_subquery */ - case 392: /* explain_options */ - case 396: /* stream_options */ - case 397: /* subtable_opt */ - case 398: /* expression */ - case 400: /* where_clause_opt */ - case 401: /* signed */ - case 402: /* literal_func */ - case 405: /* expr_or_subquery */ - case 406: /* pseudo_column */ - case 407: /* column_reference */ - case 408: /* function_expression */ - case 409: /* case_when_expression */ - case 414: /* star_func_para */ - case 416: /* case_when_else_opt */ - case 417: /* common_expression */ - case 418: /* when_then_expr */ - case 419: /* predicate */ - case 422: /* in_predicate_value */ - case 423: /* boolean_value_expression */ - case 424: /* boolean_primary */ - case 425: /* from_clause_opt */ - case 426: /* table_reference_list */ - case 427: /* table_reference */ - case 428: /* table_primary */ - case 429: /* joined_table */ - case 431: /* subquery */ - case 432: /* parenthesized_joined_table */ - case 434: /* search_condition */ - case 435: /* query_specification */ - case 439: /* range_opt */ - case 440: /* every_opt */ - case 441: /* fill_opt */ - case 442: /* twindow_clause_opt */ - case 444: /* having_clause_opt */ - case 445: /* select_item */ - case 447: /* partition_item */ - case 450: /* query_expression */ - case 451: /* query_simple */ - case 453: /* slimit_clause_opt */ - case 454: /* limit_clause_opt */ - case 455: /* union_query_expression */ - case 456: /* query_simple_or_subquery */ - case 458: /* sort_specification */ + case 330: /* cmd */ + case 333: /* literal */ + case 339: /* with_opt */ + case 345: /* search_condition */ + case 349: /* db_options */ + case 351: /* alter_db_options */ + case 353: /* start_opt */ + case 354: /* end_opt */ + case 358: /* signed */ + case 360: /* retention */ + case 361: /* full_table_name */ + case 364: /* table_options */ + case 368: /* alter_table_clause */ + case 369: /* alter_table_options */ + case 372: /* signed_literal */ + case 373: /* create_subtable_clause */ + case 376: /* drop_table_clause */ + case 378: /* column_def */ + case 382: /* duration_literal */ + case 383: /* rollup_func_name */ + case 385: /* col_name */ + case 386: /* db_name_cond_opt */ + case 387: /* like_pattern_opt */ + case 388: /* table_name_cond */ + case 389: /* from_db_opt */ + case 391: /* tag_item */ + case 393: /* full_index_name */ + case 394: /* index_options */ + case 397: /* sliding_opt */ + case 398: /* sma_stream_opt */ + case 399: /* func */ + case 401: /* query_or_subquery */ + case 404: /* explain_options */ + case 405: /* insert_query */ + case 411: /* stream_options */ + case 414: /* subtable_opt */ + case 415: /* expression */ + case 417: /* where_clause_opt */ + case 418: /* literal_func */ + case 421: /* expr_or_subquery */ + case 422: /* pseudo_column */ + case 423: /* column_reference */ + case 424: /* function_expression */ + case 425: /* case_when_expression */ + case 430: /* star_func_para */ + case 432: /* case_when_else_opt */ + case 433: /* common_expression */ + case 434: /* when_then_expr */ + case 435: /* predicate */ + case 438: /* in_predicate_value */ + case 439: /* boolean_value_expression */ + case 440: /* boolean_primary */ + case 441: /* from_clause_opt */ + case 442: /* table_reference_list */ + case 443: /* table_reference */ + case 444: /* table_primary */ + case 445: /* joined_table */ + case 447: /* subquery */ + case 448: /* parenthesized_joined_table */ + case 450: /* query_specification */ + case 454: /* range_opt */ + case 455: /* every_opt */ + case 456: /* fill_opt */ + case 457: /* twindow_clause_opt */ + case 459: /* having_clause_opt */ + case 460: /* select_item */ + case 462: /* partition_item */ + case 465: /* query_expression */ + case 466: /* query_simple */ + case 468: /* slimit_clause_opt */ + case 469: /* limit_clause_opt */ + case 470: /* union_query_expression */ + case 471: /* query_simple_or_subquery */ + case 473: /* sort_specification */ { - nodesDestroyNode((yypminor->yy600)); + nodesDestroyNode((yypminor->yy448)); +} + break; + case 331: /* account_options */ + case 332: /* alter_account_options */ + case 334: /* alter_account_option */ + case 352: /* speed_opt */ + case 408: /* bufsize_opt */ +{ + } break; - case 325: /* account_options */ - case 326: /* alter_account_options */ - case 328: /* alter_account_option */ - case 343: /* speed_opt */ - case 394: /* bufsize_opt */ + case 335: /* user_name */ + case 342: /* db_name */ + case 343: /* table_name */ + case 344: /* topic_name */ + case 346: /* dnode_endpoint */ + case 370: /* column_name */ + case 384: /* function_name */ + case 392: /* column_alias */ + case 395: /* index_name */ + case 400: /* sma_func_name */ + case 402: /* cgroup_name */ + case 409: /* language_opt */ + case 410: /* stream_name */ + case 420: /* table_alias */ + case 426: /* star_func */ + case 428: /* noarg_func */ + case 446: /* alias_opt */ { } break; - case 329: /* user_name */ - case 332: /* priv_level */ - case 335: /* db_name */ - case 336: /* topic_name */ - case 337: /* dnode_endpoint */ - case 358: /* column_name */ - case 366: /* table_name */ - case 373: /* function_name */ - case 381: /* column_alias */ - case 384: /* index_name */ - case 390: /* cgroup_name */ - case 395: /* stream_name */ - case 404: /* table_alias */ - case 410: /* star_func */ - case 412: /* noarg_func */ - case 430: /* alias_opt */ + case 336: /* sysinfo_opt */ { } break; - case 330: /* sysinfo_opt */ + case 337: /* privileges */ + case 340: /* priv_type_list */ + case 341: /* priv_type */ { } break; - case 331: /* privileges */ - case 333: /* priv_type_list */ - case 334: /* priv_type */ + case 338: /* priv_level */ { } break; - case 338: /* force_opt */ - case 339: /* not_exists_opt */ - case 341: /* exists_opt */ - case 391: /* analyze_opt */ - case 393: /* agg_func_opt */ - case 436: /* set_quantifier_opt */ + case 347: /* force_opt */ + case 348: /* not_exists_opt */ + case 350: /* exists_opt */ + case 403: /* analyze_opt */ + case 406: /* or_replace_opt */ + case 407: /* agg_func_opt */ + case 451: /* set_quantifier_opt */ { } break; - case 344: /* integer_list */ - case 345: /* variable_list */ - case 346: /* retention_list */ - case 350: /* column_def_list */ - case 351: /* tags_def_opt */ - case 353: /* multi_create_clause */ - case 354: /* tags_def */ - case 355: /* multi_drop_clause */ - case 362: /* specific_cols_opt */ - case 363: /* expression_list */ - case 365: /* col_name_list */ - case 368: /* duration_list */ - case 369: /* rollup_func_list */ - case 379: /* tag_list_opt */ - case 385: /* func_list */ - case 399: /* dnode_list */ - case 403: /* literal_list */ - case 411: /* star_func_para_list */ - case 413: /* other_para_list */ - case 415: /* when_then_list */ - case 437: /* select_list */ - case 438: /* partition_by_clause_opt */ - case 443: /* group_by_clause_opt */ - case 446: /* partition_list */ - case 449: /* group_by_list */ - case 452: /* order_by_clause_opt */ - case 457: /* sort_specification_list */ + case 355: /* integer_list */ + case 356: /* variable_list */ + case 357: /* retention_list */ + case 362: /* column_def_list */ + case 363: /* tags_def_opt */ + case 365: /* multi_create_clause */ + case 366: /* tags_def */ + case 367: /* multi_drop_clause */ + case 374: /* specific_cols_opt */ + case 375: /* expression_list */ + case 377: /* col_name_list */ + case 379: /* duration_list */ + case 380: /* rollup_func_list */ + case 390: /* tag_list_opt */ + case 396: /* func_list */ + case 412: /* col_list_opt */ + case 413: /* tag_def_or_ref_opt */ + case 416: /* dnode_list */ + case 419: /* literal_list */ + case 427: /* star_func_para_list */ + case 429: /* other_para_list */ + case 431: /* when_then_list */ + case 452: /* select_list */ + case 453: /* partition_by_clause_opt */ + case 458: /* group_by_clause_opt */ + case 461: /* partition_list */ + case 464: /* group_by_list */ + case 467: /* order_by_clause_opt */ + case 472: /* sort_specification_list */ { - nodesDestroyList((yypminor->yy601)); + nodesDestroyList((yypminor->yy432)); } break; - case 347: /* alter_db_option */ - case 370: /* alter_table_option */ + case 359: /* alter_db_option */ + case 381: /* alter_table_option */ { } break; - case 359: /* type_name */ + case 371: /* type_name */ { } break; - case 420: /* compare_op */ - case 421: /* in_op */ + case 436: /* compare_op */ + case 437: /* in_op */ { } break; - case 433: /* join_type */ + case 449: /* join_type */ { } break; - case 448: /* fill_mode */ + case 463: /* fill_mode */ { } break; - case 459: /* ordering_specification_opt */ + case 474: /* ordering_specification_opt */ { } break; - case 460: /* null_ordering_opt */ + case 475: /* null_ordering_opt */ { } @@ -2839,15 +2992,18 @@ static YYACTIONTYPE yy_find_shift_action( do{ i = yy_shift_ofst[stateno]; assert( i>=0 ); - /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ + assert( i<=YY_ACTTAB_COUNT ); + assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); assert( iLookAhead!=YYNOCODE ); assert( iLookAhead < YYNTOKEN ); i += iLookAhead; - if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ + assert( i<(int)YY_NLOOKAHEAD ); + if( yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", @@ -2862,16 +3018,8 @@ static YYACTIONTYPE yy_find_shift_action( #ifdef YYWILDCARD { int j = i - iLookAhead + YYWILDCARD; - if( -#if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && -#endif -#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j0 - ){ + assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) ); + if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", @@ -2885,6 +3033,7 @@ static YYACTIONTYPE yy_find_shift_action( #endif /* YYWILDCARD */ return yy_default[stateno]; }else{ + assert( i>=0 && iyytos; #ifndef NDEBUG if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ - yysize = yyRuleInfo[yyruleno].nrhs; + yysize = yyRuleInfoNRhs[yyruleno]; if( yysize ){ - fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n", + fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n", yyTracePrompt, - yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno); + yyruleno, yyRuleName[yyruleno], + yyrulenoyytos - yypParser->yystack)>yypParser->yyhwm ){ yypParser->yyhwm++; @@ -3643,11 +4417,11 @@ static YYACTIONTYPE yy_reduce( YYMINORTYPE yylhsminor; case 0: /* cmd ::= CREATE ACCOUNT NK_ID PASS NK_STRING account_options */ { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } - yy_destructor(yypParser,325,&yymsp[0].minor); + yy_destructor(yypParser,331,&yymsp[0].minor); break; case 1: /* cmd ::= ALTER ACCOUNT NK_ID alter_account_options */ { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } - yy_destructor(yypParser,326,&yymsp[0].minor); + yy_destructor(yypParser,332,&yymsp[0].minor); break; case 2: /* account_options ::= */ { } @@ -3661,20 +4435,20 @@ static YYACTIONTYPE yy_reduce( case 9: /* account_options ::= account_options USERS literal */ yytestcase(yyruleno==9); case 10: /* account_options ::= account_options CONNS literal */ yytestcase(yyruleno==10); case 11: /* account_options ::= account_options STATE literal */ yytestcase(yyruleno==11); -{ yy_destructor(yypParser,325,&yymsp[-2].minor); +{ yy_destructor(yypParser,331,&yymsp[-2].minor); { } - yy_destructor(yypParser,327,&yymsp[0].minor); + yy_destructor(yypParser,333,&yymsp[0].minor); } break; case 12: /* alter_account_options ::= alter_account_option */ -{ yy_destructor(yypParser,328,&yymsp[0].minor); +{ yy_destructor(yypParser,334,&yymsp[0].minor); { } } break; case 13: /* alter_account_options ::= alter_account_options alter_account_option */ -{ yy_destructor(yypParser,326,&yymsp[-1].minor); +{ yy_destructor(yypParser,332,&yymsp[-1].minor); { } - yy_destructor(yypParser,328,&yymsp[0].minor); + yy_destructor(yypParser,334,&yymsp[0].minor); } break; case 14: /* alter_account_option ::= PASS literal */ @@ -3688,1524 +4462,1608 @@ static YYACTIONTYPE yy_reduce( case 22: /* alter_account_option ::= CONNS literal */ yytestcase(yyruleno==22); case 23: /* alter_account_option ::= STATE literal */ yytestcase(yyruleno==23); { } - yy_destructor(yypParser,327,&yymsp[0].minor); + yy_destructor(yypParser,333,&yymsp[0].minor); break; case 24: /* cmd ::= CREATE USER user_name PASS NK_STRING sysinfo_opt */ -{ pCxt->pRootNode = createCreateUserStmt(pCxt, &yymsp[-3].minor.yy77, &yymsp[-1].minor.yy0, yymsp[0].minor.yy287); } +{ pCxt->pRootNode = createCreateUserStmt(pCxt, &yymsp[-3].minor.yy113, &yymsp[-1].minor.yy0, yymsp[0].minor.yy551); } break; case 25: /* cmd ::= ALTER USER user_name PASS NK_STRING */ -{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy77, TSDB_ALTER_USER_PASSWD, &yymsp[0].minor.yy0); } +{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy113, TSDB_ALTER_USER_PASSWD, &yymsp[0].minor.yy0); } break; case 26: /* cmd ::= ALTER USER user_name ENABLE NK_INTEGER */ -{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy77, TSDB_ALTER_USER_ENABLE, &yymsp[0].minor.yy0); } +{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy113, TSDB_ALTER_USER_ENABLE, &yymsp[0].minor.yy0); } break; case 27: /* cmd ::= ALTER USER user_name SYSINFO NK_INTEGER */ -{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy77, TSDB_ALTER_USER_SYSINFO, &yymsp[0].minor.yy0); } +{ pCxt->pRootNode = createAlterUserStmt(pCxt, &yymsp[-2].minor.yy113, TSDB_ALTER_USER_SYSINFO, &yymsp[0].minor.yy0); } break; case 28: /* cmd ::= DROP USER user_name */ -{ pCxt->pRootNode = createDropUserStmt(pCxt, &yymsp[0].minor.yy77); } +{ pCxt->pRootNode = createDropUserStmt(pCxt, &yymsp[0].minor.yy113); } break; case 29: /* sysinfo_opt ::= */ -{ yymsp[1].minor.yy287 = 1; } +{ yymsp[1].minor.yy551 = 1; } break; case 30: /* sysinfo_opt ::= SYSINFO NK_INTEGER */ -{ yymsp[-1].minor.yy287 = taosStr2Int8(yymsp[0].minor.yy0.z, NULL, 10); } +{ yymsp[-1].minor.yy551 = taosStr2Int8(yymsp[0].minor.yy0.z, NULL, 10); } break; - case 31: /* cmd ::= GRANT privileges ON priv_level TO user_name */ -{ pCxt->pRootNode = createGrantStmt(pCxt, yymsp[-4].minor.yy717, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy77); } + case 31: /* cmd ::= GRANT privileges ON priv_level with_opt TO user_name */ +{ pCxt->pRootNode = createGrantStmt(pCxt, yymsp[-5].minor.yy837, &yymsp[-3].minor.yy777, &yymsp[0].minor.yy113, yymsp[-2].minor.yy448); } break; - case 32: /* cmd ::= REVOKE privileges ON priv_level FROM user_name */ -{ pCxt->pRootNode = createRevokeStmt(pCxt, yymsp[-4].minor.yy717, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy77); } + case 32: /* cmd ::= REVOKE privileges ON priv_level with_opt FROM user_name */ +{ pCxt->pRootNode = createRevokeStmt(pCxt, yymsp[-5].minor.yy837, &yymsp[-3].minor.yy777, &yymsp[0].minor.yy113, yymsp[-2].minor.yy448); } break; case 33: /* privileges ::= ALL */ -{ yymsp[0].minor.yy717 = PRIVILEGE_TYPE_ALL; } +{ yymsp[0].minor.yy837 = PRIVILEGE_TYPE_ALL; } break; case 34: /* privileges ::= priv_type_list */ case 36: /* priv_type_list ::= priv_type */ yytestcase(yyruleno==36); -{ yylhsminor.yy717 = yymsp[0].minor.yy717; } - yymsp[0].minor.yy717 = yylhsminor.yy717; +{ yylhsminor.yy837 = yymsp[0].minor.yy837; } + yymsp[0].minor.yy837 = yylhsminor.yy837; break; case 35: /* privileges ::= SUBSCRIBE */ -{ yymsp[0].minor.yy717 = PRIVILEGE_TYPE_SUBSCRIBE; } +{ yymsp[0].minor.yy837 = PRIVILEGE_TYPE_SUBSCRIBE; } break; case 37: /* priv_type_list ::= priv_type_list NK_COMMA priv_type */ -{ yylhsminor.yy717 = yymsp[-2].minor.yy717 | yymsp[0].minor.yy717; } - yymsp[-2].minor.yy717 = yylhsminor.yy717; +{ yylhsminor.yy837 = yymsp[-2].minor.yy837 | yymsp[0].minor.yy837; } + yymsp[-2].minor.yy837 = yylhsminor.yy837; break; case 38: /* priv_type ::= READ */ -{ yymsp[0].minor.yy717 = PRIVILEGE_TYPE_READ; } +{ yymsp[0].minor.yy837 = PRIVILEGE_TYPE_READ; } break; case 39: /* priv_type ::= WRITE */ -{ yymsp[0].minor.yy717 = PRIVILEGE_TYPE_WRITE; } +{ yymsp[0].minor.yy837 = PRIVILEGE_TYPE_WRITE; } break; case 40: /* priv_level ::= NK_STAR NK_DOT NK_STAR */ -{ yylhsminor.yy77 = yymsp[-2].minor.yy0; } - yymsp[-2].minor.yy77 = yylhsminor.yy77; +{ yylhsminor.yy777.first = yymsp[-2].minor.yy0; yylhsminor.yy777.second = yymsp[0].minor.yy0; } + yymsp[-2].minor.yy777 = yylhsminor.yy777; break; case 41: /* priv_level ::= db_name NK_DOT NK_STAR */ -{ yylhsminor.yy77 = yymsp[-2].minor.yy77; } - yymsp[-2].minor.yy77 = yylhsminor.yy77; - break; - case 42: /* priv_level ::= topic_name */ - case 460: /* alias_opt ::= table_alias */ yytestcase(yyruleno==460); -{ yylhsminor.yy77 = yymsp[0].minor.yy77; } - yymsp[0].minor.yy77 = yylhsminor.yy77; - break; - case 43: /* cmd ::= CREATE DNODE dnode_endpoint */ -{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[0].minor.yy77, NULL); } - break; - case 44: /* cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER */ -{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy0); } - break; - case 45: /* cmd ::= DROP DNODE NK_INTEGER force_opt */ -{ pCxt->pRootNode = createDropDnodeStmt(pCxt, &yymsp[-1].minor.yy0, yymsp[0].minor.yy841); } - break; - case 46: /* cmd ::= DROP DNODE dnode_endpoint force_opt */ -{ pCxt->pRootNode = createDropDnodeStmt(pCxt, &yymsp[-1].minor.yy77, yymsp[0].minor.yy841); } - break; - case 47: /* cmd ::= ALTER DNODE NK_INTEGER NK_STRING */ +{ yylhsminor.yy777.first = yymsp[-2].minor.yy113; yylhsminor.yy777.second = yymsp[0].minor.yy0; } + yymsp[-2].minor.yy777 = yylhsminor.yy777; + break; + case 42: /* priv_level ::= db_name NK_DOT table_name */ +{ yylhsminor.yy777.first = yymsp[-2].minor.yy113; yylhsminor.yy777.second = yymsp[0].minor.yy113; } + yymsp[-2].minor.yy777 = yylhsminor.yy777; + break; + case 43: /* priv_level ::= topic_name */ +{ yylhsminor.yy777.first = yymsp[0].minor.yy113; yylhsminor.yy777.second = nil_token; } + yymsp[0].minor.yy777 = yylhsminor.yy777; + break; + case 44: /* with_opt ::= */ + case 137: /* start_opt ::= */ yytestcase(yyruleno==137); + case 141: /* end_opt ::= */ yytestcase(yyruleno==141); + case 265: /* like_pattern_opt ::= */ yytestcase(yyruleno==265); + case 340: /* subtable_opt ::= */ yytestcase(yyruleno==340); + case 456: /* case_when_else_opt ::= */ yytestcase(yyruleno==456); + case 486: /* from_clause_opt ::= */ yytestcase(yyruleno==486); + case 515: /* where_clause_opt ::= */ yytestcase(yyruleno==515); + case 524: /* twindow_clause_opt ::= */ yytestcase(yyruleno==524); + case 530: /* sliding_opt ::= */ yytestcase(yyruleno==530); + case 532: /* fill_opt ::= */ yytestcase(yyruleno==532); + case 546: /* having_clause_opt ::= */ yytestcase(yyruleno==546); + case 548: /* range_opt ::= */ yytestcase(yyruleno==548); + case 550: /* every_opt ::= */ yytestcase(yyruleno==550); + case 563: /* slimit_clause_opt ::= */ yytestcase(yyruleno==563); + case 567: /* limit_clause_opt ::= */ yytestcase(yyruleno==567); +{ yymsp[1].minor.yy448 = NULL; } + break; + case 45: /* with_opt ::= WITH search_condition */ + case 487: /* from_clause_opt ::= FROM table_reference_list */ yytestcase(yyruleno==487); + case 516: /* where_clause_opt ::= WHERE search_condition */ yytestcase(yyruleno==516); + case 547: /* having_clause_opt ::= HAVING search_condition */ yytestcase(yyruleno==547); +{ yymsp[-1].minor.yy448 = yymsp[0].minor.yy448; } + break; + case 46: /* cmd ::= CREATE DNODE dnode_endpoint */ +{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[0].minor.yy113, NULL); } + break; + case 47: /* cmd ::= CREATE DNODE dnode_endpoint PORT NK_INTEGER */ +{ pCxt->pRootNode = createCreateDnodeStmt(pCxt, &yymsp[-2].minor.yy113, &yymsp[0].minor.yy0); } + break; + case 48: /* cmd ::= DROP DNODE NK_INTEGER force_opt */ +{ pCxt->pRootNode = createDropDnodeStmt(pCxt, &yymsp[-1].minor.yy0, yymsp[0].minor.yy369); } + break; + case 49: /* cmd ::= DROP DNODE dnode_endpoint force_opt */ +{ pCxt->pRootNode = createDropDnodeStmt(pCxt, &yymsp[-1].minor.yy113, yymsp[0].minor.yy369); } + break; + case 50: /* cmd ::= ALTER DNODE NK_INTEGER NK_STRING */ { pCxt->pRootNode = createAlterDnodeStmt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0, NULL); } break; - case 48: /* cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING */ + case 51: /* cmd ::= ALTER DNODE NK_INTEGER NK_STRING NK_STRING */ { pCxt->pRootNode = createAlterDnodeStmt(pCxt, &yymsp[-2].minor.yy0, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } break; - case 49: /* cmd ::= ALTER ALL DNODES NK_STRING */ + case 52: /* cmd ::= ALTER ALL DNODES NK_STRING */ { pCxt->pRootNode = createAlterDnodeStmt(pCxt, NULL, &yymsp[0].minor.yy0, NULL); } break; - case 50: /* cmd ::= ALTER ALL DNODES NK_STRING NK_STRING */ + case 53: /* cmd ::= ALTER ALL DNODES NK_STRING NK_STRING */ { pCxt->pRootNode = createAlterDnodeStmt(pCxt, NULL, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } break; - case 51: /* dnode_endpoint ::= NK_STRING */ - case 52: /* dnode_endpoint ::= NK_ID */ yytestcase(yyruleno==52); - case 53: /* dnode_endpoint ::= NK_IPTOKEN */ yytestcase(yyruleno==53); - case 346: /* db_name ::= NK_ID */ yytestcase(yyruleno==346); - case 347: /* table_name ::= NK_ID */ yytestcase(yyruleno==347); - case 348: /* column_name ::= NK_ID */ yytestcase(yyruleno==348); - case 349: /* function_name ::= NK_ID */ yytestcase(yyruleno==349); - case 350: /* table_alias ::= NK_ID */ yytestcase(yyruleno==350); - case 351: /* column_alias ::= NK_ID */ yytestcase(yyruleno==351); - case 352: /* user_name ::= NK_ID */ yytestcase(yyruleno==352); - case 353: /* topic_name ::= NK_ID */ yytestcase(yyruleno==353); - case 354: /* stream_name ::= NK_ID */ yytestcase(yyruleno==354); - case 355: /* cgroup_name ::= NK_ID */ yytestcase(yyruleno==355); - case 356: /* index_name ::= NK_ID */ yytestcase(yyruleno==356); - case 395: /* noarg_func ::= NOW */ yytestcase(yyruleno==395); - case 396: /* noarg_func ::= TODAY */ yytestcase(yyruleno==396); - case 397: /* noarg_func ::= TIMEZONE */ yytestcase(yyruleno==397); - case 398: /* noarg_func ::= DATABASE */ yytestcase(yyruleno==398); - case 399: /* noarg_func ::= CLIENT_VERSION */ yytestcase(yyruleno==399); - case 400: /* noarg_func ::= SERVER_VERSION */ yytestcase(yyruleno==400); - case 401: /* noarg_func ::= SERVER_STATUS */ yytestcase(yyruleno==401); - case 402: /* noarg_func ::= CURRENT_USER */ yytestcase(yyruleno==402); - case 403: /* noarg_func ::= USER */ yytestcase(yyruleno==403); - case 404: /* star_func ::= COUNT */ yytestcase(yyruleno==404); - case 405: /* star_func ::= FIRST */ yytestcase(yyruleno==405); - case 406: /* star_func ::= LAST */ yytestcase(yyruleno==406); - case 407: /* star_func ::= LAST_ROW */ yytestcase(yyruleno==407); -{ yylhsminor.yy77 = yymsp[0].minor.yy0; } - yymsp[0].minor.yy77 = yylhsminor.yy77; - break; - case 54: /* force_opt ::= */ - case 73: /* not_exists_opt ::= */ yytestcase(yyruleno==73); - case 75: /* exists_opt ::= */ yytestcase(yyruleno==75); - case 284: /* analyze_opt ::= */ yytestcase(yyruleno==284); - case 291: /* agg_func_opt ::= */ yytestcase(yyruleno==291); - case 468: /* set_quantifier_opt ::= */ yytestcase(yyruleno==468); -{ yymsp[1].minor.yy841 = false; } - break; - case 55: /* force_opt ::= FORCE */ - case 285: /* analyze_opt ::= ANALYZE */ yytestcase(yyruleno==285); - case 292: /* agg_func_opt ::= AGGREGATE */ yytestcase(yyruleno==292); - case 469: /* set_quantifier_opt ::= DISTINCT */ yytestcase(yyruleno==469); -{ yymsp[0].minor.yy841 = true; } - break; - case 56: /* cmd ::= ALTER LOCAL NK_STRING */ + case 54: /* dnode_endpoint ::= NK_STRING */ + case 55: /* dnode_endpoint ::= NK_ID */ yytestcase(yyruleno==55); + case 56: /* dnode_endpoint ::= NK_IPTOKEN */ yytestcase(yyruleno==56); + case 289: /* sma_func_name ::= COUNT */ yytestcase(yyruleno==289); + case 290: /* sma_func_name ::= FIRST */ yytestcase(yyruleno==290); + case 291: /* sma_func_name ::= LAST */ yytestcase(yyruleno==291); + case 292: /* sma_func_name ::= LAST_ROW */ yytestcase(yyruleno==292); + case 382: /* db_name ::= NK_ID */ yytestcase(yyruleno==382); + case 383: /* table_name ::= NK_ID */ yytestcase(yyruleno==383); + case 384: /* column_name ::= NK_ID */ yytestcase(yyruleno==384); + case 385: /* function_name ::= NK_ID */ yytestcase(yyruleno==385); + case 386: /* table_alias ::= NK_ID */ yytestcase(yyruleno==386); + case 387: /* column_alias ::= NK_ID */ yytestcase(yyruleno==387); + case 388: /* user_name ::= NK_ID */ yytestcase(yyruleno==388); + case 389: /* topic_name ::= NK_ID */ yytestcase(yyruleno==389); + case 390: /* stream_name ::= NK_ID */ yytestcase(yyruleno==390); + case 391: /* cgroup_name ::= NK_ID */ yytestcase(yyruleno==391); + case 392: /* index_name ::= NK_ID */ yytestcase(yyruleno==392); + case 432: /* noarg_func ::= NOW */ yytestcase(yyruleno==432); + case 433: /* noarg_func ::= TODAY */ yytestcase(yyruleno==433); + case 434: /* noarg_func ::= TIMEZONE */ yytestcase(yyruleno==434); + case 435: /* noarg_func ::= DATABASE */ yytestcase(yyruleno==435); + case 436: /* noarg_func ::= CLIENT_VERSION */ yytestcase(yyruleno==436); + case 437: /* noarg_func ::= SERVER_VERSION */ yytestcase(yyruleno==437); + case 438: /* noarg_func ::= SERVER_STATUS */ yytestcase(yyruleno==438); + case 439: /* noarg_func ::= CURRENT_USER */ yytestcase(yyruleno==439); + case 440: /* noarg_func ::= USER */ yytestcase(yyruleno==440); + case 441: /* star_func ::= COUNT */ yytestcase(yyruleno==441); + case 442: /* star_func ::= FIRST */ yytestcase(yyruleno==442); + case 443: /* star_func ::= LAST */ yytestcase(yyruleno==443); + case 444: /* star_func ::= LAST_ROW */ yytestcase(yyruleno==444); +{ yylhsminor.yy113 = yymsp[0].minor.yy0; } + yymsp[0].minor.yy113 = yylhsminor.yy113; + break; + case 57: /* force_opt ::= */ + case 77: /* not_exists_opt ::= */ yytestcase(yyruleno==77); + case 79: /* exists_opt ::= */ yytestcase(yyruleno==79); + case 309: /* analyze_opt ::= */ yytestcase(yyruleno==309); + case 316: /* agg_func_opt ::= */ yytestcase(yyruleno==316); + case 322: /* or_replace_opt ::= */ yytestcase(yyruleno==322); + case 505: /* set_quantifier_opt ::= */ yytestcase(yyruleno==505); +{ yymsp[1].minor.yy369 = false; } + break; + case 58: /* force_opt ::= FORCE */ + case 310: /* analyze_opt ::= ANALYZE */ yytestcase(yyruleno==310); + case 317: /* agg_func_opt ::= AGGREGATE */ yytestcase(yyruleno==317); + case 506: /* set_quantifier_opt ::= DISTINCT */ yytestcase(yyruleno==506); +{ yymsp[0].minor.yy369 = true; } + break; + case 59: /* cmd ::= ALTER LOCAL NK_STRING */ { pCxt->pRootNode = createAlterLocalStmt(pCxt, &yymsp[0].minor.yy0, NULL); } break; - case 57: /* cmd ::= ALTER LOCAL NK_STRING NK_STRING */ + case 60: /* cmd ::= ALTER LOCAL NK_STRING NK_STRING */ { pCxt->pRootNode = createAlterLocalStmt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } break; - case 58: /* cmd ::= CREATE QNODE ON DNODE NK_INTEGER */ + case 61: /* cmd ::= CREATE QNODE ON DNODE NK_INTEGER */ { pCxt->pRootNode = createCreateComponentNodeStmt(pCxt, QUERY_NODE_CREATE_QNODE_STMT, &yymsp[0].minor.yy0); } break; - case 59: /* cmd ::= DROP QNODE ON DNODE NK_INTEGER */ + case 62: /* cmd ::= DROP QNODE ON DNODE NK_INTEGER */ { pCxt->pRootNode = createDropComponentNodeStmt(pCxt, QUERY_NODE_DROP_QNODE_STMT, &yymsp[0].minor.yy0); } break; - case 60: /* cmd ::= CREATE BNODE ON DNODE NK_INTEGER */ + case 63: /* cmd ::= CREATE BNODE ON DNODE NK_INTEGER */ { pCxt->pRootNode = createCreateComponentNodeStmt(pCxt, QUERY_NODE_CREATE_BNODE_STMT, &yymsp[0].minor.yy0); } break; - case 61: /* cmd ::= DROP BNODE ON DNODE NK_INTEGER */ + case 64: /* cmd ::= DROP BNODE ON DNODE NK_INTEGER */ { pCxt->pRootNode = createDropComponentNodeStmt(pCxt, QUERY_NODE_DROP_BNODE_STMT, &yymsp[0].minor.yy0); } break; - case 62: /* cmd ::= CREATE SNODE ON DNODE NK_INTEGER */ + case 65: /* cmd ::= CREATE SNODE ON DNODE NK_INTEGER */ { pCxt->pRootNode = createCreateComponentNodeStmt(pCxt, QUERY_NODE_CREATE_SNODE_STMT, &yymsp[0].minor.yy0); } break; - case 63: /* cmd ::= DROP SNODE ON DNODE NK_INTEGER */ + case 66: /* cmd ::= DROP SNODE ON DNODE NK_INTEGER */ { pCxt->pRootNode = createDropComponentNodeStmt(pCxt, QUERY_NODE_DROP_SNODE_STMT, &yymsp[0].minor.yy0); } break; - case 64: /* cmd ::= CREATE MNODE ON DNODE NK_INTEGER */ + case 67: /* cmd ::= CREATE MNODE ON DNODE NK_INTEGER */ { pCxt->pRootNode = createCreateComponentNodeStmt(pCxt, QUERY_NODE_CREATE_MNODE_STMT, &yymsp[0].minor.yy0); } break; - case 65: /* cmd ::= DROP MNODE ON DNODE NK_INTEGER */ + case 68: /* cmd ::= DROP MNODE ON DNODE NK_INTEGER */ { pCxt->pRootNode = createDropComponentNodeStmt(pCxt, QUERY_NODE_DROP_MNODE_STMT, &yymsp[0].minor.yy0); } break; - case 66: /* cmd ::= CREATE DATABASE not_exists_opt db_name db_options */ -{ pCxt->pRootNode = createCreateDatabaseStmt(pCxt, yymsp[-2].minor.yy841, &yymsp[-1].minor.yy77, yymsp[0].minor.yy600); } + case 69: /* cmd ::= CREATE DATABASE not_exists_opt db_name db_options */ +{ pCxt->pRootNode = createCreateDatabaseStmt(pCxt, yymsp[-2].minor.yy369, &yymsp[-1].minor.yy113, yymsp[0].minor.yy448); } + break; + case 70: /* cmd ::= DROP DATABASE exists_opt db_name */ +{ pCxt->pRootNode = createDropDatabaseStmt(pCxt, yymsp[-1].minor.yy369, &yymsp[0].minor.yy113); } + break; + case 71: /* cmd ::= USE db_name */ +{ pCxt->pRootNode = createUseDatabaseStmt(pCxt, &yymsp[0].minor.yy113); } + break; + case 72: /* cmd ::= ALTER DATABASE db_name alter_db_options */ +{ pCxt->pRootNode = createAlterDatabaseStmt(pCxt, &yymsp[-1].minor.yy113, yymsp[0].minor.yy448); } + break; + case 73: /* cmd ::= FLUSH DATABASE db_name */ +{ pCxt->pRootNode = createFlushDatabaseStmt(pCxt, &yymsp[0].minor.yy113); } + break; + case 74: /* cmd ::= TRIM DATABASE db_name speed_opt */ +{ pCxt->pRootNode = createTrimDatabaseStmt(pCxt, &yymsp[-1].minor.yy113, yymsp[0].minor.yy788); } + break; + case 75: /* cmd ::= COMPACT DATABASE db_name start_opt end_opt */ +{ pCxt->pRootNode = createCompactStmt(pCxt, &yymsp[-2].minor.yy113, yymsp[-1].minor.yy448, yymsp[0].minor.yy448); } + break; + case 76: /* not_exists_opt ::= IF NOT EXISTS */ +{ yymsp[-2].minor.yy369 = true; } + break; + case 78: /* exists_opt ::= IF EXISTS */ + case 323: /* or_replace_opt ::= OR REPLACE */ yytestcase(yyruleno==323); +{ yymsp[-1].minor.yy369 = true; } + break; + case 80: /* db_options ::= */ +{ yymsp[1].minor.yy448 = createDefaultDatabaseOptions(pCxt); } break; - case 67: /* cmd ::= DROP DATABASE exists_opt db_name */ -{ pCxt->pRootNode = createDropDatabaseStmt(pCxt, yymsp[-1].minor.yy841, &yymsp[0].minor.yy77); } + case 81: /* db_options ::= db_options BUFFER NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_BUFFER, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 68: /* cmd ::= USE db_name */ -{ pCxt->pRootNode = createUseDatabaseStmt(pCxt, &yymsp[0].minor.yy77); } + case 82: /* db_options ::= db_options CACHEMODEL NK_STRING */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_CACHEMODEL, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 69: /* cmd ::= ALTER DATABASE db_name alter_db_options */ -{ pCxt->pRootNode = createAlterDatabaseStmt(pCxt, &yymsp[-1].minor.yy77, yymsp[0].minor.yy600); } + case 83: /* db_options ::= db_options CACHESIZE NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_CACHESIZE, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 70: /* cmd ::= FLUSH DATABASE db_name */ -{ pCxt->pRootNode = createFlushDatabaseStmt(pCxt, &yymsp[0].minor.yy77); } + case 84: /* db_options ::= db_options COMP NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_COMP, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 71: /* cmd ::= TRIM DATABASE db_name speed_opt */ -{ pCxt->pRootNode = createTrimDatabaseStmt(pCxt, &yymsp[-1].minor.yy77, yymsp[0].minor.yy248); } + case 85: /* db_options ::= db_options DURATION NK_INTEGER */ + case 86: /* db_options ::= db_options DURATION NK_VARIABLE */ yytestcase(yyruleno==86); +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_DAYS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 72: /* not_exists_opt ::= IF NOT EXISTS */ -{ yymsp[-2].minor.yy841 = true; } + case 87: /* db_options ::= db_options MAXROWS NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_MAXROWS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 74: /* exists_opt ::= IF EXISTS */ -{ yymsp[-1].minor.yy841 = true; } + case 88: /* db_options ::= db_options MINROWS NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_MINROWS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 76: /* db_options ::= */ -{ yymsp[1].minor.yy600 = createDefaultDatabaseOptions(pCxt); } + case 89: /* db_options ::= db_options KEEP integer_list */ + case 90: /* db_options ::= db_options KEEP variable_list */ yytestcase(yyruleno==90); +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_KEEP, yymsp[0].minor.yy432); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 77: /* db_options ::= db_options BUFFER NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_BUFFER, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 91: /* db_options ::= db_options PAGES NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_PAGES, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 78: /* db_options ::= db_options CACHEMODEL NK_STRING */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_CACHEMODEL, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 92: /* db_options ::= db_options PAGESIZE NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_PAGESIZE, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 79: /* db_options ::= db_options CACHESIZE NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_CACHESIZE, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 93: /* db_options ::= db_options TSDB_PAGESIZE NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_TSDB_PAGESIZE, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 80: /* db_options ::= db_options COMP NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_COMP, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 94: /* db_options ::= db_options PRECISION NK_STRING */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_PRECISION, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 81: /* db_options ::= db_options DURATION NK_INTEGER */ - case 82: /* db_options ::= db_options DURATION NK_VARIABLE */ yytestcase(yyruleno==82); -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_DAYS, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 95: /* db_options ::= db_options REPLICA NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_REPLICA, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 83: /* db_options ::= db_options MAXROWS NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_MAXROWS, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 96: /* db_options ::= db_options VGROUPS NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_VGROUPS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 84: /* db_options ::= db_options MINROWS NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_MINROWS, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 97: /* db_options ::= db_options SINGLE_STABLE NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_SINGLE_STABLE, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 85: /* db_options ::= db_options KEEP integer_list */ - case 86: /* db_options ::= db_options KEEP variable_list */ yytestcase(yyruleno==86); -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_KEEP, yymsp[0].minor.yy601); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 98: /* db_options ::= db_options RETENTIONS retention_list */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_RETENTIONS, yymsp[0].minor.yy432); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 87: /* db_options ::= db_options PAGES NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_PAGES, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 99: /* db_options ::= db_options SCHEMALESS NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_SCHEMALESS, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 88: /* db_options ::= db_options PAGESIZE NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_PAGESIZE, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 100: /* db_options ::= db_options WAL_LEVEL NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_WAL, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 89: /* db_options ::= db_options TSDB_PAGESIZE NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_TSDB_PAGESIZE, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 101: /* db_options ::= db_options WAL_FSYNC_PERIOD NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_FSYNC, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 90: /* db_options ::= db_options PRECISION NK_STRING */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_PRECISION, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 102: /* db_options ::= db_options WAL_RETENTION_PERIOD NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_WAL_RETENTION_PERIOD, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 91: /* db_options ::= db_options REPLICA NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_REPLICA, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 103: /* db_options ::= db_options WAL_RETENTION_PERIOD NK_MINUS NK_INTEGER */ +{ + SToken t = yymsp[-1].minor.yy0; + t.n = (yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z; + yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-3].minor.yy448, DB_OPTION_WAL_RETENTION_PERIOD, &t); + } + yymsp[-3].minor.yy448 = yylhsminor.yy448; + break; + case 104: /* db_options ::= db_options WAL_RETENTION_SIZE NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_WAL_RETENTION_SIZE, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 105: /* db_options ::= db_options WAL_RETENTION_SIZE NK_MINUS NK_INTEGER */ +{ + SToken t = yymsp[-1].minor.yy0; + t.n = (yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z; + yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-3].minor.yy448, DB_OPTION_WAL_RETENTION_SIZE, &t); + } + yymsp[-3].minor.yy448 = yylhsminor.yy448; + break; + case 106: /* db_options ::= db_options WAL_ROLL_PERIOD NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_WAL_ROLL_PERIOD, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 107: /* db_options ::= db_options WAL_SEGMENT_SIZE NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_WAL_SEGMENT_SIZE, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 108: /* db_options ::= db_options STT_TRIGGER NK_INTEGER */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_STT_TRIGGER, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 109: /* db_options ::= db_options TABLE_PREFIX signed */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_TABLE_PREFIX, yymsp[0].minor.yy448); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 110: /* db_options ::= db_options TABLE_SUFFIX signed */ +{ yylhsminor.yy448 = setDatabaseOption(pCxt, yymsp[-2].minor.yy448, DB_OPTION_TABLE_SUFFIX, yymsp[0].minor.yy448); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 111: /* alter_db_options ::= alter_db_option */ +{ yylhsminor.yy448 = createAlterDatabaseOptions(pCxt); yylhsminor.yy448 = setAlterDatabaseOption(pCxt, yylhsminor.yy448, &yymsp[0].minor.yy53); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 112: /* alter_db_options ::= alter_db_options alter_db_option */ +{ yylhsminor.yy448 = setAlterDatabaseOption(pCxt, yymsp[-1].minor.yy448, &yymsp[0].minor.yy53); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; + break; + case 113: /* alter_db_option ::= BUFFER NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_BUFFER; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 92: /* db_options ::= db_options VGROUPS NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_VGROUPS, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 114: /* alter_db_option ::= CACHEMODEL NK_STRING */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_CACHEMODEL; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 93: /* db_options ::= db_options SINGLE_STABLE NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_SINGLE_STABLE, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 115: /* alter_db_option ::= CACHESIZE NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_CACHESIZE; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 94: /* db_options ::= db_options RETENTIONS retention_list */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_RETENTIONS, yymsp[0].minor.yy601); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 116: /* alter_db_option ::= WAL_FSYNC_PERIOD NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_FSYNC; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 95: /* db_options ::= db_options SCHEMALESS NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_SCHEMALESS, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 117: /* alter_db_option ::= KEEP integer_list */ + case 118: /* alter_db_option ::= KEEP variable_list */ yytestcase(yyruleno==118); +{ yymsp[-1].minor.yy53.type = DB_OPTION_KEEP; yymsp[-1].minor.yy53.pList = yymsp[0].minor.yy432; } break; - case 96: /* db_options ::= db_options WAL_LEVEL NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_WAL, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 119: /* alter_db_option ::= PAGES NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_PAGES; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 97: /* db_options ::= db_options WAL_FSYNC_PERIOD NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_FSYNC, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 120: /* alter_db_option ::= REPLICA NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_REPLICA; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 98: /* db_options ::= db_options WAL_RETENTION_PERIOD NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_WAL_RETENTION_PERIOD, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 121: /* alter_db_option ::= WAL_LEVEL NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_WAL; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 99: /* db_options ::= db_options WAL_RETENTION_PERIOD NK_MINUS NK_INTEGER */ + case 122: /* alter_db_option ::= STT_TRIGGER NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_STT_TRIGGER; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } + break; + case 123: /* alter_db_option ::= MINROWS NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_MINROWS; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } + break; + case 124: /* alter_db_option ::= WAL_RETENTION_PERIOD NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_WAL_RETENTION_PERIOD; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } + break; + case 125: /* alter_db_option ::= WAL_RETENTION_PERIOD NK_MINUS NK_INTEGER */ { SToken t = yymsp[-1].minor.yy0; t.n = (yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z; - yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-3].minor.yy600, DB_OPTION_WAL_RETENTION_PERIOD, &t); + yymsp[-2].minor.yy53.type = DB_OPTION_WAL_RETENTION_PERIOD; yymsp[-2].minor.yy53.val = t; } - yymsp[-3].minor.yy600 = yylhsminor.yy600; break; - case 100: /* db_options ::= db_options WAL_RETENTION_SIZE NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_WAL_RETENTION_SIZE, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 126: /* alter_db_option ::= WAL_RETENTION_SIZE NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = DB_OPTION_WAL_RETENTION_SIZE; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 101: /* db_options ::= db_options WAL_RETENTION_SIZE NK_MINUS NK_INTEGER */ + case 127: /* alter_db_option ::= WAL_RETENTION_SIZE NK_MINUS NK_INTEGER */ { SToken t = yymsp[-1].minor.yy0; t.n = (yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z; - yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-3].minor.yy600, DB_OPTION_WAL_RETENTION_SIZE, &t); + yymsp[-2].minor.yy53.type = DB_OPTION_WAL_RETENTION_SIZE; yymsp[-2].minor.yy53.val = t; } - yymsp[-3].minor.yy600 = yylhsminor.yy600; - break; - case 102: /* db_options ::= db_options WAL_ROLL_PERIOD NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_WAL_ROLL_PERIOD, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 103: /* db_options ::= db_options WAL_SEGMENT_SIZE NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_WAL_SEGMENT_SIZE, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 104: /* db_options ::= db_options STT_TRIGGER NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_STT_TRIGGER, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 105: /* db_options ::= db_options TABLE_PREFIX NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_TABLE_PREFIX, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 106: /* db_options ::= db_options TABLE_SUFFIX NK_INTEGER */ -{ yylhsminor.yy600 = setDatabaseOption(pCxt, yymsp[-2].minor.yy600, DB_OPTION_TABLE_SUFFIX, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 107: /* alter_db_options ::= alter_db_option */ -{ yylhsminor.yy600 = createAlterDatabaseOptions(pCxt); yylhsminor.yy600 = setAlterDatabaseOption(pCxt, yylhsminor.yy600, &yymsp[0].minor.yy661); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 108: /* alter_db_options ::= alter_db_options alter_db_option */ -{ yylhsminor.yy600 = setAlterDatabaseOption(pCxt, yymsp[-1].minor.yy600, &yymsp[0].minor.yy661); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; - break; - case 109: /* alter_db_option ::= BUFFER NK_INTEGER */ -{ yymsp[-1].minor.yy661.type = DB_OPTION_BUFFER; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } - break; - case 110: /* alter_db_option ::= CACHEMODEL NK_STRING */ -{ yymsp[-1].minor.yy661.type = DB_OPTION_CACHEMODEL; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } - break; - case 111: /* alter_db_option ::= CACHESIZE NK_INTEGER */ -{ yymsp[-1].minor.yy661.type = DB_OPTION_CACHESIZE; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } - break; - case 112: /* alter_db_option ::= WAL_FSYNC_PERIOD NK_INTEGER */ -{ yymsp[-1].minor.yy661.type = DB_OPTION_FSYNC; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } - break; - case 113: /* alter_db_option ::= KEEP integer_list */ - case 114: /* alter_db_option ::= KEEP variable_list */ yytestcase(yyruleno==114); -{ yymsp[-1].minor.yy661.type = DB_OPTION_KEEP; yymsp[-1].minor.yy661.pList = yymsp[0].minor.yy601; } - break; - case 115: /* alter_db_option ::= PAGES NK_INTEGER */ -{ yymsp[-1].minor.yy661.type = DB_OPTION_PAGES; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } - break; - case 116: /* alter_db_option ::= REPLICA NK_INTEGER */ -{ yymsp[-1].minor.yy661.type = DB_OPTION_REPLICA; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } - break; - case 117: /* alter_db_option ::= WAL_LEVEL NK_INTEGER */ -{ yymsp[-1].minor.yy661.type = DB_OPTION_WAL; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } - break; - case 118: /* alter_db_option ::= STT_TRIGGER NK_INTEGER */ -{ yymsp[-1].minor.yy661.type = DB_OPTION_STT_TRIGGER; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } - break; - case 119: /* integer_list ::= NK_INTEGER */ -{ yylhsminor.yy601 = createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy601 = yylhsminor.yy601; - break; - case 120: /* integer_list ::= integer_list NK_COMMA NK_INTEGER */ - case 316: /* dnode_list ::= dnode_list DNODE NK_INTEGER */ yytestcase(yyruleno==316); -{ yylhsminor.yy601 = addNodeToList(pCxt, yymsp[-2].minor.yy601, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); } - yymsp[-2].minor.yy601 = yylhsminor.yy601; - break; - case 121: /* variable_list ::= NK_VARIABLE */ -{ yylhsminor.yy601 = createNodeList(pCxt, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy601 = yylhsminor.yy601; - break; - case 122: /* variable_list ::= variable_list NK_COMMA NK_VARIABLE */ -{ yylhsminor.yy601 = addNodeToList(pCxt, yymsp[-2].minor.yy601, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } - yymsp[-2].minor.yy601 = yylhsminor.yy601; - break; - case 123: /* retention_list ::= retention */ - case 145: /* multi_create_clause ::= create_subtable_clause */ yytestcase(yyruleno==145); - case 148: /* multi_drop_clause ::= drop_table_clause */ yytestcase(yyruleno==148); - case 155: /* column_def_list ::= column_def */ yytestcase(yyruleno==155); - case 199: /* rollup_func_list ::= rollup_func_name */ yytestcase(yyruleno==199); - case 204: /* col_name_list ::= col_name */ yytestcase(yyruleno==204); - case 253: /* tag_list_opt ::= tag_item */ yytestcase(yyruleno==253); - case 266: /* func_list ::= func */ yytestcase(yyruleno==266); - case 344: /* literal_list ::= signed_literal */ yytestcase(yyruleno==344); - case 410: /* other_para_list ::= star_func_para */ yytestcase(yyruleno==410); - case 416: /* when_then_list ::= when_then_expr */ yytestcase(yyruleno==416); - case 471: /* select_list ::= select_item */ yytestcase(yyruleno==471); - case 482: /* partition_list ::= partition_item */ yytestcase(yyruleno==482); - case 536: /* sort_specification_list ::= sort_specification */ yytestcase(yyruleno==536); -{ yylhsminor.yy601 = createNodeList(pCxt, yymsp[0].minor.yy600); } - yymsp[0].minor.yy601 = yylhsminor.yy601; - break; - case 124: /* retention_list ::= retention_list NK_COMMA retention */ - case 156: /* column_def_list ::= column_def_list NK_COMMA column_def */ yytestcase(yyruleno==156); - case 200: /* rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name */ yytestcase(yyruleno==200); - case 205: /* col_name_list ::= col_name_list NK_COMMA col_name */ yytestcase(yyruleno==205); - case 254: /* tag_list_opt ::= tag_list_opt NK_COMMA tag_item */ yytestcase(yyruleno==254); - case 267: /* func_list ::= func_list NK_COMMA func */ yytestcase(yyruleno==267); - case 345: /* literal_list ::= literal_list NK_COMMA signed_literal */ yytestcase(yyruleno==345); - case 411: /* other_para_list ::= other_para_list NK_COMMA star_func_para */ yytestcase(yyruleno==411); - case 472: /* select_list ::= select_list NK_COMMA select_item */ yytestcase(yyruleno==472); - case 483: /* partition_list ::= partition_list NK_COMMA partition_item */ yytestcase(yyruleno==483); - case 537: /* sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ yytestcase(yyruleno==537); -{ yylhsminor.yy601 = addNodeToList(pCxt, yymsp[-2].minor.yy601, yymsp[0].minor.yy600); } - yymsp[-2].minor.yy601 = yylhsminor.yy601; - break; - case 125: /* retention ::= NK_VARIABLE NK_COLON NK_VARIABLE */ -{ yylhsminor.yy600 = createNodeListNodeEx(pCxt, createDurationValueNode(pCxt, &yymsp[-2].minor.yy0), createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 126: /* speed_opt ::= */ - case 293: /* bufsize_opt ::= */ yytestcase(yyruleno==293); -{ yymsp[1].minor.yy248 = 0; } - break; - case 127: /* speed_opt ::= MAX_SPEED NK_INTEGER */ - case 294: /* bufsize_opt ::= BUFSIZE NK_INTEGER */ yytestcase(yyruleno==294); -{ yymsp[-1].minor.yy248 = taosStr2Int32(yymsp[0].minor.yy0.z, NULL, 10); } - break; - case 128: /* cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options */ - case 130: /* cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options */ yytestcase(yyruleno==130); -{ pCxt->pRootNode = createCreateTableStmt(pCxt, yymsp[-6].minor.yy841, yymsp[-5].minor.yy600, yymsp[-3].minor.yy601, yymsp[-1].minor.yy601, yymsp[0].minor.yy600); } - break; - case 129: /* cmd ::= CREATE TABLE multi_create_clause */ -{ pCxt->pRootNode = createCreateMultiTableStmt(pCxt, yymsp[0].minor.yy601); } - break; - case 131: /* cmd ::= DROP TABLE multi_drop_clause */ -{ pCxt->pRootNode = createDropTableStmt(pCxt, yymsp[0].minor.yy601); } - break; - case 132: /* cmd ::= DROP STABLE exists_opt full_table_name */ -{ pCxt->pRootNode = createDropSuperTableStmt(pCxt, yymsp[-1].minor.yy841, yymsp[0].minor.yy600); } - break; - case 133: /* cmd ::= ALTER TABLE alter_table_clause */ - case 318: /* cmd ::= query_or_subquery */ yytestcase(yyruleno==318); -{ pCxt->pRootNode = yymsp[0].minor.yy600; } - break; - case 134: /* cmd ::= ALTER STABLE alter_table_clause */ -{ pCxt->pRootNode = setAlterSuperTableType(yymsp[0].minor.yy600); } - break; - case 135: /* alter_table_clause ::= full_table_name alter_table_options */ -{ yylhsminor.yy600 = createAlterTableModifyOptions(pCxt, yymsp[-1].minor.yy600, yymsp[0].minor.yy600); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; - break; - case 136: /* alter_table_clause ::= full_table_name ADD COLUMN column_name type_name */ -{ yylhsminor.yy600 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy600, TSDB_ALTER_TABLE_ADD_COLUMN, &yymsp[-1].minor.yy77, yymsp[0].minor.yy888); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; - break; - case 137: /* alter_table_clause ::= full_table_name DROP COLUMN column_name */ -{ yylhsminor.yy600 = createAlterTableDropCol(pCxt, yymsp[-3].minor.yy600, TSDB_ALTER_TABLE_DROP_COLUMN, &yymsp[0].minor.yy77); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; - break; - case 138: /* alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name */ -{ yylhsminor.yy600 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy600, TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, &yymsp[-1].minor.yy77, yymsp[0].minor.yy888); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; - break; - case 139: /* alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name */ -{ yylhsminor.yy600 = createAlterTableRenameCol(pCxt, yymsp[-4].minor.yy600, TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, &yymsp[-1].minor.yy77, &yymsp[0].minor.yy77); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; - break; - case 140: /* alter_table_clause ::= full_table_name ADD TAG column_name type_name */ -{ yylhsminor.yy600 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy600, TSDB_ALTER_TABLE_ADD_TAG, &yymsp[-1].minor.yy77, yymsp[0].minor.yy888); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; - break; - case 141: /* alter_table_clause ::= full_table_name DROP TAG column_name */ -{ yylhsminor.yy600 = createAlterTableDropCol(pCxt, yymsp[-3].minor.yy600, TSDB_ALTER_TABLE_DROP_TAG, &yymsp[0].minor.yy77); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; - break; - case 142: /* alter_table_clause ::= full_table_name MODIFY TAG column_name type_name */ -{ yylhsminor.yy600 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy600, TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, &yymsp[-1].minor.yy77, yymsp[0].minor.yy888); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; - break; - case 143: /* alter_table_clause ::= full_table_name RENAME TAG column_name column_name */ -{ yylhsminor.yy600 = createAlterTableRenameCol(pCxt, yymsp[-4].minor.yy600, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, &yymsp[-1].minor.yy77, &yymsp[0].minor.yy77); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; - break; - case 144: /* alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal */ -{ yylhsminor.yy600 = createAlterTableSetTag(pCxt, yymsp[-5].minor.yy600, &yymsp[-2].minor.yy77, yymsp[0].minor.yy600); } - yymsp[-5].minor.yy600 = yylhsminor.yy600; - break; - case 146: /* multi_create_clause ::= multi_create_clause create_subtable_clause */ - case 149: /* multi_drop_clause ::= multi_drop_clause drop_table_clause */ yytestcase(yyruleno==149); - case 417: /* when_then_list ::= when_then_list when_then_expr */ yytestcase(yyruleno==417); -{ yylhsminor.yy601 = addNodeToList(pCxt, yymsp[-1].minor.yy601, yymsp[0].minor.yy600); } - yymsp[-1].minor.yy601 = yylhsminor.yy601; break; - case 147: /* create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_cols_opt TAGS NK_LP expression_list NK_RP table_options */ -{ yylhsminor.yy600 = createCreateSubTableClause(pCxt, yymsp[-9].minor.yy841, yymsp[-8].minor.yy600, yymsp[-6].minor.yy600, yymsp[-5].minor.yy601, yymsp[-2].minor.yy601, yymsp[0].minor.yy600); } - yymsp[-9].minor.yy600 = yylhsminor.yy600; + case 128: /* integer_list ::= NK_INTEGER */ +{ yylhsminor.yy432 = createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy432 = yylhsminor.yy432; + break; + case 129: /* integer_list ::= integer_list NK_COMMA NK_INTEGER */ + case 351: /* dnode_list ::= dnode_list DNODE NK_INTEGER */ yytestcase(yyruleno==351); +{ yylhsminor.yy432 = addNodeToList(pCxt, yymsp[-2].minor.yy432, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); } + yymsp[-2].minor.yy432 = yylhsminor.yy432; + break; + case 130: /* variable_list ::= NK_VARIABLE */ +{ yylhsminor.yy432 = createNodeList(pCxt, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy432 = yylhsminor.yy432; + break; + case 131: /* variable_list ::= variable_list NK_COMMA NK_VARIABLE */ +{ yylhsminor.yy432 = addNodeToList(pCxt, yymsp[-2].minor.yy432, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } + yymsp[-2].minor.yy432 = yylhsminor.yy432; + break; + case 132: /* retention_list ::= retention */ + case 162: /* multi_create_clause ::= create_subtable_clause */ yytestcase(yyruleno==162); + case 165: /* multi_drop_clause ::= drop_table_clause */ yytestcase(yyruleno==165); + case 172: /* column_def_list ::= column_def */ yytestcase(yyruleno==172); + case 215: /* rollup_func_list ::= rollup_func_name */ yytestcase(yyruleno==215); + case 220: /* col_name_list ::= col_name */ yytestcase(yyruleno==220); + case 271: /* tag_list_opt ::= tag_item */ yytestcase(yyruleno==271); + case 285: /* func_list ::= func */ yytestcase(yyruleno==285); + case 380: /* literal_list ::= signed_literal */ yytestcase(yyruleno==380); + case 447: /* other_para_list ::= star_func_para */ yytestcase(yyruleno==447); + case 453: /* when_then_list ::= when_then_expr */ yytestcase(yyruleno==453); + case 508: /* select_list ::= select_item */ yytestcase(yyruleno==508); + case 519: /* partition_list ::= partition_item */ yytestcase(yyruleno==519); + case 574: /* sort_specification_list ::= sort_specification */ yytestcase(yyruleno==574); +{ yylhsminor.yy432 = createNodeList(pCxt, yymsp[0].minor.yy448); } + yymsp[0].minor.yy432 = yylhsminor.yy432; + break; + case 133: /* retention_list ::= retention_list NK_COMMA retention */ + case 166: /* multi_drop_clause ::= multi_drop_clause NK_COMMA drop_table_clause */ yytestcase(yyruleno==166); + case 173: /* column_def_list ::= column_def_list NK_COMMA column_def */ yytestcase(yyruleno==173); + case 216: /* rollup_func_list ::= rollup_func_list NK_COMMA rollup_func_name */ yytestcase(yyruleno==216); + case 221: /* col_name_list ::= col_name_list NK_COMMA col_name */ yytestcase(yyruleno==221); + case 272: /* tag_list_opt ::= tag_list_opt NK_COMMA tag_item */ yytestcase(yyruleno==272); + case 286: /* func_list ::= func_list NK_COMMA func */ yytestcase(yyruleno==286); + case 381: /* literal_list ::= literal_list NK_COMMA signed_literal */ yytestcase(yyruleno==381); + case 448: /* other_para_list ::= other_para_list NK_COMMA star_func_para */ yytestcase(yyruleno==448); + case 509: /* select_list ::= select_list NK_COMMA select_item */ yytestcase(yyruleno==509); + case 520: /* partition_list ::= partition_list NK_COMMA partition_item */ yytestcase(yyruleno==520); + case 575: /* sort_specification_list ::= sort_specification_list NK_COMMA sort_specification */ yytestcase(yyruleno==575); +{ yylhsminor.yy432 = addNodeToList(pCxt, yymsp[-2].minor.yy432, yymsp[0].minor.yy448); } + yymsp[-2].minor.yy432 = yylhsminor.yy432; + break; + case 134: /* retention ::= NK_VARIABLE NK_COLON NK_VARIABLE */ +{ yylhsminor.yy448 = createNodeListNodeEx(pCxt, createDurationValueNode(pCxt, &yymsp[-2].minor.yy0), createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 135: /* speed_opt ::= */ + case 318: /* bufsize_opt ::= */ yytestcase(yyruleno==318); +{ yymsp[1].minor.yy788 = 0; } + break; + case 136: /* speed_opt ::= MAX_SPEED NK_INTEGER */ + case 319: /* bufsize_opt ::= BUFSIZE NK_INTEGER */ yytestcase(yyruleno==319); +{ yymsp[-1].minor.yy788 = taosStr2Int32(yymsp[0].minor.yy0.z, NULL, 10); } + break; + case 138: /* start_opt ::= START WITH NK_INTEGER */ + case 142: /* end_opt ::= END WITH NK_INTEGER */ yytestcase(yyruleno==142); +{ yymsp[-2].minor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0); } + break; + case 139: /* start_opt ::= START WITH NK_STRING */ + case 143: /* end_opt ::= END WITH NK_STRING */ yytestcase(yyruleno==143); +{ yymsp[-2].minor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0); } + break; + case 140: /* start_opt ::= START WITH TIMESTAMP NK_STRING */ + case 144: /* end_opt ::= END WITH TIMESTAMP NK_STRING */ yytestcase(yyruleno==144); +{ yymsp[-3].minor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0); } + break; + case 145: /* cmd ::= CREATE TABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def_opt table_options */ + case 147: /* cmd ::= CREATE STABLE not_exists_opt full_table_name NK_LP column_def_list NK_RP tags_def table_options */ yytestcase(yyruleno==147); +{ pCxt->pRootNode = createCreateTableStmt(pCxt, yymsp[-6].minor.yy369, yymsp[-5].minor.yy448, yymsp[-3].minor.yy432, yymsp[-1].minor.yy432, yymsp[0].minor.yy448); } + break; + case 146: /* cmd ::= CREATE TABLE multi_create_clause */ +{ pCxt->pRootNode = createCreateMultiTableStmt(pCxt, yymsp[0].minor.yy432); } + break; + case 148: /* cmd ::= DROP TABLE multi_drop_clause */ +{ pCxt->pRootNode = createDropTableStmt(pCxt, yymsp[0].minor.yy432); } + break; + case 149: /* cmd ::= DROP STABLE exists_opt full_table_name */ +{ pCxt->pRootNode = createDropSuperTableStmt(pCxt, yymsp[-1].minor.yy369, yymsp[0].minor.yy448); } + break; + case 150: /* cmd ::= ALTER TABLE alter_table_clause */ + case 353: /* cmd ::= query_or_subquery */ yytestcase(yyruleno==353); + case 354: /* cmd ::= insert_query */ yytestcase(yyruleno==354); +{ pCxt->pRootNode = yymsp[0].minor.yy448; } + break; + case 151: /* cmd ::= ALTER STABLE alter_table_clause */ +{ pCxt->pRootNode = setAlterSuperTableType(yymsp[0].minor.yy448); } + break; + case 152: /* alter_table_clause ::= full_table_name alter_table_options */ +{ yylhsminor.yy448 = createAlterTableModifyOptions(pCxt, yymsp[-1].minor.yy448, yymsp[0].minor.yy448); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; + break; + case 153: /* alter_table_clause ::= full_table_name ADD COLUMN column_name type_name */ +{ yylhsminor.yy448 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy448, TSDB_ALTER_TABLE_ADD_COLUMN, &yymsp[-1].minor.yy113, yymsp[0].minor.yy728); } + yymsp[-4].minor.yy448 = yylhsminor.yy448; + break; + case 154: /* alter_table_clause ::= full_table_name DROP COLUMN column_name */ +{ yylhsminor.yy448 = createAlterTableDropCol(pCxt, yymsp[-3].minor.yy448, TSDB_ALTER_TABLE_DROP_COLUMN, &yymsp[0].minor.yy113); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; + break; + case 155: /* alter_table_clause ::= full_table_name MODIFY COLUMN column_name type_name */ +{ yylhsminor.yy448 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy448, TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, &yymsp[-1].minor.yy113, yymsp[0].minor.yy728); } + yymsp[-4].minor.yy448 = yylhsminor.yy448; + break; + case 156: /* alter_table_clause ::= full_table_name RENAME COLUMN column_name column_name */ +{ yylhsminor.yy448 = createAlterTableRenameCol(pCxt, yymsp[-4].minor.yy448, TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, &yymsp[-1].minor.yy113, &yymsp[0].minor.yy113); } + yymsp[-4].minor.yy448 = yylhsminor.yy448; + break; + case 157: /* alter_table_clause ::= full_table_name ADD TAG column_name type_name */ +{ yylhsminor.yy448 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy448, TSDB_ALTER_TABLE_ADD_TAG, &yymsp[-1].minor.yy113, yymsp[0].minor.yy728); } + yymsp[-4].minor.yy448 = yylhsminor.yy448; + break; + case 158: /* alter_table_clause ::= full_table_name DROP TAG column_name */ +{ yylhsminor.yy448 = createAlterTableDropCol(pCxt, yymsp[-3].minor.yy448, TSDB_ALTER_TABLE_DROP_TAG, &yymsp[0].minor.yy113); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; + break; + case 159: /* alter_table_clause ::= full_table_name MODIFY TAG column_name type_name */ +{ yylhsminor.yy448 = createAlterTableAddModifyCol(pCxt, yymsp[-4].minor.yy448, TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, &yymsp[-1].minor.yy113, yymsp[0].minor.yy728); } + yymsp[-4].minor.yy448 = yylhsminor.yy448; + break; + case 160: /* alter_table_clause ::= full_table_name RENAME TAG column_name column_name */ +{ yylhsminor.yy448 = createAlterTableRenameCol(pCxt, yymsp[-4].minor.yy448, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, &yymsp[-1].minor.yy113, &yymsp[0].minor.yy113); } + yymsp[-4].minor.yy448 = yylhsminor.yy448; + break; + case 161: /* alter_table_clause ::= full_table_name SET TAG column_name NK_EQ signed_literal */ +{ yylhsminor.yy448 = createAlterTableSetTag(pCxt, yymsp[-5].minor.yy448, &yymsp[-2].minor.yy113, yymsp[0].minor.yy448); } + yymsp[-5].minor.yy448 = yylhsminor.yy448; + break; + case 163: /* multi_create_clause ::= multi_create_clause create_subtable_clause */ + case 454: /* when_then_list ::= when_then_list when_then_expr */ yytestcase(yyruleno==454); +{ yylhsminor.yy432 = addNodeToList(pCxt, yymsp[-1].minor.yy432, yymsp[0].minor.yy448); } + yymsp[-1].minor.yy432 = yylhsminor.yy432; break; - case 150: /* drop_table_clause ::= exists_opt full_table_name */ -{ yylhsminor.yy600 = createDropTableClause(pCxt, yymsp[-1].minor.yy841, yymsp[0].minor.yy600); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + case 164: /* create_subtable_clause ::= not_exists_opt full_table_name USING full_table_name specific_cols_opt TAGS NK_LP expression_list NK_RP table_options */ +{ yylhsminor.yy448 = createCreateSubTableClause(pCxt, yymsp[-9].minor.yy369, yymsp[-8].minor.yy448, yymsp[-6].minor.yy448, yymsp[-5].minor.yy432, yymsp[-2].minor.yy432, yymsp[0].minor.yy448); } + yymsp[-9].minor.yy448 = yylhsminor.yy448; break; - case 151: /* specific_cols_opt ::= */ - case 182: /* tags_def_opt ::= */ yytestcase(yyruleno==182); - case 252: /* tag_list_opt ::= */ yytestcase(yyruleno==252); - case 480: /* partition_by_clause_opt ::= */ yytestcase(yyruleno==480); - case 504: /* group_by_clause_opt ::= */ yytestcase(yyruleno==504); - case 523: /* order_by_clause_opt ::= */ yytestcase(yyruleno==523); -{ yymsp[1].minor.yy601 = NULL; } + case 167: /* drop_table_clause ::= exists_opt full_table_name */ +{ yylhsminor.yy448 = createDropTableClause(pCxt, yymsp[-1].minor.yy369, yymsp[0].minor.yy448); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 152: /* specific_cols_opt ::= NK_LP col_name_list NK_RP */ -{ yymsp[-2].minor.yy601 = yymsp[-1].minor.yy601; } + case 168: /* specific_cols_opt ::= */ + case 198: /* tags_def_opt ::= */ yytestcase(yyruleno==198); + case 270: /* tag_list_opt ::= */ yytestcase(yyruleno==270); + case 326: /* col_list_opt ::= */ yytestcase(yyruleno==326); + case 328: /* tag_def_or_ref_opt ::= */ yytestcase(yyruleno==328); + case 517: /* partition_by_clause_opt ::= */ yytestcase(yyruleno==517); + case 542: /* group_by_clause_opt ::= */ yytestcase(yyruleno==542); + case 561: /* order_by_clause_opt ::= */ yytestcase(yyruleno==561); +{ yymsp[1].minor.yy432 = NULL; } break; - case 153: /* full_table_name ::= table_name */ -{ yylhsminor.yy600 = createRealTableNode(pCxt, NULL, &yymsp[0].minor.yy77, NULL); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 169: /* specific_cols_opt ::= NK_LP col_name_list NK_RP */ + case 327: /* col_list_opt ::= NK_LP col_name_list NK_RP */ yytestcase(yyruleno==327); +{ yymsp[-2].minor.yy432 = yymsp[-1].minor.yy432; } break; - case 154: /* full_table_name ::= db_name NK_DOT table_name */ -{ yylhsminor.yy600 = createRealTableNode(pCxt, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy77, NULL); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 170: /* full_table_name ::= table_name */ +{ yylhsminor.yy448 = createRealTableNode(pCxt, NULL, &yymsp[0].minor.yy113, NULL); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 157: /* column_def ::= column_name type_name */ -{ yylhsminor.yy600 = createColumnDefNode(pCxt, &yymsp[-1].minor.yy77, yymsp[0].minor.yy888, NULL); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + case 171: /* full_table_name ::= db_name NK_DOT table_name */ +{ yylhsminor.yy448 = createRealTableNode(pCxt, &yymsp[-2].minor.yy113, &yymsp[0].minor.yy113, NULL); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 158: /* column_def ::= column_name type_name COMMENT NK_STRING */ -{ yylhsminor.yy600 = createColumnDefNode(pCxt, &yymsp[-3].minor.yy77, yymsp[-2].minor.yy888, &yymsp[0].minor.yy0); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; + case 174: /* column_def ::= column_name type_name */ +{ yylhsminor.yy448 = createColumnDefNode(pCxt, &yymsp[-1].minor.yy113, yymsp[0].minor.yy728, NULL); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 159: /* type_name ::= BOOL */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_BOOL); } + case 175: /* type_name ::= BOOL */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_BOOL); } break; - case 160: /* type_name ::= TINYINT */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_TINYINT); } + case 176: /* type_name ::= TINYINT */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_TINYINT); } break; - case 161: /* type_name ::= SMALLINT */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_SMALLINT); } + case 177: /* type_name ::= SMALLINT */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_SMALLINT); } break; - case 162: /* type_name ::= INT */ - case 163: /* type_name ::= INTEGER */ yytestcase(yyruleno==163); -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_INT); } + case 178: /* type_name ::= INT */ + case 179: /* type_name ::= INTEGER */ yytestcase(yyruleno==179); +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_INT); } break; - case 164: /* type_name ::= BIGINT */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_BIGINT); } + case 180: /* type_name ::= BIGINT */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_BIGINT); } break; - case 165: /* type_name ::= FLOAT */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_FLOAT); } + case 181: /* type_name ::= FLOAT */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_FLOAT); } break; - case 166: /* type_name ::= DOUBLE */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_DOUBLE); } + case 182: /* type_name ::= DOUBLE */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_DOUBLE); } break; - case 167: /* type_name ::= BINARY NK_LP NK_INTEGER NK_RP */ -{ yymsp[-3].minor.yy888 = createVarLenDataType(TSDB_DATA_TYPE_BINARY, &yymsp[-1].minor.yy0); } + case 183: /* type_name ::= BINARY NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy728 = createVarLenDataType(TSDB_DATA_TYPE_BINARY, &yymsp[-1].minor.yy0); } break; - case 168: /* type_name ::= TIMESTAMP */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_TIMESTAMP); } + case 184: /* type_name ::= TIMESTAMP */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_TIMESTAMP); } break; - case 169: /* type_name ::= NCHAR NK_LP NK_INTEGER NK_RP */ -{ yymsp[-3].minor.yy888 = createVarLenDataType(TSDB_DATA_TYPE_NCHAR, &yymsp[-1].minor.yy0); } + case 185: /* type_name ::= NCHAR NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy728 = createVarLenDataType(TSDB_DATA_TYPE_NCHAR, &yymsp[-1].minor.yy0); } break; - case 170: /* type_name ::= TINYINT UNSIGNED */ -{ yymsp[-1].minor.yy888 = createDataType(TSDB_DATA_TYPE_UTINYINT); } + case 186: /* type_name ::= TINYINT UNSIGNED */ +{ yymsp[-1].minor.yy728 = createDataType(TSDB_DATA_TYPE_UTINYINT); } break; - case 171: /* type_name ::= SMALLINT UNSIGNED */ -{ yymsp[-1].minor.yy888 = createDataType(TSDB_DATA_TYPE_USMALLINT); } + case 187: /* type_name ::= SMALLINT UNSIGNED */ +{ yymsp[-1].minor.yy728 = createDataType(TSDB_DATA_TYPE_USMALLINT); } break; - case 172: /* type_name ::= INT UNSIGNED */ -{ yymsp[-1].minor.yy888 = createDataType(TSDB_DATA_TYPE_UINT); } + case 188: /* type_name ::= INT UNSIGNED */ +{ yymsp[-1].minor.yy728 = createDataType(TSDB_DATA_TYPE_UINT); } break; - case 173: /* type_name ::= BIGINT UNSIGNED */ -{ yymsp[-1].minor.yy888 = createDataType(TSDB_DATA_TYPE_UBIGINT); } + case 189: /* type_name ::= BIGINT UNSIGNED */ +{ yymsp[-1].minor.yy728 = createDataType(TSDB_DATA_TYPE_UBIGINT); } break; - case 174: /* type_name ::= JSON */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_JSON); } + case 190: /* type_name ::= JSON */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_JSON); } break; - case 175: /* type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP */ -{ yymsp[-3].minor.yy888 = createVarLenDataType(TSDB_DATA_TYPE_VARCHAR, &yymsp[-1].minor.yy0); } + case 191: /* type_name ::= VARCHAR NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy728 = createVarLenDataType(TSDB_DATA_TYPE_VARCHAR, &yymsp[-1].minor.yy0); } break; - case 176: /* type_name ::= MEDIUMBLOB */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_MEDIUMBLOB); } + case 192: /* type_name ::= MEDIUMBLOB */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_MEDIUMBLOB); } break; - case 177: /* type_name ::= BLOB */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_BLOB); } + case 193: /* type_name ::= BLOB */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_BLOB); } break; - case 178: /* type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP */ -{ yymsp[-3].minor.yy888 = createVarLenDataType(TSDB_DATA_TYPE_VARBINARY, &yymsp[-1].minor.yy0); } + case 194: /* type_name ::= VARBINARY NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy728 = createVarLenDataType(TSDB_DATA_TYPE_VARBINARY, &yymsp[-1].minor.yy0); } break; - case 179: /* type_name ::= DECIMAL */ -{ yymsp[0].minor.yy888 = createDataType(TSDB_DATA_TYPE_DECIMAL); } + case 195: /* type_name ::= DECIMAL */ +{ yymsp[0].minor.yy728 = createDataType(TSDB_DATA_TYPE_DECIMAL); } break; - case 180: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP */ -{ yymsp[-3].minor.yy888 = createDataType(TSDB_DATA_TYPE_DECIMAL); } + case 196: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_RP */ +{ yymsp[-3].minor.yy728 = createDataType(TSDB_DATA_TYPE_DECIMAL); } break; - case 181: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP */ -{ yymsp[-5].minor.yy888 = createDataType(TSDB_DATA_TYPE_DECIMAL); } + case 197: /* type_name ::= DECIMAL NK_LP NK_INTEGER NK_COMMA NK_INTEGER NK_RP */ +{ yymsp[-5].minor.yy728 = createDataType(TSDB_DATA_TYPE_DECIMAL); } break; - case 183: /* tags_def_opt ::= tags_def */ - case 409: /* star_func_para_list ::= other_para_list */ yytestcase(yyruleno==409); -{ yylhsminor.yy601 = yymsp[0].minor.yy601; } - yymsp[0].minor.yy601 = yylhsminor.yy601; + case 199: /* tags_def_opt ::= tags_def */ + case 329: /* tag_def_or_ref_opt ::= tags_def */ yytestcase(yyruleno==329); + case 446: /* star_func_para_list ::= other_para_list */ yytestcase(yyruleno==446); +{ yylhsminor.yy432 = yymsp[0].minor.yy432; } + yymsp[0].minor.yy432 = yylhsminor.yy432; break; - case 184: /* tags_def ::= TAGS NK_LP column_def_list NK_RP */ -{ yymsp[-3].minor.yy601 = yymsp[-1].minor.yy601; } + case 200: /* tags_def ::= TAGS NK_LP column_def_list NK_RP */ + case 330: /* tag_def_or_ref_opt ::= TAGS NK_LP col_name_list NK_RP */ yytestcase(yyruleno==330); +{ yymsp[-3].minor.yy432 = yymsp[-1].minor.yy432; } break; - case 185: /* table_options ::= */ -{ yymsp[1].minor.yy600 = createDefaultTableOptions(pCxt); } + case 201: /* table_options ::= */ +{ yymsp[1].minor.yy448 = createDefaultTableOptions(pCxt); } break; - case 186: /* table_options ::= table_options COMMENT NK_STRING */ -{ yylhsminor.yy600 = setTableOption(pCxt, yymsp[-2].minor.yy600, TABLE_OPTION_COMMENT, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 202: /* table_options ::= table_options COMMENT NK_STRING */ +{ yylhsminor.yy448 = setTableOption(pCxt, yymsp[-2].minor.yy448, TABLE_OPTION_COMMENT, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 187: /* table_options ::= table_options MAX_DELAY duration_list */ -{ yylhsminor.yy600 = setTableOption(pCxt, yymsp[-2].minor.yy600, TABLE_OPTION_MAXDELAY, yymsp[0].minor.yy601); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 203: /* table_options ::= table_options MAX_DELAY duration_list */ +{ yylhsminor.yy448 = setTableOption(pCxt, yymsp[-2].minor.yy448, TABLE_OPTION_MAXDELAY, yymsp[0].minor.yy432); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 188: /* table_options ::= table_options WATERMARK duration_list */ -{ yylhsminor.yy600 = setTableOption(pCxt, yymsp[-2].minor.yy600, TABLE_OPTION_WATERMARK, yymsp[0].minor.yy601); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 204: /* table_options ::= table_options WATERMARK duration_list */ +{ yylhsminor.yy448 = setTableOption(pCxt, yymsp[-2].minor.yy448, TABLE_OPTION_WATERMARK, yymsp[0].minor.yy432); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 189: /* table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP */ -{ yylhsminor.yy600 = setTableOption(pCxt, yymsp[-4].minor.yy600, TABLE_OPTION_ROLLUP, yymsp[-1].minor.yy601); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; + case 205: /* table_options ::= table_options ROLLUP NK_LP rollup_func_list NK_RP */ +{ yylhsminor.yy448 = setTableOption(pCxt, yymsp[-4].minor.yy448, TABLE_OPTION_ROLLUP, yymsp[-1].minor.yy432); } + yymsp[-4].minor.yy448 = yylhsminor.yy448; break; - case 190: /* table_options ::= table_options TTL NK_INTEGER */ -{ yylhsminor.yy600 = setTableOption(pCxt, yymsp[-2].minor.yy600, TABLE_OPTION_TTL, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 206: /* table_options ::= table_options TTL NK_INTEGER */ +{ yylhsminor.yy448 = setTableOption(pCxt, yymsp[-2].minor.yy448, TABLE_OPTION_TTL, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 191: /* table_options ::= table_options SMA NK_LP col_name_list NK_RP */ -{ yylhsminor.yy600 = setTableOption(pCxt, yymsp[-4].minor.yy600, TABLE_OPTION_SMA, yymsp[-1].minor.yy601); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; + case 207: /* table_options ::= table_options SMA NK_LP col_name_list NK_RP */ +{ yylhsminor.yy448 = setTableOption(pCxt, yymsp[-4].minor.yy448, TABLE_OPTION_SMA, yymsp[-1].minor.yy432); } + yymsp[-4].minor.yy448 = yylhsminor.yy448; break; - case 192: /* table_options ::= table_options DELETE_MARK duration_list */ -{ yylhsminor.yy600 = setTableOption(pCxt, yymsp[-2].minor.yy600, TABLE_OPTION_DELETE_MARK, yymsp[0].minor.yy601); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 208: /* table_options ::= table_options DELETE_MARK duration_list */ +{ yylhsminor.yy448 = setTableOption(pCxt, yymsp[-2].minor.yy448, TABLE_OPTION_DELETE_MARK, yymsp[0].minor.yy432); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 193: /* alter_table_options ::= alter_table_option */ -{ yylhsminor.yy600 = createAlterTableOptions(pCxt); yylhsminor.yy600 = setTableOption(pCxt, yylhsminor.yy600, yymsp[0].minor.yy661.type, &yymsp[0].minor.yy661.val); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 209: /* alter_table_options ::= alter_table_option */ +{ yylhsminor.yy448 = createAlterTableOptions(pCxt); yylhsminor.yy448 = setTableOption(pCxt, yylhsminor.yy448, yymsp[0].minor.yy53.type, &yymsp[0].minor.yy53.val); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 194: /* alter_table_options ::= alter_table_options alter_table_option */ -{ yylhsminor.yy600 = setTableOption(pCxt, yymsp[-1].minor.yy600, yymsp[0].minor.yy661.type, &yymsp[0].minor.yy661.val); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + case 210: /* alter_table_options ::= alter_table_options alter_table_option */ +{ yylhsminor.yy448 = setTableOption(pCxt, yymsp[-1].minor.yy448, yymsp[0].minor.yy53.type, &yymsp[0].minor.yy53.val); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 195: /* alter_table_option ::= COMMENT NK_STRING */ -{ yymsp[-1].minor.yy661.type = TABLE_OPTION_COMMENT; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } + case 211: /* alter_table_option ::= COMMENT NK_STRING */ +{ yymsp[-1].minor.yy53.type = TABLE_OPTION_COMMENT; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 196: /* alter_table_option ::= TTL NK_INTEGER */ -{ yymsp[-1].minor.yy661.type = TABLE_OPTION_TTL; yymsp[-1].minor.yy661.val = yymsp[0].minor.yy0; } + case 212: /* alter_table_option ::= TTL NK_INTEGER */ +{ yymsp[-1].minor.yy53.type = TABLE_OPTION_TTL; yymsp[-1].minor.yy53.val = yymsp[0].minor.yy0; } break; - case 197: /* duration_list ::= duration_literal */ - case 374: /* expression_list ::= expr_or_subquery */ yytestcase(yyruleno==374); -{ yylhsminor.yy601 = createNodeList(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy600)); } - yymsp[0].minor.yy601 = yylhsminor.yy601; + case 213: /* duration_list ::= duration_literal */ + case 410: /* expression_list ::= expr_or_subquery */ yytestcase(yyruleno==410); +{ yylhsminor.yy432 = createNodeList(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy448)); } + yymsp[0].minor.yy432 = yylhsminor.yy432; break; - case 198: /* duration_list ::= duration_list NK_COMMA duration_literal */ - case 375: /* expression_list ::= expression_list NK_COMMA expr_or_subquery */ yytestcase(yyruleno==375); -{ yylhsminor.yy601 = addNodeToList(pCxt, yymsp[-2].minor.yy601, releaseRawExprNode(pCxt, yymsp[0].minor.yy600)); } - yymsp[-2].minor.yy601 = yylhsminor.yy601; + case 214: /* duration_list ::= duration_list NK_COMMA duration_literal */ + case 411: /* expression_list ::= expression_list NK_COMMA expr_or_subquery */ yytestcase(yyruleno==411); +{ yylhsminor.yy432 = addNodeToList(pCxt, yymsp[-2].minor.yy432, releaseRawExprNode(pCxt, yymsp[0].minor.yy448)); } + yymsp[-2].minor.yy432 = yylhsminor.yy432; break; - case 201: /* rollup_func_name ::= function_name */ -{ yylhsminor.yy600 = createFunctionNode(pCxt, &yymsp[0].minor.yy77, NULL); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 217: /* rollup_func_name ::= function_name */ +{ yylhsminor.yy448 = createFunctionNode(pCxt, &yymsp[0].minor.yy113, NULL); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 202: /* rollup_func_name ::= FIRST */ - case 203: /* rollup_func_name ::= LAST */ yytestcase(yyruleno==203); - case 256: /* tag_item ::= QTAGS */ yytestcase(yyruleno==256); -{ yylhsminor.yy600 = createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 218: /* rollup_func_name ::= FIRST */ + case 219: /* rollup_func_name ::= LAST */ yytestcase(yyruleno==219); + case 274: /* tag_item ::= QTAGS */ yytestcase(yyruleno==274); +{ yylhsminor.yy448 = createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 206: /* col_name ::= column_name */ - case 257: /* tag_item ::= column_name */ yytestcase(yyruleno==257); -{ yylhsminor.yy600 = createColumnNode(pCxt, NULL, &yymsp[0].minor.yy77); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 222: /* col_name ::= column_name */ + case 275: /* tag_item ::= column_name */ yytestcase(yyruleno==275); +{ yylhsminor.yy448 = createColumnNode(pCxt, NULL, &yymsp[0].minor.yy113); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 207: /* cmd ::= SHOW DNODES */ + case 223: /* cmd ::= SHOW DNODES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_DNODES_STMT); } break; - case 208: /* cmd ::= SHOW USERS */ + case 224: /* cmd ::= SHOW USERS */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_USERS_STMT); } break; - case 209: /* cmd ::= SHOW USER PRIVILEGES */ + case 225: /* cmd ::= SHOW USER PRIVILEGES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_USER_PRIVILEGES_STMT); } break; - case 210: /* cmd ::= SHOW DATABASES */ + case 226: /* cmd ::= SHOW DATABASES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_DATABASES_STMT); } break; - case 211: /* cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt */ -{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_TABLES_STMT, yymsp[-2].minor.yy600, yymsp[0].minor.yy600, OP_TYPE_LIKE); } + case 227: /* cmd ::= SHOW db_name_cond_opt TABLES like_pattern_opt */ +{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_TABLES_STMT, yymsp[-2].minor.yy448, yymsp[0].minor.yy448, OP_TYPE_LIKE); } break; - case 212: /* cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt */ -{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_STABLES_STMT, yymsp[-2].minor.yy600, yymsp[0].minor.yy600, OP_TYPE_LIKE); } + case 228: /* cmd ::= SHOW db_name_cond_opt STABLES like_pattern_opt */ +{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_STABLES_STMT, yymsp[-2].minor.yy448, yymsp[0].minor.yy448, OP_TYPE_LIKE); } break; - case 213: /* cmd ::= SHOW db_name_cond_opt VGROUPS */ -{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_VGROUPS_STMT, yymsp[-1].minor.yy600, NULL, OP_TYPE_LIKE); } + case 229: /* cmd ::= SHOW db_name_cond_opt VGROUPS */ +{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_VGROUPS_STMT, yymsp[-1].minor.yy448, NULL, OP_TYPE_LIKE); } break; - case 214: /* cmd ::= SHOW MNODES */ + case 230: /* cmd ::= SHOW MNODES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_MNODES_STMT); } break; - case 215: /* cmd ::= SHOW QNODES */ + case 231: /* cmd ::= SHOW QNODES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_QNODES_STMT); } break; - case 216: /* cmd ::= SHOW FUNCTIONS */ + case 232: /* cmd ::= SHOW FUNCTIONS */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_FUNCTIONS_STMT); } break; - case 217: /* cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt */ -{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_INDEXES_STMT, yymsp[0].minor.yy600, yymsp[-1].minor.yy600, OP_TYPE_EQUAL); } + case 233: /* cmd ::= SHOW INDEXES FROM table_name_cond from_db_opt */ +{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_INDEXES_STMT, yymsp[0].minor.yy448, yymsp[-1].minor.yy448, OP_TYPE_EQUAL); } break; - case 218: /* cmd ::= SHOW STREAMS */ + case 234: /* cmd ::= SHOW STREAMS */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_STREAMS_STMT); } break; - case 219: /* cmd ::= SHOW ACCOUNTS */ + case 235: /* cmd ::= SHOW ACCOUNTS */ { pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_EXPRIE_STATEMENT); } break; - case 220: /* cmd ::= SHOW APPS */ + case 236: /* cmd ::= SHOW APPS */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_APPS_STMT); } break; - case 221: /* cmd ::= SHOW CONNECTIONS */ + case 237: /* cmd ::= SHOW CONNECTIONS */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CONNECTIONS_STMT); } break; - case 222: /* cmd ::= SHOW LICENCES */ - case 223: /* cmd ::= SHOW GRANTS */ yytestcase(yyruleno==223); + case 238: /* cmd ::= SHOW LICENCES */ + case 239: /* cmd ::= SHOW GRANTS */ yytestcase(yyruleno==239); { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_LICENCES_STMT); } break; - case 224: /* cmd ::= SHOW CREATE DATABASE db_name */ -{ pCxt->pRootNode = createShowCreateDatabaseStmt(pCxt, &yymsp[0].minor.yy77); } + case 240: /* cmd ::= SHOW CREATE DATABASE db_name */ +{ pCxt->pRootNode = createShowCreateDatabaseStmt(pCxt, &yymsp[0].minor.yy113); } break; - case 225: /* cmd ::= SHOW CREATE TABLE full_table_name */ -{ pCxt->pRootNode = createShowCreateTableStmt(pCxt, QUERY_NODE_SHOW_CREATE_TABLE_STMT, yymsp[0].minor.yy600); } + case 241: /* cmd ::= SHOW CREATE TABLE full_table_name */ +{ pCxt->pRootNode = createShowCreateTableStmt(pCxt, QUERY_NODE_SHOW_CREATE_TABLE_STMT, yymsp[0].minor.yy448); } break; - case 226: /* cmd ::= SHOW CREATE STABLE full_table_name */ -{ pCxt->pRootNode = createShowCreateTableStmt(pCxt, QUERY_NODE_SHOW_CREATE_STABLE_STMT, yymsp[0].minor.yy600); } + case 242: /* cmd ::= SHOW CREATE STABLE full_table_name */ +{ pCxt->pRootNode = createShowCreateTableStmt(pCxt, QUERY_NODE_SHOW_CREATE_STABLE_STMT, yymsp[0].minor.yy448); } break; - case 227: /* cmd ::= SHOW QUERIES */ + case 243: /* cmd ::= SHOW QUERIES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_QUERIES_STMT); } break; - case 228: /* cmd ::= SHOW SCORES */ + case 244: /* cmd ::= SHOW SCORES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_SCORES_STMT); } break; - case 229: /* cmd ::= SHOW TOPICS */ + case 245: /* cmd ::= SHOW TOPICS */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_TOPICS_STMT); } break; - case 230: /* cmd ::= SHOW VARIABLES */ - case 231: /* cmd ::= SHOW CLUSTER VARIABLES */ yytestcase(yyruleno==231); + case 246: /* cmd ::= SHOW VARIABLES */ + case 247: /* cmd ::= SHOW CLUSTER VARIABLES */ yytestcase(yyruleno==247); { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_VARIABLES_STMT); } break; - case 232: /* cmd ::= SHOW LOCAL VARIABLES */ + case 248: /* cmd ::= SHOW LOCAL VARIABLES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_LOCAL_VARIABLES_STMT); } break; - case 233: /* cmd ::= SHOW DNODE NK_INTEGER VARIABLES like_pattern_opt */ -{ pCxt->pRootNode = createShowDnodeVariablesStmt(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[-2].minor.yy0), yymsp[0].minor.yy600); } + case 249: /* cmd ::= SHOW DNODE NK_INTEGER VARIABLES like_pattern_opt */ +{ pCxt->pRootNode = createShowDnodeVariablesStmt(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[-2].minor.yy0), yymsp[0].minor.yy448); } break; - case 234: /* cmd ::= SHOW BNODES */ + case 250: /* cmd ::= SHOW BNODES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_BNODES_STMT); } break; - case 235: /* cmd ::= SHOW SNODES */ + case 251: /* cmd ::= SHOW SNODES */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_SNODES_STMT); } break; - case 236: /* cmd ::= SHOW CLUSTER */ + case 252: /* cmd ::= SHOW CLUSTER */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CLUSTER_STMT); } break; - case 237: /* cmd ::= SHOW TRANSACTIONS */ + case 253: /* cmd ::= SHOW TRANSACTIONS */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_TRANSACTIONS_STMT); } break; - case 238: /* cmd ::= SHOW TABLE DISTRIBUTED full_table_name */ -{ pCxt->pRootNode = createShowTableDistributedStmt(pCxt, yymsp[0].minor.yy600); } + case 254: /* cmd ::= SHOW TABLE DISTRIBUTED full_table_name */ +{ pCxt->pRootNode = createShowTableDistributedStmt(pCxt, yymsp[0].minor.yy448); } break; - case 239: /* cmd ::= SHOW CONSUMERS */ + case 255: /* cmd ::= SHOW CONSUMERS */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_CONSUMERS_STMT); } break; - case 240: /* cmd ::= SHOW SUBSCRIPTIONS */ + case 256: /* cmd ::= SHOW SUBSCRIPTIONS */ { pCxt->pRootNode = createShowStmt(pCxt, QUERY_NODE_SHOW_SUBSCRIPTIONS_STMT); } break; - case 241: /* cmd ::= SHOW TAGS FROM table_name_cond from_db_opt */ -{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_TAGS_STMT, yymsp[0].minor.yy600, yymsp[-1].minor.yy600, OP_TYPE_EQUAL); } + case 257: /* cmd ::= SHOW TAGS FROM table_name_cond from_db_opt */ +{ pCxt->pRootNode = createShowStmtWithCond(pCxt, QUERY_NODE_SHOW_TAGS_STMT, yymsp[0].minor.yy448, yymsp[-1].minor.yy448, OP_TYPE_EQUAL); } break; - case 242: /* cmd ::= SHOW TABLE TAGS tag_list_opt FROM table_name_cond from_db_opt */ -{ pCxt->pRootNode = createShowTableTagsStmt(pCxt, yymsp[-1].minor.yy600, yymsp[0].minor.yy600, yymsp[-3].minor.yy601); } + case 258: /* cmd ::= SHOW TABLE TAGS tag_list_opt FROM table_name_cond from_db_opt */ +{ pCxt->pRootNode = createShowTableTagsStmt(pCxt, yymsp[-1].minor.yy448, yymsp[0].minor.yy448, yymsp[-3].minor.yy432); } break; - case 243: /* cmd ::= SHOW VNODES NK_INTEGER */ + case 259: /* cmd ::= SHOW VNODES NK_INTEGER */ { pCxt->pRootNode = createShowVnodesStmt(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0), NULL); } break; - case 244: /* cmd ::= SHOW VNODES NK_STRING */ + case 260: /* cmd ::= SHOW VNODES NK_STRING */ { pCxt->pRootNode = createShowVnodesStmt(pCxt, NULL, createValueNode(pCxt, TSDB_DATA_TYPE_VARCHAR, &yymsp[0].minor.yy0)); } break; - case 245: /* db_name_cond_opt ::= */ - case 250: /* from_db_opt ::= */ yytestcase(yyruleno==250); -{ yymsp[1].minor.yy600 = createDefaultDatabaseCondValue(pCxt); } + case 261: /* cmd ::= SHOW db_name_cond_opt ALIVE */ +{ pCxt->pRootNode = createShowAliveStmt(pCxt, yymsp[-1].minor.yy448, QUERY_NODE_SHOW_DB_ALIVE_STMT); } break; - case 246: /* db_name_cond_opt ::= db_name NK_DOT */ -{ yylhsminor.yy600 = createIdentifierValueNode(pCxt, &yymsp[-1].minor.yy77); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + case 262: /* cmd ::= SHOW CLUSTER ALIVE */ +{ pCxt->pRootNode = createShowAliveStmt(pCxt, NULL, QUERY_NODE_SHOW_CLUSTER_ALIVE_STMT); } break; - case 247: /* like_pattern_opt ::= */ - case 306: /* subtable_opt ::= */ yytestcase(yyruleno==306); - case 419: /* case_when_else_opt ::= */ yytestcase(yyruleno==419); - case 449: /* from_clause_opt ::= */ yytestcase(yyruleno==449); - case 478: /* where_clause_opt ::= */ yytestcase(yyruleno==478); - case 487: /* twindow_clause_opt ::= */ yytestcase(yyruleno==487); - case 492: /* sliding_opt ::= */ yytestcase(yyruleno==492); - case 494: /* fill_opt ::= */ yytestcase(yyruleno==494); - case 508: /* having_clause_opt ::= */ yytestcase(yyruleno==508); - case 510: /* range_opt ::= */ yytestcase(yyruleno==510); - case 512: /* every_opt ::= */ yytestcase(yyruleno==512); - case 525: /* slimit_clause_opt ::= */ yytestcase(yyruleno==525); - case 529: /* limit_clause_opt ::= */ yytestcase(yyruleno==529); -{ yymsp[1].minor.yy600 = NULL; } + case 263: /* db_name_cond_opt ::= */ + case 268: /* from_db_opt ::= */ yytestcase(yyruleno==268); +{ yymsp[1].minor.yy448 = createDefaultDatabaseCondValue(pCxt); } break; - case 248: /* like_pattern_opt ::= LIKE NK_STRING */ -{ yymsp[-1].minor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0); } + case 264: /* db_name_cond_opt ::= db_name NK_DOT */ +{ yylhsminor.yy448 = createIdentifierValueNode(pCxt, &yymsp[-1].minor.yy113); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 249: /* table_name_cond ::= table_name */ -{ yylhsminor.yy600 = createIdentifierValueNode(pCxt, &yymsp[0].minor.yy77); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 266: /* like_pattern_opt ::= LIKE NK_STRING */ +{ yymsp[-1].minor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0); } break; - case 251: /* from_db_opt ::= FROM db_name */ -{ yymsp[-1].minor.yy600 = createIdentifierValueNode(pCxt, &yymsp[0].minor.yy77); } + case 267: /* table_name_cond ::= table_name */ +{ yylhsminor.yy448 = createIdentifierValueNode(pCxt, &yymsp[0].minor.yy113); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 255: /* tag_item ::= TBNAME */ -{ yylhsminor.yy600 = setProjectionAlias(pCxt, createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL), &yymsp[0].minor.yy0); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 269: /* from_db_opt ::= FROM db_name */ +{ yymsp[-1].minor.yy448 = createIdentifierValueNode(pCxt, &yymsp[0].minor.yy113); } break; - case 258: /* tag_item ::= column_name column_alias */ -{ yylhsminor.yy600 = setProjectionAlias(pCxt, createColumnNode(pCxt, NULL, &yymsp[-1].minor.yy77), &yymsp[0].minor.yy77); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + case 273: /* tag_item ::= TBNAME */ +{ yylhsminor.yy448 = setProjectionAlias(pCxt, createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL), &yymsp[0].minor.yy0); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 259: /* tag_item ::= column_name AS column_alias */ -{ yylhsminor.yy600 = setProjectionAlias(pCxt, createColumnNode(pCxt, NULL, &yymsp[-2].minor.yy77), &yymsp[0].minor.yy77); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 276: /* tag_item ::= column_name column_alias */ +{ yylhsminor.yy448 = setProjectionAlias(pCxt, createColumnNode(pCxt, NULL, &yymsp[-1].minor.yy113), &yymsp[0].minor.yy113); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 260: /* cmd ::= CREATE SMA INDEX not_exists_opt full_index_name ON full_table_name index_options */ -{ pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_SMA, yymsp[-4].minor.yy841, yymsp[-3].minor.yy600, yymsp[-1].minor.yy600, NULL, yymsp[0].minor.yy600); } + case 277: /* tag_item ::= column_name AS column_alias */ +{ yylhsminor.yy448 = setProjectionAlias(pCxt, createColumnNode(pCxt, NULL, &yymsp[-2].minor.yy113), &yymsp[0].minor.yy113); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 261: /* cmd ::= DROP INDEX exists_opt full_index_name */ -{ pCxt->pRootNode = createDropIndexStmt(pCxt, yymsp[-1].minor.yy841, yymsp[0].minor.yy600); } + case 278: /* cmd ::= CREATE SMA INDEX not_exists_opt full_index_name ON full_table_name index_options */ +{ pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_SMA, yymsp[-4].minor.yy369, yymsp[-3].minor.yy448, yymsp[-1].minor.yy448, NULL, yymsp[0].minor.yy448); } break; - case 262: /* full_index_name ::= index_name */ -{ yylhsminor.yy600 = createRealTableNodeForIndexName(pCxt, NULL, &yymsp[0].minor.yy77); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 279: /* cmd ::= CREATE INDEX not_exists_opt full_index_name ON full_table_name NK_LP col_name_list NK_RP */ +{ pCxt->pRootNode = createCreateIndexStmt(pCxt, INDEX_TYPE_NORMAL, yymsp[-6].minor.yy369, yymsp[-5].minor.yy448, yymsp[-3].minor.yy448, yymsp[-1].minor.yy432, NULL); } break; - case 263: /* full_index_name ::= db_name NK_DOT index_name */ -{ yylhsminor.yy600 = createRealTableNodeForIndexName(pCxt, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy77); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 280: /* cmd ::= DROP INDEX exists_opt full_index_name */ +{ pCxt->pRootNode = createDropIndexStmt(pCxt, yymsp[-1].minor.yy369, yymsp[0].minor.yy448); } break; - case 264: /* index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt sma_stream_opt */ -{ yymsp[-9].minor.yy600 = createIndexOption(pCxt, yymsp[-7].minor.yy601, releaseRawExprNode(pCxt, yymsp[-3].minor.yy600), NULL, yymsp[-1].minor.yy600, yymsp[0].minor.yy600); } + case 281: /* full_index_name ::= index_name */ +{ yylhsminor.yy448 = createRealTableNodeForIndexName(pCxt, NULL, &yymsp[0].minor.yy113); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 265: /* index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt sma_stream_opt */ -{ yymsp[-11].minor.yy600 = createIndexOption(pCxt, yymsp[-9].minor.yy601, releaseRawExprNode(pCxt, yymsp[-5].minor.yy600), releaseRawExprNode(pCxt, yymsp[-3].minor.yy600), yymsp[-1].minor.yy600, yymsp[0].minor.yy600); } + case 282: /* full_index_name ::= db_name NK_DOT index_name */ +{ yylhsminor.yy448 = createRealTableNodeForIndexName(pCxt, &yymsp[-2].minor.yy113, &yymsp[0].minor.yy113); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 268: /* func ::= function_name NK_LP expression_list NK_RP */ -{ yylhsminor.yy600 = createFunctionNode(pCxt, &yymsp[-3].minor.yy77, yymsp[-1].minor.yy601); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; + case 283: /* index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_RP sliding_opt sma_stream_opt */ +{ yymsp[-9].minor.yy448 = createIndexOption(pCxt, yymsp[-7].minor.yy432, releaseRawExprNode(pCxt, yymsp[-3].minor.yy448), NULL, yymsp[-1].minor.yy448, yymsp[0].minor.yy448); } break; - case 269: /* sma_stream_opt ::= */ - case 297: /* stream_options ::= */ yytestcase(yyruleno==297); -{ yymsp[1].minor.yy600 = createStreamOptions(pCxt); } + case 284: /* index_options ::= FUNCTION NK_LP func_list NK_RP INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt sma_stream_opt */ +{ yymsp[-11].minor.yy448 = createIndexOption(pCxt, yymsp[-9].minor.yy432, releaseRawExprNode(pCxt, yymsp[-5].minor.yy448), releaseRawExprNode(pCxt, yymsp[-3].minor.yy448), yymsp[-1].minor.yy448, yymsp[0].minor.yy448); } break; - case 270: /* sma_stream_opt ::= sma_stream_opt WATERMARK duration_literal */ - case 301: /* stream_options ::= stream_options WATERMARK duration_literal */ yytestcase(yyruleno==301); -{ ((SStreamOptions*)yymsp[-2].minor.yy600)->pWatermark = releaseRawExprNode(pCxt, yymsp[0].minor.yy600); yylhsminor.yy600 = yymsp[-2].minor.yy600; } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 287: /* func ::= sma_func_name NK_LP expression_list NK_RP */ +{ yylhsminor.yy448 = createFunctionNode(pCxt, &yymsp[-3].minor.yy113, yymsp[-1].minor.yy432); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; break; - case 271: /* sma_stream_opt ::= sma_stream_opt MAX_DELAY duration_literal */ -{ ((SStreamOptions*)yymsp[-2].minor.yy600)->pDelay = releaseRawExprNode(pCxt, yymsp[0].minor.yy600); yylhsminor.yy600 = yymsp[-2].minor.yy600; } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 288: /* sma_func_name ::= function_name */ + case 497: /* alias_opt ::= table_alias */ yytestcase(yyruleno==497); +{ yylhsminor.yy113 = yymsp[0].minor.yy113; } + yymsp[0].minor.yy113 = yylhsminor.yy113; break; - case 272: /* sma_stream_opt ::= sma_stream_opt DELETE_MARK duration_literal */ - case 304: /* stream_options ::= stream_options DELETE_MARK duration_literal */ yytestcase(yyruleno==304); -{ ((SStreamOptions*)yymsp[-2].minor.yy600)->pDeleteMark = releaseRawExprNode(pCxt, yymsp[0].minor.yy600); yylhsminor.yy600 = yymsp[-2].minor.yy600; } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 293: /* sma_stream_opt ::= */ + case 331: /* stream_options ::= */ yytestcase(yyruleno==331); +{ yymsp[1].minor.yy448 = createStreamOptions(pCxt); } break; - case 273: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_or_subquery */ -{ pCxt->pRootNode = createCreateTopicStmtUseQuery(pCxt, yymsp[-3].minor.yy841, &yymsp[-2].minor.yy77, yymsp[0].minor.yy600); } + case 294: /* sma_stream_opt ::= sma_stream_opt WATERMARK duration_literal */ +{ ((SStreamOptions*)yymsp[-2].minor.yy448)->pWatermark = releaseRawExprNode(pCxt, yymsp[0].minor.yy448); yylhsminor.yy448 = yymsp[-2].minor.yy448; } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 274: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name */ -{ pCxt->pRootNode = createCreateTopicStmtUseDb(pCxt, yymsp[-4].minor.yy841, &yymsp[-3].minor.yy77, &yymsp[0].minor.yy77, false); } + case 295: /* sma_stream_opt ::= sma_stream_opt MAX_DELAY duration_literal */ +{ ((SStreamOptions*)yymsp[-2].minor.yy448)->pDelay = releaseRawExprNode(pCxt, yymsp[0].minor.yy448); yylhsminor.yy448 = yymsp[-2].minor.yy448; } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 275: /* cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS DATABASE db_name */ -{ pCxt->pRootNode = createCreateTopicStmtUseDb(pCxt, yymsp[-6].minor.yy841, &yymsp[-5].minor.yy77, &yymsp[0].minor.yy77, true); } + case 296: /* sma_stream_opt ::= sma_stream_opt DELETE_MARK duration_literal */ +{ ((SStreamOptions*)yymsp[-2].minor.yy448)->pDeleteMark = releaseRawExprNode(pCxt, yymsp[0].minor.yy448); yylhsminor.yy448 = yymsp[-2].minor.yy448; } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 276: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name */ -{ pCxt->pRootNode = createCreateTopicStmtUseTable(pCxt, yymsp[-4].minor.yy841, &yymsp[-3].minor.yy77, yymsp[0].minor.yy600, false); } + case 297: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS query_or_subquery */ +{ pCxt->pRootNode = createCreateTopicStmtUseQuery(pCxt, yymsp[-3].minor.yy369, &yymsp[-2].minor.yy113, yymsp[0].minor.yy448); } break; - case 277: /* cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS STABLE full_table_name */ -{ pCxt->pRootNode = createCreateTopicStmtUseTable(pCxt, yymsp[-6].minor.yy841, &yymsp[-5].minor.yy77, yymsp[0].minor.yy600, true); } + case 298: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS DATABASE db_name */ +{ pCxt->pRootNode = createCreateTopicStmtUseDb(pCxt, yymsp[-4].minor.yy369, &yymsp[-3].minor.yy113, &yymsp[0].minor.yy113, false); } break; - case 278: /* cmd ::= DROP TOPIC exists_opt topic_name */ -{ pCxt->pRootNode = createDropTopicStmt(pCxt, yymsp[-1].minor.yy841, &yymsp[0].minor.yy77); } + case 299: /* cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS DATABASE db_name */ +{ pCxt->pRootNode = createCreateTopicStmtUseDb(pCxt, yymsp[-6].minor.yy369, &yymsp[-5].minor.yy113, &yymsp[0].minor.yy113, true); } break; - case 279: /* cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name */ -{ pCxt->pRootNode = createDropCGroupStmt(pCxt, yymsp[-3].minor.yy841, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy77); } + case 300: /* cmd ::= CREATE TOPIC not_exists_opt topic_name AS STABLE full_table_name */ +{ pCxt->pRootNode = createCreateTopicStmtUseTable(pCxt, yymsp[-4].minor.yy369, &yymsp[-3].minor.yy113, yymsp[0].minor.yy448, false); } break; - case 280: /* cmd ::= DESC full_table_name */ - case 281: /* cmd ::= DESCRIBE full_table_name */ yytestcase(yyruleno==281); -{ pCxt->pRootNode = createDescribeStmt(pCxt, yymsp[0].minor.yy600); } + case 301: /* cmd ::= CREATE TOPIC not_exists_opt topic_name WITH META AS STABLE full_table_name */ +{ pCxt->pRootNode = createCreateTopicStmtUseTable(pCxt, yymsp[-6].minor.yy369, &yymsp[-5].minor.yy113, yymsp[0].minor.yy448, true); } break; - case 282: /* cmd ::= RESET QUERY CACHE */ + case 302: /* cmd ::= DROP TOPIC exists_opt topic_name */ +{ pCxt->pRootNode = createDropTopicStmt(pCxt, yymsp[-1].minor.yy369, &yymsp[0].minor.yy113); } + break; + case 303: /* cmd ::= DROP CONSUMER GROUP exists_opt cgroup_name ON topic_name */ +{ pCxt->pRootNode = createDropCGroupStmt(pCxt, yymsp[-3].minor.yy369, &yymsp[-2].minor.yy113, &yymsp[0].minor.yy113); } + break; + case 304: /* cmd ::= DESC full_table_name */ + case 305: /* cmd ::= DESCRIBE full_table_name */ yytestcase(yyruleno==305); +{ pCxt->pRootNode = createDescribeStmt(pCxt, yymsp[0].minor.yy448); } + break; + case 306: /* cmd ::= RESET QUERY CACHE */ { pCxt->pRootNode = createResetQueryCacheStmt(pCxt); } break; - case 283: /* cmd ::= EXPLAIN analyze_opt explain_options query_or_subquery */ -{ pCxt->pRootNode = createExplainStmt(pCxt, yymsp[-2].minor.yy841, yymsp[-1].minor.yy600, yymsp[0].minor.yy600); } + case 307: /* cmd ::= EXPLAIN analyze_opt explain_options query_or_subquery */ + case 308: /* cmd ::= EXPLAIN analyze_opt explain_options insert_query */ yytestcase(yyruleno==308); +{ pCxt->pRootNode = createExplainStmt(pCxt, yymsp[-2].minor.yy369, yymsp[-1].minor.yy448, yymsp[0].minor.yy448); } + break; + case 311: /* explain_options ::= */ +{ yymsp[1].minor.yy448 = createDefaultExplainOptions(pCxt); } break; - case 286: /* explain_options ::= */ -{ yymsp[1].minor.yy600 = createDefaultExplainOptions(pCxt); } + case 312: /* explain_options ::= explain_options VERBOSE NK_BOOL */ +{ yylhsminor.yy448 = setExplainVerbose(pCxt, yymsp[-2].minor.yy448, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 287: /* explain_options ::= explain_options VERBOSE NK_BOOL */ -{ yylhsminor.yy600 = setExplainVerbose(pCxt, yymsp[-2].minor.yy600, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 313: /* explain_options ::= explain_options RATIO NK_FLOAT */ +{ yylhsminor.yy448 = setExplainRatio(pCxt, yymsp[-2].minor.yy448, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 288: /* explain_options ::= explain_options RATIO NK_FLOAT */ -{ yylhsminor.yy600 = setExplainRatio(pCxt, yymsp[-2].minor.yy600, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 314: /* cmd ::= CREATE or_replace_opt agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt language_opt */ +{ pCxt->pRootNode = createCreateFunctionStmt(pCxt, yymsp[-7].minor.yy369, yymsp[-9].minor.yy369, &yymsp[-6].minor.yy113, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy728, yymsp[-1].minor.yy788, &yymsp[0].minor.yy113, yymsp[-10].minor.yy369); } break; - case 289: /* cmd ::= CREATE agg_func_opt FUNCTION not_exists_opt function_name AS NK_STRING OUTPUTTYPE type_name bufsize_opt */ -{ pCxt->pRootNode = createCreateFunctionStmt(pCxt, yymsp[-6].minor.yy841, yymsp[-8].minor.yy841, &yymsp[-5].minor.yy77, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy888, yymsp[0].minor.yy248); } + case 315: /* cmd ::= DROP FUNCTION exists_opt function_name */ +{ pCxt->pRootNode = createDropFunctionStmt(pCxt, yymsp[-1].minor.yy369, &yymsp[0].minor.yy113); } break; - case 290: /* cmd ::= DROP FUNCTION exists_opt function_name */ -{ pCxt->pRootNode = createDropFunctionStmt(pCxt, yymsp[-1].minor.yy841, &yymsp[0].minor.yy77); } + case 320: /* language_opt ::= */ +{ yymsp[1].minor.yy113 = nil_token; } break; - case 295: /* cmd ::= CREATE STREAM not_exists_opt stream_name stream_options INTO full_table_name tags_def_opt subtable_opt AS query_or_subquery */ -{ pCxt->pRootNode = createCreateStreamStmt(pCxt, yymsp[-8].minor.yy841, &yymsp[-7].minor.yy77, yymsp[-4].minor.yy600, yymsp[-6].minor.yy600, yymsp[-3].minor.yy601, yymsp[-2].minor.yy600, yymsp[0].minor.yy600); } + case 321: /* language_opt ::= LANGUAGE NK_STRING */ +{ yymsp[-1].minor.yy113 = yymsp[0].minor.yy0; } break; - case 296: /* cmd ::= DROP STREAM exists_opt stream_name */ -{ pCxt->pRootNode = createDropStreamStmt(pCxt, yymsp[-1].minor.yy841, &yymsp[0].minor.yy77); } + case 324: /* cmd ::= CREATE STREAM not_exists_opt stream_name stream_options INTO full_table_name col_list_opt tag_def_or_ref_opt subtable_opt AS query_or_subquery */ +{ pCxt->pRootNode = createCreateStreamStmt(pCxt, yymsp[-9].minor.yy369, &yymsp[-8].minor.yy113, yymsp[-5].minor.yy448, yymsp[-7].minor.yy448, yymsp[-3].minor.yy432, yymsp[-2].minor.yy448, yymsp[0].minor.yy448, yymsp[-4].minor.yy432); } break; - case 298: /* stream_options ::= stream_options TRIGGER AT_ONCE */ -{ ((SStreamOptions*)yymsp[-2].minor.yy600)->triggerType = STREAM_TRIGGER_AT_ONCE; yylhsminor.yy600 = yymsp[-2].minor.yy600; } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 325: /* cmd ::= DROP STREAM exists_opt stream_name */ +{ pCxt->pRootNode = createDropStreamStmt(pCxt, yymsp[-1].minor.yy369, &yymsp[0].minor.yy113); } break; - case 299: /* stream_options ::= stream_options TRIGGER WINDOW_CLOSE */ -{ ((SStreamOptions*)yymsp[-2].minor.yy600)->triggerType = STREAM_TRIGGER_WINDOW_CLOSE; yylhsminor.yy600 = yymsp[-2].minor.yy600; } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 332: /* stream_options ::= stream_options TRIGGER AT_ONCE */ + case 333: /* stream_options ::= stream_options TRIGGER WINDOW_CLOSE */ yytestcase(yyruleno==333); +{ yylhsminor.yy448 = setStreamOptions(pCxt, yymsp[-2].minor.yy448, SOPT_TRIGGER_TYPE_SET, &yymsp[0].minor.yy0, NULL); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 300: /* stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal */ -{ ((SStreamOptions*)yymsp[-3].minor.yy600)->triggerType = STREAM_TRIGGER_MAX_DELAY; ((SStreamOptions*)yymsp[-3].minor.yy600)->pDelay = releaseRawExprNode(pCxt, yymsp[0].minor.yy600); yylhsminor.yy600 = yymsp[-3].minor.yy600; } - yymsp[-3].minor.yy600 = yylhsminor.yy600; + case 334: /* stream_options ::= stream_options TRIGGER MAX_DELAY duration_literal */ +{ yylhsminor.yy448 = setStreamOptions(pCxt, yymsp[-3].minor.yy448, SOPT_TRIGGER_TYPE_SET, &yymsp[-1].minor.yy0, releaseRawExprNode(pCxt, yymsp[0].minor.yy448)); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; break; - case 302: /* stream_options ::= stream_options IGNORE EXPIRED NK_INTEGER */ -{ ((SStreamOptions*)yymsp[-3].minor.yy600)->ignoreExpired = taosStr2Int8(yymsp[0].minor.yy0.z, NULL, 10); yylhsminor.yy600 = yymsp[-3].minor.yy600; } - yymsp[-3].minor.yy600 = yylhsminor.yy600; + case 335: /* stream_options ::= stream_options WATERMARK duration_literal */ +{ yylhsminor.yy448 = setStreamOptions(pCxt, yymsp[-2].minor.yy448, SOPT_WATERMARK_SET, NULL, releaseRawExprNode(pCxt, yymsp[0].minor.yy448)); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 303: /* stream_options ::= stream_options FILL_HISTORY NK_INTEGER */ -{ ((SStreamOptions*)yymsp[-2].minor.yy600)->fillHistory = taosStr2Int8(yymsp[0].minor.yy0.z, NULL, 10); yylhsminor.yy600 = yymsp[-2].minor.yy600; } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 336: /* stream_options ::= stream_options IGNORE EXPIRED NK_INTEGER */ +{ yylhsminor.yy448 = setStreamOptions(pCxt, yymsp[-3].minor.yy448, SOPT_IGNORE_EXPIRED_SET, &yymsp[0].minor.yy0, NULL); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; break; - case 305: /* stream_options ::= stream_options IGNORE UPDATE NK_INTEGER */ -{ ((SStreamOptions*)yymsp[-3].minor.yy600)->ignoreUpdate = taosStr2Int8(yymsp[0].minor.yy0.z, NULL, 10); yylhsminor.yy600 = yymsp[-3].minor.yy600; } - yymsp[-3].minor.yy600 = yylhsminor.yy600; + case 337: /* stream_options ::= stream_options FILL_HISTORY NK_INTEGER */ +{ yylhsminor.yy448 = setStreamOptions(pCxt, yymsp[-2].minor.yy448, SOPT_FILL_HISTORY_SET, &yymsp[0].minor.yy0, NULL); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 307: /* subtable_opt ::= SUBTABLE NK_LP expression NK_RP */ - case 493: /* sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ yytestcase(yyruleno==493); - case 513: /* every_opt ::= EVERY NK_LP duration_literal NK_RP */ yytestcase(yyruleno==513); -{ yymsp[-3].minor.yy600 = releaseRawExprNode(pCxt, yymsp[-1].minor.yy600); } + case 338: /* stream_options ::= stream_options DELETE_MARK duration_literal */ +{ yylhsminor.yy448 = setStreamOptions(pCxt, yymsp[-2].minor.yy448, SOPT_DELETE_MARK_SET, NULL, releaseRawExprNode(pCxt, yymsp[0].minor.yy448)); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 308: /* cmd ::= KILL CONNECTION NK_INTEGER */ + case 339: /* stream_options ::= stream_options IGNORE UPDATE NK_INTEGER */ +{ yylhsminor.yy448 = setStreamOptions(pCxt, yymsp[-3].minor.yy448, SOPT_IGNORE_UPDATE_SET, &yymsp[0].minor.yy0, NULL); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; + break; + case 341: /* subtable_opt ::= SUBTABLE NK_LP expression NK_RP */ + case 531: /* sliding_opt ::= SLIDING NK_LP duration_literal NK_RP */ yytestcase(yyruleno==531); + case 551: /* every_opt ::= EVERY NK_LP duration_literal NK_RP */ yytestcase(yyruleno==551); +{ yymsp[-3].minor.yy448 = releaseRawExprNode(pCxt, yymsp[-1].minor.yy448); } + break; + case 342: /* cmd ::= KILL CONNECTION NK_INTEGER */ { pCxt->pRootNode = createKillStmt(pCxt, QUERY_NODE_KILL_CONNECTION_STMT, &yymsp[0].minor.yy0); } break; - case 309: /* cmd ::= KILL QUERY NK_STRING */ + case 343: /* cmd ::= KILL QUERY NK_STRING */ { pCxt->pRootNode = createKillQueryStmt(pCxt, &yymsp[0].minor.yy0); } break; - case 310: /* cmd ::= KILL TRANSACTION NK_INTEGER */ + case 344: /* cmd ::= KILL TRANSACTION NK_INTEGER */ { pCxt->pRootNode = createKillStmt(pCxt, QUERY_NODE_KILL_TRANSACTION_STMT, &yymsp[0].minor.yy0); } break; - case 311: /* cmd ::= BALANCE VGROUP */ + case 345: /* cmd ::= BALANCE VGROUP */ { pCxt->pRootNode = createBalanceVgroupStmt(pCxt); } break; - case 312: /* cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER */ + case 346: /* cmd ::= BALANCE VGROUP LEADER */ +{ pCxt->pRootNode = createBalanceVgroupLeaderStmt(pCxt); } + break; + case 347: /* cmd ::= MERGE VGROUP NK_INTEGER NK_INTEGER */ { pCxt->pRootNode = createMergeVgroupStmt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0); } break; - case 313: /* cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list */ -{ pCxt->pRootNode = createRedistributeVgroupStmt(pCxt, &yymsp[-1].minor.yy0, yymsp[0].minor.yy601); } + case 348: /* cmd ::= REDISTRIBUTE VGROUP NK_INTEGER dnode_list */ +{ pCxt->pRootNode = createRedistributeVgroupStmt(pCxt, &yymsp[-1].minor.yy0, yymsp[0].minor.yy432); } break; - case 314: /* cmd ::= SPLIT VGROUP NK_INTEGER */ + case 349: /* cmd ::= SPLIT VGROUP NK_INTEGER */ { pCxt->pRootNode = createSplitVgroupStmt(pCxt, &yymsp[0].minor.yy0); } break; - case 315: /* dnode_list ::= DNODE NK_INTEGER */ -{ yymsp[-1].minor.yy601 = createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); } - break; - case 317: /* cmd ::= DELETE FROM full_table_name where_clause_opt */ -{ pCxt->pRootNode = createDeleteStmt(pCxt, yymsp[-1].minor.yy600, yymsp[0].minor.yy600); } - break; - case 319: /* cmd ::= INSERT INTO full_table_name NK_LP col_name_list NK_RP query_or_subquery */ -{ pCxt->pRootNode = createInsertStmt(pCxt, yymsp[-4].minor.yy600, yymsp[-2].minor.yy601, yymsp[0].minor.yy600); } - break; - case 320: /* cmd ::= INSERT INTO full_table_name query_or_subquery */ -{ pCxt->pRootNode = createInsertStmt(pCxt, yymsp[-1].minor.yy600, NULL, yymsp[0].minor.yy600); } - break; - case 321: /* literal ::= NK_INTEGER */ -{ yylhsminor.yy600 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_UBIGINT, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 322: /* literal ::= NK_FLOAT */ -{ yylhsminor.yy600 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 323: /* literal ::= NK_STRING */ -{ yylhsminor.yy600 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 324: /* literal ::= NK_BOOL */ -{ yylhsminor.yy600 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 325: /* literal ::= TIMESTAMP NK_STRING */ -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0)); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; - break; - case 326: /* literal ::= duration_literal */ - case 336: /* signed_literal ::= signed */ yytestcase(yyruleno==336); - case 357: /* expr_or_subquery ::= expression */ yytestcase(yyruleno==357); - case 358: /* expression ::= literal */ yytestcase(yyruleno==358); - case 359: /* expression ::= pseudo_column */ yytestcase(yyruleno==359); - case 360: /* expression ::= column_reference */ yytestcase(yyruleno==360); - case 361: /* expression ::= function_expression */ yytestcase(yyruleno==361); - case 362: /* expression ::= case_when_expression */ yytestcase(yyruleno==362); - case 392: /* function_expression ::= literal_func */ yytestcase(yyruleno==392); - case 441: /* boolean_value_expression ::= boolean_primary */ yytestcase(yyruleno==441); - case 445: /* boolean_primary ::= predicate */ yytestcase(yyruleno==445); - case 447: /* common_expression ::= expr_or_subquery */ yytestcase(yyruleno==447); - case 448: /* common_expression ::= boolean_value_expression */ yytestcase(yyruleno==448); - case 451: /* table_reference_list ::= table_reference */ yytestcase(yyruleno==451); - case 453: /* table_reference ::= table_primary */ yytestcase(yyruleno==453); - case 454: /* table_reference ::= joined_table */ yytestcase(yyruleno==454); - case 458: /* table_primary ::= parenthesized_joined_table */ yytestcase(yyruleno==458); - case 515: /* query_simple ::= query_specification */ yytestcase(yyruleno==515); - case 516: /* query_simple ::= union_query_expression */ yytestcase(yyruleno==516); - case 519: /* query_simple_or_subquery ::= query_simple */ yytestcase(yyruleno==519); - case 521: /* query_or_subquery ::= query_expression */ yytestcase(yyruleno==521); -{ yylhsminor.yy600 = yymsp[0].minor.yy600; } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 327: /* literal ::= NULL */ -{ yylhsminor.yy600 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 328: /* literal ::= NK_QUESTION */ -{ yylhsminor.yy600 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createPlaceholderValueNode(pCxt, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 329: /* duration_literal ::= NK_VARIABLE */ -{ yylhsminor.yy600 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 330: /* signed ::= NK_INTEGER */ -{ yylhsminor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_UBIGINT, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 331: /* signed ::= NK_PLUS NK_INTEGER */ -{ yymsp[-1].minor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_UBIGINT, &yymsp[0].minor.yy0); } - break; - case 332: /* signed ::= NK_MINUS NK_INTEGER */ + case 350: /* dnode_list ::= DNODE NK_INTEGER */ +{ yymsp[-1].minor.yy432 = createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &yymsp[0].minor.yy0)); } + break; + case 352: /* cmd ::= DELETE FROM full_table_name where_clause_opt */ +{ pCxt->pRootNode = createDeleteStmt(pCxt, yymsp[-1].minor.yy448, yymsp[0].minor.yy448); } + break; + case 355: /* insert_query ::= INSERT INTO full_table_name NK_LP col_name_list NK_RP query_or_subquery */ +{ yymsp[-6].minor.yy448 = createInsertStmt(pCxt, yymsp[-4].minor.yy448, yymsp[-2].minor.yy432, yymsp[0].minor.yy448); } + break; + case 356: /* insert_query ::= INSERT INTO full_table_name query_or_subquery */ +{ yymsp[-3].minor.yy448 = createInsertStmt(pCxt, yymsp[-1].minor.yy448, NULL, yymsp[0].minor.yy448); } + break; + case 357: /* literal ::= NK_INTEGER */ +{ yylhsminor.yy448 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_UBIGINT, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 358: /* literal ::= NK_FLOAT */ +{ yylhsminor.yy448 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 359: /* literal ::= NK_STRING */ +{ yylhsminor.yy448 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 360: /* literal ::= NK_BOOL */ +{ yylhsminor.yy448 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 361: /* literal ::= TIMESTAMP NK_STRING */ +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0)); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; + break; + case 362: /* literal ::= duration_literal */ + case 372: /* signed_literal ::= signed */ yytestcase(yyruleno==372); + case 393: /* expr_or_subquery ::= expression */ yytestcase(yyruleno==393); + case 394: /* expression ::= literal */ yytestcase(yyruleno==394); + case 395: /* expression ::= pseudo_column */ yytestcase(yyruleno==395); + case 396: /* expression ::= column_reference */ yytestcase(yyruleno==396); + case 397: /* expression ::= function_expression */ yytestcase(yyruleno==397); + case 398: /* expression ::= case_when_expression */ yytestcase(yyruleno==398); + case 429: /* function_expression ::= literal_func */ yytestcase(yyruleno==429); + case 478: /* boolean_value_expression ::= boolean_primary */ yytestcase(yyruleno==478); + case 482: /* boolean_primary ::= predicate */ yytestcase(yyruleno==482); + case 484: /* common_expression ::= expr_or_subquery */ yytestcase(yyruleno==484); + case 485: /* common_expression ::= boolean_value_expression */ yytestcase(yyruleno==485); + case 488: /* table_reference_list ::= table_reference */ yytestcase(yyruleno==488); + case 490: /* table_reference ::= table_primary */ yytestcase(yyruleno==490); + case 491: /* table_reference ::= joined_table */ yytestcase(yyruleno==491); + case 495: /* table_primary ::= parenthesized_joined_table */ yytestcase(yyruleno==495); + case 553: /* query_simple ::= query_specification */ yytestcase(yyruleno==553); + case 554: /* query_simple ::= union_query_expression */ yytestcase(yyruleno==554); + case 557: /* query_simple_or_subquery ::= query_simple */ yytestcase(yyruleno==557); + case 559: /* query_or_subquery ::= query_expression */ yytestcase(yyruleno==559); +{ yylhsminor.yy448 = yymsp[0].minor.yy448; } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 363: /* literal ::= NULL */ +{ yylhsminor.yy448 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 364: /* literal ::= NK_QUESTION */ +{ yylhsminor.yy448 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createPlaceholderValueNode(pCxt, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 365: /* duration_literal ::= NK_VARIABLE */ +{ yylhsminor.yy448 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createDurationValueNode(pCxt, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 366: /* signed ::= NK_INTEGER */ +{ yylhsminor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_UBIGINT, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 367: /* signed ::= NK_PLUS NK_INTEGER */ +{ yymsp[-1].minor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_UBIGINT, &yymsp[0].minor.yy0); } + break; + case 368: /* signed ::= NK_MINUS NK_INTEGER */ { SToken t = yymsp[-1].minor.yy0; t.n = (yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z; - yylhsminor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &t); + yylhsminor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_BIGINT, &t); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 333: /* signed ::= NK_FLOAT */ -{ yylhsminor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 369: /* signed ::= NK_FLOAT */ +{ yylhsminor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 334: /* signed ::= NK_PLUS NK_FLOAT */ -{ yymsp[-1].minor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0); } + case 370: /* signed ::= NK_PLUS NK_FLOAT */ +{ yymsp[-1].minor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &yymsp[0].minor.yy0); } break; - case 335: /* signed ::= NK_MINUS NK_FLOAT */ + case 371: /* signed ::= NK_MINUS NK_FLOAT */ { SToken t = yymsp[-1].minor.yy0; t.n = (yymsp[0].minor.yy0.z + yymsp[0].minor.yy0.n) - yymsp[-1].minor.yy0.z; - yylhsminor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &t); + yylhsminor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_DOUBLE, &t); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; - break; - case 337: /* signed_literal ::= NK_STRING */ -{ yylhsminor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 338: /* signed_literal ::= NK_BOOL */ -{ yylhsminor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 339: /* signed_literal ::= TIMESTAMP NK_STRING */ -{ yymsp[-1].minor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0); } - break; - case 340: /* signed_literal ::= duration_literal */ - case 342: /* signed_literal ::= literal_func */ yytestcase(yyruleno==342); - case 412: /* star_func_para ::= expr_or_subquery */ yytestcase(yyruleno==412); - case 474: /* select_item ::= common_expression */ yytestcase(yyruleno==474); - case 484: /* partition_item ::= expr_or_subquery */ yytestcase(yyruleno==484); - case 520: /* query_simple_or_subquery ::= subquery */ yytestcase(yyruleno==520); - case 522: /* query_or_subquery ::= subquery */ yytestcase(yyruleno==522); - case 535: /* search_condition ::= common_expression */ yytestcase(yyruleno==535); -{ yylhsminor.yy600 = releaseRawExprNode(pCxt, yymsp[0].minor.yy600); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 341: /* signed_literal ::= NULL */ -{ yylhsminor.yy600 = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 343: /* signed_literal ::= NK_QUESTION */ -{ yylhsminor.yy600 = createPlaceholderValueNode(pCxt, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 363: /* expression ::= NK_LP expression NK_RP */ - case 446: /* boolean_primary ::= NK_LP boolean_value_expression NK_RP */ yytestcase(yyruleno==446); - case 534: /* subquery ::= NK_LP subquery NK_RP */ yytestcase(yyruleno==534); -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, releaseRawExprNode(pCxt, yymsp[-1].minor.yy600)); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 364: /* expression ::= NK_PLUS expr_or_subquery */ + yymsp[-1].minor.yy448 = yylhsminor.yy448; + break; + case 373: /* signed_literal ::= NK_STRING */ +{ yylhsminor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 374: /* signed_literal ::= NK_BOOL */ +{ yylhsminor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_BOOL, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 375: /* signed_literal ::= TIMESTAMP NK_STRING */ +{ yymsp[-1].minor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_TIMESTAMP, &yymsp[0].minor.yy0); } + break; + case 376: /* signed_literal ::= duration_literal */ + case 378: /* signed_literal ::= literal_func */ yytestcase(yyruleno==378); + case 449: /* star_func_para ::= expr_or_subquery */ yytestcase(yyruleno==449); + case 511: /* select_item ::= common_expression */ yytestcase(yyruleno==511); + case 521: /* partition_item ::= expr_or_subquery */ yytestcase(yyruleno==521); + case 558: /* query_simple_or_subquery ::= subquery */ yytestcase(yyruleno==558); + case 560: /* query_or_subquery ::= subquery */ yytestcase(yyruleno==560); + case 573: /* search_condition ::= common_expression */ yytestcase(yyruleno==573); +{ yylhsminor.yy448 = releaseRawExprNode(pCxt, yymsp[0].minor.yy448); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 377: /* signed_literal ::= NULL */ +{ yylhsminor.yy448 = createValueNode(pCxt, TSDB_DATA_TYPE_NULL, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 379: /* signed_literal ::= NK_QUESTION */ +{ yylhsminor.yy448 = createPlaceholderValueNode(pCxt, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 399: /* expression ::= NK_LP expression NK_RP */ + case 483: /* boolean_primary ::= NK_LP boolean_value_expression NK_RP */ yytestcase(yyruleno==483); + case 572: /* subquery ::= NK_LP subquery NK_RP */ yytestcase(yyruleno==572); +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, releaseRawExprNode(pCxt, yymsp[-1].minor.yy448)); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 400: /* expression ::= NK_PLUS expr_or_subquery */ { - SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, releaseRawExprNode(pCxt, yymsp[0].minor.yy600)); + SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, releaseRawExprNode(pCxt, yymsp[0].minor.yy448)); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 365: /* expression ::= NK_MINUS expr_or_subquery */ + case 401: /* expression ::= NK_MINUS expr_or_subquery */ { - SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, createOperatorNode(pCxt, OP_TYPE_MINUS, releaseRawExprNode(pCxt, yymsp[0].minor.yy600), NULL)); + SToken t = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &t, createOperatorNode(pCxt, OP_TYPE_MINUS, releaseRawExprNode(pCxt, yymsp[0].minor.yy448), NULL)); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 366: /* expression ::= expr_or_subquery NK_PLUS expr_or_subquery */ + case 402: /* expression ::= expr_or_subquery NK_PLUS expr_or_subquery */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 367: /* expression ::= expr_or_subquery NK_MINUS expr_or_subquery */ + case 403: /* expression ::= expr_or_subquery NK_MINUS expr_or_subquery */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 368: /* expression ::= expr_or_subquery NK_STAR expr_or_subquery */ + case 404: /* expression ::= expr_or_subquery NK_STAR expr_or_subquery */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 369: /* expression ::= expr_or_subquery NK_SLASH expr_or_subquery */ + case 405: /* expression ::= expr_or_subquery NK_SLASH expr_or_subquery */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 370: /* expression ::= expr_or_subquery NK_REM expr_or_subquery */ + case 406: /* expression ::= expr_or_subquery NK_REM expr_or_subquery */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_REM, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_REM, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 371: /* expression ::= column_reference NK_ARROW NK_STRING */ + case 407: /* expression ::= column_reference NK_ARROW NK_STRING */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_JSON_GET_VALUE, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_JSON_GET_VALUE, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[0].minor.yy0))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 372: /* expression ::= expr_or_subquery NK_BITAND expr_or_subquery */ + case 408: /* expression ::= expr_or_subquery NK_BITAND expr_or_subquery */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_AND, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_AND, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 373: /* expression ::= expr_or_subquery NK_BITOR expr_or_subquery */ + case 409: /* expression ::= expr_or_subquery NK_BITOR expr_or_subquery */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_OR, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_OR, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 376: /* column_reference ::= column_name */ -{ yylhsminor.yy600 = createRawExprNode(pCxt, &yymsp[0].minor.yy77, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy77)); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 377: /* column_reference ::= table_name NK_DOT column_name */ -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy77, createColumnNode(pCxt, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy77)); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 378: /* pseudo_column ::= ROWTS */ - case 379: /* pseudo_column ::= TBNAME */ yytestcase(yyruleno==379); - case 381: /* pseudo_column ::= QSTART */ yytestcase(yyruleno==381); - case 382: /* pseudo_column ::= QEND */ yytestcase(yyruleno==382); - case 383: /* pseudo_column ::= QDURATION */ yytestcase(yyruleno==383); - case 384: /* pseudo_column ::= WSTART */ yytestcase(yyruleno==384); - case 385: /* pseudo_column ::= WEND */ yytestcase(yyruleno==385); - case 386: /* pseudo_column ::= WDURATION */ yytestcase(yyruleno==386); - case 387: /* pseudo_column ::= IROWTS */ yytestcase(yyruleno==387); - case 388: /* pseudo_column ::= QTAGS */ yytestcase(yyruleno==388); - case 394: /* literal_func ::= NOW */ yytestcase(yyruleno==394); -{ yylhsminor.yy600 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL)); } - yymsp[0].minor.yy600 = yylhsminor.yy600; - break; - case 380: /* pseudo_column ::= table_name NK_DOT TBNAME */ -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[0].minor.yy0, createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[-2].minor.yy77)))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 389: /* function_expression ::= function_name NK_LP expression_list NK_RP */ - case 390: /* function_expression ::= star_func NK_LP star_func_para_list NK_RP */ yytestcase(yyruleno==390); -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy77, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-3].minor.yy77, yymsp[-1].minor.yy601)); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; - break; - case 391: /* function_expression ::= CAST NK_LP expr_or_subquery AS type_name NK_RP */ -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0, createCastFunctionNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy600), yymsp[-1].minor.yy888)); } - yymsp[-5].minor.yy600 = yylhsminor.yy600; - break; - case 393: /* literal_func ::= noarg_func NK_LP NK_RP */ -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-2].minor.yy77, NULL)); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 408: /* star_func_para_list ::= NK_STAR */ -{ yylhsminor.yy601 = createNodeList(pCxt, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy0)); } - yymsp[0].minor.yy601 = yylhsminor.yy601; - break; - case 413: /* star_func_para ::= table_name NK_DOT NK_STAR */ - case 477: /* select_item ::= table_name NK_DOT NK_STAR */ yytestcase(yyruleno==477); -{ yylhsminor.yy600 = createColumnNode(pCxt, &yymsp[-2].minor.yy77, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 414: /* case_when_expression ::= CASE when_then_list case_when_else_opt END */ -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, createCaseWhenNode(pCxt, NULL, yymsp[-2].minor.yy601, yymsp[-1].minor.yy600)); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; - break; - case 415: /* case_when_expression ::= CASE common_expression when_then_list case_when_else_opt END */ -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0, createCaseWhenNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy600), yymsp[-2].minor.yy601, yymsp[-1].minor.yy600)); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; - break; - case 418: /* when_then_expr ::= WHEN common_expression THEN common_expression */ -{ yymsp[-3].minor.yy600 = createWhenThenNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600)); } - break; - case 420: /* case_when_else_opt ::= ELSE common_expression */ -{ yymsp[-1].minor.yy600 = releaseRawExprNode(pCxt, yymsp[0].minor.yy600); } - break; - case 421: /* predicate ::= expr_or_subquery compare_op expr_or_subquery */ - case 426: /* predicate ::= expr_or_subquery in_op in_predicate_value */ yytestcase(yyruleno==426); + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 412: /* column_reference ::= column_name */ +{ yylhsminor.yy448 = createRawExprNode(pCxt, &yymsp[0].minor.yy113, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy113)); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 413: /* column_reference ::= table_name NK_DOT column_name */ +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy113, &yymsp[0].minor.yy113, createColumnNode(pCxt, &yymsp[-2].minor.yy113, &yymsp[0].minor.yy113)); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 414: /* pseudo_column ::= ROWTS */ + case 415: /* pseudo_column ::= TBNAME */ yytestcase(yyruleno==415); + case 417: /* pseudo_column ::= QSTART */ yytestcase(yyruleno==417); + case 418: /* pseudo_column ::= QEND */ yytestcase(yyruleno==418); + case 419: /* pseudo_column ::= QDURATION */ yytestcase(yyruleno==419); + case 420: /* pseudo_column ::= WSTART */ yytestcase(yyruleno==420); + case 421: /* pseudo_column ::= WEND */ yytestcase(yyruleno==421); + case 422: /* pseudo_column ::= WDURATION */ yytestcase(yyruleno==422); + case 423: /* pseudo_column ::= IROWTS */ yytestcase(yyruleno==423); + case 424: /* pseudo_column ::= ISFILLED */ yytestcase(yyruleno==424); + case 425: /* pseudo_column ::= QTAGS */ yytestcase(yyruleno==425); + case 431: /* literal_func ::= NOW */ yytestcase(yyruleno==431); +{ yylhsminor.yy448 = createRawExprNode(pCxt, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[0].minor.yy0, NULL)); } + yymsp[0].minor.yy448 = yylhsminor.yy448; + break; + case 416: /* pseudo_column ::= table_name NK_DOT TBNAME */ +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy113, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[0].minor.yy0, createNodeList(pCxt, createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &yymsp[-2].minor.yy113)))); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 426: /* function_expression ::= function_name NK_LP expression_list NK_RP */ + case 427: /* function_expression ::= star_func NK_LP star_func_para_list NK_RP */ yytestcase(yyruleno==427); +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy113, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-3].minor.yy113, yymsp[-1].minor.yy432)); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; + break; + case 428: /* function_expression ::= CAST NK_LP expr_or_subquery AS type_name NK_RP */ +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0, createCastFunctionNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy448), yymsp[-1].minor.yy728)); } + yymsp[-5].minor.yy448 = yylhsminor.yy448; + break; + case 430: /* literal_func ::= noarg_func NK_LP NK_RP */ +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy113, &yymsp[0].minor.yy0, createFunctionNode(pCxt, &yymsp[-2].minor.yy113, NULL)); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 445: /* star_func_para_list ::= NK_STAR */ +{ yylhsminor.yy432 = createNodeList(pCxt, createColumnNode(pCxt, NULL, &yymsp[0].minor.yy0)); } + yymsp[0].minor.yy432 = yylhsminor.yy432; + break; + case 450: /* star_func_para ::= table_name NK_DOT NK_STAR */ + case 514: /* select_item ::= table_name NK_DOT NK_STAR */ yytestcase(yyruleno==514); +{ yylhsminor.yy448 = createColumnNode(pCxt, &yymsp[-2].minor.yy113, &yymsp[0].minor.yy0); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; + break; + case 451: /* case_when_expression ::= CASE when_then_list case_when_else_opt END */ +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0, createCaseWhenNode(pCxt, NULL, yymsp[-2].minor.yy432, yymsp[-1].minor.yy448)); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; + break; + case 452: /* case_when_expression ::= CASE common_expression when_then_list case_when_else_opt END */ +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0, createCaseWhenNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy448), yymsp[-2].minor.yy432, yymsp[-1].minor.yy448)); } + yymsp[-4].minor.yy448 = yylhsminor.yy448; + break; + case 455: /* when_then_expr ::= WHEN common_expression THEN common_expression */ +{ yymsp[-3].minor.yy448 = createWhenThenNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448)); } + break; + case 457: /* case_when_else_opt ::= ELSE common_expression */ +{ yymsp[-1].minor.yy448 = releaseRawExprNode(pCxt, yymsp[0].minor.yy448); } + break; + case 458: /* predicate ::= expr_or_subquery compare_op expr_or_subquery */ + case 463: /* predicate ::= expr_or_subquery in_op in_predicate_value */ yytestcase(yyruleno==463); { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, yymsp[-1].minor.yy666, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, yymsp[-1].minor.yy156, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 422: /* predicate ::= expr_or_subquery BETWEEN expr_or_subquery AND expr_or_subquery */ + case 459: /* predicate ::= expr_or_subquery BETWEEN expr_or_subquery AND expr_or_subquery */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-4].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-4].minor.yy600), releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-4].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-4].minor.yy448), releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-4].minor.yy600 = yylhsminor.yy600; + yymsp[-4].minor.yy448 = yylhsminor.yy448; break; - case 423: /* predicate ::= expr_or_subquery NOT BETWEEN expr_or_subquery AND expr_or_subquery */ + case 460: /* predicate ::= expr_or_subquery NOT BETWEEN expr_or_subquery AND expr_or_subquery */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-5].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-5].minor.yy600), releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-5].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, yymsp[-5].minor.yy448), releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-5].minor.yy600 = yylhsminor.yy600; + yymsp[-5].minor.yy448 = yylhsminor.yy448; break; - case 424: /* predicate ::= expr_or_subquery IS NULL */ + case 461: /* predicate ::= expr_or_subquery IS NULL */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), NULL)); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), NULL)); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 425: /* predicate ::= expr_or_subquery IS NOT NULL */ + case 462: /* predicate ::= expr_or_subquery IS NOT NULL */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-3].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, yymsp[-3].minor.yy600), NULL)); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-3].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, yymsp[-3].minor.yy448), NULL)); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; + yymsp[-3].minor.yy448 = yylhsminor.yy448; break; - case 427: /* compare_op ::= NK_LT */ -{ yymsp[0].minor.yy666 = OP_TYPE_LOWER_THAN; } + case 464: /* compare_op ::= NK_LT */ +{ yymsp[0].minor.yy156 = OP_TYPE_LOWER_THAN; } break; - case 428: /* compare_op ::= NK_GT */ -{ yymsp[0].minor.yy666 = OP_TYPE_GREATER_THAN; } + case 465: /* compare_op ::= NK_GT */ +{ yymsp[0].minor.yy156 = OP_TYPE_GREATER_THAN; } break; - case 429: /* compare_op ::= NK_LE */ -{ yymsp[0].minor.yy666 = OP_TYPE_LOWER_EQUAL; } + case 466: /* compare_op ::= NK_LE */ +{ yymsp[0].minor.yy156 = OP_TYPE_LOWER_EQUAL; } break; - case 430: /* compare_op ::= NK_GE */ -{ yymsp[0].minor.yy666 = OP_TYPE_GREATER_EQUAL; } + case 467: /* compare_op ::= NK_GE */ +{ yymsp[0].minor.yy156 = OP_TYPE_GREATER_EQUAL; } break; - case 431: /* compare_op ::= NK_NE */ -{ yymsp[0].minor.yy666 = OP_TYPE_NOT_EQUAL; } + case 468: /* compare_op ::= NK_NE */ +{ yymsp[0].minor.yy156 = OP_TYPE_NOT_EQUAL; } break; - case 432: /* compare_op ::= NK_EQ */ -{ yymsp[0].minor.yy666 = OP_TYPE_EQUAL; } + case 469: /* compare_op ::= NK_EQ */ +{ yymsp[0].minor.yy156 = OP_TYPE_EQUAL; } break; - case 433: /* compare_op ::= LIKE */ -{ yymsp[0].minor.yy666 = OP_TYPE_LIKE; } + case 470: /* compare_op ::= LIKE */ +{ yymsp[0].minor.yy156 = OP_TYPE_LIKE; } break; - case 434: /* compare_op ::= NOT LIKE */ -{ yymsp[-1].minor.yy666 = OP_TYPE_NOT_LIKE; } + case 471: /* compare_op ::= NOT LIKE */ +{ yymsp[-1].minor.yy156 = OP_TYPE_NOT_LIKE; } break; - case 435: /* compare_op ::= MATCH */ -{ yymsp[0].minor.yy666 = OP_TYPE_MATCH; } + case 472: /* compare_op ::= MATCH */ +{ yymsp[0].minor.yy156 = OP_TYPE_MATCH; } break; - case 436: /* compare_op ::= NMATCH */ -{ yymsp[0].minor.yy666 = OP_TYPE_NMATCH; } + case 473: /* compare_op ::= NMATCH */ +{ yymsp[0].minor.yy156 = OP_TYPE_NMATCH; } break; - case 437: /* compare_op ::= CONTAINS */ -{ yymsp[0].minor.yy666 = OP_TYPE_JSON_CONTAINS; } + case 474: /* compare_op ::= CONTAINS */ +{ yymsp[0].minor.yy156 = OP_TYPE_JSON_CONTAINS; } break; - case 438: /* in_op ::= IN */ -{ yymsp[0].minor.yy666 = OP_TYPE_IN; } + case 475: /* in_op ::= IN */ +{ yymsp[0].minor.yy156 = OP_TYPE_IN; } break; - case 439: /* in_op ::= NOT IN */ -{ yymsp[-1].minor.yy666 = OP_TYPE_NOT_IN; } + case 476: /* in_op ::= NOT IN */ +{ yymsp[-1].minor.yy156 = OP_TYPE_NOT_IN; } break; - case 440: /* in_predicate_value ::= NK_LP literal_list NK_RP */ -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, createNodeListNode(pCxt, yymsp[-1].minor.yy601)); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 477: /* in_predicate_value ::= NK_LP literal_list NK_RP */ +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, createNodeListNode(pCxt, yymsp[-1].minor.yy432)); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 442: /* boolean_value_expression ::= NOT boolean_primary */ + case 479: /* boolean_value_expression ::= NOT boolean_primary */ { - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_NOT, releaseRawExprNode(pCxt, yymsp[0].minor.yy600), NULL)); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-1].minor.yy0, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_NOT, releaseRawExprNode(pCxt, yymsp[0].minor.yy448), NULL)); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 443: /* boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */ + case 480: /* boolean_value_expression ::= boolean_value_expression OR boolean_value_expression */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_OR, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 444: /* boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */ + case 481: /* boolean_value_expression ::= boolean_value_expression AND boolean_value_expression */ { - SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy600); - SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy600); - yylhsminor.yy600 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); + SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy448); + SToken e = getTokenFromRawExprNode(pCxt, yymsp[0].minor.yy448); + yylhsminor.yy448 = createRawExprNodeExt(pCxt, &s, &e, createLogicConditionNode(pCxt, LOGIC_COND_TYPE_AND, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; - break; - case 450: /* from_clause_opt ::= FROM table_reference_list */ - case 479: /* where_clause_opt ::= WHERE search_condition */ yytestcase(yyruleno==479); - case 509: /* having_clause_opt ::= HAVING search_condition */ yytestcase(yyruleno==509); -{ yymsp[-1].minor.yy600 = yymsp[0].minor.yy600; } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 452: /* table_reference_list ::= table_reference_list NK_COMMA table_reference */ -{ yylhsminor.yy600 = createJoinTableNode(pCxt, JOIN_TYPE_INNER, yymsp[-2].minor.yy600, yymsp[0].minor.yy600, NULL); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 489: /* table_reference_list ::= table_reference_list NK_COMMA table_reference */ +{ yylhsminor.yy448 = createJoinTableNode(pCxt, JOIN_TYPE_INNER, yymsp[-2].minor.yy448, yymsp[0].minor.yy448, NULL); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 455: /* table_primary ::= table_name alias_opt */ -{ yylhsminor.yy600 = createRealTableNode(pCxt, NULL, &yymsp[-1].minor.yy77, &yymsp[0].minor.yy77); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + case 492: /* table_primary ::= table_name alias_opt */ +{ yylhsminor.yy448 = createRealTableNode(pCxt, NULL, &yymsp[-1].minor.yy113, &yymsp[0].minor.yy113); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 456: /* table_primary ::= db_name NK_DOT table_name alias_opt */ -{ yylhsminor.yy600 = createRealTableNode(pCxt, &yymsp[-3].minor.yy77, &yymsp[-1].minor.yy77, &yymsp[0].minor.yy77); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; + case 493: /* table_primary ::= db_name NK_DOT table_name alias_opt */ +{ yylhsminor.yy448 = createRealTableNode(pCxt, &yymsp[-3].minor.yy113, &yymsp[-1].minor.yy113, &yymsp[0].minor.yy113); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; break; - case 457: /* table_primary ::= subquery alias_opt */ -{ yylhsminor.yy600 = createTempTableNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy600), &yymsp[0].minor.yy77); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + case 494: /* table_primary ::= subquery alias_opt */ +{ yylhsminor.yy448 = createTempTableNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy448), &yymsp[0].minor.yy113); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 459: /* alias_opt ::= */ -{ yymsp[1].minor.yy77 = nil_token; } + case 496: /* alias_opt ::= */ +{ yymsp[1].minor.yy113 = nil_token; } break; - case 461: /* alias_opt ::= AS table_alias */ -{ yymsp[-1].minor.yy77 = yymsp[0].minor.yy77; } + case 498: /* alias_opt ::= AS table_alias */ +{ yymsp[-1].minor.yy113 = yymsp[0].minor.yy113; } break; - case 462: /* parenthesized_joined_table ::= NK_LP joined_table NK_RP */ - case 463: /* parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ yytestcase(yyruleno==463); -{ yymsp[-2].minor.yy600 = yymsp[-1].minor.yy600; } + case 499: /* parenthesized_joined_table ::= NK_LP joined_table NK_RP */ + case 500: /* parenthesized_joined_table ::= NK_LP parenthesized_joined_table NK_RP */ yytestcase(yyruleno==500); +{ yymsp[-2].minor.yy448 = yymsp[-1].minor.yy448; } break; - case 464: /* joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ -{ yylhsminor.yy600 = createJoinTableNode(pCxt, yymsp[-4].minor.yy560, yymsp[-5].minor.yy600, yymsp[-2].minor.yy600, yymsp[0].minor.yy600); } - yymsp[-5].minor.yy600 = yylhsminor.yy600; + case 501: /* joined_table ::= table_reference join_type JOIN table_reference ON search_condition */ +{ yylhsminor.yy448 = createJoinTableNode(pCxt, yymsp[-4].minor.yy596, yymsp[-5].minor.yy448, yymsp[-2].minor.yy448, yymsp[0].minor.yy448); } + yymsp[-5].minor.yy448 = yylhsminor.yy448; break; - case 465: /* join_type ::= */ -{ yymsp[1].minor.yy560 = JOIN_TYPE_INNER; } + case 502: /* join_type ::= */ +{ yymsp[1].minor.yy596 = JOIN_TYPE_INNER; } break; - case 466: /* join_type ::= INNER */ -{ yymsp[0].minor.yy560 = JOIN_TYPE_INNER; } + case 503: /* join_type ::= INNER */ +{ yymsp[0].minor.yy596 = JOIN_TYPE_INNER; } break; - case 467: /* query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ + case 504: /* query_specification ::= SELECT set_quantifier_opt select_list from_clause_opt where_clause_opt partition_by_clause_opt range_opt every_opt fill_opt twindow_clause_opt group_by_clause_opt having_clause_opt */ { - yymsp[-11].minor.yy600 = createSelectStmt(pCxt, yymsp[-10].minor.yy841, yymsp[-9].minor.yy601, yymsp[-8].minor.yy600); - yymsp[-11].minor.yy600 = addWhereClause(pCxt, yymsp[-11].minor.yy600, yymsp[-7].minor.yy600); - yymsp[-11].minor.yy600 = addPartitionByClause(pCxt, yymsp[-11].minor.yy600, yymsp[-6].minor.yy601); - yymsp[-11].minor.yy600 = addWindowClauseClause(pCxt, yymsp[-11].minor.yy600, yymsp[-2].minor.yy600); - yymsp[-11].minor.yy600 = addGroupByClause(pCxt, yymsp[-11].minor.yy600, yymsp[-1].minor.yy601); - yymsp[-11].minor.yy600 = addHavingClause(pCxt, yymsp[-11].minor.yy600, yymsp[0].minor.yy600); - yymsp[-11].minor.yy600 = addRangeClause(pCxt, yymsp[-11].minor.yy600, yymsp[-5].minor.yy600); - yymsp[-11].minor.yy600 = addEveryClause(pCxt, yymsp[-11].minor.yy600, yymsp[-4].minor.yy600); - yymsp[-11].minor.yy600 = addFillClause(pCxt, yymsp[-11].minor.yy600, yymsp[-3].minor.yy600); + yymsp[-11].minor.yy448 = createSelectStmt(pCxt, yymsp[-10].minor.yy369, yymsp[-9].minor.yy432, yymsp[-8].minor.yy448); + yymsp[-11].minor.yy448 = addWhereClause(pCxt, yymsp[-11].minor.yy448, yymsp[-7].minor.yy448); + yymsp[-11].minor.yy448 = addPartitionByClause(pCxt, yymsp[-11].minor.yy448, yymsp[-6].minor.yy432); + yymsp[-11].minor.yy448 = addWindowClauseClause(pCxt, yymsp[-11].minor.yy448, yymsp[-2].minor.yy448); + yymsp[-11].minor.yy448 = addGroupByClause(pCxt, yymsp[-11].minor.yy448, yymsp[-1].minor.yy432); + yymsp[-11].minor.yy448 = addHavingClause(pCxt, yymsp[-11].minor.yy448, yymsp[0].minor.yy448); + yymsp[-11].minor.yy448 = addRangeClause(pCxt, yymsp[-11].minor.yy448, yymsp[-5].minor.yy448); + yymsp[-11].minor.yy448 = addEveryClause(pCxt, yymsp[-11].minor.yy448, yymsp[-4].minor.yy448); + yymsp[-11].minor.yy448 = addFillClause(pCxt, yymsp[-11].minor.yy448, yymsp[-3].minor.yy448); } break; - case 470: /* set_quantifier_opt ::= ALL */ -{ yymsp[0].minor.yy841 = false; } + case 507: /* set_quantifier_opt ::= ALL */ +{ yymsp[0].minor.yy369 = false; } break; - case 473: /* select_item ::= NK_STAR */ -{ yylhsminor.yy600 = createColumnNode(pCxt, NULL, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy600 = yylhsminor.yy600; + case 510: /* select_item ::= NK_STAR */ +{ yylhsminor.yy448 = createColumnNode(pCxt, NULL, &yymsp[0].minor.yy0); } + yymsp[0].minor.yy448 = yylhsminor.yy448; break; - case 475: /* select_item ::= common_expression column_alias */ - case 485: /* partition_item ::= expr_or_subquery column_alias */ yytestcase(yyruleno==485); -{ yylhsminor.yy600 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy600), &yymsp[0].minor.yy77); } - yymsp[-1].minor.yy600 = yylhsminor.yy600; + case 512: /* select_item ::= common_expression column_alias */ + case 522: /* partition_item ::= expr_or_subquery column_alias */ yytestcase(yyruleno==522); +{ yylhsminor.yy448 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy448), &yymsp[0].minor.yy113); } + yymsp[-1].minor.yy448 = yylhsminor.yy448; break; - case 476: /* select_item ::= common_expression AS column_alias */ - case 486: /* partition_item ::= expr_or_subquery AS column_alias */ yytestcase(yyruleno==486); -{ yylhsminor.yy600 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), &yymsp[0].minor.yy77); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 513: /* select_item ::= common_expression AS column_alias */ + case 523: /* partition_item ::= expr_or_subquery AS column_alias */ yytestcase(yyruleno==523); +{ yylhsminor.yy448 = setProjectionAlias(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), &yymsp[0].minor.yy113); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 481: /* partition_by_clause_opt ::= PARTITION BY partition_list */ - case 505: /* group_by_clause_opt ::= GROUP BY group_by_list */ yytestcase(yyruleno==505); - case 524: /* order_by_clause_opt ::= ORDER BY sort_specification_list */ yytestcase(yyruleno==524); -{ yymsp[-2].minor.yy601 = yymsp[0].minor.yy601; } + case 518: /* partition_by_clause_opt ::= PARTITION BY partition_list */ + case 543: /* group_by_clause_opt ::= GROUP BY group_by_list */ yytestcase(yyruleno==543); + case 562: /* order_by_clause_opt ::= ORDER BY sort_specification_list */ yytestcase(yyruleno==562); +{ yymsp[-2].minor.yy432 = yymsp[0].minor.yy432; } break; - case 488: /* twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */ -{ yymsp[-5].minor.yy600 = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy600), releaseRawExprNode(pCxt, yymsp[-1].minor.yy600)); } + case 525: /* twindow_clause_opt ::= SESSION NK_LP column_reference NK_COMMA duration_literal NK_RP */ +{ yymsp[-5].minor.yy448 = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy448), releaseRawExprNode(pCxt, yymsp[-1].minor.yy448)); } break; - case 489: /* twindow_clause_opt ::= STATE_WINDOW NK_LP expr_or_subquery NK_RP */ -{ yymsp[-3].minor.yy600 = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy600)); } + case 526: /* twindow_clause_opt ::= STATE_WINDOW NK_LP expr_or_subquery NK_RP */ +{ yymsp[-3].minor.yy448 = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-1].minor.yy448)); } break; - case 490: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ -{ yymsp[-5].minor.yy600 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy600), NULL, yymsp[-1].minor.yy600, yymsp[0].minor.yy600); } + case 527: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_RP sliding_opt fill_opt */ +{ yymsp[-5].minor.yy448 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy448), NULL, yymsp[-1].minor.yy448, yymsp[0].minor.yy448); } break; - case 491: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ -{ yymsp[-7].minor.yy600 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-5].minor.yy600), releaseRawExprNode(pCxt, yymsp[-3].minor.yy600), yymsp[-1].minor.yy600, yymsp[0].minor.yy600); } + case 528: /* twindow_clause_opt ::= INTERVAL NK_LP duration_literal NK_COMMA duration_literal NK_RP sliding_opt fill_opt */ +{ yymsp[-7].minor.yy448 = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, yymsp[-5].minor.yy448), releaseRawExprNode(pCxt, yymsp[-3].minor.yy448), yymsp[-1].minor.yy448, yymsp[0].minor.yy448); } break; - case 495: /* fill_opt ::= FILL NK_LP fill_mode NK_RP */ -{ yymsp[-3].minor.yy600 = createFillNode(pCxt, yymsp[-1].minor.yy798, NULL); } + case 529: /* twindow_clause_opt ::= EVENT_WINDOW START WITH search_condition END WITH search_condition */ +{ yymsp[-6].minor.yy448 = createEventWindowNode(pCxt, yymsp[-3].minor.yy448, yymsp[0].minor.yy448); } break; - case 496: /* fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ -{ yymsp[-5].minor.yy600 = createFillNode(pCxt, FILL_MODE_VALUE, createNodeListNode(pCxt, yymsp[-1].minor.yy601)); } + case 533: /* fill_opt ::= FILL NK_LP fill_mode NK_RP */ +{ yymsp[-3].minor.yy448 = createFillNode(pCxt, yymsp[-1].minor.yy46, NULL); } break; - case 497: /* fill_opt ::= FILL NK_LP VALUE_F NK_COMMA literal_list NK_RP */ -{ yymsp[-5].minor.yy600 = createFillNode(pCxt, FILL_MODE_VALUE_F, createNodeListNode(pCxt, yymsp[-1].minor.yy601)); } + case 534: /* fill_opt ::= FILL NK_LP VALUE NK_COMMA literal_list NK_RP */ +{ yymsp[-5].minor.yy448 = createFillNode(pCxt, FILL_MODE_VALUE, createNodeListNode(pCxt, yymsp[-1].minor.yy432)); } break; - case 498: /* fill_mode ::= NONE */ -{ yymsp[0].minor.yy798 = FILL_MODE_NONE; } + case 535: /* fill_opt ::= FILL NK_LP VALUE_F NK_COMMA literal_list NK_RP */ +{ yymsp[-5].minor.yy448 = createFillNode(pCxt, FILL_MODE_VALUE_F, createNodeListNode(pCxt, yymsp[-1].minor.yy432)); } break; - case 499: /* fill_mode ::= PREV */ -{ yymsp[0].minor.yy798 = FILL_MODE_PREV; } + case 536: /* fill_mode ::= NONE */ +{ yymsp[0].minor.yy46 = FILL_MODE_NONE; } break; - case 500: /* fill_mode ::= NULL */ -{ yymsp[0].minor.yy798 = FILL_MODE_NULL; } + case 537: /* fill_mode ::= PREV */ +{ yymsp[0].minor.yy46 = FILL_MODE_PREV; } break; - case 501: /* fill_mode ::= NULL_F */ -{ yymsp[0].minor.yy798 = FILL_MODE_NULL_F; } + case 538: /* fill_mode ::= NULL */ +{ yymsp[0].minor.yy46 = FILL_MODE_NULL; } break; - case 502: /* fill_mode ::= LINEAR */ -{ yymsp[0].minor.yy798 = FILL_MODE_LINEAR; } + case 539: /* fill_mode ::= NULL_F */ +{ yymsp[0].minor.yy46 = FILL_MODE_NULL_F; } break; - case 503: /* fill_mode ::= NEXT */ -{ yymsp[0].minor.yy798 = FILL_MODE_NEXT; } + case 540: /* fill_mode ::= LINEAR */ +{ yymsp[0].minor.yy46 = FILL_MODE_LINEAR; } break; - case 506: /* group_by_list ::= expr_or_subquery */ -{ yylhsminor.yy601 = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); } - yymsp[0].minor.yy601 = yylhsminor.yy601; + case 541: /* fill_mode ::= NEXT */ +{ yymsp[0].minor.yy46 = FILL_MODE_NEXT; } break; - case 507: /* group_by_list ::= group_by_list NK_COMMA expr_or_subquery */ -{ yylhsminor.yy601 = addNodeToList(pCxt, yymsp[-2].minor.yy601, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy600))); } - yymsp[-2].minor.yy601 = yylhsminor.yy601; + case 544: /* group_by_list ::= expr_or_subquery */ +{ yylhsminor.yy432 = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } + yymsp[0].minor.yy432 = yylhsminor.yy432; break; - case 511: /* range_opt ::= RANGE NK_LP expr_or_subquery NK_COMMA expr_or_subquery NK_RP */ -{ yymsp[-5].minor.yy600 = createInterpTimeRange(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy600), releaseRawExprNode(pCxt, yymsp[-1].minor.yy600)); } + case 545: /* group_by_list ::= group_by_list NK_COMMA expr_or_subquery */ +{ yylhsminor.yy432 = addNodeToList(pCxt, yymsp[-2].minor.yy432, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, yymsp[0].minor.yy448))); } + yymsp[-2].minor.yy432 = yylhsminor.yy432; break; - case 514: /* query_expression ::= query_simple order_by_clause_opt slimit_clause_opt limit_clause_opt */ + case 549: /* range_opt ::= RANGE NK_LP expr_or_subquery NK_COMMA expr_or_subquery NK_RP */ +{ yymsp[-5].minor.yy448 = createInterpTimeRange(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy448), releaseRawExprNode(pCxt, yymsp[-1].minor.yy448)); } + break; + case 552: /* query_expression ::= query_simple order_by_clause_opt slimit_clause_opt limit_clause_opt */ { - yylhsminor.yy600 = addOrderByClause(pCxt, yymsp[-3].minor.yy600, yymsp[-2].minor.yy601); - yylhsminor.yy600 = addSlimitClause(pCxt, yylhsminor.yy600, yymsp[-1].minor.yy600); - yylhsminor.yy600 = addLimitClause(pCxt, yylhsminor.yy600, yymsp[0].minor.yy600); + yylhsminor.yy448 = addOrderByClause(pCxt, yymsp[-3].minor.yy448, yymsp[-2].minor.yy432); + yylhsminor.yy448 = addSlimitClause(pCxt, yylhsminor.yy448, yymsp[-1].minor.yy448); + yylhsminor.yy448 = addLimitClause(pCxt, yylhsminor.yy448, yymsp[0].minor.yy448); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; + yymsp[-3].minor.yy448 = yylhsminor.yy448; break; - case 517: /* union_query_expression ::= query_simple_or_subquery UNION ALL query_simple_or_subquery */ -{ yylhsminor.yy600 = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, yymsp[-3].minor.yy600, yymsp[0].minor.yy600); } - yymsp[-3].minor.yy600 = yylhsminor.yy600; + case 555: /* union_query_expression ::= query_simple_or_subquery UNION ALL query_simple_or_subquery */ +{ yylhsminor.yy448 = createSetOperator(pCxt, SET_OP_TYPE_UNION_ALL, yymsp[-3].minor.yy448, yymsp[0].minor.yy448); } + yymsp[-3].minor.yy448 = yylhsminor.yy448; break; - case 518: /* union_query_expression ::= query_simple_or_subquery UNION query_simple_or_subquery */ -{ yylhsminor.yy600 = createSetOperator(pCxt, SET_OP_TYPE_UNION, yymsp[-2].minor.yy600, yymsp[0].minor.yy600); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 556: /* union_query_expression ::= query_simple_or_subquery UNION query_simple_or_subquery */ +{ yylhsminor.yy448 = createSetOperator(pCxt, SET_OP_TYPE_UNION, yymsp[-2].minor.yy448, yymsp[0].minor.yy448); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 526: /* slimit_clause_opt ::= SLIMIT NK_INTEGER */ - case 530: /* limit_clause_opt ::= LIMIT NK_INTEGER */ yytestcase(yyruleno==530); -{ yymsp[-1].minor.yy600 = createLimitNode(pCxt, &yymsp[0].minor.yy0, NULL); } + case 564: /* slimit_clause_opt ::= SLIMIT NK_INTEGER */ + case 568: /* limit_clause_opt ::= LIMIT NK_INTEGER */ yytestcase(yyruleno==568); +{ yymsp[-1].minor.yy448 = createLimitNode(pCxt, &yymsp[0].minor.yy0, NULL); } break; - case 527: /* slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ - case 531: /* limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ yytestcase(yyruleno==531); -{ yymsp[-3].minor.yy600 = createLimitNode(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } + case 565: /* slimit_clause_opt ::= SLIMIT NK_INTEGER SOFFSET NK_INTEGER */ + case 569: /* limit_clause_opt ::= LIMIT NK_INTEGER OFFSET NK_INTEGER */ yytestcase(yyruleno==569); +{ yymsp[-3].minor.yy448 = createLimitNode(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } break; - case 528: /* slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ - case 532: /* limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ yytestcase(yyruleno==532); -{ yymsp[-3].minor.yy600 = createLimitNode(pCxt, &yymsp[0].minor.yy0, &yymsp[-2].minor.yy0); } + case 566: /* slimit_clause_opt ::= SLIMIT NK_INTEGER NK_COMMA NK_INTEGER */ + case 570: /* limit_clause_opt ::= LIMIT NK_INTEGER NK_COMMA NK_INTEGER */ yytestcase(yyruleno==570); +{ yymsp[-3].minor.yy448 = createLimitNode(pCxt, &yymsp[0].minor.yy0, &yymsp[-2].minor.yy0); } break; - case 533: /* subquery ::= NK_LP query_expression NK_RP */ -{ yylhsminor.yy600 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-1].minor.yy600); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 571: /* subquery ::= NK_LP query_expression NK_RP */ +{ yylhsminor.yy448 = createRawExprNodeExt(pCxt, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-1].minor.yy448); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 538: /* sort_specification ::= expr_or_subquery ordering_specification_opt null_ordering_opt */ -{ yylhsminor.yy600 = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy600), yymsp[-1].minor.yy32, yymsp[0].minor.yy385); } - yymsp[-2].minor.yy600 = yylhsminor.yy600; + case 576: /* sort_specification ::= expr_or_subquery ordering_specification_opt null_ordering_opt */ +{ yylhsminor.yy448 = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy448), yymsp[-1].minor.yy666, yymsp[0].minor.yy585); } + yymsp[-2].minor.yy448 = yylhsminor.yy448; break; - case 539: /* ordering_specification_opt ::= */ -{ yymsp[1].minor.yy32 = ORDER_ASC; } + case 577: /* ordering_specification_opt ::= */ +{ yymsp[1].minor.yy666 = ORDER_ASC; } break; - case 540: /* ordering_specification_opt ::= ASC */ -{ yymsp[0].minor.yy32 = ORDER_ASC; } + case 578: /* ordering_specification_opt ::= ASC */ +{ yymsp[0].minor.yy666 = ORDER_ASC; } break; - case 541: /* ordering_specification_opt ::= DESC */ -{ yymsp[0].minor.yy32 = ORDER_DESC; } + case 579: /* ordering_specification_opt ::= DESC */ +{ yymsp[0].minor.yy666 = ORDER_DESC; } break; - case 542: /* null_ordering_opt ::= */ -{ yymsp[1].minor.yy385 = NULL_ORDER_DEFAULT; } + case 580: /* null_ordering_opt ::= */ +{ yymsp[1].minor.yy585 = NULL_ORDER_DEFAULT; } break; - case 543: /* null_ordering_opt ::= NULLS FIRST */ -{ yymsp[-1].minor.yy385 = NULL_ORDER_FIRST; } + case 581: /* null_ordering_opt ::= NULLS FIRST */ +{ yymsp[-1].minor.yy585 = NULL_ORDER_FIRST; } break; - case 544: /* null_ordering_opt ::= NULLS LAST */ -{ yymsp[-1].minor.yy385 = NULL_ORDER_LAST; } + case 582: /* null_ordering_opt ::= NULLS LAST */ +{ yymsp[-1].minor.yy585 = NULL_ORDER_LAST; } break; default: break; /********** End reduce actions ************************************************/ }; - assert( yyrulenocreateTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_COLS, TSDB_SYSTEM_TABLE, 2) + .addColumn("table_name", TSDB_DATA_TYPE_BINARY, TSDB_TABLE_NAME_LEN) + .addColumn("db_name", TSDB_DATA_TYPE_BINARY, TSDB_DB_NAME_LEN) + .done(); mcs->createTableBuilder(TSDB_INFORMATION_SCHEMA_DB, TSDB_INS_TABLE_USER_PRIVILEGES, TSDB_SYSTEM_TABLE, 2) .addColumn("user_name", TSDB_DATA_TYPE_BINARY, TSDB_USER_LEN) .addColumn("privilege", TSDB_DATA_TYPE_BINARY, 10) @@ -222,6 +226,7 @@ void generateDatabases(MockCatalogService* mcs) { generateTestTables(g_mockCatalogService.get(), "cache_db"); generateTestStables(g_mockCatalogService.get(), "cache_db"); mcs->createDatabase("rollup_db", true); + mcs->createDatabase("testus", false, 0, TSDB_TIME_PRECISION_NANO); } } // namespace @@ -248,7 +253,8 @@ int32_t __catalogGetCachedTableHashVgroup(SCatalog* pCtg, const SName* pTableNam return code; } -int32_t __catalogGetCachedTableVgMeta(SCatalog* pCtg, const SName* pTableName, SVgroupInfo* pVgroup, STableMeta** pTableMeta) { +int32_t __catalogGetCachedTableVgMeta(SCatalog* pCtg, const SName* pTableName, SVgroupInfo* pVgroup, + STableMeta** pTableMeta) { int32_t code = g_mockCatalogService->catalogGetTableMeta(pTableName, pTableMeta, true); if (code) return code; code = g_mockCatalogService->catalogGetTableHashVgroup(pTableName, pVgroup, true); @@ -273,15 +279,13 @@ int32_t __catalogGetDBCfg(SCatalog* pCtg, SRequestConnInfo* pConn, const char* d return g_mockCatalogService->catalogGetDBCfg(dbFName, pDbCfg); } -int32_t __catalogChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, const char* user, const char* dbFName, AUTH_TYPE type, - bool* pass) { - *pass = true; +int32_t __catalogChkAuth(SCatalog* pCtg, SRequestConnInfo* pConn, SUserAuthInfo *pAuth, SUserAuthRes* pRes) { + pRes->pass = true; return 0; } -int32_t __catalogChkAuthFromCache(SCatalog* pCtg, const char* user, const char* dbFName, AUTH_TYPE type, bool* pass, - bool* exists) { - *pass = true; +int32_t __catalogChkAuthFromCache(SCatalog* pCtg, SUserAuthInfo *pAuth, SUserAuthRes* pRes, bool* exists) { + pRes->pass = true; *exists = true; return 0; } diff --git a/source/libs/parser/test/mockCatalogService.cpp b/source/libs/parser/test/mockCatalogService.cpp index 9cc55a7cd55a0060635e9a9044ac076ce5a77119..f6a8b407d76071ceb0324ee492655d2959565f7c 100644 --- a/source/libs/parser/test/mockCatalogService.cpp +++ b/source/libs/parser/test/mockCatalogService.cpp @@ -33,7 +33,6 @@ std::unique_ptr g_mockCatalogService; class TableBuilder : public ITableBuilder { public: virtual TableBuilder& addColumn(const string& name, int8_t type, int32_t bytes) { - assert(colId_ <= schema()->tableInfo.numOfTags + schema()->tableInfo.numOfColumns); SSchema* col = schema()->schema + (colId_ - 1); col->type = type; col->colId = colId_++; @@ -332,7 +331,7 @@ class MockCatalogServiceImpl { info.dstTbUid = getNextId(); info.dstVgId = pReq->dstVgId; genEpSet(&info.epSet); - info.expr = strdup(pReq->expr); + info.expr = taosStrdup(pReq->expr); auto it = index_.find(pReq->stb); if (index_.end() == it) { index_.insert(std::make_pair(string(pReq->stb), std::vector{info})); @@ -347,12 +346,13 @@ class MockCatalogServiceImpl { dnode_.insert(std::make_pair(dnodeId, epSet)); } - void createDatabase(const string& db, bool rollup, int8_t cacheLast) { + void createDatabase(const string& db, bool rollup, int8_t cacheLast, int8_t precision) { SDbCfgInfo cfg = {0}; if (rollup) { cfg.pRetensions = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SRetention)); } cfg.cacheLast = cacheLast; + cfg.precision = precision; dbCfg_.insert(std::make_pair(db, cfg)); } @@ -375,7 +375,7 @@ class MockCatalogServiceImpl { STableIndexInfo* copyTableIndexInfo(STableIndexInfo* pDst, const STableIndexInfo* pSrc) const { memcpy(pDst, pSrc, sizeof(STableIndexInfo)); - pDst->expr = strdup(pSrc->expr); + pDst->expr = taosStrdup(pSrc->expr); return pDst; } @@ -427,7 +427,7 @@ class MockCatalogServiceImpl { int32_t copyTableSchemaMeta(const string& db, const string& tbname, std::unique_ptr* dst) const { STableMeta* src = getTableSchemaMeta(db, tbname); if (nullptr == src) { - return TSDB_CODE_TSC_INVALID_TABLE_NAME; + return TSDB_CODE_PAR_TABLE_NOT_EXIST; } int32_t len = sizeof(STableMeta) + sizeof(SSchema) * (src->tableInfo.numOfTags + src->tableInfo.numOfColumns); dst->reset((STableMeta*)taosMemoryCalloc(1, len)); @@ -589,8 +589,8 @@ class MockCatalogServiceImpl { *pUserAuthData = taosArrayInit(num, sizeof(SMetaRes)); for (int32_t i = 0; i < num; ++i) { SMetaRes res = {0}; - res.pRes = taosMemoryCalloc(1, sizeof(bool)); - *(bool*)(res.pRes) = true; + res.pRes = taosMemoryCalloc(1, sizeof(SUserAuthRes)); + ((SUserAuthRes*)res.pRes)->pass = true; taosArrayPush(*pUserAuthData, &res); } } @@ -682,8 +682,8 @@ void MockCatalogService::createDnode(int32_t dnodeId, const string& host, int16_ impl_->createDnode(dnodeId, host, port); } -void MockCatalogService::createDatabase(const string& db, bool rollup, int8_t cacheLast) { - impl_->createDatabase(db, rollup, cacheLast); +void MockCatalogService::createDatabase(const string& db, bool rollup, int8_t cacheLast, int8_t precision) { + impl_->createDatabase(db, rollup, cacheLast, precision); } int32_t MockCatalogService::catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta, diff --git a/source/libs/parser/test/mockCatalogService.h b/source/libs/parser/test/mockCatalogService.h index acd7fab8e17e2f9843d8b9beb3848f4f32c64c2b..cc955df2b0ba8e7811a3cd43ddab378b29ecc9fc 100644 --- a/source/libs/parser/test/mockCatalogService.h +++ b/source/libs/parser/test/mockCatalogService.h @@ -65,7 +65,8 @@ class MockCatalogService { void createFunction(const std::string& func, int8_t funcType, int8_t outputType, int32_t outputLen, int32_t bufSize); void createSmaIndex(const SMCreateSmaReq* pReq); void createDnode(int32_t dnodeId, const std::string& host, int16_t port); - void createDatabase(const std::string& db, bool rollup = false, int8_t cacheLast = 0); + void createDatabase(const std::string& db, bool rollup = false, int8_t cacheLast = 0, + int8_t precision = TSDB_TIME_PRECISION_MILLI); int32_t catalogGetTableMeta(const SName* pTableName, STableMeta** pTableMeta, bool onlyCache = false) const; int32_t catalogGetTableHashVgroup(const SName* pTableName, SVgroupInfo* vgInfo, bool onlyCache = false) const; diff --git a/source/libs/parser/test/parAlterToBalanceTest.cpp b/source/libs/parser/test/parAlterToBalanceTest.cpp index ba1ba9fc831ec8661cc7a8252a1772d5bbae6317..db74e66d2bb06b1de08a187583ee9fadfe72e8b4 100644 --- a/source/libs/parser/test/parAlterToBalanceTest.cpp +++ b/source/libs/parser/test/parAlterToBalanceTest.cpp @@ -21,6 +21,25 @@ namespace ParserTest { class ParserInitialATest : public ParserDdlTest {}; +/* + * ALTER ACCOUNT account_name alter_account_options + * + * alter_account_options: + * alter_account_option ... + * + * alter_account_option: { + * PASS value + * | PPS value + * | TSERIES value + * | STORAGE value + * | STREAMS value + * | QTIME value + * | DBS value + * | USERS value + * | CONNS value + * | STATE value + * } + */ TEST_F(ParserInitialATest, alterAccount) { useDb("root", "test"); @@ -48,6 +67,7 @@ TEST_F(ParserInitialATest, alterDnode) { setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_DNODE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_CONFIG_DNODE); SMCfgDnodeReq req = {0}; ASSERT_EQ(tDeserializeSMCfgDnodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); ASSERT_EQ(req.dnodeId, expect.dnodeId); @@ -86,10 +106,11 @@ TEST_F(ParserInitialATest, alterDnode) { * | KEEP {int_value | duration_value} -- rang [1, 365000], default 3650, unit day * | PAGES int_value -- rang [64, INT32_MAX], default 256, unit page * | REPLICA int_value -- todo: enum 1, 3, default 1, unit replica - * | STRICT {'off' | 'on'} -- todo: default 'off' * | WAL_LEVEL int_value -- enum 1, 2, default 1 - * | SST_TRIGGER int_value -- rang [1, 16], default 8 - * } + * | STT_TRIGGER int_value -- rang [1, 16], default 8 + * | MINROWS int_value -- rang [10, 1000], default 100 + * | WAL_RETENTION_PERIOD int_value -- rang [-1, INT32_MAX], default 0 + * | WAL_RETENTION_SIZE int_value -- rang [-1, INT32_MAX], default 0 */ TEST_F(ParserInitialATest, alterDatabase) { useDb("root", "test"); @@ -114,6 +135,9 @@ TEST_F(ParserInitialATest, alterDatabase) { expect.cacheLastSize = -1; expect.replications = -1; expect.sstTrigger = -1; + expect.minRows = -1; + expect.walRetentionPeriod = -2; + expect.walRetentionSize = -2; }; auto setAlterDbBuffer = [&](int32_t buffer) { expect.buffer = buffer; }; auto setAlterDbPageSize = [&](int32_t pageSize) { expect.pageSize = pageSize; }; @@ -130,10 +154,16 @@ TEST_F(ParserInitialATest, alterDatabase) { auto setAlterDbStrict = [&](int8_t strict) { expect.strict = strict; }; auto setAlterDbCacheModel = [&](int8_t cacheModel) { expect.cacheLast = cacheModel; }; auto setAlterDbReplica = [&](int8_t replications) { expect.replications = replications; }; - auto setAlterDbSstTrigger = [&](int8_t sstTrigger) { expect.sstTrigger = sstTrigger; }; + auto setAlterDbSttTrigger = [&](int8_t sstTrigger) { expect.sstTrigger = sstTrigger; }; + auto setAlterDbMinRows = [&](int32_t minRows) { expect.minRows = minRows; }; + auto setAlterDbWalRetentionPeriod = [&](int32_t walRetentionPeriod) { + expect.walRetentionPeriod = walRetentionPeriod; + }; + auto setAlterDbWalRetentionSize = [&](int32_t walRetentionSize) { expect.walRetentionSize = walRetentionSize; }; setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_DATABASE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_DB); SAlterDbReq req = {0}; ASSERT_EQ(tDeserializeSAlterDbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); ASSERT_EQ(std::string(req.db), std::string(expect.db)); @@ -150,6 +180,9 @@ TEST_F(ParserInitialATest, alterDatabase) { ASSERT_EQ(req.cacheLast, expect.cacheLast); ASSERT_EQ(req.replications, expect.replications); ASSERT_EQ(req.sstTrigger, expect.sstTrigger); + ASSERT_EQ(req.minRows, expect.minRows); + ASSERT_EQ(req.walRetentionPeriod, expect.walRetentionPeriod); + ASSERT_EQ(req.walRetentionSize, expect.walRetentionSize); }); const int32_t MINUTE_PER_DAY = MILLISECOND_PER_DAY / MILLISECOND_PER_MINUTE; @@ -161,11 +194,14 @@ TEST_F(ParserInitialATest, alterDatabase) { setAlterDbFsync(200); setAlterDbWal(1); setAlterDbCacheModel(TSDB_CACHE_MODEL_LAST_ROW); - setAlterDbSstTrigger(16); + setAlterDbSttTrigger(16); setAlterDbBuffer(16); setAlterDbPages(128); + setAlterDbReplica(3); + setAlterDbWalRetentionPeriod(10); + setAlterDbWalRetentionSize(20); run("ALTER DATABASE test BUFFER 16 CACHEMODEL 'last_row' CACHESIZE 32 WAL_FSYNC_PERIOD 200 KEEP 10 PAGES 128 " - "WAL_LEVEL 1 STT_TRIGGER 16"); + "REPLICA 3 WAL_LEVEL 1 STT_TRIGGER 16 WAL_RETENTION_PERIOD 10 WAL_RETENTION_SIZE 20"); clearAlterDbReq(); initAlterDb("test"); @@ -240,6 +276,45 @@ TEST_F(ParserInitialATest, alterDatabase) { setAlterDbWal(2); run("ALTER DATABASE test WAL_LEVEL 2"); clearAlterDbReq(); + + initAlterDb("test"); + setAlterDbReplica(1); + run("ALTER DATABASE test REPLICA 1"); + setAlterDbReplica(3); + run("ALTER DATABASE test REPLICA 3"); + clearAlterDbReq(); + + initAlterDb("test"); + setAlterDbSttTrigger(1); + run("ALTER DATABASE test STT_TRIGGER 1"); + setAlterDbSttTrigger(4); + run("ALTER DATABASE test STT_TRIGGER 4"); + setAlterDbSttTrigger(16); + run("ALTER DATABASE test STT_TRIGGER 16"); + clearAlterDbReq(); + + initAlterDb("test"); + setAlterDbMinRows(10); + run("ALTER DATABASE test MINROWS 10"); + setAlterDbMinRows(50); + run("ALTER DATABASE test MINROWS 50"); + setAlterDbMinRows(1000); + run("ALTER DATABASE test MINROWS 1000"); + clearAlterDbReq(); + + initAlterDb("test"); + setAlterDbWalRetentionPeriod(-1); + run("ALTER DATABASE test WAL_RETENTION_PERIOD -1"); + setAlterDbWalRetentionPeriod(50); + run("ALTER DATABASE test WAL_RETENTION_PERIOD 50"); + clearAlterDbReq(); + + initAlterDb("test"); + setAlterDbWalRetentionSize(-1); + run("ALTER DATABASE test WAL_RETENTION_SIZE -1"); + setAlterDbWalRetentionSize(50); + run("ALTER DATABASE test WAL_RETENTION_SIZE 50"); + clearAlterDbReq(); } TEST_F(ParserInitialATest, alterDatabaseSemanticCheck) { @@ -260,6 +335,7 @@ TEST_F(ParserInitialATest, alterDatabaseSemanticCheck) { run("ALTER DATABASE test PAGES 63", TSDB_CODE_PAR_INVALID_DB_OPTION); run("ALTER DATABASE test WAL_LEVEL 0", TSDB_CODE_PAR_INVALID_DB_OPTION); run("ALTER DATABASE test WAL_LEVEL 3", TSDB_CODE_PAR_INVALID_DB_OPTION); + run("ALTER DATABASE test REPLICA 2", TSDB_CODE_PAR_INVALID_DB_OPTION); run("ALTER DATABASE test STT_TRIGGER 0", TSDB_CODE_PAR_INVALID_DB_OPTION); run("ALTER DATABASE test STT_TRIGGER 17", TSDB_CODE_PAR_INVALID_DB_OPTION); // Regardless of the specific sentence @@ -267,7 +343,7 @@ TEST_F(ParserInitialATest, alterDatabaseSemanticCheck) { } /* - * ALTER LOCAL dnode_id 'config' ['value'] + * ALTER LOCAL 'config' ['value'] */ TEST_F(ParserInitialATest, alterLocal) { useDb("root", "test"); @@ -311,19 +387,19 @@ TEST_F(ParserInitialATest, alterLocal) { * | ADD COLUMN col_name column_type * | DROP COLUMN col_name * | MODIFY COLUMN col_name column_type - * | RENAME COLUMN old_col_name new_col_name -- normal table - * | ADD TAG tag_name tag_type -- super table - * | DROP TAG tag_name -- super table - * | MODIFY TAG tag_name tag_type -- super table - * | RENAME TAG old_tag_name new_tag_name -- super table - * | SET TAG tag_name = new_tag_value -- child table + * | RENAME COLUMN old_col_name new_col_name -- only normal table + * | ADD TAG tag_name tag_type -- only super table + * | DROP TAG tag_name -- only super table + * | MODIFY TAG tag_name tag_type -- only super table + * | RENAME TAG old_tag_name new_tag_name -- only super table + * | SET TAG tag_name = new_tag_value -- only child table * } * * alter_table_options: * alter_table_option ... * * alter_table_option: { - * TTL int_value -- child/normal table + * TTL int_value -- only child/normal table * | COMMENT 'string_value' * } */ @@ -344,7 +420,7 @@ TEST_F(ParserInitialATest, alterSTable) { expect.name[len] = '\0'; expect.alterType = alterType; if (nullptr != pComment) { - expect.comment = strdup(pComment); + expect.comment = taosStrdup(pComment); expect.commentLen = strlen(pComment); } @@ -379,6 +455,7 @@ TEST_F(ParserInitialATest, alterSTable) { setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_SUPER_TABLE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_STB); SMAlterStbReq req = {0}; ASSERT_EQ(tDeserializeSMAlterStbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); ASSERT_EQ(std::string(req.name), std::string(expect.name)); @@ -444,136 +521,257 @@ TEST_F(ParserInitialATest, alterSTableSemanticCheck) { run("ALTER STABLE st1 TTL 10", TSDB_CODE_PAR_INVALID_ALTER_TABLE); } +/* + * ALTER TABLE [db_name.]tb_name alter_table_clause + * + * alter_table_clause: { + * alter_table_options + * | ADD COLUMN col_name column_type + * | DROP COLUMN col_name + * | MODIFY COLUMN col_name column_type + * | RENAME COLUMN old_col_name new_col_name -- only normal table + * | ADD TAG tag_name tag_type -- only super table + * | DROP TAG tag_name -- only super table + * | MODIFY TAG tag_name tag_type -- only super table + * | RENAME TAG old_tag_name new_tag_name -- only super table + * | SET TAG tag_name = new_tag_value -- only child table + * } + * + * alter_table_options: + * alter_table_option ... + * + * alter_table_option: { + * TTL int_value -- only child/normal table + * | COMMENT 'string_value' + * } + */ TEST_F(ParserInitialATest, alterTable) { useDb("root", "test"); - SVAlterTbReq expect = {0}; - - auto clearAlterTbReq = [&]() { - free(expect.tbName); - free(expect.colName); - free(expect.colNewName); - free(expect.tagName); - memset(&expect, 0, sizeof(SVAlterTbReq)); - }; - - auto setAlterTableCol = [&](const char* pTbname, int8_t alterType, const char* pColName, int8_t dataType = 0, - int32_t dataBytes = 0, const char* pNewColName = nullptr) { - expect.tbName = strdup(pTbname); - expect.action = alterType; - expect.colName = strdup(pColName); - - switch (alterType) { - case TSDB_ALTER_TABLE_ADD_COLUMN: - expect.type = dataType; - expect.flags = COL_SMA_ON; - expect.bytes = dataBytes > 0 ? dataBytes : (dataType > 0 ? tDataTypes[dataType].bytes : 0); - break; - case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES: - expect.colModBytes = dataBytes; - break; - case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME: - expect.colNewName = strdup(pNewColName); - break; - default: - break; - } - }; - - auto setAlterTableTag = [&](const char* pTbname, const char* pTagName, uint8_t* pNewVal, uint32_t bytes) { - expect.tbName = strdup(pTbname); - expect.action = TSDB_ALTER_TABLE_UPDATE_TAG_VAL; - expect.tagName = strdup(pTagName); - - expect.isNull = (nullptr == pNewVal); - expect.nTagVal = bytes; - expect.pTagVal = pNewVal; - }; - - auto setAlterTableOptions = [&](const char* pTbname, int32_t ttl, char* pComment = nullptr) { - expect.tbName = strdup(pTbname); - expect.action = TSDB_ALTER_TABLE_UPDATE_OPTIONS; - if (-1 != ttl) { - expect.updateTTL = true; - expect.newTTL = ttl; - } - if (nullptr != pComment) { - expect.newCommentLen = strlen(pComment); - expect.newComment = pComment; - } - }; - - setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { - ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_VNODE_MODIF_STMT); - SVnodeModifOpStmt* pStmt = (SVnodeModifOpStmt*)pQuery->pRoot; - - ASSERT_EQ(pStmt->sqlNodeType, QUERY_NODE_ALTER_TABLE_STMT); - ASSERT_NE(pStmt->pDataBlocks, nullptr); - ASSERT_EQ(taosArrayGetSize(pStmt->pDataBlocks), 1); - SVgDataBlocks* pVgData = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, 0); - void* pBuf = POINTER_SHIFT(pVgData->pData, sizeof(SMsgHead)); - SVAlterTbReq req = {0}; - SDecoder coder = {0}; - tDecoderInit(&coder, (uint8_t*)pBuf, pVgData->size); - ASSERT_EQ(tDecodeSVAlterTbReq(&coder, &req), TSDB_CODE_SUCCESS); - - ASSERT_EQ(std::string(req.tbName), std::string(expect.tbName)); - ASSERT_EQ(req.action, expect.action); - if (nullptr != expect.colName) { - ASSERT_EQ(std::string(req.colName), std::string(expect.colName)); - } - ASSERT_EQ(req.type, expect.type); - ASSERT_EQ(req.flags, expect.flags); - ASSERT_EQ(req.bytes, expect.bytes); - ASSERT_EQ(req.colModBytes, expect.colModBytes); - if (nullptr != expect.colNewName) { - ASSERT_EQ(std::string(req.colNewName), std::string(expect.colNewName)); - } - if (nullptr != expect.tagName) { - ASSERT_EQ(std::string(req.tagName), std::string(expect.tagName)); - } - ASSERT_EQ(req.isNull, expect.isNull); - ASSERT_EQ(req.nTagVal, expect.nTagVal); - ASSERT_EQ(memcmp(req.pTagVal, expect.pTagVal, expect.nTagVal), 0); - ASSERT_EQ(req.updateTTL, expect.updateTTL); - ASSERT_EQ(req.newTTL, expect.newTTL); - if (nullptr != expect.newComment) { - ASSERT_EQ(std::string(req.newComment), std::string(expect.newComment)); - ASSERT_EQ(req.newCommentLen, strlen(req.newComment)); - ASSERT_EQ(expect.newCommentLen, strlen(expect.newComment)); - } - - tDecoderClear(&coder); - }); - - setAlterTableOptions("t1", 10, nullptr); - run("ALTER TABLE t1 TTL 10"); - clearAlterTbReq(); - - setAlterTableOptions("t1", -1, (char*)"test"); - run("ALTER TABLE t1 COMMENT 'test'"); - clearAlterTbReq(); - - setAlterTableCol("t1", TSDB_ALTER_TABLE_ADD_COLUMN, "cc1", TSDB_DATA_TYPE_BIGINT); - run("ALTER TABLE t1 ADD COLUMN cc1 BIGINT"); - clearAlterTbReq(); - - setAlterTableCol("t1", TSDB_ALTER_TABLE_DROP_COLUMN, "c1"); - run("ALTER TABLE t1 DROP COLUMN c1"); - clearAlterTbReq(); - - setAlterTableCol("t1", TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, "c2", TSDB_DATA_TYPE_VARCHAR, 30 + VARSTR_HEADER_SIZE); - run("ALTER TABLE t1 MODIFY COLUMN c2 VARCHAR(30)"); - clearAlterTbReq(); - - setAlterTableCol("t1", TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, "c1", 0, 0, "cc1"); - run("ALTER TABLE t1 RENAME COLUMN c1 cc1"); - clearAlterTbReq(); - - int32_t val = 10; - setAlterTableTag("st1s1", "tag1", (uint8_t*)&val, sizeof(val)); - run("ALTER TABLE st1s1 SET TAG tag1=10"); - clearAlterTbReq(); + // normal/child table + { + SVAlterTbReq expect = {0}; + + auto clearAlterTbReq = [&]() { + free(expect.tbName); + free(expect.colName); + free(expect.colNewName); + free(expect.tagName); + memset(&expect, 0, sizeof(SVAlterTbReq)); + }; + + auto setAlterTableCol = [&](const char* pTbname, int8_t alterType, const char* pColName, int8_t dataType = 0, + int32_t dataBytes = 0, const char* pNewColName = nullptr) { + expect.tbName = strdup(pTbname); + expect.action = alterType; + expect.colName = strdup(pColName); + + switch (alterType) { + case TSDB_ALTER_TABLE_ADD_COLUMN: + expect.type = dataType; + expect.flags = COL_SMA_ON; + expect.bytes = dataBytes > 0 ? dataBytes : (dataType > 0 ? tDataTypes[dataType].bytes : 0); + break; + case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES: + expect.colModBytes = dataBytes; + break; + case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME: + expect.colNewName = strdup(pNewColName); + break; + default: + break; + } + }; + + auto setAlterTableTag = [&](const char* pTbname, const char* pTagName, uint8_t* pNewVal, uint32_t bytes) { + expect.tbName = strdup(pTbname); + expect.action = TSDB_ALTER_TABLE_UPDATE_TAG_VAL; + expect.tagName = strdup(pTagName); + + expect.isNull = (nullptr == pNewVal); + expect.nTagVal = bytes; + expect.pTagVal = pNewVal; + }; + + auto setAlterTableOptions = [&](const char* pTbname, int32_t ttl, char* pComment = nullptr) { + expect.tbName = strdup(pTbname); + expect.action = TSDB_ALTER_TABLE_UPDATE_OPTIONS; + if (-1 != ttl) { + expect.updateTTL = true; + expect.newTTL = ttl; + } + if (nullptr != pComment) { + expect.newCommentLen = strlen(pComment); + expect.newComment = pComment; + } + }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_VNODE_MODIFY_STMT); + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot; + + ASSERT_EQ(pStmt->sqlNodeType, QUERY_NODE_ALTER_TABLE_STMT); + ASSERT_NE(pStmt->pDataBlocks, nullptr); + ASSERT_EQ(taosArrayGetSize(pStmt->pDataBlocks), 1); + SVgDataBlocks* pVgData = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, 0); + void* pBuf = POINTER_SHIFT(pVgData->pData, sizeof(SMsgHead)); + SVAlterTbReq req = {0}; + SDecoder coder = {0}; + tDecoderInit(&coder, (uint8_t*)pBuf, pVgData->size); + ASSERT_EQ(tDecodeSVAlterTbReq(&coder, &req), TSDB_CODE_SUCCESS); + + ASSERT_EQ(std::string(req.tbName), std::string(expect.tbName)); + ASSERT_EQ(req.action, expect.action); + if (nullptr != expect.colName) { + ASSERT_EQ(std::string(req.colName), std::string(expect.colName)); + } + ASSERT_EQ(req.type, expect.type); + ASSERT_EQ(req.flags, expect.flags); + ASSERT_EQ(req.bytes, expect.bytes); + ASSERT_EQ(req.colModBytes, expect.colModBytes); + if (nullptr != expect.colNewName) { + ASSERT_EQ(std::string(req.colNewName), std::string(expect.colNewName)); + } + if (nullptr != expect.tagName) { + ASSERT_EQ(std::string(req.tagName), std::string(expect.tagName)); + } + ASSERT_EQ(req.isNull, expect.isNull); + ASSERT_EQ(req.nTagVal, expect.nTagVal); + if (nullptr != req.pTagVal) { + ASSERT_EQ(memcmp(req.pTagVal, expect.pTagVal, expect.nTagVal), 0); + } + ASSERT_EQ(req.updateTTL, expect.updateTTL); + ASSERT_EQ(req.newTTL, expect.newTTL); + if (nullptr != expect.newComment) { + ASSERT_EQ(std::string(req.newComment), std::string(expect.newComment)); + ASSERT_EQ(req.newCommentLen, strlen(req.newComment)); + ASSERT_EQ(expect.newCommentLen, strlen(expect.newComment)); + } + + tDecoderClear(&coder); + }); + + setAlterTableOptions("t1", 10, nullptr); + run("ALTER TABLE t1 TTL 10"); + clearAlterTbReq(); + + setAlterTableOptions("t1", -1, (char*)"test"); + run("ALTER TABLE t1 COMMENT 'test'"); + clearAlterTbReq(); + + setAlterTableCol("t1", TSDB_ALTER_TABLE_ADD_COLUMN, "cc1", TSDB_DATA_TYPE_BIGINT); + run("ALTER TABLE t1 ADD COLUMN cc1 BIGINT"); + clearAlterTbReq(); + + setAlterTableCol("t1", TSDB_ALTER_TABLE_DROP_COLUMN, "c1"); + run("ALTER TABLE t1 DROP COLUMN c1"); + clearAlterTbReq(); + + setAlterTableCol("t1", TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES, "c2", TSDB_DATA_TYPE_VARCHAR, 30 + VARSTR_HEADER_SIZE); + run("ALTER TABLE t1 MODIFY COLUMN c2 VARCHAR(30)"); + clearAlterTbReq(); + + setAlterTableCol("t1", TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME, "c1", 0, 0, "cc1"); + run("ALTER TABLE t1 RENAME COLUMN c1 cc1"); + clearAlterTbReq(); + + int32_t val = 10; + setAlterTableTag("st1s1", "tag1", (uint8_t*)&val, sizeof(val)); + run("ALTER TABLE st1s1 SET TAG tag1=10"); + clearAlterTbReq(); + } + + // super table + { + SMAlterStbReq expect = {0}; + + auto clearAlterStbReq = [&]() { + tFreeSMAltertbReq(&expect); + memset(&expect, 0, sizeof(SMAlterStbReq)); + }; + + auto setAlterStbReq = [&](const char* pTbname, int8_t alterType, int32_t numOfFields = 0, + const char* pField1Name = nullptr, int8_t field1Type = 0, int32_t field1Bytes = 0, + const char* pField2Name = nullptr, const char* pComment = nullptr) { + int32_t len = snprintf(expect.name, sizeof(expect.name), "0.test.%s", pTbname); + expect.name[len] = '\0'; + expect.alterType = alterType; + if (nullptr != pComment) { + expect.comment = strdup(pComment); + expect.commentLen = strlen(pComment); + } + + expect.numOfFields = numOfFields; + if (NULL == expect.pFields) { + expect.pFields = taosArrayInit(2, sizeof(TAOS_FIELD)); + TAOS_FIELD field = {0}; + taosArrayPush(expect.pFields, &field); + taosArrayPush(expect.pFields, &field); + } + + TAOS_FIELD* pField = (TAOS_FIELD*)taosArrayGet(expect.pFields, 0); + if (NULL != pField1Name) { + strcpy(pField->name, pField1Name); + pField->name[strlen(pField1Name)] = '\0'; + } else { + memset(pField, 0, sizeof(TAOS_FIELD)); + } + pField->type = field1Type; + pField->bytes = field1Bytes > 0 ? field1Bytes : (field1Type > 0 ? tDataTypes[field1Type].bytes : 0); + + pField = (TAOS_FIELD*)taosArrayGet(expect.pFields, 1); + if (NULL != pField2Name) { + strcpy(pField->name, pField2Name); + pField->name[strlen(pField2Name)] = '\0'; + } else { + memset(pField, 0, sizeof(TAOS_FIELD)); + } + pField->type = 0; + pField->bytes = 0; + }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_TABLE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_STB); + SMAlterStbReq req = {0}; + ASSERT_EQ(tDeserializeSMAlterStbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); + ASSERT_EQ(std::string(req.name), std::string(expect.name)); + ASSERT_EQ(req.alterType, expect.alterType); + ASSERT_EQ(req.numOfFields, expect.numOfFields); + if (expect.numOfFields > 0) { + TAOS_FIELD* pField = (TAOS_FIELD*)taosArrayGet(req.pFields, 0); + TAOS_FIELD* pExpectField = (TAOS_FIELD*)taosArrayGet(expect.pFields, 0); + ASSERT_EQ(std::string(pField->name), std::string(pExpectField->name)); + ASSERT_EQ(pField->type, pExpectField->type); + ASSERT_EQ(pField->bytes, pExpectField->bytes); + } + if (expect.numOfFields > 1) { + TAOS_FIELD* pField = (TAOS_FIELD*)taosArrayGet(req.pFields, 1); + TAOS_FIELD* pExpectField = (TAOS_FIELD*)taosArrayGet(expect.pFields, 1); + ASSERT_EQ(std::string(pField->name), std::string(pExpectField->name)); + ASSERT_EQ(pField->type, pExpectField->type); + ASSERT_EQ(pField->bytes, pExpectField->bytes); + } + tFreeSMAltertbReq(&req); + }); + + setAlterStbReq("st1", TSDB_ALTER_TABLE_ADD_TAG, 1, "tag11", TSDB_DATA_TYPE_BIGINT); + run("ALTER TABLE st1 ADD TAG tag11 BIGINT"); + clearAlterStbReq(); + + setAlterStbReq("st1", TSDB_ALTER_TABLE_DROP_TAG, 1, "tag1"); + run("ALTER TABLE st1 DROP TAG tag1"); + clearAlterStbReq(); + + setAlterStbReq("st1", TSDB_ALTER_TABLE_UPDATE_TAG_BYTES, 1, "tag2", TSDB_DATA_TYPE_VARCHAR, + 30 + VARSTR_HEADER_SIZE); + run("ALTER TABLE st1 MODIFY TAG tag2 VARCHAR(30)"); + clearAlterStbReq(); + + setAlterStbReq("st1", TSDB_ALTER_TABLE_UPDATE_TAG_NAME, 2, "tag1", 0, 0, "tag11"); + run("ALTER TABLE st1 RENAME TAG tag1 tag11"); + clearAlterStbReq(); + } } TEST_F(ParserInitialATest, alterTableSemanticCheck) { @@ -588,7 +786,7 @@ TEST_F(ParserInitialATest, alterTableSemanticCheck) { } /* - * ALTER USER user_name PASS str_value + * ALTER USER user_name alter_user_clause * * alter_user_clause: { * PASS str_value @@ -618,6 +816,7 @@ TEST_F(ParserInitialATest, alterUser) { setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_ALTER_USER_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_USER); SAlterUserReq req = {0}; ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSAlterUserReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); @@ -659,4 +858,21 @@ TEST_F(ParserInitialATest, balanceVgroup) { run("BALANCE VGROUP"); } +/* + * BALANCE VGROUP LEADER + */ +TEST_F(ParserInitialATest, balanceVgroupLeader) { + useDb("root", "test"); + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_BALANCE_VGROUP_LEADER_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_BALANCE_VGROUP_LEADER); + SBalanceVgroupLeaderReq req = {0}; + ASSERT_EQ(tDeserializeSBalanceVgroupLeaderReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), + TSDB_CODE_SUCCESS); + }); + + run("BALANCE VGROUP LEADER"); +} + } // namespace ParserTest \ No newline at end of file diff --git a/source/libs/parser/test/parExplainToSyncdbTest.cpp b/source/libs/parser/test/parExplainToSyncdbTest.cpp index f88d6d316b13606ba95226e669a59bcc588bf566..f23685b3058b911f23baf8c37c6608ab989de5c7 100644 --- a/source/libs/parser/test/parExplainToSyncdbTest.cpp +++ b/source/libs/parser/test/parExplainToSyncdbTest.cpp @@ -52,8 +52,8 @@ TEST_F(ParserExplainToSyncdbTest, grant) { ASSERT_EQ(string(req.objname), string(expect.objname)); }); - setAlterUserReq(TSDB_ALTER_USER_ADD_ALL_DB, "wxy", "0.test"); - run("GRANT ALL ON test.* TO wxy"); + setAlterUserReq(TSDB_ALTER_USER_ADD_ALL_DB, "wxy", "0.*"); + run("GRANT ALL ON *.* TO wxy"); setAlterUserReq(TSDB_ALTER_USER_ADD_READ_DB, "wxy", "0.test"); run("GRANT READ ON test.* TO wxy"); @@ -138,10 +138,38 @@ TEST_F(ParserExplainToSyncdbTest, redistributeVgroup) { TEST_F(ParserExplainToSyncdbTest, revoke) { useDb("root", "test"); - run("REVOKE ALL ON test.* FROM wxy"); + SAlterUserReq expect = {0}; + + auto setAlterUserReq = [&](int8_t alterType, const string& user, const string& obj) { + expect.alterType = alterType; + snprintf(expect.user, sizeof(expect.user), "%s", user.c_str()); + snprintf(expect.objname, sizeof(expect.objname), "%s", obj.c_str()); + }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_REVOKE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_ALTER_USER); + SAlterUserReq req = {0}; + ASSERT_EQ(tDeserializeSAlterUserReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); + ASSERT_EQ(req.alterType, expect.alterType); + ASSERT_EQ(string(req.user), string(expect.user)); + ASSERT_EQ(string(req.objname), string(expect.objname)); + }); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_ALL_DB, "wxy", "0.*"); + run("REVOKE ALL ON *.* FROM wxy"); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_READ_DB, "wxy", "0.test"); run("REVOKE READ ON test.* FROM wxy"); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_WRITE_DB, "wxy", "0.test"); run("REVOKE WRITE ON test.* FROM wxy"); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_ALL_DB, "wxy", "0.test"); run("REVOKE READ, WRITE ON test.* FROM wxy"); + + setAlterUserReq(TSDB_ALTER_USER_REMOVE_SUBSCRIBE_TOPIC, "wxy", "0.tp1"); + run("REVOKE SUBSCRIBE ON tp1 FROM wxy"); } // todo syncdb diff --git a/source/libs/parser/test/parInitialCTest.cpp b/source/libs/parser/test/parInitialCTest.cpp index eb264687f12ee4f5fc4777478d7b199eef9dc25b..6a08193a39a1e1da7f321ae111445e5d714ac1ac 100644 --- a/source/libs/parser/test/parInitialCTest.cpp +++ b/source/libs/parser/test/parInitialCTest.cpp @@ -13,6 +13,8 @@ * along with this program. If not, see . */ +#include + #include "parTestUtil.h" using namespace std; @@ -21,12 +23,70 @@ namespace ParserTest { class ParserInitialCTest : public ParserDdlTest {}; +/* + * COMPACT DATABASE db_name [START WITH start_time] [END WITH END_time] + */ +TEST_F(ParserInitialCTest, compact) { + SCompactDbReq expect = {0}; + + auto setCompactDbReq = [&](const char* pDb, int64_t start = INT64_MIN, int64_t end = INT64_MAX) { + snprintf(expect.db, sizeof(expect.db), "0.%s", pDb); + expect.timeRange.skey = start; + expect.timeRange.ekey = end; + }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_COMPACT_DATABASE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_COMPACT_DB); + SCompactDbReq req = {0}; + ASSERT_EQ(tDeserializeSCompactDbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req), TSDB_CODE_SUCCESS); + ASSERT_EQ(std::string(req.db), std::string(expect.db)); + ASSERT_EQ(req.timeRange.skey, expect.timeRange.skey); + ASSERT_EQ(req.timeRange.ekey, expect.timeRange.ekey); + }); + + setCompactDbReq("test"); + run("COMPACT DATABASE test"); + + setCompactDbReq("test", 1678168883000, 1678255283000); + run("COMPACT DATABASE test START WITH '2023-03-07 14:01:23' END WITH '2023-03-08 14:01:23'"); + + setCompactDbReq("testus", 1673071283000000000); + run("COMPACT DATABASE testus START WITH TIMESTAMP '2023-01-07 14:01:23'"); + + setCompactDbReq("testus", INT64_MIN, 1675749683000000000); + run("COMPACT DATABASE testus END WITH 1675749683000000000"); +} + +/* + * CREATE ACCOUNT account_name PASS value [create_account_options] + * + * create_account_options: + * create_account_option ... + * + * create_account_option: { + * PPS value + * | TSERIES value + * | STORAGE value + * | STREAMS value + * | QTIME value + * | DBS value + * | USERS value + * | CONNS value + * | STATE value + * } + */ TEST_F(ParserInitialCTest, createAccount) { useDb("root", "test"); run("CREATE ACCOUNT ac_wxy PASS '123456'", TSDB_CODE_PAR_EXPRIE_STATEMENT, PARSER_STAGE_PARSE); } +/* + * CREATE BNODE ON DNODE dnode_id + * the server does not support it temporarily + */ + /* * CREATE DATABASE [IF NOT EXISTS] db_name [database_options] * @@ -68,7 +128,7 @@ TEST_F(ParserInitialCTest, createDatabase) { memset(&expect, 0, sizeof(SCreateDbReq)); }; - auto setCreateDbReqFunc = [&](const char* pDbname, int8_t igExists = 0) { + auto setCreateDbReq = [&](const char* pDbname, int8_t igExists = 0) { int32_t len = snprintf(expect.db, sizeof(expect.db), "0.%s", pDbname); expect.db[len] = '\0'; expect.ignoreExist = igExists; @@ -102,28 +162,28 @@ TEST_F(ParserInitialCTest, createDatabase) { expect.tsdbPageSize = TSDB_DEFAULT_TSDB_PAGESIZE; }; - auto setDbBufferFunc = [&](int32_t buffer) { expect.buffer = buffer; }; - auto setDbCachelastFunc = [&](int8_t cachelast) { expect.cacheLast = cachelast; }; + auto setDbBuffer = [&](int32_t buffer) { expect.buffer = buffer; }; + auto setDbCachelast = [&](int8_t cachelast) { expect.cacheLast = cachelast; }; auto setDbCachelastSize = [&](int8_t cachelastSize) { expect.cacheLastSize = cachelastSize; }; - auto setDbCompressionFunc = [&](int8_t compressionLevel) { expect.compression = compressionLevel; }; - auto setDbDaysFunc = [&](int32_t daysPerFile) { expect.daysPerFile = daysPerFile; }; - auto setDbFsyncFunc = [&](int32_t fsyncPeriod) { expect.walFsyncPeriod = fsyncPeriod; }; - auto setDbMaxRowsFunc = [&](int32_t maxRowsPerBlock) { expect.maxRows = maxRowsPerBlock; }; - auto setDbMinRowsFunc = [&](int32_t minRowsPerBlock) { expect.minRows = minRowsPerBlock; }; - auto setDbKeepFunc = [&](int32_t keep0, int32_t keep1 = 0, int32_t keep2 = 0) { + auto setDbCompression = [&](int8_t compressionLevel) { expect.compression = compressionLevel; }; + auto setDbDays = [&](int32_t daysPerFile) { expect.daysPerFile = daysPerFile; }; + auto setDbFsync = [&](int32_t fsyncPeriod) { expect.walFsyncPeriod = fsyncPeriod; }; + auto setDbMaxRows = [&](int32_t maxRowsPerBlock) { expect.maxRows = maxRowsPerBlock; }; + auto setDbMinRows = [&](int32_t minRowsPerBlock) { expect.minRows = minRowsPerBlock; }; + auto setDbKeep = [&](int32_t keep0, int32_t keep1 = 0, int32_t keep2 = 0) { expect.daysToKeep0 = keep0; expect.daysToKeep1 = 0 == keep1 ? expect.daysToKeep0 : keep1; expect.daysToKeep2 = 0 == keep2 ? expect.daysToKeep1 : keep2; }; - auto setDbPagesFunc = [&](int32_t pages) { expect.pages = pages; }; - auto setDbPageSizeFunc = [&](int32_t pagesize) { expect.pageSize = pagesize; }; - auto setDbPrecisionFunc = [&](int8_t precision) { expect.precision = precision; }; - auto setDbReplicaFunc = [&](int8_t replica) { expect.replications = replica; }; - auto setDbStrictaFunc = [&](int8_t strict) { expect.strict = strict; }; - auto setDbWalLevelFunc = [&](int8_t walLevel) { expect.walLevel = walLevel; }; - auto setDbVgroupsFunc = [&](int32_t numOfVgroups) { expect.numOfVgroups = numOfVgroups; }; - auto setDbSingleStableFunc = [&](int8_t singleStable) { expect.numOfStables = singleStable; }; - auto addDbRetentionFunc = [&](int64_t freq, int64_t keep, int8_t freqUnit, int8_t keepUnit) { + auto setDbPages = [&](int32_t pages) { expect.pages = pages; }; + auto setDbPageSize = [&](int32_t pagesize) { expect.pageSize = pagesize; }; + auto setDbPrecision = [&](int8_t precision) { expect.precision = precision; }; + auto setDbReplica = [&](int8_t replica) { expect.replications = replica; }; + auto setDbStricta = [&](int8_t strict) { expect.strict = strict; }; + auto setDbWalLevel = [&](int8_t walLevel) { expect.walLevel = walLevel; }; + auto setDbVgroups = [&](int32_t numOfVgroups) { expect.numOfVgroups = numOfVgroups; }; + auto setDbSingleStable = [&](int8_t singleStable) { expect.numOfStables = singleStable; }; + auto addDbRetention = [&](int64_t freq, int64_t keep, int8_t freqUnit, int8_t keepUnit) { SRetention retention = {0}; retention.freq = freq; retention.keep = keep; @@ -135,7 +195,7 @@ TEST_F(ParserInitialCTest, createDatabase) { taosArrayPush(expect.pRetensions, &retention); ++expect.numOfRetensions; }; - auto setDbSchemalessFunc = [&](int8_t schemaless) { expect.schemaless = schemaless; }; + auto setDbSchemaless = [&](int8_t schemaless) { expect.schemaless = schemaless; }; auto setDbWalRetentionPeriod = [&](int32_t walRetentionPeriod) { expect.walRetentionPeriod = walRetentionPeriod; }; auto setDbWalRetentionSize = [&](int32_t walRetentionSize) { expect.walRetentionSize = walRetentionSize; }; auto setDbWalRollPeriod = [&](int32_t walRollPeriod) { expect.walRollPeriod = walRollPeriod; }; @@ -147,6 +207,7 @@ TEST_F(ParserInitialCTest, createDatabase) { setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_DATABASE_STMT); + ASSERT_EQ(pQuery->pCmdMsg->msgType, TDMT_MND_CREATE_DB); SCreateDbReq req = {0}; ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSCreateDbReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); @@ -195,32 +256,32 @@ TEST_F(ParserInitialCTest, createDatabase) { tFreeSCreateDbReq(&req); }); - setCreateDbReqFunc("wxy_db"); + setCreateDbReq("wxy_db"); run("CREATE DATABASE wxy_db"); clearCreateDbReq(); - setCreateDbReqFunc("wxy_db", 1); - setDbBufferFunc(64); - setDbCachelastFunc(2); + setCreateDbReq("wxy_db", 1); + setDbBuffer(64); + setDbCachelast(2); setDbCachelastSize(20); - setDbCompressionFunc(1); - setDbDaysFunc(100 * 1440); - setDbFsyncFunc(100); - setDbMaxRowsFunc(1000); - setDbMinRowsFunc(100); - setDbKeepFunc(1440 * 1440); - setDbPagesFunc(96); - setDbPageSizeFunc(8); - setDbPrecisionFunc(TSDB_TIME_PRECISION_NANO); - setDbReplicaFunc(3); - addDbRetentionFunc(15 * MILLISECOND_PER_SECOND, 7 * MILLISECOND_PER_DAY, TIME_UNIT_SECOND, TIME_UNIT_DAY); - addDbRetentionFunc(1 * MILLISECOND_PER_MINUTE, 21 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY); - addDbRetentionFunc(15 * MILLISECOND_PER_MINUTE, 500 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY); - // setDbStrictaFunc(1); - setDbWalLevelFunc(2); - setDbVgroupsFunc(100); - setDbSingleStableFunc(1); - setDbSchemalessFunc(1); + setDbCompression(1); + setDbDays(100 * 1440); + setDbFsync(100); + setDbMaxRows(1000); + setDbMinRows(100); + setDbKeep(1440 * 1440); + setDbPages(96); + setDbPageSize(8); + setDbPrecision(TSDB_TIME_PRECISION_NANO); + setDbReplica(3); + addDbRetention(15 * MILLISECOND_PER_SECOND, 7 * MILLISECOND_PER_DAY, TIME_UNIT_SECOND, TIME_UNIT_DAY); + addDbRetention(1 * MILLISECOND_PER_MINUTE, 21 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY); + addDbRetention(15 * MILLISECOND_PER_MINUTE, 500 * MILLISECOND_PER_DAY, TIME_UNIT_MINUTE, TIME_UNIT_DAY); + // setDbStricta(1); + setDbWalLevel(2); + setDbVgroups(100); + setDbSingleStable(1); + setDbSchemaless(1); setDbWalRetentionPeriod(-1); setDbWalRetentionSize(-1); setDbWalRollPeriod(10); @@ -259,16 +320,16 @@ TEST_F(ParserInitialCTest, createDatabase) { "TSDB_PAGESIZE 32"); clearCreateDbReq(); - setCreateDbReqFunc("wxy_db", 1); - setDbDaysFunc(100); - setDbKeepFunc(1440, 300 * 60, 400 * 1440); + setCreateDbReq("wxy_db", 1); + setDbDays(100); + setDbKeep(1440, 300 * 60, 400 * 1440); run("CREATE DATABASE IF NOT EXISTS wxy_db " "DURATION 100m " "KEEP 1440m,300h,400d "); clearCreateDbReq(); - setCreateDbReqFunc("wxy_db", 1); - setDbReplicaFunc(3); + setCreateDbReq("wxy_db", 1); + setDbReplica(3); setDbWalRetentionPeriod(TSDB_REPS_DEF_DB_WAL_RET_PERIOD); setDbWalRetentionSize(TSDB_REPS_DEF_DB_WAL_RET_SIZE); setDbWalRollPeriod(TSDB_REPS_DEF_DB_WAL_ROLL_PERIOD); @@ -287,6 +348,9 @@ TEST_F(ParserInitialCTest, createDatabaseSemanticCheck) { run("create database db2 retentions 15s:7d,5m:21d,10m:10d", TSDB_CODE_PAR_INVALID_DB_OPTION); } +/* + * CREATE DNODE {dnode_endpoint | dnode_host_name PORT port_val} + */ TEST_F(ParserInitialCTest, createDnode) { useDb("root", "test"); @@ -294,7 +358,7 @@ TEST_F(ParserInitialCTest, createDnode) { auto clearCreateDnodeReq = [&]() { memset(&expect, 0, sizeof(SCreateDnodeReq)); }; - auto setCreateDnodeReqFunc = [&](const char* pFqdn, int32_t port = tsServerPort) { + auto setCreateDnodeReq = [&](const char* pFqdn, int32_t port = tsServerPort) { strcpy(expect.fqdn, pFqdn); expect.port = port; }; @@ -308,44 +372,49 @@ TEST_F(ParserInitialCTest, createDnode) { ASSERT_EQ(req.port, expect.port); }); - setCreateDnodeReqFunc("abc1", 7030); + setCreateDnodeReq("abc1", 7030); run("CREATE DNODE 'abc1' PORT 7030"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("1.1.1.1", 8030); + setCreateDnodeReq("1.1.1.1", 8030); run("CREATE DNODE 1.1.1.1 PORT 8030"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("host1", 9030); + setCreateDnodeReq("host1", 9030); run("CREATE DNODE host1 PORT 9030"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("abc2", 7040); + setCreateDnodeReq("abc2", 7040); run("CREATE DNODE 'abc2:7040'"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("1.1.1.2"); + setCreateDnodeReq("1.1.1.2"); run("CREATE DNODE 1.1.1.2"); clearCreateDnodeReq(); - setCreateDnodeReqFunc("host2"); + setCreateDnodeReq("host2"); run("CREATE DNODE host2"); clearCreateDnodeReq(); } -// CREATE [AGGREGATE] FUNCTION [IF NOT EXISTS] func_name AS library_path OUTPUTTYPE type_name [BUFSIZE value] +/* + * CREATE [OR REPLACE] [AGGREGATE] FUNCTION [IF NOT EXISTS] func_name + * AS library_path OUTPUTTYPE type_name [BUFSIZE value] [LANGUAGE value] + */ TEST_F(ParserInitialCTest, createFunction) { useDb("root", "test"); SCreateFuncReq expect = {0}; - auto setCreateFuncReqFunc = [&](const char* pUdfName, int8_t outputType, int32_t outputBytes = 0, - int8_t funcType = TSDB_FUNC_TYPE_SCALAR, int8_t igExists = 0, int32_t bufSize = 0) { + auto setCreateFuncReq = [&](const char* pUdfName, int8_t outputType, int32_t outputBytes = 0, + int8_t funcType = TSDB_FUNC_TYPE_SCALAR, int8_t igExists = 0, int32_t bufSize = 0, + int8_t language = TSDB_FUNC_SCRIPT_BIN_LIB, int8_t orReplace = 0) { memset(&expect, 0, sizeof(SCreateFuncReq)); strcpy(expect.name, pUdfName); + expect.orReplace = orReplace; expect.igExists = igExists; expect.funcType = funcType; - expect.scriptType = TSDB_FUNC_SCRIPT_BIN_LIB; + expect.scriptType = language; expect.outputType = outputType; expect.outputLen = outputBytes > 0 ? outputBytes : tDataTypes[outputType].bytes; expect.bufSize = bufSize; @@ -357,21 +426,90 @@ TEST_F(ParserInitialCTest, createFunction) { ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSCreateFuncReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); ASSERT_EQ(std::string(req.name), std::string(expect.name)); + ASSERT_EQ(req.orReplace, expect.orReplace); ASSERT_EQ(req.igExists, expect.igExists); ASSERT_EQ(req.funcType, expect.funcType); ASSERT_EQ(req.scriptType, expect.scriptType); ASSERT_EQ(req.outputType, expect.outputType); ASSERT_EQ(req.outputLen, expect.outputLen); ASSERT_EQ(req.bufSize, expect.bufSize); + + tFreeSCreateFuncReq(&req); + }); + + struct udfFile { + udfFile(const std::string& filename) : path_(filename) { + std::ofstream file(filename, std::ios::binary); + file << 123 << "abc" << '\n'; + file.close(); + } + ~udfFile() { remove(path_.c_str()); } + std::string path_; + } udffile("udf"); + + setCreateFuncReq("udf1", TSDB_DATA_TYPE_INT); + run("CREATE FUNCTION udf1 AS 'udf' OUTPUTTYPE INT"); + + setCreateFuncReq("udf2", TSDB_DATA_TYPE_DOUBLE, 0, TSDB_FUNC_TYPE_AGGREGATE, 1, 8, TSDB_FUNC_SCRIPT_PYTHON, 1); + run("CREATE OR REPLACE AGGREGATE FUNCTION IF NOT EXISTS udf2 AS 'udf' OUTPUTTYPE DOUBLE BUFSIZE 8 LANGUAGE 'python'"); +} + +/* + * CREATE MNODE ON DNODE dnode_id + */ +TEST_F(ParserInitialCTest, createMnode) { + useDb("root", "test"); + + SMCreateMnodeReq expect = {0}; + + auto setCreateMnodeReq = [&](int32_t dnodeId) { expect.dnodeId = dnodeId; }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_MNODE_STMT); + SMCreateMnodeReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == + tDeserializeSCreateDropMQSNodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); + + ASSERT_EQ(req.dnodeId, expect.dnodeId); }); - setCreateFuncReqFunc("udf1", TSDB_DATA_TYPE_INT); - // run("CREATE FUNCTION udf1 AS './build/lib/libudf1.so' OUTPUTTYPE INT"); + setCreateMnodeReq(1); + run("CREATE MNODE ON DNODE 1"); +} - setCreateFuncReqFunc("udf2", TSDB_DATA_TYPE_DOUBLE, 0, TSDB_FUNC_TYPE_AGGREGATE, 1, 8); - // run("CREATE AGGREGATE FUNCTION IF NOT EXISTS udf2 AS './build/lib/libudf2.so' OUTPUTTYPE DOUBLE BUFSIZE 8"); +/* + * CREATE QNODE ON DNODE dnode_id + */ +TEST_F(ParserInitialCTest, createQnode) { + useDb("root", "test"); + + SMCreateQnodeReq expect = {0}; + + auto setCreateQnodeReq = [&](int32_t dnodeId) { expect.dnodeId = dnodeId; }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_QNODE_STMT); + SMCreateQnodeReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == + tDeserializeSCreateDropMQSNodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); + + ASSERT_EQ(req.dnodeId, expect.dnodeId); + }); + + setCreateQnodeReq(1); + run("CREATE QNODE ON DNODE 1"); } +/* + * CREATE SMA INDEX index_name ON tb_name index_option + * + * index_option: + * FUNCTION(functions) INTERVAL(interval_val [, interval_offset]) [SLIDING(sliding_val)] + * [WATERMARK(watermark_val)] [MAX_DELAY(max_delay_val)] + * + * functions: + * function [, function] ... + */ TEST_F(ParserInitialCTest, createSmaIndex) { useDb("root", "test"); @@ -439,24 +577,39 @@ TEST_F(ParserInitialCTest, createSmaIndex) { "DELETE_MARK 1000s"); } -TEST_F(ParserInitialCTest, createMnode) { +/* + * CREATE SNODE ON DNODE dnode_id + */ +TEST_F(ParserInitialCTest, createSnode) { useDb("root", "test"); - run("CREATE MNODE ON DNODE 1"); -} + SMCreateSnodeReq expect = {0}; -TEST_F(ParserInitialCTest, createQnode) { - useDb("root", "test"); + auto setCreateSnodeReq = [&](int32_t dnodeId) { expect.dnodeId = dnodeId; }; - run("CREATE QNODE ON DNODE 1"); -} + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_CREATE_SNODE_STMT); + SMCreateSnodeReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == + tDeserializeSCreateDropMQSNodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); -TEST_F(ParserInitialCTest, createSnode) { - useDb("root", "test"); + ASSERT_EQ(req.dnodeId, expect.dnodeId); + }); + setCreateSnodeReq(1); run("CREATE SNODE ON DNODE 1"); } +/* + * CREATE STABLE [IF NOT EXISTS] stb_name (create_definition [, create_definitionn] ...) + * TAGS (create_definition [, create_definition] ...) [table_options] + * + * create_definition: + * col_name column_definition + * + * column_definition: + * type_name [COMMENT 'string_value'] + */ TEST_F(ParserInitialCTest, createStable) { useDb("root", "test"); @@ -467,7 +620,7 @@ TEST_F(ParserInitialCTest, createStable) { memset(&expect, 0, sizeof(SMCreateStbReq)); }; - auto setCreateStbReqFunc = + auto setCreateStbReq = [&](const char* pDbName, const char* pTbName, int8_t igExists = 0, int64_t delay1 = -1, int64_t delay2 = -1, int64_t watermark1 = TSDB_DEFAULT_ROLLUP_WATERMARK, int64_t watermark2 = TSDB_DEFAULT_ROLLUP_WATERMARK, int64_t deleteMark1 = TSDB_DEFAULT_ROLLUP_DELETE_MARK, int64_t deleteMark2 = TSDB_DEFAULT_ROLLUP_DELETE_MARK, @@ -483,13 +636,13 @@ TEST_F(ParserInitialCTest, createStable) { expect.deleteMark2 = deleteMark2; // expect.ttl = ttl; if (nullptr != pComment) { - expect.pComment = strdup(pComment); + expect.pComment = taosStrdup(pComment); expect.commentLen = strlen(pComment); } }; - auto addFieldToCreateStbReqFunc = [&](bool col, const char* pFieldName, uint8_t type, int32_t bytes = 0, - int8_t flags = COL_SMA_ON) { + auto addFieldToCreateStbReq = [&](bool col, const char* pFieldName, uint8_t type, int32_t bytes = 0, + int8_t flags = COL_SMA_ON) { SField field = {0}; strcpy(field.name, pFieldName); field.type = type; @@ -565,52 +718,52 @@ TEST_F(ParserInitialCTest, createStable) { tFreeSMCreateStbReq(&req); }); - setCreateStbReqFunc("test", "t1"); - addFieldToCreateStbReqFunc(true, "ts", TSDB_DATA_TYPE_TIMESTAMP); - addFieldToCreateStbReqFunc(true, "c1", TSDB_DATA_TYPE_INT); - addFieldToCreateStbReqFunc(false, "id", TSDB_DATA_TYPE_INT); + setCreateStbReq("test", "t1"); + addFieldToCreateStbReq(true, "ts", TSDB_DATA_TYPE_TIMESTAMP); + addFieldToCreateStbReq(true, "c1", TSDB_DATA_TYPE_INT); + addFieldToCreateStbReq(false, "id", TSDB_DATA_TYPE_INT); run("CREATE STABLE t1(ts TIMESTAMP, c1 INT) TAGS(id INT)"); clearCreateStbReq(); - setCreateStbReqFunc("rollup_db", "t1", 1, 100 * MILLISECOND_PER_SECOND, 10 * MILLISECOND_PER_MINUTE, 10, - 1 * MILLISECOND_PER_MINUTE, 1000 * MILLISECOND_PER_SECOND, 200 * MILLISECOND_PER_MINUTE, 100, - "test create table"); - addFieldToCreateStbReqFunc(true, "ts", TSDB_DATA_TYPE_TIMESTAMP, 0, 0); - addFieldToCreateStbReqFunc(true, "c1", TSDB_DATA_TYPE_INT); - addFieldToCreateStbReqFunc(true, "c2", TSDB_DATA_TYPE_UINT); - addFieldToCreateStbReqFunc(true, "c3", TSDB_DATA_TYPE_BIGINT); - addFieldToCreateStbReqFunc(true, "c4", TSDB_DATA_TYPE_UBIGINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c5", TSDB_DATA_TYPE_FLOAT, 0, 0); - addFieldToCreateStbReqFunc(true, "c6", TSDB_DATA_TYPE_DOUBLE, 0, 0); - addFieldToCreateStbReqFunc(true, "c7", TSDB_DATA_TYPE_BINARY, 20 + VARSTR_HEADER_SIZE, 0); - addFieldToCreateStbReqFunc(true, "c8", TSDB_DATA_TYPE_SMALLINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c9", TSDB_DATA_TYPE_USMALLINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c10", TSDB_DATA_TYPE_TINYINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c11", TSDB_DATA_TYPE_UTINYINT, 0, 0); - addFieldToCreateStbReqFunc(true, "c12", TSDB_DATA_TYPE_BOOL, 0, 0); - addFieldToCreateStbReqFunc(true, "c13", TSDB_DATA_TYPE_NCHAR, 30 * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE, 0); - addFieldToCreateStbReqFunc(true, "c14", TSDB_DATA_TYPE_VARCHAR, 50 + VARSTR_HEADER_SIZE, 0); - addFieldToCreateStbReqFunc(false, "a1", TSDB_DATA_TYPE_TIMESTAMP); - addFieldToCreateStbReqFunc(false, "a2", TSDB_DATA_TYPE_INT); - addFieldToCreateStbReqFunc(false, "a3", TSDB_DATA_TYPE_UINT); - addFieldToCreateStbReqFunc(false, "a4", TSDB_DATA_TYPE_BIGINT); - addFieldToCreateStbReqFunc(false, "a5", TSDB_DATA_TYPE_UBIGINT); - addFieldToCreateStbReqFunc(false, "a6", TSDB_DATA_TYPE_FLOAT); - addFieldToCreateStbReqFunc(false, "a7", TSDB_DATA_TYPE_DOUBLE); - addFieldToCreateStbReqFunc(false, "a8", TSDB_DATA_TYPE_BINARY, 20 + VARSTR_HEADER_SIZE); - addFieldToCreateStbReqFunc(false, "a9", TSDB_DATA_TYPE_SMALLINT); - addFieldToCreateStbReqFunc(false, "a10", TSDB_DATA_TYPE_USMALLINT); - addFieldToCreateStbReqFunc(false, "a11", TSDB_DATA_TYPE_TINYINT); - addFieldToCreateStbReqFunc(false, "a12", TSDB_DATA_TYPE_UTINYINT); - addFieldToCreateStbReqFunc(false, "a13", TSDB_DATA_TYPE_BOOL); - addFieldToCreateStbReqFunc(false, "a14", TSDB_DATA_TYPE_NCHAR, 30 * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE); - addFieldToCreateStbReqFunc(false, "a15", TSDB_DATA_TYPE_VARCHAR, 50 + VARSTR_HEADER_SIZE); + setCreateStbReq("rollup_db", "t1", 1, 100 * MILLISECOND_PER_SECOND, 10 * MILLISECOND_PER_MINUTE, 10, + 1 * MILLISECOND_PER_MINUTE, 1000 * MILLISECOND_PER_SECOND, 200 * MILLISECOND_PER_MINUTE, 100, + "test create table"); + addFieldToCreateStbReq(true, "ts", TSDB_DATA_TYPE_TIMESTAMP, 0, 0); + addFieldToCreateStbReq(true, "c1", TSDB_DATA_TYPE_INT); + addFieldToCreateStbReq(true, "c2", TSDB_DATA_TYPE_UINT); + addFieldToCreateStbReq(true, "c3", TSDB_DATA_TYPE_BIGINT); + addFieldToCreateStbReq(true, "c4", TSDB_DATA_TYPE_UBIGINT, 0, 0); + addFieldToCreateStbReq(true, "c5", TSDB_DATA_TYPE_FLOAT, 0, 0); + addFieldToCreateStbReq(true, "c6", TSDB_DATA_TYPE_DOUBLE, 0, 0); + addFieldToCreateStbReq(true, "c7", TSDB_DATA_TYPE_BINARY, 20 + VARSTR_HEADER_SIZE, 0); + addFieldToCreateStbReq(true, "c8", TSDB_DATA_TYPE_SMALLINT, 0, 0); + addFieldToCreateStbReq(true, "c9", TSDB_DATA_TYPE_USMALLINT, 0, 0); + addFieldToCreateStbReq(true, "c10", TSDB_DATA_TYPE_TINYINT, 0, 0); + addFieldToCreateStbReq(true, "c11", TSDB_DATA_TYPE_UTINYINT, 0, 0); + addFieldToCreateStbReq(true, "c12", TSDB_DATA_TYPE_BOOL, 0, 0); + addFieldToCreateStbReq(true, "c13", TSDB_DATA_TYPE_NCHAR, 30 * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE, 0); + addFieldToCreateStbReq(true, "c14", TSDB_DATA_TYPE_VARCHAR, 50 + VARSTR_HEADER_SIZE, 0); + addFieldToCreateStbReq(false, "a1", TSDB_DATA_TYPE_TIMESTAMP); + addFieldToCreateStbReq(false, "a2", TSDB_DATA_TYPE_INT); + addFieldToCreateStbReq(false, "a3", TSDB_DATA_TYPE_UINT); + addFieldToCreateStbReq(false, "a4", TSDB_DATA_TYPE_BIGINT); + addFieldToCreateStbReq(false, "a5", TSDB_DATA_TYPE_UBIGINT); + addFieldToCreateStbReq(false, "a6", TSDB_DATA_TYPE_FLOAT); + addFieldToCreateStbReq(false, "a7", TSDB_DATA_TYPE_DOUBLE); + addFieldToCreateStbReq(false, "a8", TSDB_DATA_TYPE_BINARY, 20 + VARSTR_HEADER_SIZE); + addFieldToCreateStbReq(false, "a9", TSDB_DATA_TYPE_SMALLINT); + addFieldToCreateStbReq(false, "a10", TSDB_DATA_TYPE_USMALLINT); + addFieldToCreateStbReq(false, "a11", TSDB_DATA_TYPE_TINYINT); + addFieldToCreateStbReq(false, "a12", TSDB_DATA_TYPE_UTINYINT); + addFieldToCreateStbReq(false, "a13", TSDB_DATA_TYPE_BOOL); + addFieldToCreateStbReq(false, "a14", TSDB_DATA_TYPE_NCHAR, 30 * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE); + addFieldToCreateStbReq(false, "a15", TSDB_DATA_TYPE_VARCHAR, 50 + VARSTR_HEADER_SIZE); run("CREATE STABLE IF NOT EXISTS rollup_db.t1(" "ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), " - "c8 SMALLINT, c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, " + "c8 SMALLINT, c9 SMALLINT UNSIGNED, c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, " "c13 NCHAR(30), c14 VARCHAR(50)) " "TAGS (a1 TIMESTAMP, a2 INT, a3 INT UNSIGNED, a4 BIGINT, a5 BIGINT UNSIGNED, a6 FLOAT, a7 DOUBLE, " - "a8 BINARY(20), a9 SMALLINT, a10 SMALLINT UNSIGNED COMMENT 'test column comment', a11 TINYINT, " + "a8 BINARY(20), a9 SMALLINT, a10 SMALLINT UNSIGNED, a11 TINYINT, " "a12 TINYINT UNSIGNED, a13 BOOL, a14 NCHAR(30), a15 VARCHAR(50)) " "TTL 100 COMMENT 'test create table' SMA(c1, c2, c3) ROLLUP (MIN) MAX_DELAY 100s,10m WATERMARK 10a,1m " "DELETE_MARK 1000s,200m"); @@ -630,6 +783,20 @@ TEST_F(ParserInitialCTest, createStableSemanticCheck) { TSDB_CODE_PAR_INVALID_TABLE_OPTION); } +/* + * CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] + * INTO stb_name [TAGS (create_definition [, create_definition] ...)] [SUBTABLE (expr)] AS subquery + * + * stream_options: + * stream_option ... + * + * stream_option: { + * TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time] + * | WATERMARK time + * | IGNORE EXPIRED value + * | FILL_HISTORY value + * } + */ TEST_F(ParserInitialCTest, createStream) { useDb("root", "test"); @@ -641,23 +808,27 @@ TEST_F(ParserInitialCTest, createStream) { }; auto setCreateStreamReq = [&](const char* pStream, const char* pSrcDb, const char* pSql, const char* pDstStb, - int8_t igExists = 0, int8_t triggerType = STREAM_TRIGGER_AT_ONCE, int64_t maxDelay = 0, - int64_t watermark = 0, int8_t igExpired = STREAM_DEFAULT_IGNORE_EXPIRED, - int8_t fillHistory = STREAM_DEFAULT_FILL_HISTORY, - int8_t igUpdate = STREAM_DEFAULT_IGNORE_UPDATE) { + int8_t igExists = 0) { snprintf(expect.name, sizeof(expect.name), "0.%s", pStream); snprintf(expect.sourceDB, sizeof(expect.sourceDB), "0.%s", pSrcDb); snprintf(expect.targetStbFullName, sizeof(expect.targetStbFullName), "0.test.%s", pDstStb); expect.igExists = igExists; - expect.sql = strdup(pSql); - expect.triggerType = triggerType; - expect.maxDelay = maxDelay; - expect.watermark = watermark; - expect.fillHistory = fillHistory; - expect.igExpired = igExpired; - expect.igUpdate = igUpdate; + expect.sql = taosStrdup(pSql); }; + auto setStreamOptions = + [&](int8_t createStb = STREAM_CREATE_STABLE_TRUE, int8_t triggerType = STREAM_TRIGGER_WINDOW_CLOSE, + int64_t maxDelay = 0, int64_t watermark = 0, int8_t igExpired = STREAM_DEFAULT_IGNORE_EXPIRED, + int8_t fillHistory = STREAM_DEFAULT_FILL_HISTORY, int8_t igUpdate = STREAM_DEFAULT_IGNORE_UPDATE) { + expect.createStb = createStb; + expect.triggerType = triggerType; + expect.maxDelay = maxDelay; + expect.watermark = watermark; + expect.fillHistory = fillHistory; + expect.igExpired = igExpired; + expect.igUpdate = igUpdate; + }; + auto addTag = [&](const char* pFieldName, uint8_t type, int32_t bytes = 0) { SField field = {0}; strcpy(field.name, pFieldName); @@ -701,21 +872,26 @@ TEST_F(ParserInitialCTest, createStream) { ASSERT_EQ(pField->flags, pExpectField->flags); } } + ASSERT_EQ(req.checkpointFreq, expect.checkpointFreq); + ASSERT_EQ(req.createStb, expect.createStb); ASSERT_EQ(req.igUpdate, expect.igUpdate); tFreeSCMCreateStreamReq(&req); }); - setCreateStreamReq("s1", "test", "create stream s1 into st1 as select count(*) from t1 interval(10s)", "st1"); - run("CREATE STREAM s1 INTO st1 AS SELECT COUNT(*) FROM t1 INTERVAL(10S)"); + setCreateStreamReq("s1", "test", "create stream s1 into st3 as select count(*) from t1 interval(10s)", "st3"); + setStreamOptions(); + run("CREATE STREAM s1 INTO st3 AS SELECT COUNT(*) FROM t1 INTERVAL(10S)"); clearCreateStreamReq(); setCreateStreamReq( "s1", "test", "create stream if not exists s1 trigger max_delay 20s watermark 10s ignore expired 0 fill_history 1 ignore " - "update 1 into st1 as select count(*) from t1 interval(10s)", - "st1", 1, STREAM_TRIGGER_MAX_DELAY, 20 * MILLISECOND_PER_SECOND, 10 * MILLISECOND_PER_SECOND, 0, 1, 1); + "update 1 into st3 as select count(*) from t1 interval(10s)", + "st3", 1); + setStreamOptions(STREAM_CREATE_STABLE_TRUE, STREAM_TRIGGER_MAX_DELAY, 20 * MILLISECOND_PER_SECOND, + 10 * MILLISECOND_PER_SECOND, 0, 1, 1); run("CREATE STREAM IF NOT EXISTS s1 TRIGGER MAX_DELAY 20s WATERMARK 10s IGNORE EXPIRED 0 FILL_HISTORY 1 IGNORE " - "UPDATE 1 INTO st1 AS SELECT COUNT(*) FROM t1 INTERVAL(10S)"); + "UPDATE 1 INTO st3 AS SELECT COUNT(*) FROM t1 INTERVAL(10S)"); clearCreateStreamReq(); setCreateStreamReq("s1", "test", @@ -724,9 +900,19 @@ TEST_F(ParserInitialCTest, createStream) { "st3"); addTag("tname", TSDB_DATA_TYPE_VARCHAR, 10 + VARSTR_HEADER_SIZE); addTag("id", TSDB_DATA_TYPE_INT); + setStreamOptions(); run("CREATE STREAM s1 INTO st3 TAGS(tname VARCHAR(10), id INT) SUBTABLE(CONCAT('new-', tname)) " "AS SELECT _WSTART wstart, COUNT(*) cnt FROM st1 PARTITION BY TBNAME tname, tag1 id INTERVAL(10S)"); clearCreateStreamReq(); + + // st1 already exists + setCreateStreamReq( + "s1", "test", + "create stream s1 into st1 tags(tag2) as select max(c1), c2 from t1 partition by tbname tag2 interval(10s)", + "st1"); + setStreamOptions(STREAM_CREATE_STABLE_FALSE); + run("CREATE STREAM s1 INTO st1 TAGS(tag2) AS SELECT MAX(c1), c2 FROM t1 PARTITION BY TBNAME tag2 INTERVAL(10S)"); + clearCreateStreamReq(); } TEST_F(ParserInitialCTest, createStreamSemanticCheck) { @@ -734,25 +920,123 @@ TEST_F(ParserInitialCTest, createStreamSemanticCheck) { run("CREATE STREAM s1 INTO st1 AS SELECT PERCENTILE(c1, 30) FROM t1 INTERVAL(10S)", TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC); + run("CREATE STREAM s2 INTO st1 AS SELECT ts, to_json('{c1:1}') FROM st1 PARTITION BY TBNAME", + TSDB_CODE_PAR_INVALID_STREAM_QUERY); + run("CREATE STREAM s3 INTO st3 TAGS(tname VARCHAR(10), id INT) SUBTABLE(CONCAT('new-', tbname)) " + "AS SELECT _WSTART wstart, COUNT(*) cnt FROM st1 INTERVAL(10S)", TSDB_CODE_PAR_INVALID_STREAM_QUERY); } +/* + * CREATE TABLE [IF NOT EXISTS] [db_name.]tb_name (create_definition [, create_definitionn] ...) [table_options] + * + * CREATE TABLE create_subtable_clause + * + * CREATE TABLE [IF NOT EXISTS] [db_name.]tb_name (create_definition [, create_definitionn] ...) + * [TAGS (create_definition [, create_definitionn] ...)] + * [table_options] + * + * create_subtable_clause: { + * create_subtable_clause [create_subtable_clause] ... + * | [IF NOT EXISTS] [db_name.]tb_name USING [db_name.]stb_name [(tag_name [, tag_name] ...)] + * TAGS (tag_value [, tag_value] ...) + * } + * + * create_definition: + * col_name column_definition + * + * column_definition: + * type_name [comment 'string_value'] + * + * table_options: + * table_option ... + * + * table_option: { + * COMMENT 'string_value' + * | WATERMARK duration[,duration] + * | MAX_DELAY duration[,duration] + * | ROLLUP(func_name [, func_name] ...) + * | SMA(col_name [, col_name] ...) + * | TTL value + * } + */ TEST_F(ParserInitialCTest, createTable) { useDb("root", "test"); + SVCreateTbBatchReq expect = {0}; + + auto addCreateTbReq = [&](const char* pName, bool ignoreExists = false, int32_t ttl = TSDB_DEFAULT_TABLE_TTL, + const char* pComment = nullptr) { + SVCreateTbReq req = {0}; + req.name = taosStrdup(pName); + if (ignoreExists) { + req.flags |= TD_CREATE_IF_NOT_EXISTS; + } + req.ttl = ttl; + if (nullptr != pComment) { + req.comment = taosStrdup(pComment); + req.commentLen = strlen(pComment); + } + ++expect.nReqs; + if (nullptr == expect.pArray) { + expect.pArray = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SVCreateTbReq)); + } + taosArrayPush(expect.pArray, &req); + }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + return; // todo + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_VNODE_MODIFY_STMT); + SVnodeModifyOpStmt* pStmt = (SVnodeModifyOpStmt*)pQuery->pRoot; + + ASSERT_EQ(pStmt->sqlNodeType, QUERY_NODE_CREATE_TABLE_STMT); + ASSERT_NE(pStmt->pDataBlocks, nullptr); + int32_t numOfBlocks = taosArrayGetSize(pStmt->pDataBlocks); + for (int32_t i = 0; i < numOfBlocks; ++i) { + SVgDataBlocks* pVgData = (SVgDataBlocks*)taosArrayGetP(pStmt->pDataBlocks, i); + void* pBuf = POINTER_SHIFT(pVgData->pData, sizeof(SMsgHead)); + SVCreateTbBatchReq req = {0}; + SDecoder coder = {0}; + tDecoderInit(&coder, (uint8_t*)pBuf, pVgData->size); + ASSERT_EQ(tDecodeSVCreateTbBatchReq(&coder, &req), TSDB_CODE_SUCCESS); + ASSERT_EQ(req.nReqs, expect.nReqs); + for (int32_t j = 0; j < req.nReqs; ++j) { + SVCreateTbReq* pReq = req.pReqs + j; + SVCreateTbReq* pExpect = (SVCreateTbReq*)taosArrayGet(expect.pArray, j); + ASSERT_EQ(pReq->flags, pExpect->flags); + ASSERT_EQ(std::string(pReq->name), std::string(pExpect->name)); + ASSERT_EQ(pReq->uid, pExpect->uid); + ASSERT_EQ(pReq->ctime, pExpect->ctime); + ASSERT_EQ(pReq->ttl, pExpect->ttl); + ASSERT_EQ(pReq->commentLen, pExpect->commentLen); + ASSERT_EQ(std::string(pReq->comment), std::string(pExpect->comment)); + ASSERT_EQ(pReq->type, pExpect->type); + if (TD_NORMAL_TABLE == pExpect->type) { + ASSERT_EQ(pReq->ntb.schemaRow.version, pExpect->ntb.schemaRow.version); + ASSERT_EQ(pReq->ntb.schemaRow.nCols, pExpect->ntb.schemaRow.nCols); + } else if (TD_CHILD_TABLE == pExpect->type) { + ASSERT_EQ(std::string(pReq->ctb.stbName), std::string(pExpect->ctb.stbName)); + ASSERT_EQ(pReq->ctb.tagNum, pExpect->ctb.tagNum); + ASSERT_EQ(pReq->ctb.suid, pExpect->ctb.suid); + } + } + tDecoderClear(&coder); + } + }); + run("CREATE TABLE t1(ts TIMESTAMP, c1 INT)"); run("CREATE TABLE IF NOT EXISTS test.t1(" "ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), " - "c8 SMALLINT, c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, " + "c8 SMALLINT, c9 SMALLINT UNSIGNED, c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, " "c13 NCHAR(30), c15 VARCHAR(50)) " "TTL 100 COMMENT 'test create table' SMA(c1, c2, c3)"); run("CREATE TABLE IF NOT EXISTS rollup_db.t1(" "ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), " - "c8 SMALLINT, c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, " + "c8 SMALLINT, c9 SMALLINT UNSIGNED, c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, " "c13 NCHAR(30), c14 VARCHAR(50)) " "TAGS (a1 TIMESTAMP, a2 INT, a3 INT UNSIGNED, a4 BIGINT, a5 BIGINT UNSIGNED, a6 FLOAT, a7 DOUBLE, a8 BINARY(20), " - "a9 SMALLINT, a10 SMALLINT UNSIGNED COMMENT 'test column comment', a11 TINYINT, a12 TINYINT UNSIGNED, a13 BOOL, " + "a9 SMALLINT, a10 SMALLINT UNSIGNED, a11 TINYINT, a12 TINYINT UNSIGNED, a13 BOOL, " "a14 NCHAR(30), a15 VARCHAR(50)) " "TTL 100 COMMENT 'test create table' SMA(c1, c2, c3) ROLLUP (MIN)"); @@ -763,7 +1047,7 @@ TEST_F(ParserInitialCTest, createTable) { "IF NOT EXISTS test.t2 USING test.st1 (tag1, tag2) TAGS(2, 'abc') " "IF NOT EXISTS test.t3 USING test.st1 (tag1, tag2) TAGS(3, 'abc') "); - // run("CREATE TABLE IF NOT EXISTS t1 USING st1 TAGS(1, 'wxy', NOW + 1S)"); + run("CREATE TABLE IF NOT EXISTS t1 USING st1 TAGS(1, 'wxy', NOW + 1S)"); } TEST_F(ParserInitialCTest, createTableSemanticCheck) { @@ -781,6 +1065,11 @@ TEST_F(ParserInitialCTest, createTableSemanticCheck) { run(sql, TSDB_CODE_PAR_TOO_MANY_COLUMNS); } +/* + * CREATE TOPIC [IF NOT EXISTS] topic_name AS subquery + * + * CREATE TOPIC [IF NOT EXISTS] topic_name [WITH META] AS {DATABASE db_name | STABLE stb_name } + */ TEST_F(ParserInitialCTest, createTopic) { useDb("root", "test"); @@ -788,8 +1077,8 @@ TEST_F(ParserInitialCTest, createTopic) { auto clearCreateTopicReq = [&]() { memset(&expect, 0, sizeof(SCMCreateTopicReq)); }; - auto setCreateTopicReqFunc = [&](const char* pTopicName, int8_t igExists, const char* pSql, const char* pAst, - const char* pDbName = nullptr, const char* pTbname = nullptr, int8_t withMeta = 0) { + auto setCreateTopicReq = [&](const char* pTopicName, int8_t igExists, const char* pSql, const char* pAst, + const char* pDbName = nullptr, const char* pTbname = nullptr, int8_t withMeta = 0) { snprintf(expect.name, sizeof(expect.name), "0.%s", pTopicName); expect.igExists = igExists; expect.sql = (char*)pSql; @@ -833,31 +1122,34 @@ TEST_F(ParserInitialCTest, createTopic) { tFreeSCMCreateTopicReq(&req); }); - setCreateTopicReqFunc("tp1", 0, "create topic tp1 as select * from t1", "ast"); + setCreateTopicReq("tp1", 0, "create topic tp1 as select * from t1", "ast"); run("CREATE TOPIC tp1 AS SELECT * FROM t1"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 1, "create topic if not exists tp1 as select ts, ceil(c1) from t1", "ast"); + setCreateTopicReq("tp1", 1, "create topic if not exists tp1 as select ts, ceil(c1) from t1", "ast"); run("CREATE TOPIC IF NOT EXISTS tp1 AS SELECT ts, CEIL(c1) FROM t1"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 0, "create topic tp1 as database test", nullptr, "test"); + setCreateTopicReq("tp1", 0, "create topic tp1 as database test", nullptr, "test"); run("CREATE TOPIC tp1 AS DATABASE test"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 0, "create topic tp1 with meta as database test", nullptr, "test", nullptr, 1); + setCreateTopicReq("tp1", 0, "create topic tp1 with meta as database test", nullptr, "test", nullptr, 1); run("CREATE TOPIC tp1 WITH META AS DATABASE test"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 1, "create topic if not exists tp1 as stable st1", nullptr, "test", "st1"); + setCreateTopicReq("tp1", 1, "create topic if not exists tp1 as stable st1", nullptr, "test", "st1"); run("CREATE TOPIC IF NOT EXISTS tp1 AS STABLE st1"); clearCreateTopicReq(); - setCreateTopicReqFunc("tp1", 1, "create topic if not exists tp1 with meta as stable st1", nullptr, "test", "st1", 1); + setCreateTopicReq("tp1", 1, "create topic if not exists tp1 with meta as stable st1", nullptr, "test", "st1", 1); run("CREATE TOPIC IF NOT EXISTS tp1 WITH META AS STABLE st1"); clearCreateTopicReq(); } +/* + * CREATE USER use_name PASS password [SYSINFO value] + */ TEST_F(ParserInitialCTest, createUser) { useDb("root", "test"); diff --git a/source/libs/parser/test/parInitialDTest.cpp b/source/libs/parser/test/parInitialDTest.cpp index 3ded71242b961ceaf12abbdff44272c7fa6cb32c..203156ec883427f943c847a24ea2ac734c645f2a 100644 --- a/source/libs/parser/test/parInitialDTest.cpp +++ b/source/libs/parser/test/parInitialDTest.cpp @@ -99,7 +99,7 @@ TEST_F(ParserInitialDTest, dropDnode) { expect.force = force; }; - auto setDropDnodeReqByEndpoint = [&](const char* pFqdn, int32_t port, bool force = false) { + auto setDropDnodeReqByEndpoint = [&](const char* pFqdn, int32_t port = tsServerPort, bool force = false) { strcpy(expect.fqdn, pFqdn); expect.port = port; expect.force = force; @@ -131,6 +131,14 @@ TEST_F(ParserInitialDTest, dropDnode) { setDropDnodeReqByEndpoint("host2", 8030, true); run("DROP DNODE 'host2:8030' FORCE"); clearDropDnodeReq(); + + setDropDnodeReqByEndpoint("host1"); + run("DROP DNODE host1"); + clearDropDnodeReq(); + + setDropDnodeReqByEndpoint("host2", tsServerPort, true); + run("DROP DNODE host2 FORCE"); + clearDropDnodeReq(); } // todo DROP function @@ -174,7 +182,21 @@ TEST_F(ParserInitialDTest, dropMnode) { TEST_F(ParserInitialDTest, dropQnode) { useDb("root", "test"); - run("DROP qnode on dnode 1"); + SMDropQnodeReq expect = {0}; + + auto setDropQnodeReq = [&](int32_t dnodeId) { expect.dnodeId = dnodeId; }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_DROP_QNODE_STMT); + SMDropQnodeReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == + tDeserializeSCreateDropMQSNodeReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); + + ASSERT_EQ(req.dnodeId, expect.dnodeId); + }); + + setDropQnodeReq(1); + run("DROP QNODE ON DNODE 1"); } TEST_F(ParserInitialDTest, dropSnode) { @@ -223,6 +245,7 @@ TEST_F(ParserInitialDTest, dropTable) { useDb("root", "test"); run("DROP TABLE t1"); + run("DROP TABLE t1, st1s1, st1s2"); } TEST_F(ParserInitialDTest, dropTopic) { @@ -237,7 +260,20 @@ TEST_F(ParserInitialDTest, dropUser) { login("root"); useDb("root", "test"); - run("DROP user wxy"); + SDropUserReq expect = {0}; + + auto setDropUserReq = [&](const char* pUser) { sprintf(expect.user, "%s", pUser); }; + + setCheckDdlFunc([&](const SQuery* pQuery, ParserStage stage) { + ASSERT_EQ(nodeType(pQuery->pRoot), QUERY_NODE_DROP_USER_STMT); + SDropUserReq req = {0}; + ASSERT_TRUE(TSDB_CODE_SUCCESS == tDeserializeSDropUserReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req)); + + ASSERT_EQ(std::string(req.user), std::string(expect.user)); + }); + + setDropUserReq("wxy"); + run("DROP USER wxy"); } } // namespace ParserTest diff --git a/source/libs/parser/test/parSelectTest.cpp b/source/libs/parser/test/parSelectTest.cpp index fcd8dd1f2635040f7f4b7e59f07302246f0a7630..c60257cc228d72c48b258e86e02936856c320753 100644 --- a/source/libs/parser/test/parSelectTest.cpp +++ b/source/libs/parser/test/parSelectTest.cpp @@ -286,7 +286,7 @@ TEST_F(ParserSelectTest, interval) { TEST_F(ParserSelectTest, intervalSemanticCheck) { useDb("root", "test"); - run("SELECT c1 FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN); + run("SELECT c1 FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_INVALID_OPTR_USAGE); run("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 3 INTERVAL(1d) FILL(NEXT)", TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE); run("SELECT HISTOGRAM(c1, 'log_bin', '{\"start\": -33,\"factor\": 55,\"count\": 5,\"infinity\": false}', 1) FROM t1 " "WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59' INTERVAL(10s) FILL(NULL)", @@ -459,6 +459,8 @@ TEST_F(ParserSelectTest, joinSemanticCheck) { run("SELECT * FROM (SELECT tag1, SUM(c1) s FROM st1 GROUP BY tag1) t1, st1 t2 where t1.tag1 = t2.tag1", TSDB_CODE_PAR_NOT_SUPPORT_JOIN); + + run("SELECT count(*) FROM t1 a join t1 b on a.ts=b.ts where a.ts=b.ts"); } } // namespace ParserTest diff --git a/source/libs/parser/test/parTestMain.cpp b/source/libs/parser/test/parTestMain.cpp index de2ce554593749ff420cc13312c84414d0e99f73..8d13d7cf0e75bd5672ed0be1dc096fbb7a4868ea 100644 --- a/source/libs/parser/test/parTestMain.cpp +++ b/source/libs/parser/test/parTestMain.cpp @@ -86,6 +86,7 @@ static void parseArg(int argc, char* argv[]) { {"dump", no_argument, NULL, 'd'}, {"async", required_argument, NULL, 'a'}, {"skipSql", required_argument, NULL, 's'}, + {"limitSql", required_argument, NULL, 'i'}, {"log", required_argument, NULL, 'l'}, {0, 0, 0, 0} }; @@ -101,6 +102,9 @@ static void parseArg(int argc, char* argv[]) { case 's': setSkipSqlNum(optarg); break; + case 'i': + setLimitSqlNum(optarg); + break; case 'l': setLogLevel(optarg); break; diff --git a/source/libs/parser/test/parTestUtil.cpp b/source/libs/parser/test/parTestUtil.cpp index dbae302e426fb0c842c175ae17b71a1f1767e65d..dfe9fcf96e74175484090d9bbf2b8bfc36ccf53b 100644 --- a/source/libs/parser/test/parTestUtil.cpp +++ b/source/libs/parser/test/parTestUtil.cpp @@ -49,9 +49,11 @@ bool g_dump = false; bool g_testAsyncApis = true; int32_t g_logLevel = 131; int32_t g_skipSql = 0; +int32_t g_limitSql = 0; -void setAsyncFlag(const char* pFlag) { g_testAsyncApis = stoi(pFlag) > 0 ? true : false; } -void setSkipSqlNum(const char* pNum) { g_skipSql = stoi(pNum); } +void setAsyncFlag(const char* pArg) { g_testAsyncApis = stoi(pArg) > 0 ? true : false; } +void setSkipSqlNum(const char* pArg) { g_skipSql = stoi(pArg); } +void setLimitSqlNum(const char* pArg) { g_limitSql = stoi(pArg); } struct TerminateFlag : public exception { const char* what() const throw() { return "success and terminate"; } @@ -63,22 +65,28 @@ int32_t getLogLevel() { return g_logLevel; } class ParserTestBaseImpl { public: - ParserTestBaseImpl(ParserTestBase* pBase) : pBase_(pBase), sqlNo_(0) {} + ParserTestBaseImpl(ParserTestBase* pBase) : pBase_(pBase), sqlNo_(0), sqlNum_(0) { + caseEnv_.numOfSkipSql_ = g_skipSql; + caseEnv_.numOfLimitSql_ = g_limitSql; + } void login(const std::string& user) { caseEnv_.user_ = user; } void useDb(const string& acctId, const string& db) { caseEnv_.acctId_ = acctId; caseEnv_.db_ = db; - caseEnv_.nsql_ = g_skipSql; } void run(const string& sql, int32_t expect, ParserStage checkStage) { ++sqlNo_; - if (caseEnv_.nsql_ > 0) { - --(caseEnv_.nsql_); + if (caseEnv_.numOfSkipSql_ > 0) { + --(caseEnv_.numOfSkipSql_); + return; + } + if (caseEnv_.numOfLimitSql_ > 0 && caseEnv_.numOfLimitSql_ == sqlNum_) { return; } + ++sqlNum_; runInternalFuncs(sql, expect, checkStage); runApis(sql, expect, checkStage); @@ -94,9 +102,10 @@ class ParserTestBaseImpl { string acctId_; string user_; string db_; - int32_t nsql_; + int32_t numOfSkipSql_; + int32_t numOfLimitSql_; - caseEnv() : user_("wangxiaoyu"), nsql_(0) {} + caseEnv() : user_("wangxiaoyu"), numOfSkipSql_(0) {} }; struct stmtEnv { @@ -532,6 +541,7 @@ class ParserTestBaseImpl { stmtRes res_; ParserTestBase* pBase_; int32_t sqlNo_; + int32_t sqlNum_; }; ParserTestBase::ParserTestBase() : impl_(new ParserTestBaseImpl(this)) {} diff --git a/source/libs/parser/test/parTestUtil.h b/source/libs/parser/test/parTestUtil.h index 3e5fab592729a9d98010900be1ef6dbbedc0d07f..5d9680c477d90e0268e3383ff089013006735a8d 100644 --- a/source/libs/parser/test/parTestUtil.h +++ b/source/libs/parser/test/parTestUtil.h @@ -65,10 +65,11 @@ class ParserDdlTest : public ParserTestBase { extern bool g_dump; -extern void setAsyncFlag(const char* pFlag); -extern void setLogLevel(const char* pLogLevel); +extern void setAsyncFlag(const char* pArg); +extern void setLogLevel(const char* pArg); extern int32_t getLogLevel(); -extern void setSkipSqlNum(const char* pNum); +extern void setSkipSqlNum(const char* pArg); +extern void setLimitSqlNum(const char* pArg); } // namespace ParserTest diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index bfde50761ae3995a56af5719c2953eb90cb48d74..b9ea5ba0cd4d43d0234410213373e13f7a236734 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -100,6 +100,7 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) { SExprNode* pToBeRewrittenExpr = (SExprNode*)(*pNode); pCol->node.resType = pToBeRewrittenExpr->resType; strcpy(pCol->node.aliasName, pToBeRewrittenExpr->aliasName); + strcpy(pCol->node.userAlias, ((SExprNode*)pExpr)->userAlias); strcpy(pCol->colName, ((SExprNode*)pExpr)->aliasName); if (QUERY_NODE_FUNCTION == nodeType(pExpr)) { setColumnInfo((SFunctionNode*)pExpr, pCol); @@ -381,6 +382,20 @@ static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect code = addDefaultScanCol(pRealTable->pMeta, &pScan->pScanCols); } + if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pTags && NULL == pSelect->pPartitionByList) { + pScan->pTags = nodesCloneList(pSelect->pTags); + if (NULL == pScan->pTags) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + } + + if (TSDB_CODE_SUCCESS == code && NULL != pSelect->pSubtable && NULL == pSelect->pPartitionByList) { + pScan->pSubtable = nodesCloneNode(pSelect->pSubtable); + if (NULL == pScan->pSubtable) { + code = TSDB_CODE_OUT_OF_MEMORY; + } + } + // set output if (TSDB_CODE_SUCCESS == code) { code = createColumnByRewriteExprs(pScan->pScanCols, &pScan->node.pTargets); @@ -823,6 +838,29 @@ static int32_t createWindowLogicNodeByInterval(SLogicPlanContext* pCxt, SInterva return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode); } +static int32_t createWindowLogicNodeByEvent(SLogicPlanContext* pCxt, SEventWindowNode* pEvent, SSelectStmt* pSelect, + SLogicNode** pLogicNode) { + SWindowLogicNode* pWindow = (SWindowLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_WINDOW); + if (NULL == pWindow) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + pWindow->winType = WINDOW_TYPE_EVENT; + pWindow->node.groupAction = getGroupAction(pCxt, pSelect); + pWindow->node.requireDataOrder = + pCxt->pPlanCxt->streamQuery ? DATA_ORDER_LEVEL_IN_BLOCK : getRequireDataOrder(true, pSelect); + pWindow->node.resultDataOrder = + pCxt->pPlanCxt->streamQuery ? DATA_ORDER_LEVEL_GLOBAL : pWindow->node.requireDataOrder; + pWindow->pStartCond = nodesCloneNode(pEvent->pStartCond); + pWindow->pEndCond = nodesCloneNode(pEvent->pEndCond); + pWindow->pTspk = nodesCloneNode(pEvent->pCol); + if (NULL == pWindow->pStartCond || NULL == pWindow->pEndCond || NULL == pWindow->pTspk) { + nodesDestroyNode((SNode*)pWindow); + return TSDB_CODE_OUT_OF_MEMORY; + } + return createWindowLogicNodeFinalize(pCxt, pSelect, pWindow, pLogicNode); +} + static int32_t createWindowLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) { if (NULL == pSelect->pWindow) { return TSDB_CODE_SUCCESS; @@ -835,6 +873,8 @@ static int32_t createWindowLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSele return createWindowLogicNodeBySession(pCxt, (SSessionWindowNode*)pSelect->pWindow, pSelect, pLogicNode); case QUERY_NODE_INTERVAL_WINDOW: return createWindowLogicNodeByInterval(pCxt, (SIntervalWindowNode*)pSelect->pWindow, pSelect, pLogicNode); + case QUERY_NODE_EVENT_WINDOW: + return createWindowLogicNodeByEvent(pCxt, (SEventWindowNode*)pSelect->pWindow, pSelect, pLogicNode); default: break; } @@ -1371,7 +1411,7 @@ static int32_t createSetOperatorLogicNode(SLogicPlanContext* pCxt, SSetOperator* static int32_t getMsgType(ENodeType sqlType) { switch (sqlType) { case QUERY_NODE_CREATE_TABLE_STMT: - case QUERY_NODE_CREATE_MULTI_TABLE_STMT: + case QUERY_NODE_CREATE_MULTI_TABLES_STMT: return TDMT_VND_CREATE_TABLE; case QUERY_NODE_DROP_TABLE_STMT: return TDMT_VND_DROP_TABLE; @@ -1385,7 +1425,7 @@ static int32_t getMsgType(ENodeType sqlType) { return TDMT_VND_SUBMIT; } -static int32_t createVnodeModifLogicNode(SLogicPlanContext* pCxt, SVnodeModifOpStmt* pStmt, SLogicNode** pLogicNode) { +static int32_t createVnodeModifLogicNode(SLogicPlanContext* pCxt, SVnodeModifyOpStmt* pStmt, SLogicNode** pLogicNode) { SVnodeModifyLogicNode* pModif = (SVnodeModifyLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY); if (NULL == pModif) { return TSDB_CODE_OUT_OF_MEMORY; @@ -1404,7 +1444,7 @@ static int32_t createDeleteRootLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* p static int32_t createDeleteScanLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* pDelete, SLogicNode** pLogicNode) { SScanLogicNode* pScan = NULL; - int32_t code = makeScanLogicNode(pCxt, (SRealTableNode*)pDelete->pFromTable, false, (SLogicNode**)&pScan); + int32_t code = makeScanLogicNode(pCxt, (SRealTableNode*)pDelete->pFromTable, false, (SLogicNode**)&pScan); // set columns to scan if (TSDB_CODE_SUCCESS == code) { @@ -1569,8 +1609,8 @@ static int32_t createQueryLogicNode(SLogicPlanContext* pCxt, SNode* pStmt, SLogi switch (nodeType(pStmt)) { case QUERY_NODE_SELECT_STMT: return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt, pLogicNode); - case QUERY_NODE_VNODE_MODIF_STMT: - return createVnodeModifLogicNode(pCxt, (SVnodeModifOpStmt*)pStmt, pLogicNode); + case QUERY_NODE_VNODE_MODIFY_STMT: + return createVnodeModifLogicNode(pCxt, (SVnodeModifyOpStmt*)pStmt, pLogicNode); case QUERY_NODE_EXPLAIN_STMT: return createQueryLogicNode(pCxt, ((SExplainStmt*)pStmt)->pQuery, pLogicNode); case QUERY_NODE_SET_OPERATOR: diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index 27c155566680f0e82a37b2a1914eafc055b51cb4..f1ad82452167950201b5c26f8cea0851160830a3 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -740,6 +740,88 @@ static int32_t pushDownCondOptJoinExtractMergeCond(SOptimizeContext* pCxt, SJoin return code; } +static bool pushDownCondOptIsTag(SNode* pNode, SNodeList* pTableCols) { + if (QUERY_NODE_COLUMN != nodeType(pNode)) { + return false; + } + SColumnNode* pCol = (SColumnNode*)pNode; + if (COLUMN_TYPE_TAG != pCol->colType) { + return false; + } + return pushDownCondOptBelongThisTable(pNode, pTableCols); +} + +static bool pushDownCondOptIsTagEqualCond(SJoinLogicNode* pJoin, SNode* pCond) { + if (QUERY_NODE_OPERATOR != nodeType(pCond)) { + return false; + } + SOperatorNode* pOper = (SOperatorNode*)pCond; + if (OP_TYPE_EQUAL != pOper->opType) { + return false; + } + if (QUERY_NODE_COLUMN != nodeType(pOper->pLeft) || QUERY_NODE_COLUMN != nodeType(pOper->pRight)) { + return false; + } + SColumnNode* pLeft = (SColumnNode*)(pOper->pLeft); + SColumnNode* pRight = (SColumnNode*)(pOper->pRight); + //TODO: add cast to operator and remove this restriction of optimization + if (pLeft->node.resType.type != pRight->node.resType.type || pLeft->node.resType.bytes != pRight->node.resType.bytes) { + return false; + } + SNodeList* pLeftCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0))->pTargets; + SNodeList* pRightCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1))->pTargets; + if (pushDownCondOptIsTag(pOper->pLeft, pLeftCols)) { + return pushDownCondOptIsTag(pOper->pRight, pRightCols); + } else if (pushDownCondOptIsTag(pOper->pLeft, pRightCols)) { + return pushDownCondOptIsTag(pOper->pRight, pLeftCols); + } + return false; +} + +static int32_t pushDownCondOptJoinExtractTagEqualLogicCond(SJoinLogicNode* pJoin) { + SLogicConditionNode* pLogicCond = (SLogicConditionNode*)(pJoin->pOnConditions); + + int32_t code = TSDB_CODE_SUCCESS; + SNodeList* pTagEqualConds = NULL; + SNode* pCond = NULL; + FOREACH(pCond, pLogicCond->pParameterList) { + if (pushDownCondOptIsTagEqualCond(pJoin, pCond)) { + code = nodesListMakeAppend(&pTagEqualConds, nodesCloneNode(pCond)); + } + } + + SNode* pTempTagEqCond = NULL; + if (TSDB_CODE_SUCCESS == code) { + code = nodesMergeConds(&pTempTagEqCond, &pTagEqualConds); + } + + if (TSDB_CODE_SUCCESS == code) { + pJoin->pTagEqualConditions = pTempTagEqCond; + return TSDB_CODE_SUCCESS; + } else { + nodesDestroyList(pTagEqualConds); + return TSDB_CODE_PLAN_INTERNAL_ERROR; + } + return TSDB_CODE_SUCCESS; +} + +static int32_t pushDownCondOptJoinExtractTagEqualCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) { + if (NULL == pJoin->pOnConditions) { + pJoin->pTagEqualConditions = NULL; + return TSDB_CODE_SUCCESS; + } + if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->pOnConditions) && + LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)(pJoin->pOnConditions))->condType) { + return pushDownCondOptJoinExtractTagEqualLogicCond(pJoin); + } + + if (pushDownCondOptIsTagEqualCond(pJoin, pJoin->pOnConditions)) { + pJoin->pTagEqualConditions = nodesCloneNode(pJoin->pOnConditions); + } + + return TSDB_CODE_SUCCESS; +} + static int32_t pushDownCondOptDealJoin(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) { if (OPTIMIZE_FLAG_TEST_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE)) { return TSDB_CODE_SUCCESS; @@ -774,6 +856,10 @@ static int32_t pushDownCondOptDealJoin(SOptimizeContext* pCxt, SJoinLogicNode* p code = pushDownCondOptJoinExtractMergeCond(pCxt, pJoin); } + if (TSDB_CODE_SUCCESS == code) { + code = pushDownCondOptJoinExtractTagEqualCond(pCxt, pJoin); + } + if (TSDB_CODE_SUCCESS == code) { OPTIMIZE_FLAG_SET_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE); pCxt->optimized = true; @@ -1079,11 +1165,23 @@ static bool sortPriKeyOptMayBeOptimized(SLogicNode* pNode) { if (!sortPriKeyOptIsPriKeyOrderBy(pSort->pSortKeys) || 1 != LIST_LENGTH(pSort->node.pChildren)) { return false; } + SNode* pChild; + FOREACH(pChild, pSort->node.pChildren) { + SLogicNode* pSortDescendent = optFindPossibleNode((SLogicNode*)pChild, sortPriKeyOptMayBeOptimized); + if (pSortDescendent != NULL) { + return false; + } + } return true; } static int32_t sortPriKeyOptGetSequencingNodesImpl(SLogicNode* pNode, bool groupSort, bool* pNotOptimize, SNodeList** pSequencingNodes) { + if (NULL != pNode->pLimit || NULL != pNode->pSlimit) { + *pNotOptimize = false; + return TSDB_CODE_SUCCESS; + } + switch (nodeType(pNode)) { case QUERY_NODE_LOGIC_PLAN_SCAN: { SScanLogicNode* pScan = (SScanLogicNode*)pNode; @@ -1280,18 +1378,14 @@ static int32_t smaIndexOptFindSmaFunc(SNode* pQueryFunc, SNodeList* pSmaFuncs) { return -1; } -static int32_t smaIndexOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNodeList* pSmaFuncs, SNodeList** pOutput, - int32_t* pWStrartIndex) { +static int32_t smaIndexOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNodeList* pSmaFuncs, + SNodeList** pOutput) { SNodeList* pCols = NULL; SNode* pFunc = NULL; int32_t code = TSDB_CODE_SUCCESS; int32_t index = 0; int32_t smaFuncIndex = -1; - *pWStrartIndex = -1; FOREACH(pFunc, pFuncs) { - if (FUNCTION_TYPE_WSTART == ((SFunctionNode*)pFunc)->funcType) { - *pWStrartIndex = index; - } smaFuncIndex = smaIndexOptFindSmaFunc(pFunc, pSmaFuncs); if (smaFuncIndex < 0) { break; @@ -1313,8 +1407,7 @@ static int32_t smaIndexOptCreateSmaCols(SNodeList* pFuncs, uint64_t tableId, SNo return code; } -static int32_t smaIndexOptCouldApplyIndex(SScanLogicNode* pScan, STableIndexInfo* pIndex, SNodeList** pCols, - int32_t* pWStrartIndex) { +static int32_t smaIndexOptCouldApplyIndex(SScanLogicNode* pScan, STableIndexInfo* pIndex, SNodeList** pCols) { SWindowLogicNode* pWindow = (SWindowLogicNode*)pScan->node.pParent; if (!smaIndexOptEqualInterval(pScan, pWindow, pIndex)) { return TSDB_CODE_SUCCESS; @@ -1322,36 +1415,34 @@ static int32_t smaIndexOptCouldApplyIndex(SScanLogicNode* pScan, STableIndexInfo SNodeList* pSmaFuncs = NULL; int32_t code = nodesStringToList(pIndex->expr, &pSmaFuncs); if (TSDB_CODE_SUCCESS == code) { - code = smaIndexOptCreateSmaCols(pWindow->pFuncs, pIndex->dstTbUid, pSmaFuncs, pCols, pWStrartIndex); + code = smaIndexOptCreateSmaCols(pWindow->pFuncs, pIndex->dstTbUid, pSmaFuncs, pCols); } nodesDestroyList(pSmaFuncs); return code; } static int32_t smaIndexOptApplyIndex(SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan, STableIndexInfo* pIndex, - SNodeList* pSmaCols, int32_t wstrartIndex) { + SNodeList* pSmaCols) { SLogicNode* pSmaScan = NULL; int32_t code = smaIndexOptCreateSmaScan(pScan, pIndex, pSmaCols, &pSmaScan); if (TSDB_CODE_SUCCESS == code) { code = replaceLogicNode(pLogicSubplan, pScan->node.pParent, pSmaScan); } + if (TSDB_CODE_SUCCESS == code) { + nodesDestroyNode((SNode*)pScan->node.pParent); + } return code; } -static void smaIndexOptDestroySmaIndex(void* p) { taosMemoryFree(((STableIndexInfo*)p)->expr); } - static int32_t smaIndexOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan, SScanLogicNode* pScan) { int32_t code = TSDB_CODE_SUCCESS; int32_t nindexes = taosArrayGetSize(pScan->pSmaIndexes); for (int32_t i = 0; i < nindexes; ++i) { STableIndexInfo* pIndex = taosArrayGet(pScan->pSmaIndexes, i); SNodeList* pSmaCols = NULL; - int32_t wstrartIndex = -1; - code = smaIndexOptCouldApplyIndex(pScan, pIndex, &pSmaCols, &wstrartIndex); + code = smaIndexOptCouldApplyIndex(pScan, pIndex, &pSmaCols); if (TSDB_CODE_SUCCESS == code && NULL != pSmaCols) { - code = smaIndexOptApplyIndex(pLogicSubplan, pScan, pIndex, pSmaCols, wstrartIndex); - taosArrayDestroyEx(pScan->pSmaIndexes, smaIndexOptDestroySmaIndex); - pScan->pSmaIndexes = NULL; + code = smaIndexOptApplyIndex(pLogicSubplan, pScan, pIndex, pSmaCols); pCxt->optimized = true; break; } @@ -2286,7 +2377,7 @@ static int32_t lastRowScanOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogic if (NULL != cxt.pLastCols) { cxt.doAgg = false; lastRowScanOptSetLastTargets(pScan->pScanCols, cxt.pLastCols); - nodesWalkExprs(pScan->pScanPseudoCols, lastRowScanOptSetColDataType, &cxt); + NODES_DESTORY_LIST(pScan->pScanPseudoCols); lastRowScanOptSetLastTargets(pScan->node.pTargets, cxt.pLastCols); nodesClearList(cxt.pLastCols); } @@ -2521,7 +2612,7 @@ static bool tbCntScanOptIsEligibleAggFuncs(SNodeList* pAggFuncs) { return false; } } - return true; + return LIST_LENGTH(pAggFuncs) > 0; } static bool tbCntScanOptIsEligibleAgg(SAggLogicNode* pAgg) { @@ -2589,7 +2680,9 @@ static bool tbCntScanOptIsEligibleConds(STbCntScanOptInfo* pInfo, SNode* pCondit if (NULL == pConditions) { return true; } - + if (LIST_LENGTH(pInfo->pAgg->pGroupKeys) != 0) { + return false; + } if (QUERY_NODE_LOGIC_CONDITION == nodeType(pConditions)) { return tbCntScanOptIsEligibleLogicCond(pInfo, (SLogicConditionNode*)pConditions); } diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c index f016ca165b8c26f851a27d68e24f27004c21ac61..e07c6ebcfef99773c82030c75bb77d1f2d0545c9 100644 --- a/source/libs/planner/src/planPhysiCreater.c +++ b/source/libs/planner/src/planPhysiCreater.c @@ -610,7 +610,8 @@ static int32_t createSystemTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pScan->accountId = pCxt->pPlanCxt->acctId; pScan->sysInfo = pCxt->pPlanCxt->sysInfo; if (0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_TABLES) || - 0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_TAGS)) { + 0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_TAGS) || + 0 == strcmp(pScanLogicNode->tableName.tname, TSDB_INS_TABLE_COLS)) { vgroupInfoToNodeAddr(pScanLogicNode->pVgroupList->vgroups, &pSubplan->execNode); } else { pSubplan->execNode.nodeId = MNODE_HANDLE; @@ -704,6 +705,9 @@ static int32_t createJoinPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren pJoinLogicNode->pOnConditions, &pJoin->pOnConditions); } + if (TSDB_CODE_SUCCESS == code && NULL != pJoinLogicNode->pTagEqualConditions) { + code = setNodeSlotId(pCxt, pLeftDesc->dataBlockId, pRightDesc->dataBlockId, pJoinLogicNode->pTagEqualConditions, &pJoin->pTagEqualCondtions); + } if (TSDB_CODE_SUCCESS == code) { code = setConditionsSlotId(pCxt, (const SLogicNode*)pJoinLogicNode, (SPhysiNode*)pJoin); } @@ -1088,9 +1092,15 @@ static int32_t doCreateExchangePhysiNode(SPhysiPlanContext* pCxt, SExchangeLogic pExchange->srcStartGroupId = pExchangeLogicNode->srcStartGroupId; pExchange->srcEndGroupId = pExchangeLogicNode->srcEndGroupId; pExchange->seqRecvData = pExchangeLogicNode->seqRecvData; - *pPhyNode = (SPhysiNode*)pExchange; - return TSDB_CODE_SUCCESS; + int32_t code = setConditionsSlotId(pCxt, (const SLogicNode*)pExchangeLogicNode, (SPhysiNode*)pExchange); + if (TSDB_CODE_SUCCESS == code) { + *pPhyNode = (SPhysiNode*)pExchange; + } else { + nodesDestroyNode((SNode*)pExchange); + } + + return code; } static int32_t createStreamScanPhysiNodeByExchange(SPhysiPlanContext* pCxt, SExchangeLogicNode* pExchangeLogicNode, @@ -1118,6 +1128,9 @@ static int32_t createStreamScanPhysiNodeByExchange(SPhysiPlanContext* pCxt, SExc if (TSDB_CODE_SUCCESS == code) { code = addDataBlockSlots(pCxt, pScan->pScanCols, pScan->node.pOutputDataBlockDesc); } + if (TSDB_CODE_SUCCESS == code) { + code = setConditionsSlotId(pCxt, (const SLogicNode*)pExchangeLogicNode, (SPhysiNode*)pScan); + } if (TSDB_CODE_SUCCESS == code) { *pPhyNode = (SPhysiNode*)pScan; @@ -1299,6 +1312,33 @@ static int32_t createStateWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pC return code; } +static int32_t createEventWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, + SWindowLogicNode* pWindowLogicNode, SPhysiNode** pPhyNode) { + SEventWinodwPhysiNode* pEvent = (SEventWinodwPhysiNode*)makePhysiNode( + pCxt, (SLogicNode*)pWindowLogicNode, + (pCxt->pPlanCxt->streamQuery ? QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT : QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT)); + if (NULL == pEvent) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + SDataBlockDescNode* pChildTupe = (((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc); + int32_t code = setNodeSlotId(pCxt, pChildTupe->dataBlockId, -1, pWindowLogicNode->pStartCond, &pEvent->pStartCond); + if (TSDB_CODE_SUCCESS == code) { + code = setNodeSlotId(pCxt, pChildTupe->dataBlockId, -1, pWindowLogicNode->pEndCond, &pEvent->pEndCond); + } + if (TSDB_CODE_SUCCESS == code) { + code = createWindowPhysiNodeFinalize(pCxt, pChildren, &pEvent->window, pWindowLogicNode); + } + + if (TSDB_CODE_SUCCESS == code) { + *pPhyNode = (SPhysiNode*)pEvent; + } else { + nodesDestroyNode((SNode*)pEvent); + } + + return code; +} + static int32_t createWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SWindowLogicNode* pWindowLogicNode, SPhysiNode** pPhyNode) { switch (pWindowLogicNode->winType) { @@ -1308,6 +1348,8 @@ static int32_t createWindowPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildr return createSessionWindowPhysiNode(pCxt, pChildren, pWindowLogicNode, pPhyNode); case WINDOW_TYPE_STATE: return createStateWindowPhysiNode(pCxt, pChildren, pWindowLogicNode, pPhyNode); + case WINDOW_TYPE_EVENT: + return createEventWindowPhysiNode(pCxt, pChildren, pWindowLogicNode, pPhyNode); default: break; } @@ -1604,6 +1646,9 @@ static int32_t createPhysiNode(SPhysiPlanContext* pCxt, SLogicNode* pLogicNode, if (TSDB_CODE_SUCCESS == code) { code = nodesListStrictAppend(pChildren, (SNode*)pChild); } + if (TSDB_CODE_SUCCESS != code) { + break; + } } if (TSDB_CODE_SUCCESS == code) { @@ -1689,6 +1734,7 @@ static int32_t createQueryInserter(SPhysiPlanContext* pCxt, SVnodeModifyLogicNod strcpy(pInserter->tableName, pModify->tableName); pInserter->vgId = pModify->pVgroupList->vgroups[0].vgId; pInserter->epSet = pModify->pVgroupList->vgroups[0].epSet; + pInserter->explain = (QUERY_NODE_EXPLAIN_STMT == nodeType(pCxt->pPlanCxt->pAstRoot) ? true : false); vgroupInfoToNodeAddr(pModify->pVgroupList->vgroups, &pSubplan->execNode); int32_t code = setListSlotId(pCxt, pSubplan->pNode->pOutputDataBlockDesc->dataBlockId, -1, pModify->pInsertCols, diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c index 4c8b996a75f19920d8f64bbd91b5d98fbe192f97..fd77261818702defef8aa928e10a73cb66e28b20 100644 --- a/source/libs/planner/src/planSpliter.c +++ b/source/libs/planner/src/planSpliter.c @@ -742,6 +742,18 @@ static int32_t stbSplSplitState(SSplitContext* pCxt, SStableSplitInfo* pInfo) { } } +static int32_t stbSplSplitEventForStream(SSplitContext* pCxt, SStableSplitInfo* pInfo) { + return TSDB_CODE_PLAN_INTERNAL_ERROR; +} + +static int32_t stbSplSplitEvent(SSplitContext* pCxt, SStableSplitInfo* pInfo) { + if (pCxt->pPlanCxt->streamQuery) { + return stbSplSplitEventForStream(pCxt, pInfo); + } else { + return stbSplSplitSessionOrStateForBatch(pCxt, pInfo); + } +} + static bool stbSplIsPartTableWinodw(SWindowLogicNode* pWindow) { return stbSplHasPartTbname(stbSplGetPartKeys((SLogicNode*)nodesListGetNode(pWindow->node.pChildren, 0))); } @@ -754,6 +766,8 @@ static int32_t stbSplSplitWindowForCrossTable(SSplitContext* pCxt, SStableSplitI return stbSplSplitSession(pCxt, pInfo); case WINDOW_TYPE_STATE: return stbSplSplitState(pCxt, pInfo); + case WINDOW_TYPE_EVENT: + return stbSplSplitEvent(pCxt, pInfo); default: break; } @@ -1351,7 +1365,8 @@ static int32_t unAllSplCreateExchangeNode(SSplitContext* pCxt, int32_t startGrou pExchange->srcEndGroupId = pCxt->groupId - 1; pExchange->node.precision = pProject->node.precision; pExchange->node.pTargets = nodesCloneList(pProject->node.pTargets); - if (NULL == pExchange->node.pTargets) { + pExchange->node.pConditions = nodesCloneNode(pProject->node.pConditions); + if (NULL == pExchange->node.pTargets || (NULL != pProject->node.pConditions && NULL == pExchange->node.pConditions)) { return TSDB_CODE_OUT_OF_MEMORY; } TSWAP(pExchange->node.pLimit, pProject->node.pLimit); diff --git a/source/libs/planner/src/planUtil.c b/source/libs/planner/src/planUtil.c index fd6cb730f8e7c9109e089b06aaf20cd8fd88ca28..4b8009347d5e44ce236f99652b4814e36b8af459 100644 --- a/source/libs/planner/src/planUtil.c +++ b/source/libs/planner/src/planUtil.c @@ -200,6 +200,15 @@ static int32_t adjustStateDataRequirement(SWindowLogicNode* pWindow, EDataOrderL return TSDB_CODE_SUCCESS; } +static int32_t adjustEventDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) { + if (requirement <= pWindow->node.resultDataOrder) { + return TSDB_CODE_SUCCESS; + } + pWindow->node.resultDataOrder = requirement; + pWindow->node.requireDataOrder = requirement; + return TSDB_CODE_SUCCESS; +} + static int32_t adjustWindowDataRequirement(SWindowLogicNode* pWindow, EDataOrderLevel requirement) { switch (pWindow->winType) { case WINDOW_TYPE_INTERVAL: @@ -208,6 +217,8 @@ static int32_t adjustWindowDataRequirement(SWindowLogicNode* pWindow, EDataOrder return adjustSessionDataRequirement(pWindow, requirement); case WINDOW_TYPE_STATE: return adjustStateDataRequirement(pWindow, requirement); + case WINDOW_TYPE_EVENT: + return adjustEventDataRequirement(pWindow, requirement); default: break; } diff --git a/source/libs/planner/src/planner.c b/source/libs/planner/src/planner.c index c6a4a97f6ed9179cbae090c8b16f7e298b9ea0ba..58b8e53478ef48dfb7fb4198cc50426a8387cf77 100644 --- a/source/libs/planner/src/planner.c +++ b/source/libs/planner/src/planner.c @@ -19,6 +19,14 @@ #include "scalar.h" #include "tglobal.h" +static void debugPrintNode(SNode* pNode) { + char* pStr = NULL; + nodesNodeToString(pNode, false, &pStr, NULL); + printf("%s\n", pStr); + taosMemoryFree(pStr); + return; +} + static void dumpQueryPlan(SQueryPlan* pPlan) { if (!tsQueryPlannerTrace) { return; diff --git a/source/libs/planner/test/planBasicTest.cpp b/source/libs/planner/test/planBasicTest.cpp index 150df76416d71514fc226f35b48ec4f57701d31b..10ab71ab0e68e2a31c798c46e3c2f685a70d2201 100644 --- a/source/libs/planner/test/planBasicTest.cpp +++ b/source/libs/planner/test/planBasicTest.cpp @@ -104,6 +104,8 @@ TEST_F(PlanBasicTest, interpFunc) { run("SELECT _IROWTS, INTERP(c1) FROM t1 RANGE('2017-7-14 18:00:00', '2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR)"); + run("SELECT _IROWTS, INTERP(c1), _ISFILLED FROM t1 RANGE('2017-7-14 18:00:00', '2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR)"); + run("SELECT TBNAME, _IROWTS, INTERP(c1) FROM t1 PARTITION BY TBNAME " "RANGE('2017-7-14 18:00:00', '2017-7-14 19:00:00') EVERY(5s) FILL(LINEAR)"); } diff --git a/source/dnode/vnode/src/tsdb/tsdbCompact.c b/source/libs/planner/test/planEventTest.cpp similarity index 60% rename from source/dnode/vnode/src/tsdb/tsdbCompact.c rename to source/libs/planner/test/planEventTest.cpp index fb3917be64faa058b52f1f13a86ec0034486f279..c4db1459982de3c8daf6b8b37795a806ddd77d01 100644 --- a/source/dnode/vnode/src/tsdb/tsdbCompact.c +++ b/source/libs/planner/test/planEventTest.cpp @@ -13,15 +13,21 @@ * along with this program. If not, see . */ -#include "tsdb.h" +#include "planTestUtil.h" +#include "planner.h" -typedef struct { - STsdb *pTsdb; - STsdbFS fs; -} STsdbCompactor; +using namespace std; -int32_t tsdbCompact(STsdb *pTsdb) { - int32_t code = 0; - // TODO - return code; +class PlanEventTest : public PlannerTestBase {}; + +TEST_F(PlanEventTest, basic) { + useDb("root", "test"); + + run("SELECT COUNT(*) FROM t1 EVENT_WINDOW START WITH c1 > 10 END WITH c2 = 'abc'"); +} + +TEST_F(PlanEventTest, stable) { + useDb("root", "test"); + + run("SELECT COUNT(*) FROM st1 EVENT_WINDOW START WITH c1 > 10 END WITH c2 = 'abc'"); } diff --git a/source/libs/planner/test/planOtherTest.cpp b/source/libs/planner/test/planOtherTest.cpp index 4741d241b5ac8b5541b6f92d08dbe1dd26151099..3a12d62340f1744db5d351d7494e2e181b512d76 100644 --- a/source/libs/planner/test/planOtherTest.cpp +++ b/source/libs/planner/test/planOtherTest.cpp @@ -30,7 +30,7 @@ TEST_F(PlanOtherTest, createTopic) { TEST_F(PlanOtherTest, createStream) { useDb("root", "test"); - run("create stream if not exists s1 trigger window_close watermark 10s into st1 as select count(*) from t1 " + run("create stream if not exists s1 trigger window_close watermark 10s into st3 as select count(*) from t1 " "interval(10s)"); run("CREATE STREAM s1 INTO st3 TAGS(tname VARCHAR(10), id INT) SUBTABLE(CONCAT('new-', tname)) " @@ -43,9 +43,9 @@ TEST_F(PlanOtherTest, createStream) { TEST_F(PlanOtherTest, createStreamUseSTable) { useDb("root", "test"); - run("CREATE STREAM IF NOT EXISTS s1 into st1 as SELECT COUNT(*) FROM st1 INTERVAL(10s)"); + run("CREATE STREAM IF NOT EXISTS s1 into st3 as SELECT COUNT(*) FROM st1 INTERVAL(10s)"); - run("CREATE STREAM IF NOT EXISTS s1 into st1 as SELECT COUNT(*) FROM st1 PARTITION BY TBNAME INTERVAL(10s)"); + run("CREATE STREAM IF NOT EXISTS s1 into st3 as SELECT COUNT(*) FROM st1 PARTITION BY TBNAME INTERVAL(10s)"); } TEST_F(PlanOtherTest, createSmaIndex) { diff --git a/source/libs/qcom/src/queryUtil.c b/source/libs/qcom/src/queryUtil.c index c74882cf23dac901eab09b779afd56cbfb55dcaa..c70ea57401e2391507298f7b9db1756843fcfa1c 100644 --- a/source/libs/qcom/src/queryUtil.c +++ b/source/libs/qcom/src/queryUtil.c @@ -116,8 +116,6 @@ int32_t cleanupTaskQueue() { } static void execHelper(struct SSchedMsg* pSchedMsg) { - assert(pSchedMsg != NULL && pSchedMsg->ahandle != NULL); - __async_exec_fn_t execFn = (__async_exec_fn_t)pSchedMsg->ahandle; int32_t code = execFn(pSchedMsg->thandle); if (code != 0 && pSchedMsg->msg != NULL) { @@ -126,8 +124,6 @@ static void execHelper(struct SSchedMsg* pSchedMsg) { } int32_t taosAsyncExec(__async_exec_fn_t execFn, void* execParam, int32_t* code) { - assert(execFn != NULL); - SSchedMsg schedMsg = {0}; schedMsg.fp = execHelper; schedMsg.ahandle = execFn; @@ -138,7 +134,10 @@ int32_t taosAsyncExec(__async_exec_fn_t execFn, void* execParam, int32_t* code) } void destroySendMsgInfo(SMsgSendInfo* pMsgBody) { - assert(pMsgBody != NULL); + if (NULL == pMsgBody) { + return; + } + taosMemoryFreeClear(pMsgBody->target.dbFName); taosMemoryFreeClear(pMsgBody->msgInfo.pData); if (pMsgBody->paramFreeFp) { @@ -195,6 +194,8 @@ char* jobTaskStatusStr(int32_t status) { return "EXECUTING"; case JOB_TASK_STATUS_PART_SUCC: return "PARTIAL_SUCCEED"; + case JOB_TASK_STATUS_FETCH: + return "FETCHING"; case JOB_TASK_STATUS_SUCC: return "SUCCEED"; case JOB_TASK_STATUS_FAIL: @@ -243,7 +244,8 @@ void destroyQueryExecRes(SExecResult* pRes) { break; } case TDMT_VND_SUBMIT: { - tFreeSSubmitRsp((SSubmitRsp*)pRes->res); + tDestroySSubmitRsp2((SSubmitRsp2*)pRes->res, TSDB_MSG_FLG_DECODE); + taosMemoryFreeClear(pRes->res); break; } case TDMT_SCH_QUERY: @@ -393,7 +395,7 @@ char* parseTagDatatoJson(void* p) { } else if (pTagVal->nData == 0) { value = cJSON_CreateString(""); } else { - ASSERT(0); + goto end; } cJSON_AddItemToObject(json, tagJsonKey, value); @@ -412,7 +414,7 @@ char* parseTagDatatoJson(void* p) { } cJSON_AddItemToObject(json, tagJsonKey, value); } else { - ASSERT(0); + goto end; } } string = cJSON_PrintUnformatted(json); @@ -420,7 +422,7 @@ end: cJSON_Delete(json); taosArrayDestroy(pTagVals); if (string == NULL) { - string = strdup(TSDB_DATA_NULL_STR_L); + string = taosStrdup(TSDB_DATA_NULL_STR_L); } return string; } @@ -447,7 +449,6 @@ int32_t cloneTableMeta(STableMeta* pSrc, STableMeta** pDst) { return TSDB_CODE_SUCCESS; } - void freeVgInfo(SDBVgInfo* vgInfo) { if (NULL == vgInfo) { return; @@ -459,7 +460,6 @@ void freeVgInfo(SDBVgInfo* vgInfo) { taosMemoryFreeClear(vgInfo); } - int32_t cloneDbVgInfo(SDBVgInfo* pSrc, SDBVgInfo** pDst) { if (NULL == pSrc) { *pDst = NULL; @@ -498,3 +498,61 @@ int32_t cloneDbVgInfo(SDBVgInfo* pSrc, SDBVgInfo** pDst) { return TSDB_CODE_SUCCESS; } + +int32_t cloneSVreateTbReq(SVCreateTbReq* pSrc, SVCreateTbReq** pDst) { + if (NULL == pSrc) { + *pDst = NULL; + return TSDB_CODE_SUCCESS; + } + + *pDst = taosMemoryCalloc(1, sizeof(SVCreateTbReq)); + if (NULL == *pDst) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + (*pDst)->flags = pSrc->flags; + if (pSrc->name) { + (*pDst)->name = taosStrdup(pSrc->name); + } + (*pDst)->uid = pSrc->uid; + (*pDst)->ctime = pSrc->ctime; + (*pDst)->ttl = pSrc->ttl; + (*pDst)->commentLen = pSrc->commentLen; + if (pSrc->comment) { + (*pDst)->comment = taosStrdup(pSrc->comment); + } + (*pDst)->type = pSrc->type; + + if (pSrc->type == TSDB_CHILD_TABLE) { + if (pSrc->ctb.stbName) { + (*pDst)->ctb.stbName = taosStrdup(pSrc->ctb.stbName); + } + (*pDst)->ctb.tagNum = pSrc->ctb.tagNum; + (*pDst)->ctb.suid = pSrc->ctb.suid; + if (pSrc->ctb.tagName) { + (*pDst)->ctb.tagName = taosArrayDup(pSrc->ctb.tagName, NULL); + } + STag* pTag = (STag*)pSrc->ctb.pTag; + if (pTag) { + (*pDst)->ctb.pTag = taosMemoryMalloc(pTag->len); + memcpy((*pDst)->ctb.pTag, pTag, pTag->len); + } + } else { + (*pDst)->ntb.schemaRow.nCols = pSrc->ntb.schemaRow.nCols; + (*pDst)->ntb.schemaRow.version = pSrc->ntb.schemaRow.nCols; + if (pSrc->ntb.schemaRow.nCols > 0 && pSrc->ntb.schemaRow.pSchema) { + (*pDst)->ntb.schemaRow.pSchema = taosMemoryMalloc(pSrc->ntb.schemaRow.nCols * sizeof(SSchema)); + memcpy((*pDst)->ntb.schemaRow.pSchema, pSrc->ntb.schemaRow.pSchema, pSrc->ntb.schemaRow.nCols * sizeof(SSchema)); + } + } + + return TSDB_CODE_SUCCESS; +} + +void freeDbCfgInfo(SDbCfgInfo *pInfo) { + if (pInfo) { + taosArrayDestroy(pInfo->pRetensions); + } + taosMemoryFree(pInfo); +} + diff --git a/source/libs/qcom/src/querymsg.c b/source/libs/qcom/src/querymsg.c index 2e4b000761220e4d49a3c03778efe89effebed8a..01b136d5e0ca5387ec525848ec7561ee09f6c38d 100644 --- a/source/libs/qcom/src/querymsg.c +++ b/source/libs/qcom/src/querymsg.c @@ -407,7 +407,7 @@ int32_t queryCreateTableMetaFromMsg(STableMetaRsp *msg, bool isStb, STableMeta * pTableMeta->tableInfo.rowSize += pTableMeta->schema[i].bytes; } - qDebug("table %s uid %" PRIx64 " meta returned, type %d vgId:%d db %s stb %s suid %" PRIx64 " sver %d tver %d" PRIx64 + qDebug("table %s uid %" PRIx64 " meta returned, type %d vgId:%d db %s stb %s suid %" PRIx64 " sver %d tver %d" " tagNum %d colNum %d precision %d rowSize %d", msg->tbName, pTableMeta->uid, pTableMeta->tableType, pTableMeta->vgId, msg->dbFName, msg->stbName, pTableMeta->suid, pTableMeta->sversion, pTableMeta->tversion, pTableMeta->tableInfo.numOfTags, @@ -527,7 +527,7 @@ int32_t queryProcessGetSerVerRsp(void *output, char *msg, int32_t msgSize) { return code; } - *(char **)output = strdup(out.ver); + *(char **)output = taosStrdup(out.ver); return code; } @@ -587,7 +587,8 @@ int32_t queryProcessRetrieveFuncRsp(void *output, char *msg, int32_t msgSize) { memcpy(output, funcInfo, sizeof(*funcInfo)); taosArrayDestroy(out.pFuncInfos); - + taosArrayDestroy(out.pFuncExtraInfos); + return TSDB_CODE_SUCCESS; } diff --git a/source/libs/qworker/inc/qwInt.h b/source/libs/qworker/inc/qwInt.h index bde05d41164c0ed36fc662f21e145a8967052ab0..4bc357d7dda790e833908acaa6bb20b3cd5a9b35 100644 --- a/source/libs/qworker/inc/qwInt.h +++ b/source/libs/qworker/inc/qwInt.h @@ -76,6 +76,7 @@ typedef struct SQWDebug { bool lockEnable; bool statusEnable; bool dumpEnable; + bool forceStop; bool sleepSimulate; bool deadSimulate; bool redirectSimulate; @@ -119,7 +120,8 @@ typedef struct SQWTaskCtx { int8_t explain; int8_t needFetch; int8_t localExec; - int32_t msgType; + int32_t queryMsgType; + int32_t fetchMsgType; int32_t level; uint64_t sId; @@ -206,6 +208,8 @@ typedef struct SQWorkerMgmt { int32_t paramIdx; } SQWorkerMgmt; +#define QW_CTX_NOT_EXISTS_ERR_CODE(mgmt) (atomic_load_8(&(mgmt)->nodeStopped) ? TSDB_CODE_VND_STOPPED : TSDB_CODE_QRY_TASK_CTX_NOT_EXIST) + #define QW_FPARAMS_DEF SQWorker *mgmt, uint64_t sId, uint64_t qId, uint64_t tId, int64_t rId, int32_t eId #define QW_IDS() sId, qId, tId, rId, eId #define QW_FPARAMS() mgmt, QW_IDS() @@ -246,6 +250,7 @@ typedef struct SQWorkerMgmt { #define QW_QUERY_RUNNING(ctx) (QW_GET_PHASE(ctx) == QW_PHASE_PRE_QUERY || QW_GET_PHASE(ctx) == QW_PHASE_PRE_CQUERY) #define QW_FETCH_RUNNING(ctx) ((ctx)->inFetch) +#define QW_QUERY_NOT_STARTED(ctx) (QW_GET_PHASE(ctx) == -1) #define QW_SET_QTID(id, qId, tId, eId) \ do { \ @@ -332,34 +337,34 @@ typedef struct SQWorkerMgmt { #define QW_LOCK(type, _lock) \ do { \ if (QW_READ == (type)) { \ - assert(atomic_load_32((_lock)) >= 0); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value before read lock"); \ QW_LOCK_DEBUG("QW RLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ taosRLockLatch(_lock); \ QW_LOCK_DEBUG("QW RLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) > 0); \ + ASSERTS(atomic_load_32((_lock)) > 0, "invalid lock value after read lock"); \ } else { \ - assert(atomic_load_32((_lock)) >= 0); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value before write lock"); \ QW_LOCK_DEBUG("QW WLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ taosWLockLatch(_lock); \ QW_LOCK_DEBUG("QW WLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY); \ + ASSERTS(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY, "invalid lock value after write lock"); \ } \ } while (0) #define QW_UNLOCK(type, _lock) \ do { \ if (QW_READ == (type)) { \ - assert(atomic_load_32((_lock)) > 0); \ + ASSERTS(atomic_load_32((_lock)) > 0, "invalid lock value before read unlock"); \ QW_LOCK_DEBUG("QW RULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ taosRUnLockLatch(_lock); \ QW_LOCK_DEBUG("QW RULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) >= 0); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value after read unlock"); \ } else { \ - assert(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY); \ + ASSERTS(atomic_load_32((_lock)) == TD_RWLATCH_WRITE_FLAG_COPY, "invalid lock value before write unlock"); \ QW_LOCK_DEBUG("QW WULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ taosWUnLockLatch(_lock); \ QW_LOCK_DEBUG("QW WULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) >= 0); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value after write unlock"); \ } \ } while (0) diff --git a/source/libs/qworker/src/qwDbg.c b/source/libs/qworker/src/qwDbg.c index 7a755cd36f46f87674096bae5b970a137c4e4655..f2e48918ab053ec3f789b621e5e78fb645df80fa 100644 --- a/source/libs/qworker/src/qwDbg.c +++ b/source/libs/qworker/src/qwDbg.c @@ -9,11 +9,13 @@ #include "tmsg.h" #include "tname.h" -SQWDebug gQWDebug = {.statusEnable = true, +SQWDebug gQWDebug = {.lockEnable = false, + .statusEnable = true, .dumpEnable = false, .redirectSimulate = false, .deadSimulate = false, - .sleepSimulate = false}; + .sleepSimulate = false, + .forceStop = false}; int32_t qwDbgValidateStatus(QW_FPARAMS_DEF, int8_t oriStatus, int8_t newStatus, bool *ignore) { if (!gQWDebug.statusEnable) { @@ -124,10 +126,10 @@ void qwDbgDumpTasksInfo(SQWorker *mgmt) { void *key = taosHashGetKey(pIter, NULL); QW_GET_QTID(key, qId, tId, eId); - QW_TASK_DLOG("%p lock:%x, phase:%d, type:%d, explain:%d, needFetch:%d, localExec:%d, msgType:%d, " + QW_TASK_DLOG("%p lock:%x, phase:%d, type:%d, explain:%d, needFetch:%d, localExec:%d, queryMsgType:%d, " "sId:%" PRId64 ", level:%d, queryGotData:%d, queryRsped:%d, queryEnd:%d, queryContinue:%d, queryInQueue:%d, " "rspCode:%x, affectedRows:%" PRId64 ", taskHandle:%p, sinkHandle:%p, tbFName:%s, sver:%d, tver:%d, events:%d,%d,%d,%d,%d", - ctx, ctx->lock, ctx->phase, ctx->taskType, ctx->explain, ctx->needFetch, ctx->localExec, ctx->msgType, + ctx, ctx->lock, ctx->phase, ctx->taskType, ctx->explain, ctx->needFetch, ctx->localExec, ctx->queryMsgType, ctx->sId, ctx->level, ctx->queryGotData, ctx->queryRsped, ctx->queryEnd, ctx->queryContinue, ctx->queryInQueue, ctx->rspCode, ctx->affectedRows, ctx->taskHandle, ctx->sinkHandle, ctx->tbInfo.tbFName, ctx->tbInfo.sversion, ctx->tbInfo.tversion, ctx->events[QW_EVENT_CANCEL], ctx->events[QW_EVENT_READY], @@ -257,19 +259,30 @@ void qwDbgSimulateDead(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *rsped) { static int32_t ignoreTime = 0; if (++ignoreTime > 10 && 0 == taosRand() % 9) { + if (ctx->fetchMsgType == TDMT_SCH_FETCH) { + qwBuildAndSendErrorRsp(TDMT_SCH_LINK_BROKEN, &ctx->ctrlConnInfo, TSDB_CODE_RPC_BROKEN_LINK); + qwBuildAndSendErrorRsp(ctx->fetchMsgType + 1, &ctx->dataConnInfo, TSDB_CODE_QRY_TASK_CTX_NOT_EXIST); + *rsped = true; + + taosSsleep(3); + return; + } + +#if 0 SRpcHandleInfo *pConn = ((ctx->msgType == TDMT_SCH_FETCH || ctx->msgType == TDMT_SCH_MERGE_FETCH) ? &ctx->dataConnInfo - : &ctx->ctrlConnInfo); + : &ctx->ctrlConnInfo); qwBuildAndSendErrorRsp(ctx->msgType + 1, pConn, TSDB_CODE_RPC_BROKEN_LINK); - + qwBuildAndSendDropMsg(QW_FPARAMS(), pConn); *rsped = true; - + return; +#endif } } -int32_t qwDbgEnableDebug(char *option) { +int32_t qWorkerDbgEnableDebug(char *option) { if (0 == strcasecmp(option, "lock")) { gQWDebug.lockEnable = true; qError("qw lock debug enabled"); @@ -306,6 +319,12 @@ int32_t qwDbgEnableDebug(char *option) { return TSDB_CODE_SUCCESS; } + if (0 == strcasecmp(option, "forceStop")) { + gQWDebug.forceStop = true; + qError("qw forceStop debug enabled"); + return TSDB_CODE_SUCCESS; + } + qError("invalid qw debug option:%s", option); return TSDB_CODE_APP_ERROR; diff --git a/source/libs/qworker/src/qwUtil.c b/source/libs/qworker/src/qwUtil.c index 7ee7c50c9687d26f94825a5b0888caba9371f66d..a342e48cc196df512aa1c91193c6afa5ab7c11cc 100644 --- a/source/libs/qworker/src/qwUtil.c +++ b/source/libs/qworker/src/qwUtil.c @@ -213,15 +213,9 @@ int32_t qwAcquireTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx **ctx) { QW_SET_QTID(id, qId, tId, eId); *ctx = taosHashAcquire(mgmt->ctxHash, id, sizeof(id)); - int8_t nodeStopped = atomic_load_8(&mgmt->nodeStopped); if (NULL == (*ctx)) { - if (!nodeStopped) { - QW_TASK_DLOG_E("task ctx not exist, may be dropped"); - QW_ERR_RET(TSDB_CODE_QRY_TASK_CTX_NOT_EXIST); - } else { - QW_TASK_DLOG_E("node stopped"); - QW_ERR_RET(TSDB_CODE_VND_STOPPED); - } + QW_TASK_DLOG_E("acquired task ctx not exist, may be dropped"); + QW_ERR_RET(QW_CTX_NOT_EXISTS_ERR_CODE(mgmt)); } return TSDB_CODE_SUCCESS; @@ -232,16 +226,9 @@ int32_t qwGetTaskCtx(QW_FPARAMS_DEF, SQWTaskCtx **ctx) { QW_SET_QTID(id, qId, tId, eId); *ctx = taosHashGet(mgmt->ctxHash, id, sizeof(id)); - int8_t nodeStopped = atomic_load_8(&mgmt->nodeStopped); - if (NULL == (*ctx)) { - if (!nodeStopped) { - QW_TASK_DLOG_E("task ctx not exist, may be dropped"); - QW_ERR_RET(TSDB_CODE_QRY_TASK_CTX_NOT_EXIST); - } else { - QW_TASK_DLOG_E("node stopped"); - QW_ERR_RET(TSDB_CODE_VND_STOPPED); - } + QW_TASK_DLOG_E("get task ctx not exist, may be dropped"); + QW_ERR_RET(QW_CTX_NOT_EXISTS_ERR_CODE(mgmt)); } return TSDB_CODE_SUCCESS; @@ -334,7 +321,8 @@ int32_t qwDropTaskCtx(QW_FPARAMS_DEF) { SQWTaskCtx *ctx = taosHashGet(mgmt->ctxHash, id, sizeof(id)); if (NULL == ctx) { - QW_ERR_RET(TSDB_CODE_QRY_TASK_CTX_NOT_EXIST); + QW_TASK_DLOG_E("drop task ctx not exist, may be dropped"); + QW_ERR_RET(QW_CTX_NOT_EXISTS_ERR_CODE(mgmt)); } octx = *ctx; @@ -346,7 +334,7 @@ int32_t qwDropTaskCtx(QW_FPARAMS_DEF) { if (taosHashRemove(mgmt->ctxHash, id, sizeof(id))) { QW_TASK_ELOG_E("taosHashRemove from ctx hash failed"); - QW_ERR_RET(TSDB_CODE_QRY_TASK_CTX_NOT_EXIST); + QW_ERR_RET(QW_CTX_NOT_EXISTS_ERR_CODE(mgmt)); } qwFreeTaskCtx(&octx); diff --git a/source/libs/qworker/src/qworker.c b/source/libs/qworker/src/qworker.c index 2df0109d1912fa63b7c0719ac4579157939304ae..9db049508126d2665726f79a56456b2c09e45656 100644 --- a/source/libs/qworker/src/qworker.c +++ b/source/libs/qworker/src/qworker.c @@ -18,6 +18,50 @@ SQWorkerMgmt gQwMgmt = { .qwNum = 0, }; +int32_t qwStopAllTasks(SQWorker *mgmt) { + uint64_t qId, tId, sId; + int32_t eId; + int64_t rId = 0; + + void *pIter = taosHashIterate(mgmt->ctxHash, NULL); + while (pIter) { + SQWTaskCtx *ctx = (SQWTaskCtx *)pIter; + void *key = taosHashGetKey(pIter, NULL); + QW_GET_QTID(key, qId, tId, eId); + + QW_LOCK(QW_WRITE, &ctx->lock); + + sId = ctx->sId; + + QW_TASK_DLOG_E("start to force stop task"); + + if (QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP) || QW_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) { + QW_TASK_WLOG_E("task already dropping"); + QW_UNLOCK(QW_WRITE, &ctx->lock); + + pIter = taosHashIterate(mgmt->ctxHash, pIter); + continue; + } + + if (QW_QUERY_RUNNING(ctx)) { + qwKillTaskHandle(ctx, TSDB_CODE_VND_STOPPED); + QW_TASK_DLOG_E("task running, async killed"); + } else if (QW_FETCH_RUNNING(ctx)) { + QW_UPDATE_RSP_CODE(ctx, TSDB_CODE_VND_STOPPED); + QW_SET_EVENT_RECEIVED(ctx, QW_EVENT_DROP); + QW_TASK_DLOG_E("task fetching, update drop received"); + } else { + qwDropTask(QW_FPARAMS()); + } + + QW_UNLOCK(QW_WRITE, &ctx->lock); + + pIter = taosHashIterate(mgmt->ctxHash, pIter); + } + + return TSDB_CODE_SUCCESS; +} + int32_t qwProcessHbLinkBroken(SQWorker *mgmt, SQWMsg *qwMsg, SSchedulerHbReq *req) { int32_t code = 0; SSchedulerHbRsp rsp = {0}; @@ -147,7 +191,6 @@ int32_t qwExecTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *queryStop) { size_t numOfResBlock = taosArrayGetSize(pResList); for (int32_t j = 0; j < numOfResBlock; ++j) { SSDataBlock *pRes = taosArrayGetP(pResList, j); - ASSERT(pRes->info.rows > 0); SInputData inputData = {.pData = pRes}; code = dsPutDataBlock(sinkHandle, &inputData, &qcontinue); @@ -156,7 +199,7 @@ int32_t qwExecTask(QW_FPARAMS_DEF, SQWTaskCtx *ctx, bool *queryStop) { QW_ERR_JRET(code); } - QW_TASK_DLOG("data put into sink, rows:%d, continueExecTask:%d", pRes->info.rows, qcontinue); + QW_TASK_DLOG("data put into sink, rows:%" PRId64 ", continueExecTask:%d", pRes->info.rows, qcontinue); } if (numOfResBlock == 0 || (hasMore == false)) { @@ -203,7 +246,7 @@ _return: } bool qwTaskNotInExec(SQWTaskCtx *ctx) { - qTaskInfo_t taskHandle = ctx->taskHandle; + qTaskInfo_t taskHandle = ctx->taskHandle; if (NULL == taskHandle || !qTaskIsExecuting(taskHandle)) { return true; } @@ -211,6 +254,7 @@ bool qwTaskNotInExec(SQWTaskCtx *ctx) { return false; } + int32_t qwGenerateSchHbRsp(SQWorker *mgmt, SQWSchStatus *sch, SQWHbInfo *hbInfo) { int32_t taskNum = 0; @@ -393,6 +437,40 @@ int32_t qwGetDeleteResFromSink(QW_FPARAMS_DEF, SQWTaskCtx *ctx, SDeleteRes *pRes return TSDB_CODE_SUCCESS; } + +int32_t qwQuickRspFetchReq(QW_FPARAMS_DEF, SQWTaskCtx * ctx, SQWMsg *qwMsg, int32_t code) { + if (QUERY_RSP_POLICY_QUICK == tsQueryRspPolicy && ctx != NULL) { + if (QW_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) { + void *rsp = NULL; + int32_t dataLen = 0; + SOutputData sOutput = {0}; + if (qwGetQueryResFromSink(QW_FPARAMS(), ctx, &dataLen, &rsp, &sOutput)) { + return TSDB_CODE_SUCCESS; + } + + if (rsp) { + bool qComplete = (DS_BUF_EMPTY == sOutput.bufStatus && sOutput.queryEnd); + + qwBuildFetchRsp(rsp, &sOutput, dataLen, qComplete); + if (qComplete) { + atomic_store_8((int8_t *)&ctx->queryEnd, true); + } + + qwMsg->connInfo = ctx->dataConnInfo; + QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_FETCH); + + qwBuildAndSendFetchRsp(ctx->fetchMsgType + 1, &qwMsg->connInfo, rsp, dataLen, code); + rsp = NULL; + + QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, tstrerror(code), + dataLen); + } + } + } + + return TSDB_CODE_SUCCESS; +} + int32_t qwHandlePrePhaseEvents(QW_FPARAMS_DEF, int8_t phase, SQWPhaseInput *input, SQWPhaseOutput *output) { int32_t code = 0; SQWTaskCtx *ctx = NULL; @@ -541,7 +619,7 @@ _return: if (QW_PHASE_POST_QUERY == phase && ctx && !ctx->queryRsped) { bool rsped = false; - SQWMsg qwMsg = {.msgType = ctx->msgType, .connInfo = ctx->ctrlConnInfo}; + SQWMsg qwMsg = {.msgType = ctx->queryMsgType, .connInfo = ctx->ctrlConnInfo}; qwDbgSimulateRedirect(&qwMsg, ctx, &rsped); qwDbgSimulateDead(QW_FPARAMS(), ctx, &rsped); if (!rsped) { @@ -591,6 +669,8 @@ int32_t qwPreprocessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) { QW_ERR_JRET(qwAddTaskStatus(QW_FPARAMS(), JOB_TASK_STATUS_INIT)); + qwSendQueryRsp(QW_FPARAMS(), qwMsg->msgType + 1, ctx, code, true); + _return: if (ctx) { @@ -617,7 +697,7 @@ int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, char *sql) { ctx->taskType = qwMsg->msgInfo.taskType; ctx->explain = qwMsg->msgInfo.explain; ctx->needFetch = qwMsg->msgInfo.needFetch; - ctx->msgType = qwMsg->msgType; + ctx->queryMsgType = qwMsg->msgType; ctx->localExec = false; // QW_TASK_DLOGL("subplan json string, len:%d, %s", qwMsg->msgLen, qwMsg->msg); @@ -641,7 +721,7 @@ int32_t qwProcessQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg, char *sql) { QW_ERR_JRET(TSDB_CODE_APP_ERROR); } - qwSendQueryRsp(QW_FPARAMS(), qwMsg->msgType + 1, ctx, code, true); + //qwSendQueryRsp(QW_FPARAMS(), qwMsg->msgType + 1, ctx, code, true); ctx->level = plan->level; atomic_store_ptr(&ctx->taskHandle, pTaskInfo); @@ -658,32 +738,7 @@ _return: input.msgType = qwMsg->msgType; code = qwHandlePostPhaseEvents(QW_FPARAMS(), QW_PHASE_POST_QUERY, &input, NULL); - if (QUERY_RSP_POLICY_QUICK == tsQueryRspPolicy && ctx != NULL && QW_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) { - void *rsp = NULL; - int32_t dataLen = 0; - SOutputData sOutput = {0}; - if (qwGetQueryResFromSink(QW_FPARAMS(), ctx, &dataLen, &rsp, &sOutput)) { - return TSDB_CODE_SUCCESS; - } - - if (rsp) { - bool qComplete = (DS_BUF_EMPTY == sOutput.bufStatus && sOutput.queryEnd); - - qwBuildFetchRsp(rsp, &sOutput, dataLen, qComplete); - if (qComplete) { - atomic_store_8((int8_t *)&ctx->queryEnd, true); - } - - qwMsg->connInfo = ctx->dataConnInfo; - QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_FETCH); - - qwBuildAndSendFetchRsp(ctx->msgType + 1, &qwMsg->connInfo, rsp, dataLen, code); - rsp = NULL; - - QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, tstrerror(code), - dataLen); - } - } + qwQuickRspFetchReq(QW_FPARAMS(), ctx, qwMsg, code); QW_RET(TSDB_CODE_SUCCESS); } @@ -707,8 +762,10 @@ int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) { atomic_store_8((int8_t *)&ctx->queryInQueue, 0); atomic_store_8((int8_t *)&ctx->queryContinue, 0); - QW_ERR_JRET(qwExecTask(QW_FPARAMS(), ctx, &queryStop)); - + if (!queryStop) { + QW_ERR_JRET(qwExecTask(QW_FPARAMS(), ctx, &queryStop)); + } + if (QW_EVENT_RECEIVED(ctx, QW_EVENT_FETCH)) { SOutputData sOutput = {0}; QW_ERR_JRET(qwGetQueryResFromSink(QW_FPARAMS(), ctx, &dataLen, &rsp, &sOutput)); @@ -731,7 +788,7 @@ int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) { qwMsg->connInfo = ctx->dataConnInfo; QW_SET_EVENT_PROCESSED(ctx, QW_EVENT_FETCH); - qwBuildAndSendFetchRsp(ctx->msgType + 1, &qwMsg->connInfo, rsp, dataLen, code); + qwBuildAndSendFetchRsp(ctx->fetchMsgType + 1, &qwMsg->connInfo, rsp, dataLen, code); rsp = NULL; QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, @@ -753,13 +810,14 @@ int32_t qwProcessCQuery(QW_FPARAMS_DEF, SQWMsg *qwMsg) { rsp = NULL; qwMsg->connInfo = ctx->dataConnInfo; - qwBuildAndSendFetchRsp(ctx->msgType + 1, &qwMsg->connInfo, NULL, 0, code); + qwBuildAndSendFetchRsp(ctx->fetchMsgType + 1, &qwMsg->connInfo, NULL, 0, code); QW_TASK_DLOG("fetch rsp send, handle:%p, code:%x - %s, dataLen:%d", qwMsg->connInfo.handle, code, tstrerror(code), 0); } QW_LOCK(QW_WRITE, &ctx->lock); - if (atomic_load_8((int8_t*)&ctx->queryEnd) || (queryStop && (0 == atomic_load_8((int8_t *)&ctx->queryContinue))) || code) { + if (atomic_load_8((int8_t *)&ctx->queryEnd) || (queryStop && (0 == atomic_load_8((int8_t *)&ctx->queryContinue))) || + code) { // Note: query is not running anymore QW_SET_PHASE(ctx, QW_PHASE_POST_CQUERY); QW_UNLOCK(QW_WRITE, &ctx->lock); @@ -786,7 +844,7 @@ int32_t qwProcessFetch(QW_FPARAMS_DEF, SQWMsg *qwMsg) { QW_ERR_JRET(qwGetTaskCtx(QW_FPARAMS(), &ctx)); - ctx->msgType = qwMsg->msgType; + ctx->fetchMsgType = qwMsg->msgType; ctx->dataConnInfo = qwMsg->connInfo; SOutputData sOutput = {0}; @@ -848,7 +906,12 @@ _return: qwBuildAndSendFetchRsp(qwMsg->msgType + 1, &qwMsg->connInfo, rsp, dataLen, code); QW_TASK_DLOG("%s send, handle:%p, code:%x - %s, dataLen:%d", TMSG_INFO(qwMsg->msgType + 1), qwMsg->connInfo.handle, code, tstrerror(code), dataLen); + } else { + qwFreeFetchRsp(rsp); + rsp = NULL; } + } else { + //qwQuickRspFetchReq(QW_FPARAMS(), ctx, qwMsg, code); } QW_RET(TSDB_CODE_SUCCESS); @@ -973,6 +1036,10 @@ void qwProcessHbTimerEvent(void *param, void *tmrId) { qwDbgDumpMgmtInfo(mgmt); + if (gQWDebug.forceStop) { + (void)qwStopAllTasks(mgmt); + } + QW_LOCK(QW_READ, &mgmt->schLock); int32_t schNum = taosHashGetSize(mgmt->schHash); @@ -1186,45 +1253,9 @@ void qWorkerStopAllTasks(void *qWorkerMgmt) { QW_DLOG("start to stop all tasks, taskNum:%d", taosHashGetSize(mgmt->ctxHash)); - uint64_t qId, tId, sId; - int32_t eId; - int64_t rId = 0; - atomic_store_8(&mgmt->nodeStopped, 1); - void *pIter = taosHashIterate(mgmt->ctxHash, NULL); - while (pIter) { - SQWTaskCtx *ctx = (SQWTaskCtx *)pIter; - void *key = taosHashGetKey(pIter, NULL); - QW_GET_QTID(key, qId, tId, eId); - - QW_LOCK(QW_WRITE, &ctx->lock); - - sId = ctx->sId; - - QW_TASK_DLOG_E("start to force stop task"); - - if (QW_EVENT_RECEIVED(ctx, QW_EVENT_DROP) || QW_EVENT_PROCESSED(ctx, QW_EVENT_DROP)) { - QW_TASK_WLOG_E("task already dropping"); - QW_UNLOCK(QW_WRITE, &ctx->lock); - - pIter = taosHashIterate(mgmt->ctxHash, pIter); - continue; - } - - if (QW_QUERY_RUNNING(ctx)) { - qwKillTaskHandle(ctx, TSDB_CODE_VND_STOPPED); - } else if (QW_FETCH_RUNNING(ctx)) { - QW_UPDATE_RSP_CODE(ctx, TSDB_CODE_VND_STOPPED); - QW_SET_EVENT_RECEIVED(ctx, QW_EVENT_DROP); - } else { - qwDropTask(QW_FPARAMS()); - } - - QW_UNLOCK(QW_WRITE, &ctx->lock); - - pIter = taosHashIterate(mgmt->ctxHash, pIter); - } + (void)qwStopAllTasks(mgmt); } void qWorkerDestroy(void **qWorkerMgmt) { @@ -1292,7 +1323,7 @@ int32_t qWorkerProcessLocalQuery(void *pMgmt, uint64_t sId, uint64_t qId, uint64 ctx->taskType = qwMsg->msgInfo.taskType; ctx->explain = qwMsg->msgInfo.explain; ctx->needFetch = qwMsg->msgInfo.needFetch; - ctx->msgType = qwMsg->msgType; + ctx->queryMsgType = qwMsg->msgType; ctx->localExec = true; ctx->explainRes = explainRes; @@ -1347,7 +1378,7 @@ int32_t qWorkerProcessLocalFetch(void *pMgmt, uint64_t sId, uint64_t qId, uint64 QW_ERR_JRET(qwGetTaskCtx(QW_FPARAMS(), &ctx)); - ctx->msgType = TDMT_SCH_MERGE_FETCH; + ctx->fetchMsgType = TDMT_SCH_MERGE_FETCH; ctx->explainRes = explainRes; SOutputData sOutput = {0}; diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index 25e65d25885c8b3ee8e1f1f8f55d5ecdef1e669c..02a21b66edc1d12a09300f2204ab914327c06775 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -15,7 +15,7 @@ #include #include "os.h" #include "thash.h" -//#include "queryLog.h" +// #include "queryLog.h" #include "filter.h" #include "filterInt.h" #include "functionMgt.h" @@ -123,36 +123,16 @@ int8_t filterGetRangeCompFuncFromOptrs(uint8_t optr, uint8_t optr2) { return -1; } -__compar_fn_t gDataCompare[] = {compareInt32Val, - compareInt8Val, - compareInt16Val, - compareInt64Val, - compareFloatVal, - compareDoubleVal, - compareLenPrefixedStr, - comparestrPatternMatch, - compareChkInString, - comparewcsPatternMatch, - compareLenPrefixedWStr, - compareUint8Val, - compareUint16Val, - compareUint32Val, - compareUint64Val, - setChkInBytes1, - setChkInBytes2, - setChkInBytes4, - setChkInBytes8, - comparestrRegexMatch, - comparestrRegexNMatch, - setChkNotInBytes1, - setChkNotInBytes2, - setChkNotInBytes4, - setChkNotInBytes8, - compareChkNotInString, - comparestrPatternNMatch, - comparewcsPatternNMatch, - comparewcsRegexMatch, - comparewcsRegexNMatch,}; +__compar_fn_t gDataCompare[] = { + compareInt32Val, compareInt8Val, compareInt16Val, compareInt64Val, + compareFloatVal, compareDoubleVal, compareLenPrefixedStr, comparestrPatternMatch, + compareChkInString, comparewcsPatternMatch, compareLenPrefixedWStr, compareUint8Val, + compareUint16Val, compareUint32Val, compareUint64Val, setChkInBytes1, + setChkInBytes2, setChkInBytes4, setChkInBytes8, comparestrRegexMatch, + comparestrRegexNMatch, setChkNotInBytes1, setChkNotInBytes2, setChkNotInBytes4, + setChkNotInBytes8, compareChkNotInString, comparestrPatternNMatch, comparewcsPatternNMatch, + comparewcsRegexMatch, comparewcsRegexNMatch, +}; __compar_fn_t gInt8SignCompare[] = {compareInt8Val, compareInt8Int16, compareInt8Int32, compareInt8Int64, compareInt8Float, compareInt8Double}; @@ -341,7 +321,7 @@ __compar_fn_t filterGetCompFuncEx(int32_t lType, int32_t rType, int32_t optr) { if (TSDB_DATA_TYPE_NULL == rType || TSDB_DATA_TYPE_JSON == rType) { return NULL; } - + switch (lType) { case TSDB_DATA_TYPE_TINYINT: { if (IS_SIGNED_NUMERIC_TYPE(rType) || IS_FLOAT_TYPE(rType)) { @@ -519,7 +499,7 @@ int32_t filterReuseRangeCtx(SFilterRangeCtx *ctx, int32_t type, int32_t options) int32_t filterConvertRange(SFilterRangeCtx *cur, SFilterRange *ra, bool *notNull) { int64_t tmp = 0; - + if (!FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { int32_t sr = cur->pCompareFunc(&ra->s, getDataMin(cur->type, &tmp)); if (sr == 0) { @@ -704,7 +684,7 @@ int32_t filterAddRangeImpl(void *h, SFilterRange *ra, int32_t optr) { int32_t filterAddRange(void *h, SFilterRange *ra, int32_t optr) { SFilterRangeCtx *ctx = (SFilterRangeCtx *)h; - int64_t tmp = 0; + int64_t tmp = 0; if (FILTER_GET_FLAG(ra->sflag, RANGE_FLG_NULL)) { SIMPLE_COPY_VALUES(&ra->s, getDataMin(ctx->type, &tmp)); @@ -991,7 +971,7 @@ int32_t filterAddField(SFilterInfo *info, void *desc, void **data, int32_t type, bool freeIfExists, int16_t *srcFlag) { int32_t idx = -1; uint32_t *num; - bool sameBuf = false; + bool sameBuf = false; num = &info->fields[type].num; @@ -1251,13 +1231,13 @@ int32_t filterAddUnitFromUnit(SFilterInfo *dst, SFilterInfo *src, SFilterUnit *u SFilterField *t = FILTER_UNIT_LEFT_FIELD(src, u); if (u->right.type == FLD_TYPE_VALUE) { - void *data = FILTER_UNIT_VAL_DATA(src, u); + void *data = FILTER_UNIT_VAL_DATA(src, u); SFilterField *rField = FILTER_UNIT_RIGHT_FIELD(src, u); if (IS_VAR_DATA_TYPE(type)) { if (FILTER_UNIT_OPTR(u) == OP_TYPE_IN) { - filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, POINTER_BYTES, - false, &rField->flag); // POINTER_BYTES should be sizeof(SHashObj), but POINTER_BYTES is also right. + filterAddField(dst, NULL, &data, FLD_TYPE_VALUE, &right, POINTER_BYTES, false, + &rField->flag); // POINTER_BYTES should be sizeof(SHashObj), but POINTER_BYTES is also right. t = FILTER_GET_FIELD(dst, right); FILTER_SET_FLAG(t->flag, FLD_DATA_IS_HASH); @@ -1651,12 +1631,7 @@ void filterDumpInfoToString(SFilterInfo *info, const char *msg, int32_t options) SValueNode *var = (SValueNode *)field->desc; SDataType *dType = &var->node.resType; - // if (dType->type == TSDB_DATA_TYPE_VALUE_ARRAY) { - // qDebug("VAL%d => [type:TS][val:[%" PRIi64 "] - [%" PRId64 "]]", i, *(int64_t *)field->data, - // *(((int64_t *)field->data) + 1)); - // } else { qDebug("VAL%d => [type:%d][val:%" PRIx64 "]", i, dType->type, var->datum.i); // TODO - //} } else if (field->data) { qDebug("VAL%d => [type:NIL][val:NIL]", i); // TODO } @@ -1976,18 +1951,7 @@ int32_t fltInitValFieldData(SFilterInfo *info) { fi->data = taosMemoryCalloc(1, bytes); } else { - if (dType->type == TSDB_DATA_TYPE_VALUE_ARRAY) { // TIME RANGE - /* - fi->data = taosMemoryCalloc(dType->bytes, tDataTypes[type].bytes); - for (int32_t a = 0; a < dType->bytes; ++a) { - int64_t *v = taosArrayGet(var->arr, a); - assignVal((char *)fi->data + a * tDataTypes[type].bytes, (char *)v, 0, type); - } - */ - continue; - } else { - fi->data = taosMemoryCalloc(1, sizeof(int64_t)); - } + fi->data = taosMemoryCalloc(1, sizeof(int64_t)); } if (dType->type == type) { @@ -3120,9 +3084,8 @@ static FORCE_INLINE bool filterExecuteImplIsNull(void *pinfo, int32_t numOfRows, for (int32_t i = 0; i < numOfRows; ++i) { uint32_t uidx = info->groups[0].unitIdxs[0]; - void *colData = colDataGetData((SColumnInfoData *)info->cunits[uidx].colData, i); - p[i] = ((colData == NULL) || colDataIsNull((SColumnInfoData *)info->cunits[uidx].colData, 0, i, NULL)); + p[i] = colDataIsNull((SColumnInfoData *)info->cunits[uidx].colData, 0, i, NULL); if (p[i] == 0) { all = false; } else { @@ -3146,9 +3109,8 @@ static FORCE_INLINE bool filterExecuteImplNotNull(void *pinfo, int32_t numOfRows for (int32_t i = 0; i < numOfRows; ++i) { uint32_t uidx = info->groups[0].unitIdxs[0]; - void *colData = colDataGetData((SColumnInfoData *)info->cunits[uidx].colData, i); - p[i] = ((colData != NULL) && !colDataIsNull((SColumnInfoData *)info->cunits[uidx].colData, 0, i, NULL)); + p[i] = !colDataIsNull((SColumnInfoData *)info->cunits[uidx].colData, 0, i, NULL); if (p[i] == 0) { all = false; } else { @@ -3178,13 +3140,13 @@ bool filterExecuteImplRange(void *pinfo, int32_t numOfRows, SColumnInfoData *pRe for (int32_t i = 0; i < numOfRows; ++i) { SColumnInfoData *pData = info->cunits[0].colData; - void *colData = colDataGetData(pData, i); - if (colData == NULL || colDataIsNull_s(pData, i)) { + if (colDataIsNull_s(pData, i)) { all = false; p[i] = 0; continue; } + void *colData = colDataGetData(pData, i); p[i] = (*rfunc)(colData, colData, valData, valData2, func); if (p[i] == 0) { @@ -3210,13 +3172,13 @@ bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, SColumnInfoData *pRes for (int32_t i = 0; i < numOfRows; ++i) { uint32_t uidx = info->groups[0].unitIdxs[0]; - void *colData = colDataGetData((SColumnInfoData *)info->cunits[uidx].colData, i); - if (colData == NULL || colDataIsNull_s((SColumnInfoData *)info->cunits[uidx].colData, i)) { + if (colDataIsNull_s((SColumnInfoData *)info->cunits[uidx].colData, i)) { p[i] = 0; all = false; continue; } + void *colData = colDataGetData((SColumnInfoData *)info->cunits[uidx].colData, i); // match/nmatch for nchar type need convert from ucs4 to mbs if (info->cunits[uidx].dataType == TSDB_DATA_TYPE_NCHAR && (info->cunits[uidx].optr == OP_TYPE_MATCH || info->cunits[uidx].optr == OP_TYPE_NMATCH)) { @@ -3274,7 +3236,7 @@ bool filterExecuteImpl(void *pinfo, int32_t numOfRows, SColumnInfoData *pRes, SC if (!isNull) { colData = colDataGetData((SColumnInfoData *)(cunit->colData), i); } - + if (colData == NULL || isNull) { p[i] = optr == OP_TYPE_IS_NULL ? true : false; } else { @@ -3771,31 +3733,31 @@ EDealRes fltReviseRewriter(SNode **pNode, void *pContext) { return DEAL_RES_CONTINUE; } -/* - if (!FILTER_GET_FLAG(stat->info->options, FLT_OPTION_TIMESTAMP)) { - return DEAL_RES_CONTINUE; - } + /* + if (!FILTER_GET_FLAG(stat->info->options, FLT_OPTION_TIMESTAMP)) { + return DEAL_RES_CONTINUE; + } - if (TSDB_DATA_TYPE_BINARY != valueNode->node.resType.type && TSDB_DATA_TYPE_NCHAR != valueNode->node.resType.type) { - return DEAL_RES_CONTINUE; - } + if (TSDB_DATA_TYPE_BINARY != valueNode->node.resType.type && TSDB_DATA_TYPE_NCHAR != + valueNode->node.resType.type) { return DEAL_RES_CONTINUE; + } - if (stat->precision < 0) { - int32_t code = fltAddValueNodeToConverList(stat, valueNode); - if (code) { - stat->code = code; - return DEAL_RES_ERROR; - } + if (stat->precision < 0) { + int32_t code = fltAddValueNodeToConverList(stat, valueNode); + if (code) { + stat->code = code; + return DEAL_RES_ERROR; + } - return DEAL_RES_CONTINUE; - } + return DEAL_RES_CONTINUE; + } - int32_t code = sclConvertToTsValueNode(stat->precision, valueNode); - if (code) { - stat->code = code; - return DEAL_RES_ERROR; - } -*/ + int32_t code = sclConvertToTsValueNode(stat->precision, valueNode); + if (code) { + stat->code = code; + return DEAL_RES_ERROR; + } + */ return DEAL_RES_CONTINUE; } @@ -3941,7 +3903,7 @@ EDealRes fltReviseRewriter(SNode **pNode, void *pContext) { stat->scalarMode = true; return DEAL_RES_CONTINUE; } - int32_t type = vectorGetConvertType(refNode->node.resType.type, listNode->node.resType.type); + int32_t type = vectorGetConvertType(refNode->node.resType.type, listNode->node.resType.type); if (0 != type && type != refNode->node.resType.type) { stat->scalarMode = true; return DEAL_RES_CONTINUE; @@ -3965,14 +3927,14 @@ int32_t fltReviseNodes(SFilterInfo *pInfo, SNode **pNode, SFltTreeStat *pStat) { FLT_ERR_JRET(pStat->code); -/* - int32_t nodeNum = taosArrayGetSize(pStat->nodeList); - for (int32_t i = 0; i < nodeNum; ++i) { - SValueNode *valueNode = *(SValueNode **)taosArrayGet(pStat->nodeList, i); + /* + int32_t nodeNum = taosArrayGetSize(pStat->nodeList); + for (int32_t i = 0; i < nodeNum; ++i) { + SValueNode *valueNode = *(SValueNode **)taosArrayGet(pStat->nodeList, i); - FLT_ERR_JRET(sclConvertToTsValueNode(pStat->precision, valueNode)); - } -*/ + FLT_ERR_JRET(sclConvertToTsValueNode(pStat->precision, valueNode)); + } + */ _return: diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index c1e958b055f3442f8338c3dcdcae68bd318f0091..d9295656e8c4b882e5af1d735d7399b7dfb5a332 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -53,12 +53,15 @@ int32_t sclCreateColumnInfoData(SDataType *pType, int32_t numOfRows, SScalarPara int32_t code = colInfoDataEnsureCapacity(pColumnData, numOfRows, true); if (code != TSDB_CODE_SUCCESS) { terrno = TSDB_CODE_OUT_OF_MEMORY; + colDataDestroy(pColumnData); taosMemoryFree(pColumnData); return terrno; } pParam->columnData = pColumnData; pParam->colAlloced = true; + pParam->numOfRows = numOfRows; + return TSDB_CODE_SUCCESS; } @@ -69,7 +72,7 @@ int32_t sclConvertValueToSclParam(SValueNode *pValueNode, SScalarParam *out, int return code; } - colDataAppend(in.columnData, 0, nodesGetValueFromNode(pValueNode), false); + colDataSetVal(in.columnData, 0, nodesGetValueFromNode(pValueNode), false); colInfoDataEnsureCapacity(out->columnData, 1, true); code = vectorConvertSingleColImpl(&in, out, overflow, -1, -1); @@ -337,9 +340,9 @@ int32_t sclInitParam(SNode *node, SScalarParam *param, SScalarCtx *ctx, int32_t SCL_RET(TSDB_CODE_OUT_OF_MEMORY); } if (TSDB_DATA_TYPE_NULL == valueNode->node.resType.type || valueNode->isNull) { - colDataAppendNULL(param->columnData, 0); + colDataSetNULL(param->columnData, 0); } else { - colDataAppend(param->columnData, 0, nodesGetValueFromNode(valueNode), false); + colDataSetVal(param->columnData, 0, nodesGetValueFromNode(valueNode), false); } break; } @@ -605,7 +608,7 @@ int32_t sclWalkCaseWhenList(SScalarCtx *ctx, SNodeList *pList, struct SListCell if (*equal) { bool isNull = colDataIsNull_s(pThen->columnData, (pThen->numOfRows > 1 ? rowIdx : 0)); char *pData = isNull ? NULL : colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? rowIdx : 0)); - colDataAppend(output->columnData, rowIdx, pData, isNull); + colDataSetVal(output->columnData, rowIdx, pData, isNull); if (0 == rowIdx && 1 == pCase->numOfRows && 1 == pWhen->numOfRows && 1 == pThen->numOfRows && totalRows > 1) { SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); @@ -619,7 +622,7 @@ int32_t sclWalkCaseWhenList(SScalarCtx *ctx, SNodeList *pList, struct SListCell if (pElse) { bool isNull = colDataIsNull_s(pElse->columnData, (pElse->numOfRows > 1 ? rowIdx : 0)); char *pData = isNull ? NULL : colDataGetData(pElse->columnData, (pElse->numOfRows > 1 ? rowIdx : 0)); - colDataAppend(output->columnData, rowIdx, pData, isNull); + colDataSetVal(output->columnData, rowIdx, pData, isNull); if (0 == rowIdx && 1 == pCase->numOfRows && 1 == pElse->numOfRows && totalRows > 1) { SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); @@ -629,7 +632,7 @@ int32_t sclWalkCaseWhenList(SScalarCtx *ctx, SNodeList *pList, struct SListCell goto _return; } - colDataAppend(output->columnData, rowIdx, NULL, true); + colDataSetVal(output->columnData, rowIdx, NULL, true); if (0 == rowIdx && 1 == pCase->numOfRows && totalRows > 1) { SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); @@ -668,7 +671,7 @@ int32_t sclWalkWhenList(SScalarCtx *ctx, SNodeList *pList, struct SListCell *pCe if (*whenValue) { bool isNull = colDataIsNull_s(pThen->columnData, (pThen->numOfRows > 1 ? rowIdx : 0)); char *pData = isNull ? NULL : colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? rowIdx : 0)); - colDataAppend(output->columnData, rowIdx, pData, isNull); + colDataSetVal(output->columnData, rowIdx, pData, isNull); if (preSingle && 0 == rowIdx && 1 == pWhen->numOfRows && 1 == pThen->numOfRows && totalRows > 1) { SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); @@ -687,7 +690,7 @@ int32_t sclWalkWhenList(SScalarCtx *ctx, SNodeList *pList, struct SListCell *pCe if (pElse) { bool isNull = colDataIsNull_s(pElse->columnData, (pElse->numOfRows > 1 ? rowIdx : 0)); char *pData = isNull ? NULL : colDataGetData(pElse->columnData, (pElse->numOfRows > 1 ? rowIdx : 0)); - colDataAppend(output->columnData, rowIdx, pData, isNull); + colDataSetVal(output->columnData, rowIdx, pData, isNull); if (preSingle && 0 == rowIdx && 1 == pElse->numOfRows && totalRows > 1) { SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); @@ -697,7 +700,7 @@ int32_t sclWalkWhenList(SScalarCtx *ctx, SNodeList *pList, struct SListCell *pCe goto _return; } - colDataAppend(output->columnData, rowIdx, NULL, true); + colDataSetVal(output->columnData, rowIdx, NULL, true); if (preSingle && 0 == rowIdx && totalRows > 1) { SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); @@ -740,6 +743,10 @@ int32_t sclExecFunction(SFunctionNode *node, SScalarCtx *ctx, SScalarParam *outp SCL_ERR_JRET(code); } + if (rowNum == 0) { + goto _return; + } + code = (*ffpSet.process)(params, paramNum, output); if (code) { sclError("scalar function exec failed, funcId:%d, code:%s", node->funcId, tstrerror(code)); @@ -815,7 +822,7 @@ int32_t sclExecLogic(SLogicConditionNode *node, SScalarCtx *ctx, SScalarParam *o } if (complete) { - colDataAppend(output->columnData, i, (char *)&value, false); + colDataSetVal(output->columnData, i, (char *)&value, false); if (value) { numOfQualified++; } @@ -920,7 +927,7 @@ int32_t sclExecCaseWhen(SCaseWhenNode *node, SScalarCtx *ctx, SScalarParam *outp for (int32_t i = 0; i < rowNum; ++i) { bool *equal = (bool *)colDataGetData(comp.columnData, (comp.numOfRows > 1 ? i : 0)); if (*equal) { - colDataAppend(output->columnData, i, colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? i : 0)), + colDataSetVal(output->columnData, i, colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? i : 0)), colDataIsNull_s(pThen->columnData, (pThen->numOfRows > 1 ? i : 0))); if (0 == i && 1 == pCase->numOfRows && 1 == pWhen->numOfRows && 1 == pThen->numOfRows && rowNum > 1) { SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); @@ -938,7 +945,7 @@ int32_t sclExecCaseWhen(SCaseWhenNode *node, SScalarCtx *ctx, SScalarParam *outp for (int32_t i = 0; i < rowNum; ++i) { bool *whenValue = (bool *)colDataGetData(pWhen->columnData, (pWhen->numOfRows > 1 ? i : 0)); if (*whenValue) { - colDataAppend(output->columnData, i, colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? i : 0)), + colDataSetVal(output->columnData, i, colDataGetData(pThen->columnData, (pThen->numOfRows > 1 ? i : 0)), colDataIsNull_s(pThen->columnData, (pThen->numOfRows > 1 ? i : 0))); if (0 == i && 1 == pWhen->numOfRows && 1 == pThen->numOfRows && rowNum > 1) { SCL_ERR_JRET(sclExtendResRows(output, output, ctx->pBlockList)); @@ -1032,23 +1039,43 @@ bool sclContainsAggFuncNode(SNode *pNode) { return aggFunc; } +static uint8_t sclGetOpValueNodeTsPrecision(SNode *pLeft, SNode *pRight) { + uint8_t lPrec = ((SExprNode *)pLeft)->resType.precision; + uint8_t rPrec = ((SExprNode *)pRight)->resType.precision; + + uint8_t lType = ((SExprNode *)pLeft)->resType.type; + uint8_t rType = ((SExprNode *)pRight)->resType.type; + + if (TSDB_DATA_TYPE_TIMESTAMP == lType && TSDB_DATA_TYPE_TIMESTAMP == rType) { + return TMAX(lPrec, rPrec); + } else if (TSDB_DATA_TYPE_TIMESTAMP == lType && TSDB_DATA_TYPE_TIMESTAMP != rType) { + return lPrec; + } else if (TSDB_DATA_TYPE_TIMESTAMP == rType && TSDB_DATA_TYPE_TIMESTAMP != lType) { + return rPrec; + } + + return 0; +} int32_t sclConvertOpValueNodeTs(SOperatorNode *node, SScalarCtx *ctx) { int32_t code = 0; - + if (node->pLeft && SCL_IS_VAR_VALUE_NODE(node->pLeft)) { if (node->pRight && (TSDB_DATA_TYPE_TIMESTAMP == ((SExprNode *)node->pRight)->resType.type)) { - SCL_ERR_JRET(sclConvertToTsValueNode(((SExprNode *)node->pRight)->resType.precision, (SValueNode*)node->pLeft)); + SCL_ERR_JRET( + sclConvertToTsValueNode(sclGetOpValueNodeTsPrecision(node->pLeft, node->pRight), (SValueNode *)node->pLeft)); } } else if (node->pRight && SCL_IS_NOTNULL_CONST_NODE(node->pRight)) { if (node->pLeft && (TSDB_DATA_TYPE_TIMESTAMP == ((SExprNode *)node->pLeft)->resType.type)) { if (SCL_IS_VAR_VALUE_NODE(node->pRight)) { - SCL_ERR_JRET(sclConvertToTsValueNode(((SExprNode *)node->pLeft)->resType.precision, (SValueNode*)node->pRight)); + SCL_ERR_JRET(sclConvertToTsValueNode(sclGetOpValueNodeTsPrecision(node->pLeft, node->pRight), + (SValueNode *)node->pRight)); } else if (QUERY_NODE_NODE_LIST == node->pRight->type) { - SNode* pNode; - FOREACH(pNode, ((SNodeListNode*)node->pRight)->pNodeList) { + SNode *pNode; + FOREACH(pNode, ((SNodeListNode *)node->pRight)->pNodeList) { if (SCL_IS_VAR_VALUE_NODE(pNode)) { - SCL_ERR_JRET(sclConvertToTsValueNode(((SExprNode *)node->pLeft)->resType.precision, (SValueNode*)pNode)); + SCL_ERR_JRET( + sclConvertToTsValueNode(sclGetOpValueNodeTsPrecision(node->pLeft, pNode), (SValueNode *)pNode)); } } } @@ -1063,29 +1090,28 @@ _return: return DEAL_RES_ERROR; } - - int32_t sclConvertCaseWhenValueNodeTs(SCaseWhenNode *node, SScalarCtx *ctx) { int32_t code = 0; if (NULL == node->pCase) { return TSDB_CODE_SUCCESS; } - + if (SCL_IS_VAR_VALUE_NODE(node->pCase)) { - SNode* pNode; + SNode *pNode; FOREACH(pNode, node->pWhenThenList) { SExprNode *pExpr = (SExprNode *)((SWhenThenNode *)pNode)->pWhen; if (TSDB_DATA_TYPE_TIMESTAMP == pExpr->resType.type) { - SCL_ERR_JRET(sclConvertToTsValueNode(pExpr->resType.precision, (SValueNode*)node->pCase)); + SCL_ERR_JRET(sclConvertToTsValueNode(pExpr->resType.precision, (SValueNode *)node->pCase)); break; } } } else if (TSDB_DATA_TYPE_TIMESTAMP == ((SExprNode *)node->pCase)->resType.type) { - SNode* pNode; + SNode *pNode; FOREACH(pNode, node->pWhenThenList) { if (SCL_IS_VAR_VALUE_NODE(((SWhenThenNode *)pNode)->pWhen)) { - SCL_ERR_JRET(sclConvertToTsValueNode(((SExprNode *)node->pCase)->resType.precision, (SValueNode*)((SWhenThenNode *)pNode)->pWhen)); + SCL_ERR_JRET(sclConvertToTsValueNode(((SExprNode *)node->pCase)->resType.precision, + (SValueNode *)((SWhenThenNode *)pNode)->pWhen)); } } } @@ -1248,7 +1274,6 @@ EDealRes sclRewriteLogic(SNode **pNode, SScalarCtx *ctx) { return DEAL_RES_CONTINUE; } - EDealRes sclRewriteOperator(SNode **pNode, SScalarCtx *ctx) { SOperatorNode *node = (SOperatorNode *)*pNode; diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index 411b9b7ab504176f77c691cce1b83452ec2267c0..df327075297428f9ba1d9cc717db913b4e33c931 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -43,7 +43,7 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu float *out = (float *)pOutputData->pData; for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } out[i] = (in[i] >= 0) ? in[i] : -in[i]; @@ -56,7 +56,7 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu double *out = (double *)pOutputData->pData; for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } out[i] = (in[i] >= 0) ? in[i] : -in[i]; @@ -69,7 +69,7 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu int8_t *out = (int8_t *)pOutputData->pData; for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } out[i] = (in[i] >= 0) ? in[i] : -in[i]; @@ -82,7 +82,7 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu int16_t *out = (int16_t *)pOutputData->pData; for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } out[i] = (in[i] >= 0) ? in[i] : -in[i]; @@ -95,7 +95,7 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu int32_t *out = (int32_t *)pOutputData->pData; for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } out[i] = (in[i] >= 0) ? in[i] : -in[i]; @@ -108,7 +108,7 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu int64_t *out = (int64_t *)pOutputData->pData; for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } out[i] = (in[i] >= 0) ? in[i] : -in[i]; @@ -118,7 +118,7 @@ int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu case TSDB_DATA_TYPE_NULL: { for (int32_t i = 0; i < pInput->numOfRows; ++i) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); } break; } @@ -144,12 +144,12 @@ static int32_t doScalarFunctionUnique(SScalarParam *pInput, int32_t inputNum, SS for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i) || IS_NULL_TYPE(type)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } double result = valFn(getValueFn(pInputData->pData, i)); if (isinf(result) || isnan(result)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); } else { out[i] = result; } @@ -179,29 +179,29 @@ static int32_t doScalarFunctionUnique2(SScalarParam *pInput, int32_t inputNum, S if (pInput[0].numOfRows == pInput[1].numOfRows) { for (int32_t i = 0; i < numOfRows; ++i) { if (colDataIsNull_s(pInputData[0], i) || colDataIsNull_s(pInputData[1], i) || hasNullType) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } result = valFn(getValueFn[0](pInputData[0]->pData, i), getValueFn[1](pInputData[1]->pData, i)); if (isinf(result) || isnan(result)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); } else { out[i] = result; } } } else if (pInput[0].numOfRows == 1) { // left operand is constant if (colDataIsNull_s(pInputData[0], 0) || hasNullType) { - colDataAppendNNULL(pOutputData, 0, pInput[1].numOfRows); + colDataSetNNULL(pOutputData, 0, pInput[1].numOfRows); } else { for (int32_t i = 0; i < numOfRows; ++i) { if (colDataIsNull_s(pInputData[1], i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } result = valFn(getValueFn[0](pInputData[0]->pData, 0), getValueFn[1](pInputData[1]->pData, i)); if (isinf(result) || isnan(result)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } @@ -210,17 +210,17 @@ static int32_t doScalarFunctionUnique2(SScalarParam *pInput, int32_t inputNum, S } } else if (pInput[1].numOfRows == 1) { if (colDataIsNull_s(pInputData[1], 0) || hasNullType) { - colDataAppendNNULL(pOutputData, 0, pInput[0].numOfRows); + colDataSetNNULL(pOutputData, 0, pInput[0].numOfRows); } else { for (int32_t i = 0; i < numOfRows; ++i) { if (colDataIsNull_s(pInputData[0], i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } result = valFn(getValueFn[0](pInputData[0]->pData, i), getValueFn[1](pInputData[1]->pData, 0)); if (isinf(result) || isnan(result)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } @@ -247,7 +247,7 @@ static int32_t doScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarP for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } out[i] = f1(in[i]); @@ -261,7 +261,7 @@ static int32_t doScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarP for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } out[i] = d1(in[i]); @@ -271,7 +271,7 @@ static int32_t doScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarP case TSDB_DATA_TYPE_NULL: { for (int32_t i = 0; i < pInput->numOfRows; ++i) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); } break; } @@ -365,7 +365,7 @@ static int32_t doLengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarP for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } @@ -447,7 +447,7 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu bool hasNull = false; for (int32_t i = 0; i < inputNum; ++i) { if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) { - colDataAppendNULL(pOutputData, k); + colDataSetNULL(pOutputData, k); hasNull = true; break; } @@ -468,7 +468,7 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu } } varDataSetLen(output, dataLen); - colDataAppend(pOutputData, k, output, false); + colDataSetVal(pOutputData, k, output, false); output += varDataTLen(output); } @@ -522,7 +522,7 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p for (int32_t k = 0; k < numOfRows; ++k) { if (colDataIsNull_s(pInputData[0], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0]))) { - colDataAppendNULL(pOutputData, k); + colDataSetNULL(pOutputData, k); continue; } @@ -553,11 +553,11 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p } if (hasNull) { - colDataAppendNULL(pOutputData, k); + colDataSetNULL(pOutputData, k); memset(output, 0, dataLen); } else { varDataSetLen(output, dataLen); - colDataAppend(pOutputData, k, output, false); + colDataSetVal(pOutputData, k, output, false); output += varDataTLen(output); } } @@ -584,7 +584,7 @@ static int32_t doCaseConvFunction(SScalarParam *pInput, int32_t inputNum, SScala for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } @@ -600,7 +600,7 @@ static int32_t doCaseConvFunction(SScalarParam *pInput, int32_t inputNum, SScala } } varDataSetLen(output, len); - colDataAppend(pOutputData, i, output, false); + colDataSetVal(pOutputData, i, output, false); output += varDataTLen(output); } @@ -622,7 +622,7 @@ static int32_t doTrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarPar for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } @@ -631,7 +631,7 @@ static int32_t doTrimFunction(SScalarParam *pInput, int32_t inputNum, SScalarPar int32_t charLen = (type == TSDB_DATA_TYPE_VARCHAR) ? len : len / TSDB_NCHAR_SIZE; trimFn(input, output, type, charLen); - colDataAppend(pOutputData, i, output, false); + colDataSetVal(pOutputData, i, output, false); output += varDataTLen(output); } @@ -660,7 +660,7 @@ int32_t substrFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } char *input = colDataGetData(pInput[0].columnData, i); @@ -682,7 +682,7 @@ int32_t substrFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu } varDataSetLen(output, resLen); - colDataAppend(pOutputData, i, output, false); + colDataSetVal(pOutputData, i, output, false); output += varDataTLen(output); } @@ -711,7 +711,7 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp for (int32_t i = 0; i < pInput[0].numOfRows; ++i) { if (colDataIsNull_s(pInput[0].columnData, i)) { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } @@ -1014,7 +1014,7 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp } } - colDataAppend(pOutput->columnData, i, output, false); + colDataSetVal(pOutput->columnData, i, output, false); } pOutput->numOfRows = pInput->numOfRows; @@ -1038,7 +1038,7 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam * for (int32_t i = 0; i < pInput[0].numOfRows; ++i) { if (colDataIsNull_s(pInput[0].columnData, i)) { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } @@ -1055,11 +1055,11 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam * if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) { timeVal = timeVal / 1000; } else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) { - timeVal = timeVal / (1000 * 1000); + timeVal = timeVal / ((int64_t)(1000 * 1000)); } else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) { - timeVal = timeVal / (1000 * 1000 * 1000); + timeVal = timeVal / ((int64_t)(1000 * 1000 * 1000)); } else { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } hasFraction = true; @@ -1067,9 +1067,15 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam * } struct tm tmInfo; - taosLocalTime((const time_t *)&timeVal, &tmInfo); + int32_t len = 0; + + if (taosLocalTime((const time_t *)&timeVal, &tmInfo, buf) == NULL) { + len = (int32_t)strlen(buf); + goto _end; + } + strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tmInfo); - int32_t len = (int32_t)strlen(buf); + len = (int32_t)strlen(buf); // add timezone string if (tzLen > 0) { @@ -1103,10 +1109,11 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam * len += fracLen; } +_end: memmove(buf + VARSTR_HEADER_SIZE, buf, len); varDataSetLen(buf, len); - colDataAppend(pOutput->columnData, i, buf, false); + colDataSetVal(pOutput->columnData, i, buf, false); } pOutput->numOfRows = pInput->numOfRows; @@ -1121,7 +1128,7 @@ int32_t toUnixtimestampFunction(SScalarParam *pInput, int32_t inputNum, SScalarP for (int32_t i = 0; i < pInput[0].numOfRows; ++i) { if (colDataIsNull_s(pInput[0].columnData, i)) { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } char *input = colDataGetData(pInput[0].columnData, i); @@ -1129,9 +1136,9 @@ int32_t toUnixtimestampFunction(SScalarParam *pInput, int32_t inputNum, SScalarP int64_t timeVal = 0; int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal); if (ret != TSDB_CODE_SUCCESS) { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); } else { - colDataAppend(pOutput->columnData, i, (char *)&timeVal, false); + colDataSetVal(pOutput->columnData, i, (char *)&timeVal, false); } } @@ -1163,7 +1170,7 @@ int32_t toJsonFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu } } - colDataAppend(pOutput->columnData, i, (const char *)pTag, false); + colDataSetVal(pOutput->columnData, i, (const char *)pTag, false); tTagFree(pTag); taosArrayDestroy(pTagVals); } @@ -1208,7 +1215,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara for (int32_t i = 0; i < pInput[0].numOfRows; ++i) { if (colDataIsNull_s(pInput[0].columnData, i)) { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } @@ -1217,7 +1224,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */ int32_t ret = convertStringToTimestamp(type, input, TSDB_TIME_PRECISION_NANO, &timeVal); if (ret != TSDB_CODE_SUCCESS) { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } // If converted value is less than 10digits in second, use value in second instead @@ -1264,7 +1271,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara } else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) { timeVal = timeVal * factor; } else { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } break; @@ -1279,7 +1286,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara } else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) { timeVal = timeVal * factor; } else { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } break; @@ -1294,7 +1301,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara } else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) { timeVal = timeVal * factor / factor / 60 * 60 * factor; } else { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } break; @@ -1309,7 +1316,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara } else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) { timeVal = timeVal * factor / factor / 3600 * 3600 * factor; } else { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } break; @@ -1317,19 +1324,19 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara case 86400000: { /* 1d */ if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) { if (ignoreTz) { - timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000)) % (86400L * 1000); + timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000)) % (((int64_t)86400) * 1000); } else { timeVal = timeVal / 1000 / 86400 * 86400 * 1000; } } else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) { if (ignoreTz) { - timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000000)) % (86400L * 1000000); + timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000000)) % (((int64_t)86400) * 1000000); } else { timeVal = timeVal / 1000000 / 86400 * 86400 * 1000000; } } else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) { if (ignoreTz) { - timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000000000)) % (86400L * 1000000000); + timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000000000)) % (((int64_t)86400) * 1000000000); } else { timeVal = timeVal / 1000000000 / 86400 * 86400 * 1000000000; } @@ -1340,7 +1347,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara timeVal = timeVal * factor / factor / 86400 * 86400 * factor; } } else { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } break; @@ -1355,7 +1362,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara } else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) { timeVal = timeVal * factor / factor / 604800 * 604800 * factor; } else { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } break; @@ -1394,7 +1401,7 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara } } - colDataAppend(pOutput->columnData, i, (char *)&timeVal, false); + colDataSetVal(pOutput->columnData, i, (char *)&timeVal, false); } pOutput->numOfRows = pInput->numOfRows; @@ -1466,7 +1473,7 @@ int32_t timeDiffFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p } if (hasNull) { - colDataAppendNULL(pOutput->columnData, i); + colDataSetNULL(pOutput->columnData, i); continue; } @@ -1528,7 +1535,7 @@ int32_t timeDiffFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p } } - colDataAppend(pOutput->columnData, i, (char *)&result, false); + colDataSetVal(pOutput->columnData, i, (char *)&result, false); } pOutput->numOfRows = numOfRows; @@ -1542,7 +1549,7 @@ int32_t nowFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu int64_t ts = taosGetTimestamp(timePrec); for (int32_t i = 0; i < pInput->numOfRows; ++i) { - colDataAppendInt64(pOutput->columnData, i, &ts); + colDataSetInt64(pOutput->columnData, i, &ts); } pOutput->numOfRows = pInput->numOfRows; return TSDB_CODE_SUCCESS; @@ -1554,7 +1561,7 @@ int32_t todayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOut int64_t ts = taosGetTimestampToday(timePrec); for (int32_t i = 0; i < pInput->numOfRows; ++i) { - colDataAppendInt64(pOutput->columnData, i, &ts); + colDataSetInt64(pOutput->columnData, i, &ts); } pOutput->numOfRows = pInput->numOfRows; return TSDB_CODE_SUCCESS; @@ -1565,7 +1572,7 @@ int32_t timezoneFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p memcpy(varDataVal(output), tsTimezoneStr, TD_TIMEZONE_LEN); varDataSetLen(output, strlen(tsTimezoneStr)); for (int32_t i = 0; i < pInput->numOfRows; ++i) { - colDataAppend(pOutput->columnData, i, output, false); + colDataSetVal(pOutput->columnData, i, output, false); } pOutput->numOfRows = pInput->numOfRows; return TSDB_CODE_SUCCESS; @@ -1655,107 +1662,44 @@ int32_t charLengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam return doLengthFunction(pInput, inputNum, pOutput, tcharlength); } -#if 0 -static void reverseCopy(char* dest, const char* src, int16_t type, int32_t numOfRows) { - switch(type) { - case TSDB_DATA_TYPE_TINYINT: - case TSDB_DATA_TYPE_UTINYINT:{ - int8_t* p = (int8_t*) dest; - int8_t* pSrc = (int8_t*) src; - - for(int32_t i = 0; i < numOfRows; ++i) { - p[i] = pSrc[numOfRows - i - 1]; - } - return; - } - - case TSDB_DATA_TYPE_SMALLINT: - case TSDB_DATA_TYPE_USMALLINT:{ - int16_t* p = (int16_t*) dest; - int16_t* pSrc = (int16_t*) src; - - for(int32_t i = 0; i < numOfRows; ++i) { - p[i] = pSrc[numOfRows - i - 1]; - } - return; - } - case TSDB_DATA_TYPE_INT: - case TSDB_DATA_TYPE_UINT: { - int32_t* p = (int32_t*) dest; - int32_t* pSrc = (int32_t*) src; - - for(int32_t i = 0; i < numOfRows; ++i) { - p[i] = pSrc[numOfRows - i - 1]; - } - return; - } - case TSDB_DATA_TYPE_BIGINT: - case TSDB_DATA_TYPE_UBIGINT: { - int64_t* p = (int64_t*) dest; - int64_t* pSrc = (int64_t*) src; - - for(int32_t i = 0; i < numOfRows; ++i) { - p[i] = pSrc[numOfRows - i - 1]; - } - return; - } - case TSDB_DATA_TYPE_FLOAT: { - float* p = (float*) dest; - float* pSrc = (float*) src; - - for(int32_t i = 0; i < numOfRows; ++i) { - p[i] = pSrc[numOfRows - i - 1]; - } - return; - } - case TSDB_DATA_TYPE_DOUBLE: { - double* p = (double*) dest; - double* pSrc = (double*) src; - - for(int32_t i = 0; i < numOfRows; ++i) { - p[i] = pSrc[numOfRows - i - 1]; - } - return; - } - default: assert(0); - } -} -#endif - bool getTimePseudoFuncEnv(SFunctionNode *UNUSED_PARAM(pFunc), SFuncExecEnv *pEnv) { pEnv->calcMemSize = sizeof(int64_t); return true; } int32_t qStartTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { - colDataAppendInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 0)); + colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 0)); return TSDB_CODE_SUCCESS; } int32_t qEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { - colDataAppendInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 1)); + colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 1)); return TSDB_CODE_SUCCESS; } int32_t winDurFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { - colDataAppendInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 2)); + colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 2)); return TSDB_CODE_SUCCESS; } int32_t winStartTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { - colDataAppendInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 3)); + colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 3)); return TSDB_CODE_SUCCESS; } int32_t winEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { - colDataAppendInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 4)); + colDataSetInt64(pOutput->columnData, pOutput->numOfRows, (int64_t *)colDataGetData(pInput->columnData, 4)); return TSDB_CODE_SUCCESS; } int32_t qTbnameFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { char* p = colDataGetVarData(pInput->columnData, 0); - colDataAppendNItems(pOutput->columnData, pOutput->numOfRows, p, pInput->numOfRows); + int32_t code = colDataSetNItems(pOutput->columnData, pOutput->numOfRows, p, pInput->numOfRows, true); + if (code) { + return code; + } + pOutput->numOfRows += pInput->numOfRows; return TSDB_CODE_SUCCESS; } @@ -1833,7 +1777,7 @@ int32_t sumScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam * } if (hasNull) { - colDataAppendNULL(pOutputData, 0); + colDataSetNULL(pOutputData, 0); } pOutput->numOfRows = 1; @@ -1945,7 +1889,7 @@ static int32_t doMinMaxScalarFunction(SScalarParam *pInput, int32_t inputNum, SS } if (hasNull) { - colDataAppendNULL(pOutputData, 0); + colDataSetNULL(pOutputData, 0); } pOutput->numOfRows = 1; @@ -2049,7 +1993,7 @@ int32_t avgScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam * } if (hasNull || (count == 0)) { - colDataAppendNULL(pOutputData, 0); + colDataSetNULL(pOutputData, 0); } else { if (IS_SIGNED_NUMERIC_TYPE(type)) { int64_t *out = (int64_t *)pOutputData->pData; @@ -2158,7 +2102,7 @@ int32_t stddevScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara double *out = (double *)pOutputData->pData; if (hasNull) { - colDataAppendNULL(pOutputData, 0); + colDataSetNULL(pOutputData, 0); } else { *out = 0; #if 0 @@ -2325,7 +2269,7 @@ int32_t leastSQRScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarPa } if (count == 0) { - colDataAppendNULL(pOutputData, 0); + colDataSetNULL(pOutputData, 0); } else { matrix[1][1] = (double)count; matrix[1][0] = matrix[0][1]; @@ -2341,7 +2285,7 @@ int32_t leastSQRScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarPa size_t len = snprintf(varDataVal(buf), sizeof(buf) - VARSTR_HEADER_SIZE, "{slop:%.6lf, intercept:%.6lf}", matrix02, matrix12); varDataSetLen(buf, len); - colDataAppend(pOutputData, 0, buf, false); + colDataSetVal(pOutputData, 0, buf, false); } pOutput->numOfRows = 1; @@ -2366,9 +2310,9 @@ int32_t percentileScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalar } if (hasNull) { - colDataAppendNULL(pOutputData, 0); + colDataSetNULL(pOutputData, 0); } else { - colDataAppend(pOutputData, 0, (char *)&val, false); + colDataSetVal(pOutputData, 0, (char *)&val, false); } pOutput->numOfRows = 1; @@ -2411,10 +2355,10 @@ int32_t spreadScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara } if (hasNull) { - colDataAppendNULL(pOutputData, 0); + colDataSetNULL(pOutputData, 0); } else { double result = max - min; - colDataAppend(pOutputData, 0, (char *)&result, false); + colDataSetVal(pOutputData, 0, (char *)&result, false); } pOutput->numOfRows = 1; @@ -2437,7 +2381,7 @@ int32_t nonCalcScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarPar double *out = (double *)pOutputData->pData; if (hasNull) { - colDataAppendNULL(pOutputData, 0); + colDataSetNULL(pOutputData, 0); } else { *out = 0; } @@ -2606,7 +2550,7 @@ int32_t stateCountScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalar for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } @@ -2617,7 +2561,7 @@ int32_t stateCountScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalar } else { count = 0; } - colDataAppend(pOutputData, i, (char *)&out, false); + colDataSetVal(pOutputData, i, (char *)&out, false); } pOutput->numOfRows = pInput->numOfRows; @@ -2632,7 +2576,7 @@ int32_t stateDurationScalarFunction(SScalarParam *pInput, int32_t inputNum, SSca for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, i); + colDataSetNULL(pOutputData, i); continue; } @@ -2641,7 +2585,7 @@ int32_t stateDurationScalarFunction(SScalarParam *pInput, int32_t inputNum, SSca if (ret) { out = 0; } - colDataAppend(pOutputData, i, (char *)&out, false); + colDataSetVal(pOutputData, i, (char *)&out, false); } pOutput->numOfRows = pInput->numOfRows; @@ -2882,7 +2826,7 @@ int32_t histogramScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarP bins[k].upper, bins[k].percentage); } varDataSetLen(buf, len); - colDataAppend(pOutputData, k, buf, false); + colDataSetVal(pOutputData, k, buf, false); } taosMemoryFree(bins); @@ -2898,12 +2842,12 @@ int32_t selectScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara for (int32_t i = 0; i < pInput->numOfRows; ++i) { if (colDataIsNull_s(pInputData, i)) { - colDataAppendNULL(pOutputData, 0); + colDataSetNULL(pOutputData, 0); continue; } char *data = colDataGetData(pInputData, i); - colDataAppend(pOutputData, i, data, false); + colDataSetVal(pOutputData, i, data, false); } pOutput->numOfRows = 1; diff --git a/source/libs/scalar/src/sclvector.c b/source/libs/scalar/src/sclvector.c index e9f345215e5c7eb5792a7141484ca244be560c75..4d803cb6388c75211dcea9db6a0dc353b91c71aa 100644 --- a/source/libs/scalar/src/sclvector.c +++ b/source/libs/scalar/src/sclvector.c @@ -242,7 +242,7 @@ static FORCE_INLINE void varToTimestamp(char *buf, SScalarParam *pOut, int32_t r value = 0; } - colDataAppendInt64(pOut->columnData, rowIndex, &value); + colDataSetInt64(pOut->columnData, rowIndex, &value); } static FORCE_INLINE void varToSigned(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { @@ -265,22 +265,22 @@ static FORCE_INLINE void varToSigned(char *buf, SScalarParam *pOut, int32_t rowI case TSDB_DATA_TYPE_TINYINT: { int8_t value = (int8_t)taosStr2Int8(buf, NULL, 10); - colDataAppendInt8(pOut->columnData, rowIndex, (int8_t *)&value); + colDataSetInt8(pOut->columnData, rowIndex, (int8_t *)&value); break; } case TSDB_DATA_TYPE_SMALLINT: { int16_t value = (int16_t)taosStr2Int16(buf, NULL, 10); - colDataAppendInt16(pOut->columnData, rowIndex, (int16_t *)&value); + colDataSetInt16(pOut->columnData, rowIndex, (int16_t *)&value); break; } case TSDB_DATA_TYPE_INT: { int32_t value = (int32_t)taosStr2Int32(buf, NULL, 10); - colDataAppendInt32(pOut->columnData, rowIndex, (int32_t *)&value); + colDataSetInt32(pOut->columnData, rowIndex, (int32_t *)&value); break; } case TSDB_DATA_TYPE_BIGINT: { int64_t value = (int64_t)taosStr2Int64(buf, NULL, 10); - colDataAppendInt64(pOut->columnData, rowIndex, (int64_t *)&value); + colDataSetInt64(pOut->columnData, rowIndex, (int64_t *)&value); break; } } @@ -305,22 +305,22 @@ static FORCE_INLINE void varToUnsigned(char *buf, SScalarParam *pOut, int32_t ro switch (pOut->columnData->info.type) { case TSDB_DATA_TYPE_UTINYINT: { uint8_t value = (uint8_t)taosStr2UInt8(buf, NULL, 10); - colDataAppendInt8(pOut->columnData, rowIndex, (int8_t *)&value); + colDataSetInt8(pOut->columnData, rowIndex, (int8_t *)&value); break; } case TSDB_DATA_TYPE_USMALLINT: { uint16_t value = (uint16_t)taosStr2UInt16(buf, NULL, 10); - colDataAppendInt16(pOut->columnData, rowIndex, (int16_t *)&value); + colDataSetInt16(pOut->columnData, rowIndex, (int16_t *)&value); break; } case TSDB_DATA_TYPE_UINT: { uint32_t value = (uint32_t)taosStr2UInt32(buf, NULL, 10); - colDataAppendInt32(pOut->columnData, rowIndex, (int32_t *)&value); + colDataSetInt32(pOut->columnData, rowIndex, (int32_t *)&value); break; } case TSDB_DATA_TYPE_UBIGINT: { uint64_t value = (uint64_t)taosStr2UInt64(buf, NULL, 10); - colDataAppendInt64(pOut->columnData, rowIndex, (int64_t *)&value); + colDataSetInt64(pOut->columnData, rowIndex, (int64_t *)&value); break; } } @@ -329,18 +329,18 @@ static FORCE_INLINE void varToUnsigned(char *buf, SScalarParam *pOut, int32_t ro static FORCE_INLINE void varToFloat(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { if (TSDB_DATA_TYPE_FLOAT == pOut->columnData->info.type) { float value = taosStr2Float(buf, NULL); - colDataAppendFloat(pOut->columnData, rowIndex, &value); + colDataSetFloat(pOut->columnData, rowIndex, &value); return; } double value = taosStr2Double(buf, NULL); - colDataAppendDouble(pOut->columnData, rowIndex, &value); + colDataSetDouble(pOut->columnData, rowIndex, &value); } static FORCE_INLINE void varToBool(char *buf, SScalarParam *pOut, int32_t rowIndex, int32_t *overflow) { int64_t value = taosStr2Int64(buf, NULL, 10); bool v = (value != 0) ? true : false; - colDataAppendInt8(pOut->columnData, rowIndex, (int8_t *)&v); + colDataSetInt8(pOut->columnData, rowIndex, (int8_t *)&v); } // todo remove this malloc @@ -357,7 +357,7 @@ static FORCE_INLINE void varToNchar(char *buf, SScalarParam *pOut, int32_t rowIn } varDataSetLen(t, len); - colDataAppend(pOut->columnData, rowIndex, t, false); + colDataSetVal(pOut->columnData, rowIndex, t, false); taosMemoryFree(t); } @@ -372,7 +372,7 @@ static FORCE_INLINE void ncharToVar(char *buf, SScalarParam *pOut, int32_t rowIn } varDataSetLen(t, len); - colDataAppend(pOut->columnData, rowIndex, t, false); + colDataSetVal(pOut->columnData, rowIndex, t, false); taosMemoryFree(t); } @@ -409,7 +409,7 @@ int32_t vectorConvertFromVarData(SSclVectorConvCtx *pCtx, int32_t *overflow) { for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (IS_HELPER_NULL(pCtx->pIn->columnData, i)) { - colDataAppendNULL(pCtx->pOut->columnData, i); + colDataSetNULL(pCtx->pOut->columnData, i); continue; } @@ -599,7 +599,7 @@ int32_t vectorConvertToVarData(SSclVectorConvCtx *pCtx) { pCtx->inType == TSDB_DATA_TYPE_TIMESTAMP) { for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } @@ -610,13 +610,13 @@ int32_t vectorConvertToVarData(SSclVectorConvCtx *pCtx) { if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { varToNchar(tmp, pCtx->pOut, i, NULL); } else { - colDataAppend(pOutputCol, i, (char *)tmp, false); + colDataSetVal(pOutputCol, i, (char *)tmp, false); } } } else if (IS_UNSIGNED_NUMERIC_TYPE(pCtx->inType)) { for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } @@ -627,13 +627,13 @@ int32_t vectorConvertToVarData(SSclVectorConvCtx *pCtx) { if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { varToNchar(tmp, pCtx->pOut, i, NULL); } else { - colDataAppend(pOutputCol, i, (char *)tmp, false); + colDataSetVal(pOutputCol, i, (char *)tmp, false); } } } else if (IS_FLOAT_TYPE(pCtx->inType)) { for (int32_t i = pCtx->startIndex; i <= pCtx->endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } @@ -644,7 +644,7 @@ int32_t vectorConvertToVarData(SSclVectorConvCtx *pCtx) { if (pCtx->outType == TSDB_DATA_TYPE_NCHAR) { varToNchar(tmp, pCtx->pOut, i, NULL); } else { - colDataAppend(pOutputCol, i, (char *)tmp, false); + colDataSetVal(pOutputCol, i, (char *)tmp, false); } } } else { @@ -722,52 +722,52 @@ int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut, case TSDB_DATA_TYPE_BOOL: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } bool value = 0; GET_TYPED_DATA(value, bool, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendInt8(pOutputCol, i, (int8_t *)&value); + colDataSetInt8(pOutputCol, i, (int8_t *)&value); } break; } case TSDB_DATA_TYPE_TINYINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } int8_t value = 0; GET_TYPED_DATA(value, int8_t, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendInt8(pOutputCol, i, (int8_t *)&value); + colDataSetInt8(pOutputCol, i, (int8_t *)&value); } break; } case TSDB_DATA_TYPE_SMALLINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } int16_t value = 0; GET_TYPED_DATA(value, int16_t, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendInt16(pOutputCol, i, (int16_t *)&value); + colDataSetInt16(pOutputCol, i, (int16_t *)&value); } break; } case TSDB_DATA_TYPE_INT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } int32_t value = 0; GET_TYPED_DATA(value, int32_t, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendInt32(pOutputCol, i, (int32_t *)&value); + colDataSetInt32(pOutputCol, i, (int32_t *)&value); } break; } @@ -775,91 +775,91 @@ int32_t vectorConvertSingleColImpl(const SScalarParam *pIn, SScalarParam *pOut, case TSDB_DATA_TYPE_TIMESTAMP: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } int64_t value = 0; GET_TYPED_DATA(value, int64_t, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendInt64(pOutputCol, i, (int64_t *)&value); + colDataSetInt64(pOutputCol, i, (int64_t *)&value); } break; } case TSDB_DATA_TYPE_UTINYINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } uint8_t value = 0; GET_TYPED_DATA(value, uint8_t, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendInt8(pOutputCol, i, (int8_t *)&value); + colDataSetInt8(pOutputCol, i, (int8_t *)&value); } break; } case TSDB_DATA_TYPE_USMALLINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } uint16_t value = 0; GET_TYPED_DATA(value, uint16_t, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendInt16(pOutputCol, i, (int16_t *)&value); + colDataSetInt16(pOutputCol, i, (int16_t *)&value); } break; } case TSDB_DATA_TYPE_UINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } uint32_t value = 0; GET_TYPED_DATA(value, uint32_t, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendInt32(pOutputCol, i, (int32_t *)&value); + colDataSetInt32(pOutputCol, i, (int32_t *)&value); } break; } case TSDB_DATA_TYPE_UBIGINT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } uint64_t value = 0; GET_TYPED_DATA(value, uint64_t, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendInt64(pOutputCol, i, (int64_t *)&value); + colDataSetInt64(pOutputCol, i, (int64_t *)&value); } break; } case TSDB_DATA_TYPE_FLOAT: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } float value = 0; GET_TYPED_DATA(value, float, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendFloat(pOutputCol, i, (float *)&value); + colDataSetFloat(pOutputCol, i, (float *)&value); } break; } case TSDB_DATA_TYPE_DOUBLE: { for (int32_t i = cCtx.startIndex; i <= cCtx.endIndex; ++i) { if (colDataIsNull_f(pInputCol->nullbitmap, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } double value = 0; GET_TYPED_DATA(value, double, cCtx.inType, colDataGetData(pInputCol, i)); - colDataAppendDouble(pOutputCol, i, (double *)&value); + colDataSetDouble(pOutputCol, i, (double *)&value); } break; } @@ -915,6 +915,7 @@ int32_t vectorConvertSingleCol(SScalarParam *input, SScalarParam *output, int32_ SDataType t = {.type = type}; t.bytes = IS_VAR_DATA_TYPE(t.type)? input->columnData->info.bytes:tDataTypes[type].bytes; + t.precision = input->columnData->info.precision; int32_t code = sclCreateColumnInfoData(&t, input->numOfRows, output); if (code != TSDB_CODE_SUCCESS) { @@ -1007,11 +1008,11 @@ static void vectorMathAddHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRig double *output = (double *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, numOfRows); + colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) + getVectorDoubleValueFnRight(RIGHT_COL, 0); @@ -1027,11 +1028,11 @@ static void vectorMathTsAddHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pR int64_t *output = (int64_t *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, numOfRows); + colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = @@ -1103,7 +1104,7 @@ void vectorMathAdd(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut } else if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(pLeftCol->pData, i) + getVectorBigintValueFnRight(pRightCol->pData, i); @@ -1117,7 +1118,7 @@ void vectorMathAdd(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) + getVectorDoubleValueFnRight(RIGHT_COL, i); @@ -1142,11 +1143,11 @@ static void vectorMathSubHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRig double *output = (double *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, numOfRows); + colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = (getVectorDoubleValueFnLeft(LEFT_COL, i) - getVectorDoubleValueFnRight(RIGHT_COL, 0)) * factor; @@ -1162,11 +1163,11 @@ static void vectorMathTsSubHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pR int64_t *output = (int64_t *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, numOfRows); + colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = @@ -1204,7 +1205,7 @@ void vectorMathSub(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut } else if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(pLeftCol->pData, i) - getVectorBigintValueFnRight(pRightCol->pData, i); @@ -1218,7 +1219,7 @@ void vectorMathSub(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) - getVectorDoubleValueFnRight(RIGHT_COL, i); @@ -1243,11 +1244,11 @@ static void vectorMathMultiplyHelper(SColumnInfoData *pLeftCol, SColumnInfoData double *output = (double *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, numOfRows); + colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) * getVectorDoubleValueFnRight(RIGHT_COL, 0); @@ -1273,7 +1274,7 @@ void vectorMathMultiply(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) * getVectorDoubleValueFnRight(RIGHT_COL, i); @@ -1306,18 +1307,18 @@ void vectorMathDivide(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *p if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL || (getVectorDoubleValueFnRight(RIGHT_COL, i) == 0)) { // divide by 0 check - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) / getVectorDoubleValueFnRight(RIGHT_COL, i); } } else if (pLeft->numOfRows == 1) { if (IS_HELPER_NULL(pLeftCol, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, pRight->numOfRows); + colDataSetNNULL(pOutputCol, 0, pRight->numOfRows); } else { for (; i >= 0 && i < pRight->numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pRightCol, i) || (getVectorDoubleValueFnRight(RIGHT_COL, i) == 0)) { // divide by 0 check - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } *output = getVectorDoubleValueFnLeft(LEFT_COL, 0) / getVectorDoubleValueFnRight(RIGHT_COL, i); @@ -1326,11 +1327,11 @@ void vectorMathDivide(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *p } else if (pRight->numOfRows == 1) { if (IS_HELPER_NULL(pRightCol, 0) || (getVectorDoubleValueFnRight(RIGHT_COL, 0) == 0)) { // Set pLeft->numOfRows NULL value (divde by 0 check) - colDataAppendNNULL(pOutputCol, 0, pLeft->numOfRows); + colDataSetNNULL(pOutputCol, 0, pLeft->numOfRows); } else { for (; i >= 0 && i < pLeft->numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } *output = getVectorDoubleValueFnLeft(LEFT_COL, i) / getVectorDoubleValueFnRight(RIGHT_COL, 0); @@ -1361,14 +1362,14 @@ void vectorMathRemainder(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } double lx = getVectorDoubleValueFnLeft(LEFT_COL, i); double rx = getVectorDoubleValueFnRight(RIGHT_COL, i); if (isnan(lx) || isinf(lx) || isnan(rx) || isinf(rx) || FLT_EQUAL(rx, 0)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } @@ -1377,17 +1378,17 @@ void vectorMathRemainder(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam } else if (pLeft->numOfRows == 1) { double lx = getVectorDoubleValueFnLeft(LEFT_COL, 0); if (IS_HELPER_NULL(pLeftCol, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, pRight->numOfRows); + colDataSetNNULL(pOutputCol, 0, pRight->numOfRows); } else { for (; i >= 0 && i < pRight->numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pRightCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } double rx = getVectorDoubleValueFnRight(RIGHT_COL, i); if (isnan(rx) || isinf(rx) || FLT_EQUAL(rx, 0)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } @@ -1397,17 +1398,17 @@ void vectorMathRemainder(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam } else if (pRight->numOfRows == 1) { double rx = getVectorDoubleValueFnRight(RIGHT_COL, 0); if (IS_HELPER_NULL(pRightCol, 0) || FLT_EQUAL(rx, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, pLeft->numOfRows); + colDataSetNNULL(pOutputCol, 0, pLeft->numOfRows); } else { for (; i >= 0 && i < pLeft->numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } double lx = getVectorDoubleValueFnLeft(LEFT_COL, i); if (isnan(lx) || isinf(lx)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } @@ -1436,7 +1437,7 @@ void vectorMathMinus(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pO double *output = (double *)pOutputCol->pData; for (; i < pLeft->numOfRows && i >= 0; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; } double result = getVectorDoubleValueFnLeft(LEFT_COL, i); @@ -1451,11 +1452,11 @@ void vectorAssign(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, pOut->numOfRows = pLeft->numOfRows; if (colDataIsNull_s(pRight->columnData, 0)) { - colDataAppendNNULL(pOutputCol, 0, pOut->numOfRows); + colDataSetNNULL(pOutputCol, 0, pOut->numOfRows); } else { char *d = colDataGetData(pRight->columnData, 0); for (int32_t i = 0; i < pOut->numOfRows; ++i) { - colDataAppend(pOutputCol, i, d, false); + colDataSetVal(pOutputCol, i, d, false); } } @@ -1471,11 +1472,11 @@ static void vectorBitAndHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRigh int64_t *output = (int64_t *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, numOfRows); + colDataSetNNULL(pOutputCol, 0, numOfRows); } else { for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(LEFT_COL, i) & getVectorBigintValueFnRight(RIGHT_COL, 0); @@ -1501,7 +1502,7 @@ void vectorBitAnd(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(LEFT_COL, i) & getVectorBigintValueFnRight(RIGHT_COL, i); @@ -1524,12 +1525,12 @@ static void vectorBitOrHelper(SColumnInfoData *pLeftCol, SColumnInfoData *pRight int64_t *output = (int64_t *)pOutputCol->pData; if (IS_HELPER_NULL(pRightCol, 0)) { // Set pLeft->numOfRows NULL value - colDataAppendNNULL(pOutputCol, 0, numOfRows); + colDataSetNNULL(pOutputCol, 0, numOfRows); } else { int64_t rx = getVectorBigintValueFnRight(RIGHT_COL, 0); for (; i >= 0 && i < numOfRows; i += step, output += 1) { if (IS_HELPER_NULL(pLeftCol, i)) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(LEFT_COL, i) | rx; @@ -1555,7 +1556,7 @@ void vectorBitOr(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, if (pLeft->numOfRows == pRight->numOfRows) { for (; i < pRight->numOfRows && i >= 0; i += step, output += 1) { if (IS_NULL) { - colDataAppendNULL(pOutputCol, i); + colDataSetNULL(pOutputCol, i); continue; // TODO set null or ignore } *output = getVectorBigintValueFnLeft(LEFT_COL, i) | getVectorBigintValueFnRight(RIGHT_COL, i); @@ -1617,7 +1618,7 @@ int32_t doVectorCompareImpl(SScalarParam *pLeft, SScalarParam *pRight, SScalarPa if (IS_HELPER_NULL(pLeft->columnData, leftIndex) || IS_HELPER_NULL(pRight->columnData, rightIndex)) { bool res = false; - colDataAppendInt8(pOut->columnData, i, (int8_t *)&res); + colDataSetInt8(pOut->columnData, i, (int8_t *)&res); continue; } @@ -1640,10 +1641,10 @@ int32_t doVectorCompareImpl(SScalarParam *pLeft, SScalarParam *pRight, SScalarPa } if (!result) { - colDataAppendInt8(pOut->columnData, i, (int8_t *)&result); + colDataSetInt8(pOut->columnData, i, (int8_t *)&result); } else { bool res = filterDoCompare(fp, optr, pLeftData, pRightData); - colDataAppendInt8(pOut->columnData, i, (int8_t *)&res); + colDataSetInt8(pOut->columnData, i, (int8_t *)&res); if (res) { ++num; } @@ -1690,13 +1691,13 @@ void doVectorCompare(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pO for (; i >= 0 && i < pLeft->numOfRows; i += step) { if (IS_HELPER_NULL(pLeft->columnData, i)) { bool res = false; - colDataAppendInt8(pOut->columnData, i, (int8_t *)&res); + colDataSetInt8(pOut->columnData, i, (int8_t *)&res); continue; } char *pLeftData = colDataGetData(pLeft->columnData, i); bool res = filterDoCompare(fp, optr, pLeftData, pRight->pHashFilter); - colDataAppendInt8(pOut->columnData, i, (int8_t *)&res); + colDataSetInt8(pOut->columnData, i, (int8_t *)&res); if (res) { pOut->numOfQualified++; } @@ -1783,7 +1784,7 @@ void vectorNotMatch(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOu void vectorIsNull(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { for (int32_t i = 0; i < pLeft->numOfRows; ++i) { int8_t v = IS_HELPER_NULL(pLeft->columnData, i) ? 1 : 0; - colDataAppendInt8(pOut->columnData, i, &v); + colDataSetInt8(pOut->columnData, i, &v); } pOut->numOfRows = pLeft->numOfRows; } @@ -1791,7 +1792,7 @@ void vectorIsNull(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, void vectorNotNull(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, int32_t _ord) { for (int32_t i = 0; i < pLeft->numOfRows; ++i) { int8_t v = IS_HELPER_NULL(pLeft->columnData, i) ? 0 : 1; - colDataAppendInt8(pOut->columnData, i, &v); + colDataSetInt8(pOut->columnData, i, &v); } pOut->numOfRows = pLeft->numOfRows; } @@ -1801,7 +1802,7 @@ void vectorIsTrue(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pOut, for (int32_t i = 0; i < pOut->numOfRows; ++i) { if (colDataIsNull_s(pOut->columnData, i)) { int8_t v = 0; - colDataAppendInt8(pOut->columnData, i, &v); + colDataSetInt8(pOut->columnData, i, &v); colDataClearNull_f(pOut->columnData->nullbitmap, i); } } @@ -1844,7 +1845,7 @@ void vectorJsonContains(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam getJsonValue(pLeftData, jsonKey, &isExist); } - colDataAppend(pOutputCol, i, (const char *)(&isExist), false); + colDataSetVal(pOutputCol, i, (const char *)(&isExist), false); } taosMemoryFree(jsonKey); } @@ -1870,7 +1871,7 @@ void vectorJsonArrow(SScalarParam *pLeft, SScalarParam *pRight, SScalarParam *pO bool isExist = false; STagVal value = getJsonValue(pLeftData, jsonKey, &isExist); char *data = isExist ? tTagValToData(&value, true) : NULL; - colDataAppend(pOutputCol, i, data, data == NULL); + colDataSetVal(pOutputCol, i, data, data == NULL); if (isExist && IS_VAR_DATA_TYPE(value.type) && data) { taosMemoryFree(data); } diff --git a/source/libs/scalar/test/CMakeLists.txt b/source/libs/scalar/test/CMakeLists.txt index 32f5e098c5c2c17961dad115a455377c228edf20..caaf86264c579196c9e5b8988a6c633ef1a70d2c 100644 --- a/source/libs/scalar/test/CMakeLists.txt +++ b/source/libs/scalar/test/CMakeLists.txt @@ -1,4 +1,4 @@ enable_testing() -#add_subdirectory(filter) +add_subdirectory(filter) add_subdirectory(scalar) diff --git a/source/libs/scalar/test/filter/filterTests.cpp b/source/libs/scalar/test/filter/filterTests.cpp index 2f518e2e597ba7e08f60eb1df72c5d349777880c..51ee9b6570f571f9e06917c3f712064dfd66ee7d 100644 --- a/source/libs/scalar/test/filter/filterTests.cpp +++ b/source/libs/scalar/test/filter/filterTests.cpp @@ -33,6 +33,7 @@ #include "os.h" #include "filter.h" +#include "filterInt.h" #include "nodes.h" #include "scalar.h" #include "stub.h" @@ -111,7 +112,7 @@ void flttMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pColumn, i, (const char *)value, false); + colDataSetVal(pColumn, i, (const char *)value, false); if (IS_VAR_DATA_TYPE(dataType)) { value = (char *)value + varDataTLen(value); } else { @@ -135,7 +136,7 @@ void flttMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pColumn, i, (const char *)value, false); + colDataSetVal(pColumn, i, (const char *)value, false); if (IS_VAR_DATA_TYPE(dataType)) { value = (char *)value + varDataTLen(value); } else { @@ -344,6 +345,7 @@ TEST(timerangeTest, greater_and_lower_not_strict) { nodesDestroyNode(logicNode1); } +#if 0 TEST(columnTest, smallint_column_greater_double_value) { SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL; int16_t leftv[5] = {1, 2, 3, 4, 5}; @@ -634,8 +636,8 @@ TEST(columnTest, binary_column_is_null) { flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv); SColumnInfoData *pcolumn = (SColumnInfoData *)taosArrayGetLast(src->pDataBlock); - colDataAppend(pcolumn, 2, NULL, true); - colDataAppend(pcolumn, 4, NULL, true); + colDataSetVal(pcolumn, 2, NULL, true); + colDataSetVal(pcolumn, 4, NULL, true); flttMakeOpNode(&opNode, OP_TYPE_IS_NULL, TSDB_DATA_TYPE_BOOL, pLeft, NULL); SFilterInfo *filter = NULL; @@ -682,7 +684,7 @@ TEST(columnTest, binary_column_is_not_null) { flttMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv); SColumnInfoData *pcolumn = (SColumnInfoData *)taosArrayGetLast(src->pDataBlock); - colDataAppend(pcolumn, 4, NULL, true); + colDataSetVal(pcolumn, 4, NULL, true); flttMakeOpNode(&opNode, OP_TYPE_IS_NOT_NULL, TSDB_DATA_TYPE_BOOL, pLeft, NULL); @@ -1337,6 +1339,127 @@ TEST(scalarModelogicTest, diff_columns_or_and_or) { nodesDestroyNode(logicNode1); blockDataDestroy(src); } +#endif + +template +int32_t compareSignedWithUnsigned(SignedT l, UnsignedT r) { + if (l < 0) return -1; + auto l_uint64 = static_cast(l); + auto r_uint64 = static_cast(r); + if (l_uint64 < r_uint64) return -1; + if (l_uint64 > r_uint64) return 1; + return 0; +} + +template +int32_t compareUnsignedWithSigned(UnsignedT l, SignedT r) { + if (r < 0) return 1; + auto l_uint64 = static_cast(l); + auto r_uint64 = static_cast(r); + if (l_uint64 < r_uint64) return -1; + if (l_uint64 > r_uint64) return 1; + return 0; +} + +template +void doCompareWithValueRange_SignedWithUnsigned(__compar_fn_t fp) { + int32_t signedMin = -10, signedMax = 10; + int32_t unsignedMin = 0, unsignedMax = 10; + for (SignedT l = signedMin; l <= signedMax; ++l) { + for (UnsignedT r = unsignedMin; r <= unsignedMax; ++r) { + ASSERT_EQ(fp(&l, &r), compareSignedWithUnsigned(l, r)); + } + } +} + +template +void doCompareWithValueRange_UnsignedWithSigned(__compar_fn_t fp) { + int32_t signedMin = -10, signedMax = 10; + int32_t unsignedMin = 0, unsignedMax = 10; + for (UnsignedT l = unsignedMin; l <= unsignedMax; ++l) { + for (SignedT r = signedMin; r <= signedMax; ++r) { + ASSERT_EQ(fp(&l, &r), compareUnsignedWithSigned(l, r)); + } + } +} + +template +void doCompareWithValueRange_OnlyLeftType(__compar_fn_t fp, int32_t rType) { + switch (rType) { + case TSDB_DATA_TYPE_UTINYINT: + doCompareWithValueRange_SignedWithUnsigned(fp); + break; + case TSDB_DATA_TYPE_USMALLINT: + doCompareWithValueRange_SignedWithUnsigned(fp); + break; + case TSDB_DATA_TYPE_UINT: + doCompareWithValueRange_SignedWithUnsigned(fp); + break; + case TSDB_DATA_TYPE_UBIGINT: + doCompareWithValueRange_SignedWithUnsigned(fp); + break; + case TSDB_DATA_TYPE_TINYINT: + doCompareWithValueRange_UnsignedWithSigned(fp); + break; + case TSDB_DATA_TYPE_SMALLINT: + doCompareWithValueRange_UnsignedWithSigned(fp); + break; + case TSDB_DATA_TYPE_INT: + doCompareWithValueRange_UnsignedWithSigned(fp); + break; + case TSDB_DATA_TYPE_BIGINT: + doCompareWithValueRange_UnsignedWithSigned(fp); + break; + default: + FAIL(); + } +} + +void doCompare(const std::vector &lTypes, const std::vector &rTypes, int32_t oper) { + for (int i = 0; i < lTypes.size(); ++i) { + for (int j = 0; j < rTypes.size(); ++j) { + auto fp = filterGetCompFuncEx(lTypes[i], rTypes[j], oper); + switch (lTypes[i]) { + case TSDB_DATA_TYPE_TINYINT: + doCompareWithValueRange_OnlyLeftType(fp, rTypes[j]); + break; + case TSDB_DATA_TYPE_SMALLINT: + doCompareWithValueRange_OnlyLeftType(fp, rTypes[j]); + break; + case TSDB_DATA_TYPE_INT: + doCompareWithValueRange_OnlyLeftType(fp, rTypes[j]); + break; + case TSDB_DATA_TYPE_BIGINT: + doCompareWithValueRange_OnlyLeftType(fp, rTypes[j]); + break; + case TSDB_DATA_TYPE_UTINYINT: + doCompareWithValueRange_OnlyLeftType(fp, rTypes[j]); + break; + case TSDB_DATA_TYPE_USMALLINT: + doCompareWithValueRange_OnlyLeftType(fp, rTypes[j]); + break; + case TSDB_DATA_TYPE_UINT: + doCompareWithValueRange_OnlyLeftType(fp, rTypes[j]); + break; + case TSDB_DATA_TYPE_UBIGINT: + doCompareWithValueRange_OnlyLeftType(fp, rTypes[j]); + break; + default: + FAIL(); + } + } + } +} + +TEST(dataCompareTest, signed_and_unsigned_int) { + std::vector lType = {TSDB_DATA_TYPE_TINYINT, TSDB_DATA_TYPE_SMALLINT, TSDB_DATA_TYPE_INT, + TSDB_DATA_TYPE_BIGINT}; + std::vector rType = {TSDB_DATA_TYPE_UTINYINT, TSDB_DATA_TYPE_USMALLINT, TSDB_DATA_TYPE_UINT, + TSDB_DATA_TYPE_UBIGINT}; + + doCompare(lType, rType, OP_TYPE_GREATER_THAN); + doCompare(rType, lType, OP_TYPE_GREATER_THAN); +} int main(int argc, char **argv) { taosSeedRand(taosGetTimestampSec()); diff --git a/source/libs/scalar/test/scalar/scalarTests.cpp b/source/libs/scalar/test/scalar/scalarTests.cpp index 97002ed9bfaa5e1edca3654a910237422ffdcb9a..fe86e18ce340f256bc90b6f19c0aa7ed891073cf 100644 --- a/source/libs/scalar/test/scalar/scalarTests.cpp +++ b/source/libs/scalar/test/scalar/scalarTests.cpp @@ -158,7 +158,7 @@ void scltMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in res->info.rows = rowNum; SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pColumn, i, (const char *)value, false); + colDataSetVal(pColumn, i, (const char *)value, false); if (IS_VAR_DATA_TYPE(dataType)) { value = (char *)value + varDataTLen(value); } else { @@ -183,7 +183,7 @@ void scltMakeColumnNode(SNode **pNode, SSDataBlock **block, int32_t dataType, in SColumnInfoData *pColumn = (SColumnInfoData *)taosArrayGetLast(res->pDataBlock); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pColumn, i, (const char *)value, false); + colDataSetVal(pColumn, i, (const char *)value, false); if (IS_VAR_DATA_TYPE(dataType)) { value = (char *)value + varDataTLen(value); } else { @@ -1880,8 +1880,8 @@ TEST(columnTest, binary_column_is_null) { scltMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv); SColumnInfoData *pcolumn = (SColumnInfoData *)taosArrayGetLast(src->pDataBlock); - colDataAppend(pcolumn, 2, NULL, true); - colDataAppend(pcolumn, 4, NULL, true); + colDataSetVal(pcolumn, 2, NULL, true); + colDataSetVal(pcolumn, 4, NULL, true); scltMakeOpNode(&opNode, OP_TYPE_IS_NULL, TSDB_DATA_TYPE_BOOL, pLeft, NULL); @@ -1924,7 +1924,7 @@ TEST(columnTest, binary_column_is_not_null) { scltMakeColumnNode(&pLeft, &src, TSDB_DATA_TYPE_BINARY, 3, rowNum, leftv); SColumnInfoData *pcolumn = (SColumnInfoData *)taosArrayGetLast(src->pDataBlock); - colDataAppend(pcolumn, 4, NULL, true); + colDataSetVal(pcolumn, 4, NULL, true); scltMakeOpNode(&opNode, OP_TYPE_IS_NOT_NULL, TSDB_DATA_TYPE_BOOL, pLeft, NULL); @@ -2030,7 +2030,7 @@ void scltMakeDataBlock(SScalarParam **pInput, int32_t type, void *pVal, int32_t if (setVal) { for (int32_t i = 0; i < num; ++i) { - colDataAppend(input->columnData, i, (const char *)pVal, false); + colDataSetVal(input->columnData, i, (const char *)pVal, false); } } else { // memset(input->data, 0, num * bytes); @@ -2225,7 +2225,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { int8_t v = val_tinyint + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("tiny_int before ABS:%d\n", v); } @@ -2243,7 +2243,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { int8_t v = val_tinyint + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("tiny_int before ABS:%d\n", v); } @@ -2263,7 +2263,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { int16_t v = val_smallint + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("small_int before ABS:%d\n", v); } @@ -2281,7 +2281,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { int16_t v = val_smallint + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("small_int before ABS:%d\n", v); } @@ -2301,7 +2301,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { int32_t v = val_int + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("int before ABS:%d\n", v); } @@ -2319,7 +2319,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { int32_t v = val_int + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("int before ABS:%d\n", v); } @@ -2339,7 +2339,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { float v = val_float + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("float before ABS:%f\n", v); } @@ -2357,7 +2357,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { float v = val_float + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("float before ABS:%f\n", v); } @@ -2377,7 +2377,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { double v = val_double + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("double before ABS:%f\n", v); } @@ -2395,7 +2395,7 @@ TEST(ScalarFunctionTest, absFunction_column) { scltMakeDataBlock(&pOutput, type, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { double v = val_double + i; - colDataAppend(pInput->columnData, i, (const char *)&v, false); + colDataSetVal(pInput->columnData, i, (const char *)&v, false); PRINTF("double before ABS:%f\n", v); } @@ -2466,7 +2466,7 @@ TEST(ScalarFunctionTest, sinFunction_column) { scltMakeDataBlock(&pInput, type, 0, rowNum, false); scltMakeDataBlock(&pOutput, otype, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput->columnData, i, (const char *)&val_tinyint[i], false); + colDataSetVal(pInput->columnData, i, (const char *)&val_tinyint[i], false); PRINTF("tiny_int before SIN:%d\n", *(int8_t *)colDataGetData(pInput->columnData, i)); } @@ -2485,7 +2485,7 @@ TEST(ScalarFunctionTest, sinFunction_column) { scltMakeDataBlock(&pInput, type, 0, rowNum, false); scltMakeDataBlock(&pOutput, otype, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput->columnData, i, (const char *)&val_float[i], false); + colDataSetVal(pInput->columnData, i, (const char *)&val_float[i], false); PRINTF("float before SIN:%f\n", *((float *)colDataGetData(pInput->columnData, i))); } @@ -2556,7 +2556,7 @@ TEST(ScalarFunctionTest, cosFunction_column) { scltMakeDataBlock(&pInput, type, 0, rowNum, false); scltMakeDataBlock(&pOutput, otype, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput->columnData, i, (const char *)&val_tinyint[i], false); + colDataSetVal(pInput->columnData, i, (const char *)&val_tinyint[i], false); PRINTF("tiny_int before COS:%d\n", *(int8_t *)colDataGetData(pInput->columnData, i)); } @@ -2575,7 +2575,7 @@ TEST(ScalarFunctionTest, cosFunction_column) { scltMakeDataBlock(&pInput, type, 0, rowNum, false); scltMakeDataBlock(&pOutput, otype, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput->columnData, i, (const char *)&val_float[i], false); + colDataSetVal(pInput->columnData, i, (const char *)&val_float[i], false); PRINTF("float before COS:%f\n", *(float *)colDataGetData(pInput->columnData, i)); } @@ -2646,7 +2646,7 @@ TEST(ScalarFunctionTest, tanFunction_column) { scltMakeDataBlock(&pInput, type, 0, rowNum, false); scltMakeDataBlock(&pOutput, otype, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput->columnData, i, (const char *)&val_tinyint[i], false); + colDataSetVal(pInput->columnData, i, (const char *)&val_tinyint[i], false); PRINTF("tiny_int before TAN:%d\n", *((int8_t *)colDataGetData(pInput->columnData, i))); } @@ -2665,7 +2665,7 @@ TEST(ScalarFunctionTest, tanFunction_column) { scltMakeDataBlock(&pInput, type, 0, rowNum, false); scltMakeDataBlock(&pOutput, otype, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput->columnData, i, (const char *)&val_float[i], false); + colDataSetVal(pInput->columnData, i, (const char *)&val_float[i], false); PRINTF("float before TAN:%f\n", *((float *)colDataGetData(pInput->columnData, i))); } @@ -2736,7 +2736,7 @@ TEST(ScalarFunctionTest, asinFunction_column) { scltMakeDataBlock(&pInput, type, 0, rowNum, false); scltMakeDataBlock(&pOutput, otype, 0, rowNum, false); for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput->columnData, i, (const char *)&val_tinyint[i], false); + colDataSetVal(pInput->columnData, i, (const char *)&val_tinyint[i], false); PRINTF("tiny_int before ASIN:%d\n", *((int8_t *)colDataGetData(pInput->columnData, i))); } @@ -3395,7 +3395,7 @@ TEST(ScalarFunctionTest, logFunction_column) { scltMakeDataBlock(&input[i], type, 0, rowNum, false); pInput[i] = *input[i]; for (int32_t j = 0; j < rowNum; ++j) { - colDataAppend(pInput[i].columnData, j, (const char *)&val_tinyint[i][j], false); + colDataSetVal(pInput[i].columnData, j, (const char *)&val_tinyint[i][j], false); } PRINTF("tiny_int before LOG:%d,%d,%d\n", *((int8_t *)pInput[i].data + 0), *((int8_t *)pInput[i].data + 1), *((int8_t *)pInput[i].data + 2)); @@ -3419,7 +3419,7 @@ TEST(ScalarFunctionTest, logFunction_column) { scltMakeDataBlock(&input[i], type, 0, rowNum, false); pInput[i] = *input[i]; for (int32_t j = 0; j < rowNum; ++j) { - colDataAppend(pInput[i].columnData, j, (const char *)&val_float[i][j], false); + colDataSetVal(pInput[i].columnData, j, (const char *)&val_float[i][j], false); } PRINTF("float before LOG:%f,%f,%f\n", *((float *)colDataGetData(pInput[i], 0)), *((float *)colDataGetData(pInput[i], 1)), *((float *)colDataGetData(pInput[i], 2))); @@ -3442,12 +3442,12 @@ TEST(ScalarFunctionTest, logFunction_column) { scltMakeDataBlock(&input[0], TSDB_DATA_TYPE_TINYINT, 0, rowNum, false); pInput[0] = *input[0]; for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput[0].columnData, i, (const char *)¶m0[i], false); + colDataSetVal(pInput[0].columnData, i, (const char *)¶m0[i], false); } scltMakeDataBlock(&input[1], TSDB_DATA_TYPE_FLOAT, 0, rowNum, false); pInput[1] = *input[1]; for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput[1].columnData, i, (const char *)¶m1[i], false); + colDataSetVal(pInput[1].columnData, i, (const char *)¶m1[i], false); } PRINTF("tiny_int, float before LOG:{%d,%f}, {%d,%f}, {%d,%f}\n", *((int8_t *)pInput[0].data + 0), *((float *)pInput[1].data + 0), *((int8_t *)pInput[0].data + 1), *((float *)pInput[1].data + 1), @@ -3558,7 +3558,7 @@ TEST(ScalarFunctionTest, powFunction_column) { scltMakeDataBlock(&input[i], type, 0, rowNum, false); pInput[i] = *input[i]; for (int32_t j = 0; j < rowNum; ++j) { - colDataAppend(pInput[i].columnData, j, (const char *)&val_tinyint[i][j], false); + colDataSetVal(pInput[i].columnData, j, (const char *)&val_tinyint[i][j], false); } PRINTF("tiny_int before POW:%d,%d,%d\n", *((int8_t *)pInput[i].data + 0), *((int8_t *)pInput[i].data + 1), *((int8_t *)pInput[i].data + 2)); @@ -3583,7 +3583,7 @@ TEST(ScalarFunctionTest, powFunction_column) { scltMakeDataBlock(&input[i], type, 0, rowNum, false); pInput[i] = *input[i]; for (int32_t j = 0; j < rowNum; ++j) { - colDataAppend(pInput[i].columnData, j, (const char *)&val_float[i][j], false); + colDataSetVal(pInput[i].columnData, j, (const char *)&val_float[i][j], false); } PRINTF("float before POW:%f,%f,%f\n", *((float *)pInput[i].data + 0), *((float *)pInput[i].data + 1), *((float *)pInput[i].data + 2)); @@ -3606,12 +3606,12 @@ TEST(ScalarFunctionTest, powFunction_column) { scltMakeDataBlock(&input[0], TSDB_DATA_TYPE_TINYINT, 0, rowNum, false); pInput[0] = *input[0]; for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput[0].columnData, i, (const char *)¶m0[i], false); + colDataSetVal(pInput[0].columnData, i, (const char *)¶m0[i], false); } scltMakeDataBlock(&input[1], TSDB_DATA_TYPE_FLOAT, 0, rowNum, false); pInput[1] = *input[1]; for (int32_t i = 0; i < rowNum; ++i) { - colDataAppend(pInput[1].columnData, i, (const char *)¶m1[i], false); + colDataSetVal(pInput[1].columnData, i, (const char *)¶m1[i], false); } PRINTF("tiny_int, float before POW:{%d,%f}, {%d,%f}, {%d,%f}\n", *((int8_t *)pInput[0].data + 0), *((float *)pInput[1].data + 0), *((int8_t *)pInput[0].data + 1), *((float *)pInput[1].data + 1), diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h index e8216fcd7c7d6f50981218ae8c27531390903382..7840fe2017a6f384e70f1553105c7293a4abb2d7 100644 --- a/source/libs/scheduler/inc/schInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -54,7 +54,6 @@ typedef enum { #define SCHEDULE_DEFAULT_MAX_JOB_NUM 1000 #define SCHEDULE_DEFAULT_MAX_TASK_NUM 1000 -#define SCHEDULE_DEFAULT_MAX_NODE_TABLE_NUM 200 // unit is TSDB_TABLE_NUM_UNIT #define SCHEDULE_DEFAULT_POLICY SCH_LOAD_SEQ #define SCHEDULE_DEFAULT_MAX_NODE_NUM 20 @@ -134,7 +133,7 @@ typedef struct SSchStatusFps { typedef struct SSchedulerCfg { uint32_t maxJobNum; - int32_t maxNodeTableNum; + int64_t maxNodeTableNum; SCH_POLICY schPolicy; bool enableReSchedule; } SSchedulerCfg; @@ -175,7 +174,7 @@ typedef struct SSchHbCallbackParam { typedef struct SSchFlowControl { SRWLatch lock; bool sorted; - int32_t tableNumSum; + int64_t tableNumSum; uint32_t execTaskNum; SArray *taskList; // Element is SSchTask* } SSchFlowControl; @@ -193,7 +192,7 @@ typedef struct SSchLevel { int32_t taskSucceed; int32_t taskNum; int32_t taskLaunchedNum; - int32_t taskDoneNum; + int32_t taskExecDoneNum; SArray *subTasks; // Element is SSchTask } SSchLevel; @@ -230,6 +229,7 @@ typedef struct SSchTask { SSchRedirectCtx redirectCtx; // task redirect context bool waitRetry; // wait for retry int32_t execId; // task current execute index + int32_t failedExecId; // last failed task execute index SSchLevel *level; // level SRWLatch planLock; // task update plan lock SSubplan *plan; // subplan @@ -298,6 +298,7 @@ typedef struct SSchJob { SExecResult execRes; void *fetchRes; // TODO free it or not bool fetched; + bool noMoreRetry; int64_t resNumOfRows; // from int32_t to int64_t SSchResInfo userRes; char *sql; @@ -332,13 +333,16 @@ extern SSchedulerMgmt schMgmt; ((_job)->attr.localExec && SCH_IS_QUERY_JOB(_job) && (!SCH_IS_INSERT_JOB(_job)) && \ (!SCH_IS_DATA_BIND_QRY_TASK(_task))) -#define SCH_UPDATE_REDICT_CODE(job, _code) atomic_val_compare_exchange_32(&((job)->redirectCode), 0, _code) -#define SCH_GET_REDICT_CODE(job, _code) (((!NO_RET_REDIRECT_ERROR(_code)) || (job)->redirectCode == 0) ? (_code) : (job)->redirectCode) +#define SCH_UPDATE_REDIRECT_CODE(job, _code) atomic_val_compare_exchange_32(&((job)->redirectCode), 0, _code) +#define SCH_GET_REDIRECT_CODE(job, _code) (((!NO_RET_REDIRECT_ERROR(_code)) || (job)->redirectCode == 0) ? (_code) : (job)->redirectCode) #define SCH_SET_TASK_STATUS(task, st) atomic_store_8(&(task)->status, st) #define SCH_GET_TASK_STATUS(task) atomic_load_8(&(task)->status) #define SCH_GET_TASK_STATUS_STR(task) jobTaskStatusStr(SCH_GET_TASK_STATUS(task)) +#define SCH_TASK_ALREADY_LAUNCHED(task) (SCH_GET_TASK_STATUS(task) >= JOB_TASK_STATUS_EXEC) +#define SCH_TASK_EXEC_DONE(task) (SCH_GET_TASK_STATUS(task) >= JOB_TASK_STATUS_PART_SUCC) + #define SCH_GET_TASK_HANDLE(_task) ((_task) ? (_task)->handle : NULL) #define SCH_SET_TASK_HANDLE(_task, _handle) ((_task)->handle = (_handle)) @@ -360,6 +364,7 @@ extern SSchedulerMgmt schMgmt; (SCH_IS_DATA_BIND_QRY_TASK(_task) && SCH_JOB_NEED_FLOW_CTRL(_job) && SCH_IS_LEVEL_UNFINISHED((_task)->level)) #define SCH_FETCH_TYPE(_pSrcTask) (SCH_IS_DATA_BIND_QRY_TASK(_pSrcTask) ? TDMT_SCH_FETCH : TDMT_SCH_MERGE_FETCH) #define SCH_TASK_NEED_FETCH(_task) ((_task)->plan->subplanType != SUBPLAN_TYPE_MODIFY) +#define SCH_MULTI_LEVEL_LAUNCHED(_job) ((_job)->levelIdx != ((_job)->levelNum - 1)) #define SCH_SET_JOB_TYPE(_job, type) \ do { \ @@ -376,16 +381,24 @@ extern SSchedulerMgmt schMgmt; #define SCH_JOB_NEED_DROP(_job) (SCH_IS_QUERY_JOB(_job)) #define SCH_IS_EXPLAIN_JOB(_job) (EXPLAIN_MODE_ANALYZE == (_job)->attr.explainMode) #define SCH_NETWORK_ERR(_code) ((_code) == TSDB_CODE_RPC_BROKEN_LINK || (_code) == TSDB_CODE_RPC_NETWORK_UNAVAIL || (_code) == TSDB_CODE_RPC_SOMENODE_NOT_CONNECTED) -#define SCH_MERGE_TASK_NETWORK_ERR(_task, _code, _len) \ - (SCH_NETWORK_ERR(_code) && (((_len) > 0) || (!SCH_IS_DATA_BIND_TASK(_task)) || (_task)->redirectCtx.inRedirect)) #define SCH_REDIRECT_MSGTYPE(_msgType) \ ((_msgType) == TDMT_SCH_LINK_BROKEN || (_msgType) == TDMT_SCH_QUERY || (_msgType) == TDMT_SCH_MERGE_QUERY || \ (_msgType) == TDMT_SCH_FETCH || (_msgType) == TDMT_SCH_MERGE_FETCH) -#define SCH_TASK_NEED_REDIRECT(_task, _msgType, _code, _rspLen) \ - (SCH_REDIRECT_MSGTYPE(_msgType) && \ - (NEED_SCHEDULER_REDIRECT_ERROR(_code) || SCH_MERGE_TASK_NETWORK_ERR((_task), (_code), (_rspLen)))) -#define SCH_NEED_RETRY(_msgType, _code) \ - ((SCH_NETWORK_ERR(_code) && SCH_REDIRECT_MSGTYPE(_msgType)) || (_code) == TSDB_CODE_SCH_TIMEOUT_ERROR) +#define SCH_LOW_LEVEL_NETWORK_ERR(_job, _task, _code) \ + (SCH_NETWORK_ERR(_code) && ((_task)->level->level == (_job)->levelIdx)) +#define SCH_TOP_LEVEL_NETWORK_ERR(_job, _task, _code) \ + (SCH_NETWORK_ERR(_code) && ((_task)->level->level > (_job)->levelIdx)) +#define SCH_TASK_RETRY_NETWORK_ERR(_task, _code) \ + (SCH_NETWORK_ERR(_code) && (_task)->redirectCtx.inRedirect) + +#define SCH_JOB_NEED_RETRY(_job, _task, _msgType, _code) \ + (SCH_REDIRECT_MSGTYPE(_msgType) && SCH_TOP_LEVEL_NETWORK_ERR(_job, _task, _code)) +#define SCH_TASKSET_NEED_RETRY(_job, _task, _msgType, _code) \ + (SCH_REDIRECT_MSGTYPE(_msgType) && \ + (NEED_SCHEDULER_REDIRECT_ERROR(_code) || SCH_LOW_LEVEL_NETWORK_ERR((_job), (_task), (_code)) || SCH_TASK_RETRY_NETWORK_ERR((_task), (_code)))) +#define SCH_TASK_NEED_RETRY(_msgType, _code) \ + ((SCH_REDIRECT_MSGTYPE(_msgType) && SCH_NETWORK_ERR(_code)) || (_code) == TSDB_CODE_SCH_TIMEOUT_ERROR) + #define SCH_IS_LEVEL_UNFINISHED(_level) ((_level)->taskLaunchedNum < (_level)->taskNum) #define SCH_GET_CUR_EP(_addr) (&(_addr)->epSet.eps[(_addr)->epSet.inUse]) @@ -478,37 +491,42 @@ extern SSchedulerMgmt schMgmt; #define SCH_LOCK(type, _lock) \ do { \ if (SCH_READ == (type)) { \ - assert(atomic_load_32(_lock) >= 0); \ + ASSERTS(atomic_load_32(_lock) >= 0, "invalid lock value before read lock"); \ SCH_LOCK_DEBUG("SCH RLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ taosRLockLatch(_lock); \ SCH_LOCK_DEBUG("SCH RLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32(_lock) > 0); \ + ASSERTS(atomic_load_32(_lock) > 0, "invalid lock value after read lock"); \ } else { \ - assert(atomic_load_32(_lock) >= 0); \ + ASSERTS(atomic_load_32(_lock) >= 0, "invalid lock value before write lock"); \ SCH_LOCK_DEBUG("SCH WLOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ taosWLockLatch(_lock); \ SCH_LOCK_DEBUG("SCH WLOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32(_lock) == TD_RWLATCH_WRITE_FLAG_COPY); \ + ASSERTS(atomic_load_32(_lock) == TD_RWLATCH_WRITE_FLAG_COPY, "invalid lock value after write lock"); \ } \ } while (0) #define SCH_UNLOCK(type, _lock) \ do { \ if (SCH_READ == (type)) { \ - assert(atomic_load_32((_lock)) > 0); \ + ASSERTS(atomic_load_32((_lock)) > 0, "invalid lock value before read unlock"); \ SCH_LOCK_DEBUG("SCH RULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ taosRUnLockLatch(_lock); \ SCH_LOCK_DEBUG("SCH RULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) >= 0); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value after read unlock"); \ } else { \ - assert(atomic_load_32((_lock)) & TD_RWLATCH_WRITE_FLAG_COPY); \ + ASSERTS(atomic_load_32((_lock)) & TD_RWLATCH_WRITE_FLAG_COPY, "invalid lock value before write unlock"); \ SCH_LOCK_DEBUG("SCH WULOCK%p:%d, %s:%d B", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ taosWUnLockLatch(_lock); \ SCH_LOCK_DEBUG("SCH WULOCK%p:%d, %s:%d E", (_lock), atomic_load_32(_lock), __FILE__, __LINE__); \ - assert(atomic_load_32((_lock)) >= 0); \ + ASSERTS(atomic_load_32((_lock)) >= 0, "invalid lock value after write unlock"); \ } \ } while (0) +#define SCH_RESET_JOB_LEVEL_IDX(_job) do { \ + (_job)->levelIdx = (_job)->levelNum - 1; \ + SCH_JOB_DLOG("set job levelIdx to %d", (_job)->levelIdx); \ +} while (0) + void schDeregisterTaskHb(SSchJob *pJob, SSchTask *pTask); void schCleanClusterHb(void *pTrans); int32_t schLaunchTask(SSchJob *job, SSchTask *task); @@ -561,7 +579,7 @@ int32_t schInitJob(int64_t *pJobId, SSchedulerReq *pReq); int32_t schExecJob(SSchJob *pJob, SSchedulerReq *pReq); int32_t schDumpJobExecRes(SSchJob *pJob, SExecResult *pRes); int32_t schUpdateTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask, SEpSet *pEpSet); -int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32_t rspCode); +int32_t schHandleTaskSetRetry(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32_t rspCode); void schProcessOnOpEnd(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq *pReq, int32_t errCode); int32_t schProcessOnOpBegin(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq *pReq); void schProcessOnCbEnd(SSchJob *pJob, SSchTask *pTask, int32_t errCode); @@ -590,6 +608,10 @@ int32_t schHandleJobDrop(SSchJob *pJob, int32_t errCode); bool schChkCurrentOp(SSchJob *pJob, int32_t op, int8_t sync); int32_t schProcessFetchRsp(SSchJob *pJob, SSchTask *pTask, char *msg, int32_t rspCode); int32_t schProcessExplainRsp(SSchJob *pJob, SSchTask *pTask, SExplainRsp *rsp); +int32_t schHandleJobRetry(SSchJob *pJob, SSchTask *pTask, SDataBuf *pMsg, int32_t rspCode); +int32_t schChkResetJobRetry(SSchJob *pJob, int32_t rspCode); +void schResetTaskForRetry(SSchJob *pJob, SSchTask *pTask); +int32_t schChkUpdateRedirectCtx(SSchJob *pJob, SSchTask *pTask, SEpSet *pEpSet, int32_t rspCode); extern SSchDebug gSCHDebug; diff --git a/source/libs/scheduler/src/schFlowCtrl.c b/source/libs/scheduler/src/schFlowCtrl.c index 5e4fe4b8a1f2795cfbd4dff838304fe0e36343ff..8c2b65e1259685fcb1fb8502cbf3710faa4e426c 100644 --- a/source/libs/scheduler/src/schFlowCtrl.c +++ b/source/libs/scheduler/src/schFlowCtrl.c @@ -46,7 +46,7 @@ int32_t schChkJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel) { return TSDB_CODE_SUCCESS; } - int32_t sum = 0; + int64_t sum = 0; int32_t taskNum = taosArrayGetSize(pJob->dataSrcTasks); for (int32_t i = 0; i < taskNum; ++i) { SSchTask *pTask = *(SSchTask **)taosArrayGet(pJob->dataSrcTasks, i); @@ -55,7 +55,7 @@ int32_t schChkJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel) { } if (schMgmt.cfg.maxNodeTableNum <= 0 || sum < schMgmt.cfg.maxNodeTableNum) { - SCH_JOB_DLOG("job no need flow ctrl, totalTableNum:%d", sum); + SCH_JOB_DLOG("job no need flow ctrl, totalTableNum:%" PRId64, sum); return TSDB_CODE_SUCCESS; } @@ -68,7 +68,7 @@ int32_t schChkJobNeedFlowCtrl(SSchJob *pJob, SSchLevel *pLevel) { SCH_SET_JOB_NEED_FLOW_CTRL(pJob); - SCH_JOB_DLOG("job NEED flow ctrl, totalTableNum:%d", sum); + SCH_JOB_DLOG("job NEED flow ctrl, totalTableNum:%" PRId64, sum); return TSDB_CODE_SUCCESS; } @@ -94,7 +94,7 @@ int32_t schDecTaskFlowQuota(SSchJob *pJob, SSchTask *pTask) { --ctrl->execTaskNum; ctrl->tableNumSum -= pTask->plan->execNodeStat.tableNum; - SCH_TASK_DLOG("task quota removed, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", ep->fqdn, + SCH_TASK_DLOG("task quota removed, fqdn:%s, port:%d, tableNum:%d, remainNum:%" PRId64 ", remainExecTaskNum:%d", ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, ctrl->tableNumSum, ctrl->execTaskNum); _return: @@ -125,7 +125,7 @@ int32_t schCheckIncTaskFlowQuota(SSchJob *pJob, SSchTask *pTask, bool *enough) { SCH_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); } - SCH_TASK_DLOG("task quota added, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", ep->fqdn, + SCH_TASK_DLOG("task quota added, fqdn:%s, port:%d, tableNum:%d, remainNum:%" PRId64 ", remainExecTaskNum:%d", ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, nctrl.tableNumSum, nctrl.execTaskNum); *enough = true; @@ -142,7 +142,7 @@ int32_t schCheckIncTaskFlowQuota(SSchJob *pJob, SSchTask *pTask, bool *enough) { break; } - int32_t sum = pTask->plan->execNodeStat.tableNum + ctrl->tableNumSum; + int64_t sum = pTask->plan->execNodeStat.tableNum + ctrl->tableNumSum; if (sum <= schMgmt.cfg.maxNodeTableNum) { ctrl->tableNumSum = sum; @@ -173,7 +173,7 @@ int32_t schCheckIncTaskFlowQuota(SSchJob *pJob, SSchTask *pTask, bool *enough) { _return: - SCH_TASK_DLOG("task quota %s added, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", + SCH_TASK_DLOG("task quota %s added, fqdn:%s, port:%d, tableNum:%d, remainNum:%" PRId64 ", remainExecTaskNum:%d", ((*enough) ? "" : "NOT"), ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, ctrl->tableNumSum, ctrl->execTaskNum); @@ -203,7 +203,7 @@ int32_t schLaunchTasksInFlowCtrlListImpl(SSchJob *pJob, SSchFlowControl *ctrl) { return TSDB_CODE_SUCCESS; } - int32_t remainNum = schMgmt.cfg.maxNodeTableNum - ctrl->tableNumSum; + int64_t remainNum = schMgmt.cfg.maxNodeTableNum - ctrl->tableNumSum; int32_t taskNum = taosArrayGetSize(ctrl->taskList); int32_t code = 0; SSchTask *pTask = NULL; @@ -217,7 +217,7 @@ int32_t schLaunchTasksInFlowCtrlListImpl(SSchJob *pJob, SSchFlowControl *ctrl) { SEp *ep = SCH_GET_CUR_EP(&pTask->plan->execNode); if (pTask->plan->execNodeStat.tableNum > remainNum && ctrl->execTaskNum > 0) { - SCH_TASK_DLOG("task NOT to launch, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", ep->fqdn, + SCH_TASK_DLOG("task NOT to launch, fqdn:%s, port:%d, tableNum:%d, remainNum:%" PRId64 ", remainExecTaskNum:%d", ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, ctrl->tableNumSum, ctrl->execTaskNum); continue; @@ -228,14 +228,14 @@ int32_t schLaunchTasksInFlowCtrlListImpl(SSchJob *pJob, SSchFlowControl *ctrl) { taosArrayRemove(ctrl->taskList, i); - SCH_TASK_DLOG("task to launch, fqdn:%s, port:%d, tableNum:%d, remainNum:%d, remainExecTaskNum:%d", ep->fqdn, + SCH_TASK_DLOG("task to launch, fqdn:%s, port:%d, tableNum:%d, remainNum:%" PRId64 ", remainExecTaskNum:%d", ep->fqdn, ep->port, pTask->plan->execNodeStat.tableNum, ctrl->tableNumSum, ctrl->execTaskNum); SCH_ERR_JRET(schAsyncLaunchTaskImpl(pJob, pTask)); remainNum -= pTask->plan->execNodeStat.tableNum; if (remainNum <= 0) { - SCH_TASK_DLOG("no more task to launch, fqdn:%s, port:%d, remainNum:%d, remainExecTaskNum:%d", ep->fqdn, ep->port, + SCH_TASK_DLOG("no more task to launch, fqdn:%s, port:%d, remainNum:%" PRId64 ", remainExecTaskNum:%d", ep->fqdn, ep->port, ctrl->tableNumSum, ctrl->execTaskNum); break; @@ -244,7 +244,7 @@ int32_t schLaunchTasksInFlowCtrlListImpl(SSchJob *pJob, SSchFlowControl *ctrl) { if (i < (taskNum - 1)) { SSchTask *pLastTask = *(SSchTask **)taosArrayGetLast(ctrl->taskList); if (remainNum < pLastTask->plan->execNodeStat.tableNum) { - SCH_TASK_DLOG("no more task to launch, fqdn:%s, port:%d, remainNum:%d, remainExecTaskNum:%d, smallestInList:%d", + SCH_TASK_DLOG("no more task to launch, fqdn:%s, port:%d, remainNum:%" PRId64 ", remainExecTaskNum:%d, smallestInList:%d", ep->fqdn, ep->port, ctrl->tableNumSum, ctrl->execTaskNum, pLastTask->plan->execNodeStat.tableNum); break; @@ -282,7 +282,6 @@ int32_t schLaunchTasksInFlowCtrlList(SSchJob *pJob, SSchTask *pTask) { } int32_t code = schLaunchTasksInFlowCtrlListImpl(pJob, ctrl); - ; SCH_ERR_RET(code); return code; // to avoid compiler error diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c index 6a8f81f8c78a0146396371d79f4c8ed95e73b1fb..e7bfe95795f44f61ee4d1cc02873a21b80438369 100644 --- a/source/libs/scheduler/src/schJob.c +++ b/source/libs/scheduler/src/schJob.c @@ -83,6 +83,10 @@ int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { oriStatus = SCH_GET_JOB_STATUS(pJob); if (oriStatus == newStatus) { + if (JOB_TASK_STATUS_FETCH == newStatus) { + return code; + } + SCH_ERR_JRET(TSDB_CODE_SCH_IGNORE_ERROR); } @@ -108,10 +112,19 @@ int32_t schUpdateJobStatus(SSchJob *pJob, int8_t newStatus) { break; case JOB_TASK_STATUS_PART_SUCC: if (newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_SUCC && - newStatus != JOB_TASK_STATUS_DROP && newStatus != JOB_TASK_STATUS_EXEC) { + newStatus != JOB_TASK_STATUS_DROP && newStatus != JOB_TASK_STATUS_EXEC && + newStatus != JOB_TASK_STATUS_FETCH) { SCH_ERR_JRET(TSDB_CODE_APP_ERROR); } + break; + case JOB_TASK_STATUS_FETCH: + if (newStatus != JOB_TASK_STATUS_FAIL && newStatus != JOB_TASK_STATUS_SUCC && + newStatus != JOB_TASK_STATUS_DROP && newStatus != JOB_TASK_STATUS_EXEC && + newStatus != JOB_TASK_STATUS_FETCH) { + SCH_ERR_JRET(TSDB_CODE_APP_ERROR); + } + break; case JOB_TASK_STATUS_SUCC: case JOB_TASK_STATUS_FAIL: @@ -234,7 +247,7 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { } SSchTask *pTask = taosArrayGet(pLevel->subTasks, 0); - if (SUBPLAN_TYPE_MODIFY != pTask->plan->subplanType) { + if (SUBPLAN_TYPE_MODIFY != pTask->plan->subplanType || EXPLAIN_MODE_DISABLE != pJob->attr.explainMode) { pJob->attr.needFetch = true; } } @@ -288,7 +301,7 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { } pJob->levelNum = levelNum; - pJob->levelIdx = levelNum - 1; + SCH_RESET_JOB_LEVEL_IDX(pJob); SSchLevel level = {0}; SNodeListNode *plans = NULL; @@ -484,7 +497,7 @@ int32_t schProcessOnJobFailure(SSchJob *pJob, int32_t errCode) { if (TSDB_CODE_SCH_IGNORE_ERROR == errCode) { return TSDB_CODE_SCH_IGNORE_ERROR; } - + schUpdateJobErrCode(pJob, errCode); int32_t code = atomic_load_32(&pJob->errCode); @@ -537,7 +550,9 @@ int32_t schProcessOnExplainDone(SSchJob *pJob, SSchTask *pTask, SRetrieveTableRs SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_SUCC); - schProcessOnDataFetched(pJob); + if (!SCH_IS_INSERT_JOB(pJob)) { + schProcessOnDataFetched(pJob); + } return TSDB_CODE_SUCCESS; } @@ -548,9 +563,9 @@ int32_t schLaunchJobLowerLevel(SSchJob *pJob, SSchTask *pTask) { } SSchLevel *pLevel = pTask->level; - int32_t doneNum = atomic_add_fetch_32(&pLevel->taskDoneNum, 1); + int32_t doneNum = atomic_add_fetch_32(&pLevel->taskExecDoneNum, 1); if (doneNum == pLevel->taskNum) { - pJob->levelIdx--; + atomic_sub_fetch_32(&pJob->levelIdx, 1); pLevel = taosArrayGet(pJob->levels, pJob->levelIdx); for (int32_t i = 0; i < pLevel->taskNum; ++i) { @@ -560,6 +575,10 @@ int32_t schLaunchJobLowerLevel(SSchJob *pJob, SSchTask *pTask) { continue; } + if (SCH_TASK_ALREADY_LAUNCHED(pTask)) { + continue; + } + SCH_ERR_RET(schLaunchTask(pJob, pTask)); } } @@ -682,7 +701,7 @@ void schFreeJobImpl(void *job) { int32_t schJobFetchRows(SSchJob *pJob) { int32_t code = 0; - if (!(pJob->attr.explainMode == EXPLAIN_MODE_STATIC)) { + if (!(pJob->attr.explainMode == EXPLAIN_MODE_STATIC) && !(SCH_IS_EXPLAIN_JOB(pJob) && SCH_IS_INSERT_JOB(pJob))) { SCH_ERR_RET(schLaunchFetchTask(pJob)); if (schChkCurrentOp(pJob, SCH_OP_FETCH, true)) { @@ -714,7 +733,7 @@ int32_t schInitJob(int64_t *pJobId, SSchedulerReq *pReq) { pJob->attr.localExec = pReq->localReq; pJob->conn = *pReq->pConn; if (pReq->sql) { - pJob->sql = strdup(pReq->sql); + pJob->sql = taosStrdup(pReq->sql); } pJob->pDag = pReq->pDag; pJob->allocatorRefId = nodesMakeAllocatorWeakRef(pReq->allocatorRefId); @@ -809,6 +828,75 @@ void schDirectPostJobRes(SSchedulerReq *pReq, int32_t errCode) { } } +int32_t schChkResetJobRetry(SSchJob *pJob, int32_t rspCode) { + if (pJob->status >= JOB_TASK_STATUS_PART_SUCC) { + SCH_LOCK(SCH_WRITE, &pJob->resLock); + if (pJob->fetched) { + SCH_UNLOCK(SCH_WRITE, &pJob->resLock); + pJob->noMoreRetry = true; + SCH_JOB_ELOG("already fetched while got error %s", tstrerror(rspCode)); + SCH_ERR_RET(rspCode); + } + SCH_UNLOCK(SCH_WRITE, &pJob->resLock); + + schUpdateJobStatus(pJob, JOB_TASK_STATUS_EXEC); + } + + return TSDB_CODE_SUCCESS; +} + +int32_t schResetJobForRetry(SSchJob *pJob, int32_t rspCode) { + SCH_ERR_RET(schChkResetJobRetry(pJob, rspCode)); + + int32_t numOfLevels = taosArrayGetSize(pJob->levels); + for (int32_t i = 0; i < numOfLevels; ++i) { + SSchLevel *pLevel = taosArrayGet(pJob->levels, i); + + pLevel->taskExecDoneNum = 0; + pLevel->taskLaunchedNum = 0; + + int32_t numOfTasks = taosArrayGetSize(pLevel->subTasks); + for (int32_t j = 0; j < numOfTasks; ++j) { + SSchTask *pTask = taosArrayGet(pLevel->subTasks, j); + SCH_LOCK_TASK(pTask); + SCH_ERR_RET(schChkUpdateRedirectCtx(pJob, pTask, NULL, rspCode)); + qClearSubplanExecutionNode(pTask->plan); + schResetTaskForRetry(pJob, pTask); + SCH_UNLOCK_TASK(pTask); + } + } + + SCH_RESET_JOB_LEVEL_IDX(pJob); + + return TSDB_CODE_SUCCESS; +} + + +int32_t schHandleJobRetry(SSchJob *pJob, SSchTask *pTask, SDataBuf *pMsg, int32_t rspCode) { + int32_t code = 0; + + taosMemoryFreeClear(pMsg->pData); + taosMemoryFreeClear(pMsg->pEpSet); + + SCH_UNLOCK_TASK(pTask); + + SCH_TASK_DLOG("start to redirect all job tasks cause of error: %s", tstrerror(rspCode)); + + SCH_ERR_JRET(schResetJobForRetry(pJob, rspCode)); + + SCH_ERR_JRET(schLaunchJob(pJob)); + + SCH_LOCK_TASK(pTask); + + SCH_RET(code); + +_return: + + SCH_LOCK_TASK(pTask); + + SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); +} + bool schChkCurrentOp(SSchJob *pJob, int32_t op, int8_t sync) { bool r = false; SCH_LOCK(SCH_READ, &pJob->opStatus.lock); @@ -905,7 +993,7 @@ int32_t schProcessOnOpBegin(SSchJob *pJob, SCH_OP_TYPE type, SSchedulerReq *pReq SCH_ERR_RET(TSDB_CODE_APP_ERROR); } - if (status != JOB_TASK_STATUS_PART_SUCC) { + if (status != JOB_TASK_STATUS_PART_SUCC && status != JOB_TASK_STATUS_FETCH) { SCH_JOB_ELOG("job status error for fetch, status:%s", jobTaskStatusStr(status)); SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); } diff --git a/source/libs/scheduler/src/schRemote.c b/source/libs/scheduler/src/schRemote.c index b6de9383d7a6e59ac7453227ead12fb4ba095edc..80fdc7594cc63b8e893de9e4e7cf193592deb885 100644 --- a/source/libs/scheduler/src/schRemote.c +++ b/source/libs/scheduler/src/schRemote.c @@ -34,12 +34,12 @@ int32_t schValidateRspMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgType) { if (lastMsgType != reqMsgType) { SCH_TASK_ELOG("rsp msg type mis-match, last sent msgType:%s, rspType:%s", TMSG_INFO(lastMsgType), TMSG_INFO(msgType)); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + SCH_ERR_RET(TSDB_CODE_QW_MSG_ERROR); } - if (taskStatus != JOB_TASK_STATUS_PART_SUCC) { + if (taskStatus != JOB_TASK_STATUS_FETCH) { SCH_TASK_ELOG("rsp msg conflicted with task status, status:%s, rspType:%s", jobTaskStatusStr(taskStatus), TMSG_INFO(msgType)); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + SCH_ERR_RET(TSDB_CODE_QW_MSG_ERROR); } return TSDB_CODE_SUCCESS; @@ -60,13 +60,13 @@ int32_t schValidateRspMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgType) { if (lastMsgType != reqMsgType) { SCH_TASK_ELOG("rsp msg type mis-match, last sent msgType:%s, rspType:%s", TMSG_INFO(lastMsgType), TMSG_INFO(msgType)); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + SCH_ERR_RET(TSDB_CODE_QW_MSG_ERROR); } if (taskStatus != JOB_TASK_STATUS_EXEC) { SCH_TASK_ELOG("rsp msg conflicted with task status, status:%s, rspType:%s", jobTaskStatusStr(taskStatus), TMSG_INFO(msgType)); - SCH_ERR_RET(TSDB_CODE_SCH_STATUS_ERROR); + SCH_ERR_RET(TSDB_CODE_QW_MSG_ERROR); } return TSDB_CODE_SUCCESS; @@ -137,25 +137,12 @@ int32_t schProcessExplainRsp(SSchJob *pJob, SSchTask *pTask, SExplainRsp *rsp) { return TSDB_CODE_SUCCESS; } -// Note: no more task error processing, handled in function internal -int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDataBuf *pMsg, int32_t rspCode) { +int32_t schProcessResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDataBuf *pMsg, int32_t rspCode) { int32_t code = 0; char *msg = pMsg->pData; int32_t msgSize = pMsg->len; int32_t msgType = pMsg->msgType; - bool dropExecNode = (msgType == TDMT_SCH_LINK_BROKEN || SCH_NETWORK_ERR(rspCode)); - if (SCH_IS_QUERY_JOB(pJob)) { - SCH_ERR_JRET(schUpdateTaskHandle(pJob, pTask, dropExecNode, pMsg->handle, execId)); - } - - SCH_ERR_JRET(schValidateRspMsgType(pJob, pTask, msgType)); - - int32_t reqType = IsReq(pMsg) ? pMsg->msgType : (pMsg->msgType - 1); - if (SCH_TASK_NEED_REDIRECT(pTask, reqType, rspCode, pMsg->len)) { - SCH_RET(schHandleRedirect(pJob, pTask, (SDataBuf *)pMsg, rspCode)); - } - pTask->redirectCtx.inRedirect = false; switch (msgType) { @@ -261,46 +248,51 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDa if (msg) { SDecoder coder = {0}; - SSubmitRsp *rsp = taosMemoryMalloc(sizeof(*rsp)); + SSubmitRsp2 *rsp = taosMemoryMalloc(sizeof(*rsp)); tDecoderInit(&coder, msg, msgSize); - code = tDecodeSSubmitRsp(&coder, rsp); + code = tDecodeSSubmitRsp2(&coder, rsp); + tDecoderClear(&coder); if (code) { - SCH_TASK_ELOG("decode submitRsp failed, code:%d", code); - tFreeSSubmitRsp(rsp); + SCH_TASK_ELOG("tDecodeSSubmitRsp2 failed, code:%d", code); + tDestroySSubmitRsp2(rsp, TSDB_MSG_FLG_DECODE); + taosMemoryFree(rsp); SCH_ERR_JRET(code); } - if (rsp->nBlocks > 0) { - for (int32_t i = 0; i < rsp->nBlocks; ++i) { - SSubmitBlkRsp *blk = rsp->pBlocks + i; - if (TSDB_CODE_SUCCESS != blk->code) { - code = blk->code; - tFreeSSubmitRsp(rsp); - SCH_ERR_JRET(code); + atomic_add_fetch_64(&pJob->resNumOfRows, rsp->affectedRows); + + int32_t createTbRspNum = taosArrayGetSize(rsp->aCreateTbRsp); + SCH_TASK_DLOG("submit succeed, affectedRows:%d, createTbRspNum:%d", rsp->affectedRows, createTbRspNum); + + if (rsp->aCreateTbRsp && taosArrayGetSize(rsp->aCreateTbRsp) > 0) { + SCH_LOCK(SCH_WRITE, &pJob->resLock); + if (pJob->execRes.res) { + SSubmitRsp2 *sum = pJob->execRes.res; + sum->affectedRows += rsp->affectedRows; + if (sum->aCreateTbRsp) { + taosArrayAddAll(sum->aCreateTbRsp, rsp->aCreateTbRsp); + taosArrayDestroy(rsp->aCreateTbRsp); + } else { + TSWAP(sum->aCreateTbRsp, rsp->aCreateTbRsp); } + taosMemoryFree(rsp); + } else { + pJob->execRes.res = rsp; + pJob->execRes.msgType = TDMT_VND_SUBMIT; } - } - - atomic_add_fetch_64(&pJob->resNumOfRows, rsp->affectedRows); - SCH_TASK_DLOG("submit succeed, affectedRows:%d, blocks:%d", rsp->affectedRows, rsp->nBlocks); - - SCH_LOCK(SCH_WRITE, &pJob->resLock); - if (pJob->execRes.res) { - SSubmitRsp *sum = pJob->execRes.res; - sum->affectedRows += rsp->affectedRows; - sum->nBlocks += rsp->nBlocks; - if (rsp->nBlocks > 0 && rsp->pBlocks) { - sum->pBlocks = taosMemoryRealloc(sum->pBlocks, sum->nBlocks * sizeof(*sum->pBlocks)); - memcpy(sum->pBlocks + sum->nBlocks - rsp->nBlocks, rsp->pBlocks, rsp->nBlocks * sizeof(*sum->pBlocks)); + pJob->execRes.numOfBytes += pTask->msgLen; + SCH_UNLOCK(SCH_WRITE, &pJob->resLock); + } else { + SCH_LOCK(SCH_WRITE, &pJob->resLock); + pJob->execRes.numOfBytes += pTask->msgLen; + if (NULL == pJob->execRes.res) { + TSWAP(pJob->execRes.res, rsp); + pJob->execRes.msgType = TDMT_VND_SUBMIT; } - taosMemoryFree(rsp->pBlocks); + SCH_UNLOCK(SCH_WRITE, &pJob->resLock); + tDestroySSubmitRsp2(rsp, TSDB_MSG_FLG_DECODE); taosMemoryFree(rsp); - } else { - pJob->execRes.res = rsp; - pJob->execRes.msgType = TDMT_VND_SUBMIT; } - pJob->execRes.numOfBytes += pTask->msgLen; - SCH_UNLOCK(SCH_WRITE, &pJob->resLock); } taosMemoryFreeClear(msg); @@ -336,6 +328,14 @@ int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDa SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); } + if (taosArrayGetSize(pTask->parents) == 0 && SCH_IS_EXPLAIN_JOB(pJob) && SCH_IS_INSERT_JOB(pJob)) { + SRetrieveTableRsp *pRsp = NULL; + SCH_ERR_JRET(qExecExplainEnd(pJob->explainCtx, &pRsp)); + if (pRsp) { + SCH_ERR_JRET(schProcessOnExplainDone(pJob, pTask, pRsp)); + } + } + SQueryTableRsp rsp = {0}; if (tDeserializeSQueryTableRsp(msg, msgSize, &rsp) < 0) { SCH_TASK_ELOG("tDeserializeSQueryTableRsp failed, msgSize:%d", msgSize); @@ -410,6 +410,38 @@ _return: SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); } + + +// Note: no more task error processing, handled in function internal +int32_t schHandleResponseMsg(SSchJob *pJob, SSchTask *pTask, int32_t execId, SDataBuf *pMsg, int32_t rspCode) { + int32_t code = 0; + int32_t msgType = pMsg->msgType; + char *msg = pMsg->pData; + + bool dropExecNode = (msgType == TDMT_SCH_LINK_BROKEN || SCH_NETWORK_ERR(rspCode)); + if (SCH_IS_QUERY_JOB(pJob)) { + SCH_ERR_JRET(schUpdateTaskHandle(pJob, pTask, dropExecNode, pMsg->handle, execId)); + } + + SCH_ERR_JRET(schValidateRspMsgType(pJob, pTask, msgType)); + + int32_t reqType = IsReq(pMsg) ? pMsg->msgType : (pMsg->msgType - 1); + if (SCH_JOB_NEED_RETRY(pJob, pTask, reqType, rspCode)) { + SCH_RET(schHandleJobRetry(pJob, pTask, (SDataBuf *)pMsg, rspCode)); + } else if (SCH_TASKSET_NEED_RETRY(pJob, pTask, reqType, rspCode)) { + SCH_RET(schHandleTaskSetRetry(pJob, pTask, (SDataBuf *)pMsg, rspCode)); + } + + pTask->redirectCtx.inRedirect = false; + + SCH_RET(schProcessResponseMsg(pJob, pTask, execId, pMsg, rspCode)); + +_return: + + taosMemoryFreeClear(msg); + + SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); +} int32_t schHandleCallback(void *param, SDataBuf *pMsg, int32_t rspCode) { int32_t code = 0; SSchTaskCallbackParam *pParam = (SSchTaskCallbackParam *)param; @@ -874,7 +906,7 @@ int32_t schUpdateSendTargetInfo(SMsgSendInfo *pMsgSendInfo, SQueryNodeAddr *addr } else { pMsgSendInfo->target.type = TARGET_TYPE_VNODE; pMsgSendInfo->target.vgId = addr->nodeId; - pMsgSendInfo->target.dbFName = strdup(pTask->plan->dbFName); + pMsgSendInfo->target.dbFName = taosStrdup(pTask->plan->dbFName); } return TSDB_CODE_SUCCESS; diff --git a/source/libs/scheduler/src/schStatus.c b/source/libs/scheduler/src/schStatus.c index 4c16a81a05003166978dd9ee0f96b2c876f6fefd..9d0ad30e2a47de92136ec1f25bffa6f761ea7725 100644 --- a/source/libs/scheduler/src/schStatus.c +++ b/source/libs/scheduler/src/schStatus.c @@ -34,6 +34,9 @@ int32_t schSwitchJobStatus(SSchJob* pJob, int32_t status, void* param) { case JOB_TASK_STATUS_PART_SUCC: SCH_ERR_JRET(schProcessOnJobPartialSuccess(pJob)); break; + case JOB_TASK_STATUS_FETCH: + SCH_ERR_JRET(schJobFetchRows(pJob)); + break; case JOB_TASK_STATUS_SUCC: break; case JOB_TASK_STATUS_FAIL: diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index 8e60222ca6d4d53b189cffaf05fbae8c7f5dcdde..207753ae2571fe292ca009cb6af51030bf0667f0 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -64,6 +64,7 @@ int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel * pTask->plan = pPlan; pTask->level = pLevel; pTask->execId = -1; + pTask->failedExecId = -2; pTask->timeoutUsec = SCH_DEFAULT_TASK_TIMEOUT_USEC; pTask->taskId = schGenTaskId(); @@ -166,7 +167,7 @@ int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, v schUpdateTaskExecNode(pJob, pTask, handle, execId); - if ((execId != pTask->execId) || pTask->waitRetry) { // ignore it + if ((execId != pTask->execId || execId <= pTask->failedExecId) || pTask->waitRetry) { // ignore it SCH_TASK_DLOG("handle not updated since execId %d is already not current execId %d, waitRetry %d", execId, pTask->execId, pTask->waitRetry); SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR); @@ -182,6 +183,8 @@ int32_t schProcessOnTaskFailure(SSchJob *pJob, SSchTask *pTask, int32_t errCode) return TSDB_CODE_SCH_IGNORE_ERROR; } + pTask->failedExecId = pTask->execId; + int8_t jobStatus = 0; if (schJobNeedToStop(pJob, &jobStatus)) { SCH_TASK_DLOG("no more task failure processing cause of job status %s", jobTaskStatusStr(jobStatus)); @@ -375,7 +378,8 @@ int32_t schChkUpdateRedirectCtx(SSchJob *pJob, SSchTask *pTask, SEpSet *pEpSet, if (lastTime > tsMaxRetryWaitTime) { SCH_TASK_DLOG("task no more redirect retry since timeout, now:%" PRId64 ", start:%" PRId64 ", max:%d, total:%d", nowTs, pCtx->startTs, tsMaxRetryWaitTime, pCtx->totalTimes); - SCH_ERR_RET(SCH_GET_REDICT_CODE(pJob, rspCode)); + pJob->noMoreRetry = true; + SCH_ERR_RET(SCH_GET_REDIRECT_CODE(pJob, rspCode)); } pCtx->periodMs *= tsRedirectFactor; @@ -401,32 +405,35 @@ _return: return TSDB_CODE_SUCCESS; } -int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32_t rspCode) { - int32_t code = 0; - - SCH_TASK_DLOG("task will be redirected now, status:%s, code:%s", SCH_GET_TASK_STATUS_STR(pTask), tstrerror(rspCode)); - - if (NULL == pData) { - pTask->retryTimes = 0; - } - - if (!NO_RET_REDIRECT_ERROR(rspCode)) { - SCH_UPDATE_REDICT_CODE(pJob, rspCode); - } - - SCH_ERR_JRET(schChkUpdateRedirectCtx(pJob, pTask, pData ? pData->pEpSet : NULL, rspCode)); - +void schResetTaskForRetry(SSchJob *pJob, SSchTask *pTask) { pTask->waitRetry = true; schDropTaskOnExecNode(pJob, pTask); + if (pTask->delayTimer) { + taosTmrStopA(&pTask->delayTimer); + } taosHashClear(pTask->execNodes); schRemoveTaskFromExecList(pJob, pTask); schDeregisterTaskHb(pJob, pTask); - atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1); taosMemoryFreeClear(pTask->msg); pTask->msgLen = 0; pTask->lastMsgType = 0; + pTask->childReady = 0; memset(&pTask->succeedAddr, 0, sizeof(pTask->succeedAddr)); +} + +int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32_t rspCode) { + int32_t code = 0; + + SCH_TASK_DLOG("task will be redirected now, status:%s, code:%s", SCH_GET_TASK_STATUS_STR(pTask), tstrerror(rspCode)); + + if (!NO_RET_REDIRECT_ERROR(rspCode)) { + SCH_UPDATE_REDIRECT_CODE(pJob, rspCode); + } + + SCH_ERR_JRET(schChkUpdateRedirectCtx(pJob, pTask, pData ? pData->pEpSet : NULL, rspCode)); + + schResetTaskForRetry(pJob, pTask); if (SCH_IS_DATA_BIND_TASK(pTask)) { if (pData && pData->pEpSet) { @@ -442,12 +449,6 @@ int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32 SCH_TASK_DLOG("switch task target node %d epset to %d/%d", addr->nodeId, addr->epSet.inUse, addr->epSet.numOfEps); } - if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { - if (JOB_TASK_STATUS_EXEC == SCH_GET_TASK_STATUS(pTask)) { - SCH_ERR_JRET(schLaunchTasksInFlowCtrlList(pJob, pTask)); - } - } - SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT); SCH_ERR_JRET(schDelayLaunchTask(pJob, pTask)); @@ -483,20 +484,10 @@ _return: SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); } -int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32_t rspCode) { +int32_t schHandleTaskSetRetry(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32_t rspCode) { int32_t code = 0; - if (JOB_TASK_STATUS_PART_SUCC == pJob->status) { - SCH_LOCK(SCH_WRITE, &pJob->resLock); - if (pJob->fetched) { - SCH_UNLOCK(SCH_WRITE, &pJob->resLock); - SCH_TASK_ELOG("already fetched while got error %s", tstrerror(rspCode)); - SCH_ERR_JRET(rspCode); - } - SCH_UNLOCK(SCH_WRITE, &pJob->resLock); - - schUpdateJobStatus(pJob, JOB_TASK_STATUS_EXEC); - } + SCH_ERR_JRET(schChkResetJobRetry(pJob, rspCode)); if (SYNC_OTHER_LEADER_REDIRECT_ERROR(rspCode)) { if (NULL == pData->pEpSet) { @@ -506,7 +497,19 @@ int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32 } } + SCH_TASK_DLOG("start to redirect current task set cause of error: %s", tstrerror(rspCode)); + + for (int32_t i = 0; i < pJob->levelNum; ++i) { + SSchLevel *pLevel = taosArrayGet(pJob->levels, i); + + pLevel->taskExecDoneNum = 0; + pLevel->taskLaunchedNum = 0; + } + + SCH_RESET_JOB_LEVEL_IDX(pJob); + code = schDoTaskRedirect(pJob, pTask, pData, rspCode); + taosMemoryFreeClear(pData->pData); taosMemoryFreeClear(pData->pEpSet); @@ -618,6 +621,13 @@ int32_t schMoveTaskToExecList(SSchJob *pJob, SSchTask *pTask, bool *moved) { */ int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bool *needRetry) { + if (pJob->noMoreRetry) { + *needRetry = false; + SCH_TASK_DLOG("task no more retry since job no more retry, retryTimes:%d/%d", pTask->retryTimes, + pTask->maxRetryTimes); + return TSDB_CODE_SUCCESS; + } + if (TSDB_CODE_SCH_TIMEOUT_ERROR == errCode) { pTask->maxExecTimes++; pTask->maxRetryTimes++; @@ -642,7 +652,7 @@ int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bo return TSDB_CODE_SUCCESS; } - if (!SCH_NEED_RETRY(pTask->lastMsgType, errCode)) { + if (!SCH_TASK_NEED_RETRY(pTask->lastMsgType, errCode)) { *needRetry = false; SCH_TASK_DLOG("task no more retry cause of errCode, errCode:%x - %s", errCode, tstrerror(errCode)); return TSDB_CODE_SUCCESS; @@ -1064,7 +1074,6 @@ int32_t schLaunchTaskImpl(void *param) { SCH_ERR_JRET(TSDB_CODE_SCH_IGNORE_ERROR); } - // NOTE: race condition: the task should be put into the hash table before send msg to server if (SCH_GET_TASK_STATUS(pTask) != JOB_TASK_STATUS_EXEC) { SCH_ERR_JRET(schPushTaskToExecList(pJob, pTask)); SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_EXEC); @@ -1269,6 +1278,8 @@ int32_t schLaunchFetchTask(SSchJob *pJob) { return TSDB_CODE_SUCCESS; } + SCH_SET_TASK_STATUS(pJob->fetchTask, JOB_TASK_STATUS_FETCH); + if (SCH_IS_LOCAL_EXEC_TASK(pJob, pJob->fetchTask)) { SCH_ERR_JRET(schExecLocalFetch(pJob, pJob->fetchTask)); } else { diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index 7cd5e957b6b8d47871274f80632a65ec11485753..e7561ccb7ecf68c5030e12a19c04f3d1a9661cb5 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -18,6 +18,7 @@ #include "schInt.h" #include "tmsg.h" #include "tref.h" +#include "tglobal.h" SSchedulerMgmt schMgmt = { .jobRef = -1, @@ -30,11 +31,12 @@ int32_t schedulerInit() { } schMgmt.cfg.maxJobNum = SCHEDULE_DEFAULT_MAX_JOB_NUM; - schMgmt.cfg.maxNodeTableNum = SCHEDULE_DEFAULT_MAX_NODE_TABLE_NUM; + schMgmt.cfg.maxNodeTableNum = tsQueryMaxConcurrentTables; schMgmt.cfg.schPolicy = SCHEDULE_DEFAULT_POLICY; schMgmt.cfg.enableReSchedule = true; - qDebug("schedule policy init to %d", schMgmt.cfg.schPolicy); + qDebug("schedule init, policy: %d, maxNodeTableNum: %" PRId64", reSchedule:%d", + schMgmt.cfg.schPolicy, schMgmt.cfg.maxNodeTableNum, schMgmt.cfg.enableReSchedule); schMgmt.jobRef = taosOpenRef(schMgmt.cfg.maxJobNum, schFreeJobImpl); if (schMgmt.jobRef < 0) { @@ -91,7 +93,7 @@ int32_t schedulerFetchRows(int64_t jobId, SSchedulerReq *pReq) { SCH_ERR_JRET(schHandleOpBeginEvent(jobId, &pJob, SCH_OP_FETCH, pReq)); - SCH_ERR_JRET(schJobFetchRows(pJob)); + SCH_ERR_JRET(schSwitchJobStatus(pJob, JOB_TASK_STATUS_FETCH, pReq)); _return: diff --git a/source/libs/stream/CMakeLists.txt b/source/libs/stream/CMakeLists.txt index ceddf4f2153735c4d8423dde806272419dc35fc5..790547bb6154e6a53847f609d918fe4fac784c29 100644 --- a/source/libs/stream/CMakeLists.txt +++ b/source/libs/stream/CMakeLists.txt @@ -9,7 +9,7 @@ target_include_directories( target_link_libraries( stream PUBLIC tdb - PRIVATE os util transport qcom executor + PRIVATE os util transport qcom executor wal ) if(${BUILD_TEST}) diff --git a/source/libs/stream/inc/streamInc.h b/source/libs/stream/inc/streamInc.h index 66496f11f8b2da8ad46d91637efdeb1444f26319..b17afeec98da39a6cd7e28be4ee074f971d025c3 100644 --- a/source/libs/stream/inc/streamInc.h +++ b/source/libs/stream/inc/streamInc.h @@ -39,12 +39,12 @@ int32_t streamBroadcastToChildren(SStreamTask* pTask, const SSDataBlock* pBlock) int32_t tEncodeStreamRetrieveReq(SEncoder* pEncoder, const SStreamRetrieveReq* pReq); -int32_t streamDispatchOneCheckReq(SStreamTask* pTask, const SStreamTaskCheckReq* pReq, int32_t nodeId, SEpSet* pEpSet); +int32_t streamDispatchCheckMsg(SStreamTask* pTask, const SStreamTaskCheckReq* pReq, int32_t nodeId, SEpSet* pEpSet); int32_t streamDispatchOneRecoverFinishReq(SStreamTask* pTask, const SStreamRecoverFinishReq* pReq, int32_t vgId, SEpSet* pEpSet); -SStreamQueueItem* streamMergeQueueItem(SStreamQueueItem* dst, SStreamQueueItem* elem); +SStreamQueueItem* streamMergeQueueItem(SStreamQueueItem* dst, SStreamQueueItem* pElem); #ifdef __cplusplus } diff --git a/source/libs/stream/src/stream.c b/source/libs/stream/src/stream.c index 60729c4d0e5a292990eae57bccbdd3cc4c783ab9..f4ee0b98b7f4a996817d544132f8abb03f7b2f9b 100644 --- a/source/libs/stream/src/stream.c +++ b/source/libs/stream/src/stream.c @@ -16,6 +16,8 @@ #include "streamInc.h" #include "ttimer.h" +#define STREAM_TASK_INPUT_QUEUEU_CAPACITY 3000 + int32_t streamInit() { int8_t old; while (1) { @@ -50,7 +52,7 @@ void streamCleanUp() { void streamSchedByTimer(void* param, void* tmrId) { SStreamTask* pTask = (void*)param; - if (atomic_load_8(&pTask->taskStatus) == TASK_STATUS__DROPPING) { + if (streamTaskShouldStop(&pTask->status)) { streamMetaReleaseTask(NULL, pTask); return; } @@ -64,15 +66,16 @@ void streamSchedByTimer(void* param, void* tmrId) { taosFreeQitem(trigger); return; } - trigger->pBlock->info.type = STREAM_GET_ALL; + trigger->pBlock->info.type = STREAM_GET_ALL; atomic_store_8(&pTask->triggerStatus, TASK_TRIGGER_STATUS__INACTIVE); - if (streamTaskInput(pTask, (SStreamQueueItem*)trigger) < 0) { + if (tAppendDataToInputQueue(pTask, (SStreamQueueItem*)trigger) < 0) { taosFreeQitem(trigger); taosTmrReset(streamSchedByTimer, (int32_t)pTask->triggerParam, pTask, streamEnv.timer, &pTask->timer); return; } + streamSchedExec(pTask); } @@ -91,31 +94,33 @@ int32_t streamSetupTrigger(SStreamTask* pTask) { int32_t streamSchedExec(SStreamTask* pTask) { int8_t schedStatus = - atomic_val_compare_exchange_8(&pTask->schedStatus, TASK_SCHED_STATUS__INACTIVE, TASK_SCHED_STATUS__WAITING); + atomic_val_compare_exchange_8(&pTask->status.schedStatus, TASK_SCHED_STATUS__INACTIVE, TASK_SCHED_STATUS__WAITING); + if (schedStatus == TASK_SCHED_STATUS__INACTIVE) { SStreamTaskRunReq* pRunReq = rpcMallocCont(sizeof(SStreamTaskRunReq)); if (pRunReq == NULL) { - atomic_store_8(&pTask->schedStatus, TASK_SCHED_STATUS__INACTIVE); + terrno = TSDB_CODE_OUT_OF_MEMORY; + atomic_store_8(&pTask->status.schedStatus, TASK_SCHED_STATUS__INACTIVE); return -1; } + pRunReq->head.vgId = pTask->nodeId; - pRunReq->streamId = pTask->streamId; - pRunReq->taskId = pTask->taskId; - SRpcMsg msg = { - .msgType = TDMT_STREAM_TASK_RUN, - .pCont = pRunReq, - .contLen = sizeof(SStreamTaskRunReq), - }; + pRunReq->streamId = pTask->id.streamId; + pRunReq->taskId = pTask->id.taskId; + + SRpcMsg msg = { .msgType = TDMT_STREAM_TASK_RUN, .pCont = pRunReq, .contLen = sizeof(SStreamTaskRunReq) }; tmsgPutToQueue(pTask->pMsgCb, STREAM_QUEUE, &msg); + qDebug("trigger to run s-task:%s", pTask->id.idStr); } + return 0; } -int32_t streamTaskEnqueue(SStreamTask* pTask, const SStreamDispatchReq* pReq, SRpcMsg* pRsp) { +int32_t streamTaskEnqueueBlocks(SStreamTask* pTask, const SStreamDispatchReq* pReq, SRpcMsg* pRsp) { SStreamDataBlock* pData = taosAllocateQitem(sizeof(SStreamDataBlock), DEF_QITEM, 0); int8_t status; - // enqueue + // enqueue data block if (pData != NULL) { pData->type = STREAM_INPUT__DATA_BLOCK; pData->srcVgId = pReq->dataSrcVgId; @@ -123,10 +128,10 @@ int32_t streamTaskEnqueue(SStreamTask* pTask, const SStreamDispatchReq* pReq, SR /*pData->blocks = pReq->data;*/ /*pBlock->sourceVer = pReq->sourceVer;*/ streamDispatchReqToData(pReq, pData); - if (streamTaskInput(pTask, (SStreamQueueItem*)pData) == 0) { + if (tAppendDataToInputQueue(pTask, (SStreamQueueItem*)pData) == 0) { status = TASK_INPUT_STATUS__NORMAL; - } else { - status = TASK_INPUT_STATUS__FAILED; + } else { // input queue is full, upstream is blocked now + status = TASK_INPUT_STATUS__BLOCKED; } } else { streamTaskInputFail(pTask); @@ -142,10 +147,12 @@ int32_t streamTaskEnqueue(SStreamTask* pTask, const SStreamDispatchReq* pReq, SR pCont->upstreamNodeId = htonl(pReq->upstreamNodeId); pCont->upstreamTaskId = htonl(pReq->upstreamTaskId); pCont->downstreamNodeId = htonl(pTask->nodeId); - pCont->downstreamTaskId = htonl(pTask->taskId); + pCont->downstreamTaskId = htonl(pTask->id.taskId); pRsp->pCont = buf; + pRsp->contLen = sizeof(SMsgHead) + sizeof(SStreamDispatchRsp); tmsgSendRsp(pRsp); + return status == TASK_INPUT_STATUS__NORMAL ? 0 : -1; } @@ -155,7 +162,7 @@ int32_t streamTaskEnqueueRetrieve(SStreamTask* pTask, SStreamRetrieveReq* pReq, // enqueue if (pData != NULL) { - qDebug("task %d(child %d) recv retrieve req from task %d, reqId %" PRId64, pTask->taskId, pTask->selfChildId, + qDebug("task %d(child %d) recv retrieve req from task %d, reqId %" PRId64, pTask->id.taskId, pTask->selfChildId, pReq->srcTaskId, pReq->reqId); pData->type = STREAM_INPUT__DATA_RETRIEVE; @@ -164,7 +171,7 @@ int32_t streamTaskEnqueueRetrieve(SStreamTask* pTask, SStreamRetrieveReq* pReq, /*pData->blocks = pReq->data;*/ /*pBlock->sourceVer = pReq->sourceVer;*/ streamRetrieveReqToData(pReq, pData); - if (streamTaskInput(pTask, (SStreamQueueItem*)pData) == 0) { + if (tAppendDataToInputQueue(pTask, (SStreamQueueItem*)pData) == 0) { status = TASK_INPUT_STATUS__NORMAL; } else { status = TASK_INPUT_STATUS__FAILED; @@ -205,20 +212,17 @@ int32_t streamTaskOutput(SStreamTask* pTask, SStreamDataBlock* pBlock) { } int32_t streamProcessDispatchReq(SStreamTask* pTask, SStreamDispatchReq* pReq, SRpcMsg* pRsp, bool exec) { - qDebug("task %d receive dispatch req from node %d task %d", pTask->taskId, pReq->upstreamNodeId, - pReq->upstreamTaskId); + qDebug("s-task:%s receive dispatch req from taskId:%d(vgId:%d)", pTask->id.idStr, pReq->upstreamTaskId, + pReq->upstreamNodeId); - streamTaskEnqueue(pTask, pReq, pRsp); + // todo add the input queue buffer limitation + streamTaskEnqueueBlocks(pTask, pReq, pRsp); tDeleteStreamDispatchReq(pReq); if (exec) { if (streamTryExec(pTask) < 0) { return -1; } - - /*if (pTask->outputType == TASK_OUTPUT__FIXED_DISPATCH || pTask->outputType == TASK_OUTPUT__SHUFFLE_DISPATCH) {*/ - /*streamDispatch(pTask);*/ - /*}*/ } else { streamSchedExec(pTask); } @@ -228,13 +232,14 @@ int32_t streamProcessDispatchReq(SStreamTask* pTask, SStreamDispatchReq* pReq, S int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp, int32_t code) { ASSERT(pRsp->inputStatus == TASK_OUTPUT_STATUS__NORMAL || pRsp->inputStatus == TASK_OUTPUT_STATUS__BLOCKED); - - qDebug("task %d receive dispatch rsp, code: %x", pTask->taskId, code); + qDebug("s-task:%s receive dispatch rsp, code: %x", pTask->id.idStr, code); if (pTask->outputType == TASK_OUTPUT__SHUFFLE_DISPATCH) { int32_t leftRsp = atomic_sub_fetch_32(&pTask->shuffleDispatcher.waitingRspCnt, 1); - qDebug("task %d is shuffle, left waiting rsp %d", pTask->taskId, leftRsp); - if (leftRsp > 0) return 0; + qDebug("task %d is shuffle, left waiting rsp %d", pTask->id.taskId, leftRsp); + if (leftRsp > 0) { + return 0; + } } int8_t old = atomic_exchange_8(&pTask->outputStatus, pRsp->inputStatus); @@ -261,7 +266,7 @@ int32_t streamProcessRunReq(SStreamTask* pTask) { } int32_t streamProcessRetrieveReq(SStreamTask* pTask, SStreamRetrieveReq* pReq, SRpcMsg* pRsp) { - qDebug("task %d receive retrieve req from node %d task %d", pTask->taskId, pReq->srcNodeId, pReq->srcTaskId); + qDebug("task %d receive retrieve req from node %d task %d", pTask->id.taskId, pReq->srcNodeId, pReq->srcTaskId); streamTaskEnqueueRetrieve(pTask, pReq, pRsp); @@ -275,7 +280,71 @@ int32_t streamProcessRetrieveReq(SStreamTask* pTask, SStreamRetrieveReq* pReq, S return 0; } -int32_t streamProcessRetrieveRsp(SStreamTask* pTask, SStreamRetrieveRsp* pRsp) { - // +bool tInputQueueIsFull(const SStreamTask* pTask) { + return taosQueueItemSize((pTask->inputQueue->queue)) >= STREAM_TASK_INPUT_QUEUEU_CAPACITY; +} + +int32_t tAppendDataToInputQueue(SStreamTask* pTask, SStreamQueueItem* pItem) { + int8_t type = pItem->type; + + if (type == STREAM_INPUT__DATA_SUBMIT) { + SStreamDataSubmit2* pSubmitBlock = (SStreamDataSubmit2*)pItem; + int32_t total = taosQueueItemSize(pTask->inputQueue->queue) + 1; + qDebug("s-task:%s submit enqueue %p %p msgLen:%d ver:%" PRId64 ", total in queue:%d", pTask->id.idStr, + pItem, pSubmitBlock->submit.msgStr, pSubmitBlock->submit.msgLen, + pSubmitBlock->submit.ver, total); + + if ((pTask->taskLevel == TASK_LEVEL__SOURCE) && total > STREAM_TASK_INPUT_QUEUEU_CAPACITY) { + qError("s-task:%s input queue is full, capacity:%d, abort", pTask->id.idStr, STREAM_TASK_INPUT_QUEUEU_CAPACITY); + streamDataSubmitDestroy(pSubmitBlock); + taosFreeQitem(pSubmitBlock); + return -1; + } + + taosWriteQitem(pTask->inputQueue->queue, pSubmitBlock); + } else if (type == STREAM_INPUT__DATA_BLOCK || type == STREAM_INPUT__DATA_RETRIEVE || + type == STREAM_INPUT__REF_DATA_BLOCK) { + int32_t total = taosQueueItemSize(pTask->inputQueue->queue) + 1; + if ((pTask->taskLevel == TASK_LEVEL__SOURCE) && total > STREAM_TASK_INPUT_QUEUEU_CAPACITY) { + qError("s-task:%s input queue is full, capacity:%d, abort", pTask->id.idStr, STREAM_TASK_INPUT_QUEUEU_CAPACITY); + return -1; + } + + qDebug("s-task:%s data block enqueue, total in queue:%d", pTask->id.idStr, total); + taosWriteQitem(pTask->inputQueue->queue, pItem); + } else if (type == STREAM_INPUT__CHECKPOINT) { + taosWriteQitem(pTask->inputQueue->queue, pItem); + } else if (type == STREAM_INPUT__GET_RES) { + taosWriteQitem(pTask->inputQueue->queue, pItem); + } + + if (type != STREAM_INPUT__GET_RES && type != STREAM_INPUT__CHECKPOINT && pTask->triggerParam != 0) { + atomic_val_compare_exchange_8(&pTask->triggerStatus, TASK_TRIGGER_STATUS__INACTIVE, TASK_TRIGGER_STATUS__ACTIVE); + } + +#if 0 + atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__NORMAL); +#endif + return 0; } + +void* streamQueueNextItem(SStreamQueue* queue) { + int8_t dequeueFlag = atomic_exchange_8(&queue->status, STREAM_QUEUE__PROCESSING); + if (dequeueFlag == STREAM_QUEUE__FAILED) { + ASSERT(queue->qItem != NULL); + return streamQueueCurItem(queue); + } else { + queue->qItem = NULL; + taosGetQitem(queue->qall, &queue->qItem); + if (queue->qItem == NULL) { + taosReadAllQitems(queue->queue, queue->qall); + taosGetQitem(queue->qall, &queue->qItem); + } + return streamQueueCurItem(queue); + } +} + +void streamTaskInputFail(SStreamTask* pTask) { + atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED); +} \ No newline at end of file diff --git a/source/libs/stream/src/streamCheckpoint.c b/source/libs/stream/src/streamCheckpoint.c index efd19074da1b2f51e1217b3f7ab359f2b4a33c95..670cfbead1e180061fe0f972290351125eb9852c 100644 --- a/source/libs/stream/src/streamCheckpoint.c +++ b/source/libs/stream/src/streamCheckpoint.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ +#if 0 #include "streamInc.h" int32_t tEncodeSStreamCheckpointSourceReq(SEncoder* pEncoder, const SStreamCheckpointSourceReq* pReq) { @@ -192,3 +193,4 @@ int32_t streamProcessCheckpointRsp(SStreamMeta* pMeta, SStreamTask* pTask, SStre // set status normal return 0; } +#endif diff --git a/source/libs/stream/src/streamData.c b/source/libs/stream/src/streamData.c index 8b869cc59f669d3de6a1bc49ca874b75a4189645..96022850a3511b20b2b6003d1f9409b27400011a 100644 --- a/source/libs/stream/src/streamData.c +++ b/source/libs/stream/src/streamData.c @@ -17,7 +17,7 @@ int32_t streamDispatchReqToData(const SStreamDispatchReq* pReq, SStreamDataBlock* pData) { int32_t blockNum = pReq->blockNum; - SArray* pArray = taosArrayInit_s(blockNum, sizeof(SSDataBlock), blockNum); + SArray* pArray = taosArrayInit_s(sizeof(SSDataBlock), blockNum); if (pArray == NULL) { return -1; } @@ -26,7 +26,7 @@ int32_t streamDispatchReqToData(const SStreamDispatchReq* pReq, SStreamDataBlock ASSERT(pReq->blockNum == taosArrayGetSize(pReq->dataLen)); for (int32_t i = 0; i < blockNum; i++) { - SRetrieveTableRsp* pRetrieve = taosArrayGetP(pReq->data, i); + SRetrieveTableRsp* pRetrieve = (SRetrieveTableRsp*) taosArrayGetP(pReq->data, i); SSDataBlock* pDataBlock = taosArrayGet(pArray, i); blockDecode(pDataBlock, pRetrieve->data); // TODO: refactor @@ -48,10 +48,12 @@ int32_t streamRetrieveReqToData(const SStreamRetrieveReq* pReq, SStreamDataBlock if (pArray == NULL) { return -1; } + taosArrayPush(pArray, &(SSDataBlock){0}); SRetrieveTableRsp* pRetrieve = pReq->pRetrieve; SSDataBlock* pDataBlock = taosArrayGet(pArray, 0); blockDecode(pDataBlock, pRetrieve->data); + // TODO: refactor pDataBlock->info.window.skey = be64toh(pRetrieve->skey); pDataBlock->info.window.ekey = be64toh(pRetrieve->ekey); @@ -65,87 +67,98 @@ int32_t streamRetrieveReqToData(const SStreamRetrieveReq* pReq, SStreamDataBlock return 0; } -SStreamDataSubmit* streamDataSubmitNew(SSubmitReq* pReq) { - SStreamDataSubmit* pDataSubmit = (SStreamDataSubmit*)taosAllocateQitem(sizeof(SStreamDataSubmit), DEF_QITEM, 0); - if (pDataSubmit == NULL) return NULL; +SStreamDataSubmit2* streamDataSubmitNew(SPackedData submit, int32_t type) { + SStreamDataSubmit2* pDataSubmit = (SStreamDataSubmit2*)taosAllocateQitem(sizeof(SStreamDataSubmit2), DEF_QITEM, 0); + if (pDataSubmit == NULL) { + return NULL; + } + pDataSubmit->dataRef = (int32_t*)taosMemoryMalloc(sizeof(int32_t)); - if (pDataSubmit->dataRef == NULL) goto FAIL; - pDataSubmit->data = pReq; - *pDataSubmit->dataRef = 1; - pDataSubmit->type = STREAM_INPUT__DATA_SUBMIT; + if (pDataSubmit->dataRef == NULL) { + taosFreeQitem(pDataSubmit); + return NULL; + } + + pDataSubmit->submit = submit; + *pDataSubmit->dataRef = 1; // initialize the reference count to be 1 + pDataSubmit->type = type; + return pDataSubmit; -FAIL: - taosFreeQitem(pDataSubmit); - return NULL; } -SStreamMergedSubmit* streamMergedSubmitNew() { - SStreamMergedSubmit* pMerged = (SStreamMergedSubmit*)taosAllocateQitem(sizeof(SStreamMergedSubmit), DEF_QITEM, 0); - if (pMerged == NULL) return NULL; - pMerged->reqs = taosArrayInit(0, sizeof(void*)); +void streamDataSubmitDestroy(SStreamDataSubmit2* pDataSubmit) { + int32_t ref = atomic_sub_fetch_32(pDataSubmit->dataRef, 1); + ASSERT(ref >= 0 && pDataSubmit->type == STREAM_INPUT__DATA_SUBMIT); + + if (ref == 0) { + taosMemoryFree(pDataSubmit->submit.msgStr); + taosMemoryFree(pDataSubmit->dataRef); + } +} + +SStreamMergedSubmit2* streamMergedSubmitNew() { + SStreamMergedSubmit2* pMerged = (SStreamMergedSubmit2*)taosAllocateQitem(sizeof(SStreamMergedSubmit2), DEF_QITEM, 0); + if (pMerged == NULL) { + return NULL; + } + + pMerged->submits = taosArrayInit(0, sizeof(SPackedData)); pMerged->dataRefs = taosArrayInit(0, sizeof(void*)); - if (pMerged->dataRefs == NULL || pMerged->reqs == NULL) goto FAIL; + + if (pMerged->dataRefs == NULL || pMerged->submits == NULL) { + taosArrayDestroy(pMerged->submits); + taosArrayDestroy(pMerged->dataRefs); + taosFreeQitem(pMerged); + return NULL; + } + pMerged->type = STREAM_INPUT__MERGED_SUBMIT; return pMerged; -FAIL: - if (pMerged->reqs) taosArrayDestroy(pMerged->reqs); - if (pMerged->dataRefs) taosArrayDestroy(pMerged->dataRefs); - taosFreeQitem(pMerged); - return NULL; } -int32_t streamMergeSubmit(SStreamMergedSubmit* pMerged, SStreamDataSubmit* pSubmit) { +int32_t streamMergeSubmit(SStreamMergedSubmit2* pMerged, SStreamDataSubmit2* pSubmit) { taosArrayPush(pMerged->dataRefs, &pSubmit->dataRef); - taosArrayPush(pMerged->reqs, &pSubmit->data); + taosArrayPush(pMerged->submits, &pSubmit->submit); pMerged->ver = pSubmit->ver; return 0; } -static FORCE_INLINE void streamDataSubmitRefInc(SStreamDataSubmit* pDataSubmit) { +static FORCE_INLINE void streamDataSubmitRefInc(SStreamDataSubmit2* pDataSubmit) { atomic_add_fetch_32(pDataSubmit->dataRef, 1); } -SStreamDataSubmit* streamSubmitRefClone(SStreamDataSubmit* pSubmit) { - SStreamDataSubmit* pSubmitClone = taosAllocateQitem(sizeof(SStreamDataSubmit), DEF_QITEM, 0); +SStreamDataSubmit2* streamSubmitBlockClone(SStreamDataSubmit2* pSubmit) { + SStreamDataSubmit2* pSubmitClone = taosAllocateQitem(sizeof(SStreamDataSubmit2), DEF_QITEM, 0); if (pSubmitClone == NULL) { return NULL; } + streamDataSubmitRefInc(pSubmit); - memcpy(pSubmitClone, pSubmit, sizeof(SStreamDataSubmit)); + memcpy(pSubmitClone, pSubmit, sizeof(SStreamDataSubmit2)); return pSubmitClone; } -void streamDataSubmitRefDec(SStreamDataSubmit* pDataSubmit) { - int32_t ref = atomic_sub_fetch_32(pDataSubmit->dataRef, 1); - ASSERT(ref >= 0); - if (ref == 0) { - taosMemoryFree(pDataSubmit->data); - taosMemoryFree(pDataSubmit->dataRef); - } -} - -SStreamQueueItem* streamMergeQueueItem(SStreamQueueItem* dst, SStreamQueueItem* elem) { - ASSERT(elem); - if (dst->type == STREAM_INPUT__DATA_BLOCK && elem->type == STREAM_INPUT__DATA_BLOCK) { +SStreamQueueItem* streamMergeQueueItem(SStreamQueueItem* dst, SStreamQueueItem* pElem) { + if (dst->type == STREAM_INPUT__DATA_BLOCK && pElem->type == STREAM_INPUT__DATA_BLOCK) { SStreamDataBlock* pBlock = (SStreamDataBlock*)dst; - SStreamDataBlock* pBlockSrc = (SStreamDataBlock*)elem; + SStreamDataBlock* pBlockSrc = (SStreamDataBlock*)pElem; taosArrayAddAll(pBlock->blocks, pBlockSrc->blocks); taosArrayDestroy(pBlockSrc->blocks); - taosFreeQitem(elem); + taosFreeQitem(pElem); return dst; - } else if (dst->type == STREAM_INPUT__MERGED_SUBMIT && elem->type == STREAM_INPUT__DATA_SUBMIT) { - SStreamMergedSubmit* pMerged = (SStreamMergedSubmit*)dst; - SStreamDataSubmit* pBlockSrc = (SStreamDataSubmit*)elem; + } else if (dst->type == STREAM_INPUT__MERGED_SUBMIT && pElem->type == STREAM_INPUT__DATA_SUBMIT) { + SStreamMergedSubmit2* pMerged = (SStreamMergedSubmit2*)dst; + SStreamDataSubmit2* pBlockSrc = (SStreamDataSubmit2*)pElem; streamMergeSubmit(pMerged, pBlockSrc); - taosFreeQitem(elem); + taosFreeQitem(pElem); return dst; - } else if (dst->type == STREAM_INPUT__DATA_SUBMIT && elem->type == STREAM_INPUT__DATA_SUBMIT) { - SStreamMergedSubmit* pMerged = streamMergedSubmitNew(); + } else if (dst->type == STREAM_INPUT__DATA_SUBMIT && pElem->type == STREAM_INPUT__DATA_SUBMIT) { + SStreamMergedSubmit2* pMerged = streamMergedSubmitNew(); ASSERT(pMerged); - streamMergeSubmit(pMerged, (SStreamDataSubmit*)dst); - streamMergeSubmit(pMerged, (SStreamDataSubmit*)elem); + streamMergeSubmit(pMerged, (SStreamDataSubmit2*)dst); + streamMergeSubmit(pMerged, (SStreamDataSubmit2*)pElem); taosFreeQitem(dst); - taosFreeQitem(elem); + taosFreeQitem(pElem); return (SStreamQueueItem*)pMerged; } else { return NULL; @@ -161,33 +174,27 @@ void streamFreeQitem(SStreamQueueItem* data) { taosArrayDestroyEx(((SStreamDataBlock*)data)->blocks, (FDelete)blockDataFreeRes); taosFreeQitem(data); } else if (type == STREAM_INPUT__DATA_SUBMIT) { - streamDataSubmitRefDec((SStreamDataSubmit*)data); + streamDataSubmitDestroy((SStreamDataSubmit2*)data); taosFreeQitem(data); } else if (type == STREAM_INPUT__MERGED_SUBMIT) { - SStreamMergedSubmit* pMerge = (SStreamMergedSubmit*)data; - int32_t sz = taosArrayGetSize(pMerge->reqs); + SStreamMergedSubmit2* pMerge = (SStreamMergedSubmit2*)data; + int32_t sz = taosArrayGetSize(pMerge->submits); for (int32_t i = 0; i < sz; i++) { int32_t* pRef = taosArrayGetP(pMerge->dataRefs, i); int32_t ref = atomic_sub_fetch_32(pRef, 1); ASSERT(ref >= 0); if (ref == 0) { - void* dataStr = taosArrayGetP(pMerge->reqs, i); - taosMemoryFree(dataStr); + SPackedData* pSubmit = (SPackedData*)taosArrayGet(pMerge->submits, i); + taosMemoryFree(pSubmit->msgStr); taosMemoryFree(pRef); } } - taosArrayDestroy(pMerge->reqs); + taosArrayDestroy(pMerge->submits); taosArrayDestroy(pMerge->dataRefs); taosFreeQitem(pMerge); } else if (type == STREAM_INPUT__REF_DATA_BLOCK) { SStreamRefDataBlock* pRefBlock = (SStreamRefDataBlock*)data; - - int32_t ref = atomic_sub_fetch_32(pRefBlock->dataRef, 1); - ASSERT(ref >= 0); - if (ref == 0) { - blockDataDestroy(pRefBlock->pBlock); - taosMemoryFree(pRefBlock->dataRef); - } + blockDataDestroy(pRefBlock->pBlock); taosFreeQitem(pRefBlock); } } diff --git a/source/libs/stream/src/streamDispatch.c b/source/libs/stream/src/streamDispatch.c index f2b1db19e8eb3a15f9edf04d1bbbac3a6c750e0c..d12eca7ce318901917187ceca030eadc85cb9adf 100644 --- a/source/libs/stream/src/streamDispatch.c +++ b/source/libs/stream/src/streamDispatch.c @@ -121,9 +121,9 @@ int32_t streamBroadcastToChildren(SStreamTask* pTask, const SSDataBlock* pBlock) int32_t actualLen = blockEncode(pBlock, pRetrieve->data, numOfCols); SStreamRetrieveReq req = { - .streamId = pTask->streamId, + .streamId = pTask->id.streamId, .srcNodeId = pTask->nodeId, - .srcTaskId = pTask->taskId, + .srcTaskId = pTask->id.taskId, .pRetrieve = pRetrieve, .retrieveLen = dataStrLen, }; @@ -168,7 +168,7 @@ int32_t streamBroadcastToChildren(SStreamTask* pTask, const SSDataBlock* pBlock) } buf = NULL; - qDebug("task %d(child %d) send retrieve req to task %d at node %d, reqId %" PRId64, pTask->taskId, + qDebug("s-task:%s (child %d) send retrieve req to task %d at node %d, reqId %" PRId64, pTask->id.idStr, pTask->selfChildId, pEpInfo->taskId, pEpInfo->nodeId, req.reqId); } code = 0; @@ -208,7 +208,7 @@ static int32_t streamAddBlockToDispatchMsg(const SSDataBlock* pBlock, SStreamDis return 0; } -int32_t streamDispatchOneCheckReq(SStreamTask* pTask, const SStreamTaskCheckReq* pReq, int32_t nodeId, SEpSet* pEpSet) { +int32_t streamDispatchCheckMsg(SStreamTask* pTask, const SStreamTaskCheckReq* pReq, int32_t nodeId, SEpSet* pEpSet) { void* buf = NULL; int32_t code = -1; SRpcMsg msg = {0}; @@ -230,22 +230,21 @@ int32_t streamDispatchOneCheckReq(SStreamTask* pTask, const SStreamTaskCheckReq* SEncoder encoder; tEncoderInit(&encoder, abuf, tlen); if ((code = tEncodeSStreamTaskCheckReq(&encoder, pReq)) < 0) { - goto FAIL; + rpcFreeCont(buf); + return code; } + tEncoderClear(&encoder); msg.contLen = tlen + sizeof(SMsgHead); msg.pCont = buf; msg.msgType = TDMT_STREAM_TASK_CHECK; - qDebug("dispatch from task %d to task %d node %d: check msg", pTask->taskId, pReq->downstreamTaskId, nodeId); + qDebug("s-task:%s dispatch check msg to downstream s-task:%" PRIx64 ":%d node %d: check msg", pTask->id.idStr, + pReq->streamId, pReq->downstreamTaskId, nodeId); tmsgSendReq(pEpSet, &msg); - return 0; -FAIL: - if (buf) rpcFreeCont(buf); - return code; } int32_t streamDispatchOneRecoverFinishReq(SStreamTask* pTask, const SStreamRecoverFinishReq* pReq, int32_t vgId, @@ -278,10 +277,11 @@ int32_t streamDispatchOneRecoverFinishReq(SStreamTask* pTask, const SStreamRecov msg.contLen = tlen + sizeof(SMsgHead); msg.pCont = buf; msg.msgType = TDMT_STREAM_RECOVER_FINISH; + msg.info.noResp = 1; tmsgSendReq(pEpSet, &msg); - qDebug("dispatch from task %d to task %d node %d: recover finish msg", pTask->taskId, pReq->taskId, vgId); + qDebug("dispatch from task %d to task %d node %d: recover finish msg", pTask->id.taskId, pReq->taskId, vgId); return 0; FAIL: @@ -318,8 +318,7 @@ int32_t streamDispatchOneDataReq(SStreamTask* pTask, const SStreamDispatchReq* p msg.pCont = buf; msg.msgType = pTask->dispatchMsgType; - qDebug("dispatch from task %d to task %d node %d: data msg", pTask->taskId, pReq->taskId, vgId); - + qDebug("dispatch from s-task:%s to taskId:%d vgId:%d data msg", pTask->id.idStr, pReq->taskId, vgId); tmsgSendReq(pEpSet, &msg); code = 0; @@ -381,9 +380,9 @@ int32_t streamDispatchAllBlocks(SStreamTask* pTask, const SStreamDataBlock* pDat if (pTask->outputType == TASK_OUTPUT__FIXED_DISPATCH) { SStreamDispatchReq req = { - .streamId = pTask->streamId, + .streamId = pTask->id.streamId, .dataSrcVgId = pData->srcVgId, - .upstreamTaskId = pTask->taskId, + .upstreamTaskId = pTask->id.taskId, .upstreamChildId = pTask->selfChildId, .upstreamNodeId = pTask->nodeId, .blockNum = blockNum, @@ -401,14 +400,15 @@ int32_t streamDispatchAllBlocks(SStreamTask* pTask, const SStreamDataBlock* pDat goto FAIL_FIXED_DISPATCH; } } + int32_t vgId = pTask->fixedEpDispatcher.nodeId; SEpSet* pEpSet = &pTask->fixedEpDispatcher.epSet; int32_t downstreamTaskId = pTask->fixedEpDispatcher.taskId; req.taskId = downstreamTaskId; - qDebug("dispatch from task %d (child id %d) to down stream task %d in vnode %d", pTask->taskId, pTask->selfChildId, - downstreamTaskId, vgId); + qDebug("s-task:%s (child taskId:%d) dispatch blocks:%d to down stream s-task:%d in vgId:%d", pTask->id.idStr, + pTask->selfChildId, blockNum, downstreamTaskId, vgId); if (streamDispatchOneDataReq(pTask, &req, vgId, pEpSet) < 0) { goto FAIL_FIXED_DISPATCH; @@ -431,9 +431,9 @@ int32_t streamDispatchAllBlocks(SStreamTask* pTask, const SStreamDataBlock* pDat } for (int32_t i = 0; i < vgSz; i++) { - pReqs[i].streamId = pTask->streamId; + pReqs[i].streamId = pTask->id.streamId; pReqs[i].dataSrcVgId = pData->srcVgId; - pReqs[i].upstreamTaskId = pTask->taskId; + pReqs[i].upstreamTaskId = pTask->id.taskId; pReqs[i].upstreamChildId = pTask->selfChildId; pReqs[i].upstreamNodeId = pTask->nodeId; pReqs[i].blockNum = 0; @@ -493,6 +493,8 @@ int32_t streamDispatchAllBlocks(SStreamTask* pTask, const SStreamDataBlock* pDat int32_t streamDispatch(SStreamTask* pTask) { ASSERT(pTask->outputType == TASK_OUTPUT__FIXED_DISPATCH || pTask->outputType == TASK_OUTPUT__SHUFFLE_DISPATCH); + qDebug("s-task:%s try to dispatch intermediate result block to downstream, numofBlocks in outputQ:%d", pTask->id.idStr, + taosQueueItemSize(pTask->outputQueue->queue)); int8_t old = atomic_val_compare_exchange_8(&pTask->outputStatus, TASK_OUTPUT_STATUS__NORMAL, TASK_OUTPUT_STATUS__WAIT); @@ -502,13 +504,12 @@ int32_t streamDispatch(SStreamTask* pTask) { SStreamDataBlock* pBlock = streamQueueNextItem(pTask->outputQueue); if (pBlock == NULL) { - qDebug("stream stop dispatching since no output: task %d", pTask->taskId); + qDebug("s-task:%s stream stop dispatching since no output in output queue", pTask->id.idStr); atomic_store_8(&pTask->outputStatus, TASK_OUTPUT_STATUS__NORMAL); return 0; } - ASSERT(pBlock->type == STREAM_INPUT__DATA_BLOCK); - qDebug("stream dispatching: task %d", pTask->taskId); + ASSERT(pBlock->type == STREAM_INPUT__DATA_BLOCK); int32_t code = 0; if (streamDispatchAllBlocks(pTask, pBlock) < 0) { @@ -517,9 +518,9 @@ int32_t streamDispatch(SStreamTask* pTask) { atomic_store_8(&pTask->outputStatus, TASK_OUTPUT_STATUS__NORMAL); goto FREE; } + FREE: taosArrayDestroyEx(pBlock->blocks, (FDelete)blockDataFreeRes); taosFreeQitem(pBlock); return code; } - diff --git a/source/libs/stream/src/streamExec.c b/source/libs/stream/src/streamExec.c index 786ee9d079a229eb78e1c04ae3eba20bf5393351..e093d450742289d64c3bc705aef46a0171cbcfd3 100644 --- a/source/libs/stream/src/streamExec.c +++ b/source/libs/stream/src/streamExec.c @@ -15,62 +15,90 @@ #include "streamInc.h" +#define STREAM_EXEC_MAX_BATCH_NUM 100 + +bool streamTaskShouldStop(const SStreamStatus* pStatus) { + int32_t status = atomic_load_8((int8_t*) &pStatus->taskStatus); + return (status == TASK_STATUS__STOP) || (status == TASK_STATUS__DROPPING); +} + static int32_t streamTaskExecImpl(SStreamTask* pTask, const void* data, SArray* pRes) { - int32_t code; - void* exec = pTask->exec.executor; + int32_t code = TSDB_CODE_SUCCESS; + void* pExecutor = pTask->exec.pExecutor; + + while (pTask->taskLevel == TASK_LEVEL__SOURCE) { + int8_t status = atomic_load_8(&pTask->status.taskStatus); + if (status != TASK_STATUS__NORMAL) { + qError("stream task wait for the end of fill history, s-task:%s, status:%d", pTask->id.idStr, + atomic_load_8(&pTask->status.taskStatus)); + taosMsleep(2); + } else { + break; + } + } // set input const SStreamQueueItem* pItem = (const SStreamQueueItem*)data; if (pItem->type == STREAM_INPUT__GET_RES) { const SStreamTrigger* pTrigger = (const SStreamTrigger*)data; - qSetMultiStreamInput(exec, pTrigger->pBlock, 1, STREAM_INPUT__DATA_BLOCK); + qSetMultiStreamInput(pExecutor, pTrigger->pBlock, 1, STREAM_INPUT__DATA_BLOCK); } else if (pItem->type == STREAM_INPUT__DATA_SUBMIT) { ASSERT(pTask->taskLevel == TASK_LEVEL__SOURCE); - const SStreamDataSubmit* pSubmit = (const SStreamDataSubmit*)data; - qDebug("task %d %p set submit input %p %p %d 1", pTask->taskId, pTask, pSubmit, pSubmit->data, *pSubmit->dataRef); - qSetMultiStreamInput(exec, pSubmit->data, 1, STREAM_INPUT__DATA_SUBMIT); + const SStreamDataSubmit2* pSubmit = (const SStreamDataSubmit2*)data; + qSetMultiStreamInput(pExecutor, &pSubmit->submit, 1, STREAM_INPUT__DATA_SUBMIT); + qDebug("s-task:%s set submit blocks as source block completed, %p %p len:%d ver:%" PRId64, pTask->id.idStr, pSubmit, pSubmit->submit.msgStr, + pSubmit->submit.msgLen, pSubmit->submit.ver); } else if (pItem->type == STREAM_INPUT__DATA_BLOCK || pItem->type == STREAM_INPUT__DATA_RETRIEVE) { const SStreamDataBlock* pBlock = (const SStreamDataBlock*)data; - SArray* blocks = pBlock->blocks; - qDebug("task %d %p set ssdata input", pTask->taskId, pTask); - qSetMultiStreamInput(exec, blocks->pData, blocks->size, STREAM_INPUT__DATA_BLOCK); + + SArray* pBlockList = pBlock->blocks; + int32_t numOfBlocks = taosArrayGetSize(pBlockList); + qDebug("s-task:%s set sdata blocks as input num:%d, ver:%"PRId64, pTask->id.idStr, numOfBlocks, pBlock->sourceVer); + qSetMultiStreamInput(pExecutor, pBlockList->pData, numOfBlocks, STREAM_INPUT__DATA_BLOCK); } else if (pItem->type == STREAM_INPUT__MERGED_SUBMIT) { - const SStreamMergedSubmit* pMerged = (const SStreamMergedSubmit*)data; - SArray* blocks = pMerged->reqs; - qDebug("task %d %p set submit input (merged), batch num: %d", pTask->taskId, pTask, (int32_t)blocks->size); - qSetMultiStreamInput(exec, blocks->pData, blocks->size, STREAM_INPUT__MERGED_SUBMIT); + const SStreamMergedSubmit2* pMerged = (const SStreamMergedSubmit2*)data; + + SArray* pBlockList = pMerged->submits; + int32_t numOfBlocks = taosArrayGetSize(pBlockList); + qDebug("s-task:%s %p set submit input (merged), batch num:%d", pTask->id.idStr, pTask, numOfBlocks); + qSetMultiStreamInput(pExecutor, pBlockList->pData, numOfBlocks, STREAM_INPUT__MERGED_SUBMIT); } else if (pItem->type == STREAM_INPUT__REF_DATA_BLOCK) { const SStreamRefDataBlock* pRefBlock = (const SStreamRefDataBlock*)data; - qSetMultiStreamInput(exec, pRefBlock->pBlock, 1, STREAM_INPUT__DATA_BLOCK); + qSetMultiStreamInput(pExecutor, pRefBlock->pBlock, 1, STREAM_INPUT__DATA_BLOCK); } else { ASSERT(0); } - // exec + // pExecutor while (1) { - if (pTask->taskStatus == TASK_STATUS__DROPPING) { + if (streamTaskShouldStop(&pTask->status)) { return 0; } SSDataBlock* output = NULL; uint64_t ts = 0; - if ((code = qExecTask(exec, &output, &ts)) < 0) { - /*ASSERT(false);*/ - qError("unexpected stream execution, stream %" PRId64 " task: %d, since %s", pTask->streamId, pTask->taskId, - terrstr()); + if ((code = qExecTask(pExecutor, &output, &ts)) < 0) { + if (code == TSDB_CODE_QRY_IN_EXEC) { + resetTaskInfo(pExecutor); + } + + qError("unexpected stream execution, s-task:%s since %s", pTask->id.idStr, terrstr()); continue; } + if (output == NULL) { if (pItem->type == STREAM_INPUT__DATA_RETRIEVE) { - SSDataBlock block = {0}; + SSDataBlock block = {0}; + const SStreamDataBlock* pRetrieveBlock = (const SStreamDataBlock*)data; ASSERT(taosArrayGetSize(pRetrieveBlock->blocks) == 1); + assignOneDataBlock(&block, taosArrayGet(pRetrieveBlock->blocks, 0)); block.info.type = STREAM_PULL_OVER; block.info.childId = pTask->selfChildId; taosArrayPush(pRes, &block); - qDebug("task %d(child %d) processed retrieve, reqId %" PRId64, pTask->taskId, pTask->selfChildId, + qDebug("task %d(child %d) processed retrieve, reqId %" PRId64, pTask->id.taskId, pTask->selfChildId, pRetrieveBlock->reqId); } break; @@ -83,20 +111,21 @@ static int32_t streamTaskExecImpl(SStreamTask* pTask, const void* data, SArray* continue; } - qDebug("task %d(child %d) executed and get block", pTask->taskId, pTask->selfChildId); + qDebug("s-task:%s (child %d) executed and get block", pTask->id.idStr, pTask->selfChildId); SSDataBlock block = {0}; assignOneDataBlock(&block, output); block.info.childId = pTask->selfChildId; taosArrayPush(pRes, &block); } + return 0; } int32_t streamScanExec(SStreamTask* pTask, int32_t batchSz) { ASSERT(pTask->taskLevel == TASK_LEVEL__SOURCE); - void* exec = pTask->exec.executor; + void* exec = pTask->exec.pExecutor; qSetStreamOpOpen(exec); bool finished = false; @@ -110,14 +139,15 @@ int32_t streamScanExec(SStreamTask* pTask, int32_t batchSz) { int32_t batchCnt = 0; while (1) { - if (atomic_load_8(&pTask->taskStatus) == TASK_STATUS__DROPPING) { + if (streamTaskShouldStop(&pTask->status)) { + taosArrayDestroy(pRes); return 0; } SSDataBlock* output = NULL; uint64_t ts = 0; if (qExecTask(exec, &output, &ts) < 0) { - return -1; + continue; } if (output == NULL) { if (qStreamRecoverScanFinished(exec)) { @@ -133,12 +163,26 @@ int32_t streamScanExec(SStreamTask* pTask, int32_t batchSz) { block.info.childId = pTask->selfChildId; taosArrayPush(pRes, &block); - if (++batchCnt >= batchSz) break; + batchCnt++; + + qDebug("s-task:%s scan exec block num %d, block limit %d", pTask->id.idStr, batchCnt, batchSz); + + if (batchCnt >= batchSz) { + break; + } } + if (taosArrayGetSize(pRes) == 0) { - taosArrayDestroy(pRes); - break; + if (finished) { + taosArrayDestroy(pRes); + qDebug("s-task:%s finish recover exec task ", pTask->id.idStr); + break; + } else { + qDebug("s-task:%s continue recover exec task ", pTask->id.idStr); + continue; + } } + SStreamDataBlock* qRes = taosAllocateQitem(sizeof(SStreamDataBlock), DEF_QITEM, 0); if (qRes == NULL) { taosArrayDestroyEx(pRes, (FDelete)blockDataFreeRes); @@ -151,9 +195,13 @@ int32_t streamScanExec(SStreamTask* pTask, int32_t batchSz) { streamTaskOutput(pTask, qRes); if (pTask->outputType == TASK_OUTPUT__FIXED_DISPATCH || pTask->outputType == TASK_OUTPUT__SHUFFLE_DISPATCH) { + qDebug("task %d scan exec dispatch block num %d", pTask->id.taskId, batchCnt); streamDispatch(pTask); } - if (finished) break; + + if (finished) { + break; + } } return 0; } @@ -163,7 +211,7 @@ int32_t streamBatchExec(SStreamTask* pTask, int32_t batchLimit) { // fetch all queue item, merge according to batchLimit int32_t numOfItems = taosReadAllQitems(pTask->inputQueue1, pTask->inputQall); if (numOfItems == 0) { - qDebug("task: %d, stream task exec over, queue empty", pTask->taskId); + qDebug("task: %d, stream task exec over, queue empty", pTask->id.taskId); return 0; } SStreamQueueItem* pMerged = NULL; @@ -198,102 +246,143 @@ int32_t streamBatchExec(SStreamTask* pTask, int32_t batchLimit) { int32_t streamExecForAll(SStreamTask* pTask) { while (1) { - int32_t batchCnt = 1; - void* input = NULL; + int32_t batchSize = 1; + void* pInput = NULL; + + // merge multiple input data if possible in the input queue. + qDebug("s-task:%s start to extract data block from inputQ", pTask->id.idStr); + while (1) { SStreamQueueItem* qItem = streamQueueNextItem(pTask->inputQueue); if (qItem == NULL) { - qDebug("stream task exec over, queue empty, task: %d", pTask->taskId); break; } - if (input == NULL) { - input = qItem; + + if (pInput == NULL) { + pInput = qItem; streamQueueProcessSuccess(pTask->inputQueue); if (pTask->taskLevel == TASK_LEVEL__SINK) { break; } } else { - void* newRet; - if ((newRet = streamMergeQueueItem(input, qItem)) == NULL) { + void* newRet = NULL; + if ((newRet = streamMergeQueueItem(pInput, qItem)) == NULL) { streamQueueProcessFail(pTask->inputQueue); break; } else { - batchCnt++; - input = newRet; + batchSize++; + pInput = newRet; streamQueueProcessSuccess(pTask->inputQueue); + if (batchSize > STREAM_EXEC_MAX_BATCH_NUM) { + break; + } } } } - if (pTask->taskStatus == TASK_STATUS__DROPPING) { - if (input) streamFreeQitem(input); + if (streamTaskShouldStop(&pTask->status)) { + if (pInput) { + streamFreeQitem(pInput); + } return 0; } - if (input == NULL) { + if (pInput == NULL) { break; } if (pTask->taskLevel == TASK_LEVEL__SINK) { - ASSERT(((SStreamQueueItem*)input)->type == STREAM_INPUT__DATA_BLOCK); - streamTaskOutput(pTask, input); + ASSERT(((SStreamQueueItem*)pInput)->type == STREAM_INPUT__DATA_BLOCK); + qDebug("s-task:%s sink node start to sink result. numOfBlocks:%d", pTask->id.idStr, batchSize); + streamTaskOutput(pTask, pInput); continue; } SArray* pRes = taosArrayInit(0, sizeof(SSDataBlock)); + qDebug("s-task:%s start to execute, numOfBlocks:%d", pTask->id.idStr, batchSize); + + streamTaskExecImpl(pTask, pInput, pRes); + + int64_t ckId = 0; + int64_t dataVer = 0; + qGetCheckpointVersion(pTask->exec.pExecutor, &dataVer, &ckId); + if (dataVer > pTask->chkInfo.version) { // save it since the checkpoint is updated + qDebug("s-task:%s exec end, start to update check point, ver from %" PRId64 " to %" PRId64 + ", checkPoint id:%" PRId64 " -> %" PRId64, + pTask->id.idStr, pTask->chkInfo.version, dataVer, pTask->chkInfo.id, ckId); - qDebug("stream task %d exec begin, msg batch: %d", pTask->taskId, batchCnt); - streamTaskExecImpl(pTask, input, pRes); - qDebug("stream task %d exec end", pTask->taskId); + pTask->chkInfo = (SCheckpointInfo) {.version = dataVer, .id = ckId, .currentVer = pTask->chkInfo.currentVer}; + + taosWLockLatch(&pTask->pMeta->lock); + + streamMetaSaveTask(pTask->pMeta, pTask); + if (streamMetaCommit(pTask->pMeta) < 0) { + taosWUnLockLatch(&pTask->pMeta->lock); + qError("s-task:%s failed to commit stream meta, since %s", pTask->id.idStr, terrstr()); + return -1; + } else { + taosWUnLockLatch(&pTask->pMeta->lock); + qDebug("s-task:%s update checkpoint ver succeed", pTask->id.idStr); + } + } else { + qDebug("s-task:%s exec end", pTask->id.idStr); + } if (taosArrayGetSize(pRes) != 0) { SStreamDataBlock* qRes = taosAllocateQitem(sizeof(SStreamDataBlock), DEF_QITEM, 0); if (qRes == NULL) { taosArrayDestroyEx(pRes, (FDelete)blockDataFreeRes); - streamFreeQitem(input); + streamFreeQitem(pInput); return -1; } + qRes->type = STREAM_INPUT__DATA_BLOCK; qRes->blocks = pRes; - if (((SStreamQueueItem*)input)->type == STREAM_INPUT__DATA_SUBMIT) { - SStreamDataSubmit* pSubmit = (SStreamDataSubmit*)input; + if (((SStreamQueueItem*)pInput)->type == STREAM_INPUT__DATA_SUBMIT) { + SStreamDataSubmit2* pSubmit = (SStreamDataSubmit2*)pInput; qRes->childId = pTask->selfChildId; qRes->sourceVer = pSubmit->ver; - } else if (((SStreamQueueItem*)input)->type == STREAM_INPUT__MERGED_SUBMIT) { - SStreamMergedSubmit* pMerged = (SStreamMergedSubmit*)input; + } else if (((SStreamQueueItem*)pInput)->type == STREAM_INPUT__MERGED_SUBMIT) { + SStreamMergedSubmit2* pMerged = (SStreamMergedSubmit2*)pInput; qRes->childId = pTask->selfChildId; qRes->sourceVer = pMerged->ver; } if (streamTaskOutput(pTask, qRes) < 0) { taosArrayDestroyEx(pRes, (FDelete)blockDataFreeRes); - streamFreeQitem(input); + streamFreeQitem(pInput); taosFreeQitem(qRes); return -1; } } else { taosArrayDestroy(pRes); } - streamFreeQitem(input); + streamFreeQitem(pInput); } return 0; } int32_t streamTryExec(SStreamTask* pTask) { + // this function may be executed by multi-threads, so status check is required. int8_t schedStatus = - atomic_val_compare_exchange_8(&pTask->schedStatus, TASK_SCHED_STATUS__WAITING, TASK_SCHED_STATUS__ACTIVE); + atomic_val_compare_exchange_8(&pTask->status.schedStatus, TASK_SCHED_STATUS__WAITING, TASK_SCHED_STATUS__ACTIVE); + if (schedStatus == TASK_SCHED_STATUS__WAITING) { int32_t code = streamExecForAll(pTask); if (code < 0) { - atomic_store_8(&pTask->schedStatus, TASK_SCHED_STATUS__FAILED); + atomic_store_8(&pTask->status.schedStatus, TASK_SCHED_STATUS__FAILED); return -1; } - atomic_store_8(&pTask->schedStatus, TASK_SCHED_STATUS__INACTIVE); - if (!taosQueueEmpty(pTask->inputQueue->queue)) { + // todo the task should be commit here + atomic_store_8(&pTask->status.schedStatus, TASK_SCHED_STATUS__INACTIVE); + qDebug("s-task:%s exec completed", pTask->id.idStr); + + if (!taosQueueEmpty(pTask->inputQueue->queue) && (!streamTaskShouldStop(&pTask->status))) { streamSchedExec(pTask); } } + return 0; } diff --git a/source/libs/stream/src/streamMeta.c b/source/libs/stream/src/streamMeta.c index e345bc1c6e32bff6351bd6b4a1212d89012aba60..af54904c4315d773a24a6cbb6fa92ddc529522de 100644 --- a/source/libs/stream/src/streamMeta.c +++ b/source/libs/stream/src/streamMeta.c @@ -18,22 +18,29 @@ #include "ttimer.h" SStreamMeta* streamMetaOpen(const char* path, void* ahandle, FTaskExpand expandFunc, int32_t vgId) { + int32_t code = -1; SStreamMeta* pMeta = taosMemoryCalloc(1, sizeof(SStreamMeta)); if (pMeta == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } + int32_t len = strlen(path) + 20; char* streamPath = taosMemoryCalloc(1, len); sprintf(streamPath, "%s/%s", path, "stream"); - pMeta->path = strdup(streamPath); + pMeta->path = taosStrdup(streamPath); if (tdbOpen(pMeta->path, 16 * 1024, 1, &pMeta->db, 0) < 0) { taosMemoryFree(streamPath); goto _err; } sprintf(streamPath, "%s/%s", pMeta->path, "checkpoints"); - taosMulModeMkDir(streamPath, 0755); + code = taosMulModeMkDir(streamPath, 0755); + if (code != 0) { + terrno = TAOS_SYSTEM_ERROR(code); + taosMemoryFree(streamPath); + goto _err; + } taosMemoryFree(streamPath); if (tdbTbOpen("task.db", sizeof(int32_t), -1, NULL, pMeta->db, &pMeta->pTaskDb, 0) < 0) { @@ -44,23 +51,33 @@ SStreamMeta* streamMetaOpen(const char* path, void* ahandle, FTaskExpand expandF goto _err; } - pMeta->pTasks = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_ENTRY_LOCK); + _hash_fn_t fp = taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT); + pMeta->pTasks = taosHashInit(64, fp, true, HASH_ENTRY_LOCK); if (pMeta->pTasks == NULL) { goto _err; } + // task list + pMeta->pTaskList = taosArrayInit(4, sizeof(int32_t)); + if (pMeta->pTaskList == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + goto _err; + } + if (streamMetaBegin(pMeta) < 0) { goto _err; } + pMeta->vgId = vgId; pMeta->ahandle = ahandle; pMeta->expandFunc = expandFunc; - + taosInitRWLatch(&pMeta->lock); return pMeta; _err: taosMemoryFree(pMeta->path); if (pMeta->pTasks) taosHashCleanup(pMeta->pTasks); + if (pMeta->pTaskList) taosArrayDestroy(pMeta->pTaskList); if (pMeta->pTaskDb) tdbTbClose(pMeta->pTaskDb); if (pMeta->pCheckpointDb) tdbTbClose(pMeta->pCheckpointDb); if (pMeta->db) tdbClose(pMeta->db); @@ -77,17 +94,21 @@ void streamMetaClose(SStreamMeta* pMeta) { void* pIter = NULL; while (1) { pIter = taosHashIterate(pMeta->pTasks, pIter); - if (pIter == NULL) break; + if (pIter == NULL) { + break; + } + SStreamTask* pTask = *(SStreamTask**)pIter; if (pTask->timer) { taosTmrStop(pTask->timer); pTask->timer = NULL; } - tFreeSStreamTask(pTask); - /*streamMetaReleaseTask(pMeta, pTask);*/ + + tFreeStreamTask(pTask); } + taosHashCleanup(pMeta->pTasks); - taosHashCleanup(pMeta->pRecoverStatus); + pMeta->pTaskList = taosArrayDestroy(pMeta->pTaskList); taosMemoryFree(pMeta->path); taosMemoryFree(pMeta); } @@ -100,7 +121,7 @@ int32_t streamMetaAddSerializedTask(SStreamMeta* pMeta, int64_t ver, char* msg, } SDecoder decoder; tDecoderInit(&decoder, (uint8_t*)msg, msgLen); - if (tDecodeSStreamTask(&decoder, pTask) < 0) { + if (tDecodeStreamTask(&decoder, pTask) < 0) { tDecoderClear(&decoder); goto FAIL; } @@ -111,12 +132,12 @@ int32_t streamMetaAddSerializedTask(SStreamMeta* pMeta, int64_t ver, char* msg, goto FAIL; } - if (taosHashPut(pMeta->pTasks, &pTask->taskId, sizeof(int32_t), &pTask, sizeof(void*)) < 0) { + if (taosHashPut(pMeta->pTasks, &pTask->id.taskId, sizeof(int32_t), &pTask, sizeof(void*)) < 0) { goto FAIL; } - if (tdbTbUpsert(pMeta->pTaskDb, &pTask->taskId, sizeof(int32_t), msg, msgLen, pMeta->txn) < 0) { - taosHashRemove(pMeta->pTasks, &pTask->taskId, sizeof(int32_t)); + if (tdbTbUpsert(pMeta->pTaskDb, &pTask->id.taskId, sizeof(int32_t), msg, msgLen, pMeta->txn) < 0) { + taosHashRemove(pMeta->pTasks, &pTask->id.taskId, sizeof(int32_t)); ASSERT(0); goto FAIL; } @@ -124,21 +145,16 @@ int32_t streamMetaAddSerializedTask(SStreamMeta* pMeta, int64_t ver, char* msg, return 0; FAIL: - if (pTask) tFreeSStreamTask(pTask); + if (pTask) tFreeStreamTask(pTask); return -1; } #endif -#if 1 -int32_t streamMetaAddTask(SStreamMeta* pMeta, int64_t ver, SStreamTask* pTask) { - void* buf = NULL; - if (pMeta->expandFunc(pMeta->ahandle, pTask, ver) < 0) { - return -1; - } - +int32_t streamMetaSaveTask(SStreamMeta* pMeta, SStreamTask* pTask) { + void* buf = NULL; int32_t len; int32_t code; - tEncodeSize(tEncodeSStreamTask, pTask, len, code); + tEncodeSize(tEncodeStreamTask, pTask, len, code); if (code < 0) { return -1; } @@ -149,46 +165,58 @@ int32_t streamMetaAddTask(SStreamMeta* pMeta, int64_t ver, SStreamTask* pTask) { SEncoder encoder = {0}; tEncoderInit(&encoder, buf, len); - tEncodeSStreamTask(&encoder, pTask); + tEncodeStreamTask(&encoder, pTask); tEncoderClear(&encoder); - if (tdbTbUpsert(pMeta->pTaskDb, &pTask->taskId, sizeof(int32_t), buf, len, pMeta->txn) < 0) { - ASSERT(0); + if (tdbTbUpsert(pMeta->pTaskDb, &pTask->id.taskId, sizeof(int32_t), buf, len, pMeta->txn) < 0) { return -1; } taosMemoryFree(buf); - taosHashPut(pMeta->pTasks, &pTask->taskId, sizeof(int32_t), &pTask, sizeof(void*)); - return 0; } -#endif -SStreamTask* streamMetaGetTask(SStreamMeta* pMeta, int32_t taskId) { - SStreamTask** ppTask = (SStreamTask**)taosHashGet(pMeta->pTasks, &taskId, sizeof(int32_t)); - if (ppTask) { - ASSERT((*ppTask)->taskId == taskId); - return *ppTask; - } else { - return NULL; +// add to the ready tasks hash map, not the restored tasks hash map +int32_t streamMetaAddDeployedTask(SStreamMeta* pMeta, int64_t ver, SStreamTask* pTask) { + if (pMeta->expandFunc(pMeta->ahandle, pTask, ver) < 0) { + tFreeStreamTask(pTask); + return -1; + } + + if (streamMetaSaveTask(pMeta, pTask) < 0) { + tFreeStreamTask(pTask); + return -1; + } + + if (streamMetaCommit(pMeta) < 0) { + tFreeStreamTask(pTask); + return -1; } + + taosHashPut(pMeta->pTasks, &pTask->id.taskId, sizeof(int32_t), &pTask, POINTER_BYTES); + taosArrayPush(pMeta->pTaskList, &pTask->id.taskId); + return 0; +} + +int32_t streamMetaGetNumOfTasks(const SStreamMeta* pMeta) { + size_t size = taosHashGetSize(pMeta->pTasks); + ASSERT(taosArrayGetSize(pMeta->pTaskList) == taosHashGetSize(pMeta->pTasks)); + + return (int32_t) size; } SStreamTask* streamMetaAcquireTask(SStreamMeta* pMeta, int32_t taskId) { taosRLockLatch(&pMeta->lock); SStreamTask** ppTask = (SStreamTask**)taosHashGet(pMeta->pTasks, &taskId, sizeof(int32_t)); - if (ppTask) { - SStreamTask* pTask = *ppTask; - if (atomic_load_8(&pTask->taskStatus) != TASK_STATUS__DROPPING) { - atomic_add_fetch_32(&pTask->refCnt, 1); + if (ppTask != NULL) { + if (!streamTaskShouldStop(&(*ppTask)->status)) { + atomic_add_fetch_32(&(*ppTask)->refCnt, 1); taosRUnLockLatch(&pMeta->lock); - return pTask; - } else { - taosRUnLockLatch(&pMeta->lock); - return NULL; + return *ppTask; } } + taosRUnLockLatch(&pMeta->lock); return NULL; } @@ -197,8 +225,8 @@ void streamMetaReleaseTask(SStreamMeta* pMeta, SStreamTask* pTask) { int32_t left = atomic_sub_fetch_32(&pTask->refCnt, 1); ASSERT(left >= 0); if (left == 0) { - ASSERT(atomic_load_8(&pTask->taskStatus) == TASK_STATUS__DROPPING); - tFreeSStreamTask(pTask); + ASSERT(streamTaskShouldStop(&pTask->status)); + tFreeStreamTask(pTask); } } @@ -206,15 +234,23 @@ void streamMetaRemoveTask(SStreamMeta* pMeta, int32_t taskId) { SStreamTask** ppTask = (SStreamTask**)taosHashGet(pMeta->pTasks, &taskId, sizeof(int32_t)); if (ppTask) { SStreamTask* pTask = *ppTask; + + taosWLockLatch(&pMeta->lock); + taosHashRemove(pMeta->pTasks, &taskId, sizeof(int32_t)); tdbTbDelete(pMeta->pTaskDb, &taskId, sizeof(int32_t), pMeta->txn); - /*if (pTask->timer) { - * taosTmrStop(pTask->timer);*/ - /*pTask->timer = NULL;*/ - /*}*/ - atomic_store_8(&pTask->taskStatus, TASK_STATUS__DROPPING); - taosWLockLatch(&pMeta->lock); + atomic_store_8(&pTask->status.taskStatus, TASK_STATUS__STOP); + + int32_t num = taosArrayGetSize(pMeta->pTaskList); + for(int32_t i = 0; i < num; ++i) { + int32_t* pTaskId = taosArrayGet(pMeta->pTaskList, i); + if (*pTaskId == taskId) { + taosArrayRemove(pMeta->pTaskList, i); + break; + } + } + streamMetaReleaseTask(pMeta, pTask); taosWUnLockLatch(&pMeta->lock); } @@ -230,9 +266,12 @@ int32_t streamMetaBegin(SStreamMeta* pMeta) { int32_t streamMetaCommit(SStreamMeta* pMeta) { if (tdbCommit(pMeta->db, pMeta->txn) < 0) { + ASSERT(0); return -1; } + if (tdbPostCommit(pMeta->db, pMeta->txn) < 0) { + ASSERT(0); return -1; } @@ -255,7 +294,7 @@ int32_t streamMetaAbort(SStreamMeta* pMeta) { return 0; } -int32_t streamLoadTasks(SStreamMeta* pMeta) { +int32_t streamLoadTasks(SStreamMeta* pMeta, int64_t ver) { TBC* pCur = NULL; if (tdbTbcOpen(pMeta->pTaskDb, &pCur, NULL) < 0) { return -1; @@ -277,24 +316,31 @@ int32_t streamLoadTasks(SStreamMeta* pMeta) { tdbTbcClose(pCur); return -1; } + tDecoderInit(&decoder, (uint8_t*)pVal, vLen); - tDecodeSStreamTask(&decoder, pTask); + tDecodeStreamTask(&decoder, pTask); tDecoderClear(&decoder); - if (pMeta->expandFunc(pMeta->ahandle, pTask, -1) < 0) { + if (pMeta->expandFunc(pMeta->ahandle, pTask, pTask->chkInfo.version) < 0) { tdbFree(pKey); tdbFree(pVal); tdbTbcClose(pCur); return -1; } - if (taosHashPut(pMeta->pTasks, &pTask->taskId, sizeof(int32_t), &pTask, sizeof(void*)) < 0) { + if (taosHashPut(pMeta->pTasks, &pTask->id.taskId, sizeof(int32_t), &pTask, sizeof(void*)) < 0) { tdbFree(pKey); tdbFree(pVal); tdbTbcClose(pCur); return -1; } - pTask->taskStatus = TASK_STATUS__NORMAL; + + taosArrayPush(pMeta->pTaskList, &pTask->id.taskId); + + if (pTask->fillHistory) { + pTask->status.taskStatus = TASK_STATUS__WAIT_DOWNSTREAM; + streamTaskCheckDownstream(pTask, ver); + } } tdbFree(pKey); diff --git a/source/libs/stream/src/streamQueue.c b/source/libs/stream/src/streamQueue.c index 7eafcdc93ea20b96140391c0e555ff5caf5bff93..882fba718bb3bc6cde73cea38c151e849936a155 100644 --- a/source/libs/stream/src/streamQueue.c +++ b/source/libs/stream/src/streamQueue.c @@ -46,6 +46,7 @@ void streamQueueClose(SStreamQueue* queue) { taosMemoryFree(queue); } +#if 0 bool streamQueueResEmpty(const SStreamQueueRes* pRes) { // return true; @@ -101,3 +102,4 @@ SStreamQueueRes streamQueueGetRes(SStreamQueue1* pQueue) { if (pNode) return streamQueueBuildRes(pNode); return (SStreamQueueRes){0}; } +#endif diff --git a/source/libs/stream/src/streamRecover.c b/source/libs/stream/src/streamRecover.c index 061b211ddfa7045e0121b01d28dc77a581a401d2..26429ea7647aa1aa93eb32ea0f88c89938635933 100644 --- a/source/libs/stream/src/streamRecover.c +++ b/source/libs/stream/src/streamRecover.c @@ -16,9 +16,12 @@ #include "streamInc.h" int32_t streamTaskLaunchRecover(SStreamTask* pTask, int64_t version) { - qDebug("task %d at node %d launch recover", pTask->taskId, pTask->nodeId); + qDebug("s-task:%s at node %d launch recover", pTask->id.idStr, pTask->nodeId); + if (pTask->taskLevel == TASK_LEVEL__SOURCE) { - atomic_store_8(&pTask->taskStatus, TASK_STATUS__RECOVER_PREPARE); + atomic_store_8(&pTask->status.taskStatus, TASK_STATUS__RECOVER_PREPARE); + qDebug("s-task:%s set task status:%d and start recover", pTask->id.idStr, pTask->status.taskStatus); + streamSetParamForRecover(pTask); streamSourceRecoverPrepareStep1(pTask, version); @@ -33,46 +36,47 @@ int32_t streamTaskLaunchRecover(SStreamTask* pTask, int64_t version) { memcpy(serializedReq, &req, len); - SRpcMsg rpcMsg = { - .contLen = len, - .pCont = serializedReq, - .msgType = TDMT_VND_STREAM_RECOVER_NONBLOCKING_STAGE, - }; - + SRpcMsg rpcMsg = { .contLen = len, .pCont = serializedReq, .msgType = TDMT_VND_STREAM_RECOVER_NONBLOCKING_STAGE }; if (tmsgPutToQueue(pTask->pMsgCb, STREAM_QUEUE, &rpcMsg) < 0) { /*ASSERT(0);*/ } } else if (pTask->taskLevel == TASK_LEVEL__AGG) { - atomic_store_8(&pTask->taskStatus, TASK_STATUS__NORMAL); + atomic_store_8(&pTask->status.taskStatus, TASK_STATUS__NORMAL); streamSetParamForRecover(pTask); streamAggRecoverPrepare(pTask); } else if (pTask->taskLevel == TASK_LEVEL__SINK) { - atomic_store_8(&pTask->taskStatus, TASK_STATUS__NORMAL); + atomic_store_8(&pTask->status.taskStatus, TASK_STATUS__NORMAL); } + return 0; } // checkstatus int32_t streamTaskCheckDownstream(SStreamTask* pTask, int64_t version) { + qDebug("s-taks:%s in fill history stage, ver:%"PRId64, pTask->id.idStr, version); + SStreamTaskCheckReq req = { - .streamId = pTask->streamId, - .upstreamTaskId = pTask->taskId, + .streamId = pTask->id.streamId, + .upstreamTaskId = pTask->id.taskId, .upstreamNodeId = pTask->nodeId, .childId = pTask->selfChildId, }; + // serialize if (pTask->outputType == TASK_OUTPUT__FIXED_DISPATCH) { + req.reqId = tGenIdPI64(); req.downstreamNodeId = pTask->fixedEpDispatcher.nodeId; req.downstreamTaskId = pTask->fixedEpDispatcher.taskId; pTask->checkReqId = req.reqId; - qDebug("task %d at node %d check downstream task %d at node %d", pTask->taskId, pTask->nodeId, req.downstreamTaskId, + qDebug("s-task:%s at node %d check downstream task %d at node %d", pTask->id.idStr, pTask->nodeId, req.downstreamTaskId, req.downstreamNodeId); - streamDispatchOneCheckReq(pTask, &req, pTask->fixedEpDispatcher.nodeId, &pTask->fixedEpDispatcher.epSet); + streamDispatchCheckMsg(pTask, &req, pTask->fixedEpDispatcher.nodeId, &pTask->fixedEpDispatcher.epSet); } else if (pTask->outputType == TASK_OUTPUT__SHUFFLE_DISPATCH) { SArray* vgInfo = pTask->shuffleDispatcher.dbInfo.pVgroupInfos; + int32_t vgSz = taosArrayGetSize(vgInfo); pTask->recoverTryingDownstream = vgSz; pTask->checkReqIds = taosArrayInit(vgSz, sizeof(int64_t)); @@ -83,14 +87,15 @@ int32_t streamTaskCheckDownstream(SStreamTask* pTask, int64_t version) { taosArrayPush(pTask->checkReqIds, &req.reqId); req.downstreamNodeId = pVgInfo->vgId; req.downstreamTaskId = pVgInfo->taskId; - qDebug("task %d at node %d check downstream task %d at node %d (shuffle)", pTask->taskId, pTask->nodeId, + qDebug("s-task:%s at node %d check downstream task %d at node %d (shuffle)", pTask->id.idStr, pTask->nodeId, req.downstreamTaskId, req.downstreamNodeId); - streamDispatchOneCheckReq(pTask, &req, pVgInfo->vgId, &pVgInfo->epSet); + streamDispatchCheckMsg(pTask, &req, pVgInfo->vgId, &pVgInfo->epSet); } } else { - qDebug("task %d at node %d direct launch recover since no downstream", pTask->taskId, pTask->nodeId); + qDebug("s-task:%s at node %d direct launch recover since no downstream", pTask->id.idStr, pTask->nodeId); streamTaskLaunchRecover(pTask, version); } + return 0; } @@ -104,109 +109,139 @@ int32_t streamRecheckOneDownstream(SStreamTask* pTask, const SStreamTaskCheckRsp .downstreamNodeId = pRsp->downstreamNodeId, .childId = pRsp->childId, }; - qDebug("task %d at node %d check downstream task %d at node %d (recheck)", pTask->taskId, pTask->nodeId, + + qDebug("s-task:%s at node %d check downstream task %d at node %d (recheck)", pTask->id.idStr, pTask->nodeId, req.downstreamTaskId, req.downstreamNodeId); + if (pTask->outputType == TASK_OUTPUT__FIXED_DISPATCH) { - streamDispatchOneCheckReq(pTask, &req, pRsp->downstreamNodeId, &pTask->fixedEpDispatcher.epSet); + streamDispatchCheckMsg(pTask, &req, pRsp->downstreamNodeId, &pTask->fixedEpDispatcher.epSet); } else if (pTask->outputType == TASK_OUTPUT__SHUFFLE_DISPATCH) { SArray* vgInfo = pTask->shuffleDispatcher.dbInfo.pVgroupInfos; int32_t vgSz = taosArrayGetSize(vgInfo); for (int32_t i = 0; i < vgSz; i++) { SVgroupInfo* pVgInfo = taosArrayGet(vgInfo, i); if (pVgInfo->taskId == req.downstreamTaskId) { - streamDispatchOneCheckReq(pTask, &req, pRsp->downstreamNodeId, &pVgInfo->epSet); + streamDispatchCheckMsg(pTask, &req, pRsp->downstreamNodeId, &pVgInfo->epSet); } } } + return 0; } -int32_t streamProcessTaskCheckReq(SStreamTask* pTask, const SStreamTaskCheckReq* pReq) { - return atomic_load_8(&pTask->taskStatus) == TASK_STATUS__NORMAL; +int32_t streamTaskCheckStatus(SStreamTask* pTask) { + return atomic_load_8(&pTask->status.taskStatus) == TASK_STATUS__NORMAL? 1:0; } int32_t streamProcessTaskCheckRsp(SStreamTask* pTask, const SStreamTaskCheckRsp* pRsp, int64_t version) { qDebug("task %d at node %d recv check rsp from task %d at node %d: status %d", pRsp->upstreamTaskId, pRsp->upstreamNodeId, pRsp->downstreamTaskId, pRsp->downstreamNodeId, pRsp->status); + if (pRsp->status == 1) { if (pTask->outputType == TASK_OUTPUT__SHUFFLE_DISPATCH) { bool found = false; - for (int32_t i = 0; i < taosArrayGetSize(pTask->checkReqIds); i++) { + + int32_t numOfReqs = taosArrayGetSize(pTask->checkReqIds); + for (int32_t i = 0; i < numOfReqs; i++) { int64_t reqId = *(int64_t*)taosArrayGet(pTask->checkReqIds, i); if (reqId == pRsp->reqId) { found = true; break; } } - if (!found) return -1; + + if (!found) { + return -1; + } + int32_t left = atomic_sub_fetch_32(&pTask->recoverTryingDownstream, 1); ASSERT(left >= 0); + if (left == 0) { taosArrayDestroy(pTask->checkReqIds); pTask->checkReqIds = NULL; + + qDebug("s-task:%s all downstream tasks:%d are ready, now enter into recover stage", pTask->id.idStr, numOfReqs); streamTaskLaunchRecover(pTask, version); } } else if (pTask->outputType == TASK_OUTPUT__FIXED_DISPATCH) { - if (pRsp->reqId != pTask->checkReqId) return -1; + if (pRsp->reqId != pTask->checkReqId) { + return -1; + } + streamTaskLaunchRecover(pTask, version); } else { ASSERT(0); } - } else { + } else { // not ready, wait for 100ms and retry + qDebug("s-task:%s downstream taskId:%d (vgId:%d) not ready, wait for 100ms and retry", pTask->id.idStr, + pRsp->downstreamTaskId, pRsp->downstreamNodeId); + taosMsleep(100); streamRecheckOneDownstream(pTask, pRsp); } + return 0; } // common int32_t streamSetParamForRecover(SStreamTask* pTask) { - void* exec = pTask->exec.executor; + void* exec = pTask->exec.pExecutor; return qStreamSetParamForRecover(exec); } int32_t streamRestoreParam(SStreamTask* pTask) { - void* exec = pTask->exec.executor; + void* exec = pTask->exec.pExecutor; return qStreamRestoreParam(exec); } + int32_t streamSetStatusNormal(SStreamTask* pTask) { - pTask->taskStatus = TASK_STATUS__NORMAL; + atomic_store_8(&pTask->status.taskStatus, TASK_STATUS__NORMAL); return 0; } // source int32_t streamSourceRecoverPrepareStep1(SStreamTask* pTask, int64_t ver) { - void* exec = pTask->exec.executor; + void* exec = pTask->exec.pExecutor; return qStreamSourceRecoverStep1(exec, ver); } int32_t streamBuildSourceRecover1Req(SStreamTask* pTask, SStreamRecoverStep1Req* pReq) { pReq->msgHead.vgId = pTask->nodeId; - pReq->streamId = pTask->streamId; - pReq->taskId = pTask->taskId; + pReq->streamId = pTask->id.streamId; + pReq->taskId = pTask->id.taskId; return 0; } int32_t streamSourceRecoverScanStep1(SStreamTask* pTask) { - // return streamScanExec(pTask, 100); } int32_t streamBuildSourceRecover2Req(SStreamTask* pTask, SStreamRecoverStep2Req* pReq) { pReq->msgHead.vgId = pTask->nodeId; - pReq->streamId = pTask->streamId; - pReq->taskId = pTask->taskId; + pReq->streamId = pTask->id.streamId; + pReq->taskId = pTask->id.taskId; return 0; } int32_t streamSourceRecoverScanStep2(SStreamTask* pTask, int64_t ver) { - void* exec = pTask->exec.executor; + void* exec = pTask->exec.pExecutor; + const char* id = pTask->id.idStr; + + int64_t st = taosGetTimestampMs(); + qDebug("s-task:%s recover step2(blocking stage) started", id); if (qStreamSourceRecoverStep2(exec, ver) < 0) { } - return streamScanExec(pTask, 100); + + int32_t code = streamScanExec(pTask, 100); + + double el = (taosGetTimestampMs() - st) / 1000.0; + qDebug("s-task:%s recover step2(blocking stage) ended, elapsed time:%.2fs", id, el); + + return code; } int32_t streamDispatchRecoverFinishReq(SStreamTask* pTask) { SStreamRecoverFinishReq req = { - .streamId = pTask->streamId, + .streamId = pTask->id.streamId, .childId = pTask->selfChildId, }; // serialize @@ -227,13 +262,13 @@ int32_t streamDispatchRecoverFinishReq(SStreamTask* pTask) { // agg int32_t streamAggRecoverPrepare(SStreamTask* pTask) { - void* exec = pTask->exec.executor; pTask->recoverWaitingUpstream = taosArrayGetSize(pTask->childEpInfo); + qDebug("s-task:%s wait for %d upstreams", pTask->id.idStr, pTask->recoverWaitingUpstream); return 0; } int32_t streamAggChildrenRecoverFinish(SStreamTask* pTask) { - void* exec = pTask->exec.executor; + void* exec = pTask->exec.pExecutor; if (qStreamRestoreParam(exec) < 0) { return -1; } @@ -247,6 +282,7 @@ int32_t streamAggChildrenRecoverFinish(SStreamTask* pTask) { int32_t streamProcessRecoverFinishReq(SStreamTask* pTask, int32_t childId) { if (pTask->taskLevel == TASK_LEVEL__AGG) { int32_t left = atomic_sub_fetch_32(&pTask->recoverWaitingUpstream, 1); + qDebug("s-task:%s remain unfinished child tasks:%d", pTask->id.idStr, left); ASSERT(left >= 0); if (left == 0) { streamAggChildrenRecoverFinish(pTask); diff --git a/source/libs/stream/src/streamState.c b/source/libs/stream/src/streamState.c index b4e44cc5b7009d91e93011ee9f8cdcd79238d1c1..7bea989e3a63be5110deb9e8dbb5b00ac6eed643 100644 --- a/source/libs/stream/src/streamState.c +++ b/source/libs/stream/src/streamState.c @@ -121,7 +121,7 @@ SStreamState* streamStateOpen(char* path, SStreamTask* pTask, bool specPath, int char statePath[1024]; if (!specPath) { - sprintf(statePath, "%s/%d", path, pTask->taskId); + sprintf(statePath, "%s/%d", path, pTask->id.taskId); } else { memset(statePath, 0, 1024); tstrncpy(statePath, path, 1024); @@ -130,21 +130,25 @@ SStreamState* streamStateOpen(char* path, SStreamTask* pTask, bool specPath, int char cfgPath[1030]; sprintf(cfgPath, "%s/cfg", statePath); + szPage = szPage < 0 ? 4096 : szPage; + pages = pages < 0 ? 256 : pages; char cfg[1024]; memset(cfg, 0, 1024); TdFilePtr pCfgFile = taosOpenFile(cfgPath, TD_FILE_READ); if (pCfgFile != NULL) { - int64_t size; + int64_t size = 0; taosFStatFile(pCfgFile, &size, NULL); - taosReadFile(pCfgFile, cfg, size); - sscanf(cfg, "%d\n%d\n", &szPage, &pages); + if (size > 0) { + taosReadFile(pCfgFile, cfg, size); + sscanf(cfg, "%d\n%d\n", &szPage, &pages); + } } else { - taosMulModeMkDir(statePath, 0755); - pCfgFile = taosOpenFile(cfgPath, TD_FILE_WRITE | TD_FILE_CREATE); - szPage = szPage < 0 ? 4096 : szPage; - pages = pages < 0 ? 256 : pages; - sprintf(cfg, "%d\n%d\n", szPage, pages); - taosWriteFile(pCfgFile, cfg, strlen(cfg)); + int32_t code = taosMulModeMkDir(statePath, 0755); + if (code == 0) { + pCfgFile = taosOpenFile(cfgPath, TD_FILE_WRITE | TD_FILE_CREATE); + sprintf(cfg, "%d\n%d\n", szPage, pages); + taosWriteFile(pCfgFile, cfg, strlen(cfg)); + } } taosCloseFile(&pCfgFile); @@ -179,11 +183,17 @@ SStreamState* streamStateOpen(char* path, SStreamTask* pTask, bool specPath, int goto _err; } + if (tdbTbOpen("partag.state.db", sizeof(int64_t), -1, NULL, pState->pTdbState->db, &pState->pTdbState->pParTagDb, 0) < + 0) { + goto _err; + } + if (streamStateBegin(pState) < 0) { goto _err; } pState->pTdbState->pOwner = pTask; + pState->checkPointId = 0; return pState; @@ -193,6 +203,7 @@ _err: tdbTbClose(pState->pTdbState->pFillStateDb); tdbTbClose(pState->pTdbState->pSessionStateDb); tdbTbClose(pState->pTdbState->pParNameDb); + tdbTbClose(pState->pTdbState->pParTagDb); tdbClose(pState->pTdbState->db); streamStateDestroy(pState); return NULL; @@ -206,6 +217,7 @@ void streamStateClose(SStreamState* pState) { tdbTbClose(pState->pTdbState->pFillStateDb); tdbTbClose(pState->pTdbState->pSessionStateDb); tdbTbClose(pState->pTdbState->pParNameDb); + tdbTbClose(pState->pTdbState->pParTagDb); tdbClose(pState->pTdbState->db); streamStateDestroy(pState); @@ -232,6 +244,7 @@ int32_t streamStateCommit(SStreamState* pState) { TDB_TXN_WRITE | TDB_TXN_READ_UNCOMMITTED) < 0) { return -1; } + pState->checkPointId++; return 0; } @@ -840,10 +853,17 @@ _end: return res; } +int32_t streamStatePutParTag(SStreamState* pState, int64_t groupId, const void* tag, int32_t tagLen) { + return tdbTbUpsert(pState->pTdbState->pParTagDb, &groupId, sizeof(int64_t), tag, tagLen, pState->pTdbState->txn); +} + +int32_t streamStateGetParTag(SStreamState* pState, int64_t groupId, void** tagVal, int32_t* tagLen) { + return tdbTbGet(pState->pTdbState->pParTagDb, &groupId, sizeof(int64_t), tagVal, tagLen); +} + int32_t streamStatePutParName(SStreamState* pState, int64_t groupId, const char tbname[TSDB_TABLE_NAME_LEN]) { - tdbTbUpsert(pState->pTdbState->pParNameDb, &groupId, sizeof(int64_t), tbname, TSDB_TABLE_NAME_LEN, - pState->pTdbState->txn); - return 0; + return tdbTbUpsert(pState->pTdbState->pParNameDb, &groupId, sizeof(int64_t), tbname, TSDB_TABLE_NAME_LEN, + pState->pTdbState->txn); } int32_t streamStateGetParName(SStreamState* pState, int64_t groupId, void** pVal) { diff --git a/source/libs/stream/src/streamTask.c b/source/libs/stream/src/streamTask.c index e9aba0bc3941d501ba25a5ea28aaf02e11d42cbd..f301d9d5175f52624284675fb2be44d17d7bafd9 100644 --- a/source/libs/stream/src/streamTask.c +++ b/source/libs/stream/src/streamTask.c @@ -15,15 +15,22 @@ #include "executor.h" #include "tstream.h" +#include "wal.h" -SStreamTask* tNewSStreamTask(int64_t streamId) { +SStreamTask* tNewStreamTask(int64_t streamId) { SStreamTask* pTask = (SStreamTask*)taosMemoryCalloc(1, sizeof(SStreamTask)); if (pTask == NULL) { return NULL; } - pTask->taskId = tGenIdPI32(); - pTask->streamId = streamId; - pTask->schedStatus = TASK_SCHED_STATUS__INACTIVE; + + pTask->id.taskId = tGenIdPI32(); + pTask->id.streamId = streamId; + + char buf[128] = {0}; + sprintf(buf, "0x%"PRIx64"-%d", pTask->id.streamId, pTask->id.taskId); + + pTask->id.idStr = taosStrdup(buf); + pTask->status.schedStatus = TASK_SCHED_STATUS__INACTIVE; pTask->inputStatus = TASK_INPUT_STATUS__NORMAL; pTask->outputStatus = TASK_OUTPUT_STATUS__NORMAL; @@ -48,24 +55,24 @@ int32_t tDecodeStreamEpInfo(SDecoder* pDecoder, SStreamChildEpInfo* pInfo) { return 0; } -int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask) { +int32_t tEncodeStreamTask(SEncoder* pEncoder, const SStreamTask* pTask) { if (tStartEncode(pEncoder) < 0) return -1; - if (tEncodeI64(pEncoder, pTask->streamId) < 0) return -1; - if (tEncodeI32(pEncoder, pTask->taskId) < 0) return -1; + if (tEncodeI64(pEncoder, pTask->id.streamId) < 0) return -1; + if (tEncodeI32(pEncoder, pTask->id.taskId) < 0) return -1; if (tEncodeI32(pEncoder, pTask->totalLevel) < 0) return -1; if (tEncodeI8(pEncoder, pTask->taskLevel) < 0) return -1; if (tEncodeI8(pEncoder, pTask->outputType) < 0) return -1; if (tEncodeI16(pEncoder, pTask->dispatchMsgType) < 0) return -1; - if (tEncodeI8(pEncoder, pTask->taskStatus) < 0) return -1; - if (tEncodeI8(pEncoder, pTask->schedStatus) < 0) return -1; + if (tEncodeI8(pEncoder, pTask->status.taskStatus) < 0) return -1; + if (tEncodeI8(pEncoder, pTask->status.schedStatus) < 0) return -1; if (tEncodeI32(pEncoder, pTask->selfChildId) < 0) return -1; if (tEncodeI32(pEncoder, pTask->nodeId) < 0) return -1; if (tEncodeSEpSet(pEncoder, &pTask->epSet) < 0) return -1; - if (tEncodeI64(pEncoder, pTask->recoverSnapVer) < 0) return -1; - if (tEncodeI64(pEncoder, pTask->startVer) < 0) return -1; + if (tEncodeI64(pEncoder, pTask->chkInfo.id) < 0) return -1; + if (tEncodeI64(pEncoder, pTask->chkInfo.version) < 0) return -1; if (tEncodeI8(pEncoder, pTask->fillHistory) < 0) return -1; int32_t epSz = taosArrayGetSize(pTask->childEpInfo); @@ -101,24 +108,24 @@ int32_t tEncodeSStreamTask(SEncoder* pEncoder, const SStreamTask* pTask) { return pEncoder->pos; } -int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask) { +int32_t tDecodeStreamTask(SDecoder* pDecoder, SStreamTask* pTask) { if (tStartDecode(pDecoder) < 0) return -1; - if (tDecodeI64(pDecoder, &pTask->streamId) < 0) return -1; - if (tDecodeI32(pDecoder, &pTask->taskId) < 0) return -1; + if (tDecodeI64(pDecoder, &pTask->id.streamId) < 0) return -1; + if (tDecodeI32(pDecoder, &pTask->id.taskId) < 0) return -1; if (tDecodeI32(pDecoder, &pTask->totalLevel) < 0) return -1; if (tDecodeI8(pDecoder, &pTask->taskLevel) < 0) return -1; if (tDecodeI8(pDecoder, &pTask->outputType) < 0) return -1; if (tDecodeI16(pDecoder, &pTask->dispatchMsgType) < 0) return -1; - if (tDecodeI8(pDecoder, &pTask->taskStatus) < 0) return -1; - if (tDecodeI8(pDecoder, &pTask->schedStatus) < 0) return -1; + if (tDecodeI8(pDecoder, &pTask->status.taskStatus) < 0) return -1; + if (tDecodeI8(pDecoder, &pTask->status.schedStatus) < 0) return -1; if (tDecodeI32(pDecoder, &pTask->selfChildId) < 0) return -1; if (tDecodeI32(pDecoder, &pTask->nodeId) < 0) return -1; if (tDecodeSEpSet(pDecoder, &pTask->epSet) < 0) return -1; - if (tDecodeI64(pDecoder, &pTask->recoverSnapVer) < 0) return -1; - if (tDecodeI64(pDecoder, &pTask->startVer) < 0) return -1; + if (tDecodeI64(pDecoder, &pTask->chkInfo.id) < 0) return -1; + if (tDecodeI64(pDecoder, &pTask->chkInfo.version) < 0) return -1; if (tDecodeI8(pDecoder, &pTask->fillHistory) < 0) return -1; int32_t epSz; @@ -162,24 +169,47 @@ int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask) { return 0; } -void tFreeSStreamTask(SStreamTask* pTask) { - qDebug("free stream task %d", pTask->taskId); - if (pTask->inputQueue) streamQueueClose(pTask->inputQueue); - if (pTask->outputQueue) streamQueueClose(pTask->outputQueue); - if (pTask->exec.qmsg) taosMemoryFree(pTask->exec.qmsg); - if (pTask->exec.executor) qDestroyTask(pTask->exec.executor); +void tFreeStreamTask(SStreamTask* pTask) { + qDebug("free s-task:%s", pTask->id.idStr); + + if (pTask->inputQueue) { + streamQueueClose(pTask->inputQueue); + } + if (pTask->outputQueue) { + streamQueueClose(pTask->outputQueue); + } + if (pTask->exec.qmsg) { + taosMemoryFree(pTask->exec.qmsg); + } + + if (pTask->exec.pExecutor) { + qDestroyTask(pTask->exec.pExecutor); + pTask->exec.pExecutor = NULL; + } + + if (pTask->exec.pWalReader != NULL) { + walCloseReader(pTask->exec.pWalReader); + } + taosArrayDestroyP(pTask->childEpInfo, taosMemoryFree); if (pTask->outputType == TASK_OUTPUT__TABLE) { - tDeleteSSchemaWrapper(pTask->tbSink.pSchemaWrapper); + tDeleteSchemaWrapper(pTask->tbSink.pSchemaWrapper); taosMemoryFree(pTask->tbSink.pTSchema); } + if (pTask->outputType == TASK_OUTPUT__SHUFFLE_DISPATCH) { taosArrayDestroy(pTask->shuffleDispatcher.dbInfo.pVgroupInfos); taosArrayDestroy(pTask->checkReqIds); pTask->checkReqIds = NULL; } - if (pTask->pState) streamStateClose(pTask->pState); + if (pTask->pState) { + streamStateClose(pTask->pState); + } + + if (pTask->id.idStr != NULL) { + taosMemoryFree((void*)pTask->id.idStr); + } taosMemoryFree(pTask); } diff --git a/source/libs/stream/src/streamUpdate.c b/source/libs/stream/src/streamUpdate.c index 1ce4a35dff6441a9ec289d1cb94eb24743122762..be12c72d004711e6c126792b5a7cfe4053ad1f18 100644 --- a/source/libs/stream/src/streamUpdate.c +++ b/source/libs/stream/src/streamUpdate.c @@ -85,9 +85,7 @@ static int64_t adjustWatermark(int64_t adjInterval, int64_t originInt, int64_t w watermark = TMAX(originInt / adjInterval, 1) * adjInterval; } else if (watermark > MAX_NUM_SCALABLE_BF * adjInterval) { watermark = MAX_NUM_SCALABLE_BF * adjInterval; - }/* else if (watermark < MIN_NUM_SCALABLE_BF * adjInterval) { - watermark = MIN_NUM_SCALABLE_BF * adjInterval; - }*/ // Todo(liuyao) save window info to tdb + } return watermark; } diff --git a/source/libs/sync/inc/syncCommit.h b/source/libs/sync/inc/syncCommit.h index 7d638a7336e387cfbf69f7ec43c841310d127c16..07b4702b1b54957ebf5692d4608158c7510e77f7 100644 --- a/source/libs/sync/inc/syncCommit.h +++ b/source/libs/sync/inc/syncCommit.h @@ -48,8 +48,6 @@ extern "C" { void syncOneReplicaAdvance(SSyncNode* pSyncNode); void syncMaybeAdvanceCommitIndex(SSyncNode* pSyncNode); -bool syncAgreeIndex(SSyncNode* pSyncNode, SRaftId* pRaftId, SyncIndex index); -bool syncAgree(SSyncNode* pSyncNode, SyncIndex index); bool syncNodeAgreedUpon(SSyncNode* pNode, SyncIndex index); int64_t syncNodeUpdateCommitIndex(SSyncNode* ths, SyncIndex commitIndex); diff --git a/source/libs/sync/inc/syncInt.h b/source/libs/sync/inc/syncInt.h index 7e08e195c1d255783da14967a26a4386b31e0b6b..6f2c1a1ad0e76d233d516e36ee419cae43fcc409 100644 --- a/source/libs/sync/inc/syncInt.h +++ b/source/libs/sync/inc/syncInt.h @@ -71,6 +71,7 @@ typedef struct SRaftId { typedef struct SRaftStore { SyncTerm currentTerm; SRaftId voteFor; + TdThreadMutex mutex; } SRaftStore; typedef struct SSyncHbTimerData { @@ -282,7 +283,7 @@ void syncNodeCandidate2Follower(SSyncNode* pSyncNode); // raft vote -------------- void syncNodeVoteForTerm(SSyncNode* pSyncNode, SyncTerm term, SRaftId* pRaftId); -void syncNodeVoteForSelf(SSyncNode* pSyncNode); +void syncNodeVoteForSelf(SSyncNode* pSyncNode, SyncTerm term); // log replication SSyncLogReplMgr* syncNodeGetLogReplMgr(SSyncNode* pNode, SRaftId* pDestId); diff --git a/source/libs/sync/inc/syncPipeline.h b/source/libs/sync/inc/syncPipeline.h index 504a9f0bd77158a2e73ed1b3d1da317cbf1ddcd6..d709e33cd46aa091255afa84a3e3aac91bbe1d03 100644 --- a/source/libs/sync/inc/syncPipeline.h +++ b/source/libs/sync/inc/syncPipeline.h @@ -59,36 +59,37 @@ typedef struct SSyncLogBuffer { } SSyncLogBuffer; // SSyncLogRepMgr -SSyncLogReplMgr* syncLogReplMgrCreate(); -void syncLogReplMgrDestroy(SSyncLogReplMgr* pMgr); -void syncLogReplMgrReset(SSyncLogReplMgr* pMgr); +SSyncLogReplMgr* syncLogReplCreate(); +void syncLogReplDestroy(SSyncLogReplMgr* pMgr); +void syncLogReplReset(SSyncLogReplMgr* pMgr); -int32_t syncNodeLogReplMgrInit(SSyncNode* pNode); -void syncNodeLogReplMgrDestroy(SSyncNode* pNode); +int32_t syncNodeLogReplInit(SSyncNode* pNode); +void syncNodeLogReplDestroy(SSyncNode* pNode); // access -static FORCE_INLINE int64_t syncLogGetRetryBackoffTimeMs(SSyncLogReplMgr* pMgr) { - return (1 << pMgr->retryBackoff) * SYNC_LOG_REPL_RETRY_WAIT_MS; +static FORCE_INLINE int64_t syncLogReplGetRetryBackoffTimeMs(SSyncLogReplMgr* pMgr) { + return ((int64_t)1 << pMgr->retryBackoff) * SYNC_LOG_REPL_RETRY_WAIT_MS; } -static FORCE_INLINE int32_t syncLogGetNextRetryBackoff(SSyncLogReplMgr* pMgr) { +static FORCE_INLINE int32_t syncLogReplGetNextRetryBackoff(SSyncLogReplMgr* pMgr) { return TMIN(pMgr->retryBackoff + 1, SYNC_MAX_RETRY_BACKOFF); } -SyncTerm syncLogReplMgrGetPrevLogTerm(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index); +SyncTerm syncLogReplGetPrevLogTerm(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index); -int32_t syncLogReplMgrReplicateOnce(SSyncLogReplMgr* pMgr, SSyncNode* pNode); -int32_t syncLogReplMgrReplicateOneTo(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index, SyncTerm* pTerm, - SRaftId* pDestId, bool* pBarrier); -int32_t syncLogReplMgrReplicateAttempt(SSyncLogReplMgr* pMgr, SSyncNode* pNode); -int32_t syncLogReplMgrReplicateProbe(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index); +int32_t syncLogReplDoOnce(SSyncLogReplMgr* pMgr, SSyncNode* pNode); +int32_t syncLogReplAttempt(SSyncLogReplMgr* pMgr, SSyncNode* pNode); +int32_t syncLogReplProbe(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index); -int32_t syncLogReplMgrProcessReply(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg); -int32_t syncLogReplMgrProcessReplyAsRecovery(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg); -int32_t syncLogReplMgrProcessReplyAsNormal(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg); +int32_t syncLogReplRetryOnNeed(SSyncLogReplMgr* pMgr, SSyncNode* pNode); +int32_t syncLogReplSendTo(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index, SyncTerm* pTerm, SRaftId* pDestId, + bool* pBarrier); -int32_t syncLogReplMgrProcessHeartbeatReply(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncHeartbeatReply* pMsg); -int32_t syncLogReplMgrRetryOnNeed(SSyncLogReplMgr* pMgr, SSyncNode* pNode); +int32_t syncLogReplProcessReply(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg); +int32_t syncLogReplProcessReplyAsRecovery(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg); +int32_t syncLogReplProcessReplyAsNormal(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg); + +int32_t syncLogReplProcessHeartbeatReply(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncHeartbeatReply* pMsg); // SSyncLogBuffer SSyncLogBuffer* syncLogBufferCreate(); @@ -99,6 +100,8 @@ int32_t syncLogBufferReInit(SSyncLogBuffer* pBuf, SSyncNode* pNode); // access int64_t syncLogBufferGetEndIndex(SSyncLogBuffer* pBuf); SyncTerm syncLogBufferGetLastMatchTerm(SSyncLogBuffer* pBuf); +bool syncLogBufferIsEmpty(SSyncLogBuffer* pBuf); + int32_t syncLogBufferAppend(SSyncLogBuffer* pBuf, SSyncNode* pNode, SSyncRaftEntry* pEntry); int32_t syncLogBufferAccept(SSyncLogBuffer* pBuf, SSyncNode* pNode, SSyncRaftEntry* pEntry, SyncTerm prevTerm); int64_t syncLogBufferProceed(SSyncLogBuffer* pBuf, SSyncNode* pNode, SyncTerm* pMatchTerm); @@ -110,8 +113,8 @@ SSyncRaftEntry* syncLogBufferGetOneEntry(SSyncLogBuffer* pBuf, SSyncNode* pNode, int32_t syncLogBufferValidate(SSyncLogBuffer* pBuf); int32_t syncLogBufferRollback(SSyncLogBuffer* pBuf, SSyncNode* pNode, SyncIndex toIndex); -int32_t syncLogFsmExecute(SSyncNode* pNode, SSyncFSM* pFsm, ESyncState role, SyncTerm term, SSyncRaftEntry* pEntry, - int32_t applyCode); +int32_t syncFsmExecute(SSyncNode* pNode, SSyncFSM* pFsm, ESyncState role, SyncTerm term, SSyncRaftEntry* pEntry, + int32_t applyCode); #ifdef __cplusplus } #endif diff --git a/source/libs/sync/inc/syncRaftEntry.h b/source/libs/sync/inc/syncRaftEntry.h index 58944eb08c88800e90294bc625733d7f3c7e2051..f9447e016882f9c219a74ef96394d00535bc411f 100644 --- a/source/libs/sync/inc/syncRaftEntry.h +++ b/source/libs/sync/inc/syncRaftEntry.h @@ -45,43 +45,10 @@ SSyncRaftEntry* syncEntryBuildNoop(SyncTerm term, SyncIndex index, int32_t vgId) void syncEntryDestroy(SSyncRaftEntry* pEntry); void syncEntry2OriginalRpc(const SSyncRaftEntry* pEntry, SRpcMsg* pRpcMsg); // step 7 -static FORCE_INLINE bool syncLogIsReplicationBarrier(SSyncRaftEntry* pEntry) { +static FORCE_INLINE bool syncLogReplBarrier(SSyncRaftEntry* pEntry) { return pEntry->originalRpcType == TDMT_SYNC_NOOP; } -typedef struct SRaftEntryHashCache { - SHashObj* pEntryHash; - int32_t maxCount; - int32_t currentCount; - TdThreadMutex mutex; - SSyncNode* pSyncNode; -} SRaftEntryHashCache; - -SRaftEntryHashCache* raftCacheCreate(SSyncNode* pSyncNode, int32_t maxCount); -void raftCacheDestroy(SRaftEntryHashCache* pCache); -int32_t raftCachePutEntry(struct SRaftEntryHashCache* pCache, SSyncRaftEntry* pEntry); -int32_t raftCacheGetEntry(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry); -int32_t raftCacheGetEntryP(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry); -int32_t raftCacheDelEntry(struct SRaftEntryHashCache* pCache, SyncIndex index); -int32_t raftCacheGetAndDel(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry); -int32_t raftCacheClear(struct SRaftEntryHashCache* pCache); - -typedef struct SRaftEntryCache { - SSkipList* pSkipList; - int32_t maxCount; - int32_t currentCount; - int32_t refMgr; - TdThreadMutex mutex; - SSyncNode* pSyncNode; -} SRaftEntryCache; - -SRaftEntryCache* raftEntryCacheCreate(SSyncNode* pSyncNode, int32_t maxCount); -void raftEntryCacheDestroy(SRaftEntryCache* pCache); -int32_t raftEntryCachePutEntry(struct SRaftEntryCache* pCache, SSyncRaftEntry* pEntry); -int32_t raftEntryCacheGetEntry(struct SRaftEntryCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry); -int32_t raftEntryCacheGetEntryP(struct SRaftEntryCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry); -int32_t raftEntryCacheClear(struct SRaftEntryCache* pCache, int32_t count); - #ifdef __cplusplus } #endif diff --git a/source/libs/sync/inc/syncRaftStore.h b/source/libs/sync/inc/syncRaftStore.h index 21a8fc64a811a832bc3893223b4c1940a6638f54..38a8ed234b8dcfa04454230b6224ff2b838b3fb6 100644 --- a/source/libs/sync/inc/syncRaftStore.h +++ b/source/libs/sync/inc/syncRaftStore.h @@ -26,14 +26,15 @@ extern "C" { #define RAFT_STORE_PATH_LEN (TSDB_FILENAME_LEN * 2) #define EMPTY_RAFT_ID ((SRaftId){.addr = 0, .vgId = 0}) -int32_t raftStoreReadFile(SSyncNode *pNode); -int32_t raftStoreWriteFile(SSyncNode *pNode); +int32_t raftStoreOpen(SSyncNode *pNode); +void raftStoreClose(SSyncNode *pNode); bool raftStoreHasVoted(SSyncNode *pNode); void raftStoreVote(SSyncNode *pNode, SRaftId *pRaftId); void raftStoreClearVote(SSyncNode *pNode); void raftStoreNextTerm(SSyncNode *pNode); void raftStoreSetTerm(SSyncNode *pNode, SyncTerm term); +SyncTerm raftStoreGetTerm(SSyncNode *pNode); #ifdef __cplusplus } diff --git a/source/libs/sync/inc/syncReplication.h b/source/libs/sync/inc/syncReplication.h index f2e240344fc377f90764a5df51a79736e6353ff4..04456b2454cec3d1005d7d617d0a3bc17e158555 100644 --- a/source/libs/sync/inc/syncReplication.h +++ b/source/libs/sync/inc/syncReplication.h @@ -51,11 +51,10 @@ int32_t syncNodeHeartbeatPeers(SSyncNode* pSyncNode); int32_t syncNodeSendHeartbeat(SSyncNode* pSyncNode, const SRaftId* pDestId, SRpcMsg* pMsg); int32_t syncNodeReplicate(SSyncNode* pSyncNode); -int32_t syncNodeReplicateOne(SSyncNode* pSyncNode, SRaftId* pDestId, bool snapshot); +int32_t syncNodeReplicateReset(SSyncNode* pSyncNode, SRaftId* pDestId); int32_t syncNodeReplicateWithoutLock(SSyncNode* pNode); int32_t syncNodeSendAppendEntries(SSyncNode* pNode, const SRaftId* destRaftId, SRpcMsg* pRpcMsg); -int32_t syncNodeMaybeSendAppendEntries(SSyncNode* pNode, const SRaftId* destRaftId, SRpcMsg* pRpcMsg); #ifdef __cplusplus } diff --git a/source/libs/sync/src/syncAppendEntries.c b/source/libs/sync/src/syncAppendEntries.c index 835e5d248e345cbbb3206e35d67ddd20717009db..deae4b0b3feb2e0a2b0ea5cbe97e2d330c55aea6 100644 --- a/source/libs/sync/src/syncAppendEntries.c +++ b/source/libs/sync/src/syncAppendEntries.c @@ -89,21 +89,13 @@ // /\ UNCHANGED <> // -SSyncRaftEntry* syncBuildRaftEntryFromAppendEntries(const SyncAppendEntries* pMsg) { - SSyncRaftEntry* pEntry = taosMemoryMalloc(pMsg->dataLen); - if (pEntry == NULL) { - terrno = TSDB_CODE_OUT_OF_MEMORY; - return NULL; - } - (void)memcpy(pEntry, pMsg->data, pMsg->dataLen); - ASSERT(pEntry->bytes == pMsg->dataLen); - return pEntry; -} - int32_t syncNodeOnAppendEntries(SSyncNode* ths, const SRpcMsg* pRpcMsg) { SyncAppendEntries* pMsg = pRpcMsg->pCont; SRpcMsg rpcRsp = {0}; bool accepted = false; + SSyncRaftEntry* pEntry = NULL; + bool resetElect = false; + // if already drop replica, do not process if (!syncNodeInRaftGroup(ths, &(pMsg->srcId))) { syncLogRecvAppendEntries(ths, pMsg, "not in my config"); @@ -120,31 +112,30 @@ int32_t syncNodeOnAppendEntries(SSyncNode* ths, const SRpcMsg* pRpcMsg) { // prepare response msg pReply->srcId = ths->myRaftId; pReply->destId = pMsg->srcId; - pReply->term = ths->raftStore.currentTerm; + pReply->term = raftStoreGetTerm(ths); pReply->success = false; pReply->matchIndex = SYNC_INDEX_INVALID; pReply->lastSendIndex = pMsg->prevLogIndex + 1; pReply->startTime = ths->startTime; - if (pMsg->term < ths->raftStore.currentTerm) { + if (pMsg->term < raftStoreGetTerm(ths)) { goto _SEND_RESPONSE; } - if (pMsg->term > ths->raftStore.currentTerm) { + if (pMsg->term > raftStoreGetTerm(ths)) { pReply->term = pMsg->term; } syncNodeStepDown(ths, pMsg->term); - syncNodeResetElectTimer(ths); + resetElect = true; - if (pMsg->dataLen < (int32_t)sizeof(SSyncRaftEntry)) { + if (pMsg->dataLen < sizeof(SSyncRaftEntry)) { sError("vgId:%d, incomplete append entries received. prev index:%" PRId64 ", term:%" PRId64 ", datalen:%d", ths->vgId, pMsg->prevLogIndex, pMsg->prevLogTerm, pMsg->dataLen); goto _IGNORE; } - SSyncRaftEntry* pEntry = syncBuildRaftEntryFromAppendEntries(pMsg); - + pEntry = syncEntryBuildFromAppendEntries(pMsg); if (pEntry == NULL) { sError("vgId:%d, failed to get raft entry from append entries since %s", ths->vgId, terrstr()); goto _IGNORE; @@ -183,13 +174,13 @@ _SEND_RESPONSE: // commit index, i.e. leader notice me if (syncLogBufferCommit(ths->pLogBuf, ths, ths->commitIndex) < 0) { sError("vgId:%d, failed to commit raft fsm log since %s.", ths->vgId, terrstr()); - goto _out; } -_out: + if (resetElect) syncNodeResetElectTimer(ths); return 0; _IGNORE: rpcFreeCont(rpcRsp.pCont); + syncEntryDestroy(pEntry); return 0; } diff --git a/source/libs/sync/src/syncAppendEntriesReply.c b/source/libs/sync/src/syncAppendEntriesReply.c index 44a29da3ea0e54d4e9932183a67d298a9c6239ed..7c343c0e5d343e79d9f74e63b9548830e9b78a5f 100644 --- a/source/libs/sync/src/syncAppendEntriesReply.c +++ b/source/libs/sync/src/syncAppendEntriesReply.c @@ -40,7 +40,7 @@ // int32_t syncNodeOnAppendEntriesReply(SSyncNode* ths, const SRpcMsg* pRpcMsg) { - SyncAppendEntriesReply* pMsg = pRpcMsg->pCont; + SyncAppendEntriesReply* pMsg = (SyncAppendEntriesReply*)pRpcMsg->pCont; int32_t ret = 0; // if already drop replica, do not process @@ -50,19 +50,19 @@ int32_t syncNodeOnAppendEntriesReply(SSyncNode* ths, const SRpcMsg* pRpcMsg) { } // drop stale response - if (pMsg->term < ths->raftStore.currentTerm) { + if (pMsg->term < raftStoreGetTerm(ths)) { syncLogRecvAppendEntriesReply(ths, pMsg, "drop stale response"); return 0; } if (ths->state == TAOS_SYNC_STATE_LEADER) { - if (pMsg->term > ths->raftStore.currentTerm) { + if (pMsg->term > raftStoreGetTerm(ths)) { syncLogRecvAppendEntriesReply(ths, pMsg, "error term"); syncNodeStepDown(ths, pMsg->term); return -1; } - ASSERT(pMsg->term == ths->raftStore.currentTerm); + ASSERT(pMsg->term == raftStoreGetTerm(ths)); sTrace("vgId:%d, received append entries reply. srcId:0x%016" PRIx64 ", term:%" PRId64 ", matchIndex:%" PRId64 "", pMsg->vgId, pMsg->srcId.addr, pMsg->term, pMsg->matchIndex); @@ -85,7 +85,7 @@ int32_t syncNodeOnAppendEntriesReply(SSyncNode* ths, const SRpcMsg* pRpcMsg) { sError("vgId:%d, failed to get log repl mgr for src addr: 0x%016" PRIx64, ths->vgId, pMsg->srcId.addr); return -1; } - (void)syncLogReplMgrProcessReply(pMgr, ths, pMsg); + (void)syncLogReplProcessReply(pMgr, ths, pMsg); } return 0; } diff --git a/source/libs/sync/src/syncCommit.c b/source/libs/sync/src/syncCommit.c index 6d256a735de387ac10523580b7d25508d8c10a80..01f1f00c8b557b4205ff1a1a3d7aef573b9e136c 100644 --- a/source/libs/sync/src/syncCommit.c +++ b/source/libs/sync/src/syncCommit.c @@ -44,22 +44,6 @@ // /\ UNCHANGED <> // -bool syncAgreeIndex(SSyncNode* pSyncNode, SRaftId* pRaftId, SyncIndex index) { - // I am leader, I agree - if (syncUtilSameId(pRaftId, &(pSyncNode->myRaftId)) && pSyncNode->state == TAOS_SYNC_STATE_LEADER) { - return true; - } - - // follower agree - SyncIndex matchIndex = syncIndexMgrGetIndex(pSyncNode->pMatchIndex, pRaftId); - if (matchIndex >= index) { - return true; - } - - // not agree - return false; -} - static inline int64_t syncNodeAbs64(int64_t a, int64_t b) { ASSERT(a >= 0); ASSERT(b >= 0); @@ -85,19 +69,6 @@ bool syncNodeAgreedUpon(SSyncNode* pNode, SyncIndex index) { return count >= pNode->quorum; } -bool syncAgree(SSyncNode* pNode, SyncIndex index) { - int agreeCount = 0; - for (int i = 0; i < pNode->replicaNum; ++i) { - if (syncAgreeIndex(pNode, &(pNode->replicasId[i]), index)) { - ++agreeCount; - } - if (agreeCount >= pNode->quorum) { - return true; - } - } - return false; -} - int64_t syncNodeUpdateCommitIndex(SSyncNode* ths, SyncIndex commitIndex) { SyncIndex lastVer = ths->pLogStore->syncLogLastIndex(ths->pLogStore); commitIndex = TMAX(commitIndex, ths->commitIndex); @@ -111,7 +82,7 @@ int64_t syncNodeCheckCommitIndex(SSyncNode* ths, SyncIndex indexLikely) { SyncIndex commitIndex = indexLikely; syncNodeUpdateCommitIndex(ths, commitIndex); sTrace("vgId:%d, agreed upon. role:%d, term:%" PRId64 ", index:%" PRId64 "", ths->vgId, ths->state, - ths->raftStore.currentTerm, commitIndex); + raftStoreGetTerm(ths), commitIndex); } return ths->commitIndex; } diff --git a/source/libs/sync/src/syncElection.c b/source/libs/sync/src/syncElection.c index 682ace83ecfa99e4781f70915048cf62a5e2d76f..3699efbc594c812c798c0c4b6aa38a6ae001edc5 100644 --- a/source/libs/sync/src/syncElection.c +++ b/source/libs/sync/src/syncElection.c @@ -51,7 +51,7 @@ static int32_t syncNodeRequestVotePeers(SSyncNode* pNode) { SyncRequestVote* pMsg = rpcMsg.pCont; pMsg->srcId = pNode->myRaftId; pMsg->destId = pNode->peersId[i]; - pMsg->term = pNode->raftStore.currentTerm; + pMsg->term = raftStoreGetTerm(pNode); ret = syncNodeGetLastIndexTerm(pNode, &pMsg->lastLogIndex, &pMsg->lastLogTerm); if (ret < 0) { @@ -85,10 +85,12 @@ int32_t syncNodeElect(SSyncNode* pSyncNode) { // start election raftStoreNextTerm(pSyncNode); raftStoreClearVote(pSyncNode); - voteGrantedReset(pSyncNode->pVotesGranted, pSyncNode->raftStore.currentTerm); - votesRespondReset(pSyncNode->pVotesRespond, pSyncNode->raftStore.currentTerm); - syncNodeVoteForSelf(pSyncNode); + SyncTerm currentTerm = raftStoreGetTerm(pSyncNode); + voteGrantedReset(pSyncNode->pVotesGranted, currentTerm); + votesRespondReset(pSyncNode->pVotesRespond, currentTerm); + syncNodeVoteForSelf(pSyncNode, currentTerm); + if (voteGrantedMajority(pSyncNode->pVotesGranted)) { // only myself, to leader ASSERT(!pSyncNode->pVotesGranted->toLeader); @@ -113,6 +115,5 @@ int32_t syncNodeElect(SSyncNode* pSyncNode) { ASSERT(ret == 0); syncNodeResetElectTimer(pSyncNode); - return ret; } diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c index 803df6b662f93f2ab0281e859705397e81c1d41a..966b3ed09380fc16410b83a35008d74227bed1af 100644 --- a/source/libs/sync/src/syncMain.c +++ b/source/libs/sync/src/syncMain.c @@ -37,11 +37,11 @@ #include "syncVoteMgr.h" #include "tglobal.h" #include "tref.h" +#include "syncUtil.h" static void syncNodeEqPingTimer(void* param, void* tmrId); static void syncNodeEqElectTimer(void* param, void* tmrId); static void syncNodeEqHeartbeatTimer(void* param, void* tmrId); -static int32_t syncNodeEqNoop(SSyncNode* ths); static int32_t syncNodeAppendNoop(SSyncNode* ths); static void syncNodeEqPeerHeartbeatTimer(void* param, void* tmrId); static bool syncIsConfigChanged(const SSyncCfg* pOldCfg, const SSyncCfg* pNewCfg); @@ -183,6 +183,9 @@ int32_t syncProcessMsg(int64_t rid, SRpcMsg* pMsg) { case TDMT_SYNC_TIMEOUT: code = syncNodeOnTimeout(pSyncNode, pMsg); break; + case TDMT_SYNC_TIMEOUT_ELECTION: + code = syncNodeOnTimeout(pSyncNode, pMsg); + break; case TDMT_SYNC_CLIENT_REQUEST: code = syncNodeOnClientRequest(pSyncNode, pMsg, NULL); break; @@ -207,6 +210,9 @@ int32_t syncProcessMsg(int64_t rid, SRpcMsg* pMsg) { case TDMT_SYNC_LOCAL_CMD: code = syncNodeOnLocalCmd(pSyncNode, pMsg); break; + case TDMT_SYNC_FORCE_FOLLOWER: + code = syncForceBecomeFollower(pSyncNode, pMsg); + break; default: terrno = TSDB_CODE_MSG_NOT_PROCESSED; code = -1; @@ -229,6 +235,20 @@ int32_t syncLeaderTransfer(int64_t rid) { return ret; } +int32_t syncForceBecomeFollower(SSyncNode* ths, const SRpcMsg* pRpcMsg) { + syncNodeBecomeFollower(ths, "force election"); + + SRpcMsg rsp = { + .code = 0, + .pCont = pRpcMsg->info.rsp, + .contLen = pRpcMsg->info.rspLen, + .info = pRpcMsg->info, + }; + tmsgSendRsp(&rsp); + + return 0; +} + int32_t syncSendTimeoutRsp(int64_t rid, int64_t seq) { SSyncNode* pNode = syncNodeAcquire(rid); if (pNode == NULL) return -1; @@ -271,86 +291,38 @@ int32_t syncBeginSnapshot(int64_t rid, int64_t lastApplyIndex) { return -1; } + SyncIndex beginIndex = pSyncNode->pLogStore->syncLogBeginIndex(pSyncNode->pLogStore); + SyncIndex endIndex = pSyncNode->pLogStore->syncLogEndIndex(pSyncNode->pLogStore); + bool isEmpty = pSyncNode->pLogStore->syncLogIsEmpty(pSyncNode->pLogStore); + + if (isEmpty || !(lastApplyIndex >= beginIndex && lastApplyIndex <= endIndex)) { + sNTrace(pSyncNode, "new-snapshot-index:%" PRId64 ", empty:%d, do not delete wal", lastApplyIndex, isEmpty); + syncNodeRelease(pSyncNode); + return 0; + } + int32_t code = 0; + int64_t logRetention = 0; if (syncNodeIsMnode(pSyncNode)) { // mnode - int64_t logRetention = SYNC_MNODE_LOG_RETENTION; - - SyncIndex beginIndex = pSyncNode->pLogStore->syncLogBeginIndex(pSyncNode->pLogStore); - SyncIndex endIndex = pSyncNode->pLogStore->syncLogEndIndex(pSyncNode->pLogStore); - int64_t logNum = endIndex - beginIndex; - bool isEmpty = pSyncNode->pLogStore->syncLogIsEmpty(pSyncNode->pLogStore); - - if (isEmpty || (!isEmpty && logNum < logRetention)) { - sNTrace(pSyncNode, "new-snapshot-index:%" PRId64 ", log-num:%" PRId64 ", empty:%d, do not delete wal", - lastApplyIndex, logNum, isEmpty); - syncNodeRelease(pSyncNode); - return 0; - } - - goto _DEL_WAL; - + logRetention = tsMndLogRetention; } else { - SyncIndex beginIndex = pSyncNode->pLogStore->syncLogBeginIndex(pSyncNode->pLogStore); - SyncIndex endIndex = pSyncNode->pLogStore->syncLogEndIndex(pSyncNode->pLogStore); - bool isEmpty = pSyncNode->pLogStore->syncLogIsEmpty(pSyncNode->pLogStore); - - if (isEmpty || !(lastApplyIndex >= beginIndex && lastApplyIndex <= endIndex)) { - sNTrace(pSyncNode, "new-snapshot-index:%" PRId64 ", empty:%d, do not delete wal", lastApplyIndex, isEmpty); - syncNodeRelease(pSyncNode); - return 0; - } - // vnode if (pSyncNode->replicaNum > 1) { // multi replicas + logRetention = SYNC_VNODE_LOG_RETENTION; + } + } - lastApplyIndex = TMAX(lastApplyIndex - SYNC_VNODE_LOG_RETENTION, beginIndex - 1); - - if (pSyncNode->state == TAOS_SYNC_STATE_LEADER) { - pSyncNode->minMatchIndex = syncMinMatchIndex(pSyncNode); - - for (int32_t i = 0; i < pSyncNode->peersNum; ++i) { - int64_t matchIndex = syncIndexMgrGetIndex(pSyncNode->pMatchIndex, &(pSyncNode->peersId[i])); - if (lastApplyIndex > matchIndex) { - sNTrace(pSyncNode, - "new-snapshot-index:%" PRId64 " is greater than match-index:%" PRId64 - " of dnode:%d, do not delete wal", - lastApplyIndex, matchIndex, DID(&pSyncNode->peersId[i])); - - syncNodeRelease(pSyncNode); - return 0; - } - } - - } else if (pSyncNode->state == TAOS_SYNC_STATE_FOLLOWER) { - if (lastApplyIndex > pSyncNode->minMatchIndex) { - sNTrace(pSyncNode, - "new-snapshot-index:%" PRId64 " is greater than min-match-index:%" PRId64 ", do not delete wal", - lastApplyIndex, pSyncNode->minMatchIndex); - syncNodeRelease(pSyncNode); - return 0; - } - - } else if (pSyncNode->state == TAOS_SYNC_STATE_CANDIDATE) { - sNTrace(pSyncNode, "new-snapshot-index:%" PRId64 " candidate, do not delete wal", lastApplyIndex); - syncNodeRelease(pSyncNode); - return 0; - - } else { - sNTrace(pSyncNode, "new-snapshot-index:%" PRId64 " unknown state, do not delete wal", lastApplyIndex); - syncNodeRelease(pSyncNode); - return 0; - } - - goto _DEL_WAL; - - } else { - // one replica - - goto _DEL_WAL; + if (pSyncNode->replicaNum > 1) { + if (pSyncNode->state != TAOS_SYNC_STATE_LEADER && pSyncNode->state != TAOS_SYNC_STATE_FOLLOWER) { + sNTrace(pSyncNode, "new-snapshot-index:%" PRId64 " candidate or unknown state, do not delete wal", + lastApplyIndex); + syncNodeRelease(pSyncNode); + return 0; } + logRetention = TMAX(logRetention, lastApplyIndex - pSyncNode->minMatchIndex + logRetention); } _DEL_WAL: @@ -367,7 +339,7 @@ _DEL_WAL: atomic_store_64(&pSyncNode->snapshottingIndex, lastApplyIndex); pSyncNode->snapshottingTime = taosGetTimestampMs(); - code = walBeginSnapshot(pData->pWal, lastApplyIndex); + code = walBeginSnapshot(pData->pWal, lastApplyIndex, logRetention); if (code == 0) { sNTrace(pSyncNode, "wal snapshot begin, index:%" PRId64 ", last apply index:%" PRId64, pSyncNode->snapshottingIndex, lastApplyIndex); @@ -437,55 +409,12 @@ bool syncNodeIsReadyForRead(SSyncNode* pSyncNode) { return false; } - if (pSyncNode->restoreFinish) { - return true; - } - - bool ready = false; - if (!pSyncNode->pFsm->FpApplyQueueEmptyCb(pSyncNode->pFsm)) { - // apply queue not empty - ready = false; - - } else { - if (!pSyncNode->pLogStore->syncLogIsEmpty(pSyncNode->pLogStore)) { - SyncIndex lastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore); - SSyncRaftEntry* pEntry = NULL; - SLRUCache* pCache = pSyncNode->pLogStore->pCache; - LRUHandle* h = taosLRUCacheLookup(pCache, &lastIndex, sizeof(lastIndex)); - int32_t code = 0; - if (h) { - pEntry = (SSyncRaftEntry*)taosLRUCacheValue(pCache, h); - code = 0; - - pSyncNode->pLogStore->cacheHit++; - sNTrace(pSyncNode, "hit cache index:%" PRId64 ", bytes:%u, %p", lastIndex, pEntry->bytes, pEntry); - - } else { - pSyncNode->pLogStore->cacheMiss++; - sNTrace(pSyncNode, "miss cache index:%" PRId64, lastIndex); - - code = pSyncNode->pLogStore->syncLogGetEntry(pSyncNode->pLogStore, lastIndex, &pEntry); - } - - if (code == 0 && pEntry != NULL) { - if (pEntry->originalRpcType == TDMT_SYNC_NOOP && pEntry->term == pSyncNode->raftStore.currentTerm) { - ready = true; - } - - if (h) { - taosLRUCacheRelease(pCache, h, false); - } else { - syncEntryDestroy(pEntry); - } - } - } - } - - if (!ready) { + if (!pSyncNode->restoreFinish) { terrno = TSDB_CODE_SYN_RESTORING; + return false; } - return ready; + return true; } bool syncIsReadyForRead(int64_t rid) { @@ -664,7 +593,7 @@ int32_t syncNodePropose(SSyncNode* pSyncNode, SRpcMsg* pMsg, bool isWeak, int64_ int32_t code = syncNodeOnClientRequest(pSyncNode, pMsg, &retIndex); if (code == 0) { pMsg->info.conn.applyIndex = retIndex; - pMsg->info.conn.applyTerm = pSyncNode->raftStore.currentTerm; + pMsg->info.conn.applyTerm = raftStoreGetTerm(pSyncNode); sTrace("vgId:%d, propose optimized msg, index:%" PRId64 " type:%s", pSyncNode->vgId, retIndex, TMSG_INFO(pMsg->msgType)); return 1; @@ -688,7 +617,7 @@ int32_t syncNodePropose(SSyncNode* pSyncNode, SRpcMsg* pMsg, bool isWeak, int64_ sNTrace(pSyncNode, "propose msg, type:%s", TMSG_INFO(pMsg->msgType)); code = (*pSyncNode->syncEqMsg)(pSyncNode->msgcb, &rpcMsg); if (code != 0) { - sError("vgId:%d, failed to propose msg while enqueue since %s", pSyncNode->vgId, terrstr()); + sWarn("vgId:%d, failed to propose msg while enqueue since %s", pSyncNode->vgId, terrstr()); (void)syncRespMgrDel(pSyncNode->pSyncRespMgr, seqNum); } @@ -823,14 +752,25 @@ SSyncNode* syncNodeOpen(SSyncInfo* pSyncInfo) { // init by SSyncInfo pSyncNode->vgId = pSyncInfo->vgId; SSyncCfg* pCfg = &pSyncNode->raftCfg.cfg; + bool updated = false; sInfo("vgId:%d, start to open sync node, replica:%d selfIndex:%d", pSyncNode->vgId, pCfg->replicaNum, pCfg->myIndex); for (int32_t i = 0; i < pCfg->replicaNum; ++i) { SNodeInfo* pNode = &pCfg->nodeInfo[i]; - tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort); + if (tmsgUpdateDnodeInfo(&pNode->nodeId, &pNode->clusterId, pNode->nodeFqdn, &pNode->nodePort)) { + updated = true; + } sInfo("vgId:%d, index:%d ep:%s:%u dnode:%d cluster:%" PRId64, pSyncNode->vgId, i, pNode->nodeFqdn, pNode->nodePort, pNode->nodeId, pNode->clusterId); } + if (updated) { + sInfo("vgId:%d, save config info since dnode info changed", pSyncNode->vgId); + if (syncWriteCfgFile(pSyncNode) != 0) { + sError("vgId:%d, failed to write sync cfg file on dnode info updated", pSyncNode->vgId); + goto _error; + } + } + pSyncNode->pWal = pSyncInfo->pWal; pSyncNode->msgcb = pSyncInfo->msgcb; pSyncNode->syncSendMSg = pSyncInfo->syncSendMSg; @@ -911,7 +851,7 @@ SSyncNode* syncNodeOpen(SSyncInfo* pSyncInfo) { // init TLA+ server vars pSyncNode->state = TAOS_SYNC_STATE_FOLLOWER; - if (raftStoreReadFile(pSyncNode) != 0) { + if (raftStoreOpen(pSyncNode) != 0) { sError("vgId:%d, failed to open raft store at path %s", pSyncNode->vgId, pSyncNode->raftStorePath); goto _error; } @@ -1027,7 +967,7 @@ SSyncNode* syncNodeOpen(SSyncInfo* pSyncInfo) { pSyncNode->changing = false; // replication mgr - if (syncNodeLogReplMgrInit(pSyncNode) < 0) { + if (syncNodeLogReplInit(pSyncNode) < 0) { sError("vgId:%d, failed to init repl mgr since %s.", pSyncNode->vgId, terrstr()); goto _error; } @@ -1159,29 +1099,9 @@ int32_t syncNodeStartStandBy(SSyncNode* pSyncNode) { } void syncNodePreClose(SSyncNode* pSyncNode) { - if (pSyncNode != NULL && pSyncNode->pFsm != NULL && pSyncNode->pFsm->FpApplyQueueItems != NULL) { - while (1) { - int32_t aqItems = pSyncNode->pFsm->FpApplyQueueItems(pSyncNode->pFsm); - sTrace("vgId:%d, pre close, %d items in apply queue", pSyncNode->vgId, aqItems); - if (aqItems == 0 || aqItems == -1) { - break; - } - taosMsleep(20); - } - } - -#if 0 - if (pSyncNode->pNewNodeReceiver != NULL) { - if (snapshotReceiverIsStart(pSyncNode->pNewNodeReceiver)) { - snapshotReceiverStop(pSyncNode->pNewNodeReceiver); - } - - sDebug("vgId:%d, snapshot receiver destroy while preclose sync node, data:%p", pSyncNode->vgId, - pSyncNode->pNewNodeReceiver); - snapshotReceiverDestroy(pSyncNode->pNewNodeReceiver); - pSyncNode->pNewNodeReceiver = NULL; - } -#endif + ASSERT(pSyncNode != NULL); + ASSERT(pSyncNode->pFsm != NULL); + ASSERT(pSyncNode->pFsm->FpApplyQueueItems != NULL); // stop elect timer syncNodeStopElectTimer(pSyncNode); @@ -1189,6 +1109,9 @@ void syncNodePreClose(SSyncNode* pSyncNode) { // stop heartbeat timer syncNodeStopHeartbeatTimer(pSyncNode); + // stop ping timer + syncNodeStopPingTimer(pSyncNode); + // clean rsp syncRespCleanRsp(pSyncNode->pSyncRespMgr); } @@ -1212,7 +1135,13 @@ void syncNodeClose(SSyncNode* pSyncNode) { if (pSyncNode == NULL) return; sNInfo(pSyncNode, "sync close, node:%p", pSyncNode); - syncNodeLogReplMgrDestroy(pSyncNode); + syncRespCleanRsp(pSyncNode->pSyncRespMgr); + + syncNodeStopPingTimer(pSyncNode); + syncNodeStopElectTimer(pSyncNode); + syncNodeStopHeartbeatTimer(pSyncNode); + syncNodeLogReplDestroy(pSyncNode); + syncRespMgrDestroy(pSyncNode->pSyncRespMgr); pSyncNode->pSyncRespMgr = NULL; voteGrantedDestroy(pSyncNode->pVotesGranted); @@ -1228,10 +1157,6 @@ void syncNodeClose(SSyncNode* pSyncNode) { syncLogBufferDestroy(pSyncNode->pLogBuf); pSyncNode->pLogBuf = NULL; - syncNodeStopPingTimer(pSyncNode); - syncNodeStopElectTimer(pSyncNode); - syncNodeStopHeartbeatTimer(pSyncNode); - for (int32_t i = 0; i < TSDB_MAX_REPLICA; ++i) { if (pSyncNode->senders[i] != NULL) { sDebug("vgId:%d, snapshot sender destroy while close, data:%p", pSyncNode->vgId, pSyncNode->senders[i]); @@ -1259,6 +1184,8 @@ void syncNodeClose(SSyncNode* pSyncNode) { taosMemoryFree(pSyncNode->pFsm); } + raftStoreClose(pSyncNode); + taosMemoryFree(pSyncNode); } @@ -1491,7 +1418,7 @@ void syncNodeDoConfigChange(SSyncNode* pSyncNode, SSyncCfg* pNewConfig, SyncInde } // log begin config change - sNInfo(pSyncNode, "begin do config change, from %d to %d", pSyncNode->vgId, oldConfig.replicaNum, + sNInfo(pSyncNode, "begin do config change, from %d to %d, replicas:%d", pSyncNode->vgId, oldConfig.replicaNum, pNewConfig->replicaNum); if (IamInNew) { @@ -1633,7 +1560,7 @@ _END: // raft state change -------------- void syncNodeUpdateTerm(SSyncNode* pSyncNode, SyncTerm term) { - if (term > pSyncNode->raftStore.currentTerm) { + if (term > raftStoreGetTerm(pSyncNode)) { raftStoreSetTerm(pSyncNode, term); char tmpBuf[64]; snprintf(tmpBuf, sizeof(tmpBuf), "update term to %" PRId64, term); @@ -1643,24 +1570,23 @@ void syncNodeUpdateTerm(SSyncNode* pSyncNode, SyncTerm term) { } void syncNodeUpdateTermWithoutStepDown(SSyncNode* pSyncNode, SyncTerm term) { - if (term > pSyncNode->raftStore.currentTerm) { + if (term > raftStoreGetTerm(pSyncNode)) { raftStoreSetTerm(pSyncNode, term); } } void syncNodeStepDown(SSyncNode* pSyncNode, SyncTerm newTerm) { - if (pSyncNode->raftStore.currentTerm > newTerm) { - sNTrace(pSyncNode, "step down, ignore, new-term:%" PRId64 ", current-term:%" PRId64, newTerm, - pSyncNode->raftStore.currentTerm); + SyncTerm currentTerm = raftStoreGetTerm(pSyncNode); + if (currentTerm > newTerm) { + sNTrace(pSyncNode, "step down, ignore, new-term:%" PRId64 ", current-term:%" PRId64, newTerm, currentTerm); return; } do { - sNTrace(pSyncNode, "step down, new-term:%" PRId64 ", current-term:%" PRId64, newTerm, - pSyncNode->raftStore.currentTerm); + sNTrace(pSyncNode, "step down, new-term:%" PRId64 ", current-term:%" PRId64, newTerm, currentTerm); } while (0); - if (pSyncNode->raftStore.currentTerm < newTerm) { + if (currentTerm < newTerm) { raftStoreSetTerm(pSyncNode, newTerm); char tmpBuf[64]; snprintf(tmpBuf, sizeof(tmpBuf), "step down, update term to %" PRId64, newTerm); @@ -1688,8 +1614,8 @@ void syncNodeBecomeFollower(SSyncNode* pSyncNode, const char* debugStr) { pSyncNode->state = TAOS_SYNC_STATE_FOLLOWER; syncNodeStopHeartbeatTimer(pSyncNode); - // reset elect timer - syncNodeResetElectTimer(pSyncNode); + // trace log + sNTrace(pSyncNode, "become follower %s", debugStr); // send rsp to client syncNodeLeaderChangeRsp(pSyncNode); @@ -1705,8 +1631,8 @@ void syncNodeBecomeFollower(SSyncNode* pSyncNode, const char* debugStr) { // reset log buffer syncLogBufferReset(pSyncNode->pLogBuf, pSyncNode); - // trace log - sNTrace(pSyncNode, "become follower %s", debugStr); + // reset elect timer + syncNodeResetElectTimer(pSyncNode); } // TLA+ Spec @@ -1773,8 +1699,7 @@ void syncNodeBecomeLeader(SSyncNode* pSyncNode, const char* debugStr) { #endif // close receiver - if (pSyncNode != NULL && pSyncNode->pNewNodeReceiver != NULL && - snapshotReceiverIsStart(pSyncNode->pNewNodeReceiver)) { + if (snapshotReceiverIsStart(pSyncNode->pNewNodeReceiver)) { snapshotReceiverStop(pSyncNode->pNewNodeReceiver); } @@ -1820,8 +1745,8 @@ void syncNodeCandidate2Leader(SSyncNode* pSyncNode) { SyncIndex lastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore); ASSERT(lastIndex >= 0); - sInfo("vgId:%d, become leader. term:%" PRId64 ", commit index:%" PRId64 ", last index:%" PRId64 "", - pSyncNode->vgId, pSyncNode->raftStore.currentTerm, pSyncNode->commitIndex, lastIndex); + sInfo("vgId:%d, become leader. term:%" PRId64 ", commit index:%" PRId64 ", last index:%" PRId64 "", pSyncNode->vgId, + raftStoreGetTerm(pSyncNode), pSyncNode->commitIndex, lastIndex); } bool syncNodeIsMnode(SSyncNode* pSyncNode) { return (pSyncNode->vgId == 1); } @@ -1840,7 +1765,7 @@ void syncNodeFollower2Candidate(SSyncNode* pSyncNode) { pSyncNode->state = TAOS_SYNC_STATE_CANDIDATE; SyncIndex lastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore); sInfo("vgId:%d, become candidate from follower. term:%" PRId64 ", commit index:%" PRId64 ", last index:%" PRId64, - pSyncNode->vgId, pSyncNode->raftStore.currentTerm, pSyncNode->commitIndex, lastIndex); + pSyncNode->vgId, raftStoreGetTerm(pSyncNode), pSyncNode->commitIndex, lastIndex); sNTrace(pSyncNode, "follower to candidate"); } @@ -1850,7 +1775,7 @@ void syncNodeLeader2Follower(SSyncNode* pSyncNode) { syncNodeBecomeFollower(pSyncNode, "leader to follower"); SyncIndex lastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore); sInfo("vgId:%d, become follower from leader. term:%" PRId64 ", commit index:%" PRId64 ", last index:%" PRId64, - pSyncNode->vgId, pSyncNode->raftStore.currentTerm, pSyncNode->commitIndex, lastIndex); + pSyncNode->vgId, raftStoreGetTerm(pSyncNode), pSyncNode->commitIndex, lastIndex); sNTrace(pSyncNode, "leader to follower"); } @@ -1860,7 +1785,7 @@ void syncNodeCandidate2Follower(SSyncNode* pSyncNode) { syncNodeBecomeFollower(pSyncNode, "candidate to follower"); SyncIndex lastIndex = pSyncNode->pLogStore->syncLogLastIndex(pSyncNode->pLogStore); sInfo("vgId:%d, become follower from candidate. term:%" PRId64 ", commit index:%" PRId64 ", last index:%" PRId64, - pSyncNode->vgId, pSyncNode->raftStore.currentTerm, pSyncNode->commitIndex, lastIndex); + pSyncNode->vgId, raftStoreGetTerm(pSyncNode), pSyncNode->commitIndex, lastIndex); sNTrace(pSyncNode, "candidate to follower"); } @@ -1868,7 +1793,7 @@ void syncNodeCandidate2Follower(SSyncNode* pSyncNode) { // just called by syncNodeVoteForSelf // need assert void syncNodeVoteForTerm(SSyncNode* pSyncNode, SyncTerm term, SRaftId* pRaftId) { - ASSERT(term == pSyncNode->raftStore.currentTerm); + ASSERT(term == raftStoreGetTerm(pSyncNode)); bool voted = raftStoreHasVoted(pSyncNode); ASSERT(!voted); @@ -1876,8 +1801,8 @@ void syncNodeVoteForTerm(SSyncNode* pSyncNode, SyncTerm term, SRaftId* pRaftId) } // simulate get vote from outside -void syncNodeVoteForSelf(SSyncNode* pSyncNode) { - syncNodeVoteForTerm(pSyncNode, pSyncNode->raftStore.currentTerm, &pSyncNode->myRaftId); +void syncNodeVoteForSelf(SSyncNode* pSyncNode, SyncTerm currentTerm) { + syncNodeVoteForTerm(pSyncNode, currentTerm, &pSyncNode->myRaftId); SRpcMsg rpcMsg = {0}; int32_t ret = syncBuildRequestVoteReply(&rpcMsg, pSyncNode->vgId); @@ -1886,7 +1811,7 @@ void syncNodeVoteForSelf(SSyncNode* pSyncNode) { SyncRequestVoteReply* pMsg = rpcMsg.pCont; pMsg->srcId = pSyncNode->myRaftId; pMsg->destId = pSyncNode->myRaftId; - pMsg->term = pSyncNode->raftStore.currentTerm; + pMsg->term = currentTerm; pMsg->voteGranted = true; voteGrantedVote(pSyncNode->pVotesGranted, pMsg); @@ -2184,24 +2109,19 @@ static void syncNodeEqPeerHeartbeatTimer(void* param, void* tmrId) { if (timerLogicClock == msgLogicClock) { if (tsNow > pData->execTime) { -#if 0 - sTrace( - "vgId:%d, hbDataRid:%ld, EXECUTE this step-------- heartbeat tsNow:%ld, exec:%ld, tsNow-exec:%ld, " - "---------", - pSyncNode->vgId, hbDataRid, tsNow, pData->execTime, tsNow - pData->execTime); -#endif - pData->execTime += pSyncTimer->timerMS; SRpcMsg rpcMsg = {0}; (void)syncBuildHeartbeat(&rpcMsg, pSyncNode->vgId); + pSyncNode->minMatchIndex = syncMinMatchIndex(pSyncNode); + SyncHeartbeat* pSyncMsg = rpcMsg.pCont; pSyncMsg->srcId = pSyncNode->myRaftId; pSyncMsg->destId = pData->destId; - pSyncMsg->term = pSyncNode->raftStore.currentTerm; + pSyncMsg->term = raftStoreGetTerm(pSyncNode); pSyncMsg->commitIndex = pSyncNode->commitIndex; - pSyncMsg->minMatchIndex = syncMinMatchIndex(pSyncNode); + pSyncMsg->minMatchIndex = pSyncNode->minMatchIndex; pSyncMsg->privateTerm = 0; pSyncMsg->timeStamp = tsNow; @@ -2213,11 +2133,6 @@ static void syncNodeEqPeerHeartbeatTimer(void* param, void* tmrId) { syncLogSendHeartbeat(pSyncNode, pSyncMsg, false, timerElapsed, pData->execTime); syncNodeSendHeartbeat(pSyncNode, &pSyncMsg->destId, &rpcMsg); } else { -#if 0 - sTrace( - "vgId:%d, hbDataRid:%ld, pass this step-------- heartbeat tsNow:%ld, exec:%ld, tsNow-exec:%ld, ---------", - pSyncNode->vgId, hbDataRid, tsNow, pData->execTime, tsNow - pData->execTime); -#endif } if (syncIsInit()) { @@ -2238,30 +2153,6 @@ static void syncNodeEqPeerHeartbeatTimer(void* param, void* tmrId) { syncNodeRelease(pSyncNode); } -static int32_t syncNodeEqNoop(SSyncNode* pNode) { - if (pNode->state == TAOS_SYNC_STATE_LEADER) { - terrno = TSDB_CODE_SYN_NOT_LEADER; - return -1; - } - - SyncIndex index = pNode->pLogStore->syncLogWriteIndex(pNode->pLogStore); - SyncTerm term = pNode->raftStore.currentTerm; - SSyncRaftEntry* pEntry = syncEntryBuildNoop(term, index, pNode->vgId); - if (pEntry == NULL) return -1; - - SRpcMsg rpcMsg = {0}; - int32_t code = syncBuildClientRequestFromNoopEntry(&rpcMsg, pEntry, pNode->vgId); - syncEntryDestroy(pEntry); - - sNTrace(pNode, "propose msg, type:noop"); - code = (*pNode->syncEqMsg)(pNode->msgcb, &rpcMsg); - if (code != 0) { - sError("failed to propose noop msg while enqueue since %s", terrstr()); - } - - return code; -} - static void deleteCacheEntry(const void* key, size_t keyLen, void* value) { taosMemoryFree(value); } int32_t syncCacheEntry(SSyncLogStore* pLogStore, SSyncRaftEntry* pEntry, LRUHandle** h) { @@ -2290,8 +2181,8 @@ int32_t syncNodeAppend(SSyncNode* ths, SSyncRaftEntry* pEntry) { // append to log buffer if (syncLogBufferAppend(ths->pLogBuf, ths, pEntry) < 0) { sError("vgId:%d, failed to enqueue sync log buffer, index:%" PRId64, ths->vgId, pEntry->index); - terrno = TSDB_CODE_SYN_BUFFER_FULL; - (void)syncLogFsmExecute(ths, ths->pFsm, ths->state, ths->raftStore.currentTerm, pEntry, TSDB_CODE_SYN_BUFFER_FULL); + ASSERT(terrno != 0); + (void)syncFsmExecute(ths, ths->pFsm, ths->state, raftStoreGetTerm(ths), pEntry, terrno); syncEntryDestroy(pEntry); return -1; } @@ -2364,7 +2255,7 @@ bool syncNodeSnapshotRecving(SSyncNode* pSyncNode) { static int32_t syncNodeAppendNoop(SSyncNode* ths) { SyncIndex index = syncLogBufferGetEndIndex(ths->pLogBuf); - SyncTerm term = ths->raftStore.currentTerm; + SyncTerm term = raftStoreGetTerm(ths); SSyncRaftEntry* pEntry = syncEntryBuildNoop(term, index, ths->vgId); if (pEntry == NULL) { @@ -2380,7 +2271,7 @@ static int32_t syncNodeAppendNoopOld(SSyncNode* ths) { int32_t ret = 0; SyncIndex index = ths->pLogStore->syncLogWriteIndex(ths->pLogStore); - SyncTerm term = ths->raftStore.currentTerm; + SyncTerm term = raftStoreGetTerm(ths); SSyncRaftEntry* pEntry = syncEntryBuildNoop(term, index, ths->vgId); ASSERT(pEntry != NULL); @@ -2407,6 +2298,7 @@ static int32_t syncNodeAppendNoopOld(SSyncNode* ths) { int32_t syncNodeOnHeartbeat(SSyncNode* ths, const SRpcMsg* pRpcMsg) { SyncHeartbeat* pMsg = pRpcMsg->pCont; + bool resetElect = false; const STraceId* trace = &pRpcMsg->info.traceId; char tbuf[40] = {0}; @@ -2416,25 +2308,33 @@ int32_t syncNodeOnHeartbeat(SSyncNode* ths, const SRpcMsg* pRpcMsg) { int64_t timeDiff = tsMs - pMsg->timeStamp; syncLogRecvHeartbeat(ths, pMsg, timeDiff, tbuf); + if (!syncNodeInRaftGroup(ths, &pMsg->srcId)) { + sWarn( + "vgId:%d, drop heartbeat msg from dnode:%d, because it come from another cluster:%d, differ from current " + "cluster:%d", + ths->vgId, DID(&(pMsg->srcId)), CID(&(pMsg->srcId)), CID(&(ths->myRaftId))); + return 0; + } + SRpcMsg rpcMsg = {0}; (void)syncBuildHeartbeatReply(&rpcMsg, ths->vgId); + SyncTerm currentTerm = raftStoreGetTerm(ths); SyncHeartbeatReply* pMsgReply = rpcMsg.pCont; pMsgReply->destId = pMsg->srcId; pMsgReply->srcId = ths->myRaftId; - pMsgReply->term = ths->raftStore.currentTerm; + pMsgReply->term = currentTerm; pMsgReply->privateTerm = 8864; // magic number pMsgReply->startTime = ths->startTime; pMsgReply->timeStamp = tsMs; - if (pMsg->term == ths->raftStore.currentTerm && ths->state != TAOS_SYNC_STATE_LEADER) { + if (pMsg->term == currentTerm && ths->state != TAOS_SYNC_STATE_LEADER) { syncIndexMgrSetRecvTime(ths->pNextIndex, &(pMsg->srcId), tsMs); + resetElect = true; - syncNodeResetElectTimer(ths); ths->minMatchIndex = pMsg->minMatchIndex; if (ths->state == TAOS_SYNC_STATE_FOLLOWER) { - // syncNodeFollowerCommit(ths, pMsg->commitIndex); SRpcMsg rpcMsgLocalCmd = {0}; (void)syncBuildLocalCmd(&rpcMsgLocalCmd, ths->vgId); @@ -2456,8 +2356,7 @@ int32_t syncNodeOnHeartbeat(SSyncNode* ths, const SRpcMsg* pRpcMsg) { } } - if (pMsg->term >= ths->raftStore.currentTerm && ths->state != TAOS_SYNC_STATE_FOLLOWER) { - // syncNodeStepDown(ths, pMsg->term); + if (pMsg->term >= currentTerm && ths->state != TAOS_SYNC_STATE_FOLLOWER) { SRpcMsg rpcMsgLocalCmd = {0}; (void)syncBuildLocalCmd(&rpcMsgLocalCmd, ths->vgId); @@ -2477,15 +2376,10 @@ int32_t syncNodeOnHeartbeat(SSyncNode* ths, const SRpcMsg* pRpcMsg) { } } - /* - // htonl - SMsgHead* pHead = rpcMsg.pCont; - pHead->contLen = htonl(pHead->contLen); - pHead->vgId = htonl(pHead->vgId); - */ - // reply syncNodeSendMsgById(&pMsgReply->destId, ths, &rpcMsg); + + if (resetElect) syncNodeResetElectTimer(ths); return 0; } @@ -2506,7 +2400,7 @@ int32_t syncNodeOnHeartbeatReply(SSyncNode* ths, const SRpcMsg* pRpcMsg) { syncIndexMgrSetRecvTime(ths->pMatchIndex, &pMsg->srcId, tsMs); - return syncLogReplMgrProcessHeartbeatReply(pMgr, ths, pMsg); + return syncLogReplProcessHeartbeatReply(pMgr, ths, pMsg); } int32_t syncNodeOnHeartbeatReplyOld(SSyncNode* ths, const SRpcMsg* pRpcMsg) { @@ -2533,6 +2427,10 @@ int32_t syncNodeOnLocalCmd(SSyncNode* ths, const SRpcMsg* pRpcMsg) { syncNodeStepDown(ths, pMsg->currentTerm); } else if (pMsg->cmd == SYNC_LOCAL_CMD_FOLLOWER_CMT) { + if (syncLogBufferIsEmpty(ths->pLogBuf)) { + sError("vgId:%d, sync log buffer is empty.", ths->vgId); + return 0; + } SyncTerm matchTerm = syncLogBufferGetLastMatchTerm(ths->pLogBuf); if (pMsg->currentTerm == matchTerm) { (void)syncNodeUpdateCommitIndex(ths, pMsg->commitIndex); @@ -2565,7 +2463,7 @@ int32_t syncNodeOnClientRequest(SSyncNode* ths, SRpcMsg* pMsg, SyncIndex* pRetIn int32_t code = 0; SyncIndex index = syncLogBufferGetEndIndex(ths->pLogBuf); - SyncTerm term = ths->raftStore.currentTerm; + SyncTerm term = raftStoreGetTerm(ths); SSyncRaftEntry* pEntry = NULL; if (pMsg->msgType == TDMT_SYNC_CLIENT_REQUEST) { pEntry = syncEntryBuildFromClientRequest(pMsg->pCont, term, index); @@ -2609,73 +2507,6 @@ const char* syncStr(ESyncState state) { } } -#if 0 -int32_t syncDoLeaderTransfer(SSyncNode* ths, SRpcMsg* pRpcMsg, SSyncRaftEntry* pEntry) { - if (ths->state != TAOS_SYNC_STATE_FOLLOWER) { - sNTrace(ths, "I am not follower, can not do leader transfer"); - return 0; - } - - if (!ths->restoreFinish) { - sNTrace(ths, "restore not finish, can not do leader transfer"); - return 0; - } - - if (pEntry->term < ths->raftStore.currentTerm) { - sNTrace(ths, "little term:%" PRId64 ", can not do leader transfer", pEntry->term); - return 0; - } - - if (pEntry->index < syncNodeGetLastIndex(ths)) { - sNTrace(ths, "little index:%" PRId64 ", can not do leader transfer", pEntry->index); - return 0; - } - - /* - if (ths->vgId > 1) { - sNTrace(ths, "I am vnode, can not do leader transfer"); - return 0; - } - */ - - SyncLeaderTransfer* pSyncLeaderTransfer = pRpcMsg->pCont; - sNTrace(ths, "do leader transfer, index:%" PRId64, pEntry->index); - - bool sameId = syncUtilSameId(&(pSyncLeaderTransfer->newLeaderId), &(ths->myRaftId)); - bool sameNodeInfo = strcmp(pSyncLeaderTransfer->newNodeInfo.nodeFqdn, ths->myNodeInfo.nodeFqdn) == 0 && - pSyncLeaderTransfer->newNodeInfo.nodePort == ths->myNodeInfo.nodePort; - - bool same = sameId || sameNodeInfo; - if (same) { - // reset elect timer now! - int32_t electMS = 1; - int32_t ret = syncNodeRestartElectTimer(ths, electMS); - ASSERT(ret == 0); - - sNTrace(ths, "maybe leader transfer to %s:%d %" PRId64, pSyncLeaderTransfer->newNodeInfo.nodeFqdn, - pSyncLeaderTransfer->newNodeInfo.nodePort, pSyncLeaderTransfer->newLeaderId.addr); - } - - if (ths->pFsm->FpLeaderTransferCb != NULL) { - SFsmCbMeta cbMeta = { - .code = 0, - .currentTerm = ths->raftStore.currentTerm, - .flag = 0, - .index = pEntry->index, - .lastConfigIndex = syncNodeGetSnapshotConfigIndex(ths, pEntry->index), - .isWeak = pEntry->isWeak, - .seqNum = pEntry->seqNum, - .state = ths->state, - .term = pEntry->term, - }; - ths->pFsm->FpLeaderTransferCb(ths->pFsm, pRpcMsg, &cbMeta); - } - - return 0; -} - -#endif - int32_t syncNodeUpdateNewConfigIndex(SSyncNode* ths, SSyncCfg* pNewCfg) { for (int32_t i = 0; i < pNewCfg->replicaNum; ++i) { SRaftId raftId = { diff --git a/source/libs/sync/src/syncMessage.c b/source/libs/sync/src/syncMessage.c index 7d534c671e6c80453f8a3b47fffebcf8028e062e..72c8887803c778e0cd8a82b4b11273ad2b1df5f2 100644 --- a/source/libs/sync/src/syncMessage.c +++ b/source/libs/sync/src/syncMessage.c @@ -22,7 +22,7 @@ int32_t syncBuildTimeout(SRpcMsg* pMsg, ESyncTimeoutType timeoutType, uint64_t l SSyncNode* pNode) { int32_t bytes = sizeof(SyncTimeout); pMsg->pCont = rpcMallocCont(bytes); - pMsg->msgType = TDMT_SYNC_TIMEOUT; + pMsg->msgType = (timeoutType == SYNC_TIMEOUT_ELECTION) ? TDMT_SYNC_TIMEOUT_ELECTION : TDMT_SYNC_TIMEOUT; pMsg->contLen = bytes; if (pMsg->pCont == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -31,7 +31,7 @@ int32_t syncBuildTimeout(SRpcMsg* pMsg, ESyncTimeoutType timeoutType, uint64_t l SyncTimeout* pTimeout = pMsg->pCont; pTimeout->bytes = bytes; - pTimeout->msgType = TDMT_SYNC_TIMEOUT; + pTimeout->msgType = pMsg->msgType; pTimeout->vgId = pNode->vgId; pTimeout->timeoutType = timeoutType; pTimeout->logicClock = logicClock; @@ -176,7 +176,7 @@ int32_t syncBuildAppendEntriesFromRaftEntry(SSyncNode* pNode, SSyncRaftEntry* pE pMsg->prevLogTerm = prevLogTerm; pMsg->vgId = pNode->vgId; pMsg->srcId = pNode->myRaftId; - pMsg->term = pNode->raftStore.currentTerm; + pMsg->term = raftStoreGetTerm(pNode); pMsg->commitIndex = pNode->commitIndex; pMsg->privateTerm = 0; return 0; diff --git a/source/libs/sync/src/syncPipeline.c b/source/libs/sync/src/syncPipeline.c index d1ef8701bec35dc9f9c11350dc70a0b961c9a64a..6bebef77dc75ac0ec0adc0273d23bec4789cf527 100644 --- a/source/libs/sync/src/syncPipeline.c +++ b/source/libs/sync/src/syncPipeline.c @@ -48,7 +48,16 @@ int32_t syncLogBufferAppend(SSyncLogBuffer* pBuf, SSyncNode* pNode, SSyncRaftEnt SyncIndex index = pEntry->index; if (index - pBuf->startIndex >= pBuf->size) { - sError("vgId:%d, failed to append due to sync log buffer full. index:%" PRId64 "", pNode->vgId, index); + terrno = TSDB_CODE_SYN_BUFFER_FULL; + sError("vgId:%d, failed to append since %s. index:%" PRId64 "", pNode->vgId, terrstr(), index); + goto _err; + } + + SyncIndex appliedIndex = pNode->pFsm->FpAppliedIndexCb(pNode->pFsm); + if (pNode->restoreFinish && pBuf->commitIndex - appliedIndex >= pBuf->size) { + terrno = TSDB_CODE_SYN_WRITE_STALL; + sError("vgId:%d, failed to append since %s. index:%" PRId64 ", commit-index:%" PRId64 ", applied-index:%" PRId64, + pNode->vgId, terrstr(), index, pBuf->commitIndex, appliedIndex); goto _err; } @@ -61,6 +70,7 @@ int32_t syncLogBufferAppend(SSyncLogBuffer* pBuf, SSyncNode* pNode, SSyncRaftEnt SSyncRaftEntry* pMatch = pBuf->entries[(index - 1 + pBuf->size) % pBuf->size].pItem; ASSERTS(pMatch != NULL, "no matched log entry"); ASSERT(pMatch->index + 1 == index); + ASSERT(pMatch->term <= pEntry->term); SSyncLogBufEntry tmp = {.pItem = pEntry, .prevLogIndex = pMatch->index, .prevLogTerm = pMatch->term}; pBuf->entries[index % pBuf->size] = tmp; @@ -76,7 +86,7 @@ _err: return -1; } -SyncTerm syncLogReplMgrGetPrevLogTerm(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index) { +SyncTerm syncLogReplGetPrevLogTerm(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index) { SSyncLogBuffer* pBuf = pNode->pLogBuf; SSyncRaftEntry* pEntry = NULL; SyncIndex prevIndex = index - 1; @@ -252,6 +262,7 @@ int32_t syncLogBufferInit(SSyncLogBuffer* pBuf, SSyncNode* pNode) { int32_t syncLogBufferReInit(SSyncLogBuffer* pBuf, SSyncNode* pNode) { taosThreadMutexLock(&pBuf->mutex); + syncLogBufferValidate(pBuf); for (SyncIndex index = pBuf->startIndex; index < pBuf->endIndex; index++) { SSyncRaftEntry* pEntry = pBuf->entries[(index + pBuf->size) % pBuf->size].pItem; if (pEntry == NULL) continue; @@ -264,6 +275,7 @@ int32_t syncLogBufferReInit(SSyncLogBuffer* pBuf, SSyncNode* pNode) { if (ret < 0) { sError("vgId:%d, failed to re-initialize sync log buffer since %s.", pNode->vgId, terrstr()); } + syncLogBufferValidate(pBuf); taosThreadMutexUnlock(&pBuf->mutex); return ret; } @@ -282,6 +294,13 @@ SyncTerm syncLogBufferGetLastMatchTerm(SSyncLogBuffer* pBuf) { return term; } +bool syncLogBufferIsEmpty(SSyncLogBuffer* pBuf) { + taosThreadMutexLock(&pBuf->mutex); + bool empty = (pBuf->endIndex <= pBuf->startIndex); + taosThreadMutexUnlock(&pBuf->mutex); + return empty; +} + int32_t syncLogBufferAccept(SSyncLogBuffer* pBuf, SSyncNode* pNode, SSyncRaftEntry* pEntry, SyncTerm prevTerm) { taosThreadMutexLock(&pBuf->mutex); syncLogBufferValidate(pBuf); @@ -297,7 +316,7 @@ int32_t syncLogBufferAccept(SSyncLogBuffer* pBuf, SSyncNode* pNode, SSyncRaftEnt " %" PRId64 ", %" PRId64 ")", pNode->vgId, pEntry->index, pEntry->term, pBuf->startIndex, pBuf->commitIndex, pBuf->matchIndex, pBuf->endIndex); - SyncTerm term = syncLogReplMgrGetPrevLogTerm(NULL, pNode, index + 1); + SyncTerm term = syncLogReplGetPrevLogTerm(NULL, pNode, index + 1); ASSERT(pEntry->term >= 0); if (term == pEntry->term) { ret = 0; @@ -332,7 +351,7 @@ int32_t syncLogBufferAccept(SSyncLogBuffer* pBuf, SSyncNode* pNode, SSyncRaftEnt " %" PRId64 " %" PRId64 ", %" PRId64 ")", pNode->vgId, pEntry->index, pEntry->term, pBuf->startIndex, pBuf->commitIndex, pBuf->matchIndex, pBuf->endIndex); - SyncTerm existPrevTerm = syncLogReplMgrGetPrevLogTerm(NULL, pNode, index); + SyncTerm existPrevTerm = syncLogReplGetPrevLogTerm(NULL, pNode, index); ASSERT(pEntry->term == pExist->term && (pEntry->index > pBuf->matchIndex || prevTerm == existPrevTerm)); ret = 0; goto _out; @@ -463,9 +482,9 @@ _out: return matchIndex; } -int32_t syncLogFsmExecute(SSyncNode* pNode, SSyncFSM* pFsm, ESyncState role, SyncTerm term, SSyncRaftEntry* pEntry, - int32_t applyCode) { - if ((pNode->replicaNum == 1) && pNode->restoreFinish && pNode->vgId != 1) { +int32_t syncFsmExecute(SSyncNode* pNode, SSyncFSM* pFsm, ESyncState role, SyncTerm term, SSyncRaftEntry* pEntry, + int32_t applyCode) { + if (pNode->replicaNum == 1 && pNode->restoreFinish && pNode->vgId != 1) { return 0; } @@ -514,7 +533,7 @@ int32_t syncLogBufferCommit(SSyncLogBuffer* pBuf, SSyncNode* pNode, int64_t comm SSyncLogStore* pLogStore = pNode->pLogStore; SSyncFSM* pFsm = pNode->pFsm; ESyncState role = pNode->state; - SyncTerm term = pNode->raftStore.currentTerm; + SyncTerm currentTerm = raftStoreGetTerm(pNode); SyncGroupId vgId = pNode->vgId; int32_t ret = -1; int64_t upperIndex = TMIN(commitIndex, pBuf->matchIndex); @@ -529,7 +548,7 @@ int32_t syncLogBufferCommit(SSyncLogBuffer* pBuf, SSyncNode* pNode, int64_t comm } sTrace("vgId:%d, commit. log buffer: [%" PRId64 " %" PRId64 " %" PRId64 ", %" PRId64 "), role:%d, term:%" PRId64, - pNode->vgId, pBuf->startIndex, pBuf->commitIndex, pBuf->matchIndex, pBuf->endIndex, role, term); + pNode->vgId, pBuf->startIndex, pBuf->commitIndex, pBuf->matchIndex, pBuf->endIndex, role, currentTerm); // execute in fsm for (int64_t index = pBuf->commitIndex + 1; index <= upperIndex; index++) { @@ -545,16 +564,16 @@ int32_t syncLogBufferCommit(SSyncLogBuffer* pBuf, SSyncNode* pNode, int64_t comm pEntry->term, TMSG_INFO(pEntry->originalRpcType)); } - if (syncLogFsmExecute(pNode, pFsm, role, term, pEntry, 0) != 0) { + if (syncFsmExecute(pNode, pFsm, role, currentTerm, pEntry, 0) != 0) { sError("vgId:%d, failed to execute sync log entry. index:%" PRId64 ", term:%" PRId64 ", role:%d, current term:%" PRId64, - vgId, pEntry->index, pEntry->term, role, term); + vgId, pEntry->index, pEntry->term, role, currentTerm); goto _out; } pBuf->commitIndex = index; sTrace("vgId:%d, committed index:%" PRId64 ", term:%" PRId64 ", role:%d, current term:%" PRId64 "", pNode->vgId, - pEntry->index, pEntry->term, role, term); + pEntry->index, pEntry->term, role, currentTerm); if (!inBuf) { syncEntryDestroy(pEntry); @@ -576,11 +595,11 @@ int32_t syncLogBufferCommit(SSyncLogBuffer* pBuf, SSyncNode* pNode, int64_t comm _out: // mark as restored if needed if (!pNode->restoreFinish && pBuf->commitIndex >= pNode->commitIndex && pEntry != NULL && - pNode->raftStore.currentTerm <= pEntry->term) { - pNode->pFsm->FpRestoreFinishCb(pNode->pFsm); + currentTerm <= pEntry->term) { + pNode->pFsm->FpRestoreFinishCb(pNode->pFsm, pBuf->commitIndex); pNode->restoreFinish = true; - sInfo("vgId:%d, restore finished. log buffer: [%" PRId64 " %" PRId64 " %" PRId64 ", %" PRId64 ")", pNode->vgId, - pBuf->startIndex, pBuf->commitIndex, pBuf->matchIndex, pBuf->endIndex); + sInfo("vgId:%d, restore finished. term:%" PRId64 ", log buffer: [%" PRId64 " %" PRId64 " %" PRId64 ", %" PRId64 ")", + pNode->vgId, currentTerm, pBuf->startIndex, pBuf->commitIndex, pBuf->matchIndex, pBuf->endIndex); } if (!inBuf) { @@ -592,7 +611,7 @@ _out: return ret; } -void syncLogReplMgrReset(SSyncLogReplMgr* pMgr) { +void syncLogReplReset(SSyncLogReplMgr* pMgr) { if (pMgr == NULL) return; ASSERT(pMgr->startIndex >= 0); @@ -606,22 +625,22 @@ void syncLogReplMgrReset(SSyncLogReplMgr* pMgr) { pMgr->retryBackoff = 0; } -int32_t syncLogReplMgrRetryOnNeed(SSyncLogReplMgr* pMgr, SSyncNode* pNode) { +int32_t syncLogReplRetryOnNeed(SSyncLogReplMgr* pMgr, SSyncNode* pNode) { if (pMgr->endIndex <= pMgr->startIndex) { return 0; } SRaftId* pDestId = &pNode->replicasId[pMgr->peerId]; if (pMgr->retryBackoff == SYNC_MAX_RETRY_BACKOFF) { - syncLogReplMgrReset(pMgr); - sWarn("vgId:%d, reset sync log repl mgr since retry backoff exceeding limit. peer:%" PRIx64, pNode->vgId, + syncLogReplReset(pMgr); + sWarn("vgId:%d, reset sync log repl since retry backoff exceeding limit. peer:%" PRIx64, pNode->vgId, pDestId->addr); return -1; } int32_t ret = -1; bool retried = false; - int64_t retryWaitMs = syncLogGetRetryBackoffTimeMs(pMgr); + int64_t retryWaitMs = syncLogReplGetRetryBackoffTimeMs(pMgr); int64_t nowMs = taosGetMonoTimestampMs(); int count = 0; int64_t firstIndex = -1; @@ -638,16 +657,16 @@ int32_t syncLogReplMgrRetryOnNeed(SSyncLogReplMgr* pMgr, SSyncNode* pNode) { if (pMgr->states[pos].acked) { if (pMgr->matchIndex < index && pMgr->states[pos].timeMs + (syncGetRetryMaxWaitMs() << 3) < nowMs) { - syncLogReplMgrReset(pMgr); - sWarn("vgId:%d, reset sync log repl mgr since stagnation. index:%" PRId64 ", peer:%" PRIx64, pNode->vgId, - index, pDestId->addr); + syncLogReplReset(pMgr); + sWarn("vgId:%d, reset sync log repl since stagnation. index:%" PRId64 ", peer:%" PRIx64, pNode->vgId, index, + pDestId->addr); goto _out; } continue; } bool barrier = false; - if (syncLogReplMgrReplicateOneTo(pMgr, pNode, index, &term, pDestId, &barrier) < 0) { + if (syncLogReplSendTo(pMgr, pNode, index, &term, pDestId, &barrier) < 0) { sError("vgId:%d, failed to replicate sync log entry since %s. index:%" PRId64 ", dest:%" PRIx64 "", pNode->vgId, terrstr(), index, pDestId->addr); goto _out; @@ -668,7 +687,7 @@ int32_t syncLogReplMgrRetryOnNeed(SSyncLogReplMgr* pMgr, SSyncNode* pNode) { ret = 0; _out: if (retried) { - pMgr->retryBackoff = syncLogGetNextRetryBackoff(pMgr); + pMgr->retryBackoff = syncLogReplGetNextRetryBackoff(pMgr); SSyncLogBuffer* pBuf = pNode->pLogBuf; sInfo("vgId:%d, resend %d sync log entries. dest:%" PRIx64 ", indexes:%" PRId64 " ..., terms: ... %" PRId64 ", retryWaitMs:%" PRId64 ", mgr: [%" PRId64 " %" PRId64 ", %" PRId64 "), buffer: [%" PRId64 " %" PRId64 @@ -679,7 +698,7 @@ _out: return ret; } -int32_t syncLogReplMgrProcessReplyAsRecovery(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg) { +int32_t syncLogReplProcessReplyAsRecovery(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg) { SSyncLogBuffer* pBuf = pNode->pLogBuf; SRaftId destId = pMsg->srcId; ASSERT(pMgr->restored == false); @@ -689,7 +708,7 @@ int32_t syncLogReplMgrProcessReplyAsRecovery(SSyncLogReplMgr* pMgr, SSyncNode* p ASSERT(pMgr->matchIndex == 0); if (pMsg->matchIndex < 0) { pMgr->restored = true; - sInfo("vgId:%d, sync log repl mgr restored. peer: dnode:%d (%" PRIx64 "), mgr: rs(%d) [%" PRId64 " %" PRId64 + sInfo("vgId:%d, sync log repl restored. peer: dnode:%d (%" PRIx64 "), mgr: rs(%d) [%" PRId64 " %" PRId64 ", %" PRId64 "), buffer: [%" PRId64 " %" PRId64 " %" PRId64 ", %" PRId64 ")", pNode->vgId, DID(&destId), destId.addr, pMgr->restored, pMgr->startIndex, pMgr->matchIndex, pMgr->endIndex, pBuf->startIndex, pBuf->commitIndex, pBuf->matchIndex, pBuf->endIndex); @@ -697,7 +716,7 @@ int32_t syncLogReplMgrProcessReplyAsRecovery(SSyncLogReplMgr* pMgr, SSyncNode* p } } else { if (pMsg->lastSendIndex < pMgr->startIndex || pMsg->lastSendIndex >= pMgr->endIndex) { - syncLogReplMgrRetryOnNeed(pMgr, pNode); + syncLogReplRetryOnNeed(pMgr, pNode); return 0; } @@ -706,7 +725,7 @@ int32_t syncLogReplMgrProcessReplyAsRecovery(SSyncLogReplMgr* pMgr, SSyncNode* p if (pMsg->success && pMsg->matchIndex == pMsg->lastSendIndex) { pMgr->matchIndex = pMsg->matchIndex; pMgr->restored = true; - sInfo("vgId:%d, sync log repl mgr restored. peer: dnode:%d (%" PRIx64 "), mgr: rs(%d) [%" PRId64 " %" PRId64 + sInfo("vgId:%d, sync log repl restored. peer: dnode:%d (%" PRIx64 "), mgr: rs(%d) [%" PRId64 " %" PRId64 ", %" PRId64 "), buffer: [%" PRId64 " %" PRId64 " %" PRId64 ", %" PRId64 ")", pNode->vgId, DID(&destId), destId.addr, pMgr->restored, pMgr->startIndex, pMgr->matchIndex, pMgr->endIndex, pBuf->startIndex, pBuf->commitIndex, pBuf->matchIndex, pBuf->endIndex); @@ -731,8 +750,9 @@ int32_t syncLogReplMgrProcessReplyAsRecovery(SSyncLogReplMgr* pMgr, SSyncNode* p SyncIndex index = TMIN(pMsg->matchIndex, pNode->pLogBuf->matchIndex); if (pMsg->matchIndex < pNode->pLogBuf->matchIndex) { - term = syncLogReplMgrGetPrevLogTerm(pMgr, pNode, index + 1); - if (term < 0 || (term != pMsg->lastMatchTerm && (index + 1 == firstVer || index == firstVer))) { + term = syncLogReplGetPrevLogTerm(pMgr, pNode, index + 1); + if ((index + 1 < firstVer) || (term < 0) || + (term != pMsg->lastMatchTerm && (index + 1 == firstVer || index == firstVer))) { ASSERT(term >= 0 || terrno == TSDB_CODE_WAL_LOG_NOT_EXIST); if (syncNodeStartSnapshot(pNode, &destId) < 0) { sError("vgId:%d, failed to start snapshot for peer dnode:%d", pNode->vgId, DID(&destId)); @@ -753,53 +773,52 @@ int32_t syncLogReplMgrProcessReplyAsRecovery(SSyncLogReplMgr* pMgr, SSyncNode* p } // attempt to replicate the raft log at index - (void)syncLogReplMgrReset(pMgr); - return syncLogReplMgrReplicateProbe(pMgr, pNode, index); + (void)syncLogReplReset(pMgr); + return syncLogReplProbe(pMgr, pNode, index); } -int32_t syncLogReplMgrProcessHeartbeatReply(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncHeartbeatReply* pMsg) { +int32_t syncLogReplProcessHeartbeatReply(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncHeartbeatReply* pMsg) { SSyncLogBuffer* pBuf = pNode->pLogBuf; taosThreadMutexLock(&pBuf->mutex); if (pMsg->startTime != 0 && pMsg->startTime != pMgr->peerStartTime) { - sInfo("vgId:%d, reset sync log repl mgr in heartbeat. peer:%" PRIx64 ", start time:%" PRId64 ", old:%" PRId64 "", + sInfo("vgId:%d, reset sync log repl in heartbeat. peer:%" PRIx64 ", start time:%" PRId64 ", old:%" PRId64 "", pNode->vgId, pMsg->srcId.addr, pMsg->startTime, pMgr->peerStartTime); - syncLogReplMgrReset(pMgr); + syncLogReplReset(pMgr); pMgr->peerStartTime = pMsg->startTime; } taosThreadMutexUnlock(&pBuf->mutex); return 0; } -int32_t syncLogReplMgrProcessReply(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg) { +int32_t syncLogReplProcessReply(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg) { SSyncLogBuffer* pBuf = pNode->pLogBuf; taosThreadMutexLock(&pBuf->mutex); if (pMsg->startTime != pMgr->peerStartTime) { - sInfo("vgId:%d, reset sync log repl mgr in appendlog reply. peer:%" PRIx64 ", start time:%" PRId64 - ", old:%" PRId64, + sInfo("vgId:%d, reset sync log repl in appendlog reply. peer:%" PRIx64 ", start time:%" PRId64 ", old:%" PRId64, pNode->vgId, pMsg->srcId.addr, pMsg->startTime, pMgr->peerStartTime); - syncLogReplMgrReset(pMgr); + syncLogReplReset(pMgr); pMgr->peerStartTime = pMsg->startTime; } if (pMgr->restored) { - (void)syncLogReplMgrProcessReplyAsNormal(pMgr, pNode, pMsg); + (void)syncLogReplProcessReplyAsNormal(pMgr, pNode, pMsg); } else { - (void)syncLogReplMgrProcessReplyAsRecovery(pMgr, pNode, pMsg); + (void)syncLogReplProcessReplyAsRecovery(pMgr, pNode, pMsg); } taosThreadMutexUnlock(&pBuf->mutex); return 0; } -int32_t syncLogReplMgrReplicateOnce(SSyncLogReplMgr* pMgr, SSyncNode* pNode) { +int32_t syncLogReplDoOnce(SSyncLogReplMgr* pMgr, SSyncNode* pNode) { if (pMgr->restored) { - (void)syncLogReplMgrReplicateAttempt(pMgr, pNode); + (void)syncLogReplAttempt(pMgr, pNode); } else { - (void)syncLogReplMgrReplicateProbe(pMgr, pNode, pNode->pLogBuf->matchIndex); + (void)syncLogReplProbe(pMgr, pNode, pNode->pLogBuf->matchIndex); } return 0; } -int32_t syncLogReplMgrReplicateProbe(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index) { +int32_t syncLogReplProbe(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index) { ASSERT(!pMgr->restored); ASSERT(pMgr->startIndex >= 0); int64_t retryMaxWaitMs = syncGetRetryMaxWaitMs(); @@ -809,12 +828,12 @@ int32_t syncLogReplMgrReplicateProbe(SSyncLogReplMgr* pMgr, SSyncNode* pNode, Sy nowMs < pMgr->states[pMgr->startIndex % pMgr->size].timeMs + retryMaxWaitMs) { return 0; } - (void)syncLogReplMgrReset(pMgr); + (void)syncLogReplReset(pMgr); SRaftId* pDestId = &pNode->replicasId[pMgr->peerId]; bool barrier = false; SyncTerm term = -1; - if (syncLogReplMgrReplicateOneTo(pMgr, pNode, index, &term, pDestId, &barrier) < 0) { + if (syncLogReplSendTo(pMgr, pNode, index, &term, pDestId, &barrier) < 0) { sError("vgId:%d, failed to replicate log entry since %s. index:%" PRId64 ", dest: 0x%016" PRIx64 "", pNode->vgId, terrstr(), index, pDestId->addr); return -1; @@ -837,7 +856,7 @@ int32_t syncLogReplMgrReplicateProbe(SSyncLogReplMgr* pMgr, SSyncNode* pNode, Sy return 0; } -int32_t syncLogReplMgrReplicateAttempt(SSyncLogReplMgr* pMgr, SSyncNode* pNode) { +int32_t syncLogReplAttempt(SSyncLogReplMgr* pMgr, SSyncNode* pNode) { ASSERT(pMgr->restored); SRaftId* pDestId = &pNode->replicasId[pMgr->peerId]; @@ -859,7 +878,7 @@ int32_t syncLogReplMgrReplicateAttempt(SSyncLogReplMgr* pMgr, SSyncNode* pNode) SRaftId* pDestId = &pNode->replicasId[pMgr->peerId]; bool barrier = false; SyncTerm term = -1; - if (syncLogReplMgrReplicateOneTo(pMgr, pNode, index, &term, pDestId, &barrier) < 0) { + if (syncLogReplSendTo(pMgr, pNode, index, &term, pDestId, &barrier) < 0) { sError("vgId:%d, failed to replicate log entry since %s. index:%" PRId64 ", dest: 0x%016" PRIx64 "", pNode->vgId, terrstr(), index, pDestId->addr); return -1; @@ -882,7 +901,7 @@ int32_t syncLogReplMgrReplicateAttempt(SSyncLogReplMgr* pMgr, SSyncNode* pNode) } } - syncLogReplMgrRetryOnNeed(pMgr, pNode); + syncLogReplRetryOnNeed(pMgr, pNode); SSyncLogBuffer* pBuf = pNode->pLogBuf; sTrace("vgId:%d, replicated %d msgs to peer:%" PRIx64 ". indexes:%" PRId64 "..., terms: ...%" PRId64 @@ -893,14 +912,14 @@ int32_t syncLogReplMgrReplicateAttempt(SSyncLogReplMgr* pMgr, SSyncNode* pNode) return 0; } -int32_t syncLogReplMgrProcessReplyAsNormal(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg) { +int32_t syncLogReplProcessReplyAsNormal(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncAppendEntriesReply* pMsg) { ASSERT(pMgr->restored == true); if (pMgr->startIndex <= pMsg->lastSendIndex && pMsg->lastSendIndex < pMgr->endIndex) { if (pMgr->startIndex < pMgr->matchIndex && pMgr->retryBackoff > 0) { - int64_t firstSentMs = pMgr->states[pMgr->startIndex % pMgr->size].timeMs; - int64_t lastSentMs = pMgr->states[(pMgr->endIndex - 1) % pMgr->size].timeMs; - int64_t timeDiffMs = lastSentMs - firstSentMs; - if (timeDiffMs > 0 && timeDiffMs < (SYNC_LOG_REPL_RETRY_WAIT_MS << (pMgr->retryBackoff - 1))) { + int64_t firstMs = pMgr->states[pMgr->startIndex % pMgr->size].timeMs; + int64_t lastMs = pMgr->states[(pMgr->endIndex - 1) % pMgr->size].timeMs; + int64_t diffMs = lastMs - firstMs; + if (diffMs > 0 && diffMs < ((int64_t)SYNC_LOG_REPL_RETRY_WAIT_MS << (pMgr->retryBackoff - 1))) { pMgr->retryBackoff -= 1; } } @@ -912,10 +931,10 @@ int32_t syncLogReplMgrProcessReplyAsNormal(SSyncLogReplMgr* pMgr, SSyncNode* pNo pMgr->startIndex = pMgr->matchIndex; } - return syncLogReplMgrReplicateAttempt(pMgr, pNode); + return syncLogReplAttempt(pMgr, pNode); } -SSyncLogReplMgr* syncLogReplMgrCreate() { +SSyncLogReplMgr* syncLogReplCreate() { SSyncLogReplMgr* pMgr = taosMemoryCalloc(1, sizeof(SSyncLogReplMgr)); if (pMgr == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -927,13 +946,9 @@ SSyncLogReplMgr* syncLogReplMgrCreate() { ASSERT(pMgr->size == TSDB_SYNC_LOG_BUFFER_SIZE); return pMgr; - -_err: - taosMemoryFree(pMgr); - return NULL; } -void syncLogReplMgrDestroy(SSyncLogReplMgr* pMgr) { +void syncLogReplDestroy(SSyncLogReplMgr* pMgr) { if (pMgr == NULL) { return; } @@ -941,10 +956,10 @@ void syncLogReplMgrDestroy(SSyncLogReplMgr* pMgr) { return; } -int32_t syncNodeLogReplMgrInit(SSyncNode* pNode) { +int32_t syncNodeLogReplInit(SSyncNode* pNode) { for (int i = 0; i < TSDB_MAX_REPLICA; i++) { ASSERT(pNode->logReplMgrs[i] == NULL); - pNode->logReplMgrs[i] = syncLogReplMgrCreate(); + pNode->logReplMgrs[i] = syncLogReplCreate(); if (pNode->logReplMgrs[i] == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -954,9 +969,9 @@ int32_t syncNodeLogReplMgrInit(SSyncNode* pNode) { return 0; } -void syncNodeLogReplMgrDestroy(SSyncNode* pNode) { +void syncNodeLogReplDestroy(SSyncNode* pNode) { for (int i = 0; i < TSDB_MAX_REPLICA; i++) { - syncLogReplMgrDestroy(pNode->logReplMgrs[i]); + syncLogReplDestroy(pNode->logReplMgrs[i]); pNode->logReplMgrs[i] = NULL; } } @@ -1072,6 +1087,7 @@ int32_t syncLogBufferRollback(SSyncLogBuffer* pBuf, SSyncNode* pNode, SyncIndex int32_t syncLogBufferReset(SSyncLogBuffer* pBuf, SSyncNode* pNode) { taosThreadMutexLock(&pBuf->mutex); + syncLogBufferValidate(pBuf); SyncIndex lastVer = pNode->pLogStore->syncLogLastIndex(pNode->pLogStore); ASSERT(lastVer == pBuf->matchIndex); SyncIndex index = pBuf->endIndex - 1; @@ -1086,8 +1102,9 @@ int32_t syncLogBufferReset(SSyncLogBuffer* pBuf, SSyncNode* pNode) { // reset repl mgr for (int i = 0; i < pNode->replicaNum; i++) { SSyncLogReplMgr* pMgr = pNode->logReplMgrs[i]; - syncLogReplMgrReset(pMgr); + syncLogReplReset(pMgr); } + syncLogBufferValidate(pBuf); taosThreadMutexUnlock(&pBuf->mutex); return 0; } @@ -1109,8 +1126,8 @@ SSyncRaftEntry* syncLogBufferGetOneEntry(SSyncLogBuffer* pBuf, SSyncNode* pNode, return pEntry; } -int32_t syncLogReplMgrReplicateOneTo(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index, SyncTerm* pTerm, - SRaftId* pDestId, bool* pBarrier) { +int32_t syncLogReplSendTo(SSyncLogReplMgr* pMgr, SSyncNode* pNode, SyncIndex index, SyncTerm* pTerm, SRaftId* pDestId, + bool* pBarrier) { SSyncRaftEntry* pEntry = NULL; SRpcMsg msgOut = {0}; bool inBuf = false; @@ -1123,16 +1140,16 @@ int32_t syncLogReplMgrReplicateOneTo(SSyncLogReplMgr* pMgr, SSyncNode* pNode, Sy if (terrno == TSDB_CODE_WAL_LOG_NOT_EXIST) { SSyncLogReplMgr* pMgr = syncNodeGetLogReplMgr(pNode, pDestId); if (pMgr) { - sInfo("vgId:%d, reset sync log repl mgr of peer:%" PRIx64 " since %s. index:%" PRId64, pNode->vgId, - pDestId->addr, terrstr(), index); - (void)syncLogReplMgrReset(pMgr); + sInfo("vgId:%d, reset sync log repl of peer:%" PRIx64 " since %s. index:%" PRId64, pNode->vgId, pDestId->addr, + terrstr(), index); + (void)syncLogReplReset(pMgr); } } goto _err; } - *pBarrier = syncLogIsReplicationBarrier(pEntry); + *pBarrier = syncLogReplBarrier(pEntry); - prevLogTerm = syncLogReplMgrGetPrevLogTerm(pMgr, pNode, index); + prevLogTerm = syncLogReplGetPrevLogTerm(pMgr, pNode, index); if (prevLogTerm < 0) { sError("vgId:%d, failed to get prev log term since %s. index:%" PRId64 "", pNode->vgId, terrstr(), index); goto _err; diff --git a/source/libs/sync/src/syncRaftCfg.c b/source/libs/sync/src/syncRaftCfg.c index 806949c81e2ad8598a7d2901769c53a0bfa2daa8..f780e255ce77eb485ffcd1de8d078718dc1973a5 100644 --- a/source/libs/sync/src/syncRaftCfg.c +++ b/source/libs/sync/src/syncRaftCfg.c @@ -224,7 +224,7 @@ _OVER: int32_t syncAddCfgIndex(SSyncNode *pNode, SyncIndex cfgIndex) { SRaftCfg *pCfg = &pNode->raftCfg; - if (pCfg->configIndexCount <= MAX_CONFIG_INDEX_COUNT) { + if (pCfg->configIndexCount < MAX_CONFIG_INDEX_COUNT) { return -1; } diff --git a/source/libs/sync/src/syncRaftEntry.c b/source/libs/sync/src/syncRaftEntry.c index 623f1b77a428806a859c4ba5ffc42404ad9d0c84..8f42780eb9247489b100bb9f167de33613b1629c 100644 --- a/source/libs/sync/src/syncRaftEntry.c +++ b/source/libs/sync/src/syncRaftEntry.c @@ -64,10 +64,13 @@ SSyncRaftEntry* syncEntryBuildFromRpcMsg(const SRpcMsg* pMsg, SyncTerm term, Syn } SSyncRaftEntry* syncEntryBuildFromAppendEntries(const SyncAppendEntries* pMsg) { - SSyncRaftEntry* pEntry = syncEntryBuild((int32_t)(pMsg->dataLen)); - if (pEntry == NULL) return NULL; - + SSyncRaftEntry* pEntry = taosMemoryMalloc(pMsg->dataLen); + if (pEntry == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return NULL; + } memcpy(pEntry, pMsg->data, pMsg->dataLen); + ASSERT(pEntry->bytes == pMsg->dataLen); return pEntry; } @@ -102,344 +105,3 @@ void syncEntry2OriginalRpc(const SSyncRaftEntry* pEntry, SRpcMsg* pRpcMsg) { pRpcMsg->pCont = rpcMallocCont(pRpcMsg->contLen); memcpy(pRpcMsg->pCont, pEntry->data, pRpcMsg->contLen); } - -SRaftEntryHashCache* raftCacheCreate(SSyncNode* pSyncNode, int32_t maxCount) { - SRaftEntryHashCache* pCache = taosMemoryMalloc(sizeof(SRaftEntryHashCache)); - if (pCache == NULL) { - sError("vgId:%d, raft cache create error", pSyncNode->vgId); - return NULL; - } - - pCache->pEntryHash = - taosHashInit(sizeof(SyncIndex), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); - if (pCache->pEntryHash == NULL) { - sError("vgId:%d, raft cache create hash error", pSyncNode->vgId); - return NULL; - } - - taosThreadMutexInit(&(pCache->mutex), NULL); - pCache->maxCount = maxCount; - pCache->currentCount = 0; - pCache->pSyncNode = pSyncNode; - - return pCache; -} - -void raftCacheDestroy(SRaftEntryHashCache* pCache) { - if (pCache != NULL) { - taosThreadMutexLock(&pCache->mutex); - taosHashCleanup(pCache->pEntryHash); - taosThreadMutexUnlock(&pCache->mutex); - taosThreadMutexDestroy(&(pCache->mutex)); - taosMemoryFree(pCache); - } -} - -// success, return 1 -// max count, return 0 -// error, return -1 -int32_t raftCachePutEntry(struct SRaftEntryHashCache* pCache, SSyncRaftEntry* pEntry) { - taosThreadMutexLock(&pCache->mutex); - - if (pCache->currentCount >= pCache->maxCount) { - taosThreadMutexUnlock(&pCache->mutex); - return 0; - } - - taosHashPut(pCache->pEntryHash, &(pEntry->index), sizeof(pEntry->index), pEntry, pEntry->bytes); - ++(pCache->currentCount); - - sNTrace(pCache->pSyncNode, "raft cache add, type:%s,%d, type2:%s,%d, index:%" PRId64 ", bytes:%d", - TMSG_INFO(pEntry->msgType), pEntry->msgType, TMSG_INFO(pEntry->originalRpcType), pEntry->originalRpcType, - pEntry->index, pEntry->bytes); - taosThreadMutexUnlock(&pCache->mutex); - return 1; -} - -// success, return 0 -// error, return -1 -// not exist, return -1, terrno = TSDB_CODE_WAL_LOG_NOT_EXIST -int32_t raftCacheGetEntry(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) { - if (ppEntry == NULL) { - return -1; - } - *ppEntry = NULL; - - taosThreadMutexLock(&pCache->mutex); - void* pTmp = taosHashGet(pCache->pEntryHash, &index, sizeof(index)); - if (pTmp != NULL) { - SSyncRaftEntry* pEntry = pTmp; - *ppEntry = taosMemoryMalloc(pEntry->bytes); - memcpy(*ppEntry, pTmp, pEntry->bytes); - - sNTrace(pCache->pSyncNode, "raft cache get, type:%s,%d, type2:%s,%d, index:%" PRId64, - TMSG_INFO((*ppEntry)->msgType), (*ppEntry)->msgType, TMSG_INFO((*ppEntry)->originalRpcType), - (*ppEntry)->originalRpcType, (*ppEntry)->index); - taosThreadMutexUnlock(&pCache->mutex); - return 0; - } - - taosThreadMutexUnlock(&pCache->mutex); - terrno = TSDB_CODE_WAL_LOG_NOT_EXIST; - return -1; -} - -// success, return 0 -// error, return -1 -// not exist, return -1, terrno = TSDB_CODE_WAL_LOG_NOT_EXIST -int32_t raftCacheGetEntryP(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) { - if (ppEntry == NULL) { - return -1; - } - *ppEntry = NULL; - - taosThreadMutexLock(&pCache->mutex); - void* pTmp = taosHashGet(pCache->pEntryHash, &index, sizeof(index)); - if (pTmp != NULL) { - SSyncRaftEntry* pEntry = pTmp; - *ppEntry = pEntry; - - sNTrace(pCache->pSyncNode, "raft cache get, type:%s,%d, type2:%s,%d, index:%" PRId64, - TMSG_INFO((*ppEntry)->msgType), (*ppEntry)->msgType, TMSG_INFO((*ppEntry)->originalRpcType), - (*ppEntry)->originalRpcType, (*ppEntry)->index); - taosThreadMutexUnlock(&pCache->mutex); - return 0; - } - - taosThreadMutexUnlock(&pCache->mutex); - terrno = TSDB_CODE_WAL_LOG_NOT_EXIST; - return -1; -} - -int32_t raftCacheDelEntry(struct SRaftEntryHashCache* pCache, SyncIndex index) { - taosThreadMutexLock(&pCache->mutex); - taosHashRemove(pCache->pEntryHash, &index, sizeof(index)); - --(pCache->currentCount); - taosThreadMutexUnlock(&pCache->mutex); - return 0; -} - -int32_t raftCacheGetAndDel(struct SRaftEntryHashCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) { - if (ppEntry == NULL) { - return -1; - } - *ppEntry = NULL; - - taosThreadMutexLock(&pCache->mutex); - void* pTmp = taosHashGet(pCache->pEntryHash, &index, sizeof(index)); - if (pTmp != NULL) { - SSyncRaftEntry* pEntry = pTmp; - *ppEntry = taosMemoryMalloc(pEntry->bytes); - memcpy(*ppEntry, pTmp, pEntry->bytes); - - sNTrace(pCache->pSyncNode, "raft cache get-and-del, type:%s,%d, type2:%s,%d, index:%" PRId64, - TMSG_INFO((*ppEntry)->msgType), (*ppEntry)->msgType, TMSG_INFO((*ppEntry)->originalRpcType), - (*ppEntry)->originalRpcType, (*ppEntry)->index); - - taosHashRemove(pCache->pEntryHash, &index, sizeof(index)); - --(pCache->currentCount); - - taosThreadMutexUnlock(&pCache->mutex); - return 0; - } - - taosThreadMutexUnlock(&pCache->mutex); - terrno = TSDB_CODE_WAL_LOG_NOT_EXIST; - return -1; -} - -int32_t raftCacheClear(struct SRaftEntryHashCache* pCache) { - taosThreadMutexLock(&pCache->mutex); - taosHashClear(pCache->pEntryHash); - pCache->currentCount = 0; - taosThreadMutexUnlock(&pCache->mutex); - return 0; -} - -static char* keyFn(const void* pData) { - SSyncRaftEntry* pEntry = (SSyncRaftEntry*)pData; - return (char*)(&(pEntry->index)); -} - -static int cmpFn(const void* p1, const void* p2) { return memcmp(p1, p2, sizeof(SyncIndex)); } - -static void freeRaftEntry(void* param) { - SSyncRaftEntry* pEntry = (SSyncRaftEntry*)param; - syncEntryDestroy(pEntry); -} - -SRaftEntryCache* raftEntryCacheCreate(SSyncNode* pSyncNode, int32_t maxCount) { - SRaftEntryCache* pCache = taosMemoryMalloc(sizeof(SRaftEntryCache)); - if (pCache == NULL) { - sError("vgId:%d, raft cache create error", pSyncNode->vgId); - return NULL; - } - - pCache->pSkipList = - tSkipListCreate(MAX_SKIP_LIST_LEVEL, TSDB_DATA_TYPE_BINARY, sizeof(SyncIndex), cmpFn, SL_ALLOW_DUP_KEY, keyFn); - if (pCache->pSkipList == NULL) { - sError("vgId:%d, raft cache create hash error", pSyncNode->vgId); - return NULL; - } - - taosThreadMutexInit(&(pCache->mutex), NULL); - pCache->refMgr = taosOpenRef(10, freeRaftEntry); - pCache->maxCount = maxCount; - pCache->currentCount = 0; - pCache->pSyncNode = pSyncNode; - - return pCache; -} - -void raftEntryCacheDestroy(SRaftEntryCache* pCache) { - if (pCache != NULL) { - taosThreadMutexLock(&pCache->mutex); - tSkipListDestroy(pCache->pSkipList); - if (pCache->refMgr != -1) { - taosCloseRef(pCache->refMgr); - pCache->refMgr = -1; - } - taosThreadMutexUnlock(&pCache->mutex); - taosThreadMutexDestroy(&(pCache->mutex)); - taosMemoryFree(pCache); - } -} - -// success, return 1 -// max count, return 0 -// error, return -1 -int32_t raftEntryCachePutEntry(struct SRaftEntryCache* pCache, SSyncRaftEntry* pEntry) { - taosThreadMutexLock(&pCache->mutex); - - if (pCache->currentCount >= pCache->maxCount) { - taosThreadMutexUnlock(&pCache->mutex); - return 0; - } - - SSkipListNode* pSkipListNode = tSkipListPut(pCache->pSkipList, pEntry); - ASSERT(pSkipListNode != NULL); - ++(pCache->currentCount); - - pEntry->rid = taosAddRef(pCache->refMgr, pEntry); - ASSERT(pEntry->rid >= 0); - - sNTrace(pCache->pSyncNode, "raft cache add, type:%s,%d, type2:%s,%d, index:%" PRId64 ", bytes:%d", - TMSG_INFO(pEntry->msgType), pEntry->msgType, TMSG_INFO(pEntry->originalRpcType), pEntry->originalRpcType, - pEntry->index, pEntry->bytes); - taosThreadMutexUnlock(&pCache->mutex); - return 1; -} - -// find one, return 1 -// not found, return 0 -// error, return -1 -int32_t raftEntryCacheGetEntry(struct SRaftEntryCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) { - ASSERT(ppEntry != NULL); - SSyncRaftEntry* pEntry = NULL; - int32_t code = raftEntryCacheGetEntryP(pCache, index, &pEntry); - if (code == 1) { - int32_t bytes = (int32_t)pEntry->bytes; - *ppEntry = taosMemoryMalloc((int64_t)bytes); - memcpy(*ppEntry, pEntry, pEntry->bytes); - (*ppEntry)->rid = -1; - } else { - *ppEntry = NULL; - } - return code; -} - -// find one, return 1 -// not found, return 0 -// error, return -1 -int32_t raftEntryCacheGetEntryP(struct SRaftEntryCache* pCache, SyncIndex index, SSyncRaftEntry** ppEntry) { - taosThreadMutexLock(&pCache->mutex); - - SyncIndex index2 = index; - int32_t code = 0; - - SArray* entryPArray = tSkipListGet(pCache->pSkipList, (char*)(&index2)); - int32_t arraySize = taosArrayGetSize(entryPArray); - if (arraySize == 1) { - SSkipListNode** ppNode = (SSkipListNode**)taosArrayGet(entryPArray, 0); - ASSERT(*ppNode != NULL); - *ppEntry = (SSyncRaftEntry*)SL_GET_NODE_DATA(*ppNode); - taosAcquireRef(pCache->refMgr, (*ppEntry)->rid); - code = 1; - - } else if (arraySize == 0) { - code = 0; - - } else { - ASSERT(0); - - code = -1; - } - taosArrayDestroy(entryPArray); - - taosThreadMutexUnlock(&pCache->mutex); - return code; -} - -// count = -1, clear all -// count >= 0, clear count -// return -1, error -// return delete count -int32_t raftEntryCacheClear(struct SRaftEntryCache* pCache, int32_t count) { - taosThreadMutexLock(&pCache->mutex); - int32_t returnCnt = 0; - - if (count == -1) { - // clear all - SSkipListIterator* pIter = tSkipListCreateIter(pCache->pSkipList); - while (tSkipListIterNext(pIter)) { - SSkipListNode* pNode = tSkipListIterGet(pIter); - ASSERT(pNode != NULL); - SSyncRaftEntry* pEntry = (SSyncRaftEntry*)SL_GET_NODE_DATA(pNode); - syncEntryDestroy(pEntry); - ++returnCnt; - } - tSkipListDestroyIter(pIter); - - tSkipListDestroy(pCache->pSkipList); - pCache->pSkipList = - tSkipListCreate(MAX_SKIP_LIST_LEVEL, TSDB_DATA_TYPE_BINARY, sizeof(SyncIndex), cmpFn, SL_ALLOW_DUP_KEY, keyFn); - ASSERT(pCache->pSkipList != NULL); - - } else { - // clear count - int i = 0; - SSkipListIterator* pIter = tSkipListCreateIter(pCache->pSkipList); - SArray* delNodeArray = taosArrayInit(0, sizeof(SSkipListNode*)); - - // free entry - while (tSkipListIterNext(pIter)) { - SSkipListNode* pNode = tSkipListIterGet(pIter); - ASSERT(pNode != NULL); - if (i++ >= count) { - break; - } - - // sDebug("push pNode:%p", pNode); - taosArrayPush(delNodeArray, &pNode); - ++returnCnt; - SSyncRaftEntry* pEntry = (SSyncRaftEntry*)SL_GET_NODE_DATA(pNode); - - // syncEntryDestroy(pEntry); - taosRemoveRef(pCache->refMgr, pEntry->rid); - } - tSkipListDestroyIter(pIter); - - // delete skiplist node - int32_t arraySize = taosArrayGetSize(delNodeArray); - for (int32_t i = 0; i < arraySize; ++i) { - SSkipListNode** ppNode = taosArrayGet(delNodeArray, i); - // sDebug("get pNode:%p", *ppNode); - tSkipListRemoveNode(pCache->pSkipList, *ppNode); - } - taosArrayDestroy(delNodeArray); - } - - pCache->currentCount -= returnCnt; - taosThreadMutexUnlock(&pCache->mutex); - return returnCnt; -} diff --git a/source/libs/sync/src/syncRaftStore.c b/source/libs/sync/src/syncRaftStore.c index 197d1463fd80791403425adaed75ab31d380e4bb..bd15567c874d6d2051210ddf5b4c69a65b75bf20 100644 --- a/source/libs/sync/src/syncRaftStore.c +++ b/source/libs/sync/src/syncRaftStore.c @@ -18,6 +18,9 @@ #include "syncUtil.h" #include "tjson.h" +int32_t raftStoreReadFile(SSyncNode *pNode); +int32_t raftStoreWriteFile(SSyncNode *pNode); + static int32_t raftStoreDecode(const SJson *pJson, SRaftStore *pStore) { int32_t code = 0; @@ -136,7 +139,7 @@ int32_t raftStoreWriteFile(SSyncNode *pNode) { if (taosRenameFile(file, realfile) != 0) goto _OVER; code = 0; - sInfo("vgId:%d, succeed to write raft store file:%s, len:%d", pNode->vgId, realfile, len); + sInfo("vgId:%d, succeed to write raft store file:%s, term:%" PRId64, pNode->vgId, realfile, pStore->currentTerm); _OVER: if (pJson != NULL) tjsonDelete(pJson); @@ -150,27 +153,53 @@ _OVER: return code; } +int32_t raftStoreOpen(SSyncNode *pNode) { + taosThreadMutexInit(&pNode->raftStore.mutex, NULL); + return raftStoreReadFile(pNode); +} + +void raftStoreClose(SSyncNode *pNode) { taosThreadMutexDestroy(&pNode->raftStore.mutex); } + bool raftStoreHasVoted(SSyncNode *pNode) { + taosThreadMutexLock(&pNode->raftStore.mutex); bool b = syncUtilEmptyId(&pNode->raftStore.voteFor); + taosThreadMutexUnlock(&pNode->raftStore.mutex); return (!b); } void raftStoreVote(SSyncNode *pNode, SRaftId *pRaftId) { + taosThreadMutexLock(&pNode->raftStore.mutex); pNode->raftStore.voteFor = *pRaftId; (void)raftStoreWriteFile(pNode); + taosThreadMutexUnlock(&pNode->raftStore.mutex); } void raftStoreClearVote(SSyncNode *pNode) { + taosThreadMutexLock(&pNode->raftStore.mutex); pNode->raftStore.voteFor = EMPTY_RAFT_ID; (void)raftStoreWriteFile(pNode); + taosThreadMutexUnlock(&pNode->raftStore.mutex); } void raftStoreNextTerm(SSyncNode *pNode) { + taosThreadMutexLock(&pNode->raftStore.mutex); pNode->raftStore.currentTerm++; (void)raftStoreWriteFile(pNode); + taosThreadMutexUnlock(&pNode->raftStore.mutex); } void raftStoreSetTerm(SSyncNode *pNode, SyncTerm term) { - pNode->raftStore.currentTerm = term; - (void)raftStoreWriteFile(pNode); + taosThreadMutexLock(&pNode->raftStore.mutex); + if (pNode->raftStore.currentTerm < term) { + pNode->raftStore.currentTerm = term; + (void)raftStoreWriteFile(pNode); + } + taosThreadMutexUnlock(&pNode->raftStore.mutex); +} + +SyncTerm raftStoreGetTerm(SSyncNode *pNode) { + taosThreadMutexLock(&pNode->raftStore.mutex); + SyncTerm term = pNode->raftStore.currentTerm; + taosThreadMutexUnlock(&pNode->raftStore.mutex); + return term; } diff --git a/source/libs/sync/src/syncReplication.c b/source/libs/sync/src/syncReplication.c index 3df203221b88bbd0b9d804613e2ea50e881be149..2776225a39ddd1f17de7e3dc8358f404c7914326 100644 --- a/source/libs/sync/src/syncReplication.c +++ b/source/libs/sync/src/syncReplication.c @@ -46,7 +46,14 @@ // mdest |-> j]) // /\ UNCHANGED <> -int32_t syncNodeMaybeSendAppendEntries(SSyncNode* pSyncNode, const SRaftId* destRaftId, SRpcMsg* pRpcMsg); +int32_t syncNodeReplicateReset(SSyncNode* pNode, SRaftId* pDestId) { + SSyncLogBuffer* pBuf = pNode->pLogBuf; + taosThreadMutexLock(&pBuf->mutex); + SSyncLogReplMgr* pMgr = syncNodeGetLogReplMgr(pNode, pDestId); + syncLogReplReset(pMgr); + taosThreadMutexUnlock(&pBuf->mutex); + return 0; +} int32_t syncNodeReplicate(SSyncNode* pNode) { SSyncLogBuffer* pBuf = pNode->pLogBuf; @@ -65,7 +72,7 @@ int32_t syncNodeReplicateWithoutLock(SSyncNode* pNode) { continue; } SSyncLogReplMgr* pMgr = pNode->logReplMgrs[i]; - (void)syncLogReplMgrReplicateOnce(pMgr, pNode); + (void)syncLogReplDoOnce(pMgr, pNode); } return 0; } @@ -77,20 +84,6 @@ int32_t syncNodeSendAppendEntries(SSyncNode* pSyncNode, const SRaftId* destRaftI return 0; } -int32_t syncNodeMaybeSendAppendEntries(SSyncNode* pSyncNode, const SRaftId* destRaftId, SRpcMsg* pRpcMsg) { - int32_t ret = 0; - SyncAppendEntries* pMsg = pRpcMsg->pCont; - - if (syncNodeNeedSendAppendEntries(pSyncNode, destRaftId, pMsg)) { - ret = syncNodeSendAppendEntries(pSyncNode, destRaftId, pRpcMsg); - } else { - sNTrace(pSyncNode, "do not repcate to dnode:%d for index:%" PRId64, DID(destRaftId), pMsg->prevLogIndex + 1); - rpcFreeCont(pRpcMsg->pCont); - } - - return ret; -} - int32_t syncNodeSendHeartbeat(SSyncNode* pSyncNode, const SRaftId* destId, SRpcMsg* pMsg) { return syncNodeSendMsgById(destId, pSyncNode, pMsg); } @@ -107,7 +100,7 @@ int32_t syncNodeHeartbeatPeers(SSyncNode* pSyncNode) { SyncHeartbeat* pSyncMsg = rpcMsg.pCont; pSyncMsg->srcId = pSyncNode->myRaftId; pSyncMsg->destId = pSyncNode->peersId[i]; - pSyncMsg->term = pSyncNode->raftStore.currentTerm; + pSyncMsg->term = raftStoreGetTerm(pSyncNode); pSyncMsg->commitIndex = pSyncNode->commitIndex; pSyncMsg->minMatchIndex = syncMinMatchIndex(pSyncNode); pSyncMsg->privateTerm = 0; diff --git a/source/libs/sync/src/syncRequestVote.c b/source/libs/sync/src/syncRequestVote.c index 069ea2ea88b85c91846b975513dcd681944c7ace..77e5498127ecea7bcead68d83876b5334f551567 100644 --- a/source/libs/sync/src/syncRequestVote.c +++ b/source/libs/sync/src/syncRequestVote.c @@ -20,6 +20,7 @@ #include "syncRaftStore.h" #include "syncUtil.h" #include "syncVoteMgr.h" +#include "syncUtil.h" // TLA+ Spec // HandleRequestVoteRequest(i, j, m) == @@ -89,6 +90,7 @@ static bool syncNodeOnRequestVoteLogOK(SSyncNode* ths, SyncRequestVote* pMsg) { int32_t syncNodeOnRequestVote(SSyncNode* ths, const SRpcMsg* pRpcMsg) { int32_t ret = 0; SyncRequestVote* pMsg = pRpcMsg->pCont; + bool resetElect = false; // if already drop replica, do not process if (!syncNodeInRaftGroup(ths, &pMsg->srcId)) { @@ -97,15 +99,14 @@ int32_t syncNodeOnRequestVote(SSyncNode* ths, const SRpcMsg* pRpcMsg) { } bool logOK = syncNodeOnRequestVoteLogOK(ths, pMsg); - // maybe update term - if (pMsg->term > ths->raftStore.currentTerm) { + if (pMsg->term > raftStoreGetTerm(ths)) { syncNodeStepDown(ths, pMsg->term); - // syncNodeUpdateTerm(ths, pMsg->term); } - ASSERT(pMsg->term <= ths->raftStore.currentTerm); + SyncTerm currentTerm = raftStoreGetTerm(ths); + ASSERT(pMsg->term <= currentTerm); - bool grant = (pMsg->term == ths->raftStore.currentTerm) && logOK && + bool grant = (pMsg->term == currentTerm) && logOK && ((!raftStoreHasVoted(ths)) || (syncUtilSameId(&ths->raftStore.voteFor, &pMsg->srcId))); if (grant) { // maybe has already voted for pMsg->srcId @@ -113,10 +114,10 @@ int32_t syncNodeOnRequestVote(SSyncNode* ths, const SRpcMsg* pRpcMsg) { raftStoreVote(ths, &(pMsg->srcId)); // candidate ? - syncNodeStepDown(ths, ths->raftStore.currentTerm); + syncNodeStepDown(ths, currentTerm); // forbid elect for this round - syncNodeResetElectTimer(ths); + resetElect = true; } // send msg @@ -127,12 +128,15 @@ int32_t syncNodeOnRequestVote(SSyncNode* ths, const SRpcMsg* pRpcMsg) { SyncRequestVoteReply* pReply = rpcMsg.pCont; pReply->srcId = ths->myRaftId; pReply->destId = pMsg->srcId; - pReply->term = ths->raftStore.currentTerm; + pReply->term = currentTerm; pReply->voteGranted = grant; + ASSERT(!grant || pMsg->term == pReply->term); // trace log syncLogRecvRequestVote(ths, pMsg, pReply->voteGranted, ""); syncLogSendRequestVoteReply(ths, pReply, ""); syncNodeSendMsgById(&pReply->destId, ths, &rpcMsg); + + if (resetElect) syncNodeResetElectTimer(ths); return 0; } diff --git a/source/libs/sync/src/syncRequestVoteReply.c b/source/libs/sync/src/syncRequestVoteReply.c index a0d6cbf597bb95c9d0e73b9cb9cde9f7c94d4a98..25c9f813a6fe6dc173569dfed194085a903fabf4 100644 --- a/source/libs/sync/src/syncRequestVoteReply.c +++ b/source/libs/sync/src/syncRequestVoteReply.c @@ -47,27 +47,21 @@ int32_t syncNodeOnRequestVoteReply(SSyncNode* ths, const SRpcMsg* pRpcMsg) { syncLogRecvRequestVoteReply(ths, pMsg, "not in my config"); return -1; } - + SyncTerm currentTerm = raftStoreGetTerm(ths); // drop stale response - if (pMsg->term < ths->raftStore.currentTerm) { + if (pMsg->term < currentTerm) { syncLogRecvRequestVoteReply(ths, pMsg, "drop stale response"); return -1; } - // ASSERT(!(pMsg->term > ths->raftStore.currentTerm)); - // no need this code, because if I receive reply.term, then I must have sent for that term. - // if (pMsg->term > ths->raftStore.currentTerm) { - // syncNodeUpdateTerm(ths, pMsg->term); - // } - - if (pMsg->term > ths->raftStore.currentTerm) { + if (pMsg->term > currentTerm) { syncLogRecvRequestVoteReply(ths, pMsg, "error term"); syncNodeStepDown(ths, pMsg->term); return -1; } syncLogRecvRequestVoteReply(ths, pMsg, ""); - ASSERT(pMsg->term == ths->raftStore.currentTerm); + ASSERT(pMsg->term == currentTerm); // This tallies votes even when the current state is not Candidate, // but they won't be looked at, so it doesn't matter. diff --git a/source/libs/sync/src/syncRespMgr.c b/source/libs/sync/src/syncRespMgr.c index 9373eccaef6b27fd451fa77b360972e47cbea3d7..3506d477d3692169e9cbabd1b7069d1fb4504746 100644 --- a/source/libs/sync/src/syncRespMgr.c +++ b/source/libs/sync/src/syncRespMgr.c @@ -143,7 +143,7 @@ static void syncRespCleanByTTL(SSyncRespMgr *pObj, int64_t ttl, bool rsp) { .state = pNode->state, .seqNum = *pSeqNum, .term = SYNC_TERM_INVALID, - .currentTerm = pNode->raftStore.currentTerm, + .currentTerm = SYNC_TERM_INVALID, .flag = 0, }; @@ -171,6 +171,8 @@ static void syncRespCleanByTTL(SSyncRespMgr *pObj, int64_t ttl, bool rsp) { } void syncRespCleanRsp(SSyncRespMgr *pObj) { + if (pObj == NULL) return; + SSyncNode *pNode = pObj->data; sTrace("vgId:%d, clean all resp", pNode->vgId); diff --git a/source/libs/sync/src/syncSnapshot.c b/source/libs/sync/src/syncSnapshot.c index 18f263cc95f7bb9f611cb0a81343b60e7e36d95b..a9d0ddad17d99f929c51ef60e313d2df463377e3 100644 --- a/source/libs/sync/src/syncSnapshot.c +++ b/source/libs/sync/src/syncSnapshot.c @@ -43,7 +43,7 @@ SSyncSnapshotSender *snapshotSenderCreate(SSyncNode *pSyncNode, int32_t replicaI pSender->sendingMS = SYNC_SNAPSHOT_RETRY_MS; pSender->pSyncNode = pSyncNode; pSender->replicaIndex = replicaIndex; - pSender->term = pSyncNode->raftStore.currentTerm; + pSender->term = raftStoreGetTerm(pSyncNode); pSender->startTime = 0; pSender->endTime = 0; pSender->pSyncNode->pFsm->FpGetSnapshotInfo(pSender->pSyncNode->pFsm, &pSender->snapshot); @@ -90,7 +90,7 @@ int32_t snapshotSenderStart(SSyncSnapshotSender *pSender) { memset(&pSender->lastConfig, 0, sizeof(pSender->lastConfig)); pSender->sendingMS = 0; - pSender->term = pSender->pSyncNode->raftStore.currentTerm; + pSender->term = raftStoreGetTerm(pSender->pSyncNode); pSender->startTime = taosGetTimestampMs(); pSender->lastSendTime = pSender->startTime; pSender->finish = false; @@ -105,7 +105,7 @@ int32_t snapshotSenderStart(SSyncSnapshotSender *pSender) { SyncSnapshotSend *pMsg = rpcMsg.pCont; pMsg->srcId = pSender->pSyncNode->myRaftId; pMsg->destId = pSender->pSyncNode->replicasId[pSender->replicaIndex]; - pMsg->term = pSender->pSyncNode->raftStore.currentTerm; + pMsg->term = raftStoreGetTerm(pSender->pSyncNode); pMsg->beginIndex = pSender->snapshotParam.start; pMsg->lastIndex = pSender->snapshot.lastApplyIndex; pMsg->lastTerm = pSender->snapshot.lastApplyTerm; @@ -168,24 +168,26 @@ static int32_t snapshotSend(SSyncSnapshotSender *pSender) { if (pSender->blockLen > 0) { // has read data - sSDebug(pSender, "snapshot sender continue to read, blockLen:%d seq:%d", pSender->blockLen, pSender->seq); + sSDebug(pSender, "vgId:%d, snapshot sender continue to read, blockLen:%d seq:%d", pSender->pSyncNode->vgId, + pSender->blockLen, pSender->seq); } else { // read finish, update seq to end pSender->seq = SYNC_SNAPSHOT_SEQ_END; - sSInfo(pSender, "snapshot sender read to the end, blockLen:%d seq:%d", pSender->blockLen, pSender->seq); + sSInfo(pSender, "vgId:%d, snapshot sender read to the end, blockLen:%d seq:%d", pSender->pSyncNode->vgId, + pSender->blockLen, pSender->seq); } // build msg SRpcMsg rpcMsg = {0}; if (syncBuildSnapshotSend(&rpcMsg, pSender->blockLen, pSender->pSyncNode->vgId) != 0) { - sSError(pSender, "snapshot sender build msg failed since %s", pSender->pSyncNode->vgId, terrstr()); + sSError(pSender, "vgId:%d, snapshot sender build msg failed since %s", pSender->pSyncNode->vgId, terrstr()); return -1; } SyncSnapshotSend *pMsg = rpcMsg.pCont; pMsg->srcId = pSender->pSyncNode->myRaftId; pMsg->destId = pSender->pSyncNode->replicasId[pSender->replicaIndex]; - pMsg->term = pSender->pSyncNode->raftStore.currentTerm; + pMsg->term = raftStoreGetTerm(pSender->pSyncNode); pMsg->beginIndex = pSender->snapshotParam.start; pMsg->lastIndex = pSender->snapshot.lastApplyIndex; pMsg->lastTerm = pSender->snapshot.lastApplyTerm; @@ -226,7 +228,7 @@ int32_t snapshotReSend(SSyncSnapshotSender *pSender) { SyncSnapshotSend *pMsg = rpcMsg.pCont; pMsg->srcId = pSender->pSyncNode->myRaftId; pMsg->destId = pSender->pSyncNode->replicasId[pSender->replicaIndex]; - pMsg->term = pSender->pSyncNode->raftStore.currentTerm; + pMsg->term = raftStoreGetTerm(pSender->pSyncNode); pMsg->beginIndex = pSender->snapshotParam.start; pMsg->lastIndex = pSender->snapshot.lastApplyIndex; pMsg->lastTerm = pSender->snapshot.lastApplyTerm; @@ -314,7 +316,7 @@ SSyncSnapshotReceiver *snapshotReceiverCreate(SSyncNode *pSyncNode, SRaftId from pReceiver->pWriter = NULL; pReceiver->pSyncNode = pSyncNode; pReceiver->fromId = fromId; - pReceiver->term = pSyncNode->raftStore.currentTerm; + pReceiver->term = raftStoreGetTerm(pSyncNode); pReceiver->snapshot.data = NULL; pReceiver->snapshot.lastApplyIndex = SYNC_INDEX_INVALID; pReceiver->snapshot.lastApplyTerm = 0; @@ -340,11 +342,13 @@ void snapshotReceiverDestroy(SSyncSnapshotReceiver *pReceiver) { taosMemoryFree(pReceiver); } -bool snapshotReceiverIsStart(SSyncSnapshotReceiver *pReceiver) { return pReceiver->start; } +bool snapshotReceiverIsStart(SSyncSnapshotReceiver *pReceiver) { + return (pReceiver != NULL ? pReceiver->start : false); +} static int32_t snapshotReceiverStartWriter(SSyncSnapshotReceiver *pReceiver, SyncSnapshotSend *pBeginMsg) { if (pReceiver->pWriter != NULL) { - sRError(pReceiver, "vgId:%d, snapshot receiver writer is not null"); + sRError(pReceiver, "vgId:%d, snapshot receiver writer is not null", pReceiver->pSyncNode->vgId); terrno = TSDB_CODE_SYN_INTERNAL_ERROR; return -1; } @@ -380,7 +384,7 @@ void snapshotReceiverStart(SSyncSnapshotReceiver *pReceiver, SyncSnapshotSend *p pReceiver->start = true; pReceiver->ack = SYNC_SNAPSHOT_SEQ_PREP_SNAPSHOT; - pReceiver->term = pReceiver->pSyncNode->raftStore.currentTerm; + pReceiver->term = raftStoreGetTerm(pReceiver->pSyncNode); pReceiver->fromId = pPreMsg->srcId; pReceiver->startTime = pPreMsg->startTime; @@ -437,9 +441,8 @@ static int32_t snapshotReceiverFinish(SSyncSnapshotReceiver *pReceiver, SyncSnap } // maybe update term - if (pReceiver->snapshot.lastApplyTerm > pReceiver->pSyncNode->raftStore.currentTerm) { - pReceiver->pSyncNode->raftStore.currentTerm = pReceiver->snapshot.lastApplyTerm; - (void)raftStoreWriteFile(pReceiver->pSyncNode); + if (pReceiver->snapshot.lastApplyTerm > raftStoreGetTerm(pReceiver->pSyncNode)) { + raftStoreSetTerm(pReceiver->pSyncNode, pReceiver->snapshot.lastApplyTerm); } // stop writer, apply data @@ -584,7 +587,7 @@ _SEND_REPLY: SyncSnapshotRsp *pRspMsg = rpcMsg.pCont; pRspMsg->srcId = pSyncNode->myRaftId; pRspMsg->destId = pMsg->srcId; - pRspMsg->term = pSyncNode->raftStore.currentTerm; + pRspMsg->term = raftStoreGetTerm(pSyncNode); pRspMsg->lastIndex = pMsg->lastIndex; pRspMsg->lastTerm = pMsg->lastTerm; pRspMsg->startTime = pReceiver->startTime; @@ -640,7 +643,7 @@ _SEND_REPLY: SyncSnapshotRsp *pRspMsg = rpcMsg.pCont; pRspMsg->srcId = pSyncNode->myRaftId; pRspMsg->destId = pMsg->srcId; - pRspMsg->term = pSyncNode->raftStore.currentTerm; + pRspMsg->term = raftStoreGetTerm(pSyncNode); pRspMsg->lastIndex = pMsg->lastIndex; pRspMsg->lastTerm = pMsg->lastTerm; pRspMsg->startTime = pReceiver->startTime; @@ -690,7 +693,7 @@ static int32_t syncNodeOnSnapshotReceive(SSyncNode *pSyncNode, SyncSnapshotSend SyncSnapshotRsp *pRspMsg = rpcMsg.pCont; pRspMsg->srcId = pSyncNode->myRaftId; pRspMsg->destId = pMsg->srcId; - pRspMsg->term = pSyncNode->raftStore.currentTerm; + pRspMsg->term = raftStoreGetTerm(pSyncNode); pRspMsg->lastIndex = pMsg->lastIndex; pRspMsg->lastTerm = pMsg->lastTerm; pRspMsg->startTime = pReceiver->startTime; @@ -737,7 +740,7 @@ static int32_t syncNodeOnSnapshotEnd(SSyncNode *pSyncNode, SyncSnapshotSend *pMs SyncSnapshotRsp *pRspMsg = rpcMsg.pCont; pRspMsg->srcId = pSyncNode->myRaftId; pRspMsg->destId = pMsg->srcId; - pRspMsg->term = pSyncNode->raftStore.currentTerm; + pRspMsg->term = raftStoreGetTerm(pSyncNode); pRspMsg->lastIndex = pMsg->lastIndex; pRspMsg->lastTerm = pMsg->lastTerm; pRspMsg->startTime = pReceiver->startTime; @@ -786,21 +789,20 @@ int32_t syncNodeOnSnapshot(SSyncNode *pSyncNode, const SRpcMsg *pRpcMsg) { return -1; } - if (pMsg->term < pSyncNode->raftStore.currentTerm) { + if (pMsg->term < raftStoreGetTerm(pSyncNode)) { syncLogRecvSyncSnapshotSend(pSyncNode, pMsg, "reject since small term"); terrno = TSDB_CODE_SYN_INTERNAL_ERROR; return -1; } - if (pMsg->term > pSyncNode->raftStore.currentTerm) { + if (pMsg->term > raftStoreGetTerm(pSyncNode)) { syncNodeStepDown(pSyncNode, pMsg->term); } - syncNodeResetElectTimer(pSyncNode); // state, term, seq/ack int32_t code = 0; if (pSyncNode->state == TAOS_SYNC_STATE_FOLLOWER) { - if (pMsg->term == pSyncNode->raftStore.currentTerm) { + if (pMsg->term == raftStoreGetTerm(pSyncNode)) { if (pMsg->seq == SYNC_SNAPSHOT_SEQ_PREP_SNAPSHOT) { syncLogRecvSyncSnapshotSend(pSyncNode, pMsg, "process seq pre-snapshot"); code = syncNodeOnSnapshotPrep(pSyncNode, pMsg); @@ -837,6 +839,7 @@ int32_t syncNodeOnSnapshot(SSyncNode *pSyncNode, const SRpcMsg *pRpcMsg) { code = -1; } + syncNodeResetElectTimer(pSyncNode); return code; } @@ -852,8 +855,8 @@ static int32_t syncNodeOnSnapshotPrepRsp(SSyncNode *pSyncNode, SSyncSnapshotSend pMsg->snapBeginIndex, snapshot.lastApplyIndex, snapshot.lastApplyTerm); if (pMsg->snapBeginIndex > snapshot.lastApplyIndex) { - sSError(pSender, "prepare snapshot failed since beginIndex:%d larger than applyIndex:%d", pMsg->snapBeginIndex, - snapshot.lastApplyIndex); + sSError(pSender, "prepare snapshot failed since beginIndex:%" PRId64 " larger than applyIndex:%" PRId64, + pMsg->snapBeginIndex, snapshot.lastApplyIndex); terrno = TSDB_CODE_SYN_INTERNAL_ERROR; return -1; } @@ -884,7 +887,7 @@ static int32_t syncNodeOnSnapshotPrepRsp(SSyncNode *pSyncNode, SSyncSnapshotSend SyncSnapshotSend *pSendMsg = rpcMsg.pCont; pSendMsg->srcId = pSender->pSyncNode->myRaftId; pSendMsg->destId = pSender->pSyncNode->replicasId[pSender->replicaIndex]; - pSendMsg->term = pSender->pSyncNode->raftStore.currentTerm; + pSendMsg->term = raftStoreGetTerm(pSender->pSyncNode); pSendMsg->beginIndex = pSender->snapshotParam.start; pSendMsg->lastIndex = pSender->snapshot.lastApplyIndex; pSendMsg->lastTerm = pSender->snapshot.lastApplyTerm; @@ -943,10 +946,11 @@ int32_t syncNodeOnSnapshotRsp(SSyncNode *pSyncNode, const SRpcMsg *pRpcMsg) { goto _ERROR; } - if (pMsg->term != pSyncNode->raftStore.currentTerm) { + SyncTerm currentTerm = raftStoreGetTerm(pSyncNode); + if (pMsg->term != currentTerm) { syncLogRecvSyncSnapshotRsp(pSyncNode, pMsg, "snapshot sender and receiver term not match"); sSError(pSender, "snapshot sender term not equal, msg term:%" PRId64 " currentTerm:%" PRId64, pMsg->term, - pSyncNode->raftStore.currentTerm); + currentTerm); terrno = TSDB_CODE_SYN_INTERNAL_ERROR; goto _ERROR; } @@ -966,7 +970,8 @@ int32_t syncNodeOnSnapshotRsp(SSyncNode *pSyncNode, const SRpcMsg *pRpcMsg) { if (pSender->pReader == NULL || pSender->finish) { syncLogRecvSyncSnapshotRsp(pSyncNode, pMsg, "snapshot sender invalid"); - sSError(pSender, "snapshot sender invalid, pReader:%p finish:%d", pMsg->code, pSender->pReader, pSender->finish); + sSError(pSender, "snapshot sender invalid error:%s 0x%x, pReader:%p finish:%d", tstrerror(pMsg->code), pMsg->code, + pSender->pReader, pSender->finish); terrno = pMsg->code; goto _ERROR; } @@ -987,8 +992,7 @@ int32_t syncNodeOnSnapshotRsp(SSyncNode *pSyncNode, const SRpcMsg *pRpcMsg) { if (pMsg->ack == SYNC_SNAPSHOT_SEQ_END) { syncLogRecvSyncSnapshotRsp(pSyncNode, pMsg, "process seq end"); snapshotSenderStop(pSender, true); - SSyncLogReplMgr *pMgr = syncNodeGetLogReplMgr(pSyncNode, &pMsg->srcId); - syncLogReplMgrReset(pMgr); + syncNodeReplicateReset(pSyncNode, &pMsg->srcId); return 0; } @@ -1013,8 +1017,7 @@ int32_t syncNodeOnSnapshotRsp(SSyncNode *pSyncNode, const SRpcMsg *pRpcMsg) { syncLogRecvSyncSnapshotRsp(pSyncNode, pMsg, "receive error ack"); sSError(pSender, "snapshot sender receive error ack:%d, my seq:%d", pMsg->ack, pSender->seq); snapshotSenderStop(pSender, true); - SSyncLogReplMgr *pMgr = syncNodeGetLogReplMgr(pSyncNode, &pMsg->srcId); - syncLogReplMgrReset(pMgr); + syncNodeReplicateReset(pSyncNode, &pMsg->srcId); return -1; } @@ -1022,8 +1025,6 @@ int32_t syncNodeOnSnapshotRsp(SSyncNode *pSyncNode, const SRpcMsg *pRpcMsg) { _ERROR: snapshotSenderStop(pSender, true); - SSyncLogReplMgr *pMgr = syncNodeGetLogReplMgr(pSyncNode, &pMsg->srcId); - syncLogReplMgrReset(pMgr); - + syncNodeReplicateReset(pSyncNode, &pMsg->srcId); return -1; } diff --git a/source/libs/sync/src/syncTimeout.c b/source/libs/sync/src/syncTimeout.c index 859183db9529ace6bf914fafbc381ca388880dea..a27be2853e512d73ada59bc224ce028ae208e0cb 100644 --- a/source/libs/sync/src/syncTimeout.c +++ b/source/libs/sync/src/syncTimeout.c @@ -120,9 +120,6 @@ int32_t syncNodeOnTimeout(SSyncNode* ths, const SRpcMsg* pRpc) { if (atomic_load_64(&ths->pingTimerLogicClockUser) <= pMsg->logicClock) { ++(ths->pingTimerCounter); - // syncNodePingAll(ths); - // syncNodePingPeers(ths); - syncNodeTimerRoutine(ths); } @@ -138,8 +135,6 @@ int32_t syncNodeOnTimeout(SSyncNode* ths, const SRpcMsg* pRpc) { ++(ths->heartbeatTimerCounter); sTrace("vgId:%d, sync timer, type:replicate count:%" PRIu64 ", lc-user:%" PRIu64, ths->vgId, ths->heartbeatTimerCounter, ths->heartbeatTimerLogicClockUser); - - // syncNodeReplicate(ths, true); } } else { diff --git a/source/libs/sync/src/syncUtil.c b/source/libs/sync/src/syncUtil.c index 97641b8f414dd6afe1aa8243a9bd482f68a6b57c..056a5977770c92f91c7b55e3c9554b5ccb7bafd2 100644 --- a/source/libs/sync/src/syncUtil.c +++ b/source/libs/sync/src/syncUtil.c @@ -125,7 +125,7 @@ static void syncLogBufferStates2Str(SSyncNode* pSyncNode, char* buf, int32_t buf pBuf->commitIndex, pBuf->matchIndex, pBuf->endIndex); } -static void syncLogReplMgrStates2Str(SSyncNode* pSyncNode, char* buf, int32_t bufLen) { +static void syncLogReplStates2Str(SSyncNode* pSyncNode, char* buf, int32_t bufLen) { int len = 0; len += snprintf(buf + len, bufLen - len, "%s", "{"); for (int32_t i = 0; i < pSyncNode->replicaNum; i++) { @@ -154,7 +154,7 @@ static void syncPeerState2Str(SSyncNode* pSyncNode, char* buf, int32_t bufLen) { void syncPrintNodeLog(const char* flags, ELogLevel level, int32_t dflag, SSyncNode* pNode, const char* format, ...) { if (pNode == NULL || pNode->pLogStore == NULL) return; - int64_t currentTerm = pNode->raftStore.currentTerm; + int64_t currentTerm = raftStoreGetTerm(pNode); // save error code, otherwise it will be overwritten int32_t errCode = terrno; @@ -178,7 +178,7 @@ void syncPrintNodeLog(const char* flags, ELogLevel level, int32_t dflag, SSyncNo syncCfg2SimpleStr(&pNode->raftCfg.cfg, cfgStr, sizeof(cfgStr)); char replMgrStatesStr[1024] = ""; - syncLogReplMgrStates2Str(pNode, replMgrStatesStr, sizeof(replMgrStatesStr)); + syncLogReplStates2Str(pNode, replMgrStatesStr, sizeof(replMgrStatesStr)); char bufferStatesStr[256] = ""; syncLogBufferStates2Str(pNode, bufferStatesStr, sizeof(bufferStatesStr)); @@ -260,7 +260,7 @@ void syncPrintSnapshotSenderLog(const char* flags, ELogLevel level, int32_t dfla pNode->vgId, eventLog, syncStr(pNode->state), pSender, pSender->snapshotParam.start, pSender->snapshotParam.end, pSender->snapshot.lastApplyIndex, pSender->snapshot.lastApplyTerm, pSender->snapshot.lastConfigIndex, pSender->seq, pSender->ack, pSender->finish, pSender->replicaIndex, - DID(&pNode->replicasId[pSender->replicaIndex]), pNode->raftStore.currentTerm, pNode->commitIndex, + DID(&pNode->replicasId[pSender->replicaIndex]), raftStoreGetTerm(pNode), pNode->commitIndex, logBeginIndex, logLastIndex, pNode->minMatchIndex, snapshot.lastApplyIndex, snapshot.lastApplyTerm, pNode->raftCfg.isStandBy, pNode->raftCfg.batchSize, pNode->replicaNum, pNode->raftCfg.lastConfigIndex, pNode->changing, pNode->restoreFinish, syncNodeDynamicQuorum(pNode), pNode->electTimerLogicClock, @@ -308,7 +308,7 @@ void syncPrintSnapshotReceiverLog(const char* flags, ELogLevel level, int32_t df pNode->vgId, eventLog, syncStr(pNode->state), pReceiver, pReceiver->start, pReceiver->ack, pReceiver->term, pReceiver->startTime, DID(&pReceiver->fromId), pReceiver->snapshotParam.start, pReceiver->snapshotParam.end, pReceiver->snapshot.lastApplyIndex, pReceiver->snapshot.lastApplyTerm, pReceiver->snapshot.lastConfigIndex, - pNode->raftStore.currentTerm, pNode->commitIndex, logBeginIndex, logLastIndex, pNode->minMatchIndex, + raftStoreGetTerm(pNode), pNode->commitIndex, logBeginIndex, logLastIndex, pNode->minMatchIndex, snapshot.lastApplyIndex, snapshot.lastApplyTerm, pNode->raftCfg.isStandBy, pNode->raftCfg.batchSize, pNode->replicaNum, pNode->raftCfg.lastConfigIndex, pNode->changing, pNode->restoreFinish, syncNodeDynamicQuorum(pNode), pNode->electTimerLogicClock, pNode->heartbeatTimerLogicClockUser, peerStr, cfgStr); diff --git a/source/libs/sync/test/sync_test_lib/src/syncMainDebug.c b/source/libs/sync/test/sync_test_lib/src/syncMainDebug.c index 1dbf4fb4fb70333d6a0cf0cb0a61138e58877504..18a75934fd6e5a5d96f63fad7d66b85f9c739932 100644 --- a/source/libs/sync/test/sync_test_lib/src/syncMainDebug.c +++ b/source/libs/sync/test/sync_test_lib/src/syncMainDebug.c @@ -199,7 +199,7 @@ inline char* syncNode2SimpleStr(const SSyncNode* pSyncNode) { ", sby:%d, " "r-num:%d, " "lcfg:%" PRId64 ", chging:%d, rsto:%d", - pSyncNode->vgId, syncStr(pSyncNode->state), pSyncNode->raftStore.currentTerm, pSyncNode->commitIndex, + pSyncNode->vgId, syncStr(pSyncNode->state), raftStoreGetTerm(pSyncNode), pSyncNode->commitIndex, logBeginIndex, logLastIndex, snapshot.lastApplyIndex, pSyncNode->raftCfg.isStandBy, pSyncNode->replicaNum, pSyncNode->raftCfg.lastConfigIndex, pSyncNode->changing, pSyncNode->restoreFinish); diff --git a/source/libs/sync/test/sync_test_lib/src/syncSnapshotDebug.c b/source/libs/sync/test/sync_test_lib/src/syncSnapshotDebug.c index d8740de16ae46214c8c5ed2ab2e1d622c003c300..2edcb0ad4dc4c8e593f842ee967a863b1b3019dd 100644 --- a/source/libs/sync/test/sync_test_lib/src/syncSnapshotDebug.c +++ b/source/libs/sync/test/sync_test_lib/src/syncSnapshotDebug.c @@ -137,7 +137,7 @@ int32_t syncNodeOnPreSnapshot(SSyncNode *ths, SyncPreSnapshot *pMsg) { SyncPreSnapshotReply *pMsgReply = syncPreSnapshotReplyBuild(ths->vgId); pMsgReply->srcId = ths->myRaftId; pMsgReply->destId = pMsg->srcId; - pMsgReply->term = ths->raftStore.currentTerm; + pMsgReply->term = raftStoreGetTerm(ths); SSyncLogStoreData *pData = ths->pLogStore->data; SWal *pWal = pData->pWal; diff --git a/source/libs/tdb/src/db/tdbBtree.c b/source/libs/tdb/src/db/tdbBtree.c index 4f0682a617c8d91d1a48c6afa1a7630a7d332811..c49b5726b647b2f9cb7741331b1dd6b6ede3cd87 100644 --- a/source/libs/tdb/src/db/tdbBtree.c +++ b/source/libs/tdb/src/db/tdbBtree.c @@ -74,7 +74,10 @@ int tdbBtreeOpen(int keyLen, int valLen, SPager *pPager, char const *tbname, SPg SBTree *pBt; int ret; - ASSERT(keyLen != 0); + if (keyLen == 0) { + tdbError("tdb/btree-open: key len cannot be zero."); + return -1; + } *ppBt = NULL; @@ -152,7 +155,11 @@ int tdbBtreeOpen(int keyLen, int valLen, SPager *pPager, char const *tbname, SPg tdbPostCommit(pPager->pEnv, txn); } - ASSERT(pgno != 0); + if (pgno == 0) { + tdbError("tdb/btree-open: pgno cannot be zero."); + tdbOsFree(pBt); + return -1; + } pBt->root = pgno; /* // TODO: pBt->root @@ -192,7 +199,7 @@ int tdbBtreeInsert(SBTree *pBt, const void *pKey, int kLen, const void *pVal, in ret = tdbBtcMoveTo(&btc, pKey, kLen, &c); if (ret < 0) { tdbBtcClose(&btc); - ASSERT(0); + tdbError("tdb/btree-insert: btc move to failed with ret: %d.", ret); return -1; } @@ -202,17 +209,17 @@ int tdbBtreeInsert(SBTree *pBt, const void *pKey, int kLen, const void *pVal, in if (c > 0) { btc.idx++; } else if (c == 0) { - // dup key not allowed - tdbError("unable to insert dup key. pKey: %p, kLen: %d, btc: %p, pTxn: %p", pKey, kLen, &btc, pTxn); - // ASSERT(0); + // dup key not allowed with insert + tdbBtcClose(&btc); + tdbError("tdb/btree-insert: dup key. pKey: %p, kLen: %d, btc: %p, pTxn: %p", pKey, kLen, &btc, pTxn); return -1; } } ret = tdbBtcUpsert(&btc, pKey, kLen, pVal, vLen, 1); if (ret < 0) { - ASSERT(0); tdbBtcClose(&btc); + tdbError("tdb/btree-insert: btc upsert failed with ret: %d.", ret); return -1; } @@ -233,7 +240,7 @@ int tdbBtreeDelete(SBTree *pBt, const void *pKey, int kLen, TXN *pTxn) { ret = tdbBtcMoveTo(&btc, pKey, kLen, &c); if (ret < 0) { tdbBtcClose(&btc); - ASSERT(0); + tdbError("tdb/btree-delete: btc move to failed with ret: %d.", ret); return -1; } @@ -253,7 +260,7 @@ int tdbBtreeDelete(SBTree *pBt, const void *pKey, int kLen, TXN *pTxn) { } int tdbBtreeUpsert(SBTree *pBt, const void *pKey, int nKey, const void *pData, int nData, TXN *pTxn) { - SBTC btc; + SBTC btc = {0}; int c; int ret; @@ -264,11 +271,18 @@ int tdbBtreeUpsert(SBTree *pBt, const void *pKey, int nKey, const void *pData, i // move the cursor ret = tdbBtcMoveTo(&btc, pKey, nKey, &c); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btree-upsert: btc move to failed with ret: %d.", ret); + if (TDB_CELLDECODER_FREE_KEY(&btc.coder)) { + tdbFree(btc.coder.pKey); + } tdbBtcClose(&btc); return -1; } + if (TDB_CELLDECODER_FREE_KEY(&btc.coder)) { + tdbFree(btc.coder.pKey); + } + if (btc.idx == -1) { btc.idx = 0; c = 1; @@ -280,8 +294,8 @@ int tdbBtreeUpsert(SBTree *pBt, const void *pKey, int nKey, const void *pData, i ret = tdbBtcUpsert(&btc, pKey, nKey, pData, nData, c); if (ret < 0) { - ASSERT(0); tdbBtcClose(&btc); + tdbError("tdb/btree-upsert: btc upsert failed with ret: %d.", ret); return -1; } @@ -309,7 +323,8 @@ int tdbBtreePGet(SBTree *pBt, const void *pKey, int kLen, void **ppKey, int *pkL ret = tdbBtcMoveTo(&btc, pKey, kLen, &cret); if (ret < 0) { tdbBtcClose(&btc); - ASSERT(0); + tdbError("tdb/btree-pget: btc move to failed with ret: %d.", ret); + return -1; } if (btc.idx < 0 || cret) { @@ -325,7 +340,7 @@ int tdbBtreePGet(SBTree *pBt, const void *pKey, int kLen, void **ppKey, int *pkL pTKey = tdbRealloc(*ppKey, cd.kLen); if (pTKey == NULL) { tdbBtcClose(&btc); - ASSERT(0); + tdbError("tdb/btree-pget: realloc pTKey failed."); return -1; } *ppKey = pTKey; @@ -337,7 +352,7 @@ int tdbBtreePGet(SBTree *pBt, const void *pKey, int kLen, void **ppKey, int *pkL pTVal = tdbRealloc(*ppVal, cd.vLen); if (pTVal == NULL) { tdbBtcClose(&btc); - ASSERT(0); + tdbError("tdb/btree-pget: realloc pTVal failed."); return -1; } *ppVal = pTVal; @@ -350,7 +365,7 @@ int tdbBtreePGet(SBTree *pBt, const void *pKey, int kLen, void **ppKey, int *pkL } if (TDB_CELLDECODER_FREE_VAL(&cd)) { - tdbDebug("tdb btc/pget/2 decoder: %p pVal free: %p", &cd, cd.pVal); + tdbTrace("tdb btc/pget/2 decoder: %p pVal free: %p", &cd, cd.pVal); tdbFree(cd.pVal); } @@ -366,7 +381,9 @@ static int tdbDefaultKeyCmprFn(const void *pKey1, int keyLen1, const void *pKey2 int mlen; int cret; - ASSERT(keyLen1 > 0 && keyLen2 > 0 && pKey1 != NULL && pKey2 != NULL); + if (ASSERT(keyLen1 > 0 && keyLen2 > 0 && pKey1 != NULL && pKey2 != NULL)) { + // -1 is less than + } mlen = keyLen1 < keyLen2 ? keyLen1 : keyLen2; cret = memcmp(pKey1, pKey2, mlen); @@ -381,36 +398,7 @@ static int tdbDefaultKeyCmprFn(const void *pKey1, int keyLen1, const void *pKey2 } return cret; } -/* -static int tdbBtreeOpenImpl(SBTree *pBt) { - // Try to get the root page of the an existing btree - SPgno pgno; - SPage *pPage; - int ret; - - { - // 1. TODO: Search the main DB to check if the DB exists - ret = tdbPagerOpenDB(pBt->pPager, &pgno, true, pBt); - ASSERT(ret == 0); - } - - if (pgno != 0) { - pBt->root = pgno; - return 0; - } - // Try to create a new database - ret = tdbPagerAllocPage(pBt->pPager, &pgno); - if (ret < 0) { - ASSERT(0); - return -1; - } - - ASSERT(pgno != 0); - pBt->root = pgno; - return 0; -} -*/ int tdbBtreeInitPage(SPage *pPage, void *arg, int init) { SBTree *pBt; u8 flags; @@ -546,11 +534,15 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx, TXN *pTx nOlds = 3; } for (int i = 0; i < nOlds; i++) { - ASSERT(sIdx + i <= nCells); + if (ASSERT(sIdx + i <= nCells)) { + return -1; + } SPgno pgno; if (sIdx + i == nCells) { - ASSERT(!TDB_BTREE_PAGE_IS_LEAF(pParent)); + if (ASSERT(!TDB_BTREE_PAGE_IS_LEAF(pParent))) { + return -1; + } pgno = ((SIntHdr *)(pParent->pData))->pgno; } else { pCell = tdbPageGetCell(pParent, sIdx + i); @@ -560,7 +552,7 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx, TXN *pTx ret = tdbPagerFetchPage(pBt->pPager, &pgno, pOlds + i, tdbBtreeInitPage, &((SBtreeInitPageArg){.pBt = pBt, .flags = 0}), pTxn); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btree-balance: fetch page failed with ret: %d.", ret); return -1; } @@ -679,7 +671,9 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx, TXN *pTx szRCell = tdbBtreeCellSize(pPage, pCell, 0, NULL, NULL); } - ASSERT(infoNews[iNew - 1].cnt > 0); + if (ASSERT(infoNews[iNew - 1].cnt > 0)) { + return -1; + } if (infoNews[iNew].size + szRCell >= infoNews[iNew - 1].size - szRCell) { break; @@ -722,7 +716,8 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx, TXN *pTx iarg.flags = flags; ret = tdbPagerFetchPage(pBt->pPager, &pgno, pNews + iNew, tdbBtreeInitPage, &iarg, pTxn); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btree-balance: fetch page failed with ret: %d.", ret); + return -1; } ret = tdbPagerWrite(pBt->pPager, pNews[iNew]); @@ -766,8 +761,12 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx, TXN *pTx pCell = tdbPageGetCell(pPage, oIdx); szCell = tdbBtreeCellSize(pPage, pCell, 0, NULL, NULL); - ASSERT(nNewCells <= infoNews[iNew].cnt); - ASSERT(iNew < nNews); + if (ASSERT(nNewCells <= infoNews[iNew].cnt)) { + return -1; + } + if (ASSERT(iNew < nNews)) { + return -1; + } if (nNewCells < infoNews[iNew].cnt) { tdbPageInsertCell(pNews[iNew], nNewCells, pCell, szCell, 0); @@ -806,14 +805,20 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx, TXN *pTx } } } else { - ASSERT(childNotLeaf); - ASSERT(iNew < nNews - 1); + if (ASSERT(childNotLeaf)) { + return -1; + } + if (ASSERT(iNew < nNews - 1)) { + return -1; + } // set current new page right-most child ((SIntHdr *)pNews[iNew]->pData)->pgno = ((SPgno *)pCell)[0]; // insert to parent as divider cell - ASSERT(iNew < nNews - 1); + if (ASSERT(iNew < nNews - 1)) { + return -1; + } ((SPgno *)pCell)[0] = TDB_PAGE_PGNO(pNews[iNew]); tdbPageInsertCell(pParent, sIdx++, pCell, szCell, 0); @@ -828,7 +833,9 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx, TXN *pTx } if (childNotLeaf) { - ASSERT(TDB_PAGE_TOTAL_CELLS(pNews[nNews - 1]) == infoNews[nNews - 1].cnt); + if (ASSERT(TDB_PAGE_TOTAL_CELLS(pNews[nNews - 1]) == infoNews[nNews - 1].cnt)) { + return -1; + } ((SIntHdr *)(pNews[nNews - 1]->pData))->pgno = rPgno; SIntHdr *pIntHdr = (SIntHdr *)pParent->pData; @@ -1018,7 +1025,9 @@ static int tdbBtreeEncodePayload(SPage *pPage, SCell *pCell, int nHeader, const nLeft -= kLen; // pack partial val to local if any space left if (nLocal > nHeader + kLen + sizeof(SPgno)) { - ASSERT(pVal != NULL && vLen != 0); + if (ASSERT(pVal != NULL && vLen != 0)) { + return -1; + } memcpy(pCell + nHeader + kLen, pVal, nLocal - nHeader - kLen - sizeof(SPgno)); nLeft -= nLocal - nHeader - kLen - sizeof(SPgno); } @@ -1183,9 +1192,15 @@ static int tdbBtreeEncodeCell(SPage *pPage, const void *pKey, int kLen, const vo int nPayload; int ret; - ASSERT(pPage->kLen == TDB_VARIANT_LEN || pPage->kLen == kLen); - ASSERT(pPage->vLen == TDB_VARIANT_LEN || pPage->vLen == vLen); - ASSERT(pKey != NULL && kLen > 0); + if (ASSERT(pPage->kLen == TDB_VARIANT_LEN || pPage->kLen == kLen)) { + return -1; + } + if (ASSERT(pPage->vLen == TDB_VARIANT_LEN || pPage->vLen == vLen)) { + return -1; + } + if (ASSERT(pKey != NULL && kLen > 0)) { + return -1; + } nPayload = 0; nHeader = 0; @@ -1194,7 +1209,10 @@ static int tdbBtreeEncodeCell(SPage *pPage, const void *pKey, int kLen, const vo // 1. Encode Header part /* Encode SPgno if interior page */ if (!leaf) { - ASSERT(pPage->vLen == sizeof(SPgno)); + if (pPage->vLen != sizeof(SPgno)) { + tdbError("tdb/btree-encode-cell: invalid cell."); + return -1; + } ((SPgno *)(pCell + nHeader))[0] = ((SPgno *)pVal)[0]; nHeader = nHeader + sizeof(SPgno); @@ -1219,8 +1237,8 @@ static int tdbBtreeEncodeCell(SPage *pPage, const void *pKey, int kLen, const vo ret = tdbBtreeEncodePayload(pPage, pCell, nHeader, pKey, kLen, pVal, vLen, &nPayload, pTxn, pBt); if (ret < 0) { // TODO - ASSERT(0); - return 0; + tdbError("tdb/btree-encode-cell: encode payload failed with ret: %d.", ret); + return -1; } *szCell = nHeader + nPayload; @@ -1237,7 +1255,10 @@ static int tdbBtreeDecodePayload(SPage *pPage, const SCell *pCell, int nHeader, int vLen = pDecoder->vLen; if (pDecoder->pVal) { - ASSERT(!TDB_BTREE_PAGE_IS_LEAF(pPage)); + if (TDB_BTREE_PAGE_IS_LEAF(pPage)) { + tdbError("tdb/btree-decode-payload: leaf page with non-null pVal."); + return -1; + } nPayload = pDecoder->kLen; } else { nPayload = pDecoder->kLen + pDecoder->vLen; @@ -1428,19 +1449,26 @@ static int tdbBtreeDecodeCell(SPage *pPage, const SCell *pCell, SCellDecoder *pD // Clear the state of decoder if (TDB_CELLDECODER_FREE_VAL(pDecoder)) { tdbFree(pDecoder->pVal); + TDB_CELLDECODER_CLZ_FREE_VAL(pDecoder); + // tdbTrace("tdb btc decoder val set nil: %p/0x%x ", pDecoder, pDecoder->freeKV); + } + if (TDB_CELLDECODER_FREE_KEY(pDecoder)) { + tdbFree(pDecoder->pKey); + TDB_CELLDECODER_CLZ_FREE_KEY(pDecoder); + // tdbTrace("tdb btc decoder key set nil: %p/0x%x ", pDecoder, pDecoder->freeKV); } pDecoder->kLen = -1; pDecoder->pKey = NULL; pDecoder->vLen = -1; pDecoder->pVal = NULL; pDecoder->pgno = 0; - TDB_CELLDECODER_SET_FREE_NIL(pDecoder); - - // tdbTrace("tdb btc decoder set nil: %p/0x%x ", pDecoder, pDecoder->freeKV); // 1. Decode header part if (!leaf) { - ASSERT(pPage->vLen == sizeof(SPgno)); + if (pPage->vLen != sizeof(SPgno)) { + tdbError("tdb/btree-decode-cell: invalid cell."); + return -1; + } pDecoder->pgno = ((SPgno *)(pCell + nHeader))[0]; pDecoder->pVal = (u8 *)(&(pDecoder->pgno)); @@ -1454,7 +1482,10 @@ static int tdbBtreeDecodeCell(SPage *pPage, const SCell *pCell, SCellDecoder *pD } if (pPage->vLen == TDB_VARIANT_LEN) { - ASSERT(leaf); + if (!leaf) { + tdbError("tdb/btree-decode-cell: not a leaf page."); + return -1; + } nHeader += tdbGetVarInt(pCell + nHeader, &(pDecoder->vLen)); } else { pDecoder->vLen = pPage->vLen; @@ -1486,7 +1517,10 @@ static int tdbBtreeCellSize(const SPage *pPage, SCell *pCell, int dropOfp, TXN * } if (pPage->vLen == TDB_VARIANT_LEN) { - ASSERT(leaf); + if (!leaf) { + tdbError("tdb/btree-cell-size: not a leaf page."); + return -1; + } nHeader += tdbGetVarInt(pCell + nHeader, &vLen); } else if (leaf) { vLen = pPage->vLen; @@ -1582,29 +1616,42 @@ int tdbBtcMoveToFirst(SBTC *pBtc) { ret = tdbPagerFetchPage(pPager, &pBt->root, &(pBtc->pPage), tdbBtreeInitPage, &((SBtreeInitPageArg){.pBt = pBt, .flags = TDB_BTREE_ROOT | TDB_BTREE_LEAF}), pBtc->pTxn); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-move-tofirst: fetch page failed with ret: %d.", ret); return -1; } - ASSERT(TDB_BTREE_PAGE_IS_ROOT(pBtc->pPage)); + if (!TDB_BTREE_PAGE_IS_ROOT(pBtc->pPage)) { + tdbError("tdb/btc-move-tofirst: not a root page"); + return -1; + } pBtc->iPage = 0; if (TDB_PAGE_TOTAL_CELLS(pBtc->pPage) > 0) { pBtc->idx = 0; } else { // no any data, point to an invalid position - ASSERT(TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)); + if (!TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)) { + tdbError("tdb/btc-move-to-first: not a leaf page."); + return -1; + } + pBtc->idx = -1; return 0; } } else { - ASSERT(0); + // TODO + tdbError("tdb/btc-move-to-first: move from a dirty cursor."); + return -1; #if 0 // move from a position int iPage = 0; for (; iPage < pBtc->iPage; iPage++) { - ASSERT(pBtc->idxStack[iPage] >= 0); + if (pBtc->idxStack[iPage] < 0) { + tdbError("tdb/btc-move-to-first: invalid idx: %d.", pBtc->idxStack[iPage]); + return -1; + } + if (pBtc->idxStack[iPage]) break; } @@ -1626,7 +1673,7 @@ int tdbBtcMoveToFirst(SBTC *pBtc) { ret = tdbBtcMoveDownward(pBtc); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-move-tofirst: btc move downward failed with ret: %d.", ret); return -1; } @@ -1651,7 +1698,7 @@ int tdbBtcMoveToLast(SBTC *pBtc) { ret = tdbPagerFetchPage(pPager, &pBt->root, &(pBtc->pPage), tdbBtreeInitPage, &((SBtreeInitPageArg){.pBt = pBt, .flags = TDB_BTREE_ROOT | TDB_BTREE_LEAF}), pBtc->pTxn); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-move-tolast: fetch page failed with ret: %d.", ret); return -1; } @@ -1661,18 +1708,28 @@ int tdbBtcMoveToLast(SBTC *pBtc) { pBtc->idx = TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage) ? nCells - 1 : nCells; } else { // no data at all, point to an invalid position - ASSERT(TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)); + if (!TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)) { + tdbError("tdb/btc-move-to-last: not a leaf page."); + return -1; + } + pBtc->idx = -1; return 0; } } else { - ASSERT(0); + // TODO + tdbError("tdb/btc-move-to-last: move from a dirty cursor."); + return -1; #if 0 int iPage = 0; // downward search for (; iPage < pBtc->iPage; iPage++) { - ASSERT(!TDB_BTREE_PAGE_IS_LEAF(pBtc->pgStack[iPage])); + if (TDB_BTREE_PAGE_IS_LEAF(pBtc->pgStack[iPage])) { + tdbError("tdb/btc-move-to-last: leaf page in cursor stack."); + return -1; + } + nCells = TDB_PAGE_TOTAL_CELLS(pBtc->pgStack[iPage]); if (pBtc->idxStack[iPage] != nCells) break; } @@ -1699,7 +1756,7 @@ int tdbBtcMoveToLast(SBTC *pBtc) { ret = tdbBtcMoveDownward(pBtc); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-move-tolast: btc move downward failed with ret: %d.", ret); return -1; } @@ -1757,11 +1814,16 @@ int tdbBtreeNext(SBTC *pBtc, void **ppKey, int *kLen, void **ppVal, int *vLen) { *ppVal = pVal; *vLen = cd.vLen; + } else { + if (TDB_CELLDECODER_FREE_VAL(&cd)) { + tdbTrace("tdb/btree-next2 decoder: %p pVal free: %p", &cd, cd.pVal); + tdbFree(cd.pVal); + } } ret = tdbBtcMoveToNext(pBtc); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btree-next: btc move to next failed with ret: %d.", ret); return -1; } @@ -1807,7 +1869,7 @@ int tdbBtreePrev(SBTC *pBtc, void **ppKey, int *kLen, void **ppVal, int *vLen) { ret = tdbBtcMoveToPrev(pBtc); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btree-prev: btc move to prev failed with ret: %d.", ret); return -1; } @@ -1819,7 +1881,10 @@ int tdbBtcMoveToNext(SBTC *pBtc) { int ret; SCell *pCell; - ASSERT(TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)); + if (!TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)) { + tdbError("tdb/btc-move-to-next: not a leaf page."); + return -1; + } if (pBtc->idx < 0) return -1; @@ -1838,7 +1903,10 @@ int tdbBtcMoveToNext(SBTC *pBtc) { tdbBtcMoveUpward(pBtc); pBtc->idx++; - ASSERT(!TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)); + if (TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)) { + tdbError("tdb/btree-decode-cell: should not be a leaf page here."); + return -1; + } if (pBtc->idx <= TDB_PAGE_TOTAL_CELLS(pBtc->pPage)) { break; } @@ -1850,7 +1918,7 @@ int tdbBtcMoveToNext(SBTC *pBtc) { ret = tdbBtcMoveDownward(pBtc); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-move-tonext: btc move downward failed with ret: %d.", ret); return -1; } @@ -1902,8 +1970,15 @@ static int tdbBtcMoveDownward(SBTC *pBtc) { SPgno pgno; SCell *pCell; - ASSERT(pBtc->idx >= 0); - ASSERT(!TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)); + if (pBtc->idx < 0) { + tdbError("tdb/btc-move-downward: invalid idx: %d.", pBtc->idx); + return -1; + } + + if (TDB_BTREE_PAGE_IS_LEAF(pBtc->pPage)) { + tdbError("tdb/btc-move-downward: should not be a leaf page here."); + return -1; + } if (pBtc->idx < TDB_PAGE_TOTAL_CELLS(pBtc->pPage)) { pCell = tdbPageGetCell(pBtc->pPage, pBtc->idx); @@ -1912,7 +1987,10 @@ static int tdbBtcMoveDownward(SBTC *pBtc) { pgno = ((SIntHdr *)pBtc->pPage->pData)->pgno; } - ASSERT(pgno); + if (!pgno) { + tdbError("tdb/btc-move-downward: invalid pgno."); + return -1; + } pBtc->pgStack[pBtc->iPage] = pBtc->pPage; pBtc->idxStack[pBtc->iPage] = pBtc->idx; @@ -1923,7 +2001,7 @@ static int tdbBtcMoveDownward(SBTC *pBtc) { ret = tdbPagerFetchPage(pBtc->pBt->pPager, &pgno, &pBtc->pPage, tdbBtreeInitPage, &((SBtreeInitPageArg){.pBt = pBtc->pBt, .flags = 0}), pBtc->pTxn); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-move-downward: fetch page failed with ret: %d.", ret); return -1; } @@ -1978,7 +2056,10 @@ int tdbBtcDelete(SBTC *pBtc) { int nKey; int ret; - ASSERT(idx >= 0 && idx < nCells); + if (idx < 0 || idx >= nCells) { + tdbError("tdb/btc-delete: idx: %d out of range[%d, %d).", idx, 0, nCells); + return -1; + } // drop the cell on the leaf ret = tdbPagerWrite(pPager, pBtc->pPage); @@ -2016,7 +2097,7 @@ int tdbBtcDelete(SBTC *pBtc) { ret = tdbPageUpdateCell(pPage, idx, pCell, szCell, pBtc->pTxn, pBtc->pBt); if (ret < 0) { tdbOsFree(pCell); - ASSERT(0); + tdbError("tdb/btc-delete: page update cell failed with ret: %d.", ret); return -1; } tdbOsFree(pCell); @@ -2027,11 +2108,14 @@ int tdbBtcDelete(SBTC *pBtc) { } } else { // delete the leaf page and do balance - ASSERT(TDB_PAGE_TOTAL_CELLS(pBtc->pPage) == 0); + if (TDB_PAGE_TOTAL_CELLS(pBtc->pPage) != 0) { + tdbError("tdb/btc-delete: page to be deleted should be empty."); + return -1; + } ret = tdbBtreeBalance(pBtc); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-delete: btree balance failed with ret: %d.", ret); return -1; } } @@ -2048,13 +2132,16 @@ int tdbBtcUpsert(SBTC *pBtc, const void *pKey, int kLen, const void *pData, int void *pBuf; int ret; - ASSERT(pBtc->idx >= 0); + if (pBtc->idx < 0) { + tdbError("tdb/btc-upsert: invalid idx: %d.", pBtc->idx); + return -1; + } // alloc space szBuf = kLen + nData + 14; pBuf = tdbRealloc(pBtc->pBt->pBuf, pBtc->pBt->pageSize > szBuf ? szBuf : pBtc->pBt->pageSize); if (pBuf == NULL) { - ASSERT(0); + tdbError("tdb/btc-upsert: realloc pBuf failed."); return -1; } pBtc->pBt->pBuf = pBuf; @@ -2063,7 +2150,7 @@ int tdbBtcUpsert(SBTC *pBtc, const void *pKey, int kLen, const void *pData, int // encode cell ret = tdbBtreeEncodeCell(pBtc->pPage, pKey, kLen, pData, nData, pCell, &szCell, pBtc->pTxn, pBtc->pBt); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-upsert: btree encode cell failed with ret: %d.", ret); return -1; } @@ -2076,16 +2163,22 @@ int tdbBtcUpsert(SBTC *pBtc, const void *pKey, int kLen, const void *pData, int // insert or update if (insert) { - ASSERT(pBtc->idx <= nCells); + if (pBtc->idx > nCells) { + tdbError("tdb/btc-upsert: invalid idx: %d, nCells: %d.", pBtc->idx, nCells); + return -1; + } ret = tdbPageInsertCell(pBtc->pPage, pBtc->idx, pCell, szCell, 0); } else { - ASSERT(pBtc->idx < nCells); + if (pBtc->idx >= nCells) { + tdbError("tdb/btc-upsert: invalid idx: %d, nCells: %d.", pBtc->idx, nCells); + return -1; + } ret = tdbPageUpdateCell(pBtc->pPage, pBtc->idx, pCell, szCell, pBtc->pTxn, pBtc->pBt); } if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-upsert: page insert/update cell failed with ret: %d.", ret); return -1; } @@ -2093,7 +2186,7 @@ int tdbBtcUpsert(SBTC *pBtc, const void *pKey, int kLen, const void *pData, int if (pBtc->pPage->nOverflow > 0) { ret = tdbBtreeBalance(pBtc); if (ret < 0) { - ASSERT(0); + tdbError("tdb/btc-upsert: btree balance failed with ret: %d.", ret); return -1; } } @@ -2118,8 +2211,8 @@ int tdbBtcMoveTo(SBTC *pBtc, const void *pKey, int kLen, int *pCRst) { &((SBtreeInitPageArg){.pBt = pBt, .flags = TDB_BTREE_ROOT | TDB_BTREE_LEAF}), pBtc->pTxn); if (ret < 0) { // TODO - ASSERT(0); - return 0; + tdbError("tdb/btc-move-to: fetch page failed with ret: %d.", ret); + return -1; } pBtc->iPage = 0; @@ -2127,7 +2220,9 @@ int tdbBtcMoveTo(SBTC *pBtc, const void *pKey, int kLen, int *pCRst) { // for empty tree, just return with an invalid position if (TDB_PAGE_TOTAL_CELLS(pBtc->pPage) == 0) return 0; } else { - ASSERT(0); + // TODO + tdbError("tdb/btc-move-to: move from a dirty cursor."); + return -1; #if 0 SPage *pPage; int idx; @@ -2139,7 +2234,10 @@ int tdbBtcMoveTo(SBTC *pBtc, const void *pKey, int kLen, int *pCRst) { idx = pBtc->idxStack[iPage]; nCells = TDB_PAGE_TOTAL_CELLS(pPage); - ASSERT(!TDB_BTREE_PAGE_IS_LEAF(pPage)); + if (TDB_BTREE_PAGE_IS_LEAF(pPage)) { + tdbError("tdb/btc-move-to: leaf page in cursor stack."); + return -1; + } // check if key <= current position if (idx < nCells) { @@ -2188,7 +2286,6 @@ int tdbBtcMoveTo(SBTC *pBtc, const void *pKey, int kLen, int *pCRst) { } else { lidx = lidx + 1; } - // compare last cell if (lidx <= ridx) { pBtc->idx = ridx; @@ -2242,7 +2339,10 @@ int tdbBtcClose(SBTC *pBtc) { if (pBtc->iPage < 0) return 0; for (;;) { - ASSERT(pBtc->pPage); + if (NULL == pBtc->pPage) { + tdbError("tdb/btc-close: null ptr pPage."); + return -1; + } tdbPagerReturnPage(pBtc->pBt->pPager, pBtc->pPage, pBtc->pTxn); diff --git a/source/libs/tdb/src/db/tdbDb.c b/source/libs/tdb/src/db/tdbDb.c index c79279c658a746e83a40eaed6fd6cb8cbe6e31d7..952c49db73a2c8986d67c8e327175ad00e778ae6 100644 --- a/source/libs/tdb/src/db/tdbDb.c +++ b/source/libs/tdb/src/db/tdbDb.c @@ -247,7 +247,10 @@ void tdbEnvRemovePager(TDB *pDb, SPager *pPager) { // remove from the list for (ppPager = &pDb->pgrList; *ppPager && (*ppPager != pPager); ppPager = &((*ppPager)->pNext)) { } - ASSERT(*ppPager == pPager); + if (*ppPager != pPager) { + tdbError("tdb/db: invalid pPager: %p, *ppPager: %p", pPager, *ppPager); + return; + } *ppPager = pPager->pNext; // remove from hash @@ -255,7 +258,10 @@ void tdbEnvRemovePager(TDB *pDb, SPager *pPager) { ppPager = &pDb->pgrHash[hash % pDb->nPgrHash]; for (; *ppPager && *ppPager != pPager; ppPager = &((*ppPager)->pHashNext)) { } - ASSERT(*ppPager == pPager); + if (*ppPager != pPager) { + tdbError("tdb/db: invalid pPager: %p, *ppPager: %p", pPager, *ppPager); + return; + } *ppPager = pPager->pNext; // decrease the counter diff --git a/source/libs/tdb/src/db/tdbPCache.c b/source/libs/tdb/src/db/tdbPCache.c index 4896568c7f5ce45ce816f16d3eec0436cf51dfc5..262f3d27e648cfebb4f081c725f443756cb6a06d 100644 --- a/source/libs/tdb/src/db/tdbPCache.c +++ b/source/libs/tdb/src/db/tdbPCache.c @@ -236,10 +236,10 @@ void tdbPCacheInvalidatePage(SPCache *pCache, SPager *pPager, SPgno pgno) { void tdbPCacheRelease(SPCache *pCache, SPage *pPage, TXN *pTxn) { i32 nRef; - ASSERT(pTxn); - - // nRef = tdbUnrefPage(pPage); - // ASSERT(nRef >= 0); + if (!pTxn) { + tdbError("tdb/pcache: null ptr pTxn, release failed."); + return; + } tdbPCacheLock(pCache); nRef = tdbUnrefPage(pPage); @@ -275,7 +275,10 @@ static SPage *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, TXN *pTxn) SPage *pPage = NULL; SPage *pPageH = NULL; - ASSERT(pTxn); + if (!pTxn) { + tdbError("tdb/pcache: null ptr pTxn, fetch impl failed."); + return NULL; + } // 1. Search the hash table pPage = pCache->pgHash[tdbPCachePageHash(pPgid) % pCache->nHash]; @@ -315,8 +318,8 @@ static SPage *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, TXN *pTxn) if (!pPage && pTxn->xMalloc != NULL) { ret = tdbPageCreate(pCache->szPage, &pPage, pTxn->xMalloc, pTxn->xArg); if (ret < 0 || pPage == NULL) { - // TODO - ASSERT(0); + tdbError("tdb/pcache: ret: %" PRId32 " pPage: %p, page create failed.", ret, pPage); + // TODO: recycle other backup pages return NULL; } @@ -370,7 +373,11 @@ static SPage *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, TXN *pTxn) static void tdbPCachePinPage(SPCache *pCache, SPage *pPage) { if (pPage->pLruNext != NULL) { - ASSERT(tdbGetPageRef(pPage) == 0); + int32_t nRef = tdbGetPageRef(pPage); + if (nRef != 0) { + tdbError("tdb/pcache: pin page's ref not zero: %" PRId32, nRef); + return; + } pPage->pLruPrev->pLruNext = pPage->pLruNext; pPage->pLruNext->pLruPrev = pPage->pLruPrev; @@ -383,13 +390,23 @@ static void tdbPCachePinPage(SPCache *pCache, SPage *pPage) { } static void tdbPCacheUnpinPage(SPCache *pCache, SPage *pPage) { - i32 nRef; - - ASSERT(pPage->isLocal); - ASSERT(!pPage->isDirty); - ASSERT(tdbGetPageRef(pPage) == 0); - - ASSERT(pPage->pLruNext == NULL); + i32 nRef = tdbGetPageRef(pPage); + if (nRef != 0) { + tdbError("tdb/pcache: unpin page's ref not zero: %" PRId32, nRef); + return; + } + if (!pPage->isLocal) { + tdbError("tdb/pcache: unpin page's not local: %" PRIu8, pPage->isLocal); + return; + } + if (pPage->isDirty) { + tdbError("tdb/pcache: unpin page's dirty: %" PRIu8, pPage->isDirty); + return; + } + if (NULL != pPage->pLruNext) { + tdbError("tdb/pcache: unpin page's pLruNext not null."); + return; + } tdbTrace("pCache:%p unpin page %p/%d, nPages:%d, pgno:%d, ", pCache, pPage, pPage->id, pCache->nPages, TDB_PAGE_PGNO(pPage)); diff --git a/source/libs/tdb/src/db/tdbPage.c b/source/libs/tdb/src/db/tdbPage.c index dc448c986e628b4c7af9dd03aa84706c8053da71..c6310f4985da8fc18a4502d5a4dda5ecfa0d8a64 100644 --- a/source/libs/tdb/src/db/tdbPage.c +++ b/source/libs/tdb/src/db/tdbPage.c @@ -43,9 +43,15 @@ int tdbPageCreate(int pageSize, SPage **ppPage, void *(*xMalloc)(void *, size_t) u8 *ptr; int size; - ASSERT(xMalloc); + if (!xMalloc) { + tdbError("tdb/page-create: null xMalloc."); + return -1; + } - ASSERT(TDB_IS_PGSIZE_VLD(pageSize)); + if (!TDB_IS_PGSIZE_VLD(pageSize)) { + tdbError("tdb/page-create: invalid pageSize: %d.", pageSize); + return -1; + } *ppPage = NULL; size = pageSize + sizeof(*pPage); @@ -69,16 +75,24 @@ int tdbPageCreate(int pageSize, SPage **ppPage, void *(*xMalloc)(void *, size_t) *ppPage = pPage; - tdbTrace("page/create: %p/%d %p", pPage, pPage->id, xMalloc); + tdbTrace("tdb/page-create: %p/%d %p", pPage, pPage->id, xMalloc); return 0; } int tdbPageDestroy(SPage *pPage, void (*xFree)(void *arg, void *ptr), void *arg) { u8 *ptr; - tdbTrace("page/destroy: %p/%d %p", pPage, pPage->id, xFree); - ASSERT(!pPage->isDirty); - ASSERT(xFree); + tdbTrace("tdb/page-destroy: %p/%d %p", pPage, pPage->id, xFree); + + if (pPage->isDirty) { + tdbError("tdb/page-destroy: dirty page: %" PRIu8 ".", pPage->isDirty); + return -1; + } + + if (!xFree) { + tdbError("tdb/page-destroy: null xFree."); + return -1; + } for (int iOvfl = 0; iOvfl < pPage->nOverflow; iOvfl++) { tdbTrace("tdbPage/destroy/free ovfl cell: %p/%p", pPage->apOvfl[iOvfl], pPage); @@ -105,7 +119,10 @@ void tdbPageZero(SPage *pPage, u8 szAmHdr, int (*xCellSize)(const SPage *, SCell pPage->nOverflow = 0; pPage->xCellSize = xCellSize; - ASSERT((u8 *)pPage->pPageFtr == pPage->pFreeEnd); + if ((u8 *)pPage->pPageFtr != pPage->pFreeEnd) { + tdbError("tdb/page-zero: invalid page, pFreeEnd: %p, pPageFtr: %p", pPage->pFreeEnd, pPage->pPageFtr); + return; + } } void tdbPageInit(SPage *pPage, u8 szAmHdr, int (*xCellSize)(const SPage *, SCell *, int, TXN *, SBTree *pBt)) { @@ -121,8 +138,15 @@ void tdbPageInit(SPage *pPage, u8 szAmHdr, int (*xCellSize)(const SPage *, SCell pPage->nOverflow = 0; pPage->xCellSize = xCellSize; - ASSERT(pPage->pFreeEnd >= pPage->pFreeStart); - ASSERT(pPage->pFreeEnd - pPage->pFreeStart <= TDB_PAGE_NFREE(pPage)); + if (pPage->pFreeEnd < pPage->pFreeStart) { + tdbError("tdb/page-init: invalid page, pFreeEnd: %p, pFreeStart: %p", pPage->pFreeEnd, pPage->pFreeStart); + return; + } + if (pPage->pFreeEnd - pPage->pFreeStart > TDB_PAGE_NFREE(pPage)) { + tdbError("tdb/page-init: invalid page, pFreeEnd: %p, pFreeStart: %p, NFREE: %d", pPage->pFreeEnd, pPage->pFreeStart, + TDB_PAGE_NFREE(pPage)); + return; + } } int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell, u8 asOvfl) { @@ -132,7 +156,11 @@ int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell, u8 asOvfl int lidx; // local idx SCell *pNewCell; - ASSERT(szCell <= TDB_PAGE_MAX_FREE_BLOCK(pPage, pPage->pPageHdr - pPage->pData)); + if (szCell > TDB_PAGE_MAX_FREE_BLOCK(pPage, pPage->pPageHdr - pPage->pData)) { + tdbError("tdb/page-insert-cell: invalid page, szCell: %d, max free: %lu", szCell, + TDB_PAGE_MAX_FREE_BLOCK(pPage, pPage->pPageHdr - pPage->pData)); + return -1; + } nFree = TDB_PAGE_NFREE(pPage); nCells = TDB_PAGE_NCELLS(pPage); @@ -176,7 +204,11 @@ int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell, u8 asOvfl TDB_PAGE_CELL_OFFSET_AT_SET(pPage, lidx, pNewCell - pPage->pData); TDB_PAGE_NCELLS_SET(pPage, nCells + 1); - ASSERT(pPage->pFreeStart == pPage->pCellIdx + TDB_PAGE_OFFSET_SIZE(pPage) * (nCells + 1)); + if (pPage->pFreeStart != pPage->pCellIdx + TDB_PAGE_OFFSET_SIZE(pPage) * (nCells + 1)) { + tdbError("tdb/page-insert-cell: invalid page, pFreeStart: %p, pCellIdx: %p, nCells: %d", pPage->pFreeStart, + pPage->pCellIdx, nCells); + return -1; + } } for (; iOvfl < pPage->nOverflow; iOvfl++) { @@ -200,7 +232,10 @@ int tdbPageDropCell(SPage *pPage, int idx, TXN *pTxn, SBTree *pBt) { nCells = TDB_PAGE_NCELLS(pPage); - ASSERT(idx >= 0 && idx < nCells + pPage->nOverflow); + if (idx < 0 || idx >= nCells + pPage->nOverflow) { + tdbError("tdb/page-drop-cell: idx: %d out of range, nCells: %d, nOvfl: %d.", idx, nCells, pPage->nOverflow); + return -1; + } iOvfl = 0; for (; iOvfl < pPage->nOverflow; iOvfl++) { @@ -228,7 +263,10 @@ int tdbPageDropCell(SPage *pPage, int idx, TXN *pTxn, SBTree *pBt) { for (; iOvfl < pPage->nOverflow; iOvfl++) { pPage->aiOvfl[iOvfl]--; - ASSERT(pPage->aiOvfl[iOvfl] > 0); + if (pPage->aiOvfl[iOvfl] <= 0) { + tdbError("tdb/page-drop-cell: invalid ai idx: %d", pPage->aiOvfl[iOvfl]); + return -1; + } } return 0; @@ -240,12 +278,19 @@ void tdbPageCopy(SPage *pFromPage, SPage *pToPage, int deepCopyOvfl) { pToPage->pFreeStart = pToPage->pPageHdr + (pFromPage->pFreeStart - pFromPage->pPageHdr); pToPage->pFreeEnd = (u8 *)(pToPage->pPageFtr) - ((u8 *)pFromPage->pPageFtr - pFromPage->pFreeEnd); - ASSERT(pToPage->pFreeEnd >= pToPage->pFreeStart); + if (pToPage->pFreeEnd < pToPage->pFreeStart) { + tdbError("tdb/page-copy: invalid to page, pFreeStart: %p, pFreeEnd: %p", pToPage->pFreeStart, pToPage->pFreeEnd); + return; + } memcpy(pToPage->pPageHdr, pFromPage->pPageHdr, pFromPage->pFreeStart - pFromPage->pPageHdr); memcpy(pToPage->pFreeEnd, pFromPage->pFreeEnd, (u8 *)pFromPage->pPageFtr - pFromPage->pFreeEnd); - ASSERT(TDB_PAGE_CCELLS(pToPage) == pToPage->pFreeEnd - pToPage->pData); + if (TDB_PAGE_CCELLS(pToPage) != pToPage->pFreeEnd - pToPage->pData) { + tdbError("tdb/page-copy: invalid to page, cell body: %d, range: %ld", TDB_PAGE_CCELLS(pToPage), + pToPage->pFreeEnd - pToPage->pData); + return; + } delta = (pToPage->pPageHdr - pToPage->pData) - (pFromPage->pPageHdr - pFromPage->pData); if (delta != 0) { @@ -295,8 +340,16 @@ static int tdbPageAllocate(SPage *pPage, int szCell, SCell **ppCell) { *ppCell = NULL; nFree = TDB_PAGE_NFREE(pPage); - ASSERT(nFree >= szCell + TDB_PAGE_OFFSET_SIZE(pPage)); - ASSERT(TDB_PAGE_CCELLS(pPage) == pPage->pFreeEnd - pPage->pData); + if (nFree < szCell + TDB_PAGE_OFFSET_SIZE(pPage)) { + tdbError("tdb/page-allocate: invalid cell size, nFree: %d, szCell: %d, szOffset: %d", nFree, szCell, + TDB_PAGE_OFFSET_SIZE(pPage)); + return -1; + } + if (TDB_PAGE_CCELLS(pPage) != pPage->pFreeEnd - pPage->pData) { + tdbError("tdb/page-allocate: invalid page, cell body: %d, range: %ld", TDB_PAGE_CCELLS(pPage), + pPage->pFreeEnd - pPage->pData); + return -1; + } // 1. Try to allocate from the free space block area if (pPage->pFreeEnd - pPage->pFreeStart >= szCell + TDB_PAGE_OFFSET_SIZE(pPage)) { @@ -308,7 +361,10 @@ static int tdbPageAllocate(SPage *pPage, int szCell, SCell **ppCell) { // 2. Try to allocate from the page free list cellFree = TDB_PAGE_FCELL(pPage); - ASSERT(cellFree == 0 || cellFree >= pPage->pFreeEnd - pPage->pData); + if (cellFree != 0 && cellFree < pPage->pFreeEnd - pPage->pData) { + tdbError("tdb/page-allocate: cellFree: %d, pFreeEnd: %p, pData: %p.", cellFree, pPage->pFreeEnd, pPage->pData); + return -1; + } if (cellFree && pPage->pFreeEnd - pPage->pFreeStart >= TDB_PAGE_OFFSET_SIZE(pPage)) { SCell *pPrevFreeCell = NULL; int szPrevFreeCell; @@ -353,16 +409,30 @@ static int tdbPageAllocate(SPage *pPage, int szCell, SCell **ppCell) { // 3. Try to dfragment and allocate again tdbPageDefragment(pPage); - ASSERT(pPage->pFreeEnd - pPage->pFreeStart == nFree); - ASSERT(nFree == TDB_PAGE_NFREE(pPage)); - ASSERT(pPage->pFreeEnd - pPage->pData == TDB_PAGE_CCELLS(pPage)); + if (pPage->pFreeEnd - pPage->pFreeStart != nFree) { + tdbError("tdb/page-allocate: nFree: %d, pFreeStart: %p, pFreeEnd: %p.", nFree, pPage->pFreeStart, pPage->pFreeEnd); + return -1; + } + if (TDB_PAGE_NFREE(pPage) != nFree) { + tdbError("tdb/page-allocate: nFree: %d, page free: %d.", nFree, TDB_PAGE_NFREE(pPage)); + return -1; + } + if (pPage->pFreeEnd - pPage->pData != TDB_PAGE_CCELLS(pPage)) { + tdbError("tdb/page-allocate: ccells: %d, pFreeStart: %p, pData: %p.", TDB_PAGE_CCELLS(pPage), pPage->pFreeStart, + pPage->pData); + return -1; + } pPage->pFreeEnd -= szCell; pCell = pPage->pFreeEnd; TDB_PAGE_CCELLS_SET(pPage, pPage->pFreeEnd - pPage->pData); _alloc_finish: - ASSERT(pCell); + if (NULL == pCell) { + tdbError("tdb/page-allocate: null ptr pCell."); + return -1; + } + pPage->pFreeStart += TDB_PAGE_OFFSET_SIZE(pPage); TDB_PAGE_NFREE_SET(pPage, nFree - szCell - TDB_PAGE_OFFSET_SIZE(pPage)); *ppCell = pCell; @@ -375,9 +445,18 @@ static int tdbPageFree(SPage *pPage, int idx, SCell *pCell, int szCell) { u8 *dest; u8 *src; - ASSERT(pCell >= pPage->pFreeEnd); - ASSERT(pCell + szCell <= (u8 *)(pPage->pPageFtr)); - ASSERT(pCell == TDB_PAGE_CELL_AT(pPage, idx)); + if (pCell < pPage->pFreeEnd) { + tdbError("tdb/page-free: invalid cell, cell: %p, free end: %p", pCell, pPage->pFreeEnd); + return -1; + } + if (pCell + szCell > (u8 *)(pPage->pPageFtr)) { + tdbError("tdb/page-free: cell crosses page footer, cell: %p, size: %d footer: %p", pCell, szCell, pPage->pFreeEnd); + return -1; + } + if (pCell != TDB_PAGE_CELL_AT(pPage, idx)) { + tdbError("tdb/page-free: cell pos incorrect, cell: %p, pos: %p", pCell, TDB_PAGE_CELL_AT(pPage, idx)); + return -1; + } nFree = TDB_PAGE_NFREE(pPage); @@ -390,7 +469,8 @@ static int tdbPageFree(SPage *pPage, int idx, SCell *pCell, int szCell) { pPage->pPageMethods->setFreeCellInfo(pCell, szCell, cellFree); TDB_PAGE_FCELL_SET(pPage, pCell - pPage->pData); } else { - ASSERT(0); + tdbError("tdb/page-free: invalid cell size: %d", szCell); + return -1; } } @@ -471,39 +551,59 @@ typedef struct { // cellNum static inline int getPageCellNum(SPage *pPage) { return ((SPageHdr *)(pPage->pPageHdr))[0].cellNum; } static inline void setPageCellNum(SPage *pPage, int cellNum) { - ASSERT(cellNum < 65536); + if (cellNum >= 65536) { + tdbError("tdb/page-set-cell-num: invalid cellNum: %d.", cellNum); + return; + } ((SPageHdr *)(pPage->pPageHdr))[0].cellNum = (u16)cellNum; } // cellBody static inline int getPageCellBody(SPage *pPage) { return ((SPageHdr *)(pPage->pPageHdr))[0].cellBody; } static inline void setPageCellBody(SPage *pPage, int cellBody) { - ASSERT(cellBody < 65536); + if (cellBody >= 65536) { + tdbError("tdb/page-set-cell-body: invalid cellBody: %d.", cellBody); + return; + } ((SPageHdr *)(pPage->pPageHdr))[0].cellBody = (u16)cellBody; } // cellFree static inline int getPageCellFree(SPage *pPage) { return ((SPageHdr *)(pPage->pPageHdr))[0].cellFree; } static inline void setPageCellFree(SPage *pPage, int cellFree) { - ASSERT(cellFree < 65536); + if (cellFree >= 65536) { + tdbError("tdb/page-set-cell-free: invalid cellFree: %d.", cellFree); + return; + } ((SPageHdr *)(pPage->pPageHdr))[0].cellFree = (u16)cellFree; } // nFree static inline int getPageNFree(SPage *pPage) { return ((SPageHdr *)(pPage->pPageHdr))[0].nFree; } static inline void setPageNFree(SPage *pPage, int nFree) { - ASSERT(nFree < 65536); + if (nFree >= 65536) { + tdbError("tdb/page-set-nfree: invalid nFree: %d.", nFree); + return; + } ((SPageHdr *)(pPage->pPageHdr))[0].nFree = (u16)nFree; } // cell offset static inline int getPageCellOffset(SPage *pPage, int idx) { - ASSERT(idx >= 0 && idx < getPageCellNum(pPage)); + int cellNum = getPageCellNum(pPage); + if (idx < 0 || idx >= cellNum) { + tdbError("tdb/page-cell-offset: idx: %d out of range[%d, %d).", idx, 0, cellNum); + return -1; + } + return ((u16 *)pPage->pCellIdx)[idx]; } static inline void setPageCellOffset(SPage *pPage, int idx, int offset) { - ASSERT(offset < 65536); + if (offset >= 65536) { + tdbError("tdb/page-set-cell-offset: invalid offset: %d.", offset); + return; + } ((u16 *)pPage->pCellIdx)[idx] = (u16)offset; } @@ -578,7 +678,12 @@ static inline void setLPageNFree(SPage *pPage, int nFree) { // cell offset static inline int getLPageCellOffset(SPage *pPage, int idx) { - ASSERT(idx >= 0 && idx < getLPageCellNum(pPage)); + int cellNum = getLPageCellNum(pPage); + if (idx < 0 || idx >= cellNum) { + tdbError("tdb/lpage-cell-offset: idx: %d out of range[%d, %d).", idx, 0, cellNum); + return -1; + } + return TDB_GET_U24(pPage->pCellIdx + 3 * idx); } diff --git a/source/libs/tdb/src/db/tdbPager.c b/source/libs/tdb/src/db/tdbPager.c index 63e88b0a12854780a7c153c7bffcae287dd987bf..5ea9be63dbf7bb9415668d232324ca1272b49db6 100644 --- a/source/libs/tdb/src/db/tdbPager.c +++ b/source/libs/tdb/src/db/tdbPager.c @@ -14,7 +14,7 @@ */ #include "tdbInt.h" - +/* #pragma pack(push, 1) typedef struct { u8 hdrString[16]; @@ -26,7 +26,7 @@ typedef struct { #pragma pack(pop) TDB_STATIC_ASSERT(sizeof(SFileHdr) == 128, "Size of file header is not correct"); - +*/ struct hashset_st { size_t nbits; size_t mask; @@ -234,7 +234,6 @@ int tdbPagerWrite(SPager *pPager, SPage *pPage) { int ret; SPage **ppPage; - // ASSERT(pPager->inTran); if (pPage->isDirty) return 0; // ref page one more time so the page will not be release @@ -243,23 +242,8 @@ int tdbPagerWrite(SPager *pPager, SPage *pPage) { // Set page as dirty pPage->isDirty = 1; - /* - // Add page to dirty list(TODO: NOT use O(n^2) algorithm) - for (ppPage = &pPager->pDirty; (*ppPage) && TDB_PAGE_PGNO(*ppPage) < TDB_PAGE_PGNO(pPage); - ppPage = &((*ppPage)->pDirtyNext)) { - } - if (*ppPage && TDB_PAGE_PGNO(*ppPage) == TDB_PAGE_PGNO(pPage)) { - tdbUnrefPage(pPage); - - return 0; - } - - ASSERT(*ppPage == NULL || TDB_PAGE_PGNO(*ppPage) > TDB_PAGE_PGNO(pPage)); - pPage->pDirtyNext = *ppPage; - *ppPage = pPage; - */ - tdbTrace("put page: %p %d to dirty tree: %p", pPage, TDB_PAGE_PGNO(pPage), &pPager->rbt); + tdbTrace("tdb/pager-write: put page: %p %d to dirty tree: %p", pPage, TDB_PAGE_PGNO(pPage), &pPager->rbt); tRBTreePut(&pPager->rbt, (SRBTreeNode *)pPage); // Write page to journal if neccessary @@ -327,7 +311,11 @@ int tdbPagerCommit(SPager *pPager, TXN *pTxn) { while ((pNode = tRBTreeIterNext(&iter)) != NULL) { pPage = (SPage *)pNode; - ASSERT(pPage->nOverflow == 0); + if (pPage->nOverflow != 0) { + tdbError("tdb/pager-commit: %p, pPage: %p, ovfl: %d, commit page failed.", pPager, pPage, pPage->nOverflow); + return -1; + } + ret = tdbPagerPWritePageToDB(pPager, pPage); if (ret < 0) { tdbError("failed to write page to db since %s", tstrerror(terrno)); @@ -657,12 +645,15 @@ int tdbPagerFetchPage(SPager *pPager, SPgno *ppgno, SPage **ppPage, int (*initPa loadPage = 0; ret = tdbPagerAllocPage(pPager, &pgno); if (ret < 0) { - ASSERT(0); + tdbError("tdb/pager: %p, ret: %d pgno: %" PRIu32 ", alloc page failed.", pPager, ret, pgno); return -1; } } - ASSERT(pgno > 0); + if (pgno == 0) { + tdbError("tdb/pager: %p, ret: %d pgno: %" PRIu32 ", alloc page failed.", pPager, ret, pgno); + return -1; + } // fetch a page container memcpy(&pgid, pPager->fid, TDB_FILE_ID_LEN); @@ -676,7 +667,7 @@ int tdbPagerFetchPage(SPager *pPager, SPgno *ppgno, SPage **ppPage, int (*initPa if (!TDB_PAGE_INITIALIZED(pPage)) { ret = tdbPagerInitPage(pPager, pPage, initPage, arg, loadPage); if (ret < 0) { - ASSERT(0); + tdbError("tdb/pager: %p, pPage: %p, init page failed.", pPager, pPage); return -1; } } @@ -684,8 +675,14 @@ int tdbPagerFetchPage(SPager *pPager, SPgno *ppgno, SPage **ppPage, int (*initPa // printf("thread %" PRId64 " pager fetch page %d pgno %d ppage %p\n", taosGetSelfPthreadId(), pPage->id, // TDB_PAGE_PGNO(pPage), pPage); - ASSERT(TDB_PAGE_INITIALIZED(pPage)); - ASSERT(pPage->pPager == pPager); + if (!TDB_PAGE_INITIALIZED(pPage)) { + tdbError("tdb/pager: %p, pPage: %p, fetch page uninited.", pPager, pPage); + return -1; + } + if (pPage->pPager != pPager) { + tdbError("tdb/pager: %p/%p, fetch page failed.", pPager, pPage->pPager); + return -1; + } *ppgno = pgno; *ppPage = pPage; @@ -727,8 +724,10 @@ int tdbPagerAllocPage(SPager *pPager, SPgno *ppgno) { return -1; } - ASSERT(*ppgno != 0); - + if (*ppgno == 0) { + tdbError("tdb/pager:%p, alloc new page failed.", pPager); + return -1; + } return 0; } @@ -737,8 +736,8 @@ static int tdbPagerInitPage(SPager *pPager, SPage *pPage, int (*initPage)(SPage int ret; int lcode; int nLoops; - i64 nRead; - SPgno pgno; + i64 nRead = 0; + SPgno pgno = 0; int init = 0; lcode = TDB_TRY_LOCK_PAGE(pPage); @@ -757,7 +756,6 @@ static int tdbPagerInitPage(SPager *pPager, SPage *pPage, int (*initPage)(SPage nRead = tdbOsPRead(pPager->fd, pPage->pData, pPage->pageSize, ((i64)pPage->pageSize) * (pgno - 1)); tdbTrace("tdb/pager:%p, pgno:%d, nRead:%" PRId64, pPager, pgno, nRead); if (nRead < pPage->pageSize) { - ASSERT(0); tdbError("tdb/pager:%p, pgno:%d, nRead:%" PRId64 "pgSize:%" PRId32, pPager, pgno, nRead, pPage->pageSize); TDB_UNLOCK_PAGE(pPage); return -1; @@ -768,7 +766,8 @@ static int tdbPagerInitPage(SPager *pPager, SPage *pPage, int (*initPage)(SPage ret = (*initPage)(pPage, arg, init); if (ret < 0) { - ASSERT(0); + tdbError("tdb/pager:%p, pgno:%d, nRead:%" PRId64 "pgSize:%" PRId32 " init page failed.", pPager, pgno, nRead, + pPage->pageSize); TDB_UNLOCK_PAGE(pPage); return -1; } @@ -787,7 +786,8 @@ static int tdbPagerInitPage(SPager *pPager, SPage *pPage, int (*initPage)(SPage } } } else { - ASSERT(0); + tdbError("tdb/pager:%p, pgno:%d, nRead:%" PRId64 "pgSize:%" PRId32 " lock page failed.", pPager, pgno, nRead, + pPage->pageSize); return -1; } @@ -947,6 +947,12 @@ static int tdbPagerRestore(SPager *pPager, const char *jFileName) { return 0; } +static int32_t txnIdCompareDesc(const void *pLeft, const void *pRight) { + int64_t lhs = *(int64_t *)pLeft; + int64_t rhs = *(int64_t *)pRight; + return lhs > rhs ? -1 : 1; +} + int tdbPagerRestoreJournals(SPager *pPager) { tdbDirEntryPtr pDirEntry; tdbDirPtr pDir = taosOpenDir(pPager->pEnv->dbName); @@ -955,23 +961,33 @@ int tdbPagerRestoreJournals(SPager *pPager) { return -1; } + SArray *pTxnList = taosArrayInit(16, sizeof(int64_t)); + while ((pDirEntry = tdbReadDir(pDir)) != NULL) { char *name = tdbDirEntryBaseName(tdbGetDirEntryName(pDirEntry)); if (strncmp(TDB_MAINDB_NAME "-journal", name, 16) == 0) { - char jname[TD_PATH_MAX] = {0}; - int dirLen = strlen(pPager->pEnv->dbName); - memcpy(jname, pPager->pEnv->dbName, dirLen); - jname[dirLen] = '/'; - memcpy(jname + dirLen + 1, name, strlen(name)); - if (tdbPagerRestore(pPager, jname) < 0) { - tdbCloseDir(&pDir); - - tdbError("failed to restore file due to %s. jFileName:%s", strerror(errno), name); - return -1; - } + int64_t txnId = -1; + sscanf(name, TDB_MAINDB_NAME "-journal.%" PRId64, &txnId); + taosArrayPush(pTxnList, &txnId); + } + } + taosArraySort(pTxnList, txnIdCompareDesc); + for (int i = 0; i < TARRAY_SIZE(pTxnList); ++i) { + int64_t *pTxnId = taosArrayGet(pTxnList, i); + char jname[TD_PATH_MAX] = {0}; + int dirLen = strlen(pPager->pEnv->dbName); + memcpy(jname, pPager->pEnv->dbName, dirLen); + jname[dirLen] = '/'; + sprintf(jname + dirLen + 1, TDB_MAINDB_NAME "-journal.%" PRId64, *pTxnId); + if (tdbPagerRestore(pPager, jname) < 0) { + tdbCloseDir(&pDir); + + tdbError("failed to restore file due to %s. jFileName:%s", strerror(errno), jname); + return -1; } } + taosArrayDestroy(pTxnList); tdbCloseDir(&pDir); return 0; diff --git a/source/libs/tdb/src/db/tdbTable.c b/source/libs/tdb/src/db/tdbTable.c index 972e2f29e545ae24c9fd4dd19ec29f553480c602..18d14fa474f51104442cf689bd52649598b9c396 100644 --- a/source/libs/tdb/src/db/tdbTable.c +++ b/source/libs/tdb/src/db/tdbTable.c @@ -105,8 +105,6 @@ int tdbTbOpen(const char *tbname, int keyLen, int valLen, tdb_cmpr_fn_t keyCmprF #endif - ASSERT(pPager != NULL); - if (rollback) { ret = tdbPagerRestoreJournals(pPager); if (ret < 0) { diff --git a/source/libs/tdb/src/db/tdbTxn.c b/source/libs/tdb/src/db/tdbTxn.c index 24f955fe2fde29c089b4768baae54eaea892d09e..0aeed3c140f8317c6abcec16a9fd049f6be89e1a 100644 --- a/source/libs/tdb/src/db/tdbTxn.c +++ b/source/libs/tdb/src/db/tdbTxn.c @@ -18,7 +18,10 @@ int tdbTxnOpen(TXN *pTxn, int64_t txnid, void *(*xMalloc)(void *, size_t), void (*xFree)(void *, void *), void *xArg, int flags) { // not support read-committed version at the moment - ASSERT(flags == 0 || flags == (TDB_TXN_WRITE | TDB_TXN_READ_UNCOMMITTED)); + if (flags != 0 && flags != (TDB_TXN_WRITE | TDB_TXN_READ_UNCOMMITTED)) { + tdbError("tdb/txn: invalid txn flags: %" PRId32, flags); + return -1; + } pTxn->flags = flags; pTxn->txnId = txnid; diff --git a/source/libs/tdb/src/inc/tdbInt.h b/source/libs/tdb/src/inc/tdbInt.h index 62466e9c47de9407dbcd93584ce940a3e179cba9..7a0bcc00a42a95d1f27b23384e494416e110b2e1 100644 --- a/source/libs/tdb/src/inc/tdbInt.h +++ b/source/libs/tdb/src/inc/tdbInt.h @@ -122,6 +122,8 @@ typedef struct SBtInfo { #define TDB_CELLD_F_VAL 0x2 #define TDB_CELLDECODER_SET_FREE_NIL(pCellDecoder) ((pCellDecoder)->freeKV = TDB_CELLD_F_NIL) +#define TDB_CELLDECODER_CLZ_FREE_KEY(pCellDecoder) ((pCellDecoder)->freeKV &= ~TDB_CELLD_F_KEY) +#define TDB_CELLDECODER_CLZ_FREE_VAL(pCellDecoder) ((pCellDecoder)->freeKV &= ~TDB_CELLD_F_VAL) #define TDB_CELLDECODER_SET_FREE_KEY(pCellDecoder) ((pCellDecoder)->freeKV |= TDB_CELLD_F_KEY) #define TDB_CELLDECODER_SET_FREE_VAL(pCellDecoder) ((pCellDecoder)->freeKV |= TDB_CELLD_F_VAL) diff --git a/source/libs/tfs/src/tfs.c b/source/libs/tfs/src/tfs.c index 943611ee27c6f1d6bfa51dfff211bf723764f88f..86b36b9b12b74e0d4bb0acf9676c67c258c3062f 100644 --- a/source/libs/tfs/src/tfs.c +++ b/source/libs/tfs/src/tfs.c @@ -80,7 +80,7 @@ STfs *tfsOpen(SDiskCfg *pCfg, int32_t ndisk) { void tfsClose(STfs *pTfs) { if (pTfs == NULL) return; - for (int32_t level = 0; level < TFS_MAX_LEVEL; level++) { + for (int32_t level = 0; level <= TFS_MAX_LEVEL; level++) { tfsDestroyTier(&pTfs->tiers[level]); } @@ -240,7 +240,7 @@ int32_t tfsMkdirRecurAt(STfs *pTfs, const char *rname, SDiskID diskId) { if (tfsMkdirAt(pTfs, rname, diskId) < 0) { if (errno == ENOENT) { // Try to create upper - char *s = strdup(rname); + char *s = taosStrdup(rname); // Make a copy of dirname(s) because the implementation of 'dirname' differs on different platforms. // Some platform may modify the contents of the string passed into dirname(). Others may return a pointer to @@ -248,7 +248,7 @@ int32_t tfsMkdirRecurAt(STfs *pTfs, const char *rname, SDiskID diskId) { // the pointer directly in this recursion. // See // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dirname.3.html - char *dir = strdup(taosDirName(s)); + char *dir = taosStrdup(taosDirName(s)); if (tfsMkdirRecurAt(pTfs, dir, diskId) < 0) { taosMemoryFree(s); @@ -284,7 +284,9 @@ int32_t tfsMkdir(STfs *pTfs, const char *rname) { } int32_t tfsRmdir(STfs *pTfs, const char *rname) { - ASSERT(rname[0] != 0); + if (rname[0] == 0) { + return 0; + } char aname[TMPNAME_LEN] = "\0"; @@ -293,7 +295,7 @@ int32_t tfsRmdir(STfs *pTfs, const char *rname) { for (int32_t id = 0; id < pTier->ndisk; id++) { STfsDisk *pDisk = pTier->disks[id]; snprintf(aname, TMPNAME_LEN, "%s%s%s", pDisk->path, TD_DIRSEP, rname); - uInfo("tfs remove dir : path:%s aname:%s rname:[%s]", pDisk->path, aname, rname); + uInfo("tfs remove dir:%s aname:%s rname:[%s]", pDisk->path, aname, rname); taosRemoveDir(aname); } } @@ -301,7 +303,7 @@ int32_t tfsRmdir(STfs *pTfs, const char *rname) { return 0; } -int32_t tfsRename(STfs *pTfs, char *orname, char *nrname) { +int32_t tfsRename(STfs *pTfs, const char *orname, const char *nrname) { char oaname[TMPNAME_LEN] = "\0"; char naname[TMPNAME_LEN] = "\0"; diff --git a/source/libs/tfs/src/tfsDisk.c b/source/libs/tfs/src/tfsDisk.c index ff40529ab2d75ec90be9b35ad259594f869d048e..3717bf1a6dee9deca0df7242ccb9f0c8a70a0e08 100644 --- a/source/libs/tfs/src/tfsDisk.c +++ b/source/libs/tfs/src/tfsDisk.c @@ -23,7 +23,7 @@ STfsDisk *tfsNewDisk(int32_t level, int32_t id, const char *path) { return NULL; } - pDisk->path = strdup(path); + pDisk->path = taosStrdup(path); if (pDisk->path == NULL) { taosMemoryFree(pDisk); terrno = TSDB_CODE_OUT_OF_MEMORY; diff --git a/source/libs/transport/inc/transComm.h b/source/libs/transport/inc/transComm.h index 5f964f6b1ab0e7145f61b25e2e51a1a1d1c86a9e..a2c486767f931ac7644217dba24d9cab55b48c7e 100644 --- a/source/libs/transport/inc/transComm.h +++ b/source/libs/transport/inc/transComm.h @@ -22,6 +22,7 @@ extern "C" { #include "os.h" #include "taoserror.h" #include "theap.h" +#include "tmisce.h" #include "transLog.h" #include "transportInt.h" #include "trpc.h" @@ -94,8 +95,8 @@ typedef void* queue[2]; /* Return the structure holding the given element. */ #define QUEUE_DATA(e, type, field) ((type*)((void*)((char*)(e)-offsetof(type, field)))) -//#define TRANS_RETRY_COUNT_LIMIT 100 // retry count limit -//#define TRANS_RETRY_INTERVAL 15 // retry interval (ms) +// #define TRANS_RETRY_COUNT_LIMIT 100 // retry count limit +// #define TRANS_RETRY_INTERVAL 15 // retry interval (ms) #define TRANS_CONN_TIMEOUT 3000 // connect timeout (ms) #define TRANS_READ_TIMEOUT 3000 // read timeout (ms) #define TRANS_PACKET_LIMIT 1024 * 1024 * 512 @@ -147,7 +148,8 @@ typedef struct { int8_t epsetRetryCnt; int32_t retryCode; - int hThrdIdx; + void* task; + int hThrdIdx; } STransConnCtx; #pragma pack(push, 1) diff --git a/source/libs/transport/inc/transportInt.h b/source/libs/transport/inc/transportInt.h index 2db4a72795566d3a52d55650d275fe9c65c54ae5..8ea0064d4485c031a49b39bad70fd41e0aec7a85 100644 --- a/source/libs/transport/inc/transportInt.h +++ b/source/libs/transport/inc/transportInt.h @@ -64,6 +64,11 @@ typedef struct { void (*destroyFp)(void* ahandle); bool (*failFastFp)(tmsg_t msgType); + int32_t connLimitNum; + int8_t connLimitLock; // 0: no lock. 1. lock + int8_t supportBatch; // 0: no batch, 1: support batch + int32_t batchSize; + int32_t timeToGetConn; int index; void* parent; void* tcphandle; // returned handle from TCP initialization diff --git a/source/libs/transport/src/thttp.c b/source/libs/transport/src/thttp.c index 8e5f79137fd5f693e012849ce468fffed2870fa9..04b546b36a48bd1df071c7b077d82c57c2ddea8a 100644 --- a/source/libs/transport/src/thttp.c +++ b/source/libs/transport/src/thttp.c @@ -26,6 +26,8 @@ #define HTTP_RECV_BUF_SIZE 1024 +static int32_t httpRefMgt = 0; +static int64_t httpRef = -1; typedef struct SHttpModule { uv_loop_t* loop; SAsyncPool* asyncPool; @@ -41,7 +43,6 @@ typedef struct SHttpMsg { int32_t len; EHttpCompFlag flag; int8_t quit; - SHttpModule* http; } SHttpMsg; @@ -57,7 +58,6 @@ typedef struct SHttpClient { } SHttpClient; static TdThreadOnce transHttpInit = PTHREAD_ONCE_INIT; -static SHttpModule* thttp = NULL; static void transHttpEnvInit(); static void httpHandleReq(SHttpMsg* msg); @@ -280,26 +280,29 @@ static void clientConnCb(uv_connect_t* req, int32_t status) { } int32_t httpSendQuit() { + SHttpModule* http = taosAcquireRef(httpRefMgt, httpRef); + if (http == NULL) return 0; + SHttpMsg* msg = taosMemoryCalloc(1, sizeof(SHttpMsg)); msg->quit = 1; - SHttpModule* load = atomic_load_ptr(&thttp); - if (load == NULL) { - httpDestroyMsg(msg); - tError("http-report already released"); - return -1; - } else { - msg->http = load; - } - transAsyncSend(load->asyncPool, &(msg->q)); + transAsyncSend(http->asyncPool, &(msg->q)); + taosReleaseRef(httpRefMgt, httpRef); return 0; } static int32_t taosSendHttpReportImpl(const char* server, const char* uri, uint16_t port, char* pCont, int32_t contLen, EHttpCompFlag flag) { + SHttpModule* load = taosAcquireRef(httpRefMgt, httpRef); + if (load == NULL) { + tError("http-report already released"); + return -1; + } + SHttpMsg* msg = taosMemoryMalloc(sizeof(SHttpMsg)); - msg->server = strdup(server); - msg->uri = strdup(uri); + + msg->server = taosStrdup(server); + msg->uri = taosStrdup(uri); msg->port = port; msg->cont = taosMemoryMalloc(contLen); memcpy(msg->cont, pCont, contLen); @@ -307,15 +310,9 @@ static int32_t taosSendHttpReportImpl(const char* server, const char* uri, uint1 msg->flag = flag; msg->quit = 0; - SHttpModule* load = atomic_load_ptr(&thttp); - if (load == NULL) { - httpDestroyMsg(msg); - tError("http-report already released"); - return -1; - } - - msg->http = load; - return transAsyncSend(load->asyncPool, &(msg->q)); + int ret = transAsyncSend(load->asyncPool, &(msg->q)); + taosReleaseRef(httpRefMgt, httpRef); + return ret; } static void httpDestroyClientCb(uv_handle_t* handle) { @@ -335,13 +332,19 @@ static void httpWalkCb(uv_handle_t* handle, void* arg) { return; } static void httpHandleQuit(SHttpMsg* msg) { - SHttpModule* http = msg->http; taosMemoryFree(msg); + SHttpModule* http = taosAcquireRef(httpRefMgt, httpRef); + if (http == NULL) return; + uv_walk(http->loop, httpWalkCb, NULL); + taosReleaseRef(httpRefMgt, httpRef); } static void httpHandleReq(SHttpMsg* msg) { - SHttpModule* http = msg->http; + SHttpModule* http = taosAcquireRef(httpRefMgt, httpRef); + if (http == NULL) { + goto END; + } struct sockaddr_in dest = {0}; if (taosBuildDstAddr(msg->server, msg->port, &dest) < 0) { @@ -391,6 +394,7 @@ static void httpHandleReq(SHttpMsg* msg) { int ret = uv_tcp_open((uv_tcp_t*)&cli->tcp, fd); if (ret != 0) { tError("http-report failed to open socket, reason:%s, dst:%s:%d", uv_strerror(ret), cli->addr, cli->port); + taosReleaseRef(httpRefMgt, httpRef); destroyHttpClient(cli); return; } @@ -401,21 +405,26 @@ static void httpHandleReq(SHttpMsg* msg) { cli->port); destroyHttpClient(cli); } + taosReleaseRef(httpRefMgt, httpRef); return; END: tError("http-report failed to report, reason: %s, addr: %s:%d", terrstr(), msg->server, msg->port); httpDestroyMsg(msg); + taosReleaseRef(httpRefMgt, httpRef); } -int32_t taosSendHttpReport(const char* server, const char* uri, uint16_t port, char* pCont, int32_t contLen, EHttpCompFlag flag) { +int32_t taosSendHttpReport(const char* server, const char* uri, uint16_t port, char* pCont, int32_t contLen, + EHttpCompFlag flag) { taosThreadOnce(&transHttpInit, transHttpEnvInit); return taosSendHttpReportImpl(server, uri, port, pCont, contLen, flag); } +static void transHttpDestroyHandle(void* handle) { taosMemoryFree(handle); } static void transHttpEnvInit() { - SHttpModule* http = taosMemoryMalloc(sizeof(SHttpModule)); + httpRefMgt = taosOpenRef(1, transHttpDestroyHandle); + SHttpModule* http = taosMemoryMalloc(sizeof(SHttpModule)); http->loop = taosMemoryMalloc(sizeof(uv_loop_t)); uv_loop_init(http->loop); @@ -426,21 +435,22 @@ static void transHttpEnvInit() { http = NULL; return; } - + int err = taosThreadCreate(&http->thread, NULL, httpThread, (void*)http); if (err != 0) { taosMemoryFree(http->loop); taosMemoryFree(http); http = NULL; } - atomic_store_ptr(&thttp, http); + httpRef = taosAddRef(httpRefMgt, http); } void transHttpEnvDestroy() { - SHttpModule* load = atomic_load_ptr(&thttp); - if (load == NULL) { + // remove http + if (httpRef == -1) { return; } + SHttpModule* load = taosAcquireRef(httpRefMgt, httpRef); httpSendQuit(); taosThreadJoin(load->thread, NULL); @@ -448,7 +458,7 @@ void transHttpEnvDestroy() { transAsyncPoolDestroy(load->asyncPool); uv_loop_close(load->loop); taosMemoryFree(load->loop); - taosMemoryFree(load); - atomic_store_ptr(&thttp, NULL); + taosReleaseRef(httpRefMgt, httpRef); + taosRemoveRef(httpRefMgt, httpRef); } diff --git a/source/libs/transport/src/tmsgcb.c b/source/libs/transport/src/tmsgcb.c index af2528bc9247adab655227bc8761f66ed1678491..fc95cab76e867817e53c4bde6b6507e9472a40f5 100644 --- a/source/libs/transport/src/tmsgcb.c +++ b/source/libs/transport/src/tmsgcb.c @@ -59,12 +59,16 @@ void tmsgReleaseHandle(SRpcHandleInfo* pHandle, int8_t type) { (*defaultMsgCb.re void tmsgReportStartup(const char* name, const char* desc) { (*defaultMsgCb.reportStartupFp)(name, desc); } -void tmsgUpdateDnodeInfo(int32_t* dnodeId, int64_t* clusterId, char* fqdn, uint16_t* port) { - (*defaultMsgCb.updateDnodeInfoFp)(defaultMsgCb.data, dnodeId, clusterId, fqdn, port); +bool tmsgUpdateDnodeInfo(int32_t* dnodeId, int64_t* clusterId, char* fqdn, uint16_t* port) { + if (defaultMsgCb.updateDnodeInfoFp) { + return (*defaultMsgCb.updateDnodeInfoFp)(defaultMsgCb.data, dnodeId, clusterId, fqdn, port); + } else { + return false; + } } void tmsgUpdateDnodeEpSet(SEpSet* epset) { for (int32_t i = 0; i < epset->numOfEps; ++i) { tmsgUpdateDnodeInfo(NULL, NULL, epset->eps[i].fqdn, &epset->eps[i].port); } -} \ No newline at end of file +} diff --git a/source/libs/transport/src/trans.c b/source/libs/transport/src/trans.c index 47b1ac5ca7c8a46d435ea7c412b2c7adf25d5081..0771f9198aa5e20fe37b95070781b81d01200351 100644 --- a/source/libs/transport/src/trans.c +++ b/source/libs/transport/src/trans.c @@ -13,8 +13,6 @@ * along with this program. If not, see . */ -#ifdef USE_UV - #include "transComm.h" void* (*taosInitHandle[])(uint32_t ip, uint32_t port, char* label, int32_t numOfThreads, void* fp, void* shandle) = { @@ -67,6 +65,14 @@ void* rpcOpen(const SRpcInit* pInit) { pRpc->startTimer = pInit->tfp; pRpc->destroyFp = pInit->dfp; pRpc->failFastFp = pInit->ffp; + pRpc->connLimitNum = pInit->connLimitNum; + if (pRpc->connLimitNum == 0) { + pRpc->connLimitNum = 20; + } + + pRpc->connLimitLock = pInit->connLimitLock; + pRpc->supportBatch = pInit->supportBatch; + pRpc->batchSize = pInit->batchSize; pRpc->numOfThreads = pInit->numOfThreads > TSDB_MAX_RPC_THREADS ? TSDB_MAX_RPC_THREADS : pInit->numOfThreads; if (pRpc->numOfThreads <= 0) { @@ -84,6 +90,14 @@ void* rpcOpen(const SRpcInit* pInit) { pRpc->connType = pInit->connType; pRpc->idleTime = pInit->idleTime; + pRpc->parent = pInit->parent; + if (pInit->user) { + tstrncpy(pRpc->user, pInit->user, sizeof(pRpc->user)); + } + pRpc->timeToGetConn = pInit->timeToGetConn; + if (pRpc->timeToGetConn == 0) { + pRpc->timeToGetConn = 10 * 1000; + } pRpc->tcphandle = (*taosInitHandle[pRpc->connType])(ip, pInit->localPort, pRpc->label, pRpc->numOfThreads, NULL, pRpc); @@ -91,10 +105,6 @@ void* rpcOpen(const SRpcInit* pInit) { taosMemoryFree(pRpc); return NULL; } - pRpc->parent = pInit->parent; - if (pInit->user) { - tstrncpy(pRpc->user, pInit->user, sizeof(pRpc->user)); - } int64_t refId = transAddExHandle(transGetInstMgt(), pRpc); transAcquireExHandle(transGetInstMgt(), refId); @@ -184,5 +194,3 @@ void rpcCleanup(void) { return; } - -#endif diff --git a/source/libs/transport/src/transCli.c b/source/libs/transport/src/transCli.c index 111742a6f448b735fb16d7df48bf1fc3cc479393..1709fc3cb12c21e02fab36a8bf7a9a229e6095f0 100644 --- a/source/libs/transport/src/transCli.c +++ b/source/libs/transport/src/transCli.c @@ -12,14 +12,43 @@ * along with this program. If not, see . */ -#ifdef USE_UV #include "transComm.h" +typedef struct { + int32_t numOfConn; + queue msgQ; +} SMsgList; + typedef struct SConnList { - queue conns; - int32_t size; + queue conns; + int32_t size; + SMsgList* list; } SConnList; +typedef struct { + queue wq; + int32_t len; + + int connMax; + int connCnt; + int batchLenLimit; + int sending; + + char* dst; + char* ip; + uint16_t port; + +} SCliBatchList; + +typedef struct { + queue wq; + queue listq; + int32_t wLen; + int32_t batchSize; // + int32_t batch; + SCliBatchList* pList; +} SCliBatch; + typedef struct SCliConn { T_REF_DECLARE() uv_connect_t connReq; @@ -40,16 +69,15 @@ typedef struct SCliConn { bool broken; // link broken or not ConnStatus status; // - int64_t refId; - char* ip; - uint32_t port; + SCliBatch* pBatch; SDelayTask* task; - // debug and log info - char src[32]; - char dst[32]; + char* ip; + char src[32]; + char dst[32]; + int64_t refId; } SCliConn; typedef struct SCliMsg { @@ -77,18 +105,24 @@ typedef struct SCliThrd { TdThreadMutex msgMtx; SDelayQueue* delayQueue; SDelayQueue* timeoutQueue; + SDelayQueue* waitConnQueue; uint64_t nextTimeout; // next timeout void* pTransInst; // + int connCount; void (*destroyAhandleFp)(void* ahandle); SHashObj* fqdn2ipCache; SCvtAddr cvtAddr; SHashObj* failFastCache; + SHashObj* batchCache; SCliMsg* stopMsg; bool quit; + + int newConnCount; + SHashObj* msgCount; } SCliThrd; typedef struct SCliObj { @@ -105,11 +139,12 @@ typedef struct { int32_t threshold; int64_t interval; } SFailFastItem; + // conn pool // add expire timeout and capacity limit static void* createConnPool(int size); -static void* destroyConnPool(void* pool); -static SCliConn* getConnFromPool(void* pool, char* ip, uint32_t port); +static void* destroyConnPool(SCliThrd* thread); +static SCliConn* getConnFromPool(SCliThrd* thread, char* key, bool* exceed); static void addConnToPool(void* pool, SCliConn* conn); static void doCloseIdleConn(void* param); @@ -131,6 +166,11 @@ static void cliAsyncCb(uv_async_t* handle); static void cliIdleCb(uv_idle_t* handle); static void cliPrepareCb(uv_prepare_t* handle); +static void cliHandleBatchReq(SCliBatch* pBatch, SCliThrd* pThrd); +static void cliSendBatchCb(uv_write_t* req, int status); + +SCliBatch* cliGetHeadFromList(SCliBatchList* pList); + static bool cliRecvReleaseReq(SCliConn* conn, STransMsgHead* pHead); static int32_t allocConnRef(SCliConn* conn, bool update); @@ -141,8 +181,12 @@ static SCliConn* cliCreateConn(SCliThrd* thrd); static void cliDestroyConn(SCliConn* pConn, bool clear /*clear tcp handle or not*/); static void cliDestroy(uv_handle_t* handle); static void cliSend(SCliConn* pConn); +static void cliSendBatch(SCliConn* pConn); static void cliDestroyConnMsgs(SCliConn* conn, bool destroy); +static void doFreeTimeoutMsg(void* param); +static int32_t cliPreCheckSessionLimitForMsg(SCliThrd* pThrd, char* addr, SCliMsg** pMsg); + // cli util func static FORCE_INLINE bool cliIsEpsetUpdated(int32_t code, STransConnCtx* pCtx); static FORCE_INLINE void cliMayCvtFqdnToIp(SEpSet* pEpSet, SCvtAddr* pCvtAddr); @@ -157,7 +201,9 @@ static void cliHandleResp(SCliConn* conn); // handle except about conn static void cliHandleExcept(SCliConn* conn); static void cliReleaseUnfinishedMsg(SCliConn* conn); +static void cliHandleFastFail(SCliConn* pConn, int status); +static void doNotifyApp(SCliMsg* pMsg, SCliThrd* pThrd); // handle req from app static void cliHandleReq(SCliMsg* pMsg, SCliThrd* pThrd); static void cliHandleQuit(SCliMsg* pMsg, SCliThrd* pThrd); @@ -165,6 +211,8 @@ static void cliHandleRelease(SCliMsg* pMsg, SCliThrd* pThrd); static void cliHandleUpdate(SCliMsg* pMsg, SCliThrd* pThrd); static void (*cliAsyncHandle[])(SCliMsg* pMsg, SCliThrd* pThrd) = {cliHandleReq, cliHandleQuit, cliHandleRelease, NULL, cliHandleUpdate}; +/// static void (*cliAsyncHandle[])(SCliMsg* pMsg, SCliThrd* pThrd) = {cliHandleReq, cliHandleQuit, cliHandleRelease, +/// NULL,cliHandleUpdate}; static FORCE_INLINE void destroyUserdata(STransMsg* userdata); static FORCE_INLINE void destroyCmsg(void* cmsg); @@ -186,9 +234,13 @@ static void cliWalkCb(uv_handle_t* handle, void* arg); } while (0); // snprintf may cause performance problem -#define CONN_CONSTRUCT_HASH_KEY(key, ip, port) \ - do { \ - snprintf(key, sizeof(key), "%s:%d", ip, (int)port); \ +#define CONN_CONSTRUCT_HASH_KEY(key, ip, port) \ + do { \ + char* t = key; \ + int16_t len = strlen(ip); \ + if (ip != NULL) memcpy(t, ip, len); \ + t[len] = ':'; \ + titoa(port, 10, &t[len + 1]); \ } while (0) #define CONN_PERSIST_TIME(para) ((para) <= 90000 ? 90000 : (para)) @@ -285,18 +337,15 @@ static void cliReleaseUnfinishedMsg(SCliConn* conn) { } destroyCmsg(msg); } + transQueueClear(&conn->cliMsgs); memset(&conn->ctx, 0, sizeof(conn->ctx)); } bool cliMaySendCachedMsg(SCliConn* conn) { if (!transQueueEmpty(&conn->cliMsgs)) { SCliMsg* pCliMsg = NULL; CONN_GET_NEXT_SENDMSG(conn); - if (pCliMsg == NULL) - return false; - else { - cliSend(conn); - return true; - } + cliSend(conn); + return true; } return false; _RETURN: @@ -320,6 +369,7 @@ void cliHandleResp(SCliConn* conn) { int32_t msgLen = transDumpFromBuffer(&conn->readBuf, (char**)&pHead); if (msgLen <= 0) { + taosMemoryFree(pHead); tDebug("%s conn %p recv invalid packet ", CONN_GET_INST_LABEL(conn), conn); return; } @@ -412,6 +462,7 @@ void cliHandleExceptImpl(SCliConn* pConn, int32_t code) { if (transQueueEmpty(&pConn->cliMsgs)) { if (pConn->broken == true && CONN_NO_PERSIST_BY_APP(pConn)) { tTrace("%s conn %p handle except, persist:0", CONN_GET_INST_LABEL(pConn), pConn); + if (T_REF_VAL_GET(pConn) > 1) transUnrefCliHandle(pConn); transUnrefCliHandle(pConn); return; } @@ -471,6 +522,7 @@ void cliHandleExceptImpl(SCliConn* pConn, int32_t code) { destroyCmsg(pMsg); tTrace("%s conn %p start to destroy, ref:%d", CONN_GET_INST_LABEL(pConn), pConn, T_REF_VAL_GET(pConn)); } while (!transQueueEmpty(&pConn->cliMsgs)); + if (T_REF_VAL_GET(pConn) > 1) transUnrefCliHandle(pConn); transUnrefCliHandle(pConn); } void cliHandleExcept(SCliConn* conn) { @@ -487,9 +539,9 @@ void cliConnTimeout(uv_timer_t* handle) { uv_timer_stop(handle); handle->data = NULL; taosArrayPush(pThrd->timerList, &conn->timer); - conn->timer = NULL; - cliHandleExceptImpl(conn, -1); + + cliHandleFastFail(conn, UV_ECANCELED); } void cliReadTimeoutCb(uv_timer_t* handle) { // set up timeout cb @@ -503,7 +555,8 @@ void* createConnPool(int size) { // thread local, no lock return taosHashInit(size, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); } -void* destroyConnPool(void* pool) { +void* destroyConnPool(SCliThrd* pThrd) { + void* pool = pThrd->pool; SConnList* connList = taosHashIterate((SHashObj*)pool, NULL); while (connList != NULL) { while (!QUEUE_IS_EMPTY(&connList->conns)) { @@ -511,34 +564,131 @@ void* destroyConnPool(void* pool) { SCliConn* c = QUEUE_DATA(h, SCliConn, q); cliDestroyConn(c, true); } + + SMsgList* msglist = connList->list; + while (!QUEUE_IS_EMPTY(&msglist->msgQ)) { + queue* h = QUEUE_HEAD(&msglist->msgQ); + QUEUE_REMOVE(h); + + SCliMsg* pMsg = QUEUE_DATA(h, SCliMsg, q); + + transDQCancel(pThrd->waitConnQueue, pMsg->ctx->task); + pMsg->ctx->task = NULL; + + doNotifyApp(pMsg, pThrd); + } + taosMemoryFree(msglist); + connList = taosHashIterate((SHashObj*)pool, connList); } taosHashCleanup(pool); return NULL; } -static SCliConn* getConnFromPool(void* pool, char* ip, uint32_t port) { - char key[TSDB_FQDN_LEN + 64] = {0}; - CONN_CONSTRUCT_HASH_KEY(key, ip, port); +static SCliConn* getConnFromPool(SCliThrd* pThrd, char* key, bool* exceed) { + void* pool = pThrd->pool; + SConnList* plist = taosHashGet((SHashObj*)pool, key, strlen(key) + 1); + STrans* pTranInst = pThrd->pTransInst; + if (plist == NULL) { + SConnList list = {0}; + taosHashPut((SHashObj*)pool, key, strlen(key) + 1, (void*)&list, sizeof(list)); + plist = taosHashGet(pool, key, strlen(key) + 1); + + SMsgList* nList = taosMemoryCalloc(1, sizeof(SMsgList)); + QUEUE_INIT(&nList->msgQ); + nList->numOfConn++; + + QUEUE_INIT(&plist->conns); + plist->list = nList; + } + + if (QUEUE_IS_EMPTY(&plist->conns)) { + if (plist->list->numOfConn >= pTranInst->connLimitNum) { + *exceed = true; + } + return NULL; + } + + queue* h = QUEUE_TAIL(&plist->conns); + QUEUE_REMOVE(h); + plist->size -= 1; + + SCliConn* conn = QUEUE_DATA(h, SCliConn, q); + conn->status = ConnNormal; + QUEUE_INIT(&conn->q); + + if (conn->task != NULL) { + transDQCancel(((SCliThrd*)conn->hostThrd)->timeoutQueue, conn->task); + conn->task = NULL; + } + return conn; +} - SConnList* plist = taosHashGet((SHashObj*)pool, key, strlen(key)); +static SCliConn* getConnFromPool2(SCliThrd* pThrd, char* key, SCliMsg** pMsg) { + void* pool = pThrd->pool; + STrans* pTransInst = pThrd->pTransInst; + SConnList* plist = taosHashGet((SHashObj*)pool, key, strlen(key) + 1); if (plist == NULL) { SConnList list = {0}; - taosHashPut((SHashObj*)pool, key, strlen(key), (void*)&list, sizeof(list)); - plist = taosHashGet((SHashObj*)pool, key, strlen(key)); - if (plist == NULL) return NULL; + taosHashPut((SHashObj*)pool, key, strlen(key) + 1, (void*)&list, sizeof(list)); + plist = taosHashGet(pool, key, strlen(key) + 1); + + SMsgList* nList = taosMemoryCalloc(1, sizeof(SMsgList)); + QUEUE_INIT(&nList->msgQ); + nList->numOfConn++; + QUEUE_INIT(&plist->conns); + plist->list = nList; } + STraceId* trace = &(*pMsg)->msg.info.traceId; + // no avaliable conn in pool if (QUEUE_IS_EMPTY(&plist->conns)) { + SMsgList* list = plist->list; + if ((list)->numOfConn >= pTransInst->connLimitNum) { + STraceId* trace = &(*pMsg)->msg.info.traceId; + STaskArg* arg = taosMemoryMalloc(sizeof(STaskArg)); + arg->param1 = *pMsg; + arg->param2 = pThrd; + (*pMsg)->ctx->task = transDQSched(pThrd->waitConnQueue, doFreeTimeoutMsg, arg, pTransInst->timeToGetConn); + + tGTrace("%s msg %s delay to send, wait for avaiable connect", pTransInst->label, TMSG_INFO((*pMsg)->msg.msgType)); + + QUEUE_PUSH(&(list)->msgQ, &(*pMsg)->q); + *pMsg = NULL; + } else { + // send msg in delay queue + if (!(QUEUE_IS_EMPTY(&(list)->msgQ))) { + STaskArg* arg = taosMemoryMalloc(sizeof(STaskArg)); + arg->param1 = *pMsg; + arg->param2 = pThrd; + (*pMsg)->ctx->task = transDQSched(pThrd->waitConnQueue, doFreeTimeoutMsg, arg, pTransInst->timeToGetConn); + tGTrace("%s msg %s delay to send, wait for avaiable connect", pTransInst->label, + TMSG_INFO((*pMsg)->msg.msgType)); + + QUEUE_PUSH(&(list)->msgQ, &(*pMsg)->q); + queue* h = QUEUE_HEAD(&(list)->msgQ); + QUEUE_REMOVE(h); + SCliMsg* ans = QUEUE_DATA(h, SCliMsg, q); + + *pMsg = ans; + + trace = &(*pMsg)->msg.info.traceId; + tGTrace("%s msg %s pop from delay queue, start to send", pTransInst->label, TMSG_INFO((*pMsg)->msg.msgType)); + transDQCancel(pThrd->waitConnQueue, ans->ctx->task); + } + list->numOfConn++; + } + tTrace("%s numOfConn: %d, limit: %d", pTransInst->label, list->numOfConn, pTransInst->connLimitNum); return NULL; } + queue* h = QUEUE_TAIL(&plist->conns); plist->size -= 1; - queue* h = QUEUE_HEAD(&plist->conns); + QUEUE_REMOVE(h); + SCliConn* conn = QUEUE_DATA(h, SCliConn, q); conn->status = ConnNormal; - QUEUE_REMOVE(&conn->q); QUEUE_INIT(&conn->q); if (conn->task != NULL) { @@ -566,20 +716,34 @@ static void addConnToPool(void* pool, SCliConn* conn) { cliDestroyConnMsgs(conn, false); - conn->status = ConnInPool; - if (conn->list == NULL) { - char key[TSDB_FQDN_LEN + 64] = {0}; - CONN_CONSTRUCT_HASH_KEY(key, conn->ip, conn->port); - tTrace("%s conn %p added to conn pool, read buf cap:%d", CONN_GET_INST_LABEL(conn), conn, conn->readBuf.cap); - conn->list = taosHashGet((SHashObj*)pool, key, strlen(key)); - } else { - tTrace("%s conn %p added to conn pool, read buf cap:%d", CONN_GET_INST_LABEL(conn), conn, conn->readBuf.cap); + conn->list = taosHashGet((SHashObj*)pool, conn->ip, strlen(conn->ip) + 1); } + + SConnList* pList = conn->list; + SMsgList* msgList = pList->list; + if (!QUEUE_IS_EMPTY(&msgList->msgQ)) { + queue* h = QUEUE_HEAD(&(msgList)->msgQ); + QUEUE_REMOVE(h); + + SCliMsg* pMsg = QUEUE_DATA(h, SCliMsg, q); + + transDQCancel(thrd->waitConnQueue, pMsg->ctx->task); + pMsg->ctx->task = NULL; + + transCtxMerge(&conn->ctx, &pMsg->ctx->appCtx); + transQueuePush(&conn->cliMsgs, pMsg); + + conn->status = ConnNormal; + cliSend(conn); + return; + } + + conn->status = ConnInPool; QUEUE_PUSH(&conn->list->conns, &conn->q); conn->list->size += 1; - if (conn->list->size >= 50) { + if (conn->list->size >= 20) { STaskArg* arg = taosMemoryCalloc(1, sizeof(STaskArg)); arg->param1 = conn; arg->param2 = thrd; @@ -627,7 +791,6 @@ static int32_t specifyConnRef(SCliConn* conn, bool update, int64_t handle) { static void cliAllocRecvBufferCb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { SCliConn* conn = handle->data; SConnBuffer* pBuf = &conn->readBuf; - tDebug("%s conn %p alloc read buf", CONN_GET_INST_LABEL(conn), conn); transAllocBuffer(pBuf, buf); } static void cliRecvCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { @@ -640,7 +803,7 @@ static void cliRecvCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { if (nread > 0) { pBuf->len += nread; while (transReadComplete(pBuf)) { - tDebug("%s conn %p read complete", CONN_GET_INST_LABEL(conn), conn); + tTrace("%s conn %p read complete", CONN_GET_INST_LABEL(conn), conn); if (pBuf->invalid) { cliHandleExcept(conn); break; @@ -659,7 +822,8 @@ static void cliRecvCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { return; } if (nread < 0) { - tWarn("%s conn %p read error:%s, ref:%d", CONN_GET_INST_LABEL(conn), conn, uv_err_name(nread), T_REF_VAL_GET(conn)); + tDebug("%s conn %p read error:%s, ref:%d", CONN_GET_INST_LABEL(conn), conn, uv_err_name(nread), + T_REF_VAL_GET(conn)); conn->broken = true; cliHandleExcept(conn); } @@ -671,7 +835,6 @@ static SCliConn* cliCreateConn(SCliThrd* pThrd) { conn->stream = (uv_stream_t*)taosMemoryMalloc(sizeof(uv_tcp_t)); uv_tcp_init(pThrd->loop, (uv_tcp_t*)(conn->stream)); conn->stream->data = conn; - // transSetConnOption((uv_tcp_t*)conn->stream); uv_timer_t* timer = taosArrayGetSize(pThrd->timerList) > 0 ? *(uv_timer_t**)taosArrayPop(pThrd->timerList) : NULL; if (timer == NULL) { @@ -691,9 +854,10 @@ static SCliConn* cliCreateConn(SCliThrd* pThrd) { QUEUE_INIT(&conn->q); conn->hostThrd = pThrd; conn->status = ConnNormal; - conn->broken = 0; + conn->broken = false; transRefCliHandle(conn); + atomic_add_fetch_32(&pThrd->connCount, 1); allocConnRef(conn, false); return conn; @@ -701,8 +865,23 @@ static SCliConn* cliCreateConn(SCliThrd* pThrd) { static void cliDestroyConn(SCliConn* conn, bool clear) { SCliThrd* pThrd = conn->hostThrd; tTrace("%s conn %p remove from conn pool", CONN_GET_INST_LABEL(conn), conn); + conn->broken = true; QUEUE_REMOVE(&conn->q); QUEUE_INIT(&conn->q); + + conn->broken = true; + + if (conn->list != NULL) { + SConnList* connList = conn->list; + connList->list->numOfConn--; + connList->size--; + } else { + SConnList* connList = taosHashGet((SHashObj*)pThrd->pool, conn->ip, strlen(conn->ip) + 1); + if (connList != NULL) connList->list->numOfConn--; + } + conn->list = NULL; + pThrd->newConnCount--; + transReleaseExHandle(transGetRefMgt(), conn->refId); transRemoveExHandle(transGetRefMgt(), conn->refId); conn->refId = -1; @@ -738,6 +917,8 @@ static void cliDestroy(uv_handle_t* handle) { conn->timer = NULL; } + atomic_sub_fetch_32(&pThrd->connCount, 1); + transReleaseExHandle(transGetRefMgt(), conn->refId); transRemoveExHandle(transGetRefMgt(), conn->refId); taosMemoryFree(conn->ip); @@ -748,6 +929,7 @@ static void cliDestroy(uv_handle_t* handle) { tTrace("%s conn %p destroy successfully", CONN_GET_INST_LABEL(conn), conn); transReqQueueClear(&conn->wreqQueue); transDestroyBuffer(&conn->readBuf); + taosMemoryFree(conn); } static bool cliHandleNoResp(SCliConn* conn) { @@ -784,7 +966,7 @@ static void cliSendCb(uv_write_t* req, int status) { } if (status == 0) { - tTrace("%s conn %p data already was written out", CONN_GET_INST_LABEL(pConn), pConn); + tDebug("%s conn %p data already was written out", CONN_GET_INST_LABEL(pConn), pConn); } else { if (!uv_is_closing((uv_handle_t*)&pConn->stream)) { tError("%s conn %p failed to write:%s", CONN_GET_INST_LABEL(pConn), pConn, uv_err_name(status)); @@ -798,7 +980,65 @@ static void cliSendCb(uv_write_t* req, int status) { } uv_read_start((uv_stream_t*)pConn->stream, cliAllocRecvBufferCb, cliRecvCb); } +void cliSendBatch(SCliConn* pConn) { + SCliThrd* pThrd = pConn->hostThrd; + STrans* pTransInst = pThrd->pTransInst; + SCliBatch* pBatch = pConn->pBatch; + SCliBatchList* pList = pBatch->pList; + pList->connCnt += 1; + + int32_t wLen = pBatch->wLen; + + uv_buf_t* wb = taosMemoryCalloc(wLen, sizeof(uv_buf_t)); + int i = 0; + + queue* h = NULL; + QUEUE_FOREACH(h, &pBatch->wq) { + SCliMsg* pCliMsg = QUEUE_DATA(h, SCliMsg, q); + + STransConnCtx* pCtx = pCliMsg->ctx; + + STransMsg* pMsg = (STransMsg*)(&pCliMsg->msg); + if (pMsg->pCont == 0) { + pMsg->pCont = (void*)rpcMallocCont(0); + pMsg->contLen = 0; + } + + int msgLen = transMsgLenFromCont(pMsg->contLen); + STransMsgHead* pHead = transHeadFromCont(pMsg->pCont); + + if (pHead->comp == 0) { + pHead->ahandle = pCtx != NULL ? (uint64_t)pCtx->ahandle : 0; + pHead->noResp = REQUEST_NO_RESP(pMsg) ? 1 : 0; + pHead->persist = REQUEST_PERSIS_HANDLE(pMsg) ? 1 : 0; + pHead->msgType = pMsg->msgType; + pHead->msgLen = (int32_t)htonl((uint32_t)msgLen); + pHead->release = REQUEST_RELEASE_HANDLE(pCliMsg) ? 1 : 0; + memcpy(pHead->user, pTransInst->user, strlen(pTransInst->user)); + pHead->traceId = pMsg->info.traceId; + pHead->magicNum = htonl(TRANS_MAGIC_NUM); + } + pHead->timestamp = taosHton64(taosGetTimestampUs()); + + if (pHead->comp == 0) { + if (pTransInst->compressSize != -1 && pTransInst->compressSize < pMsg->contLen) { + msgLen = transCompressMsg(pMsg->pCont, pMsg->contLen) + sizeof(STransMsgHead); + pHead->msgLen = (int32_t)htonl((uint32_t)msgLen); + } + } else { + msgLen = (int32_t)ntohl((uint32_t)(pHead->msgLen)); + } + wb[i++] = uv_buf_init((char*)pHead, msgLen); + } + + uv_write_t* req = taosMemoryCalloc(1, sizeof(uv_write_t)); + req->data = pConn; + tDebug("%s conn %p start to send batch msg, batch size:%d, msgLen:%d", CONN_GET_INST_LABEL(pConn), pConn, + pBatch->wLen, pBatch->batchSize); + uv_write(req, (uv_stream_t*)pConn->stream, wb, wLen, cliSendBatchCb); + taosMemoryFree(wb); +} void cliSend(SCliConn* pConn) { SCliThrd* pThrd = pConn->hostThrd; STrans* pTransInst = pThrd->pTransInst; @@ -883,31 +1123,154 @@ _RETURN: return; } -void cliConnCb(uv_connect_t* req, int status) { - SCliConn* pConn = req->data; - SCliThrd* pThrd = pConn->hostThrd; +static void cliDestroyBatch(SCliBatch* pBatch) { + if (pBatch == NULL) return; + while (!QUEUE_IS_EMPTY(&pBatch->wq)) { + queue* h = QUEUE_HEAD(&pBatch->wq); + QUEUE_REMOVE(h); - if (pConn->timer != NULL) { - uv_timer_stop(pConn->timer); - pConn->timer->data = NULL; - taosArrayPush(pThrd->timerList, &pConn->timer); - pConn->timer = NULL; + SCliMsg* p = QUEUE_DATA(h, SCliMsg, q); + destroyCmsg(p); + } + SCliBatchList* p = pBatch->pList; + p->sending -= 1; + taosMemoryFree(pBatch); +} +static void cliHandleBatchReq(SCliBatch* pBatch, SCliThrd* pThrd) { + if (pThrd->quit == true) { + cliDestroyBatch(pBatch); + return; + } + + if (pBatch == NULL || pBatch->wLen == 0 || QUEUE_IS_EMPTY(&pBatch->wq)) { + return; + } + STrans* pTransInst = pThrd->pTransInst; + SCliBatchList* pList = pBatch->pList; + + char key[TSDB_FQDN_LEN + 64] = {0}; + CONN_CONSTRUCT_HASH_KEY(key, pList->ip, pList->port); + + bool exceed = false; + SCliConn* conn = getConnFromPool(pThrd, key, &exceed); + + if (conn == NULL && exceed) { + tError("%s failed to send batch msg, batch size:%d, msgLen: %d, conn limit:%d", pTransInst->label, pBatch->wLen, + pBatch->batchSize, pTransInst->connLimitNum); + cliDestroyBatch(pBatch); + return; } + if (conn == NULL) { + conn = cliCreateConn(pThrd); + conn->pBatch = pBatch; + conn->ip = taosStrdup(pList->dst); + + uint32_t ipaddr = cliGetIpFromFqdnCache(pThrd->fqdn2ipCache, pList->ip); + if (ipaddr == 0xffffffff) { + uv_timer_stop(conn->timer); + conn->timer->data = NULL; + taosArrayPush(pThrd->timerList, &conn->timer); + conn->timer = NULL; + + cliHandleFastFail(conn, -1); + return; + } + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = ipaddr; + addr.sin_port = (uint16_t)htons(pList->port); + + tTrace("%s conn %p try to connect to %s", pTransInst->label, conn, pList->dst); + pThrd->newConnCount++; + int32_t fd = taosCreateSocketWithTimeout(TRANS_CONN_TIMEOUT * 10); + if (fd == -1) { + tError("%s conn %p failed to create socket, reason:%s", transLabel(pTransInst), conn, + tstrerror(TAOS_SYSTEM_ERROR(errno))); + cliHandleFastFail(conn, -1); + return; + } + int ret = uv_tcp_open((uv_tcp_t*)conn->stream, fd); + if (ret != 0) { + tError("%s conn %p failed to set stream, reason:%s", transLabel(pTransInst), conn, uv_err_name(ret)); + cliHandleFastFail(conn, -1); + return; + } + ret = transSetConnOption((uv_tcp_t*)conn->stream); + if (ret != 0) { + tError("%s conn %p failed to set socket opt, reason:%s", transLabel(pTransInst), conn, uv_err_name(ret)); + cliHandleFastFail(conn, -1); + return; + } + + ret = uv_tcp_connect(&conn->connReq, (uv_tcp_t*)(conn->stream), (const struct sockaddr*)&addr, cliConnCb); + if (ret != 0) { + uv_timer_stop(conn->timer); + conn->timer->data = NULL; + taosArrayPush(pThrd->timerList, &conn->timer); + conn->timer = NULL; + cliHandleFastFail(conn, -1); + return; + } + uv_timer_start(conn->timer, cliConnTimeout, TRANS_CONN_TIMEOUT, 0); + return; + } + + conn->pBatch = pBatch; + cliSendBatch(conn); +} +static void cliSendBatchCb(uv_write_t* req, int status) { + SCliConn* conn = req->data; + SCliThrd* thrd = conn->hostThrd; + SCliBatch* p = conn->pBatch; + + SCliBatchList* pBatchList = p->pList; + SCliBatch* nxtBatch = cliGetHeadFromList(pBatchList); + pBatchList->connCnt -= 1; + + conn->pBatch = NULL; if (status != 0) { + tDebug("%s conn %p failed to send batch msg, batch size:%d, msgLen:%d, reason:%s", CONN_GET_INST_LABEL(conn), conn, + p->wLen, p->batchSize, uv_err_name(status)); + + if (!uv_is_closing((uv_handle_t*)&conn->stream)) cliHandleExcept(conn); + + cliHandleBatchReq(nxtBatch, thrd); + } else { + tDebug("%s conn %p succ to send batch msg, batch size:%d, msgLen:%d", CONN_GET_INST_LABEL(conn), conn, p->wLen, + p->batchSize); + if (!uv_is_closing((uv_handle_t*)&conn->stream) && conn->broken == false) { + if (nxtBatch != NULL) { + conn->pBatch = nxtBatch; + cliSendBatch(conn); + } else { + addConnToPool(thrd->pool, conn); + } + } else { + cliDestroyBatch(nxtBatch); + // conn release by other callback + } + } + + cliDestroyBatch(p); + taosMemoryFree(req); +} +static void cliHandleFastFail(SCliConn* pConn, int status) { + SCliThrd* pThrd = pConn->hostThrd; + STrans* pTransInst = pThrd->pTransInst; + + if (status == -1) status = ENETUNREACH; + + if (pConn->pBatch == NULL) { SCliMsg* pMsg = transQueueGet(&pConn->cliMsgs, 0); - STrans* pTransInst = pThrd->pTransInst; - tError("%s msg %s failed to send, conn %p failed to connect to %s:%d, reason: %s", CONN_GET_INST_LABEL(pConn), - pMsg ? TMSG_INFO(pMsg->msg.msgType) : 0, pConn, pConn->ip, pConn->port, uv_strerror(status)); + STraceId* trace = &pMsg->msg.info.traceId; + tGError("%s msg %s failed to send, conn %p failed to connect to %s, reason: %s", CONN_GET_INST_LABEL(pConn), + TMSG_INFO(pMsg->msg.msgType), pConn, pConn->ip, uv_strerror(status)); + if (pMsg != NULL && REQUEST_NO_RESP(&pMsg->msg) && (pTransInst->failFastFp != NULL && pTransInst->failFastFp(pMsg->msg.msgType))) { - char* ip = pConn->ip; - uint32_t port = pConn->port; - char key[TSDB_FQDN_LEN + 64] = {0}; - CONN_CONSTRUCT_HASH_KEY(key, ip, port); - - SFailFastItem* item = taosHashGet(pThrd->failFastCache, key, strlen(key)); + SFailFastItem* item = taosHashGet(pThrd->failFastCache, pConn->ip, strlen(pConn->ip) + 1); int64_t cTimestamp = taosGetTimestampMs(); if (item != NULL) { int32_t elapse = cTimestamp - item->timestamp; @@ -919,15 +1282,43 @@ void cliConnCb(uv_connect_t* req, int status) { } } else { SFailFastItem item = {.count = 1, .timestamp = cTimestamp}; - taosHashPut(pThrd->failFastCache, key, strlen(key), &item, sizeof(SFailFastItem)); + taosHashPut(pThrd->failFastCache, pConn->ip, strlen(pConn->ip) + 1, &item, sizeof(SFailFastItem)); } } - cliHandleExcept(pConn); + } else { + tError("%s batch msg failed to send, conn %p failed to connect to %s, reason: %s", CONN_GET_INST_LABEL(pConn), + pConn, pConn->ip, uv_strerror(status)); + cliDestroyBatch(pConn->pBatch); + pConn->pBatch = NULL; + } + cliHandleExcept(pConn); +} + +void cliConnCb(uv_connect_t* req, int status) { + SCliConn* pConn = req->data; + SCliThrd* pThrd = pConn->hostThrd; + bool timeout = false; + + if (pConn->timer == NULL) { + timeout = true; + } else { + uv_timer_stop(pConn->timer); + pConn->timer->data = NULL; + taosArrayPush(pThrd->timerList, &pConn->timer); + pConn->timer = NULL; + } + + if (status != 0) { + if (timeout == false) { + cliHandleFastFail(pConn, status); + } else if (timeout == true) { + // already deal by timeout + } return; } - struct sockaddr peername, sockname; - int addrlen = sizeof(peername); + struct sockaddr peername, sockname; + int addrlen = sizeof(peername); uv_tcp_getpeername((uv_tcp_t*)pConn->stream, &peername, &addrlen); transSockInfo2Str(&peername, pConn->dst); @@ -936,10 +1327,36 @@ void cliConnCb(uv_connect_t* req, int status) { transSockInfo2Str(&sockname, pConn->src); tTrace("%s conn %p connect to server successfully", CONN_GET_INST_LABEL(pConn), pConn); - - cliSend(pConn); + if (pConn->pBatch != NULL) { + cliSendBatch(pConn); + } else { + cliSend(pConn); + } } +static void doNotifyApp(SCliMsg* pMsg, SCliThrd* pThrd) { + STransConnCtx* pCtx = pMsg->ctx; + STrans* pTransInst = pThrd->pTransInst; + + STransMsg transMsg = {0}; + transMsg.contLen = 0; + transMsg.pCont = NULL; + transMsg.code = TSDB_CODE_RPC_MAX_SESSIONS; + transMsg.msgType = pMsg->msg.msgType + 1; + transMsg.info.ahandle = pMsg->ctx->ahandle; + transMsg.info.traceId = pMsg->msg.info.traceId; + transMsg.info.hasEpSet = false; + if (pCtx->pSem != NULL) { + if (pCtx->pRsp == NULL) { + } else { + memcpy((char*)pCtx->pRsp, (char*)&transMsg, sizeof(transMsg)); + } + } else { + pTransInst->cfp(pTransInst->parent, &transMsg, NULL); + } + + destroyCmsg(pMsg); +} static void cliHandleQuit(SCliMsg* pMsg, SCliThrd* pThrd) { if (!transAsyncPoolIsEmpty(pThrd->asyncPool)) { pThrd->stopMsg = pMsg; @@ -949,7 +1366,8 @@ static void cliHandleQuit(SCliMsg* pMsg, SCliThrd* pThrd) { pThrd->quit = true; tDebug("cli work thread %p start to quit", pThrd); destroyCmsg(pMsg); - destroyConnPool(pThrd->pool); + + destroyConnPool(pThrd); uv_walk(pThrd->loop, cliWalkCb, NULL); } static void cliHandleRelease(SCliMsg* pMsg, SCliThrd* pThrd) { @@ -982,11 +1400,11 @@ static void cliHandleUpdate(SCliMsg* pMsg, SCliThrd* pThrd) { destroyCmsg(pMsg); } -SCliConn* cliGetConn(SCliMsg* pMsg, SCliThrd* pThrd, bool* ignore) { - STransConnCtx* pCtx = pMsg->ctx; +SCliConn* cliGetConn(SCliMsg** pMsg, SCliThrd* pThrd, bool* ignore, char* addr) { + STransConnCtx* pCtx = (*pMsg)->ctx; SCliConn* conn = NULL; - int64_t refId = (int64_t)(pMsg->msg.info.handle); + int64_t refId = (int64_t)((*pMsg)->msg.info.handle); if (refId != 0) { SExHandle* exh = transAcquireExHandle(transGetRefMgt(), refId); if (exh == NULL) { @@ -996,7 +1414,7 @@ SCliConn* cliGetConn(SCliMsg* pMsg, SCliThrd* pThrd, bool* ignore) { } else { conn = exh->handle; if (conn == NULL) { - conn = getConnFromPool(pThrd->pool, EPSET_GET_INUSE_IP(&pCtx->epSet), EPSET_GET_INUSE_PORT(&pCtx->epSet)); + conn = getConnFromPool2(pThrd, addr, pMsg); if (conn != NULL) specifyConnRef(conn, true, refId); } transReleaseExHandle(transGetRefMgt(), refId); @@ -1004,7 +1422,7 @@ SCliConn* cliGetConn(SCliMsg* pMsg, SCliThrd* pThrd, bool* ignore) { return conn; }; - conn = getConnFromPool(pThrd->pool, EPSET_GET_INUSE_IP(&pCtx->epSet), EPSET_GET_INUSE_PORT(&pCtx->epSet)); + conn = getConnFromPool2(pThrd, addr, pMsg); if (conn != NULL) { tTrace("%s conn %p get from conn pool:%p", CONN_GET_INST_LABEL(conn), conn, pThrd->pool); } else { @@ -1042,7 +1460,7 @@ FORCE_INLINE int32_t cliBuildExceptResp(SCliMsg* pMsg, STransMsg* pResp) { } static FORCE_INLINE uint32_t cliGetIpFromFqdnCache(SHashObj* cache, char* fqdn) { uint32_t addr = 0; - uint32_t* v = taosHashGet(cache, fqdn, strlen(fqdn)); + uint32_t* v = taosHashGet(cache, fqdn, strlen(fqdn) + 1); if (v == NULL) { addr = taosGetIpv4FromFqdn(fqdn); if (addr == 0xffffffff) { @@ -1051,7 +1469,7 @@ static FORCE_INLINE uint32_t cliGetIpFromFqdnCache(SHashObj* cache, char* fqdn) return addr; } - taosHashPut(cache, fqdn, strlen(fqdn), &addr, sizeof(addr)); + taosHashPut(cache, fqdn, strlen(fqdn) + 1, &addr, sizeof(addr)); } else { addr = *v; } @@ -1062,40 +1480,49 @@ static FORCE_INLINE void cliUpdateFqdnCache(SHashObj* cache, char* fqdn) { return; } -void cliHandleReq(SCliMsg* pMsg, SCliThrd* pThrd) { - STrans* pTransInst = pThrd->pTransInst; - STransConnCtx* pCtx = pMsg->ctx; +static void doFreeTimeoutMsg(void* param) { + STaskArg* arg = param; + SCliMsg* pMsg = arg->param1; + SCliThrd* pThrd = arg->param2; + STrans* pTransInst = pThrd->pTransInst; - cliMayCvtFqdnToIp(&pCtx->epSet, &pThrd->cvtAddr); + QUEUE_REMOVE(&pMsg->q); STraceId* trace = &pMsg->msg.info.traceId; + tGTrace("%s msg %s cannot get available conn after timeout", pTransInst->label, TMSG_INFO(pMsg->msg.msgType)); + doNotifyApp(pMsg, pThrd); + taosMemoryFree(arg); +} +void cliHandleReq(SCliMsg* pMsg, SCliThrd* pThrd) { + STrans* pTransInst = pThrd->pTransInst; - if (!EPSET_IS_VALID(&pCtx->epSet)) { - tGError("%s, msg %s sent with invalid epset", pTransInst->label, TMSG_INFO(pMsg->msg.msgType)); + cliMayCvtFqdnToIp(&pMsg->ctx->epSet, &pThrd->cvtAddr); + if (!EPSET_IS_VALID(&pMsg->ctx->epSet)) { destroyCmsg(pMsg); return; } - if (REQUEST_NO_RESP(&pMsg->msg) && (pTransInst->failFastFp != NULL && pTransInst->failFastFp(pMsg->msg.msgType))) { - char* ip = EPSET_GET_INUSE_IP(&pCtx->epSet); - uint32_t port = EPSET_GET_INUSE_PORT(&pCtx->epSet); - char key[TSDB_FQDN_LEN + 64] = {0}; - CONN_CONSTRUCT_HASH_KEY(key, ip, port); - - SFailFastItem* item = taosHashGet(pThrd->failFastCache, key, strlen(key)); - if (item != NULL) { - int32_t elapse = (int32_t)(taosGetTimestampMs() - item->timestamp); - if (item->count >= pTransInst->failFastThreshold && (elapse >= 0 && elapse <= pTransInst->failFastInterval)) { - STraceId* trace = &(pMsg->msg.info.traceId); - tGTrace("%s, msg %s cancel to send, reason: failed to connect %s:%d: count: %d, at %d", pTransInst->label, - TMSG_INFO(pMsg->msg.msgType), ip, port, item->count, elapse); - destroyCmsg(pMsg); - return; + if (rpcDebugFlag & DEBUG_TRACE) { + if (tmsgIsValid(pMsg->msg.msgType)) { + char buf[128] = {0}; + sprintf(buf, "%s", TMSG_INFO(pMsg->msg.msgType)); + int* count = taosHashGet(pThrd->msgCount, buf, sizeof(buf)); + if (NULL == 0) { + int localCount = 1; + taosHashPut(pThrd->msgCount, buf, sizeof(buf), &localCount, sizeof(localCount)); + } else { + int localCount = *count + 1; + taosHashPut(pThrd->msgCount, buf, sizeof(buf), &localCount, sizeof(localCount)); } } } + char* fqdn = EPSET_GET_INUSE_IP(&pMsg->ctx->epSet); + uint16_t port = EPSET_GET_INUSE_PORT(&pMsg->ctx->epSet); + char addr[TSDB_FQDN_LEN + 64] = {0}; + CONN_CONSTRUCT_HASH_KEY(addr, fqdn, port); + bool ignore = false; - SCliConn* conn = cliGetConn(pMsg, pThrd, &ignore); + SCliConn* conn = cliGetConn(&pMsg, pThrd, &ignore, addr); if (ignore == true) { // persist conn already release by server STransMsg resp; @@ -1106,9 +1533,13 @@ void cliHandleReq(SCliMsg* pMsg, SCliThrd* pThrd) { destroyCmsg(pMsg); return; } + if (conn == NULL && pMsg == NULL) { + return; + } + STraceId* trace = &pMsg->msg.info.traceId; if (conn != NULL) { - transCtxMerge(&conn->ctx, &pCtx->appCtx); + transCtxMerge(&conn->ctx, &pMsg->ctx->appCtx); transQueuePush(&conn->cliMsgs, pMsg); cliSend(conn); } else { @@ -1117,13 +1548,12 @@ void cliHandleReq(SCliMsg* pMsg, SCliThrd* pThrd) { int64_t refId = (int64_t)pMsg->msg.info.handle; if (refId != 0) specifyConnRef(conn, true, refId); - transCtxMerge(&conn->ctx, &pCtx->appCtx); + transCtxMerge(&conn->ctx, &pMsg->ctx->appCtx); transQueuePush(&conn->cliMsgs, pMsg); - conn->ip = strdup(EPSET_GET_INUSE_IP(&pCtx->epSet)); - conn->port = EPSET_GET_INUSE_PORT(&pCtx->epSet); + conn->ip = taosStrdup(addr); - uint32_t ipaddr = cliGetIpFromFqdnCache(pThrd->fqdn2ipCache, conn->ip); + uint32_t ipaddr = cliGetIpFromFqdnCache(pThrd->fqdn2ipCache, fqdn); if (ipaddr == 0xffffffff) { uv_timer_stop(conn->timer); conn->timer->data = NULL; @@ -1137,9 +1567,10 @@ void cliHandleReq(SCliMsg* pMsg, SCliThrd* pThrd) { struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = ipaddr; - addr.sin_port = (uint16_t)htons((uint16_t)conn->port); + addr.sin_port = (uint16_t)htons(port); - tGTrace("%s conn %p try to connect to %s:%d", pTransInst->label, conn, conn->ip, conn->port); + tGTrace("%s conn %p try to connect to %s", pTransInst->label, conn, conn->ip); + pThrd->newConnCount++; int32_t fd = taosCreateSocketWithTimeout(TRANS_CONN_TIMEOUT * 4); if (fd == -1) { tGError("%s conn %p failed to create socket, reason:%s", transLabel(pTransInst), conn, @@ -1163,25 +1594,165 @@ void cliHandleReq(SCliMsg* pMsg, SCliThrd* pThrd) { ret = uv_tcp_connect(&conn->connReq, (uv_tcp_t*)(conn->stream), (const struct sockaddr*)&addr, cliConnCb); if (ret != 0) { - tGError("%s conn %p failed to connect to %s:%d, reason:%s", pTransInst->label, conn, conn->ip, conn->port, - uv_err_name(ret)); - uv_timer_stop(conn->timer); conn->timer->data = NULL; taosArrayPush(pThrd->timerList, &conn->timer); conn->timer = NULL; - cliHandleExcept(conn); + cliHandleFastFail(conn, ret); return; } uv_timer_start(conn->timer, cliConnTimeout, TRANS_CONN_TIMEOUT, 0); } tGTrace("%s conn %p ready", pTransInst->label, conn); } + +static void cliNoBatchDealReq(queue* wq, SCliThrd* pThrd) { + int count = 0; + + while (!QUEUE_IS_EMPTY(wq)) { + queue* h = QUEUE_HEAD(wq); + QUEUE_REMOVE(h); + + SCliMsg* pMsg = QUEUE_DATA(h, SCliMsg, q); + + if (pMsg->type == Quit) { + pThrd->stopMsg = pMsg; + continue; + } + (*cliAsyncHandle[pMsg->type])(pMsg, pThrd); + + count++; + } + if (count >= 2) { + tTrace("cli process batch size:%d", count); + } +} +SCliBatch* cliGetHeadFromList(SCliBatchList* pList) { + if (QUEUE_IS_EMPTY(&pList->wq) || pList->connCnt > pList->connMax || pList->sending > pList->connMax) { + return NULL; + } + queue* hr = QUEUE_HEAD(&pList->wq); + QUEUE_REMOVE(hr); + pList->sending += 1; + + pList->len -= 1; + + SCliBatch* batch = QUEUE_DATA(hr, SCliBatch, listq); + return batch; +} + +static void cliBatchDealReq(queue* wq, SCliThrd* pThrd) { + STrans* pInst = pThrd->pTransInst; + + int count = 0; + while (!QUEUE_IS_EMPTY(wq)) { + queue* h = QUEUE_HEAD(wq); + QUEUE_REMOVE(h); + + SCliMsg* pMsg = QUEUE_DATA(h, SCliMsg, q); + + if (pMsg->type == Quit) { + pThrd->stopMsg = pMsg; + continue; + } + + if (pMsg->type == Normal && REQUEST_NO_RESP(&pMsg->msg)) { + STransConnCtx* pCtx = pMsg->ctx; + + char* ip = EPSET_GET_INUSE_IP(&pCtx->epSet); + uint32_t port = EPSET_GET_INUSE_PORT(&pCtx->epSet); + char key[TSDB_FQDN_LEN + 64] = {0}; + CONN_CONSTRUCT_HASH_KEY(key, ip, port); + + // SCliBatch** ppBatch = taosHashGet(pThrd->batchCache, key, sizeof(key)); + SCliBatchList** ppBatchList = taosHashGet(pThrd->batchCache, key, sizeof(key)); + if (ppBatchList == NULL || *ppBatchList == NULL) { + SCliBatchList* pBatchList = taosMemoryCalloc(1, sizeof(SCliBatchList)); + QUEUE_INIT(&pBatchList->wq); + pBatchList->connMax = pInst->connLimitNum; + pBatchList->connCnt = 0; + pBatchList->batchLenLimit = pInst->batchSize; + pBatchList->len += 1; + + pBatchList->ip = taosStrdup(ip); + pBatchList->dst = taosStrdup(key); + pBatchList->port = port; + + SCliBatch* pBatch = taosMemoryCalloc(1, sizeof(SCliBatch)); + QUEUE_INIT(&pBatch->wq); + QUEUE_INIT(&pBatch->listq); + + QUEUE_PUSH(&pBatch->wq, h); + pBatch->wLen += 1; + pBatch->batchSize += pMsg->msg.contLen; + pBatch->pList = pBatchList; + + QUEUE_PUSH(&pBatchList->wq, &pBatch->listq); + + taosHashPut(pThrd->batchCache, key, sizeof(key), &pBatchList, sizeof(void*)); + } else { + if (QUEUE_IS_EMPTY(&(*ppBatchList)->wq)) { + SCliBatch* pBatch = taosMemoryCalloc(1, sizeof(SCliBatch)); + QUEUE_INIT(&pBatch->wq); + QUEUE_INIT(&pBatch->listq); + + QUEUE_PUSH(&pBatch->wq, h); + pBatch->wLen += 1; + pBatch->batchSize = pMsg->msg.contLen; + pBatch->pList = *ppBatchList; + + QUEUE_PUSH(&((*ppBatchList)->wq), &pBatch->listq); + (*ppBatchList)->len += 1; + + continue; + } + + queue* hdr = QUEUE_TAIL(&((*ppBatchList)->wq)); + SCliBatch* pBatch = QUEUE_DATA(hdr, SCliBatch, listq); + if ((pBatch->batchSize + pMsg->msg.contLen) < (*ppBatchList)->batchLenLimit) { + QUEUE_PUSH(&pBatch->wq, h); + pBatch->batchSize += pMsg->msg.contLen; + pBatch->wLen += 1; + } else { + SCliBatch* pBatch = taosMemoryCalloc(1, sizeof(SCliBatch)); + QUEUE_INIT(&pBatch->wq); + QUEUE_INIT(&pBatch->listq); + + QUEUE_PUSH(&pBatch->wq, h); + pBatch->wLen += 1; + pBatch->batchSize += pMsg->msg.contLen; + pBatch->pList = *ppBatchList; + + QUEUE_PUSH(&((*ppBatchList)->wq), &pBatch->listq); + (*ppBatchList)->len += 1; + } + } + continue; + } + (*cliAsyncHandle[pMsg->type])(pMsg, pThrd); + count++; + } + + void** pIter = taosHashIterate(pThrd->batchCache, NULL); + while (pIter != NULL) { + SCliBatchList* batchList = (SCliBatchList*)(*pIter); + SCliBatch* batch = cliGetHeadFromList(batchList); + if (batch != NULL) { + cliHandleBatchReq(batch, pThrd); + } + pIter = (void**)taosHashIterate(pThrd->batchCache, pIter); + } + + if (count >= 2) { + tTrace("cli process batch size:%d", count); + } +} + static void cliAsyncCb(uv_async_t* handle) { SAsyncItem* item = handle->data; SCliThrd* pThrd = item->pThrd; - SCliMsg* pMsg = NULL; + STrans* pTransInst = pThrd->pTransInst; // batch process to avoid to lock/unlock frequently queue wq; @@ -1189,19 +1760,27 @@ static void cliAsyncCb(uv_async_t* handle) { QUEUE_MOVE(&item->qmsg, &wq); taosThreadMutexUnlock(&item->mtx); - int count = 0; - while (!QUEUE_IS_EMPTY(&wq)) { - queue* h = QUEUE_HEAD(&wq); - QUEUE_REMOVE(h); + if (rpcDebugFlag & DEBUG_TRACE) { + void* pIter = taosHashIterate(pThrd->msgCount, NULL); + while (pIter != NULL) { + int* count = pIter; + size_t len = 0; + char* key = taosHashGetKey(pIter, &len); + if (*count != 0) { + tDebug("key: %s count: %d", key, *count); + } - SCliMsg* pMsg = QUEUE_DATA(h, SCliMsg, q); - (*cliAsyncHandle[pMsg->type])(pMsg, pThrd); - count++; + pIter = taosHashIterate(pThrd->msgCount, pIter); + } + tDebug("all conn count: %d", pThrd->newConnCount); } - if (count >= 2) { - tTrace("cli process batch size:%d", count); + + int8_t supportBatch = pTransInst->supportBatch; + if (supportBatch == 0) { + cliNoBatchDealReq(&wq, pThrd); + } else if (supportBatch == 1) { + cliBatchDealReq(&wq, pThrd); } - // if (!uv_is_active((uv_handle_t*)pThrd->prepare)) uv_prepare_start(pThrd->prepare, cliPrepareCb); if (pThrd->stopMsg != NULL) cliHandleQuit(pThrd->stopMsg, pThrd); } @@ -1312,17 +1891,23 @@ void* transInitClient(uint32_t ip, uint32_t port, char* label, int numOfThreads, for (int i = 0; i < cli->numOfThreads; i++) { SCliThrd* pThrd = createThrdObj(shandle); if (pThrd == NULL) { - return NULL; + goto _err; } int err = taosThreadCreate(&pThrd->thread, NULL, cliWorkThread, (void*)(pThrd)); - if (err == 0) { + if (err != 0) { + goto _err; + } else { tDebug("success to create tranport-cli thread:%d", i); } cli->pThreadObj[i] = pThrd; } - return cli; + +_err: + taosMemoryFree(cli->pThreadObj); + taosMemoryFree(cli); + return NULL; } static FORCE_INLINE void destroyUserdata(STransMsg* userdata) { @@ -1380,7 +1965,11 @@ static SCliThrd* createThrdObj(void* trans) { taosMemoryFree(pThrd); return NULL; } - pThrd->asyncPool = transAsyncPoolCreate(pThrd->loop, 8, pThrd, cliAsyncCb); + if (pTransInst->supportBatch) { + pThrd->asyncPool = transAsyncPoolCreate(pThrd->loop, 4, pThrd, cliAsyncCb); + } else { + pThrd->asyncPool = transAsyncPoolCreate(pThrd->loop, 8, pThrd, cliAsyncCb); + } if (pThrd->asyncPool == NULL) { tError("failed to init async pool"); uv_loop_close(pThrd->loop); @@ -1408,6 +1997,8 @@ static SCliThrd* createThrdObj(void* trans) { transDQCreate(pThrd->loop, &pThrd->timeoutQueue); + transDQCreate(pThrd->loop, &pThrd->waitConnQueue); + pThrd->nextTimeout = taosGetTimestampMs() + CONN_PERSIST_TIME(pTransInst->idleTime); pThrd->pTransInst = trans; @@ -1415,7 +2006,12 @@ static SCliThrd* createThrdObj(void* trans) { pThrd->fqdn2ipCache = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); pThrd->failFastCache = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); + pThrd->batchCache = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); + pThrd->quit = false; + + pThrd->newConnCount = 0; + pThrd->msgCount = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); return pThrd; } static void destroyThrdObj(SCliThrd* pThrd) { @@ -1431,6 +2027,7 @@ static void destroyThrdObj(SCliThrd* pThrd) { transDQDestroy(pThrd->delayQueue, destroyCmsgAndAhandle); transDQDestroy(pThrd->timeoutQueue, NULL); + transDQDestroy(pThrd->waitConnQueue, NULL); tDebug("thread destroy %" PRId64, pThrd->pid); for (int i = 0; i < taosArrayGetSize(pThrd->timerList); i++) { @@ -1442,6 +2039,25 @@ static void destroyThrdObj(SCliThrd* pThrd) { taosMemoryFree(pThrd->loop); taosHashCleanup(pThrd->fqdn2ipCache); taosHashCleanup(pThrd->failFastCache); + + void** pIter = taosHashIterate(pThrd->batchCache, NULL); + while (pIter != NULL) { + SCliBatchList* pBatchList = (SCliBatchList*)(*pIter); + while (!QUEUE_IS_EMPTY(&pBatchList->wq)) { + queue* h = QUEUE_HEAD(&pBatchList->wq); + QUEUE_REMOVE(h); + + SCliBatch* pBatch = QUEUE_DATA(h, SCliBatch, listq); + cliDestroyBatch(pBatch); + } + taosMemoryFree(pBatchList->ip); + taosMemoryFree(pBatchList->dst); + taosMemoryFree(pBatchList); + + pIter = (void**)taosHashIterate(pThrd->batchCache, pIter); + } + taosHashCleanup(pThrd->batchCache); + taosHashCleanup(pThrd->msgCount); taosMemoryFree(pThrd); } @@ -1507,11 +2123,13 @@ static void cliSchedMsgToNextNode(SCliMsg* pMsg, SCliThrd* pThrd) { STrans* pTransInst = pThrd->pTransInst; STransConnCtx* pCtx = pMsg->ctx; - STraceId* trace = &pMsg->msg.info.traceId; - char tbuf[256] = {0}; - EPSET_DEBUG_STR(&pCtx->epSet, tbuf); - tGDebug("%s retry on next node,use:%s, step: %d,timeout:%" PRId64 "", transLabel(pThrd->pTransInst), tbuf, - pCtx->retryStep, pCtx->retryNextInterval); + if (rpcDebugFlag & DEBUG_DEBUG) { + STraceId* trace = &pMsg->msg.info.traceId; + char tbuf[256] = {0}; + EPSET_DEBUG_STR(&pCtx->epSet, tbuf); + tGDebug("%s retry on next node,use:%s, step: %d,timeout:%" PRId64 "", transLabel(pThrd->pTransInst), tbuf, + pCtx->retryStep, pCtx->retryNextInterval); + } STaskArg* arg = taosMemoryMalloc(sizeof(STaskArg)); arg->param1 = pMsg; @@ -1548,7 +2166,7 @@ FORCE_INLINE bool cliTryExtractEpSet(STransMsg* pResp, SEpSet* dst) { pResp->pCont = buf; pResp->contLen = len; - *dst = epset; + epsetAssign(dst, &epset); return true; } bool cliResetEpset(STransConnCtx* pCtx, STransMsg* pResp, bool hasEpSet) { @@ -1573,7 +2191,7 @@ bool cliResetEpset(STransConnCtx* pCtx, STransMsg* pResp, bool hasEpSet) { } else { if (!transEpSetIsEqual(&pCtx->epSet, &epSet)) { tDebug("epset not equal, retry new epset"); - pCtx->epSet = epSet; + epsetAssign(&pCtx->epSet, &epSet); noDelay = false; } else { if (pCtx->epsetRetryCnt >= pCtx->epSet.numOfEps) { @@ -1598,7 +2216,7 @@ bool cliResetEpset(STransConnCtx* pCtx, STransMsg* pResp, bool hasEpSet) { } else { if (!transEpSetIsEqual(&pCtx->epSet, &epSet)) { tDebug("epset not equal, retry new epset"); - pCtx->epSet = epSet; + epsetAssign(&pCtx->epSet, &epSet); noDelay = false; } else { if (pCtx->epsetRetryCnt >= pCtx->epSet.numOfEps) { @@ -1688,10 +2306,6 @@ bool cliGenRetryRule(SCliConn* pConn, STransMsg* pResp, SCliMsg* pMsg) { if (pCtx->retryNextInterval >= pCtx->retryMaxInterval) { pCtx->retryNextInterval = pCtx->retryMaxInterval; } - - // if (-1 != pCtx->retryMaxTimeout && taosGetTimestampMs() - pCtx->retryInitTimestamp >= pCtx->retryMaxTimeout) { - // return false; - // } } else { pCtx->retryNextInterval = 0; pCtx->epsetRetryCnt++; @@ -1739,11 +2353,26 @@ int cliAppCb(SCliConn* pConn, STransMsg* pResp, SCliMsg* pMsg) { STraceId* trace = &pResp->info.traceId; bool hasEpSet = cliTryExtractEpSet(pResp, &pCtx->epSet); if (hasEpSet) { - char tbuf[256] = {0}; - EPSET_DEBUG_STR(&pCtx->epSet, tbuf); - tGTrace("%s conn %p extract epset from msg", CONN_GET_INST_LABEL(pConn), pConn); + if (rpcDebugFlag & DEBUG_TRACE) { + char tbuf[256] = {0}; + EPSET_DEBUG_STR(&pCtx->epSet, tbuf); + tGTrace("%s conn %p extract epset from msg", CONN_GET_INST_LABEL(pConn), pConn); + } + } + if (rpcDebugFlag & DEBUG_TRACE) { + if (tmsgIsValid(pResp->msgType - 1)) { + char buf[128] = {0}; + sprintf(buf, "%s", TMSG_INFO(pResp->msgType - 1)); + int* count = taosHashGet(pThrd->msgCount, buf, sizeof(buf)); + if (NULL == 0) { + int localCount = 0; + taosHashPut(pThrd->msgCount, buf, sizeof(buf), &localCount, sizeof(localCount)); + } else { + int localCount = *count - 1; + taosHashPut(pThrd->msgCount, buf, sizeof(buf), &localCount, sizeof(localCount)); + } + } } - if (pCtx->pSem != NULL) { tGTrace("%s conn %p(sync) handle resp", CONN_GET_INST_LABEL(pConn), pConn); if (pCtx->pRsp == NULL) { @@ -1867,9 +2496,10 @@ int transSendRequest(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STran } TRACE_SET_MSGID(&pReq->info.traceId, tGenIdPI64()); - STransConnCtx* pCtx = taosMemoryCalloc(1, sizeof(STransConnCtx)); - pCtx->epSet = *pEpSet; + epsetAssign(&pCtx->epSet, pEpSet); + epsetAssign(&pCtx->origEpSet, pEpSet); + pCtx->ahandle = pReq->info.ahandle; pCtx->msgType = pReq->msgType; @@ -1914,8 +2544,8 @@ int transSendRecv(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STransMs TRACE_SET_MSGID(&pReq->info.traceId, tGenIdPI64()); STransConnCtx* pCtx = taosMemoryCalloc(1, sizeof(STransConnCtx)); - pCtx->epSet = *pEpSet; - pCtx->origEpSet = *pEpSet; + epsetAssign(&pCtx->epSet, pEpSet); + epsetAssign(&pCtx->origEpSet, pEpSet); pCtx->ahandle = pReq->info.ahandle; pCtx->msgType = pReq->msgType; pCtx->pSem = sem; @@ -1989,4 +2619,3 @@ int64_t transAllocHandle() { return exh->refId; } -#endif diff --git a/source/libs/transport/src/transComm.c b/source/libs/transport/src/transComm.c index 4c107a88f18d39fb4bebb2f45237a9de669e5db4..0dfc7677b315ea03d66500867fe9bedf26c0cec7 100644 --- a/source/libs/transport/src/transComm.c +++ b/source/libs/transport/src/transComm.c @@ -12,7 +12,6 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifdef USE_UV #include "transComm.h" @@ -67,7 +66,7 @@ int32_t transDecompressMsg(char** msg, int32_t len) { char* buf = taosMemoryCalloc(1, oriLen + sizeof(STransMsgHead)); STransMsgHead* pNewHead = (STransMsgHead*)buf; - int32_t decompLen = LZ4_decompress_safe(pCont + sizeof(STransCompMsg), pNewHead->content, + int32_t decompLen = LZ4_decompress_safe(pCont + sizeof(STransCompMsg), (char*)pNewHead->content, len - sizeof(STransMsgHead) - sizeof(STransCompMsg), oriLen); memcpy((char*)pNewHead, (char*)pHead, sizeof(STransMsgHead)); @@ -655,4 +654,3 @@ void transDestoryExHandle(void* handle) { } taosMemoryFree(handle); } -#endif diff --git a/source/libs/transport/src/transSvr.c b/source/libs/transport/src/transSvr.c index fa8929f7d954fd42a04f3b8bade2cb084d79c981..da3b0ad626d58d62927e64e33cf868771be115be 100644 --- a/source/libs/transport/src/transSvr.c +++ b/source/libs/transport/src/transSvr.c @@ -12,8 +12,6 @@ * along with this program. If not, see . */ -#ifdef USE_UV - #include "transComm.h" static TdThreadOnce transModuleInit = PTHREAD_ONCE_INIT; @@ -238,7 +236,7 @@ static bool uvHandleReq(SSvrConn* pConn) { if (pConn->status == ConnNormal && pHead->noResp == 0) { transRefSrvHandle(pConn); if (cost >= EXCEPTION_LIMIT_US) { - tGWarn("%s conn %p %s received from %s, local info:%s, len:%d, cost:%dus, recv exception", transLabel(pTransInst), + tGDebug("%s conn %p %s received from %s, local info:%s, len:%d, cost:%dus, recv exception", transLabel(pTransInst), pConn, TMSG_INFO(transMsg.msgType), pConn->dst, pConn->src, msgLen, (int)cost); } else { tGDebug("%s conn %p %s received from %s, local info:%s, len:%d, cost:%dus", transLabel(pTransInst), pConn, @@ -246,11 +244,11 @@ static bool uvHandleReq(SSvrConn* pConn) { } } else { if (cost >= EXCEPTION_LIMIT_US) { - tGWarn("%s conn %p %s received from %s, local info:%s, len:%d, resp:%d, code:%d, cost:%dus, recv exception", + tGDebug("%s conn %p %s received from %s, local info:%s, len:%d, noResp:%d, code:%d, cost:%dus, recv exception", transLabel(pTransInst), pConn, TMSG_INFO(transMsg.msgType), pConn->dst, pConn->src, msgLen, pHead->noResp, transMsg.code, (int)(cost)); } else { - tGDebug("%s conn %p %s received from %s, local info:%s, len:%d, resp:%d, code:%d, cost:%dus", + tGDebug("%s conn %p %s received from %s, local info:%s, len:%d, noResp:%d, code:%d, cost:%dus", transLabel(pTransInst), pConn, TMSG_INFO(transMsg.msgType), pConn->dst, pConn->src, msgLen, pHead->noResp, transMsg.code, (int)(cost)); } @@ -316,7 +314,7 @@ void uvOnRecvCb(uv_stream_t* cli, ssize_t nread, const uv_buf_t* buf) { return; } - tWarn("%s conn %p read error:%s", transLabel(pTransInst), conn, uv_err_name(nread)); + tDebug("%s conn %p read error:%s", transLabel(pTransInst), conn, uv_err_name(nread)); if (nread < 0) { conn->broken = true; if (conn->status == ConnAcquire) { @@ -679,14 +677,21 @@ void uvOnAcceptCb(uv_stream_t* stream, int status) { SServerObj* pObj = container_of(stream, SServerObj, server); uv_tcp_t* cli = (uv_tcp_t*)taosMemoryMalloc(sizeof(uv_tcp_t)); - uv_tcp_init(pObj->loop, cli); + if (cli == NULL) return; - if (uv_accept(stream, (uv_stream_t*)cli) == 0) { + int err = uv_tcp_init(pObj->loop, cli); + if (err != 0) { + tError("failed to create tcp: %s", uv_err_name(err)); + taosMemoryFree(cli); + return; + } + err = uv_accept(stream, (uv_stream_t*)cli); + if (err == 0) { #if defined(WINDOWS) || defined(DARWIN) if (pObj->numOfWorkerReady < pObj->numOfThreads) { tError("worker-threads are not ready for all, need %d instead of %d.", pObj->numOfThreads, pObj->numOfWorkerReady); - uv_close((uv_handle_t*)cli, NULL); + uv_close((uv_handle_t*)cli, uvFreeCb); return; } #endif @@ -702,8 +707,10 @@ void uvOnAcceptCb(uv_stream_t* stream, int status) { uv_write2(wr, (uv_stream_t*)&(pObj->pipe[pObj->workerIdx][0]), &buf, 1, (uv_stream_t*)cli, uvOnPipeWriteCb); } else { if (!uv_is_closing((uv_handle_t*)cli)) { - uv_close((uv_handle_t*)cli, NULL); + tError("failed to accept tcp: %s", uv_err_name(err)); + uv_close((uv_handle_t*)cli, uvFreeCb); } else { + tError("failed to accept tcp: %s", uv_err_name(err)); taosMemoryFree(cli); } } @@ -1347,5 +1354,3 @@ _return2: } int transGetConnInfo(void* thandle, STransHandleInfo* pConnInfo) { return -1; } - -#endif diff --git a/source/libs/transport/test/cliBench.c b/source/libs/transport/test/cliBench.c index 01e88b99888080ab3162669b8d8ee0083fbf2edd..aaee162cd754eb1e209fc21d8568fd703c57d303 100644 --- a/source/libs/transport/test/cliBench.c +++ b/source/libs/transport/test/cliBench.c @@ -32,22 +32,21 @@ typedef struct { void *pRpc; } SInfo; - void initLogEnv() { - const char *logDir = "/tmp/trans_cli"; - const char* defaultLogFileNamePrefix = "taoslog"; + const char *logDir = "/tmp/trans_cli"; + const char *defaultLogFileNamePrefix = "taoslog"; const int32_t maxLogFileNum = 10000; tsAsyncLog = 0; - //idxDebugFlag = 143; + // idxDebugFlag = 143; strcpy(tsLogDir, (char *)logDir); taosRemoveDir(tsLogDir); - taosMkDir(tsLogDir); - + taosMkDir(tsLogDir); + if (taosInitLog(defaultLogFileNamePrefix, maxLogFileNum) < 0) { - printf("failed to open log file in directory:%s\n", tsLogDir); + printf("failed to open log file in directory:%s\n", tsLogDir); } } - + static void processResponse(void *parent, SRpcMsg *pMsg, SEpSet *pEpSet) { SInfo *pInfo = (SInfo *)pMsg->info.ahandle; tDebug("thread:%d, response is received, type:%d contLen:%d code:0x%x", pInfo->index, pMsg->msgType, pMsg->contLen, @@ -72,11 +71,12 @@ static void *sendRequest(void *param) { rpcMsg.pCont = rpcMallocCont(pInfo->msgSize); rpcMsg.contLen = pInfo->msgSize; rpcMsg.info.ahandle = pInfo; + rpcMsg.info.noResp = 1; rpcMsg.msgType = 1; tDebug("thread:%d, send request, contLen:%d num:%d", pInfo->index, pInfo->msgSize, pInfo->num); rpcSendRequest(pInfo->pRpc, &pInfo->epSet, &rpcMsg, NULL); if (pInfo->num % 20000 == 0) tInfo("thread:%d, %d requests have been sent", pInfo->index, pInfo->num); - tsem_wait(&pInfo->rspSem); + // tsem_wait(&pInfo->rspSem); } tDebug("thread:%d, it is over", pInfo->index); @@ -112,7 +112,12 @@ int main(int argc, char *argv[]) { rpcInit.sessions = 100; rpcInit.idleTime = tsShellActivityTimer * 1000; rpcInit.user = "michael"; + rpcInit.connType = TAOS_CONN_CLIENT; + rpcInit.connLimitNum = 10; + rpcInit.connLimitLock = 1; + rpcInit.batchSize = 16 * 1024; + rpcInit.supportBatch = 1; rpcDebugFlag = 135; for (int i = 1; i < argc; ++i) { @@ -148,7 +153,6 @@ int main(int argc, char *argv[]) { exit(0); } } - initLogEnv(); diff --git a/source/libs/wal/src/walMeta.c b/source/libs/wal/src/walMeta.c index 707c47f6b17b479b731b2481100fefc66671fbea..a12f8051ba982ed627ed0767b76d344678748ca9 100644 --- a/source/libs/wal/src/walMeta.c +++ b/source/libs/wal/src/walMeta.c @@ -25,7 +25,7 @@ bool FORCE_INLINE walLogExist(SWal* pWal, int64_t ver) { } bool FORCE_INLINE walIsEmpty(SWal* pWal) { - return (pWal->vers.firstVer == -1 || pWal->vers.lastVer < pWal->vers.firstVer); // [firstVer, lastVer + 1) + return (pWal->vers.firstVer == -1 || pWal->vers.lastVer < pWal->vers.firstVer); // [firstVer, lastVer + 1) } int64_t FORCE_INLINE walGetFirstVer(SWal* pWal) { return pWal->vers.firstVer; } @@ -49,7 +49,6 @@ static FORCE_INLINE int walBuildTmpMetaName(SWal* pWal, char* buf) { static FORCE_INLINE int64_t walScanLogGetLastVer(SWal* pWal, int32_t fileIdx) { int32_t sz = taosArrayGetSize(pWal->fileInfoSet); terrno = TSDB_CODE_SUCCESS; - ASSERT(fileIdx >= 0 && fileIdx < sz); SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx); char fnameStr[WAL_FILE_LEN]; @@ -101,7 +100,6 @@ static FORCE_INLINE int64_t walScanLogGetLastVer(SWal* pWal, int32_t fileIdx) { offsetBackward = offset; } - ASSERT(offset <= end); readSize = end - offset; capacity = readSize + sizeof(magic); @@ -257,7 +255,6 @@ static void walRebuildFileInfoSet(SArray* metaLogList, SArray* actualLogList) { SWalFileInfo* pLogInfo = taosArrayGet(actualLogList, i); while (j < metaFileNum) { SWalFileInfo* pMetaInfo = taosArrayGet(metaLogList, j); - ASSERT(pMetaInfo != NULL); if (pMetaInfo->firstVer < pLogInfo->firstVer) { j++; } else if (pMetaInfo->firstVer == pLogInfo->firstVer) { @@ -298,6 +295,36 @@ void walAlignVersions(SWal* pWal) { wInfo("vgId:%d, reset commitVer to %" PRId64, pWal->cfg.vgId, pWal->vers.commitVer); } +int walRepairLogFileTs(SWal* pWal, bool* updateMeta) { + int32_t sz = taosArrayGetSize(pWal->fileInfoSet); + int32_t fileIdx = -1; + int32_t lastCloseTs = 0; + char fnameStr[WAL_FILE_LEN] = {0}; + + while (++fileIdx < sz - 1) { + SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx); + if (pFileInfo->closeTs != -1) { + lastCloseTs = pFileInfo->closeTs; + continue; + } + + walBuildLogName(pWal, pFileInfo->firstVer, fnameStr); + int32_t mtime = 0; + if (taosStatFile(fnameStr, NULL, &mtime) < 0) { + terrno = TAOS_SYSTEM_ERROR(errno); + wError("vgId:%d, failed to stat file due to %s, file:%s", pWal->cfg.vgId, strerror(errno), fnameStr); + return -1; + } + + if (updateMeta != NULL) *updateMeta = true; + if (pFileInfo->createTs == -1) pFileInfo->createTs = lastCloseTs; + pFileInfo->closeTs = mtime; + lastCloseTs = pFileInfo->closeTs; + } + + return 0; +} + bool walLogEntriesComplete(const SWal* pWal) { int32_t sz = taosArrayGetSize(pWal->fileInfoSet); bool complete = true; @@ -405,7 +432,6 @@ int walCheckAndRepairMeta(SWal* pWal) { taosArrayDestroy(actualLog); int32_t sz = taosArrayGetSize(pWal->fileInfoSet); - ASSERT(sz == actualFileNum); // scan and determine the lastVer int32_t fileIdx = sz; @@ -423,8 +449,6 @@ int walCheckAndRepairMeta(SWal* pWal) { return -1; } - ASSERT(pFileInfo->firstVer >= 0); - if (pFileInfo->lastVer >= pFileInfo->firstVer && fileSize == pFileInfo->fileSize) { totSize += pFileInfo->fileSize; continue; @@ -439,16 +463,8 @@ int walCheckAndRepairMeta(SWal* pWal) { wError("failed to scan wal last ver since %s", terrstr()); return -1; } - ASSERT(pFileInfo->fileSize == 0); - // remove the empty wal log, and its idx - wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr); - taosRemoveFile(fnameStr); - walBuildIdxName(pWal, pFileInfo->firstVer, fnameStr); - wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr); - taosRemoveFile(fnameStr); - // remove its meta entry - taosArrayRemove(pWal->fileInfoSet, fileIdx); - continue; + // empty log file + lastVer = pFileInfo->firstVer - 1; } // update lastVer @@ -467,6 +483,11 @@ int walCheckAndRepairMeta(SWal* pWal) { } (void)walAlignVersions(pWal); + // repair ts of files + if (walRepairLogFileTs(pWal, &updateMeta) < 0) { + return -1; + } + // update meta file if (updateMeta) { (void)walSaveMeta(pWal); @@ -499,8 +520,7 @@ int walReadLogHead(TdFilePtr pLogFile, int64_t offset, SWalCkHead* pCkHead) { } int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) { - int32_t sz = taosArrayGetSize(pWal->fileInfoSet); - ASSERT(fileIdx >= 0 && fileIdx < sz); + int32_t sz = taosArrayGetSize(pWal->fileInfoSet); SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx); char fnameStr[WAL_FILE_LEN]; walBuildIdxName(pWal, pFileInfo->firstVer, fnameStr); @@ -514,7 +534,6 @@ int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) { return -1; } - ASSERT(pFileInfo->fileSize > 0 && pFileInfo->firstVer >= 0 && pFileInfo->lastVer >= pFileInfo->firstVer); if (fileSize == (pFileInfo->lastVer - pFileInfo->firstVer + 1) * sizeof(SWalIdxEntry)) { return 0; } @@ -578,7 +597,7 @@ int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) { } offset += sizeof(SWalIdxEntry); - ASSERT(offset == (idxEntry.ver - pFileInfo->firstVer + 1) * sizeof(SWalIdxEntry)); + /*A(offset == (idxEntry.ver - pFileInfo->firstVer + 1) * sizeof(SWalIdxEntry));*/ // ftruncate idx file if (offset < fileSize) { @@ -600,7 +619,7 @@ int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) { int64_t count = 0; while (idxEntry.ver < pFileInfo->lastVer) { - ASSERT(idxEntry.ver == ckHead.head.version); + /*A(idxEntry.ver == ckHead.head.version);*/ idxEntry.ver += 1; idxEntry.offset += sizeof(SWalCkHead) + ckHead.head.bodyLen; @@ -677,8 +696,7 @@ int walRollFileInfo(SWal* pWal) { } char* walMetaSerialize(SWal* pWal) { - char buf[30]; - ASSERT(pWal->fileInfoSet); + char buf[30]; int sz = taosArrayGetSize(pWal->fileInfoSet); cJSON* pRoot = cJSON_CreateObject(); cJSON* pMeta = cJSON_CreateObject(); @@ -735,7 +753,7 @@ char* walMetaSerialize(SWal* pWal) { } int walMetaDeserialize(SWal* pWal, const char* bytes) { - ASSERT(taosArrayGetSize(pWal->fileInfoSet) == 0); + /*A(taosArrayGetSize(pWal->fileInfoSet) == 0);*/ cJSON *pRoot, *pMeta, *pFiles, *pInfoJson, *pField; pRoot = cJSON_Parse(bytes); if (!pRoot) goto _err; @@ -853,7 +871,9 @@ int walSaveMeta(SWal* pWal) { // flush to a tmpfile n = walBuildTmpMetaName(pWal, tmpFnameStr); - ASSERT(n < sizeof(tmpFnameStr) && "Buffer overflow of file name"); + if (n >= sizeof(tmpFnameStr)) { + return -1; + } TdFilePtr pMetaFile = taosOpenFile(tmpFnameStr, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC); if (pMetaFile == NULL) { @@ -884,7 +904,9 @@ int walSaveMeta(SWal* pWal) { // rename it n = walBuildMetaName(pWal, metaVer + 1, fnameStr); - ASSERT(n < sizeof(fnameStr) && "Buffer overflow of file name"); + if (n >= sizeof(fnameStr)) { + goto _err; + } if (taosRenameFile(tmpFnameStr, fnameStr) < 0) { wError("failed to rename file due to %s. dest:%s", strerror(errno), fnameStr); @@ -907,7 +929,6 @@ _err: } int walLoadMeta(SWal* pWal) { - ASSERT(pWal->fileInfoSet->size == 0); // find existing meta file int metaVer = walFindCurMetaVer(pWal); if (metaVer == -1) { @@ -920,7 +941,7 @@ int walLoadMeta(SWal* pWal) { int64_t fileSize = 0; taosStatFile(fnameStr, &fileSize, NULL); if (fileSize == 0) { - taosRemoveFile(fnameStr); + (void)taosRemoveFile(fnameStr); wDebug("vgId:%d, wal find empty meta ver %d", pWal->cfg.vgId, metaVer); return -1; } diff --git a/source/libs/wal/src/walMgmt.c b/source/libs/wal/src/walMgmt.c index 702d05f57696c55e88b94d2d335674bd8f262c49..54e6abd85a50a5367bcac9c1c42d910df15d6b06 100644 --- a/source/libs/wal/src/walMgmt.c +++ b/source/libs/wal/src/walMgmt.c @@ -179,17 +179,23 @@ _err: int32_t walAlter(SWal *pWal, SWalCfg *pCfg) { if (pWal == NULL) return TSDB_CODE_APP_ERROR; - if (pWal->cfg.level == pCfg->level && pWal->cfg.fsyncPeriod == pCfg->fsyncPeriod) { - wDebug("vgId:%d, old walLevel:%d fsync:%d, new walLevel:%d fsync:%d not change", pWal->cfg.vgId, pWal->cfg.level, - pWal->cfg.fsyncPeriod, pCfg->level, pCfg->fsyncPeriod); + if (pWal->cfg.level == pCfg->level && pWal->cfg.fsyncPeriod == pCfg->fsyncPeriod && + pWal->cfg.retentionPeriod == pCfg->retentionPeriod && pWal->cfg.retentionSize == pCfg->retentionSize) { + wDebug("vgId:%d, walLevel:%d fsync:%d walRetentionPeriod:%d walRetentionSize:%" PRId64 " not change", + pWal->cfg.vgId, pWal->cfg.level, pWal->cfg.fsyncPeriod, pWal->cfg.retentionPeriod, pWal->cfg.retentionSize); return 0; } - wInfo("vgId:%d, change old walLevel:%d fsync:%d, new walLevel:%d fsync:%d", pWal->cfg.vgId, pWal->cfg.level, - pWal->cfg.fsyncPeriod, pCfg->level, pCfg->fsyncPeriod); + wInfo("vgId:%d, change old walLevel:%d fsync:%d walRetentionPeriod:%d walRetentionSize:%" PRId64 + ", new walLevel:%d fsync:%d walRetentionPeriod:%d walRetentionSize:%" PRId64, + pWal->cfg.vgId, pWal->cfg.level, pWal->cfg.fsyncPeriod, pWal->cfg.retentionPeriod, pWal->cfg.retentionSize, + pCfg->level, pCfg->fsyncPeriod, pCfg->retentionPeriod, pCfg->retentionSize); pWal->cfg.level = pCfg->level; pWal->cfg.fsyncPeriod = pCfg->fsyncPeriod; + pWal->cfg.retentionPeriod = pCfg->retentionPeriod; + pWal->cfg.retentionSize = pCfg->retentionSize; + pWal->fsyncSeq = pCfg->fsyncPeriod / 1000; if (pWal->fsyncSeq <= 0) pWal->fsyncSeq = 1; diff --git a/source/libs/wal/src/walRead.c b/source/libs/wal/src/walRead.c index 0f8f140bd8a2a24e82f997b0029b8b946b1f2f1b..eed0c0dcfcdd3fc68ac45c28ed0c465f2194ce0c 100644 --- a/source/libs/wal/src/walRead.c +++ b/source/libs/wal/src/walRead.c @@ -33,12 +33,11 @@ SWalReader *walOpenReader(SWal *pWal, SWalFilterCond *cond) { pReader->pLogFile = NULL; pReader->curVersion = -1; pReader->curFileFirstVer = -1; - pReader->curInvalid = 1; pReader->capacity = 0; if (cond) { pReader->cond = *cond; } else { - pReader->cond.scanUncommited = 0; +// pReader->cond.scanUncommited = 0; pReader->cond.scanNotApplied = 0; pReader->cond.scanMeta = 0; pReader->cond.enableRef = 0; @@ -63,9 +62,6 @@ SWalReader *walOpenReader(SWal *pWal, SWalFilterCond *cond) { void walCloseReader(SWalReader *pReader) { taosCloseFile(&pReader->pIdxFile); taosCloseFile(&pReader->pLogFile); - /*if (pReader->cond.enableRef) {*/ - /*taosHashRemove(pReader->pWal->pRefHash, &pReader->readerId, sizeof(int64_t));*/ - /*}*/ taosMemoryFreeClear(pReader->pHead); taosMemoryFree(pReader); } @@ -75,19 +71,25 @@ int32_t walNextValidMsg(SWalReader *pReader) { int64_t lastVer = walGetLastVer(pReader->pWal); int64_t committedVer = walGetCommittedVer(pReader->pWal); int64_t appliedVer = walGetAppliedVer(pReader->pWal); - int64_t endVer = pReader->cond.scanUncommited ? lastVer : committedVer; - endVer = TMIN(appliedVer, endVer); + + if(appliedVer < committedVer){ // wait apply ver equal to commit ver, otherwise may lost data when consume data [TD-24010] + wDebug("vgId:%d, wal apply ver:%"PRId64" smaller than commit ver:%"PRId64, pReader->pWal->cfg.vgId, appliedVer, committedVer); + } + + int64_t endVer = TMIN(appliedVer, committedVer); wDebug("vgId:%d, wal start to fetch, index:%" PRId64 ", last index:%" PRId64 " commit index:%" PRId64 - ", applied index:%" PRId64 ", end index:%" PRId64, + ", applied index:%" PRId64", end index:%" PRId64, pReader->pWal->cfg.vgId, fetchVer, lastVer, committedVer, appliedVer, endVer); - pReader->curStopped = 0; + while (fetchVer <= endVer) { if (walFetchHeadNew(pReader, fetchVer) < 0) { return -1; } - if (pReader->pHead->head.msgType == TDMT_VND_SUBMIT || - (IS_META_MSG(pReader->pHead->head.msgType) && pReader->cond.scanMeta)) { + + int32_t type = pReader->pHead->head.msgType; + if (type == TDMT_VND_SUBMIT || ((type == TDMT_VND_DELETE) && (pReader->cond.deleteMsg == 1)) || + (IS_META_MSG(type) && pReader->cond.scanMeta)) { if (walFetchBodyNew(pReader) < 0) { return -1; } @@ -96,14 +98,17 @@ int32_t walNextValidMsg(SWalReader *pReader) { if (walSkipFetchBodyNew(pReader) < 0) { return -1; } - fetchVer++; - ASSERT(fetchVer == pReader->curVersion); + + fetchVer = pReader->curVersion; } } - pReader->curStopped = 1; + return -1; } +int64_t walReaderGetCurrentVer(const SWalReader *pReader) { return pReader->curVersion; } +int64_t walReaderGetValidFirstVer(const SWalReader *pReader) { return walGetFirstVer(pReader->pWal); } + static int64_t walReadSeekFilePos(SWalReader *pReader, int64_t fileFirstVer, int64_t ver) { int64_t ret = 0; @@ -132,7 +137,6 @@ static int64_t walReadSeekFilePos(SWalReader *pReader, int64_t fileFirstVer, int return -1; } - ASSERT(entry.ver == ver); ret = taosLSeekFile(pLogTFile, entry.offset, SEEK_SET); if (ret < 0) { terrno = TAOS_SYSTEM_ERROR(errno); @@ -144,7 +148,7 @@ static int64_t walReadSeekFilePos(SWalReader *pReader, int64_t fileFirstVer, int } static int32_t walReadChangeFile(SWalReader *pReader, int64_t fileFirstVer) { - char fnameStr[WAL_FILE_LEN]; + char fnameStr[WAL_FILE_LEN] = {0}; taosCloseFile(&pReader->pIdxFile); taosCloseFile(&pReader->pLogFile); @@ -198,31 +202,26 @@ int32_t walReadSeekVerImpl(SWalReader *pReader, int64_t ver) { return -1; } - wDebug("vgId:%d, wal version reset from %" PRId64 "(invalid:%d) to %" PRId64, pReader->pWal->cfg.vgId, - pReader->curVersion, pReader->curInvalid, ver); + wDebug("vgId:%d, wal version reset from %" PRId64 " to %" PRId64, pReader->pWal->cfg.vgId, + pReader->curVersion, ver); pReader->curVersion = ver; return 0; } -int32_t walReadSeekVer(SWalReader *pReader, int64_t ver) { +int32_t walReaderSeekVer(SWalReader *pReader, int64_t ver) { SWal *pWal = pReader->pWal; - if (!pReader->curInvalid && ver == pReader->curVersion) { + if (ver == pReader->curVersion) { wDebug("vgId:%d, wal index:%" PRId64 " match, no need to reset", pReader->pWal->cfg.vgId, ver); return 0; } - pReader->curInvalid = 1; - pReader->curVersion = ver; - if (ver > pWal->vers.lastVer || ver < pWal->vers.firstVer) { - wDebug("vgId:%d, invalid index:%" PRId64 ", first index:%" PRId64 ", last index:%" PRId64, pReader->pWal->cfg.vgId, + wInfo("vgId:%d, invalid index:%" PRId64 ", first index:%" PRId64 ", last index:%" PRId64, pReader->pWal->cfg.vgId, ver, pWal->vers.firstVer, pWal->vers.lastVer); terrno = TSDB_CODE_WAL_LOG_NOT_EXIST; return -1; } - if (ver < pWal->vers.snapshotVer) { - } if (walReadSeekVerImpl(pReader, ver) < 0) { return -1; @@ -239,21 +238,21 @@ static int32_t walFetchHeadNew(SWalReader *pRead, int64_t fetchVer) { wDebug("vgId:%d, wal starts to fetch head, index:%" PRId64, pRead->pWal->cfg.vgId, fetchVer); - if (pRead->curInvalid || pRead->curVersion != fetchVer) { - if (walReadSeekVer(pRead, fetchVer) < 0) { - ASSERT(0); - pRead->curVersion = fetchVer; - pRead->curInvalid = 1; + if (pRead->curVersion != fetchVer) { + if (walReaderSeekVer(pRead, fetchVer) < 0) { return -1; } seeked = true; } + while (1) { contLen = taosReadFile(pRead->pLogFile, pRead->pHead, sizeof(SWalCkHead)); if (contLen == sizeof(SWalCkHead)) { break; } else if (contLen == 0 && !seeked) { - walReadSeekVerImpl(pRead, fetchVer); + if(walReadSeekVerImpl(pRead, fetchVer) < 0){ + return -1; + } seeked = true; continue; } else { @@ -262,80 +261,63 @@ static int32_t walFetchHeadNew(SWalReader *pRead, int64_t fetchVer) { } else { terrno = TSDB_CODE_WAL_FILE_CORRUPTED; } - ASSERT(0); - pRead->curInvalid = 1; return -1; } } - pRead->curInvalid = 0; +// pRead->curInvalid = 0; return 0; } -static int32_t walFetchBodyNew(SWalReader *pRead) { - SWalCont *pReadHead = &pRead->pHead->head; +static int32_t walFetchBodyNew(SWalReader *pReader) { + SWalCont *pReadHead = &pReader->pHead->head; int64_t ver = pReadHead->version; - wDebug("vgId:%d, wal starts to fetch body, index:%" PRId64, pRead->pWal->cfg.vgId, ver); + wDebug("vgId:%d, wal starts to fetch body, ver:%" PRId64 " ,len:%d, total", pReader->pWal->cfg.vgId, ver, + pReadHead->bodyLen); - if (pRead->capacity < pReadHead->bodyLen) { - SWalCkHead *ptr = (SWalCkHead *)taosMemoryRealloc(pRead->pHead, sizeof(SWalCkHead) + pReadHead->bodyLen); + if (pReader->capacity < pReadHead->bodyLen) { + SWalCkHead *ptr = (SWalCkHead *)taosMemoryRealloc(pReader->pHead, sizeof(SWalCkHead) + pReadHead->bodyLen); if (ptr == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; } - pRead->pHead = ptr; - pReadHead = &pRead->pHead->head; - pRead->capacity = pReadHead->bodyLen; + + pReader->pHead = ptr; + pReadHead = &pReader->pHead->head; + pReader->capacity = pReadHead->bodyLen; } - if (pReadHead->bodyLen != taosReadFile(pRead->pLogFile, pReadHead->body, pReadHead->bodyLen)) { + if (pReadHead->bodyLen != taosReadFile(pReader->pLogFile, pReadHead->body, pReadHead->bodyLen)) { if (pReadHead->bodyLen < 0) { terrno = TAOS_SYSTEM_ERROR(errno); wError("vgId:%d, wal fetch body error:%" PRId64 ", read request index:%" PRId64 ", since %s", - pRead->pWal->cfg.vgId, pRead->pHead->head.version, ver, tstrerror(terrno)); + pReader->pWal->cfg.vgId, pReader->pHead->head.version, ver, tstrerror(terrno)); } else { wError("vgId:%d, wal fetch body error:%" PRId64 ", read request index:%" PRId64 ", since file corrupted", - pRead->pWal->cfg.vgId, pRead->pHead->head.version, ver); + pReader->pWal->cfg.vgId, pReader->pHead->head.version, ver); terrno = TSDB_CODE_WAL_FILE_CORRUPTED; } - pRead->curInvalid = 1; - ASSERT(0); - return -1; - } - - if (pReadHead->version != ver) { - wError("vgId:%d, wal fetch body error:%" PRId64 ", read request index:%" PRId64, pRead->pWal->cfg.vgId, - pRead->pHead->head.version, ver); - pRead->curInvalid = 1; - terrno = TSDB_CODE_WAL_FILE_CORRUPTED; - ASSERT(0); return -1; } - if (walValidBodyCksum(pRead->pHead) != 0) { - wError("vgId:%d, wal fetch body error:%" PRId64 ", since body checksum not passed", pRead->pWal->cfg.vgId, ver); - pRead->curInvalid = 1; + if (walValidBodyCksum(pReader->pHead) != 0) { + wError("vgId:%d, wal fetch body error:%" PRId64 ", since body checksum not passed", pReader->pWal->cfg.vgId, ver); terrno = TSDB_CODE_WAL_FILE_CORRUPTED; - ASSERT(0); return -1; } - wDebug("vgId:%d, index:%" PRId64 " is fetched, cursor advance", pRead->pWal->cfg.vgId, ver); - pRead->curVersion = ver + 1; + wDebug("vgId:%d, index:%" PRId64 " is fetched, cursor advance", pReader->pWal->cfg.vgId, ver); + pReader->curVersion = ver + 1; return 0; } static int32_t walSkipFetchBodyNew(SWalReader *pRead) { int64_t code; - ASSERT(pRead->curVersion == pRead->pHead->head.version); - ASSERT(pRead->curInvalid == 0); - code = taosLSeekFile(pRead->pLogFile, pRead->pHead->head.bodyLen, SEEK_CUR); if (code < 0) { terrno = TAOS_SYSTEM_ERROR(errno); - pRead->curInvalid = 1; - ASSERT(0); +// pRead->curInvalid = 1; return -1; } @@ -360,11 +342,11 @@ int32_t walFetchHead(SWalReader *pRead, int64_t ver, SWalCkHead *pHead) { return -1; } - if (pRead->curInvalid || pRead->curVersion != ver) { - code = walReadSeekVer(pRead, ver); + if (pRead->curVersion != ver) { + code = walReaderSeekVer(pRead, ver); if (code < 0) { - pRead->curVersion = ver; - pRead->curInvalid = 1; +// pRead->curVersion = ver; +// pRead->curInvalid = 1; return -1; } seeked = true; @@ -375,7 +357,9 @@ int32_t walFetchHead(SWalReader *pRead, int64_t ver, SWalCkHead *pHead) { if (contLen == sizeof(SWalCkHead)) { break; } else if (contLen == 0 && !seeked) { - walReadSeekVerImpl(pRead, ver); + if(walReadSeekVerImpl(pRead, ver) < 0){ + return -1; + } seeked = true; continue; } else { @@ -384,8 +368,7 @@ int32_t walFetchHead(SWalReader *pRead, int64_t ver, SWalCkHead *pHead) { } else { terrno = TSDB_CODE_WAL_FILE_CORRUPTED; } - ASSERT(0); - pRead->curInvalid = 1; +// pRead->curInvalid = 1; return -1; } } @@ -398,7 +381,7 @@ int32_t walFetchHead(SWalReader *pRead, int64_t ver, SWalCkHead *pHead) { return -1; } - pRead->curInvalid = 0; +// pRead->curInvalid = 0; return 0; } @@ -410,13 +393,10 @@ int32_t walSkipFetchBody(SWalReader *pRead, const SWalCkHead *pHead) { pRead->pWal->cfg.vgId, pHead->head.version, pRead->pWal->vers.firstVer, pRead->pWal->vers.commitVer, pRead->pWal->vers.lastVer, pRead->pWal->vers.appliedVer); - ASSERT(pRead->curVersion == pHead->head.version); - ASSERT(pRead->curInvalid == 0); - code = taosLSeekFile(pRead->pLogFile, pHead->head.bodyLen, SEEK_CUR); if (code < 0) { terrno = TAOS_SYSTEM_ERROR(errno); - pRead->curInvalid = 1; +// pRead->curInvalid = 1; return -1; } @@ -447,7 +427,6 @@ int32_t walFetchBody(SWalReader *pRead, SWalCkHead **ppHead) { if (pReadHead->bodyLen != taosReadFile(pRead->pLogFile, pReadHead->body, pReadHead->bodyLen)) { if (pReadHead->bodyLen < 0) { - ASSERT(0); terrno = TAOS_SYSTEM_ERROR(errno); wError("vgId:%d, wal fetch body error:%" PRId64 ", read request index:%" PRId64 ", since %s", pRead->pWal->cfg.vgId, pReadHead->version, ver, tstrerror(terrno)); @@ -456,25 +435,22 @@ int32_t walFetchBody(SWalReader *pRead, SWalCkHead **ppHead) { pRead->pWal->cfg.vgId, pReadHead->version, ver); terrno = TSDB_CODE_WAL_FILE_CORRUPTED; } - pRead->curInvalid = 1; - ASSERT(0); +// pRead->curInvalid = 1; return -1; } if (pReadHead->version != ver) { - ASSERT(0); wError("vgId:%d, wal fetch body error, index:%" PRId64 ", read request index:%" PRId64, pRead->pWal->cfg.vgId, pReadHead->version, ver); - pRead->curInvalid = 1; +// pRead->curInvalid = 1; terrno = TSDB_CODE_WAL_FILE_CORRUPTED; return -1; } if (walValidBodyCksum(*ppHead) != 0) { - ASSERT(0); wError("vgId:%d, wal fetch body error, index:%" PRId64 ", since body checksum not passed", pRead->pWal->cfg.vgId, ver); - pRead->curInvalid = 1; +// pRead->curInvalid = 1; terrno = TSDB_CODE_WAL_FILE_CORRUPTED; return -1; } @@ -503,8 +479,8 @@ int32_t walReadVer(SWalReader *pReader, int64_t ver) { taosThreadMutexLock(&pReader->mutex); - if (pReader->curInvalid || pReader->curVersion != ver) { - if (walReadSeekVer(pReader, ver) < 0) { + if (pReader->curVersion != ver) { + if (walReaderSeekVer(pReader, ver) < 0) { wError("vgId:%d, unexpected wal log, index:%" PRId64 ", since %s", pReader->pWal->cfg.vgId, ver, terrstr()); taosThreadMutexUnlock(&pReader->mutex); return -1; @@ -517,7 +493,10 @@ int32_t walReadVer(SWalReader *pReader, int64_t ver) { if (contLen == sizeof(SWalCkHead)) { break; } else if (contLen == 0 && !seeked) { - walReadSeekVerImpl(pReader, ver); + if(walReadSeekVerImpl(pReader, ver) < 0){ + taosThreadMutexUnlock(&pReader->mutex); + return -1; + } seeked = true; continue; } else { @@ -570,7 +549,7 @@ int32_t walReadVer(SWalReader *pReader, int64_t ver) { if (pReader->pHead->head.version != ver) { wError("vgId:%d, unexpected wal log, index:%" PRId64 ", read request index:%" PRId64, pReader->pWal->cfg.vgId, pReader->pHead->head.version, ver); - pReader->curInvalid = 1; +// pReader->curInvalid = 1; terrno = TSDB_CODE_WAL_FILE_CORRUPTED; taosThreadMutexUnlock(&pReader->mutex); return -1; @@ -583,7 +562,7 @@ int32_t walReadVer(SWalReader *pReader, int64_t ver) { uint32_t readCkSum = walCalcBodyCksum(pReader->pHead->head.body, pReader->pHead->head.bodyLen); uint32_t logCkSum = pReader->pHead->cksumBody; wError("checksum written into log:%u, checksum calculated:%u", logCkSum, readCkSum); - pReader->curInvalid = 1; +// pReader->curInvalid = 1; terrno = TSDB_CODE_WAL_FILE_CORRUPTED; taosThreadMutexUnlock(&pReader->mutex); return -1; @@ -599,7 +578,7 @@ void walReadReset(SWalReader *pReader) { taosThreadMutexLock(&pReader->mutex); taosCloseFile(&pReader->pIdxFile); taosCloseFile(&pReader->pLogFile); - pReader->curInvalid = 1; pReader->curFileFirstVer = -1; + pReader->curVersion = -1; taosThreadMutexUnlock(&pReader->mutex); } diff --git a/source/libs/wal/src/walRef.c b/source/libs/wal/src/walRef.c index 43470f4c82ab1cb35d37ae9ace9a78b938e3cbd9..6aba66192684e262baddf4215d043a875c15f6fc 100644 --- a/source/libs/wal/src/walRef.c +++ b/source/libs/wal/src/walRef.c @@ -26,7 +26,7 @@ SWalRef *walOpenRef(SWal *pWal) { } pRef->refId = tGenIdPI64(); pRef->refVer = -1; - pRef->refFile = -1; + // pRef->refFile = -1; pRef->pWal = pWal; taosHashPut(pWal->pRefHash, &pRef->refId, sizeof(int64_t), &pRef, sizeof(void *)); return pRef; @@ -45,7 +45,7 @@ void walCloseRef(SWal *pWal, int64_t refId) { taosMemoryFree(pRef); } -int32_t walRefVer(SWalRef *pRef, int64_t ver) { +int32_t walSetRefVer(SWalRef *pRef, int64_t ver) { SWal *pWal = pRef->pWal; wDebug("vgId:%d, wal ref version %" PRId64 ", refId %" PRId64, pWal->cfg.vgId, ver, pRef->refId); if (pRef->refVer != ver) { @@ -57,26 +57,12 @@ int32_t walRefVer(SWalRef *pRef, int64_t ver) { } pRef->refVer = ver; - // bsearch in fileSet - SWalFileInfo tmpInfo; - tmpInfo.firstVer = ver; - SWalFileInfo *pRet = taosArraySearch(pWal->fileInfoSet, &tmpInfo, compareWalFileInfo, TD_LE); - ASSERT(pRet != NULL); - pRef->refFile = pRet->firstVer; - taosThreadMutexUnlock(&pWal->mutex); } return 0; } -#if 1 -void walUnrefVer(SWalRef *pRef) { - pRef->refId = -1; - pRef->refFile = -1; -} -#endif - SWalRef *walRefFirstVer(SWal *pWal, SWalRef *pRef) { if (pRef == NULL) { pRef = walOpenRef(pWal); @@ -85,26 +71,19 @@ SWalRef *walRefFirstVer(SWal *pWal, SWalRef *pRef) { } } taosThreadMutexLock(&pWal->mutex); - int64_t ver = walGetFirstVer(pWal); - - wDebug("vgId:%d, wal ref version %" PRId64 " for first", pWal->cfg.vgId, ver); - pRef->refVer = ver; - // bsearch in fileSet - SWalFileInfo tmpInfo; - tmpInfo.firstVer = ver; - SWalFileInfo *pRet = taosArraySearch(pWal->fileInfoSet, &tmpInfo, compareWalFileInfo, TD_LE); - ASSERT(pRet != NULL); - pRef->refFile = pRet->firstVer; taosThreadMutexUnlock(&pWal->mutex); + wDebug("vgId:%d, wal ref version %" PRId64 " for first", pWal->cfg.vgId, ver); + return pRef; } SWalRef *walRefCommittedVer(SWal *pWal) { SWalRef *pRef = walOpenRef(pWal); if (pRef == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; return NULL; } taosThreadMutexLock(&pWal->mutex); @@ -119,7 +98,7 @@ SWalRef *walRefCommittedVer(SWal *pWal) { tmpInfo.firstVer = ver; SWalFileInfo *pRet = taosArraySearch(pWal->fileInfoSet, &tmpInfo, compareWalFileInfo, TD_LE); ASSERT(pRet != NULL); - pRef->refFile = pRet->firstVer; + // pRef->refFile = pRet->firstVer; taosThreadMutexUnlock(&pWal->mutex); return pRef; diff --git a/source/libs/wal/src/walSeek.c b/source/libs/wal/src/walSeek.c index 2cb6614b01bab90cc41e0d11408f3380de4a95fc..cbfd0ef7417389b662ece46d4032f2f7a1a31cbd 100644 --- a/source/libs/wal/src/walSeek.c +++ b/source/libs/wal/src/walSeek.c @@ -40,7 +40,6 @@ static int64_t walSeekWritePos(SWal* pWal, int64_t ver) { terrno = TAOS_SYSTEM_ERROR(errno); return -1; } - ASSERT(entry.ver == ver); code = taosLSeekFile(pLogTFile, entry.offset, SEEK_SET); if (code < 0) { terrno = TAOS_SYSTEM_ERROR(errno); @@ -53,8 +52,7 @@ static int64_t walSeekWritePos(SWal* pWal, int64_t ver) { int walInitWriteFile(SWal* pWal) { TdFilePtr pIdxTFile, pLogTFile; SWalFileInfo* pRet = taosArrayGetLast(pWal->fileInfoSet); - ASSERT(pRet != NULL); - int64_t fileFirstVer = pRet->firstVer; + int64_t fileFirstVer = pRet->firstVer; char fnameStr[WAL_FILE_LEN]; walBuildIdxName(pWal, fileFirstVer, fnameStr); @@ -109,9 +107,8 @@ int64_t walChangeWrite(SWal* pWal, int64_t ver) { tmpInfo.firstVer = ver; // bsearch in fileSet int32_t idx = taosArraySearchIdx(pWal->fileInfoSet, &tmpInfo, compareWalFileInfo, TD_LE); - ASSERT(idx != -1); + /*A(idx != -1);*/ SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, idx); - /*ASSERT(pFileInfo != NULL);*/ int64_t fileFirstVer = pFileInfo->firstVer; walBuildIdxName(pWal, fileFirstVer, fnameStr); diff --git a/source/libs/wal/src/walWrite.c b/source/libs/wal/src/walWrite.c index 96c77d09717df50920252b311c90607db5ab4dc8..9b7b3dfd5006857eb57b5e74edd39a3835fdbd71 100644 --- a/source/libs/wal/src/walWrite.c +++ b/source/libs/wal/src/walWrite.c @@ -63,7 +63,7 @@ int32_t walRestoreFromSnapshot(SWal *pWal, int64_t ver) { wInfo("vgId:%d, restore from snapshot, remove file %s", pWal->cfg.vgId, fnameStr); } } - walRemoveMeta(pWal); + (void)walRemoveMeta(pWal); pWal->writeCur = -1; pWal->totSize = 0; @@ -90,7 +90,7 @@ int32_t walCommit(SWal *pWal, int64_t ver) { if (ver < pWal->vers.commitVer) { return 0; } - if (ver > pWal->vers.lastVer) { + if (ver > pWal->vers.lastVer || pWal->vers.commitVer < pWal->vers.snapshotVer) { terrno = TSDB_CODE_WAL_INVALID_VER; return -1; } @@ -121,7 +121,7 @@ int32_t walRollback(SWal *pWal, int64_t ver) { // delete files in descending order int fileSetSize = taosArrayGetSize(pWal->fileInfoSet); for (int i = pWal->writeCur + 1; i < fileSetSize; i++) { - SWalFileInfo* pInfo = taosArrayPop(pWal->fileInfoSet); + SWalFileInfo *pInfo = taosArrayPop(pWal->fileInfoSet); walBuildLogName(pWal, pInfo->firstVer, fnameStr); wDebug("vgId:%d, wal remove file %s for rollback", pWal->cfg.vgId, fnameStr); @@ -247,21 +247,23 @@ static FORCE_INLINE int32_t walCheckAndRoll(SWal *pWal) { return 0; } -int32_t walBeginSnapshot(SWal *pWal, int64_t ver) { +int32_t walBeginSnapshot(SWal *pWal, int64_t ver, int64_t logRetention) { taosThreadMutexLock(&pWal->mutex); - + ASSERT(logRetention >= 0); pWal->vers.verInSnapshotting = ver; - wDebug("vgId:%d, wal begin snapshot for version %" PRId64 ", first ver %" PRId64 ", last ver %" PRId64, - pWal->cfg.vgId, ver, pWal->vers.firstVer, pWal->vers.lastVer); + pWal->vers.logRetention = logRetention; + + wDebug("vgId:%d, wal begin snapshot for version %" PRId64 ", log retention %" PRId64 " first ver %" PRId64 + ", last ver %" PRId64, + pWal->cfg.vgId, ver, pWal->vers.logRetention, pWal->vers.firstVer, pWal->vers.lastVer); // check file rolling - if (pWal->cfg.retentionPeriod == 0) { - if (walGetLastFileSize(pWal) != 0) { - if (walRollImpl(pWal) < 0) { - wError("vgId:%d, failed to roll wal files since %s", pWal->cfg.vgId, terrstr()); - goto _err; - } + if (walGetLastFileSize(pWal) != 0) { + if (walRollImpl(pWal) < 0) { + wError("vgId:%d, failed to roll wal files since %s", pWal->cfg.vgId, terrstr()); + goto _err; } } + taosThreadMutexUnlock(&pWal->mutex); return 0; @@ -275,67 +277,63 @@ int32_t walEndSnapshot(SWal *pWal) { taosThreadMutexLock(&pWal->mutex); int64_t ver = pWal->vers.verInSnapshotting; - wDebug("vgId:%d, wal end snapshot for version %" PRId64 ", first ver %" PRId64 ", last ver %" PRId64, pWal->cfg.vgId, - ver, pWal->vers.firstVer, pWal->vers.lastVer); + wDebug("vgId:%d, wal end snapshot for version %" PRId64 ", log retention %" PRId64 " first ver %" PRId64 + ", last ver %" PRId64, + pWal->cfg.vgId, ver, pWal->vers.logRetention, pWal->vers.firstVer, pWal->vers.lastVer); if (ver == -1) { code = -1; goto END; - }; + } pWal->vers.snapshotVer = ver; int ts = taosGetTimestampSec(); + ver = TMAX(ver - pWal->vers.logRetention, pWal->vers.firstVer - 1); + // compatible mode for refVer + bool hasTopic = false; + int64_t refVer = INT64_MAX; void *pIter = NULL; while (1) { pIter = taosHashIterate(pWal->pRefHash, pIter); if (pIter == NULL) break; SWalRef *pRef = *(SWalRef **)pIter; if (pRef->refVer == -1) continue; - ver = TMIN(ver, pRef->refVer - 1); - wDebug("vgId:%d, wal found ref %" PRId64 ", refId %" PRId64, pWal->cfg.vgId, pRef->refVer, pRef->refId); + refVer = TMIN(refVer, pRef->refVer - 1); + hasTopic = true; + } + if (pWal->cfg.retentionPeriod == 0 && hasTopic) { + wInfo("vgId:%d, wal found refVer:%" PRId64 " in compatible mode, ver:%" PRId64, pWal->cfg.vgId, refVer, ver); + ver = TMIN(ver, refVer); } + // find files safe to delete int deleteCnt = 0; int64_t newTotSize = pWal->totSize; - SWalFileInfo tmp; + SWalFileInfo tmp = {0}; tmp.firstVer = ver; - // find files safe to delete SWalFileInfo *pInfo = taosArraySearch(pWal->fileInfoSet, &tmp, compareWalFileInfo, TD_LE); + if (pInfo) { - SWalFileInfo *pLastFileInfo = taosArrayGetLast(pWal->fileInfoSet); - wDebug("vgId:%d, wal search found file info: first:%" PRId64 " last:%" PRId64, pWal->cfg.vgId, pInfo->firstVer, - pInfo->lastVer); - if (ver >= pInfo->lastVer) { + wDebug("vgId:%d, wal search found file info. ver:%" PRId64 ", first:%" PRId64 " last:%" PRId64, pWal->cfg.vgId, ver, + pInfo->firstVer, pInfo->lastVer); + ASSERT(ver <= pInfo->lastVer); + if (ver == pInfo->lastVer) { pInfo++; - wDebug("vgId:%d, wal remove advance one file: first:%" PRId64 " last:%" PRId64, pWal->cfg.vgId, pInfo->firstVer, - pInfo->lastVer); - } - if (pInfo <= pLastFileInfo) { - wDebug("vgId:%d, wal end remove for first:%" PRId64 " last:%" PRId64, pWal->cfg.vgId, pInfo->firstVer, - pInfo->lastVer); - } else { - wDebug("vgId:%d, wal no remove", pWal->cfg.vgId); } // iterate files, until the searched result + // delete according to file size or close time for (SWalFileInfo *iter = pWal->fileInfoSet->pData; iter < pInfo; iter++) { - wDebug("vgId:%d, wal check remove file %" PRId64 "(file size %" PRId64 " close ts %" PRId64 - "), new tot size %" PRId64, - pWal->cfg.vgId, iter->firstVer, iter->fileSize, iter->closeTs, newTotSize); - if (((pWal->cfg.retentionSize == 0) || (pWal->cfg.retentionSize != -1 && newTotSize > pWal->cfg.retentionSize)) || - ((pWal->cfg.retentionPeriod == 0) || - (pWal->cfg.retentionPeriod != -1 && iter->closeTs + pWal->cfg.retentionPeriod > ts))) { - // delete according to file size or close time - wDebug("vgId:%d, check pass", pWal->cfg.vgId); + if ((pWal->cfg.retentionSize > 0 && newTotSize > pWal->cfg.retentionSize) || + (pWal->cfg.retentionPeriod == 0 || + pWal->cfg.retentionPeriod > 0 && iter->closeTs >= 0 && iter->closeTs + pWal->cfg.retentionPeriod < ts)) { deleteCnt++; newTotSize -= iter->fileSize; taosArrayPush(pWal->toDeleteFiles, iter); } - wDebug("vgId:%d, check not pass", pWal->cfg.vgId); } - UPDATE_META: // make new array, remove files taosArrayPopFrontBatch(pWal->fileInfoSet, deleteCnt); if (taosArrayGetSize(pWal->fileInfoSet) == 0) { @@ -345,11 +343,12 @@ int32_t walEndSnapshot(SWal *pWal) { pWal->vers.firstVer = ((SWalFileInfo *)taosArrayGet(pWal->fileInfoSet, 0))->firstVer; } } + + // update meta pWal->writeCur = taosArrayGetSize(pWal->fileInfoSet) - 1; pWal->totSize = newTotSize; pWal->vers.verInSnapshotting = -1; - // save snapshot ver, commit ver code = walSaveMeta(pWal); if (code < 0) { goto END; @@ -357,22 +356,27 @@ int32_t walEndSnapshot(SWal *pWal) { // delete files deleteCnt = taosArrayGetSize(pWal->toDeleteFiles); - wDebug("vgId:%d, wal should delete %d files", pWal->cfg.vgId, deleteCnt); - char fnameStr[WAL_FILE_LEN]; + char fnameStr[WAL_FILE_LEN] = {0}; + pInfo = NULL; + for (int i = 0; i < deleteCnt; i++) { pInfo = taosArrayGet(pWal->toDeleteFiles, i); + walBuildLogName(pWal, pInfo->firstVer, fnameStr); - wDebug("vgId:%d, wal remove file %s", pWal->cfg.vgId, fnameStr); if (taosRemoveFile(fnameStr) < 0 && errno != ENOENT) { wError("vgId:%d, failed to remove log file %s due to %s", pWal->cfg.vgId, fnameStr, strerror(errno)); goto END; } walBuildIdxName(pWal, pInfo->firstVer, fnameStr); - wDebug("vgId:%d, wal remove file %s", pWal->cfg.vgId, fnameStr); if (taosRemoveFile(fnameStr) < 0 && errno != ENOENT) { + wError("vgId:%d, failed to remove idx file %s due to %s", pWal->cfg.vgId, fnameStr, strerror(errno)); goto END; } } + if (pInfo != NULL) { + wInfo("vgId:%d, wal log files recycled. count:%d, until ver:%" PRId64 ", closeTs:%" PRId64, pWal->cfg.vgId, + deleteCnt, pInfo->lastVer, pInfo->closeTs); + } taosArrayClear(pWal->toDeleteFiles); END: @@ -382,20 +386,33 @@ END: int32_t walRollImpl(SWal *pWal) { int32_t code = 0; + if (pWal->pIdxFile != NULL) { + code = taosFsyncFile(pWal->pIdxFile); + if (code != 0) { + terrno = TAOS_SYSTEM_ERROR(errno); + goto END; + } code = taosCloseFile(&pWal->pIdxFile); if (code != 0) { terrno = TAOS_SYSTEM_ERROR(errno); goto END; } } + if (pWal->pLogFile != NULL) { + code = taosFsyncFile(pWal->pLogFile); + if (code != 0) { + terrno = TAOS_SYSTEM_ERROR(errno); + goto END; + } code = taosCloseFile(&pWal->pLogFile); if (code != 0) { terrno = TAOS_SYSTEM_ERROR(errno); goto END; } } + TdFilePtr pIdxFile, pLogFile; // create new file int64_t newFileFirstVer = pWal->vers.lastVer + 1; @@ -441,7 +458,8 @@ END: static int32_t walWriteIndex(SWal *pWal, int64_t ver, int64_t offset) { SWalIdxEntry entry = {.ver = ver, .offset = offset}; SWalFileInfo *pFileInfo = walGetCurFileInfo(pWal); - int64_t idxOffset = (entry.ver - pFileInfo->firstVer) * sizeof(SWalIdxEntry); + + int64_t idxOffset = (entry.ver - pFileInfo->firstVer) * sizeof(SWalIdxEntry); wDebug("vgId:%d, write index, index:%" PRId64 ", offset:%" PRId64 ", at %" PRId64, pWal->cfg.vgId, ver, offset, idxOffset); diff --git a/source/libs/wal/test/walMetaTest.cpp b/source/libs/wal/test/walMetaTest.cpp index 891e7dcdaedd753d139ae30c8e1efef1c733733f..0784db917a47f5410c758337dc31cd257eca7320 100644 --- a/source/libs/wal/test/walMetaTest.cpp +++ b/source/libs/wal/test/walMetaTest.cpp @@ -264,7 +264,7 @@ TEST_F(WalCleanEnv, rollbackMultiFile) { ASSERT_EQ(code, 0); ASSERT_EQ(pWal->vers.lastVer, i); if (i == 5) { - walBeginSnapshot(pWal, i); + walBeginSnapshot(pWal, i, 0); walEndSnapshot(pWal); } } @@ -301,7 +301,7 @@ TEST_F(WalCleanDeleteEnv, roll) { ASSERT_EQ(pWal->vers.commitVer, i); } - walBeginSnapshot(pWal, i - 1); + walBeginSnapshot(pWal, i - 1, 0); ASSERT_EQ(pWal->vers.verInSnapshotting, i - 1); walEndSnapshot(pWal); ASSERT_EQ(pWal->vers.snapshotVer, i - 1); @@ -317,7 +317,7 @@ TEST_F(WalCleanDeleteEnv, roll) { ASSERT_EQ(pWal->vers.commitVer, i); } - code = walBeginSnapshot(pWal, i - 1); + code = walBeginSnapshot(pWal, i - 1, 0); ASSERT_EQ(code, 0); code = walEndSnapshot(pWal); ASSERT_EQ(code, 0); diff --git a/source/os/CMakeLists.txt b/source/os/CMakeLists.txt index bc554c48a341f51ff4cf51306a7e5b45299f4282..db066a82b6647462eb3b17e7723411477f7fa1e1 100644 --- a/source/os/CMakeLists.txt +++ b/source/os/CMakeLists.txt @@ -43,7 +43,7 @@ target_link_libraries( ) if(TD_WINDOWS) target_link_libraries( - os PUBLIC ws2_32 iconv msvcregex wcwidth winmm crashdump dbghelp + os PUBLIC ws2_32 iconv msvcregex wcwidth winmm crashdump dbghelp version ) elseif(TD_DARWIN_64) find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation) @@ -53,6 +53,10 @@ elseif(TD_DARWIN_64) target_link_libraries( os PUBLIC dl m iconv ) +elseif(TD_ALPINE) + target_link_libraries( + os PUBLIC dl m rt unwind + ) else() target_link_libraries( os PUBLIC dl m rt diff --git a/source/os/src/osDir.c b/source/os/src/osDir.c index 331d24174591648a080242b22b889866efa93eb4..3d63da7ba33adc05d201987faf438390b9bc6759 100644 --- a/source/os/src/osDir.c +++ b/source/os/src/osDir.c @@ -89,6 +89,8 @@ typedef struct dirent TdDirEntry; #endif +#define TDDIRMAXLEN 1024 + void taosRemoveDir(const char *dirname) { TdDirPtr pDir = taosOpenDir(dirname); if (pDir == NULL) return; @@ -133,8 +135,8 @@ int32_t taosMkDir(const char *dirname) { } int32_t taosMulMkDir(const char *dirname) { - if (dirname == NULL) return -1; - char temp[1024]; + if (dirname == NULL || strlen(dirname) >= TDDIRMAXLEN) return -1; + char temp[TDDIRMAXLEN]; char *pos = temp; int32_t code = 0; #ifdef WINDOWS @@ -192,8 +194,8 @@ int32_t taosMulMkDir(const char *dirname) { } int32_t taosMulModeMkDir(const char *dirname, int mode) { - if (dirname == NULL) return -1; - char temp[1024]; + if (dirname == NULL || strlen(dirname) >= TDDIRMAXLEN) return -1; + char temp[TDDIRMAXLEN]; char *pos = temp; int32_t code = 0; #ifdef WINDOWS @@ -204,8 +206,7 @@ int32_t taosMulModeMkDir(const char *dirname, int mode) { #endif if (taosDirExist(temp)) { - chmod(temp, mode); - return code; + return chmod(temp, mode); } if (strncmp(temp, TD_DIRSEP, 1) == 0) { @@ -247,12 +248,10 @@ int32_t taosMulModeMkDir(const char *dirname, int mode) { } if (code < 0 && errno == EEXIST) { - chmod(temp, mode); - return 0; + return chmod(temp, mode); } - chmod(temp, mode); - return code; + return chmod(temp, mode); } void taosRemoveOldFiles(const char *dirname, int32_t keepDays) { diff --git a/source/os/src/osFile.c b/source/os/src/osFile.c index 4cdf4cbdbc512fec2d774a442afe00a68f450bd2..dd670595f00e77275977978b87e7e293061df91f 100644 --- a/source/os/src/osFile.c +++ b/source/os/src/osFile.c @@ -132,15 +132,20 @@ int64_t taosCopyFile(const char *from, const char *to) { if (bytes < sizeof(buffer)) break; } - taosFsyncFile(pFileTo); + int code = taosFsyncFile(pFileTo); taosCloseFile(&pFileFrom); taosCloseFile(&pFileTo); + + if (code != 0) { + return -1; + } return size; _err: if (pFileFrom != NULL) taosCloseFile(&pFileFrom); if (pFileTo != NULL) taosCloseFile(&pFileTo); + /* coverity[+retval] */ taosRemoveFile(to); return -1; #endif @@ -151,7 +156,7 @@ TdFilePtr taosCreateFile(const char *path, int32_t tdFileOptions) { if (!fp) { if (errno == ENOENT) { // Try to create directory recursively - char *s = strdup(path); + char *s = taosStrdup(path); if (taosMulMkDir(taosDirName(s)) != 0) { taosMemoryFree(s); return NULL; @@ -192,7 +197,7 @@ int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime) { int32_t code = _stati64(path, &fileStat); #else struct stat fileStat; - int32_t code = stat(path, &fileStat); + int32_t code = stat(path, &fileStat); #endif if (code < 0) { return code; @@ -209,10 +214,9 @@ int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime) { return 0; } int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) { - if (pFile == NULL) { - return 0; + if (pFile == NULL || pFile->fd < 0) { + return -1; } - assert(pFile->fd >= 0); // Please check if you have closed the file. #ifdef WINDOWS @@ -234,7 +238,7 @@ int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) { #else struct stat fileStat; - int32_t code = fstat(pFile->fd, &fileStat); + int32_t code = fstat(pFile->fd, &fileStat); if (code < 0) { printf("taosFStatFile run fstat fail."); return code; @@ -266,7 +270,10 @@ TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) { } else { mode = (tdFileOptions & TD_FILE_TEXT) ? "rt+" : "rb+"; } - assert(!(tdFileOptions & TD_FILE_EXCL)); + ASSERT(!(tdFileOptions & TD_FILE_EXCL)); + if (tdFileOptions & TD_FILE_EXCL) { + return NULL; + } fp = fopen(path, mode); if (fp == NULL) { return NULL; @@ -365,7 +372,13 @@ int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) { #if FILE_WITH_LOCK taosThreadRwlockRdlock(&(pFile->rwlock)); #endif - assert(pFile->fd >= 0); // Please check if you have closed the file. + ASSERT(pFile->fd >= 0); // Please check if you have closed the file. + if (pFile->fd < 0) { +#if FILE_WITH_LOCK + taosThreadRwlockUnlock(&(pFile->rwlock)); +#endif + return -1; + } int64_t leftbytes = count; int64_t readbytes; char *tbuf = (char *)buf; @@ -409,7 +422,13 @@ int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) #if FILE_WITH_LOCK taosThreadRwlockRdlock(&(pFile->rwlock)); #endif - assert(pFile->fd >= 0); // Please check if you have closed the file. + ASSERT(pFile->fd >= 0); // Please check if you have closed the file. + if (pFile->fd < 0) { +#if FILE_WITH_LOCK + taosThreadRwlockUnlock(&(pFile->rwlock)); +#endif + return -1; + } #ifdef WINDOWS size_t pos = _lseeki64(pFile->fd, 0, SEEK_CUR); _lseeki64(pFile->fd, offset, SEEK_SET); @@ -432,6 +451,9 @@ int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) { taosThreadRwlockWrlock(&(pFile->rwlock)); #endif if (pFile->fd < 0) { +#if FILE_WITH_LOCK + taosThreadRwlockUnlock(&(pFile->rwlock)); +#endif return 0; } @@ -467,7 +489,13 @@ int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t #if FILE_WITH_LOCK taosThreadRwlockWrlock(&(pFile->rwlock)); #endif - assert(pFile->fd >= 0); // Please check if you have closed the file. + ASSERT(pFile->fd >= 0); // Please check if you have closed the file. + if (pFile->fd < 0) { +#if FILE_WITH_LOCK + taosThreadRwlockUnlock(&(pFile->rwlock)); +#endif + return 0; + } #ifdef WINDOWS size_t pos = _lseeki64(pFile->fd, 0, SEEK_CUR); _lseeki64(pFile->fd, offset, SEEK_SET); @@ -483,10 +511,13 @@ int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t } int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) { + if (pFile == NULL || pFile->fd < 0) { + return -1; + } #if FILE_WITH_LOCK taosThreadRwlockRdlock(&(pFile->rwlock)); #endif - assert(pFile->fd >= 0); // Please check if you have closed the file. + ASSERT(pFile->fd >= 0); // Please check if you have closed the file. #ifdef WINDOWS int64_t ret = _lseeki64(pFile->fd, offset, whence); #else @@ -502,12 +533,16 @@ int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) { if (pFile == NULL) { return 0; } - assert(pFile->fd >= 0); // Please check if you have closed the file. + ASSERT(pFile->fd >= 0); // Please check if you have closed the file. + if (pFile->fd < 0) { + return -1; + } - struct stat fileStat; #ifdef WINDOWS - int32_t code = _fstat(pFile->fd, &fileStat); + struct __stat64 fileStat; + int32_t code = _fstat64(pFile->fd, &fileStat); #else + struct stat fileStat; int32_t code = fstat(pFile->fd, &fileStat); #endif if (code < 0) { @@ -526,6 +561,10 @@ int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) { } int32_t taosLockFile(TdFilePtr pFile) { + ASSERT(pFile->fd >= 0); // Please check if you have closed the file. + if (pFile->fd < 0) { + return -1; + } #ifdef WINDOWS BOOL fSuccess = FALSE; LARGE_INTEGER fileSize; @@ -544,17 +583,19 @@ int32_t taosLockFile(TdFilePtr pFile) { } return 0; #else - assert(pFile->fd >= 0); // Please check if you have closed the file. - return (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB); #endif } int32_t taosUnLockFile(TdFilePtr pFile) { + ASSERT(pFile->fd >= 0); + if (pFile->fd < 0) { + return 0; + } #ifdef WINDOWS - BOOL fSuccess = FALSE; - OVERLAPPED overlapped = {0}; - HANDLE hFile = (HANDLE)_get_osfhandle(pFile->fd); + BOOL fSuccess = FALSE; + OVERLAPPED overlapped = {0}; + HANDLE hFile = (HANDLE)_get_osfhandle(pFile->fd); fSuccess = UnlockFileEx(hFile, 0, ~0, ~0, &overlapped); if (!fSuccess) { @@ -562,19 +603,19 @@ int32_t taosUnLockFile(TdFilePtr pFile) { } return 0; #else - assert(pFile->fd >= 0); // Please check if you have closed the file. - return (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB); #endif } int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) { -#ifdef WINDOWS + if (pFile == NULL) { + return 0; + } if (pFile->fd < 0) { - errno = EBADF; printf("Ftruncate file error, fd arg was negative\n"); return -1; } +#ifdef WINDOWS HANDLE h = (HANDLE)_get_osfhandle(pFile->fd); @@ -619,11 +660,6 @@ int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) { return 0; #else - if (pFile == NULL) { - return 0; - } - assert(pFile->fd >= 0); // Please check if you have closed the file. - return ftruncate(pFile->fd, l_size); #endif } @@ -651,7 +687,10 @@ int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, in if (pFileOut == NULL || pFileIn == NULL) { return 0; } - assert(pFileIn->fd >= 0 && pFileOut->fd >= 0); + ASSERT(pFileIn->fd >= 0 && pFileOut->fd >= 0); + if (pFileIn->fd < 0 || pFileOut->fd < 0) { + return 0; + } #ifdef WINDOWS @@ -744,11 +783,9 @@ int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, in } void taosFprintfFile(TdFilePtr pFile, const char *format, ...) { - if (pFile == NULL) { + if (pFile == NULL || pFile->fp == NULL) { return; } - assert(pFile->fp != NULL); - va_list ap; va_start(ap, format); vfprintf(pFile->fp, format, ap); @@ -773,7 +810,10 @@ int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) { if (*ptrBuf != NULL) { taosMemoryFreeClear(*ptrBuf); } - assert(pFile->fp != NULL); + ASSERT(pFile->fp != NULL); + if (pFile->fp == NULL) { + return -1; + } #ifdef WINDOWS *ptrBuf = taosMemoryMalloc(1024); if (*ptrBuf == NULL) return -1; @@ -793,7 +833,10 @@ int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) { if (pFile == NULL || buf == NULL) { return -1; } - assert(pFile->fp != NULL); + ASSERT(pFile->fp != NULL); + if (pFile->fp == NULL) { + return -1; + } if (fgets(buf, maxSize, pFile->fp) == NULL) { return -1; } @@ -802,9 +845,12 @@ int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) { int32_t taosEOFFile(TdFilePtr pFile) { if (pFile == NULL) { - return 0; + return -1; + } + ASSERT(pFile->fp != NULL); + if (pFile->fp == NULL) { + return -1; } - assert(pFile->fp != NULL); return feof(pFile->fp); } diff --git a/source/os/src/osLocale.c b/source/os/src/osLocale.c index 7319181a777cb8140396f592009507a151d2620b..136b8cf022346640b526cdb0bbac3c4fb8c4885c 100644 --- a/source/os/src/osLocale.c +++ b/source/os/src/osLocale.c @@ -59,11 +59,11 @@ char *taosCharsetReplace(char *charsetstr) { for (int32_t i = 0; i < tListLen(charsetRep); ++i) { if (strcasecmp(charsetRep[i].oldCharset, charsetstr) == 0) { - return strdup(charsetRep[i].newCharset); + return taosStrdup(charsetRep[i].newCharset); } } - return strdup(charsetstr); + return taosStrdup(charsetstr); } /** @@ -71,7 +71,7 @@ char *taosCharsetReplace(char *charsetstr) { * seems does not response as expected. * * In some Linux systems, setLocale(LC_CTYPE, "") may return NULL, in which case the launch of - * both the TDengine Server and the Client may be interrupted. + * both the Server and the Client may be interrupted. * * In case that the setLocale failed to be executed, the right charset needs to be set. */ @@ -171,7 +171,7 @@ void taosGetSystemLocale(char *outLocale, char *outCharset) { strcpy(outLocale, "en_US.UTF-8"); } else { tstrncpy(outLocale, locale, TD_LOCALE_LEN); - // printf("locale not configured, set to system default:%s", outLocale); + //printf("locale not configured, set to system default:%s\n", outLocale); } // if user does not specify the charset, extract it from locale diff --git a/source/os/src/osMath.c b/source/os/src/osMath.c index 41c8c9257a95fb57213c33042ac7c1339295553b..0cff0f78a618b5d82f05b55d45e2cc6303a186fd 100644 --- a/source/os/src/osMath.c +++ b/source/os/src/osMath.c @@ -15,35 +15,20 @@ #define ALLOW_FORBID_FUNC #define _DEFAULT_SOURCE -#include "os.h" #include +#include "talgo.h" -#ifdef WINDOWS -void swapStr(char* j, char* J, int width) { - int i; - char tmp; - for (i = 0; i < width; i++) { - tmp = *j; - *j = *J; - *J = tmp; - j++; - J++; - } -} -#endif - -int qsortHelper(const void* p1, const void* p2, const void* param) { +int32_t qsortHelper(const void* p1, const void* p2, const void* param) { __compar_fn_t comparFn = param; return comparFn(p1, p2); } // todo refactor: 1) move away; 2) use merge sort instead; 3) qsort is not a stable sort actually. void taosSort(void* base, int64_t sz, int64_t width, __compar_fn_t compar) { -#ifdef _ALPINE +#if defined(WINDOWS) || defined(_ALPINE) void* param = compar; - taosqsort(base, width, sz, param, qsortHelper); + taosqsort(base, sz, width, param, qsortHelper); #else qsort(base, sz, width, compar); #endif } - diff --git a/source/os/src/osMemory.c b/source/os/src/osMemory.c index 2e68bd5ccd3ad937dbcfce6988fcb7ef6060f31a..1ae4afe0e033731d26072a02e51a4fe34dc0a30f 100644 --- a/source/os/src/osMemory.c +++ b/source/os/src/osMemory.c @@ -228,6 +228,32 @@ void taosPrintBackTrace() { void taosPrintBackTrace() { return; } #endif +int32_t taosMemoryDbgInit() { +#if defined(LINUX) && !defined(_ALPINE) + int ret = mallopt(M_MMAP_THRESHOLD, 0); + if (0 == ret) { + return TAOS_SYSTEM_ERROR(errno); + } + + return 0; +#else + return TSDB_CODE_FAILED; +#endif +} + +int32_t taosMemoryDbgInitRestore() { +#if defined(LINUX) && !defined(_ALPINE) + int ret = mallopt(M_MMAP_THRESHOLD, 128 * 1024); + if (0 == ret) { + return TAOS_SYSTEM_ERROR(errno); + } + + return 0; +#else + return TSDB_CODE_FAILED; +#endif +} + void *taosMemoryMalloc(int64_t size) { #ifdef USE_TD_MEMORY void *tmp = malloc(size + sizeof(TdMemoryInfo)); @@ -266,7 +292,10 @@ void *taosMemoryRealloc(void *ptr, int64_t size) { if (ptr == NULL) return taosMemoryMalloc(size); TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo)); - assert(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL); + ASSERT(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL); + if (tpTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) { ++ return NULL; ++ } TdMemoryInfo tdMemoryInfo; memcpy(&tdMemoryInfo, pTdMemoryInfo, sizeof(TdMemoryInfo)); @@ -283,13 +312,15 @@ void *taosMemoryRealloc(void *ptr, int64_t size) { #endif } -void *taosMemoryStrDup(const char *ptr) { +char *taosStrdup(const char *ptr) { #ifdef USE_TD_MEMORY if (ptr == NULL) return NULL; TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo)); - assert(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL); - + ASSERT(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL); + if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) { + return NULL; + } void *tmp = tstrdup(pTdMemoryInfo); if (tmp == NULL) return NULL; @@ -323,7 +354,10 @@ int64_t taosMemorySize(void *ptr) { #ifdef USE_TD_MEMORY TdMemoryInfoPtr pTdMemoryInfo = (TdMemoryInfoPtr)((char *)ptr - sizeof(TdMemoryInfo)); - assert(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL); + ASSERT(pTdMemoryInfo->symbol == TD_MEMORY_SYMBOL); + if (pTdMemoryInfo->symbol != TD_MEMORY_SYMBOL) { ++ return NULL; ++ } return pTdMemoryInfo->memorySize; #else @@ -338,7 +372,7 @@ int64_t taosMemorySize(void *ptr) { } void taosMemoryTrim(int32_t size) { -#if defined(WINDOWS) || defined(DARWIN) +#if defined(WINDOWS) || defined(DARWIN) || defined(_ALPINE) // do nothing return; #else @@ -348,7 +382,7 @@ void taosMemoryTrim(int32_t size) { void* taosMemoryMallocAlign(uint32_t alignment, int64_t size) { #ifdef USE_TD_MEMORY - assert(0); + ASSERT(0); #else #if defined(LINUX) void* p = memalign(alignment, size); diff --git a/source/os/src/osRand.c b/source/os/src/osRand.c index 4998eb45a4527fd52d9559f5f99fe7f1e5362428..83c36a422d37b0af4b20a20992e79812c1544b02 100644 --- a/source/os/src/osRand.c +++ b/source/os/src/osRand.c @@ -25,7 +25,15 @@ void taosSeedRand(uint32_t seed) { return srand(seed); } -uint32_t taosRand(void) { return rand(); } +uint32_t taosRand(void) { +#ifdef WINDOWS + unsigned int pSeed; + rand_s(&pSeed); + return pSeed; +#else + return rand(); +#endif +} uint32_t taosRandR(uint32_t* pSeed) { #ifdef WINDOWS diff --git a/source/os/src/osSemaphore.c b/source/os/src/osSemaphore.c index 2f947d325263d45025a7cff835a715ac108674e7..c1ef57e9c5cc874ccc28c8228836693cb7de0db1 100644 --- a/source/os/src/osSemaphore.c +++ b/source/os/src/osSemaphore.c @@ -86,8 +86,8 @@ int32_t tsem_timewait(tsem_t* sem, int64_t ms) { while ((rc = sem_timedwait(sem, &ts)) == -1 && errno == EINTR) continue; return rc; /* This should have timed out */ - // assert(errno == ETIMEDOUT); - // assert(rc != 0); + // ASSERT(errno == ETIMEDOUT); + // ASSERT(rc != 0); // GetSystemTimeAsFileTime(&ft_after); // // We specified a non-zero wait. Time must advance. // if (ft_before.dwLowDateTime == ft_after.dwLowDateTime && ft_before.dwHighDateTime == ft_after.dwHighDateTime) @@ -132,7 +132,8 @@ int tsem_wait(tsem_t *psem) { int tsem_timewait(tsem_t *psem, int64_t milis) { if (psem == NULL || *psem == NULL) return -1; - dispatch_semaphore_wait(*psem, milis * 1000 * 1000); + dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(milis * USEC_PER_SEC)); + dispatch_semaphore_wait(*psem, time); return 0; } diff --git a/source/os/src/osSleep.c b/source/os/src/osSleep.c index a2373f952f6a22a7fd34a12b052502c04206598f..f6cc7d608d57b1343a95a5e68bd077b06d6fbfaa 100644 --- a/source/os/src/osSleep.c +++ b/source/os/src/osSleep.c @@ -22,6 +22,7 @@ #endif void taosSsleep(int32_t s) { + if (s < 0) return; #ifdef WINDOWS Sleep(1000 * s); #else @@ -30,6 +31,7 @@ void taosSsleep(int32_t s) { } void taosMsleep(int32_t ms) { + if (ms < 0) return; #ifdef WINDOWS Sleep(ms); #else @@ -38,6 +40,7 @@ void taosMsleep(int32_t ms) { } void taosUsleep(int32_t us) { + if (us < 0) return; #ifdef WINDOWS HANDLE timer; LARGE_INTEGER interval; diff --git a/source/os/src/osSocket.c b/source/os/src/osSocket.c index 3a93a26b8576976a96d6a523575413ee854fa683..2b2a0daf7b4d0bf7e69552c442a047bd9f32e0a5 100644 --- a/source/os/src/osSocket.c +++ b/source/os/src/osSocket.c @@ -298,7 +298,7 @@ int32_t taosGetSockOpt(TdSocketPtr pSocket, int32_t level, int32_t optname, void return -1; } #ifdef WINDOWS - assert(0); + ASSERT(0); return 0; #else return getsockopt(pSocket->fd, level, optname, optval, (int *)optlen); @@ -662,7 +662,7 @@ int32_t taosKeepTcpAlive(TdSocketPtr pSocket) { int taosGetLocalIp(const char *eth, char *ip) { #if defined(WINDOWS) // DO NOTHAING - assert(0); + ASSERT(0); return 0; #else int fd; @@ -689,7 +689,7 @@ int taosGetLocalIp(const char *eth, char *ip) { int taosValidIp(uint32_t ip) { #if defined(WINDOWS) // DO NOTHAING - assert(0); + ASSERT(0); return 0; #else int ret = -1; @@ -745,8 +745,10 @@ bool taosValidIpAndPort(uint32_t ip, uint16_t port) { #endif serverAdd.sin_port = (uint16_t)htons(port); - if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) <= 2) { - // printf("failed to open TCP socket: %d (%s)", errno, strerror(errno)); + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) { // exception + return false; + } else if (fd <= 2) { // in, out, err taosCloseSocketNoCheck1(fd); return false; } @@ -924,7 +926,7 @@ uint32_t ip2uint(const char *const ip_addr) { void taosBlockSIGPIPE() { #ifdef WINDOWS - // assert(0); + // ASSERT(0); #else sigset_t signal_mask; sigemptyset(&signal_mask); @@ -994,7 +996,7 @@ int32_t taosGetFqdn(char *fqdn) { #else printf("failed to get hostname, reason:%s\n", strerror(errno)); #endif - assert(0); + ASSERT(0); return -1; } @@ -1006,7 +1008,7 @@ int32_t taosGetFqdn(char *fqdn) { // hints.ai_family = AF_INET; strcpy(fqdn, hostname); strcpy(fqdn + strlen(hostname), ".local"); -#else // __APPLE__ +#else // linux struct addrinfo hints = {0}; struct addrinfo *result = NULL; hints.ai_flags = AI_CANONNAME; @@ -1018,7 +1020,7 @@ int32_t taosGetFqdn(char *fqdn) { } strcpy(fqdn, result->ai_canonname); freeaddrinfo(result); -#endif // __APPLE__ +#endif // linux return 0; } @@ -1031,7 +1033,7 @@ void taosIgnSIGPIPE() { signal(SIGPIPE, SIG_IGN); } void taosSetMaskSIGPIPE() { #ifdef WINDOWS - // assert(0); + // ASSERT(0); #else sigset_t signal_mask; sigemptyset(&signal_mask); diff --git a/source/os/src/osString.c b/source/os/src/osString.c index 5419da1c0ce49fe8e61cbf030ad540918835f465..0f459b58cd3a31118ac3c37a304449aad3834792 100644 --- a/source/os/src/osString.c +++ b/source/os/src/osString.c @@ -94,25 +94,25 @@ int32_t tasoUcs4Compare(TdUcs4 *f1_ucs4, TdUcs4 *f2_ucs4, int32_t bytes) { return 0; -#if 0 - int32_t ucs4_max_len = bytes + 4; - char *f1_mbs = taosMemoryCalloc(bytes, 1); - char *f2_mbs = taosMemoryCalloc(bytes, 1); - if (taosUcs4ToMbs(f1_ucs4, ucs4_max_len, f1_mbs) < 0) { - return -1; - } - if (taosUcs4ToMbs(f2_ucs4, ucs4_max_len, f2_mbs) < 0) { - return -1; - } - int32_t ret = strcmp(f1_mbs, f2_mbs); - taosMemoryFree(f1_mbs); - taosMemoryFree(f2_mbs); - return ret; -#endif +//#if 0 +// int32_t ucs4_max_len = bytes + 4; +// char *f1_mbs = taosMemoryCalloc(bytes, 1); +// char *f2_mbs = taosMemoryCalloc(bytes, 1); +// if (taosUcs4ToMbs(f1_ucs4, ucs4_max_len, f1_mbs) < 0) { +// return -1; +// } +// if (taosUcs4ToMbs(f2_ucs4, ucs4_max_len, f2_mbs) < 0) { +// return -1; +// } +// int32_t ret = strcmp(f1_mbs, f2_mbs); +// taosMemoryFree(f1_mbs); +// taosMemoryFree(f2_mbs); +// return ret; +//#endif } TdUcs4 *tasoUcs4Copy(TdUcs4 *target_ucs4, TdUcs4 *source_ucs4, int32_t len_ucs4) { - assert(taosMemorySize(target_ucs4) >= len_ucs4 * sizeof(TdUcs4)); + ASSERT(taosMemorySize(target_ucs4) >= len_ucs4 * sizeof(TdUcs4)); return memcpy(target_ucs4, source_ucs4, len_ucs4 * sizeof(TdUcs4)); } @@ -217,7 +217,7 @@ void taosReleaseConv(int32_t idx, iconv_t conv, ConvType type) { bool taosMbsToUcs4(const char *mbs, size_t mbsLength, TdUcs4 *ucs4, int32_t ucs4_max_len, int32_t *len) { #ifdef DISALLOW_NCHAR_WITHOUT_ICONV - printf("Nchar cannot be read and written without iconv, please install iconv library and recompile TDengine.\n"); + printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n"); return -1; #else memset(ucs4, 0, ucs4_max_len); @@ -245,7 +245,7 @@ bool taosMbsToUcs4(const char *mbs, size_t mbsLength, TdUcs4 *ucs4, int32_t ucs4 int32_t taosUcs4ToMbs(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs) { #ifdef DISALLOW_NCHAR_WITHOUT_ICONV - printf("Nchar cannot be read and written without iconv, please install iconv library and recompile TDengine.\n"); + printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n"); return -1; #else @@ -263,7 +263,7 @@ int32_t taosUcs4ToMbs(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs) { } bool taosValidateEncodec(const char *encodec) { #ifdef DISALLOW_NCHAR_WITHOUT_ICONV - printf("Nchar cannot be read and written without iconv, please install iconv library and recompile TDengine.\n"); + printf("Nchar cannot be read and written without iconv, please install iconv library and recompile.\n"); return true; #else iconv_t cd = iconv_open(encodec, DEFAULT_UNICODE_ENCODEC); @@ -351,75 +351,75 @@ char *taosStrCaseStr(const char *str, const char *pattern) { int64_t taosStr2Int64(const char *str, char **pEnd, int32_t radix) { int64_t tmp = strtoll(str, pEnd, radix); -#ifdef DARWIN +#if defined(DARWIN) || defined(_ALPINE) if (errno == EINVAL) errno = 0; #endif #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); #endif return tmp; } uint64_t taosStr2UInt64(const char *str, char **pEnd, int32_t radix) { uint64_t tmp = strtoull(str, pEnd, radix); -#ifdef DARWIN +#if defined(DARWIN) || defined(_ALPINE) if (errno == EINVAL) errno = 0; #endif #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); #endif return tmp; } int32_t taosStr2Int32(const char *str, char **pEnd, int32_t radix) { int32_t tmp = strtol(str, pEnd, radix); -#ifdef DARWIN +#if defined(DARWIN) || defined(_ALPINE) if (errno == EINVAL) errno = 0; #endif #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); #endif return tmp; } uint32_t taosStr2UInt32(const char *str, char **pEnd, int32_t radix) { uint32_t tmp = strtol(str, pEnd, radix); -#ifdef DARWIN +#if defined(DARWIN) || defined(_ALPINE) if (errno == EINVAL) errno = 0; #endif #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); #endif return tmp; } int16_t taosStr2Int16(const char *str, char **pEnd, int32_t radix) { int32_t tmp = strtol(str, pEnd, radix); -#ifdef DARWIN +#if defined(DARWIN) || defined(_ALPINE) if (errno == EINVAL) errno = 0; #endif #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); - assert(tmp >= SHRT_MIN); - assert(tmp <= SHRT_MAX); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); + ASSERT(tmp >= SHRT_MIN); + ASSERT(tmp <= SHRT_MAX); #endif return (int16_t)tmp; } uint16_t taosStr2UInt16(const char *str, char **pEnd, int32_t radix) { uint32_t tmp = strtoul(str, pEnd, radix); -#ifdef DARWIN +#if defined(DARWIN) || defined(_ALPINE) if (errno == EINVAL) errno = 0; #endif #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); - assert(tmp <= USHRT_MAX); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); + ASSERT(tmp <= USHRT_MAX); #endif return (uint16_t)tmp; } @@ -427,23 +427,23 @@ uint16_t taosStr2UInt16(const char *str, char **pEnd, int32_t radix) { int8_t taosStr2Int8(const char *str, char **pEnd, int32_t radix) { int32_t tmp = strtol(str, pEnd, radix); #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); - assert(tmp >= SCHAR_MIN); - assert(tmp <= SCHAR_MAX); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); + ASSERT(tmp >= SCHAR_MIN); + ASSERT(tmp <= SCHAR_MAX); #endif return tmp; } uint8_t taosStr2UInt8(const char *str, char **pEnd, int32_t radix) { uint32_t tmp = strtoul(str, pEnd, radix); -#ifdef DARWIN +#if defined(DARWIN) || defined(_ALPINE) if (errno == EINVAL) errno = 0; #endif #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); - assert(tmp <= UCHAR_MAX); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); + ASSERT(tmp <= UCHAR_MAX); #endif return tmp; } @@ -451,9 +451,9 @@ uint8_t taosStr2UInt8(const char *str, char **pEnd, int32_t radix) { double taosStr2Double(const char *str, char **pEnd) { double tmp = strtod(str, pEnd); #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); - assert(tmp != HUGE_VAL); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); + ASSERT(tmp != HUGE_VAL); #endif return tmp; } @@ -461,10 +461,10 @@ double taosStr2Double(const char *str, char **pEnd) { float taosStr2Float(const char *str, char **pEnd) { float tmp = strtof(str, pEnd); #ifdef TD_CHECK_STR_TO_INT_ERROR - assert(errno != ERANGE); - assert(errno != EINVAL); - assert(tmp != HUGE_VALF); - assert(tmp != NAN); + ASSERT(errno != ERANGE); + ASSERT(errno != EINVAL); + ASSERT(tmp != HUGE_VALF); + ASSERT(tmp != NAN); #endif return tmp; } diff --git a/source/os/src/osSysinfo.c b/source/os/src/osSysinfo.c index 897e68a12687e3ae713f685a2898a4061bb78f81..84004ed3c18d1bb4baa218d450e7c825d25cd385 100644 --- a/source/os/src/osSysinfo.c +++ b/source/os/src/osSysinfo.c @@ -17,6 +17,10 @@ #include "os.h" #include "taoserror.h" +#if defined(CUS_NAME) || defined(CUS_PROMPT) || defined(CUS_EMAIL) +#include "cus_name.h" +#endif + #define PROCESS_ITEM 12 #define UUIDLEN37 37 @@ -124,7 +128,7 @@ static char tsProcIOFile[25] = {0}; static void taosGetProcIOnfos() { tsPageSizeKB = sysconf(_SC_PAGESIZE) / 1024; tsOpenMax = sysconf(_SC_OPEN_MAX); - tsStreamMax = sysconf(_SC_STREAM_MAX); + tsStreamMax = TMAX(sysconf(_SC_STREAM_MAX), 0); tsProcId = (pid_t)syscall(SYS_gettid); snprintf(tsProcMemFile, sizeof(tsProcMemFile), "/proc/%d/status", tsProcId); @@ -250,9 +254,13 @@ void taosGetSystemInfo() { int32_t taosGetEmail(char *email, int32_t maxLen) { #ifdef WINDOWS - // assert(0); + // ASSERT(0); #elif defined(_TD_DARWIN_64) +#ifdef CUS_PROMPT + const char *filepath = "/usr/local/"CUS_PROMPT"/email"; +#else const char *filepath = "/usr/local/taos/email"; +#endif // CUS_PROMPT TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ); if (pFile == NULL) return false; @@ -264,8 +272,12 @@ int32_t taosGetEmail(char *email, int32_t maxLen) { taosCloseFile(&pFile); return 0; +#else +#ifdef CUS_PROMPT + const char *filepath = "/usr/local/"CUS_PROMPT"/email"; #else const char *filepath = "/usr/local/taos/email"; +#endif // CUS_PROMPT TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ); if (pFile == NULL) return false; @@ -280,11 +292,46 @@ int32_t taosGetEmail(char *email, int32_t maxLen) { #endif } +#ifdef WINDOWS +bool getWinVersionReleaseName(char *releaseName, int32_t maxLen) { + TCHAR szFileName[MAX_PATH]; + DWORD dwHandle; + DWORD dwLen; + LPVOID lpData; + UINT uLen; + VS_FIXEDFILEINFO *pFileInfo; + + GetWindowsDirectory(szFileName, MAX_PATH); + wsprintf(szFileName, L"%s%s", szFileName, L"\\explorer.exe"); + dwLen = GetFileVersionInfoSize(szFileName, &dwHandle); + if (dwLen == 0) { + return false; + } + lpData = malloc(dwLen); + if (lpData == NULL) return false; + if (!GetFileVersionInfo(szFileName, dwHandle, dwLen, lpData)) { + free(lpData); + return false; + } + + if (!VerQueryValue(lpData, L"\\", (LPVOID *)&pFileInfo, &uLen)) { + free(lpData); + return false; + } + + snprintf(releaseName, maxLen, "Windows %d.%d", HIWORD(pFileInfo->dwProductVersionMS), + LOWORD(pFileInfo->dwProductVersionMS)); + free(lpData); + return true; +} +#endif int32_t taosGetOsReleaseName(char *releaseName, int32_t maxLen) { #ifdef WINDOWS - snprintf(releaseName, maxLen, "Windows"); + if (!getWinVersionReleaseName(releaseName, maxLen)) { + snprintf(releaseName, maxLen, "Windows"); + } return 0; #elif defined(_TD_DARWIN_64) char osversion[32]; @@ -358,6 +405,10 @@ int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) { code = 0; done |= 1; } + int endPos = strlen(cpuModel)-1; + if (cpuModel[endPos] == '\n') { + cpuModel[endPos] = '\0'; + } taosCloseCmd(&pCmd); pCmd = taosOpenCmd("sysctl -n machdep.cpu.core_count"); @@ -400,11 +451,14 @@ int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) { if (code != 0 && (done & 1) == 0) { TdFilePtr pFile1 = taosOpenFile("/proc/device-tree/model", TD_FILE_READ | TD_FILE_STREAM); - if (pFile1 == NULL) return code; - taosGetsFile(pFile1, maxLen, cpuModel); - taosCloseFile(&pFile1); - code = 0; - done |= 1; + if (pFile1 != NULL) { + ssize_t bytes = taosGetsFile(pFile1, maxLen, cpuModel); + taosCloseFile(&pFile); + if (bytes > 0) { + code = 0; + done |= 1; + } + } } if (code != 0 && (done & 1) == 0) { @@ -459,7 +513,7 @@ void taosGetCpuUsage(double *cpu_system, double *cpu_engine) { curSysTotal = curSysUsed + sysCpu.idle; curProcTotal = procCpu.utime + procCpu.stime + procCpu.cutime + procCpu.cstime; - if (curSysTotal > lastSysTotal && curSysUsed >= lastSysUsed && curProcTotal >= lastProcTotal) { + if (curSysTotal - lastSysTotal > 0 && curSysUsed >= lastSysUsed && curProcTotal >= lastProcTotal) { if (cpu_system != NULL) { *cpu_system = (curSysUsed - lastSysUsed) / (double)(curSysTotal - lastSysTotal) * 100; } @@ -571,12 +625,6 @@ int32_t taosGetProcMemory(int64_t *usedKB) { } } - if (strlen(line) < 0) { - // printf("read file:%s failed", tsProcMemFile); - taosCloseFile(&pFile); - return -1; - } - char tmp[10]; sscanf(line, "%s %" PRId64, tmp, usedKB); @@ -865,7 +913,7 @@ int32_t taosGetSystemUUID(char *uid, int32_t uidlen) { char *taosGetCmdlineByPID(int pid) { #ifdef WINDOWS - assert(0); + ASSERT(0); return ""; #elif defined(_TD_DARWIN_64) static char cmdline[1024]; diff --git a/source/os/src/osSystem.c b/source/os/src/osSystem.c index c972aebbcaf8e89b7104e9c9241b5f7d11b6449d..7b6c77f7bc7ec969438689068a521ed20c123940 100644 --- a/source/os/src/osSystem.c +++ b/source/os/src/osSystem.c @@ -90,7 +90,7 @@ typedef struct FILE TdCmd; void* taosLoadDll(const char* filename) { #if defined(WINDOWS) - assert(0); + ASSERT(0); return NULL; #elif defined(_TD_DARWIN_64) return NULL; @@ -109,7 +109,7 @@ void* taosLoadDll(const char* filename) { void* taosLoadSym(void* handle, char* name) { #if defined(WINDOWS) - assert(0); + ASSERT(0); return NULL; #elif defined(_TD_DARWIN_64) return NULL; @@ -130,7 +130,7 @@ void* taosLoadSym(void* handle, char* name) { void taosCloseDll(void* handle) { #if defined(WINDOWS) - assert(0); + ASSERT(0); return; #elif defined(_TD_DARWIN_64) return; diff --git a/source/os/src/osThread.c b/source/os/src/osThread.c index 32c58695cfdac108e38112ccbfc73f35faf5ed42..39ba92fdc5e93d45facd85a2015461ad1fd68d8c 100644 --- a/source/os/src/osThread.c +++ b/source/os/src/osThread.c @@ -233,7 +233,8 @@ int32_t taosThreadSpinDestroy(TdThreadSpinlock *lock) { int32_t taosThreadSpinInit(TdThreadSpinlock *lock, int32_t pshared) { #ifdef TD_USE_SPINLOCK_AS_MUTEX - assert(pshared == 0); + ASSERT(pshared == 0); + if (pshared != 0) return -1; return pthread_mutex_init((pthread_mutex_t *)lock, NULL); #else return pthread_spin_init((pthread_spinlock_t *)lock, pshared); diff --git a/source/os/src/osTime.c b/source/os/src/osTime.c index 685693a709f4dd14efc3ffd5f277946a3293b38a..39d1de043713b83301c8f15a4030345d00536658 100644 --- a/source/os/src/osTime.c +++ b/source/os/src/osTime.c @@ -37,6 +37,9 @@ // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) // until 00:00:00 January 1, 1970 static const uint64_t TIMEEPOCH = ((uint64_t)116444736000000000ULL); +// This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) +// until 00:00:00 January 1, 1900 +static const uint64_t TIMEEPOCH1900 = ((uint64_t)116445024000000000ULL); /* * We do not implement alternate representations. However, we always @@ -407,29 +410,39 @@ time_t taosMktime(struct tm *timep) { #endif } -struct tm *taosLocalTime(const time_t *timep, struct tm *result) { +struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf) { + struct tm *res = NULL; + if (timep == NULL) { + return NULL; + } if (result == NULL) { - return localtime(timep); + res = localtime(timep); + if (res == NULL && buf != NULL) { + sprintf(buf, "NaN"); + } + return res; } #ifdef WINDOWS if (*timep < 0) { - SYSTEMTIME ss, s; - FILETIME ff, f; + if (*timep < -2208988800LL) { + if (buf != NULL) { + sprintf(buf, "NaN"); + } + return NULL; + } + + SYSTEMTIME s; + FILETIME f; LARGE_INTEGER offset; struct tm tm1; time_t tt = 0; - localtime_s(&tm1, &tt); - ss.wYear = tm1.tm_year + 1900; - ss.wMonth = tm1.tm_mon + 1; - ss.wDay = tm1.tm_mday; - ss.wHour = tm1.tm_hour; - ss.wMinute = tm1.tm_min; - ss.wSecond = tm1.tm_sec; - ss.wMilliseconds = 0; - SystemTimeToFileTime(&ss, &ff); - offset.QuadPart = ff.dwHighDateTime; - offset.QuadPart <<= 32; - offset.QuadPart |= ff.dwLowDateTime; + if (localtime_s(&tm1, &tt) != 0 ) { + if (buf != NULL) { + sprintf(buf, "NaN"); + } + return NULL; + } + offset.QuadPart = TIMEEPOCH1900; offset.QuadPart += *timep * 10000000; f.dwLowDateTime = offset.QuadPart & 0xffffffff; f.dwHighDateTime = (offset.QuadPart >> 32) & 0xffffffff; @@ -444,10 +457,18 @@ struct tm *taosLocalTime(const time_t *timep, struct tm *result) { result->tm_yday = 0; result->tm_isdst = 0; } else { - localtime_s(result, timep); + if (localtime_s(result, timep) != 0) { + if (buf != NULL) { + sprintf(buf, "NaN"); + } + return NULL; + } } #else - localtime_r(timep, result); + res = localtime_r(timep, result); + if (res == NULL && buf != NULL) { + sprintf(buf, "NaN"); + } #endif return result; } @@ -469,12 +490,16 @@ struct tm *taosLocalTimeNolock(struct tm *result, const time_t *timep, int dst) } #ifdef WINDOWS if (*timep < 0) { + return NULL; + // TODO: bugs in following code SYSTEMTIME ss, s; FILETIME ff, f; LARGE_INTEGER offset; struct tm tm1; time_t tt = 0; - localtime_s(&tm1, &tt); + if (localtime_s(&tm1, &tt) != 0) { + return NULL; + } ss.wYear = tm1.tm_year + 1900; ss.wMonth = tm1.tm_mon + 1; ss.wDay = tm1.tm_mday; @@ -500,7 +525,9 @@ struct tm *taosLocalTimeNolock(struct tm *result, const time_t *timep, int dst) result->tm_yday = 0; result->tm_isdst = 0; } else { - localtime_s(result, timep); + if (localtime_s(result, timep) != 0) { + return NULL; + } } #elif defined(LINUX) time_t secsMin = 60, secsHour = 3600, secsDay = 3600 * 24; diff --git a/source/os/src/osTimer.c b/source/os/src/osTimer.c index d1c233ea9c2a06de6f4f973395276fcae6246188..b8eb54e10e27adcba5668140936830309327dd3d 100644 --- a/source/os/src/osTimer.c +++ b/source/os/src/osTimer.c @@ -99,8 +99,8 @@ static void *taosProcessAlarmSignal(void *tharg) { setThreadName("tmr"); #ifdef _ALPINE - sevent.sigev_notify = SIGEV_THREAD; - sevent.sigev_value.sival_int = syscall(__NR_gettid); + sevent.sigev_notify = SIGEV_THREAD_ID; + sevent.sigev_notify_thread_id = syscall(__NR_gettid); #else sevent.sigev_notify = SIGEV_THREAD_ID; sevent._sigev_un._tid = syscall(__NR_gettid); @@ -114,27 +114,28 @@ static void *taosProcessAlarmSignal(void *tharg) { taosThreadCleanupPush(taosDeleteTimer, &timerId); - struct itimerspec ts; - ts.it_value.tv_sec = 0; - ts.it_value.tv_nsec = 1000000 * MSECONDS_PER_TICK; - ts.it_interval.tv_sec = 0; - ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK; - - if (timer_settime(timerId, 0, &ts, NULL)) { - // printf("Failed to init timer"); - return NULL; - } + do { + struct itimerspec ts; + ts.it_value.tv_sec = 0; + ts.it_value.tv_nsec = 1000000 * MSECONDS_PER_TICK; + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 1000000 * MSECONDS_PER_TICK; - int signo; - while (!stopTimer) { - if (sigwait(&sigset, &signo)) { - // printf("Failed to wait signal: number %d", signo); - continue; + if (timer_settime(timerId, 0, &ts, NULL)) { + // printf("Failed to init timer"); + break; } - /* //printf("Signal handling: number %d ......\n", signo); */ - callback(0); - } + int signo; + while (!stopTimer) { + if (sigwait(&sigset, &signo)) { + // printf("Failed to wait signal: number %d", signo); + continue; + } + /* //printf("Signal handling: number %d ......\n", signo); */ + callback(0); + } + } while (0); taosThreadCleanupPop(1); diff --git a/source/os/src/osTimezone.c b/source/os/src/osTimezone.c index ab5600744c887d2fb39bc2bbb3bd30ba007fecf7..cd6ad7cdb5b45c35bae19093a2a97b0c0d8e9bdf 100644 --- a/source/os/src/osTimezone.c +++ b/source/os/src/osTimezone.c @@ -893,7 +893,7 @@ void taosGetSystemTimezone(char *outTimezoneStr, enum TdTimezone *tsTimezone) { */ time_t tx1 = taosGetTimestampSec(); struct tm tm1; - taosLocalTime(&tx1, &tm1); + taosLocalTime(&tx1, &tm1, NULL); daylight = tm1.tm_isdst; /* @@ -909,7 +909,7 @@ void taosGetSystemTimezone(char *outTimezoneStr, enum TdTimezone *tsTimezone) { char buf[4096] = {0}; char *tz = NULL; { - int n = readlink("/etc/localtime", buf, sizeof(buf)); + int n = readlink("/etc/localtime", buf, sizeof(buf)-1); if (n < 0) { printf("read /etc/localtime error, reason:%s", strerror(errno)); @@ -921,7 +921,7 @@ void taosGetSystemTimezone(char *outTimezoneStr, enum TdTimezone *tsTimezone) { */ time_t tx1 = taosGetTimestampSec(); struct tm tm1; - taosLocalTime(&tx1, &tm1); + taosLocalTime(&tx1, &tm1, NULL); /* load time zone string from /etc/timezone */ // FILE *f = fopen("/etc/timezone", "r"); errno = 0; @@ -1008,7 +1008,7 @@ void taosGetSystemTimezone(char *outTimezoneStr, enum TdTimezone *tsTimezone) { */ time_t tx1 = taosGetTimestampSec(); struct tm tm1; - taosLocalTime(&tx1, &tm1); + taosLocalTime(&tx1, &tm1, NULL); /* * format example: diff --git a/source/os/test/CMakeLists.txt b/source/os/test/CMakeLists.txt index 21fb2ee630d2d0058ca48f94a1f39c10ce7abe40..fba4d23e3fa5114fa0c4420761dbc0279f9934c4 100644 --- a/source/os/test/CMakeLists.txt +++ b/source/os/test/CMakeLists.txt @@ -17,8 +17,64 @@ INCLUDE_DIRECTORIES(${TD_SOURCE_DIR}/src/util/inc) # osTests add_executable(osTests "osTests.cpp") -target_link_libraries(osTests os util gtest_main) +target_link_libraries(osTests os util gtest_main) add_test( NAME osTests COMMAND osTests +) + +add_executable(osSystemTests "osSystemTests.cpp") +target_link_libraries(osSystemTests os util gtest_main) +add_test( + NAME osSystemTests + COMMAND osSystemTests +) + +add_executable(osMathTests "osMathTests.cpp") +target_link_libraries(osMathTests os util gtest_main) +add_test( + NAME osMathTests + COMMAND osMathTests +) + +add_executable(osSignalTests "osSignalTests.cpp") +target_link_libraries(osSignalTests os util gtest_main) +add_test( + NAME osSignalTests + COMMAND osSignalTests +) + +add_executable(osSleepTests "osSleepTests.cpp") +target_link_libraries(osSleepTests os util gtest_main) +add_test( + NAME osSleepTests + COMMAND osSleepTests +) + +add_executable(osStringTests "osStringTests.cpp") +target_link_libraries(osStringTests os util gtest_main) +add_test( + NAME osStringTests + COMMAND osStringTests +) + +add_executable(osThreadTests "osThreadTests.cpp") +target_link_libraries(osThreadTests os util gtest_main) +add_test( + NAME osThreadTests + COMMAND osThreadTests +) + +add_executable(osTimeTests "osTimeTests.cpp") +target_link_libraries(osTimeTests os util gtest_main) +add_test( + NAME osTimeTests + COMMAND osTimeTests +) + +add_executable(osAtomicTests "osAtomicTests.cpp") +target_link_libraries(osAtomicTests os util gtest_main) +add_test( + NAME osAtomicTests + COMMAND osAtomicTests ) \ No newline at end of file diff --git a/source/os/test/osAtomicTests.cpp b/source/os/test/osAtomicTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eebc1574c3b286a249cf051f8c0ad41acb32b39a --- /dev/null +++ b/source/os/test/osAtomicTests.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#pragma GCC diagnostic ignored "-Wpointer-arith" + +#include "os.h" +#include "tlog.h" + +TEST(osAtomicTests, Exchange16) { + int16_t value = 123; + int16_t new_value = 456; + int16_t result = atomic_exchange_16(&value, new_value); + EXPECT_EQ(result, 123); + EXPECT_EQ(value, 456); +} + +TEST(osAtomicTests, Exchange32) { + int32_t value = 123; + int32_t new_value = 456; + int32_t result = atomic_exchange_32(&value, new_value); + EXPECT_EQ(result, 123); + EXPECT_EQ(value, 456); +} + +TEST(osAtomicTests, Exchange64) { + int64_t value = 123; + int64_t new_value = 456; + int64_t result = atomic_exchange_64(&value, new_value); + EXPECT_EQ(result, 123); + EXPECT_EQ(value, 456); +} + +TEST(osAtomicTests, ExchangePtr) { + int value1 = 123; + int value2 = 456; + int* ptr = &value1; + int* result = (int*)atomic_exchange_ptr(&ptr, &value2); + EXPECT_EQ(result, &value1); + EXPECT_EQ(*ptr, 456); +} + +TEST(osAtomicTests, ValCompareExchange8) { + int8_t value = 12; + int8_t oldval = 12; + int8_t newval = 45; + int8_t result = atomic_val_compare_exchange_8(&value, oldval, newval); + EXPECT_EQ(result, 12); + EXPECT_EQ(value, 45); + + oldval = 78; + result = atomic_val_compare_exchange_8(&value, oldval, newval); + EXPECT_EQ(result, 45); + EXPECT_EQ(value, 45); +} + +TEST(osAtomicTests, ValCompareExchange16) { + int16_t value = 123; + int16_t oldval = 123; + int16_t newval = 456; + int16_t result = atomic_val_compare_exchange_16(&value, oldval, newval); + EXPECT_EQ(result, 123); + EXPECT_EQ(value, 456); + + oldval = 789; + result = atomic_val_compare_exchange_16(&value, oldval, newval); + EXPECT_EQ(result, 456); + EXPECT_EQ(value, 456); +} + +TEST(osAtomicTests, TestAtomicExchange8) { + volatile int8_t value = 42; + int8_t new_value = 100; + int8_t old_value = atomic_exchange_8(&value, new_value); + EXPECT_EQ(old_value, 42); + EXPECT_EQ(value, new_value); +} + +TEST(osAtomicTests, TestAtomicAddFetch16) { + volatile int16_t value = 42; + int16_t increment = 10; + int16_t new_value = atomic_add_fetch_16(&value, increment); + EXPECT_EQ(new_value, 52); + EXPECT_EQ(value, 52); +} + +//TEST(osAtomicTests, AddFetchPtr) { +// uintptr_t val = 0; +// uintptr_t* ptr = &val; +// uintptr_t ret = atomic_add_fetch_ptr(ptr, 10); +// EXPECT_EQ(ret, 10); +// EXPECT_EQ(val, 10); +//} diff --git a/source/os/test/osMathTests.cpp b/source/os/test/osMathTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93c8d1f8da03cc359cd23d5feca712e8b5e6c1f3 --- /dev/null +++ b/source/os/test/osMathTests.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#pragma GCC diagnostic ignored "-Wpointer-arith" + +#include "os.h" +#include "tlog.h" + +struct TestStruct { + int a; + float b; +}; + +// Define a custom comparison function for testing +int cmpFunc(const void* a, const void* b) { + const TestStruct* pa = reinterpret_cast(a); + const TestStruct* pb = reinterpret_cast(b); + if (pa->a < pb->a) { + return -1; + } else if (pa->a > pb->a) { + return 1; + } else { + return 0; + } +} + +TEST(osMathTests, taosSort) { + // Create an array of test data + TestStruct arr[] = {{4, 2.5}, {2, 1.5}, {1, 3.5}, {3, 4.5}}; + + // Sort the array using taosSort + taosSort(arr, 4, sizeof(TestStruct), cmpFunc); + + // Check that the array is sorted correctly + EXPECT_EQ(arr[0].a, 1); + EXPECT_EQ(arr[1].a, 2); + EXPECT_EQ(arr[2].a, 3); + EXPECT_EQ(arr[3].a, 4); +} \ No newline at end of file diff --git a/source/os/test/osSignalTests.cpp b/source/os/test/osSignalTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4cc6e9e588fe02aeeaae3f128635e341d024d2d --- /dev/null +++ b/source/os/test/osSignalTests.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#pragma GCC diagnostic ignored "-Wpointer-arith" + +#include "os.h" +#include "tlog.h" + +TEST(osSignalTests, taosSetSignal) { + // Set up SIGINT handler using taosSetSignal + //taosSetSignal(SIGINT, sigint_handler); + + // Print PID for testing purposes + // printf("PID: %d\n", getpid()); + + // Wait for signal to be received +} diff --git a/source/os/test/osSleepTests.cpp b/source/os/test/osSleepTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5faa837a0ada8d5e0b8485d642c34a08dc1bcec2 --- /dev/null +++ b/source/os/test/osSleepTests.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#pragma GCC diagnostic ignored "-Wpointer-arith" + +#include "os.h" +#include "tlog.h" + +TEST(osSleepTests, taosUsleep) { + const int sleep_time1 = 1000; // sleep for 1000 microseconds + taosUsleep(sleep_time1); + + const int sleep_time2 = 0; // sleep for 0 microseconds + taosUsleep(sleep_time2); + + const int sleep_time3 = -1; // sleep for negative time + taosUsleep(sleep_time3); +} + +TEST(osSleepTests, taosSsleep) { + const int sleep_time1 = 1; + taosSsleep(sleep_time1); + + const int sleep_time2 = 0; + taosSsleep(sleep_time2); + + const int sleep_time3 = -1; + taosSsleep(sleep_time3); +} + +TEST(osSleepTests, taosMsleep) { + const int sleep_time1 = 1000; + taosMsleep(sleep_time1); + + const int sleep_time2 = 0; + taosMsleep(sleep_time2); + + const int sleep_time3 = -1; // sleep for negative time + taosMsleep(sleep_time3); +} diff --git a/source/os/test/osStringTests.cpp b/source/os/test/osStringTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e07636b1f81b9db0fb454e501441ae4e5959714 --- /dev/null +++ b/source/os/test/osStringTests.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#pragma GCC diagnostic ignored "-Wpointer-arith" + +#include "os.h" +#include "tlog.h" + +#ifdef WINDOWS +TEST(osStringTests, strsepNormalInput) { + char str[] = "This is a test string."; + char * ptr = str; + char * tok = NULL; + const char delim[] = " "; + + while ((tok = strsep(&ptr, delim)) != NULL) { + printf("%s\n", tok); + } + EXPECT_STREQ(tok, nullptr); + EXPECT_EQ(ptr, nullptr); +} + +TEST(osStringTests, strsepEmptyInput) { + char* str = ""; + char* ptr = str; + char* tok = NULL; + const char delim[] = " "; + + while ((tok = strsep(&ptr, delim)) != NULL) { + printf("%s\n", tok); + } + + EXPECT_STREQ(tok, nullptr); + EXPECT_EQ(ptr, nullptr); +} + +TEST(osStringTests, strsepNullInput) { + char * str = NULL; + char * ptr = str; + char * tok = NULL; + const char delim[] = " "; + + while ((tok = strsep(&ptr, delim)) != NULL) { + printf("%s\n", tok); + } + + EXPECT_STREQ(tok, nullptr); + EXPECT_EQ(ptr, nullptr); +} + +TEST(osStringTests, strndupNormalInput) { + const char s[] = "This is a test string."; + int size = strlen(s) + 1; + char * s2 = strndup(s, size); + + EXPECT_STREQ(s, s2); + + free(s2); +} +#endif + +TEST(osStringTests, osUcs4Tests1) { + TdUcs4 f1_ucs4[] = {0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x0000}; + TdUcs4 f2_ucs4[] = {0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x0000}; + + EXPECT_EQ(tasoUcs4Compare(f1_ucs4, f2_ucs4, sizeof(f1_ucs4)), 0); + + TdUcs4 f3_ucs4[] = {0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x0020, 0x0077, + 0x006F, 0x0072, 0x006C, 0x0064, 0x0021, 0x0000}; + TdUcs4 f4_ucs4[] = {0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x0000}; + + EXPECT_GT(tasoUcs4Compare(f3_ucs4, f4_ucs4, sizeof(f3_ucs4)), 0); + + TdUcs4 f5_ucs4[] = {0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x0000}; + TdUcs4 f6_ucs4[] = {0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x0020, 0x0077, + 0x006F, 0x0072, 0x006C, 0x0064, 0x0021, 0x0000}; + + EXPECT_LT(tasoUcs4Compare(f5_ucs4, f6_ucs4, sizeof(f5_ucs4)), 0); +} + +TEST(osStringTests, osUcs4lenTests2) { + TdUcs4 ucs4_1[] = {'H', 'e', 'l', 'l', 'o', '\0'}; + EXPECT_EQ(taosUcs4len(ucs4_1), 5); + + TdUcs4 ucs4_2[] = {'\0'}; + EXPECT_EQ(taosUcs4len(ucs4_2), 0); + + TdUcs4 ucs4_3[] = {'C', 'h', 'i', 'n', 'a', 0x4E2D, 0x6587, '\0'}; + EXPECT_EQ(taosUcs4len(ucs4_3), 7); +} diff --git a/source/os/test/osSystemTests.cpp b/source/os/test/osSystemTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dfc92a1b72b8b743a23a3cba1b6e18c66b5b982f --- /dev/null +++ b/source/os/test/osSystemTests.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#pragma GCC diagnostic ignored "-Wpointer-arith" + +#include "os.h" +#include "tlog.h" + +TEST(osSystemTest, osSystem1) { + char tmp[4096] = "test"; +#ifdef _TD_DARWIN_64 + taosLogTraceToBuf(tmp, sizeof(tmp), 4); +#elif !defined(WINDOWS) + taosLogTraceToBuf(tmp, sizeof(tmp), 3); +#else + taosLogTraceToBuf(tmp, sizeof(tmp), 8); +#endif +} diff --git a/source/os/test/osTests.cpp b/source/os/test/osTests.cpp index 2e24bb05269ba9a4529b16726ca8c59d6de7ac68..1d6542e78cd987e5228c94609cf0dd865a6d6396 100644 --- a/source/os/test/osTests.cpp +++ b/source/os/test/osTests.cpp @@ -34,6 +34,12 @@ TEST(osTest, osSystem) { ELogLevel level = DEBUG_FATAL; int32_t dflag = 255; // tsLogEmbedded ? 255 : uDebugFlag taosPrintTrace(flags, level, dflag, 0); + + const int sysLen = 64; + char osSysName[sysLen]; + int ret = taosGetOsReleaseName(osSysName, sysLen); + printf("os systeme name:%s\n", osSysName); + ASSERT_EQ(ret, 0); } void fileOperateOnFree(void *param) { diff --git a/source/libs/cache/src/cache.c b/source/os/test/osThreadTests.cpp similarity index 53% rename from source/libs/cache/src/cache.c rename to source/os/test/osThreadTests.cpp index 6dea4a4e57392be988126c579648f39a8270b9bf..e7fc4f135609b95cb5e13d49f1c5d4a50b8fec6c 100644 --- a/source/libs/cache/src/cache.c +++ b/source/os/test/osThreadTests.cpp @@ -11,4 +11,24 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - */ \ No newline at end of file + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#pragma GCC diagnostic ignored "-Wpointer-arith" + +#include "os.h" +#include "tlog.h" + +TEST(osThreadTests, osThreadTests1) { + +} diff --git a/source/os/test/osTimeTests.cpp b/source/os/test/osTimeTests.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5dd15db4ab929edb0a200e28b2fe1b2d230642ca --- /dev/null +++ b/source/os/test/osTimeTests.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#pragma GCC diagnostic ignored "-Wpointer-arith" + +#include "os.h" +#include "tlog.h" + +TEST(osTimeTests, taosLocalTimeNolock) { + time_t currentTime; + // Test when result is NULL + struct tm* result = taosLocalTimeNolock(NULL, ¤tTime, 0); + // Test when result is not NULL + struct tm expectedTime; + result = taosLocalTimeNolock(&expectedTime, ¤tTime, 1); + EXPECT_EQ(expectedTime.tm_year, result->tm_year); + EXPECT_EQ(expectedTime.tm_mon, result->tm_mon); + EXPECT_EQ(expectedTime.tm_mday, result->tm_mday); + EXPECT_EQ(expectedTime.tm_hour, result->tm_hour); + EXPECT_EQ(expectedTime.tm_min, result->tm_min); + EXPECT_EQ(expectedTime.tm_sec, result->tm_sec); + EXPECT_EQ(expectedTime.tm_wday, result->tm_wday); + EXPECT_EQ(expectedTime.tm_yday, result->tm_yday); + EXPECT_EQ(expectedTime.tm_isdst, result->tm_isdst); +} + + +TEST(osTimeTests, taosLocalTime) { + // Test 1: Test when both timep and result are not NULL + time_t timep = 1617531000; // 2021-04-04 18:10:00 + struct tm result; + struct tm* local_time = taosLocalTime(&timep, &result, NULL); + ASSERT_NE(local_time, nullptr); + ASSERT_EQ(local_time->tm_year, 121); + ASSERT_EQ(local_time->tm_mon, 3); + ASSERT_EQ(local_time->tm_mday, 4); + ASSERT_EQ(local_time->tm_hour, 18); + ASSERT_EQ(local_time->tm_min, 10); + ASSERT_EQ(local_time->tm_sec, 00); + + // Test 2: Test when timep is NULL + local_time = taosLocalTime(NULL, &result, NULL); + ASSERT_EQ(local_time, nullptr); + + // Test 3: Test when result is NULL + local_time = taosLocalTime(&timep, NULL, NULL); + ASSERT_NE(local_time, nullptr); + ASSERT_EQ(local_time->tm_year, 121); + ASSERT_EQ(local_time->tm_mon, 3); + ASSERT_EQ(local_time->tm_mday, 4); + + // Test 4: Test when timep is negative on Windows +#ifdef WINDOWS + time_t pos_timep = 1609459200; // 2021-01-01 08:00:00 + local_time = taosLocalTime(&pos_timep, &result, NULL); + ASSERT_NE(local_time, nullptr); + ASSERT_EQ(local_time->tm_year, 121); + ASSERT_EQ(local_time->tm_mon, 0); + ASSERT_EQ(local_time->tm_mday, 1); + ASSERT_EQ(local_time->tm_hour, 8); + ASSERT_EQ(local_time->tm_min, 0); + ASSERT_EQ(local_time->tm_sec, 0); + + time_t neg_timep = -1617531000; // 1918-09-29 21:50:00 + local_time = taosLocalTime(&neg_timep, &result, NULL); + ASSERT_NE(local_time, nullptr); + ASSERT_EQ(local_time->tm_year, 18); + ASSERT_EQ(local_time->tm_mon, 8); + ASSERT_EQ(local_time->tm_mday, 29); + ASSERT_EQ(local_time->tm_hour, 21); + ASSERT_EQ(local_time->tm_min, 50); + ASSERT_EQ(local_time->tm_sec, 0); + + time_t neg_timep2 = -315619200; // 1960-01-01 08:00:00 + local_time = taosLocalTime(&neg_timep2, &result, NULL); + ASSERT_NE(local_time, nullptr); + ASSERT_EQ(local_time->tm_year, 60); + ASSERT_EQ(local_time->tm_mon, 0); + ASSERT_EQ(local_time->tm_mday, 1); + ASSERT_EQ(local_time->tm_hour, 8); + ASSERT_EQ(local_time->tm_min, 0); + ASSERT_EQ(local_time->tm_sec, 0); + + time_t zero_timep = 0; // 1970-01-01 08:00:00 + local_time = taosLocalTime(&zero_timep, &result, NULL); + ASSERT_NE(local_time, nullptr); + ASSERT_EQ(local_time->tm_year, 70); + ASSERT_EQ(local_time->tm_mon, 0); + ASSERT_EQ(local_time->tm_mday, 1); + ASSERT_EQ(local_time->tm_hour, 8); + ASSERT_EQ(local_time->tm_min, 0); + ASSERT_EQ(local_time->tm_sec, 0); + + time_t over_timep = 6406301441633558; + local_time = taosLocalTime(&over_timep, &result, NULL); + ASSERT_EQ(local_time, nullptr); + + time_t neg_timep3 = -78115158887; + local_time = taosLocalTime(&neg_timep3, &result, NULL); + ASSERT_EQ(local_time, nullptr); +#endif +} \ No newline at end of file diff --git a/source/util/src/tarray.c b/source/util/src/tarray.c index 64701574bb030a6353474c85008f934c2841defc..6c7c5ddb0da9358a0c9e50459cc4a716081d5a7a 100644 --- a/source/util/src/tarray.c +++ b/source/util/src/tarray.c @@ -48,7 +48,7 @@ SArray* taosArrayInit(size_t size, size_t elemSize) { return pArray; } -SArray* taosArrayInit_s(size_t size, size_t elemSize, size_t initialSize) { +SArray* taosArrayInit_s(size_t elemSize, size_t initialSize) { SArray* pArray = taosMemoryMalloc(sizeof(SArray)); if (pArray == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; @@ -69,8 +69,6 @@ SArray* taosArrayInit_s(size_t size, size_t elemSize, size_t initialSize) { } static int32_t taosArrayResize(SArray* pArray) { - assert(pArray->size >= pArray->capacity); - size_t size = pArray->capacity; size = (size << 1u); @@ -139,6 +137,7 @@ void taosArrayRemoveDuplicate(SArray* pArray, __compar_fn_t comparFn, void (*fp) } taosArraySet(pArray, pos + 1, p2); + memset(TARRAY_GET_ELEM(pArray, i), 0, pArray->elemSize); pos += 1; } else { pos += 1; @@ -156,44 +155,6 @@ void taosArrayRemoveDuplicate(SArray* pArray, __compar_fn_t comparFn, void (*fp) pArray->size = pos + 1; } -void taosArrayRemoveDuplicateP(SArray* pArray, __compar_fn_t comparFn, void (*fp)(void*)) { - size_t size = pArray->size; - if (size <= 1) { - return; - } - - int32_t pos = 0; - for (int32_t i = 1; i < size; ++i) { - char* p1 = taosArrayGet(pArray, pos); - char* p2 = taosArrayGet(pArray, i); - - if (comparFn(p1, p2) == 0) { - // do nothing - } else { - if (pos + 1 != i) { - void* p = taosArrayGet(pArray, pos + 1); - if (fp != NULL) { - fp(p); - } - - taosArraySet(pArray, pos + 1, p2); - pos += 1; - } else { - pos += 1; - } - } - } - - if (fp != NULL) { - for (int32_t i = pos + 1; i < pArray->size; ++i) { - void* p = taosArrayGetP(pArray, i); - fp(p); - } - } - - pArray->size = pos + 1; -} - void* taosArrayAddAll(SArray* pArray, const SArray* pInput) { if (pInput) { return taosArrayAddBatch(pArray, pInput->pData, (int32_t)taosArrayGetSize(pInput)); @@ -210,6 +171,8 @@ void* taosArrayReserve(SArray* pArray, int32_t num) { void* dst = TARRAY_GET_ELEM(pArray, pArray->size); pArray->size += num; + memset(dst, 0, num * pArray->elemSize); + return dst; } @@ -255,7 +218,7 @@ size_t taosArrayGetSize(const SArray* pArray) { if (pArray == NULL) { return 0; } - return pArray->size; + return TARRAY_SIZE(pArray); } void* taosArrayInsert(SArray* pArray, size_t index, void* pData) { @@ -287,12 +250,15 @@ void* taosArrayInsert(SArray* pArray, size_t index, void* pData) { } void taosArraySet(SArray* pArray, size_t index, void* pData) { - assert(index < pArray->size); + ASSERT(index < pArray->size); memcpy(TARRAY_GET_ELEM(pArray, index), pData, pArray->elemSize); } void taosArrayPopFrontBatch(SArray* pArray, size_t cnt) { - assert(cnt <= pArray->size); + if (cnt > pArray->size) { + cnt = pArray->size; + } + pArray->size = pArray->size - cnt; if (pArray->size == 0 || cnt == 0) { return; @@ -301,12 +267,15 @@ void taosArrayPopFrontBatch(SArray* pArray, size_t cnt) { } void taosArrayPopTailBatch(SArray* pArray, size_t cnt) { - assert(cnt <= pArray->size); + if (cnt >= pArray->size) { + cnt = pArray->size; + } + pArray->size = pArray->size - cnt; } void taosArrayRemove(SArray* pArray, size_t index) { - assert(index < pArray->size); + ASSERT(index < pArray->size); if (index == pArray->size - 1) { taosArrayPop(pArray); @@ -319,6 +288,20 @@ void taosArrayRemove(SArray* pArray, size_t index) { pArray->size -= 1; } +void taosArrayRemoveBatch(SArray* pArray, size_t index, size_t num, FDelete fp) { + ASSERT(index + num <= pArray->size); + + if (fp) { + for (int32_t i = 0; i < num; i++) { + fp(taosArrayGet(pArray, index + i)); + } + } + + memmove((char*)pArray->pData + index * pArray->elemSize, (char*)pArray->pData + (index + num) * pArray->elemSize, + (pArray->size - index - num) * pArray->elemSize); + pArray->size -= num; +} + SArray* taosArrayFromList(const void* src, size_t size, size_t elemSize) { if (elemSize <= 0) { terrno = TSDB_CODE_INVALID_PARA; @@ -333,6 +316,10 @@ SArray* taosArrayFromList(const void* src, size_t size, size_t elemSize) { } SArray* taosArrayDup(const SArray* pSrc, __array_item_dup_fn_t fn) { + if (NULL == pSrc) { + return NULL; + } + if (pSrc->size == 0) { // empty array list return taosArrayInit(8, pSrc->elemSize); } @@ -374,20 +361,6 @@ void taosArrayClearEx(SArray* pArray, void (*fp)(void*)) { pArray->size = 0; } -void taosArrayClearP(SArray* pArray, FDelete fp) { - if (pArray == NULL) return; - if (fp == NULL) { - pArray->size = 0; - return; - } - - for (int32_t i = 0; i < pArray->size; ++i) { - fp(*(void**)TARRAY_GET_ELEM(pArray, i)); - } - - pArray->size = 0; -} - void* taosArrayDestroy(SArray* pArray) { if (pArray) { taosMemoryFree(pArray->pData); @@ -477,6 +450,7 @@ static void taosArrayInsertSort(SArray* pArray, __ext_compar_fn_t fn, const void if (pArray->size <= 1) { return; } + for (int32_t i = 1; i <= pArray->size - 1; ++i) { for (int32_t j = i; j > 0; --j) { if (fn(taosArrayGetP(pArray, j), taosArrayGetP(pArray, j - 1), param) == -1) { @@ -489,7 +463,6 @@ static void taosArrayInsertSort(SArray* pArray, __ext_compar_fn_t fn, const void } } } - return; } int32_t taosEncodeArray(void** buf, const SArray* pArray, FEncode encode) { @@ -518,7 +491,8 @@ void* taosDecodeArray(const void* buf, SArray** pArray, FDecode decode, int32_t // todo remove it // order array void taosArraySortPWithExt(SArray* pArray, __ext_compar_fn_t fn, const void* param) { - taosArrayGetSize(pArray) > 8 ? taosArrayQuickSort(pArray, fn, param) : taosArrayInsertSort(pArray, fn, param); + taosqsort(pArray->pData, pArray->size, pArray->elemSize, param, fn); +// taosArrayGetSize(pArray) > 8 ? taosArrayQuickSort(pArray, fn, param) : taosArrayInsertSort(pArray, fn, param); } void taosArraySwap(SArray* a, SArray* b) { @@ -538,4 +512,4 @@ void taosArraySwap(SArray* a, SArray* b) { void* data = a->pData; a->pData = b->pData; b->pData = data; -} +} \ No newline at end of file diff --git a/source/util/src/tcache.c b/source/util/src/tcache.c index 761da6986ba635cd1bafa2b49d8719fb930b1992..28d9b412a0014b63cc468e0e90b2c84f50eda2d9 100644 --- a/source/util/src/tcache.c +++ b/source/util/src/tcache.c @@ -243,11 +243,6 @@ static FORCE_INLINE STrashElem *doRemoveElemInTrashcan(SCacheObj *pCacheObj, STr if (next) { next->prev = pElem->prev; } - - if (pCacheObj->numOfElemsInTrash == 0) { - assert(pCacheObj->pTrash == NULL); - } - return next; } @@ -261,8 +256,6 @@ static FORCE_INLINE void doDestroyTrashcanElem(SCacheObj *pCacheObj, STrashElem } static void pushfrontNodeInEntryList(SCacheEntry *pEntry, SCacheNode *pNode) { - assert(pNode != NULL && pEntry != NULL); - pNode->pNext = pEntry->next; pEntry->next = pNode; pEntry->num += 1; @@ -271,7 +264,6 @@ static void pushfrontNodeInEntryList(SCacheEntry *pEntry, SCacheNode *pNode) { static void removeNodeInEntryList(SCacheEntry *pe, SCacheNode *prev, SCacheNode *pNode) { if (prev == NULL) { - ASSERT(pe->next == pNode); pe->next = pNode->pNext; } else { prev->pNext = pNode->pNext; @@ -391,7 +383,7 @@ SCacheObj *taosCacheInit(int32_t keyType, int64_t refreshTimeInMs, bool extendLi return NULL; } - pCacheObj->name = strdup(cacheName); + pCacheObj->name = taosStrdup(cacheName); doRegisterCacheObj(pCacheObj); return pCacheObj; } @@ -471,7 +463,6 @@ void *taosCacheAcquireByKey(SCacheObj *pCacheObj, const void *key, size_t keyLen SCacheNode *pNode = doSearchInEntryList(pe, key, keyLen, &prev); if (pNode != NULL) { int32_t ref = T_REF_INC(pNode); - ASSERT(ref > 0); } taosRUnLockLatch(&pe->latch); @@ -503,7 +494,7 @@ void *taosCacheAcquireByData(SCacheObj *pCacheObj, void *data) { uDebug("cache:%s, data: %p acquired by data in cache, refcnt:%d", pCacheObj->name, ptNode->data, ref); // the data if referenced by at least one object, so the reference count must be greater than the value of 2. - assert(ref >= 2); + ASSERT(ref >= 2); return data; } @@ -516,7 +507,6 @@ void *taosCacheTransferData(SCacheObj *pCacheObj, void **data) { return NULL; } - assert(T_REF_VAL_GET(ptNode) >= 1); char *d = *data; // clear its reference to old area @@ -575,19 +565,19 @@ void taosCacheRelease(SCacheObj *pCacheObj, void **data, bool _remove) { if (ref == 1) { // If it is the last ref, remove it from trashcan linked-list first, and then destroy it.Otherwise, it may be // destroyed by refresh worker if decrease ref count before removing it from linked-list. - assert(pNode->pTNodeHeader->pData == pNode); + ASSERT(pNode->pTNodeHeader->pData == pNode); __trashcan_wr_lock(pCacheObj); doRemoveElemInTrashcan(pCacheObj, pNode->pTNodeHeader); __trashcan_unlock(pCacheObj); ref = T_REF_DEC(pNode); - assert(ref == 0); + ASSERT(ref == 0); doDestroyTrashcanElem(pCacheObj, pNode->pTNodeHeader); } else { ref = T_REF_DEC(pNode); - assert(ref >= 0); + ASSERT(ref >= 0); } } else { // NOTE: remove it from hash in the first place, otherwise, the pNode may have been released by other thread @@ -609,13 +599,12 @@ void taosCacheRelease(SCacheObj *pCacheObj, void **data, bool _remove) { "others already, prev must in trashcan", pCacheObj->name, pNode->key, p->data, T_REF_VAL_GET(p), pNode->data, T_REF_VAL_GET(pNode)); - assert(p->pTNodeHeader == NULL && pNode->pTNodeHeader != NULL); + ASSERT(p->pTNodeHeader == NULL && pNode->pTNodeHeader != NULL); } else { removeNodeInEntryList(pe, prev, p); uDebug("cache:%s, key:%p, %p successfully removed from hash table, refcnt:%d", pCacheObj->name, pNode->key, pNode->data, ref); if (ref > 0) { - assert(pNode->pTNodeHeader == NULL); taosAddToTrashcan(pCacheObj, pNode); } else { // ref == 0 atomic_sub_fetch_64(&pCacheObj->sizeInBytes, pNode->size); @@ -736,7 +725,7 @@ SCacheNode *taosCreateCacheNode(const char *key, size_t keyLen, const char *pDat void taosAddToTrashcan(SCacheObj *pCacheObj, SCacheNode *pNode) { if (pNode->inTrashcan) { /* node is already in trash */ - assert(pNode->pTNodeHeader != NULL && pNode->pTNodeHeader->pData == pNode); + ASSERT(pNode->pTNodeHeader != NULL && pNode->pTNodeHeader->pData == pNode); return; } @@ -782,7 +771,7 @@ void taosTrashcanEmpty(SCacheObj *pCacheObj, bool force) { STrashElem *pElem = pCacheObj->pTrash; while (pElem) { T_REF_VAL_CHECK(pElem->pData); - assert(pElem->next != pElem && pElem->prev != pElem); + ASSERT(pElem->next != pElem && pElem->prev != pElem); if (force || (T_REF_VAL_GET(pElem->pData) == 0)) { uDebug("cache:%s, key:%p, %p removed from trashcan. numOfElem in trashcan:%d", pCacheObj->name, pElem->pData->key, @@ -814,8 +803,6 @@ void doCleanupDataCache(SCacheObj *pCacheObj) { } static void doCacheRefresh(SCacheObj *pCacheObj, int64_t time, __cache_trav_fn_t fp, void *param1) { - assert(pCacheObj != NULL); - SCacheObjTravSup sup = {.pCacheObj = pCacheObj, .fp = fp, .time = time, .param1 = param1}; doTraverseElems(pCacheObj, doRemoveExpiredFn, &sup); } @@ -827,9 +814,7 @@ void taosCacheRefreshWorkerUnexpectedStopped(void) { } void *taosCacheTimedRefresh(void *handle) { - assert(pCacheArrayList != NULL); uDebug("cache refresh thread starts"); - setThreadName("cacheRefresh"); const int32_t SLEEP_DURATION = 500; // 500 ms @@ -928,7 +913,6 @@ void taosStopCacheRefreshWorker(void) { size_t taosCacheGetNumOfObj(const SCacheObj *pCacheObj) { return pCacheObj->numOfElems + pCacheObj->numOfElemsInTrash; } SCacheIter *taosCacheCreateIter(const SCacheObj *pCacheObj) { - ASSERT(pCacheObj != NULL); SCacheIter *pIter = taosMemoryCalloc(1, sizeof(SCacheIter)); pIter->pCacheObj = (SCacheObj *)pCacheObj; pIter->entryIndex = -1; @@ -978,12 +962,8 @@ bool taosCacheIterNext(SCacheIter *pIter) { SCacheNode *pNode = pEntry->next; for (int32_t i = 0; i < pEntry->num; ++i) { - ASSERT(pNode != NULL); - pIter->pCurrent[i] = pNode; int32_t ref = T_REF_INC(pIter->pCurrent[i]); - ASSERT(ref >= 1); - pNode = pNode->pNext; } diff --git a/source/util/src/tcompare.c b/source/util/src/tcompare.c index 7a52991e817e1031de80c7ec5fd5b51c84c3015e..dc57ed97b23c7610f97a36d4c315911561eb3bbb 100644 --- a/source/util/src/tcompare.c +++ b/source/util/src/tcompare.c @@ -17,11 +17,11 @@ #define _XOPEN_SOURCE #define _DEFAULT_SOURCE #include "tcompare.h" -#include "tutil.h" #include "regex.h" #include "tdef.h" #include "thash.h" #include "tlog.h" +#include "tutil.h" #include "types.h" #include "osString.h" @@ -308,17 +308,19 @@ int32_t compareInt8Uint16(const void *pLeft, const void *pRight) { int32_t compareInt8Uint32(const void *pLeft, const void *pRight) { int8_t left = GET_INT8_VAL(pLeft); + if (left < 0) return -1; uint32_t right = GET_UINT32_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if ((uint32_t)left > right) return 1; + if ((uint32_t)left < right) return -1; return 0; } int32_t compareInt8Uint64(const void *pLeft, const void *pRight) { int8_t left = GET_INT8_VAL(pLeft); + if (left < 0) return -1; uint64_t right = GET_UINT64_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if ((uint64_t)left > right) return 1; + if ((uint64_t)left < right) return -1; return 0; } @@ -380,17 +382,19 @@ int32_t compareInt16Uint16(const void *pLeft, const void *pRight) { int32_t compareInt16Uint32(const void *pLeft, const void *pRight) { int16_t left = GET_INT16_VAL(pLeft); + if (left < 0) return -1; uint32_t right = GET_UINT32_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if ((uint32_t)left > right) return 1; + if ((uint32_t)left < right) return -1; return 0; } int32_t compareInt16Uint64(const void *pLeft, const void *pRight) { int16_t left = GET_INT16_VAL(pLeft); + if (left < 0) return -1; uint64_t right = GET_UINT64_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if ((uint64_t)left > right) return 1; + if ((uint64_t)left < right) return -1; return 0; } @@ -452,17 +456,19 @@ int32_t compareInt32Uint16(const void *pLeft, const void *pRight) { int32_t compareInt32Uint32(const void *pLeft, const void *pRight) { int32_t left = GET_INT32_VAL(pLeft); + if (left < 0) return -1; uint32_t right = GET_UINT32_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if ((uint32_t)left > right) return 1; + if ((uint32_t)left < right) return -1; return 0; } int32_t compareInt32Uint64(const void *pLeft, const void *pRight) { int32_t left = GET_INT32_VAL(pLeft); + if (left < 0) return -1; uint64_t right = GET_UINT64_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if ((uint64_t)left > right) return 1; + if ((uint64_t)left < right) return -1; return 0; } @@ -532,9 +538,10 @@ int32_t compareInt64Uint32(const void *pLeft, const void *pRight) { int32_t compareInt64Uint64(const void *pLeft, const void *pRight) { int64_t left = GET_INT64_VAL(pLeft); + if (left < 0) return -1; uint64_t right = GET_UINT64_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if ((uint64_t)left > right) return 1; + if ((uint64_t)left < right) return -1; return 0; } @@ -857,24 +864,27 @@ int32_t compareUint16Uint64(const void *pLeft, const void *pRight) { int32_t compareUint32Int8(const void *pLeft, const void *pRight) { uint32_t left = GET_UINT32_VAL(pLeft); int8_t right = GET_INT8_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if (right < 0) return 1; + if (left > (uint32_t)right) return 1; + if (left < (uint32_t)right) return -1; return 0; } int32_t compareUint32Int16(const void *pLeft, const void *pRight) { uint32_t left = GET_UINT32_VAL(pLeft); int16_t right = GET_INT16_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if (right < 0) return 1; + if (left > (uint32_t)right) return 1; + if (left < (uint32_t)right) return -1; return 0; } int32_t compareUint32Int32(const void *pLeft, const void *pRight) { uint32_t left = GET_UINT32_VAL(pLeft); int32_t right = GET_INT32_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if (right < 0) return 1; + if (left > (uint32_t)right) return 1; + if (left < (uint32_t)right) return -1; return 0; } @@ -929,32 +939,36 @@ int32_t compareUint32Uint64(const void *pLeft, const void *pRight) { int32_t compareUint64Int8(const void *pLeft, const void *pRight) { uint64_t left = GET_UINT64_VAL(pLeft); int8_t right = GET_INT8_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if (right < 0) return 1; + if (left > (uint64_t)right) return 1; + if (left < (uint64_t)right) return -1; return 0; } int32_t compareUint64Int16(const void *pLeft, const void *pRight) { uint64_t left = GET_UINT64_VAL(pLeft); int16_t right = GET_INT16_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if (right < 0) return 1; + if (left > (uint64_t)right) return 1; + if (left < (uint64_t)right) return -1; return 0; } int32_t compareUint64Int32(const void *pLeft, const void *pRight) { uint64_t left = GET_UINT64_VAL(pLeft); int32_t right = GET_INT32_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if (right < 0) return 1; + if (left > (uint64_t)right) return 1; + if (left < (uint64_t)right) return -1; return 0; } int32_t compareUint64Int64(const void *pLeft, const void *pRight) { uint64_t left = GET_UINT64_VAL(pLeft); int64_t right = GET_INT64_VAL(pRight); - if (left > right) return 1; - if (left < right) return -1; + if (right < 0) return 1; + if (left > (uint64_t)right) return 1; + if (left < (uint64_t)right) return -1; return 0; } @@ -1010,7 +1024,8 @@ int32_t compareJsonValDesc(const void *pLeft, const void *pRight) { return compa * '_': Matches one character * */ -int32_t patternMatch(const char *pattern, size_t psize, const char *str, size_t ssize, const SPatternCompareInfo *pInfo) { +int32_t patternMatch(const char *pattern, size_t psize, const char *str, size_t ssize, + const SPatternCompareInfo *pInfo) { char c, c1; int32_t i = 0; @@ -1020,9 +1035,9 @@ int32_t patternMatch(const char *pattern, size_t psize, const char *str, size_t while ((i < psize) && ((c = pattern[i++]) != 0)) { if (c == pInfo->matchAll) { /* Match "*" */ - while ((i < psize) && ((c = pattern[i++]) == pInfo->matchAll || c == pInfo->matchOne)) { + while ((i < psize) && ((c = pattern[i++]) == pInfo->matchAll || c == pInfo->matchOne)) { if (c == pInfo->matchOne) { - if (j >= ssize || str[j++] == 0) { // empty string, return not match + if (j >= ssize || str[j++] == 0) { // empty string, return not match return TSDB_PATTERN_NOWILDCARDMATCH; } else { ++nMatchChar; @@ -1077,7 +1092,8 @@ int32_t patternMatch(const char *pattern, size_t psize, const char *str, size_t return (j >= ssize || str[j] == 0) ? TSDB_PATTERN_MATCH : TSDB_PATTERN_NOMATCH; } -int32_t wcsPatternMatch(const TdUcs4 *pattern, size_t psize, const TdUcs4 *str, size_t ssize, const SPatternCompareInfo *pInfo) { +int32_t wcsPatternMatch(const TdUcs4 *pattern, size_t psize, const TdUcs4 *str, size_t ssize, + const SPatternCompareInfo *pInfo) { TdUcs4 c, c1; int32_t i = 0; @@ -1189,10 +1205,11 @@ int32_t comparestrRegexMatch(const void *pLeft, const void *pRight) { taosMemoryFree(str); taosMemoryFree(pattern); - return (ret == 0) ? 0 : 1;; + return (ret == 0) ? 0 : 1; + ; } -int32_t comparewcsRegexMatch(const void* pString, const void* pPattern) { +int32_t comparewcsRegexMatch(const void *pString, const void *pPattern) { size_t len = varDataLen(pPattern); char *pattern = taosMemoryMalloc(len + 1); @@ -1232,7 +1249,7 @@ int32_t taosArrayCompareString(const void *a, const void *b) { const char *x = *(const char **)a; const char *y = *(const char **)b; - return compareLenPrefixedStr(x, y); + return strcmp(x, y); } int32_t comparestrPatternMatch(const void *pLeft, const void *pRight) { diff --git a/source/util/src/tcompression.c b/source/util/src/tcompression.c index 695a83abb1a897c6d66ea4058832153917e86a93..b05f1808e8a3fe5b06f19a95aeeebaa7e6e9846b 100644 --- a/source/util/src/tcompression.c +++ b/source/util/src/tcompression.c @@ -327,23 +327,26 @@ int32_t tsDecompressINTImp(const char *const input, const int32_t nelements, cha // calculate the cumulative sum (prefix sum) for each number // decode[0] = prev_value + final[0] // decode[1] = decode[0] + final[1] -----> prev_value + final[0] + final[1] - // decode[2] = decode[1] + final[1] -----> prev_value + final[0] + final[1] + final[2] - // decode[3] = decode[2] + final[1] -----> prev_value + final[0] + final[1] + final[2] + final[3] + // decode[2] = decode[1] + final[2] -----> prev_value + final[0] + final[1] + final[2] + // decode[3] = decode[2] + final[3] -----> prev_value + final[0] + final[1] + final[2] + final[3] // 1, 2, 3, 4 - //+ 0, 1, 2, 3 - // 1, 3, 5, 7 + //+ 0, 1, 0, 3 + // 1, 3, 3, 7 // shift and add for the first round __m128i prev = _mm_set1_epi64x(prev_value); - delta = _mm256_add_epi64(delta, _mm256_slli_si256(delta, 8)); + __m256i x = _mm256_slli_si256(delta, 8); + + delta = _mm256_add_epi64(delta, x); _mm256_storeu_si256((__m256i *)&p[_pos], delta); - // 1, 3, 5, 7 - //+ 0, 0, 1, 3 + // 1, 3, 3, 7 + //+ 0, 0, 3, 3 // 1, 3, 6, 10 // shift and add operation for the second round __m128i firstPart = _mm_loadu_si128((__m128i *)&p[_pos]); - __m128i secPart = _mm_add_epi64(_mm_loadu_si128((__m128i *)&p[_pos + 2]), firstPart); + __m128i secondItem = _mm_set1_epi64x(p[_pos + 1]); + __m128i secPart = _mm_add_epi64(_mm_loadu_si128((__m128i *)&p[_pos + 2]), secondItem); firstPart = _mm_add_epi64(firstPart, prev); secPart = _mm_add_epi64(secPart, prev); @@ -353,15 +356,18 @@ int32_t tsDecompressINTImp(const char *const input, const int32_t nelements, cha shiftBits = _mm256_add_epi64(shiftBits, inc); prev_value = p[_pos + 3]; +// uDebug("_pos:%d %"PRId64", %"PRId64", %"PRId64", %"PRId64, _pos, p[_pos], p[_pos+1], p[_pos+2], p[_pos+3]); _pos += 4; } // handle the remain value for (int32_t i = 0; i < remain; i++) { - zigzag_value = ((w >> (v + (batch * bit))) & mask); + zigzag_value = ((w >> (v + (batch * bit * 4))) & mask); prev_value += ZIGZAG_DECODE(int64_t, zigzag_value); p[_pos++] = prev_value; +// uDebug("_pos:%d %"PRId64, _pos-1, p[_pos-1]); + v += bit; } } else { @@ -370,6 +376,8 @@ int32_t tsDecompressINTImp(const char *const input, const int32_t nelements, cha prev_value += ZIGZAG_DECODE(int64_t, zigzag_value); p[_pos++] = prev_value; +// uDebug("_pos:%d %"PRId64, _pos-1, p[_pos-1]); + v += bit; } } @@ -904,11 +912,11 @@ int32_t tsCompressDoubleImp(const char *const input, const int32_t nelements, ch return opos; } -uint64_t decodeDoubleValue(const char *const input, int32_t *const ipos, uint8_t flag) { +FORCE_INLINE uint64_t decodeDoubleValue(const char *const input, int32_t *const ipos, uint8_t flag) { uint64_t diff = 0ul; - int32_t nbytes = (flag & INT8MASK(3)) + 1; + int32_t nbytes = (flag & 0x7) + 1; for (int32_t i = 0; i < nbytes; i++) { - diff = diff | ((INT64MASK(8) & input[(*ipos)++]) << BITS_PER_BYTE * i); + diff |= (((uint64_t)0xff & input[(*ipos)++]) << BITS_PER_BYTE * i); } int32_t shift_width = (LONG_BYTES * BITS_PER_BYTE - nbytes * BITS_PER_BYTE) * (flag >> 3); diff <<= shift_width; @@ -928,25 +936,22 @@ int32_t tsDecompressDoubleImp(const char *const input, const int32_t nelements, uint8_t flags = 0; int32_t ipos = 1; int32_t opos = 0; - uint64_t prev_value = 0; + uint64_t diff = 0; + union { + uint64_t bits; + double real; + } curr; + + curr.bits = 0; for (int32_t i = 0; i < nelements; i++) { if ((i & 0x01) == 0) { flags = input[ipos++]; } - uint8_t flag = flags & INT8MASK(4); + diff = decodeDoubleValue(input, &ipos, flags & 0x0f); flags >>= 4; - - uint64_t diff = decodeDoubleValue(input, &ipos, flag); - union { - uint64_t bits; - double real; - } curr; - - uint64_t predicted = prev_value; - curr.bits = predicted ^ diff; - prev_value = curr.bits; + curr.bits ^= diff; ostream[opos++] = curr.real; } diff --git a/source/util/src/tconfig.c b/source/util/src/tconfig.c index 609a386367d825bca096b12857b8e8ece013c49d..288ea6052b580909198788f528871633048e19f1 100644 --- a/source/util/src/tconfig.c +++ b/source/util/src/tconfig.c @@ -109,7 +109,7 @@ int32_t cfgGetSize(SConfig *pCfg) { return taosArrayGetSize(pCfg->array); } static int32_t cfgCheckAndSetTimezone(SConfigItem *pItem, const char *timezone) { cfgFreeItem(pItem); - pItem->str = strdup(timezone); + pItem->str = taosStrdup(timezone); if (pItem->str == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -120,7 +120,7 @@ static int32_t cfgCheckAndSetTimezone(SConfigItem *pItem, const char *timezone) static int32_t cfgCheckAndSetCharset(SConfigItem *pItem, const char *charset) { cfgFreeItem(pItem); - pItem->str = strdup(charset); + pItem->str = taosStrdup(charset); if (pItem->str == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -131,7 +131,7 @@ static int32_t cfgCheckAndSetCharset(SConfigItem *pItem, const char *charset) { static int32_t cfgCheckAndSetLocale(SConfigItem *pItem, const char *locale) { cfgFreeItem(pItem); - pItem->str = strdup(locale); + pItem->str = taosStrdup(locale); if (pItem->str == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -149,7 +149,7 @@ static int32_t cfgCheckAndSetDir(SConfigItem *pItem, const char *inputDir) { } taosMemoryFreeClear(pItem->str); - pItem->str = strdup(fullDir); + pItem->str = taosStrdup(fullDir); if (pItem->str == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -187,7 +187,7 @@ static int32_t cfgSetInt32(SConfigItem *pItem, const char *value, ECfgSrcType st } static int32_t cfgSetInt64(SConfigItem *pItem, const char *value, ECfgSrcType stype) { - int64_t ival = (int64_t)atoi(value); + int64_t ival = (int64_t)atoll(value); if (ival < pItem->imin || ival > pItem->imax) { uError("cfg:%s, type:%s src:%s value:%" PRId64 " out of range[%" PRId64 ", %" PRId64 "]", pItem->name, cfgDtypeStr(pItem->dtype), cfgStypeStr(stype), ival, pItem->imin, pItem->imax); @@ -215,7 +215,7 @@ static int32_t cfgSetFloat(SConfigItem *pItem, const char *value, ECfgSrcType st } static int32_t cfgSetString(SConfigItem *pItem, const char *value, ECfgSrcType stype) { - char *tmp = strdup(value); + char *tmp = taosStrdup(value); if (tmp == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; uError("cfg:%s, type:%s src:%s value:%s failed to dup since %s", pItem->name, cfgDtypeStr(pItem->dtype), @@ -358,7 +358,7 @@ SConfigItem *cfgGetItem(SConfig *pCfg, const char *name) { static int32_t cfgAddItem(SConfig *pCfg, SConfigItem *pItem, const char *name) { pItem->stype = CFG_STYPE_DEFAULT; - pItem->name = strdup(name); + pItem->name = taosStrdup(name); if (pItem->name == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -417,7 +417,7 @@ int32_t cfgAddFloat(SConfig *pCfg, const char *name, float defaultVal, double mi int32_t cfgAddString(SConfig *pCfg, const char *name, const char *defaultVal, bool tsc) { SConfigItem item = {.dtype = CFG_DTYPE_STRING, .tsc = tsc}; - item.str = strdup(defaultVal); + item.str = taosStrdup(defaultVal); if (item.str == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -637,6 +637,8 @@ int32_t cfgLoadFromEnvVar(SConfig *pConfig) { int32_t code = 0; char **pEnv = environ; line[1023] = 0; + + if (pEnv == NULL) return 0; while (*pEnv != NULL) { name = value = value2 = value3 = NULL; olen = vlen = vlen2 = vlen3 = 0; diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 57b1998155bf24221eb2e57dbcdb7d8312f8f9eb..712c413e7c8dcb7c5a19789b37b77a14cac8afe6 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -52,6 +52,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_RPC_PORT_EADDRINUSE, "Port already in use") TAOS_DEFINE_ERROR(TSDB_CODE_RPC_BROKEN_LINK, "Conn is broken") TAOS_DEFINE_ERROR(TSDB_CODE_RPC_TIMEOUT, "Conn read timeout") TAOS_DEFINE_ERROR(TSDB_CODE_RPC_SOMENODE_NOT_CONNECTED, "some vnode/qnode/mnode(s) out of service") +TAOS_DEFINE_ERROR(TSDB_CODE_RPC_MAX_SESSIONS, "rpc open too many session") //common & util TAOS_DEFINE_ERROR(TSDB_CODE_TIME_UNSYNCED, "Client and server's time is not synchronized") @@ -93,9 +94,11 @@ TAOS_DEFINE_ERROR(TSDB_CODE_NO_AVAIL_DISK, "No available disk") TAOS_DEFINE_ERROR(TSDB_CODE_NOT_FOUND, "Not found") TAOS_DEFINE_ERROR(TSDB_CODE_NO_DISKSPACE, "Out of disk space") TAOS_DEFINE_ERROR(TSDB_CODE_TIMEOUT_ERROR, "Operation timeout") +TAOS_DEFINE_ERROR(TSDB_CODE_NO_ENOUGH_DISKSPACE, "No enough disk space") TAOS_DEFINE_ERROR(TSDB_CODE_APP_IS_STARTING, "Database is starting up") TAOS_DEFINE_ERROR(TSDB_CODE_APP_IS_STOPPING, "Database is closing down") +TAOS_DEFINE_ERROR(TSDB_CODE_IVLD_DATA_FMT, "Invalid data format") //client TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_OPERATION, "Invalid operation") @@ -119,7 +122,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSC_NO_WRITE_AUTH, "No write permission") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_CONN_KILLED, "Connection killed") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_SQL_SYNTAX_ERROR, "Syntax error in SQL") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DB_NOT_SELECTED, "Database not specified or available") -TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_TABLE_NAME, "Table does not exist") +//TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_TABLE_NAME, "Table does not exist") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_EXCEED_SQL_LIMIT, "SQL statement too long") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_FILE_EMPTY, "File is empty") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_LINE_SYNTAX_ERROR, "Syntax error in Line") @@ -138,6 +141,8 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSC_STMT_CLAUSE_ERROR, "not supported stmt cl TAOS_DEFINE_ERROR(TSDB_CODE_TSC_QUERY_KILLED, "Query killed") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_NO_EXEC_NODE, "No available execution node in current query policy configuration") TAOS_DEFINE_ERROR(TSDB_CODE_TSC_NOT_STABLE_ERROR, "Table is not a super table") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_STMT_CACHE_ERROR, "Stmt cache error") +TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INTERNAL_ERROR, "Internal error") // mnode-common TAOS_DEFINE_ERROR(TSDB_CODE_MND_NO_RIGHTS, "Insufficient privilege for operation") @@ -179,11 +184,13 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_MANY_ACCTS, "Too many accounts") TAOS_DEFINE_ERROR(TSDB_CODE_MND_USER_ALREADY_EXIST, "User already exists") TAOS_DEFINE_ERROR(TSDB_CODE_MND_USER_NOT_EXIST, "Invalid user") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_USER_FORMAT, "Invalid user format") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_USER_NOT_AVAILABLE, "User not available") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_PASS_FORMAT, "Invalid password format") TAOS_DEFINE_ERROR(TSDB_CODE_MND_NO_USER_FROM_CONN, "Can not get user from conn") TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_MANY_USERS, "Too many users") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_ALTER_OPER, "Invalid alter operation") TAOS_DEFINE_ERROR(TSDB_CODE_MND_AUTH_FAILURE, "Authentication failure") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_PRIVILEDGE_EXIST, "User already have this priviledge") //mnode-stable-part1 TAOS_DEFINE_ERROR(TSDB_CODE_MND_STB_ALREADY_EXIST, "STable already exists") @@ -196,6 +203,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_COLUMN_ALREADY_EXIST, "Column already exists TAOS_DEFINE_ERROR(TSDB_CODE_MND_COLUMN_NOT_EXIST, "Column does not exist") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_STB_OPTION, "Invalid stable options") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_ROW_BYTES, "Invalid row bytes") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_FIELD_VALUE_OVERFLOW, "out of range and overflow") // mnode-func TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC_NAME, "Invalid func name") @@ -206,6 +214,10 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC_BUFSIZE, "Invalid func bufSize" TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC_COMMENT, "Invalid func comment") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_FUNC_RETRIEVE, "Invalid func retrieve msg") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_TAG_INDEX_ALREADY_EXIST, "index already exists") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_TAG_INDEX_NOT_EXIST, "index not exist") + + // mnode-db 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") @@ -214,6 +226,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_DB, "Invalid database name TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_MANY_DATABASES, "Too many databases for account") TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_IN_DROPPING, "Database in dropping status") TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_NOT_EXIST, "Database not exist") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_RETENTION_PERIOD_ZERO, "WAL retention period is zero") TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_DB_ACCT, "Invalid database account") TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_OPTION_UNCHANGED, "Database options not changed") TAOS_DEFINE_ERROR(TSDB_CODE_MND_DB_INDEX_NOT_EXIST, "Index not exist") @@ -289,11 +302,12 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_STREAM_OPTION, "Invalid stream option TAOS_DEFINE_ERROR(TSDB_CODE_MND_STREAM_MUST_BE_DELETED, "Stream must be dropped first") TAOS_DEFINE_ERROR(TSDB_CODE_MND_MULTI_REPLICA_SOURCE_DB, "Stream temporarily does not support source db having replica > 1") TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOO_MANY_STREAMS, "Too many streams") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_TARGET_TABLE, "Cannot write the same stable as other stream") // mnode-sma -TAOS_DEFINE_ERROR(TSDB_CODE_MND_SMA_ALREADY_EXIST, "SMA already exists") -TAOS_DEFINE_ERROR(TSDB_CODE_MND_SMA_NOT_EXIST, "SMA does not exist") -TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_SMA_OPTION, "Invalid sma option") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_SMA_ALREADY_EXIST, "index already exists") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_SMA_NOT_EXIST, "index not exist") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_INVALID_SMA_OPTION, "Invalid sma index option") // dnode TAOS_DEFINE_ERROR(TSDB_CODE_DNODE_OFFLINE, "Dnode is offline") @@ -308,7 +322,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_SNODE_ALREADY_DEPLOYED, "Snode already deploye TAOS_DEFINE_ERROR(TSDB_CODE_SNODE_NOT_DEPLOYED, "Snode not deployed") // vnode -TAOS_DEFINE_ERROR(TSDB_CODE_VND_INVALID_VGROUP_ID, "Vnode moved to another dnode or was deleted") +TAOS_DEFINE_ERROR(TSDB_CODE_VND_INVALID_VGROUP_ID, "Vnode is closed or removed") TAOS_DEFINE_ERROR(TSDB_CODE_VND_NO_WRITE_AUTH, "Database write operation denied") TAOS_DEFINE_ERROR(TSDB_CODE_VND_NOT_EXIST, "Vnode not exist") TAOS_DEFINE_ERROR(TSDB_CODE_VND_ALREADY_EXIST, "Vnode already exist") @@ -320,6 +334,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_VND_COL_SUBSCRIBED, "Table column is subsc TAOS_DEFINE_ERROR(TSDB_CODE_VND_NO_AVAIL_BUFPOOL, "No availabe buffer pool") TAOS_DEFINE_ERROR(TSDB_CODE_VND_STOPPED, "Vnode stopped") TAOS_DEFINE_ERROR(TSDB_CODE_VND_DUP_REQUEST, "Duplicate write request") +TAOS_DEFINE_ERROR(TSDB_CODE_VND_QUERY_BUSY, "Query busy") // tsdb TAOS_DEFINE_ERROR(TSDB_CODE_TDB_INVALID_TABLE_ID, "Invalid table ID") @@ -357,7 +372,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_QRY_EXCEED_TAGS_LIMIT, "Tag conditon too many TAOS_DEFINE_ERROR(TSDB_CODE_QRY_NOT_READY, "Query not ready") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_HAS_RSP, "Query should response") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_IN_EXEC, "Multiple retrieval of this query") -TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW, "Too many time window in query") +TAOS_DEFINE_ERROR(TSDB_CODE_QRY_TOO_MANY_TIMEWINDOW, "Too many groups/time window in query") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_NOT_ENOUGH_BUFFER, "Query buffer limit has reached") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_INCONSISTAN, "File inconsistance in replica") TAOS_DEFINE_ERROR(TSDB_CODE_QRY_SYS_ERROR, "System error") @@ -400,7 +415,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_TABLE_LIMITED, "Table creation limite // sync TAOS_DEFINE_ERROR(TSDB_CODE_SYN_TIMEOUT, "Sync timeout") TAOS_DEFINE_ERROR(TSDB_CODE_SYN_IS_LEADER, "Sync is leader") -TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NOT_LEADER, "Sync not leader") +TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NOT_LEADER, "Sync leader is unreachable") TAOS_DEFINE_ERROR(TSDB_CODE_SYN_ONE_REPLICA, "Sync one replica") TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NOT_IN_NEW_CONFIG, "Sync not in new config") TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NEW_CONFIG_ERROR, "Sync new config error") @@ -408,9 +423,10 @@ TAOS_DEFINE_ERROR(TSDB_CODE_SYN_RECONFIG_NOT_READY, "Sync not ready for re TAOS_DEFINE_ERROR(TSDB_CODE_SYN_PROPOSE_NOT_READY, "Sync not ready for propose") TAOS_DEFINE_ERROR(TSDB_CODE_SYN_STANDBY_NOT_READY, "Sync not ready for standby") TAOS_DEFINE_ERROR(TSDB_CODE_SYN_BATCH_ERROR, "Sync batch error") -TAOS_DEFINE_ERROR(TSDB_CODE_SYN_RESTORING, "Sync is restoring") +TAOS_DEFINE_ERROR(TSDB_CODE_SYN_RESTORING, "Sync leader is restoring") TAOS_DEFINE_ERROR(TSDB_CODE_SYN_INVALID_SNAPSHOT_MSG, "Sync invalid snapshot msg") TAOS_DEFINE_ERROR(TSDB_CODE_SYN_BUFFER_FULL, "Sync buffer is full") +TAOS_DEFINE_ERROR(TSDB_CODE_SYN_WRITE_STALL, "Sync write stall") TAOS_DEFINE_ERROR(TSDB_CODE_SYN_INTERNAL_ERROR, "Sync internal error") //tq @@ -424,7 +440,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TQ_META_KEY_NOT_IN_TXN, "TQ meta key not in tx TAOS_DEFINE_ERROR(TSDB_CODE_TQ_META_KEY_DUP_IN_TXN, "TQ met key dup in txn") TAOS_DEFINE_ERROR(TSDB_CODE_TQ_GROUP_NOT_SET, "TQ group not exist") TAOS_DEFINE_ERROR(TSDB_CODE_TQ_TABLE_SCHEMA_NOT_FOUND, "TQ table schema not found") -TAOS_DEFINE_ERROR(TSDB_CODE_TQ_NO_COMMITTED_OFFSET, "TQ no commited offset") +TAOS_DEFINE_ERROR(TSDB_CODE_TQ_NO_COMMITTED_OFFSET, "TQ no committed offset") // wal TAOS_DEFINE_ERROR(TSDB_CODE_WAL_FILE_CORRUPTED, "WAL file is corrupted") @@ -503,7 +519,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_ONLY_ONE_JSON_TAG, "Only one tag if ther TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INCORRECT_NUM_OF_COL, "Query block has incorrect number of result columns") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INCORRECT_TIMESTAMP_VAL, "Incorrect TIMESTAMP value") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_OFFSET_LESS_ZERO, "soffset/offset can not be less than 0") -TAOS_DEFINE_ERROR(TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_BY, "slimit/soffset only available for PARTITION BY query") +TAOS_DEFINE_ERROR(TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_GROUP_BY, "slimit/soffset only available for PARTITION/GROUP BY query") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_TOPIC_QUERY, "Invalid topic query") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_DROP_STABLE, "Cannot drop super table in batch") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE, "Start(end) time of query range required or time range too large") @@ -513,7 +529,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_ROW_LENGTH, "Row length exceeds TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_COLUMNS_NUM, "Illegal number of columns") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TOO_MANY_COLUMNS, "Too many columns") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_FIRST_COLUMN, "First column must be timestamp") -TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN, "Invalid binary/nchar column length") +TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN, "Invalid binary/nchar column/tag length") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_TAGS_NUM, "Invalid number of tag columns") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_PERMISSION_DENIED, "Permission denied") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_STREAM_QUERY, "Invalid stream query") @@ -572,6 +588,8 @@ TAOS_DEFINE_ERROR(TSDB_CODE_UDF_INVALID_INPUT, "udf invalid functio TAOS_DEFINE_ERROR(TSDB_CODE_UDF_NO_FUNC_HANDLE, "udf no function handle") TAOS_DEFINE_ERROR(TSDB_CODE_UDF_INVALID_BUFSIZE, "udf invalid bufsize") TAOS_DEFINE_ERROR(TSDB_CODE_UDF_INVALID_OUTPUT_TYPE, "udf invalid output type") +TAOS_DEFINE_ERROR(TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED, "udf program language not supported") +TAOS_DEFINE_ERROR(TSDB_CODE_UDF_FUNC_EXEC_FAILURE, "udf function execution failure") //schemaless TAOS_DEFINE_ERROR(TSDB_CODE_SML_INVALID_PROTOCOL_TYPE, "Invalid line protocol type") @@ -579,6 +597,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_SML_INVALID_PRECISION_TYPE, "Invalid timestamp p TAOS_DEFINE_ERROR(TSDB_CODE_SML_INVALID_DATA, "Invalid data format") TAOS_DEFINE_ERROR(TSDB_CODE_SML_INVALID_DB_CONF, "Invalid schemaless db config") TAOS_DEFINE_ERROR(TSDB_CODE_SML_NOT_SAME_TYPE, "Not the same type like before") +TAOS_DEFINE_ERROR(TSDB_CODE_SML_INTERNAL_ERROR, "Internal error") //tsma TAOS_DEFINE_ERROR(TSDB_CODE_TSMA_INIT_FAILED, "Tsma init failed") @@ -594,6 +613,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSMA_NO_INDEX_IN_CACHE, "No tsma index in ca TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_INVALID_ENV, "Invalid rsma env") TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_INVALID_STAT, "Invalid rsma state") TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_QTASKINFO_CREATE, "Rsma qtaskinfo creation error") +TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_FS_COMMIT, "Rsma fs commit error") TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_REMOVE_EXISTS, "Rsma remove exists") TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_FETCH_MSG_MSSED_UP, "Rsma fetch msg is messed up") TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_EMPTY_INFO, "Rsma info is empty") @@ -601,6 +621,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_INVALID_SCHEMA, "Rsma invalid schema TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_REGEX_MATCH, "Rsma regex match") TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_STREAM_STATE_OPEN, "Rsma stream state open") TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_STREAM_STATE_COMMIT, "Rsma stream state commit") +TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_FS_REF, "Rsma fs ref error") +TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_FS_SYNC, "Rsma fs sync error") +TAOS_DEFINE_ERROR(TSDB_CODE_RSMA_FS_UPDATE, "Rsma fs update error") //index TAOS_DEFINE_ERROR(TSDB_CODE_INDEX_REBUILDING, "Index is rebuilding") @@ -610,6 +633,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_INDEX_INVALID_FILE, "Index file is inval TAOS_DEFINE_ERROR(TSDB_CODE_TMQ_INVALID_MSG, "Invalid message") TAOS_DEFINE_ERROR(TSDB_CODE_TMQ_CONSUMER_MISMATCH, "Consumer mismatch") TAOS_DEFINE_ERROR(TSDB_CODE_TMQ_CONSUMER_CLOSED, "Consumer closed") +TAOS_DEFINE_ERROR(TSDB_CODE_TMQ_CONSUMER_ERROR, "Consumer error, to see log") // stream TAOS_DEFINE_ERROR(TSDB_CODE_STREAM_TASK_NOT_EXIST, "Stream task not exist") diff --git a/source/util/src/thash.c b/source/util/src/thash.c index 926dc304a47caebdb0bd5c215bfc73cfefe87d5a..cf4f17bfbc3efdeae375142176c8681b0a50a4a5 100644 --- a/source/util/src/thash.c +++ b/source/util/src/thash.c @@ -150,7 +150,6 @@ static FORCE_INLINE SHashNode *doSearchInEntryList(SHashObj *pHashObj, SHashEntr //atomic_add_fetch_64(&pHashObj->compTimes, 1); if ((pNode->keyLen == keyLen) && ((*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0) && pNode->removed == 0) { - assert(pNode->hashVal == hashVal); break; } @@ -189,8 +188,6 @@ static SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *p */ static FORCE_INLINE void doUpdateHashNode(SHashObj *pHashObj, SHashEntry *pe, SHashNode *prev, SHashNode *pNode, SHashNode *pNewNode) { - assert(pNode->keyLen == pNewNode->keyLen); - atomic_sub_fetch_16(&pNode->refCount, 1); if (prev != NULL) { prev->next = pNewNode; @@ -236,7 +233,7 @@ static FORCE_INLINE bool taosHashTableEmpty(const SHashObj *pHashObj) { return t SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTypeE type) { if (fn == NULL) { - assert(0); + terrno = TSDB_CODE_INVALID_PARA; return NULL; } @@ -262,8 +259,6 @@ SHashObj *taosHashInit(size_t capacity, _hash_fn_t fn, bool update, SHashLockTyp pHashObj->freeFp = NULL; pHashObj->callbackFp = NULL; - ASSERT((pHashObj->capacity & (pHashObj->capacity - 1)) == 0); - pHashObj->hashList = (SHashEntry **)taosMemoryMalloc(pHashObj->capacity * sizeof(void *)); if (pHashObj->hashList == NULL) { taosMemoryFree(pHashObj); @@ -342,19 +337,10 @@ int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, const vo taosHashEntryWLock(pHashObj, pe); SHashNode *pNode = pe->next; -#if 0 - if (pe->num > 0) { - assert(pNode != NULL); - } else { - assert(pNode == NULL); - } -#endif - SHashNode *prev = NULL; while (pNode) { if ((pNode->keyLen == keyLen) && (*(pHashObj->equalFp))(GET_HASH_NODE_KEY(pNode), key, keyLen) == 0 && pNode->removed == 0) { - assert(pNode->hashVal == hashVal); break; } @@ -370,8 +356,6 @@ int32_t taosHashPut(SHashObj *pHashObj, const void *key, size_t keyLen, const vo } pushfrontNodeInEntryList(pe, pNewNode); - assert(pe->next != NULL); - taosHashEntryWUnlock(pHashObj, pe); // enable resize @@ -446,14 +430,6 @@ void *taosHashGetImpl(SHashObj *pHashObj, const void *key, size_t keyLen, void * char *data = NULL; taosHashEntryRLock(pHashObj, pe); -#if 0 - if (pe->num > 0) { - assert(pe->next != NULL); - } else { - assert(pe->next == NULL); - } -#endif - SHashNode *pNode = doSearchInEntryList(pHashObj, pe, key, keyLen, hashVal); if (pNode != NULL) { if (pHashObj->callbackFp != NULL) { @@ -514,8 +490,6 @@ int32_t taosHashRemove(SHashObj *pHashObj, const void *key, size_t keyLen) { // double check after locked if (pe->num == 0) { - assert(pe->next == NULL); - taosHashEntryWUnlock(pHashObj, pe); taosHashRUnlock(pHashObj); return -1; @@ -568,13 +542,10 @@ void taosHashClear(SHashObj *pHashObj) { for (int32_t i = 0; i < pHashObj->capacity; ++i) { SHashEntry *pEntry = pHashObj->hashList[i]; if (pEntry->num == 0) { - assert(pEntry->next == NULL); continue; } pNode = pEntry->next; - assert(pNode != NULL); - while (pNode) { pNext = pNode->next; FREE_HASH_NODE(pHashObj->freeFp, pNode); @@ -671,14 +642,11 @@ void taosHashTableResize(SHashObj *pHashObj) { SHashNode *pPrev = NULL; if (pe->num == 0) { - assert(pe->next == NULL); continue; } pNode = pe->next; - assert(pNode != NULL); - while (pNode != NULL) { int32_t newIdx = HASH_INDEX(pNode->hashVal, pHashObj->capacity); pNext = pNode->next; @@ -728,12 +696,8 @@ SHashNode *doCreateHashNode(const void *key, size_t keyLen, const void *pData, s } void pushfrontNodeInEntryList(SHashEntry *pEntry, SHashNode *pNode) { - assert(pNode != NULL && pEntry != NULL); - pNode->next = pEntry->next; pEntry->next = pNode; - - ASSERT(pNode->next != pNode); pEntry->num += 1; } @@ -847,19 +811,7 @@ void *taosHashIterate(SHashObj *pHashObj, void *p) { /*uint16_t prevRef = atomic_load_16(&pNode->refCount);*/ uint16_t afterRef = atomic_add_fetch_16(&pNode->refCount, 1); -#if 0 - ASSERT(prevRef < afterRef); - // the reference count value is overflow, which will cause the delete node operation immediately. - if (prevRef > afterRef) { - uError("hash entry ref count overflow, prev ref:%d, current ref:%d", prevRef, afterRef); - // restore the value - atomic_sub_fetch_16(&pNode->refCount, 1); - data = NULL; - } else { - data = GET_HASH_NODE_DATA(pNode); - } -#endif data = GET_HASH_NODE_DATA(pNode); if (afterRef >= MAX_WARNING_REF_COUNT) { diff --git a/source/util/src/thashutil.c b/source/util/src/thashutil.c index 21b9359076078900196769046b54ff31fd88b0e4..f9c7eb1f5687440d5156d1999741ef777774aa67 100644 --- a/source/util/src/thashutil.c +++ b/source/util/src/thashutil.c @@ -50,11 +50,6 @@ uint32_t taosDJB2Hash(const char *key, uint32_t len) { return hash; } -uint32_t xxHash(const char *key, uint32_t len) { - int32_t seed = 0xcc9e2d51; - return XXH32(key, len, seed); -} - uint32_t MurmurHash3_32(const char *key, uint32_t len) { const uint8_t *data = (const uint8_t *)key; const int32_t nblocks = len >> 2u; diff --git a/source/util/src/tjson.c b/source/util/src/tjson.c index 27d14d05b10185a4ca3d5d162b4b15dbd28faa3d..0b7ad330a7f5c084618650bc6c5f99ec96ea6b88 100644 --- a/source/util/src/tjson.c +++ b/source/util/src/tjson.c @@ -192,7 +192,7 @@ int32_t tjsonDupStringValue(const SJson* pJson, const char* pName, char** pVal) if (NULL == p) { return TSDB_CODE_SUCCESS; } - *pVal = strdup(p); + *pVal = taosStrdup(p); return TSDB_CODE_SUCCESS; } @@ -325,7 +325,7 @@ int32_t tjsonToTArray(const SJson* pJson, const char* pName, FToObject func, SAr const cJSON* jArray = tjsonGetObjectItem(pJson, pName); int32_t size = tjsonGetArraySize(jArray); if (size > 0) { - *pArray = taosArrayInit_s(size, itemSize, size); + *pArray = taosArrayInit_s(itemSize, size); if (NULL == *pArray) { return TSDB_CODE_OUT_OF_MEMORY; } diff --git a/source/util/src/tlist.c b/source/util/src/tlist.c index 1b12ea0cddb12545e17acfb193ba1ede592fc9e1..5d729d27d6d633d05079c6ebb708a89d5dfe7007 100644 --- a/source/util/src/tlist.c +++ b/source/util/src/tlist.c @@ -104,7 +104,6 @@ SListNode *tdListPopNode(SList *list, SListNode *node) { // Move all node elements from src to dst, the dst is assumed as an empty list void tdListMove(SList *src, SList *dst) { - // assert(dst->eleSize == src->eleSize); SListNode *node = NULL; while ((node = tdListPopHead(src)) != NULL) { tdListAppendNode(dst, node); diff --git a/source/util/src/tlog.c b/source/util/src/tlog.c index 89dd51a8924b3a24e70a665a3ae76e14541f6081..e3b1c2fa2f7fbd48604ea6cdcb4cf776f6ca7bac 100644 --- a/source/util/src/tlog.c +++ b/source/util/src/tlog.c @@ -17,11 +17,10 @@ #include "tlog.h" #include "os.h" #include "tconfig.h" -#include "tutil.h" #include "tjson.h" #include "tglobal.h" -#define LOG_MAX_LINE_SIZE (1024) +#define LOG_MAX_LINE_SIZE (10024) #define LOG_MAX_LINE_BUFFER_SIZE (LOG_MAX_LINE_SIZE + 3) #define LOG_MAX_LINE_DUMP_SIZE (1024 * 1024) #define LOG_MAX_LINE_DUMP_BUFFER_SIZE (LOG_MAX_LINE_DUMP_SIZE + 3) @@ -121,7 +120,7 @@ static FORCE_INLINE void taosUpdateDaylight() { struct timeval timeSecs; taosGetTimeOfDay(&timeSecs); time_t curTime = timeSecs.tv_sec; - ptm = taosLocalTime(&curTime, &Tm); + ptm = taosLocalTime(&curTime, &Tm, NULL); tsDaylightActive = ptm->tm_isdst; } static FORCE_INLINE int32_t taosGetDaylight() { return tsDaylightActive; } @@ -348,7 +347,6 @@ static int32_t taosOpenLogFile(char *fn, int32_t maxLines, int32_t maxFileNum) { char name[LOG_FILE_NAME_LEN + 50] = "\0"; int32_t logstat0_mtime, logstat1_mtime; - int32_t size; tsLogObj.maxLines = maxLines; tsLogObj.fileNum = maxFileNum; @@ -396,8 +394,7 @@ static int32_t taosOpenLogFile(char *fn, int32_t maxLines, int32_t maxFileNum) { printf("\nfailed to fstat log file:%s, reason:%s\n", fileName, strerror(errno)); return -1; } - size = (int32_t)filesize; - tsLogObj.lines = size / 60; + tsLogObj.lines = (int32_t)(filesize / 60); taosLSeekFile(tsLogObj.logHandle->pFile, 0, SEEK_END); @@ -437,7 +434,7 @@ static inline int32_t taosBuildLogHead(char *buffer, const char *flags) { taosGetTimeOfDay(&timeSecs); time_t curTime = timeSecs.tv_sec; - ptm = taosLocalTime(&curTime, &Tm); + ptm = taosLocalTime(&curTime, &Tm, NULL); return sprintf(buffer, "%02d/%02d %02d:%02d:%02d.%06d %08" PRId64 " %s", ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int32_t)timeSecs.tv_usec, taosGetSelfPthreadId(), flags); @@ -599,7 +596,7 @@ static int32_t taosPushLogBuffer(SLogBuff *pLogBuf, const char *msg, int32_t msg int32_t end = 0; int32_t remainSize = 0; static int64_t lostLine = 0; - char tmpBuf[128] = {0}; + char tmpBuf[128]; int32_t tmpBufLen = 0; if (pLogBuf == NULL || pLogBuf->stop) return -1; @@ -781,65 +778,6 @@ bool taosAssertDebug(bool condition, const char *file, int32_t line, const char return true; } -int32_t taosGenCrashJsonMsg(int signum, char** pMsg, int64_t clusterId, int64_t startTime) { - SJson* pJson = tjsonCreateObject(); - if (pJson == NULL) return -1; - char tmp[4096] = {0}; - - tjsonAddDoubleToObject(pJson, "reportVersion", 1); - - tjsonAddIntegerToObject(pJson, "clusterId", clusterId); - tjsonAddIntegerToObject(pJson, "startTime", startTime); - - taosGetFqdn(tmp); - tjsonAddStringToObject(pJson, "fqdn", tmp); - - tjsonAddIntegerToObject(pJson, "pid", taosGetPId()); - - taosGetAppName(tmp, NULL); - tjsonAddStringToObject(pJson, "appName", tmp); - - if (taosGetOsReleaseName(tmp, sizeof(tmp)) == 0) { - tjsonAddStringToObject(pJson, "os", tmp); - } - - float numOfCores = 0; - if (taosGetCpuInfo(tmp, sizeof(tmp), &numOfCores) == 0) { - tjsonAddStringToObject(pJson, "cpuModel", tmp); - tjsonAddDoubleToObject(pJson, "numOfCpu", numOfCores); - } else { - tjsonAddDoubleToObject(pJson, "numOfCpu", tsNumOfCores); - } - - snprintf(tmp, sizeof(tmp), "%" PRId64 " kB", tsTotalMemoryKB); - tjsonAddStringToObject(pJson, "memory", tmp); - - tjsonAddStringToObject(pJson, "version", version); - tjsonAddStringToObject(pJson, "buildInfo", buildinfo); - tjsonAddStringToObject(pJson, "gitInfo", gitinfo); - - tjsonAddIntegerToObject(pJson, "crashSig", signum); - tjsonAddIntegerToObject(pJson, "crashTs", taosGetTimestampUs()); - -#ifdef _TD_DARWIN_64 - taosLogTraceToBuf(tmp, sizeof(tmp), 4); -#elif !defined(WINDOWS) - taosLogTraceToBuf(tmp, sizeof(tmp), 3); -#else - taosLogTraceToBuf(tmp, sizeof(tmp), 8); -#endif - - tjsonAddStringToObject(pJson, "stackInfo", tmp); - - char* pCont = tjsonToString(pJson); - tjsonDelete(pJson); - - *pMsg = pCont; - - return TSDB_CODE_SUCCESS; -} - - void taosLogCrashInfo(char* nodeType, char* pMsg, int64_t msgLen, int signum, void *sigInfo) { const char *flags = "UTL FATAL "; ELogLevel level = DEBUG_FATAL; diff --git a/source/util/src/tlosertree.c b/source/util/src/tlosertree.c index bf99212b78d4e75d3cbe3eb9823881168e03c129..c476baa7908172458cb5ffba718cd55fca62772d 100644 --- a/source/util/src/tlosertree.c +++ b/source/util/src/tlosertree.c @@ -115,8 +115,6 @@ void tMergeTreeAdjust(SMultiwayMergeTreeInfo* pTree, int32_t idx) { } void tMergeTreeRebuild(SMultiwayMergeTreeInfo* pTree) { - ASSERT((pTree->totalSources & 0x1) == 0); - tMergeTreeInit(pTree); for (int32_t i = pTree->totalSources - 1; i >= pTree->numOfSources; i--) { tMergeTreeAdjust(pTree, i); diff --git a/source/util/src/tlrucache.c b/source/util/src/tlrucache.c index 264883be4e71c99f1f3f3a1fbc872bf0c522728e..e182800d9c6219c0f0326a39319a3ddf67ae54b4 100644 --- a/source/util/src/tlrucache.c +++ b/source/util/src/tlrucache.c @@ -85,13 +85,13 @@ struct SLRUEntry { #define TAOS_LRU_ENTRY_REF(h) (++(h)->refs) static bool taosLRUEntryUnref(SLRUEntry *entry) { - assert(entry->refs > 0); + ASSERT(entry->refs > 0); --entry->refs; return entry->refs == 0; } static void taosLRUEntryFree(SLRUEntry *entry) { - assert(entry->refs == 0); + ASSERT(entry->refs == 0); if (entry->deleter) { (*entry->deleter)(entry->keyData, entry->keyLength, entry->value); @@ -127,7 +127,7 @@ static void taosLRUEntryTableApply(SLRUEntryTable *table, _taos_lru_table_func_t SLRUEntry *h = table->list[i]; while (h) { SLRUEntry *n = h->nextHash; - assert(TAOS_LRU_ENTRY_IN_CACHE(h)); + ASSERT(TAOS_LRU_ENTRY_IN_CACHE(h)); func(h); h = n; } @@ -184,7 +184,7 @@ static void taosLRUEntryTableResize(SLRUEntryTable *table) { ++count; } } - assert(table->elems == count); + ASSERT(table->elems == count); taosMemoryFree(table->list); table->list = newList; @@ -240,17 +240,16 @@ struct SLRUCacheShard { static void taosLRUCacheShardMaintainPoolSize(SLRUCacheShard *shard) { while (shard->highPriPoolUsage > shard->highPriPoolCapacity) { shard->lruLowPri = shard->lruLowPri->next; - assert(shard->lruLowPri != &shard->lru); + ASSERT(shard->lruLowPri != &shard->lru); TAOS_LRU_ENTRY_SET_IN_HIGH_POOL(shard->lruLowPri, false); - assert(shard->highPriPoolUsage >= shard->lruLowPri->totalCharge); + ASSERT(shard->highPriPoolUsage >= shard->lruLowPri->totalCharge); shard->highPriPoolUsage -= shard->lruLowPri->totalCharge; } } static void taosLRUCacheShardLRUInsert(SLRUCacheShard *shard, SLRUEntry *e) { - assert(e->next == NULL); - assert(e->prev == NULL); + ASSERT(e->next == NULL && e->prev == NULL); if (shard->highPriPoolRatio > 0 && (TAOS_LRU_ENTRY_IS_HIGH_PRI(e) || TAOS_LRU_ENTRY_HAS_HIT(e))) { e->next = &shard->lru; @@ -277,8 +276,7 @@ static void taosLRUCacheShardLRUInsert(SLRUCacheShard *shard, SLRUEntry *e) { } static void taosLRUCacheShardLRURemove(SLRUCacheShard *shard, SLRUEntry *e) { - assert(e->next); - assert(e->prev); + ASSERT(e->next && e->prev); if (shard->lruLowPri == e) { shard->lruLowPri = e->prev; @@ -287,10 +285,10 @@ static void taosLRUCacheShardLRURemove(SLRUCacheShard *shard, SLRUEntry *e) { e->prev->next = e->next; e->prev = e->next = NULL; - assert(shard->lruUsage >= e->totalCharge); + ASSERT(shard->lruUsage >= e->totalCharge); shard->lruUsage -= e->totalCharge; if (TAOS_LRU_ENTRY_IN_HIGH_POOL(e)) { - assert(shard->highPriPoolUsage >= e->totalCharge); + ASSERT(shard->highPriPoolUsage >= e->totalCharge); shard->highPriPoolUsage -= e->totalCharge; } } @@ -298,13 +296,13 @@ static void taosLRUCacheShardLRURemove(SLRUCacheShard *shard, SLRUEntry *e) { static void taosLRUCacheShardEvictLRU(SLRUCacheShard *shard, size_t charge, SArray *deleted) { while (shard->usage + charge > shard->capacity && shard->lru.next != &shard->lru) { SLRUEntry *old = shard->lru.next; - assert(TAOS_LRU_ENTRY_IN_CACHE(old) && !TAOS_LRU_ENTRY_HAS_REFS(old)); + ASSERT(TAOS_LRU_ENTRY_IN_CACHE(old) && !TAOS_LRU_ENTRY_HAS_REFS(old)); taosLRUCacheShardLRURemove(shard, old); taosLRUEntryTableRemove(&shard->table, old->keyData, old->keyLength, old->hash); TAOS_LRU_ENTRY_SET_IN_CACHE(old, false); - assert(shard->usage >= old->totalCharge); + ASSERT(shard->usage >= old->totalCharge); shard->usage -= old->totalCharge; taosArrayPush(deleted, &old); @@ -391,11 +389,11 @@ static LRUStatus taosLRUCacheShardInsertEntry(SLRUCacheShard *shard, SLRUEntry * if (old != NULL) { status = TAOS_LRU_STATUS_OK_OVERWRITTEN; - assert(TAOS_LRU_ENTRY_IN_CACHE(old)); + ASSERT(TAOS_LRU_ENTRY_IN_CACHE(old)); TAOS_LRU_ENTRY_SET_IN_CACHE(old, false); if (!TAOS_LRU_ENTRY_HAS_REFS(old)) { taosLRUCacheShardLRURemove(shard, old); - assert(shard->usage >= old->totalCharge); + ASSERT(shard->usage >= old->totalCharge); shard->usage -= old->totalCharge; taosArrayPush(lastReferenceList, &old); @@ -455,7 +453,7 @@ static LRUHandle *taosLRUCacheShardLookup(SLRUCacheShard *shard, const void *key taosThreadMutexLock(&shard->mutex); e = taosLRUEntryTableLookup(&shard->table, key, keyLen, hash); if (e != NULL) { - assert(TAOS_LRU_ENTRY_IN_CACHE(e)); + ASSERT(TAOS_LRU_ENTRY_IN_CACHE(e)); if (!TAOS_LRU_ENTRY_HAS_REFS(e)) { taosLRUCacheShardLRURemove(shard, e); } @@ -474,12 +472,12 @@ static void taosLRUCacheShardErase(SLRUCacheShard *shard, const void *key, size_ SLRUEntry *e = taosLRUEntryTableRemove(&shard->table, key, keyLen, hash); if (e != NULL) { - assert(TAOS_LRU_ENTRY_IN_CACHE(e)); + ASSERT(TAOS_LRU_ENTRY_IN_CACHE(e)); TAOS_LRU_ENTRY_SET_IN_CACHE(e, false); if (!TAOS_LRU_ENTRY_HAS_REFS(e)) { taosLRUCacheShardLRURemove(shard, e); - assert(shard->usage >= e->totalCharge); + ASSERT(shard->usage >= e->totalCharge); shard->usage -= e->totalCharge; lastReference = true; } @@ -499,11 +497,11 @@ static void taosLRUCacheShardEraseUnrefEntries(SLRUCacheShard *shard) { while (shard->lru.next != &shard->lru) { SLRUEntry *old = shard->lru.next; - assert(TAOS_LRU_ENTRY_IN_CACHE(old) && !TAOS_LRU_ENTRY_HAS_REFS(old)); + ASSERT(TAOS_LRU_ENTRY_IN_CACHE(old) && !TAOS_LRU_ENTRY_HAS_REFS(old)); taosLRUCacheShardLRURemove(shard, old); taosLRUEntryTableRemove(&shard->table, old->keyData, old->keyLength, old->hash); TAOS_LRU_ENTRY_SET_IN_CACHE(old, false); - assert(shard->usage >= old->totalCharge); + ASSERT(shard->usage >= old->totalCharge); shard->usage -= old->totalCharge; taosArrayPush(lastReferenceList, &old); @@ -524,7 +522,7 @@ static bool taosLRUCacheShardRef(SLRUCacheShard *shard, LRUHandle *handle) { SLRUEntry *e = (SLRUEntry *)handle; taosThreadMutexLock(&shard->mutex); - assert(TAOS_LRU_ENTRY_HAS_REFS(e)); + ASSERT(TAOS_LRU_ENTRY_HAS_REFS(e)); TAOS_LRU_ENTRY_REF(e); taosThreadMutexUnlock(&shard->mutex); @@ -545,7 +543,7 @@ static bool taosLRUCacheShardRelease(SLRUCacheShard *shard, LRUHandle *handle, b lastReference = taosLRUEntryUnref(e); if (lastReference && TAOS_LRU_ENTRY_IN_CACHE(e)) { if (shard->usage > shard->capacity || eraseIfLastRef) { - assert(shard->lru.next == &shard->lru || eraseIfLastRef); + ASSERT(shard->lru.next == &shard->lru || eraseIfLastRef); taosLRUEntryTableRemove(&shard->table, e->keyData, e->keyLength, e->hash); TAOS_LRU_ENTRY_SET_IN_CACHE(e, false); @@ -557,7 +555,7 @@ static bool taosLRUCacheShardRelease(SLRUCacheShard *shard, LRUHandle *handle, b } if (lastReference && e->value) { - assert(shard->usage >= e->totalCharge); + ASSERT(shard->usage >= e->totalCharge); shard->usage -= e->totalCharge; } @@ -580,12 +578,22 @@ static size_t taosLRUCacheShardGetUsage(SLRUCacheShard *shard) { return usage; } +static int32_t taosLRUCacheShardGetElems(SLRUCacheShard *shard) { + int32_t elems = 0; + + taosThreadMutexLock(&shard->mutex); + elems = shard->table.elems; + taosThreadMutexUnlock(&shard->mutex); + + return elems; +} + static size_t taosLRUCacheShardGetPinnedUsage(SLRUCacheShard *shard) { size_t usage = 0; taosThreadMutexLock(&shard->mutex); - assert(shard->usage >= shard->lruUsage); + ASSERT(shard->usage >= shard->lruUsage); usage = shard->usage - shard->lruUsage; taosThreadMutexUnlock(&shard->mutex); @@ -677,7 +685,7 @@ void taosLRUCacheCleanup(SLRUCache *cache) { if (cache) { if (cache->shards) { int numShards = cache->numShards; - assert(numShards > 0); + ASSERT(numShards > 0); for (int i = 0; i < numShards; ++i) { taosLRUCacheShardCleanup(&cache->shards[i]); } @@ -755,6 +763,16 @@ size_t taosLRUCacheGetUsage(SLRUCache *cache) { return usage; } +int32_t taosLRUCacheGetElems(SLRUCache *cache) { + int32_t elems = 0; + + for (int i = 0; i < cache->numShards; ++i) { + elems += taosLRUCacheShardGetElems(&cache->shards[i]); + } + + return elems; +} + size_t taosLRUCacheGetPinnedUsage(SLRUCache *cache) { size_t usage = 0; diff --git a/source/util/src/tpagedbuf.c b/source/util/src/tpagedbuf.c index 6bcf4ad39b729786e2d562d7a928b0a4965dc03d..fa8b5d33b7e8f45fe37d658f1ba336d21a43e5b4 100644 --- a/source/util/src/tpagedbuf.c +++ b/source/util/src/tpagedbuf.c @@ -55,7 +55,7 @@ static int32_t createDiskFile(SDiskbasedBuf* pBuf) { if (pBuf->path == NULL) { // prepare the file name when needed it char path[PATH_MAX] = {0}; taosGetTmpfilePath(pBuf->prefix, "paged-buf", path); - pBuf->path = taosMemoryStrDup(path); + pBuf->path = taosStrdup(path); if (pBuf->path == NULL) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -351,7 +351,7 @@ int32_t createDiskbasedBuf(SDiskbasedBuf** pBuf, int32_t pagesize, int32_t inMem pPBuf->totalBufSize = 0; pPBuf->allocateId = -1; pPBuf->pFile = NULL; - pPBuf->id = strdup(id); + pPBuf->id = taosStrdup(id); pPBuf->fileSize = 0; pPBuf->pFree = taosArrayInit(4, sizeof(SFreeListItem)); pPBuf->freePgList = tdListNew(POINTER_BYTES); @@ -391,7 +391,7 @@ _error: return TSDB_CODE_OUT_OF_MEMORY; } -static char* doExtractPage(SDiskbasedBuf* pBuf) { +static char* doExtractPage(SDiskbasedBuf* pBuf, bool* newPage) { char* availablePage = NULL; if (NO_IN_MEM_AVAILABLE_PAGES(pBuf)) { availablePage = evictBufPage(pBuf); @@ -405,6 +405,7 @@ static char* doExtractPage(SDiskbasedBuf* pBuf) { if (availablePage == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; } + *newPage = true; } return availablePage; @@ -413,7 +414,8 @@ static char* doExtractPage(SDiskbasedBuf* pBuf) { void* getNewBufPage(SDiskbasedBuf* pBuf, int32_t* pageId) { pBuf->statis.getPages += 1; - char* availablePage = doExtractPage(pBuf); + bool newPage = false; + char* availablePage = doExtractPage(pBuf, &newPage); if (availablePage == NULL) { return NULL; } @@ -432,6 +434,9 @@ void* getNewBufPage(SDiskbasedBuf* pBuf, int32_t* pageId) { // register page id info pi = registerNewPageInfo(pBuf, *pageId); if (pi == NULL) { + if (newPage) { + taosMemoryFree(availablePage); + } return NULL; } @@ -492,7 +497,8 @@ void* getBufPage(SDiskbasedBuf* pBuf, int32_t id) { ASSERT((!BUF_PAGE_IN_MEM(*pi)) && (*pi)->pn == NULL && (((*pi)->length >= 0 && (*pi)->offset >= 0) || ((*pi)->length == -1 && (*pi)->offset == -1))); - (*pi)->pData = doExtractPage(pBuf); + bool newPage = false; + (*pi)->pData = doExtractPage(pBuf, &newPage); // failed to evict buffer page, return with error code. if ((*pi)->pData == NULL) { @@ -509,6 +515,10 @@ void* getBufPage(SDiskbasedBuf* pBuf, int32_t id) { if (HAS_DATA_IN_DISK(*pi)) { int32_t code = loadPageFromDisk(pBuf, *pi); if (code != 0) { + if (newPage) { + taosMemoryFree((*pi)->pData); + } + terrno = code; return NULL; } diff --git a/source/util/src/tqueue.c b/source/util/src/tqueue.c index 42b63588930712d2e132fd7e8bf860aef3622ff9..3769da6ccd60a2fe4a6a949ae9b66e8a5a3e1486 100644 --- a/source/util/src/tqueue.c +++ b/source/util/src/tqueue.c @@ -339,7 +339,6 @@ void taosRemoveFromQset(STaosQset *qset, STaosQueue *queue) { STaosQueue *prev = qset->head; tqueue = qset->head->next; while (tqueue) { - assert(tqueue->qset); if (tqueue == queue) { prev->next = tqueue->next; break; diff --git a/source/util/src/trbtree.c b/source/util/src/trbtree.c index ffae5441aa088f2cc71710b301d5243cb3975235..e7386d5912dd83c5a76af3c902bcd910b5ffef87 100644 --- a/source/util/src/trbtree.c +++ b/source/util/src/trbtree.c @@ -147,6 +147,10 @@ static SRBTreeNode *tRBTreePredecessor(SRBTree *pTree, SRBTreeNode *pNode) { void tRBTreeCreate(SRBTree *pTree, tRBTreeCmprFn cmprFn) { pTree->cmprFn = cmprFn; + tRBTreeClear(pTree); +} + +void tRBTreeClear(SRBTree *pTree) { pTree->n = 0; pTree->NIL = &pTree->NILNODE; pTree->NIL->color = BLACK; @@ -423,6 +427,22 @@ SRBTreeNode *tRBTreeDropByKey(SRBTree *pTree, void *pKey) { return pNode; } +SRBTreeNode *tRBTreeDropMin(SRBTree *pTree) { + SRBTreeNode *pNode = tRBTreeMin(pTree); + if (pNode) { + tRBTreeDrop(pTree, pNode); + } + return pNode; +} + +SRBTreeNode *tRBTreeDropMax(SRBTree *pTree) { + SRBTreeNode *pNode = tRBTreeMax(pTree); + if (pNode) { + tRBTreeDrop(pTree, pNode); + } + return pNode; +} + SRBTreeNode *tRBTreeGet(SRBTree *pTree, const SRBTreeNode *pKeyNode) { SRBTreeNode *pNode = pTree->root; diff --git a/source/util/src/tsched.c b/source/util/src/tsched.c index 467f26b36275a84d64d89e1e00b5e901f9867307..5c1706e405565b6bab81c39eeceacf4fb4164514 100644 --- a/source/util/src/tsched.c +++ b/source/util/src/tsched.c @@ -137,7 +137,6 @@ void *taosProcessSchedQueue(void *scheduler) { while (1) { if ((ret = tsem_wait(&pSched->fullSem)) != 0) { uFatal("wait %s fullSem failed(%s)", pSched->label, strerror(errno)); - ASSERT(0); } if (atomic_load_8(&pSched->stop)) { break; @@ -145,7 +144,6 @@ void *taosProcessSchedQueue(void *scheduler) { if ((ret = taosThreadMutexLock(&pSched->queueMutex)) != 0) { uFatal("lock %s queueMutex failed(%s)", pSched->label, strerror(errno)); - ASSERT(0); } msg = pSched->queue[pSched->fullSlot]; @@ -154,12 +152,10 @@ void *taosProcessSchedQueue(void *scheduler) { if ((ret = taosThreadMutexUnlock(&pSched->queueMutex)) != 0) { uFatal("unlock %s queueMutex failed(%s)", pSched->label, strerror(errno)); - ASSERT(0); } if ((ret = tsem_post(&pSched->emptySem)) != 0) { uFatal("post %s emptySem failed(%s)", pSched->label, strerror(errno)); - ASSERT(0); } if (msg.fp) @@ -187,12 +183,10 @@ int taosScheduleTask(void *queueScheduler, SSchedMsg *pMsg) { if ((ret = tsem_wait(&pSched->emptySem)) != 0) { uFatal("wait %s emptySem failed(%s)", pSched->label, strerror(errno)); - ASSERT(0); } if ((ret = taosThreadMutexLock(&pSched->queueMutex)) != 0) { uFatal("lock %s queueMutex failed(%s)", pSched->label, strerror(errno)); - ASSERT(0); } pSched->queue[pSched->emptySlot] = *pMsg; @@ -200,12 +194,10 @@ int taosScheduleTask(void *queueScheduler, SSchedMsg *pMsg) { if ((ret = taosThreadMutexUnlock(&pSched->queueMutex)) != 0) { uFatal("unlock %s queueMutex failed(%s)", pSched->label, strerror(errno)); - ASSERT(0); } if ((ret = tsem_post(&pSched->fullSem)) != 0) { uFatal("post %s fullSem failed(%s)", pSched->label, strerror(errno)); - ASSERT(0); } return ret; } diff --git a/source/util/src/tsimplehash.c b/source/util/src/tsimplehash.c index 70acffed5d62fb0b13fd02ff719b0aab577ae76c..4c7983a9838b93769f9f46aadf1948ae817195ee 100644 --- a/source/util/src/tsimplehash.c +++ b/source/util/src/tsimplehash.c @@ -28,19 +28,23 @@ #define HASH_INDEX(v, c) ((v) & ((c)-1)) -#define FREE_HASH_NODE(_n) \ - do { \ - taosMemoryFreeClear(_n); \ +#define FREE_HASH_NODE(_n, fp) \ + do { \ + if (fp) { \ + fp((_n)->data); \ + } \ + taosMemoryFreeClear(_n); \ } while (0); struct SSHashObj { - SHNode **hashList; - size_t capacity; // number of slots - int64_t size; // number of elements in hash table - _hash_fn_t hashFp; // hash function - _equal_fn_t equalFp; // equal function - SArray* pHashNodeBuf;// hash node allocation buffer, 1k size of each page by default - int32_t offset; // allocation offset in current page + SHNode **hashList; + size_t capacity; // number of slots + int64_t size; // number of elements in hash table + _hash_fn_t hashFp; // hash function + _equal_fn_t equalFp; // equal function + _hash_free_fn_t freeFp; // free function + SArray *pHashNodeBuf; // hash node allocation buffer, 1k size of each page by default + int32_t offset; // allocation offset in current page }; static FORCE_INLINE int32_t taosHashCapacity(int32_t length) { @@ -71,7 +75,7 @@ SSHashObj *tSimpleHashInit(size_t capacity, _hash_fn_t fn) { pHashObj->capacity = taosHashCapacity((int32_t)capacity); pHashObj->equalFp = memcmp; - pHashObj->pHashNodeBuf = taosArrayInit(10, sizeof(void*)); + pHashObj->freeFp = NULL; pHashObj->offset = 0; pHashObj->size = 0; @@ -92,6 +96,10 @@ int32_t tSimpleHashGetSize(const SSHashObj *pHashObj) { return (int32_t) pHashObj->size; } +void tSimpleHashSetFreeFp(SSHashObj* pHashObj, _hash_free_fn_t freeFp) { + pHashObj->freeFp = freeFp; +} + static void* doInternalAlloc(SSHashObj* pHashObj, int32_t size) { #if 0 void** p = taosArrayGetLast(pHashObj->pHashNodeBuf); @@ -306,7 +314,8 @@ int32_t tSimpleHashRemove(SSHashObj *pHashObj, const void *key, size_t keyLen) { } else { pPrev->next = pNode->next; } - FREE_HASH_NODE(pNode); + + FREE_HASH_NODE(pNode, pHashObj->freeFp); pHashObj->size -= 1; code = TSDB_CODE_SUCCESS; break; @@ -341,7 +350,7 @@ int32_t tSimpleHashIterateRemove(SSHashObj *pHashObj, const void *key, size_t ke *pIter = pPrev ? GET_SHASH_NODE_DATA(pPrev) : NULL; } - FREE_HASH_NODE(pNode); + FREE_HASH_NODE(pNode, pHashObj->freeFp); pHashObj->size -= 1; break; } @@ -352,10 +361,6 @@ int32_t tSimpleHashIterateRemove(SSHashObj *pHashObj, const void *key, size_t ke return TSDB_CODE_SUCCESS; } -static void destroyItems(void* pItem) { - taosMemoryFree(*(void**)pItem); -} - void tSimpleHashClear(SSHashObj *pHashObj) { if (!pHashObj || taosHashTableEmpty(pHashObj)) { return; @@ -370,14 +375,13 @@ void tSimpleHashClear(SSHashObj *pHashObj) { while (pNode) { pNext = pNode->next; - FREE_HASH_NODE(pNode); + FREE_HASH_NODE(pNode, pHashObj->freeFp); pNode = pNext; } pHashObj->hashList[i] = NULL; } - taosArrayClearEx(pHashObj->pHashNodeBuf, destroyItems); pHashObj->offset = 0; pHashObj->size = 0; } @@ -388,7 +392,6 @@ void tSimpleHashCleanup(SSHashObj *pHashObj) { } tSimpleHashClear(pHashObj); - taosArrayDestroy(pHashObj->pHashNodeBuf); taosMemoryFreeClear(pHashObj->hashList); taosMemoryFree(pHashObj); } diff --git a/source/util/src/tskiplist.c b/source/util/src/tskiplist.c index c72c5c70ae6edf397d59741b260d2aced20bdf6f..222e0e8a51e019d76f2de71a79423fcfe7b3fa65 100644 --- a/source/util/src/tskiplist.c +++ b/source/util/src/tskiplist.c @@ -268,8 +268,9 @@ SSkipListIterator *tSkipListCreateIter(SSkipList *pSkipList) { } SSkipListIterator *tSkipListCreateIterFromVal(SSkipList *pSkipList, const char *val, int32_t type, int32_t order) { - ASSERT(order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC); - ASSERT(pSkipList != NULL); + if (order != TSDB_ORDER_ASC && order != TSDB_ORDER_DESC) { + return NULL; + } SSkipListIterator *iter = doCreateSkipListIterator(pSkipList, order); if (val == NULL) { @@ -585,7 +586,6 @@ static FORCE_INLINE int32_t getSkipListRandLevel(SSkipList *pSkipList) { } } - ASSERT(level <= pSkipList->maxLevel); return level; } diff --git a/source/util/src/tutil.c b/source/util/src/tutil.c index 55d7d4f6e7dc850e13b362289b545f57b65b5bbd..6d95660103e2c78203e7531af927e8d59ae4c358 100644 --- a/source/util/src/tutil.c +++ b/source/util/src/tutil.c @@ -118,7 +118,7 @@ char **strsplit(char *z, const char *delim, int32_t *num) { if ((*num) >= size) { size = (size << 1); split = taosMemoryRealloc(split, POINTER_BYTES * size); - ASSERTS(NULL != split, "realloc memory failed. size=%d", POINTER_BYTES * size); + ASSERTS(NULL != split, "realloc memory failed. size=%d", (int32_t) POINTER_BYTES * size); } } @@ -468,7 +468,7 @@ size_t tstrncspn(const char *str, size_t size, const char *reject, size_t rsize) c3 = p[s[j + 3]]; if ((c0 | c1 | c2 | c3) != 0) { - size_t count = ((i + 1) >> 2); + size_t count = i * 4; return (c0 | c1) != 0 ? count - c0 + 1 : count - c2 + 3; } } diff --git a/source/util/src/tversion.c b/source/util/src/tversion.c index c70fdc87a6363b1a9fd08bddef3e1b3d0439162e..0f84f6bafa99464f98fea3e064ac9fb94076ffc0 100644 --- a/source/util/src/tversion.c +++ b/source/util/src/tversion.c @@ -26,8 +26,9 @@ int32_t taosVersionStrToInt(const char *vstr, int32_t *vint) { int32_t vnum[4] = {0}; int32_t len = strlen(vstr); char tmp[16] = {0}; + int32_t vpos = 0; - for (int32_t spos = 0, tpos = 0, vpos = 0; spos < len && vpos < 4; ++spos) { + for (int32_t spos = 0, tpos = 0; spos < len && vpos < 4; ++spos) { if (vstr[spos] != '.') { tmp[spos - tpos] = vstr[spos]; } else { @@ -38,6 +39,10 @@ int32_t taosVersionStrToInt(const char *vstr, int32_t *vint) { } } + if ('\0' != tmp[0] && vpos < 4) { + vnum[vpos] = atoi(tmp); + } + if (vnum[0] <= 0) { terrno = TSDB_CODE_INVALID_VERSION_STRING; return -1; @@ -66,16 +71,16 @@ int32_t taosCheckVersionCompatible(int32_t clientVer, int32_t serverVer, int32_t case 4: break; case 3: - clientVer %= 100; - serverVer %= 100; + clientVer /= 100; + serverVer /= 100; break; case 2: - clientVer %= 10000; - serverVer %= 10000; + clientVer /= 10000; + serverVer /= 10000; break; case 1: - clientVer %= 1000000; - serverVer %= 1000000; + clientVer /= 1000000; + serverVer /= 1000000; break; default: terrno = TSDB_CODE_INVALID_VERSION_NUMBER; @@ -89,3 +94,20 @@ int32_t taosCheckVersionCompatible(int32_t clientVer, int32_t serverVer, int32_t return -1; } } + +int32_t taosCheckVersionCompatibleFromStr(const char *pClientVersion, const char *pServerVersion, + int32_t comparedSegments) { + int32_t clientVersion = 0; + int32_t serverVersion = 0; + int32_t code = taosVersionStrToInt(pClientVersion, &clientVersion); + if (TSDB_CODE_SUCCESS == code) { + code = taosVersionStrToInt(pServerVersion, &serverVersion); + } + if (TSDB_CODE_SUCCESS == code) { + code = taosCheckVersionCompatible(clientVersion, serverVersion, comparedSegments); + } + if (TSDB_CODE_SUCCESS != code) { + code = terrno; + } + return code; +} \ No newline at end of file diff --git a/source/util/src/tworker.c b/source/util/src/tworker.c index 5581931178486ba05f36640edcf7500477cbc96c..6edee27c052d474355812a4b46d53331a5ab6324 100644 --- a/source/util/src/tworker.c +++ b/source/util/src/tworker.c @@ -22,7 +22,7 @@ typedef void *(*ThreadFp)(void *param); int32_t tQWorkerInit(SQWorkerPool *pool) { pool->qset = taosOpenQset(); - pool->workers = taosMemoryCalloc(pool->max, sizeof(SQWorker)); + pool->workers = taosMemoryCalloc(pool->max, sizeof(SQueueWorker)); if (pool->workers == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -31,7 +31,7 @@ int32_t tQWorkerInit(SQWorkerPool *pool) { (void)taosThreadMutexInit(&pool->mutex, NULL); for (int32_t i = 0; i < pool->max; ++i) { - SQWorker *worker = pool->workers + i; + SQueueWorker *worker = pool->workers + i; worker->id = i; worker->pool = pool; } @@ -42,14 +42,14 @@ int32_t tQWorkerInit(SQWorkerPool *pool) { void tQWorkerCleanup(SQWorkerPool *pool) { for (int32_t i = 0; i < pool->max; ++i) { - SQWorker *worker = pool->workers + i; + SQueueWorker *worker = pool->workers + i; if (taosCheckPthreadValid(worker->thread)) { taosQsetThreadResume(pool->qset); } } for (int32_t i = 0; i < pool->max; ++i) { - SQWorker *worker = pool->workers + i; + SQueueWorker *worker = pool->workers + i; if (taosCheckPthreadValid(worker->thread)) { uInfo("worker:%s:%d is stopping", pool->name, worker->id); taosThreadJoin(worker->thread, NULL); @@ -65,7 +65,7 @@ void tQWorkerCleanup(SQWorkerPool *pool) { uInfo("worker:%s is closed", pool->name); } -static void *tQWorkerThreadFp(SQWorker *worker) { +static void *tQWorkerThreadFp(SQueueWorker *worker) { SQWorkerPool *pool = worker->pool; SQueueInfo qinfo = {0}; void *msg = NULL; @@ -106,7 +106,7 @@ STaosQueue *tQWorkerAllocQueue(SQWorkerPool *pool, void *ahandle, FItem fp) { // spawn a thread to process queue if (pool->num < pool->max) { do { - SQWorker *worker = pool->workers + pool->num; + SQueueWorker *worker = pool->workers + pool->num; TdThreadAttr thAttr; taosThreadAttrInit(&thAttr); @@ -138,7 +138,7 @@ void tQWorkerFreeQueue(SQWorkerPool *pool, STaosQueue *queue) { int32_t tAutoQWorkerInit(SAutoQWorkerPool *pool) { pool->qset = taosOpenQset(); - pool->workers = taosArrayInit(2, sizeof(SQWorker *)); + pool->workers = taosArrayInit(2, sizeof(SQueueWorker *)); if (pool->workers == NULL) { terrno = TSDB_CODE_OUT_OF_MEMORY; return -1; @@ -153,14 +153,14 @@ int32_t tAutoQWorkerInit(SAutoQWorkerPool *pool) { void tAutoQWorkerCleanup(SAutoQWorkerPool *pool) { int32_t size = taosArrayGetSize(pool->workers); for (int32_t i = 0; i < size; ++i) { - SQWorker *worker = taosArrayGetP(pool->workers, i); + SQueueWorker *worker = taosArrayGetP(pool->workers, i); if (taosCheckPthreadValid(worker->thread)) { taosQsetThreadResume(pool->qset); } } for (int32_t i = 0; i < size; ++i) { - SQWorker *worker = taosArrayGetP(pool->workers, i); + SQueueWorker *worker = taosArrayGetP(pool->workers, i); if (taosCheckPthreadValid(worker->thread)) { uInfo("worker:%s:%d is stopping", pool->name, worker->id); taosThreadJoin(worker->thread, NULL); @@ -177,7 +177,7 @@ void tAutoQWorkerCleanup(SAutoQWorkerPool *pool) { uInfo("worker:%s is closed", pool->name); } -static void *tAutoQWorkerThreadFp(SQWorker *worker) { +static void *tAutoQWorkerThreadFp(SQueueWorker *worker) { SAutoQWorkerPool *pool = worker->pool; SQueueInfo qinfo = {0}; void *msg = NULL; @@ -217,12 +217,12 @@ STaosQueue *tAutoQWorkerAllocQueue(SAutoQWorkerPool *pool, void *ahandle, FItem int32_t queueNum = taosGetQueueNumber(pool->qset); int32_t curWorkerNum = taosArrayGetSize(pool->workers); - int32_t dstWorkerNum = ceil(queueNum * pool->ratio); + int32_t dstWorkerNum = ceilf(queueNum * pool->ratio); if (dstWorkerNum < 1) dstWorkerNum = 1; // spawn a thread to process queue while (curWorkerNum < dstWorkerNum) { - SQWorker *worker = taosMemoryCalloc(1, sizeof(SQWorker)); + SQueueWorker *worker = taosMemoryCalloc(1, sizeof(SQueueWorker)); if (worker == NULL || taosArrayPush(pool->workers, &worker) == NULL) { uError("worker:%s:%d failed to create", pool->name, curWorkerNum); taosMemoryFree(worker); @@ -248,7 +248,8 @@ STaosQueue *tAutoQWorkerAllocQueue(SAutoQWorkerPool *pool, void *ahandle, FItem } taosThreadAttrDestroy(&thAttr); - uInfo("worker:%s:%d is launched, total:%d", pool->name, worker->id, (int32_t)taosArrayGetSize(pool->workers)); + int32_t numOfThreads = taosArrayGetSize(pool->workers); + uInfo("worker:%s:%d is launched, total:%d, expect:%d", pool->name, worker->id, numOfThreads, dstWorkerNum); curWorkerNum++; } diff --git a/source/util/src/version.c.in b/source/util/src/version.c.in index cb307b57fce37ba4243aea83995e66612f3c4371..71998e3321e79c08e0885ac09463c0ef05b4a6fa 100644 --- a/source/util/src/version.c.in +++ b/source/util/src/version.c.in @@ -1,6 +1,7 @@ char version[64] = "${TD_VER_NUMBER}"; char compatible_version[12] = "${TD_VER_COMPATIBLE}"; char gitinfo[48] = "${TD_VER_GIT}"; +char gitinfoOfInternal[48] = "${TD_VER_GIT_INTERNAL}"; char buildinfo[64] = "Built at ${TD_VER_DATE}"; void libtaos_${TD_LIB_VER_NUMBER}_${TD_VER_OSTYPE}_${TD_VER_CPUTYPE}_${TD_VER_VERTYPE}() {}; diff --git a/source/util/src/xxhash.c b/source/util/src/xxhash.c deleted file mode 100644 index ff28749e316434a13123667848e6692e35bfb059..0000000000000000000000000000000000000000 --- a/source/util/src/xxhash.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* -* xxHash - Fast Hash algorithm -* Copyright (C) 2012-2016, Yann Collet -* -* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following disclaimer -* in the documentation and/or other materials provided with the -* distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* You can contact the author at : -* - xxHash homepage: http://www.xxhash.com -* - xxHash source repository : https://github.com/Cyan4973/xxHash -*/ - - -/* ************************************* -* Tuning parameters -***************************************/ -/*!XXH_FORCE_MEMORY_ACCESS : - * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. - * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. - * The below switch allow to select different access method for improved performance. - * Method 0 (default) : use `memcpy()`. Safe and portable. - * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). - * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. - * Method 2 : direct access. This method doesn't depend on compiler but violate C standard. - * It can generate buggy code on targets which do not support unaligned memory accesses. - * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) - * See http://stackoverflow.com/a/32095106/646947 for details. - * Prefer these methods in priority order (0 > 1 > 2) - */ -#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ -# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ - || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ - || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) -# define XXH_FORCE_MEMORY_ACCESS 2 -# elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || \ - (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ - || defined(__ARM_ARCH_7S__) )) -# define XXH_FORCE_MEMORY_ACCESS 1 -# endif -#endif - -/*!XXH_ACCEPT_NULL_INPUT_POINTER : - * If input pointer is NULL, xxHash default behavior is to dereference it, triggering a segfault. - * When this macro is enabled, xxHash actively checks input for null pointer. - * It it is, result for null input pointers is the same as a null-length input. - */ -#ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */ -# define XXH_ACCEPT_NULL_INPUT_POINTER 0 -#endif - -/*!XXH_FORCE_NATIVE_FORMAT : - * By default, xxHash library provides endian-independent Hash values, based on little-endian convention. - * Results are therefore identical for little-endian and big-endian CPU. - * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. - * Should endian-independence be of no importance for your application, you may set the #define below to 1, - * to improve speed for Big-endian CPU. - * This option has no impact on Little_Endian CPU. - */ -#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */ -# define XXH_FORCE_NATIVE_FORMAT 0 -#endif - -/*!XXH_FORCE_ALIGN_CHECK : - * This is a minor performance trick, only useful with lots of very small keys. - * It means : check for aligned/unaligned input. - * The check costs one initial branch per hash; - * set it to 0 when the input is guaranteed to be aligned, - * or when alignment doesn't matter for performance. - */ -#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ -# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) -# define XXH_FORCE_ALIGN_CHECK 0 -# else -# define XXH_FORCE_ALIGN_CHECK 1 -# endif -#endif - - -/* ************************************* -* Includes & Memory related functions -***************************************/ -/*! Modify the local functions below should you wish to use some other memory routines -* for malloc(), free() */ -#include -static void* XXH_malloc(size_t s) { return malloc(s); } -static void XXH_free (void* p) { free(p); } -/*! and for memcpy() */ -#include -static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } - -#include /* assert */ - -#define XXH_STATIC_LINKING_ONLY -#include "xxhash.h" - - -/* ************************************* -* Compiler Specific Options -***************************************/ -#ifdef _MSC_VER /* Visual Studio */ -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -# define FORCE_INLINE static __forceinline -#else -# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -# ifdef __GNUC__ -# define FORCE_INLINE static inline __attribute__((always_inline)) -# else -# define FORCE_INLINE static inline -# endif -# else -# define FORCE_INLINE static -# endif /* __STDC_VERSION__ */ -#endif - - -/* ************************************* -* Basic Types -***************************************/ -#ifndef MEM_MODULE -# if !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint8_t BYTE; - typedef uint16_t U16; - typedef uint32_t U32; -# else - typedef unsigned char BYTE; - typedef unsigned short U16; - typedef unsigned int U32; -# endif -#endif - -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) - -/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ -static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; } - -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) - -/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ -/* currently only defined for gcc and icc */ -typedef union { U32 u32; } __attribute__((packed)) unalign; -static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } - -#else - -/* portable and safe solution. Generally efficient. - * see : http://stackoverflow.com/a/32095106/646947 - */ -static U32 XXH_read32(const void* memPtr) -{ - U32 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ - - -/* **************************************** -* Compiler-specific Functions and Macros -******************************************/ -#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) - -/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ -#if defined(_MSC_VER) -# define XXH_rotl32(x,r) _rotl(x,r) -# define XXH_rotl64(x,r) _rotl64(x,r) -#else -# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) -# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) -#endif - -#if defined(_MSC_VER) /* Visual Studio */ -# define XXH_swap32 _byteswap_ulong -#elif XXH_GCC_VERSION >= 403 -# define XXH_swap32 __builtin_bswap32 -#else -static U32 XXH_swap32 (U32 x) -{ - return ((x << 24) & 0xff000000 ) | - ((x << 8) & 0x00ff0000 ) | - ((x >> 8) & 0x0000ff00 ) | - ((x >> 24) & 0x000000ff ); -} -#endif - - -/* ************************************* -* Architecture Macros -***************************************/ -typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; - -/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ -#ifndef XXH_CPU_LITTLE_ENDIAN -static int XXH_isLittleEndian(void) -{ - const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ - return one.c[0]; -} -# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() -#endif - - -/* *************************** -* Memory reads -*****************************/ -typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; - -FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align==XXH_unaligned) - return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); - else - return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr); -} - -FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE32_align(ptr, endian, XXH_unaligned); -} - -static U32 XXH_readBE32(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); -} - - -/* ************************************* -* Macros -***************************************/ -#define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1/(int)(!!(c)) }; } /* use after variable declarations */ -XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } - - -/* ******************************************************************* -* 32-bit hash functions -*********************************************************************/ -static const U32 PRIME32_1 = 2654435761U; -static const U32 PRIME32_2 = 2246822519U; -static const U32 PRIME32_3 = 3266489917U; -static const U32 PRIME32_4 = 668265263U; -static const U32 PRIME32_5 = 374761393U; - -static U32 XXH32_round(U32 seed, U32 input) -{ - seed += input * PRIME32_2; - seed = XXH_rotl32(seed, 13); - seed *= PRIME32_1; - return seed; -} - -/* mix all bits */ -static U32 XXH32_avalanche(U32 h32) -{ - h32 ^= h32 >> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - return(h32); -} - -#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) - -static U32 -XXH32_finalize(U32 h32, const void* ptr, size_t len, - XXH_endianess endian, XXH_alignment align) - -{ - const BYTE* p = (const BYTE*)ptr; - -#define PROCESS1 \ - h32 += (*p++) * PRIME32_5; \ - h32 = XXH_rotl32(h32, 11) * PRIME32_1 ; - -#define PROCESS4 \ - h32 += XXH_get32bits(p) * PRIME32_3; \ - p+=4; \ - h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; - - switch(len&15) /* or switch(bEnd - p) */ - { - case 12: PROCESS4; - /* fallthrough */ - case 8: PROCESS4; - /* fallthrough */ - case 4: PROCESS4; - return XXH32_avalanche(h32); - - case 13: PROCESS4; - /* fallthrough */ - case 9: PROCESS4; - /* fallthrough */ - case 5: PROCESS4; - PROCESS1; - return XXH32_avalanche(h32); - - case 14: PROCESS4; - /* fallthrough */ - case 10: PROCESS4; - /* fallthrough */ - case 6: PROCESS4; - PROCESS1; - PROCESS1; - return XXH32_avalanche(h32); - - case 15: PROCESS4; - /* fallthrough */ - case 11: PROCESS4; - /* fallthrough */ - case 7: PROCESS4; - /* fallthrough */ - case 3: PROCESS1; - /* fallthrough */ - case 2: PROCESS1; - /* fallthrough */ - case 1: PROCESS1; - /* fallthrough */ - case 0: return XXH32_avalanche(h32); - } - assert(0); - return h32; /* reaching this point is deemed impossible */ -} - - -FORCE_INLINE U32 -XXH32_endian_align(const void* input, size_t len, U32 seed, - XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* bEnd = p + len; - U32 h32; - -#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) - if (p==NULL) { - len=0; - bEnd=p=(const BYTE*)(size_t)16; - } -#endif - - if (len>=16) { - const BYTE* const limit = bEnd - 15; - U32 v1 = seed + PRIME32_1 + PRIME32_2; - U32 v2 = seed + PRIME32_2; - U32 v3 = seed + 0; - U32 v4 = seed - PRIME32_1; - - do { - v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4; - v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4; - v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4; - v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4; - } while (p < limit); - - h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) - + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); - } else { - h32 = seed + PRIME32_5; - } - - h32 += (U32)len; - - return XXH32_finalize(h32, p, len&15, endian, align); -} - - -XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH32_state_t state; - XXH32_reset(&state, seed); - XXH32_update(&state, input, len); - return XXH32_digest(&state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } } - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - - - -/*====== Hash streaming ======*/ - -XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) -{ - return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); -} -XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - -XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) -{ - XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)); - state.v1 = seed + PRIME32_1 + PRIME32_2; - state.v2 = seed + PRIME32_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME32_1; - /* do not write into reserved, planned to be removed in a future version */ - memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); - return XXH_OK; -} - - -FORCE_INLINE XXH_errorcode -XXH32_update_endian(XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian) -{ - if (input==NULL) -#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) - return XXH_OK; -#else - return XXH_ERROR; -#endif - - { const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - - state->total_len_32 += (unsigned)len; - state->large_len |= (len>=16) | (state->total_len_32>=16); - - if (state->memsize + len < 16) { /* fill in tmp buffer */ - XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len); - state->memsize += (unsigned)len; - return XXH_OK; - } - - if (state->memsize) { /* some data left from previous update */ - XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize); - { const U32* p32 = state->mem32; - state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++; - state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++; - state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++; - state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); - } - p += 16-state->memsize; - state->memsize = 0; - } - - if (p <= bEnd-16) { - const BYTE* const limit = bEnd - 16; - U32 v1 = state->v1; - U32 v2 = state->v2; - U32 v3 = state->v3; - U32 v4 = state->v4; - - do { - v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4; - v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4; - v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4; - v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4; - } while (p<=limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) { - XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - } - - return XXH_OK; -} - - -XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH32_update_endian(state_in, input, len, XXH_bigEndian); -} - - -FORCE_INLINE U32 -XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian) -{ - U32 h32; - - if (state->large_len) { - h32 = XXH_rotl32(state->v1, 1) - + XXH_rotl32(state->v2, 7) - + XXH_rotl32(state->v3, 12) - + XXH_rotl32(state->v4, 18); - } else { - h32 = state->v3 /* == seed */ + PRIME32_5; - } - - h32 += state->total_len_32; - - return XXH32_finalize(h32, state->mem32, state->memsize, endian, XXH_aligned); -} - - -XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_digest_endian(state_in, XXH_littleEndian); - else - return XXH32_digest_endian(state_in, XXH_bigEndian); -} - - -/*====== Canonical representation ======*/ - -/*! Default XXH result types are basic unsigned 32 and 64 bits. -* The canonical representation follows human-readable write convention, aka big-endian (large digits first). -* These functions allow transformation of hash result into and from its canonical format. -* This way, hash values can be written into a file or buffer, remaining comparable across different systems. -*/ - -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); - memcpy(dst, &hash, sizeof(*dst)); -} - -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) -{ - return XXH_readBE32(src); -} - - -#ifndef XXH_NO_LONG_LONG - -/* ******************************************************************* -* 64-bit hash functions -*********************************************************************/ - -/*====== Memory access ======*/ - -#ifndef MEM_MODULE -# define MEM_MODULE -# if !defined (__VMS) \ - && (defined (__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include - typedef uint64_t U64; -# else - /* if compiler doesn't support unsigned long long, replace by another 64-bit type */ - typedef unsigned long long U64; -# endif -#endif - - -#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) - -/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ -static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; } - -#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) - -/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ -/* currently only defined for gcc and icc */ -typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign64; -static U64 XXH_read64(const void* ptr) { return ((const unalign64*)ptr)->u64; } - -#else - -/* portable and safe solution. Generally efficient. - * see : http://stackoverflow.com/a/32095106/646947 - */ - -static U64 XXH_read64(const void* memPtr) -{ - U64 val; - memcpy(&val, memPtr, sizeof(val)); - return val; -} - -#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ - -#if defined(_MSC_VER) /* Visual Studio */ -# define XXH_swap64 _byteswap_uint64 -#elif XXH_GCC_VERSION >= 403 -# define XXH_swap64 __builtin_bswap64 -#else -static U64 XXH_swap64 (U64 x) -{ - return ((x << 56) & 0xff00000000000000ULL) | - ((x << 40) & 0x00ff000000000000ULL) | - ((x << 24) & 0x0000ff0000000000ULL) | - ((x << 8) & 0x000000ff00000000ULL) | - ((x >> 8) & 0x00000000ff000000ULL) | - ((x >> 24) & 0x0000000000ff0000ULL) | - ((x >> 40) & 0x000000000000ff00ULL) | - ((x >> 56) & 0x00000000000000ffULL); -} -#endif - -FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - if (align==XXH_unaligned) - return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); - else - return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr); -} - -FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE64_align(ptr, endian, XXH_unaligned); -} - -static U64 XXH_readBE64(const void* ptr) -{ - return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); -} - - -/*====== xxh64 ======*/ - -static const U64 PRIME64_1 = 11400714785074694791ULL; -static const U64 PRIME64_2 = 14029467366897019727ULL; -static const U64 PRIME64_3 = 1609587929392839161ULL; -static const U64 PRIME64_4 = 9650029242287828579ULL; -static const U64 PRIME64_5 = 2870177450012600261ULL; - -static U64 XXH64_round(U64 acc, U64 input) -{ - acc += input * PRIME64_2; - acc = XXH_rotl64(acc, 31); - acc *= PRIME64_1; - return acc; -} - -static U64 XXH64_mergeRound(U64 acc, U64 val) -{ - val = XXH64_round(0, val); - acc ^= val; - acc = acc * PRIME64_1 + PRIME64_4; - return acc; -} - -static U64 XXH64_avalanche(U64 h64) -{ - h64 ^= h64 >> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - return h64; -} - - -#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) - -static U64 -XXH64_finalize(U64 h64, const void* ptr, size_t len, - XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)ptr; - -#define PROCESS1_64 \ - h64 ^= (*p++) * PRIME64_5; \ - h64 = XXH_rotl64(h64, 11) * PRIME64_1; - -#define PROCESS4_64 \ - h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; \ - p+=4; \ - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - -#define PROCESS8_64 { \ - U64 const k1 = XXH64_round(0, XXH_get64bits(p)); \ - p+=8; \ - h64 ^= k1; \ - h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; \ -} - - switch(len&31) { - case 24: PROCESS8_64; - /* fallthrough */ - case 16: PROCESS8_64; - /* fallthrough */ - case 8: PROCESS8_64; - return XXH64_avalanche(h64); - - case 28: PROCESS8_64; - /* fallthrough */ - case 20: PROCESS8_64; - /* fallthrough */ - case 12: PROCESS8_64; - /* fallthrough */ - case 4: PROCESS4_64; - return XXH64_avalanche(h64); - - case 25: PROCESS8_64; - /* fallthrough */ - case 17: PROCESS8_64; - /* fallthrough */ - case 9: PROCESS8_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 29: PROCESS8_64; - /* fallthrough */ - case 21: PROCESS8_64; - /* fallthrough */ - case 13: PROCESS8_64; - /* fallthrough */ - case 5: PROCESS4_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 26: PROCESS8_64; - /* fallthrough */ - case 18: PROCESS8_64; - /* fallthrough */ - case 10: PROCESS8_64; - PROCESS1_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 30: PROCESS8_64; - /* fallthrough */ - case 22: PROCESS8_64; - /* fallthrough */ - case 14: PROCESS8_64; - /* fallthrough */ - case 6: PROCESS4_64; - PROCESS1_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 27: PROCESS8_64; - /* fallthrough */ - case 19: PROCESS8_64; - /* fallthrough */ - case 11: PROCESS8_64; - PROCESS1_64; - PROCESS1_64; - PROCESS1_64; - return XXH64_avalanche(h64); - - case 31: PROCESS8_64; - /* fallthrough */ - case 23: PROCESS8_64; - /* fallthrough */ - case 15: PROCESS8_64; - /* fallthrough */ - case 7: PROCESS4_64; - /* fallthrough */ - case 3: PROCESS1_64; - /* fallthrough */ - case 2: PROCESS1_64; - /* fallthrough */ - case 1: PROCESS1_64; - /* fallthrough */ - case 0: return XXH64_avalanche(h64); - } - - /* impossible to reach */ - assert(0); - return 0; /* unreachable, but some compilers complain without it */ -} - -FORCE_INLINE U64 -XXH64_endian_align(const void* input, size_t len, U64 seed, - XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* bEnd = p + len; - U64 h64; - -#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) - if (p==NULL) { - len=0; - bEnd=p=(const BYTE*)(size_t)32; - } -#endif - - if (len>=32) { - const BYTE* const limit = bEnd - 32; - U64 v1 = seed + PRIME64_1 + PRIME64_2; - U64 v2 = seed + PRIME64_2; - U64 v3 = seed + 0; - U64 v4 = seed - PRIME64_1; - - do { - v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8; - v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8; - v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8; - v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8; - } while (p<=limit); - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - - } else { - h64 = seed + PRIME64_5; - } - - h64 += (U64) len; - - return XXH64_finalize(h64, p, len, endian, align); -} - - -XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH64_state_t state; - XXH64_reset(&state, seed); - XXH64_update(&state, input, len); - return XXH64_digest(&state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } } - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - -/*====== Hash Streaming ======*/ - -XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) -{ - return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); -} -XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) -{ - XXH_free(statePtr); - return XXH_OK; -} - -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - -XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) -{ - XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)); - state.v1 = seed + PRIME64_1 + PRIME64_2; - state.v2 = seed + PRIME64_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME64_1; - /* do not write into reserved, planned to be removed in a future version */ - memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); - return XXH_OK; -} - -FORCE_INLINE XXH_errorcode -XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian) -{ - if (input==NULL) -#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) - return XXH_OK; -#else - return XXH_ERROR; -#endif - - { const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - - state->total_len += len; - - if (state->memsize + len < 32) { /* fill in tmp buffer */ - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); - state->memsize += (U32)len; - return XXH_OK; - } - - if (state->memsize) { /* tmp buffer is full */ - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize); - state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian)); - state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian)); - state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian)); - state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian)); - p += 32-state->memsize; - state->memsize = 0; - } - - if (p+32 <= bEnd) { - const BYTE* const limit = bEnd - 32; - U64 v1 = state->v1; - U64 v2 = state->v2; - U64 v3 = state->v3; - U64 v4 = state->v4; - - do { - v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8; - v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8; - v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8; - v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8; - } while (p<=limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) { - XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - } - - return XXH_OK; -} - -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH64_update_endian(state_in, input, len, XXH_bigEndian); -} - -FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian) -{ - U64 h64; - - if (state->total_len >= 32) { - U64 const v1 = state->v1; - U64 const v2 = state->v2; - U64 const v3 = state->v3; - U64 const v4 = state->v4; - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - } else { - h64 = state->v3 /*seed*/ + PRIME64_5; - } - - h64 += (U64) state->total_len; - - return XXH64_finalize(h64, state->mem64, (size_t)state->total_len, endian, XXH_aligned); -} - -XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_digest_endian(state_in, XXH_littleEndian); - else - return XXH64_digest_endian(state_in, XXH_bigEndian); -} - - -/*====== Canonical representation ======*/ - -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); - if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); - memcpy(dst, &hash, sizeof(*dst)); -} - -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) -{ - return XXH_readBE64(src); -} - -#endif /* XXH_NO_LONG_LONG */ diff --git a/source/util/test/utilTests.cpp b/source/util/test/utilTests.cpp index a35512541089863b66bb69dc95f8ad95504b847e..ff1d91aa9de72bd024520a859f16822078a74ef1 100644 --- a/source/util/test/utilTests.cpp +++ b/source/util/test/utilTests.cpp @@ -294,6 +294,10 @@ TEST(utilTest, tstrncspn) { const char* reject5 = "911"; v = tstrncspn(p2, strlen(p2), reject5, 0); ASSERT_EQ(v, 14); + + const char* reject6 = "Kk"; + v = tstrncspn(p2, strlen(p2), reject6, 2); + ASSERT_EQ(v, 10); } TEST(utilTest, intToHextStr) { @@ -322,4 +326,4 @@ TEST(utilTest, intToHextStr) { sprintf(destBuf, "%" PRIx64, v); ASSERT_STREQ(buf, destBuf); } -} \ No newline at end of file +} diff --git a/tests/develop-test/2-query/show_create_db.py b/tests/develop-test/2-query/show_create_db.py index e5a79074ef2a1b9881f230b3eba2011edca517af..5574a59ec2e328f10a215adb3061e5626e28b100 100644 --- a/tests/develop-test/2-query/show_create_db.py +++ b/tests/develop-test/2-query/show_create_db.py @@ -42,17 +42,17 @@ class TDTestCase: tdSql.query('show create database scd;') tdSql.checkRows(1) tdSql.checkData(0, 0, 'scd') - tdSql.checkData(0, 1, "CREATE DATABASE `scd` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 1 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0") + tdSql.checkData(0, 1, "CREATE DATABASE `scd` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 1 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0 TABLE_PREFIX 0 TABLE_SUFFIX 0 TSDB_PAGESIZE 4 WAL_RETENTION_PERIOD 0 WAL_RETENTION_SIZE 0 WAL_ROLL_PERIOD 0 WAL_SEGMENT_SIZE 0") tdSql.query('show create database scd2;') tdSql.checkRows(1) tdSql.checkData(0, 0, 'scd2') - tdSql.checkData(0, 1, "CREATE DATABASE `scd2` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 3 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0") + tdSql.checkData(0, 1, "CREATE DATABASE `scd2` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 3 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0 TABLE_PREFIX 0 TABLE_SUFFIX 0 TSDB_PAGESIZE 4 WAL_RETENTION_PERIOD 0 WAL_RETENTION_SIZE 0 WAL_ROLL_PERIOD 0 WAL_SEGMENT_SIZE 0") tdSql.query('show create database scd4') tdSql.checkRows(1) tdSql.checkData(0, 0, 'scd4') - tdSql.checkData(0, 1, "CREATE DATABASE `scd4` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 13 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0") + tdSql.checkData(0, 1, "CREATE DATABASE `scd4` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 13 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0 TABLE_PREFIX 0 TABLE_SUFFIX 0 TSDB_PAGESIZE 4 WAL_RETENTION_PERIOD 0 WAL_RETENTION_SIZE 0 WAL_ROLL_PERIOD 0 WAL_SEGMENT_SIZE 0") self.restartTaosd(1, dbname='scd') @@ -60,17 +60,17 @@ class TDTestCase: tdSql.query('show create database scd;') tdSql.checkRows(1) tdSql.checkData(0, 0, 'scd') - tdSql.checkData(0, 1, "CREATE DATABASE `scd` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 1 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0") + tdSql.checkData(0, 1, "CREATE DATABASE `scd` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 1 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0 TABLE_PREFIX 0 TABLE_SUFFIX 0 TSDB_PAGESIZE 4 WAL_RETENTION_PERIOD 0 WAL_RETENTION_SIZE 0 WAL_ROLL_PERIOD 0 WAL_SEGMENT_SIZE 0") tdSql.query('show create database scd2;') tdSql.checkRows(1) tdSql.checkData(0, 0, 'scd2') - tdSql.checkData(0, 1, "CREATE DATABASE `scd2` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 3 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0") + tdSql.checkData(0, 1, "CREATE DATABASE `scd2` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 3 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0 TABLE_PREFIX 0 TABLE_SUFFIX 0 TSDB_PAGESIZE 4 WAL_RETENTION_PERIOD 0 WAL_RETENTION_SIZE 0 WAL_ROLL_PERIOD 0 WAL_SEGMENT_SIZE 0") tdSql.query('show create database scd4') tdSql.checkRows(1) tdSql.checkData(0, 0, 'scd4') - tdSql.checkData(0, 1, "CREATE DATABASE `scd4` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 13 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0") + tdSql.checkData(0, 1, "CREATE DATABASE `scd4` BUFFER 256 CACHESIZE 1 CACHEMODEL 'none' COMP 2 DURATION 14400m WAL_FSYNC_PERIOD 3000 MAXROWS 4096 MINROWS 100 STT_TRIGGER 13 KEEP 5256000m,5256000m,5256000m PAGES 256 PAGESIZE 4 PRECISION 'ms' REPLICA 1 WAL_LEVEL 1 VGROUPS 2 SINGLE_STABLE 0 TABLE_PREFIX 0 TABLE_SUFFIX 0 TSDB_PAGESIZE 4 WAL_RETENTION_PERIOD 0 WAL_RETENTION_SIZE 0 WAL_ROLL_PERIOD 0 WAL_SEGMENT_SIZE 0") tdSql.execute('drop database scd') diff --git a/tests/develop-test/2-query/table_count_scan.py b/tests/develop-test/2-query/table_count_scan.py index 5bdc915cdde07e513c9a65fbbcd7cd35e2a93a42..758d28948dd38ee6d411e08412cdc4a8d7906a39 100644 --- a/tests/develop-test/2-query/table_count_scan.py +++ b/tests/develop-test/2-query/table_count_scan.py @@ -14,7 +14,7 @@ class TDTestCase: def init(self, conn, logSql, replicaVer=1): tdLog.debug("start to execute %s" % __file__) - tdSql.init(conn.cursor(), False) + tdSql.init(conn.cursor(), True) self._conn = conn def restartTaosd(self, index=1, dbname="db"): @@ -65,7 +65,7 @@ class TDTestCase: tdSql.query('select count(*),db_name, stable_name from information_schema.ins_tables group by db_name, stable_name;') tdSql.checkRows(3) - tdSql.checkData(0, 0, 23) + tdSql.checkData(0, 0, 24) tdSql.checkData(0, 1, 'information_schema') tdSql.checkData(0, 2, None) tdSql.checkData(1, 0, 3) @@ -77,7 +77,7 @@ class TDTestCase: tdSql.query('select count(1) v,db_name, stable_name from information_schema.ins_tables group by db_name, stable_name order by v desc;') tdSql.checkRows(3) - tdSql.checkData(0, 0, 23) + tdSql.checkData(0, 0, 24) tdSql.checkData(0, 1, 'information_schema') tdSql.checkData(0, 2, None) tdSql.checkData(1, 0, 5) @@ -93,7 +93,7 @@ class TDTestCase: tdSql.checkData(1, 1, 'performance_schema') tdSql.checkData(0, 0, 3) tdSql.checkData(0, 1, 'tbl_count') - tdSql.checkData(2, 0, 23) + tdSql.checkData(2, 0, 24) tdSql.checkData(2, 1, 'information_schema') tdSql.query("select count(*) from information_schema.ins_tables where db_name='tbl_count'") @@ -106,7 +106,7 @@ class TDTestCase: tdSql.query('select count(*) from information_schema.ins_tables') tdSql.checkRows(1) - tdSql.checkData(0, 0, 31) + tdSql.checkData(0, 0, 32) tdSql.execute('create table stba (ts timestamp, c1 bool, c2 tinyint, c3 smallint, c4 int, c5 bigint, c6 float, c7 double, c8 binary(10), c9 nchar(10), c10 tinyint unsigned, c11 smallint unsigned, c12 int unsigned, c13 bigint unsigned) TAGS(t1 int, t2 binary(10), t3 double);') @@ -189,7 +189,7 @@ class TDTestCase: tdSql.checkData(2, 0, 5) tdSql.checkData(2, 1, 'performance_schema') tdSql.checkData(2, 2, None) - tdSql.checkData(3, 0, 23) + tdSql.checkData(3, 0, 24) tdSql.checkData(3, 1, 'information_schema') tdSql.checkData(3, 2, None) @@ -204,7 +204,7 @@ class TDTestCase: tdSql.checkData(2, 0, 5) tdSql.checkData(2, 1, 'performance_schema') tdSql.checkData(2, 2, None) - tdSql.checkData(3, 0, 23) + tdSql.checkData(3, 0, 24) tdSql.checkData(3, 1, 'information_schema') tdSql.checkData(3, 2, None) @@ -215,7 +215,7 @@ class TDTestCase: tdSql.checkData(0, 1, 'tbl_count') tdSql.checkData(1, 0, 5) tdSql.checkData(1, 1, 'performance_schema') - tdSql.checkData(2, 0, 23) + tdSql.checkData(2, 0, 24) tdSql.checkData(2, 1, 'information_schema') tdSql.query("select count(*) from information_schema.ins_tables where db_name='tbl_count'") @@ -228,7 +228,7 @@ class TDTestCase: tdSql.query('select count(*) from information_schema.ins_tables') tdSql.checkRows(1) - tdSql.checkData(0, 0, 32) + tdSql.checkData(0, 0, 33) tdSql.execute('drop database tbl_count') diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/auto_create_table_json.py b/tests/develop-test/5-taos-tools/taosbenchmark/auto_create_table_json.py index a6167158a285d33a225a44d25e0a3c6ecc0e99dc..c4426010e439fcb24774c0322e0e928f0c83a572 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/auto_create_table_json.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/auto_create_table_json.py @@ -31,6 +31,8 @@ class TDTestCase: tdSql.init(conn.cursor()) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): @@ -108,49 +110,49 @@ class TDTestCase: tdLog.info("%s" % cmd) os.system("%s" % cmd) tdSql.execute("reset query cache") - tdSql.query("select count(*) from (select distinct(tbname) from db.stb2)") + tdSql.query("select count(*) from (select distinct(tbname) from stmt_db.stb2)") tdSql.checkData(0, 0, 8) - tdSql.query("select count(*) from db.stb2") + tdSql.query("select count(*) from stmt_db.stb2") tdSql.checkData(0, 0, 160) - tdSql.query("select * from information_schema.ins_databases") - tdSql.checkData(2, 14, "us") + tdSql.query("select * from information_schema.ins_databases where name='stmt_db'") + tdSql.checkData(0, 14, "us") tdSql.execute("reset query cache") - tdSql.query("select count(*) from (select distinct(tbname) from db.`stb2-2`)") + tdSql.query("select count(*) from (select distinct(tbname) from stmt_db.`stb2-2`)") tdSql.checkData(0, 0, 8) - tdSql.query("select count(*) from db.`stb2-2`") + tdSql.query("select count(*) from stmt_db.`stb2-2`") tdSql.checkData(0, 0, 160) cmd = "%s -f ./5-taos-tools/taosbenchmark/json/rest_auto_create_table.json" %binPath tdLog.info("%s" % cmd) os.system("%s" % cmd) tdSql.execute("reset query cache") - tdSql.query("select count(*) from (select distinct(tbname) from db.stb3)") + tdSql.query("select count(*) from (select distinct(tbname) from rest_db.stb3)") tdSql.checkData(0, 0, 8) - tdSql.query("select count(*) from db.stb3") + tdSql.query("select count(*) from rest_db.stb3") tdSql.checkData(0, 0, 160) - tdSql.query("select * from information_schema.ins_databases") - tdSql.checkData(2, 14, "ns") + tdSql.query("select * from information_schema.ins_databases where name='rest_db'") + tdSql.checkData(0, 14, "ns") tdSql.execute("reset query cache") - tdSql.query("select count(*) from (select distinct(tbname) from db.`stb3-2`)") + tdSql.query("select count(*) from (select distinct(tbname) from rest_db.`stb3-2`)") tdSql.checkData(0, 0, 8) - tdSql.query("select count(*) from db.`stb3-2`") + tdSql.query("select count(*) from rest_db.`stb3-2`") tdSql.checkData(0, 0, 160) cmd = "%s -f ./5-taos-tools/taosbenchmark/json/sml_auto_create_table.json" %binPath tdLog.info("%s" % cmd) os.system("%s" % cmd) tdSql.execute("reset query cache") - tdSql.query("select count(*) from (select distinct(tbname) from db.stb4)") + tdSql.query("select count(*) from (select distinct(tbname) from sml_db.stb4)") tdSql.checkData(0, 0, 8) - tdSql.query("select count(*) from db.stb4") + tdSql.query("select count(*) from sml_db.stb4") tdSql.checkData(0, 0, 160) tdSql.execute("reset query cache") - tdSql.query("select count(*) from (select distinct(tbname) from db.`stb4-2`)") + tdSql.query("select count(*) from (select distinct(tbname) from sml_db.`stb4-2`)") tdSql.checkData(0, 0, 8) - tdSql.query("select count(*) from db.`stb4-2`") + tdSql.query("select count(*) from sml_db.`stb4-2`") tdSql.checkData(0, 0, 160) tAdapter.stop() diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/commandline.py b/tests/develop-test/5-taos-tools/taosbenchmark/commandline.py index ba296584ba6e81e2f8db6860240c6535cfc62cbf..b353566b256c796f7c60af8a161fc767099391a4 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/commandline.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/commandline.py @@ -33,6 +33,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/custom_col_tag.py b/tests/develop-test/5-taos-tools/taosbenchmark/custom_col_tag.py index 0fb39c210c96d9a5db7b2f4216fe023499002f01..d1a807c201217cd04a9ec348411daa2fab7266f6 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/custom_col_tag.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/custom_col_tag.py @@ -30,6 +30,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/default_json.py b/tests/develop-test/5-taos-tools/taosbenchmark/default_json.py index 7599c82483509807d222d73557d3164c35159403..35ed2982130bb7cb3cef31414a9225b3411aeb7c 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/default_json.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/default_json.py @@ -29,25 +29,23 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) - if "community" in selfPath: - projPath = selfPath[: selfPath.find("community")] - elif "src" in selfPath: - projPath = selfPath[: selfPath.find("src")] - elif "/tools/" in selfPath: - projPath = selfPath[: selfPath.find("/tools/")] + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] else: - projPath = selfPath[: selfPath.find("tests")] + projPath = selfPath[:selfPath.find("tests")] paths = [] for root, dirs, files in os.walk(projPath): - if (tool) in files: + if ((tool) in files): rootRealPath = os.path.dirname(os.path.realpath(root)) - if "packaging" not in rootRealPath: + if ("packaging" not in rootRealPath): paths.append(os.path.join(root, tool)) break - if len(paths) == 0: + if (len(paths) == 0): tdLog.exit("taosBenchmark not found!") return else: @@ -61,9 +59,9 @@ class TDTestCase: os.system("%s" % cmd) tdSql.execute("reset query cache") tdSql.query("show db.tables") - tdSql.checkRows(10) + tdSql.checkRows(8) tdSql.query("select count(*) from db.stb") - tdSql.checkData(0, 0, 100) + tdSql.checkData(0, 0, 80) def stop(self): tdSql.close() diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/demo.py b/tests/develop-test/5-taos-tools/taosbenchmark/demo.py index 25a8d92f7e9b45e55011d5fe0bb241bb68962340..3f9c2160de24bfc7dde983178bbcef31c1e0c45f 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/demo.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/demo.py @@ -33,6 +33,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if "community" in selfPath: diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/insert_alltypes_json.py b/tests/develop-test/5-taos-tools/taosbenchmark/insert_alltypes_json.py index 080d6aea8731562c1aaa4a6aacb6aca726059b1a..cf76e362e5b8174fccff02615efc8778496e70df 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/insert_alltypes_json.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/insert_alltypes_json.py @@ -30,6 +30,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): @@ -320,7 +322,7 @@ class TDTestCase: tdSql.checkData(0, 0, 160) tdSql.query("select count(*) from db.stb where t13 like 'b1%' or t13 like 'b2%'") tdSql.checkData(0, 0, 160) - + tAdapter.stop() def stop(self): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/invalid_commandline.py b/tests/develop-test/5-taos-tools/taosbenchmark/invalid_commandline.py index d706eea068221602e057baa236b1dd671ddd1674..1a7f422123f826bbc4f22426de8c89732215a69e 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/invalid_commandline.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/invalid_commandline.py @@ -30,6 +30,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/json/default.json b/tests/develop-test/5-taos-tools/taosbenchmark/json/default.json index da22ef75e2a648e897341338bb762e4fedc6662b..c841e90b5168afc11bcf8248a0f37c9ba16d30d0 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/json/default.json +++ b/tests/develop-test/5-taos-tools/taosbenchmark/json/default.json @@ -15,13 +15,18 @@ "num_of_records_per_req": 10, "databases": [{ "dbinfo": { - "name": "db" + "name": "db", + "drop": "yes" + }, "super_tables": [{ + "child_table_exists":"no", "name": "stb", "childtable_prefix": "stb_", "childtable_count": 10, "insert_rows": 10, + "childtable_from": 1, + "childtable_to": 9, "columns": [{"type": "INT"}], "tags": [{"type": "INT"}] }] diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/json/rest_auto_create_table.json b/tests/develop-test/5-taos-tools/taosbenchmark/json/rest_auto_create_table.json index 868ff99842d9f1015e24a17aa91fc45700f036f3..078688bb7e075753bf972d4275daa21369ae10fd 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/json/rest_auto_create_table.json +++ b/tests/develop-test/5-taos-tools/taosbenchmark/json/rest_auto_create_table.json @@ -11,11 +11,12 @@ "confirm_parameter_prompt": "no", "prepared_rand": 100, "chinese": "no", + "escape_character": "yes", "insert_interval": 0, "num_of_records_per_req": 10, "databases": [{ "dbinfo": { - "name": "db", + "name": "rest_db", "drop": "yes", "replica": 1, "precision": "ns", @@ -29,7 +30,6 @@ "child_table_exists":"no", "childtable_count": 8, "childtable_prefix": "stb_", - "escape_character": "yes", "auto_create_table": "yes", "batch_create_tbl_num": 10, "data_source": "rand", @@ -54,7 +54,6 @@ "child_table_exists":"no", "childtable_count": 8, "childtable_prefix": "stb3-2_", - "escape_character": "yes", "auto_create_table": "yes", "batch_create_tbl_num": 10, "data_source": "rand", diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_auto_create_table.json b/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_auto_create_table.json index 1bbeca672b42dfe6b5b48c726fa5b11408ffcaf2..e808c9d3f3901b2ccaf63b315de164bb11a729cb 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_auto_create_table.json +++ b/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_auto_create_table.json @@ -11,11 +11,12 @@ "confirm_parameter_prompt": "no", "prepared_rand": 100, "chinese": "no", + "escape_character": "yes", "insert_interval": 0, "num_of_records_per_req": 10, "databases": [{ "dbinfo": { - "name": "db", + "name": "sml_db", "drop": "yes", "replica": 1, "precision": "ms", @@ -29,7 +30,6 @@ "child_table_exists":"no", "childtable_count": 8, "childtable_prefix": "stb_", - "escape_character": "yes", "auto_create_table": "yes", "batch_create_tbl_num": 10, "data_source": "rand", @@ -54,7 +54,6 @@ "child_table_exists":"no", "childtable_count": 8, "childtable_prefix": "stb4-2_", - "escape_character": "yes", "auto_create_table": "yes", "batch_create_tbl_num": 10, "data_source": "rand", diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_json_alltypes.json b/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_json_alltypes.json index 5a373888a6cdfe2ee8a4880863459e91c87a8fa2..26a08b3fee7af72361229b944de7fefe7f8a1317 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_json_alltypes.json +++ b/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_json_alltypes.json @@ -16,13 +16,7 @@ "databases": [{ "dbinfo": { "name": "db", - "drop": "yes", - "replica": 1, - "precision": "ms", - "keep": 36500, - "minRows": 100, - "maxRows": 4096, - "comp":2 + "drop": "yes" }, "super_tables": [{ "name": "stb1", diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_telnet_tcp.json b/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_telnet_tcp.json index 9e1241397fe13eced0000c600ad76971a30227ca..e609fcfebdf3cfb30a88b4e86d59f6b38ce4535b 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_telnet_tcp.json +++ b/tests/develop-test/5-taos-tools/taosbenchmark/json/sml_telnet_tcp.json @@ -16,7 +16,7 @@ "num_of_records_per_req": 10, "databases": [{ "dbinfo": { - "name": "db", + "name": "opentsdb_telnet", "drop": "yes" }, "super_tables": [{ diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/json/stmt_auto_create_table.json b/tests/develop-test/5-taos-tools/taosbenchmark/json/stmt_auto_create_table.json index e6e773f6167a42f19074a412527f8ccad5689e9e..0054d985ee6e68012d7840b1cb088d5d73147bec 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/json/stmt_auto_create_table.json +++ b/tests/develop-test/5-taos-tools/taosbenchmark/json/stmt_auto_create_table.json @@ -11,11 +11,12 @@ "confirm_parameter_prompt": "no", "prepared_rand": 100, "chinese": "no", + "escape_character": "yes", "insert_interval": 0, "num_of_records_per_req": 10, "databases": [{ "dbinfo": { - "name": "db", + "name": "stmt_db", "drop": "yes", "replica": 1, "precision": "us", @@ -29,7 +30,6 @@ "child_table_exists":"no", "childtable_count": 8, "childtable_prefix": "stb_", - "escape_character": "yes", "auto_create_table": "yes", "batch_create_tbl_num": 10, "data_source": "rand", @@ -54,7 +54,6 @@ "child_table_exists":"no", "childtable_count": 8, "childtable_prefix": "stb2-2_", - "escape_character": "yes", "auto_create_table": "yes", "batch_create_tbl_num": 10, "data_source": "rand", diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/json/taosc_auto_create_table.json b/tests/develop-test/5-taos-tools/taosbenchmark/json/taosc_auto_create_table.json index f683cc016b1e068c6ebf2933084977ffeb11966c..bed3598bfe8a32319968388b435ed0cd1a8a415a 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/json/taosc_auto_create_table.json +++ b/tests/develop-test/5-taos-tools/taosbenchmark/json/taosc_auto_create_table.json @@ -11,6 +11,7 @@ "confirm_parameter_prompt": "no", "prepared_rand": 100, "chinese": "no", + "escape_character": "yes", "insert_interval": 0, "num_of_records_per_req": 10, "databases": [{ @@ -29,7 +30,6 @@ "child_table_exists":"no", "childtable_count": 8, "childtable_prefix": "stb_", - "escape_character": "yes", "auto_create_table": "yes", "batch_create_tbl_num": 10, "data_source": "rand", @@ -55,7 +55,6 @@ "child_table_exists":"no", "childtable_count": 8, "childtable_prefix": "stb1-2_", - "escape_character": "yes", "auto_create_table": "yes", "batch_create_tbl_num": 10, "data_source": "rand", diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/json_tag.py b/tests/develop-test/5-taos-tools/taosbenchmark/json_tag.py index afefabef66ef8b242a98874d5c15442e173f2df9..ea1bc165202c53fa7a714a1b249dfd15a786310f 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/json_tag.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/json_tag.py @@ -30,6 +30,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/limit_offset_json.py b/tests/develop-test/5-taos-tools/taosbenchmark/limit_offset_json.py index d95e6741f8af4ee837fe903dbc60fee894bebd7f..a1a77ba0bbf0e2fccfca222b20b30a619627e1bc 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/limit_offset_json.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/limit_offset_json.py @@ -30,6 +30,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/query_json.py b/tests/develop-test/5-taos-tools/taosbenchmark/query_json.py index c4b1750340eb73016e0fa623bdc484a0d33788a4..f300e6520341e5c36ff216f1378f106a9699fce1 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/query_json.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/query_json.py @@ -35,6 +35,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): @@ -120,7 +122,7 @@ class TDTestCase: def stop(self): - tdSql.close() + tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/sample_csv_json.py b/tests/develop-test/5-taos-tools/taosbenchmark/sample_csv_json.py index fd79f1e01b4ad28f8dfb75a13d114113ab1604ea..5d4dd794887efd55b5c81b2f6f89a7403c3390ea 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/sample_csv_json.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/sample_csv_json.py @@ -30,6 +30,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/sml_interlace.py b/tests/develop-test/5-taos-tools/taosbenchmark/sml_interlace.py index 200a3c0e69bc5b2e6c3b3dd6926885c5ca8d6f8f..3e40dd6a5e69548d20178d12aa7bd0a73ef6f1c2 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/sml_interlace.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/sml_interlace.py @@ -30,6 +30,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/sml_json_alltypes.py b/tests/develop-test/5-taos-tools/taosbenchmark/sml_json_alltypes.py index 1b65e38d72587247aabbd7c598c500fa797dfd81..ff82713ca3d4edf417c45d99f96393fe2cf64de5 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/sml_json_alltypes.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/sml_json_alltypes.py @@ -29,28 +29,23 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) - if "community" in selfPath: - projPath = selfPath[: selfPath.find("community")] - elif "src" in selfPath: - projPath = selfPath[: selfPath.find("src")] - elif "/tools/" in selfPath: - projPath = selfPath[: selfPath.find("/tools/")] - elif "/tests/" in selfPath: - projPath = selfPath[: selfPath.find("/tests/")] + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] else: - tdLog.info("cannot found %s in path: %s, use system's" % (tool, selfPath)) - projPath = "/usr/local/taos/bin/" + projPath = selfPath[:selfPath.find("tests")] paths = [] - for root, dummy, files in os.walk(projPath): - if (tool) in files: + for root, dirs, files in os.walk(projPath): + if ((tool) in files): rootRealPath = os.path.dirname(os.path.realpath(root)) - if "packaging" not in rootRealPath: + if ("packaging" not in rootRealPath): paths.append(os.path.join(root, tool)) break - if len(paths) == 0: + if (len(paths) == 0): tdLog.exit("taosBenchmark not found!") return else: @@ -83,7 +78,7 @@ class TDTestCase: tdSql.checkData(1, 1, "DOUBLE") tdSql.query("describe db.stb8") if major_ver == "3": - tdSql.checkData(1, 1, "NCHAR") + tdSql.checkData(1, 1, "VARCHAR") tdSql.checkData(1, 2, 16) else: tdSql.checkData(1, 1, "NCHAR") @@ -91,7 +86,7 @@ class TDTestCase: tdSql.query("describe db.stb9") if major_ver == "3": - tdSql.checkData(1, 1, "NCHAR") + tdSql.checkData(1, 1, "VARCHAR") tdSql.checkData(1, 2, 16) else: tdSql.checkData(1, 1, "NCHAR") diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/sml_telnet_alltypes.py b/tests/develop-test/5-taos-tools/taosbenchmark/sml_telnet_alltypes.py index 241c6d63593d9cc5f203e88d7515d1085e446122..e8fa4f81fe234c6415eed425d4a91d90614cb635 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/sml_telnet_alltypes.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/sml_telnet_alltypes.py @@ -30,6 +30,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/taosadapter_json.py b/tests/develop-test/5-taos-tools/taosbenchmark/taosadapter_json.py index 4d0adde1922bb62c8987133f14d0b7647c12b504..488bb6f81e7f48a7ce5924be1b0d948eddfd7da8 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/taosadapter_json.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/taosadapter_json.py @@ -31,6 +31,8 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/taosdemoTestQueryWithJson.py b/tests/develop-test/5-taos-tools/taosbenchmark/taosdemoTestQueryWithJson.py index 19500c7dca946f3c0a1887eaa3d4bdcfa35390ef..91ebf1b1df1f5d60068a354f5c4fc10deff70b99 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/taosdemoTestQueryWithJson.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/taosdemoTestQueryWithJson.py @@ -32,30 +32,28 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) - if "community" in selfPath: - projPath = selfPath[: selfPath.find("community")] - elif "src" in selfPath: - projPath = selfPath[: selfPath.find("src")] - elif "/tools/" in selfPath: - projPath = selfPath[: selfPath.find("/tools/")] - elif "/tests/" in selfPath: - projPath = selfPath[: selfPath.find("/tests/")] + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] else: - tdLog.info("cannot found %s in path: %s, use system's" % (tool, selfPath)) - projPath = "/usr/local/taos/bin/" + projPath = selfPath[:selfPath.find("tests")] paths = [] for root, dirs, files in os.walk(projPath): - if (tool) in files: + if ((tool) in files): rootRealPath = os.path.dirname(os.path.realpath(root)) - if "packaging" not in rootRealPath: + if ("packaging" not in rootRealPath): paths.append(os.path.join(root, tool)) break - if len(paths) == 0: - return "" - return paths[0] + if (len(paths) == 0): + tdLog.exit("taosBenchmark not found!") + return + else: + tdLog.info("taosBenchmark found in %s" % paths[0]) + return paths[0] # 获取taosc接口查询的结果文件中的内容,返回每行数据,并断言数据的第一列内容。 def assertfileDataTaosc(self, filename, expectResult): diff --git a/tests/develop-test/5-taos-tools/taosbenchmark/telnet_tcp.py b/tests/develop-test/5-taos-tools/taosbenchmark/telnet_tcp.py index 23e788916f63d899d3ae3059a8062d54dcf329c6..0392b58aa2df54ebc75dc8647fed7e9bc51dd3f2 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/telnet_tcp.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/telnet_tcp.py @@ -29,27 +29,23 @@ class TDTestCase: tdSql.init(conn.cursor(), logSql) def getPath(self, tool="taosBenchmark"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) - if "community" in selfPath: - projPath = selfPath[: selfPath.find("community")] - elif "src" in selfPath: - projPath = selfPath[: selfPath.find("src")] - elif "/tools/" in selfPath: - projPath = selfPath[: selfPath.find("/tools/")] - elif "/tests/" in selfPath: - projPath = selfPath[: selfPath.find("/tests/")] + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] else: - tdLog.exit("cannot found %s in path: %s, use system's" % (tool, selfPath)) + projPath = selfPath[:selfPath.find("tests")] paths = [] for root, dirs, files in os.walk(projPath): - if (tool) in files: + if ((tool) in files): rootRealPath = os.path.dirname(os.path.realpath(root)) - if "packaging" not in rootRealPath: + if ("packaging" not in rootRealPath): paths.append(os.path.join(root, tool)) break - if len(paths) == 0: + if (len(paths) == 0): tdLog.exit("taosBenchmark not found!") return else: diff --git a/tests/develop-test/5-taos-tools/taosdump/taosdumpTestInspect.py b/tests/develop-test/5-taos-tools/taosdump/taosdumpTestInspect.py index a6c2062d6cefb5f41023ae7c5e1926e05c6dfb83..197f05aac9889181dc5d988bfb27137fed53ea0d 100644 --- a/tests/develop-test/5-taos-tools/taosdump/taosdumpTestInspect.py +++ b/tests/develop-test/5-taos-tools/taosdump/taosdumpTestInspect.py @@ -11,29 +11,27 @@ # -*- coding: utf-8 -*- -import sys import os from util.log import * from util.cases import * from util.sql import * from util.dnodes import * -import subprocess class TDTestCase: def caseDescription(self): - ''' + """ case1: [TD-14544] taosdump data inspect - ''' - return + """ def init(self, conn, logSql, replicaVar=1): - self.replicaVar = int(replicaVar) tdLog.debug("start to execute %s" % __file__) tdSql.init(conn.cursor(), logSql) self.tmpdir = "tmp" def getPath(self, tool="taosdump"): + if (platform.system().lower() == 'windows'): + tool = tool + ".exe" selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): @@ -49,31 +47,39 @@ class TDTestCase: paths.append(os.path.join(root, tool)) break if (len(paths) == 0): - return "" - return paths[0] + tdLog.exit("taosBenchmark not found!") + return + else: + tdLog.info("taosBenchmark found in %s" % paths[0]) + return paths[0] def run(self): - tdSql.prepare(replica=f"{self.replicaVar}") + tdSql.prepare() tdSql.execute("drop database if exists db") - tdSql.execute("create database db days 11 keep 3649 blocks 8 ") + tdSql.execute("create database db keep 3649 ") tdSql.execute("use db") tdSql.execute( - "create table st(ts timestamp, c1 INT, c2 BOOL, c3 TINYINT, c4 SMALLINT, c5 BIGINT, c6 FLOAT, c7 DOUBLE, c8 TIMESTAMP, c9 BINARY(10), c10 NCHAR(10), c11 TINYINT UNSIGNED, c12 SMALLINT UNSIGNED, c13 INT UNSIGNED, c14 BIGINT UNSIGNED) tags(n1 INT, w2 BOOL, t3 TINYINT, t4 SMALLINT, t5 BIGINT, t6 FLOAT, t7 DOUBLE, t8 TIMESTAMP, t9 BINARY(10), t10 NCHAR(10), t11 TINYINT UNSIGNED, t12 SMALLINT UNSIGNED, t13 INT UNSIGNED, t14 BIGINT UNSIGNED)") + "create table st(ts timestamp, c1 INT, c2 BOOL, c3 TINYINT, c4 SMALLINT, c5 BIGINT, c6 FLOAT, c7 DOUBLE, c8 TIMESTAMP, c9 BINARY(10), c10 NCHAR(10), c11 TINYINT UNSIGNED, c12 SMALLINT UNSIGNED, c13 INT UNSIGNED, c14 BIGINT UNSIGNED) tags(n1 INT, w2 BOOL, t3 TINYINT, t4 SMALLINT, t5 BIGINT, t6 FLOAT, t7 DOUBLE, t8 TIMESTAMP, t9 BINARY(10), t10 NCHAR(10), t11 TINYINT UNSIGNED, t12 SMALLINT UNSIGNED, t13 INT UNSIGNED, t14 BIGINT UNSIGNED)" + ) tdSql.execute( - "create table t1 using st tags(1, true, 1, 1, 1, 1.0, 1.0, 1, '1', '一', 1, 1, 1, 1)") + "create table t1 using st tags(1, true, 1, 1, 1, 1.0, 1.0, 1, '1', '一', 1, 1, 1, 1)" + ) tdSql.execute( - "insert into t1 values(1640000000000, 1, true, 1, 1, 1, 1.0, 1.0, 1, '1', '一', 1, 1, 1, 1)") + "insert into t1 values(1640000000000, 1, true, 1, 1, 1, 1.0, 1.0, 1, '1', '一', 1, 1, 1, 1)" + ) tdSql.execute( - "create table t2 using st tags(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)") + "create table t2 using st tags(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)" + ) tdSql.execute( - "insert into t2 values(1640000000000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)") + "insert into t2 values(1640000000000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)" + ) -# sys.exit(1) + # sys.exit(1) - binPath = self.getPath("taosdump") - if (binPath == ""): + binPath = self.getPath() + if binPath == "": tdLog.exit("taosdump not found!") else: tdLog.info("taosdump found in %s" % binPath) @@ -85,35 +91,73 @@ class TDTestCase: os.system("rm -rf %s" % self.tmpdir) os.makedirs(self.tmpdir) - os.system( - "%s --databases db -o %s -T 1" % - (binPath, self.tmpdir)) + os.system("%s --databases db -o %s -T 1" % (binPath, self.tmpdir)) + + # sys.exit(1) -# sys.exit(1) + taosdumpInspectCmd = "%s -I %s/taosdump.*/*.avro* -s | grep 'Schema:'|wc -l" % ( + binPath, + self.tmpdir, + ) + schemaTimes = subprocess.check_output(taosdumpInspectCmd, shell=True).decode( + "utf-8" + ) + print("schema found times: %d" % int(schemaTimes)) - taosdumpInspectCmd = "%s -I %s/*.avro* -s | grep 'Schema:'|wc -l" % ( - binPath, self.tmpdir) - schemaTimes = subprocess.check_output( - taosdumpInspectCmd, shell=True).decode("utf-8") + if int(schemaTimes) != 1: + caller = inspect.getframeinfo(inspect.stack()[0][0]) + tdLog.exit( + "%s(%d) failed: expected schema found times 1, actual %d" + % (caller.filename, caller.lineno, int(schemaTimes)) + ) + + taosdumpInspectCmd = ( + "%s -I %s/taosdump*/data*/*.avro* -s | grep 'Schema:'|wc -l" + % (binPath, self.tmpdir) + ) + schemaTimes = subprocess.check_output(taosdumpInspectCmd, shell=True).decode( + "utf-8" + ) print("schema found times: %d" % int(schemaTimes)) - if (int(schemaTimes) != 3): + if int(schemaTimes) != 2: caller = inspect.getframeinfo(inspect.stack()[0][0]) tdLog.exit( - "%s(%d) failed: expected schema found times 3, actual %d" % - (caller.filename, caller.lineno, int(schemaTimes))) + "%s(%d) failed: expected schema found times 2, actual %d" + % (caller.filename, caller.lineno, int(schemaTimes)) + ) + + taosdumpInspectCmd = ( + "%s -I %s/taosdump*/*.avro* | grep '=== Records:'|wc -l" + % (binPath, self.tmpdir) + ) + recordsTimes = subprocess.check_output(taosdumpInspectCmd, shell=True).decode( + "utf-8" + ) + print("records found times: %d" % int(recordsTimes)) - taosdumpInspectCmd = "%s -I %s/*.avro* | grep '=== Records:'|wc -l" % ( - binPath, self.tmpdir) - recordsTimes = subprocess.check_output( - taosdumpInspectCmd, shell=True).decode("utf-8") + if int(recordsTimes) != 1: + caller = inspect.getframeinfo(inspect.stack()[0][0]) + tdLog.exit( + "%s(%d) failed: expected records found times 1, actual %d" + % (caller.filename, caller.lineno, int(recordsTimes)) + ) + + taosdumpInspectCmd = ( + "%s -I %s/taosdump*/data*/*.avro* | grep '=== Records:'|wc -l" + % (binPath, self.tmpdir) + ) + recordsTimes = subprocess.check_output(taosdumpInspectCmd, shell=True).decode( + "utf-8" + ) print("records found times: %d" % int(recordsTimes)) - if (int(recordsTimes) != 3): + if int(recordsTimes) != 2: caller = inspect.getframeinfo(inspect.stack()[0][0]) tdLog.exit( - "%s(%d) failed: expected records found times 3, actual %d" % - (caller.filename, caller.lineno, int(recordsTimes))) + "%s(%d) failed: expected records found times 2, actual %d" + % (caller.filename, caller.lineno, int(recordsTimes)) + ) def stop(self): tdSql.close() diff --git a/tests/develop-test/test.py b/tests/develop-test/test.py index 1b0f0d0aed7c7a6410691f0b8c894c7823625832..6b1c63a1c0c4fe9415c921b97beb3dbe336235ce 100644 --- a/tests/develop-test/test.py +++ b/tests/develop-test/test.py @@ -316,9 +316,9 @@ if __name__ == "__main__": print(r) else: pass - if restful: - tAdapter.init(deployPath, masterIp) - tAdapter.stop(force_kill=True) + + tAdapter.init(deployPath, masterIp) + tAdapter.stop(force_kill=True) if dnodeNums == 1: tdDnodes.deploy(1, updateCfgDict) @@ -343,7 +343,7 @@ if __name__ == "__main__": for i in range(cursor.rowcount): if res[i][0] == "queryPolicy": if int(res[i][1]) == int(queryPolicy): - tdLog.success( + tdLog.info( f"alter queryPolicy to {queryPolicy} successfully" ) else: @@ -402,7 +402,7 @@ if __name__ == "__main__": for i in range(cursor.rowcount): if res[i][0] == "queryPolicy": if int(res[i][1]) == int(queryPolicy): - tdLog.success( + tdLog.info( f"alter queryPolicy to {queryPolicy} successfully" ) else: @@ -471,7 +471,7 @@ if __name__ == "__main__": # for i in range(tdSql.queryRows): # if tdSql.queryResult[i][0] == "queryPolicy" : # if int(tdSql.queryResult[i][1]) == int(queryPolicy): - # tdLog.success('alter queryPolicy to %d successfully'%queryPolicy) + # tdLog.info('alter queryPolicy to %d successfully'%queryPolicy) # else : # tdLog.debug(tdSql.queryResult) # tdLog.exit("alter queryPolicy to %d failed"%queryPolicy) @@ -484,7 +484,7 @@ if __name__ == "__main__": for i in range(cursor.rowcount): if res[i][0] == "queryPolicy": if int(res[i][1]) == int(queryPolicy): - tdLog.success( + tdLog.info( f"alter queryPolicy to {queryPolicy} successfully" ) else: @@ -545,7 +545,7 @@ if __name__ == "__main__": for i in range(cursor.rowcount): if res[i][0] == "queryPolicy": if int(res[i][1]) == int(queryPolicy): - tdLog.success( + tdLog.info( f"alter queryPolicy to {queryPolicy} successfully" ) else: diff --git a/tests/develop-test/win-test-file b/tests/develop-test/win-test-file new file mode 100644 index 0000000000000000000000000000000000000000..e4f3bcf56ee0ea3154232d384e005855b60e3c82 --- /dev/null +++ b/tests/develop-test/win-test-file @@ -0,0 +1,13 @@ +python3 ./test.py -f 2-query/table_count_scan.py +python3 ./test.py -f 2-query/show_create_db.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/auto_create_table_json.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/custom_col_tag.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/default_json.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/demo.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/insert_alltypes_json.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/invalid_commandline.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/json_tag.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/query_json.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/sample_csv_json.py +python3 ./test.py -f 5-taos-tools/taosbenchmark/taosdemoTestQueryWithJson.py -R +python3 ./test.py -f 5-taos-tools/taosbenchmark/telnet_tcp.py -R diff --git a/tests/docs-examples-test/jdbc.sh b/tests/docs-examples-test/jdbc.sh index d71085a40306956ea8d25e9b575c97ae9945df76..4fcc5404b6585ec64383cb8cd341687119698dd6 100644 --- a/tests/docs-examples-test/jdbc.sh +++ b/tests/docs-examples-test/jdbc.sh @@ -6,15 +6,10 @@ cd ../../docs/examples/java mvn clean test > jdbc-out.log 2>&1 tail -n 20 jdbc-out.log - -cases=`grep 'Tests run' jdbc-out.log | awk 'END{print $3}'` -totalJDBCCases=`echo ${cases/%,}` -failed=`grep 'Tests run' jdbc-out.log | awk 'END{print $5}'` -JDBCFailed=`echo ${failed/%,}` -error=`grep 'Tests run' jdbc-out.log | awk 'END{print $7}'` -JDBCError=`echo ${error/%,}` - -totalJDBCFailed=`expr $JDBCFailed + $JDBCError` +totalJDBCCases=`grep 'Tests run' jdbc-out.log | awk -F"[:,]" 'END{ print $2 }'` +failed=`grep 'Tests run' jdbc-out.log | awk -F"[:,]" 'END{ print $4 }'` +error=`grep 'Tests run' jdbc-out.log | awk -F"[:,]" 'END{ print $6 }'` +totalJDBCFailed=`expr $failed + $error` totalJDBCSuccess=`expr $totalJDBCCases - $totalJDBCFailed` if [ "$totalJDBCSuccess" -gt "0" ]; then diff --git a/tests/docs-examples-test/python.sh b/tests/docs-examples-test/python.sh index ccb391b7527fbf2490911d868d08c87436221162..2a44ee75528ed462460cc6783a2cca62f3a022ef 100644 --- a/tests/docs-examples-test/python.sh +++ b/tests/docs-examples-test/python.sh @@ -52,7 +52,7 @@ python3 conn_rest_pandas.py taos -s "drop database if exists power" # 11 -taos -s "create database if not exists test" +taos -s "create database if not exists test wal_retention_period 3600" python3 connect_native_reference.py # 12 @@ -83,4 +83,11 @@ python3 fast_write_example.py # 20 pip3 install kafka-python -python3 kafka_example.py +python3 kafka_example_consumer.py + +# 21 +pip3 install taos-ws-py +python3 conn_websocket_pandas.py + +# 22 +python3 connect_websocket_examples.py diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index ee647500cf6860f9669df1866915df9db4165de5..e79cf776480507298d051a516f9ba88bec89283e 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -5,407 +5,122 @@ #unit-test ,,y,unit-test,bash test.sh -#tsim test -,,y,script,./test.sh -f tsim/user/basic.sim -,,y,script,./test.sh -f tsim/user/password.sim -,,y,script,./test.sh -f tsim/user/privilege_db.sim -,,y,script,./test.sh -f tsim/user/privilege_sysinfo.sim -,,y,script,./test.sh -f tsim/user/privilege_topic.sim -,,y,script,./test.sh -f tsim/db/alter_option.sim -,,y,script,./test.sh -f tsim/db/alter_replica_13.sim -,,y,script,./test.sh -f tsim/db/alter_replica_31.sim -,,y,script,./test.sh -f tsim/db/basic1.sim -,,y,script,./test.sh -f tsim/db/basic2.sim -,,y,script,./test.sh -f tsim/db/basic3.sim -,,y,script,./test.sh -f tsim/db/basic4.sim -,,y,script,./test.sh -f tsim/db/basic5.sim -,,y,script,./test.sh -f tsim/db/basic6.sim -,,y,script,./test.sh -f tsim/db/commit.sim -,,y,script,./test.sh -f tsim/db/create_all_options.sim -,,y,script,./test.sh -f tsim/db/delete_reuse1.sim -,,y,script,./test.sh -f tsim/db/delete_reuse2.sim -,,y,script,./test.sh -f tsim/db/delete_reusevnode.sim -,,y,script,./test.sh -f tsim/db/delete_reusevnode2.sim -,,y,script,./test.sh -f tsim/db/delete_writing1.sim -,,y,script,./test.sh -f tsim/db/delete_writing2.sim -,,y,script,./test.sh -f tsim/db/error1.sim -,,y,script,./test.sh -f tsim/db/keep.sim -,,y,script,./test.sh -f tsim/db/len.sim -,,y,script,./test.sh -f tsim/db/repeat.sim -,,y,script,./test.sh -f tsim/db/show_create_db.sim -,,y,script,./test.sh -f tsim/db/show_create_table.sim -,,y,script,./test.sh -f tsim/db/tables.sim -,,y,script,./test.sh -f tsim/db/taosdlog.sim -,,y,script,./test.sh -f tsim/dnode/balance_replica1.sim -,,y,script,./test.sh -f tsim/dnode/balance_replica3.sim -,,y,script,./test.sh -f tsim/dnode/balance1.sim -,,y,script,./test.sh -f tsim/dnode/balance2.sim -,,y,script,./test.sh -f tsim/dnode/balance3.sim -,,y,script,./test.sh -f tsim/dnode/balancex.sim -,,y,script,./test.sh -f tsim/dnode/create_dnode.sim -,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_mnode.sim -,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_qnode_snode.sim -,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_vnode_replica1.sim -,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_vnode_replica3.sim -,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_multi_vnode_replica1.sim -,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim -,,y,script,./test.sh -f tsim/dnode/drop_dnode_force.sim -,,y,script,./test.sh -f tsim/dnode/offline_reason.sim -,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica1.sim -,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v1_leader.sim -,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v1_follower.sim -,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v2.sim -,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v3.sim -,,y,script,./test.sh -f tsim/dnode/vnode_clean.sim -,,y,script,./test.sh -f tsim/dnode/use_dropped_dnode.sim -,,y,script,./test.sh -f tsim/dnode/split_vgroup_replica1.sim -,,y,script,./test.sh -f tsim/dnode/split_vgroup_replica3.sim -,,y,script,./test.sh -f tsim/import/basic.sim -,,y,script,./test.sh -f tsim/import/commit.sim -,,y,script,./test.sh -f tsim/import/large.sim -,,y,script,./test.sh -f tsim/import/replica1.sim -,,y,script,./test.sh -f tsim/insert/backquote.sim -,,y,script,./test.sh -f tsim/insert/basic.sim -,,y,script,./test.sh -f tsim/insert/basic0.sim -,,y,script,./test.sh -f tsim/insert/basic1.sim -,,y,script,./test.sh -f tsim/insert/basic2.sim -,,y,script,./test.sh -f tsim/insert/commit-merge0.sim -,,y,script,./test.sh -f tsim/insert/insert_drop.sim -,,y,script,./test.sh -f tsim/insert/insert_select.sim -,,y,script,./test.sh -f tsim/insert/null.sim -,,y,script,./test.sh -f tsim/insert/query_block1_file.sim -,,y,script,./test.sh -f tsim/insert/query_block1_memory.sim -,,y,script,./test.sh -f tsim/insert/query_block2_file.sim -,,y,script,./test.sh -f tsim/insert/query_block2_memory.sim -,,y,script,./test.sh -f tsim/insert/query_file_memory.sim -,,y,script,./test.sh -f tsim/insert/query_multi_file.sim -,,y,script,./test.sh -f tsim/insert/tcp.sim -,,y,script,./test.sh -f tsim/insert/update0.sim -,,y,script,./test.sh -f tsim/insert/update1_sort_merge.sim -,,y,script,./test.sh -f tsim/parser/alter__for_community_version.sim -,,y,script,./test.sh -f tsim/parser/alter_column.sim -,,y,script,./test.sh -f tsim/parser/alter_stable.sim -,,y,script,./test.sh -f tsim/parser/alter.sim -,,y,script,./test.sh -f tsim/parser/alter1.sim -,,y,script,./test.sh -f tsim/parser/auto_create_tb_drop_tb.sim -,,y,script,./test.sh -f tsim/parser/auto_create_tb.sim -,,y,script,./test.sh -f tsim/parser/between_and.sim -,,y,script,./test.sh -f tsim/parser/binary_escapeCharacter.sim -,,y,script,./test.sh -f tsim/parser/col_arithmetic_operation.sim -,,y,script,./test.sh -f tsim/parser/columnValue_bigint.sim -,,y,script,./test.sh -f tsim/parser/columnValue_bool.sim -,,y,script,./test.sh -f tsim/parser/columnValue_double.sim -,,y,script,./test.sh -f tsim/parser/columnValue_float.sim -,,y,script,./test.sh -f tsim/parser/columnValue_int.sim -,,y,script,./test.sh -f tsim/parser/columnValue_smallint.sim -,,y,script,./test.sh -f tsim/parser/columnValue_tinyint.sim -,,y,script,./test.sh -f tsim/parser/columnValue_unsign.sim -,,y,script,./test.sh -f tsim/parser/commit.sim -,,y,script,./test.sh -f tsim/parser/condition.sim -,,y,script,./test.sh -f tsim/parser/constCol.sim -,,y,script,./test.sh -f tsim/parser/create_db.sim -,,y,script,./test.sh -f tsim/parser/create_mt.sim -,,y,script,./test.sh -f tsim/parser/create_tb_with_tag_name.sim -,,y,script,./test.sh -f tsim/parser/create_tb.sim -,,y,script,./test.sh -f tsim/parser/dbtbnameValidate.sim -,,y,script,./test.sh -f tsim/parser/distinct.sim -,,y,script,./test.sh -f tsim/parser/fill_us.sim -,,y,script,./test.sh -f tsim/parser/fill.sim -,,y,script,./test.sh -f tsim/parser/first_last.sim -,,y,script,./test.sh -f tsim/parser/fill_stb.sim -,,y,script,./test.sh -f tsim/parser/interp.sim -,,y,script,./test.sh -f tsim/parser/fourArithmetic-basic.sim -,,y,script,./test.sh -f tsim/parser/function.sim -,,y,script,./test.sh -f tsim/parser/groupby-basic.sim -,,y,script,./test.sh -f tsim/parser/groupby.sim -,,y,script,./test.sh -f tsim/parser/having_child.sim -,,y,script,./test.sh -f tsim/parser/having.sim -,,y,script,./test.sh -f tsim/parser/import_commit1.sim -,,y,script,./test.sh -f tsim/parser/import_commit2.sim -,,y,script,./test.sh -f tsim/parser/import_commit3.sim -,,y,script,./test.sh -f tsim/parser/import_file.sim -,,y,script,./test.sh -f tsim/parser/import.sim -,,y,script,./test.sh -f tsim/parser/insert_multiTbl.sim -,,y,script,./test.sh -f tsim/parser/insert_tb.sim -,,y,script,./test.sh -f tsim/parser/join_manyblocks.sim -,,y,script,./test.sh -f tsim/parser/join_multitables.sim -,,y,script,./test.sh -f tsim/parser/join_multivnode.sim -,,y,script,./test.sh -f tsim/parser/join.sim -,,y,script,./test.sh -f tsim/parser/last_cache.sim -,,y,script,./test.sh -f tsim/parser/last_groupby.sim -,,y,script,./test.sh -f tsim/parser/lastrow.sim -,,y,script,./test.sh -f tsim/parser/lastrow2.sim -,,y,script,./test.sh -f tsim/parser/like.sim -,,y,script,./test.sh -f tsim/parser/limit.sim -,,y,script,./test.sh -f tsim/parser/limit1.sim -,,y,script,./test.sh -f tsim/parser/mixed_blocks.sim -,,y,script,./test.sh -f tsim/parser/nchar.sim -,,y,script,./test.sh -f tsim/parser/nestquery.sim -,,y,script,./test.sh -f tsim/parser/null_char.sim -,,y,script,./test.sh -f tsim/parser/precision_ns.sim -,,y,script,./test.sh -f tsim/parser/projection_limit_offset.sim -,,y,script,./test.sh -f tsim/parser/regex.sim -,,y,script,./test.sh -f tsim/parser/regressiontest.sim -,,y,script,./test.sh -f tsim/parser/select_across_vnodes.sim -,,y,script,./test.sh -f tsim/parser/select_distinct_tag.sim -,,y,script,./test.sh -f tsim/parser/select_from_cache_disk.sim -,,y,script,./test.sh -f tsim/parser/select_with_tags.sim -,,y,script,./test.sh -f tsim/parser/selectResNum.sim -,,y,script,./test.sh -f tsim/parser/set_tag_vals.sim -,,y,script,./test.sh -f tsim/parser/single_row_in_tb.sim -,,y,script,./test.sh -f tsim/parser/sliding.sim -,,y,script,./test.sh -f tsim/parser/slimit_alter_tags.sim -,,y,script,./test.sh -f tsim/parser/slimit.sim -,,y,script,./test.sh -f tsim/parser/slimit1.sim -,,y,script,./test.sh -f tsim/parser/stableOp.sim -,,y,script,./test.sh -f tsim/parser/tags_dynamically_specifiy.sim -,,y,script,./test.sh -f tsim/parser/tags_filter.sim -,,y,script,./test.sh -f tsim/parser/tbnameIn.sim -,,y,script,./test.sh -f tsim/parser/timestamp.sim -,,y,script,./test.sh -f tsim/parser/top_groupby.sim -,,y,script,./test.sh -f tsim/parser/topbot.sim -,,y,script,./test.sh -f tsim/parser/union.sim -,,y,script,./test.sh -f tsim/parser/union_sysinfo.sim -,,y,script,./test.sh -f tsim/parser/where.sim -,,y,script,./test.sh -f tsim/query/charScalarFunction.sim -,,y,script,./test.sh -f tsim/query/explain.sim -,,y,script,./test.sh -f tsim/query/interval-offset.sim -,,y,script,./test.sh -f tsim/query/interval.sim -,,y,script,./test.sh -f tsim/query/scalarFunction.sim -,,y,script,./test.sh -f tsim/query/scalarNull.sim -,,y,script,./test.sh -f tsim/query/session.sim -,,y,script,./test.sh -f tsim/query/udf.sim -,,y,script,./test.sh -f tsim/query/udf_with_const.sim -,,y,script,./test.sh -f tsim/query/sys_tbname.sim -,,y,script,./test.sh -f tsim/query/groupby.sim -,,y,script,./test.sh -f tsim/query/forceFill.sim -,,y,script,./test.sh -f tsim/qnode/basic1.sim -,,y,script,./test.sh -f tsim/snode/basic1.sim -,,y,script,./test.sh -f tsim/mnode/basic1.sim -,,y,script,./test.sh -f tsim/mnode/basic2.sim -,,y,script,./test.sh -f tsim/mnode/basic3.sim -,,y,script,./test.sh -f tsim/mnode/basic4.sim -,,y,script,./test.sh -f tsim/mnode/basic5.sim -,,y,script,./test.sh -f tsim/show/basic.sim -,,y,script,./test.sh -f tsim/table/autocreate.sim -,,y,script,./test.sh -f tsim/table/basic1.sim -,,y,script,./test.sh -f tsim/table/basic2.sim -,,y,script,./test.sh -f tsim/table/basic3.sim -,,y,script,./test.sh -f tsim/table/bigint.sim -,,y,script,./test.sh -f tsim/table/binary.sim -,,y,script,./test.sh -f tsim/table/bool.sim -,,y,script,./test.sh -f tsim/table/column_name.sim -,,y,script,./test.sh -f tsim/table/column_num.sim -,,y,script,./test.sh -f tsim/table/column_value.sim -,,y,script,./test.sh -f tsim/table/column2.sim -,,y,script,./test.sh -f tsim/table/createmulti.sim -,,y,script,./test.sh -f tsim/table/date.sim -,,y,script,./test.sh -f tsim/table/db.table.sim -,,y,script,./test.sh -f tsim/table/delete_reuse1.sim -,,y,script,./test.sh -f tsim/table/delete_reuse2.sim -,,y,script,./test.sh -f tsim/table/delete_writing.sim -,,y,script,./test.sh -f tsim/table/describe.sim -,,y,script,./test.sh -f tsim/table/double.sim -,,y,script,./test.sh -f tsim/table/float.sim -,,y,script,./test.sh -f tsim/table/hash.sim -,,y,script,./test.sh -f tsim/table/int.sim -,,y,script,./test.sh -f tsim/table/limit.sim -,,y,script,./test.sh -f tsim/table/smallint.sim -,,y,script,./test.sh -f tsim/table/table_len.sim -,,y,script,./test.sh -f tsim/table/table.sim -,,y,script,./test.sh -f tsim/table/tinyint.sim -,,y,script,./test.sh -f tsim/table/vgroup.sim -,,n,script,./test.sh -f tsim/stream/basic0.sim -g -,,y,script,./test.sh -f tsim/stream/basic1.sim -,,y,script,./test.sh -f tsim/stream/basic2.sim -,,y,script,./test.sh -f tsim/stream/drop_stream.sim -,,y,script,./test.sh -f tsim/stream/fillHistoryBasic1.sim -,,y,script,./test.sh -f tsim/stream/fillHistoryBasic2.sim -,,y,script,./test.sh -f tsim/stream/fillHistoryBasic3.sim -,,y,script,./test.sh -f tsim/stream/distributeInterval0.sim -,,y,script,./test.sh -f tsim/stream/distributeIntervalRetrive0.sim -,,y,script,./test.sh -f tsim/stream/distributeSession0.sim -,,y,script,./test.sh -f tsim/stream/session0.sim -,,y,script,./test.sh -f tsim/stream/session1.sim -,,y,script,./test.sh -f tsim/stream/state0.sim -,,y,script,./test.sh -f tsim/stream/triggerInterval0.sim -,,y,script,./test.sh -f tsim/stream/triggerSession0.sim -,,y,script,./test.sh -f tsim/stream/partitionby.sim -,,y,script,./test.sh -f tsim/stream/partitionby1.sim -,,y,script,./test.sh -f tsim/stream/schedSnode.sim -,,y,script,./test.sh -f tsim/stream/windowClose.sim -,,y,script,./test.sh -f tsim/stream/ignoreExpiredData.sim -,,y,script,./test.sh -f tsim/stream/sliding.sim -,,y,script,./test.sh -f tsim/stream/partitionbyColumnInterval.sim -,,y,script,./test.sh -f tsim/stream/partitionbyColumnSession.sim -,,y,script,./test.sh -f tsim/stream/partitionbyColumnState.sim -,,y,script,./test.sh -f tsim/stream/deleteInterval.sim -,,y,script,./test.sh -f tsim/stream/deleteSession.sim -,,y,script,./test.sh -f tsim/stream/deleteState.sim -,,y,script,./test.sh -f tsim/stream/fillIntervalDelete0.sim -,,y,script,./test.sh -f tsim/stream/fillIntervalDelete1.sim -,,y,script,./test.sh -f tsim/stream/fillIntervalLinear.sim -,,y,script,./test.sh -f tsim/stream/fillIntervalPartitionBy.sim -,,y,script,./test.sh -f tsim/stream/fillIntervalPrevNext.sim -,,y,script,./test.sh -f tsim/stream/fillIntervalValue.sim -,,y,script,./test.sh -f tsim/trans/lossdata1.sim -,,y,script,./test.sh -f tsim/trans/create_db.sim -,,y,script,./test.sh -f tsim/tmq/basic1.sim -,,y,script,./test.sh -f tsim/tmq/basic2.sim -,,y,script,./test.sh -f tsim/tmq/basic3.sim -,,y,script,./test.sh -f tsim/tmq/basic4.sim -,,y,script,./test.sh -f tsim/tmq/basic1Of2Cons.sim -,,y,script,./test.sh -f tsim/tmq/basic2Of2Cons.sim -,,y,script,./test.sh -f tsim/tmq/basic3Of2Cons.sim -,,y,script,./test.sh -f tsim/tmq/basic4Of2Cons.sim -,,y,script,./test.sh -f tsim/tmq/basic2Of2ConsOverlap.sim -,,y,script,./test.sh -f tsim/tmq/topic.sim -,,y,script,./test.sh -f tsim/tmq/snapshot.sim -,,y,script,./test.sh -f tsim/tmq/snapshot1.sim -,,y,script,./test.sh -f tsim/stable/alter_comment.sim -,,y,script,./test.sh -f tsim/stable/alter_count.sim -,,y,script,./test.sh -f tsim/stable/alter_import.sim -,,y,script,./test.sh -f tsim/stable/alter_insert1.sim -,,y,script,./test.sh -f tsim/stable/alter_insert2.sim -,,y,script,./test.sh -f tsim/stable/alter_metrics.sim -,,y,script,./test.sh -f tsim/stable/column_add.sim -,,y,script,./test.sh -f tsim/stable/column_drop.sim -,,y,script,./test.sh -f tsim/stable/column_modify.sim -,,y,script,./test.sh -f tsim/stable/disk.sim -,,y,script,./test.sh -f tsim/stable/dnode3.sim -,,y,script,./test.sh -f tsim/stable/metrics.sim -,,y,script,./test.sh -f tsim/stable/refcount.sim -,,y,script,./test.sh -f tsim/stable/tag_add.sim -,,y,script,./test.sh -f tsim/stable/tag_drop.sim -,,y,script,./test.sh -f tsim/stable/tag_filter.sim -,,y,script,./test.sh -f tsim/stable/tag_modify.sim -,,y,script,./test.sh -f tsim/stable/tag_rename.sim -,,y,script,./test.sh -f tsim/stable/values.sim -,,y,script,./test.sh -f tsim/stable/vnode3.sim -,,y,script,./test.sh -f tsim/stable/metrics_idx.sim -,,n,script,./test.sh -f tsim/sma/drop_sma.sim -,,y,script,./test.sh -f tsim/sma/sma_leak.sim -,,y,script,./test.sh -f tsim/sma/tsmaCreateInsertQuery.sim -,,y,script,./test.sh -f tsim/sma/rsmaCreateInsertQuery.sim -,,y,script,./test.sh -f tsim/sma/rsmaPersistenceRecovery.sim -,,n,script,./test.sh -f tsim/valgrind/checkError1.sim -,,n,script,./test.sh -f tsim/valgrind/checkError2.sim -,,n,script,./test.sh -f tsim/valgrind/checkError3.sim -,,n,script,./test.sh -f tsim/valgrind/checkError4.sim -,,n,script,./test.sh -f tsim/valgrind/checkError5.sim -,,n,script,./test.sh -f tsim/valgrind/checkError6.sim -,,n,script,./test.sh -f tsim/valgrind/checkError7.sim -,,n,script,./test.sh -f tsim/valgrind/checkError8.sim -,,n,script,./test.sh -f tsim/valgrind/checkUdf.sim -,,y,script,./test.sh -f tsim/vnode/replica3_basic.sim -,,y,script,./test.sh -f tsim/vnode/replica3_repeat.sim -,,y,script,./test.sh -f tsim/vnode/replica3_vgroup.sim -,,y,script,./test.sh -f tsim/vnode/replica3_many.sim -,,y,script,./test.sh -f tsim/vnode/replica3_import.sim -,,y,script,./test.sh -f tsim/vnode/stable_balance_replica1.sim -,,y,script,./test.sh -f tsim/vnode/stable_dnode2_stop.sim -,,y,script,./test.sh -f tsim/vnode/stable_dnode2.sim -,,y,script,./test.sh -f tsim/vnode/stable_dnode3.sim -,,y,script,./test.sh -f tsim/vnode/stable_replica3_dnode6.sim -,,y,script,./test.sh -f tsim/vnode/stable_replica3_vnode3.sim -,,y,script,./test.sh -f tsim/sync/3Replica1VgElect.sim -,,y,script,./test.sh -f tsim/sync/3Replica5VgElect.sim -,,y,script,./test.sh -f tsim/sync/oneReplica1VgElect.sim -,,y,script,./test.sh -f tsim/sync/oneReplica5VgElect.sim -,,y,script,./test.sh -f tsim/catalog/alterInCurrent.sim -,,y,script,./test.sh -f tsim/scalar/in.sim -,,y,script,./test.sh -f tsim/scalar/scalar.sim -,,y,script,./test.sh -f tsim/scalar/filter.sim -,,y,script,./test.sh -f tsim/scalar/caseWhen.sim -,,y,script,./test.sh -f tsim/scalar/tsConvert.sim -,,y,script,./test.sh -f tsim/alter/cached_schema_after_alter.sim -,,y,script,./test.sh -f tsim/alter/dnode.sim -,,y,script,./test.sh -f tsim/alter/table.sim -,,y,script,./test.sh -f tsim/cache/new_metrics.sim -,,y,script,./test.sh -f tsim/cache/restart_table.sim -,,y,script,./test.sh -f tsim/cache/restart_metrics.sim -,,y,script,./test.sh -f tsim/column/commit.sim -,,y,script,./test.sh -f tsim/column/metrics.sim -,,y,script,./test.sh -f tsim/column/table.sim -,,y,script,./test.sh -f tsim/compress/commitlog.sim -,,y,script,./test.sh -f tsim/compress/compress2.sim -,,y,script,./test.sh -f tsim/compress/compress.sim -,,y,script,./test.sh -f tsim/compress/uncompress.sim -,,y,script,./test.sh -f tsim/compute/avg.sim -,,y,script,./test.sh -f tsim/compute/block_dist.sim -,,y,script,./test.sh -f tsim/compute/bottom.sim -,,y,script,./test.sh -f tsim/compute/count.sim -,,y,script,./test.sh -f tsim/compute/diff.sim -,,y,script,./test.sh -f tsim/compute/diff2.sim -,,y,script,./test.sh -f tsim/compute/first.sim -,,y,script,./test.sh -f tsim/compute/interval.sim -,,y,script,./test.sh -f tsim/compute/last_row.sim -,,y,script,./test.sh -f tsim/compute/last.sim -,,y,script,./test.sh -f tsim/compute/leastsquare.sim -,,y,script,./test.sh -f tsim/compute/max.sim -,,y,script,./test.sh -f tsim/compute/min.sim -,,y,script,./test.sh -f tsim/compute/null.sim -,,y,script,./test.sh -f tsim/compute/percentile.sim -,,y,script,./test.sh -f tsim/compute/stddev.sim -,,y,script,./test.sh -f tsim/compute/sum.sim -,,y,script,./test.sh -f tsim/compute/top.sim -,,y,script,./test.sh -f tsim/field/2.sim -,,y,script,./test.sh -f tsim/field/3.sim -,,y,script,./test.sh -f tsim/field/4.sim -,,y,script,./test.sh -f tsim/field/5.sim -,,y,script,./test.sh -f tsim/field/6.sim -,,y,script,./test.sh -f tsim/field/binary.sim -,,y,script,./test.sh -f tsim/field/bigint.sim -,,y,script,./test.sh -f tsim/field/bool.sim -,,y,script,./test.sh -f tsim/field/double.sim -,,y,script,./test.sh -f tsim/field/float.sim -,,y,script,./test.sh -f tsim/field/int.sim -,,y,script,./test.sh -f tsim/field/single.sim -,,y,script,./test.sh -f tsim/field/smallint.sim -,,y,script,./test.sh -f tsim/field/tinyint.sim -,,y,script,./test.sh -f tsim/field/unsigined_bigint.sim -,,y,script,./test.sh -f tsim/vector/metrics_field.sim -,,y,script,./test.sh -f tsim/vector/metrics_mix.sim -,,y,script,./test.sh -f tsim/vector/metrics_query.sim -,,y,script,./test.sh -f tsim/vector/metrics_tag.sim -,,y,script,./test.sh -f tsim/vector/metrics_time.sim -,,y,script,./test.sh -f tsim/vector/multi.sim -,,y,script,./test.sh -f tsim/vector/single.sim -,,y,script,./test.sh -f tsim/vector/table_field.sim -,,y,script,./test.sh -f tsim/vector/table_mix.sim -,,y,script,./test.sh -f tsim/vector/table_query.sim -,,y,script,./test.sh -f tsim/vector/table_time.sim -,,y,script,./test.sh -f tsim/wal/kill.sim -,,y,script,./test.sh -f tsim/tag/3.sim -,,y,script,./test.sh -f tsim/tag/4.sim -,,y,script,./test.sh -f tsim/tag/5.sim -,,y,script,./test.sh -f tsim/tag/6.sim -,,y,script,./test.sh -f tsim/tag/add.sim -,,y,script,./test.sh -f tsim/tag/bigint.sim -,,y,script,./test.sh -f tsim/tag/binary_binary.sim -,,y,script,./test.sh -f tsim/tag/binary.sim -,,y,script,./test.sh -f tsim/tag/bool_binary.sim -,,y,script,./test.sh -f tsim/tag/bool_int.sim -,,y,script,./test.sh -f tsim/tag/bool.sim -,,y,script,./test.sh -f tsim/tag/change.sim -,,y,script,./test.sh -f tsim/tag/column.sim -,,y,script,./test.sh -f tsim/tag/commit.sim -,,y,script,./test.sh -f tsim/tag/create.sim -,,y,script,./test.sh -f tsim/tag/delete.sim -,,y,script,./test.sh -f tsim/tag/double.sim -,,y,script,./test.sh -f tsim/tag/filter.sim -,,y,script,./test.sh -f tsim/tag/float.sim -,,y,script,./test.sh -f tsim/tag/int_binary.sim -,,y,script,./test.sh -f tsim/tag/int_float.sim -,,y,script,./test.sh -f tsim/tag/int.sim -,,y,script,./test.sh -f tsim/tag/set.sim -,,y,script,./test.sh -f tsim/tag/smallint.sim -,,y,script,./test.sh -f tsim/tag/tinyint.sim -,,y,script,./test.sh -f tsim/tag/drop_tag.sim -,,y,script,./test.sh -f tsim/tag/tbNameIn.sim -,,y,script,./test.sh -f tmp/monitor.sim +#system test +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_str.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_math.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_time.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_26.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_str.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_math.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_time.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_26.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/columnLenUpdated.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/columnLenUpdated.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/columnLenUpdated.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/columnLenUpdated.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_str.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_math.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_time.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_26.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqShow.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDropStb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb0.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb1.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb2.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb3.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb0.py -N 3 -n 3 + + +,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/delete_stable.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -R +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/database_pre_suf.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/concat.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_str.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_math.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_time.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_26.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/select_null.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/select_null.py -R +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/select_null.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/select_null.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/select_null.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/slimit.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/slimit.py -R +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/slimit.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/slimit.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/slimit.py -Q 4 + +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/create_wrong_topic.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/dropDbR3ConflictTransaction.py -N 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/basic5.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb.py -N 3 -n 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb1.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb2.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb3.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb4.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb4.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/db.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqError.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/schema.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/stbFilter.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqCheckData.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqCheckData1.py +#,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsumerGroup.py +,,n,system-test,python3 ./test.py -f 7-tmq/tmqConsumerGroup.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqAlterSchema.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb.py -N 3 -n 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1.py -N 3 -n 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-1ctb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-1ctb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-1ctb-funcNFilter.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb-funcNFilter.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-1ctb-funcNFilter.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb-funcNFilter.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqAutoCreateTbl.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDnodeRestart.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDnodeRestart1.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUpdate-1ctb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUpdateWithConsume.py -N 3 -n 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUpdate-multiCtb-snapshot0.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUpdate-multiCtb-snapshot1.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDelete-1ctb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDelete-multiCtb.py -N 3 -n 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDropStbCtb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDropNtb-snapshot0.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDropNtb-snapshot1.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUdf.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUdf-multCtb-snapshot0.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUdf-multCtb-snapshot1.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/stbTagFilter-1ctb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/dataFromTsdbNWal.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/dataFromTsdbNWal-multiCtb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmq_taosx.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/raw_block_interface_test.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/stbTagFilter-multiCtb.py +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqSubscribeStb-r3.py -N 5 +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmq3mnodeSwitch.py -N 6 -M 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmq3mnodeSwitch.py -N 6 -M 3 -n 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TD-19201.py +,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TD-21561.py +,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TS-3404.py -#system test ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/balance_vgroups_r1.py -N 6 ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/taosShell.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/taosShellError.py @@ -423,9 +138,15 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/sysinfo.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/user_control.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/user_manage.py +,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/user_privilege.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/fsync.py +,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/multilevel.py ,,n,system-test,python3 ./test.py -f 0-others/compatibility.py +,,n,system-test,python3 ./test.py -f 0-others/tag_index_basic.py +,,n,system-test,python3 ./test.py -f 0-others/udfpy_main.py +,,n,system-test,python3 ./test.py -N 3 -f 0-others/walRetention.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/alter_database.py +,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/alter_replica.py -N 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/influxdb_line_taosc_insert.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/opentsdb_telnet_line_taosc_insert.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/opentsdb_json_taosc_insert.py @@ -444,8 +165,8 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/table_param_ttl.py -R ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/update_data_muti_rows.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/db_tb_name_check.py -,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/database_pre_suf.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/InsertFuturets.py +,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/insert_wide_column.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/show.py ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/information_schema.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/abs.py @@ -550,6 +271,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_partition.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_partition.py -R ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_min_last_interval.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/last_row_interval.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max.py -R ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/min.py @@ -624,11 +346,13 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/case_when.py -R ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/blockSMA.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/blockSMA.py -R +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/projectionDesc.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/projectionDesc.py -R ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/update_data.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/tb_100w_data_order.py -,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/delete_stable.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/delete_childtable.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/delete_normaltable.py +,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/delete_systable.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/keep_expired.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/drop.py ,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/drop.py -N 3 -M 3 -i False -n 3 @@ -636,16 +360,15 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/union1.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/concat2.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/json_tag.py -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQueryInterval.py -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_str.py -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_math.py -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_time.py + ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stablity.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stablity_1.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/elapsed.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/csum.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/function_diff.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tagFilter.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/projectionDesc.py ,,n,system-test,python3 ./test.py -f 2-query/queryQnode.py ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode1mnode.py ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode2mnode.py -N 5 @@ -660,6 +383,9 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateDb.py -N 6 -M 3 -n 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateDb.py -N 6 -M 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateDb.py -N 6 -M 3 -n 3 + +,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeModifyMeta.py -N 6 -M 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeModifyMeta.py -N 6 -M 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateStb.py -N 6 -M 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateStb.py -N 6 -M 3 -n 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateStb.py -N 6 -M 3 @@ -670,6 +396,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeRestartDnodeInsertData.py -N 6 -M 3 -n 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeRestartDnodeInsertDataAsync.py -N 6 -M 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeRestartDnodeInsertDataAsync.py -N 6 -M 3 -n 3 + ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeAdd1Ddnoe.py -N 7 -M 3 -C 6 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeAdd1Ddnoe.py -N 7 -M 3 -C 6 -n 3 #,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/5dnode3mnodeDrop.py -N 5 @@ -682,68 +409,6 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica3_insertdatas.py -N 4 -M 1 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica3_insertdatas_querys.py -N 4 -M 1 ,,y,system-test,./pytest.sh python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica3_vgroups.py -N 4 -M 1 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/create_wrong_topic.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/dropDbR3ConflictTransaction.py -N 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/basic5.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb.py -N 3 -n 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb0.py -N 3 -n 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb1.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb2.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb3.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeDb4.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb0.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb1.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb2.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb3.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/subscribeStb4.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/db.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqError.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/schema.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/stbFilter.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqCheckData.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqCheckData1.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsumerGroup.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqShow.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqAlterSchema.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb.py -N 3 -n 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1.py -N 3 -n 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-1ctb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-1ctb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-1ctb-funcNFilter.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb-funcNFilter.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-1ctb-funcNFilter.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb-funcNFilter.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqAutoCreateTbl.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDnodeRestart.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDnodeRestart1.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUpdate-1ctb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUpdateWithConsume.py -N 3 -n 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUpdate-multiCtb-snapshot0.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUpdate-multiCtb-snapshot1.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDelete-1ctb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDelete-multiCtb.py -N 3 -n 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDropStb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDropStbCtb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDropNtb-snapshot0.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqDropNtb-snapshot1.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUdf.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUdf-multCtb-snapshot0.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqUdf-multCtb-snapshot1.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/stbTagFilter-1ctb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/dataFromTsdbNWal.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/dataFromTsdbNWal-multiCtb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmq_taosx.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/stbTagFilter-multiCtb.py -,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TD-19201.py -,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TD-21561.py -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmqSubscribeStb-r3.py -N 5 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmq3mnodeSwitch.py -N 6 -M 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 7-tmq/tmq3mnodeSwitch.py -N 6 -M 3 -n 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/between.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/distinct.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/varchar.py -Q 2 @@ -803,11 +468,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/arctan.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/query_cols_tags_and_or.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/interp.py -Q 2 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQueryInterval.py -Q 2 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_str.py -Q 2 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_math.py -Q 2 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_time.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stablity.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stablity_1.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/avg.py -Q 2 @@ -836,12 +497,15 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/count_partition.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_partition.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_min_last_interval.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/last_row_interval.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/last_row.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tsbsQuery.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/sml.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/case_when.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/blockSMA.py -Q 2 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/projectionDesc.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TD-21561.py -Q 2 + ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/between.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/distinct.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/varchar.py -Q 3 @@ -857,7 +521,6 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/substr.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/union.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/union1.py -Q 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/concat.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/concat2.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/concat_ws.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/concat_ws2.py -Q 3 @@ -900,11 +563,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/arccos.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/arctan.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/query_cols_tags_and_or.py -Q 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQueryInterval.py -Q 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_str.py -Q 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_math.py -Q 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_time.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stablity.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stablity_1.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/avg.py -Q 3 @@ -933,12 +592,14 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/count_partition.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_partition.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_min_last_interval.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/last_row_interval.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/last_row.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tsbsQuery.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/sml.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/interp.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/case_when.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/blockSMA.py -Q 3 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/projectionDesc.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TD-21561.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/between.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/distinct.py -Q 4 @@ -978,7 +639,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/timetruncate.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/diff.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/Timediff.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/json_tag.py -Q 4 +#,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/json_tag.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/top.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/bottom.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/percentile.py -Q 4 @@ -997,11 +658,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/arccos.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/arctan.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/query_cols_tags_and_or.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQueryInterval.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_str.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_math.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/nestedQuery_time.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stablity.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stablity_1.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/avg.py -Q 4 @@ -1012,9 +669,9 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/cast.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/function_diff.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/unique.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stateduration.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/function_stateduration.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/statecount.py -Q 4 +#,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/stateduration.py -Q 4 +#,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/function_stateduration.py -Q 4 +#,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/statecount.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tail.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/ttl_comment.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/distribute_agg_count.py -Q 4 @@ -1031,6 +688,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/count_partition.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_partition.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_min_last_interval.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/last_row_interval.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/last_row.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tsbsQuery.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/sml.py -Q 4 @@ -1041,25 +699,432 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_select.py -Q 2 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_select.py -Q 3 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_select.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -R -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -Q 2 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -Q 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/insert_null_none.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py -R -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py -Q 2 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py -Q 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/out_of_order.py -Q 4 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_min_data.py -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_min_data.py -R -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_min_data.py -Q 2 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_min_data.py -Q 3 -,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/max_min_data.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/blockSMA.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/projectionDesc.py -Q 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/odbc.py ,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TD-21561.py -Q 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 99-TDcase/TD-20582.py +#tsim test +,,y,script,./test.sh -f tsim/tmq/basic2Of2ConsOverlap.sim +,,y,script,./test.sh -f tsim/parser/where.sim +,,y,script,./test.sh -f tsim/parser/join_manyblocks.sim +,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v1_leader.sim +,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v1_follower.sim +,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v2.sim +,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v3.sim +,,y,script,./test.sh -f tsim/parser/limit1.sim +,,y,script,./test.sh -f tsim/parser/union.sim +,,y,script,./test.sh -f tsim/parser/commit.sim +,,y,script,./test.sh -f tsim/parser/nestquery.sim +,,n,script,./test.sh -f tsim/valgrind/checkError7.sim +,,y,script,./test.sh -f tsim/parser/groupby.sim +,,y,script,./test.sh -f tsim/parser/sliding.sim +,,y,script,./test.sh -f tsim/dnode/balance2.sim +,,y,script,./test.sh -f tsim/vnode/replica3_repeat.sim +,,y,script,./test.sh -f tsim/parser/col_arithmetic_operation.sim +,,y,script,./test.sh -f tsim/trans/create_db.sim +,,y,script,./test.sh -f tsim/dnode/balance3.sim +,,y,script,./test.sh -f tsim/vnode/replica3_many.sim +,,y,script,./test.sh -f tsim/stable/metrics_idx.sim +,,y,script,./test.sh -f tsim/db/alter_replica_13.sim +,,y,script,./test.sh -f tsim/sync/3Replica1VgElect.sim +,,y,script,./test.sh -f tsim/sync/3Replica5VgElect.sim +,,n,script,./test.sh -f tsim/valgrind/checkError6.sim + +,,y,script,./test.sh -f tsim/user/basic.sim +,,y,script,./test.sh -f tsim/user/password.sim +,,y,script,./test.sh -f tsim/user/privilege_db.sim +,,y,script,./test.sh -f tsim/user/privilege_sysinfo.sim +,,y,script,./test.sh -f tsim/user/privilege_topic.sim +,,y,script,./test.sh -f tsim/user/privilege_table.sim +,,y,script,./test.sh -f tsim/db/alter_option.sim +,,y,script,./test.sh -f tsim/db/alter_replica_31.sim +,,y,script,./test.sh -f tsim/db/basic1.sim +,,y,script,./test.sh -f tsim/db/basic2.sim +,,y,script,./test.sh -f tsim/db/basic3.sim +,,y,script,./test.sh -f tsim/db/basic4.sim +,,y,script,./test.sh -f tsim/db/basic5.sim +,,y,script,./test.sh -f tsim/db/basic6.sim +,,y,script,./test.sh -f tsim/db/commit.sim +,,y,script,./test.sh -f tsim/db/create_all_options.sim +,,y,script,./test.sh -f tsim/db/delete_reuse1.sim +,,y,script,./test.sh -f tsim/db/delete_reuse2.sim +,,y,script,./test.sh -f tsim/db/delete_reusevnode.sim +,,y,script,./test.sh -f tsim/db/delete_reusevnode2.sim +,,y,script,./test.sh -f tsim/db/delete_writing1.sim +,,y,script,./test.sh -f tsim/db/delete_writing2.sim +,,y,script,./test.sh -f tsim/db/error1.sim +,,y,script,./test.sh -f tsim/db/keep.sim +,,y,script,./test.sh -f tsim/db/len.sim +,,y,script,./test.sh -f tsim/db/repeat.sim +,,y,script,./test.sh -f tsim/db/show_create_db.sim +,,y,script,./test.sh -f tsim/db/show_create_table.sim +,,y,script,./test.sh -f tsim/db/tables.sim +,,y,script,./test.sh -f tsim/db/taosdlog.sim +,,y,script,./test.sh -f tsim/db/table_prefix_suffix.sim +,,y,script,./test.sh -f tsim/dnode/balance_replica1.sim +,,y,script,./test.sh -f tsim/dnode/balance_replica3.sim +,,y,script,./test.sh -f tsim/dnode/balance1.sim +,,y,script,./test.sh -f tsim/dnode/balancex.sim +,,y,script,./test.sh -f tsim/dnode/create_dnode.sim +,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_mnode.sim +,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_qnode_snode.sim +,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_vnode_replica1.sim +,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_vnode_replica3.sim +,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_multi_vnode_replica1.sim +,,y,script,./test.sh -f tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim +,,y,script,./test.sh -f tsim/dnode/drop_dnode_force.sim +,,y,script,./test.sh -f tsim/dnode/offline_reason.sim +,,y,script,./test.sh -f tsim/dnode/redistribute_vgroup_replica1.sim +,,y,script,./test.sh -f tsim/dnode/vnode_clean.sim +,,y,script,./test.sh -f tsim/dnode/use_dropped_dnode.sim +,,y,script,./test.sh -f tsim/dnode/split_vgroup_replica1.sim +,,y,script,./test.sh -f tsim/dnode/split_vgroup_replica3.sim +,,y,script,./test.sh -f tsim/import/basic.sim +,,y,script,./test.sh -f tsim/import/commit.sim +,,y,script,./test.sh -f tsim/import/large.sim +,,y,script,./test.sh -f tsim/import/replica1.sim +,,y,script,./test.sh -f tsim/insert/backquote.sim +,,y,script,./test.sh -f tsim/insert/basic.sim +,,y,script,./test.sh -f tsim/insert/basic0.sim +,,y,script,./test.sh -f tsim/insert/basic1.sim +,,y,script,./test.sh -f tsim/insert/basic2.sim +,,y,script,./test.sh -f tsim/insert/commit-merge0.sim +,,y,script,./test.sh -f tsim/insert/insert_drop.sim +,,y,script,./test.sh -f tsim/insert/insert_select.sim +,,y,script,./test.sh -f tsim/insert/null.sim +,,y,script,./test.sh -f tsim/insert/query_block1_file.sim +,,y,script,./test.sh -f tsim/insert/query_block1_memory.sim +,,y,script,./test.sh -f tsim/insert/query_block2_file.sim +,,y,script,./test.sh -f tsim/insert/query_block2_memory.sim +,,y,script,./test.sh -f tsim/insert/query_file_memory.sim +,,y,script,./test.sh -f tsim/insert/query_multi_file.sim +,,y,script,./test.sh -f tsim/insert/tcp.sim +,,y,script,./test.sh -f tsim/insert/update0.sim +,,y,script,./test.sh -f tsim/insert/delete0.sim +,,y,script,./test.sh -f tsim/insert/update1_sort_merge.sim +,,y,script,./test.sh -f tsim/insert/update2.sim +,,y,script,./test.sh -f tsim/parser/alter__for_community_version.sim +,,y,script,./test.sh -f tsim/parser/alter_column.sim +,,y,script,./test.sh -f tsim/parser/alter_stable.sim +,,y,script,./test.sh -f tsim/parser/alter.sim +,,y,script,./test.sh -f tsim/parser/alter1.sim +,,y,script,./test.sh -f tsim/parser/auto_create_tb_drop_tb.sim +,,y,script,./test.sh -f tsim/parser/auto_create_tb.sim +,,y,script,./test.sh -f tsim/parser/between_and.sim +,,y,script,./test.sh -f tsim/parser/binary_escapeCharacter.sim +,,y,script,./test.sh -f tsim/parser/columnValue_bigint.sim +,,y,script,./test.sh -f tsim/parser/columnValue_bool.sim +,,y,script,./test.sh -f tsim/parser/columnValue_double.sim +,,y,script,./test.sh -f tsim/parser/columnValue_float.sim +,,y,script,./test.sh -f tsim/parser/columnValue_int.sim +,,y,script,./test.sh -f tsim/parser/columnValue_smallint.sim +,,y,script,./test.sh -f tsim/parser/columnValue_tinyint.sim +,,y,script,./test.sh -f tsim/parser/columnValue_unsign.sim +,,y,script,./test.sh -f tsim/parser/condition.sim +,,y,script,./test.sh -f tsim/parser/constCol.sim +,,y,script,./test.sh -f tsim/parser/create_db.sim +,,y,script,./test.sh -f tsim/parser/create_mt.sim +,,y,script,./test.sh -f tsim/parser/create_tb_with_tag_name.sim +,,y,script,./test.sh -f tsim/parser/create_tb.sim +,,y,script,./test.sh -f tsim/parser/dbtbnameValidate.sim +,,y,script,./test.sh -f tsim/parser/distinct.sim +,,y,script,./test.sh -f tsim/parser/fill_us.sim +,,y,script,./test.sh -f tsim/parser/fill.sim +,,y,script,./test.sh -f tsim/parser/first_last.sim +,,y,script,./test.sh -f tsim/parser/fill_stb.sim +,,y,script,./test.sh -f tsim/parser/interp.sim +,,y,script,./test.sh -f tsim/parser/fourArithmetic-basic.sim +,,y,script,./test.sh -f tsim/parser/function.sim +,,y,script,./test.sh -f tsim/parser/groupby-basic.sim +,,y,script,./test.sh -f tsim/parser/having_child.sim +,,y,script,./test.sh -f tsim/parser/having.sim +,,y,script,./test.sh -f tsim/parser/import_commit1.sim +,,y,script,./test.sh -f tsim/parser/import_commit2.sim +,,y,script,./test.sh -f tsim/parser/import_commit3.sim +,,y,script,./test.sh -f tsim/parser/import_file.sim +,,y,script,./test.sh -f tsim/parser/import.sim +,,y,script,./test.sh -f tsim/parser/insert_multiTbl.sim +,,y,script,./test.sh -f tsim/parser/insert_tb.sim +,,y,script,./test.sh -f tsim/parser/join_multitables.sim +,,y,script,./test.sh -f tsim/parser/join_multivnode.sim +,,y,script,./test.sh -f tsim/parser/join.sim +,,y,script,./test.sh -f tsim/parser/last_cache.sim +,,y,script,./test.sh -f tsim/parser/last_groupby.sim +,,y,script,./test.sh -f tsim/parser/lastrow.sim +,,y,script,./test.sh -f tsim/parser/lastrow2.sim +,,y,script,./test.sh -f tsim/parser/like.sim +,,y,script,./test.sh -f tsim/parser/limit.sim +,,y,script,./test.sh -f tsim/parser/mixed_blocks.sim +,,y,script,./test.sh -f tsim/parser/nchar.sim +,,y,script,./test.sh -f tsim/parser/null_char.sim +,,y,script,./test.sh -f tsim/parser/precision_ns.sim +,,y,script,./test.sh -f tsim/parser/projection_limit_offset.sim +,,y,script,./test.sh -f tsim/parser/regex.sim +,,y,script,./test.sh -f tsim/parser/regressiontest.sim +,,y,script,./test.sh -f tsim/parser/select_across_vnodes.sim +,,y,script,./test.sh -f tsim/parser/select_distinct_tag.sim +,,y,script,./test.sh -f tsim/parser/select_from_cache_disk.sim +,,y,script,./test.sh -f tsim/parser/select_with_tags.sim +,,y,script,./test.sh -f tsim/parser/selectResNum.sim +,,y,script,./test.sh -f tsim/parser/set_tag_vals.sim +,,y,script,./test.sh -f tsim/parser/single_row_in_tb.sim +,,y,script,./test.sh -f tsim/parser/slimit_alter_tags.sim +,,y,script,./test.sh -f tsim/parser/slimit.sim +,,y,script,./test.sh -f tsim/parser/slimit1.sim +,,y,script,./test.sh -f tsim/parser/stableOp.sim +,,y,script,./test.sh -f tsim/parser/tags_dynamically_specifiy.sim +,,y,script,./test.sh -f tsim/parser/tags_filter.sim +,,y,script,./test.sh -f tsim/parser/tbnameIn.sim +,,y,script,./test.sh -f tsim/parser/timestamp.sim +,,y,script,./test.sh -f tsim/parser/top_groupby.sim +,,y,script,./test.sh -f tsim/parser/topbot.sim +,,y,script,./test.sh -f tsim/parser/union_sysinfo.sim +,,y,script,./test.sh -f tsim/parser/slimit_limit.sim +,,y,script,./test.sh -f tsim/parser/table_merge_limit.sim +,,y,script,./test.sh -f tsim/query/tagLikeFilter.sim +,,y,script,./test.sh -f tsim/query/charScalarFunction.sim +,,y,script,./test.sh -f tsim/query/explain.sim +,,y,script,./test.sh -f tsim/query/interval-offset.sim +,,y,script,./test.sh -f tsim/query/interval.sim +,,y,script,./test.sh -f tsim/query/scalarFunction.sim +,,y,script,./test.sh -f tsim/query/scalarNull.sim +,,y,script,./test.sh -f tsim/query/session.sim +,,y,script,./test.sh -f tsim/query/udf.sim +,,n,script,./test.sh -f tsim/query/udfpy.sim +,,y,script,./test.sh -f tsim/query/udf_with_const.sim +,,y,script,./test.sh -f tsim/query/join_interval.sim +,,y,script,./test.sh -f tsim/query/unionall_as_table.sim +,,y,script,./test.sh -f tsim/query/multi_order_by.sim +,,y,script,./test.sh -f tsim/query/sys_tbname.sim +,,y,script,./test.sh -f tsim/query/groupby.sim +,,y,script,./test.sh -f tsim/query/event.sim +,,y,script,./test.sh -f tsim/query/forceFill.sim +,,y,script,./test.sh -f tsim/query/emptyTsRange.sim +,,y,script,./test.sh -f tsim/query/partitionby.sim +,,y,script,./test.sh -f tsim/query/tableCount.sim +,,y,script,./test.sh -f tsim/query/nullColSma.sim +,,y,script,./test.sh -f tsim/query/bug3398.sim +,,y,script,./test.sh -f tsim/qnode/basic1.sim +,,y,script,./test.sh -f tsim/snode/basic1.sim +,,y,script,./test.sh -f tsim/mnode/basic1.sim +,,y,script,./test.sh -f tsim/mnode/basic2.sim +,,y,script,./test.sh -f tsim/mnode/basic3.sim +,,y,script,./test.sh -f tsim/mnode/basic4.sim +,,y,script,./test.sh -f tsim/mnode/basic5.sim +,,y,script,./test.sh -f tsim/show/basic.sim +,,y,script,./test.sh -f tsim/table/autocreate.sim +,,y,script,./test.sh -f tsim/table/basic1.sim +,,y,script,./test.sh -f tsim/table/basic2.sim +,,y,script,./test.sh -f tsim/table/basic3.sim +,,y,script,./test.sh -f tsim/table/bigint.sim +,,y,script,./test.sh -f tsim/table/binary.sim +,,y,script,./test.sh -f tsim/table/bool.sim +,,y,script,./test.sh -f tsim/table/column_name.sim +,,y,script,./test.sh -f tsim/table/column_num.sim +,,y,script,./test.sh -f tsim/table/column_value.sim +,,y,script,./test.sh -f tsim/table/column2.sim +,,y,script,./test.sh -f tsim/table/createmulti.sim +,,y,script,./test.sh -f tsim/table/date.sim +,,y,script,./test.sh -f tsim/table/db.table.sim +,,y,script,./test.sh -f tsim/table/delete_reuse1.sim +,,y,script,./test.sh -f tsim/table/delete_reuse2.sim +,,y,script,./test.sh -f tsim/table/delete_writing.sim +,,y,script,./test.sh -f tsim/table/describe.sim +,,y,script,./test.sh -f tsim/table/double.sim +,,y,script,./test.sh -f tsim/table/float.sim +,,y,script,./test.sh -f tsim/table/hash.sim +,,y,script,./test.sh -f tsim/table/int.sim +,,y,script,./test.sh -f tsim/table/limit.sim +,,y,script,./test.sh -f tsim/table/smallint.sim +,,y,script,./test.sh -f tsim/table/table_len.sim +,,y,script,./test.sh -f tsim/table/table.sim +,,y,script,./test.sh -f tsim/table/tinyint.sim +,,y,script,./test.sh -f tsim/table/vgroup.sim +,,n,script,./test.sh -f tsim/stream/basic0.sim -g +,,y,script,./test.sh -f tsim/stream/basic1.sim +,,y,script,./test.sh -f tsim/stream/basic2.sim +,,y,script,./test.sh -f tsim/stream/drop_stream.sim +,,y,script,./test.sh -f tsim/stream/fillHistoryBasic1.sim +,,y,script,./test.sh -f tsim/stream/fillHistoryBasic2.sim +,,y,script,./test.sh -f tsim/stream/fillHistoryBasic3.sim +,,y,script,./test.sh -f tsim/stream/distributeInterval0.sim +,,y,script,./test.sh -f tsim/stream/distributeIntervalRetrive0.sim +,,y,script,./test.sh -f tsim/stream/distributeSession0.sim +,,y,script,./test.sh -f tsim/stream/session0.sim +,,y,script,./test.sh -f tsim/stream/session1.sim +,,y,script,./test.sh -f tsim/stream/state0.sim +,,y,script,./test.sh -f tsim/stream/triggerInterval0.sim +,,y,script,./test.sh -f tsim/stream/triggerSession0.sim +,,y,script,./test.sh -f tsim/stream/partitionby.sim +,,y,script,./test.sh -f tsim/stream/partitionby1.sim +,,y,script,./test.sh -f tsim/stream/schedSnode.sim +,,y,script,./test.sh -f tsim/stream/windowClose.sim +,,y,script,./test.sh -f tsim/stream/ignoreExpiredData.sim +,,y,script,./test.sh -f tsim/stream/sliding.sim +,,y,script,./test.sh -f tsim/stream/partitionbyColumnInterval.sim +,,y,script,./test.sh -f tsim/stream/partitionbyColumnSession.sim +,,y,script,./test.sh -f tsim/stream/partitionbyColumnState.sim +,,y,script,./test.sh -f tsim/stream/deleteInterval.sim +,,y,script,./test.sh -f tsim/stream/deleteSession.sim +,,y,script,./test.sh -f tsim/stream/deleteState.sim +,,y,script,./test.sh -f tsim/stream/fillIntervalDelete0.sim +,,y,script,./test.sh -f tsim/stream/fillIntervalDelete1.sim +,,y,script,./test.sh -f tsim/stream/fillIntervalLinear.sim +,,y,script,./test.sh -f tsim/stream/fillIntervalPartitionBy.sim +,,y,script,./test.sh -f tsim/stream/fillIntervalPrevNext.sim +,,y,script,./test.sh -f tsim/stream/fillIntervalValue.sim +,,y,script,./test.sh -f tsim/stream/udTableAndTag0.sim +,,y,script,./test.sh -f tsim/stream/udTableAndTag1.sim +,,y,script,./test.sh -f tsim/trans/lossdata1.sim +,,y,script,./test.sh -f tsim/tmq/basic1.sim +,,y,script,./test.sh -f tsim/tmq/basic2.sim +,,y,script,./test.sh -f tsim/tmq/basic3.sim +,,y,script,./test.sh -f tsim/tmq/basic4.sim +,,y,script,./test.sh -f tsim/tmq/basic1Of2Cons.sim +,,y,script,./test.sh -f tsim/tmq/basic2Of2Cons.sim +,,y,script,./test.sh -f tsim/tmq/basic3Of2Cons.sim +,,y,script,./test.sh -f tsim/tmq/basic4Of2Cons.sim +,,y,script,./test.sh -f tsim/tmq/topic.sim +,,y,script,./test.sh -f tsim/tmq/snapshot.sim +,,y,script,./test.sh -f tsim/tmq/snapshot1.sim +,,y,script,./test.sh -f tsim/stable/alter_comment.sim +,,y,script,./test.sh -f tsim/stable/alter_count.sim +,,y,script,./test.sh -f tsim/stable/alter_import.sim +,,y,script,./test.sh -f tsim/stable/alter_insert1.sim +,,y,script,./test.sh -f tsim/stable/alter_insert2.sim +,,y,script,./test.sh -f tsim/stable/alter_metrics.sim +,,y,script,./test.sh -f tsim/stable/column_add.sim +,,y,script,./test.sh -f tsim/stable/column_drop.sim +,,y,script,./test.sh -f tsim/stable/column_modify.sim +,,y,script,./test.sh -f tsim/stable/disk.sim +,,y,script,./test.sh -f tsim/stable/dnode3.sim +,,y,script,./test.sh -f tsim/stable/metrics.sim +,,y,script,./test.sh -f tsim/stable/refcount.sim +,,y,script,./test.sh -f tsim/stable/tag_add.sim +,,y,script,./test.sh -f tsim/stable/tag_drop.sim +,,y,script,./test.sh -f tsim/stable/tag_filter.sim +,,y,script,./test.sh -f tsim/stable/tag_modify.sim +,,y,script,./test.sh -f tsim/stable/tag_rename.sim +,,y,script,./test.sh -f tsim/stable/values.sim +,,y,script,./test.sh -f tsim/stable/vnode3.sim +,,n,script,./test.sh -f tsim/sma/drop_sma.sim +,,y,script,./test.sh -f tsim/sma/sma_leak.sim +,,y,script,./test.sh -f tsim/sma/tsmaCreateInsertQuery.sim +,,y,script,./test.sh -f tsim/sma/rsmaCreateInsertQuery.sim +,,y,script,./test.sh -f tsim/sma/rsmaPersistenceRecovery.sim +,,n,script,./test.sh -f tsim/valgrind/checkError1.sim +,,n,script,./test.sh -f tsim/valgrind/checkError2.sim +,,n,script,./test.sh -f tsim/valgrind/checkError3.sim +,,n,script,./test.sh -f tsim/valgrind/checkError4.sim +,,n,script,./test.sh -f tsim/valgrind/checkError5.sim +,,n,script,./test.sh -f tsim/valgrind/checkError8.sim +,,n,script,./test.sh -f tsim/valgrind/checkUdf.sim +,,y,script,./test.sh -f tsim/vnode/replica3_basic.sim +,,y,script,./test.sh -f tsim/vnode/replica3_vgroup.sim +,,y,script,./test.sh -f tsim/vnode/replica3_import.sim +,,y,script,./test.sh -f tsim/vnode/stable_balance_replica1.sim +,,y,script,./test.sh -f tsim/vnode/stable_dnode2_stop.sim +,,y,script,./test.sh -f tsim/vnode/stable_dnode2.sim +,,y,script,./test.sh -f tsim/vnode/stable_dnode3.sim +,,y,script,./test.sh -f tsim/vnode/stable_replica3_dnode6.sim +,,y,script,./test.sh -f tsim/vnode/stable_replica3_vnode3.sim +,,y,script,./test.sh -f tsim/sync/oneReplica1VgElect.sim +,,y,script,./test.sh -f tsim/sync/oneReplica5VgElect.sim +,,y,script,./test.sh -f tsim/catalog/alterInCurrent.sim +,,y,script,./test.sh -f tsim/scalar/in.sim +,,y,script,./test.sh -f tsim/scalar/scalar.sim +,,y,script,./test.sh -f tsim/scalar/filter.sim +,,y,script,./test.sh -f tsim/scalar/caseWhen.sim +,,y,script,./test.sh -f tsim/scalar/tsConvert.sim +,,y,script,./test.sh -f tsim/alter/cached_schema_after_alter.sim +,,y,script,./test.sh -f tsim/alter/dnode.sim +,,y,script,./test.sh -f tsim/alter/table.sim +,,y,script,./test.sh -f tsim/cache/new_metrics.sim +,,y,script,./test.sh -f tsim/cache/restart_table.sim +,,y,script,./test.sh -f tsim/cache/restart_metrics.sim +,,y,script,./test.sh -f tsim/column/commit.sim +,,y,script,./test.sh -f tsim/column/metrics.sim +,,y,script,./test.sh -f tsim/column/table.sim +,,y,script,./test.sh -f tsim/compress/commitlog.sim +,,y,script,./test.sh -f tsim/compress/compress2.sim +,,y,script,./test.sh -f tsim/compress/compress.sim +,,y,script,./test.sh -f tsim/compress/uncompress.sim +,,y,script,./test.sh -f tsim/compute/avg.sim +,,y,script,./test.sh -f tsim/compute/block_dist.sim +,,y,script,./test.sh -f tsim/compute/bottom.sim +,,y,script,./test.sh -f tsim/compute/count.sim +,,y,script,./test.sh -f tsim/compute/diff.sim +,,y,script,./test.sh -f tsim/compute/diff2.sim +,,y,script,./test.sh -f tsim/compute/first.sim +,,y,script,./test.sh -f tsim/compute/interval.sim +,,y,script,./test.sh -f tsim/compute/last_row.sim +,,y,script,./test.sh -f tsim/compute/last.sim +,,y,script,./test.sh -f tsim/compute/leastsquare.sim +,,y,script,./test.sh -f tsim/compute/max.sim +,,y,script,./test.sh -f tsim/compute/min.sim +,,y,script,./test.sh -f tsim/compute/null.sim +,,y,script,./test.sh -f tsim/compute/percentile.sim +,,y,script,./test.sh -f tsim/compute/stddev.sim +,,y,script,./test.sh -f tsim/compute/sum.sim +,,y,script,./test.sh -f tsim/compute/top.sim +,,y,script,./test.sh -f tsim/field/2.sim +,,y,script,./test.sh -f tsim/field/3.sim +,,y,script,./test.sh -f tsim/field/4.sim +,,y,script,./test.sh -f tsim/field/5.sim +,,y,script,./test.sh -f tsim/field/6.sim +,,y,script,./test.sh -f tsim/field/binary.sim +,,y,script,./test.sh -f tsim/field/bigint.sim +,,y,script,./test.sh -f tsim/field/bool.sim +,,y,script,./test.sh -f tsim/field/double.sim +,,y,script,./test.sh -f tsim/field/float.sim +,,y,script,./test.sh -f tsim/field/int.sim +,,y,script,./test.sh -f tsim/field/single.sim +,,y,script,./test.sh -f tsim/field/smallint.sim +,,y,script,./test.sh -f tsim/field/tinyint.sim +,,y,script,./test.sh -f tsim/field/unsigined_bigint.sim +,,y,script,./test.sh -f tsim/vector/metrics_field.sim +,,y,script,./test.sh -f tsim/vector/metrics_mix.sim +,,y,script,./test.sh -f tsim/vector/metrics_query.sim +,,y,script,./test.sh -f tsim/vector/metrics_tag.sim +,,y,script,./test.sh -f tsim/vector/metrics_time.sim +,,y,script,./test.sh -f tsim/vector/multi.sim +,,y,script,./test.sh -f tsim/vector/single.sim +,,y,script,./test.sh -f tsim/vector/table_field.sim +,,y,script,./test.sh -f tsim/vector/table_mix.sim +,,y,script,./test.sh -f tsim/vector/table_query.sim +,,y,script,./test.sh -f tsim/vector/table_time.sim +,,y,script,./test.sh -f tsim/wal/kill.sim +,,y,script,./test.sh -f tsim/tag/3.sim +,,y,script,./test.sh -f tsim/tag/4.sim +,,y,script,./test.sh -f tsim/tag/5.sim +,,y,script,./test.sh -f tsim/tag/6.sim +,,y,script,./test.sh -f tsim/tag/add.sim +,,y,script,./test.sh -f tsim/tag/bigint.sim +,,y,script,./test.sh -f tsim/tag/binary_binary.sim +,,y,script,./test.sh -f tsim/tag/binary.sim +,,y,script,./test.sh -f tsim/tag/bool_binary.sim +,,y,script,./test.sh -f tsim/tag/bool_int.sim +,,y,script,./test.sh -f tsim/tag/bool.sim +,,y,script,./test.sh -f tsim/tag/change.sim +,,y,script,./test.sh -f tsim/tag/column.sim +,,y,script,./test.sh -f tsim/tag/commit.sim +,,y,script,./test.sh -f tsim/tag/create.sim +,,y,script,./test.sh -f tsim/tag/delete.sim +,,y,script,./test.sh -f tsim/tag/double.sim +,,y,script,./test.sh -f tsim/tag/filter.sim +,,y,script,./test.sh -f tsim/tag/float.sim +,,y,script,./test.sh -f tsim/tag/int_binary.sim +,,y,script,./test.sh -f tsim/tag/int_float.sim +,,y,script,./test.sh -f tsim/tag/int.sim +,,y,script,./test.sh -f tsim/tag/set.sim +,,y,script,./test.sh -f tsim/tag/smallint.sim +,,y,script,./test.sh -f tsim/tag/tinyint.sim +,,y,script,./test.sh -f tsim/tag/drop_tag.sim +,,y,script,./test.sh -f tsim/tag/tbNameIn.sim +,,y,script,./test.sh -f tmp/monitor.sim #develop test ,,n,develop-test,python3 ./test.py -f 2-query/table_count_scan.py ,,n,develop-test,python3 ./test.py -f 2-query/show_create_db.py @@ -1081,4 +1146,4 @@ ,,n,docs-examples-test,bash node.sh ,,n,docs-examples-test,bash csharp.sh ,,n,docs-examples-test,bash jdbc.sh -#,,n,docs-examples-test,bash go.sh +,,n,docs-examples-test,bash go.sh diff --git a/tests/parallel_test/container_build.sh b/tests/parallel_test/container_build.sh index ff854449bb913bea8bf5dd1b6477d7d9c7a7b70e..cfb5a26723602cee56f5e3332cc8a47bd4a3ec92 100755 --- a/tests/parallel_test/container_build.sh +++ b/tests/parallel_test/container_build.sh @@ -51,11 +51,25 @@ else REP_DIR=/home/TDinternal REP_REAL_PATH=$WORKDIR/TDinternal REP_MOUNT_PARAM=$REP_REAL_PATH:/home/TDinternal + fi date docker run \ -v $REP_MOUNT_PARAM \ - --rm --ulimit core=-1 taos_test:v1.0 sh -c "cd $REP_DIR;rm -rf debug;mkdir -p debug;cd debug;cmake .. -DBUILD_HTTP=false -DBUILD_TOOLS=true -DBUILD_TEST=true -DWEBSOCKET=true -DBUILD_TAOSX=true;make -j || exit 1" + -v /root/.cargo/registry:/root/.cargo/registry \ + -v /root/.cargo/git:/root/.cargo/git \ + -v /root/go/pkg/mod:/root/go/pkg/mod \ + -v /root/.cache/go-build:/root/.cache/go-build \ + -v ${REP_REAL_PATH}/enterprise/src/plugins/taosx/target:${REP_DIR}/enterprise/src/plugins/taosx/target \ + -v ${REP_REAL_PATH}/community/tools/taosws-rs/target:${REP_DIR}/community/tools/taosws-rs/target \ + -v ${REP_REAL_PATH}/community/contrib/cJson/:${REP_DIR}/community/contrib/cJson \ + -v ${REP_REAL_PATH}/community/contrib/googletest/:${REP_DIR}/community/contrib/googletest \ + -v ${REP_REAL_PATH}/community/contrib/cpp-stub/:${REP_DIR}/community/contrib/cpp-stub \ + -v ${REP_REAL_PATH}/community/contrib/libuv/:${REP_DIR}/community/contrib/libuv \ + -v ${REP_REAL_PATH}/community/contrib/lz4/:${REP_DIR}/community/contrib/lz4 \ + -v ${REP_REAL_PATH}/community/contrib/zlib/:${REP_DIR}/community/contrib/zlib \ + -v ${REP_REAL_PATH}/community/contrib/jemalloc/:${REP_DIR}/community/contrib/jemalloc \ + --rm --ulimit core=-1 taos_test:v1.0 sh -c "pip uninstall taospy -y;pip3 install taospy==2.7.2;cd $REP_DIR;rm -rf debug;mkdir -p debug;cd debug;cmake .. -DBUILD_HTTP=false -DBUILD_TOOLS=true -DBUILD_TEST=true -DWEBSOCKET=true -DBUILD_TAOSX=true -DJEMALLOC_ENABLED=true;make -j || exit 1" if [[ -d ${WORKDIR}/debugNoSan ]] ;then echo "delete ${WORKDIR}/debugNoSan" @@ -70,7 +84,20 @@ mv ${REP_REAL_PATH}/debug ${WORKDIR}/debugNoSan date docker run \ -v $REP_MOUNT_PARAM \ - --rm --ulimit core=-1 taos_test:v1.0 sh -c "cd $REP_DIR;rm -rf debug;mkdir -p debug;cd debug;cmake .. -DBUILD_HTTP=false -DBUILD_TOOLS=true -DBUILD_TEST=true -DWEBSOCKET=true -DBUILD_SANITIZER=1 -DTOOLS_SANITIZE=true -DTOOLS_BUILD_TYPE=Debug -DBUILD_TAOSX=true;make -j || exit 1 " + -v /root/.cargo/registry:/root/.cargo/registry \ + -v /root/.cargo/git:/root/.cargo/git \ + -v /root/go/pkg/mod:/root/go/pkg/mod \ + -v /root/.cache/go-build:/root/.cache/go-build \ + -v ${REP_REAL_PATH}/enterprise/src/plugins/taosx/target:${REP_DIR}/enterprise/src/plugins/taosx/target \ + -v ${REP_REAL_PATH}/community/tools/taosws-rs/target:${REP_DIR}/community/tools/taosws-rs/target \ + -v ${REP_REAL_PATH}/community/contrib/cJson/:${REP_DIR}/community/contrib/cJson \ + -v ${REP_REAL_PATH}/community/contrib/googletest/:${REP_DIR}/community/contrib/googletest \ + -v ${REP_REAL_PATH}/community/contrib/cpp-stub/:${REP_DIR}/community/contrib/cpp-stub \ + -v ${REP_REAL_PATH}/community/contrib/libuv/:${REP_DIR}/community/contrib/libuv \ + -v ${REP_REAL_PATH}/community/contrib/lz4/:${REP_DIR}/community/contrib/lz4 \ + -v ${REP_REAL_PATH}/community/contrib/zlib/:${REP_DIR}/community/contrib/zlib \ + -v ${REP_REAL_PATH}/community/contrib/jemalloc/:${REP_DIR}/community/contrib/jemalloc \ + --rm --ulimit core=-1 taos_test:v1.0 sh -c "pip uninstall taospy -y;pip3 install taospy==2.7.2;cd $REP_DIR;rm -rf debug;mkdir -p debug;cd debug;cmake .. -DBUILD_HTTP=false -DBUILD_TOOLS=true -DBUILD_TEST=true -DWEBSOCKET=true -DBUILD_SANITIZER=1 -DTOOLS_SANITIZE=true -DTOOLS_BUILD_TYPE=Debug -DBUILD_TAOSX=true -DJEMALLOC_ENABLED=true;make -j || exit 1 " mv ${REP_REAL_PATH}/debug ${WORKDIR}/debugSan diff --git a/tests/parallel_test/run.sh b/tests/parallel_test/run.sh index 43533d4f3688922d0f7670e5a74218a606c11f12..f05e0dfc83d00191a2b2b7f2812a4db62f2863bf 100755 --- a/tests/parallel_test/run.sh +++ b/tests/parallel_test/run.sh @@ -167,8 +167,10 @@ function run_thread() { local case_build_san=`echo "$line"|cut -d, -f3` if [ "${case_build_san}" == "y" ]; then case_build_san="y" + DEBUGPATH="debugSan" elif [[ "${case_build_san}" == "n" ]] || [[ "${case_build_san}" == "" ]]; then case_build_san="n" + DEBUGPATH="debugNoSan" else usage exit 1 @@ -274,6 +276,7 @@ function run_thread() { # echo "$thread_no ${line} DONE" if [ $ret -eq 0 ]; then echo -e "$case_index \e[34m DONE <<<<< \e[0m ${case_info} \e[34m[${total_time}s]\e[0m \e[32m success\e[0m" + flock -x $lock_file -c "echo \"${case_info}|success|${total_time}\" >>${success_case_file}" else if [ ! -z ${web_server} ]; then flock -x $lock_file -c "echo -e \"${hosts[index]} ret:${ret} ${line}\n ${web_server}/$test_log_dir/${case_file}.txt\" >>${failed_case_file}" @@ -300,10 +303,10 @@ function run_thread() { if [ ! -z "$corefile" ]; then echo -e "\e[34m corefiles: $corefile \e[0m" local build_dir=$log_dir/build_${hosts[index]} - local remote_build_dir="${workdirs[index]}/TDengine/debug/build" - if [ $ent -ne 0 ]; then - remote_build_dir="${workdirs[index]}/TDinternal/debug/build" - fi + local remote_build_dir="${workdirs[index]}/${DEBUGPATH}/build" + # if [ $ent -ne 0 ]; then + # remote_build_dir="${workdirs[index]}/{DEBUGPATH}/build" + # fi mkdir $build_dir 2>/dev/null if [ $? -eq 0 ]; then # scp build binary @@ -365,6 +368,8 @@ lock_file=$log_dir/$$.lock index_file=$log_dir/case_index.txt stat_file=$log_dir/stat.txt failed_case_file=$log_dir/failed.txt +success_case_file=$log_dir/success.txt + echo "0" >$index_file i=0 diff --git a/tests/parallel_test/run_case.sh b/tests/parallel_test/run_case.sh index e0b905375ac395089a536b544adbdf1049eeb036..2d736e141497b084c5b0e215881683e0e8c67b15 100755 --- a/tests/parallel_test/run_case.sh +++ b/tests/parallel_test/run_case.sh @@ -51,6 +51,9 @@ if [ $ent -eq 0 ]; then ln -s /home/TDengine/debug/build/lib/libtaos.so /usr/lib/libtaos.so 2>/dev/null ln -s /home/TDengine/debug/build/lib/libtaos.so /usr/lib/libtaos.so.1 2>/dev/null ln -s /home/TDengine/include/client/taos.h /usr/include/taos.h 2>/dev/null + ln -s /home/TDengine/include/common/taosdef.h /usr/include/taosdef.h 2>/dev/null + ln -s /home/TDengine/include/util/taoserror.h /usr/include/taoserror.h 2>/dev/null + ln -s /home/TDengine/include/libs/function/taosudf.h /usr/include/taosudf.h 2>/dev/null CONTAINER_TESTDIR=/home/TDengine else export PATH=$PATH:/home/TDinternal/debug/build/bin @@ -58,6 +61,9 @@ else ln -s /home/TDinternal/debug/build/lib/libtaos.so /usr/lib/libtaos.so 2>/dev/null ln -s /home/TDinternal/debug/build/lib/libtaos.so /usr/lib/libtaos.so.1 2>/dev/null ln -s /home/TDinternal/community/include/client/taos.h /usr/include/taos.h 2>/dev/null + ln -s /home/TDinternal/community/include/common/taosdef.h /usr/include/taosdef.h 2>/dev/null + ln -s /home/TDinternal/community/include/util/taoserror.h /usr/include/taoserror.h 2>/dev/null + ln -s /home/TDinternal/community/include/libs/function/taosudf.h /usr/include/taosudf.h 2>/dev/null CONTAINER_TESTDIR=/home/TDinternal/community fi mkdir -p /var/lib/taos/subscribe @@ -69,12 +75,19 @@ ulimit -c unlimited md5sum /usr/lib/libtaos.so.1 md5sum /home/TDinternal/debug/build/lib/libtaos.so + +#define taospy 2.7.6 +pip3 list|grep taospy +pip3 uninstall taospy -y +pip3 install --default-timeout=120 taospy==2.7.6 + $TIMEOUT_CMD $cmd RET=$? echo "cmd exit code: $RET" md5sum /usr/lib/libtaos.so.1 md5sum /home/TDinternal/debug/build/lib/libtaos.so + if [ $RET -ne 0 ]; then pwd fi diff --git a/tests/parallel_test/run_container.sh b/tests/parallel_test/run_container.sh index b5deb09341547b7e9c6d85d9e973757578ab2849..8ea2f249c193aefee1bdcb2963fcea0102483568 100755 --- a/tests/parallel_test/run_container.sh +++ b/tests/parallel_test/run_container.sh @@ -130,8 +130,6 @@ docker run \ -v ${SOURCEDIR}:/usr/local/src/ \ -v "$TMP_DIR/thread_volume/$thread_no/sim:${SIM_DIR}" \ -v ${TMP_DIR}/thread_volume/$thread_no/coredump:$coredump_dir \ - -v $WORKDIR/taos-connector-python/taos:/usr/local/lib/python3.8/site-packages/taos:ro \ - -v $WORKDIR/taos-connector-python/taosrest:/usr/local/lib/python3.8/site-packages/taosrest:ro \ --rm --ulimit core=-1 taos_test:v1.0 $CONTAINER_TESTDIR/tests/parallel_test/run_case.sh -d "$exec_dir" -c "$cmd" $extra_param ret=$? exit $ret diff --git a/tests/parallel_test/split_case.sh b/tests/parallel_test/split_case.sh new file mode 100755 index 0000000000000000000000000000000000000000..af601ed9a6a1c4d371e56d94aa45bc56b8715793 --- /dev/null +++ b/tests/parallel_test/split_case.sh @@ -0,0 +1,58 @@ +case_file="cases_temp_file" + +parm_path=$(dirname $0) +parm_path=$(pwd ${parm_path}) +echo "execute path:${parm_path}" +cd ${parm_path} +cp cases.task ${case_file} +sed -i '/^$/d' ${case_file} +sed -i '$a\%%FINISHED%%' ${case_file} + +utest="unit-test" +tsimtest="script" +systest="system-test" +devtest="develop-test" +doctest="docs-examples-test" +rm -rf win-${utest}.log win-${tsimtest}.log win-${systest}.log win-${devtest}.log win-${doctest}.log +rm -rf ${parm_path}/../${utest}/win-test-file ${parm_path}/../${tsimtest}/win-test-file ${parm_path}/../${systest}/win-test-file ${parm_path}/../${devtest}/win-test-file +while read -r line +do + echo "$line"|grep -q "^#" + if [ $? -eq 0 ]; then + continue + fi + exec_dir=$(echo "$line"|cut -d ',' -f4) + case_cmd=$(echo "$line"|cut -d ',' -f5) + if [[ "${exec_dir}" == "${utest}" ]]; then + echo ${case_cmd} >> win-${utest}.log + continue + fi + if [[ "${exec_dir}" == "${tsimtest}" ]]; then + echo ${case_cmd} >> win-${tsimtest}.log + continue + fi + if [[ "${exec_dir}" == "${systest}" ]]; then + if [[ "${case_cmd}" =~ "pytest.sh" ]]; then + case_cmd=$(echo "$case_cmd"|cut -d ' ' -f 2-) + echo ${case_cmd} >> win-${systest}.log + else + echo ${case_cmd} >> win-${systest}.log + fi + continue + fi + if [[ "${exec_dir}" == "${devtest}" ]]; then + echo ${case_cmd} >> win-${devtest}.log + continue + fi + if [[ "${exec_dir}" == "${doctest}" ]]; then + echo ${case_cmd} >> win-${doctest}.log + continue + fi +done < ${case_file} +mv win-${utest}.log ${parm_path}/../${utest}/win-test-file +mv win-${tsimtest}.log ${parm_path}/../${tsimtest}/win-test-file +mv win-${systest}.log ${parm_path}/../${systest}/win-test-file +mv win-${devtest}.log ${parm_path}/../${devtest}/win-test-file + + +rm -rf ${case_file} diff --git a/tests/pytest/auto_crash_gen.py b/tests/pytest/auto_crash_gen.py index 56629ede131606a917582a885ecaa137938adce1..00e178639992d5e5ec8a3ef292d38331ee3ce7d6 100755 --- a/tests/pytest/auto_crash_gen.py +++ b/tests/pytest/auto_crash_gen.py @@ -1,3 +1,4 @@ +import datetime import os import socket import requests @@ -238,17 +239,7 @@ def start_taosd(): start_cmd = 'cd %s && python3 test.py >>/dev/null '%(start_path) os.system(start_cmd) -def get_cmds(args_list): - # build_path = get_path() - # if repo == "community": - # crash_gen_path = build_path[:-5]+"community/tests/pytest/" - # elif repo == "TDengine": - # crash_gen_path = build_path[:-5]+"/tests/pytest/" - # else: - # pass - - # crash_gen_cmd = 'cd %s && ./crash_gen.sh --valgrind -p -t 10 -s 1000 -g 0x32c,0x32d,0x3d3,0x18,0x2501,0x369,0x388,0x061a,0x2550 '%(crash_gen_path) - +def get_cmds(args_list): crash_gen_cmd = get_auto_mix_cmds(args_list,valgrind=valgrind_mode) return crash_gen_cmd @@ -295,7 +286,7 @@ def check_status(): elif "Crash_Gen is now exiting with status code: 0" in run_code: return 0 else: - return 2 + return 2 def main(): @@ -310,7 +301,7 @@ def main(): build_path = get_path() - os.system("pip install git+https://github.com/taosdata/taos-connector-python.git") + if repo =="community": crash_gen_path = build_path[:-5]+"community/tests/pytest/" elif repo =="TDengine": @@ -334,7 +325,9 @@ def main(): if not os.path.exists(run_dir): os.mkdir(run_dir) print(crash_cmds) + starttime = datetime.datetime.now() run_crash_gen(crash_cmds) + endtime = datetime.datetime.now() status = check_status() print("exit status : ", status) @@ -349,7 +342,29 @@ def main(): print('======== crash_gen run sucess and exit as expected ========') try: - text = f"crash_gen instance exit status of docker [ {hostname} ] is : {msg_dict[status]}\n " + f" and git commit : {git_commit}" + cmd = crash_cmds.split('&')[2] + if status == 0: + log_dir = "none" + else: + log_dir= "/root/pxiao/crash_gen_logs" + + if status == 3: + core_dir = "/root/pxiao/crash_gen_logs" + else: + core_dir = "none" + + text = f''' + exit status: {msg_dict[status]} + test scope: crash_gen + owner: pxiao + hostname: {hostname} + start time: {starttime} + end time: {endtime} + git commit : {git_commit} + log dir: {log_dir} + core dir: {core_dir} + cmd: {cmd}''' + send_msg(get_msg(text)) except Exception as e: print("exception:", e) diff --git a/tests/pytest/auto_crash_gen_valgrind.py b/tests/pytest/auto_crash_gen_valgrind.py index 22fc5a480f2facfe6eff0e00460292bdd5aa1996..e37cda0a27b28738973bafcf0f8cce568af6e3e2 100755 --- a/tests/pytest/auto_crash_gen_valgrind.py +++ b/tests/pytest/auto_crash_gen_valgrind.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 +import datetime import os import socket import requests @@ -241,15 +242,6 @@ def start_taosd(): os.system(start_cmd +">>/dev/null") def get_cmds(args_list): - # build_path = get_path() - # if repo == "community": - # crash_gen_path = build_path[:-5]+"community/tests/pytest/" - # elif repo == "TDengine": - # crash_gen_path = build_path[:-5]+"/tests/pytest/" - # else: - # pass - - # crash_gen_cmd = 'cd %s && ./crash_gen.sh --valgrind -p -t 10 -s 1000 -g 0x32c,0x32d,0x3d3,0x18,0x2501,0x369,0x388,0x061a,0x2550 '%(crash_gen_path) crash_gen_cmd = get_auto_mix_cmds(args_list,valgrind=valgrind_mode) return crash_gen_cmd @@ -343,7 +335,6 @@ def main(): args = limits(args) build_path = get_path() - os.system("pip install git+https://github.com/taosdata/taos-connector-python.git >>/dev/null") if repo =="community": crash_gen_path = build_path[:-5]+"community/tests/pytest/" elif repo =="TDengine": @@ -368,7 +359,9 @@ def main(): if not os.path.exists(run_dir): os.mkdir(run_dir) print(crash_cmds) + starttime = datetime.datetime.now() run_crash_gen(crash_cmds) + endtime = datetime.datetime.now() status = check_status() # back_path = os.path.join(core_path,"valgrind_report") @@ -384,8 +377,30 @@ def main(): print('======== crash_gen run sucess and exit as expected ========') try: - text = f"crash_gen instance exit status of docker [ {hostname} ] is : {msg_dict[status]}\n " + f" and git commit : {git_commit}" - send_msg(get_msg(text)) + cmd = crash_cmds.split('&')[2] + if status == 0: + log_dir = "none" + else: + log_dir= "/root/pxiao/crash_gen_logs" + + if status == 3: + core_dir = "/root/pxiao/crash_gen_logs" + else: + core_dir = "none" + + text = f''' + exit status: {msg_dict[status]} + test scope: crash_gen + owner: pxiao + hostname: {hostname} + start time: {starttime} + end time: {endtime} + git commit : {git_commit} + log dir: {log_dir} + core dir: {core_dir} + cmd: {cmd}''' + + send_msg(get_msg(text)) except Exception as e: print("exception:", e) exit(status) diff --git a/tests/pytest/auto_crash_gen_valgrind_cluster.py b/tests/pytest/auto_crash_gen_valgrind_cluster.py index 547de9af479c51bac9f608eb01bc6e6b95b6fe48..af19836a834b08c9126afbaf5c675210d651947e 100755 --- a/tests/pytest/auto_crash_gen_valgrind_cluster.py +++ b/tests/pytest/auto_crash_gen_valgrind_cluster.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 +import datetime import os import socket import requests @@ -241,16 +242,7 @@ def start_taosd(): os.system(start_cmd +">>/dev/null") def get_cmds(args_list): - # build_path = get_path() - # if repo == "community": - # crash_gen_path = build_path[:-5]+"community/tests/pytest/" - # elif repo == "TDengine": - # crash_gen_path = build_path[:-5]+"/tests/pytest/" - # else: - # pass - - # crash_gen_cmd = 'cd %s && ./crash_gen.sh --valgrind -p -t 10 -s 1000 -g 0x32c,0x32d,0x3d3,0x18,0x2501,0x369,0x388,0x061a,0x2550 '%(crash_gen_path) - + crash_gen_cmd = get_auto_mix_cmds(args_list,valgrind=valgrind_mode) return crash_gen_cmd @@ -342,8 +334,7 @@ def main(): args = random_args(args_list) args = limits(args) - build_path = get_path() - os.system("pip install git+https://github.com/taosdata/taos-connector-python.git >>/dev/null") + build_path = get_path() if repo =="community": crash_gen_path = build_path[:-5]+"community/tests/pytest/" elif repo =="TDengine": @@ -368,7 +359,9 @@ def main(): if not os.path.exists(run_dir): os.mkdir(run_dir) print(crash_cmds) + starttime = datetime.datetime.now() run_crash_gen(crash_cmds) + endtime = datetime.datetime.now() status = check_status() # back_path = os.path.join(core_path,"valgrind_report") @@ -384,7 +377,29 @@ def main(): print('======== crash_gen run sucess and exit as expected ========') try: - text = f"crash_gen instance exit status of docker [ {hostname} ] is : {msg_dict[status]}\n " + f" and git commit : {git_commit}" + cmd = crash_cmds.split('&')[2] + if status == 0: + log_dir = "none" + else: + log_dir= "/root/pxiao/crash_gen_logs" + + if status == 3: + core_dir = "/root/pxiao/crash_gen_logs" + else: + core_dir = "none" + + text = f''' + exit status: {msg_dict[status]} + test scope: crash_gen + owner: pxiao + hostname: {hostname} + start time: {starttime} + end time: {endtime} + git commit : {git_commit} + log dir: {log_dir} + core dir: {core_dir} + cmd: {cmd}''' + send_msg(get_msg(text)) except Exception as e: print("exception:", e) diff --git a/tests/pytest/crash_gen/crash_gen_main.py b/tests/pytest/crash_gen/crash_gen_main.py index 3c39b05e699b0f90898eed9363f7e3770f8c51ce..ec588659e93ffc30d21355b970e595d08f04a9f7 100755 --- a/tests/pytest/crash_gen/crash_gen_main.py +++ b/tests/pytest/crash_gen/crash_gen_main.py @@ -18,7 +18,8 @@ from __future__ import annotations from typing import Any, Set, Tuple from typing import Dict from typing import List -from typing import Optional # Type hinting, ref: https://stackoverflow.com/questions/19202633/python-3-type-hinting-for-none +from typing import \ + Optional # Type hinting, ref: https://stackoverflow.com/questions/19202633/python-3-type-hinting-for-none import textwrap import time @@ -39,7 +40,6 @@ import gc import taos from taos.tmq import * - from .shared.types import TdColumns, TdTags # from crash_gen import ServiceManager, TdeInstance, TdeSubProcess @@ -65,10 +65,11 @@ if sys.version_info[0] < 3: # Command-line/Environment Configurations, will set a bit later # ConfigNameSpace = argparse.Namespace # gConfig: argparse.Namespace -gSvcMgr: Optional[ServiceManager] # TODO: refactor this hack, use dep injection +gSvcMgr: Optional[ServiceManager] # TODO: refactor this hack, use dep injection # logger: logging.Logger gContainer: Container + # def runThread(wt: WorkerThread): # wt.run() @@ -77,7 +78,7 @@ class WorkerThread: def __init__(self, pool: ThreadPool, tid, tc: ThreadCoordinator): """ Note: this runs in the main thread context - """ + """ # self._curStep = -1 self._pool = pool self._tid = tid @@ -91,15 +92,15 @@ class WorkerThread: if (Config.getConfig().per_thread_db_connection): # type: ignore # print("connector_type = {}".format(gConfig.connector_type)) tInst = gContainer.defTdeInstance - if Config.getConfig().connector_type == 'native': - self._dbConn = DbConn.createNative(tInst.getDbTarget()) + if Config.getConfig().connector_type == 'native': + self._dbConn = DbConn.createNative(tInst.getDbTarget()) elif Config.getConfig().connector_type == 'rest': - self._dbConn = DbConn.createRest(tInst.getDbTarget()) + self._dbConn = DbConn.createRest(tInst.getDbTarget()) elif Config.getConfig().connector_type == 'mixed': - if Dice.throw(2) == 0: # 1/2 chance - self._dbConn = DbConn.createNative(tInst.getDbTarget()) + if Dice.throw(2) == 0: # 1/2 chance + self._dbConn = DbConn.createNative(tInst.getDbTarget()) else: - self._dbConn = DbConn.createRest(tInst.getDbTarget()) + self._dbConn = DbConn.createRest(tInst.getDbTarget()) else: raise RuntimeError("Unexpected connector type: {}".format(Config.getConfig().connector_type)) @@ -138,7 +139,7 @@ class WorkerThread: # clean up if (Config.getConfig().per_thread_db_connection): # type: ignore - if self._dbConn.isOpen: #sometimes it is not open + if self._dbConn.isOpen: # sometimes it is not open self._dbConn.close() else: Logging.warning("Cleaning up worker thread, dbConn already closed") @@ -150,20 +151,19 @@ class WorkerThread: tc = self._tc # Thread Coordinator, the overall master try: tc.crossStepBarrier() # shared barrier first, INCLUDING the last one - except threading.BrokenBarrierError as err: # main thread timed out + except threading.BrokenBarrierError as err: # main thread timed out print("_bto", end="") Logging.debug("[TRD] Worker thread exiting due to main thread barrier time-out") break Logging.debug("[TRD] Worker thread [{}] exited barrier...".format(self._tid)) - self.crossStepGate() # then per-thread gate, after being tapped + self.crossStepGate() # then per-thread gate, after being tapped Logging.debug("[TRD] Worker thread [{}] exited step gate...".format(self._tid)) if not self._tc.isRunning(): print("_wts", end="") Logging.debug("[TRD] Thread Coordinator not running any more, worker thread now stopping...") break - # Before we fetch the task and run it, let's ensure we properly "use" the database (not needed any more) try: if (Config.getConfig().per_thread_db_connection): # most likely TRUE @@ -172,7 +172,8 @@ class WorkerThread: # self.useDb() # might encounter exceptions. TODO: catch except taos.error.ProgrammingError as err: errno = Helper.convertErrno(err.errno) - if errno in [0x383, 0x386, 0x00B, 0x014] : # invalid database, dropping, Unable to establish connection, Database not ready + if errno in [0x383, 0x386, 0x00B, + 0x014]: # invalid database, dropping, Unable to establish connection, Database not ready # ignore dummy = 0 else: @@ -180,12 +181,12 @@ class WorkerThread: raise # Fetch a task from the Thread Coordinator - Logging.debug( "[TRD] Worker thread [{}] about to fetch task".format(self._tid)) + Logging.debug("[TRD] Worker thread [{}] about to fetch task".format(self._tid)) task = tc.fetchTask() # Execute such a task Logging.debug("[TRD] Worker thread [{}] about to execute task: {}".format( - self._tid, task.__class__.__name__)) + self._tid, task.__class__.__name__)) task.execute(self) tc.saveExecutedTask(task) Logging.debug("[TRD] Worker thread [{}] finished executing task".format(self._tid)) @@ -228,7 +229,7 @@ class WorkerThread: self._stepGate.set() # wake up! time.sleep(0) # let the released thread run a bit else: - print("_tad", end="") # Thread already dead + print("_tad", end="") # Thread already dead def execSql(self, sql): # TODO: expose DbConn directly return self.getDbConn().execute(sql) @@ -239,7 +240,7 @@ class WorkerThread: def getQueryResult(self): return self.getDbConn().getQueryResult() - def getDbConn(self) -> DbConn : + def getDbConn(self) -> DbConn: if (Config.getConfig().per_thread_db_connection): return self._dbConn else: @@ -251,6 +252,7 @@ class WorkerThread: # else: # return self._tc.getDbState().getDbConn().query(sql) + # The coordinator of all worker threads, mostly running in main thread @@ -262,7 +264,7 @@ class ThreadCoordinator: self._pool = pool # self._wd = wd self._te = None # prepare for every new step - self._dbManager = dbManager # type: Optional[DbManager] # may be freed + self._dbManager = dbManager # type: Optional[DbManager] # may be freed self._executedTasks: List[Task] = [] # in a given step self._lock = threading.RLock() # sync access for a few things @@ -284,7 +286,7 @@ class ThreadCoordinator: return self._dbManager def crossStepBarrier(self, timeout=None): - self._stepBarrier.wait(timeout) + self._stepBarrier.wait(timeout) def requestToStop(self): self._runStatus = Status.STATUS_STOPPING @@ -292,7 +294,7 @@ class ThreadCoordinator: def _runShouldEnd(self, transitionFailed, hasAbortedTask, workerTimeout): maxSteps = Config.getConfig().max_steps # type: ignore - if self._curStep >= (maxSteps - 1): # maxStep==10, last curStep should be 9 + if self._curStep >= (maxSteps - 1): # maxStep==10, last curStep should be 9 return True if self._runStatus != Status.STATUS_RUNNING: return True @@ -304,7 +306,7 @@ class ThreadCoordinator: return True return False - def _hasAbortedTask(self): # from execution of previous step + def _hasAbortedTask(self): # from execution of previous step for task in self._executedTasks: if task.isAborted(): # print("Task aborted: {}".format(task)) @@ -319,17 +321,17 @@ class ThreadCoordinator: "--\r\n\n--> Step {} starts with main thread waking up".format(self._curStep)) # A new TE for the new step - self._te = None # set to empty first, to signal worker thread to stop + self._te = None # set to empty first, to signal worker thread to stop if not transitionFailed: # only if not failed self._te = TaskExecutor(self._curStep) Logging.debug("[TRD] Main thread waking up at step {}, tapping worker threads".format( - self._curStep)) # Now not all threads had time to go to sleep + self._curStep)) # Now not all threads had time to go to sleep # Worker threads will wake up at this point, and each execute it's own task - self.tapAllThreads() # release all worker thread from their "gates" + self.tapAllThreads() # release all worker thread from their "gates" def _syncAtBarrier(self): - # Now main thread (that's us) is ready to enter a step + # Now main thread (that's us) is ready to enter a step # let other threads go past the pool barrier, but wait at the # thread gate Logging.debug("[TRD] Main thread about to cross the barrier") @@ -341,7 +343,7 @@ class ThreadCoordinator: transitionFailed = False try: for x in self._dbs: - db = x # type: Database + db = x # type: Database sm = db.getStateMachine() Logging.debug("[STT] starting transitions for DB: {}".format(db.getName())) # at end of step, transiton the DB state @@ -357,8 +359,8 @@ class ThreadCoordinator: # for t in self._pool.threadList: # Logging.debug("[DB] use db for all worker threads") # t.useDb() - # t.execSql("use db") # main thread executing "use - # db" on behalf of every worker thread + # t.execSql("use db") # main thread executing "use + # db" on behalf of every worker thread except taos.error.ProgrammingError as err: if (err.msg == 'network unavailable'): # broken DB connection @@ -369,12 +371,13 @@ class ThreadCoordinator: self._execStats.registerFailure("Broken DB Connection") # continue # don't do that, need to tap all threads at # end, and maybe signal them to stop - if isinstance(err, CrashGenError): # our own transition failure + if isinstance(err, CrashGenError): # our own transition failure Logging.info("State transition error") # TODO: saw an error here once, let's print out stack info for err? - traceback.print_stack() # Stack frame to here. + traceback.print_stack() # Stack frame to here. Logging.info("Caused by:") - traceback.print_exception(*sys.exc_info()) # Ref: https://www.geeksforgeeks.org/how-to-print-exception-stack-trace-in-python/ + traceback.print_exception( + *sys.exc_info()) # Ref: https://www.geeksforgeeks.org/how-to-print-exception-stack-trace-in-python/ transitionFailed = True self._te = None # Not running any more self._execStats.registerFailure("State transition error: {}".format(err)) @@ -392,14 +395,14 @@ class ThreadCoordinator: # Coordinate all threads step by step self._curStep = -1 # not started yet - + self._execStats.startExec() # start the stop watch transitionFailed = False hasAbortedTask = False workerTimeout = False while not self._runShouldEnd(transitionFailed, hasAbortedTask, workerTimeout): - if not Config.getConfig().debug: # print this only if we are not in debug mode - Progress.emit(Progress.STEP_BOUNDARY) + if not Config.getConfig().debug: # print this only if we are not in debug mode + Progress.emit(Progress.STEP_BOUNDARY) # print(".", end="", flush=True) # if (self._curStep % 2) == 0: # print memory usage once every 10 steps # memUsage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss @@ -408,15 +411,14 @@ class ThreadCoordinator: # h = hpy() # print("\n") # print(h.heap()) - - + try: - self._syncAtBarrier() # For now just cross the barrier + self._syncAtBarrier() # For now just cross the barrier Progress.emit(Progress.END_THREAD_STEP) - if self._stepStartTime : + if self._stepStartTime: stepExecTime = time.time() - self._stepStartTime Progress.emitStr('{:.3f}s/{}'.format(stepExecTime, DbConnNative.totalRequests)) - DbConnNative.resetTotalRequests() # reset to zero + DbConnNative.resetTotalRequests() # reset to zero except threading.BrokenBarrierError as err: self._execStats.registerFailure("Aborted due to worker thread timeout") Logging.error("\n") @@ -439,15 +441,15 @@ class ThreadCoordinator: # At this point, all threads should be pass the overall "barrier" and before the per-thread "gate" # We use this period to do house keeping work, when all worker # threads are QUIET. - hasAbortedTask = self._hasAbortedTask() # from previous step - if hasAbortedTask: + hasAbortedTask = self._hasAbortedTask() # from previous step + if hasAbortedTask: Logging.info("Aborted task encountered, exiting test program") self._execStats.registerFailure("Aborted Task Encountered") - break # do transition only if tasks are error free + break # do transition only if tasks are error free # Ending previous step try: - transitionFailed = self._doTransition() # To start, we end step -1 first + transitionFailed = self._doTransition() # To start, we end step -1 first except taos.error.ProgrammingError as err: transitionFailed = True errno2 = Helper.convertErrno(err.errno) # correct error scheme @@ -459,32 +461,32 @@ class ThreadCoordinator: # Then we move on to the next step Progress.emit(Progress.BEGIN_THREAD_STEP) self._stepStartTime = time.time() - self._releaseAllWorkerThreads(transitionFailed) + self._releaseAllWorkerThreads(transitionFailed) - if hasAbortedTask or transitionFailed : # abnormal ending, workers waiting at "gate" + if hasAbortedTask or transitionFailed: # abnormal ending, workers waiting at "gate" Logging.debug("Abnormal ending of main thraed") elif workerTimeout: Logging.debug("Abnormal ending of main thread, due to worker timeout") - else: # regular ending, workers waiting at "barrier" + else: # regular ending, workers waiting at "barrier" Logging.debug("Regular ending, main thread waiting for all worker threads to stop...") self._syncAtBarrier() self._te = None # No more executor, time to end Logging.debug("Main thread tapping all threads one last time...") self.tapAllThreads() # Let the threads run one last time - #TODO: looks like we are not capturing the failures for the last step yet (i.e. calling registerFailure if neccessary) + # TODO: looks like we are not capturing the failures for the last step yet (i.e. calling registerFailure if neccessary) Logging.debug("\r\n\n--> Main thread ready to finish up...") Logging.debug("Main thread joining all threads") self._pool.joinAll() # Get all threads to finish - Logging.info(". . . All worker threads finished") # No CR/LF before + Logging.info(". . . All worker threads finished") # No CR/LF before self._execStats.endExec() - def cleanup(self): # free resources + def cleanup(self): # free resources self._pool.cleanup() self._pool = None - self._te = None + self._te = None self._dbManager = None self._executedTasks = [] self._lock = None @@ -492,7 +494,6 @@ class ThreadCoordinator: self._execStats = None self._runStatus = None - def printStats(self): self._execStats.printStats() @@ -523,21 +524,21 @@ class ThreadCoordinator: def _initDbs(self): ''' Initialize multiple databases, invoked at __ini__() time ''' - self._dbs = [] # type: List[Database] + self._dbs = [] # type: List[Database] dbc = self.getDbManager().getDbConn() if Config.getConfig().max_dbs == 0: self._dbs.append(Database(0, dbc)) - else: - baseDbNumber = int(datetime.datetime.now().timestamp( # Don't use Dice/random, as they are deterministic - )*333) % 888 if Config.getConfig().dynamic_db_table_names else 0 + else: + baseDbNumber = int(datetime.datetime.now().timestamp( # Don't use Dice/random, as they are deterministic + ) * 333) % 888 if Config.getConfig().dynamic_db_table_names else 0 for i in range(Config.getConfig().max_dbs): self._dbs.append(Database(baseDbNumber + i, dbc)) def pickDatabase(self): idxDb = 0 - if Config.getConfig().max_dbs != 0 : - idxDb = Dice.throw(Config.getConfig().max_dbs) # 0 to N-1 - db = self._dbs[idxDb] # type: Database + if Config.getConfig().max_dbs != 0: + idxDb = Dice.throw(Config.getConfig().max_dbs) # 0 to N-1 + db = self._dbs[idxDb] # type: Database return db def fetchTask(self) -> Task: @@ -549,12 +550,12 @@ class ThreadCoordinator: # pick a task type for current state db = self.pickDatabase() - if Dice.throw(2)==1: - taskType = db.getStateMachine().pickTaskType() # dynamic name of class + if Dice.throw(2) == 1: + taskType = db.getStateMachine().pickTaskType() # dynamic name of class else: - taskType = db.getStateMachine().balance_pickTaskType() # and an method can get balance task types + taskType = db.getStateMachine().balance_pickTaskType() # and an method can get balance task types pass - + return taskType(self._execStats, db) # create a task from it def resetExecutedTasks(self): @@ -564,6 +565,7 @@ class ThreadCoordinator: with self._lock: self._executedTasks.append(task) + class ThreadPool: def __init__(self, numThreads, maxSteps): self.numThreads = numThreads @@ -585,7 +587,8 @@ class ThreadPool: workerThread._thread.join() def cleanup(self): - self.threadList = [] # maybe clean up each? + self.threadList = [] # maybe clean up each? + # A queue of continguous POSITIVE integers, used by DbManager to generate continuous numbers # for new table names @@ -680,11 +683,11 @@ class AnyState: CAN_CREATE_DB = 1 # For below, if we can "drop the DB", but strictly speaking # only "under normal circumstances", as we may override it with the -b option - CAN_DROP_DB = 2 + CAN_DROP_DB = 2 CAN_CREATE_FIXED_SUPER_TABLE = 3 CAN_CREATE_STREAM = 3 # super table must exists CAN_CREATE_TOPIC = 3 # super table must exists - CAN_CREATE_CONSUMERS = 3 + CAN_CREATE_CONSUMERS = 3 CAN_DROP_FIXED_SUPER_TABLE = 4 CAN_DROP_TOPIC = 4 CAN_DROP_STREAM = 4 @@ -729,7 +732,7 @@ class AnyState: def canDropDb(self): # If user requests to run up to a number of DBs, # we'd then not do drop_db operations any more - if Config.getConfig().max_dbs > 0 or Config.getConfig().use_shadow_db : + if Config.getConfig().max_dbs > 0 or Config.getConfig().use_shadow_db: return False return self._info[self.CAN_DROP_DB] @@ -737,19 +740,19 @@ class AnyState: return self._info[self.CAN_CREATE_FIXED_SUPER_TABLE] def canDropFixedSuperTable(self): - if Config.getConfig().use_shadow_db: # duplicate writes to shaddow DB, in which case let's disable dropping s-table + if Config.getConfig().use_shadow_db: # duplicate writes to shaddow DB, in which case let's disable dropping s-table return False return self._info[self.CAN_DROP_FIXED_SUPER_TABLE] def canCreateTopic(self): return self._info[self.CAN_CREATE_TOPIC] - + def canDropTopic(self): return self._info[self.CAN_DROP_TOPIC] def canCreateConsumers(self): return self._info[self.CAN_CREATE_CONSUMERS] - + def canCreateStreams(self): return self._info[self.CAN_CREATE_STREAM] @@ -777,7 +780,7 @@ class AnyState: raise CrashGenError( "Unexpected more than 1 success at state: {}, with task: {}, in task set: {}".format( self.__class__.__name__, - cls.__name__, # verified just now that isinstance(task, cls) + cls.__name__, # verified just now that isinstance(task, cls) [c.__class__.__name__ for c in tasks] )) @@ -792,16 +795,17 @@ class AnyState: sCnt += 1 if (exists and sCnt <= 0): raise CrashGenError("Unexpected zero success at state: {}, with task: {}, in task set: {}".format( - self.__class__.__name__, - cls.__name__, # verified just now that isinstance(task, cls) - [c.__class__.__name__ for c in tasks] - )) + self.__class__.__name__, + cls.__name__, # verified just now that isinstance(task, cls) + [c.__class__.__name__ for c in tasks] + )) def assertNoTask(self, tasks, cls): for task in tasks: if isinstance(task, cls): raise CrashGenError( - "This task: {}, is not expected to be present, given the success/failure of others".format(cls.__name__)) + "This task: {}, is not expected to be present, given the success/failure of others".format( + cls.__name__)) def assertNoSuccess(self, tasks, cls): for task in tasks: @@ -848,7 +852,7 @@ class StateEmpty(AnyState): def verifyTasksToState(self, tasks, newState): if (self.hasSuccess(tasks, TaskCreateDb) - ): # at EMPTY, if there's succes in creating DB + ): # at EMPTY, if there's succes in creating DB if (not self.hasTask(tasks, TaskDropDb)): # and no drop_db tasks # we must have at most one. TODO: compare numbers self.assertAtMostOneSuccess(tasks, TaskCreateDb) @@ -885,19 +889,19 @@ class StateSuperTableOnly(AnyState): def verifyTasksToState(self, tasks, newState): if (self.hasSuccess(tasks, TaskDropSuperTable) - ): # we are able to drop the table - #self.assertAtMostOneSuccess(tasks, TaskDropSuperTable) + ): # we are able to drop the table + # self.assertAtMostOneSuccess(tasks, TaskDropSuperTable) # we must have had recreted it self.hasSuccess(tasks, TaskCreateSuperTable) # self._state = self.STATE_DB_ONLY # elif ( self.hasSuccess(tasks, AddFixedDataTask) ): # no success dropping the table, but added data # self.assertNoTask(tasks, DropFixedTableTask) # not true in massively parrallel cases - # self._state = self.STATE_HAS_DATA + # self._state = self.STATE_HAS_DATA # elif ( self.hasSuccess(tasks, ReadFixedDataTask) ): # no success in prev cases, but was able to read data - # self.assertNoTask(tasks, DropFixedTableTask) - # self.assertNoTask(tasks, AddFixedDataTask) - # self._state = self.STATE_TABLE_ONLY # no change + # self.assertNoTask(tasks, DropFixedTableTask) + # self.assertNoTask(tasks, AddFixedDataTask) + # self._state = self.STATE_TABLE_ONLY # no change # else: # did not drop table, did not insert data, did not read successfully, that is impossible # raise RuntimeError("Unexpected no-success scenarios") # TODO: need to revamp!! @@ -919,41 +923,41 @@ class StateHasData(AnyState): self.assertAtMostOneSuccess(tasks, TaskDropDb) # TODO: dicy elif (newState.equals(AnyState.STATE_DB_ONLY)): # in DB only if (not self.hasTask(tasks, TaskCreateDb) - ): # without a create_db task + ): # without a create_db task # we must have drop_db task self.assertNoTask(tasks, TaskDropDb) self.hasSuccess(tasks, TaskDropSuperTable) # self.assertAtMostOneSuccess(tasks, DropFixedSuperTableTask) # TODO: dicy # elif ( newState.equals(AnyState.STATE_TABLE_ONLY) ): # data deleted - # self.assertNoTask(tasks, TaskDropDb) - # self.assertNoTask(tasks, TaskDropSuperTable) - # self.assertNoTask(tasks, TaskAddData) - # self.hasSuccess(tasks, DeleteDataTasks) + # self.assertNoTask(tasks, TaskDropDb) + # self.assertNoTask(tasks, TaskDropSuperTable) + # self.assertNoTask(tasks, TaskAddData) + # self.hasSuccess(tasks, DeleteDataTasks) else: # should be STATE_HAS_DATA if (not self.hasTask(tasks, TaskCreateDb) - ): # only if we didn't create one + ): # only if we didn't create one # we shouldn't have dropped it self.assertNoTask(tasks, TaskDropDb) - if not( self.hasTask(tasks, TaskCreateSuperTable) - ): # if we didn't create the table + if not (self.hasTask(tasks, TaskCreateSuperTable) + ): # if we didn't create the table # we should not have a task that drops it self.assertNoTask(tasks, TaskDropSuperTable) # self.assertIfExistThenSuccess(tasks, ReadFixedDataTask) class StateMechine: - def __init__(self, db: Database): + def __init__(self, db: Database): self._db = db # transitition target probabilities, indexed with value of STATE_EMPTY, STATE_DB_ONLY, etc. self._stateWeights = [1, 2, 10, 40] - def init(self, dbc: DbConn): # late initailization, don't save the dbConn + def init(self, dbc: DbConn): # late initailization, don't save the dbConn try: self._curState = self._findCurrentState(dbc) # starting state - except taos.error.ProgrammingError as err: + except taos.error.ProgrammingError as err: Logging.error("Failed to initialized state machine, cannot find current state: {}".format(err)) traceback.print_stack() - raise # re-throw + raise # re-throw # TODO: seems no lnoger used, remove? def getCurrentState(self): @@ -999,28 +1003,27 @@ class StateMechine: def _findCurrentState(self, dbc: DbConn): ts = time.time() # we use this to debug how fast/slow it is to do the various queries to find the current DB state - dbName =self._db.getName() - if not dbc.existsDatabase(dbName): # dbc.hasDatabases(): # no database?! - Logging.debug( "[STT] empty database found, between {} and {}".format(ts, time.time())) + dbName = self._db.getName() + if not dbc.existsDatabase(dbName): # dbc.hasDatabases(): # no database?! + Logging.debug("[STT] empty database found, between {} and {}".format(ts, time.time())) return StateEmpty() # did not do this when openning connection, and this is NOT the worker # thread, which does this on their own dbc.use(dbName) - + if not dbc.hasTables(): # no tables - + Logging.debug("[STT] DB_ONLY found, between {} and {}".format(ts, time.time())) return StateDbOnly() # For sure we have tables, which means we must have the super table. # TODO: are we sure? - + sTable = self._db.getFixedSuperTable() - if sTable.hasRegTables(dbc): # no regular tables # print("debug=====*\n"*100) Logging.debug("[STT] SUPER_TABLE_ONLY found, between {} and {}".format(ts, time.time())) - + return StateSuperTableOnly() else: # has actual tables Logging.debug("[STT] HAS_DATA found, between {} and {}".format(ts, time.time())) @@ -1029,7 +1032,7 @@ class StateMechine: # We transition the system to a new state by examining the current state itself def transition(self, tasks, dbc: DbConn): global gSvcMgr - + if (len(tasks) == 0): # before 1st step, or otherwise empty Logging.debug("[STT] Starting State: {}".format(self._curState)) return # do nothing @@ -1038,39 +1041,39 @@ class StateMechine: dbc.execute("select * from information_schema.ins_dnodes") # Generic Checks, first based on the start state - if not Config.getConfig().ignore_errors: # verify state, only if we are asked not to ignore certain errors. + if not Config.getConfig().ignore_errors: # verify state, only if we are asked not to ignore certain errors. if self._curState.canCreateDb(): self._curState.assertIfExistThenSuccess(tasks, TaskCreateDb) # self.assertAtMostOneSuccess(tasks, CreateDbTask) # not really, in # case of multiple creation and drops if self._curState.canDropDb(): - if gSvcMgr == None: # only if we are running as client-only + if gSvcMgr == None: # only if we are running as client-only self._curState.assertIfExistThenSuccess(tasks, TaskDropDb) # self.assertAtMostOneSuccess(tasks, DropDbTask) # not really in # case of drop-create-drop # if self._state.canCreateFixedTable(): - # self.assertIfExistThenSuccess(tasks, CreateFixedTableTask) # Not true, DB may be dropped - # self.assertAtMostOneSuccess(tasks, CreateFixedTableTask) # not - # really, in case of create-drop-create + # self.assertIfExistThenSuccess(tasks, CreateFixedTableTask) # Not true, DB may be dropped + # self.assertAtMostOneSuccess(tasks, CreateFixedTableTask) # not + # really, in case of create-drop-create # if self._state.canDropFixedTable(): - # self.assertIfExistThenSuccess(tasks, DropFixedTableTask) # Not True, the whole DB may be dropped - # self.assertAtMostOneSuccess(tasks, DropFixedTableTask) # not - # really in case of drop-create-drop + # self.assertIfExistThenSuccess(tasks, DropFixedTableTask) # Not True, the whole DB may be dropped + # self.assertAtMostOneSuccess(tasks, DropFixedTableTask) # not + # really in case of drop-create-drop # if self._state.canAddData(): # self.assertIfExistThenSuccess(tasks, AddFixedDataTask) # not true # actually # if self._state.canReadData(): - # Nothing for sure + # Nothing for sure newState = self._findCurrentState(dbc) Logging.debug("[STT] New DB state determined: {}".format(newState)) # can old state move to new state through the tasks? - if not Config.getConfig().ignore_errors: # verify state, only if we are asked not to ignore certain errors. + if not Config.getConfig().ignore_errors: # verify state, only if we are asked not to ignore certain errors. self._curState.verifyTasksToState(tasks, newState) self._curState = newState @@ -1096,22 +1099,24 @@ class StateMechine: weightsTypes = BasicTypes.copy() # this matrixs can balance the Frequency of TaskTypes - balance_TaskType_matrixs = {'TaskDropDb': 5 , 'TaskDropTopics': 20 , 'TaskDropStreams':10 , 'TaskDropStreamTables':10 , - 'TaskReadData':50 , 'TaskDropSuperTable':5 , 'TaskAlterTags':3 , 'TaskAddData':10, - 'TaskDeleteData':10 , 'TaskCreateDb':10 , 'TaskCreateStream': 3, 'TaskCreateTopic' :3, - 'TaskCreateConsumers':10, 'TaskCreateSuperTable': 10 } # TaskType : balance_matrixs of task - - for task , weights in balance_TaskType_matrixs.items(): - + balance_TaskType_matrixs = {'TaskDropDb': 5, 'TaskDropTopics': 20, 'TaskDropStreams': 10, + 'TaskDropStreamTables': 10, + 'TaskReadData': 50, 'TaskDropSuperTable': 5, 'TaskAlterTags': 3, 'TaskAddData': 10, + 'TaskDeleteData': 10, 'TaskCreateDb': 10, 'TaskCreateStream': 3, + 'TaskCreateTopic': 3, + 'TaskCreateConsumers': 10, + 'TaskCreateSuperTable': 10} # TaskType : balance_matrixs of task + + for task, weights in balance_TaskType_matrixs.items(): + for basicType in BasicTypes: if basicType.__name__ == task: for _ in range(weights): weightsTypes.append(basicType) - task = random.sample(weightsTypes,1) + task = random.sample(weightsTypes, 1) return task[0] - # ref: # https://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/ def _weighted_choice_sub(self, weights) -> int: @@ -1123,6 +1128,7 @@ class StateMechine: return i raise CrashGenError("Unexpected no choice") + class Database: ''' We use this to represent an actual TDengine database inside a service instance, possibly in a cluster environment. @@ -1131,16 +1137,16 @@ class Database: TODO: consider moving, but keep in mind it contains "StateMachine" ''' - _clsLock = threading.Lock() # class wide lock + _clsLock = threading.Lock() # class wide lock _lastInt = 101 # next one is initial integer - _lastTick = None # Optional[datetime] - _lastLaggingTick = None # Optional[datetime] # lagging tick, for out-of-sequence (oos) data insertions + _lastTick = None # Optional[datetime] + _lastLaggingTick = None # Optional[datetime] # lagging tick, for out-of-sequence (oos) data insertions - def __init__(self, dbNum: int, dbc: DbConn): # TODO: remove dbc - self._dbNum = dbNum # we assign a number to databases, for our testing purpose + def __init__(self, dbNum: int, dbc: DbConn): # TODO: remove dbc + self._dbNum = dbNum # we assign a number to databases, for our testing purpose self._stateMachine = StateMechine(self) self._stateMachine.init(dbc) - + self._lock = threading.RLock() def getStateMachine(self) -> StateMechine: @@ -1152,7 +1158,7 @@ class Database: def getName(self): return "db_{}".format(self._dbNum) - def filterTasks(self, inTasks: List[Task]): # Pick out those belonging to us + def filterTasks(self, inTasks: List[Task]): # Pick out those belonging to us outTasks = [] for task in inTasks: if task.getDb().isSame(self): @@ -1184,38 +1190,42 @@ class Database: # start time will be auto generated , start at 10 years ago local time local_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-16] local_epoch_time = [int(i) for i in local_time.split("-")] - #local_epoch_time will be such as : [2022, 7, 18] + # local_epoch_time will be such as : [2022, 7, 18] - t1 = datetime.datetime(local_epoch_time[0]-5, local_epoch_time[1], local_epoch_time[2]) + t1 = datetime.datetime(local_epoch_time[0] - 5, local_epoch_time[1], local_epoch_time[2]) t2 = datetime.datetime.now() # maybe a very large number, takes 69 years to exceed Python int range elSec = int(t2.timestamp() - t1.timestamp()) elSec2 = (elSec % (8 * 12 * 30 * 24 * 60 * 60 / 500)) * \ - 500 # a number representing seconds within 10 years + 500 # a number representing seconds within 10 years # print("elSec = {}".format(elSec)) - t3 = datetime.datetime(local_epoch_time[0]-10, local_epoch_time[1], local_epoch_time[2]) # default "keep" is 10 years + t3 = datetime.datetime(local_epoch_time[0] - 10, local_epoch_time[1], + local_epoch_time[2]) # default "keep" is 10 years t4 = datetime.datetime.fromtimestamp( t3.timestamp() + elSec2) # see explanation above Logging.debug("Setting up TICKS to start from: {}".format(t4)) return t4 @classmethod - def getNextTick(cls): + def getNextTick(cls): ''' Fetch a timestamp tick, with some random factor, may not be unique. - ''' + ''' with cls._clsLock: # prevent duplicate tick - if cls._lastLaggingTick is None or cls._lastTick is None : # not initialized + if cls._lastLaggingTick is None or cls._lastTick is None: # not initialized # 10k at 1/20 chance, should be enough to avoid overlaps tick = cls.setupLastTick() cls._lastTick = tick - cls._lastLaggingTick = tick + datetime.timedelta(0, -60*2) # lagging behind 2 minutes, should catch up fast + cls._lastLaggingTick = tick + datetime.timedelta(0, + -60 * 2) # lagging behind 2 minutes, should catch up fast # if : # should be quite a bit into the future - if Config.isSet('mix_oos_data') and Dice.throw(20) == 0: # if asked to do so, and 1 in 20 chance, return lagging tick - cls._lastLaggingTick += datetime.timedelta(0, 1) # pick the next sequence from the lagging tick sequence - return cls._lastLaggingTick + if Config.isSet('mix_oos_data') and Dice.throw( + 20) == 0: # if asked to do so, and 1 in 20 chance, return lagging tick + cls._lastLaggingTick += datetime.timedelta(0, + 1) # pick the next sequence from the lagging tick sequence + return cls._lastLaggingTick else: # regular # add one second to it cls._lastTick += datetime.timedelta(0, 1) @@ -1332,9 +1342,7 @@ class Task(): # Logging.debug("Creating new task {}...".format(self._taskNum)) self._execStats = execStats - self._db = db # A task is always associated/for a specific DB - - + self._db = db # A task is always associated/for a specific DB def isSuccess(self): return self._err is None @@ -1367,82 +1375,78 @@ class Task(): def _isServiceStable(self): if not gSvcMgr: return True # we don't run service, so let's assume it's stable - return gSvcMgr.isStable() # otherwise let's examine the service + return gSvcMgr.isStable() # otherwise let's examine the service def _isErrAcceptable(self, errno, msg): if errno in [ - # TDengine 2.x Error Codes: - 0x05, # TSDB_CODE_RPC_NOT_READY - 0x0B, # Unable to establish connection, more details in TD-1648 - # 0x200, # invalid SQL, TODO: re-examine with TD-934 - 0x20F, # query terminated, possibly due to vnoding being dropped, see TD-1776 - 0x213, # "Disconnected from service", result of "kill connection ???" - 0x217, # "db not selected", client side defined error code - # 0x218, # "Table does not exist" client side defined error code - 0x360, # Table already exists - 0x362, - # 0x369, # tag already exists - 0x36A, 0x36B, 0x36D, - 0x381, - 0x380, # "db not selected" - 0x383, - 0x386, # DB is being dropped?! - 0x503, - 0x510, # vnode not in ready state - 0x14, # db not ready, errno changed - 0x600, # Invalid table ID, why? - 0x218, # Table does not exist - - # TDengine 3.0 Error Codes: - 0x0333, # Object is creating # TODO: this really is NOT an acceptable error - 0x0369, # Tag already exists - 0x0388, # Database not exist - 0x03A0, # STable already exists - 0x03A1, # STable [does] not exist - 0x03AA, # Tag already exists - 0x0603, # Table already exists - 0x2603, # Table does not exist, replaced by 2662 below - 0x260d, # Tags number not matched - 0x2662, # Table does not exist #TODO: what about 2603 above? - 0x2600, # database not specified, SQL: show stables , database droped , and show tables - 0x032C, # Object is creating - 0x032D, # Object is dropping - 0x03D3, # Conflict transaction not completed - 0x0707, # Query not ready , it always occur at replica 3 - 0x707, # Query not ready - 0x396, # Database in creating status - 0x386, # Database in droping status - 0x03E1, # failed on tmq_subscribe ,topic not exist - 0x03ed , # Topic must be dropped first, SQL: drop database db_0 - 0x0203 , # Invalid value - 0x03f0 , # Stream already exist , topic already exists - - - - - 1000 # REST catch-all error - ]: - return True # These are the ALWAYS-ACCEPTABLE ones + # TDengine 2.x Error Codes: + 0x05, # TSDB_CODE_RPC_NOT_READY + 0x0B, # Unable to establish connection, more details in TD-1648 + # 0x200, # invalid SQL, TODO: re-examine with TD-934 + 0x20F, # query terminated, possibly due to vnoding being dropped, see TD-1776 + 0x213, # "Disconnected from service", result of "kill connection ???" + 0x217, # "db not selected", client side defined error code + # 0x218, # "Table does not exist" client side defined error code + 0x360, # Table already exists + 0x362, + # 0x369, # tag already exists + 0x36A, 0x36B, 0x36D, + 0x381, + 0x380, # "db not selected" + 0x383, + 0x386, # DB is being dropped?! + 0x503, + 0x510, # vnode not in ready state + 0x14, # db not ready, errno changed + 0x600, # Invalid table ID, why? + 0x218, # Table does not exist + + # TDengine 3.0 Error Codes: + 0x0333, # Object is creating # TODO: this really is NOT an acceptable error + 0x0369, # Tag already exists + 0x0388, # Database not exist + 0x03A0, # STable already exists + 0x03A1, # STable [does] not exist + 0x03AA, # Tag already exists + 0x0603, # Table already exists + 0x2603, # Table does not exist, replaced by 2662 below + 0x260d, # Tags number not matched + 0x2662, # Table does not exist #TODO: what about 2603 above? + 0x2600, # database not specified, SQL: show stables , database droped , and show tables + 0x032C, # Object is creating + 0x032D, # Object is dropping + 0x03D3, # Conflict transaction not completed + 0x0707, # Query not ready , it always occur at replica 3 + 0x707, # Query not ready + 0x396, # Database in creating status + 0x386, # Database in droping status + 0x03E1, # failed on tmq_subscribe ,topic not exist + 0x03ed, # Topic must be dropped first, SQL: drop database db_0 + 0x0203, # Invalid value + 0x03f0, # Stream already exist , topic already exists + + 1000 # REST catch-all error + ]: + return True # These are the ALWAYS-ACCEPTABLE ones # This case handled below already. # elif (errno in [ 0x0B ]) and Settings.getConfig().auto_start_service: # return True # We may get "network unavilable" when restarting service - elif Config.getConfig().ignore_errors: # something is specified on command line + elif Config.getConfig().ignore_errors: # something is specified on command line moreErrnos = [int(v, 0) for v in Config.getConfig().ignore_errors.split(',')] if errno in moreErrnos: return True - elif errno == 0x200 : # invalid SQL, we need to div in a bit more + elif errno == 0x200: # invalid SQL, we need to div in a bit more if msg.find("invalid column name") != -1: - return True - elif msg.find("tags number not matched") != -1: # mismatched tags after modification return True - elif msg.find("duplicated column names") != -1: # also alter table tag issues + elif msg.find("tags number not matched") != -1: # mismatched tags after modification return True - elif not self._isServiceStable(): # We are managing service, and ... + elif msg.find("duplicated column names") != -1: # also alter table tag issues + return True + elif not self._isServiceStable(): # We are managing service, and ... Logging.info("Ignoring error when service starting/stopping: errno = {}, msg = {}".format(errno, msg)) return True - - return False # Not an acceptable error + return False # Not an acceptable error def execute(self, wt: WorkerThread): wt.verifyThreadSelf() @@ -1453,7 +1457,7 @@ class Task(): self.logDebug( "[-] executing task {}...".format(self.__class__.__name__)) - self._err = None # TODO: type hint mess up? + self._err = None # TODO: type hint mess up? self._execStats.beginTaskType(self.__class__.__name__) # mark beginning errno2 = None @@ -1465,19 +1469,19 @@ class Task(): errno2 = Helper.convertErrno(err.errno) if (Config.getConfig().continue_on_exception): # user choose to continue self.logDebug("[=] Continue after TAOS exception: errno=0x{:X}, msg: {}, SQL: {}".format( - errno2, err, wt.getDbConn().getLastSql())) + errno2, err, wt.getDbConn().getLastSql())) self._err = err elif self._isErrAcceptable(errno2, err.__str__()): self.logDebug("[=] Acceptable Taos library exception: errno=0x{:X}, msg: {}, SQL: {}".format( - errno2, err, wt.getDbConn().getLastSql())) + errno2, err, wt.getDbConn().getLastSql())) # print("_", end="", flush=True) Progress.emit(Progress.ACCEPTABLE_ERROR) self._err = err - else: # not an acceptable error + else: # not an acceptable error shortTid = threading.get_ident() % 10000 errMsg = "[=] Unexpected Taos library exception ({}): errno=0x{:X}, thread={}, msg: {}, SQL: {}".format( self.__class__.__name__, - errno2, + errno2, shortTid, err, wt.getDbConn().getLastSql()) self.logDebug(errMsg) @@ -1485,7 +1489,8 @@ class Task(): # raise # so that we see full stack traceback.print_exc() print( - "\n\n----------------------------\nProgram ABORTED Due to Unexpected TAOS Error: \n\n{}\n".format(errMsg) + + "\n\n----------------------------\nProgram ABORTED Due to Unexpected TAOS Error: \n\n{}\n".format( + errMsg) + "----------------------------\n") # sys.exit(-1) self._err = err @@ -1502,10 +1507,10 @@ class Task(): traceback.print_exc() # except BaseException: # TODO: what is this again??!! # raise RuntimeError("Punt") - # self.logDebug( - # "[=] Unexpected exception, SQL: {}".format( - # wt.getDbConn().getLastSql())) - # raise + # self.logDebug( + # "[=] Unexpected exception, SQL: {}".format( + # wt.getDbConn().getLastSql())) + # raise self._execStats.endTaskType(self.__class__.__name__, self.isSuccess()) self.logDebug("[X] task execution completed, {}, status: {}".format( @@ -1524,12 +1529,12 @@ class Task(): def getQueryResult(self, wt: WorkerThread): # execute an SQL on the worker thread return wt.getQueryResult() - def lockTable(self, ftName): # full table name + def lockTable(self, ftName): # full table name # print(" <<" + ftName + '_', end="", flush=True) - with Task._lock: # SHORT lock! so we only protect lock creation - if not ftName in Task._tableLocks: # Create new lock and add to list, if needed + with Task._lock: # SHORT lock! so we only protect lock creation + if not ftName in Task._tableLocks: # Create new lock and add to list, if needed Task._tableLocks[ftName] = threading.Lock() - + # No lock protection, anybody can do this any time lock = Task._tableLocks[ftName] # Logging.info("Acquiring lock: {}, {}".format(ftName, lock)) @@ -1538,7 +1543,7 @@ class Task(): def unlockTable(self, ftName): # print('_' + ftName + ">> ", end="", flush=True) - with Task._lock: + with Task._lock: if not ftName in self._tableLocks: raise RuntimeError("Corrupt state, no such lock") lock = Task._tableLocks[ftName] @@ -1588,11 +1593,11 @@ class ExecutionStats: t[0] += 1 # index 0 has the "total" execution times if isSuccess: t[1] += 1 # index 1 has the "success" execution times - if eno != None: + if eno != None: if klassName not in self._errors: self._errors[klassName] = {} errors = self._errors[klassName] - errors[eno] = errors[eno]+1 if eno in errors else 1 + errors[eno] = errors[eno] + 1 if eno in errors else 1 def beginTaskType(self, klassName): with self._lock: @@ -1615,7 +1620,7 @@ class ExecutionStats: Logging.info( "----------------------------------------------------------------------") Logging.info( - "| Crash_Gen test {}, with the following stats:". format( + "| Crash_Gen test {}, with the following stats:".format( "FAILED (reason: {})".format( self._failureReason) if self._failed else "SUCCEEDED")) Logging.info("| Task Execution Times (success/total):") @@ -1628,7 +1633,7 @@ class ExecutionStats: # print("errors = {}".format(errors)) errStrs = ["0x{:X}:{}".format(eno, n) for (eno, n) in errors.items()] # print("error strings = {}".format(errStrs)) - errStr = ", ".join(errStrs) + errStr = ", ".join(errStrs) Logging.info("| {0:<24}: {1}/{2} (Errors: {3})".format(k, n[1], n[0], errStr)) Logging.info( @@ -1647,8 +1652,8 @@ class ExecutionStats: Logging.info("| Top numbers written: {}".format(TaskExecutor.getBoundedList())) Logging.info("| Active DB Native Connections (now): {}".format(DbConnNative.totalConnections)) Logging.info("| Longest native query time: {:.3f} seconds, started: {}". - format(MyTDSql.longestQueryTime, - time.strftime("%x %X", time.localtime(MyTDSql.lqStartTime))) ) + format(MyTDSql.longestQueryTime, + time.strftime("%x %X", time.localtime(MyTDSql.lqStartTime)))) Logging.info("| Longest native query: {}".format(MyTDSql.longestQuery)) Logging.info( "----------------------------------------------------------------------") @@ -1662,12 +1667,12 @@ class StateTransitionTask(Task): _baseTableNumber = None - _endState = None # TODO: no longter used? + _endState = None # TODO: no longter used? @classmethod def getInfo(cls): # each sub class should supply their own information raise RuntimeError("Overriding method expected") - + @classmethod def getEndState(cls): # TODO: optimize by calling it fewer times raise RuntimeError("Overriding method expected") @@ -1687,7 +1692,7 @@ class StateTransitionTask(Task): @classmethod def getRegTableName(cls, i): - if ( StateTransitionTask._baseTableNumber is None): # Set it one time + if (StateTransitionTask._baseTableNumber is None): # Set it one time StateTransitionTask._baseTableNumber = Dice.throw( 999) if Config.getConfig().dynamic_db_table_names else 0 return "reg_table_{}".format(StateTransitionTask._baseTableNumber + i) @@ -1711,16 +1716,21 @@ class TaskCreateDb(StateTransitionTask): repStr = "" if Config.getConfig().num_replicas != 1: # numReplica = Dice.throw(Settings.getConfig().max_replicas) + 1 # 1,2 ... N - numReplica = Config.getConfig().num_replicas # fixed, always + numReplica = Config.getConfig().num_replicas # fixed, always repStr = "replica {}".format(numReplica) - updatePostfix = "" if Config.getConfig().verify_data else "" # allow update only when "verify data" is active , 3.0 version default is update 1 - vg_nums = random.randint(1,8) - cache_model = Dice.choice(['none' , 'last_row' , 'last_value' , 'both']) - buffer = random.randint(3,128) + updatePostfix = "" if Config.getConfig().verify_data else "" # allow update only when "verify data" is active , 3.0 version default is update 1 + vg_nums = random.randint(1, 8) + cache_model = Dice.choice(['none', 'last_row', 'last_value', 'both']) + buffer = random.randint(3, 128) dbName = self._db.getName() - self.execWtSql(wt, "create database {} {} {} vgroups {} cachemodel '{}' buffer {} ".format(dbName, repStr, updatePostfix, vg_nums, cache_model,buffer ) ) + self.execWtSql(wt, "create database {} {} {} vgroups {} cachemodel '{}' buffer {} ".format(dbName, repStr, + updatePostfix, + vg_nums, + cache_model, + buffer)) if dbName == "db_0" and Config.getConfig().use_shadow_db: - self.execWtSql(wt, "create database {} {} {} ".format("db_s", repStr, updatePostfix ) ) + self.execWtSql(wt, "create database {} {} {} ".format("db_s", repStr, updatePostfix)) + class TaskDropDb(StateTransitionTask): @classmethod @@ -1732,19 +1742,20 @@ class TaskDropDb(StateTransitionTask): return state.canDropDb() def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): - + try: - self.queryWtSql(wt, "drop database {}".format(self._db.getName())) # drop database maybe failed ,because topic exists + self.queryWtSql(wt, "drop database {}".format( + self._db.getName())) # drop database maybe failed ,because topic exists except taos.error.ProgrammingError as err: errno = Helper.convertErrno(err.errno) - if errno in [0x0203]: # drop maybe failed + if errno in [0x0203]: # drop maybe failed pass Logging.debug("[OPS] database dropped at {}".format(time.time())) class TaskCreateStream(StateTransitionTask): - + @classmethod def getEndState(cls): return StateHasData() @@ -1755,39 +1766,40 @@ class TaskCreateStream(StateTransitionTask): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): dbname = self._db.getName() - - sub_stream_name = dbname+ '_sub_stream' + + sub_stream_name = dbname + '_sub_stream' sub_stream_tb_name = 'stream_tb_sub' - super_stream_name = dbname+ '_super_stream' + super_stream_name = dbname + '_super_stream' super_stream_tb_name = 'stream_tb_super' if not self._db.exists(wt.getDbConn()): Logging.debug("Skipping task, no DB yet") return - sTable = self._db.getFixedSuperTable() # type: TdSuperTable + sTable = self._db.getFixedSuperTable() # type: TdSuperTable # wt.execSql("use db") # should always be in place - stbname =sTable.getName() + stbname = sTable.getName() sub_tables = sTable.getRegTables(wt.getDbConn()) - aggExpr = Dice.choice([ - 'count(*)', 'avg(speed)', 'sum(speed)', 'stddev(speed)','min(speed)', 'max(speed)', 'first(speed)', 'last(speed)', - 'apercentile(speed, 10)', 'last_row(*)', 'twa(speed)']) - - stream_sql = '' # set default value + aggExpr = Dice.choice([ + 'count(*)', 'avg(speed)', 'sum(speed)', 'stddev(speed)', 'min(speed)', 'max(speed)', 'first(speed)', + 'last(speed)', + 'apercentile(speed, 10)', 'last_row(*)', 'twa(speed)']) + + stream_sql = '' # set default value if sub_tables: sub_tbname = sub_tables[0] # create stream with query above sub_table - stream_sql = 'create stream {} into {}.{} as select {}, avg(speed) FROM {}.{} PARTITION BY tbname INTERVAL(5s) SLIDING(3s) '.\ - format(sub_stream_name,dbname,sub_stream_tb_name ,aggExpr,dbname,sub_tbname) + stream_sql = 'create stream {} into {}.{} as select {}, avg(speed) FROM {}.{} PARTITION BY tbname INTERVAL(5s) SLIDING(3s) '. \ + format(sub_stream_name, dbname, sub_stream_tb_name, aggExpr, dbname, sub_tbname) else: - stream_sql = 'create stream {} into {}.{} as select {}, avg(speed) FROM {}.{} PARTITION BY tbname INTERVAL(5s) SLIDING(3s) '.\ - format(super_stream_name,dbname,super_stream_tb_name,aggExpr, dbname,stbname) + stream_sql = 'create stream {} into {}.{} as select {}, avg(speed) FROM {}.{} PARTITION BY tbname INTERVAL(5s) SLIDING(3s) '. \ + format(super_stream_name, dbname, super_stream_tb_name, aggExpr, dbname, stbname) self.execWtSql(wt, stream_sql) Logging.debug("[OPS] stream is creating at {}".format(time.time())) class TaskCreateTopic(StateTransitionTask): - + @classmethod def getEndState(cls): return StateHasData() @@ -1798,40 +1810,46 @@ class TaskCreateTopic(StateTransitionTask): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): dbname = self._db.getName() - - sub_topic_name = dbname+ '_sub_topic' - super_topic_name = dbname+ '_super_topic' - stable_topic = dbname+ '_stable_topic' - db_topic = 'database_' + dbname+ '_topics' + + sub_topic_name = dbname + '_sub_topic' + super_topic_name = dbname + '_super_topic' + stable_topic = dbname + '_stable_topic' + db_topic = 'database_' + dbname + '_topics' if not self._db.exists(wt.getDbConn()): Logging.debug("Skipping task, no DB yet") return - sTable = self._db.getFixedSuperTable() # type: TdSuperTable + sTable = self._db.getFixedSuperTable() # type: TdSuperTable # wt.execSql("use db") # should always be in place # create topic if not exists topic_ctb_column as select ts, c1, c2, c3 from stb1; - stbname =sTable.getName() + stbname = sTable.getName() sub_tables = sTable.getRegTables(wt.getDbConn()) - scalarExpr = Dice.choice([ '*','speed','color','abs(speed)','acos(speed)','asin(speed)','atan(speed)','ceil(speed)','cos(speed)','cos(speed)', - 'floor(speed)','log(speed,2)','pow(speed,2)','round(speed)','sin(speed)','sqrt(speed)','char_length(color)','concat(color,color)', - 'concat_ws(" ", color,color," ")','length(color)', 'lower(color)', 'ltrim(color)','substr(color , 2)','upper(color)','cast(speed as double)', - 'cast(ts as bigint)']) + scalarExpr = Dice.choice( + ['*', 'speed', 'color', 'abs(speed)', 'acos(speed)', 'asin(speed)', 'atan(speed)', 'ceil(speed)', + 'cos(speed)', 'cos(speed)', + 'floor(speed)', 'log(speed,2)', 'pow(speed,2)', 'round(speed)', 'sin(speed)', 'sqrt(speed)', + 'char_length(color)', 'concat(color,color)', + 'concat_ws(" ", color,color," ")', 'length(color)', 'lower(color)', 'ltrim(color)', 'substr(color , 2)', + 'upper(color)', 'cast(speed as double)', + 'cast(ts as bigint)']) topic_sql = '' # set default value - if Dice.throw(3)==0: # create topic : source data from sub query - if sub_tables: # if not empty + if Dice.throw(3) == 0: # create topic : source data from sub query + if sub_tables: # if not empty sub_tbname = sub_tables[0] # create topic : source data from sub query of sub stable - topic_sql = 'create topic {} as select {} FROM {}.{} ; '.format(sub_topic_name,scalarExpr,dbname,sub_tbname) - + topic_sql = 'create topic {} as select {} FROM {}.{} ; '.format(sub_topic_name, scalarExpr, dbname, + sub_tbname) + else: # create topic : source data from sub query of stable - topic_sql = 'create topic {} as select {} FROM {}.{} '.format(super_topic_name,scalarExpr, dbname,stbname) - elif Dice.throw(3)==1: # create topic : source data from super table - topic_sql = 'create topic {} AS STABLE {}.{} '.format(stable_topic,dbname,stbname) - - elif Dice.throw(3)==2: # create topic : source data from whole database - topic_sql = 'create topic {} AS DATABASE {} '.format(db_topic,dbname) + topic_sql = 'create topic {} as select {} FROM {}.{} '.format(super_topic_name, scalarExpr, dbname, + stbname) + elif Dice.throw(3) == 1: # create topic : source data from super table + topic_sql = 'create topic {} AS STABLE {}.{} '.format(stable_topic, dbname, stbname) + + elif Dice.throw(3) == 2: # create topic : source data from whole database + topic_sql = 'create topic {} AS DATABASE {} '.format(db_topic, dbname) else: pass @@ -1840,8 +1858,9 @@ class TaskCreateTopic(StateTransitionTask): self.execWtSql(wt, topic_sql) Logging.debug("[OPS] db topic is creating at {}".format(time.time())) + class TaskDropTopics(StateTransitionTask): - + @classmethod def getEndState(cls): return StateHasData() @@ -1852,21 +1871,21 @@ class TaskDropTopics(StateTransitionTask): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): dbname = self._db.getName() - if not self._db.exists(wt.getDbConn()): Logging.debug("Skipping task, no DB yet") return - sTable = self._db.getFixedSuperTable() # type: TdSuperTable + sTable = self._db.getFixedSuperTable() # type: TdSuperTable # wt.execSql("use db") # should always be in place tblName = sTable.getName() if sTable.hasTopics(wt.getDbConn()): - sTable.dropTopics(wt.getDbConn(),dbname,None) # drop topics of database - sTable.dropTopics(wt.getDbConn(),dbname,tblName) # drop topics of stable + sTable.dropTopics(wt.getDbConn(), dbname, None) # drop topics of database + sTable.dropTopics(wt.getDbConn(), dbname, tblName) # drop topics of stable + class TaskDropStreams(StateTransitionTask): - + @classmethod def getEndState(cls): return StateHasData() @@ -1877,20 +1896,20 @@ class TaskDropStreams(StateTransitionTask): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): # dbname = self._db.getName() - if not self._db.exists(wt.getDbConn()): Logging.debug("Skipping task, no DB yet") return - sTable = self._db.getFixedSuperTable() # type: TdSuperTable + sTable = self._db.getFixedSuperTable() # type: TdSuperTable # wt.execSql("use db") # should always be in place # tblName = sTable.getName() if sTable.hasStreams(wt.getDbConn()): sTable.dropStreams(wt.getDbConn()) # drop stream of database + class TaskDropStreamTables(StateTransitionTask): - + @classmethod def getEndState(cls): return StateHasData() @@ -1901,42 +1920,42 @@ class TaskDropStreamTables(StateTransitionTask): def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): # dbname = self._db.getName() - if not self._db.exists(wt.getDbConn()): Logging.debug("Skipping task, no DB yet") return - sTable = self._db.getFixedSuperTable() # type: TdSuperTable - wt.execSql("use db") # should always be in place + sTable = self._db.getFixedSuperTable() # type: TdSuperTable + wt.execSql("use db") # should always be in place # tblName = sTable.getName() if sTable.hasStreamTables(wt.getDbConn()): - sTable.dropStreamTables(wt.getDbConn()) # drop stream tables + sTable.dropStreamTables(wt.getDbConn()) # drop stream tables + class TaskCreateConsumers(StateTransitionTask): - + @classmethod def getEndState(cls): return StateHasData() @classmethod def canBeginFrom(cls, state: AnyState): - return state.canCreateConsumers() + return state.canCreateConsumers() def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): - if Config.getConfig().connector_type == 'native': - - sTable = self._db.getFixedSuperTable() # type: TdSuperTable + if Config.getConfig().connector_type == 'native': + + sTable = self._db.getFixedSuperTable() # type: TdSuperTable # wt.execSql("use db") # should always be in place if sTable.hasTopics(wt.getDbConn()): - sTable.createConsumer(wt.getDbConn(),random.randint(1,10)) + sTable.createConsumer(wt.getDbConn(), random.randint(1, 10)) pass else: print(" restful not support tmq consumers") - return + return + - class TaskCreateSuperTable(StateTransitionTask): @classmethod def getEndState(cls): @@ -1951,9 +1970,9 @@ class TaskCreateSuperTable(StateTransitionTask): Logging.debug("Skipping task, no DB yet") return - sTable = self._db.getFixedSuperTable() # type: TdSuperTable + sTable = self._db.getFixedSuperTable() # type: TdSuperTable # wt.execSql("use db") # should always be in place - + sTable.create(wt.getDbConn(), {'ts': TdDataType.TIMESTAMP, 'speed': TdDataType.INT, 'color': TdDataType.BINARY16}, { 'b': TdDataType.BINARY200, 'f': TdDataType.FLOAT}, @@ -1974,11 +1993,10 @@ class TdSuperTable: def getName(self): return self._stName - - def drop(self, dbc, skipCheck = False): + def drop(self, dbc, skipCheck=False): dbName = self._dbName - if self.exists(dbc) : # if myself exists - fullTableName = dbName + '.' + self._stName + if self.exists(dbc): # if myself exists + fullTableName = dbName + '.' + self._stName dbc.execute("DROP TABLE {}".format(fullTableName)) else: if not skipCheck: @@ -1989,64 +2007,55 @@ class TdSuperTable: return dbc.existsSuperTable(self._stName) # TODO: odd semantic, create() method is usually static? - def create(self, dbc, cols: TdColumns, tags: TdTags, dropIfExists = False): + def create(self, dbc, cols: TdColumns, tags: TdTags, dropIfExists=False): '''Creating a super table''' dbName = self._dbName dbc.execute("USE " + dbName) - fullTableName = dbName + '.' + self._stName + fullTableName = dbName + '.' + self._stName if dbc.existsSuperTable(self._stName): - if dropIfExists: - dbc.execute("DROP TABLE {}".format(fullTableName)) - - else: # error + if dropIfExists: + dbc.execute("DROP TABLE {}".format(fullTableName)) + + else: # error raise CrashGenError("Cannot create super table, already exists: {}".format(self._stName)) # Now let's create sql = "CREATE TABLE {} ({})".format( fullTableName, - ",".join(['%s %s'%(k,v.value) for (k,v) in cols.items()])) - if tags : + ",".join(['%s %s' % (k, v.value) for (k, v) in cols.items()])) + if tags: sql += " TAGS ({})".format( - ",".join(['%s %s'%(k,v.value) for (k,v) in tags.items()]) - ) + ",".join(['%s %s' % (k, v.value) for (k, v) in tags.items()]) + ) else: sql += " TAGS (dummy int) " - dbc.execute(sql) + dbc.execute(sql) + + def createConsumer(self, dbc, Consumer_nums): - def createConsumer(self, dbc,Consumer_nums): - def generateConsumer(current_topic_list): - conf = TaosTmqConf() - conf.set("group.id", "tg2") - conf.set("td.connect.user", "root") - conf.set("td.connect.pass", "taosdata") -# conf.set("enable.auto.commit", "true") -# def tmq_commit_cb_print(tmq, resp, offset, param=None): -# print(f"commit: {resp}, tmq: {tmq}, offset: {offset}, param: {param}") -# conf.set_auto_commit_cb(tmq_commit_cb_print, None) - consumer = conf.new_consumer() - topic_list = TaosTmqList() + consumer = Consumer({"group.id": "tg2", "td.connect.user": "root", "td.connect.pass": "taosdata"}) + topic_list = [] for topic in current_topic_list: topic_list.append(topic) - try: - consumer.subscribe(topic_list) - except TmqError as e : - pass + + consumer.subscribe(topic_list) # consumer with random work life time_start = time.time() while 1: - res = consumer.poll(1000) - if time.time() - time_start >random.randint(5,50) : + res = consumer.poll(1) + consumer.commit(res) + if time.time() - time_start > random.randint(5, 50): break try: consumer.unsubscribe() - except TmqError as e : + except TmqError as e: pass return - + # mulit Consumer current_topic_list = self.getTopicLists(dbc) for i in range(Consumer_nums): @@ -2067,84 +2076,86 @@ class TdSuperTable: def getRegTables(self, dbc: DbConn): dbName = self._dbName try: - dbc.query("select distinct TBNAME from {}.{}".format(dbName, self._stName)) # TODO: analyze result set later - except taos.error.ProgrammingError as err: - errno2 = Helper.convertErrno(err.errno) + dbc.query("select distinct TBNAME from {}.{}".format(dbName, + self._stName)) # TODO: analyze result set later + except taos.error.ProgrammingError as err: + errno2 = Helper.convertErrno(err.errno) Logging.debug("[=] Failed to get tables from super table: errno=0x{:X}, msg: {}".format(errno2, err)) raise qr = dbc.getQueryResult() - return [v[0] for v in qr] # list transformation, ref: https://stackoverflow.com/questions/643823/python-list-transformation + return [v[0] for v in + qr] # list transformation, ref: https://stackoverflow.com/questions/643823/python-list-transformation def hasRegTables(self, dbc: DbConn): - + if dbc.existsSuperTable(self._stName): return dbc.query("SELECT * FROM {}.{}".format(self._dbName, self._stName)) > 0 else: return False - def hasStreamTables(self,dbc: DbConn): - + def hasStreamTables(self, dbc: DbConn): + return dbc.query("show {}.stables like 'stream_tb%'".format(self._dbName)) > 0 - def hasStreams(self,dbc: DbConn): + def hasStreams(self, dbc: DbConn): return dbc.query("show streams") > 0 - def hasTopics(self,dbc: DbConn): - + def hasTopics(self, dbc: DbConn): + return dbc.query("show topics") > 0 - def dropTopics(self,dbc: DbConn , dbname=None,stb_name=None): + def dropTopics(self, dbc: DbConn, dbname=None, stb_name=None): dbc.query("show topics ") topics = dbc.getQueryResult() - if dbname !=None and stb_name == None : - + if dbname != None and stb_name == None: + for topic in topics: if dbname in topic[0] and topic[0].startswith("database"): try: dbc.execute('drop topic {}'.format(topic[0])) - Logging.debug("[OPS] topic {} is droping at {}".format(topic,time.time())) - except taos.error.ProgrammingError as err: + Logging.debug("[OPS] topic {} is droping at {}".format(topic, time.time())) + except taos.error.ProgrammingError as err: errno = Helper.convertErrno(err.errno) - if errno in [0x03EB]: # Topic subscribed cannot be dropped - pass + if errno in [0x03EB]: # Topic subscribed cannot be dropped + pass # for subsript in subscriptions: - + else: pass pass return True - elif dbname !=None and stb_name!= None: + elif dbname != None and stb_name != None: for topic in topics: if topic[0].startswith(self._dbName) and topic[0].endswith('topic'): dbc.execute('drop topic {}'.format(topic[0])) - Logging.debug("[OPS] topic {} is droping at {}".format(topic,time.time())) + Logging.debug("[OPS] topic {} is droping at {}".format(topic, time.time())) return True else: return True pass - def dropStreams(self,dbc:DbConn): + def dropStreams(self, dbc: DbConn): dbc.query("show streams ") Streams = dbc.getQueryResult() for Stream in Streams: if Stream[0].startswith(self._dbName): dbc.execute('drop stream {}'.format(Stream[0])) - + return not dbc.query("show streams ") > 0 def dropStreamTables(self, dbc: DbConn): dbc.query("show {}.stables like 'stream_tb%'".format(self._dbName)) - + StreamTables = dbc.getQueryResult() - for StreamTable in StreamTables: + for StreamTable in StreamTables: if self.dropStreams(dbc): - dbc.execute('drop table {}.{}'.format(self._dbName,StreamTable[0])) - + dbc.execute('drop table {}.{}'.format(self._dbName, StreamTable[0])) + return not dbc.query("show {}.stables like 'stream_tb%'".format(self._dbName)) def ensureRegTable(self, task: Optional[Task], dbc: DbConn, regTableName: str): @@ -2155,16 +2166,16 @@ class TdSuperTable: ''' dbName = self._dbName sql = "select tbname from {}.{} where tbname in ('{}')".format(dbName, self._stName, regTableName) - if dbc.query(sql) >= 1 : # reg table exists already + if dbc.query(sql) >= 1: # reg table exists already return # acquire a lock first, so as to be able to *verify*. More details in TD-1471 - fullTableName = dbName + '.' + regTableName + fullTableName = dbName + '.' + regTableName if task is not None: # Somethime thie operation is requested on behalf of a "task" # Logging.info("Locking table for creation: {}".format(fullTableName)) - task.lockTable(fullTableName) # in which case we'll lock this table to ensure serialized access + task.lockTable(fullTableName) # in which case we'll lock this table to ensure serialized access # Logging.info("Table locked for creation".format(fullTableName)) - Progress.emit(Progress.CREATE_TABLE_ATTEMPT) # ATTEMPT to create a new table + Progress.emit(Progress.CREATE_TABLE_ATTEMPT) # ATTEMPT to create a new table # print("(" + fullTableName[-3:] + ")", end="", flush=True) try: sql = "CREATE TABLE {} USING {}.{} tags ({})".format( @@ -2176,17 +2187,17 @@ class TdSuperTable: finally: if task is not None: # Logging.info("Unlocking table after creation: {}".format(fullTableName)) - task.unlockTable(fullTableName) # no matter what + task.unlockTable(fullTableName) # no matter what # Logging.info("Table unlocked after creation: {}".format(fullTableName)) - def _getTagStrForSql(self, dbc) : + def _getTagStrForSql(self, dbc): tags = self._getTags(dbc) tagStrs = [] - for tagName in tags: + for tagName in tags: tagType = tags[tagName] if tagType == 'BINARY': tagStrs.append("'Beijing-Shanghai-LosAngeles'") - elif tagType== 'VARCHAR': + elif tagType == 'VARCHAR': tagStrs.append("'London-Paris-Berlin'") elif tagType == 'FLOAT': tagStrs.append('9.9') @@ -2200,12 +2211,12 @@ class TdSuperTable: dbc.query("DESCRIBE {}.{}".format(self._dbName, self._stName)) stCols = dbc.getQueryResult() # print(stCols) - ret = {row[0]:row[1] for row in stCols if row[3]=='TAG'} # name:type + ret = {row[0]: row[1] for row in stCols if row[3] == 'TAG'} # name:type # print("Tags retrieved: {}".format(ret)) return ret def addTag(self, dbc, tagName, tagType): - if tagName in self._getTags(dbc): # already + if tagName in self._getTags(dbc): # already return # sTable.addTag("extraTag", "int") sql = "alter table {}.{} add tag {} {}".format( @@ -2213,33 +2224,33 @@ class TdSuperTable: dbc.execute(sql) def dropTag(self, dbc, tagName): - if not tagName in self._getTags(dbc): # don't have this tag + if not tagName in self._getTags(dbc): # don't have this tag return sql = "alter table {}.{} drop tag {}".format(self._dbName, self._stName, tagName) dbc.execute(sql) def changeTag(self, dbc, oldTag, newTag): tags = self._getTags(dbc) - if not oldTag in tags: # don't have this tag + if not oldTag in tags: # don't have this tag return - if newTag in tags: # already have this tag + if newTag in tags: # already have this tag return sql = "alter table {}.{} change tag {} {}".format(self._dbName, self._stName, oldTag, newTag) dbc.execute(sql) def generateQueries(self, dbc: DbConn) -> List[SqlQuery]: ''' Generate queries to test/exercise this super table ''' - ret = [] # type: List[SqlQuery] + ret = [] # type: List[SqlQuery] for rTbName in self.getRegTables(dbc): # regular tables - - filterExpr = Dice.choice([ # TODO: add various kind of WHERE conditions + + filterExpr = Dice.choice([ # TODO: add various kind of WHERE conditions None ]) # Run the query against the regular table first - doAggr = (Dice.throw(2) == 0) # 1 in 2 chance - if not doAggr: # don't do aggregate query, just simple one + doAggr = (Dice.throw(2) == 0) # 1 in 2 chance + if not doAggr: # don't do aggregate query, just simple one commonExpr = Dice.choice([ '*', 'abs(speed)', @@ -2256,7 +2267,7 @@ class TdSuperTable: 'sin(speed)', 'sqrt(speed)', 'char_length(color)', - 'concat(color,color)', + 'concat(color,color)', 'concat_ws(" ", color,color," ")', 'length(color)', 'lower(color)', @@ -2276,26 +2287,26 @@ class TdSuperTable: 'distinct(color)' ] ) - ret.append(SqlQuery( # reg table + ret.append(SqlQuery( # reg table "select {} from {}.{}".format(commonExpr, self._dbName, rTbName))) - ret.append(SqlQuery( # super table + ret.append(SqlQuery( # super table "select {} from {}.{}".format(commonExpr, self._dbName, self.getName()))) - else: # Aggregate query - aggExpr = Dice.choice([ + else: # Aggregate query + aggExpr = Dice.choice([ 'count(*)', 'avg(speed)', # 'twa(speed)', # TODO: this one REQUIRES a where statement, not reasonable - 'sum(speed)', - 'stddev(speed)', + 'sum(speed)', + 'stddev(speed)', # SELECTOR functions - 'min(speed)', - 'max(speed)', - 'first(speed)', + 'min(speed)', + 'max(speed)', + 'first(speed)', 'last(speed)', - 'top(speed, 50)', # TODO: not supported? - 'bottom(speed, 50)', # TODO: not supported? - 'apercentile(speed, 10)', # TODO: TD-1316 - 'last_row(*)', # TODO: commented out per TD-3231, we should re-create + 'top(speed, 50)', # TODO: not supported? + 'bottom(speed, 50)', # TODO: not supported? + 'apercentile(speed, 10)', # TODO: TD-1316 + 'last_row(*)', # TODO: commented out per TD-3231, we should re-create # Transformation Functions # 'diff(speed)', # TODO: no supported?! 'spread(speed)', @@ -2313,21 +2324,21 @@ class TdSuperTable: 'sample(speed,5)', 'STATECOUNT(speed,"LT",1)', 'STATEDURATION(speed,"LT",1)', - 'twa(speed)' - - ]) # TODO: add more from 'top' + 'twa(speed)' + + ]) # TODO: add more from 'top' - # if aggExpr not in ['stddev(speed)']: # STDDEV not valid for super tables?! (Done in TD-1049) sql = "select {} from {}.{}".format(aggExpr, self._dbName, self.getName()) - if Dice.throw(3) == 0: # 1 in X chance - partion_expr = Dice.choice(['color','tbname']) + if Dice.throw(3) == 0: # 1 in X chance + partion_expr = Dice.choice(['color', 'tbname']) sql = sql + ' partition BY ' + partion_expr + ' order by ' + partion_expr Progress.emit(Progress.QUERY_GROUP_BY) # Logging.info("Executing GROUP-BY query: " + sql) ret.append(SqlQuery(sql)) - return ret + return ret + class TaskReadData(StateTransitionTask): @classmethod @@ -2345,60 +2356,61 @@ class TaskReadData(StateTransitionTask): def _reconnectIfNeeded(self, wt): # 1 in 20 chance, simulate a broken connection, only if service stable (not restarting) - if random.randrange(20)==0: # and self._canRestartService(): # TODO: break connection in all situations + if random.randrange(20) == 0: # and self._canRestartService(): # TODO: break connection in all situations # Logging.info("Attempting to reconnect to server") # TODO: change to DEBUG - Progress.emit(Progress.SERVICE_RECONNECT_START) + Progress.emit(Progress.SERVICE_RECONNECT_START) try: wt.getDbConn().close() wt.getDbConn().open() - except ConnectionError as err: # may fail + except ConnectionError as err: # may fail if not gSvcMgr: Logging.error("Failed to reconnect in client-only mode") - raise # Not OK if we are running in client-only mode - if gSvcMgr.isRunning(): # may have race conditon, but low prob, due to + raise # Not OK if we are running in client-only mode + if gSvcMgr.isRunning(): # may have race conditon, but low prob, due to Logging.error("Failed to reconnect when managed server is running") - raise # Not OK if we are running normally + raise # Not OK if we are running normally - Progress.emit(Progress.SERVICE_RECONNECT_FAILURE) + Progress.emit(Progress.SERVICE_RECONNECT_FAILURE) # Logging.info("Ignoring DB reconnect error") # print("_r", end="", flush=True) - Progress.emit(Progress.SERVICE_RECONNECT_SUCCESS) + Progress.emit(Progress.SERVICE_RECONNECT_SUCCESS) # The above might have taken a lot of time, service might be running # by now, causing error below to be incorrectly handled due to timing issue - return # TODO: fix server restart status race condtion - + return # TODO: fix server restart status race condtion def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): self._reconnectIfNeeded(wt) dbc = wt.getDbConn() sTable = self._db.getFixedSuperTable() - + for q in sTable.generateQueries(dbc): # regular tables try: sql = q.getSql() # if 'GROUP BY' in sql: # Logging.info("Executing GROUP-BY query: " + sql) dbc.execute(sql) - except taos.error.ProgrammingError as err: + except taos.error.ProgrammingError as err: errno2 = Helper.convertErrno(err.errno) Logging.debug("[=] Read Failure: errno=0x{:X}, msg: {}, SQL: {}".format(errno2, err, dbc.getLastSql())) raise + class SqlQuery: @classmethod def buildRandom(cls, db: Database): '''Build a random query against a certain database''' - + dbName = db.getName() - def __init__(self, sql:str = None): + def __init__(self, sql: str = None): self._sql = sql def getSql(self): return self._sql - + + class TaskDropSuperTable(StateTransitionTask): @classmethod def getEndState(cls): @@ -2421,7 +2433,7 @@ class TaskDropSuperTable(StateTransitionTask): regTableName = self.getRegTableName(i) # "db.reg_table_{}".format(i) try: self.execWtSql(wt, "drop table {}.{}". - format(self._db.getName(), regTableName)) # nRows always 0, like MySQL + format(self._db.getName(), regTableName)) # nRows always 0, like MySQL except taos.error.ProgrammingError as err: # correcting for strange error number scheme errno2 = Helper.convertErrno(err.errno) @@ -2429,7 +2441,6 @@ class TaskDropSuperTable(StateTransitionTask): isSuccess = False Logging.debug("[DB] Acceptable error when dropping a table") continue # try to delete next regular table - if (not tickOutput): tickOutput = True # Print only one time @@ -2441,8 +2452,6 @@ class TaskDropSuperTable(StateTransitionTask): # Drop the super table itself tblName = self._db.getFixedSuperTableName() self.execWtSql(wt, "drop table {}.{}".format(self._db.getName(), tblName)) - - class TaskAlterTags(StateTransitionTask): @@ -2472,6 +2481,7 @@ class TaskAlterTags(StateTransitionTask): sTable.changeTag(dbc, "extraTag", "newTag") # sql = "alter table db.{} change tag extraTag newTag".format(tblName) + class TaskRestartService(StateTransitionTask): _isRunning = False _classLock = threading.Lock() @@ -2484,11 +2494,12 @@ class TaskRestartService(StateTransitionTask): def canBeginFrom(cls, state: AnyState): if Config.getConfig().auto_start_service: return state.canDropFixedSuperTable() # Basicallly when we have the super table - return False # don't run this otherwise + return False # don't run this otherwise CHANCE_TO_RESTART_SERVICE = 200 + def _executeInternal(self, te: TaskExecutor, wt: WorkerThread): - if not Config.getConfig().auto_start_service: # only execute when we are in -a mode + if not Config.getConfig().auto_start_service: # only execute when we are in -a mode print("_a", end="", flush=True) return @@ -2498,20 +2509,22 @@ class TaskRestartService(StateTransitionTask): return self._isRunning = True - if Dice.throw(self.CHANCE_TO_RESTART_SERVICE) == 0: # 1 in N chance + if Dice.throw(self.CHANCE_TO_RESTART_SERVICE) == 0: # 1 in N chance dbc = wt.getDbConn() - dbc.execute("select * from information_schema.ins_databases") # simple delay, align timing with other workers + dbc.execute( + "select * from information_schema.ins_databases") # simple delay, align timing with other workers gSvcMgr.restart() self._isRunning = False + class TaskAddData(StateTransitionTask): # Track which table is being actively worked on activeTable: Set[int] = set() # We use these two files to record operations to DB, useful for power-off tests - fAddLogReady = None # type: Optional[io.TextIOWrapper] - fAddLogDone = None # type: Optional[io.TextIOWrapper] + fAddLogReady = None # type: Optional[io.TextIOWrapper] + fAddLogDone = None # type: Optional[io.TextIOWrapper] @classmethod def prepToRecordOps(cls): @@ -2532,12 +2545,12 @@ class TaskAddData(StateTransitionTask): def canBeginFrom(cls, state: AnyState): return state.canAddData() - def _lockTableIfNeeded(self, fullTableName, extraMsg = ''): + def _lockTableIfNeeded(self, fullTableName, extraMsg=''): if Config.getConfig().verify_data: # Logging.info("Locking table: {}".format(fullTableName)) - self.lockTable(fullTableName) + self.lockTable(fullTableName) # Logging.info("Table locked {}: {}".format(extraMsg, fullTableName)) - # print("_w" + str(nextInt % 100), end="", flush=True) # Trace what was written + # print("_w" + str(nextInt % 100), end="", flush=True) # Trace what was written else: # Logging.info("Skipping locking table") pass @@ -2545,15 +2558,15 @@ class TaskAddData(StateTransitionTask): def _unlockTableIfNeeded(self, fullTableName): if Config.getConfig().verify_data: # Logging.info("Unlocking table: {}".format(fullTableName)) - self.unlockTable(fullTableName) + self.unlockTable(fullTableName) # Logging.info("Table unlocked: {}".format(fullTableName)) else: pass # Logging.info("Skipping unlocking table") - def _addDataInBatch(self, db, dbc, regTableName, te: TaskExecutor): - numRecords = self.LARGE_NUMBER_OF_RECORDS if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_RECORDS - + def _addDataInBatch(self, db, dbc, regTableName, te: TaskExecutor): + numRecords = self.LARGE_NUMBER_OF_RECORDS if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_RECORDS + fullTableName = db.getName() + '.' + regTableName self._lockTableIfNeeded(fullTableName, 'batch') @@ -2571,10 +2584,8 @@ class TaskAddData(StateTransitionTask): # Logging.info("Data added in batch: {}".format(sql)) self._unlockTableIfNeeded(fullTableName) - - - def _addData(self, db: Database, dbc, regTableName, te: TaskExecutor): # implied: NOT in batches - numRecords = self.LARGE_NUMBER_OF_RECORDS if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_RECORDS + def _addData(self, db: Database, dbc, regTableName, te: TaskExecutor): # implied: NOT in batches + numRecords = self.LARGE_NUMBER_OF_RECORDS if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_RECORDS for j in range(numRecords): # number of records per table intToWrite = db.getNextInt() @@ -2587,13 +2598,14 @@ class TaskAddData(StateTransitionTask): self.fAddLogReady.write("Ready to write {} to {}\n".format(intToWrite, regTableName)) self.fAddLogReady.flush() os.fsync(self.fAddLogReady.fileno()) - + # TODO: too ugly trying to lock the table reliably, refactor... fullTableName = db.getName() + '.' + regTableName - self._lockTableIfNeeded(fullTableName) # so that we are verify read-back. TODO: deal with exceptions before unlock - + self._lockTableIfNeeded( + fullTableName) # so that we are verify read-back. TODO: deal with exceptions before unlock + try: - sql = "INSERT INTO {} VALUES ('{}', {}, '{}');".format( # removed: tags ('{}', {}) + sql = "INSERT INTO {} VALUES ('{}', {}, '{}');".format( # removed: tags ('{}', {}) fullTableName, # ds.getFixedSuperTableName(), # ds.getNextBinary(), ds.getNextFloat(), @@ -2604,55 +2616,56 @@ class TaskAddData(StateTransitionTask): intWrote = intToWrite # Quick hack, attach an update statement here. TODO: create an "update" task - if (not Config.getConfig().use_shadow_db) and Dice.throw(5) == 0: # 1 in N chance, plus not using shaddow DB - intToUpdate = db.getNextInt() # Updated, but should not succeed + if (not Config.getConfig().use_shadow_db) and Dice.throw( + 5) == 0: # 1 in N chance, plus not using shaddow DB + intToUpdate = db.getNextInt() # Updated, but should not succeed nextColor = db.getNextColor() - sql = "INSERt INTO {} VALUES ('{}', {}, '{}');".format( # "INSERt" means "update" here - fullTableName, - nextTick, intToUpdate, nextColor) + sql = "INSERt INTO {} VALUES ('{}', {}, '{}');".format( # "INSERt" means "update" here + fullTableName, + nextTick, intToUpdate, nextColor) # sql = "UPDATE {} set speed={}, color='{}' WHERE ts='{}'".format( # fullTableName, db.getNextInt(), db.getNextColor(), nextTick) dbc.execute(sql) - intWrote = intToUpdate # We updated, seems TDengine non-cluster accepts this. + intWrote = intToUpdate # We updated, seems TDengine non-cluster accepts this. - except: # Any exception at all - self._unlockTableIfNeeded(fullTableName) + except: # Any exception at all + self._unlockTableIfNeeded(fullTableName) raise # Now read it back and verify, we might encounter an error if table is dropped - if Config.getConfig().verify_data: # only if command line asks for it + if Config.getConfig().verify_data: # only if command line asks for it try: readBack = dbc.queryScalar("SELECT speed from {}.{} WHERE ts='{}'". - format(db.getName(), regTableName, nextTick)) - if readBack != intWrote : + format(db.getName(), regTableName, nextTick)) + if readBack != intWrote: raise taos.error.ProgrammingError( "Failed to read back same data, wrote: {}, read: {}" .format(intWrote, readBack), 0x999) except taos.error.ProgrammingError as err: errno = Helper.convertErrno(err.errno) - if errno == CrashGenError.INVALID_EMPTY_RESULT: # empty result + if errno == CrashGenError.INVALID_EMPTY_RESULT: # empty result raise taos.error.ProgrammingError( "Failed to read back same data for tick: {}, wrote: {}, read: EMPTY" .format(nextTick, intWrote), errno) - elif errno == CrashGenError.INVALID_MULTIPLE_RESULT : # multiple results + elif errno == CrashGenError.INVALID_MULTIPLE_RESULT: # multiple results raise taos.error.ProgrammingError( "Failed to read back same data for tick: {}, wrote: {}, read: MULTIPLE RESULTS" .format(nextTick, intWrote), errno) - elif errno in [0x218, 0x362]: # table doesn't exist + elif errno in [0x218, 0x362]: # table doesn't exist # do nothing pass else: # Re-throw otherwise raise finally: - self._unlockTableIfNeeded(fullTableName) # Quite ugly, refactor lock/unlock + self._unlockTableIfNeeded(fullTableName) # Quite ugly, refactor lock/unlock # Done with read-back verification, unlock the table now else: - self._unlockTableIfNeeded(fullTableName) + self._unlockTableIfNeeded(fullTableName) - # Successfully wrote the data into the DB, let's record it somehow + # Successfully wrote the data into the DB, let's record it somehow te.recordDataMark(intWrote) if Config.getConfig().record_ops: @@ -2666,17 +2679,17 @@ class TaskAddData(StateTransitionTask): # ds = self._dbManager # Quite DANGEROUS here, may result in multi-thread client access db = self._db dbc = wt.getDbConn() - numTables = self.LARGE_NUMBER_OF_TABLES if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_TABLES + numTables = self.LARGE_NUMBER_OF_TABLES if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_TABLES numRecords = self.LARGE_NUMBER_OF_RECORDS if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_RECORDS - tblSeq = list(range(numTables )) - random.shuffle(tblSeq) # now we have random sequence + tblSeq = list(range(numTables)) + random.shuffle(tblSeq) # now we have random sequence for i in tblSeq: if (i in self.activeTable): # wow already active # print("x", end="", flush=True) # concurrent insertion Progress.emit(Progress.CONCURRENT_INSERTION) else: self.activeTable.add(i) # marking it active - + dbName = db.getName() sTable = db.getFixedSuperTable() regTableName = self.getRegTableName(i) # "db.reg_table_{}".format(i) @@ -2684,21 +2697,22 @@ class TaskAddData(StateTransitionTask): # self._lockTable(fullTableName) # "create table" below. Stop it if the table is "locked" sTable.ensureRegTable(self, wt.getDbConn(), regTableName) # Ensure the table exists # self._unlockTable(fullTableName) - - if Dice.throw(1) == 0: # 1 in 2 chance + + if Dice.throw(1) == 0: # 1 in 2 chance self._addData(db, dbc, regTableName, te) else: self._addDataInBatch(db, dbc, regTableName, te) self.activeTable.discard(i) # not raising an error, unlike remove + class TaskDeleteData(StateTransitionTask): # Track which table is being actively worked on activeTable: Set[int] = set() # We use these two files to record operations to DB, useful for power-off tests - fAddLogReady = None # type: Optional[io.TextIOWrapper] - fAddLogDone = None # type: Optional[io.TextIOWrapper] + fAddLogReady = None # type: Optional[io.TextIOWrapper] + fAddLogDone = None # type: Optional[io.TextIOWrapper] @classmethod def prepToRecordOps(cls): @@ -2719,12 +2733,12 @@ class TaskDeleteData(StateTransitionTask): def canBeginFrom(cls, state: AnyState): return state.canDeleteData() - def _lockTableIfNeeded(self, fullTableName, extraMsg = ''): + def _lockTableIfNeeded(self, fullTableName, extraMsg=''): if Config.getConfig().verify_data: # Logging.info("Locking table: {}".format(fullTableName)) - self.lockTable(fullTableName) + self.lockTable(fullTableName) # Logging.info("Table locked {}: {}".format(extraMsg, fullTableName)) - # print("_w" + str(nextInt % 100), end="", flush=True) # Trace what was written + # print("_w" + str(nextInt % 100), end="", flush=True) # Trace what was written else: # Logging.info("Skipping locking table") pass @@ -2732,15 +2746,15 @@ class TaskDeleteData(StateTransitionTask): def _unlockTableIfNeeded(self, fullTableName): if Config.getConfig().verify_data: # Logging.info("Unlocking table: {}".format(fullTableName)) - self.unlockTable(fullTableName) + self.unlockTable(fullTableName) # Logging.info("Table unlocked: {}".format(fullTableName)) else: pass # Logging.info("Skipping unlocking table") - def _deleteData(self, db: Database, dbc, regTableName, te: TaskExecutor): # implied: NOT in batches - numRecords = self.LARGE_NUMBER_OF_RECORDS if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_RECORDS - del_Records = int(numRecords/5) + def _deleteData(self, db: Database, dbc, regTableName, te: TaskExecutor): # implied: NOT in batches + numRecords = self.LARGE_NUMBER_OF_RECORDS if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_RECORDS + del_Records = int(numRecords / 5) if Dice.throw(2) == 0: for j in range(del_Records): # number of records per table intToWrite = db.getNextInt() @@ -2753,13 +2767,14 @@ class TaskDeleteData(StateTransitionTask): self.fAddLogReady.write("Ready to delete {} to {}\n".format(intToWrite, regTableName)) self.fAddLogReady.flush() os.fsync(self.fAddLogReady.fileno()) - + # TODO: too ugly trying to lock the table reliably, refactor... fullTableName = db.getName() + '.' + regTableName - self._lockTableIfNeeded(fullTableName) # so that we are verify read-back. TODO: deal with exceptions before unlock - + self._lockTableIfNeeded( + fullTableName) # so that we are verify read-back. TODO: deal with exceptions before unlock + try: - sql = "delete from {} where ts = '{}' ;".format( # removed: tags ('{}', {}) + sql = "delete from {} where ts = '{}' ;".format( # removed: tags ('{}', {}) fullTableName, # ds.getFixedSuperTableName(), # ds.getNextBinary(), ds.getNextFloat(), @@ -2772,45 +2787,46 @@ class TaskDeleteData(StateTransitionTask): intWrote = intToWrite # Quick hack, attach an update statement here. TODO: create an "update" task - if (not Config.getConfig().use_shadow_db) and Dice.throw(5) == 0: # 1 in N chance, plus not using shaddow DB - intToUpdate = db.getNextInt() # Updated, but should not succeed + if (not Config.getConfig().use_shadow_db) and Dice.throw( + 5) == 0: # 1 in N chance, plus not using shaddow DB + intToUpdate = db.getNextInt() # Updated, but should not succeed # nextColor = db.getNextColor() - sql = "delete from {} where ts = '{}' ;".format( # "INSERt" means "update" here - fullTableName, - nextTick) + sql = "delete from {} where ts = '{}' ;".format( # "INSERt" means "update" here + fullTableName, + nextTick) # sql = "UPDATE {} set speed={}, color='{}' WHERE ts='{}'".format( # fullTableName, db.getNextInt(), db.getNextColor(), nextTick) dbc.execute(sql) - intWrote = intToUpdate # We updated, seems TDengine non-cluster accepts this. + intWrote = intToUpdate # We updated, seems TDengine non-cluster accepts this. - except: # Any exception at all - self._unlockTableIfNeeded(fullTableName) + except: # Any exception at all + self._unlockTableIfNeeded(fullTableName) raise # Now read it back and verify, we might encounter an error if table is dropped - if Config.getConfig().verify_data: # only if command line asks for it + if Config.getConfig().verify_data: # only if command line asks for it try: dbc.query("SELECT * from {}.{} WHERE ts='{}'". - format(db.getName(), regTableName, nextTick)) + format(db.getName(), regTableName, nextTick)) result = dbc.getQueryResult() - if len(result)==0: + if len(result) == 0: # means data has been delete - print("D1",end="") # DF means delete failed + print("D1", end="") # DF means delete failed else: - print("DF",end="") # DF means delete failed + print("DF", end="") # DF means delete failed except taos.error.ProgrammingError as err: errno = Helper.convertErrno(err.errno) # if errno == CrashGenError.INVALID_EMPTY_RESULT: # empty result # print("D1",end="") # D1 means delete data success and only 1 record - if errno in [0x218, 0x362,0x2662]: # table doesn't exist + if errno in [0x218, 0x362, 0x2662]: # table doesn't exist # do nothing pass else: # Re-throw otherwise raise finally: - self._unlockTableIfNeeded(fullTableName) # Quite ugly, refactor lock/unlock + self._unlockTableIfNeeded(fullTableName) # Quite ugly, refactor lock/unlock # Done with read-back verification, unlock the table now # Successfully wrote the data into the DB, let's record it somehow te.recordDataMark(intWrote) @@ -2824,52 +2840,54 @@ class TaskDeleteData(StateTransitionTask): self.fAddLogReady.write("Ready to delete {} to {}\n".format(intToWrite, regTableName)) self.fAddLogReady.flush() os.fsync(self.fAddLogReady.fileno()) - + # TODO: too ugly trying to lock the table reliably, refactor... fullTableName = db.getName() + '.' + regTableName - self._lockTableIfNeeded(fullTableName) # so that we are verify read-back. TODO: deal with exceptions before unlock - + self._lockTableIfNeeded( + fullTableName) # so that we are verify read-back. TODO: deal with exceptions before unlock + try: - sql = "delete from {} ;".format( # removed: tags ('{}', {}) + sql = "delete from {} ;".format( # removed: tags ('{}', {}) fullTableName) # Logging.info("Adding data: {}".format(sql)) dbc.execute(sql) # Logging.info("Data added: {}".format(sql)) - + # Quick hack, attach an update statement here. TODO: create an "update" task - if (not Config.getConfig().use_shadow_db) and Dice.throw(5) == 0: # 1 in N chance, plus not using shaddow DB - sql = "delete from {} ;".format( # "INSERt" means "update" here - fullTableName) + if (not Config.getConfig().use_shadow_db) and Dice.throw( + 5) == 0: # 1 in N chance, plus not using shaddow DB + sql = "delete from {} ;".format( # "INSERt" means "update" here + fullTableName) dbc.execute(sql) - except: # Any exception at all - self._unlockTableIfNeeded(fullTableName) + except: # Any exception at all + self._unlockTableIfNeeded(fullTableName) raise # Now read it back and verify, we might encounter an error if table is dropped - if Config.getConfig().verify_data: # only if command line asks for it + if Config.getConfig().verify_data: # only if command line asks for it try: dbc.query("SELECT * from {}.{} WHERE ts='{}'". - format(db.getName(), regTableName, nextTick)) + format(db.getName(), regTableName, nextTick)) result = dbc.getQueryResult() - if len(result)==0: + if len(result) == 0: # means data has been delete - print("DA",end="") + print("DA", end="") else: - print("DF",end="") # DF means delete failed + print("DF", end="") # DF means delete failed except taos.error.ProgrammingError as err: errno = Helper.convertErrno(err.errno) # if errno == CrashGenError.INVALID_EMPTY_RESULT: # empty result # print("Da",end="") # Da means delete data success and for all datas - if errno in [0x218, 0x362,0x2662]: # table doesn't exist + if errno in [0x218, 0x362, 0x2662]: # table doesn't exist # do nothing pass else: # Re-throw otherwise raise finally: - self._unlockTableIfNeeded(fullTableName) # Quite ugly, refactor lock/unlock + self._unlockTableIfNeeded(fullTableName) # Quite ugly, refactor lock/unlock # Done with read-back verification, unlock the table now if Config.getConfig().record_ops: @@ -2883,17 +2901,17 @@ class TaskDeleteData(StateTransitionTask): # ds = self._dbManager # Quite DANGEROUS here, may result in multi-thread client access db = self._db dbc = wt.getDbConn() - numTables = self.LARGE_NUMBER_OF_TABLES if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_TABLES + numTables = self.LARGE_NUMBER_OF_TABLES if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_TABLES numRecords = self.LARGE_NUMBER_OF_RECORDS if Config.getConfig().larger_data else self.SMALL_NUMBER_OF_RECORDS - tblSeq = list(range(numTables )) - random.shuffle(tblSeq) # now we have random sequence + tblSeq = list(range(numTables)) + random.shuffle(tblSeq) # now we have random sequence for i in tblSeq: if (i in self.activeTable): # wow already active # print("x", end="", flush=True) # concurrent insertion Progress.emit(Progress.CONCURRENT_INSERTION) else: self.activeTable.add(i) # marking it active - + dbName = db.getName() sTable = db.getFixedSuperTable() regTableName = self.getRegTableName(i) # "db.reg_table_{}".format(i) @@ -2901,54 +2919,57 @@ class TaskDeleteData(StateTransitionTask): # self._lockTable(fullTableName) # "create table" below. Stop it if the table is "locked" sTable.ensureRegTable(self, wt.getDbConn(), regTableName) # Ensure the table exists # self._unlockTable(fullTableName) - + self._deleteData(db, dbc, regTableName, te) - + self.activeTable.discard(i) # not raising an error, unlike remove -class ThreadStacks: # stack info for all threads +class ThreadStacks: # stack info for all threads def __init__(self): self._allStacks = {} - allFrames = sys._current_frames() # All current stack frames, keyed with "ident" + allFrames = sys._current_frames() # All current stack frames, keyed with "ident" for th in threading.enumerate(): # For each thread - stack = traceback.extract_stack(allFrames[th.ident]) #type: ignore # Get stack for a thread - shortTid = th.native_id % 10000 #type: ignore - self._allStacks[shortTid] = stack # Was using th.native_id + stack = traceback.extract_stack(allFrames[th.ident]) # type: ignore # Get stack for a thread + shortTid = th.native_id % 10000 # type: ignore + self._allStacks[shortTid] = stack # Was using th.native_id - def record_current_time(self,current_time): + def record_current_time(self, current_time): self.current_time = current_time - def print(self, filteredEndName = None, filterInternal = False): - for shortTid, stack in self._allStacks.items(): # for each thread, stack frames top to bottom + def print(self, filteredEndName=None, filterInternal=False): + for shortTid, stack in self._allStacks.items(): # for each thread, stack frames top to bottom lastFrame = stack[-1] - if filteredEndName: # we need to filter out stacks that match this name - if lastFrame.name == filteredEndName : # end did not match + if filteredEndName: # we need to filter out stacks that match this name + if lastFrame.name == filteredEndName: # end did not match continue if filterInternal: - if lastFrame.name in ['wait', 'invoke_excepthook', - '_wait', # The Barrier exception - 'svcOutputReader', # the svcMgr thread - '__init__']: # the thread that extracted the stack - continue # ignore + if lastFrame.name in ['wait', 'invoke_excepthook', + '_wait', # The Barrier exception + 'svcOutputReader', # the svcMgr thread + '__init__']: # the thread that extracted the stack + continue # ignore # Now print print("\n<----- Thread Info for LWP/ID: {} (most recent call last) <-----".format(shortTid)) - + lastSqlForThread = DbConn.fetchSqlForThread(shortTid) last_sql_commit_time = DbConn.get_save_sql_time(shortTid) # time_cost = DbConn.get_time_cost() - print("Last SQL statement attempted from thread {} ({:.4f} sec ago) is: {}".format(shortTid, self.current_time-last_sql_commit_time ,lastSqlForThread)) + print("Last SQL statement attempted from thread {} ({:.4f} sec ago) is: {}".format(shortTid, + self.current_time - last_sql_commit_time, + lastSqlForThread)) stackFrame = 0 - for frame in stack: # was using: reversed(stack) + for frame in stack: # was using: reversed(stack) # print(frame) print("[{sf}] File {filename}, line {lineno}, in {name}".format( sf=stackFrame, filename=frame.filename, lineno=frame.lineno, name=frame.name)) print(" {}".format(frame.line)) stackFrame += 1 print("-----> End of Thread Info ----->\n") - if self.current_time-last_sql_commit_time >100: # dead lock occured + if self.current_time - last_sql_commit_time > 100: # dead lock occured print("maybe dead locked of thread {} ".format(shortTid)) + class ClientManager: def __init__(self): Logging.info("Starting service manager") @@ -3041,36 +3062,35 @@ class ClientManager: # time.sleep(2.0) # dbManager = None # release? - def run(self, svcMgr): + def run(self, svcMgr): # self._printLastNumbers() # global gConfig # Prepare Tde Instance global gContainer - tInst = gContainer.defTdeInstance = TdeInstance() # "subdir to hold the instance" + tInst = gContainer.defTdeInstance = TdeInstance() # "subdir to hold the instance" cfg = Config.getConfig() dbManager = DbManager(cfg.connector_type, tInst.getDbTarget()) # Regular function thPool = ThreadPool(cfg.num_threads, cfg.max_steps) self.tc = ThreadCoordinator(thPool, dbManager) - + Logging.info("Starting client instance: {}".format(tInst)) self.tc.run() # print("exec stats: {}".format(self.tc.getExecStats())) # print("TC failed = {}".format(self.tc.isFailed())) - if svcMgr: # gConfig.auto_start_service: + if svcMgr: # gConfig.auto_start_service: svcMgr.stopTaosServices() svcMgr = None - # Release global variables # gConfig = None Config.clearConfig() gSvcMgr = None logger = None - + thPool = None - dbManager.cleanUp() # destructor wouldn't run in time + dbManager.cleanUp() # destructor wouldn't run in time dbManager = None # Print exec status, etc., AFTER showing messages from the server @@ -3082,7 +3102,7 @@ class ClientManager: # Release variables here self.tc = None - gc.collect() # force garbage collection + gc.collect() # force garbage collection # h = hpy() # print("\n----- Final Python Heap -----\n") # print(h.heap()) @@ -3093,37 +3113,38 @@ class ClientManager: # self.tc.getDbManager().cleanUp() # clean up first, so we can show ZERO db connections self.tc.printStats() + class MainExec: - def __init__(self): + def __init__(self): self._clientMgr = None - self._svcMgr = None # type: Optional[ServiceManager] + self._svcMgr = None # type: Optional[ServiceManager] signal.signal(signal.SIGTERM, self.sigIntHandler) - signal.signal(signal.SIGINT, self.sigIntHandler) + signal.signal(signal.SIGINT, self.sigIntHandler) signal.signal(signal.SIGUSR1, self.sigUsrHandler) # different handler! def sigUsrHandler(self, signalNumber, frame): if self._clientMgr: self._clientMgr.sigUsrHandler(signalNumber, frame) - elif self._svcMgr: # Only if no client mgr, we are running alone + elif self._svcMgr: # Only if no client mgr, we are running alone self._svcMgr.sigUsrHandler(signalNumber, frame) - + def sigIntHandler(self, signalNumber, frame): - if self._svcMgr: + if self._svcMgr: self._svcMgr.sigIntHandler(signalNumber, frame) - if self._clientMgr: + if self._clientMgr: self._clientMgr.sigIntHandler(signalNumber, frame) def runClient(self): global gSvcMgr if Config.getConfig().auto_start_service: - gSvcMgr = self._svcMgr = ServiceManager(1) # hack alert - gSvcMgr.startTaosServices() # we start, don't run - + gSvcMgr = self._svcMgr = ServiceManager(1) # hack alert + gSvcMgr.startTaosServices() # we start, don't run + self._clientMgr = ClientManager() ret = None - try: - ret = self._clientMgr.run(self._svcMgr) # stop TAOS service inside + try: + ret = self._clientMgr.run(self._svcMgr) # stop TAOS service inside except requests.exceptions.ConnectionError as err: Logging.warning("Failed to open REST connection to DB: {}".format(err)) # don't raise @@ -3131,10 +3152,11 @@ class MainExec: def runService(self): global gSvcMgr - gSvcMgr = self._svcMgr = ServiceManager(Config.getConfig().num_dnodes) # save it in a global variable TODO: hack alert + gSvcMgr = self._svcMgr = ServiceManager( + Config.getConfig().num_dnodes) # save it in a global variable TODO: hack alert - gSvcMgr.run() # run to some end state - gSvcMgr = self._svcMgr = None + gSvcMgr.run() # run to some end state + gSvcMgr = self._svcMgr = None def _buildCmdLineParser(self): parser = argparse.ArgumentParser( @@ -3145,7 +3167,7 @@ class MainExec: 1. You build TDengine in the top level ./build directory, as described in offical docs 2. You run the server there before this script: ./build/bin/taosd -c test/cfg - ''')) + ''')) parser.add_argument( '-a', @@ -3209,7 +3231,7 @@ class MainExec: '-n', '--dynamic-db-table-names', action='store_true', - help='Use non-fixed names for dbs/tables, for -b, useful for multi-instance executions (default: false)') + help='Use non-fixed names for dbs/tables, for -b, useful for multi-instance executions (default: false)') parser.add_argument( '-o', '--num-dnodes', @@ -3259,19 +3281,18 @@ class MainExec: return parser - - def init(self): # TODO: refactor + def init(self): # TODO: refactor global gContainer - gContainer = Container() # micky-mouse DI + gContainer = Container() # micky-mouse DI - global gSvcMgr # TODO: refactor away + global gSvcMgr # TODO: refactor away gSvcMgr = None parser = self._buildCmdLineParser() Config.init(parser) # Sanity check for arguments - if Config.getConfig().use_shadow_db and Config.getConfig().max_dbs>1 : + if Config.getConfig().use_shadow_db and Config.getConfig().max_dbs > 1: raise CrashGenError("Cannot combine use-shadow-db with max-dbs of more than 1") Logging.clsInit(Config.getConfig().debug) @@ -3282,10 +3303,10 @@ class MainExec: if Config.getConfig().run_tdengine: # run server try: self.runService() - return 0 # success + return 0 # success except ConnectionError as err: Logging.error("Failed to make DB connection, please check DB instance manually") - return -1 # failure + return -1 # failure else: return self.runClient() @@ -3294,7 +3315,7 @@ class Container(): _propertyList = {'defTdeInstance'} def __init__(self): - self._cargo = {} # No cargo at the beginning + self._cargo = {} # No cargo at the beginning def _verifyValidProperty(self, name): if not name in self._propertyList: @@ -3303,10 +3324,10 @@ class Container(): # Called for an attribute, when other mechanisms fail (compare to __getattribute__) def __getattr__(self, name): self._verifyValidProperty(name) - return self._cargo[name] # just a simple lookup + return self._cargo[name] # just a simple lookup def __setattr__(self, name, value): - if name == '_cargo' : # reserved vars + if name == '_cargo': # reserved vars super().__setattr__(name, value) return self._verifyValidProperty(name) diff --git a/tests/pytest/util/autogen.py b/tests/pytest/util/autogen.py new file mode 100644 index 0000000000000000000000000000000000000000..90cd347b9aed49816bc0de4242bacff8891173bc --- /dev/null +++ b/tests/pytest/util/autogen.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- + +import sys +from util.log import * +from util.cases import * +from util.sql import * +import threading +import random +import string +import time + + +# +# Auto Gen class +# +class AutoGen: + def __init__(self): + self.ts = 1600000000000 + self.batch_size = 100 + seed = time.clock_gettime(time.CLOCK_REALTIME) + random.seed(seed) + + # set start ts + def set_start_ts(self, ts): + self.ts = ts + + # set batch size + def set_batch_size(self, batch_size): + self.batch_size = batch_size + + # _columns_sql + def gen_columns_sql(self, pre, cnt, binary_len, nchar_len): + types = [ + 'timestamp', + 'tinyint', + 'smallint', + 'tinyint unsigned', + 'smallint unsigned', + 'int', + 'bigint', + 'int unsigned', + 'bigint unsigned', + 'float', + 'double', + 'bool', + f'varchar({binary_len})', + f'nchar({nchar_len})' + ] + + sqls = "" + metas = [] + for i in range(cnt): + colname = f"{pre}{i}" + sel = i % len(types) + coltype = types[sel] + sql = f"{colname} {coltype}" + if sqls != "": + sqls += "," + sqls += sql + metas.append(sel) + + return metas, sqls; + + # gen tags data + def gen_data(self, i, marr): + datas = "" + for c in marr: + data = "" + if c == 0 : # timestamp + data = "%d" % (self.ts + i) + elif c <= 4 : # small + data = "%d"%(i%128) + elif c <= 8 : # int + data = f"{i}" + elif c <= 10 : # float + data = "%f"%(i+i/1000) + elif c <= 11 : # bool + data = "%d"%(i%2) + elif c == 12 : # binary + data = '"' + self.random_string(self.bin_len) + '"' + elif c == 13 : # binary + data = '"' + self.random_string(self.nch_len) + '"' + + if datas != "": + datas += "," + datas += data + + return datas + + # generate specail wide random string + def random_string(self, count): + letters = string.ascii_letters + return ''.join(random.choice(letters) for i in range(count)) + + # create db + def create_db(self, dbname): + self.dbname = dbname + tdSql.execute(f'create database {dbname}') + tdSql.execute(f'use {dbname}') + + # create table or stable + def create_stable(self, stbname, tag_cnt, column_cnt, binary_len, nchar_len): + self.bin_len = binary_len + self.nch_len = nchar_len + self.stbname = stbname + self.mtags, tags = self.gen_columns_sql("t", tag_cnt, binary_len, nchar_len) + self.mcols, cols = self.gen_columns_sql("c", column_cnt - 1, binary_len, nchar_len) + + sql = f"create table {stbname} (ts timestamp, {cols}) tags({tags})" + tdSql.execute(sql) + + # create child table + def create_child(self, stbname, prename, cnt): + self.child_cnt = cnt + self.child_name = prename + for i in range(cnt): + tags_data = self.gen_data(i, self.mtags) + sql = f"create table {prename}{i} using {stbname} tags({tags_data})" + tdSql.execute(sql) + + tdLog.info(f"create child tables {cnt} ok") + + def insert_data_child(self, child_name, cnt, batch_size, step): + values = "" + print("insert child data") + ts = self.ts + + # loop do + for i in range(cnt): + value = self.gen_data(i, self.mcols) + ts += step + values += f"({ts},{value}) " + if batch_size == 1 or (i > 0 and i % batch_size == 0) : + sql = f"insert into {child_name} values {values}" + tdSql.execute(sql) + if batch_size > 40: + tdLog.info(f" insert data i={i}") + values = "" + + # end batch + if values != "": + sql = f"insert into {child_name} values {values}" + tdSql.execute(sql) + tdLog.info(f" insert data i={i}") + values = "" + + tdLog.info(f" insert child data {child_name} finished, insert rows={cnt}") + + # insert data + def insert_data(self, cnt): + for i in range(self.child_cnt): + name = f"{self.child_name}{i}" + self.insert_data_child(name, cnt, self.batch_size, 1) + + tdLog.info(f" insert data ok, child table={self.child_cnt} insert rows={cnt}") + + # insert same timestamp to all childs + def insert_samets(self, cnt): + for i in range(self.child_cnt): + name = f"{self.child_name}{i}" + self.insert_data_child(name, cnt, self.batch_size, 0) + + tdLog.info(f" insert same timestamp ok, child table={self.child_cnt} insert rows={cnt}") + + diff --git a/tests/pytest/util/cases.py b/tests/pytest/util/cases.py index 82aa5523596c8d62557bad7d41d02e1ca897c9a9..536b8f30d3582875e85d1260861d6839f8503f6f 100644 --- a/tests/pytest/util/cases.py +++ b/tests/pytest/util/cases.py @@ -17,6 +17,7 @@ import time import datetime import inspect import importlib +import traceback from util.log import * @@ -75,6 +76,7 @@ class TDCases: case.run() except Exception as e: tdLog.notice(repr(e)) + traceback.print_exc() tdLog.exit("%s failed" % (fileName)) case.stop() runNum += 1 @@ -94,14 +96,14 @@ class TDCases: tdLog.notice("total %d Windows test case(s) executed" % (runNum)) - def runOneWindows(self, conn, fileName): + def runOneWindows(self, conn, fileName, replicaVar=1): testModule = self.__dynamicLoadModule(fileName) runNum = 0 for tmp in self.windowsCases: if tmp.name.find(fileName) != -1: case = testModule.TDTestCase() - case.init(conn, self._logSql) + case.init(conn, self._logSql,replicaVar) try: case.run() except Exception as e: diff --git a/tests/pytest/util/cluster.py b/tests/pytest/util/cluster.py index 72b7e1fddff7fcfce3c9fb83eeb74f2cefc01f18..a6e3530dc99edc631cfabc0608089a26ca61673e 100644 --- a/tests/pytest/util/cluster.py +++ b/tests/pytest/util/cluster.py @@ -52,8 +52,9 @@ class ConfigureyCluster: dnode.addExtraCfg("secondEp", f"{hostname}:{startPort_sec}") # configure dnoe of independent mnodes - if num <= self.mnodeNums and self.mnodeNums != 0 and independentMnode == True : - dnode.addExtraCfg("supportVnodes", 0) + if num <= self.mnodeNums and self.mnodeNums != 0 and independentMnode == "True" : + tdLog.info("set mnode supportVnodes 0") + dnode.addExtraCfg("supportVnodes", 0) # print(dnode) self.dnodes.append(dnode) return self.dnodes @@ -71,6 +72,7 @@ class ConfigureyCluster: tdSql.init(conn.cursor()) mnodeNums=int(mnodeNums) for i in range(2,mnodeNums+1): + tdLog.info("create mnode on dnode %d"%i) tdSql.execute(" create mnode on dnode %d;"%i) diff --git a/tests/pytest/util/common.py b/tests/pytest/util/common.py index 5b73989d6f22b25c056cba802328d8e3d583ef87..6d813a416644661bf83881b753afe0d55d97d5f2 100644 --- a/tests/pytest/util/common.py +++ b/tests/pytest/util/common.py @@ -739,6 +739,11 @@ class TDCom: else: os.system("unset LD_PRELOAD; pkill %s " % processorName) + def gen_tag_col_str(self, gen_type, data_type, count): + """ + gen multi tags or cols by gen_type + """ + return ','.join(map(lambda i: f'{gen_type}{i} {data_type}', range(count))) def is_json(msg): if isinstance(msg, str): @@ -775,4 +780,5 @@ def dict2toml(in_dict: dict, file:str): with open(file, 'w') as f: toml.dump(in_dict, f) + tdCom = TDCom() diff --git a/tests/pytest/util/dnodes-default.py b/tests/pytest/util/dnodes-default.py index 8da36f30748251f307a9152fd8907bdebc9e1405..6809c1082ca8db3c099f4d047be46104c0dccf5b 100644 --- a/tests/pytest/util/dnodes-default.py +++ b/tests/pytest/util/dnodes-default.py @@ -46,11 +46,11 @@ class TDSimClient: self.path = path def getLogDir(self): - self.logDir = "%s/sim/psim/log" % (self.path) + self.logDir = os.path.join(self.path,"sim","psim","log") return self.logDir def getCfgDir(self): - self.cfgDir = "%s/sim/psim/cfg" % (self.path) + self.cfgDir = os.path.join(self.path,"sim","psim","cfg") return self.cfgDir def setTestCluster(self, value): @@ -65,9 +65,9 @@ class TDSimClient: tdLog.exit(cmd) def deploy(self): - self.logDir = "%s/sim/psim/log" % (self.path) - self.cfgDir = "%s/sim/psim/cfg" % (self.path) - self.cfgPath = "%s/sim/psim/cfg/taos.cfg" % (self.path) + self.logDir = os.path.join(self.path,"sim","psim","log") + self.cfgDir = os.path.join(self.path,"sim","psim","cfg") + self.cfgPath = os.path.join(self.path,"sim","psim","cfg","taos.cfg") cmd = "rm -rf " + self.logDir if os.system(cmd) != 0: @@ -131,11 +131,10 @@ class TDDnode: return totalSize def deploy(self): - self.logDir = "%s/sim/dnode%d/log" % (self.path, self.index) - self.dataDir = "%s/sim/dnode%d/data" % (self.path, self.index) - self.cfgDir = "%s/sim/dnode%d/cfg" % (self.path, self.index) - self.cfgPath = "%s/sim/dnode%d/cfg/taos.cfg" % ( - self.path, self.index) + self.logDir = os.path.join(self.path,"sim","dnode%d" % self.index, "log") + self.dataDir = os.path.join(self.path,"sim","dnode%d" % self.index, "data") + self.cfgDir = os.path.join(self.path,"sim","dnode%d" % self.index, "cfg") + self.cfgPath = os.path.join(self.path,"sim","dnode%d" % self.index, "cfg","taos.cfg") cmd = "rm -rf " + self.dataDir if os.system(cmd) != 0: @@ -325,11 +324,11 @@ class TDDnode: tdLog.exit(cmd) def getDnodeRootDir(self, index): - dnodeRootDir = "%s/sim/psim/dnode%d" % (self.path, index) + dnodeRootDir = os.path.join(self.path,"sim","psim","dnode%d" % index) return dnodeRootDir def getDnodesRootDir(self): - dnodesRootDir = "%s/sim/psim" % (self.path) + dnodesRootDir = os.path.join(self.path,"sim","psim") return dnodesRootDir diff --git a/tests/pytest/util/dnodes-no-random-fail.py b/tests/pytest/util/dnodes-no-random-fail.py index a973f8da52d63aa04ecc3eb4afea47c93419e0c5..0e433e9664ef7ca05652e6fbb03949a9311c0bdf 100644 --- a/tests/pytest/util/dnodes-no-random-fail.py +++ b/tests/pytest/util/dnodes-no-random-fail.py @@ -44,11 +44,11 @@ class TDSimClient: self.path = path def getLogDir(self): - self.logDir = "%s/sim/psim/log" % (self.path) + self.logDir = os.path.join(self.path,"sim","psim","log") return self.logDir def getCfgDir(self): - self.cfgDir = "%s/sim/psim/cfg" % (self.path) + self.cfgDir = os.path.join(self.path,"sim","psim","cfg") return self.cfgDir def setTestCluster(self, value): @@ -63,9 +63,9 @@ class TDSimClient: tdLog.exit(cmd) def deploy(self): - self.logDir = "%s/sim/psim/log" % (self.path) - self.cfgDir = "%s/sim/psim/cfg" % (self.path) - self.cfgPath = "%s/sim/psim/cfg/taos.cfg" % (self.path) + self.logDir = os.path.join(self.path,"sim","psim","log") + self.cfgDir = os.path.join(self.path,"sim","psim","cfg") + self.cfgPath = os.path.join(self.path,"sim","psim","cfg","taos.cfg") cmd = "rm -rf " + self.logDir if os.system(cmd) != 0: @@ -129,11 +129,10 @@ class TDDnode: return totalSize def deploy(self): - self.logDir = "%s/sim/dnode%d/log" % (self.path, self.index) - self.dataDir = "%s/sim/dnode%d/data" % (self.path, self.index) - self.cfgDir = "%s/sim/dnode%d/cfg" % (self.path, self.index) - self.cfgPath = "%s/sim/dnode%d/cfg/taos.cfg" % ( - self.path, self.index) + self.logDir = os.path.join(self.path,"sim","dnode%d" % self.index, "log") + self.dataDir = os.path.join(self.path,"sim","dnode%d" % self.index, "data") + self.cfgDir = os.path.join(self.path,"sim","dnode%d" % self.index, "cfg") + self.cfgPath = os.path.join(self.path,"sim","dnode%d" % self.index, "cfg","taos.cfg") cmd = "rm -rf " + self.dataDir if os.system(cmd) != 0: @@ -323,11 +322,11 @@ class TDDnode: tdLog.exit(cmd) def getDnodeRootDir(self, index): - dnodeRootDir = "%s/sim/psim/dnode%d" % (self.path, index) + dnodeRootDir = os.path.join(self.path,"sim","psim","dnode%d" % index) return dnodeRootDir def getDnodesRootDir(self): - dnodesRootDir = "%s/sim/psim" % (self.path) + dnodesRootDir = os.path.join(self.path,"sim","psim") return dnodesRootDir diff --git a/tests/pytest/util/dnodes-random-fail.py b/tests/pytest/util/dnodes-random-fail.py index 9b653844f880f6f0667c2b96bf9a264c04d5c613..1c527290ec3c0a24b0a0175da104eeca2ffcfdfb 100644 --- a/tests/pytest/util/dnodes-random-fail.py +++ b/tests/pytest/util/dnodes-random-fail.py @@ -41,11 +41,11 @@ class TDSimClient: self.path = path def getLogDir(self): - self.logDir = "%s/sim/psim/log" % (self.path) + self.logDir = os.path.join(self.path,"sim","psim","log") return self.logDir def getCfgDir(self): - self.cfgDir = "%s/sim/psim/cfg" % (self.path) + self.cfgDir = os.path.join(self.path,"sim","psim","cfg") return self.cfgDir def setTestCluster(self, value): @@ -60,9 +60,9 @@ class TDSimClient: tdLog.exit(cmd) def deploy(self): - self.logDir = "%s/sim/psim/log" % (self.path) - self.cfgDir = "%s/sim/psim/cfg" % (self.path) - self.cfgPath = "%s/sim/psim/cfg/taos.cfg" % (self.path) + self.logDir = os.path.join(self.path,"sim","psim","log") + self.cfgDir = os.path.join(self.path,"sim","psim","cfg") + self.cfgPath = os.path.join(self.path,"sim","psim","cfg","taos.cfg") cmd = "rm -rf " + self.logDir if os.system(cmd) != 0: @@ -126,11 +126,10 @@ class TDDnode: return totalSize def deploy(self): - self.logDir = "%s/sim/dnode%d/log" % (self.path, self.index) - self.dataDir = "%s/sim/dnode%d/data" % (self.path, self.index) - self.cfgDir = "%s/sim/dnode%d/cfg" % (self.path, self.index) - self.cfgPath = "%s/sim/dnode%d/cfg/taos.cfg" % ( - self.path, self.index) + self.logDir = os.path.join(self.path,"sim","dnode%d" % self.index, "log") + self.dataDir = os.path.join(self.path,"sim","dnode%d" % self.index, "data") + self.cfgDir = os.path.join(self.path,"sim","dnode%d" % self.index, "cfg") + self.cfgPath = os.path.join(self.path,"sim","dnode%d" % self.index, "cfg","taos.cfg") cmd = "rm -rf " + self.dataDir if os.system(cmd) != 0: @@ -320,11 +319,11 @@ class TDDnode: tdLog.exit(cmd) def getDnodeRootDir(self, index): - dnodeRootDir = "%s/sim/psim/dnode%d" % (self.path, index) + dnodeRootDir = os.path.join(self.path,"sim","psim","dnode%d" % index) return dnodeRootDir def getDnodesRootDir(self): - dnodesRootDir = "%s/sim/psim" % (self.path) + dnodesRootDir = os.path.join(self.path,"sim","psim") return dnodesRootDir diff --git a/tests/pytest/util/dnodes.py b/tests/pytest/util/dnodes.py index a1682f47b3e229e24a9b7bdd750b8cbe4890dea5..80ab5baa9a8a23132abf75686ccdc6bebb6d8238 100644 --- a/tests/pytest/util/dnodes.py +++ b/tests/pytest/util/dnodes.py @@ -15,6 +15,7 @@ import sys import os import os.path import platform +import distro import subprocess from time import sleep import base64 @@ -22,6 +23,7 @@ import json import copy from fabric2 import Connection from util.log import * +from shutil import which class TDSimClient: @@ -43,14 +45,16 @@ class TDSimClient: "supportVnodes": "1024", "enableQueryHb": "1", "telemetryReporting": "0", + "tqDebugflag": "135", + "wDebugflag":"135", } def getLogDir(self): - self.logDir = "%s/sim/psim/log" % (self.path) + self.logDir = os.path.join(self.path,"sim","psim","log") return self.logDir def getCfgDir(self): - self.cfgDir = "%s/sim/psim/cfg" % (self.path) + self.cfgDir = os.path.join(self.path,"sim","psim","cfg") return self.cfgDir def setTestCluster(self, value): @@ -65,9 +69,9 @@ class TDSimClient: tdLog.exit(cmd) def deploy(self, *updatecfgDict): - self.logDir = "%s/sim/psim/log" % (self.path) - self.cfgDir = "%s/sim/psim/cfg" % (self.path) - self.cfgPath = "%s/sim/psim/cfg/taos.cfg" % (self.path) + self.logDir = os.path.join(self.path,"sim","psim","log") + self.cfgDir = os.path.join(self.path,"sim","psim","cfg") + self.cfgPath = os.path.join(self.path,"sim","psim","cfg","taos.cfg") cmd = "rm -rf " + self.logDir if os.system(cmd) != 0: @@ -166,9 +170,9 @@ class TDDnode: if value: selfPath = os.path.dirname(os.path.realpath(__file__)) if ("community" in selfPath): - self.execPath = os.path.abspath(self.path + "/community/tests/script/sh/exec.sh") + self.execPath = os.path.abspath(self.path + "/community/tests/script/sh/exec.sh") else: - self.execPath = os.path.abspath(self.path + "/tests/script/sh/exec.sh") + self.execPath = os.path.abspath(self.path + "/tests/script/sh/exec.sh") def getDataSize(self): totalSize = 0 @@ -203,11 +207,10 @@ class TDDnode: self.remote_conn.run("python3 ./test.py %s -d %s -e %s"%(valgrindStr,remoteCfgDictStr,execCmdStr)) def deploy(self, *updatecfgDict): - self.logDir = "%s/sim/dnode%d/log" % (self.path, self.index) - self.dataDir = "%s/sim/dnode%d/data" % (self.path, self.index) - self.cfgDir = "%s/sim/dnode%d/cfg" % (self.path, self.index) - self.cfgPath = "%s/sim/dnode%d/cfg/taos.cfg" % ( - self.path, self.index) + self.logDir = os.path.join(self.path,"sim","dnode%d" % self.index, "log") + self.dataDir = os.path.join(self.path,"sim","dnode%d" % self.index, "data") + self.cfgDir = os.path.join(self.path,"sim","dnode%d" % self.index, "cfg") + self.cfgPath = os.path.join(self.path,"sim","dnode%d" % self.index, "cfg","taos.cfg") cmd = "rm -rf " + self.dataDir if os.system(cmd) != 0: @@ -468,20 +471,25 @@ class TDDnode: tdLog.exit("dnode:%d is not deployed" % (self.index)) if self.valgrind == 0: - if self.asan: - asanDir = "%s/sim/asan/dnode%d.asan" % ( - self.path, self.index) - cmd = "nohup %s -c %s > /dev/null 2> %s & " % ( - binPath, self.cfgDir, asanDir) + if platform.system().lower() == 'windows': + cmd = "mintty -h never %s -c %s" % (binPath, self.cfgDir) else: - cmd = "nohup %s -c %s > /dev/null 2>&1 & " % ( - binPath, self.cfgDir) + if self.asan: + asanDir = "%s/sim/asan/dnode%d.asan" % ( + self.path, self.index) + cmd = "nohup %s -c %s > /dev/null 2> %s & " % ( + binPath, self.cfgDir, asanDir) + else: + cmd = "nohup %s -c %s > /dev/null 2>&1 & " % ( + binPath, self.cfgDir) else: valgrindCmdline = "valgrind --log-file=\"%s/../log/valgrind.log\" --tool=memcheck --leak-check=full --show-reachable=no --track-origins=yes --show-leak-kinds=all -v --workaround-gcc296-bugs=yes"%self.cfgDir - - cmd = "nohup %s %s -c %s 2>&1 & " % ( - valgrindCmdline, binPath, self.cfgDir) - + if platform.system().lower() == 'windows': + cmd = "mintty -h never %s %s -c %s" % ( + valgrindCmdline, binPath, self.cfgDir) + else: + cmd = "nohup %s %s -c %s 2>&1 & " % ( + valgrindCmdline, binPath, self.cfgDir) print(cmd) if (self.remoteIP == ""): @@ -564,6 +572,8 @@ class TDDnode: while(processID): if not platform.system().lower() == 'windows' or (onlyKillOnceWindows == 0 and platform.system().lower() == 'windows'): killCmd = "kill -INT %s > /dev/null 2>&1" % processID + if platform.system().lower() == 'windows': + killCmd = "kill -INT %s > nul 2>&1" % processID os.system(killCmd) onlyKillOnceWindows = 1 time.sleep(1) @@ -631,11 +641,11 @@ class TDDnode: tdLog.exit(cmd) def getDnodeRootDir(self, index): - dnodeRootDir = "%s/sim/psim/dnode%d" % (self.path, index) + dnodeRootDir = os.path.join(self.path,"sim","psim","dnode%d" % index) return dnodeRootDir def getDnodesRootDir(self): - dnodesRootDir = "%s/sim/psim" % (self.path) + dnodesRootDir = os.path.join(self.path,"sim","psim") return dnodesRootDir @@ -686,7 +696,7 @@ class TDDnodes: if ("community" in selfPath): self.stopDnodesPath = os.path.abspath(self.path + "/community/tests/script/sh/stop_dnodes.sh") self.stopDnodesSigintPath = os.path.abspath(self.path + "/community/tests/script/sh/sigint_stop_dnodes.sh") - else: + else: self.stopDnodesPath = os.path.abspath(self.path + "/tests/script/sh/stop_dnodes.sh") self.stopDnodesSigintPath = os.path.abspath(self.path + "/tests/script/sh/sigint_stop_dnodes.sh") tdLog.info("run in address sanitizer mode") @@ -765,7 +775,8 @@ class TDDnodes: def stopAll(self): tdLog.info("stop all dnodes, asan:%d" % self.asan) - if self.asan: + distro_id = distro.id() + if self.asan and distro_id != "alpine": tdLog.info("execute script: %s" % self.stopDnodesPath) os.system(self.stopDnodesPath) tdLog.info("execute finished") @@ -777,24 +788,44 @@ class TDDnodes: for i in range(len(self.dnodes)): self.dnodes[i].stop() - psCmd = "ps -ef | grep -w taosd | grep 'root' | grep -v grep| grep -v defunct | awk '{print $2}' | xargs" - processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() - if processID: - cmd = "sudo systemctl stop taosd" - os.system(cmd) - # if os.system(cmd) != 0 : - # tdLog.exit(cmd) - psCmd = "ps -ef|grep -w taosd| grep -v grep| grep -v defunct | awk '{print $2}' | xargs" - processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() - while(processID): - if platform.system().lower() == 'windows': + + if (distro_id == "alpine"): + print(distro_id) + psCmd = "ps -ef | grep -w taosd | grep 'root' | grep -v grep| grep -v defunct | awk '{print $2}' | xargs" + processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() + while(processID): + print(processID) + killCmd = "kill -9 %s > /dev/null 2>&1" % processID + os.system(killCmd) + time.sleep(1) + processID = subprocess.check_output( + psCmd, shell=True).decode("utf-8").strip() + elif platform.system().lower() == 'windows': + psCmd = "for /f %a in ('wmic process where \"name='taosd.exe'\" get processId ^| xargs echo ^| awk '{print $2}' ^&^& echo aa') do @(ps | grep %a | awk '{print $1}' | xargs)" + processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() + while(processID): + print(processID) killCmd = "kill -9 %s > nul 2>&1" % processID - else: + os.system(killCmd) + time.sleep(1) + processID = subprocess.check_output( + psCmd, shell=True).decode("utf-8").strip() + else: + psCmd = "ps -ef | grep -w taosd | grep 'root' | grep -v grep| grep -v defunct | awk '{print $2}' | xargs" + processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() + if processID: + cmd = "sudo systemctl stop taosd" + os.system(cmd) + # if os.system(cmd) != 0 : + # tdLog.exit(cmd) + psCmd = "ps -ef|grep -w taosd| grep -v grep| grep -v defunct | awk '{print $2}' | xargs" + processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() + while(processID): killCmd = "kill -9 %s > /dev/null 2>&1" % processID - os.system(killCmd) - time.sleep(1) - processID = subprocess.check_output( - psCmd, shell=True).decode("utf-8").strip() + os.system(killCmd) + time.sleep(1) + processID = subprocess.check_output( + psCmd, shell=True).decode("utf-8").strip() if self.killValgrind == 1: psCmd = "ps -ef|grep -w valgrind.bin| grep -v grep | awk '{print $2}' | xargs" diff --git a/tests/pytest/util/gettime.py b/tests/pytest/util/gettime.py index 94eed384789b85b746a523c3a0875bf1f5b711ea..d4a5e18dc9e9fb8f3ee032219d05c8a6d53becfb 100644 --- a/tests/pytest/util/gettime.py +++ b/tests/pytest/util/gettime.py @@ -18,6 +18,9 @@ class GetTime: def get_ms_timestamp(self,ts_str): _ts_str = ts_str + if "+" in _ts_str: + timestamp = datetime.fromisoformat(_ts_str) + return int((timestamp-datetime.fromtimestamp(0,timestamp.tzinfo)).total_seconds())*1000+int(timestamp.microsecond / 1000) if " " in ts_str: p = ts_str.split(" ")[1] if len(p) > 15 : diff --git a/tests/pytest/util/sql.py b/tests/pytest/util/sql.py index 9cfd1d368edfa319aa4e80b307cbcc09020245ff..783ee476cb5d3b34ffc4461e336412b0259dc975 100644 --- a/tests/pytest/util/sql.py +++ b/tests/pytest/util/sql.py @@ -23,6 +23,15 @@ import pandas as pd from util.log import * from util.constant import * +# from datetime import timezone +import time + +def _parse_ns_timestamp(timestr): + dt_obj = datetime.datetime.strptime(timestr[:len(timestr)-3], "%Y-%m-%d %H:%M:%S.%f") + tz = int(int((dt_obj-datetime.datetime.fromtimestamp(0,dt_obj.tzinfo)).total_seconds())*1e9) + int(dt_obj.microsecond * 1000) + int(timestr[-3:]) + return tz + + def _parse_datetime(timestr): try: return datetime.datetime.strptime(timestr, '%Y-%m-%d %H:%M:%S.%f') @@ -227,28 +236,102 @@ class TDSql: self.checkRowCol(row, col) return self.cursor.istype(col, dataType) + def checkData(self, row, col, data): + if row >= self.queryRows: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, self.sql, row+1, self.queryRows) + tdLog.exit("%s(%d) failed: sql:%s, row:%d is larger than queryRows:%d" % args) + if col >= self.queryCols: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, self.sql, col+1, self.queryCols) + tdLog.exit("%s(%d) failed: sql:%s, col:%d is larger than queryCols:%d" % args) + self.checkRowCol(row, col) + if self.queryResult[row][col] != data: if self.cursor.istype(col, "TIMESTAMP"): - # suppose user want to check nanosecond timestamp if a longer data passed - if (len(data) >= 28): - if pd.to_datetime(self.queryResult[row][col]) == pd.to_datetime(data): - tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") + # suppose user want to check nanosecond timestamp if a longer data passed`` + if isinstance(data,str) : + if (len(data) >= 28): + if self.queryResult[row][col] == _parse_ns_timestamp(data): + # tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{pd.to_datetime(resultData)} == expect:{data}") + tdLog.info("check successfully") + else: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, self.sql, row, col, self.queryResult[row][col], data) + tdLog.exit("%s(%d) failed: sql:%s row:%d col:%d data:%s != expect:%s" % args) + else: + if self.queryResult[row][col].astimezone(datetime.timezone.utc) == _parse_datetime(data).astimezone(datetime.timezone.utc): + # tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") + tdLog.info("check successfully") + else: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, self.sql, row, col, self.queryResult[row][col], data) + tdLog.exit("%s(%d) failed: sql:%s row:%d col:%d data:%s != expect:%s" % args) + return + elif isinstance(data,int): + if len(str(data)) == 16: + precision = 'us' + elif len(str(data)) == 13: + precision = 'ms' + elif len(str(data)) == 19: + precision = 'ns' + else: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, self.sql, row, col, self.queryResult[row][col], data) + tdLog.exit("%s(%d) failed: sql:%s row:%d col:%d data:%s != expect:%s" % args) + return + success = False + if precision == 'ms': + dt_obj = self.queryResult[row][col] + ts = int(int((dt_obj-datetime.datetime.fromtimestamp(0,dt_obj.tzinfo)).total_seconds())*1000) + int(dt_obj.microsecond/1000) + if ts == data: + success = True + elif precision == 'us': + dt_obj = self.queryResult[row][col] + ts = int(int((dt_obj-datetime.datetime.fromtimestamp(0,dt_obj.tzinfo)).total_seconds())*1e6) + int(dt_obj.microsecond) + if ts == data: + success = True + elif precision == 'ns': + if data == self.queryResult[row][col]: + success = True + if success: + tdLog.info("check successfully") + else: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, self.sql, row, col, self.queryResult[row][col], data) + tdLog.exit("%s(%d) failed: sql:%s row:%d col:%d data:%s != expect:%s" % args) + return + elif isinstance(data,datetime.datetime): + dt_obj = self.queryResult[row][col] + delt_data = data-datetime.datetime.fromtimestamp(0,data.tzinfo) + delt_result = self.queryResult[row][col] - datetime.datetime.fromtimestamp(0,self.queryResult[row][col].tzinfo) + if delt_data == delt_result: + tdLog.info("check successfully") + else: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, self.sql, row, col, self.queryResult[row][col], data) + tdLog.exit("%s(%d) failed: sql:%s row:%d col:%d data:%s != expect:%s" % args) + return else: - if self.queryResult[row][col] == _parse_datetime(data): - tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") - return + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno, self.sql, row, col, self.queryResult[row][col], data) + tdLog.exit("%s(%d) failed: sql:%s row:%d col:%d data:%s != expect:%s" % args) if str(self.queryResult[row][col]) == str(data): - tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") + # tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") + tdLog.info("check successfully") return elif isinstance(data, float): if abs(data) >= 1 and abs((self.queryResult[row][col] - data) / data) <= 0.000001: - tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") + # tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") + tdLog.info("check successfully") elif abs(data) < 1 and abs(self.queryResult[row][col] - data) <= 0.000001: - tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") + # tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") + tdLog.info("check successfully") + else: caller = inspect.getframeinfo(inspect.stack()[1][0]) args = (caller.filename, caller.lineno, self.sql, row, col, self.queryResult[row][col], data) @@ -258,8 +341,71 @@ class TDSql: caller = inspect.getframeinfo(inspect.stack()[1][0]) args = (caller.filename, caller.lineno, self.sql, row, col, self.queryResult[row][col], data) tdLog.exit("%s(%d) failed: sql:%s row:%d col:%d data:%s != expect:%s" % args) + tdLog.info("check successfully") + + # return true or false replace exit, no print out + def checkRowColNoExit(self, row, col): + caller = inspect.getframeinfo(inspect.stack()[2][0]) + if row < 0: + args = (caller.filename, caller.lineno, self.sql, row) + return False + if col < 0: + args = (caller.filename, caller.lineno, self.sql, row) + return False + if row > self.queryRows: + args = (caller.filename, caller.lineno, self.sql, row, self.queryRows) + return False + if col > self.queryCols: + args = (caller.filename, caller.lineno, self.sql, col, self.queryCols) + return False + + return True + + + # return true or false replace exit, no print out + def checkDataNoExit(self, row, col, data): + if self.checkRowColNoExit(row, col) == False: + return False + if self.queryResult[row][col] != data: + if self.cursor.istype(col, "TIMESTAMP"): + # suppose user want to check nanosecond timestamp if a longer data passed + if (len(data) >= 28): + if pd.to_datetime(self.queryResult[row][col]) == pd.to_datetime(data): + return True + else: + if self.queryResult[row][col] == _parse_datetime(data): + return True + return False + + if str(self.queryResult[row][col]) == str(data): + return True + elif isinstance(data, float): + if abs(data) >= 1 and abs((self.queryResult[row][col] - data) / data) <= 0.000001: + return True + elif abs(data) < 1 and abs(self.queryResult[row][col] - data) <= 0.000001: + return True + else: + return False + else: + return False + + return True + + + # loop execute sql then sleep(waitTime) , if checkData ok break loop + def checkDataLoop(self, row, col, data, sql, loopCount, waitTime): + # loop check util checkData return true + for i in range(loopCount): + self.query(sql) + if self.checkDataNoExit(row, col, data) : + self.checkData(row, col, data) + return + time.sleep(waitTime) + + # last check + self.query(sql) + self.checkData(row, col, data) - tdLog.info(f"sql:{self.sql}, row:{row} col:{col} data:{self.queryResult[row][col]} == expect:{data}") def getData(self, row, col): self.checkRowCol(row, col) diff --git a/tests/pytest/util/taosadapter.py b/tests/pytest/util/taosadapter.py index 7dd62266319bd1462ce7bad6ff6ec358cfe31678..1f1c38672e130f54478d1fed408f2948d2ec892a 100644 --- a/tests/pytest/util/taosadapter.py +++ b/tests/pytest/util/taosadapter.py @@ -1,4 +1,4 @@ -import socket +import requests from fabric2 import Connection from util.log import * from util.common import * @@ -132,9 +132,9 @@ class TAdapter: tdLog.exit(cmd) def deploy(self, *update_cfg_dict): - self.log_dir = f"{self.path}/sim/dnode1/log" - self.cfg_dir = f"{self.path}/sim/dnode1/cfg" - self.cfg_path = f"{self.cfg_dir}/taosadapter.toml" + self.log_dir = os.path.join(self.path,"sim","dnode1","log") + self.cfg_dir = os.path.join(self.path,"sim","dnode1","cfg") + self.cfg_path = os.path.join(self.cfg_dir,"taosadapter.toml") cmd = f"touch {self.cfg_path}" if os.system(cmd) != 0: @@ -162,7 +162,7 @@ class TAdapter: tdLog.info(f"taosadapter found: {bin_path}") if platform.system().lower() == 'windows': - cmd = f"mintty -h never {bin_path} -c {self.cfg_dir}" + cmd = f"mintty -h never {bin_path} -c {self.cfg_path}" else: cmd = f"nohup {bin_path} -c {self.cfg_path} > /dev/null & " @@ -170,7 +170,7 @@ class TAdapter: self.remote_exec(self.taosadapter_cfg_dict, f"tAdapter.deployed=1\ntAdapter.log_dir={self.log_dir}\ntAdapter.cfg_dir={self.cfg_dir}\ntAdapter.start()") self.running = 1 else: - os.system(f"rm -rf {self.log_dir}/taosadapter*") + os.system(f"rm -rf {self.log_dir}{os.sep}taosadapter*") if os.system(cmd) != 0: tdLog.exit(cmd) self.running = 1 @@ -179,22 +179,19 @@ class TAdapter: time.sleep(0.1) taosadapter_port = self.taosadapter_cfg_dict["port"] - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(3) - try: - res = s.connect_ex((self.remoteIP, taosadapter_port)) - s.shutdown(2) - if res == 0: - tdLog.info(f"the taosadapter has been started, using port:{taosadapter_port}") - else: - tdLog.info(f"the taosadapter do not started!!!") - except socket.error as e: - tdLog.notice("socket connect error!") - finally: - if s: - s.close() - # tdLog.debug("the taosadapter has been started.") - time.sleep(1) + for i in range(5): + ip = 'localhost' + if self.remoteIP != "": + ip = self.remoteIP + url = f'http://{ip}:{taosadapter_port}/-/ping' + try: + r = requests.get(url) + if r.status_code == 200: + tdLog.info(f"the taosadapter has been started, using port:{taosadapter_port}") + break + except Exception: + tdLog.info(f"the taosadapter do not started!!!") + time.sleep(1) def start_taosadapter(self): """ @@ -228,34 +225,36 @@ class TAdapter: def stop(self, force_kill=False): signal = "-9" if force_kill else "-15" - if self.remoteIP: self.remote_exec(self.taosadapter_cfg_dict, "tAdapter.running=1\ntAdapter.stop()") tdLog.info("stop taosadapter") return - toBeKilled = "taosadapter" - - if self.running != 0: + if platform.system().lower() == 'windows': psCmd = f"ps -ef|grep -w {toBeKilled}| grep -v grep | awk '{{print $2}}'" processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() - # psCmd = f"pgrep {toBeKilled}" - while(processID): - killCmd = "kill %s %s > /dev/null 2>&1" % (signal, processID) + killCmd = "kill %s %s > nul 2>&1" % (signal, processID) os.system(killCmd) time.sleep(1) processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() - if not platform.system().lower() == 'windows': + self.running = 0 + tdLog.debug(f"taosadapter is stopped by kill {signal}") + + else: + if self.running != 0: + psCmd = f"ps -ef|grep -w {toBeKilled}| grep -v grep | awk '{{print $2}}'" + processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() + while(processID): + killCmd = "kill %s %s > /dev/null 2>&1" % (signal, processID) + os.system(killCmd) + time.sleep(1) + processID = subprocess.check_output(psCmd, shell=True).decode("utf-8").strip() port = 6041 fuserCmd = f"fuser -k -n tcp {port} > /dev/null" os.system(fuserCmd) - # for port in range(6030, 6041): - # fuserCmd = f"fuser -k -n tcp {port} > /dev/null" - # os.system(fuserCmd) - - self.running = 0 - tdLog.debug(f"taosadapter is stopped by kill {signal}") + self.running = 0 + tdLog.debug(f"taosadapter is stopped by kill {signal}") diff --git a/tests/requirements.txt b/tests/requirements.txt index ce459414c44c6adcb8c8a77b03ea790480a41cd2..5cdd9e02beed40b73a083041e1b4d043dcd48adb 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,3 +3,9 @@ numpy fabric2 psutil pandas +toml +distro +requests +pexpect +faker +pyopenssl diff --git a/tests/script/api/batchprepare.c b/tests/script/api/batchprepare.c index d1a80d9683a8599ba4123236dc8738c84f0bc291..99507ef5c3ae58d786dbfe8f91e72400d471ec3f 100644 --- a/tests/script/api/batchprepare.c +++ b/tests/script/api/batchprepare.c @@ -122,9 +122,11 @@ int insertAUTOTest2(TAOS_STMT *stmt, TAOS *taos); int insertAUTOTest3(TAOS_STMT *stmt, TAOS *taos); int queryColumnTest(TAOS_STMT *stmt, TAOS *taos); int queryMiscTest(TAOS_STMT *stmt, TAOS *taos); +int insertNonExistsTb(TAOS_STMT *stmt, TAOS *taos); enum { TTYPE_INSERT = 1, + TTYPE_INSERT_NG, TTYPE_QUERY, }; @@ -187,6 +189,8 @@ CaseCfg gCase[] = { {"query:SUBT-COLUMN", tListLen(fullColList), fullColList, TTYPE_QUERY, 0, false, false, queryColumnTest, 10, 10, 1, 3, 0, 0, 1, 2}, {"query:SUBT-MISC", tListLen(fullColList), fullColList, TTYPE_QUERY, 0, false, false, queryMiscTest, 10, 10, 1, 3, 0, 0, 1, 2}, + {"query:NG-TBNEXISTS",tListLen(fullColList), fullColList, TTYPE_INSERT_NG,0, false, false, insertNonExistsTb, 10, 10, 1, 3, 0, 0, 1, -1}, + // {"query:SUBT-COLUMN", tListLen(fullColList), fullColList, TTYPE_QUERY, 0, false, false, queryColumnTest, 1, 10, 1, 1, 0, 0, 1, 2}, // {"query:SUBT-MISC", tListLen(fullColList), fullColList, TTYPE_QUERY, 0, false, false, queryMiscTest, 2, 10, 1, 1, 0, 0, 1, 2}, @@ -232,8 +236,8 @@ CaseCtrl gCaseCtrl = { .printCreateTblSql = true, .printQuerySql = true, .printStmtSql = true, - .printVerbose = false, - .printRes = false, + .printVerbose = true, + .printRes = true, .autoCreateTbl = false, .numericParam = false, .rowNum = 0, @@ -250,7 +254,7 @@ CaseCtrl gCaseCtrl = { .funcIdxList = NULL, .checkParamNum = false, .runTimes = 0, - .caseIdx = 24, + .caseIdx = 26, .caseNum = 1, .caseRunIdx = -1, .caseRunNum = -1, @@ -2191,6 +2195,47 @@ int queryMiscTest(TAOS_STMT *stmt, TAOS *taos) { } +int insertNonExistsTb(TAOS_STMT *stmt, TAOS *taos) { + BindData data = {0}; + prepareInsertData(&data); + + int code = taos_stmt_prepare(stmt, data.sql, 0); + if (code != 0){ + printf("!!!failed to execute taos_stmt_prepare. error:%s\n", taos_stmt_errstr(stmt)); + exit(1); + } + + bpCheckIsInsert(stmt, 1); + + char *buf = "tbnexist"; + code = bpSetTableNameTags(&data, 0, buf, stmt); + if (code == 0){ + printf("!!!taos_stmt_set_tbname expected error not occurred\n"); + exit(1); + } + + if (0 == taos_stmt_bind_param_batch(stmt, data.pBind)) { + printf("!!!taos_stmt_bind_param_batch expected error not occurred\n"); + exit(1); + } + + if (0 == taos_stmt_add_batch(stmt)) { + printf("!!!taos_stmt_add_batch expected error not occurred\n"); + exit(1); + } + + if (0 == taos_stmt_execute(stmt)) { + printf("!!!taos_stmt_execute expected error not occurred\n"); + exit(1); + } + + destroyData(&data); + + return 0; +} + + + int errorSQLTest1(TAOS_STMT *stmt, TAOS *taos) { BindData data = {0}; @@ -2213,6 +2258,10 @@ int errorSQLTest1(TAOS_STMT *stmt, TAOS *taos) { } void prepareCheckResultImpl(TAOS * taos, char *tname, bool printr, int expected, bool silent) { + if (TTYPE_INSERT_NG == gCurCase->testType) { + return; + } + char sql[255] = "SELECT * FROM "; int32_t rows = 0; diff --git a/tests/script/api/insertSameTs.c b/tests/script/api/insertSameTs.c new file mode 100644 index 0000000000000000000000000000000000000000..ff5e4dd154afaf62d6c64d415b80ede1d9cb9b83 --- /dev/null +++ b/tests/script/api/insertSameTs.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +// TAOS standard API example. The same syntax as MySQL, but only a subset +// to compile: gcc -o demo demo.c -ltaos + +#include +#include +#include +#include +#include "taos.h" // TAOS header file + +static void queryDB(TAOS *taos, char *command) { + int i; + TAOS_RES *pSql = NULL; + int32_t code = -1; + + for (i = 0; i < 5; i++) { + if (NULL != pSql) { + taos_free_result(pSql); + pSql = NULL; + } + + pSql = taos_query(taos, command); + code = taos_errno(pSql); + if (0 == code) { + break; + } + } + + if (code != 0) { + fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql)); + taos_free_result(pSql); + taos_close(taos); + exit(EXIT_FAILURE); + } + + taos_free_result(pSql); +} + +void Test(TAOS *taos, char *qstr); + +int main(int argc, char *argv[]) { + char qstr[1024]; + + // connect to server + if (argc < 2) { + printf("please input server-ip \n"); + return 0; + } + + TAOS *taos = taos_connect(argv[1], "root", "taosdata", NULL, 0); + if (taos == NULL) { + printf("failed to connect to server, reason:%s\n", "null taos"/*taos_errstr(taos)*/); + exit(1); + } + Test(taos, qstr); + taos_close(taos); + taos_cleanup(); +} +void Test(TAOS *taos, char *qstr) { + queryDB(taos, "drop database if exists demo"); + queryDB(taos, "create database demo vgroups 1 minrows 10"); + TAOS_RES *result; + queryDB(taos, "use demo"); + + queryDB(taos, "create table m1 (ts timestamp, ti tinyint, si smallint, i int, bi bigint, f float, d double, b binary(10))"); + printf("success to create table\n"); + + int i = 0; + for (int32_t n = 0; n < 10; ++n) { + for (i = 0; i < 10; ++i) { + int32_t v = n * 10 + i; + sprintf(qstr, "insert into m1 values (%" PRId64 ", %d, %d, %d, %d, %f, %lf, '%s')", (uint64_t)1546300800000, v, v, v, v*10000000, v*1.0, v*2.0, "hello"); + printf("qstr: %s\n", qstr); + + TAOS_RES *result1 = taos_query(taos, qstr); + if (result1 == NULL || taos_errno(result1) != 0) { + printf("failed to insert row, reason:%s\n", taos_errstr(result1)); + taos_free_result(result1); + exit(1); + } else { + printf("insert row: %i\n", v); + } + taos_free_result(result1); + + strcpy(qstr, "flush database demo"); + result1 = taos_query(taos, qstr); + if (result1 == NULL || taos_errno(result1) != 0) { + printf("failed to fluash database, reason:%s\n", taos_errstr(result1)); + taos_free_result(result1); + exit(1); + } + taos_free_result(result1); + } + } + + // query the records + sprintf(qstr, "SELECT * FROM m1 order by ts desc"); + result = taos_query(taos, qstr); + if (result == NULL || taos_errno(result) != 0) { + printf("failed to select, reason:%s\n", taos_errstr(result)); + taos_free_result(result); + exit(1); + } + + TAOS_ROW row; + int rows = 0; + int num_fields = taos_field_count(result); + TAOS_FIELD *fields = taos_fetch_fields(result); + + printf("num_fields = %d\n", num_fields); + printf("select * from table order by ts desc, result:\n"); + // fetch the records row by row + while ((row = taos_fetch_row(result))) { + char temp[1024] = {0}; + rows++; + taos_print_row(temp, row, fields, num_fields); + printf("%s\n", temp); + } + + taos_free_result(result); +} + diff --git a/tests/script/api/makefile b/tests/script/api/makefile index 75a2273f12dc2809ac0cec4fa090caf3231e9ba1..6739794cc8e09025ec18ee92100453edce082f77 100644 --- a/tests/script/api/makefile +++ b/tests/script/api/makefile @@ -14,6 +14,7 @@ exe: gcc $(CFLAGS) ./batchprepare.c -o $(ROOT)batchprepare $(LFLAGS) gcc $(CFLAGS) ./stopquery.c -o $(ROOT)stopquery $(LFLAGS) gcc $(CFLAGS) ./dbTableRoute.c -o $(ROOT)dbTableRoute $(LFLAGS) + gcc $(CFLAGS) ./insertSameTs.c -o $(ROOT)insertSameTs $(LFLAGS) clean: rm $(ROOT)batchprepare diff --git a/tests/script/coverage_test.sh b/tests/script/coverage_test.sh index e0e7490d3ab7616cfc44ceab7c4c951b21663004..535b6802f25c1a94549ae9ea5fbb67f08601f258 100755 --- a/tests/script/coverage_test.sh +++ b/tests/script/coverage_test.sh @@ -12,6 +12,7 @@ fi today=`date +"%Y%m%d"` TDENGINE_DIR=/root/TDengine JDBC_DIR=/root/taos-connector-jdbc +TAOSKEEPER_DIR=/root/taoskeeper TDENGINE_COVERAGE_REPORT=$TDENGINE_DIR/tests/coverage-report-$today.log # Color setting @@ -56,9 +57,9 @@ function buildTDengine() { rm -rf * if [ "$branch" == "3.0" ]; then echo "3.0 =============" - cmake -DCOVER=true -DBUILD_TEST=true -DBUILD_HTTP=false -DBUILD_TOOLS=true .. + cmake -DCOVER=true -DBUILD_TEST=true -DBUILD_HTTP=false -DBUILD_TOOLS=true .. > /dev/null else - cmake -DCOVER=true -DBUILD_TOOLS=true -DBUILD_HTTP=false .. > /dev/null + cmake -DCOVER=true -DBUILD_TEST=true -DBUILD_TOOLS=true -DBUILD_HTTP=false .. > /dev/null fi make -j make install @@ -108,6 +109,19 @@ function runUnitTest() { echo " $TDENGINE_DIR/debug" cd $TDENGINE_DIR/debug ctest -j12 + + echo " $TDENGINE_DIR/tests/script/api" + cd $TDENGINE_DIR/tests/script/api + make clean && make + + stopTaosd + stopTaosadapter + + nohup taosd -c /etc/taos >> /dev/null 2>&1 & + ./batchprepare 127.0.0.1 + ./dbTableRoute 127.0.0.1 + ./stopquery 127.0.0.1 demo t1 + echo "3.0 unit test done" } @@ -115,7 +129,7 @@ function runSimCases() { echo "=== Run sim cases ===" cd $TDENGINE_DIR/tests/script - runCasesOneByOne ../parallel_test/cases.task sim + runCasesOneByOne ../parallel_test/cases.task sim totalSuccess=`grep 'sim success' $TDENGINE_COVERAGE_REPORT | wc -l` if [ "$totalSuccess" -gt "0" ]; then @@ -130,6 +144,9 @@ function runSimCases() { function runPythonCases() { echo "=== Run python cases ===" + + cd $TDENGINE_DIR/tests/parallel_test + sed -i '/compatibility.py/d' cases.task cd $TDENGINE_DIR/tests/system-test runCasesOneByOne ../parallel_test/cases.task system-test @@ -160,14 +177,32 @@ function runJDBCCases() { stopTaosd stopTaosadapter - taosd -c /etc/taos >> /dev/null 2>&1 & - taosadapter >> /dev/null 2>&1 & + nohup taosd -c /etc/taos >> /dev/null 2>&1 & + nohup taosadapter >> /dev/null 2>&1 & mvn clean test > result.txt 2>&1 summary=`grep "Tests run:" result.txt | tail -n 1` echo -e "### JDBC test result: $summary ###" | tee -a $TDENGINE_COVERAGE_REPORT } +function runTaosKeeperCases() { + echo "=== Run taoskeeper cases ===" + + cd $TAOSKEEPER_DIR + git checkout -- . + git reset --hard HEAD + git checkout master + git pull + + stopTaosd + stopTaosadapter + + taosd -c /etc/taos >> /dev/null 2>&1 & + taosadapter >> /dev/null 2>&1 & + + go mod tidy && go test -v ./... +} + function runTest() { echo "run Test" @@ -179,6 +214,7 @@ function runTest() { runSimCases runPythonCases runJDBCCases + runTaosKeeperCases stopTaosd cd $TDENGINE_DIR/tests/script @@ -196,7 +232,7 @@ function lcovFunc { lcov -d . --capture --rc lcov_branch_coverage=1 --rc genhtml_branch_coverage=1 --no-external -b $TDENGINE_DIR -o coverage.info # remove exclude paths - if [ "$branch" == "3.0" ]; then + if [ "$branch" == "main" ] ; then lcov --remove coverage.info \ '*/contrib/*' '*/tests/*' '*/test/*' '*/tools/*' '*/libs/sync/*'\ '*/AccessBridgeCalls.c' '*/ttszip.c' '*/dataInserter.c' '*/tlinearhash.c' '*/tsimplehash.c' '*/tsdbDiskData.c'\ @@ -206,6 +242,8 @@ function lcovFunc { '*/tthread.c' '*/tversion.c' '*/ctgDbg.c' '*/schDbg.c' '*/qwDbg.c' '*/tencode.h' '*/catalog.c'\ '*/tqSnapshot.c' '*/tsdbSnapshot.c''*/metaSnapshot.c' '*/smaSnapshot.c' '*/tqOffsetSnapshot.c'\ '*/vnodeSnapshot.c' '*/metaSnapshot.c' '*/tsdbSnapshot.c' '*/mndGrant.c' '*/mndSnode.c' '*/streamRecover.c'\ + '*/osAtomic.c' '*/osDir.c' '*/osFile.c' '*/osMath.c' '*/osSignal.c' '*/osSleep.c' '*/osString.c' '*/osSystem.c'\ + '*/osThread.c' '*/osTime.c' '*/osTimezone.c' \ --rc lcov_branch_coverage=1 -o coverage.info else lcov --remove coverage.info \ diff --git a/tests/script/sh/bit_and.c b/tests/script/sh/bit_and.c index 2f2e48fdb0882db2a40c9aae019402e031343d13..f3bf71ce946b5b5d62ac6d63de4c2532a799721e 100644 --- a/tests/script/sh/bit_and.c +++ b/tests/script/sh/bit_and.c @@ -1,61 +1,47 @@ -#include -#include #include +#include +#include #include "taosudf.h" +DLL_EXPORT int32_t bit_and_init() { return 0; } -DLL_EXPORT int32_t bit_and_init() { - return 0; -} - -DLL_EXPORT int32_t bit_and_destroy() { - return 0; -} - -DLL_EXPORT int32_t bit_and(SUdfDataBlock* block, SUdfColumn *resultCol) { +DLL_EXPORT int32_t bit_and_destroy() { return 0; } - if (block->numOfCols < 2) { - return TSDB_CODE_UDF_INVALID_INPUT; - } +DLL_EXPORT int32_t bit_and(SUdfDataBlock* block, SUdfColumn* resultCol) { + if (block->numOfCols < 2) { + return TSDB_CODE_UDF_INVALID_INPUT; + } - for (int32_t i = 0; i < block->numOfCols; ++i) { - SUdfColumn* col = block->udfCols[i]; - if (!(col->colMeta.type == TSDB_DATA_TYPE_INT)) { - return TSDB_CODE_UDF_INVALID_INPUT; - } + for (int32_t i = 0; i < block->numOfCols; ++i) { + SUdfColumn* col = block->udfCols[i]; + if (!(col->colMeta.type == TSDB_DATA_TYPE_INT)) { + return TSDB_CODE_UDF_INVALID_INPUT; } + } - SUdfColumnMeta *meta = &resultCol->colMeta; - meta->bytes = 4; - meta->type = TSDB_DATA_TYPE_INT; - meta->scale = 0; - meta->precision = 0; - - - SUdfColumnData *resultData = &resultCol->colData; - - resultData->numOfRows = block->numOfRows; - - for (int32_t i = 0; i < resultData->numOfRows; ++i) { - if (udfColDataIsNull(block->udfCols[0], i)) { - udfColDataSetNull(resultCol, i); - continue; - } - int32_t result = *(int32_t*)udfColDataGetData(block->udfCols[0], i); - int j = 1; - for (; j < block->numOfCols; ++j) { - if (udfColDataIsNull(block->udfCols[j], i)) { - udfColDataSetNull(resultCol, i); - break; - } - - char* colData = udfColDataGetData(block->udfCols[j], i); - result &= *(int32_t*)colData; - } - if (j == block->numOfCols) { - udfColDataSet(resultCol, i, (char*)&result, false); - } + SUdfColumnData* resultData = &resultCol->colData; + for (int32_t i = 0; i < block->numOfRows; ++i) { + if (udfColDataIsNull(block->udfCols[0], i)) { + udfColDataSetNull(resultCol, i); + continue; } - return TSDB_CODE_SUCCESS; + int32_t result = *(int32_t*)udfColDataGetData(block->udfCols[0], i); + int j = 1; + for (; j < block->numOfCols; ++j) { + if (udfColDataIsNull(block->udfCols[j], i)) { + udfColDataSetNull(resultCol, i); + break; + } + + char* colData = udfColDataGetData(block->udfCols[j], i); + result &= *(int32_t*)colData; + } + if (j == block->numOfCols) { + udfColDataSet(resultCol, i, (char*)&result, false); + } + } + resultData->numOfRows = block->numOfRows; + + return TSDB_CODE_SUCCESS; } diff --git a/tests/script/sh/cfg.sh b/tests/script/sh/cfg.sh index 7d4d747e54bab9ed98b42ab1902f8580e17fca6c..bf58185f6201b5046608881d9c9f1a5b5e8de3ac 100755 --- a/tests/script/sh/cfg.sh +++ b/tests/script/sh/cfg.sh @@ -45,11 +45,7 @@ fi TAOS_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/sh/checkAsan.sh b/tests/script/sh/checkAsan.sh index 72257227916785de3d174349d4c83d3302064295..b6cb4f6280b24453a9a8171ace944b4003948b53 100755 --- a/tests/script/sh/checkAsan.sh +++ b/tests/script/sh/checkAsan.sh @@ -2,7 +2,19 @@ set +e #set -x +if [[ "$OSTYPE" == "darwin"* ]]; then + TD_OS="Darwin" +else + OS=$(cat /etc/*-release | grep "^NAME=" | cut -d= -f2) + len=$(echo ${#OS}) + len=$((len-2)) + TD_OS=$(echo -ne ${OS:1:${len}} | cut -d" " -f1) +fi +if [[ "$TD_OS" == "Alpine" ]]; then + echo -e "os is Alpine,skip check Asan" + exit 0 +fi unset LD_PRELOAD SCRIPT_DIR=`dirname $0` cd $SCRIPT_DIR/../ @@ -38,7 +50,11 @@ python_error=`cat ${LOG_DIR}/*.info | grep -w "stack" | wc -l` # /root/TDengine/source/libs/function/src/builtinsimpl.c:856:29: runtime error: signed integer overflow: 9223372036854775806 + 9223372036854775805 cannot be represented in type 'long int' # /root/TDengine/source/libs/scalar/src/sclvector.c:1075:66: runtime error: signed integer overflow: 9223372034707292160 + 1668838476672 cannot be represented in type 'long int' # /root/TDengine/source/common/src/tdataformat.c:1876:7: runtime error: signed integer overflow: 8252423483843671206 + 2406154664059062870 cannot be represented in type 'long int' +# /home/chr/TDengine/source/libs/scalar/src/filter.c:3149:14: runtime error: applying non-zero offset 18446744073709551615 to null pointer +# /home/chr/TDengine/source/libs/scalar/src/filter.c:3149:14: runtime error: applying non-zero offset 18446744073709551615 to null pointer +# /home/TDinternal/community/source/libs/scalar/src/sclvector.c:1109:66: runtime error: signed integer overflow: 9223372034707292160 + 1676867897049 cannot be represented in type 'long int' + runtime_error=`cat ${LOG_DIR}/*.asan | grep "runtime error" | grep -v "trees.c:873" | grep -v "sclfunc.c.*outside the range of representable values of type"| grep -v "signed integer overflow" |grep -v "strerror.c"| grep -v "asan_malloc_linux.cc" |wc -l` echo -e "\033[44;32;1m"asan error_num: $error_num"\033[0m" diff --git a/tests/script/sh/checkValgrind.bat b/tests/script/sh/checkValgrind.bat new file mode 100644 index 0000000000000000000000000000000000000000..cd80750fde70b434e97113be34785c675f4b1211 --- /dev/null +++ b/tests/script/sh/checkValgrind.bat @@ -0,0 +1,2 @@ +@echo off +echo 0 \ No newline at end of file diff --git a/tests/script/sh/clear.sh b/tests/script/sh/clear.sh index 4ee296cf058370552b14c31b67006830e84847dd..587a33f633fbfac4319cf5f6724a29fa60680a91 100755 --- a/tests/script/sh/clear.sh +++ b/tests/script/sh/clear.sh @@ -48,11 +48,7 @@ fi TAOS_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/sh/deploy.bat b/tests/script/sh/deploy.bat index 38e7022edec2c5dae9053e11934a65e108a75b93..fd76b3007874ef5ccdcbd6cacb5681587cec9a9d 100644 --- a/tests/script/sh/deploy.bat +++ b/tests/script/sh/deploy.bat @@ -54,7 +54,7 @@ if %NODE% == 6 set NODE=7600 if %NODE% == 7 set NODE=7700 if %NODE% == 8 set NODE=7800 -rem set "fqdn=" +set "fqdn=localhost" for /f "skip=1" %%A in ( 'wmic computersystem get caption' ) do if not defined fqdn set "fqdn=%%A" diff --git a/tests/script/sh/deploy.sh b/tests/script/sh/deploy.sh index 217bd66ef61d937a575145e36c645db37b20f046..7da8da09bfcf3810b692ff25f37333c93ae87497 100755 --- a/tests/script/sh/deploy.sh +++ b/tests/script/sh/deploy.sh @@ -39,11 +39,7 @@ fi TAOS_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/sh/exec-default.sh b/tests/script/sh/exec-default.sh index f648315c6745f63cfba9eb06ecfd53a9ccef1fed..0a83fa1dc81e5b510e85c2a5e2bf7f646f69e684 100755 --- a/tests/script/sh/exec-default.sh +++ b/tests/script/sh/exec-default.sh @@ -54,11 +54,7 @@ fi TAOS_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/sh/exec-no-random-fail.sh b/tests/script/sh/exec-no-random-fail.sh index e01b18a8e6bb0d4631a28c64c6accd57bceb9076..b15783afb569a760405091dea54dcbb6832fa920 100755 --- a/tests/script/sh/exec-no-random-fail.sh +++ b/tests/script/sh/exec-no-random-fail.sh @@ -54,11 +54,7 @@ fi TAOS_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/sh/exec-random-fail.sh b/tests/script/sh/exec-random-fail.sh index 1f31899e3ac26861fc1860d10cb0a4899ff7bf36..15f2864ca6d9b371412e173ea81034a52a437994 100755 --- a/tests/script/sh/exec-random-fail.sh +++ b/tests/script/sh/exec-random-fail.sh @@ -54,11 +54,7 @@ fi TAOS_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/sh/exec.bat b/tests/script/sh/exec.bat index 88dd43349ed9d49774faafe827b77126286c741d..75957882922a0bcf20dee10d5824f3c488b0697f 100644 --- a/tests/script/sh/exec.bat +++ b/tests/script/sh/exec.bat @@ -50,7 +50,7 @@ if %EXEC_OPTON% == start ( goto :finish ) echo check taosd online - tail -n +0 %TAOS_LOG% | grep -q "TDengine initialized successfully" || goto :check_online + tail -n +0 %TAOS_LOG% | grep -E "TDengine initialized successfully|from offline to online" || goto :check_online echo finish goto :finish ) diff --git a/tests/script/sh/exec.sh b/tests/script/sh/exec.sh index c8cb121b8a88b618cbd7410e95741091655cef38..f548a4cc418d34ac5d4fe27fb944181c54b3a5c2 100755 --- a/tests/script/sh/exec.sh +++ b/tests/script/sh/exec.sh @@ -10,6 +10,14 @@ set +e #set -x +if [[ "$OSTYPE" == "darwin"* ]]; then + TD_OS="Darwin" +else + OS=$(cat /etc/*-release | grep "^NAME=" | cut -d= -f2) + len=$(echo ${#OS}) + len=$((len-2)) + TD_OS=$(echo -ne ${OS:1:${len}} | cut -d" " -f1) +fi unset LD_PRELOAD UNAME_BIN=`which uname` @@ -44,7 +52,10 @@ do ;; esac done - +if [[ "$VALGRIND_OPTION" = "true" ]] && [[ "$TD_OS" == "Alpine" ]]; then + echo alpine skip valgrind + VALGRIND_OPTION="false" +fi SCRIPT_DIR=`dirname $0` cd $SCRIPT_DIR/../ SCRIPT_DIR=`pwd` @@ -59,11 +70,7 @@ fi TAOS_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/sh/exec_tarbitrator.sh b/tests/script/sh/exec_tarbitrator.sh index e985bd65856025b2db8dfef724fdc652b2a03392..eacf5fd2262e54e5ef8d2f475e9cc4faf0515430 100755 --- a/tests/script/sh/exec_tarbitrator.sh +++ b/tests/script/sh/exec_tarbitrator.sh @@ -51,11 +51,7 @@ fi TAOS_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/sh/l2norm.c b/tests/script/sh/l2norm.c index 8ccdffb8d69d1ba27410ad61a74ee3d7ca156be2..0b7f5bf7f6756c11331cae3140a9bf6b5cba024b 100644 --- a/tests/script/sh/l2norm.c +++ b/tests/script/sh/l2norm.c @@ -16,7 +16,7 @@ DLL_EXPORT int32_t l2norm_destroy() { DLL_EXPORT int32_t l2norm_start(SUdfInterBuf *buf) { *(int64_t*)(buf->buf) = 0; buf->bufLen = sizeof(double); - buf->numOfResult = 0; + buf->numOfResult = 1; return 0; } @@ -58,20 +58,11 @@ DLL_EXPORT int32_t l2norm(SUdfDataBlock* block, SUdfInterBuf *interBuf, SUdfInte *(double*)(newInterBuf->buf) = sumSquares; newInterBuf->bufLen = sizeof(double); - - if (interBuf->numOfResult == 0 && numNotNull == 0) { - newInterBuf->numOfResult = 0; - } else { - newInterBuf->numOfResult = 1; - } + newInterBuf->numOfResult = 1; return 0; } DLL_EXPORT int32_t l2norm_finish(SUdfInterBuf* buf, SUdfInterBuf *resultData) { - if (buf->numOfResult == 0) { - resultData->numOfResult = 0; - return 0; - } double sumSquares = *(double*)(buf->buf); *(double*)(resultData->buf) = sqrt(sumSquares); resultData->bufLen = sizeof(double); diff --git a/tests/script/sh/max_vol.c b/tests/script/sh/max_vol.c new file mode 100644 index 0000000000000000000000000000000000000000..4f9ecd33a7e3471a6502857a81db09470236b059 --- /dev/null +++ b/tests/script/sh/max_vol.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include + +#include "taosudf.h" + +#define STR_MAX_LEN 256 // inter buffer length + +// init +DLL_EXPORT int32_t max_vol_init() +{ + return 0; +} + +// destory +DLL_EXPORT int32_t max_vol_destroy() +{ + return 0; +} + +// start +DLL_EXPORT int32_t max_vol_start(SUdfInterBuf *buf) +{ + memset(buf->buf, 0, sizeof(float) + STR_MAX_LEN); + // set init value + *((float*)buf->buf) = -10000000; + buf->bufLen = sizeof(float) + STR_MAX_LEN; + buf->numOfResult = 0; + return 0; +} + +DLL_EXPORT int32_t max_vol(SUdfDataBlock *block, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf) { + float maxValue = *(float *)interBuf->buf; + char strBuff[STR_MAX_LEN] = "inter1buf"; + + if (block->numOfCols < 2) + { + return TSDB_CODE_UDF_INVALID_INPUT; + } + + // check data type + for (int32_t i = 0; i < block->numOfCols; ++i) + { + SUdfColumn *col = block->udfCols[i]; + if( i == block->numOfCols - 1) { + // last column is device id , must varchar + if (col->colMeta.type != TSDB_DATA_TYPE_VARCHAR ) { + return TSDB_CODE_UDF_INVALID_INPUT; + } + } else { + if (col->colMeta.type != TSDB_DATA_TYPE_FLOAT) { + return TSDB_CODE_UDF_INVALID_INPUT; + } + } + } + + // calc max voltage + SUdfColumn *lastCol = block->udfCols[block->numOfCols - 1]; + for (int32_t i = 0; i < (block->numOfCols - 1); ++i) { + for (int32_t j = 0; j < block->numOfRows; ++j) { + SUdfColumn *col = block->udfCols[i]; + if (udfColDataIsNull(col, j)) { + continue; + } + char *data = udfColDataGetData(col, j); + float voltage = *(float *)data; + if (voltage > maxValue) { + maxValue = voltage; + char *valData = udfColDataGetData(lastCol, j); + // get device id + char *deviceId = valData + sizeof(uint16_t); + sprintf(strBuff, "%s_(%d,%d)_%f", deviceId, j, i, maxValue); + } + } + } + + *(float*)newInterBuf->buf = maxValue; + strcpy(newInterBuf->buf + sizeof(float), strBuff); + newInterBuf->bufLen = sizeof(float) + strlen(strBuff)+1; + newInterBuf->numOfResult = 1; + return 0; +} + +DLL_EXPORT int32_t max_vol_finish(SUdfInterBuf *buf, SUdfInterBuf *resultData) +{ + char * str = buf->buf + sizeof(float); + // copy to des + char * des = resultData->buf + sizeof(uint16_t); + strcpy(des, str); + + // set binary type len + uint16_t len = strlen(str); + *((uint16_t*)resultData->buf) = len; + + // set buf len + resultData->bufLen = len + sizeof(uint16_t); + // set row count + resultData->numOfResult = 1; + return 0; +} diff --git a/tests/script/sh/mv_old_data.sh b/tests/script/sh/mv_old_data.sh index 3f4be6714fd757ee60d21ee97be5d411e3f95bdd..1a6bd22c621873253bf98690900759c1ef2304d7 100755 --- a/tests/script/sh/mv_old_data.sh +++ b/tests/script/sh/mv_old_data.sh @@ -20,11 +20,7 @@ fi TAOS_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/sh/prepare_pyudf.sh b/tests/script/sh/prepare_pyudf.sh new file mode 100755 index 0000000000000000000000000000000000000000..b72f8c9f77f94cf35a6bf1daef93ee773e53acfe --- /dev/null +++ b/tests/script/sh/prepare_pyudf.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set +e + +FILE=/usr/local/lib/libtaospyudf.so +if [ ! -f "$FILE" ]; then + echo "$FILE does not exist." + apt install -y python3 python3-dev python3-venv + /usr/bin/python3 -m venv /udfenv + source /udfenv/bin/activate + pip3 install taospyudf + ldconfig + deactivate +else + echo "show dependencies of $FILE" + ldd $FILE +fi diff --git a/tests/script/sh/pybitand.py b/tests/script/sh/pybitand.py new file mode 100644 index 0000000000000000000000000000000000000000..1df724794ec20c6a133f3800046c897c722a173e --- /dev/null +++ b/tests/script/sh/pybitand.py @@ -0,0 +1,21 @@ +def init(): + pass + +def process(block): + (rows, cols) = block.shape() + result = [] + for i in range(rows): + r = 2 ** 32 - 1 + for j in range(cols): + cell = block.data(i,j) + if cell is None: + result.append(None) + break + else: + r = r & cell + else: + result.append(r) + return result + +def destroy(): + pass diff --git a/tests/script/sh/pyl2norm.py b/tests/script/sh/pyl2norm.py new file mode 100644 index 0000000000000000000000000000000000000000..105f546b7d186f466f4fcad5eca38ecf5ff7b5e1 --- /dev/null +++ b/tests/script/sh/pyl2norm.py @@ -0,0 +1,27 @@ +import json +import math + +def init(): + pass + +def destroy(): + pass + +def start(): + return json.dumps(0.0).encode('utf-8') + +def finish(buf): + sum_squares = json.loads(buf) + result = math.sqrt(sum_squares) + return result + +def reduce(datablock, buf): + (rows, cols) = datablock.shape() + sum_squares = json.loads(buf) + + for i in range(rows): + for j in range(cols): + cell = datablock.data(i,j) + if cell is not None: + sum_squares += cell * cell + return json.dumps(sum_squares).encode('utf-8') diff --git a/tests/script/test-win.bat b/tests/script/test-win.bat new file mode 100644 index 0000000000000000000000000000000000000000..66bef2008d168c4a2286a8068d4d196230164fc9 --- /dev/null +++ b/tests/script/test-win.bat @@ -0,0 +1,67 @@ +@echo off +SETLOCAL EnableDelayedExpansion +for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do ( set "DEL=%%a") +set /a a=0 +echo Windows Taosd Full Test +set /a exitNum=0 +rm -rf failed.txt +set caseFile="win-test-file" +if not "%2" == "" ( + set caseFile="%2" +) +for /F "usebackq tokens=*" %%i in (!caseFile!) do ( + set line=%%i + call :CheckSkipCase %%i + if !skipCase! == false ( + if "!line:~,9!" == "./test.sh" ( + set /a a+=1 + echo !a! Processing %%i + call :GetTimeSeconds !time! + set time1=!_timeTemp! + echo Start at !time! + call !line:./test.sh=wtest.bat! > result_!a!.txt 2>error_!a!.txt || set /a errorlevel=8 + if errorlevel 1 ( call :colorEcho 0c "failed" &echo. && set /a exitNum=8 && echo %%i >>failed.txt ) else ( call :colorEcho 0a "Success" &echo. ) + ) + ) +) +exit /b !exitNum! + +:colorEcho +set timeNow=%time% +call :GetTimeSeconds %timeNow% +set time2=%_timeTemp% +set /a interTime=%time2% - %time1% +echo End at %timeNow% , cast %interTime%s +echo off + "%~2" +findstr /v /a:%1 /R "^$" "%~2" nul +del "%~2" > nul 2>&1i +goto :eof + +:GetTimeSeconds +set tt=%1 +set tt=%tt:.= % +set tt=%tt::= % +set tt=%tt: 0= % +set /a index=1 +for %%a in (%tt%) do ( + if !index! EQU 1 ( + set /a hh=%%a + )^ + else if !index! EQU 2 ( + set /a mm=%%a + + )^ + else if !index! EQU 3 ( + set /a ss=%%a + ) + set /a index=index+1 +) +set /a _timeTemp=(%hh%*60+%mm%)*60+%ss% +goto :eof + +:CheckSkipCase +set skipCase=false +@REM if "%*" == "./test.sh -f tsim/query/scalarFunction.sim" ( set skipCase=true ) +echo %* | grep valgrind && set skipCase=true +:goto eof \ No newline at end of file diff --git a/tests/script/test.sh b/tests/script/test.sh index 19180382fd30de26667fef44a5ebc54d19d5b6a7..b10865dd65a8ac2a0771ca49b58ef72ed473bec3 100755 --- a/tests/script/test.sh +++ b/tests/script/test.sh @@ -51,11 +51,7 @@ fi TOP_DIR=`pwd` TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` diff --git a/tests/script/tsim/alter/table.sim b/tests/script/tsim/alter/table.sim index dccfc7f5d6f9bf2afb71cd0c44dc85e722758538..5f45b446ca2c1d0ee8a38b930de1c6a97f69ad2a 100644 --- a/tests/script/tsim/alter/table.sim +++ b/tests/script/tsim/alter/table.sim @@ -657,6 +657,34 @@ if $data20 != null then return -1 endi +print =============== error for normal table +sql create table tb2023(ts timestamp, f int); +sql_error alter table tb2023 add column v varchar(16375); +sql_error alter table tb2023 add column v varchar(16385); +sql_error alter table tb2023 add column v varchar(33100); +sql alter table tb2023 add column v varchar(16374); +sql_error alter table tb2023 modify column v varchar(16375); +sql desc tb2023 +sql alter table tb2023 drop column v +sql_error alter table tb2023 add column v nchar(4094); +sql alter table tb2023 add column v nchar(4093); +sql_error alter table tb2023 modify column v nchar(4094); +sql desc tb2023 + +print =============== error for super table +sql create table stb2023(ts timestamp, f int) tags(t1 int); +sql_error alter table stb2023 add column v varchar(16375); +sql_error alter table stb2023 add column v varchar(16385); +sql_error alter table stb2023 add column v varchar(33100); +sql alter table stb2023 add column v varchar(16374); +sql_error alter table stb2023 modify column v varchar(16375); +sql desc stb2023 +sql alter table stb2023 drop column v +sql_error alter table stb2023 add column v nchar(4094); +sql alter table stb2023 add column v nchar(4093); +sql_error alter table stb2023 modify column v nchar(4094); +sql desc stb2023 + print ======= over sql drop database d1 sql select * from information_schema.ins_databases diff --git a/tests/script/tsim/catalog/alterInCurrent.sim b/tests/script/tsim/catalog/alterInCurrent.sim index 3cb337bbe1930104a21d3d31bf4d5d34a2515352..521858c36859293562ae73a3826b39d5b89c8676 100644 --- a/tests/script/tsim/catalog/alterInCurrent.sim +++ b/tests/script/tsim/catalog/alterInCurrent.sim @@ -67,4 +67,19 @@ sql insert into t1 values (1591060628000, 1); sql alter table st1 drop tag t2; sql create table t2 using st1 tags(2); +print ======== drop tag in super table +sql create database if not exists aaa; +sql select table_name, db_name from information_schema.ins_tables t where t.db_name like 'aaa'; +if $rows != 0 then + return -1 +endi +sql drop database if exists foo; +sql create database if not exists foo; +sql create table foo.t(ts timestamp,name varchar(20)); +sql create table foo.xt(ts timestamp,name varchar(20)); +sql select table_name, db_name from information_schema.ins_tables t where t.db_name like 'foo'; +if $rows != 2 then + return -1 +endi + system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/db/alter_option.sim b/tests/script/tsim/db/alter_option.sim index f4392fbca4727a9a8b2adfba3b24ebf2a5c9ed1a..f20f861bd0d40df47ab9c6e1792651410678f515 100644 --- a/tests/script/tsim/db/alter_option.sim +++ b/tests/script/tsim/db/alter_option.sim @@ -285,14 +285,12 @@ sql_error alter database db keep -1 print ============== modify minrows sql_error alter database db minrows 8 -sql_error alter database db minrows 200 -sql_error alter database db minrows 11 -sql_error alter database db minrows 8000 -sql_error alter database db minrows 8001 +sql_error alter database db minrows 8000000 +sql_error alter database db minrows 8001000 print ============== modify maxrows -sql_error alter database db maxrows 1000 -sql_error alter database db maxrows 2000 +sql_error alter database db maxrows 10000001 +sql_error alter database db maxrows 20000000 sql_error alter database db maxrows 11 # equal minrows sql_error alter database db maxrows 10 # little than minrows diff --git a/tests/script/tsim/db/create_all_options.sim b/tests/script/tsim/db/create_all_options.sim index 382cc986e241d3108268491ae1b0ca9ef1c51bdb..abba824e827eace92d8e2c84685e07fdfbaa4b8d 100644 --- a/tests/script/tsim/db/create_all_options.sim +++ b/tests/script/tsim/db/create_all_options.sim @@ -298,11 +298,11 @@ sql drop database db sql_error create database db MAXROWS -1 sql_error create database db MAXROWS 0 sql_error create database db MAXROWS 199 -sql_error create database db MAXROWS 10001 +sql_error create database db MAXROWS 10000001 sql_error create database db MINROWS -1 sql_error create database db MINROWS 0 sql_error create database db MINROWS 9 -sql_error create database db MINROWS 1001 +sql_error create database db MINROWS 1000001 sql_error create database db MAXROWS 500 MINROWS 1000 print ====> PRECISION ['ms' | 'us' | 'ns', default: ms] diff --git a/tests/script/tsim/db/error1.sim b/tests/script/tsim/db/error1.sim index 32dbe826cca48f64c1825a75a72d7fd7f8b12906..64b17125aae37fa7a71b838374125f5ddea24a95 100644 --- a/tests/script/tsim/db/error1.sim +++ b/tests/script/tsim/db/error1.sim @@ -58,16 +58,16 @@ if $data23 != 0 then return -1 endi -print ========== stop dnode2 -system sh/exec.sh -n dnode2 -s stop -x SIGKILL +#print ========== stop dnode2 +#system sh/exec.sh -n dnode2 -s stop -x SIGKILL -sleep 1000 -print =============== drop database -sql_error drop database d1 +#sleep 1000 +#print =============== drop database +sql drop database d1 -print ========== start dnode2 -system sh/exec.sh -n dnode2 -s start -sleep 1000 +#print ========== start dnode2 +#system sh/exec.sh -n dnode2 -s start +#sleep 1000 print =============== re-create database $x = 0 diff --git a/tests/script/tsim/db/table_prefix_suffix.sim b/tests/script/tsim/db/table_prefix_suffix.sim new file mode 100644 index 0000000000000000000000000000000000000000..1b483d7df788826769f6d35ef10fa6d04116d8a9 --- /dev/null +++ b/tests/script/tsim/db/table_prefix_suffix.sim @@ -0,0 +1,182 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +sql drop database if exists db1; +sql create database db1 vgroups 5 TABLE_PREFIX 1 TABLE_SUFFIX 2; +sql use db1; +sql create table atb1aa (ts timestamp, f1 int); +sql create table btb1bb (ts timestamp, f1 int); +sql create table ctb1cc (ts timestamp, f1 int); +sql create table dtb1dd (ts timestamp, f1 int); +sql create table atb2aa (ts timestamp, f1 int); +sql create table btb2bb (ts timestamp, f1 int); +sql create table ctb2cc (ts timestamp, f1 int); +sql create table dtb2dd (ts timestamp, f1 int); +sql create table etb2ee (ts timestamp, f1 int); +sql show create database db1; +sql select count(*) a from information_schema.ins_tables where db_name='db1' group by vgroup_id having(count(*) > 0) order by a; +if $rows != 2 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 5 then + return -1 +endi +sql drop database if exists db1; + +sql drop database if exists db2; +sql create database db2 vgroups 5 TABLE_PREFIX -1 TABLE_SUFFIX -2; +sql use db2; +sql create table taaa11 (ts timestamp, f1 int); +sql create table tbbb11 (ts timestamp, f1 int); +sql create table tccc11 (ts timestamp, f1 int); +sql create table tddd11 (ts timestamp, f1 int); +sql create table taaa22 (ts timestamp, f1 int); +sql create table tbbb22 (ts timestamp, f1 int); +sql create table tccc22 (ts timestamp, f1 int); +sql create table tddd22 (ts timestamp, f1 int); +sql create table teee22 (ts timestamp, f1 int); +sql show create database db2; +sql select count(*) a from information_schema.ins_tables where db_name='db2' group by vgroup_id having(count(*) > 0) order by a; +if $rows != 2 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 5 then + return -1 +endi +sql drop database if exists db2; + +sql drop database if exists db3; +sql create database db3 vgroups 5 TABLE_PREFIX -1; +sql use db3; +sql create table taaa11 (ts timestamp, f1 int); +sql create table tbbb11 (ts timestamp, f1 int); +sql create table tccc11 (ts timestamp, f1 int); +sql create table tddd11 (ts timestamp, f1 int); +sql create table zaaa22 (ts timestamp, f1 int); +sql create table zbbb22 (ts timestamp, f1 int); +sql create table zccc22 (ts timestamp, f1 int); +sql create table zddd22 (ts timestamp, f1 int); +sql create table zeee22 (ts timestamp, f1 int); +sql show create database db3; +sql select count(*) a from information_schema.ins_tables where db_name='db3' group by vgroup_id having(count(*) > 0) order by a; +if $rows != 2 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 5 then + return -1 +endi +sql drop database if exists db3; + +sql drop database if exists db4; +sql create database db4 vgroups 5 TABLE_SUFFIX -2; +sql use db4; +sql create table taaa11 (ts timestamp, f1 int); +sql create table tbbb11 (ts timestamp, f1 int); +sql create table tccc11 (ts timestamp, f1 int); +sql create table tddd11 (ts timestamp, f1 int); +sql create table zaaa22 (ts timestamp, f1 int); +sql create table zbbb22 (ts timestamp, f1 int); +sql create table zccc22 (ts timestamp, f1 int); +sql create table zddd22 (ts timestamp, f1 int); +sql create table zeee22 (ts timestamp, f1 int); +sql show create database db4; +sql select count(*) a from information_schema.ins_tables where db_name='db4' group by vgroup_id having(count(*) > 0) order by a; +if $rows != 2 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 5 then + return -1 +endi +sql drop database if exists db4; + +sql drop database if exists db5; +sql create database db5 vgroups 5 TABLE_PREFIX 1; +sql use db5; +sql create table taaa11 (ts timestamp, f1 int); +sql create table baaa11 (ts timestamp, f1 int); +sql create table caaa11 (ts timestamp, f1 int); +sql create table daaa11 (ts timestamp, f1 int); +sql create table faaa11 (ts timestamp, f1 int); +sql create table gbbb11 (ts timestamp, f1 int); +sql create table hbbb11 (ts timestamp, f1 int); +sql create table ibbb11 (ts timestamp, f1 int); +sql create table jbbb11 (ts timestamp, f1 int); +sql show create database db5; +sql select count(*) a from information_schema.ins_tables where db_name='db5' group by vgroup_id having(count(*) > 0) order by a; +if $rows != 2 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 5 then + return -1 +endi +sql drop database if exists db5; + +sql drop database if exists db6; +sql create database db6 vgroups 5 TABLE_SUFFIX 2; +sql use db6; +sql create table taaa11 (ts timestamp, f1 int); +sql create table taaa12 (ts timestamp, f1 int); +sql create table taaa13 (ts timestamp, f1 int); +sql create table taaa14 (ts timestamp, f1 int); +sql create table tbbb23 (ts timestamp, f1 int); +sql create table tbbb24 (ts timestamp, f1 int); +sql create table tbbb31 (ts timestamp, f1 int); +sql create table tbbb32 (ts timestamp, f1 int); +sql create table tbbb33 (ts timestamp, f1 int); +sql show create database db6; +sql select count(*) a from information_schema.ins_tables where db_name='db6' group by vgroup_id having(count(*) > 0) order by a; +if $rows != 2 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +if $data10 != 5 then + return -1 +endi +sql drop database if exists db6; + +sql drop database if exists db7; +sql create database db7 vgroups 5 TABLE_PREFIX -100 TABLE_SUFFIX -92; +sql use db7; +sql create table taaa11 (ts timestamp, f1 int); +sql create table taaa12 (ts timestamp, f1 int); +sql create table taaa13 (ts timestamp, f1 int); +sql create table tbbb21 (ts timestamp, f1 int); +sql create table tbbb22 (ts timestamp, f1 int); +sql create table tbbb23 (ts timestamp, f1 int); +sql create table tbbb24 (ts timestamp, f1 int); +sql create table tccc31 (ts timestamp, f1 int); +sql create table tccc32 (ts timestamp, f1 int); +sql create table tccc33 (ts timestamp, f1 int); +sql create table tddd24 (ts timestamp, f1 int); +sql create table tddd31 (ts timestamp, f1 int); +sql create table tddd32 (ts timestamp, f1 int); +sql create table tddd33 (ts timestamp, f1 int); +sql show create database db7; +sql select count(*) a from information_schema.ins_tables where db_name='db7' group by vgroup_id having(count(*) > 0) order by a; +sql drop database if exists db7; + +sql_error create database db8 vgroups 5 TABLE_PREFIX -1 TABLE_SUFFIX 2; +sql_error create database db8 vgroups 5 TABLE_PREFIX 191 TABLE_SUFFIX 192; +sql_error create database db8 vgroups 5 TABLE_PREFIX -192 TABLE_SUFFIX -191; +sql_error create database db8 vgroups 5 TABLE_PREFIX 100 TABLE_SUFFIX 92; + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/dnode/balance3.sim b/tests/script/tsim/dnode/balance3.sim index 2fb284b46614e37ee6ac27bd13a16eb7429e9d86..d0235e096e483e93c1785b555be93150c2a3c35e 100644 --- a/tests/script/tsim/dnode/balance3.sim +++ b/tests/script/tsim/dnode/balance3.sim @@ -130,13 +130,13 @@ print dnode4 openVnodes $data(4)[2] if $data(1)[2] != 1 then return -1 endi -if $data(2)[2] != 1 then +if $data(2)[2] != 2 then return -1 endi if $data(3)[2] != 2 then return -1 endi -if $data(4)[2] != 2 then +if $data(4)[2] != 1 then return -1 endi @@ -216,7 +216,7 @@ endi print ========== step4 sql create database d3 replica 3 vgroups 1 -sql create table d3.t3 (t timestamp, i int) +sql create table d3.t3 (t timestamp, i int) sql insert into d3.t3 values(now+1s, 35) sql insert into d3.t3 values(now+2s, 34) sql insert into d3.t3 values(now+3s, 33) @@ -231,10 +231,10 @@ print dnode5 openVnodes $data(5)[2] if $data(1)[2] != 2 then return -1 endi -if $data(3)[2] != 2 then +if $data(3)[2] != 3 then return -1 endi -if $data(4)[2] != 3 then +if $data(4)[2] != 2 then return -1 endi if $data(5)[2] != 2 then @@ -315,10 +315,10 @@ endi if $data(3)[2] != null then return -1 endi -if $data(4)[2] != 2 then +if $data(4)[2] != 3 then return -1 endi -if $data(5)[2] != 3 then +if $data(5)[2] != 2 then return -1 endi if $data(6)[2] != 2 then diff --git a/tests/script/tsim/dnode/balancex.sim b/tests/script/tsim/dnode/balancex.sim index 0cfc64a954f10457ab720990c758cfe4032e900a..6f077be521e4a4835b3c778a1dee25ea61a8c4eb 100644 --- a/tests/script/tsim/dnode/balancex.sim +++ b/tests/script/tsim/dnode/balancex.sim @@ -145,10 +145,10 @@ print dnode2 openVnodes $data(4)[2] if $data(1)[2] != 1 then return -1 endi -if $data(2)[2] != 1 then +if $data(2)[2] != 2 then return -1 endi -if $data(3)[2] != 2 then +if $data(3)[2] != 1 then return -1 endi if $data(4)[2] != 1 then diff --git a/tests/script/tsim/dnode/drop_dnode_force.sim b/tests/script/tsim/dnode/drop_dnode_force.sim index 26e48933be4929e158a407fd512734720be32d95..bce51a98887dd4aa9bfe6a4bb444424fdf8b006d 100644 --- a/tests/script/tsim/dnode/drop_dnode_force.sim +++ b/tests/script/tsim/dnode/drop_dnode_force.sim @@ -50,6 +50,21 @@ endi print =============== step2 create database sql create database d1 vgroups 1 replica 3 sql use d1 + +$wt = 0 +stepwt1: + $wt = $wt + 1 + sleep 1000 + if $wt == 200 then + print ====> dnode not ready! + return -1 + endi +sql show transactions +if $rows != 0 then + print wait 1 seconds to alter + goto stepwt1 +endi + sql create table d1.st0 (ts timestamp, i int) tags (j int) sql create table d1.c0 using st0 tags(0) sql create table d1.c1 using st0 tags(1) @@ -120,9 +135,9 @@ if $rows != 12 then return -1 endi -print =============== step3: create qnode snode on dnode 2 -sql create qnode on dnode 2 -sql create snode on dnode 2 +print =============== step3: create qnode snode on dnode 3 +sql create qnode on dnode 3 +sql create snode on dnode 3 sql select * from information_schema.ins_qnodes if $rows != 1 then return -1 @@ -136,16 +151,16 @@ print =============== step4: create mnode on dnode 2 sql create mnode on dnode 3 sql create mnode on dnode 2 $x = 0 -step4: +step4: $x = $x + 1 sleep 1000 if $x == 10 then return -1 endi sql select * from information_schema.ins_mnodes -x step4 -print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4] -print $data[1][0] $data[1][1] $data[1][2] $data[1][3] $data[1][4] -print $data[2][0] $data[2][1] $data[2][2] $data[2][3] $data[1][4] +print $data[0][0] $data[0][1] $data[0][2] $data[0][3] $data[0][4] +print $data[1][0] $data[1][1] $data[1][2] $data[1][3] $data[1][4] +print $data[2][0] $data[2][1] $data[2][2] $data[2][3] $data[1][4] #if $data(1)[2] != leader then # goto step4 #endi @@ -157,7 +172,7 @@ endi #endi print =============== step5: create dnode 5 -system sh/exec.sh -n dnode2 -s stop -x SIGINT +system sh/exec.sh -n dnode3 -s stop -x SIGINT system sh/exec.sh -n dnode5 -s start $x = 0 step5: @@ -179,10 +194,10 @@ endi if $data(1)[4] != ready then goto step5 endi -if $data(2)[4] != offline then +if $data(2)[4] != ready then goto step5 endi -if $data(3)[4] != ready then +if $data(3)[4] != offline then goto step5 endi if $data(4)[4] != ready then @@ -192,9 +207,9 @@ if $data(5)[4] != ready then goto step5 endi -print =============== step5a: drop dnode 2 -sql_error drop dnode 2 -sql drop dnode 2 force +print =============== step5a: drop dnode 3 +sql_error drop dnode 3 +sql drop dnode 3 force print select * from information_schema.ins_dnodes; sql select * from information_schema.ins_dnodes; diff --git a/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim b/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim index 0fa7320ff6cd515452748c6c81e82011eb4f8dcb..ef5001dcee28012ca40d2d09cd933b1e5ee1ec34 100644 --- a/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim +++ b/tests/script/tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim @@ -170,6 +170,20 @@ if $leaderExist != 1 then goto step35 endi +$wt = 0 +stepwt1: + $wt = $wt + 1 + sleep 1000 + if $wt == 200 then + print ====> dnode not ready! + return -1 + endi +sql show transactions +if $rows != 0 then + print wait 1 seconds to alter + goto stepwt1 +endi + print =============== step36: create table sql use d1 sql create table d1.st (ts timestamp, i int) tags (j int) diff --git a/tests/script/tsim/dnode/offline_reason.sim b/tests/script/tsim/dnode/offline_reason.sim index 6b1686dbb4c2a16920c0c71ccc8b5e84371d5b72..8c4d8b47f765f22f07e8f5114797c94dc89c67ca 100644 --- a/tests/script/tsim/dnode/offline_reason.sim +++ b/tests/script/tsim/dnode/offline_reason.sim @@ -8,10 +8,10 @@ sql connect sql create dnode $hostname port 7200 sql select * from information_schema.ins_dnodes -print dnode1 off: $data(1)[6] -print dnode2 off: $data(2)[6] +print dnode1 off: $data(1)[7] +print dnode2 off: $data(2)[7] -if $data(2)[6] != @status not received@ then +if $data(2)[7] != @status not received@ then return -1 endi @@ -50,9 +50,9 @@ step3: return -1 endi sql select * from information_schema.ins_dnodes -print dnode1 off: $data(1)[6] -print dnode2 off: $data(2)[6] -if $data(2)[6] != @status msg timeout@ then +print dnode1 off: $data(1)[7] +print dnode2 off: $data(2)[7] +if $data(2)[7] != @status msg timeout@ then goto step3 endi @@ -77,9 +77,9 @@ step5: endi sql select * from information_schema.ins_dnodes -print dnode1 off: $data(1)[6] -print dnode2 off: $data(3)[6] -if $data(3)[6] != @dnodeId not match@ then +print dnode1 off: $data(1)[7] +print dnode2 off: $data(3)[7] +if $data(3)[7] != @dnodeId not match@ then goto step5 endi @@ -98,10 +98,10 @@ step6: endi sql select * from information_schema.ins_dnodes -print dnode1 off: $data(1)[6] -print dnode2 off: $data(3)[6] -print dnode3 off: $data(4)[6] -if $data(4)[6] != @interval not match@ then +print dnode1 off: $data(1)[7] +print dnode2 off: $data(3)[7] +print dnode3 off: $data(4)[67 +if $data(4)[7] != @interval not match@ then goto step6 endi @@ -120,11 +120,11 @@ step7: endi sql select * from information_schema.ins_dnodes -print dnode1 off: $data(1)[6] -print dnode3 off: $data(3)[6] -print dnode4 off: $data(4)[6] -print dnode5 off: $data(5)[6] -if $data(5)[6] != @locale not match@ then +print dnode1 off: $data(1)[7] +print dnode3 off: $data(3)[7] +print dnode4 off: $data(4)[7] +print dnode5 off: $data(5)[7] +if $data(5)[7] != @locale not match@ then goto step7 endi @@ -143,12 +143,12 @@ step8: endi sql select * from information_schema.ins_dnodes -print dnode1 off: $data(1)[6] -print dnode3 off: $data(3)[6] -print dnode4 off: $data(4)[6] -print dnode5 off: $data(5)[6] -print dnode6 off: $data(6)[6] -if $data(6)[6] != @charset not match@ then +print dnode1 off: $data(1)[7] +print dnode3 off: $data(3)[7] +print dnode4 off: $data(4)[7] +print dnode5 off: $data(5)[7] +print dnode6 off: $data(6)[7] +if $data(6)[7] != @charset not match@ then goto step8 endi diff --git a/tests/script/tsim/dnode/split_vgroup_replica1.sim b/tests/script/tsim/dnode/split_vgroup_replica1.sim index 1bdd322714a1e8e7443d337daacc69d3ce2a4792..51d63d25f482985b67ae37f2d4f005b8010f759e 100644 --- a/tests/script/tsim/dnode/split_vgroup_replica1.sim +++ b/tests/script/tsim/dnode/split_vgroup_replica1.sim @@ -11,7 +11,6 @@ system sh/cfg.sh -n dnode1 -c supportVnodes -v 0 system sh/exec.sh -n dnode1 -s start system sh/exec.sh -n dnode2 -s start sql connect -sql create user u1 pass 'taosdata' print =============== step1 create dnode2 sql create dnode $hostname port 7200 @@ -73,8 +72,21 @@ print =============== step3: create database sql use d1 sql create table d1.st (ts timestamp, i int) tags (j int) sql create table d1.c1 using st tags(1) +sql create table d1.c2 using st tags(2) +sql create table d1.c3 using st tags(3) +sql create table d1.c4 using st tags(4) +sql create table d1.c5 using st tags(5) +sql insert into d1.c1 values (now, 1); +sql insert into d1.c2 values (now, 2); +sql insert into d1.c3 values (now, 3); +sql insert into d1.c4 values (now, 4); +sql insert into d1.c5 values (now, 5); sql show d1.tables -if $rows != 1 then +if $rows != 5 then + return -1 +endi +sql select * from d1.st +if $rows != 5 then return -1 endi @@ -82,6 +94,34 @@ print =============== step4: split print split vgroup 2 sql split vgroup 2 +print =============== step5: check split result +sql show d1.tables +#if $rows != 5 then +# return -1 +#endi +#sql select * from d1.st +#if $rows != 5 then +# return -1 +#endi + +print =============== step6: create tables +sql create table d1.c6 using st tags(6) +sql create table d1.c7 using st tags(7) +sql create table d1.c8 using st tags(8) +sql create table d1.c9 using st tags(9) +sql insert into d1.c6 values (now, 6); +sql insert into d1.c7 values (now, 7); +sql insert into d1.c8 values (now, 8); +sql insert into d1.c9 values (now, 9); +sql show d1.tables +#if $rows != 9 then +# return -1 +#endi +#sql select * from d1.st +#if $rows != 9 then +# return -1 +#endi + system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode2 -s stop -x SIGINT system sh/exec.sh -n dnode3 -s stop -x SIGINT diff --git a/tests/script/tsim/dnode/vnode_clean.sim b/tests/script/tsim/dnode/vnode_clean.sim index ba1d083c68e069fdbfecbd13144f31750a81eb81..aead25938ec0b7c1e52ed69ddbfcd58f79d060b7 100644 --- a/tests/script/tsim/dnode/vnode_clean.sim +++ b/tests/script/tsim/dnode/vnode_clean.sim @@ -207,10 +207,10 @@ print dnode2 openVnodes $data(4)[2] if $data(1)[2] != 1 then return -1 endi -if $data(3)[2] != 1 then +if $data(3)[2] != 2 then return -1 endi -if $data(4)[2] != 2 then +if $data(4)[2] != 1 then return -1 endi diff --git a/tests/script/tsim/insert/delete0.sim b/tests/script/tsim/insert/delete0.sim new file mode 100644 index 0000000000000000000000000000000000000000..56538536439bbf3d7e9937353ee65acaea34fb43 --- /dev/null +++ b/tests/script/tsim/insert/delete0.sim @@ -0,0 +1,161 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print =============== create database with different precision +sql create database d0 keep 365 +sql create database d1 keep 365 precision 'ms' +sql create database d2 keep 365 precision 'us' +sql create database d3 keep 365 precision 'ns' + +sql select * from information_schema.ins_databases +if $rows != 6 then + return -1 +endi + +print $data00 $data01 $data02 + + +sql create table if not exists d0.stb (ts timestamp, c1 int, c2 float, c3 double) tags (t1 int unsigned) +sql create table if not exists d1.stb (ts timestamp, c1 int, c2 float, c3 double) tags (t1 int unsigned) +sql create table if not exists d2.stb (ts timestamp, c1 int, c2 float, c3 double) tags (t1 int unsigned) +sql create table if not exists d3.stb (ts timestamp, c1 int, c2 float, c3 double) tags (t1 int unsigned) +sql create table if not exists d0.ntb (ts timestamp, c1 int, c2 float, c3 double) +sql create table if not exists d1.ntb (ts timestamp, c1 int, c2 float, c3 double) +sql create table if not exists d2.ntb (ts timestamp, c1 int, c2 float, c3 double) +sql create table if not exists d3.ntb (ts timestamp, c1 int, c2 float, c3 double) + +sql create table d0.ct1 using d0.stb tags(1000) +sql create table d1.ct1 using d1.stb tags(1000) +sql create table d2.ct1 using d2.stb tags(1000) +sql create table d3.ct1 using d3.stb tags(1000) +sql create table d0.ct2 using d0.stb tags(1000) +sql create table d1.ct2 using d1.stb tags(1000) +sql create table d2.ct2 using d2.stb tags(1000) +sql create table d3.ct2 using d3.stb tags(1000) + + +sql insert into d0.ct1 values(now+0s, 10, 2.0, 3.0) +sql insert into d1.ct1 values(now+0s, 10, 2.0, 3.0) +sql insert into d2.ct1 values(now+0s, 10, 2.0, 3.0) +sql insert into d3.ct1 values(now+0s, 10, 2.0, 3.0) +sql insert into d0.ct2 values(now+0s, 10, 2.0, 3.0) +sql insert into d1.ct2 values(now+0s, 10, 2.0, 3.0) +sql insert into d2.ct2 values(now+0s, 10, 2.0, 3.0) +sql insert into d3.ct2 values(now+0s, 10, 2.0, 3.0) +sql insert into d0.ntb values(now+0s, 10, 2.0, 3.0) +sql insert into d1.ntb values(now+0s, 10, 2.0, 3.0) +sql insert into d2.ntb values(now+0s, 10, 2.0, 3.0) +sql insert into d3.ntb values(now+0s, 10, 2.0, 3.0) + + +print =============== query data from super table +sql select count(*) from d0.stb +if $data00 != 2 then + return -1 +endi +sql select count(*) from d1.stb +if $data00 != 2 then + return -1 +endi +sql select count(*) from d2.stb +if $data00 != 2 then + return -1 +endi +sql select count(*) from d3.stb +if $data00 != 2 then + return -1 +endi + +print =============== delete from child table +sql delete from d0.ct1 where ts < now() +sql delete from d1.ct1 where ts < now() +sql delete from d2.ct1 where ts < now() +sql delete from d3.ct1 where ts < now() + + +print =============== query data from super table +sql select count(*) from d0.stb +if $data00 != 1 then + return -1 +endi +sql select count(*) from d1.stb +if $data00 != 1 then + return -1 +endi +sql select count(*) from d2.stb +if $data00 != 1 then + return -1 +endi +sql select count(*) from d3.stb +if $data00 != 1 then + return -1 +endi +print =============== query data from normal table +sql select count(*) from d0.ntb +if $data00 != 1 then + return -1 +endi +sql select count(*) from d1.ntb +if $data00 != 1 then + return -1 +endi +sql select count(*) from d2.ntb +if $data00 != 1 then + return -1 +endi +sql select count(*) from d3.ntb +if $data00 != 1 then + return -1 +endi + +print =============== delete from super table +sql delete from d0.stb where ts < now() +sql delete from d1.stb where ts < now() +sql delete from d2.stb where ts < now() +sql delete from d3.stb where ts < now() + +print =============== query data from super table +sql select count(*) from d0.stb +if $data00 != 0 then + return -1 +endi +sql select count(*) from d1.stb +if $data00 != 0 then + return -1 +endi +sql select count(*) from d2.stb +if $data00 != 0 then + return -1 +endi +sql select count(*) from d3.stb +if $data00 != 0 then + return -1 +endi + +print =============== delete from normal table +sql delete from d0.ntb where ts < now() +sql delete from d1.ntb where ts < now() +sql delete from d2.ntb where ts < now() +sql delete from d3.ntb where ts < now() + +print =============== query data from normal table +sql select count(*) from d0.ntb +if $data00 != 0 then + return -1 +endi +sql select count(*) from d1.ntb +if $data00 != 0 then + return -1 +endi +sql select count(*) from d2.ntb +if $data00 != 0 then + return -1 +endi +sql select count(*) from d3.ntb +if $data00 != 0 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/insert/update2.sim b/tests/script/tsim/insert/update2.sim new file mode 100644 index 0000000000000000000000000000000000000000..d2b5b052678a93499157dea219571df6ed67c6b7 --- /dev/null +++ b/tests/script/tsim/insert/update2.sim @@ -0,0 +1,221 @@ +################################################################################################ +# migrate from 2.0 insert_update2.sim +################################################################################################ + +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/exec.sh -n dnode1 -s start + +sleep 2000 +sql connect + +### 4096*0.8 - 1 = 3275 +$rowSuperBlk = 3275 +### 4096 - 3275 -1 - 1 = 819 +$rowSubBlk = 819 +$ts0 = 1672372800000 +$ts1 = 1672372900000 +$ts2 = 1672686800000 + +$i = 0 +$db = db0 +$stb1 = stb1 +$tb1 = tb1 +$stb2 = stb2 +$tb2 = tb2 + +print ====== create database +sql drop database if exists $db +sql create database $db keep 1000 duration 10 +print ====== create tables +sql use $db +sql create table $stb1 (ts timestamp, c1 bigint, c2 bigint, c3 bigint) tags(t1 int) +sql create table $stb2 (ts timestamp, c1 bigint, c2 bigint, c3 bigint, c4 bigint, c5 bigint, c6 bigint, c7 bigint, c8 bigint, c9 bigint, c10 bigint, c11 bigint, c12 bigint, c13 bigint, c14 bigint, c15 bigint, c16 bigint, c17 bigint, c18 bigint, c19 bigint, c20 bigint, c21 bigint, c22 bigint, c23 bigint, c24 bigint, c25 bigint, c26 bigint, c27 bigint, c28 bigint, c29 bigint, c30 bigint) tags(t1 int) +sql create table $tb1 using $stb1 tags(1) +sql create table $tb2 using $stb2 tags(2) +print ====== tables created + + +print ========== step 1: merge dataRow in mem + +$i = 0 +while $i < $rowSuperBlk + $xs = $i * 10 + $ts = $ts2 + $xs + sql insert into $tb1 (ts,c1) values ( $ts , $i ) + $i = $i + 1 +endw + +sql insert into $tb1 values ( $ts0 , 1,NULL,0) +sql insert into $tb1 (ts,c2,c3) values ( $ts0 , 1,1) + +sql select * from $tb1 where ts = $ts0 +if $rows != 1 then + return -1 +endi +if $data01 != 1 then + return -1 +endi +if $data02 != 1 then + return -1 +endi +if $data03 != 1 then + return -1 +endi + +print ========== step 2: merge kvRow in mem +$i = 0 +while $i < $rowSuperBlk + $xs = $i * 10 + $ts = $ts2 + $xs + sql insert into $tb2 (ts,c1) values ( $ts , $i ) + $i = $i + 1 +endw + +sql insert into $tb2 (ts,c3,c8,c10) values ( $ts0 , 1,NULL,0) +sql insert into $tb2 (ts,c8,c10) values ( $ts0 , 1,1) + +sql select ts,c1,c3,c8,c10 from $tb2 where ts = $ts0 +if $rows != 1 then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data02 != 1 then + return -1 +endi +if $data03 != 1 then + return -1 +endi +if $data04 != 1 then + return -1 +endi + +print ================== restart server to commit data into disk +system sh/exec.sh -n dnode1 -s stop -x SIGINT +sleep 2000 +system sh/exec.sh -n dnode1 -s start +print ================== server restart completed +sleep 2000 + +print ========== step 3: merge dataRow in file +sql insert into $tb1 (ts,c1) values ( $ts0 , 2) +print ========== step 4: merge kvRow in file +sql insert into $tb2 (ts,c3) values ( $ts0 , 2) + +print ================== restart server to commit data into disk +system sh/exec.sh -n dnode1 -s stop -x SIGINT +sleep 2000 +system sh/exec.sh -n dnode1 -s start +print ================== server restart completed +sleep 2000 + +sql select * from $tb1 where ts = $ts0 +if $rows != 1 then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data02 != 1 then + return -1 +endi +if $data03 != 1 then + return -1 +endi + +sql select ts,c1,c3,c8,c10 from $tb2 where ts = $ts0 +if $rows != 1 then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data02 != 2 then + return -1 +endi +if $data03 != 1 then + return -1 +endi +if $data04 != 1 then + return -1 +endi + + +print ========== step 5: merge dataRow in file/mem +$i = 0 +while $i < $rowSubBlk + $xs = $i * 1 + $ts = $ts1 + $xs + sql insert into $tb1 (ts,c1) values ( $ts , $i ) + $i = $i + 1 +endw +print ========== step 6: merge kvRow in file/mem +$i = 0 +while $i < $rowSubBlk + $xs = $i * 1 + $ts = $ts1 + $xs + sql insert into $tb2 (ts,c1) values ( $ts , $i ) + $i = $i + 1 +endw + +print ================== restart server to commit data into disk +system sh/exec.sh -n dnode1 -s stop -x SIGINT +sleep 2000 +system sh/exec.sh -n dnode1 -s start +print ================== server restart completed +sleep 2000 + +sql insert into $tb1 (ts,c3) values ( $ts0 , 3) +sql insert into $tb2 (ts,c3) values ( $ts0 , 3) +$tsN = $ts0 + 1 +sql insert into $tb1 (ts,c1,c3) values ( $tsN , 1,0) +sql insert into $tb2 (ts,c3,c8) values ( $tsN , 100,200) +$tsN = $ts0 + 2 +sql insert into $tb1 (ts,c1,c3) values ( $tsN , 1,0) +sql insert into $tb2 (ts,c3,c8) values ( $tsN , 100,200) + +print ================== restart server to commit data into disk +system sh/exec.sh -n dnode1 -s stop -x SIGINT +sleep 2000 +system sh/exec.sh -n dnode1 -s start +print ================== server restart completed +sleep 2000 + + +sql select * from $tb1 where ts = $ts0 +if $rows != 1 then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data02 != 1 then + return -1 +endi +if $data03 != 3 then + return -1 +endi + +sql select ts,c1,c3,c8,c10 from $tb2 where ts = $ts0 +if $rows != 1 then + return -1 +endi +if $data01 != NULL then + return -1 +endi +if $data02 != 3 then + return -1 +endi +if $data03 != 1 then + return -1 +endi + +if $data04 != 1 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/tsim/parser/alter_column.sim b/tests/script/tsim/parser/alter_column.sim index c70a604c738fca48600a480594b98f08b1daa14f..d569e47735a9d09eb5626dfd84aa0e17642db92b 100644 --- a/tests/script/tsim/parser/alter_column.sim +++ b/tests/script/tsim/parser/alter_column.sim @@ -48,7 +48,7 @@ sql_error alter table tb modify column c2 binary(10); sql_error alter table tb modify column c2 binary(9); sql_error alter table tb modify column c2 binary(-9); sql_error alter table tb modify column c2 binary(0); -sql alter table tb modify column c2 binary(17000); +sql_error alter table tb modify column c2 binary(17000); sql_error alter table tb modify column c2 nchar(30); sql_error alter table tb modify column c3 double; sql_error alter table tb modify column c3 nchar(10); diff --git a/tests/script/tsim/parser/col_arithmetic_operation.sim b/tests/script/tsim/parser/col_arithmetic_operation.sim index 9a2ba34c85e552585770bb42913b8c83ddd58131..a11b99d3d60329f33bd5e191d32ce1af4be772b8 100644 --- a/tests/script/tsim/parser/col_arithmetic_operation.sim +++ b/tests/script/tsim/parser/col_arithmetic_operation.sim @@ -9,7 +9,7 @@ $dbPrefix = ca_db $tbPrefix = ca_tb $stbPrefix = ca_stb $tbNum = 10 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum $ts0 = 1537146000000 $delta = 600000 @@ -18,6 +18,7 @@ $i = 0 $db = $dbPrefix . $i $stb = $stbPrefix . $i +print drop database $db -x step1 sql drop database $db -x step1 step1: sql create database $db diff --git a/tests/script/tsim/parser/col_arithmetic_query.sim b/tests/script/tsim/parser/col_arithmetic_query.sim index b77dcbe4982744a59b61687f70d5a650229361e4..1537db9a8365b0eb104f62ae74367d53bf9a10bd 100644 --- a/tests/script/tsim/parser/col_arithmetic_query.sim +++ b/tests/script/tsim/parser/col_arithmetic_query.sim @@ -4,7 +4,7 @@ $dbPrefix = ca_db $tbPrefix = ca_tb $stbPrefix = ca_stb -$rowNum = 10000 +$rowNum = 1000 $i = 0 $db = $dbPrefix . $i @@ -33,7 +33,7 @@ endi # asc/desc order [d.2] ====================================================== sql select c1 *( 2 / 3 ), c1/c1 from $tb order by ts asc; -if $rows != 10000 then +if $rows != 1000 then return -1 endi if $data00 != 0.000000000 then @@ -57,7 +57,7 @@ if $data91 != 1.000000000 then endi sql select (c1 * 2) % 7.9, c1*1, c1*1*1, c1*c1, c1*c1*c1 from $tb order by ts desc; -if $rows != 10000 then +if $rows != 1000 then return -1 endi if $data00 != 2.200000000 then @@ -151,7 +151,7 @@ sql select top(c1,1) - 88 from $tb # all data types [d.6] ================================================================ sql select c2-c1*1.1, c3/c2, c4*c3, c5%c4, (c6+c4)%22, c2-c2 from $tb -if $rows != 10000 then +if $rows != 1000 then return -1 endi if $data00 != 0.000000000 then @@ -221,7 +221,7 @@ if $data90 != 76.000000000 then return -1 endi -sql select c4 / 99.123 from $tb limit 10 offset 9999; +sql select c4 / 99.123 from $tb limit 10 offset 999; if $rows != 1 then return -1 endi @@ -237,7 +237,7 @@ sql_error select c2-c2, c3-c4, c5%c3 from $tb fill(value, 12); # constant column. [d.13]============================================================== sql select c1, c2+c6, 12.9876545678, 1, 1.1 from $tb -if $rows != 10000 then +if $rows != 1000 then return -1 endi if $data00 != 0 then @@ -261,7 +261,7 @@ endi # column value filter [d.14]=========================================================== sql select c1, c2+c6, 12.9876545678, 1, 1.1 from $tb where c1<2 -if $rows != 2000 then +if $rows != 200 then return -1 endi if $data00 != 0 then @@ -338,13 +338,14 @@ sql select (count(c1) * 2) % 7.9, (count(c1) * 2), ( count(1)*2) from $stb if $rows != 1 then return -1 endi -if $data00 != 1.800000000 then +print $data00 +if $data00 != 6.500000000 then return -1 endi -if $data01 != 100000.000000000 then +if $data01 != 10000.000000000 then return -1 endi -if $data02 != 200000.000000000 then +if $data02 != 20000.000000000 then return -1 endi @@ -371,7 +372,7 @@ endi if $data00 != 0.000000000 then return -1 endi -if $data01 != 225000.000000000 then +if $data01 != 22500.000000000 then return -1 endi if $data02 != 8.077777778 then @@ -383,7 +384,7 @@ endi if $data04 != 0.444444444 then return -1 endi -if $data05 != 450000.000000000 then +if $data05 != 45000.000000000 then return -1 endi @@ -484,10 +485,10 @@ endi if $data10 != 0.000000000 then return -1 endi -if $data20 != 0.997600000 then +if $data20 != 0.976000000 then return -1 endi -if $data90 != 7.980800000 then +if $data90 != 7.808000000 then return -1 endi @@ -496,7 +497,7 @@ sql select first(c6) - sum(c6) + 12 from $stb limit 12 offset 0; if $rows != 1 then return -1 endi -if $data00 != -449988.000000000 then +if $data00 != -44988.000000000 then return -1 endi @@ -546,7 +547,7 @@ endi # interval query [d.17]=============================================================== sql select avg(c2)*count(c2), sum(c3)-first(c3), last(c4)+9 from ca_stb0 interval(1s) -if $rows != 10000 then +if $rows != 1000 then return -1 endi diff --git a/tests/script/tsim/parser/commit.sim b/tests/script/tsim/parser/commit.sim index a9bf8b26ebda178ed789f3119eac7203a6889f9b..84610ad379e614bb50aefb90691fc10e287d8ba2 100644 --- a/tests/script/tsim/parser/commit.sim +++ b/tests/script/tsim/parser/commit.sim @@ -7,7 +7,7 @@ $dbPrefix = sc_db $tbPrefix = sc_tb $stbPrefix = sc_stb $tbNum = 10 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum $loops = 5 $log = 1 diff --git a/tests/script/tsim/parser/groupby.sim b/tests/script/tsim/parser/groupby.sim index 4ee9c530a79c72ccac12a99922af1eeefc7485ed..637b7553fd741d8bf89fce3baf67d817391ea0e5 100644 --- a/tests/script/tsim/parser/groupby.sim +++ b/tests/script/tsim/parser/groupby.sim @@ -7,7 +7,7 @@ $dbPrefix = group_db $tbPrefix = group_tb $mtPrefix = group_mt $tbNum = 8 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum print =============== groupby.sim @@ -88,7 +88,7 @@ if $row != 20 then return -1 endi -if $data00 != 100 then +if $data00 != 10 then return -1 endi @@ -96,7 +96,7 @@ if $data01 != 0 then return -1 endi -if $data10 != 100 then +if $data10 != 10 then return -1 endi @@ -186,7 +186,7 @@ if $data04 != 0.00000 then return -1 endi -if $data10 != 100 then +if $data10 != 10 then return -1 endi @@ -227,7 +227,7 @@ if $row != 20 then return -1 endi -if $data00 != 800 then +if $data00 != 80 then return -1 endi @@ -235,7 +235,7 @@ if $data01 != 0 then return -1 endi -if $data10 != 800 then +if $data10 != 80 then return -1 endi @@ -243,7 +243,7 @@ if $data11 != 1 then return -1 endi -if $data90 != 800 then +if $data90 != 80 then return -1 endi @@ -297,7 +297,7 @@ if $data00 != $data03 then return -1 endi -if $data01 != @70-01-01 08:01:49.900@ then +if $data01 != @70-01-01 08:01:40.900@ then return -1 endi @@ -305,7 +305,7 @@ if $data02 != @70-01-01 08:01:40.000@ then return -1 endi -if $data07 != 800 then +if $data07 != 80 then return -1 endi @@ -313,7 +313,7 @@ if $data10 != $data13 then return -1 endi -if $data11 != @70-01-01 08:01:49.901@ then +if $data11 != @70-01-01 08:01:40.901@ then return -1 endi @@ -321,7 +321,7 @@ if $data12 != @70-01-01 08:01:40.001@ then return -1 endi -if $data17 != 800 then +if $data17 != 80 then return -1 endi @@ -329,7 +329,7 @@ if $data90 != $data93 then return -1 endi -if $data91 != @70-01-01 08:01:49.909@ then +if $data91 != @70-01-01 08:01:40.909@ then return -1 endi @@ -337,11 +337,11 @@ if $data92 != @70-01-01 08:01:40.009@ then return -1 endi -if $data97 != 800 then +if $data97 != 80 then return -1 endi -if $data95 != 7200 then +if $data95 != 720 then return -1 endi @@ -358,7 +358,7 @@ if $data00 != 0 then return -1 endi -if $data11 != 800 then +if $data11 != 80 then return -1 endi @@ -372,7 +372,7 @@ if $data00 != 0 then return -1 endi -if $data01 != @70-01-01 08:01:49.900@ then +if $data01 != @70-01-01 08:01:40.900@ then return -1 endi @@ -389,13 +389,13 @@ if $data04 != 0 then return -1 endi -if $data06 != 100 then +if $data06 != 10 then return -1 endi sql select count(*),first(ts),last(ts),min(c3) from group_tb1 group by c4 order by c4; -if $rows != 10000 then +if $rows != 1000 then return -1 endi @@ -415,18 +415,18 @@ if $data03 != 0 then return -1 endi -sql select count(*),first(ts),last(ts),min(c3) from group_tb1 group by c4 limit 1; +sql select count(*),first(ts),last(ts),min(c3) from group_tb1 group by c4 slimit 1; if $rows != 1 then return -1 endi -sql select count(*),first(ts),last(ts),min(c3) from group_tb1 group by c4 limit 20 offset 9990; +sql select count(*),first(ts),last(ts),min(c3) from group_tb1 group by c4 slimit 20 soffset 990; if $rows != 10 then return -1 endi sql select count(*),first(ts),last(ts),min(c3),max(c3),sum(c3),avg(c3),sum(c4)/count(c4) from group_tb1 group by c4; -if $rows != 10000 then +if $rows != 1000 then return -1 endi @@ -441,32 +441,32 @@ if $rows != 100 then return -1 endi -if $data00 != 100 then +if $data00 != 10 then return -1 endi -if $data01 != 495000 then +if $data01 != 4500 then return -1 endi -if $data02 != 100 then +if $data02 != 10 then return -1 endi -if $data03 != 4950.000000000 then - print expect 4950.000000000 , acutal $data03 +if $data03 != 450.000000000 then + print expect 450.000000000 , acutal $data03 return -1 endi -if $data10 != 100 then +if $data10 != 10 then return -1 endi -if $data11 != 495100 then +if $data11 != 4510 then return -1 endi -if $data13 != 4951.000000000 then +if $data13 != 451.000000000 then return -1 endi @@ -481,19 +481,19 @@ if $rows != 1 then return -1 endi -#if $data00 != 79200.000000000 then +#if $data00 != 2160.000000000 then # return -1 #endi -#if $data01 != @binary99@ then +#if $data01 != @binary27@ then # return -1 #endi -#if $data02 != 99.000000000 then +#if $data02 != 27.000000000 then # return -1 #endi -#if $data03 != 99.000000000 then +#if $data03 != 27.000000000 then # return -1 #endi @@ -503,7 +503,7 @@ if $rows != 100 then return -1 endi -if $data00 != 4851.000000000 then +if $data00 != 441.000000000 then return -1 endi @@ -511,19 +511,19 @@ if $data01 != 0 then return -1 endi -if $data02 != 9900 then +if $data02 != 900 then return -1 endi -if $data03 != 4950.000000000 then +if $data03 != 450.000000000 then return -1 endi -if $data04 != 2886.607004772 then +if $data04 != 287.228132327 then return -1 endi -if $data10 != 4852.000000000 then +if $data10 != 442.000000000 then return -1 endi @@ -531,15 +531,15 @@ if $data11 != 1 then return -1 endi -if $data12 != 9901 then +if $data12 != 901 then return -1 endi -if $data13 != 4951.000000000 then +if $data13 != 451.000000000 then return -1 endi -if $data14 != 2886.607004772 then +if $data14 != 287.228132327 then return -1 endi diff --git a/tests/script/tsim/parser/interp.sim b/tests/script/tsim/parser/interp.sim index e6512a22d79da5ca5970665f08e369e582eed361..f74a2dc6243ad6d2bf7acf3a5f57d80df3d53cbb 100644 --- a/tests/script/tsim/parser/interp.sim +++ b/tests/script/tsim/parser/interp.sim @@ -7,7 +7,7 @@ $dbPrefix = intp_db $tbPrefix = intp_tb $stbPrefix = intp_stb $tbNum = 4 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum $ts0 = 1537146000000 $delta = 600000 diff --git a/tests/script/tsim/parser/join_manyblocks.sim b/tests/script/tsim/parser/join_manyblocks.sim index 154316a03f694d7ea375f1cc7d3cc4ad903cd9b9..7fd0df21b31b598b54dbeaa3e7780a1e9c0ea010 100644 --- a/tests/script/tsim/parser/join_manyblocks.sim +++ b/tests/script/tsim/parser/join_manyblocks.sim @@ -6,8 +6,8 @@ sql connect $dbPrefix = join_m_db $tbPrefix = join_tb $mtPrefix = join_mt -$tbNum = 3 -$rowNum = 20000 +$tbNum = 20 +$rowNum = 200 $totalNum = $tbNum * $rowNum print =============== join_manyBlocks.sim @@ -78,8 +78,8 @@ print ==============> td-3313 sql select join_mt0.ts,join_mt0.ts,join_mt0.t1 from join_mt0, join_mt1 where join_mt0.ts=join_mt1.ts and join_mt0.t1=join_mt1.t1; print $row -if $row != 60000 then - print expect 60000, actual: $row +if $row != 4000 then + print expect 4000, actual: $row return -1 endi diff --git a/tests/script/tsim/parser/last_cache.sim b/tests/script/tsim/parser/last_cache.sim index 9a41a9f5aa6de119eddfc7cf31eeddccacd1fe5e..3f1a29d928eed421ee23aab79444495ecbeed6f2 100644 --- a/tests/script/tsim/parser/last_cache.sim +++ b/tests/script/tsim/parser/last_cache.sim @@ -54,6 +54,7 @@ sql insert into tbd values ("2021-05-11 10:12:29",NULL,NULL,NULL,NULL ) run tsim/parser/last_cache_query.sim +sql flush database $db system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s start diff --git a/tests/script/tsim/parser/limit1.sim b/tests/script/tsim/parser/limit1.sim index c35617fc4fc64cedbe667a4153bac1a9064f4a91..bae5eba7a4395099ad50105b6259cc69a7b5947e 100644 --- a/tests/script/tsim/parser/limit1.sim +++ b/tests/script/tsim/parser/limit1.sim @@ -7,7 +7,7 @@ $dbPrefix = lm1_db $tbPrefix = lm1_tb $stbPrefix = lm1_stb $tbNum = 10 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum $ts0 = 1537146000000 $delta = 600000 @@ -55,6 +55,7 @@ print ====== tables created run tsim/parser/limit1_tb.sim run tsim/parser/limit1_stb.sim +sql flush database $db print ================== restart server to commit data into disk system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s start diff --git a/tests/script/tsim/parser/limit1_stb.sim b/tests/script/tsim/parser/limit1_stb.sim index be0963c0fdf3b15750512715b8fa752184436df6..731a218de5d11f11b623a8348344597fb84f78b8 100644 --- a/tests/script/tsim/parser/limit1_stb.sim +++ b/tests/script/tsim/parser/limit1_stb.sim @@ -4,7 +4,7 @@ $dbPrefix = lm1_db $tbPrefix = lm1_tb $stbPrefix = lm1_stb $tbNum = 10 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum $ts0 = 1537146000000 $delta = 600000 @@ -453,13 +453,14 @@ endi ### [TBASE-361] $offset = $rowNum / 2 $offset = $offset + 1 +print === select _wstart, max(c1), min(c2), avg(c3), count(c4), sum(c5), spread(c6), first(c7), last(c8), first(c9) from $stb where ts >= $ts0 and ts <= $tsu and t1 > 1 and t1 < 8 interval(5m) limit $offset offset $offset sql select _wstart, max(c1), min(c2), avg(c3), count(c4), sum(c5), spread(c6), first(c7), last(c8), first(c9) from $stb where ts >= $ts0 and ts <= $tsu and t1 > 1 and t1 < 8 interval(5m) limit $offset offset $offset $val = $rowNum - $offset if $rows != $val then print expect $val, actual:$rows return -1 endi -if $data00 != @18-10-22 02:30:00.000@ then +if $data00 != @18-09-20 20:30:00.000@ then return -1 endi if $data01 != 1 then @@ -483,6 +484,7 @@ if $rows != 2 then return -1 endi +print === select max(c1), min(c2), avg(c3), sum(c5), spread(c6), first(c7), last(c8), first(c9) from $stb where ts >= $ts0 and ts <= $tsu and t1 > 1 and t1 < 5 and c1 > 0 and c2 < 9 and c3 > 1 and c4 < 7 and c5 > 4 partition by t1 interval(5m) limit 1 offset 0 sql select max(c1), min(c2), avg(c3), sum(c5), spread(c6), first(c7), last(c8), first(c9) from $stb where ts >= $ts0 and ts <= $tsu and t1 > 1 and t1 < 5 and c1 > 0 and c2 < 9 and c3 > 1 and c4 < 7 and c5 > 4 partition by t1 interval(5m) limit 1 offset 0 if $rows != 3 then return -1 diff --git a/tests/script/tsim/parser/limit1_tb.sim b/tests/script/tsim/parser/limit1_tb.sim index 0ba82654187ab773dd0d84d488e3e1b2e5f50381..e6407e3024e4747f591570689e2ce77c031158df 100644 --- a/tests/script/tsim/parser/limit1_tb.sim +++ b/tests/script/tsim/parser/limit1_tb.sim @@ -4,7 +4,7 @@ $dbPrefix = lm1_db $tbPrefix = lm1_tb $stbPrefix = lm1_stb $tbNum = 10 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum $ts0 = 1537146000000 $delta = 600000 @@ -13,7 +13,7 @@ $i = 0 $db = $dbPrefix . $i $stb = $stbPrefix . $i -print ====== use db +print ====== use $db sql use $db ##### select from table @@ -664,9 +664,9 @@ endi if $data21 != 4.027681991 then return -1 endi - +print select _wstart, count(c1), count(c2), count(c3), count(c4), count(c5), count(c6) from $tb where ts >= $ts0 and ts <= $tsu interval(27m) sql select _wstart, count(c1), count(c2), count(c3), count(c4), count(c5), count(c6) from $tb where ts >= $ts0 and ts <= $tsu interval(27m) -if $rows != 3704 then +if $rows != 371 then return -1 endi if $data01 != 2 then @@ -994,11 +994,14 @@ endi $offset = $rowNum / 10 $offset = $offset * 3 $offset = $offset - 1 + +print === select * from $tb where c1 < 5 and c1 > 1 order by ts asc limit 3 offset $offset sql select * from $tb where c1 < 5 and c1 > 1 order by ts asc limit 3 offset $offset if $rows != 1 then return -1 endi -if $data00 != @18-11-25 18:40:00.000@ then +print $data00 +if $data00 != @18-09-24 06:40:00.000@ then return -1 endi if $data01 != 4 then @@ -1012,19 +1015,19 @@ sql select * from $tb order by ts desc limit 5 if $rows != 5 then return -1 endi -if $data00 != @18-11-25 19:30:00.000@ then +if $data00 != @18-09-24 07:30:00.000@ then return -1 endi if $data01 != 9 then return -1 endi -if $data10 != @18-11-25 19:20:00.000@ then +if $data10 != @18-09-24 07:20:00.000@ then return -1 endi if $data12 != 8 then return -1 endi -if $data20 != @18-11-25 19:10:00.000@ then +if $data20 != @18-09-24 07:10:00.000@ then return -1 endi if $data23 != 7.00000 then @@ -1048,7 +1051,7 @@ endi if $data39 != nchar6 then return -1 endi -if $data40 != @18-11-25 18:50:00.000@ then +if $data40 != @18-09-24 06:50:00.000@ then return -1 endi @@ -1056,19 +1059,19 @@ sql select * from $tb order by ts desc limit 5 offset 1 if $rows != 5 then return -1 endi -if $data00 != @18-11-25 19:20:00.000@ then +if $data00 != @18-09-24 07:20:00.000@ then return -1 endi if $data01 != 8 then return -1 endi -if $data10 != @18-11-25 19:10:00.000@ then +if $data10 != @18-09-24 07:10:00.000@ then return -1 endi if $data12 != 7 then return -1 endi -if $data20 != @18-11-25 19:00:00.000@ then +if $data20 != @18-09-24 07:00:00.000@ then return -1 endi if $data23 != 6.00000 then @@ -1092,12 +1095,13 @@ endi if $data39 != nchar5 then return -1 endi -if $data40 != @18-11-25 18:40:00.000@ then +if $data40 != @18-09-24 06:40:00.000@ then return -1 endi $offset = $rowNum $offset = $offset - 2 +print ==== select * from $tb order by ts desc limit 5 offset $offset sql select * from $tb order by ts desc limit 5 offset $offset if $rows != 2 then return -1 @@ -1119,16 +1123,16 @@ sql select * from $tb where c1 < 8 order by ts desc limit 3 offset 2 if $rows != 3 then return -1 endi -if $data00 != @18-11-25 18:50:00.000@ then +if $data00 != @18-09-24 06:50:00.000@ then return -1 endi if $data01 != 5 then return -1 endi -if $data10 != @18-11-25 18:40:00.000@ then +if $data10 != @18-09-24 06:40:00.000@ then return -1 endi -if $data20 != @18-11-25 18:30:00.000@ then +if $data20 != @18-09-24 06:30:00.000@ then return -1 endi if $data12 != 4 then diff --git a/tests/script/tsim/parser/nestquery.sim b/tests/script/tsim/parser/nestquery.sim index 2a363de43df0f774cbbd6b163c3bfd550f10ea1d..c2189d0bddbe91d001ccca378214935df317f2a8 100644 --- a/tests/script/tsim/parser/nestquery.sim +++ b/tests/script/tsim/parser/nestquery.sim @@ -8,7 +8,7 @@ print ======================== dnode1 start $dbPrefix = nest_db $tbPrefix = nest_tb $mtPrefix = nest_mt -$tbNum = 10 +$tbNum = 3 $rowNum = 10000 $totalNum = $tbNum * $rowNum @@ -23,7 +23,7 @@ sql create database if not exists $db sql use $db sql create table $mt (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c5 tinyint, c6 double, c7 bool, c8 binary(10), c9 nchar(9)) TAGS(t1 int) -$half = $tbNum / 2 +$half = 2 $i = 0 while $i < $half @@ -69,7 +69,7 @@ sql select count(*) from (select count(*) from nest_mt0 group by tbname) if $rows != 1 then return -1 endi -if $data00 != 10 then +if $data00 != 4 then return -1 endi @@ -77,7 +77,7 @@ sql select count(*) from (select count(*) from nest_mt0 partition by tbname inte if $rows != 1 then return -1 endi -if $data00 != 170 then +if $data00 != 68 then return -1 endi @@ -85,7 +85,7 @@ sql select sum(a) from (select count(*) a from nest_mt0 partition by tbname inte if $rows != 1 then return -1 endi -if $data00 != 100000 then +if $data00 != 40000 then return -1 endi diff --git a/tests/script/tsim/parser/projection_limit_offset.sim b/tests/script/tsim/parser/projection_limit_offset.sim index 669ff3a179c67bce6970868b1fac1bbefccc9d0f..2d99b0a296621ca0b29f908dba8714afde47076c 100644 --- a/tests/script/tsim/parser/projection_limit_offset.sim +++ b/tests/script/tsim/parser/projection_limit_offset.sim @@ -7,7 +7,7 @@ $dbPrefix = group_db $tbPrefix = group_tb $mtPrefix = group_mt $tbNum = 8 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum print =============== projection_limit_offset.sim @@ -81,199 +81,199 @@ $ts2 = $tb2 . .ts sql select ts from group_mt0 print $rows -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' limit 8000 offset 0; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' limit 8000 offset 0; if $rows != 4008 then print expect 4008, actual:$rows return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' limit 8000 offset 1; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' limit 8000 offset 1; if $rows != 4007 then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' limit 8000 offset 101; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' limit 8000 offset 101; print $rows if $rows != 3907 then return -1 endi -if $data00 != @70-01-01 08:01:43.101@ then +if $data00 != @70-01-01 08:01:40.101@ then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' limit 8000 offset 902; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' limit 8000 offset 902; if $rows != 3106 then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' limit 8000 offset 400; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' limit 8000 offset 400; if $rows != 3608 then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' limit 8000 offset 4007; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' limit 8000 offset 4007; if $rows != 1 then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' limit 2000 offset 4008; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' limit 2000 offset 4008; if $rows != 0 then return -1 endi #==================================order by desc, multi vnode, limit/offset=================================== -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' order by ts desc limit 8000 offset 0; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' order by ts desc limit 8000 offset 0; if $rows != 4008 then return -1 endi -if $data00 != @70-01-01 08:01:43.500@ then +if $data00 != @70-01-01 08:01:40.500@ then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' order by ts desc limit 8000 offset 1; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' order by ts desc limit 8000 offset 1; if $rows != 4007 then return -1 endi -if $data00 != @70-01-01 08:01:43.500@ then +if $data00 != @70-01-01 08:01:40.500@ then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' order by ts desc limit 8000 offset 101; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' order by ts desc limit 8000 offset 101; print $rows if $rows != 3907 then return -1 endi -if $data00 != @70-01-01 08:01:43.488@ then +if $data00 != @70-01-01 08:01:40.488@ then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' order by ts desc limit 8000 offset 902; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' order by ts desc limit 8000 offset 902; if $rows != 3106 then return -1 endi -if $data00 != @70-01-01 08:01:43.388@ then +if $data00 != @70-01-01 08:01:40.388@ then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' order by ts desc limit 8000 offset 400; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' order by ts desc limit 8000 offset 400; if $rows != 3608 then return -1 endi -if $data00 != @70-01-01 08:01:43.450@ then +if $data00 != @70-01-01 08:01:40.450@ then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' order by ts desc limit 8000 offset 4007; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' order by ts desc limit 8000 offset 4007; if $rows != 1 then return -1 endi -if $data00 != @70-01-01 08:01:43.000@ then +if $data00 != @70-01-01 08:01:40.000@ then return -1 endi -sql select ts from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.500' order by ts desc limit 2000 offset 4008; +sql select ts from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.500' order by ts desc limit 2000 offset 4008; if $rows != 0 then return -1 endi #=================================single value filter====================================== -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts asc limit 10 offset 0; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts asc limit 10 offset 0; if $row != 8 then return -1 endi -if $data00 != @70-01-01 08:01:43.000@ then +if $data00 != @70-01-01 08:01:40.000@ then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts asc limit 10 offset 1; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts asc limit 10 offset 1; if $row != 7 then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts asc limit 10 offset 2; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts asc limit 10 offset 2; if $row != 6 then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts asc limit 10 offset 4; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts asc limit 10 offset 4; if $row != 4 then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts asc limit 10 offset 7; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts asc limit 10 offset 7; if $row != 1 then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts asc limit 10 offset 8; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts asc limit 10 offset 8; if $row != 0 then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts asc limit 10 offset 9; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts asc limit 10 offset 9; if $row != 0 then return -1 endi #===============================single value filter, order by desc============================ -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts desc limit 10 offset 0; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts desc limit 10 offset 0; if $row != 8 then return -1 endi -if $data00 != @70-01-01 08:01:43.000@ then +if $data00 != @70-01-01 08:01:40.000@ then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts desc limit 10 offset 1; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts desc limit 10 offset 1; if $row != 7 then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts desc limit 10 offset 2; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts desc limit 10 offset 2; if $row != 6 then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts desc limit 10 offset 4; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts desc limit 10 offset 4; if $row != 4 then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts desc limit 10 offset 7; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts desc limit 10 offset 7; if $row != 1 then return -1 endi -if $data00 != @70-01-01 08:01:43.000@ then +if $data00 != @70-01-01 08:01:40.000@ then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts desc limit 10 offset 8; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts desc limit 10 offset 8; if $row != 0 then return -1 endi -sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:43' and ts<='1970-1-1 8:1:43.00' order by ts desc limit 10 offset 9; +sql select ts,tbname from group_mt0 where ts>='1970-1-1 8:1:40' and ts<='1970-1-1 8:1:40.00' order by ts desc limit 10 offset 9; if $row != 0 then return -1 endi #[tbase-695] -sql select ts,tbname from group_mt0 where ts>='1970-01-01 8:1:40' and ts<'1970-1-1 8:1:45' and c1<99999999 limit 100000 offset 5000 +sql select ts,tbname from group_mt0 where ts>='1970-01-01 8:1:40' and ts<'1970-1-1 8:1:40.500' and c1<99999999 limit 10000 offset 500 print ===> $data00 $data01 $data02 $data03 $data04 $data05 $data06 $data07 $data08 $data09 print ===> $data10 $data11 $data12 $data13 $data14 $data15 $data16 $data17 $data18 $data19 print ===> $data20 $data21 $data22 $data23 $data24 $data25 $data26 $data27 $data28 $data29 print ===> $data30 $data31 $data32 $data33 $data34 $data35 $data36 $data37 $data38 $data39 -if $row != 35000 then +if $row != 3500 then return -1 endi @@ -301,7 +301,7 @@ print tbase-722 sql select spread(ts) from group_tb0; print $data00 -if $data00 != 9999.000000000 then +if $data00 != 999.000000000 then return -1 endi diff --git a/tests/script/tsim/parser/selectResNum.sim b/tests/script/tsim/parser/selectResNum.sim index 43365b2af2c8fe52a3ce3e36d057ba9dcdc25a5d..11310782402b8e98fadcbaa9bf740c806c52443a 100644 --- a/tests/script/tsim/parser/selectResNum.sim +++ b/tests/script/tsim/parser/selectResNum.sim @@ -7,10 +7,10 @@ $dbPrefix = sc_db $tbPrefix = sc_tb $stbPrefix = sc_stb $tbNum = 10 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum $loops = 200000 -$log = 10000 +$log = 1000 $ts0 = 1537146000000 $delta = 600000 print ========== selectResNum.sim diff --git a/tests/script/tsim/parser/sliding.sim b/tests/script/tsim/parser/sliding.sim index b9353e2c61b5d84d74486d1cc458103a7bf4e851..1cb4cb5340f993ee25b4f73e8b076375ea28a445 100644 --- a/tests/script/tsim/parser/sliding.sim +++ b/tests/script/tsim/parser/sliding.sim @@ -7,7 +7,7 @@ $dbPrefix = sliding_db $tbPrefix = sliding_tb $mtPrefix = sliding_mt $tbNum = 8 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum print =============== sliding.sim @@ -49,9 +49,23 @@ while $i < $tbNum $nchar = $nchar . $c $nchar = $nchar . ' - sql insert into $tb values ($tstart , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) - $tstart = $tstart + 30 - $x = $x + 1 + $next = $tstart + 30 + $f = $x + 1 + $c1 = $f / 100 + $c1 = $c1 * 100 + $c1 = $f - $c1 + + $binary1 = ' . binary + $binary1 = $binary1 . $c1 + $binary1 = $binary1 . ' + + $nchar1 = ' . nchar + $nchar1 = $nchar1 . $c1 + $nchar1 = $nchar1 . ' + + sql insert into $tb values ($tstart , $c , $c , $c , $c , $c , $c , $c , $binary , $nchar ) ($next , $c1 , $c1 , $c1 , $c1 , $c1 , $c1 , $c1 , $binary1 , $nchar1 ) + $tstart = $tstart + 60 + $x = $x + 2 endw $i = $i + 1 @@ -74,25 +88,25 @@ $ts1 = $tb1 . .ts $ts2 = $tb2 . .ts print ===============================interval_sliding query -sql select _wstart, count(*) from sliding_tb0 interval(30s) sliding(30s); +sql select _wstart, count(*) from sliding_tb0 interval(3s) sliding(3s); if $row != 10 then return -1 endi if $data00 != @00-01-01 00:00:00.000@ then return -1 endi -if $data01 != 1000 then +if $data01 != 100 then return -1 endi -if $data10 != @00-01-01 00:00:30.000@ then +if $data10 != @00-01-01 00:00:03.000@ then return -1 endi -if $data11 != 1000 then +if $data11 != 100 then return -1 endi sql select _wstart, stddev(c1) from sliding_tb0 interval(10a) sliding(10a); -if $row != 10000 then +if $row != 1000 then return -1 endi if $data00 != @00-01-01 00:00:00.000@ then @@ -109,10 +123,10 @@ if $data91 != 0.000000000 then endi sql select _wstart, stddev(c1),count(c2),first(c3),last(c4) from sliding_tb0 interval(10a) sliding(10a) order by _wstart desc; -if $row != 10000 then +if $row != 1000 then return -1 endi -if $data00 != @00-01-01 00:04:59.970@ then +if $data00 != @00-01-01 00:00:29.970@ then return -1 endi if $data01 != 0.000000000 then @@ -127,7 +141,7 @@ endi if $data04 != 99 then return -1 endi -if $data90 != @00-01-01 00:04:59.700@ then +if $data90 != @00-01-01 00:00:29.700@ then return -1 endi if $data91 != 0.000000000 then @@ -143,41 +157,41 @@ if $data94 != 90 then return -1 endi -sql select _wstart, count(c2),last(c4) from sliding_tb0 interval(30s) sliding(10s) order by _wstart asc; +sql select _wstart, count(c2),last(c4) from sliding_tb0 interval(3s) sliding(1s) order by _wstart asc; if $row != 32 then return -1 endi -if $data00 != @99-12-31 23:59:40.000@ then - print expect 12-31 23:59:40.000, actual: $data00 +if $data00 != @99-12-31 23:59:58.000@ then + print expect 12-31 23:59:58.000, actual: $data00 return -1 endi -if $data01 != 334 then +if $data01 != 34 then return -1 endi if $data02 != 33 then return -1 endi -sql select _wstart, count(c2),stddev(c3),first(c4),last(c4) from sliding_tb0 where ts>'2000-01-01 0:0:0' and ts<'2000-1-1 0:0:31' interval(30s) sliding(30s) order by _wstart asc; +sql select _wstart, count(c2),stddev(c3),first(c4),last(c4) from sliding_tb0 where ts>'2000-01-01 0:0:0' and ts<'2000-1-1 0:0:4' interval(3s) sliding(3s) order by _wstart asc; if $row != 2 then return -1 endi if $data04 != 99 then return -1 endi -if $data01 != 999 then +if $data01 != 99 then return -1 endi -if $data02 != 28.837977152 then +if $data02 != 28.577380332 then return -1 endi #interval offset + limit -sql select _wstart, count(c2), first(c3),stddev(c4) from sliding_tb0 interval(10a) sliding(10a) order by _wstart desc limit 10 offset 990; +sql select _wstart, count(c2), first(c3),stddev(c4) from sliding_tb0 interval(10a) sliding(10a) order by _wstart desc limit 10 offset 90; if $row != 10 then return -1 endi -if $data00 != @00-01-01 00:04:30.270@ then +if $data00 != @00-01-01 00:00:27.270@ then return -1 endi if $data01 != 1 then @@ -189,7 +203,7 @@ endi if $data03 != 0.000000000 then return -1 endi -if $data90 != @00-01-01 00:04:30.000@ then +if $data90 != @00-01-01 00:00:27.000@ then return -1 endi if $data91 != 1 then @@ -203,43 +217,43 @@ if $data93 != 0.000000000 then endi #interval offset test -sql select _wstart, count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(30s) order by _wstart asc limit 1000 offset 1; +sql select _wstart, count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(3s) order by _wstart asc limit 100 offset 1; if $row != 9 then return -1 endi -if $data00 != @00-01-01 00:00:30.000@ then +if $data00 != @00-01-01 00:00:03.000@ then return -1 endi -if $data01 != 1000 then +if $data01 != 100 then return -1 endi if $data02 != 99 then return -1 endi -if $data80 != @00-01-01 00:04:30.000@ then +if $data80 != @00-01-01 00:00:27.000@ then return -1 endi -if $data81 != 1000 then +if $data81 != 100 then return -1 endi -sql select _wstart, count(c2),last(c4),stddev(c3) from sliding_tb0 where ts>'2000-1-1 0:0:0' and ts<'2000-1-1 0:0:31' interval(30s) sliding(30s) order by _wstart asc limit 1000 offset 0; +sql select _wstart, count(c2),last(c4),stddev(c3) from sliding_tb0 where ts>'2000-1-1 0:0:0' and ts<'2000-1-1 0:0:4' interval(3s) sliding(3s) order by _wstart asc limit 100 offset 0; if $row != 2 then return -1 endi if $data00 != @00-01-01 00:00:00.000@ then return -1 endi -if $data01 != 999 then +if $data01 != 99 then return -1 endi if $data02 != 99 then return -1 endi -if $data03 != 28.837977152 then +if $data03 != 28.577380332 then return -1 endi -if $data10 != @00-01-01 00:00:30.000@ then +if $data10 != @00-01-01 00:00:03.000@ then return -1 endi if $data11 != 34 then @@ -252,14 +266,14 @@ if $data13 != 9.810708435 then return -1 endi -sql select _wstart, count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 1; +sql select _wstart, count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 1; if $row != 15 then return -1 endi if $data00 != @00-01-01 00:00:00.000@ then return -1 endi -if $data01 != 1000 then +if $data01 != 100 then return -1 endi if $data02 != 99 then @@ -268,85 +282,85 @@ endi if $data03 != 28.866070048 then return -1 endi -if $data90 != @00-01-01 00:03:00.000@ then +if $data90 != @00-01-01 00:00:18.000@ then return -1 endi -if $data91 != 1000 then +if $data91 != 100 then return -1 endi if $data92 != 99 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 5; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 5; if $row != 11 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 6; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 6; if $row != 10 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 7; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 7; if $row != 9 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 8; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 8; if $row != 8 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 9; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 9; if $row != 7 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 10; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 10; if $row != 6 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 11; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 11; if $row != 5 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 12; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 12; if $row != 4 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 13; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 13; if $row != 3 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 14; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 14; if $row != 2 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 15; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 15; if $row != 1 then return -1 endi -sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(30s) sliding(20s) order by _wstart asc limit 100 offset 16; +sql select count(c2),last(c4),stddev(c3) from sliding_tb0 interval(3s) sliding(2s) order by _wstart asc limit 100 offset 16; if $row != 0 then return -1 endi -sql select _wstart, count(c2),last(c4),stddev(c3),spread(c3) from sliding_tb0 where c2 = 0 interval(30s) order by _wstart desc; +sql select _wstart, count(c2),last(c4),stddev(c3),spread(c3) from sliding_tb0 where c2 = 0 interval(3s) order by _wstart desc; if $row != 10 then return -1 endi -#00-01-01 00:04:30.000| 10| 0| 0.000000000| 0.000000000| -if $data00 != @00-01-01 00:04:30.000@ then +#00-01-01 00:00:27.000 | 1 | 0 | 0.000000000 | 0.000000000 | +if $data00 != @00-01-01 00:00:27.000@ then return -1 endi -if $data01 != 10 then +if $data01 != 1 then return -1 endi if $data02 != 0 then @@ -356,18 +370,18 @@ if $data03 != 0.000000000 then return -1 endi -sql select count(c2),last(c4),stddev(c3),spread(c3) from sliding_tb0 where c2 = 0 interval(30s) sliding(20s) order by _wstart desc limit 1 offset 15; +sql select count(c2),last(c4),stddev(c3),spread(c3) from sliding_tb0 where c2 = 0 interval(3s) sliding(2s) order by _wstart desc limit 1 offset 14; if $row != 1 then return -1 endi -sql select count(c2),last(c4),stddev(c3),spread(c3) from sliding_tb0 where c2 = 0 interval(30s) sliding(20s) order by _wstart desc limit 1 offset 16; +sql select count(c2),last(c4),stddev(c3),spread(c3) from sliding_tb0 where c2 = 0 interval(3s) sliding(2s) order by _wstart desc limit 1 offset 15; if $row != 0 then return -1 endi sql select _wstart, count(c2), first(c3),stddev(c4) from sliding_tb0 interval(10a) order by _wstart desc limit 10 offset 2; -if $data00 != @00-01-01 00:04:59.910@ then +if $data00 != @00-01-01 00:00:29.910@ then return -1 endi diff --git a/tests/script/tsim/parser/slimit1_query.sim b/tests/script/tsim/parser/slimit1_query.sim index 9a27d5523b04c3466e2a6223dd10695f05e9662a..1167fe0b3dba3d25349fdd2401ece10f0ea09afa 100644 --- a/tests/script/tsim/parser/slimit1_query.sim +++ b/tests/script/tsim/parser/slimit1_query.sim @@ -70,7 +70,7 @@ endi ### empty result set sql select count(*) from stb partition by t2,t1 order by t2 asc slimit 0 soffset 0 -if $rows != 9 then +if $rows != 0 then return -1 endi diff --git a/tests/script/tsim/parser/slimit_limit.sim b/tests/script/tsim/parser/slimit_limit.sim new file mode 100644 index 0000000000000000000000000000000000000000..546ef576871b00c14e7a90d7244c2a4f40dc70c7 --- /dev/null +++ b/tests/script/tsim/parser/slimit_limit.sim @@ -0,0 +1,113 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +sql drop database if exists db1; +sql create database db1 vgroups 1; +sql use db1; +sql create stable sta (ts timestamp, f1 int, f2 binary(200)) tags(t1 int, t2 int, t3 int); +sql create table tba1 using sta tags(1, 1, 1); +sql create table tba2 using sta tags(2, 2, 2); +sql create table tba3 using sta tags(3, 3, 3); +sql create table tba4 using sta tags(4, 4, 4); +sql create table tba5 using sta tags(5, 5, 5); +sql create table tba6 using sta tags(6, 6, 6); +sql create table tba7 using sta tags(7, 7, 7); +sql create table tba8 using sta tags(8, 8, 8); +sql create index index1 on sta (t2); +sql insert into tba1 values ('2022-04-26 15:15:01', 1, "a"); +sql insert into tba1 values ('2022-04-26 15:15:02', 11, "a"); +sql insert into tba2 values ('2022-04-26 15:15:01', 2, "a"); +sql insert into tba2 values ('2022-04-26 15:15:02', 22, "a"); +sql insert into tba3 values ('2022-04-26 15:15:01', 3, "a"); +sql insert into tba4 values ('2022-04-26 15:15:01', 4, "a"); +sql insert into tba5 values ('2022-04-26 15:15:01', 5, "a"); +sql insert into tba6 values ('2022-04-26 15:15:01', 6, "a"); +sql insert into tba7 values ('2022-04-26 15:15:01', 7, "a"); +sql insert into tba8 values ('2022-04-26 15:15:01', 8, "a"); + +sql select t1,count(*) from sta group by t1 limit 1; +if $rows != 8 then + return -1 +endi +sql select t1,count(*) from sta group by t1 slimit 1; +if $rows != 1 then + return -1 +endi +sql select f1,count(*) from sta group by f1 limit 1; +if $rows != 10 then + return -1 +endi +sql select f1,count(*) from sta group by f1 slimit 1; +if $rows != 1 then + return -1 +endi +sql select t1,f1,count(*) from sta group by t1, f1 limit 1; +if $rows != 10 then + return -1 +endi +sql select t1,f1,count(*) from sta group by t1, f1 slimit 1; +if $rows != 1 then + return -1 +endi +sql select t1,f1,count(*) from sta group by f1, t1 limit 1; +if $rows != 10 then + return -1 +endi +sql select t1,f1,count(*) from sta group by f1, t1 slimit 1; +if $rows != 1 then + return -1 +endi + +sql select t1,count(*) from sta group by t1 order by t1 limit 1; +if $rows != 1 then + return -1 +endi +sql select t1,count(*) from sta group by t1 order by t1 slimit 1; +if $rows != 8 then + return -1 +endi +sql select f1,count(*) from sta group by f1 order by f1 limit 1; +if $rows != 1 then + return -1 +endi +sql select f1,count(*) from sta group by f1 order by f1 slimit 1; +if $rows != 10 then + return -1 +endi +sql select t1,f1,count(*) from sta group by t1, f1 order by t1,f1 limit 1; +if $rows != 1 then + return -1 +endi +sql select t1,f1,count(*) from sta group by t1, f1 order by t1,f1 slimit 1; +if $rows != 10 then + return -1 +endi +sql select t1,f1,count(*) from sta group by f1, t1 order by f1,t1 limit 1; +if $rows != 1 then + return -1 +endi +sql select t1,f1,count(*) from sta group by f1, t1 order by f1,t1 slimit 1; +if $rows != 10 then + return -1 +endi + +sql select t1,count(*) from sta group by t1 slimit 1 limit 1; +if $rows != 1 then + return -1 +endi +sql select f1,count(*) from sta group by f1 slimit 1 limit 1; +if $rows != 1 then + return -1 +endi +sql select t1,f1,count(*) from sta group by t1, f1 slimit 1 limit 1; +if $rows != 1 then + return -1 +endi +sql select t1,f1,count(*) from sta group by f1, t1 slimit 1 limit 1; +if $rows != 1 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/parser/table_merge_limit.sim b/tests/script/tsim/parser/table_merge_limit.sim new file mode 100644 index 0000000000000000000000000000000000000000..7d67b6d3a270c8587c85123963b564c82ea18762 --- /dev/null +++ b/tests/script/tsim/parser/table_merge_limit.sim @@ -0,0 +1,47 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +$dbPrefix = m_fl_db +$tbPrefix = m_fl_tb +$mtPrefix = m_fl_mt +$tbNum = 2 +$rowNum = 513 +$totalNum = $tbNum * $rowNum +$ts0 = 1537146000000 +$delta = 600000 +print ========== fill.sim +$i = 0 +$db = $dbPrefix . $i +$mt = $mtPrefix . $i + +sql drop database $db -x step1 +step1: +sql create database $db vgroups 1 +sql use $db +sql create table $mt (ts timestamp, c1 int) tags(tgcol int) + +$i = 0 +$ts = $ts0 +while $i < $tbNum + $tb = $tbPrefix . $i + sql create table $tb using $mt tags( $i ) + + $x = 0 + while $x < $rowNum + $xs = $x * $delta + $ts = $ts0 + $xs + sql insert into $tb values ( $ts , $x ) + $x = $x + 1 + endw + + $i = $i + 1 +endw + +sql select * from $mt order by ts limit 10 +if $rows != 10 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/parser/union.sim b/tests/script/tsim/parser/union.sim index 9e7c6f77cc90f9612e9d258880322c218892c828..dee5da96e8488a14cc615d7ab3944ccf6558f93e 100644 --- a/tests/script/tsim/parser/union.sim +++ b/tests/script/tsim/parser/union.sim @@ -8,7 +8,7 @@ $tbPrefix = union_tb $tbPrefix1 = union_tb_ $mtPrefix = union_mt $tbNum = 10 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum print =============== union.sim @@ -65,7 +65,7 @@ sql create table $mt1 (ts timestamp, c1 int, c2 float, c3 bigint, c4 smallint, c $j = 0 $t = 1578203484000 -$rowNum = 1000 +$rowNum = 100 $tbNum = 5 $i = 0 @@ -117,7 +117,7 @@ sql_error (select c1 from union_tb0 limit 1 union all select c1 from union_tb1 l # sql with parenthese sql (select c1 from union_tb0) -if $rows != 10000 then +if $rows != 1000 then return -1 endi if $data00 != 0 then @@ -187,7 +187,7 @@ endi if $data10 != 1 then return -1 endi -if $data20 != 4950000 then +if $data20 != 495000 then return -1 endi @@ -202,7 +202,7 @@ endi if $data10 != 1 then return -1 endi -if $data20 != 495000 then +if $data20 != 49500 then return -1 endi @@ -211,7 +211,7 @@ sql (select count(*) as c from union_tb0, union_tb1 where union_tb0.ts=union_tb1 if $rows != 11 then return -1 endi -if $data00 != 10000 then +if $data00 != 1000 then return -1 endi if $data10 != 9 then @@ -227,7 +227,7 @@ endi print ===========================================tags union # two super table tag union, limit is not active during retrieve tags query sql (select t1 from union_mt0) union all (select t1 from union_mt0) -if $rows != 200000 then +if $rows != 20000 then return -1 endi @@ -248,7 +248,7 @@ sql (select count(*) as c from union_tb0 where ts > now + 3650d) union all (sele if $rows != 2 then return -1 endi -#if $data00 != 495000 then +#if $data00 != 49500 then # return -1 #endi @@ -272,7 +272,7 @@ endi # multi-vnode projection query sql (select c1 from union_mt0) union all select c1 from union_mt0; -if $rows != 200000 then +if $rows != 20000 then return -1 endi @@ -330,10 +330,10 @@ sql (select sum(c1) as a from union_tb0 limit 1) union all (select sum(c3) as a if $rows != 2 then return -1 endi -if $data00 != 495000 then +if $data00 != 49500 then return -1 endi -if $data10 != 495000 then +if $data10 != 49500 then return -1 endi diff --git a/tests/script/tsim/parser/where.sim b/tests/script/tsim/parser/where.sim index c1660883b6189a74c38b59b95c4c4fc1fcad8a90..8ab47dacafe9ae39f49db82d045574b2a3448884 100644 --- a/tests/script/tsim/parser/where.sim +++ b/tests/script/tsim/parser/where.sim @@ -7,7 +7,7 @@ $dbPrefix = wh_db $tbPrefix = wh_tb $mtPrefix = wh_mt $tbNum = 10 -$rowNum = 10000 +$rowNum = 1000 $totalNum = $tbNum * $rowNum print =============== where.sim @@ -62,7 +62,7 @@ sql select count(*) from $tb where c1<10 and c1<>2 if $rows != 1 then return -1 endi -if $data00 != 900 then +if $data00 != 90 then return -1 endi @@ -308,9 +308,9 @@ if $row != 0 then endi sql select * from wh_mt0 where c3 = 1; -print $rows -> 1000 +print $rows -> 100 print $data00 $data01 $data02 -if $row != 1000 then +if $row != 100 then return -1 endi diff --git a/tests/script/tsim/query/bug3398.sim b/tests/script/tsim/query/bug3398.sim new file mode 100644 index 0000000000000000000000000000000000000000..3ca88cf4596fcc8e732eb9ef94b3e1cdb8fc45de --- /dev/null +++ b/tests/script/tsim/query/bug3398.sim @@ -0,0 +1,30 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print =============== create database +sql create database test + +print =============== create super table and child table +sql use test + +sql CREATE STABLE st (day timestamp, c2 int) TAGS (vin binary(32)) + +sql insert into test.g using st TAGS ("TAG1") values("2023-05-03 00:00:00.000", 1) +sql insert into test.t using st TAGS ("TAG1") values("2023-05-03 00:00:00.000", 1) +sql insert into test.tg using st TAGS ("TAG1") values("2023-05-03 00:00:00.000", 1) + +sql select sum(case when t.c2 is NULL then 0 else 1 end + case when t.c2 is NULL then 0 else 1 end), sum(case when t.c2 is NULL then 0 else 1 end + case when t.c2 is NULL then 0 else 1 end + case when t.c2 is NULL then 0 else 1 end) from test.t t, test.g g, test.tg tg where t.day = g.day and t.day = tg.day and t.day between '2021-05-03' and '2023-05-04' and t.vin = 'TAG1' and t.vin = g.vin and t.vin = tg.vin group by t.day; + +print $rows $data00 $data01 +if $rows != 1 then + return -1 +endi +if $data00 != 2.000000000 then + return -1 +endi + +if $data01 != 3.000000000 then + return -1 +endi diff --git a/tests/script/tsim/query/emptyTsRange.sim b/tests/script/tsim/query/emptyTsRange.sim new file mode 100644 index 0000000000000000000000000000000000000000..ca3daf2bbb8dd089204c8f38088d1c123077da64 --- /dev/null +++ b/tests/script/tsim/query/emptyTsRange.sim @@ -0,0 +1,20 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +sql drop database if exists db1; +sql create database if not exists db1; +sql use db1; +sql create stable sta (ts timestamp, f1 double, f2 binary(200)) tags(t1 int); +sql create table tba1 using sta tags(1); +sql insert into tba1 values ('2022-04-26 15:15:01', 1.0, "a"); +sql insert into tba1 values ('2022-04-26 15:15:02', 2.0, "b"); +sql insert into tba1 values ('2022-04-26 15:15:04', 4.0, "b"); +sql insert into tba1 values ('2022-04-26 15:15:05', 5.0, "b"); +sql select last_row(*) from sta where ts >= 1678901803783 and ts <= 1678901803783 and _c0 <= 1678901803782 interval(10d,8d) fill(linear) order by _wstart desc; +if $rows != 0 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/event.sim b/tests/script/tsim/query/event.sim new file mode 100644 index 0000000000000000000000000000000000000000..16fe0f4a137426a9ef6b9bf0fd0434290584e581 --- /dev/null +++ b/tests/script/tsim/query/event.sim @@ -0,0 +1,239 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print ======== prepare data + +sql drop database if exists db1; +sql create database db1 vgroups 5; +sql use db1; +sql create stable sta (ts timestamp, f1 int, f2 binary(10), f3 bool) tags(t1 int, t2 bool, t3 binary(10)); +sql create table tba1 using sta tags(0, false, '0'); +sql create table tba2 using sta tags(1, true, '1'); +sql insert into tba1 values ('2022-09-26 15:15:01', 0, "a", false); +sql insert into tba1 values ('2022-09-26 15:15:02', 1, "0", true); +sql insert into tba1 values ('2022-09-26 15:15:03', 5, "5", false); +sql insert into tba1 values ('2022-09-26 15:15:04', 3, 'b', false); +sql insert into tba1 values ('2022-09-26 15:15:05', 0, '1', false); +sql insert into tba1 values ('2022-09-26 15:15:06', 2, 'd', true); +sql insert into tba2 values ('2022-09-26 15:15:01', 0, "a", false); +sql insert into tba2 values ('2022-09-26 15:15:02', 1, "0", true); +sql insert into tba2 values ('2022-09-26 15:15:03', 5, "5", false); +sql insert into tba2 values ('2022-09-26 15:15:04', 3, 'b', false); +sql insert into tba2 values ('2022-09-26 15:15:05', 0, '1', false); +sql insert into tba2 values ('2022-09-26 15:15:06', 2, 'd', true); + +# child table: no window +print ====> select count(*) from tba1 event_window start with f1 = 0 end with f2 = 'c'; +sql select count(*) from tba1 event_window start with f1 = 0 end with f2 = 'c'; +if $rows != 0 then + return -1 +endi + +# child table: single row window +print ====> select count(*) from tba1 event_window start with f1 = 0 end with f3 = false; +sql select count(*) from tba1 event_window start with f1 = 0 end with f3 = false; +if $rows != 2 then + return -1 +endi +if $data00 != 1 then + return -1 +endi + +# child table: multi rows window +print ====> select count(*) from tba1 event_window start with f1 = 0 end with f2 = 'b'; +sql select count(*) from tba1 event_window start with f1 = 0 end with f2 = 'b'; +if $rows != 1 then + return -1 +endi +if $data00 != 4 then + return -1 +endi + +# child table: multi windows +print ====> select count(*) from tba1 event_window start with f1 >= 0 end with f3 = true; +sql select count(*) from tba1 event_window start with f1 >= 0 end with f3 = true; +if $rows != 2 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 4 then + return -1 +endi + +# super table: no window +print ====> select count(*) from sta event_window start with f1 = 0 end with f2 = 'c'; +sql select count(*) from sta event_window start with f1 = 0 end with f2 = 'c'; +if $rows != 0 then + return -1 +endi + +# super table: single row window +print ====> select count(*) from sta event_window start with f1 = 0 end with f3 = false; +sql select count(*) from sta event_window start with f1 = 0 end with f3 = false; +if $rows != 4 then + return -1 +endi +if $data00 != 1 then + return -1 +endi + +# super table: multi rows window +print ====> select count(*) from sta event_window start with f1 = 0 end with f2 = 'b'; +sql select count(*) from sta event_window start with f1 = 0 end with f2 = 'b'; +if $rows != 1 then + return -1 +endi +if $data00 != 7 then + return -1 +endi + +# super table: multi windows +print ====> select count(*) from sta event_window start with f1 >= 0 end with f3 = true; +sql select count(*) from sta event_window start with f1 >= 0 end with f3 = true; +if $rows != 4 then + return -1 +endi +if $data00 != 3 then + return -1 +endi +if $data10 != 1 then + return -1 +endi +if $data20 != 7 then + return -1 +endi +if $data30 != 1 then + return -1 +endi + +# multi-child table: no window +print ====> select tbname, count(*) from sta partition by tbname event_window start with f1 = 0 end with f2 = 'c'; +sql select tbname, count(*) from sta partition by tbname event_window start with f1 = 0 end with f2 = 'c'; +if $rows != 0 then + return -1 +endi + +# multi-child table: single row window +print ====> select tbname, count(*) from sta partition by tbname event_window start with f1 = 0 end with f3 = false; +sql select tbname, count(*) from sta partition by tbname event_window start with f1 = 0 end with f3 = false; +if $rows != 4 then + return -1 +endi +if $data01 != 1 then + return -1 +endi + +# multi-child table: multi rows window +print ====> select tbname, count(*) from sta partition by tbname event_window start with f1 = 0 end with f2 = 'b'; +sql select tbname, count(*) from sta partition by tbname event_window start with f1 = 0 end with f2 = 'b'; +if $rows != 2 then + return -1 +endi +if $data01 != 4 then + return -1 +endi +if $data11 != 4 then + return -1 +endi + +# multi-child table: multi windows +print ====> select tbname, count(*) from sta partition by tbname event_window start with f1 >= 0 end with f3 = true; +sql select tbname, count(*) from sta partition by tbname event_window start with f1 >= 0 end with f3 = true; +if $rows != 4 then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data11 != 4 then + return -1 +endi + +# where + partition by +print ====> select tbname, count(*) from sta where f3 = false partition by tbname event_window start with f1 >0 end with f2 > 0; +sql select tbname, count(*) from sta where f3 = false partition by tbname event_window start with f1 >0 end with f2 > 0; +if $rows != 4 then + return -1 +endi +if $data01 != 1 then + return -1 +endi +if $data11 != 2 then + return -1 +endi + +# where + order by +print ====> select count(*) cnt from tba1 where f3 = false event_window start with f1 >0 end with f2 > 0 order by cnt desc; +sql select count(*) cnt from tba1 where f3 = false event_window start with f1 >0 end with f2 > 0 order by cnt desc; +if $rows != 2 then + return -1 +endi +if $data00 != 2 then + return -1 +endi +if $data10 != 1 then + return -1 +endi + +# where + partition by + order by +print ====> select tbname, count(*) cnt from sta where f3 = false partition by tbname event_window start with f1 >0 end with f2 > 0 order by cnt; +sql select tbname, count(*) cnt from sta where f3 = false partition by tbname event_window start with f1 >0 end with f2 > 0 order by cnt; +if $rows != 4 then + return -1 +endi +if $data01 != 1 then + return -1 +endi +if $data11 != 1 then + return -1 +endi + +# where + partition by + order by + limit +print ====> select tbname, count(*) cnt from sta where f3 = false partition by tbname event_window start with f1 >0 end with f2 > 0 order by cnt limit 2 offset 2; +sql select tbname, count(*) cnt from sta where f3 = false partition by tbname event_window start with f1 >0 end with f2 > 0 order by cnt limit 2 offset 2; +if $rows != 2 then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data11 != 2 then + return -1 +endi + +# subquery(where + partition by + order by + limit) +print ====> select * from (select tbname tname, count(*) cnt from sta where f3 = false partition by tbname event_window start with f1 >0 end with f2 > 0 order by cnt limit 2 offset 2); +sql select * from (select tbname tname, count(*) cnt from sta where f3 = false partition by tbname event_window start with f1 >0 end with f2 > 0 order by cnt limit 2 offset 2); +if $rows != 2 then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data11 != 2 then + return -1 +endi + +# subquery + where + partition by + order by + limit +print ====> select tname, count(*) cnt from (select tbname tname, * from sta) where f3 = false partition by tname event_window start with f1 >0 end with f2 > 0 order by cnt limit 2 offset 2; +sql select tname, count(*) cnt from (select tbname tname, * from sta) where f3 = false partition by tname event_window start with f1 >0 end with f2 > 0 order by cnt limit 2 offset 2; +if $rows != 2 then + return -1 +endi +if $data01 != 2 then + return -1 +endi +if $data11 != 2 then + return -1 +endi + +sql_error select f1, f2 from sta event_window start with f1 >0 end with f2 > 0; +sql_error select count(*) from sta event_window start with f1 >0 end with f2 > 0 partition by tbname; +sql_error select count(*) from sta event_window start with f1 >0 end with f2 > 0 group by tbname; +sql_error select count(*) from sta event_window start with f1 >0 end with f2 > 0 fill(NULL); + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/explain.sim b/tests/script/tsim/query/explain.sim index 78d905233b7d59d64f2c17cc5a97b7b84888bfab..2a8f07178804a166fc9e4c0e2163840825bd4459 100644 --- a/tests/script/tsim/query/explain.sim +++ b/tests/script/tsim/query/explain.sim @@ -4,7 +4,7 @@ system sh/exec.sh -n dnode1 -s start sql connect print ======== step1 -sql create database db1 vgroups 3; +sql create database db1 vgroups 3 cachesize 10 cachemodel 'both'; sql use db1; sql select * from information_schema.ins_databases; sql create stable st1 (ts timestamp, f1 int, f2 binary(200)) tags(t1 int); @@ -29,43 +29,71 @@ sql insert into tb4 values (now, 4, "Bitmap Heap Scan on tenk1 t1 (cost=5.07..2 #sql create table tb4 using st2 tags(4); #sql insert into tb4 values (now, 4, "Bitmap Heap Scan on tenk1 t1 (cost=5.07..229.20 rows=101 width=244) (actual time=0.080..0.526 rows=100 loops=1)"); +# for explain insert into select +sql create table t1 (ts timestamp, f1 int, f2 binary(200), t1 int); print ======== step2 sql explain select * from st1 where -2; +sql explain insert into t1 select * from st1 where -2; sql explain select ts from tb1; +sql explain insert into t1(ts) select ts from tb1; sql explain select * from st1; +sql explain insert into t1 select * from st1; sql explain select * from st1 order by ts; +sql explain insert into t1 select * from st1 order by ts; sql explain select * from information_schema.ins_stables; sql explain select count(*),sum(f1) from tb1; sql explain select count(*),sum(f1) from st1; sql explain select count(*),sum(f1) from st1 group by f1; #sql explain select count(f1) from tb1 interval(10s, 2s) sliding(3s) fill(prev); +sql explain insert into t1(ts, t1) select _wstart, count(*) from st1 interval(10s); print ======== step3 sql explain verbose true select * from st1 where -2; +sql explain verbose true insert into t1 select * from st1 where -2; sql explain verbose true select ts from tb1 where f1 > 0; +sql explain verbose true insert into t1(ts) select ts from tb1 where f1 > 0; sql explain verbose true select * from st1 where f1 > 0 and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00'; +sql explain verbose true insert into t1 select * from st1 where f1 > 0 and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00'; sql explain verbose true select count(*) from st1 partition by tbname slimit 1 soffset 2 limit 2 offset 1; sql explain verbose true select * from information_schema.ins_stables where db_name='db2'; sql explain verbose true select st1.f1 from st1 join st2 on st1.ts=st2.ts and st1.f1 > 0; +sql explain verbose true insert into t1(ts) select st1.f1 from st1 join st2 on st1.ts=st2.ts and st1.f1 > 0; +sql explain verbose true insert into t1(ts, t1) select _wstart, count(*) from st1 interval(10s); +sql explain verbose true select distinct tbname, table_name from information_schema.ins_tables; +sql explain verbose true select diff(f1) as f11 from tb1 order by f11; +sql explain verbose true select count(*) from st1 where ts > now - 3m and ts < now interval(10s) fill(linear); +sql explain verbose true select count(*) from st1 partition by tbname; +sql explain verbose true select count(*) from information_schema.ins_tables group by stable_name; +sql explain verbose true select last(*) from st1; +sql explain verbose true select last_row(*) from st1; +sql explain verbose true select interp(f1) from tb1 where ts > now - 3m and ts < now range(now-3m,now) every(1m) fill(prev); +sql explain verbose true select _wstart, _wend, count(*) from tb1 EVENT_WINDOW start with f1 > 0 end with f1 < 10; print ======== step4 sql explain analyze select ts from st1 where -2; +sql explain analyze insert into t1(ts) select ts from st1 where -2; sql explain analyze select ts from tb1; +sql explain analyze insert into t1(ts) select ts from tb1; sql explain analyze select ts from st1; -sql explain analyze select ts from st1; +sql explain analyze insert into t1(ts) select ts from st1; sql explain analyze select ts from st1 order by ts; +sql explain analyze insert into t1(ts) select ts from st1 order by ts; sql explain analyze select * from information_schema.ins_stables; sql explain analyze select count(*),sum(f1) from tb1; sql explain analyze select count(*),sum(f1) from st1; sql explain analyze select count(*),sum(f1) from st1 group by f1; +sql explain analyze insert into t1(ts, t1) select _wstart, count(*) from st1 interval(10s); print ======== step5 sql explain analyze verbose true select ts from st1 where -2; +sql explain analyze verbose true insert into t1(ts) select ts from st1 where -2; sql explain analyze verbose true select ts from tb1; +sql explain analyze verbose true insert into t1(ts) select ts from tb1; sql explain analyze verbose true select ts from st1; -sql explain analyze verbose true select ts from st1; +sql explain analyze verbose true insert into t1(ts) select ts from st1; sql explain analyze verbose true select ts from st1 order by ts; +sql explain analyze verbose true insert into t1(ts) select ts from st1 order by ts; sql explain analyze verbose true select * from information_schema.ins_stables; sql explain analyze verbose true select count(*),sum(f1) from tb1; sql explain analyze verbose true select count(*),sum(f1) from st1; @@ -77,6 +105,13 @@ sql explain analyze verbose true select * from information_schema.ins_stables wh sql explain analyze verbose true select * from (select min(f1),count(*) a from st1 where f1 > 0) where a < 0; sql explain analyze verbose true select count(f1) from st1 group by tbname; sql explain analyze verbose true select st1.f1 from st1 join st2 on st1.ts=st2.ts and st1.f1 > 0; +sql explain analyze verbose true select diff(f1) as f11 from tb1 order by f11; +sql explain analyze verbose true select count(*) from st1 where ts > now - 3m and ts < now interval(10s) fill(linear); +sql explain analyze verbose true select count(*) from information_schema.ins_tables group by stable_name; +sql explain analyze verbose true select last(*) from st1; +sql explain analyze verbose true select last_row(*) from st1; +sql explain analyze verbose true select interp(f1) from tb1 where ts > now - 3m and ts < now range(now-3m,now) every(1m) fill(prev); +sql explain analyze verbose true select _wstart, _wend, count(*) from tb1 EVENT_WINDOW start with f1 > 0 end with f1 < 10; #not pass case #sql explain verbose true select count(*),sum(f1) as aa from tb1 where (f1 > 0 or f1 < -1) and ts > '2020-10-31 00:00:00' and ts < '2021-10-31 00:00:00' order by aa; diff --git a/tests/script/tsim/query/interval-offset.sim b/tests/script/tsim/query/interval-offset.sim index f4d95df083ca9f80ad5ed68d71992689aa7f66be..0d796af0a0ed1d154667c0d647131829625b34d3 100644 --- a/tests/script/tsim/query/interval-offset.sim +++ b/tests/script/tsim/query/interval-offset.sim @@ -212,10 +212,10 @@ print ===> rows2: $data20 $data21 $data22 $data23 $data24 if $rows != 3 then return -1 endi -if $data01 != 2 then +if $data01 != 4 then return -1 endi -if $data04 != 2 then +if $data04 != 4 then return -1 endi diff --git a/tests/script/tsim/query/join.sim b/tests/script/tsim/query/join.sim new file mode 100644 index 0000000000000000000000000000000000000000..adb0338ef704ebf257a176f5c9772c5aecac08c4 --- /dev/null +++ b/tests/script/tsim/query/join.sim @@ -0,0 +1,72 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +$dbPrefix = db +$tbPrefix1 = tba +$tbPrefix2 = tbb +$mtPrefix = stb +$tbNum = 10000 +$rowNum = 2 + +print =============== step1 +$i = 0 +$db = $dbPrefix . $i +$mt1 = $mtPrefix . $i +$i = 1 +$mt2 = $mtPrefix . $i + +sql drop database $db -x step1 +step1: +sql create database $db +sql use $db +sql create table $mt1 (ts timestamp, f1 int) TAGS(tag1 int, tag2 binary(500)) +sql create table $mt2 (ts timestamp, f1 int) TAGS(tag1 int, tag2 binary(500)) + +print ====== start create child tables and insert data +$i = 0 +while $i < $tbNum + $tb = $tbPrefix1 . $i + sql create table $tb using $mt1 tags( $i , 'aaaaaaaaaaaaaaaaaaaaaaaaaaa') + + $x = 0 + while $x < $rowNum + $cc = $x * 60000 + $ms = 1601481600000 + $cc + + sql insert into $tb values ($ms , $x ) + $x = $x + 1 + endw + + $i = $i + 1 +endw + +print =============== step2 +$i = 0 +while $i < $tbNum + $tb = $tbPrefix2 . $i + sql create table $tb using $mt2 tags( $i , 'aaaaaaaaaaaaaaaaaaaaaaaaaaa') + + $x = 0 + while $x < $rowNum + $cc = $x * 60000 + $ms = 1601481600000 + $cc + + sql insert into $tb values ($ms , $x ) + $x = $x + 1 + endw + + $i = $i + 1 +endw + +sql select * from tba0 t1, tbb0 t2 where t1.ts=t2.ts; +if $rows != 2 then + return -1 +endi +sql select * from stb0 t1, stb1 t2 where t1.ts=t2.ts and t1.tag2=t2.tag2; +if $rows != 200000000 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/join_interval.sim b/tests/script/tsim/query/join_interval.sim new file mode 100644 index 0000000000000000000000000000000000000000..14994a5cc1b77909ebcc40fae93880f9fda065f0 --- /dev/null +++ b/tests/script/tsim/query/join_interval.sim @@ -0,0 +1,42 @@ + +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c udf -v 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print ======== step create databases +sql create database d1 +sql create database d2 +sql create table d1.t1(ts timestamp, i int) tags(t int); +sql create table d2.t1(ts timestamp, i int); +sql insert into d1.t11 using d1.t1 tags(1) values(1500000000000, 0)(1500000000001, 1)(1500000000002,2)(1500000000003,3)(1500000000004,4) +sql insert into d1.t12 using d1.t1 tags(2) values(1500000000000, 0)(1500000000001, 1)(1500000000002,2)(1500000000003,3)(1500000000004,4) +sql insert into d1.t13 using d1.t1 tags(3) values(1500000000000, 0)(1500000000001, 1)(1500000000002,2)(1500000000003,3)(1500000000004,4) + +sql insert into d2.t1 values(1500000000000,0)(1500000000001,1)(1500000000002,2) + +sql select _wstart,_wend,count((a.ts)),count(b.ts) from d1.t1 a, d2.t1 b where a.ts is not null and a.ts = b.ts interval(1a) ; +if $data02 != 3 then + return -1 +endi + +if $data03 != 3 then + return -1 +endi + +if $data12 != 3 then + return -1 +endi + +if $data13 != 3 then + return -1 +endi +if $data22 != 3 then + return -1 +endi + +if $data23 != 3 then + return -1 +endi +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/multi_order_by.sim b/tests/script/tsim/query/multi_order_by.sim new file mode 100644 index 0000000000000000000000000000000000000000..7b7f2abe365333b2f63a5825ed7945450bddc0d5 --- /dev/null +++ b/tests/script/tsim/query/multi_order_by.sim @@ -0,0 +1,57 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +sql create database test; +sql use test; + +sql create table t(ts timestamp, f int); +sql insert into t values(now,0)(now+1s, 1)(now+2s, 2)(now+3s,3)(now+4s,4)(now+5s,5)(now+6s,6)(now+7s,7)(now+8s,8)(now+9s,9) +sql select * from (select * from t order by ts desc limit 3 offset 2) order by ts; +print $data01 $data11 $data21 +if $data01 != 5 then + return -1 +endi +if $data11 != 6 then + return -1 +endi +if $data21 != 7 then + return -1 +endi +sql select * from (select * from t order by ts limit 3 offset 2) order by ts desc; +print $data01 $data11 $data21 +if $data01 != 4 then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data21 != 2 then + return -1 +endi +sql select * from (select * from t order by ts desc limit 3 offset 2) order by ts desc; +print $data01 $data11 $data21 +if $data01 != 7 then + return -1 +endi +if $data11 != 6 then + return -1 +endi +if $data21 != 5 then + return -1 +endi +sql select * from (select * from t order by ts limit 3 offset 2) order by ts; +print $data01 $data11 $data21 +if $data01 != 2 then + return -1 +endi +if $data11 != 3 then + return -1 +endi +if $data21 != 4 then + return -1 +endi + + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/nullColSma.sim b/tests/script/tsim/query/nullColSma.sim new file mode 100644 index 0000000000000000000000000000000000000000..886274e7e59ca22a557a8ed861585592d5402fbb --- /dev/null +++ b/tests/script/tsim/query/nullColSma.sim @@ -0,0 +1,139 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +$dbPrefix = m_in_db +$tbPrefix = m_in_tb +$mtPrefix = m_in_mt +$tbNum = 1 +$rowNum = 200 +$totalNum = 400 + +print =============== step1 +$i = 0 +$db = $dbPrefix . $i +$mt = $mtPrefix . $i + +sql drop database if exists $db +sql create database $db vgroups 1 maxrows 200 minrows 10; +sql use $db +sql create table $mt (ts timestamp, f1 int, f2 float) TAGS(tgcol int) + +print ====== start create child tables and insert data +$i = 0 +while $i < $tbNum + $tb = $tbPrefix . $i + sql create table $tb using $mt tags( $i ) + + $x = 0 + while $x < $rowNum + $cc = $x * 1 + $ms = 1601481600000 + $cc + + sql insert into $tb values ($ms , NULL , $x ) + $x = $x + 1 + endw + + $i = $i + 1 +endw + +$i = 1 +$tb = $tbPrefix . $i +sql create table $tb using $mt tags( $i ) + +$x = 0 +while $x < $rowNum + $cc = $x * 1 + $ms = 1601481600000 + $cc + + sql insert into $tb values ($ms , $x , NULL ) + $x = $x + 1 +endw + +sql flush database $db + +print =============== step2 +$i = 0 +$tb = $tbPrefix . $i +sql select max(f1) from $tb +if $rows != 1 then + return -1 +endi +if $data00 != NULL then + return -1 +endi + +$i = 1 +$tb = $tbPrefix . $i +sql select max(f2) from $tb +if $rows != 1 then + return -1 +endi +if $data00 != NULL then + return -1 +endi + +$rowNum = 10 + +print ====== insert more data +$i = 0 +while $i < $tbNum + $tb = $tbPrefix . $i + + $x = 0 + while $x < $rowNum + $cc = $x * 1 + $ms = 1601481700000 + $cc + + sql insert into $tb values ($ms , $x , $x ) + $x = $x + 1 + endw + + $i = $i + 1 +endw + +$i = 1 +$tb = $tbPrefix . $i +$x = 0 +while $x < $rowNum + $cc = $x * 1 + $ms = 1601481700000 + $cc + + sql insert into $tb values ($ms , $x , $x ) + $x = $x + 1 +endw + +sql flush database $db + +print =============== step3 +$i = 0 +$tb = $tbPrefix . $i +sql select max(f1) from $tb +if $rows != 1 then + return -1 +endi +if $data00 != 9 then + return -1 +endi + +$i = 1 +$tb = $tbPrefix . $i +sql select max(f2) from $tb +if $rows != 1 then + return -1 +endi +if $data00 != 9.00000 then + print $data00 + return -1 +endi + + +print =============== clear +#sql drop database $db +#sql select * from information_schema.ins_databases +#if $rows != 0 then +# return -1 +#endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/partitionby.sim b/tests/script/tsim/query/partitionby.sim new file mode 100644 index 0000000000000000000000000000000000000000..8babd1aa8de8e0ad943312e6712d297c3c5242b4 --- /dev/null +++ b/tests/script/tsim/query/partitionby.sim @@ -0,0 +1,39 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +$dbPrefix = db +$tbPrefix1 = tba +$tbPrefix2 = tbb +$mtPrefix = stb +$tbNum = 10 +$rowNum = 2 + +print =============== step1 +$i = 0 +$db = $dbPrefix . $i +$mt1 = $mtPrefix . $i +$i = 1 +$mt2 = $mtPrefix . $i + +sql drop database $db -x step1 +step1: +sql create database $db vgroups 3 +sql use $db +sql create table $mt1 (ts timestamp, f1 int) TAGS(tag1 int, tag2 binary(500)) +sql create table tb0 using $mt1 tags(0, 'a'); +sql create table tb1 using $mt1 tags(1, 'b'); +sql create table tb2 using $mt1 tags(1, 'a'); +sql create table tb3 using $mt1 tags(1, 'a'); +sql create table tb4 using $mt1 tags(3, 'b'); +sql create table tb5 using $mt1 tags(3, 'a'); +sql create table tb6 using $mt1 tags(3, 'b'); +sql create table tb7 using $mt1 tags(3, 'b'); + +sql select * from $mt1 partition by tag1,tag2 limit 1; +if $rows != 0 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/sys_tbname.sim b/tests/script/tsim/query/sys_tbname.sim index 4587dcd4f7ff9c455f8f87c663e7f00cbf32957a..849aeb2ac5dabc46e6770de956e4e885e988e2ab 100644 --- a/tests/script/tsim/query/sys_tbname.sim +++ b/tests/script/tsim/query/sys_tbname.sim @@ -51,9 +51,14 @@ if $data00 != @ins_stables@ then return -1 endi +sql select * from information_schema.ins_tables where table_name=''; +if $rows != 0 then + return -1 +endi + sql select tbname from information_schema.ins_tables; print $rows $data00 -if $rows != 32 then +if $rows != 33 then return -1 endi if $data00 != @ins_tables@ then @@ -104,5 +109,26 @@ if $rows != 5000 then return -1 endi - +sql create database d1; +sql create stable d1.st1 (ts timestamp, f int) tags(t int); +sql create stable d1.st2 (ts timestamp, f int) tags(t int); +sql create table d1.ct1 using d1.st1 tags(1); +sql create table d1.ct2 using d1.st2 tags(2); + +sql create database d2; +sql create stable d2.st1(ts timestamp, f int) tags(t int); +sql create stable d2.st2(ts timestamp, f int) tags(t int); +sql create table d2.ct1 using d2.st1 tags(1); +sql create table d2.ct2 using d2.st2 tags(2); + +sql create database d3; +sql create stable d3.st1(ts timestamp, f int) tags(t int); +sql create stable d3.st2(ts timestamp, f int) tags(t int); +sql create table d3.ct1 using d3.st1 tags(1); +sql create table d3.ct2 using d3.st2 tags(2); +sql select count(*), stable_name, db_name from information_schema.ins_tables where db_name != 'd2' group by stable_name,db_name +print $rows +if $rows != 9 then + return -1 +endi #system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/tableCount.sim b/tests/script/tsim/query/tableCount.sim new file mode 100644 index 0000000000000000000000000000000000000000..6e65852dcc4ccab82e44fc0260227fe5709c2259 --- /dev/null +++ b/tests/script/tsim/query/tableCount.sim @@ -0,0 +1,119 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +sql drop database if exists db1; +sql create database db1 vgroups 3; +sql create database db1; +sql use db1; +sql create stable sta (ts timestamp, f1 int, f2 binary(200)) tags(t1 int, t2 int, t3 int); +sql create stable stb (ts timestamp, f1 int, f2 binary(200)) tags(t1 int, t2 int, t3 int); +sql create table tba1 using sta tags(1, 1, 1); +sql create table tba2 using sta tags(2, 2, 2); +sql create table tba3 using sta tags(3, 3, 3); +sql create table tba4 using sta tags(3, 3, 3); +sql create table tba5 using sta tags(3, 3, 3); +sql create table tba6 using sta tags(3, 3, 3); +sql create table tba7 using sta tags(3, 3, 3); +sql create table tba8 using sta tags(3, 3, 3); +sql create table tbb1 using stb tags(4, 4, 4); +sql create table tbb2 using stb tags(5, 5, 5); +sql create table tbb3 using stb tags(6, 6, 6); +sql create table tbb4 using stb tags(4, 4, 4); +sql create table tbb5 using stb tags(5, 5, 5); +sql create table tbb6 using stb tags(6, 6, 6); +sql create table tbb7 using stb tags(7, 7, 7); +sql create table tbb8 using stb tags(8, 8, 8); +sql create table tbn1 (ts timestamp, f1 int); +sql create database db2 vgroups 3; +sql create database db2; +sql use db2; +sql create stable sta (ts timestamp, f1 int, f2 binary(200)) tags(t1 int, t2 int, t3 int); +sql create stable stb (ts timestamp, f1 int, f2 binary(200)) tags(t1 int, t2 int, t3 int); +sql create table tba1 using sta tags(1, 1, 1); +sql create table tba2 using sta tags(2, 2, 2); +sql create table tbb1 using stb tags(4, 4, 4); +sql create table tbb2 using stb tags(5, 5, 5); +sql create table tbb3 using stb tags(6, 6, 6); + +sql select count(table_name) from information_schema.ins_tables group by stable_name; +if $rows != 3 then + return -1 +endi +sql select count(table_name) from information_schema.ins_tables group by db_name; +if $rows != 4 then + return -1 +endi +sql select count(table_name) from information_schema.ins_tables group by db_name, stable_name; +if $rows != 7 then + return -1 +endi +sql select stable_name,count(table_name) from information_schema.ins_tables group by stable_name order by stable_name; +if $rows != 3 then + return -1 +endi +if $data01 != 30 then + return -1 +endi +if $data11 != 10 then + return -1 +endi +if $data21 != 11 then + return -1 +endi +sql select db_name,count(table_name) from information_schema.ins_tables group by db_name order by db_name; +if $rows != 4 then + return -1 +endi +if $data01 != 17 then + return -1 +endi +if $data11 != 5 then + return -1 +endi +if $data21 != 24 then + return -1 +endi +if $data31 != 5 then + return -1 +endi +sql select db_name,stable_name,count(table_name) from information_schema.ins_tables group by db_name, stable_name order by db_name, stable_name; +if $rows != 7 then + return -1 +endi +if $data02 != 1 then + return -1 +endi +if $data12 != 8 then + return -1 +endi +if $data22 != 8 then + return -1 +endi +if $data32 != 2 then + return -1 +endi +if $data42 != 3 then + return -1 +endi +if $data52 != 24 then + return -1 +endi +if $data62 != 5 then + return -1 +endi +sql select count(table_name) from information_schema.ins_tables where db_name='db1' and stable_name='sta' group by stable_name +print $rows , $data00 +if $rows != 1 then + return -1 +endi +if $data00 != 8 then + return -1 +endi +sql select distinct db_name from information_schema.ins_tables; +print $rows +if $rows != 4 then + return -1 +endi +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/tagLikeFilter.sim b/tests/script/tsim/query/tagLikeFilter.sim new file mode 100644 index 0000000000000000000000000000000000000000..79c1bc7c0bda151b0613689e0081735e6f0372f8 --- /dev/null +++ b/tests/script/tsim/query/tagLikeFilter.sim @@ -0,0 +1,36 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +sql drop database if exists db1; +sql create database if not exists db1 vgroups 10; +sql use db1; +sql create stable sta (ts timestamp, f1 double, f2 binary(200)) tags(t1 binary(100)); +sql create table tba1 using sta tags('ZQMPvstuzZVzCRjFTQawILuGSqZKSqlJwcBtZMxrAEqBbzChHWVDMiAZJwESzJAf'); +sql create table tba2 using sta tags('ieofwehughkreghughuerugu34jf9340aieefjalie28ffj8fj8fafjaekdfjfii'); +sql create table tba3 using sta tags('ZQMPvstuzZVzCRjFTQawILuGSqabSqlJwcBtZMxrAEqBbzChHWVDMiAZJwESzJAf'); +sql insert into tba1 values ('2022-04-26 15:15:01', 1.0, "a"); +sql insert into tba2 values ('2022-04-26 15:15:01', 1.0, "a"); +sql insert into tba2 values ('2022-04-26 15:15:02', 1.0, "a"); +sql insert into tba3 values ('2022-04-26 15:15:01', 1.0, "a"); +sql insert into tba3 values ('2022-04-26 15:15:02', 1.0, "a"); +sql insert into tba3 values ('2022-04-26 15:15:03', 1.0, "a"); +sql select t1 from sta where t1 like '%ab%'; +if $rows != 3 then + return -1 +endi +sql select t1 from sta where t1 like '%ax%'; +if $rows != 0 then + return -1 +endi +sql select t1 from sta where t1 like '%cd%'; +if $rows != 0 then + return -1 +endi +sql select t1 from sta where t1 like '%ii'; +if $rows != 2 then + return -1 +endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/udf.sim b/tests/script/tsim/query/udf.sim index 0b48a815e21900c4a80e3ea883e6b95f26bcf695..e539f115317abcd2b64279ec476f8f3464a559d5 100644 --- a/tests/script/tsim/query/udf.sim +++ b/tests/script/tsim/query/udf.sim @@ -23,12 +23,15 @@ if $system_content == Windows_NT then return 0; endi if $system_content == Windows_NT then - sql create function bit_and as 'C:\\Windows\\Temp\\bitand.dll' outputtype int bufSize 8; + sql create function bit_and as 'C:\\Windows\\Temp\\bitand.dll' outputtype int; sql create aggregate function l2norm as 'C:\\Windows\\Temp\\l2norm.dll' outputtype double bufSize 8; else - sql create function bit_and as '/tmp/udf/libbitand.so' outputtype int bufSize 8; + sql create function bit_and as '/tmp/udf/libbitand.so' outputtype int; sql create aggregate function l2norm as '/tmp/udf/libl2norm.so' outputtype double bufSize 8; endi + +sql_error create function bit_and as '/tmp/udf/libbitand.so' oputtype json; + sql show functions; if $rows != 2 then return -1 diff --git a/tests/script/tsim/query/udf_with_const.sim b/tests/script/tsim/query/udf_with_const.sim index 7a2a3389bd155e1c384823ce94c3fdd96b14139e..4a12dd68682a1afe39bf31be1b5b249d2433ee72 100644 --- a/tests/script/tsim/query/udf_with_const.sim +++ b/tests/script/tsim/query/udf_with_const.sim @@ -23,9 +23,9 @@ if $system_content == Windows_NT then endi if $system_content == Windows_NT then - sql create function gpd as 'C:\\Windows\\Temp\\gpd.dll' outputtype int bufSize 8; + sql create function gpd as 'C:\\Windows\\Temp\\gpd.dll' outputtype int; else - sql create function gpd as '/tmp/udf/libgpd.so' outputtype int bufSize 8; + sql create function gpd as '/tmp/udf/libgpd.so' outputtype int; endi sql show functions; if $rows != 1 then diff --git a/tests/script/tsim/query/udfpy.sim b/tests/script/tsim/query/udfpy.sim new file mode 100644 index 0000000000000000000000000000000000000000..9e0492ffd95e3baed20a77ddf3423a1e8872c1d0 --- /dev/null +++ b/tests/script/tsim/query/udfpy.sim @@ -0,0 +1,328 @@ +system_content printf %OS% +if $system_content == Windows_NT then + return 0; +endi + +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/cfg.sh -n dnode1 -c udf -v 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print ======== step1 udf +system sh/compile_udf.sh +system sh/prepare_pyudf.sh +system mkdir -p /tmp/pyudf +system cp sh/pybitand.py /tmp/pyudf/ +system cp sh/pyl2norm.py /tmp/pyudf/ +system ls /tmp/pyudf + +sql create database udf vgroups 3; +sql use udf; +sql select * from information_schema.ins_databases; + +sql create table t (ts timestamp, f int); +sql insert into t values(now, 1)(now+1s, 2); + +system_content printf %OS% +if $system_content == Windows_NT then + return 0; +endi +if $system_content == Windows_NT then + sql create function bit_and as 'C:\\Windows\\Temp\\bitand.dll' outputtype int; + sql create aggregate function l2norm as 'C:\\Windows\\Temp\\l2norm.dll' outputtype double bufSize 8; +else + sql create function bit_and as '/tmp/udf/libbitand.so' outputtype int; + sql create aggregate function l2norm as '/tmp/udf/libl2norm.so' outputtype double bufSize 8; +endi +sql create function pybitand as '/tmp/pyudf/pybitand.py' outputtype int language 'python'; +sql create aggregate function pyl2norm as '/tmp/pyudf/pyl2norm.py' outputtype double bufSize 128 language 'python'; + +sql show functions; +if $rows != 4 then + return -1 +endi + +sql select func_language, func_body,name from information_schema.ins_functions order by name +if $rows != 4 then + return -1 +endi + +if $data00 != @C@ then + return -1 +endi +if $data10 != @C@ then + return -1 +endi +if $data20 != @Python@ then + return -1 +endi +if $data30 != @Python@ then + return -1 +endi + +sql select bit_and(f, f) from t; +if $rows != 2 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 2 then + return -1 +endi + +sql select pybitand(f, f) from t; +if $rows != 2 then + return -1 +endi +if $data00 != 1 then + return -1 +endi +if $data10 != 2 then + return -1 +endi + +sql select l2norm(f) from t; +if $rows != 1 then + print expect 1, actual $rows + return -1 +endi +if $data00 != 2.236067977 then + return -1 +endi + +sql select pyl2norm(f) from t; +if $rows != 1 then + print expect 1, actual $rows + return -1 +endi +if $data00 != 2.236067977 then + return -1 +endi + +sql create table t2 (ts timestamp, f1 int, f2 int); +sql insert into t2 values(now, 0, 0)(now+1s, 1, 1); +sql select bit_and(f1, f2) from t2; +if $rows != 2 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 1 then + return -1 +endi + +sql select l2norm(f1, f2) from t2; +if $rows != 1 then + return -1 +endi +if $data00 != 1.414213562 then + return -1 +endi + +sql select pybitand(f1, f2) from t2; +if $rows != 2 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 1 then + return -1 +endi + +sql select pyl2norm(f1, f2) from t2; +if $rows != 1 then + return -1 +endi +if $data00 != 1.414213562 then + return -1 +endi + +sql insert into t2 values(now+2s, 1, null)(now+3s, null, 2); +sql select bit_and(f1, f2) from t2; +print $rows , $data00 , $data10 , $data20 , $data30 +if $rows != 4 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 1 then + return -1 +endi + +if $data20 != NULL then + return -1 +endi + +if $data30 != NULL then + return -1 +endi + +sql select l2norm(f1, f2) from t2; +print $rows, $data00 +if $rows != 1 then + return -1 +endi +if $data00 != 2.645751311 then + return -1 +endi + +sql select pybitand(f1, f2) from t2; +print $rows , $data00 , $data10 , $data20 , $data30 +if $rows != 4 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 1 then + return -1 +endi + +if $data20 != NULL then + return -1 +endi + +if $data30 != NULL then + return -1 +endi + +sql select pyl2norm(f1, f2) from t2; +print $rows, $data00 +if $rows != 1 then + return -1 +endi +if $data00 != 2.645751311 then + return -1 +endi + + +sql insert into t2 values(now+4s, 4, 8)(now+5s, 5, 9); +sql select l2norm(f1-f2), l2norm(f1+f2) from t2; +print $rows , $data00 , $data01 +if $rows != 1 then + return -1; +endi +if $data00 != 5.656854249 then + return -1 +endi +if $data01 != 18.547236991 then + return -1 +endi + +sql select l2norm(bit_and(f2, f1)), l2norm(bit_and(f1, f2)) from t2; +print $rows , $data00 , $data01 +if $rows != 1 then + return -1 +endi +if $data00 != 1.414213562 then + return -1 +endi +if $data01 != 1.414213562 then + return -1 +endi + +sql select l2norm(f2) from udf.t2 group by 1-bit_and(f1, f2) order by 1-bit_and(f1,f2); +print $rows , $data00 , $data10 , $data20 +if $rows != 3 then + return -1 +endi +if $data00 != 2.000000000 then + return -1 +endi +if $data10 != 9.055385138 then + return -1 +endi +if $data20 != 8.000000000 then + return -1 +endi + +sql select pyl2norm(f1-f2), pyl2norm(f1+f2) from t2; +print $rows , $data00 , $data01 +if $rows != 1 then + return -1; +endi +if $data00 != 5.656854249 then + return -1 +endi +if $data01 != 18.547236991 then + return -1 +endi + +sql select pyl2norm(pybitand(f2, f1)), pyl2norm(pybitand(f1, f2)) from t2; +print $rows , $data00 , $data01 +if $rows != 1 then + return -1 +endi +if $data00 != 1.414213562 then + return -1 +endi +if $data01 != 1.414213562 then + return -1 +endi + +sql select pyl2norm(f2) from udf.t2 group by 1-pybitand(f1, f2) order by 1-pybitand(f1,f2); +print $rows , $data00 , $data10 , $data20 +if $rows != 3 then + return -1 +endi +if $data00 != 2.000000000 then + return -1 +endi +if $data10 != 9.055385138 then + return -1 +endi +if $data20 != 8.000000000 then + return -1 +endi + +sql create or replace function bit_and as '/tmp/udf/libbitand.so' outputtype int +sql select func_version from information_schema.ins_functions where name='bit_and' +if $data00 != 1 then + return -1 +endi +sql select bit_and(f1, f2) from t2; +print $rows , $data00 , $data10 , $data20 , $data30 , $data40 , $data50 +if $rows != 6 then + return -1 +endi +if $data00 != 0 then + return -1 +endi +if $data10 != 1 then + return -1 +endi + +if $data20 != NULL then + return -1 +endi + +if $data30 != NULL then + return -1 +endi + +if $data40 != 0 then + return -1 +endi +if $data50 != 1 then + return -1 +endi +#sql drop function bit_and; +#sql show functions; +#if $rows != 1 then +# return -1 +#endi +#if $data00 != @l2norm@ then +# return -1 +# endi +#sql drop function l2norm; +#sql show functions; +#if $rows != 0 then +# return -1 +#endi + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/query/unionall_as_table.sim b/tests/script/tsim/query/unionall_as_table.sim new file mode 100644 index 0000000000000000000000000000000000000000..4d8f99071829050a5da6de2c6b1ea2feb41d27bb --- /dev/null +++ b/tests/script/tsim/query/unionall_as_table.sim @@ -0,0 +1,45 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +sql create database test; +sql use test; +sql CREATE STABLE bw_yc_h_substation_mea (ts TIMESTAMP, create_date VARCHAR(50), create_time VARCHAR(30), load_time TIMESTAMP, sum_p_value FLOAT, sum_sz_value FLOAT, sum_gl_ys FLOAT, sum_g_value FLOAT) TAGS (id VARCHAR(50), name NCHAR(200), datasource VARCHAR(50), sys_flag VARCHAR(50)); +sql CREATE STABLE aw_yc_h_substation_mea (ts TIMESTAMP, create_date VARCHAR(50), create_time VARCHAR(30), load_time TIMESTAMP, sum_p_value FLOAT, sum_sz_value FLOAT, sum_gl_ys FLOAT, sum_g_value FLOAT) TAGS (id VARCHAR(50), name NCHAR(200), datasource VARCHAR(50), sys_flag VARCHAR(50)); +sql CREATE STABLE dw_yc_h_substation_mea (ts TIMESTAMP, create_date VARCHAR(50), create_time VARCHAR(30), load_time TIMESTAMP, sum_p_value FLOAT, sum_sz_value FLOAT, sum_gl_ys FLOAT, sum_g_value FLOAT) TAGS (id VARCHAR(50), name NCHAR(200), datasource VARCHAR(50), sys_flag VARCHAR(50)); +sql insert into t1 using dw_yc_h_substation_mea tags('1234567890','testa','0021001','abc01') values(now,'2023-03-27','00:01:00',now,2.3,3.3,4.4,5.5); +sql insert into t2 using dw_yc_h_substation_mea tags('2234567890','testb','0022001','abc02') values(now,'2023-03-27','00:01:00',now,2.3,2.3,2.4,2.5); +sql insert into t3 using aw_yc_h_substation_mea tags('2234567890','testc','0023001','abc03') values(now,'2023-03-27','00:15:00',now,2.3,2.3,2.4,2.5); +sql insert into t4 using bw_yc_h_substation_mea tags('4234567890','testd','0021001','abc03') values(now,'2023-03-27','00:45:00',now,2.3,2.3,2.4,2.5); +sql insert into t5 using bw_yc_h_substation_mea tags('5234567890','testd','0021001','abc03') values(now,'2023-03-27','00:00:00',now,2.3,2.3,2.4,2.5); +sql select t.ts,t.id,t.name,t.create_date,t.create_time,t.datasource,t.sum_p_value from (select ts,id,name,create_date,create_time,datasource,sum_p_value from bw_yc_h_substation_mea where create_date='2023-03-27' and substr(create_time,4,2) in ('00','15','30','45') union all select ts,id,name,create_date,create_time,datasource,sum_p_value from aw_yc_h_substation_mea where create_date='2023-03-27' and substr(create_time,4,2) in ('00','15','30','45') union all select ts,id,name,create_date,create_time,datasource,sum_p_value from dw_yc_h_substation_mea where create_date='2023-03-27' and substr(create_time,4,2) in ('00','15','30','45')) t where t.datasource='0021001' and t.id='4234567890' order by t.create_time; + +if $rows != 1 then + return -1 +endi +if $data01 != @4234567890@ then + return -1 +endi +if $data05 != @0021001@ then + return -1 +endi + +sql create table st (ts timestamp, f int) tags (t int); +sql insert into ct1 using st tags(1) values(now, 1)(now+1s, 2) +sql insert into ct2 using st tags(2) values(now+2s, 3)(now+3s, 4) +sql select count(*) from (select * from ct1 union all select * from ct2) +if $rows != 1 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +sql select count(*) from (select * from ct1 union select * from ct2) +if $rows != 1 then + return -1 +endi +if $data00 != 4 then + return -1 +endi +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/scalar/tsConvert.sim b/tests/script/tsim/scalar/tsConvert.sim index 75efdb442f5055b559950173c68941a2260aa5bd..ad8d3b3b93382ac706edaeac85ab58fabf14e04d 100644 --- a/tests/script/tsim/scalar/tsConvert.sim +++ b/tests/script/tsim/scalar/tsConvert.sim @@ -13,7 +13,7 @@ sql insert into tb1 values ('2022-07-10 16:31:00', 1, '1'); sql insert into tb1 values ('2022-07-10 16:32:00', 2, '2'); sql insert into tb1 values ('2022-07-10 16:33:00', 3, '3'); sql insert into tb1 values ('2022-07-10 16:34:00', 4, '4'); -sql select * from (select ts,TIMETRUNCATE(ts,1d),TIMETRUNCATE(ts,1h),timediff(TIMETRUNCATE(ts,1d),TIMETRUNCATE(ts,1h),1h) as td from tb1 where ts >='2022-06-01 00:00:00' and ts <=' 2022-11-3 23:59:59' ) t where td >12; +sql select * from (select ts,TIMETRUNCATE(ts,1d),TIMETRUNCATE(ts,1h),timediff(TIMETRUNCATE(ts,1d),TIMETRUNCATE(ts,1h),1h) as td from tb1 where ts >='2022-06-01 00:00:00' and ts <='2022-11-3 23:59:59' ) t where td >12; if $rows != 4 then return -1 endi diff --git a/tests/script/tsim/show/basic.sim b/tests/script/tsim/show/basic.sim index cae7a66589bac72c352ed855902f3b23bb798046..8990e492fa9aa3805cc8427827484958a7fc4aaf 100644 --- a/tests/script/tsim/show/basic.sim +++ b/tests/script/tsim/show/basic.sim @@ -244,5 +244,15 @@ if $rows <= 0 then return -1 endi +sql show cluster alive; +if $rows <= 0 then + return -1 +endi + +sql show db.alive; +if $rows <= 0 then + return -1 +endi + system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode2 -s stop -x SIGINT diff --git a/tests/script/tsim/sma/rsmaCreateInsertQuery.sim b/tests/script/tsim/sma/rsmaCreateInsertQuery.sim index 508e6f88c14f09d4e55c8bd3d40ea78426e5fa43..b3144e4e0dd217319a0d58bf3222360fcd5fa355 100644 --- a/tests/script/tsim/sma/rsmaCreateInsertQuery.sim +++ b/tests/script/tsim/sma/rsmaCreateInsertQuery.sim @@ -81,8 +81,60 @@ if $data01 != 10 then endi #=================================================================== +system sh/exec.sh -n dnode1 -s stop -x SIGINT +system sh/exec.sh -n dnode1 -s start +print =============== wait maxdelay 15+2 seconds for results after reboot +sleep 17000 + +print =============== select * from retention level 2 from memory after reboot +sql select * from ct1; +print $data00 $data01 +if $rows > 2 then + print retention level 2 file rows $rows > 2 + return -1 +endi + + +if $data01 != 1 then + if $data01 != 10 then + print =============> $data01 + print retention level 2 file result $data01 != 1 or 10 + return -1 + endi +endi + +print =============== select * from retention level 1 from memory after reboot +sql select * from ct1 where ts > now-8d; +print $data00 $data01 +if $rows > 2 then + print retention level 1 file rows $rows > 2 + return -1 +endi + +if $data01 != 1 then + if $data01 != 10 then + print retention level 1 file result $data01 != 1 or 10 + return -1 + endi +endi + +print =============== select * from retention level 0 from memory after reboot +sql select * from ct1 where ts > now-3d; +print $data00 $data01 +print $data10 $data11 +print $data20 $data21 + +if $rows < 1 then + print retention level 0 file rows $rows < 1 + return -1 +endi + +if $data01 != 10 then + print retention level 0 file result $data01 != 10 + return -1 +endi -#==================== reboot to trigger commit data to file +#==================== flush database to trigger commit data to file sql flush database d0; system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s start diff --git a/tests/script/tsim/sma/rsmaPersistenceRecovery.sim b/tests/script/tsim/sma/rsmaPersistenceRecovery.sim index 4117a2403dcc7156a8b9ea3adb840fe25b26b376..0c9d23335ea3b378a2dbe849dc8f7fd773470dea 100644 --- a/tests/script/tsim/sma/rsmaPersistenceRecovery.sim +++ b/tests/script/tsim/sma/rsmaPersistenceRecovery.sim @@ -82,9 +82,62 @@ if $data01 != 10 then endi #=================================================================== +system sh/exec.sh -n dnode1 -s stop -x SIGINT +system sh/exec.sh -n dnode1 -s start +print =============== wait maxdelay 5+2 seconds for results after reboot +sleep 7000 + +print =============== select * from retention level 2 from memory after reboot +sql select * from ct1; +print $data00 $data01 $data02 +print $data10 $data11 $data12 +if $rows > 2 then + print retention level 2 file rows $rows > 2 + return -1 +endi + + +if $data01 != 100 then + if $data01 != 10 then + print retention level 2 file result $data01 != 100 or 10 + return -1 + endi +endi + +print =============== select * from retention level 1 from memory after reboot +sql select * from ct1 where ts > now-8d; +print $data00 $data01 $data02 +print $data10 $data11 $data12 +if $rows > 2 then + print retention level 1 file rows $rows > 2 + return -1 +endi + +if $data01 != 100 then + if $data01 != 10 then + print retention level 1 file result $data01 != 100 or 10 + return -1 + endi +endi + +print =============== select * from retention level 0 from memory after reboot +sql select * from ct1 where ts > now-3d; +print $data00 $data01 $data02 +print $data10 $data11 $data12 +print $data20 $data21 $data22 + +if $rows < 1 then + print retention level 0 file rows $rows < 1 + return -1 +endi + +if $data01 != 10 then + print retention level 0 file result $data01 != 10 + return -1 +endi -#==================== reboot to trigger commit data to file +#==================== flush database to trigger commit data to file sql flush database d0; system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s start diff --git a/tests/script/tsim/sma/tsmaCreateInsertQuery.sim b/tests/script/tsim/sma/tsmaCreateInsertQuery.sim index 442b4970e4e09652666378962a8e04d9ae8616fd..9b6fc96bc00fde8418bf1d29d4c8cd8fc7f02091 100644 --- a/tests/script/tsim/sma/tsmaCreateInsertQuery.sim +++ b/tests/script/tsim/sma/tsmaCreateInsertQuery.sim @@ -7,9 +7,10 @@ sql connect print =============== create database sql create database d1 keep 36500d vgroups 1 sql use d1 +sql alter local 'querySmaOptimize' '1'; print =============== create super table, include column type for count/sum/min/max/first -sql create table if not exists stb (ts timestamp, c1 int, c2 float, c3 double) tags (t1 int unsigned) +sql create table if not exists stb (ts timestamp, c1 int, c2 float, c3 double, c4 binary(10),c5 nchar(10)) tags (t1 int unsigned) sql show stables if $rows != 1 then @@ -25,16 +26,32 @@ if $rows != 1 then endi print =============== insert data, mode1: one row one table in sql -sql insert into ct1 values('2022-10-19 09:55:45.682', 10, 2.0, 3.0) -sql insert into ct1 values('2022-10-19 09:55:46.682', 11, 2.1, 3.1)('2022-10-19 09:55:47.682', -12, -2.2, -3.2)('2022-10-19 09:55:48.682', -13, -2.3, -3.3) +sql insert into ct1 values('2022-10-19 09:55:45.682', 10, 2.0, 3.0, "a", "n0") +sql insert into ct1 values('2022-10-19 09:55:46.682', 11, 2.1, 3.1,"b","n1")('2022-10-19 09:55:47.682', -12, -2.2, -3.2,"c","n2")('2022-10-19 09:55:48.682', -13, -2.3, -3.3,"d","n3") print =============== create sma index from super table sql create sma index sma_index_name1 on stb function(max(c1),max(c2),min(c1)) interval(5m,10s) sliding(5m) watermark 1s max_delay 1s -print $data00 $data01 $data02 $data03 +sql create sma index sma_index_name2 on stb function(sum(c1),first(c1), last(c1), first(c4),last(c4),count(c4),first(c5),last(c5),count(c5),apercentile(c1,80,"t-digest"), avg(c2),count(c3), spread(c3), stddev(c2), hyperloglog(c2), hyperloglog(c4), hyperloglog(c5)) interval(5m,10s) sliding(5m); +# for varchar/binary +sql_error create sma index sma_index_name3 on stb function(sum(c4)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(min(c4)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(max(c4)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(avg(c4)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(apercentile(c4)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(spread(c4)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(stddev(c4)) interval(5m,10s) sliding(5m); +# for nchar +sql_error create sma index sma_index_name3 on stb function(sum(c5)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(min(c5)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(max(c5)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(avg(c5)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(apercentile(c5)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(spread(c5)) interval(5m,10s) sliding(5m); +sql_error create sma index sma_index_name3 on stb function(stddev(c5)) interval(5m,10s) sliding(5m); print =============== trigger stream to execute sma aggr task and insert sma data into sma store -sql insert into ct1 values('2022-10-19 09:55:50.682', 20, 20.0, 30.0) +sql insert into ct1 values('2022-10-19 09:55:50.682', 20, 20.0, 30.0,"e","n5") #==================== sleep 2s to wait for tsma result sleep 2000 @@ -42,9 +59,11 @@ print =============== show streams ================================ sql show streams; print $data00 $data01 $data02 -if $data00 != sma_index_name1 then - print $data00 - return -1 +if $data00 != sma_index_name1 then + if $data00 != sma_index_name2 then + print $data00 + return -1 + endi endi print =============== select * from ct1 from memory @@ -117,7 +136,76 @@ system sh/exec.sh -n dnode1 -s stop -x SIGINT system sh/exec.sh -n dnode1 -s start sleep 50 +print =============== select * from ct1 from memory after reboot +sql select * from ct1; +print $data00 $data01 $data02 $data03 +print $data10 $data11 $data12 $data13 +print $data20 $data21 $data22 $data23 +print $data30 $data31 $data32 $data33 +print $data40 $data41 $data42 $data43 +if $rows != 5 then + print rows $rows != 5 + return -1 +endi +print =============== select * from stb from memory in designated vgroup after reboot +sql select _wstart, _wend, min(c1),max(c2),max(c1) from stb interval(5m,10s) sliding(5m); +print $data00 $data01 $data02 $data03 $data04 +print $data10 $data11 $data12 $data13 $data14 +if $rows != 1 then + print rows $rows != 1 + return -1 +endi + +if $data02 != -13 then + print data02 $data02 != -13 + return -1 +endi + +if $data03 != 20.00000 then + print data03 $data03 != 20.00000 + return -1 +endi + +if $data04 != 20 then + print data04 $data04 != 20 + return -1 +endi + +print =============== select * from stb from memory in common vgroups after reboot +sql select _wstart, _wend, min(c1),max(c2),max(c1),max(c3) from stb interval(5m,10s) sliding(5m); +print $data00 $data01 $data02 $data03 $data04 $data05 +if $rows != 1 then + print rows $rows != 1 + return -1 +endi + +if $data02 != -13 then + print data02 $data02 != -13 + return -1 +endi + +if $data03 != 20.00000 then + print data03 $data03 != 20.00000 + return -1 +endi + +if $data04 != 20 then + print data04 $data04 != 20 + return -1 +endi + +if $data05 != 30.000000000 then + print data05 $data05 != 30.000000000 + return -1 +endi + + +#==================== flush database to trigger commit data to file +sql flush database d1; +system sh/exec.sh -n dnode1 -s stop -x SIGINT +system sh/exec.sh -n dnode1 -s start +sleep 50 print =============== select * from ct1 from file sql select * from ct1; print $data00 $data01 $data02 $data03 diff --git a/tests/script/tsim/stream/basic0.sim b/tests/script/tsim/stream/basic0.sim index 8e3e99978b5a877bd6f2f9bb51daf9a05e50140a..68c5894cbff7c6bdfdbd932ece85e6eae324cd28 100644 --- a/tests/script/tsim/stream/basic0.sim +++ b/tests/script/tsim/stream/basic0.sim @@ -48,24 +48,35 @@ sleep 100 #=================================================================== print =============== query data from child table +$loop_count = 0 + +loop0: +sleep 200 + +$loop_count = $loop_count + 1 +if $loop_count == 20 then + return -1 +endi + sql select `_wstart`,`min(k)`,`max(k)`,sum_alias from outstb + print rows: $rows print $data00 $data01 $data02 $data03 if $rows != 1 then - return -1 + goto loop0 endi if $data01 != 234 then - return -1 + goto loop0 endi if $data02 != 234 then - return -1 + goto loop0 endi if $data03 != 234 then print expect 234, actual $data03 - return -1 + goto loop0 endi #=================================================================== @@ -77,23 +88,34 @@ sleep 100 #=================================================================== print =============== query data from child table +$loop_count = 0 + +loop1: +sleep 200 + +$loop_count = $loop_count + 1 +if $loop_count == 20 then + return -1 +endi + sql select `_wstart`,`min(k)`,`max(k)`,sum_alias from outstb + print rows: $rows print $data00 $data01 $data02 $data03 if $rows != 1 then - return -1 + goto loop1 endi if $data01 != -111 then - return -1 + goto loop1 endi if $data02 != 234 then - return -1 + goto loop1 endi if $data03 != 123 then - return -1 + goto loop1 endi #=================================================================== @@ -105,36 +127,46 @@ sleep 100 #=================================================================== print =============== query data from child table +$loop_count = 0 + +loop2: +sleep 200 + +$loop_count = $loop_count + 1 +if $loop_count == 20 then + return -1 +endi + sql select `_wstart`,`min(k)`,`max(k)`,sum_alias from outstb print rows: $rows print $data00 $data01 $data02 $data03 print $data10 $data11 $data12 $data13 if $rows != 2 then - return -1 + goto loop2 endi if $data01 != -111 then - return -1 + goto loop2 endi if $data02 != 234 then - return -1 + goto loop2 endi if $data03 != 123 then - return -1 + goto loop2 endi if $data11 != 789 then - return -1 + goto loop2 endi if $data12 != 789 then - return -1 + goto loop2 endi if $data13 != 789 then - return -1 + goto loop2 endi _OVER: diff --git a/tests/script/tsim/stream/basic1.sim b/tests/script/tsim/stream/basic1.sim index c61c7667f8fef94ea84b7379a4a6fc12cc5b2141..65032817b31c6aa2060b7c681d87801d73f7c84b 100644 --- a/tests/script/tsim/stream/basic1.sim +++ b/tests/script/tsim/stream/basic1.sim @@ -17,7 +17,7 @@ sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams1 trigger at_once into streamt as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s); sql insert into t1 values(1648791213000,1,2,3,1.0); sql insert into t1 values(1648791223001,2,2,3,1.1); sql insert into t1 values(1648791233002,3,2,3,2.1); @@ -37,7 +37,7 @@ if $loop_count == 20 then endi if $rows != 4 then - print =====rows=$rows + print =====rows=$rows expect 4 goto loop0 endi @@ -53,7 +53,7 @@ if $data02 != 2 then endi if $data03 != 5 then - print =====data03=$data03 + print =====data03=$data03, expect:5 goto loop0 endi @@ -545,8 +545,8 @@ sql create table t2 using st tags(2,2,2); sql create table t3 using st tags(2,2,2); sql create table t4 using st tags(2,2,2); sql create table t5 using st tags(2,2,2); -sql create stream streams2 trigger at_once into streamt as select _wstart, count(*) c1, sum(a) c3,max(b) c4 from st partition by tbname interval(10s); -sql create stream streams3 trigger at_once into streamt3 as select _wstart, count(*) c1, sum(a) c3,max(b) c4, now c5 from st partition by tbname interval(10s); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, sum(a) c3,max(b) c4 from st partition by tbname interval(10s); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart, count(*) c1, sum(a) c3,max(b) c4, now c5 from st partition by tbname interval(10s); sql insert into t1 values(1648791213000,1,1,1,1.0) t2 values(1648791213000,2,2,2,2.0) t3 values(1648791213000,3,3,3,3.0) t4 values(1648791213000,4,4,4,4.0); @@ -667,7 +667,7 @@ sql create database test3 vgroups 1; sql use test3; sql create stable st(ts timestamp, a int, b int , c int) tags(ta int,tb int,tc int); sql create table ts1 using st tags(1,1,1); -sql create stream stream_t3 trigger at_once into streamtST3 as select ts, min(a) c6, a, b, c, ta, tb, tc from ts1 interval(10s) ; +sql create stream stream_t3 trigger at_once IGNORE EXPIRED 0 into streamtST3 as select ts, min(a) c6, a, b, c, ta, tb, tc from ts1 interval(10s) ; sql insert into ts1 values(1648791211000,1,2,3); sleep 50 @@ -701,7 +701,7 @@ endi sql create database test4 vgroups 1; sql use test4; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams4 trigger at_once into streamt4 as select _wstart, count(*) c1 from t1 where a > 5 interval(10s); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart, count(*) c1 from t1 where a > 5 interval(10s); sql insert into t1 values(1648791213000,1,2,3,1.0); $loop_count = 0 @@ -797,8 +797,8 @@ sql create database test5 vgroups 1; sql use test5; sql create stable st(ts timestamp, a int, b int , c int) tags(ta int,tb int,tc int); sql create table ts1 using st tags(1,1,1); -sql create stream streams5 trigger at_once into streamt5 as select count(*), _wstart, _wend, max(a) from ts1 interval(10s) ; -sql create stream streams6 trigger at_once into streamt6 as select count(*), _wstart, _wend, max(a), _wstart as ts from ts1 interval(10s) ; +sql create stream streams5 trigger at_once IGNORE EXPIRED 0 into streamt5 as select count(*), _wstart, _wend, max(a) from ts1 interval(10s) ; +sql create stream streams6 trigger at_once IGNORE EXPIRED 0 into streamt6 as select count(*), _wstart, _wend, max(a), _wstart as ts from ts1 interval(10s) ; sql_error create stream streams7 trigger at_once into streamt7 as select _wstart, count(*), _wstart, _wend, max(a) from ts1 interval(10s) ; sql_error create stream streams8 trigger at_once into streamt8 as select count(*), _wstart, _wstart, _wend, max(a) from ts1 interval(10s) ; @@ -840,7 +840,7 @@ sql create database test7 vgroups 1; sql use test7; sql create stable st(ts timestamp, a int, b int , c int) tags(ta int,tb int,tc int); sql create table ts1 using st tags(1,1,1); -sql create stream streams7 trigger at_once into streamt7 as select _wstart, count(*) from ts1 interval(10s) ; +sql create stream streams7 trigger at_once IGNORE EXPIRED 0 into streamt7 as select _wstart, count(*) from ts1 interval(10s) ; sql insert into ts1 values(1648791211000,1,2,3); sql_error insert into ts1 values(-1648791211000,1,2,3); @@ -887,4 +887,20 @@ if $rows != 1 then goto loop19 endi +print select * from information_schema.ins_stream_tasks; +sql select * from information_schema.ins_stream_tasks; + +if $rows == 0 then + print =====rows=$rows + return -1 +endi + +print select * from information_schema.ins_streams; +sql select * from information_schema.ins_streams; + +if $rows == 0 then + print =====rows=$rows + return -1 +endi + system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/stream/checkStreamSTable.sim b/tests/script/tsim/stream/checkStreamSTable.sim new file mode 100644 index 0000000000000000000000000000000000000000..288dd35cfedb6b63d7b97af59ee52d427e2e0353 --- /dev/null +++ b/tests/script/tsim/stream/checkStreamSTable.sim @@ -0,0 +1,500 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 + +print ===== step1 + +system sh/exec.sh -n dnode1 -s start +sleep 50 +sql connect + +print ===== step2 + +sql create database result vgroups 1; + +sql create database test vgroups 4; +sql use test; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stable result.streamt0(ts timestamp,a int,b int) tags(ta int,tb varchar(100),tc int); + +sql create stream streams0 trigger at_once into result.streamt0 tags(tb) as select _wstart, count(*) c1, max(a) c2 from st partition by tbname tb interval(10s); +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,2,2,3); + +$loop_count = 0 + +sql select _wstart, count(*) c1, max(a) c2 from st partition by tbname interval(10s); +print $data00, $data01, $data02 +print $data10, $data11, $data12 +print $data20, $data21, $data22 + +loop0: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result.streamt0 order by ta; + +if $rows != 2 then + print =====rows=$rows + print $data00, $data01, $data02 + print $data10, $data11, $data12 + print $data20, $data21, $data22 + goto loop0 +endi + +if $data01 != 1 then + print =====data01=$data01 + goto loop0 +endi + +if $data02 != 1 then + print =====data02=$data02 + goto loop0 +endi + +if $data03 != NULL then + print =====data03=$data03 + goto loop0 +endi + +if $data04 != t1 then + print =====data04=$data04 + goto loop0 +endi + +if $data11 != 1 then + print =====data11=$data11 + goto loop0 +endi + +if $data12 != 2 then + print =====data12=$data12 + goto loop0 +endi + +if $data13 != NULL then + print =====data13=$data13 + goto loop0 +endi + +if $data14 != t2 then + print =====data14=$data14 + goto loop0 +endi + +print ===== step3 + +sql create database result1 vgroups 1; + +sql create database test1 vgroups 4; +sql use test1; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stable result1.streamt1(ts timestamp,a int,b int,c int) tags(ta varchar(100),tb int,tc int); + +sql create stream streams1 trigger at_once into result1.streamt1(ts,c,a,b) tags(ta) as select _wstart, count(*) c1, max(a),min(b) c2 from st partition by tbname as ta interval(10s); +sql insert into t1 values(1648791213000,10,20,30); +sql insert into t2 values(1648791213000,40,50,60); + +$loop_count = 0 + +sql select _wstart, count(*) c1, max(a),min(b) c2 from st partition by tbname interval(10s); +print $data00, $data01, $data02, $data03 +print $data10, $data11, $data12, $data13 +print $data20, $data21, $data22, $data23 + +loop1: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result1.streamt1 order by ta; + +if $rows != 2 then + print =====rows=$rows + print $data00, $data01, $data02, $data03 + print $data10, $data11, $data12, $data13 + print $data20, $data21, $data22, $data23 + goto loop1 +endi + +if $data01 != 10 then + print =====data01=$data01 + goto loop1 +endi + +if $data02 != 20 then + print =====data02=$data02 + goto loop1 +endi + +if $data03 != 1 then + print =====data03=$data03 + goto loop1 +endi + +if $data11 != 40 then + print =====data11=$data11 + goto loop1 +endi + +if $data12 != 50 then + print =====data12=$data12 + goto loop1 +endi + +if $data13 != 1 then + print =====data13=$data13 + goto loop1 +endi + + +print ===== step4 + +sql create database result2 vgroups 1; + +sql create database test2 vgroups 4; +sql use test2; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stable result2.streamt2(ts timestamp, a int , b int) tags(ta varchar(20)); + +# tag dest 1, source 2 +sql_error create stream streams2 trigger at_once into result2.streamt2 TAGS(aa varchar(100), ta int) as select _wstart, count(*) c1, max(a) from st partition by tbname as aa, ta interval(10s); + +# column dest 3, source 4 +sql_error create stream streams2 trigger at_once into result2.streamt2 as select _wstart, count(*) c1, max(a), max(b) from st partition by tbname interval(10s); + +# column dest 3, source 4 +sql_error create stream streams2 trigger at_once into result2.streamt2(ts, a, b) as select _wstart, count(*) c1, max(a), max(b) from st partition by tbname interval(10s); + +# column dest 3, source 2 +sql_error create stream streams2 trigger at_once into result2.streamt2 as select _wstart, count(*) c1 from st partition by tbname interval(10s); + +# column dest 3, source 2 +sql create stream streams2 trigger at_once into result2.streamt2(ts, a) tags(ta) as select _wstart, count(*) c1 from st partition by tbname as ta interval(10s); + + +print ===== step5 + +sql create database result3 vgroups 1; + +sql create database test3 vgroups 4; +sql use test3; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,2,3); +sql create table t2 using st tags(4,5,6); + +sql create stable result3.streamt3(ts timestamp,a int,b int,c int, d int) tags(ta int,tb int,tc int); + +sql create stream streams3 trigger at_once into result3.streamt3(ts,c,a,b) as select _wstart, count(*) c1, max(a),min(b) c2 from st interval(10s); + +sql insert into t1 values(1648791213000,10,20,30); +sql insert into t2 values(1648791213000,40,50,60); + +$loop_count = 0 + +sql select _wstart, count(*) c1, max(a),min(b) c2 from st interval(10s); +print $data00, $data01, $data02, $data03, $data04 +print $data10, $data11, $data12, $data13, $data14 +print $data20, $data21, $data22, $data23, $data24 + +loop2: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result3.streamt3; + +if $rows != 1 then + print =====rows=$rows + print $data00, $data01, $data02, $data03 + print $data10, $data11, $data12, $data13 + print $data20, $data21, $data22, $data23 + goto loop2 +endi + +if $data01 != 40 then + print =====data01=$data01 + goto loop2 +endi + +if $data02 != 20 then + print =====data02=$data02 + goto loop2 +endi + +if $data03 != 2 then + print =====data03=$data03 + goto loop2 +endi + +if $data04 != NULL then + print =====data04=$data04 + goto loop2 +endi + +print ===== drop ... + +sql drop stream if exists streams0; +sql drop stream if exists streams1; +sql drop stream if exists streams2; +sql drop stream if exists streams3; +sql drop database if exists test; +sql drop database if exists test1; +sql drop database if exists test2; +sql drop database if exists test3; +sql drop database if exists result; +sql drop database if exists result1; +sql drop database if exists result2; +sql drop database if exists result3; + +print ===== step6 + +sql create database result4 vgroups 1; + +sql create database test4 vgroups 4; +sql use test4; + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,2,3); +sql create table t2 using st tags(4,5,6); + +sql create stable result4.streamt4(ts timestamp,a int,b int,c int, d int) tags(tg1 int,tg2 int,tg3 int); + +sql create stream streams4 trigger at_once into result4.streamt4(ts,c,a,b) tags(tg2, tg3, tg1) subtable( concat("tbl-", cast(tg1 as varchar(10)) ) ) as select _wstart, count(*) c1, max(a),min(b) c2 from st partition by ta+1 as tg1, cast(tb as bigint) as tg2, tc as tg3 interval(10s); + +sql insert into t1 values(1648791213000,10,20,30); +sql insert into t2 values(1648791213000,40,50,60); + +$loop_count = 0 + +sql select _wstart, count(*) c1, max(a),min(b) c2 from st partition by ta+1 as tg1, cast(tb as bigint) as tg2, tc as tg3 interval(10s); +print $data00, $data01, $data02, $data03 +print $data10, $data11, $data12, $data13 +print $data20, $data21, $data22, $data23 + +loop3: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result4.streamt4 order by tg1; + +if $rows != 2 then + print =====rows=$rows + print $data00, $data01, $data02, $data03 + print $data10, $data11, $data12, $data13 + print $data20, $data21, $data22, $data23 + goto loop3 +endi + +if $data01 != 10 then + print =====data01=$data01 + goto loop3 +endi + +if $data02 != 20 then + print =====data02=$data02 + goto loop3 +endi + +if $data03 != 1 then + print =====data03=$data03 + goto loop3 +endi + +if $data04 != NULL then + print =====data04=$data04 + goto loop3 +endi + +if $data11 != 40 then + print =====data11=$data11 + goto loop3 +endi + +if $data12 != 50 then + print =====data12=$data12 + goto loop3 +endi + +if $data13 != 1 then + print =====data13=$data13 + goto loop3 +endi + +if $data14 != NULL then + print =====data14=$data14 + goto loop3 +endi + +print ===== step7 + +sql create database result5 vgroups 1; + +sql create database test5 vgroups 4; +sql use test5; + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,2,3); +sql create table t2 using st tags(4,5,6); + +sql create stable result5.streamt5(ts timestamp,a int,b int,c int, d int) tags(tg1 int,tg2 int,tg3 int); + +sql create stream streams5 trigger at_once into result5.streamt5(ts,c,a,b) tags(tg2, tg3, tg1) subtable( concat("tbl-", cast(tg3 as varchar(10)) ) ) as select _wstart, count(*) c1, max(a),min(b) c2 from st partition by ta+1 as tg1, cast(tb as bigint) as tg2, a as tg3 session(ts, 10s); + +sql insert into t1 values(1648791213000,NULL,NULL,NULL); + +$loop_count = 0 + +print select _wstart, count(*) c1, max(a),min(b) c2 from st partition by ta+1 as tg1, cast(tb as bigint) as tg2, a as tg3 session(ts, 10s); +sql select _wstart, count(*) c1, max(a),min(b) c2 from st partition by ta+1 as tg1, cast(tb as bigint) as tg2, a as tg3 session(ts, 10s); +print $data00, $data01, $data02, $data03 +print $data10, $data11, $data12, $data13 +print $data20, $data21, $data22, $data23 + +loop4: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +print sql select * from result5.streamt5 order by tg1; +sql select * from result5.streamt5 order by tg1; +print $data00, $data01, $data02, $data03 $data04 $data05 $data06 $data07 +print $data10, $data11, $data12, $data13 +print $data20, $data21, $data22, $data23 + +if $rows != 1 then + print =====rows=$rows + goto loop4 +endi + +if $data01 != NULL then + print =====data01=$data01 + goto loop4 +endi + +if $data02 != NULL then + print =====data02=$data02 + goto loop4 +endi + +if $data03 != 1 then + print =====data03=$data03 + goto loop4 +endi + +if $data04 != NULL then + print =====data04=$data04 + goto loop4 +endi + +if $data05 != 2 then + print =====data05=$data05 + goto loop4 +endi + +if $data06 != 2 then + print =====data06=$data06 + goto loop4 +endi + +if $data07 != NULL then + print =====data07=$data07 + goto loop4 +endi + +sql drop stream if exists streams4; +sql drop stream if exists streams5; +sql drop database if exists test4; +sql drop database if exists test5; +sql drop database if exists result4; +sql drop database if exists result5; + +print ===== step8 + +sql drop stream if exists streams8; +sql drop database if exists test8; +sql create database test8 vgroups 1; +sql use test8; +sql create table t1(ts timestamp, a int, b int , c int, d double); +sql create stream streams8 trigger at_once into streamt8 as select _wstart as ts, count(*) c1, count(d) c2, count(c) c3 from t1 partition by tbname interval(10s) ; + +sql drop stream streams8; +sql create stream streams71 trigger at_once into streamt8(ts, c2) tags(group_id)as select _wstart, count(*) from t1 partition by tbname as group_id interval(10s); + +sql insert into t1 values(1648791233000,1,2,3,1.0); + +loop8: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from streamt8; +print $data00, $data01, $data02, $data03 +print $data10, $data11, $data12, $data13 +print $data20, $data21, $data22, $data23 + +if $rows != 1 then + print =====rows=$rows + goto loop8 +endi + +if $data01 != NULL then + print =====data01=$data01 + goto loop8 +endi + +if $data02 != 1 then + print =====data02=$data02 + goto loop8 +endi + +if $data03 != NULL then + print =====data03=$data03 + goto loop8 +endi + +print ======over + +system sh/stop_dnodes.sh diff --git a/tests/script/tsim/stream/checkStreamSTable1.sim b/tests/script/tsim/stream/checkStreamSTable1.sim new file mode 100644 index 0000000000000000000000000000000000000000..495e1cf35854b4e1f434c793b29091b7ec5b034d --- /dev/null +++ b/tests/script/tsim/stream/checkStreamSTable1.sim @@ -0,0 +1,71 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 + +print ===== step1 + +system sh/exec.sh -n dnode1 -s start +sleep 50 +sql connect + +print ===== step2 + +sql create database test vgroups 4; +sql use test; +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); +sql create stream streams1 trigger at_once into streamt1 as select _wstart, count(*) c1, count(a) c2 from st interval(1s) ; +sql insert into t1 values(1648791211000,1,2,3); +sql insert into t1 values(1648791212000,2,2,3); + +$loop_count = 0 +loop0: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +print 1 select * from streamt1; +sql select * from streamt1; + +if $rows != 2 then + print rows=$rows + goto loop0 +endi + +print drop stream streams1 +sql drop stream streams1; + +print alter table streamt1 add column c3 double +sql alter table streamt1 add column c3 double; + +print create stream streams1 trigger at_once into streamt1 as select _wstart, count(*) c1, count(a) c2, avg(b) c3 from st interval(1s) ; +sql create stream streams1 trigger at_once into streamt1 as select _wstart, count(*) c1, count(a) c2, avg(b) c3 from st interval(1s) ; + +sql insert into t2 values(1648791213000,1,2,3); +sql insert into t1 values(1648791214000,1,2,3); + +$loop_count = 0 +loop1: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +print 2 select * from streamt1; +sql select * from streamt1; + +if $rows != 4 then + print rows=$rows + goto loop1 +endi + +print ======over + +system sh/stop_dnodes.sh diff --git a/tests/script/tsim/stream/deleteInterval.sim b/tests/script/tsim/stream/deleteInterval.sim index 7532b2d5def428d0c83e420c128bdc33f438f392..9540e448d44b4ed21499134e6a6b0e91f29b5020 100644 --- a/tests/script/tsim/stream/deleteInterval.sim +++ b/tests/script/tsim/stream/deleteInterval.sim @@ -16,7 +16,7 @@ sql drop database if exists test; sql create database test vgroups 1; sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams0 trigger at_once into streamt as select _wstart c1, count(*) c2, max(a) c3 from t1 interval(10s); +sql create stream streams0 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart c1, count(*) c2, max(a) c3 from t1 interval(10s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sleep 200 @@ -193,7 +193,7 @@ sql use test2; sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams2 trigger at_once into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st interval(10s); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st interval(10s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t2 values(1648791213000,NULL,NULL,NULL,NULL); @@ -419,7 +419,7 @@ sql use test3; sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams3 trigger at_once into test.streamt3 as select _wstart c1, count(*) c2, max(a) c3 from st interval(10s); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into test.streamt3 as select _wstart c1, count(*) c2, max(a) c3 from st interval(10s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t2 values(1648791213000,NULL,NULL,NULL,NULL); diff --git a/tests/script/tsim/stream/deleteSession.sim b/tests/script/tsim/stream/deleteSession.sim index c3c64a597774c490a1491816e0e2175be739828d..364593917835a82f043e3d04439346d8a91f17fd 100644 --- a/tests/script/tsim/stream/deleteSession.sim +++ b/tests/script/tsim/stream/deleteSession.sim @@ -16,7 +16,7 @@ sql drop database if exists test; sql create database test vgroups 1; sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams0 trigger at_once into streamt as select _wstart c1, count(*) c2, max(a) c3 from t1 session(ts, 5s); +sql create stream streams0 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart c1, count(*) c2, max(a) c3 from t1 session(ts, 5s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sleep 200 @@ -191,7 +191,7 @@ sql use test2; sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams2 trigger at_once into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st session(ts,5s); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st session(ts,5s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t2 values(1648791213000,NULL,NULL,NULL,NULL); @@ -422,7 +422,7 @@ sql use test3; sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams3 trigger at_once into test.streamt3 as select _wstart c1, count(*) c2, max(a) c3 from st session(ts,5s); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into test.streamt3 as select _wstart c1, count(*) c2, max(a) c3 from st session(ts,5s); sql insert into t1 values(1648791210000,1,1,1,NULL); sql insert into t1 values(1648791210001,2,2,2,NULL); @@ -532,8 +532,8 @@ sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -print create stream streams4 trigger at_once into streamt4 as select _wstart, count(*) c1 from st partition by tbname session(ts, 2s); -sql create stream streams4 trigger at_once into streamt4 as select _wstart, count(*) c1 from st partition by tbname session(ts, 2s); +print create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart, count(*) c1 from st partition by tbname session(ts, 2s); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart, count(*) c1 from st partition by tbname session(ts, 2s); sql insert into t1 values(1648791210000,1,2,3); sql insert into t1 values(1648791220000,2,2,3); diff --git a/tests/script/tsim/stream/deleteState.sim b/tests/script/tsim/stream/deleteState.sim index 45d9bc3e39e926c459fb210345ba5713a6528867..c84e52067cade9cf9df2452d73a5d41260bfc3a9 100644 --- a/tests/script/tsim/stream/deleteState.sim +++ b/tests/script/tsim/stream/deleteState.sim @@ -16,7 +16,7 @@ sql drop database if exists test; sql create database test vgroups 1; sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams0 trigger at_once into streamt as select _wstart c1, count(*) c2, max(b) c3 from t1 state_window(a); +sql create stream streams0 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart c1, count(*) c2, max(b) c3 from t1 state_window(a); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sleep 200 @@ -51,13 +51,8 @@ if $loop_count == 10 then return -1 endi -if $data01 != 1 then - print =====data01=$data01 - goto loop1 -endi - -if $data02 != NULL then - print =====data02=$data02 +if $rows != 0 then + print =====rows=$rows goto loop1 endi @@ -197,8 +192,8 @@ sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -print create stream streams4 trigger at_once into streamt4 as select _wstart, count(*) c1 from st partition by tbname state_window(c); -sql create stream streams4 trigger at_once into streamt4 as select _wstart, count(*) c1 from st partition by tbname state_window(c); +print create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart, count(*) c1 from st partition by tbname state_window(c); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart, count(*) c1 from st partition by tbname state_window(c); sql insert into t1 values(1648791210000,1,2,1); sql insert into t1 values(1648791220000,2,2,2); diff --git a/tests/script/tsim/stream/distributeInterval0.sim b/tests/script/tsim/stream/distributeInterval0.sim index 1d58922928c7313aa97bff2ed29e26e9e1035952..1559d3d32b5752ce9ec3be66117daeab354ca1ca 100644 --- a/tests/script/tsim/stream/distributeInterval0.sim +++ b/tests/script/tsim/stream/distributeInterval0.sim @@ -272,4 +272,122 @@ if $data12 != 2 then goto loop3 endi +print ===== step3 + +sql drop database if exists test4; +sql create database test4 vgroups 10; +sql use test4; +sql create stable st(ts timestamp,a int,b int,c varchar(250) ) tags(ta int,tb int,tc int); +sql create table aaa using st tags(1,1,1); +sql create table bbb using st tags(2,2,2); +sql create table ccc using st tags(3,2,2); +sql create table ddd using st tags(4,2,2); + + +sql create stream streams1 ignore expired 0 fill_history 0 watermark 3s into streamst subtable(c) as select _wstart, c , count(*) c1, last_row(b) c2 from st partition by c interval(1s) ; + +sql insert into aaa values(1648791221001,2,2,"/a1/aa/aa"); +sql insert into bbb values(1648791221001,2,2,"/a1/aa/aa"); +sql insert into ccc values(1648791221001,2,2,"/a1/aa/aa"); +sql insert into ddd values(1648791221001,2,2,"/a1/aa/aa"); + +sql insert into aaa values(1648791222002,2,2,"/a2/aa/aa"); +sql insert into bbb values(1648791222002,2,2,"/a2/aa/aa"); +sql insert into ccc values(1648791222002,2,2,"/a2/aa/aa"); +sql insert into ddd values(1648791222002,2,2,"/a2/aa/aa"); + +sql insert into aaa values(1648791223003,2,2,"/a3/aa/aa"); +sql insert into bbb values(1648791223003,2,2,"/a3/aa/aa"); +sql insert into ccc values(1648791223003,2,2,"/a3/aa/aa"); +sql insert into ddd values(1648791223003,2,2,"/a3/aa/aa"); + +sql insert into aaa values(1648791224003,2,2,"/a4/aa/aa"); +sql insert into bbb values(1648791224003,2,2,"/a4/aa/aa"); +sql insert into ccc values(1648791224003,2,2,"/a4/aa/aa"); +sql insert into ddd values(1648791224003,2,2,"/a4/aa/aa"); + + +sql insert into aaa values(1648791225003,2,2,"/a5/aa/aa"); +sql insert into bbb values(1648791225003,2,2,"/a5/aa/aa"); +sql insert into ccc values(1648791225003,2,2,"/a5/aa/aa"); +sql insert into ddd values(1648791225003,2,2,"/a5/aa/aa"); + +sql insert into aaa values(1648791226003,2,2,"/a6/aa/aa"); +sql insert into bbb values(1648791226003,2,2,"/a6/aa/aa"); +sql insert into ccc values(1648791226003,2,2,"/a6/aa/aa"); +sql insert into ddd values(1648791226003,2,2,"/a6/aa/aa"); + +$loop_count = 0 + +loop4: +sleep 200 + +$loop_count = $loop_count + 1 +if $loop_count == 20 then + return -1 +endi + +sql select * from streamst; + +if $rows == 0 then + goto loop4 +endi + +sql delete from aaa where ts = 1648791223003 ; + +$loop_count = 0 + +loop5: +sleep 200 + +$loop_count = $loop_count + 1 +if $loop_count == 20 then + return -1 +endi + +sql select * from streamst; + +if $rows == 0 then + goto loop5 +endi + + +sql delete from ccc; + +$loop_count = 0 + +loop6: +sleep 200 + +$loop_count = $loop_count + 1 +if $loop_count == 20 then + return -1 +endi + +sql select * from streamst; + +if $rows == 0 then + goto loop6 +endi + +sql delete from ddd; + +$loop_count = 0 + +loop7: +sleep 200 + +$loop_count = $loop_count + 1 +if $loop_count == 20 then + return -1 +endi + +sql select * from streamst; + +if $rows == 0 then + goto loop7 +endi + +print ===== over + system sh/stop_dnodes.sh diff --git a/tests/script/tsim/stream/distributeIntervalRetrive0.sim b/tests/script/tsim/stream/distributeIntervalRetrive0.sim index ae2f9afdb5a542c9895820ae7d64bcacdd5f0ebc..a2d9c4ab458219beb81d53a4ad1148806e068e71 100644 --- a/tests/script/tsim/stream/distributeIntervalRetrive0.sim +++ b/tests/script/tsim/stream/distributeIntervalRetrive0.sim @@ -3,7 +3,6 @@ system sh/deploy.sh -n dnode1 -i 1 system sh/deploy.sh -n dnode2 -i 2 system sh/exec.sh -n dnode1 -s start -#==system sh/exec.sh -n dnode1 -s start -v sleep 50 sql connect @@ -11,7 +10,6 @@ sql connect sql create dnode $hostname2 port 7200 system sh/exec.sh -n dnode2 -s start -#==system sh/exec.sh -n dnode2 -s start -v print ===== step1 $x = 0 @@ -37,14 +35,14 @@ endi print ===== step2 -sql create database test vgroups 4; +sql create database test vgroups 10; sql use test; sql create stable st(ts timestamp, a int, b int , c int, d double) tags(ta int,tb int,tc int); sql create table ts1 using st tags(1,1,1); sql create table ts2 using st tags(2,2,2); sql create table ts3 using st tags(3,2,2); sql create table ts4 using st tags(4,2,2); -sql create stream stream_t1 trigger at_once into streamtST1 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s); +sql create stream stream_t1 trigger at_once IGNORE EXPIRED 0 delete_mark 10s into streamtST1 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s); sleep 1000 @@ -235,6 +233,29 @@ endi print loop3 over +sql insert into ts1 values(1648791200001,1,12,3,1.0); +sql insert into ts2 values(1648791200001,1,12,3,1.0); +sql insert into ts3 values(1648791200001,1,12,3,1.0); +sql insert into ts4 values(1648791200001,1,12,3,1.0); + +$loop_count = 0 +loop31: +sleep 1000 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from streamtST1; + +if $rows <= 4 then + print =====rows=$rows + goto loop31 +endi + +print loop31 over + sql drop stream if exists streams1; sql drop database if exists test1; @@ -243,7 +264,7 @@ sql use test1; sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams1 trigger at_once into streamt1 as select _wstart as c0, count(*) c1, count(a) c2 from st interval(10s) ; +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 delete_mark 20s into streamt1 as select _wstart as c0, count(*) c1, count(a) c2 from st interval(10s) ; sql insert into t1 values(1648791211000,1,2,3); diff --git a/tests/script/tsim/stream/distributeSession0.sim b/tests/script/tsim/stream/distributeSession0.sim index d752f5c29ce774b07286f44076fbcd415faa9acd..25ac479a38dbd90d2d2dc79ef1c027e709646e30 100644 --- a/tests/script/tsim/stream/distributeSession0.sim +++ b/tests/script/tsim/stream/distributeSession0.sim @@ -39,7 +39,7 @@ sql use test; sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); sql create table ts1 using st tags(1,1,1); sql create table ts2 using st tags(2,2,2); -sql create stream stream_t1 trigger at_once into streamtST as select _wstart, count(*) c1, sum(a) c2 , max(b) c3 from st session(ts, 10s) ; +sql create stream stream_t1 trigger at_once IGNORE EXPIRED 0 into streamtST as select _wstart, count(*) c1, sum(a) c2 , max(b) c3 from st session(ts, 10s) ; sleep 1000 diff --git a/tests/script/tsim/stream/fillHistoryBasic1.sim b/tests/script/tsim/stream/fillHistoryBasic1.sim index 772a09c0176512ca1617e53cc87e16ec20fb2a4a..e7a8da90e23c6b83bbc0b7beb6f736312f292b89 100644 --- a/tests/script/tsim/stream/fillHistoryBasic1.sim +++ b/tests/script/tsim/stream/fillHistoryBasic1.sim @@ -17,7 +17,7 @@ sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream stream1 trigger at_once fill_history 1 into streamt as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s); +sql create stream stream1 trigger at_once fill_history 1 IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s); sql insert into t1 values(1648791213000,1,2,3,1.0); sql insert into t1 values(1648791223001,2,2,3,1.1); @@ -479,7 +479,7 @@ sql insert into t1 values(1648791233002,3,2,3,2.1); sql insert into t1 values(1648791243003,4,2,3,3.1); sql insert into t1 values(1648791213004,4,2,3,4.1); -sql create stream stream2 trigger at_once fill_history 1 into streamt as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s); +sql create stream stream2 trigger at_once fill_history 1 IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s); sleep 5000 sql select `_wstart`, c1, c2 ,c3 ,c4, c5 from streamt; diff --git a/tests/script/tsim/stream/fillHistoryBasic2.sim b/tests/script/tsim/stream/fillHistoryBasic2.sim index 3af198259d2c7bb4c5c39af3acd39d222f217d1c..2f6c3ea92d3c374557fcac3b63684022198239a5 100644 --- a/tests/script/tsim/stream/fillHistoryBasic2.sim +++ b/tests/script/tsim/stream/fillHistoryBasic2.sim @@ -79,7 +79,7 @@ sql insert into ts3 values(1648791243005,4,42,3,3.1) (1648791243003,4,2,33,3.1) sql insert into ts4 values(1648791243005,4,42,3,3.1) (1648791243003,4,2,33,3.1) (1648791243006,4,2,3,3.1) (1648791213001,1,52,13,1.0) (1648791223001,22,22,83,1.1) (1648791233004,13,12,13,2.1) ; sql insert into ts3 values(1648791243006,4,2,3,3.1) (1648791213001,1,52,13,1.0) (1648791223001,22,22,83,1.1) ; -sql create stream stream_t1 trigger at_once fill_history 1 watermark 1d into streamtST1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s); +sql create stream stream_t1 trigger at_once fill_history 1 watermark 1d IGNORE EXPIRED 0 into streamtST1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s); sleep 1000 @@ -211,7 +211,7 @@ sql insert into ts1 values(1648791222001,2,2,3); sql insert into ts2 values(1648791211000,1,2,3); sql insert into ts2 values(1648791222001,2,2,3); -sql create stream stream_t2 trigger at_once fill_history 1 watermark 20s into streamtST1 as select _wstart, count(*) c1, count(a) c2 , sum(a) c3 , max(b) c5, min(c) c6 from st interval(10s) ; +sql create stream stream_t2 trigger at_once fill_history 1 watermark 20s IGNORE EXPIRED 0 into streamtST1 as select _wstart, count(*) c1, count(a) c2 , sum(a) c3 , max(b) c5, min(c) c6 from st interval(10s) ; $loop_count = 0 loop2: @@ -241,7 +241,7 @@ sql use test3; sql create stable st(ts timestamp, a int, b int , c int) tags(ta int,tb int,tc int); sql create table ts1 using st tags(1,1,1); sql create table ts2 using st tags(2,2,2); -sql create stream stream_t3 trigger at_once into streamtST3 as select ts, min(a) c6, a, b, c, ta, tb, tc from st interval(10s) ; +sql create stream stream_t3 trigger at_once IGNORE EXPIRED 0 into streamtST3 as select ts, min(a) c6, a, b, c, ta, tb, tc from st interval(10s) ; sql insert into ts1 values(1648791211000,1,2,3); sleep 50 diff --git a/tests/script/tsim/stream/fillHistoryBasic3.sim b/tests/script/tsim/stream/fillHistoryBasic3.sim index db8d6bc2d0ac7ae9b8c5d182b3d6eea63c02c7dd..44d7ee9d9e592ae68703bc707ab0b860444626fc 100644 --- a/tests/script/tsim/stream/fillHistoryBasic3.sim +++ b/tests/script/tsim/stream/fillHistoryBasic3.sim @@ -17,7 +17,7 @@ sql create table t2 using st tags(2,2,2); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t2 values(1648791213000,NULL,NULL,NULL,NULL); -sql create stream streams2 trigger at_once fill_history 1 into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a interval(10s); +sql create stream streams2 trigger at_once fill_history 1 IGNORE EXPIRED 0 into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a interval(10s); sleep 3000 diff --git a/tests/script/tsim/stream/fillIntervalDelete0.sim b/tests/script/tsim/stream/fillIntervalDelete0.sim index 77d09d5ae891010dbc154d3aa7b807bc31f86d69..41b018a86222e4a0ba2311f71dc4d19cb8160afc 100644 --- a/tests/script/tsim/stream/fillIntervalDelete0.sim +++ b/tests/script/tsim/stream/fillIntervalDelete0.sim @@ -16,11 +16,11 @@ sql drop database if exists test1; sql create database test1 vgroups 1; sql use test1; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams1 trigger at_once into streamt1 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(NULL); -sql create stream streams2 trigger at_once into streamt2 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value,100,200,300); -sql create stream streams3 trigger at_once into streamt3 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); -sql create stream streams4 trigger at_once into streamt4 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); -sql create stream streams5 trigger at_once into streamt5 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(NULL); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt2 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value,100,200,300); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); +sql create stream streams5 trigger at_once IGNORE EXPIRED 0 into streamt5 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); sql insert into t1 values(1648791213000,1,1,1,1.0,'aaa'); sleep 200 @@ -163,7 +163,7 @@ endi if $data01 != 4 then print =====data01=$data01 - return -1 + goto loop3 endi @@ -239,7 +239,7 @@ endi if $data01 != 6 then print =====data01=$data01 - return -1 + goto loop5 endi @@ -256,11 +256,11 @@ sql use test6; sql create stable st(ts timestamp, a int, b int , c int, d double, s varchar(20)) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(1,1,1); -sql create stream streams6 trigger at_once into streamt6 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(NULL); -sql create stream streams7 trigger at_once into streamt7 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value,100,200,300); -sql create stream streams8 trigger at_once into streamt8 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); -sql create stream streams9 trigger at_once into streamt9 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); -sql create stream streams10 trigger at_once into streamt10 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); +sql create stream streams6 trigger at_once IGNORE EXPIRED 0 into streamt6 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(NULL); +sql create stream streams7 trigger at_once IGNORE EXPIRED 0 into streamt7 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value,100,200,300); +sql create stream streams8 trigger at_once IGNORE EXPIRED 0 into streamt8 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); +sql create stream streams9 trigger at_once IGNORE EXPIRED 0 into streamt9 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); +sql create stream streams10 trigger at_once IGNORE EXPIRED 0 into streamt10 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); sql insert into t1 values(1648791210000,1,1,1,1.0,'aaa'); sql insert into t1 values(1648791217000,1,1,1,1.0,'aaa'); diff --git a/tests/script/tsim/stream/fillIntervalDelete1.sim b/tests/script/tsim/stream/fillIntervalDelete1.sim index ca347f120a8dacbc5d6e3d09099cc4e21fc8ed76..108f5f862dcac8ff3f785d87f959bb530c0da56f 100644 --- a/tests/script/tsim/stream/fillIntervalDelete1.sim +++ b/tests/script/tsim/stream/fillIntervalDelete1.sim @@ -18,11 +18,11 @@ sql drop database if exists test1; sql create database test1 vgroups 1; sql use test1; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams1 trigger at_once into streamt1 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(NULL); -sql create stream streams2 trigger at_once into streamt2 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value,100,200,300); -sql create stream streams3 trigger at_once into streamt3 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); -sql create stream streams4 trigger at_once into streamt4 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); -sql create stream streams5 trigger at_once into streamt5 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(NULL); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt2 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value,100,200,300); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); +sql create stream streams5 trigger at_once IGNORE EXPIRED 0 into streamt5 as select _wstart as ts, max(a), sum(b), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); sql insert into t1 values(1648791210000,0,0,0,0.0,'aaa'); sql insert into t1 values(1648791213000,1,1,1,1.0,'bbb'); @@ -221,11 +221,11 @@ sql use test6; sql create stable st(ts timestamp, a int, b int , c int, d double, s varchar(20)) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(1,1,1); -sql create stream streams6 trigger at_once into streamt6 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(NULL); -sql create stream streams7 trigger at_once into streamt7 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value,100,200,300); -sql create stream streams8 trigger at_once into streamt8 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); -sql create stream streams9 trigger at_once into streamt9 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); -sql create stream streams10 trigger at_once into streamt10 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); +sql create stream streams6 trigger at_once IGNORE EXPIRED 0 into streamt6 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(NULL); +sql create stream streams7 trigger at_once IGNORE EXPIRED 0 into streamt7 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value,100,200,300); +sql create stream streams8 trigger at_once IGNORE EXPIRED 0 into streamt8 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); +sql create stream streams9 trigger at_once IGNORE EXPIRED 0 into streamt9 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); +sql create stream streams10 trigger at_once IGNORE EXPIRED 0 into streamt10 as select _wstart as ts, max(a), sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); sql insert into t1 values(1648791210000,1,1,1,1.0,'aaa'); sql insert into t1 values(1648791215000,6,8,8,8.0,'bbb'); @@ -325,19 +325,19 @@ if $rows != 12 then endi if $data21 != 3 then print ====streamt10=data21=$data21 - return -1 + goto loop6 endi if $data31 != 4 then print ====streamt10=data31=$data31 - return -1 + goto loop6 endi if $data71 != 8 then print ====streamt10=data71=$data71 - return -1 + goto loop6 endi if $data91 != 10 then print ====streamt10=data91=$data91 - return -1 + goto loop6 endi @@ -353,11 +353,11 @@ sql drop database if exists test7; sql create database test7 vgroups 1; sql use test7; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams11 trigger at_once into streamt11 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(NULL); -sql create stream streams12 trigger at_once into streamt12 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(value,100.0,200); -sql create stream streams13 trigger at_once into streamt13 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(next); -sql create stream streams14 trigger at_once into streamt14 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(prev); -sql create stream streams15 trigger at_once into streamt15 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(linear); +sql create stream streams11 trigger at_once IGNORE EXPIRED 0 into streamt11 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(NULL); +sql create stream streams12 trigger at_once IGNORE EXPIRED 0 into streamt12 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(value,100.0,200); +sql create stream streams13 trigger at_once IGNORE EXPIRED 0 into streamt13 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(next); +sql create stream streams14 trigger at_once IGNORE EXPIRED 0 into streamt14 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(prev); +sql create stream streams15 trigger at_once IGNORE EXPIRED 0 into streamt15 as select _wstart as ts, avg(a), count(*), timezone(), to_iso8601(1) from t1 where ts >= 1648791210000 and ts < 1648791240000 interval(1s) fill(linear); sql insert into t1 values(1648791210000,1,1,1,1.0,'aaa'); diff --git a/tests/script/tsim/stream/fillIntervalLinear.sim b/tests/script/tsim/stream/fillIntervalLinear.sim index 4d0f101b6c10f4ca14499c7d59c68ea46a16b8d6..3fa369d8d517732ad22fad3582c9aa43e3e127be 100644 --- a/tests/script/tsim/stream/fillIntervalLinear.sim +++ b/tests/script/tsim/stream/fillIntervalLinear.sim @@ -9,12 +9,14 @@ system sh/exec.sh -n dnode1 -s start sleep 200 sql connect +print step 1 start + sql drop stream if exists streams1; sql drop database if exists test1; sql create database test1 vgroups 1; sql use test1; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams1 trigger at_once into streamt1 as select _wstart as ts, max(a)+sum(c), avg(b), first(s), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart as ts, max(a)+sum(c), avg(b), first(s), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); sql insert into t1 values(1648791213000,4,4,4,4.0,'aaa') (1648791216000,5,5,5,5.0,'bbb'); sql insert into t1 values(1648791210000,1,1,1,1.0,'ccc') (1648791219000,2,2,2,2.0,'ddd') (1648791222000,3,3,3,3.0,'eee'); @@ -38,168 +40,172 @@ endi if $data01 != 2.000000000 then print =====data01=$data01 - return -1 + goto loop1 endi if $data02 != 1.000000000 then print =====data02=$data02 - return -1 + goto loop1 endi if $data03 != ccc then print =====data03=$data03 - return -1 + goto loop1 endi if $data04 != 1 then print =====data04=$data04 - return -1 + goto loop1 endi if $data11 != 4.000000000 then print =====data11=$data11 - return -1 + goto loop1 endi + if $data12 != 2.000000000 then print =====data12=$data12 - return -1 + goto loop1 endi + if $data13 != NULL then print =====data13=$data13 - return -1 + goto loop1 endi if $data21 != 6.000000000 then print =====data21=$data21 - return -1 + goto loop1 endi if $data22 != 3.000000000 then print =====data22=$data22 - return -1 + goto loop1 endi if $data23 != NULL then print =====data23=$data23 - return -1 + goto loop1 endi if $data31 != 8.000000000 then print =====data31=$data31 - return -1 + goto loop1 endi if $data32 != 4.000000000 then print =====data32=$data32 - return -1 + goto loop1 endi if $data33 != aaa then print =====data33=$data33 - return -1 + goto loop1 endi if $data41 != 8.666666667 then print =====data41=$data41 - return -1 + goto loop1 endi if $data42 != 4.333333333 then print =====data42=$data42 - return -1 + goto loop1 endi if $data43 != NULL then print =====data43=$data43 - return -1 + goto loop1 endi if $data51 != 9.333333333 then print =====data01=$data01 - return -1 + goto loop1 endi if $data52 != 4.666666667 then print =====data52=$data52 - return -1 + goto loop1 endi if $data53 != NULL then print =====data53=$data53 - return -1 + goto loop1 endi if $data61 != 10.000000000 then print =====data61=$data61 - return -1 + goto loop1 endi if $data62 != 5.000000000 then print =====data62=$data62 - return -1 + goto loop1 endi if $data71 != 8.000000000 then print =====data71=$data71 - return -1 + goto loop1 endi if $data72 != 4.000000000 then print =====data72=$data72 - return -1 + goto loop1 endi if $data81 != 6.000000000 then print =====data81=$data81 - return -1 + goto loop1 endi if $data82 != 3.000000000 then print =====data82=$data82 - return -1 + goto loop1 endi if $data91 != 4.000000000 then print =====data91=$data91 - return -1 + goto loop1 endi if $data92 != 2.000000000 then print =====data92=$data92 - return -1 + goto loop1 endi if $data[10][1] != 4.666666667 then print =====data[10][1]=$data[10][1] - return -1 + goto loop1 endi if $data[10][2] != 2.333333333 then print =====data[10][2]=$data[10][2] - return -1 + goto loop1 endi if $data[11][1] != 5.333333333 then print =====data[11][1]=$data[11][1] - return -1 + goto loop1 endi if $data[11][2] != 2.666666667 then print =====data[11][2]=$data[11][2] - return -1 + goto loop1 endi if $data[12][1] != 6.000000000 then print =====data[12][1]=$data[12][1] - return -1 + goto loop1 endi if $data[12][2] != 3.000000000 then print =====data[12][2]=$data[12][2] - return -1 + goto loop1 endi +print step 1 end +print step 2 start sql drop stream if exists streams2; sql drop database if exists test2; sql create database test2 vgroups 1; sql use test2; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams2 trigger at_once into streamt2 as select _wstart as ts, max(a)+sum(c), avg(b), first(s), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt2 as select _wstart as ts, max(a)+sum(c), avg(b), first(s), count(*) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(linear); sql insert into t1 values(1648791210000,1,1,1,1.0,'ccc') (1648791219000,2,2,2,2.0,'ddd') (1648791222000,3,3,3,3.0,'eee'); sql insert into t1 values(1648791213000,4,4,4,4.0,'aaa') (1648791216000,5,5,5,5.0,'bbb'); @@ -224,168 +230,170 @@ endi if $data01 != 2.000000000 then print =====data01=$data01 - return -1 + goto loop2 endi if $data02 != 1.000000000 then print =====data02=$data02 - return -1 + goto loop2 endi if $data03 != ccc then print =====data03=$data03 - return -1 + goto loop2 endi if $data04 != 1 then print =====data04=$data04 - return -1 + goto loop2 endi if $data11 != 4.000000000 then print =====data11=$data11 - return -1 + goto loop2 endi if $data12 != 2.000000000 then print =====data12=$data12 - return -1 + goto loop2 endi if $data13 != NULL then print =====data13=$data13 - return -1 + goto loop2 endi if $data21 != 6.000000000 then print =====data21=$data21 - return -1 + goto loop2 endi if $data22 != 3.000000000 then print =====data22=$data22 - return -1 + goto loop2 endi if $data23 != NULL then print =====data23=$data23 - return -1 + goto loop2 endi if $data31 != 8.000000000 then print =====data31=$data31 - return -1 + goto loop2 endi if $data32 != 4.000000000 then print =====data32=$data32 - return -1 + goto loop2 endi if $data33 != aaa then print =====data33=$data33 - return -1 + goto loop2 endi if $data41 != 8.666666667 then print =====data41=$data41 - return -1 + goto loop2 endi if $data42 != 4.333333333 then print =====data42=$data42 - return -1 + goto loop2 endi if $data43 != NULL then print =====data43=$data43 - return -1 + goto loop2 endi if $data51 != 9.333333333 then print =====data01=$data01 - return -1 + goto loop2 endi if $data52 != 4.666666667 then print =====data52=$data52 - return -1 + goto loop2 endi if $data53 != NULL then print =====data53=$data53 - return -1 + goto loop2 endi if $data61 != 10.000000000 then print =====data61=$data61 - return -1 + goto loop2 endi if $data62 != 5.000000000 then print =====data62=$data62 - return -1 + goto loop2 endi if $data71 != 8.000000000 then print =====data71=$data71 - return -1 + goto loop2 endi if $data72 != 4.000000000 then print =====data72=$data72 - return -1 + goto loop2 endi if $data81 != 6.000000000 then print =====data81=$data81 - return -1 + goto loop2 endi if $data82 != 3.000000000 then print =====data82=$data82 - return -1 + goto loop2 endi if $data91 != 4.000000000 then print =====data91=$data91 - return -1 + goto loop2 endi if $data92 != 2.000000000 then print =====data92=$data92 - return -1 + goto loop2 endi if $data[10][1] != 4.666666667 then print =====data[10][1]=$data[10][1] - return -1 + goto loop2 endi if $data[10][2] != 2.333333333 then print =====data[10][2]=$data[10][2] - return -1 + goto loop2 endi if $data[11][1] != 5.333333333 then print =====data[11][1]=$data[11][1] - return -1 + goto loop2 endi if $data[11][2] != 2.666666667 then print =====data[11][2]=$data[11][2] - return -1 + goto loop2 endi if $data[12][1] != 6.000000000 then print =====data[12][1]=$data[12][1] - return -1 + goto loop2 endi if $data[12][2] != 3.000000000 then print =====data[12][2]=$data[12][2] - return -1 + goto loop2 endi +print step 2 end +print step 3 start sql drop stream if exists streams3; sql drop database if exists test3; sql create database test3 vgroups 1; sql use test3; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams3 trigger at_once into streamt3 as select _wstart as ts, max(a), b+c, s, b+1, 1 from t1 where ts >= 1648791150000 and ts < 1648791261000 interval(1s) fill(linear); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart as ts, max(a), b+c, s, b+1, 1 from t1 where ts >= 1648791150000 and ts < 1648791261000 interval(1s) fill(linear); sql insert into t1 values(1648791215000,1,1,1,1.0,'aaa'); sql insert into t1 values(1648791217000,2,2,2,2.0,'bbb'); sql insert into t1 values(1648791211000,3,3,3,3.0,'ccc'); @@ -412,98 +420,98 @@ endi if $data01 != 3 then print =====data01=$data01 - return -1 + goto loop3 endi if $data02 != 6.000000000 then print =====data02=$data02 - return -1 + goto loop3 endi if $data03 != ccc then print =====data03=$data03 - return -1 + goto loop3 endi if $data11 != 3 then print =====data11=$data11 - return -1 + goto loop3 endi if $data12 != 7.000000000 then print =====data12=$data12 - return -1 + goto loop3 endi if $data13 != NULL then print =====data13=$data13 - return -1 + goto loop3 endi if $data21 != 4 then print =====data21=$data21 - return -1 + goto loop3 endi if $data22 != 8.000000000 then print =====data22=$data22 - return -1 + goto loop3 endi if $data23 != ddd then print =====data23=$data23 - return -1 + goto loop3 endi if $data31 != 2 then print =====data31=$data31 - return -1 + goto loop3 endi if $data32 != 5.000000000 then print =====data32=$data32 - return -1 + goto loop3 endi if $data33 != NULL then print =====data33=$data33 - return -1 + goto loop3 endi if $data41 != 1 then print =====data41=$data41 - return -1 + goto loop3 endi if $data42 != 2.000000000 then print =====data42=$data42 - return -1 + goto loop3 endi if $data43 != aaa then print =====data43=$data43 - return -1 + goto loop3 endi if $data51 != 1 then print =====data51=$data51 - return -1 + goto loop3 endi if $data52 != 3.000000000 then print =====data52=$data52 - return -1 + goto loop3 endi if $data53 != NULL then print =====data53=$data53 - return -1 + goto loop3 endi if $data61 != 2 then print =====data61=$data61 - return -1 + goto loop3 endi if $data62 != 4.000000000 then print =====data62=$data62 - return -1 + goto loop3 endi if $data63 != bbb then print =====data63=$data63 - return -1 + goto loop3 endi @@ -534,42 +542,42 @@ endi if $data01 != 6 then print =====data01=$data01 - return -1 + goto loop4 endi if $data02 != 12.000000000 then print =====data02=$data02 - return -1 + goto loop4 endi if $data03 != fff then print =====data03=$data03 - return -1 + goto loop4 endi if $data11 != 6 then print =====data11=$data11 - return -1 + goto loop4 endi if $data12 != 13.000000000 then print =====data12=$data12 - return -1 + goto loop4 endi if $data13 != NULL then print =====data13=$data13 - return -1 + goto loop4 endi if $data21 != 7 then print =====data21=$data21 - return -1 + goto loop4 endi if $data22 != 14.000000000 then print =====data22=$data22 - return -1 + goto loop4 endi if $data23 != ggg then print =====data23=$data23 - return -1 + goto loop4 endi @@ -626,33 +634,10 @@ if $data[12][3] != hhh then return -1 endi -if $data[13][1] != 8 then - print =====data[13][1]=$data[13][1] - return -1 -endi -if $data[13][2] != 17.000000000 then - print =====data[13][2]=$data[13][2] - return -1 -endi -if $data[13][3] != NULL then - print =====data[13][3]=$data[13][3] - return -1 -endi -if $data[14][1] != 9 then - print =====data[14][1]=$data[14][1] - return -1 -endi -if $data[14][2] != 18.000000000 then - print =====data[14][2]=$data[14][2] - return -1 -endi -if $data[14][3] != iii then - print =====data[14][3]=$data[14][3] - return -1 -endi +print step 3 end diff --git a/tests/script/tsim/stream/fillIntervalPartitionBy.sim b/tests/script/tsim/stream/fillIntervalPartitionBy.sim index 8c06ca8bbdfe5ffd99ea81513a56827f5f22376d..6a11b9952c9126810d9b6431c36e09ccf7f14894 100644 --- a/tests/script/tsim/stream/fillIntervalPartitionBy.sim +++ b/tests/script/tsim/stream/fillIntervalPartitionBy.sim @@ -18,11 +18,11 @@ sql use test1; sql create stable st(ts timestamp, a int, b int , c int, d double, s varchar(20)) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams1 trigger at_once into streamt1 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(NULL); -sql create stream streams2 trigger at_once into streamt2 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(value,100,200,300); -sql create stream streams3 trigger at_once into streamt3 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(next); -sql create stream streams4 trigger at_once into streamt4 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(prev); -sql create stream streams5 trigger at_once into streamt5 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(linear); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(NULL); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt2 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(value,100,200,300); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(next); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(prev); +sql create stream streams5 trigger at_once IGNORE EXPIRED 0 into streamt5 as select _wstart as ts, max(a) c1, sum(b), count(*) from st where ts >= 1648791210000 and ts < 1648791261000 partition by ta interval(1s) fill(linear); sql insert into t1 values(1648791210000,0,0,0,0.0,'aaa'); sql insert into t1 values(1648791213000,1,1,1,1.0,'bbb'); @@ -149,7 +149,7 @@ endi if $data04 == 0 then print ====streamt1=data04=$data04 - return -1 + goto loop4 endi sql select group_id,count(*) from streamt1 group by group_id; @@ -168,7 +168,7 @@ endi if $data04 == 0 then print ====streamt2=data04=$data04 - return -1 + goto loop4 endi sql select group_id,count(*) from streamt2 group by group_id; @@ -187,7 +187,7 @@ endi if $data04 == 0 then print ====streamt3=data04=$data04 - return -1 + goto loop4 endi sql select group_id,count(*) from streamt3 group by group_id; @@ -207,7 +207,7 @@ endi if $data04 == 0 then print ====streamt4=data04=$data04 - return -1 + goto loop4 endi sql select group_id,count(*) from streamt4 group by group_id; @@ -226,7 +226,7 @@ endi if $data04 == 0 then print ====streamt5=data04=$data04 - return -1 + goto loop4 endi sql select group_id,count(*) from streamt5 group by group_id; diff --git a/tests/script/tsim/stream/fillIntervalPrevNext.sim b/tests/script/tsim/stream/fillIntervalPrevNext.sim index 4eadd7e7b1b976bcd7b78b5a4a3ec37de6a5549d..ec963e1d4a8dd02e8ac1aaa01ac415d82bb2ecfc 100644 --- a/tests/script/tsim/stream/fillIntervalPrevNext.sim +++ b/tests/script/tsim/stream/fillIntervalPrevNext.sim @@ -15,8 +15,8 @@ sql drop database if exists test1; sql create database test1 vgroups 1; sql use test1; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams1 trigger at_once into streamt1 as select _wstart as ts, count(*) c1, max(b)+sum(a) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); -sql create stream streams2 trigger at_once into streamt2 as select _wstart as ts, count(*) c1, max(a)+min(c), avg(b) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart as ts, count(*) c1, max(b)+sum(a) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt2 as select _wstart as ts, count(*) c1, max(a)+min(c), avg(b) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); sql insert into t1 values(1648791213000,4,4,4,4.0,'aaa') (1648791215000,5,5,5,5.0,'aaa'); sql insert into t1 values(1648791211000,1,1,1,1.0,'aaa') (1648791217000,2,2,2,2.0,'aaa') (1648791220000,3,3,3,3.0,'aaa'); @@ -228,31 +228,31 @@ endi if $data72 != 6.000000000 then print =====data72=$data72 - return -1 + goto loop1 endi if $data73 != 3.000000000 then print =====data73=$data73 - return -1 + goto loop1 endi if $data82 != 6.000000000 then print =====data82=$data82 - return -1 + goto loop1 endi if $data83 != 3.000000000 then print =====data83=$data83 - return -1 + goto loop1 endi if $data92 != 6.000000000 then print =====data92=$data92 - return -1 + goto loop1 endi if $data93 != 3.000000000 then print =====data93=$data93 - return -1 + goto loop1 endi @@ -263,8 +263,8 @@ sql drop database if exists test5; sql create database test5 vgroups 1; sql use test5; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams5 trigger at_once into streamt5 as select _wstart as ts, count(*) c1, max(b)+sum(a) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); -sql create stream streams6 trigger at_once into streamt6 as select _wstart as ts, count(*) c1, max(a)+min(c), avg(b) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); +sql create stream streams5 trigger at_once IGNORE EXPIRED 0 into streamt5 as select _wstart as ts, count(*) c1, max(b)+sum(a) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(prev); +sql create stream streams6 trigger at_once IGNORE EXPIRED 0 into streamt6 as select _wstart as ts, count(*) c1, max(a)+min(c), avg(b) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(next); sql insert into t1 values(1648791211000,1,1,1,1.0,'aaa') (1648791217000,2,2,2,2.0,'aaa') (1648791220000,3,3,3,3.0,'aaa'); sql insert into t1 values(1648791213000,4,4,4,4.0,'aaa') (1648791215000,5,5,5,5.0,'aaa'); @@ -483,535 +483,33 @@ endi if $data72 != 6.000000000 then print =====data72=$data72 - return -1 + goto loop6 endi if $data73 != 3.000000000 then print =====data73=$data73 - return -1 + goto loop6 endi if $data82 != 6.000000000 then print =====data82=$data82 - return -1 + goto loop6 endi if $data83 != 3.000000000 then print =====data83=$data83 - return -1 + goto loop6 endi if $data92 != 6.000000000 then print =====data92=$data92 - return -1 + goto loop6 endi if $data93 != 3.000000000 then print =====data93=$data93 - return -1 -endi - - - -sql drop stream if exists streams7; -sql drop stream if exists streams8; -sql drop database if exists test7; -sql create database test7 vgroups 1; -sql use test7; -sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams7 trigger at_once into streamt7 as select _wstart as ts, max(a), b+c, s from t1 where ts >= 1648791150000 and ts < 1648791261000 interval(1s) fill(prev); -sql create stream streams8 trigger at_once into streamt8 as select _wstart as ts, max(a), 1, b+1 from t1 where ts >= 1648791150000 and ts < 1648791261000 interval(1s) fill(next); -sql insert into t1 values(1648791215000,1,1,1,1.0,'aaa'); -sql insert into t1 values(1648791217000,2,2,2,2.0,'bbb'); -sql insert into t1 values(1648791211000,3,3,3,3.0,'ccc'); -sql insert into t1 values(1648791213000,4,4,4,4.0,'ddd'); - - -$loop_count = 0 - -loop7: -sleep 300 -sql select * from streamt7 order by ts; - -$loop_count = $loop_count + 1 -if $loop_count == 10 then - return -1 -endi - - -if $rows != 7 then - print =====rows=$rows - goto loop7 -endi - - -if $data01 != 3 then - print =====data01=$data01 - return -1 -endi -if $data02 != 6.000000000 then - print =====data02=$data02 - return -1 -endi -if $data03 != ccc then - print =====data03=$data03 - return -1 -endi - -if $data11 != 3 then - print =====data11=$data11 - return -1 -endi -if $data12 != 6.000000000 then - print =====data12=$data12 - return -1 -endi -if $data13 != ccc then - print =====data13=$data13 - return -1 -endi - - -if $data21 != 4 then - print =====data21=$data21 - return -1 -endi -if $data22 != 8.000000000 then - print =====data22=$data22 - return -1 -endi -if $data23 != ddd then - print =====data23=$data23 - return -1 -endi - - -if $data31 != 4 then - print =====data31=$data31 - return -1 -endi -if $data32 != 8.000000000 then - print =====data32=$data32 - return -1 -endi -if $data33 != ddd then - print =====data33=$data33 - return -1 -endi - - -if $data41 != 1 then - print =====data41=$data41 - return -1 -endi -if $data42 != 2.000000000 then - print =====data42=$data42 - return -1 -endi -if $data43 != aaa then - print =====data43=$data43 - return -1 -endi - - -if $data51 != 1 then - print =====data51=$data51 - return -1 -endi -if $data52 != 2.000000000 then - print =====data52=$data52 - return -1 -endi -if $data53 != aaa then - print =====data53=$data53 - return -1 -endi - - -if $data61 != 2 then - print =====data61=$data61 - return -1 -endi -if $data62 != 4.000000000 then - print =====data62=$data62 - return -1 -endi -if $data63 != bbb then - print =====data63=$data63 - return -1 -endi - -#-------------- - -sleep 200 -sql select * from streamt8 order by ts; - - -if $rows != 7 then - print =====rows=$rows - return -1 -endi - - -if $data01 != 3 then - print =====data01=$data01 - return -1 -endi -if $data02 != 1 then - print =====data02=$data02 - return -1 -endi -if $data03 != 4.000000000 then - print =====data03=$data03 - return -1 -endi - -if $data11 != 4 then - print =====data11=$data11 - return -1 -endi -if $data12 != 1 then - print =====data12=$data12 - return -1 -endi -if $data13 != 5.000000000 then - print =====data13=$data13 - return -1 -endi - - -if $data21 != 4 then - print =====data21=$data21 - return -1 -endi -if $data22 != 1 then - print =====data22=$data22 - return -1 -endi -if $data23 != 5.000000000 then - print =====data23=$data23 - return -1 -endi - - -if $data31 != 1 then - print =====data31=$data31 - return -1 -endi -if $data32 != 1 then - print =====data32=$data32 - return -1 -endi -if $data33 != 2.000000000 then - print =====data33=$data33 - return -1 -endi - - -if $data41 != 1 then - print =====data41=$data41 - return -1 -endi -if $data42 != 1 then - print =====data42=$data42 - return -1 -endi -if $data43 != 2.000000000 then - print =====data43=$data43 - return -1 -endi - - -if $data51 != 2 then - print =====data51=$data51 - return -1 -endi -if $data52 != 1 then - print =====data52=$data52 - return -1 -endi -if $data53 != 3.000000000 then - print =====data53=$data53 - return -1 -endi - - -if $data61 != 2 then - print =====data61=$data61 - return -1 -endi -if $data62 != 1 then - print =====data62=$data62 - return -1 -endi -if $data63 != 3.000000000 then - print =====data63=$data63 - return -1 -endi - -sql insert into t1 values(1648791212000,5,5,5,5.0,'eee'); -sql insert into t1 values(1648791207000,6,6,6,6.0,'fff') (1648791209000,7,7,7,7.0,'ggg') (1648791219000,8,8,8,8.0,'hhh') (1648791221000,9,9,9,9.0,'iii'); - - - -$loop_count = 0 - -loop8: -sleep 200 -sql select * from streamt7 order by ts; - -$loop_count = $loop_count + 1 -if $loop_count == 10 then - return -1 -endi - - -if $rows != 15 then - print =====rows=$rows - goto loop8 -endi - - -if $data01 != 6 then - print =====data01=$data01 - return -1 -endi -if $data02 != 12.000000000 then - print =====data02=$data02 - return -1 -endi -if $data03 != fff then - print =====data03=$data03 - return -1 -endi - -if $data11 != 6 then - print =====data11=$data11 - return -1 -endi -if $data12 != 12.000000000 then - print =====data12=$data12 - return -1 -endi -if $data13 != fff then - print =====data13=$data13 - return -1 -endi - - -if $data21 != 7 then - print =====data21=$data21 - return -1 -endi -if $data22 != 14.000000000 then - print =====data22=$data22 - return -1 -endi -if $data23 != ggg then - print =====data23=$data23 - return -1 -endi - - -if $data31 != 7 then - print =====data31=$data31 - return -1 -endi -if $data32 != 14.000000000 then - print =====data32=$data32 - return -1 -endi -if $data33 != ggg then - print =====data33=$data33 - return -1 -endi - -if $data51 != 5 then - print =====data51=$data51 - return -1 -endi -if $data52 != 10.000000000 then - print =====data52=$data52 - return -1 -endi -if $data53 != eee then - print =====data53=$data53 - return -1 -endi - - -if $data[11][1] != 2 then - print =====data[11][1]=$data[11][1] - return -1 -endi -if $data[11][2] != 4.000000000 then - print =====data[11][2]=$data[11][2] - return -1 -endi -if $data[11][3] != bbb then - print =====data[11][3]=$data[11][3] - return -1 -endi - -if $data[12][1] != 8 then - print =====data[12][1]=$data[12][1] - return -1 -endi -if $data[12][2] != 16.000000000 then - print =====data[12][2]=$data[12][2] - return -1 -endi -if $data[12][3] != hhh then - print =====data[12][3]=$data[12][3] - return -1 -endi - -if $data[13][1] != 8 then - print =====data[13][1]=$data[13][1] - return -1 -endi -if $data[13][2] != 16.000000000 then - print =====data[13][2]=$data[13][2] - return -1 -endi -if $data[13][3] != hhh then - print =====data[13][3]=$data[13][3] - return -1 -endi - -if $data[14][1] != 9 then - print =====data[14][1]=$data[14][1] - return -1 -endi -if $data[14][2] != 18.000000000 then - print =====data[14][2]=$data[14][2] - return -1 -endi -if $data[14][3] != iii then - print =====data[14][3]=$data[14][3] - return -1 -endi - -print fill next-----------------890 -sql use test7; -sql select * from streamt8 order by ts; - -if $rows != 15 then - print =====rows=$rows - goto loop8 -endi - - -if $data01 != 6 then - print =====data01=$data01 - return -1 -endi -if $data02 != 1 then - print =====data02=$data02 - return -1 -endi -if $data03 != 7.000000000 then - print =====data03=$data03 - return -1 -endi - -if $data11 != 7 then - print =====data11=$data11 - return -1 -endi -if $data13 != 8.000000000 then - print =====data13=$data13 - return -1 -endi - - -if $data21 != 7 then - print =====data21=$data21 - return -1 -endi -if $data23 != 8.000000000 then - print =====data23=$data23 - return -1 -endi - - -if $data31 != 3 then - print =====data31=$data31 - return -1 -endi -if $data33 != 4.000000000 then - print =====data33=$data33 - return -1 -endi - -if $data51 != 5 then - print =====data51=$data51 - return -1 -endi -if $data53 != 6.000000000 then - print =====data53=$data53 - return -1 -endi - - -if $data[11][1] != 8 then - print =====data[11][1]=$data[11][1] - return -1 -endi -if $data[11][2] != 1 then - print =====data[11][2]=$data[11][2] - return -1 -endi -if $data[11][3] != 9.000000000 then - print =====data[11][3]=$data[11][3] - return -1 -endi - -if $data[12][1] != 8 then - print =====data[12][1]=$data[12][1] - return -1 -endi -if $data[12][3] != 9.000000000 then - print =====data[12][3]=$data[12][3] - return -1 -endi - -if $data[13][1] != 9 then - print =====data[13][1]=$data[13][1] - return -1 -endi -if $data[13][3] != 10.000000000 then - print =====data[13][3]=$data[13][3] - return -1 -endi - -if $data[14][1] != 9 then - print =====data[14][1]=$data[14][1] - return -1 -endi -if $data[14][3] != 10.000000000 then - print =====data[14][3]=$data[14][3] - return -1 + goto loop6 endi - - - - - - - - - - - - - - - - - - - #==system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/stream/fillIntervalPrevNext1.sim b/tests/script/tsim/stream/fillIntervalPrevNext1.sim new file mode 100644 index 0000000000000000000000000000000000000000..40ef895c5af3253f7dae61623c6c1b0f5741850d --- /dev/null +++ b/tests/script/tsim/stream/fillIntervalPrevNext1.sim @@ -0,0 +1,559 @@ +$loop_all = 0 +looptest: + +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +#==system sh/exec.sh -n dnode1 -s start -v + +sleep 200 +sql connect + + +sql drop stream if exists streams7; +sql drop stream if exists streams8; +sql drop database if exists test7; +sql create database test7 vgroups 1; +sql use test7; +sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); +sql create stream streams7 trigger at_once IGNORE EXPIRED 0 into streamt7 as select _wstart as ts, max(a), b+c, s from t1 where ts >= 1648791150000 and ts < 1648791261000 interval(1s) fill(prev); +sql create stream streams8 trigger at_once IGNORE EXPIRED 0 into streamt8 as select _wstart as ts, max(a), 1, b+1 from t1 where ts >= 1648791150000 and ts < 1648791261000 interval(1s) fill(next); +sql insert into t1 values(1648791215000,1,1,1,1.0,'aaa'); +sql insert into t1 values(1648791217000,2,2,2,2.0,'bbb'); +sql insert into t1 values(1648791211000,3,3,3,3.0,'ccc'); +sql insert into t1 values(1648791213000,4,4,4,4.0,'ddd'); + + +$loop_count = 0 + +loop7: +sleep 300 +sql select * from streamt7 order by ts; + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + + +if $rows != 7 then + print =====rows=$rows + goto loop7 +endi + + +if $data01 != 3 then + print =====data01=$data01 + goto loop7 +endi +if $data02 != 6.000000000 then + print =====data02=$data02 + goto loop7 +endi +if $data03 != ccc then + print =====data03=$data03 + goto loop7 +endi + +if $data11 != 3 then + print =====data11=$data11 + goto loop7 +endi +if $data12 != 6.000000000 then + print =====data12=$data12 + goto loop7 +endi +if $data13 != ccc then + print =====data13=$data13 + goto loop7 +endi + + +if $data21 != 4 then + print =====data21=$data21 + goto loop7 +endi +if $data22 != 8.000000000 then + print =====data22=$data22 + goto loop7 +endi +if $data23 != ddd then + print =====data23=$data23 + goto loop7 +endi + + +if $data31 != 4 then + print =====data31=$data31 + goto loop7 +endi +if $data32 != 8.000000000 then + print =====data32=$data32 + goto loop7 +endi +if $data33 != ddd then + print =====data33=$data33 + goto loop7 +endi + + +if $data41 != 1 then + print =====data41=$data41 + goto loop7 +endi +if $data42 != 2.000000000 then + print =====data42=$data42 + goto loop7 +endi +if $data43 != aaa then + print =====data43=$data43 + goto loop7 +endi + + +if $data51 != 1 then + print =====data51=$data51 + goto loop7 +endi +if $data52 != 2.000000000 then + print =====data52=$data52 + goto loop7 +endi +if $data53 != aaa then + print =====data53=$data53 + goto loop7 +endi + + +if $data61 != 2 then + print =====data61=$data61 + goto loop7 +endi +if $data62 != 4.000000000 then + print =====data62=$data62 + goto loop7 +endi +if $data63 != bbb then + print =====data63=$data63 + goto loop7 +endi + +#-------------- + +loop71: + +$loop_count = 0 +sleep 300 + +sql select * from streamt8 order by ts; + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +if $rows != 7 then + print =====rows=$rows + goto loop71 +endi + + +if $data01 != 3 then + print =====data01=$data01 + goto loop71 +endi +if $data02 != 1 then + print =====data02=$data02 + goto loop71 +endi +if $data03 != 4.000000000 then + print =====data03=$data03 + goto loop71 +endi + +if $data11 != 4 then + print =====data11=$data11 + goto loop71 +endi +if $data12 != 1 then + print =====data12=$data12 + goto loop71 +endi +if $data13 != 5.000000000 then + print =====data13=$data13 + goto loop71 +endi + + +if $data21 != 4 then + print =====data21=$data21 + goto loop71 +endi +if $data22 != 1 then + print =====data22=$data22 + goto loop71 +endi +if $data23 != 5.000000000 then + print =====data23=$data23 + goto loop71 +endi + + +if $data31 != 1 then + print =====data31=$data31 + goto loop71 +endi +if $data32 != 1 then + print =====data32=$data32 + goto loop71 +endi +if $data33 != 2.000000000 then + print =====data33=$data33 + goto loop71 +endi + + +if $data41 != 1 then + print =====data41=$data41 + goto loop71 +endi +if $data42 != 1 then + print =====data42=$data42 + goto loop71 +endi +if $data43 != 2.000000000 then + print =====data43=$data43 + goto loop71 +endi + + +if $data51 != 2 then + print =====data51=$data51 + goto loop71 +endi +if $data52 != 1 then + print =====data52=$data52 + goto loop71 +endi +if $data53 != 3.000000000 then + print =====data53=$data53 + goto loop71 +endi + + +if $data61 != 2 then + print =====data61=$data61 + goto loop71 +endi +if $data62 != 1 then + print =====data62=$data62 + goto loop71 +endi +if $data63 != 3.000000000 then + print =====data63=$data63 + goto loop71 +endi + +sql insert into t1 values(1648791212000,5,5,5,5.0,'eee'); +sql insert into t1 values(1648791207000,6,6,6,6.0,'fff') (1648791209000,7,7,7,7.0,'ggg') (1648791219000,8,8,8,8.0,'hhh') (1648791221000,9,9,9,9.0,'iii'); + + + +$loop_count = 0 + +loop8: +sleep 200 +sql select * from streamt7 order by ts; + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + + +if $rows != 15 then + print =====rows=$rows + goto loop8 +endi + + +if $data01 != 6 then + print =====data01=$data01 + goto loop8 +endi +if $data02 != 12.000000000 then + print =====data02=$data02 + goto loop8 +endi +if $data03 != fff then + print =====data03=$data03 + goto loop8 +endi + +if $data11 != 6 then + print =====data11=$data11 + goto loop8 +endi +if $data12 != 12.000000000 then + print =====data12=$data12 + goto loop8 +endi +if $data13 != fff then + print =====data13=$data13 + goto loop8 +endi + + +if $data21 != 7 then + print =====data21=$data21 + goto loop8 +endi +if $data22 != 14.000000000 then + print =====data22=$data22 + goto loop8 +endi +if $data23 != ggg then + print =====data23=$data23 + goto loop8 +endi + + +if $data31 != 7 then + print =====data31=$data31 + goto loop8 +endi +if $data32 != 14.000000000 then + print =====data32=$data32 + goto loop8 +endi +if $data33 != ggg then + print =====data33=$data33 + goto loop8 +endi + +if $data51 != 5 then + print =====data51=$data51 + goto loop8 +endi +if $data52 != 10.000000000 then + print =====data52=$data52 + goto loop8 +endi +if $data53 != eee then + print =====data53=$data53 + goto loop8 +endi + + +if $data[11][1] != 2 then + print =====data[11][1]=$data[11][1] + goto loop8 +endi +if $data[11][2] != 4.000000000 then + print =====data[11][2]=$data[11][2] + goto loop8 +endi +if $data[11][3] != bbb then + print =====data[11][3]=$data[11][3] + goto loop8 +endi + +if $data[12][1] != 8 then + print =====data[12][1]=$data[12][1] + goto loop8 +endi +if $data[12][2] != 16.000000000 then + print =====data[12][2]=$data[12][2] + goto loop8 +endi +if $data[12][3] != hhh then + print =====data[12][3]=$data[12][3] + goto loop8 +endi + +if $data[13][1] != 8 then + print =====data[13][1]=$data[13][1] + goto loop8 +endi +if $data[13][2] != 16.000000000 then + print =====data[13][2]=$data[13][2] + goto loop8 +endi +if $data[13][3] != hhh then + print =====data[13][3]=$data[13][3] + goto loop8 +endi + +if $data[14][1] != 9 then + print =====data[14][1]=$data[14][1] + goto loop8 +endi +if $data[14][2] != 18.000000000 then + print =====data[14][2]=$data[14][2] + goto loop8 +endi +if $data[14][3] != iii then + print =====data[14][3]=$data[14][3] + goto loop8 +endi + +print fill next-----------------890 +sql use test7; +sql select * from streamt8 order by ts; + +if $rows != 15 then + print =====rows=$rows + goto loop8 +endi + + +if $data01 != 6 then + print =====data01=$data01 + goto loop8 +endi +if $data02 != 1 then + print =====data02=$data02 + goto loop8 +endi +if $data03 != 7.000000000 then + print =====data03=$data03 + goto loop8 +endi + +if $data11 != 7 then + print =====data11=$data11 + goto loop8 +endi +if $data13 != 8.000000000 then + print =====data13=$data13 + goto loop8 +endi + + +if $data21 != 7 then + print =====data21=$data21 + goto loop8 +endi +if $data23 != 8.000000000 then + print =====data23=$data23 + goto loop8 +endi + + +if $data31 != 3 then + print =====data31=$data31 + goto loop8 +endi +if $data33 != 4.000000000 then + print =====data33=$data33 + goto loop8 +endi + +if $data51 != 5 then + print =====data51=$data51 + goto loop8 +endi +if $data53 != 6.000000000 then + print =====data53=$data53 + goto loop8 +endi + + +if $data[11][1] != 8 then + print =====data[11][1]=$data[11][1] + goto loop8 +endi +if $data[11][2] != 1 then + print =====data[11][2]=$data[11][2] + goto loop8 +endi +if $data[11][3] != 9.000000000 then + print =====data[11][3]=$data[11][3] + goto loop8 +endi + +if $data[12][1] != 8 then + print =====data[12][1]=$data[12][1] + goto loop8 +endi +if $data[12][3] != 9.000000000 then + print =====data[12][3]=$data[12][3] + goto loop8 +endi + +if $data[13][1] != 9 then + print =====data[13][1]=$data[13][1] + goto loop8 +endi +if $data[13][3] != 10.000000000 then + print =====data[13][3]=$data[13][3] + goto loop8 +endi + +if $data[14][1] != 9 then + print =====data[14][1]=$data[14][1] + goto loop8 +endi +if $data[14][3] != 10.000000000 then + print =====data[14][3]=$data[14][3] + goto loop8 +endi + + + + + + + + + + + + + + + + + + + + + + +#==system sh/exec.sh -n dnode1 -s stop -x SIGINT +#==print =============== check +#==$null= + +#==system_content sh/checkValgrind.sh -n dnode1 +#==print cmd return result ----> [ $system_content ] +#==if $system_content > 0 then +#== return -1 +#==endi + +#==if $system_content == $null then +#== return -1 +#==endi +#==return 1 + + + +sql drop stream if exists streams0; +sql drop stream if exists streams1; +sql drop stream if exists streams2; +sql drop stream if exists streams3; +sql drop stream if exists streams4; +sql drop stream if exists streams5; +sql drop stream if exists streams6; +sql drop stream if exists streams7; +sql drop stream if exists streams8; + +sql use test7; +sql select * from t1; +print $data00 + +$loop_all = $loop_all + 1 +print ============loop_all=$loop_all + +system sh/stop_dnodes.sh + +#goto looptest \ No newline at end of file diff --git a/tests/script/tsim/stream/fillIntervalRange.sim b/tests/script/tsim/stream/fillIntervalRange.sim index a0905141f2bed1230abd3f51acc867aed19d1c45..0e0dfb46d88c3102fffc3a467307863ea40fc1a4 100644 --- a/tests/script/tsim/stream/fillIntervalRange.sim +++ b/tests/script/tsim/stream/fillIntervalRange.sim @@ -13,7 +13,7 @@ sql create database test vgroups 1; sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20));; -sql create stream streams1 trigger at_once into streamt as select _wstart ts, count(*) c1 from t1 interval(1s) fill(NULL); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart ts, count(*) c1 from t1 interval(1s) fill(NULL); sql insert into t1 values(1648791211000,1,2,3,1.0,'aaa'); sleep 100 sql insert into t1 values(1648795308000,1,2,3,1.0,'aaa'); @@ -126,10 +126,10 @@ sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); print create stream streams1 trigger at_once into streamt as select _wstart ts, max(a) c1 from t1 interval(1s) fill(linear); -sql create stream streams1 trigger at_once into streamt as select _wstart ts, max(a) c1 from t1 interval(1s) fill(linear); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart ts, max(a) c1 from t1 interval(1s) fill(linear); print create stream streams2 trigger at_once into streamt2 as select _wstart ts, max(a) c1 from t1 interval(1s) fill(prev); -sql create stream streams2 trigger at_once into streamt2 as select _wstart ts, max(a) c1 from t1 interval(1s) fill(prev); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt2 as select _wstart ts, max(a) c1 from t1 interval(1s) fill(prev); sql insert into t1 values(1648791211000,1,2,3,1.0,'aaa'); sleep 100 diff --git a/tests/script/tsim/stream/fillIntervalValue.sim b/tests/script/tsim/stream/fillIntervalValue.sim index 2cd419397fdb0230aacd8983c2c5b238e82ab673..b447e9a5594ccd85fc8a164fd9c6aa848c09b168 100644 --- a/tests/script/tsim/stream/fillIntervalValue.sim +++ b/tests/script/tsim/stream/fillIntervalValue.sim @@ -13,8 +13,8 @@ sql create database test vgroups 1; sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20));; -sql create stream streams1 trigger at_once into streamt as select _wstart ts, count(*) c1 from t1 where ts > 1648791210000 and ts < 1648791413000 interval(10s) fill(value, 100); -sql create stream streams1a trigger at_once into streamta as select _wstart ts, count(*) c1 from t1 where ts > 1648791210000 and ts < 1648791413000 interval(10s) fill(value_f, 100); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart ts, count(*) c1 from t1 where ts > 1648791210000 and ts < 1648791413000 interval(10s) fill(value, 100); +sql create stream streams1a trigger at_once IGNORE EXPIRED 0 into streamta as select _wstart ts, count(*) c1 from t1 where ts > 1648791210000 and ts < 1648791413000 interval(10s) fill(value_f, 100); sql insert into t1 values(1648791213000,1,2,3,1.0,'aaa'); sleep 100 sql insert into t1 values(1648791233000,1,2,3,1.0,'aaa'); @@ -146,7 +146,7 @@ sql drop database if exists test2; sql create database test2 vgroups 1; sql use test2; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams2 trigger at_once into streamt2 as select _wstart as ts, count(*) c1, max(b)+sum(a) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value, 100,200); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt2 as select _wstart as ts, count(*) c1, max(b)+sum(a) from t1 where ts >= 1648791210000 and ts < 1648791261000 interval(1s) fill(value, 100,200); sql insert into t1 values(1648791211000,1,1,1,1.0,'aaa') (1648791217000,2,2,2,2.0,'aaa') (1648791220000,3,3,3,3.0,'aaa'); sql insert into t1 values(1648791213000,4,4,4,4.0,'aaa') (1648791215000,5,5,5,5.0,'aaa'); @@ -280,7 +280,7 @@ sql drop database if exists test3; sql create database test3 vgroups 1; sql use test3; sql create table t1(ts timestamp, a int, b int , c int, d double, s varchar(20)); -sql create stream streams3 trigger at_once into streamt3 as select _wstart as ts, max(b), a+b, c from t1 where ts >= 1648791200000 and ts < 1648791261000 interval(10s) sliding(3s) fill(value, 100,200,300); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart as ts, max(b), a+b, c from t1 where ts >= 1648791200000 and ts < 1648791261000 interval(10s) sliding(3s) fill(value, 100,200,300); sql insert into t1 values(1648791220000,1,1,1,1.0,'aaa'); sleep 100 @@ -471,8 +471,8 @@ sql create stable st(ts timestamp,a int,b int,c int, d double, s varchar(20) ) t sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams4 trigger at_once into streamt4 as select _wstart ts, count(*) c1, concat(tbname, 'aaa') as pname, timezone() from st where ts > 1648791000000 and ts < 1648793000000 partition by tbname interval(10s) fill(NULL); -sql create stream streams4a trigger at_once into streamt4a as select _wstart ts, count(*) c1, concat(tbname, 'aaa') as pname, timezone() from st where ts > 1648791000000 and ts < 1648793000000 partition by tbname interval(10s) fill(NULL_F); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart ts, count(*) c1, concat(tbname, 'aaa') as pname, timezone() from st where ts > 1648791000000 and ts < 1648793000000 partition by tbname interval(10s) fill(NULL); +sql create stream streams4a trigger at_once IGNORE EXPIRED 0 into streamt4a as select _wstart ts, count(*) c1, concat(tbname, 'aaa') as pname, timezone() from st where ts > 1648791000000 and ts < 1648793000000 partition by tbname interval(10s) fill(NULL_F); sql insert into t1 values(1648791213000,1,2,3,1.0,'aaa'); sql insert into t1 values(1648791233000,1,2,3,1.0,'aaa'); sql insert into t1 values(1648791273000,1,2,3,1.0,'aaa'); diff --git a/tests/script/tsim/stream/ignoreCheckUpdate.sim b/tests/script/tsim/stream/ignoreCheckUpdate.sim index 7f99c534c8d5ffca96f9a394e330c33bf7500afb..2cd0117febdf4baa683489f2c2892dcfbe11f617 100644 --- a/tests/script/tsim/stream/ignoreCheckUpdate.sim +++ b/tests/script/tsim/stream/ignoreCheckUpdate.sim @@ -12,9 +12,9 @@ sql create database test vgroups 1; sql use test; sql create table t1(ts timestamp, a int, b int , c int); -print create stream streams0 trigger at_once ignore update 1 into streamt as select _wstart c1, count(*) c2, max(b) c3 from t1 interval(10s); +print create stream streams0 trigger at_once IGNORE EXPIRED 0 ignore update 1 into streamt as select _wstart c1, count(*) c2, max(b) c3 from t1 interval(10s); -sql create stream streams0 trigger at_once ignore update 1 into streamt as select _wstart c1, count(*) c2, max(b) c3 from t1 interval(10s); +sql create stream streams0 trigger at_once IGNORE EXPIRED 0 ignore update 1 into streamt as select _wstart c1, count(*) c2, max(b) c3 from t1 interval(10s); sql insert into t1 values(1648791213000,1,1,1); sql insert into t1 values(1648791213000,2,2,2); diff --git a/tests/script/tsim/stream/ignoreExpiredData.sim b/tests/script/tsim/stream/ignoreExpiredData.sim index b143b7977fe6e1de9e716ba32d153d076830478a..fb6cf2eec6a44d0f25c31e4c3fa79f6e352c69ce 100644 --- a/tests/script/tsim/stream/ignoreExpiredData.sim +++ b/tests/script/tsim/stream/ignoreExpiredData.sim @@ -116,7 +116,7 @@ sql create stream stream_t1 trigger at_once IGNORE EXPIRED 1 into streamtST1 as sql create stream stream_t2 trigger at_once IGNORE EXPIRED 1 into streamtST2 as select _wstart, count(*) c1, count(a) c2 , sum(a) c3 , max(b) c5, min(c) c6 from st session(ts, 10s) ; sql insert into ts1 values(1648791211000,1,2,3); sql insert into ts1 values(1648791222001,2,2,3); -sleep 300 +sleep 200 sql insert into ts2 values(1648791211000,1,2,3); sql insert into ts2 values(1648791222001,2,2,3); @@ -160,4 +160,4 @@ if $data02 != 1 then goto loop5 endi -system sh/stop_dnodes.sh \ No newline at end of file +system sh/stop_dnodes.sh diff --git a/tests/script/tsim/stream/partitionby.sim b/tests/script/tsim/stream/partitionby.sim index bc2c07b951373ae924d836664977dfe5897e845a..e63459e97d42de9ca666e1d7b493923b6155dd30 100644 --- a/tests/script/tsim/stream/partitionby.sim +++ b/tests/script/tsim/stream/partitionby.sim @@ -12,7 +12,7 @@ sql create table ts1 using st tags(1,1,1); sql create table ts2 using st tags(2,2,2); sql create table ts3 using st tags(3,2,2); sql create table ts4 using st tags(4,2,2); -sql create stream stream_t1 trigger at_once into test0.streamtST1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from st partition by ta,tb,tc interval(10s); +sql create stream stream_t1 trigger at_once IGNORE EXPIRED 0 into test0.streamtST1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from st partition by ta,tb,tc interval(10s); sql insert into ts1 values(1648791213001,1,12,3,1.0); sql insert into ts2 values(1648791213001,1,12,3,1.0); @@ -67,7 +67,7 @@ sql create table ts1 using st tags(1,2,3); sql create table ts2 using st tags(1,3,4); sql create table ts3 using st tags(1,4,5); -sql create stream streams1 trigger at_once into streamt as select _wstart, count(*) c1, count(a) c2 from st partition by ta,tb,tc interval(10s); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, count(a) c2 from st partition by ta,tb,tc interval(10s); sql insert into ts1 values(1648791211000,1,2,3); @@ -98,7 +98,7 @@ sql create stable st(ts timestamp,a int,b int,c int,id int) tags(ta int,tb int,t sql create table ts1 using st tags(1,1,1); sql create table ts2 using st tags(2,2,2); -sql create stream stream_t2 trigger at_once watermark 20s into streamtST as select _wstart, count(*) c1, count(a) c2 , sum(a) c3 , max(b) c5, min(c) c6, max(id) c7 from st partition by ta interval(10s) ; +sql create stream stream_t2 trigger at_once watermark 20s IGNORE EXPIRED 0 into streamtST as select _wstart, count(*) c1, count(a) c2 , sum(a) c3 , max(b) c5, min(c) c6, max(id) c7 from st partition by ta interval(10s) ; sql insert into ts1 values(1648791211000,1,2,3,1); sql insert into ts1 values(1648791222001,2,2,3,2); sql insert into ts2 values(1648791211000,1,2,3,3); diff --git a/tests/script/tsim/stream/partitionby1.sim b/tests/script/tsim/stream/partitionby1.sim index b29666cad7df8178e65f7032948d8b01ebd86855..c8bb25e0dd371331a0a6e42b6ad3ebe956451eba 100644 --- a/tests/script/tsim/stream/partitionby1.sim +++ b/tests/script/tsim/stream/partitionby1.sim @@ -11,7 +11,7 @@ sql create table ts1 using st tags(1,1,1); sql create table ts2 using st tags(2,2,2); sql create table ts3 using st tags(3,2,2); sql create table ts4 using st tags(4,2,2); -sql create stream stream_t1 trigger at_once into streamtST1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from st partition by tbname interval(10s); +sql create stream stream_t1 trigger at_once IGNORE EXPIRED 0 into streamtST1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from st partition by tbname interval(10s); sql insert into ts1 values(1648791213001,1,12,3,1.0); sql insert into ts2 values(1648791213001,1,12,3,1.0); @@ -43,7 +43,7 @@ sql create table ts1 using st tags(1,2,3); sql create table ts2 using st tags(1,3,4); sql create table ts3 using st tags(1,4,5); -sql create stream streams1 trigger at_once into streamt as select _wstart, count(*) c1, count(a) c2 from st partition by tbname interval(10s); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, count(a) c2 from st partition by tbname interval(10s); sql insert into ts1 values(1648791211000,1,2,3); @@ -74,7 +74,7 @@ sql create stable st(ts timestamp,a int,b int,c int,id int) tags(ta int,tb int,t sql create table ts1 using st tags(1,1,1); sql create table ts2 using st tags(2,2,2); -sql create stream stream_t2 trigger at_once into streamtST as select _wstart, count(*) c1, count(a) c2 , sum(a) c3 , max(b) c5, min(c) c6, max(id) c7 from st partition by tbname interval(10s) ; +sql create stream stream_t2 trigger at_once IGNORE EXPIRED 0 into streamtST as select _wstart, count(*) c1, count(a) c2 , sum(a) c3 , max(b) c5, min(c) c6, max(id) c7 from st partition by tbname interval(10s) ; sql insert into ts1 values(1648791211000,1,2,3,1); sql insert into ts1 values(1648791222001,2,2,3,2); sql insert into ts2 values(1648791211000,1,2,3,3); diff --git a/tests/script/tsim/stream/partitionbyColumnInterval.sim b/tests/script/tsim/stream/partitionbyColumnInterval.sim index 2e57e8d699ec1b04a303c4888083a3408130b724..94053990e443229782a34143f95ad6ff594fd6af 100644 --- a/tests/script/tsim/stream/partitionbyColumnInterval.sim +++ b/tests/script/tsim/stream/partitionbyColumnInterval.sim @@ -16,7 +16,7 @@ sql drop database if exists test; sql create database test vgroups 1; sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams0 trigger at_once into streamt as select _wstart c1, count(*) c2, max(a) c3, _group_key(a) c4 from t1 partition by a interval(10s); +sql create stream streams0 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart c1, count(*) c2, max(a) c3, _group_key(a) c4 from t1 partition by a interval(10s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); @@ -197,7 +197,7 @@ sql drop database if exists test1; sql create database test1 vgroups 1; sql use test1; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams1 trigger at_once into streamt1 as select _wstart c1, count(*) c2, max(c) c3, _group_key(a+b) c4 from t1 partition by a+b interval(10s); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart c1, count(*) c2, max(c) c3, _group_key(a+b) c4 from t1 partition by a+b interval(10s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); @@ -284,7 +284,7 @@ sql use test2; sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams2 trigger at_once into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a interval(10s); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a interval(10s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); @@ -481,7 +481,7 @@ sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); sql create table t3 using st tags(2,2,2); sql create table t4 using st tags(2,2,2); -sql create stream streams4 trigger at_once into test.streamt4 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a interval(10s); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into test.streamt4 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a interval(10s); sql insert into t1 values(1648791213000,2,2,3,1.0); sql insert into t2 values(1648791213000,2,2,3,1.0); @@ -571,7 +571,7 @@ sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); sql create table t3 using st tags(2,2,2); sql create table t4 using st tags(2,2,2); -sql create stream streams5 trigger at_once into test.streamt5 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a interval(10s); +sql create stream streams5 trigger at_once IGNORE EXPIRED 0 into test.streamt5 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a interval(10s); sql insert into t1 values(1648791213000,1,2,3,1.0); sql insert into t2 values(1648791213000,2,2,3,1.0); diff --git a/tests/script/tsim/stream/partitionbyColumnSession.sim b/tests/script/tsim/stream/partitionbyColumnSession.sim index 1742d52cf03f9a6d2ec159295495cebfbb39aefc..bb3f6015c715bbcb7324cb8153fc081b7794f4bf 100644 --- a/tests/script/tsim/stream/partitionbyColumnSession.sim +++ b/tests/script/tsim/stream/partitionbyColumnSession.sim @@ -16,7 +16,7 @@ sql drop database if exists test; sql create database test vgroups 1; sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams0 trigger at_once into streamt as select _wstart c1, count(*) c2, max(a) c3, _group_key(a) c4 from t1 partition by a session(ts, 5s); +sql create stream streams0 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart c1, count(*) c2, max(a) c3, _group_key(a) c4 from t1 partition by a session(ts, 5s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); @@ -196,7 +196,7 @@ sql drop database if exists test1; sql create database test1 vgroups 1; sql use test1; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams1 trigger at_once into streamt1 as select _wstart c1, count(*) c2, max(c) c3, _group_key(a+b) c4 from t1 partition by a+b session(ts, 5s); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart c1, count(*) c2, max(c) c3, _group_key(a+b) c4 from t1 partition by a+b session(ts, 5s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); @@ -282,7 +282,7 @@ sql use test2; sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams2 trigger at_once into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a session(ts, 5s); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into test.streamt2 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a session(ts, 5s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); @@ -478,7 +478,7 @@ sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); sql create table t3 using st tags(2,2,2); sql create table t4 using st tags(2,2,2); -sql create stream streams4 trigger at_once into test.streamt4 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a session(ts, 5s); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into test.streamt4 as select _wstart c1, count(*) c2, max(a) c3 from st partition by a session(ts, 5s); sql insert into t1 values(1648791213000,2,2,3,1.0); sql insert into t2 values(1648791213000,2,2,3,1.0); diff --git a/tests/script/tsim/stream/partitionbyColumnState.sim b/tests/script/tsim/stream/partitionbyColumnState.sim index 75d01b17ec6495be9644ce7e7db401a0147b3a52..b69ab2df52f6a43ffc36a7dbc91c853d4902c00b 100644 --- a/tests/script/tsim/stream/partitionbyColumnState.sim +++ b/tests/script/tsim/stream/partitionbyColumnState.sim @@ -11,7 +11,7 @@ sql drop database if exists test; sql create database test vgroups 1; sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams0 trigger at_once into streamt as select _wstart c1, count(*) c2, max(a) c3, _group_key(a) c4 from t1 partition by a state_window(b); +sql create stream streams0 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart c1, count(*) c2, max(a) c3, _group_key(a) c4 from t1 partition by a state_window(b); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); @@ -27,13 +27,8 @@ if $loop_count == 10 then return -1 endi -if $data01 != 1 then - print =====data01=$data01 - goto loop0 -endi - -if $data02 != NULL then - print =====data02=$data02 +if $rows != 0 then + print =====rows=$rows goto loop0 endi @@ -191,7 +186,7 @@ sql drop database if exists test1; sql create database test1 vgroups 1; sql use test1; sql create table t1(ts timestamp, a int, b int , c int, d int); -sql create stream streams1 trigger at_once into streamt1 as select _wstart c1, count(*) c2, max(d) c3, _group_key(a+b) c4 from t1 partition by a+b state_window(c); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart c1, count(*) c2, max(d) c3, _group_key(a+b) c4 from t1 partition by a+b state_window(c); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL); diff --git a/tests/script/tsim/stream/schedSnode.sim b/tests/script/tsim/stream/schedSnode.sim index 2caecf50a202db447b6b45e37ce99cd50ed4ec7f..6a4d6f79bb1fbc11ea8e8da5754e997f6c914955 100644 --- a/tests/script/tsim/stream/schedSnode.sim +++ b/tests/script/tsim/stream/schedSnode.sim @@ -20,7 +20,7 @@ sql create table ts1 using st tags(1,1,1); sql create table ts2 using st tags(2,2,2); sql create table ts3 using st tags(3,2,2); sql create table ts4 using st tags(4,2,2); -sql create stream stream_t1 trigger at_once into target.streamtST1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s); +sql create stream stream_t1 trigger at_once IGNORE EXPIRED 0 into target.streamtST1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s); sleep 1000 diff --git a/tests/script/tsim/stream/session0.sim b/tests/script/tsim/stream/session0.sim index 5e95428e0a2d34adaf830fc74019e320513d2586..622c5f7c6d4fa2d33e6cbdad9f4270c23009b441 100644 --- a/tests/script/tsim/stream/session0.sim +++ b/tests/script/tsim/stream/session0.sim @@ -17,7 +17,7 @@ sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double,id int); -sql create stream streams1 trigger at_once into streamt as select _wstart, count(*) c1, sum(a), max(a), min(d), stddev(a), last(a), first(d), max(id) s from t1 session(ts,10s); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, sum(a), max(a), min(d), stddev(a), last(a), first(d), max(id) s from t1 session(ts,10s); sql insert into t1 values(1648791213000,NULL,NULL,NULL,NULL,1); sql insert into t1 values(1648791223001,10,2,3,1.1,2); sql insert into t1 values(1648791233002,3,2,3,2.1,3); @@ -179,7 +179,7 @@ endi sql create database test2 vgroups 1; sql use test2; sql create table t2(ts timestamp, a int, b int , c int, d double, id int); -sql create stream streams2 trigger at_once watermark 1d into streamt2 as select _wstart,apercentile(a,30) c1, apercentile(a,70), apercentile(a,20,"t-digest") c2, apercentile(a,60,"t-digest") c3, max(id) c4 from t2 session(ts,10s); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 watermark 1d into streamt2 as select _wstart,apercentile(a,30) c1, apercentile(a,70), apercentile(a,20,"t-digest") c2, apercentile(a,60,"t-digest") c3, max(id) c4 from t2 session(ts,10s); sql insert into t2 values(1648791213001,1,1,3,1.0,1); sql insert into t2 values(1648791213002,2,2,6,3.4,2); sql insert into t2 values(1648791213003,4,9,3,4.8,3); @@ -229,13 +229,13 @@ endi sql create database test3 vgroups 1; sql use test3; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams3 trigger at_once watermark 1d into streamt3 as select _wstart, min(b), a,c from t1 session(ts,10s); -sql create stream streams4 trigger at_once watermark 1d into streamt4 as select _wstart, max(b), a,c from t1 session(ts,10s); -# sql create stream streams5 trigger at_once watermark 1d into streamt5 as select _wstart, top(b,3), a,c from t1 session(ts,10s); -# sql create stream streams6 trigger at_once watermark 1d into streamt6 as select _wstart, bottom(b,3), a,c from t1 session(ts,10s); -# sql create stream streams7 trigger at_once watermark 1d into streamt7 as select _wstart, spread(a), elapsed(ts), hyperloglog(a) from t1 session(ts,10s); -sql create stream streams7 trigger at_once watermark 1d into streamt7 as select _wstart, spread(a), hyperloglog(a) from t1 session(ts,10s); -# sql create stream streams8 trigger at_once watermark 1d into streamt8 as select _wstart, histogram(a,"user_input", "[1,3,5,7]", 1), histogram(a,"user_input", "[1,3,5,7]", 0) from t1 session(ts,10s); +sql create stream streams3 trigger at_once watermark 1d IGNORE EXPIRED 0 into streamt3 as select _wstart, min(b), a,c from t1 session(ts,10s); +sql create stream streams4 trigger at_once watermark 1d IGNORE EXPIRED 0 into streamt4 as select _wstart, max(b), a,c from t1 session(ts,10s); +# sql create stream streams5 trigger at_once watermark 1d IGNORE EXPIRED 0 into streamt5 as select _wstart, top(b,3), a,c from t1 session(ts,10s); +# sql create stream streams6 trigger at_once watermark 1d IGNORE EXPIRED 0 into streamt6 as select _wstart, bottom(b,3), a,c from t1 session(ts,10s); +# sql create stream streams7 trigger at_once watermark 1d IGNORE EXPIRED 0 into streamt7 as select _wstart, spread(a), elapsed(ts), hyperloglog(a) from t1 session(ts,10s); +sql create stream streams7 trigger at_once watermark 1d IGNORE EXPIRED 0 into streamt7 as select _wstart, spread(a), hyperloglog(a) from t1 session(ts,10s); +# sql create stream streams8 trigger at_once watermark 1d IGNORE EXPIRED 0 into streamt8 as select _wstart, histogram(a,"user_input", "[1,3,5,7]", 1), histogram(a,"user_input", "[1,3,5,7]", 0) from t1 session(ts,10s); sql insert into t1 values(1648791213001,1,1,1,1.0); sql insert into t1 values(1648791213002,2,3,2,3.4); sql insert into t1 values(1648791213003,4,9,3,4.8); diff --git a/tests/script/tsim/stream/session1.sim b/tests/script/tsim/stream/session1.sim index f535fd619fbedfa87598569ba7edfde82bd18086..3ad7c6f04ed4bb63878bb3a3503b75e089e08e9f 100644 --- a/tests/script/tsim/stream/session1.sim +++ b/tests/script/tsim/stream/session1.sim @@ -17,7 +17,7 @@ sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double,id int); -sql create stream streams2 trigger at_once into streamt as select _wstart, count(*) c1, sum(a), min(b), max(id) s from t1 session(ts,10s); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, sum(a), min(b), max(id) s from t1 session(ts,10s); sql insert into t1 values(1648791210000,1,1,1,1.1,1); sql insert into t1 values(1648791220000,2,2,2,2.1,2); sql insert into t1 values(1648791230000,3,3,3,3.1,3); @@ -200,7 +200,7 @@ endi sql create database test1 vgroups 1; sql use test1; sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams3 trigger at_once into streamt3 as select _wstart, count(*) c1 from t1 where a > 5 session(ts, 5s); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart, count(*) c1 from t1 where a > 5 session(ts, 5s); sql insert into t1 values(1648791213000,1,2,3,1.0); $loop_count = 0 diff --git a/tests/script/tsim/stream/sliding.sim b/tests/script/tsim/stream/sliding.sim index 8287274cd2a008f264365ea06d049428ae645d2f..e12e3c6686c3d35924f43c1675134ba9a0bff65c 100644 --- a/tests/script/tsim/stream/sliding.sim +++ b/tests/script/tsim/stream/sliding.sim @@ -17,10 +17,10 @@ sql use test; sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb int,tc int); sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams1 trigger at_once into streamt as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s) sliding (5s); -sql create stream streams2 trigger at_once watermark 1d into streamt2 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s) sliding (5s); -sql create stream stream_t1 trigger at_once into streamtST as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s) sliding (5s); -sql create stream stream_t2 trigger at_once watermark 1d into streamtST2 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s) sliding (5s); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s) sliding (5s); +sql create stream streams2 trigger at_once watermark 1d IGNORE EXPIRED 0 into streamt2 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s) sliding (5s); +sql create stream stream_t1 trigger at_once IGNORE EXPIRED 0 into streamtST as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s) sliding (5s); +sql create stream stream_t2 trigger at_once watermark 1d IGNORE EXPIRED 0 into streamtST2 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s) sliding (5s); sql insert into t1 values(1648791210000,1,2,3,1.0); sql insert into t1 values(1648791216000,2,2,3,1.1); @@ -309,8 +309,8 @@ sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams11 trigger at_once into streamt as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s, 5s); -sql create stream streams12 trigger at_once into streamt2 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s, 5s); +sql create stream streams11 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s, 5s); +sql create stream streams12 trigger at_once IGNORE EXPIRED 0 into streamt2 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s, 5s); sql insert into t1 values(1648791213000,1,2,3,1.0); sql insert into t1 values(1648791223001,2,2,3,1.1); @@ -442,9 +442,9 @@ sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams21 trigger at_once into streamt as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s, 5s); -sql create stream streams22 trigger at_once into streamt2 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s, 5s); -sql create stream streams23 trigger at_once into streamt3 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(20s) sliding(10s); +sql create stream streams21 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s, 5s); +sql create stream streams22 trigger at_once IGNORE EXPIRED 0 into streamt2 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(10s, 5s); +sql create stream streams23 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart, count(*) c1, sum(a) c3 , max(b) c4, min(c) c5 from st interval(20s) sliding(10s); sql insert into t1 values(1648791213000,1,1,1,1.0); sql insert into t1 values(1648791223001,2,2,2,1.1); @@ -683,7 +683,7 @@ sql create stable st(ts timestamp, a int, b int, c int, d double) tags(ta int,tb sql create table t1 using st tags(1,1,1); sql create table t2 using st tags(2,2,2); -sql create stream streams4 trigger at_once into streamt4 as select _wstart as ts, count(*),min(a) c1 from st interval(10s) sliding(5s); +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into streamt4 as select _wstart as ts, count(*),min(a) c1 from st interval(10s) sliding(5s); sql insert into t1 values(1648791213000,1,1,1,1.0); sql insert into t1 values(1648791243000,2,1,1,1.0); diff --git a/tests/script/tsim/stream/state0.sim b/tests/script/tsim/stream/state0.sim index 07abdc0040d962bc6c6b6b0f15996cdf973ab450..d009f742b7311e6b4840e4ed7ccea9e92f9fa6e8 100644 --- a/tests/script/tsim/stream/state0.sim +++ b/tests/script/tsim/stream/state0.sim @@ -17,9 +17,9 @@ sql use test; sql create table t1(ts timestamp, a int, b int , c int, d double, id int); -print create stream streams1 trigger at_once into streamt1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(a) c4, min(c) c5, max(id) c from t1 state_window(a); +print create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(a) c4, min(c) c5, max(id) c from t1 state_window(a); -sql create stream streams1 trigger at_once into streamt1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(a) c4, min(c) c5, max(id) c from t1 state_window(a); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(a) c4, min(c) c5, max(id) c from t1 state_window(a); sql insert into t1 values(1648791213000,1,2,3,1.0,1); sql insert into t1 values(1648791213000,1,2,3,1.0,2); @@ -453,9 +453,9 @@ sql use test1; sql create table t1(ts timestamp, a int, b int , c int, d double, id int); -print create stream streams2 trigger at_once into streamt1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(a) c4, min(c) c5, max(id) c from t1 state_window(a); +print create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(a) c4, min(c) c5, max(id) c from t1 state_window(a); -sql create stream streams2 trigger at_once into streamt1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(a) c4, min(c) c5, max(id) c from t1 state_window(a); +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(a) c4, min(c) c5, max(id) c from t1 state_window(a); sql insert into t1 values(1648791212000,2,2,3,1.0,1); sql insert into t1 values(1648791213000,1,2,3,1.0,1); @@ -501,9 +501,9 @@ sql use test3; sql create table t1(ts timestamp, a int, b int , c int, d double, id int); -print create stream streams3 trigger at_once into streamt3 as select _wstart, count(*) c1, sum(b) c3 from t1 state_window(a); +print create stream streams3 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart, count(*) c1, sum(b) c3 from t1 state_window(a); -sql create stream streams3 trigger at_once into streamt3 as select _wstart, count(*) c1, sum(b) c3 from t1 state_window(a); +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into streamt3 as select _wstart, count(*) c1, sum(b) c3 from t1 state_window(a); sql insert into t1 values(1648791212000,1,2,3,1.0,1); sql insert into t1 values(1648791213000,2,2,3,1.0,1); sql insert into t1 values(1648791214000,3,2,4,1.0,2); @@ -553,9 +553,9 @@ sql create table st (ts timestamp, c1 tinyint, c2 smallint) tags (t1 tinyint) ; sql create table t1 using st tags (-81) ; sql create table t2 using st tags (-81) ; -print create stream if not exists streams4 trigger window_close into streamt4 as select _wstart AS startts, min(c1),count(c1) from t1 state_window(c1); +print create stream if not exists streams4 trigger window_close IGNORE EXPIRED 0 into streamt4 as select _wstart AS startts, min(c1),count(c1) from t1 state_window(c1); -sql create stream if not exists streams4 trigger window_close into streamt4 as select _wstart AS startts, min(c1),count(c1) from t1 state_window(c1); +sql create stream if not exists streams4 trigger window_close IGNORE EXPIRED 0 into streamt4 as select _wstart AS startts, min(c1),count(c1) from t1 state_window(c1); sql insert into t1 (ts, c1) values (1668073288209, 11); sql insert into t1 (ts, c1) values (1668073288210, 11); @@ -742,9 +742,9 @@ sql create table tb (ts timestamp, a int); sql insert into tb values (now + 1m , 1 ); sql create table b (c timestamp, d int, e int , f int, g double); -print create stream streams0 trigger at_once into streamt as select _wstart c1, count(*) c2, max(a) c3 from tb state_window(a); +print create stream streams0 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart c1, count(*) c2, max(a) c3 from tb state_window(a); -sql create stream streams0 trigger at_once into streamt as select _wstart c1, count(*) c2, max(a) c3 from tb state_window(a); +sql create stream streams0 trigger at_once IGNORE EXPIRED 0 into streamt as select _wstart c1, count(*) c2, max(a) c3 from tb state_window(a); sql insert into b values(1648791213000,NULL,NULL,NULL,NULL); sql select * from streamt order by c1, c2, c3; diff --git a/tests/script/tsim/stream/state1.sim b/tests/script/tsim/stream/state1.sim new file mode 100644 index 0000000000000000000000000000000000000000..67e02c0890821dc2a57776e64faa95ee9a89c997 --- /dev/null +++ b/tests/script/tsim/stream/state1.sim @@ -0,0 +1,157 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sleep 50 +sql connect + +print step 1 +print =============== create database +sql create database test vgroups 4; +sql select * from information_schema.ins_databases; +if $rows != 3 then + return -1 +endi + +print $data00 $data01 $data02 + +sql use test; + +sql create table t1(ts timestamp, a int, b int , c int, d double, id int); + +print create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart, count(*) c1 from t1 state_window(a); + +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into streamt1 as select _wstart, count(*) c1 from t1 state_window(a); + +sql insert into t1(ts) values(1648791213000); + +$loop_count = 0 +loop0: + +sleep 300 +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from streamt1; +print $data00 $data01 +print $data10 $data11 + +if $rows != 0 then + print =====rows=$rows + goto loop0 +endi + +sql insert into t1 values(1648791214000,1,2,3,1.0,3); +$loop_count = 0 +loop1: + +sleep 300 +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from streamt1; +print $data00 $data01 +print $data10 $data11 + +if $rows != 1 then + print =====rows=$rows + goto loop1 +endi + +sql insert into t1 values(1648791215000,2,2,3,1.0,4); + +$loop_count = 0 +loop2: + +sleep 300 +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from streamt1; + +if $rows != 2 then + print =====rows=$rows + goto loop2 +endi + +sql insert into t1(ts) values(1648791216000); + +$loop_count = 0 +loop3: + +sleep 300 +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from streamt1; +if $rows != 2 then + print =====rows=$rows + goto loop3 +endi + +print step 1 over +print step 2 + +sql create database test2 vgroups 1; +sql use test2; +sql create table t1(ts timestamp, a int, b int , c int, d double); +print create stream streams2 trigger at_once watermark 1000s into streamt2 as select _wstart, count(*) c1, count(d) c2 from t1 partition by b state_window(a) +sql create stream streams2 trigger at_once watermark 1000s into streamt2 as select _wstart, count(*) c1, count(d) c2 from t1 partition by b state_window(a); + +sql insert into t1 values(1648791213000,1,2,3,1.0); +sql insert into t1 values(1648791213010,1,2,3,1.1); + +$loop_count = 0 +loop4: + +sleep 300 +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from streamt2; +print $data00 $data01 +print $data10 $data11 + +if $rows != 1 then + print =====rows=$rows + goto loop4 +endi + +print insert into t1 values(1648791213005,2,2,3,1.1) +sql insert into t1 values(1648791213005,2,2,3,1.1); + +$loop_count = 0 +loop5: + +sleep 300 +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +print select * from streamt2 +sql select * from streamt2; +print $data00 $data01 +print $data10 $data11 +print $data20 $data21 +print $data30 $data31 + +if $rows != 3 then + print =====rows=$rows + goto loop5 +endi + +print step 2 over + +print state1 end + +system sh/stop_dnodes.sh diff --git a/tests/script/tsim/stream/triggerInterval0.sim b/tests/script/tsim/stream/triggerInterval0.sim index b522dcf035f66c439e8c59a8190d9228ea8dca5c..1c62f689ac3269357cdd39b8e2bb517d4e76e869 100644 --- a/tests/script/tsim/stream/triggerInterval0.sim +++ b/tests/script/tsim/stream/triggerInterval0.sim @@ -15,7 +15,7 @@ print $data00 $data01 $data02 sql use test sql create table t1(ts timestamp, a int, b int , c int, d double); -sql create stream streams1 trigger window_close into streamt as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s); +sql create stream streams1 trigger window_close IGNORE EXPIRED 0 into streamt as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t1 interval(10s); sql insert into t1 values(1648791213001,1,2,3,1.0); sleep 300 diff --git a/tests/script/tsim/stream/triggerSession0.sim b/tests/script/tsim/stream/triggerSession0.sim index 4c664cf7c7b9ad8d29b0439066cefc3c130fc25e..81a016be2b2e5781495596a5a42a255b4f48c813 100644 --- a/tests/script/tsim/stream/triggerSession0.sim +++ b/tests/script/tsim/stream/triggerSession0.sim @@ -15,7 +15,7 @@ print $data00 $data01 $data02 sql use test; sql create table t2(ts timestamp, a int, b int , c int, d double); -sql create stream streams2 trigger window_close into streamt2 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t2 session(ts, 10s); +sql create stream streams2 trigger window_close IGNORE EXPIRED 0 into streamt2 as select _wstart, count(*) c1, count(d) c2 , sum(a) c3 , max(b) c4, min(c) c5 from t2 session(ts, 10s); sql insert into t2 values(1648791213000,1,2,3,1.0); sql insert into t2 values(1648791222999,1,2,3,1.0); diff --git a/tests/script/tsim/stream/udTableAndTag0.sim b/tests/script/tsim/stream/udTableAndTag0.sim new file mode 100644 index 0000000000000000000000000000000000000000..e3ab344bbef11e25bb9531e4a4f723b40722abd4 --- /dev/null +++ b/tests/script/tsim/stream/udTableAndTag0.sim @@ -0,0 +1,446 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 + +print ===== step1 + +system sh/exec.sh -n dnode1 -s start +sleep 50 +sql connect + +print ===== step2 +print ===== table name + +sql create database result vgroups 1; + +sql create database test vgroups 4; +sql use test; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +#sql_error create stream streams1 trigger at_once IGNORE EXPIRED 0 into result.streamt SUBTABLE("aaa") as select _wstart, count(*) c1 from st interval(10s); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into result.streamt SUBTABLE(concat("aaa-", tbname)) as select _wstart, count(*) c1 from st partition by tbname interval(10s); +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,1,2,3); + +$loop_count = 0 +loop0: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select table_name from information_schema.ins_tables where db_name="result" order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 + print $data10 + print $data20 + print $data30 + goto loop0 +endi + +if $data00 != aaa-t1 then + print =====data00=$data00 + goto loop0 +endi + +if $data10 != aaa-t2 then + print =====data10=$data10 + goto loop0 +endi + +$loop_count = 0 +loop1: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result.streamt; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop1 +endi + + +print ===== step3 +print ===== tag name + +sql create database result2 vgroups 1; + +sql create database test2 vgroups 4; +sql use test2; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into result2.streamt2 TAGS(cc varchar(100)) as select _wstart, count(*) c1 from st partition by concat("tag-", tbname) as cc interval(10s); +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,1,2,3); + + +$loop_count = 0 +loop2: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select tag_name from information_schema.ins_tags where db_name="result2" and stable_name = "streamt2" order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop2 +endi + +if $data00 != cc then + print data00 != cc + print =====data00=$data00 + goto loop2 +endi + +if $data10 != cc then + print =====data10=$data10 + goto loop2 +endi + +sql select cc from result2.streamt2 order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop2 +endi + +if $data00 != tag-t1 then + print data00 != tag-t1 + print =====data00=$data00 + goto loop2 +endi + +if $data10 != tag-t2 then + print =====data10=$data10 + goto loop2 +endi + +$loop_count = 0 +loop3: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result2.streamt2; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop3 +endi + + +print ===== step4 +print ===== tag name + table name + +sql create database result3 vgroups 1; + +sql create database test3 vgroups 4; +sql use test3; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into result3.streamt3 TAGS(dd varchar(100)) SUBTABLE(concat("tbn-", tbname)) as select _wstart, count(*) c1 from st partition by concat("tag-", tbname) as dd, tbname interval(10s); +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,1,2,3); + + +$loop_count = 0 +loop4: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select tag_name from information_schema.ins_tags where db_name="result3" and stable_name = "streamt3" order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop4 +endi + +if $data00 != dd then + print =====data00=$data00 + goto loop4 +endi + +if $data10 != dd then + print =====data10=$data10 + goto loop4 +endi + +sql select dd from result3.streamt3 order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop4 +endi + +if $data00 != tag-t1 then + print =====data00=$data00 + goto loop4 +endi + +if $data10 != tag-t2 then + print =====data10=$data10 + goto loop4 +endi + +$loop_count = 0 +loop5: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result3.streamt3; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop5 +endi + +$loop_count = 0 +loop6: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select table_name from information_schema.ins_tables where db_name="result3" order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop6 +endi + +if $data00 != tbn-t1 then + print =====data00=$data00 + goto loop6 +endi + +if $data10 != tbn-t2 then + print =====data10=$data10 + goto loop6 +endi + + +print ===== step5 +print ===== tag name + table name + +sql create database result4 vgroups 1; + +sql create database test4 vgroups 4; +sql use test4; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); +sql create table t3 using st tags(3,3,3); + +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into result4.streamt4 TAGS(dd varchar(100)) SUBTABLE(concat("tbn-", tbname)) as select _wstart, count(*) c1 from st partition by concat("tag-", tbname) as dd, tbname interval(10s); +sql insert into t1 values(1648791213000,1,1,1) t2 values(1648791213000,2,2,2) t3 values(1648791213000,3,3,3); + + +$loop_count = 0 +loop7: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select table_name from information_schema.ins_tables where db_name="result4" order by 1; + +if $rows != 3 then + print =====rows=$rows + print $data00 $data10 + goto loop7 +endi + +if $data00 != tbn-t1 then + print =====data00=$data00 + goto loop7 +endi + +if $data10 != tbn-t2 then + print =====data10=$data10 + goto loop7 +endi + +if $data20 != tbn-t3 then + print =====data20=$data20 + goto loop7 +endi + +$loop_count = 0 +loop8: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result4.streamt4 order by 3; + +if $rows != 3 then + print =====rows=$rows + print $data00 $data10 + goto loop8 +endi + +if $data01 != 1 then + print =====data01=$data01 + goto loop8 +endi + +if $data02 != tag-t1 then + print =====data02=$data02 + goto loop8 +endi + +if $data11 != 1 then + print =====data11=$data11 + goto loop8 +endi + +if $data12 != tag-t2 then + print =====data12=$data12 + goto loop8 +endi + +if $data21 != 1 then + print =====data21=$data21 + goto loop8 +endi + +if $data22 != tag-t3 then + print =====data22=$data22 + goto loop8 +endi + +print ===== step6 +print ===== transform tag value + +sql drop stream if exists streams1; +sql drop stream if exists streams2; +sql drop stream if exists streams3; +sql drop stream if exists streams4; +sql drop stream if exists streams5; + +sql drop database if exists test1; +sql drop database if exists test2; +sql drop database if exists test3; +sql drop database if exists test4; +sql drop database if exists test5; + +sql drop database if exists result1; +sql drop database if exists result2; +sql drop database if exists result3; +sql drop database if exists result4; +sql drop database if exists result5; + + + +sql create database result6 vgroups 1; + +sql create database test6 vgroups 4; +sql use test6; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta varchar(20), tb int, tc int); +sql create table t1 using st tags("1",1,1); +sql create table t2 using st tags("2",2,2); +sql create table t3 using st tags("3",3,3); + +sql create stream streams6 trigger at_once IGNORE EXPIRED 0 into result6.streamt6 TAGS(dd int) as select _wstart, count(*) c1 from st partition by concat(ta, "0") as dd, tbname interval(10s); +sql insert into t1 values(1648791213000,1,1,1) t2 values(1648791213000,2,2,2) t3 values(1648791213000,3,3,3); + + +$loop_count = 0 +loop9: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result6.streamt6 order by 3; + +if $rows != 3 then + print =====rows=$rows + print $data00 $data10 + goto loop9 +endi + +if $data02 != 10 then + print =====data02=$data02 + goto loop9 +endi + +if $data12 != 20 then + print =====data12=$data12 + goto loop9 +endi + +if $data22 != 30 then + print =====data22=$data22 + goto loop8 +endi + +print ======over + +system sh/stop_dnodes.sh diff --git a/tests/script/tsim/stream/udTableAndTag1.sim b/tests/script/tsim/stream/udTableAndTag1.sim new file mode 100644 index 0000000000000000000000000000000000000000..fbedaa6e4e2bb65d191546edc4b66cbfea5201d6 --- /dev/null +++ b/tests/script/tsim/stream/udTableAndTag1.sim @@ -0,0 +1,373 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 + +print ===== step1 + +system sh/exec.sh -n dnode1 -s start +sleep 50 +sql connect + +print ===== step2 +print ===== table name + +sql create database result vgroups 1; + +sql create database test vgroups 4; +sql use test; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +#sql_error create stream streams1 trigger at_once IGNORE EXPIRED 0 into result.streamt SUBTABLE("aaa") as select _wstart, count(*) c1 from st interval(10s); +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into result.streamt SUBTABLE( concat("aaa-", cast(a as varchar(10) ) ) ) as select _wstart, count(*) c1 from st partition by a interval(10s); +print ===== insert into 1 +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,2,2,3); + +$loop_count = 0 +loop0: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select table_name from information_schema.ins_tables where db_name="result" order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + print $data20 $data30 + goto loop0 +endi + +if $data00 != aaa-1 then + print =====data00=$data00 + goto loop0 +endi + +if $data10 != aaa-2 then + print =====data10=$data10 + goto loop0 +endi + +$loop_count = 0 +loop1: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result.streamt; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop1 +endi + + +print ===== step3 +print ===== column name + +sql create database result2 vgroups 1; + +sql create database test2 vgroups 4; +sql use test2; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into result2.streamt2 TAGS(cc varchar(100)) as select _wstart, count(*) c1 from st partition by concat("col-", cast(a as varchar(10) ) ) as cc interval(10s); +print ===== insert into 2 +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,2,2,3); + + +$loop_count = 0 +loop2: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select tag_name from information_schema.ins_tags where db_name="result2" and stable_name = "streamt2" order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop2 +endi + +if $data00 != cc then + print =====data00=$data00 + goto loop2 +endi + +if $data10 != cc then + print =====data10=$data10 + goto loop2 +endi + +sql select cc from result2.streamt2 order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop2 +endi + +if $data00 != col-1 then + print =====data00=$data00 + goto loop2 +endi + +if $data10 != col-2 then + print =====data10=$data10 + goto loop2 +endi + +$loop_count = 0 +loop3: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result2.streamt2; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop3 +endi + + +print ===== step4 +print ===== column name + table name + +sql create database result3 vgroups 1; + +sql create database test3 vgroups 4; +sql use test3; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into result3.streamt3 TAGS(dd varchar(100)) SUBTABLE(concat("tbn-", cast(a as varchar(10) ) ) ) as select _wstart, count(*) c1 from st partition by concat("col-", cast(a as varchar(10) ) ) as dd, a interval(10s); +print ===== insert into 3 +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,2,2,3); + + +$loop_count = 0 +loop4: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select tag_name from information_schema.ins_tags where db_name="result3" and stable_name = "streamt3" order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop4 +endi + +if $data00 != dd then + print =====data00=$data00 + goto loop4 +endi + +if $data10 != dd then + print =====data10=$data10 + goto loop4 +endi + +sql select dd from result3.streamt3 order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop4 +endi + +if $data00 != col-1 then + print =====data00=$data00 + goto loop4 +endi + +if $data10 != col-2 then + print =====data10=$data10 + goto loop4 +endi + +$loop_count = 0 +loop5: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result3.streamt3; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop5 +endi + +$loop_count = 0 +loop6: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select table_name from information_schema.ins_tables where db_name="result3" order by 1; + +if $rows != 2 then + print =====rows=$rows + print $data00 $data10 + goto loop6 +endi + +if $data00 != tbn-1 then + print =====data00=$data00 + goto loop6 +endi + +if $data10 != tbn-2 then + print =====data10=$data10 + goto loop6 +endi + +print ===== step5 +print ===== tag name + table name + +sql create database result4 vgroups 1; + +sql create database test4 vgroups 4; +sql use test4; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); +sql create table t3 using st tags(3,3,3); + +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into result4.streamt4 TAGS(dd varchar(100)) SUBTABLE(concat("tbn-", dd)) as select _wstart, count(*) c1 from st partition by concat("t", cast(a as varchar(10) ) ) as dd interval(10s); +sql insert into t1 values(1648791213000,1,1,1) t2 values(1648791213000,2,2,2) t3 values(1648791213000,3,3,3); + + +$loop_count = 0 +loop7: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select table_name from information_schema.ins_tables where db_name="result4" order by 1; + +if $rows != 3 then + print =====rows=$rows + print $data00 $data10 + goto loop7 +endi + +if $data00 != tbn-t1 then + print =====data00=$data00 + goto loop7 +endi + +if $data10 != tbn-t2 then + print =====data10=$data10 + goto loop7 +endi + +if $data20 != tbn-t3 then + print =====data20=$data20 + goto loop7 +endi + +$loop_count = 0 +loop8: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result4.streamt4 order by 3; + +if $rows != 3 then + print =====rows=$rows + print $data00 $data10 + goto loop8 +endi + +if $data01 != 1 then + print =====data01=$data01 + goto loop8 +endi + +if $data02 != t1 then + print =====data02=$data02 + goto loop8 +endi + +if $data11 != 1 then + print =====data11=$data11 + goto loop8 +endi + +if $data12 != t2 then + print =====data12=$data12 + goto loop8 +endi + +if $data21 != 1 then + print =====data21=$data21 + goto loop8 +endi + +if $data22 != t3 then + print =====data22=$data22 + goto loop8 +endi + +print ======over + +system sh/stop_dnodes.sh diff --git a/tests/script/tsim/stream/udTableAndTag2.sim b/tests/script/tsim/stream/udTableAndTag2.sim new file mode 100644 index 0000000000000000000000000000000000000000..c0e72712df56be2f24f48a7ce1efb681da325b57 --- /dev/null +++ b/tests/script/tsim/stream/udTableAndTag2.sim @@ -0,0 +1,515 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 + +print ===== step1 + +system sh/exec.sh -n dnode1 -s start +sleep 50 +sql connect + +print ===== step2 +print ===== table name + +sql create database result vgroups 1; + +sql create database test vgroups 4; +sql use test; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stream streams1 trigger at_once IGNORE EXPIRED 0 into result.streamt SUBTABLE("aaa") as select _wstart, count(*) c1 from st interval(10s); +print ===== insert into 1 +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,2,2,3); + +$loop_count = 0 +loop0: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select table_name from information_schema.ins_tables where db_name="result" order by 1; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop0 +endi + +if $data00 != aaa then + print =====data00=$data00 + goto loop0 +endi + + +$loop_count = 0 +loop1: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result.streamt; + +if $rows != 1 then + print =====rows=$rows + print $data00 $data10 + goto loop1 +endi + +if $data01 != 2 then + print =====data01=$data01 + goto loop1 +endi + +# group id +if $data02 == NULL then + print =====data02=$data02 + goto loop1 +endi + + +print ===== step3 +print ===== column name + +sql create database result2 vgroups 1; + +sql create database test2 vgroups 4; +sql use test2; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stream streams2 trigger at_once IGNORE EXPIRED 0 into result2.streamt2 TAGS(cc varchar(100)) as select _wstart, count(*) c1 from st interval(10s); +print ===== insert into 2 +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,2,2,3); + + +$loop_count = 0 +loop2: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +print select tag_name from information_schema.ins_tags where db_name="result2" and stable_name = "streamt2" order by 1; + +sql select tag_name from information_schema.ins_tags where db_name="result2" and stable_name = "streamt2" order by 1; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop2 +endi + +if $data00 != cc then + print =====data00=$data00 + goto loop2 +endi + +print sql select cc from result2.streamt2 order by 1; + +$loop_count = 0 +loop21: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select cc from result2.streamt2 order by 1; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop21 +endi + +if $data00 != NULL then + print =====data00=$data00 + goto loop21 +endi + + +$loop_count = 0 +loop3: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result2.streamt2; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop3 +endi + +if $data01 != 2 then + print =====data01=$data01 + goto loop3 +endi + +if $data02 != NULL then + print =====data02=$data02 + goto loop3 +endi + + +print ===== step4 +print ===== column name + table name + +sql create database result3 vgroups 1; + +sql create database test3 vgroups 4; +sql use test3; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stream streams3 trigger at_once IGNORE EXPIRED 0 into result3.streamt3 TAGS(dd varchar(100)) SUBTABLE(concat("tbn-", "1") ) as select _wstart, count(*) c1 from st interval(10s); +print ===== insert into 3 +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,2,2,3); + + +$loop_count = 0 +loop4: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select tag_name from information_schema.ins_tags where db_name="result3" and stable_name = "streamt3" order by 1; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop4 +endi + +if $data00 != dd then + print =====data00=$data00 + goto loop4 +endi + +sql select dd from result3.streamt3 order by 1; + +if $rows != 1 then + print =====rows=$rows + print $data00 $data10 + goto loop4 +endi + +if $data00 != NULL then + print =====data00=$data00 + goto loop4 +endi + +$loop_count = 0 +loop5: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result3.streamt3; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop5 +endi + +if $data01 != 2 then + print =====data01=$data01 + goto loop5 +endi + +if $data02 != NULL then + print =====data02=$data02 + goto loop5 +endi + +$loop_count = 0 +loop6: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select table_name from information_schema.ins_tables where db_name="result3" order by 1; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop6 +endi + +if $data00 != tbn-1 then + print =====data00=$data00 + goto loop6 +endi + +print ===== step5 +print ===== tag name + table name + +sql create database result4 vgroups 1; + +sql create database test4 vgroups 1; +sql use test4; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); +sql create table t3 using st tags(3,3,3); + +sql create stream streams4 trigger at_once IGNORE EXPIRED 0 into result4.streamt4 TAGS(dd varchar(100)) SUBTABLE(concat("tbn-", "1")) as select _wstart, count(*) c1 from st interval(10s); +sql insert into t1 values(1648791213000,1,1,1) t2 values(1648791213000,2,2,2) t3 values(1648791213000,3,3,3); + + +$loop_count = 0 +loop7: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select table_name from information_schema.ins_tables where db_name="result4" order by 1; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop7 +endi + +if $data00 != tbn-1 then + print =====data00=$data00 + goto loop7 +endi + +$loop_count = 0 +loop8: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result4.streamt4 order by 3; + +if $rows != 1 then + print =====rows=$rows + print $data00 $data10 + goto loop8 +endi + +if $data01 != 3 then + print =====data01=$data01 + goto loop8 +endi + +if $data02 != NULL then + print =====data02=$data02 + goto loop8 +endi + + +print ===== step6 +print ===== table name + +sql create database result5 vgroups 1; + +sql create database test5 vgroups 1; +sql use test5; + + +sql create stable st(ts timestamp,a int,b int,c int) tags(ta int,tb int,tc int); +sql create table t1 using st tags(1,1,1); +sql create table t2 using st tags(2,2,2); + +sql create stream streams51 trigger at_once IGNORE EXPIRED 0 into result5.streamt51 SUBTABLE("aaa") as select _wstart, count(*) c1 from st interval(10s); +sql create stream streams52 trigger at_once IGNORE EXPIRED 0 into result5.streamt52 TAGS(cc varchar(100)) as select _wstart, count(*) c1 from st interval(10s); +sql create stream streams53 trigger at_once IGNORE EXPIRED 0 into result5.streamt53 TAGS(dd varchar(100)) SUBTABLE(concat("aaa-", "1") ) as select _wstart, count(*) c1 from st interval(10s); + +sql insert into t1 values(1648791213000,1,2,3); +sql insert into t2 values(1648791213000,2,2,3); + +$loop_count = 0 +loop9: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +print select table_name from information_schema.ins_tables where db_name="result5" order by 1; + +sql select table_name from information_schema.ins_tables where db_name="result5" order by 1; + +if $rows != 3 then + print =====rows=$rows + print $data00 + print $data10 + print $data20 + print $data40 + goto loop9 +endi + +if $data00 != aaa then + print =====data00=$data00 + goto loop9 +endi + +if $data10 != aaa-1 then + print =====data00=$data00 + goto loop9 +endi + +$loop_count = 0 +loop10: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +print sql select tag_name from information_schema.ins_tags where db_name="result5" and stable_name = "streamt52" order by 1; + +sql select tag_name from information_schema.ins_tags where db_name="result5" and stable_name = "streamt52" order by 1; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop10 +endi + +if $data00 != cc then + print =====data00=$data00 + goto loop10 +endi + +print sql select tag_name from information_schema.ins_tags where db_name="result5" and stable_name = "streamt53" order by 1; + +sql select tag_name from information_schema.ins_tags where db_name="result5" and stable_name = "streamt53" order by 1; + +if $rows != 1 then + print =====rows=$rows + print $data00 + print $data10 + goto loop10 +endi + +if $data00 != dd then + print =====data00=$data00 + goto loop10 +endi + + + + + +$loop_count = 0 +loop11: + +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from result5.streamt51; + +if $rows != 1 then + print =====rows=$rows + print $data00 $data10 + goto loop11 +endi + +if $data01 != 2 then + print =====data01=$data01 + goto loop11 +endi + +sql select * from result5.streamt52; + +if $rows != 1 then + print =====rows=$rows + print $data00 $data10 + goto loop11 +endi + +if $data01 != 2 then + print =====data01=$data01 + goto loop11 +endi + +sql select * from result5.streamt53; + +if $rows != 1 then + print =====rows=$rows + print $data00 $data10 + goto loop11 +endi + +if $data01 != 2 then + print =====data01=$data01 + goto loop11 +endi + +print ======over + +system sh/stop_dnodes.sh diff --git a/tests/script/tsim/stream/windowClose.sim b/tests/script/tsim/stream/windowClose.sim index 9fcdcfb9599db5bbd2d4e93a069647a2518abaac..d3bc25d731f7a3800f0ae84d4ce2177cd573242a 100644 --- a/tests/script/tsim/stream/windowClose.sim +++ b/tests/script/tsim/stream/windowClose.sim @@ -68,7 +68,7 @@ sql select * from streamt2; if $rows != 1 then print ======streamt2=$rows - return -1 + goto loop1 endi sql select * from streamt3; @@ -80,7 +80,7 @@ endi sql select * from streamt4; if $rows != 1 then print ======streamt4=$rows - return -1 + goto loop1 endi sql select * from streamt5; @@ -92,7 +92,7 @@ endi sql select * from streamt6; if $rows != 1 then print ======streamt6=$rows - return -1 + goto loop1 endi sql select * from streamt7; @@ -104,7 +104,7 @@ endi sql select * from streamt8; if $rows != 1 then print ======streamt8=$rows - return -1 + goto loop1 endi sql select * from streamt9; @@ -116,7 +116,7 @@ endi sql select * from streamt10; if $rows != 1 then print ======streamt10=$rows - return -1 + goto loop1 endi sql select * from streamt11; @@ -125,4 +125,6 @@ if $rows != 2 then goto loop1 endi +print ======over + system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/sync/3Replica1VgElect.sim b/tests/script/tsim/sync/3Replica1VgElect.sim index f069ff40e597df927d7162d5d628a7d8a50a23ca..aae1b25636b46a738096b93f8325e2d6f8a1306c 100644 --- a/tests/script/tsim/sync/3Replica1VgElect.sim +++ b/tests/script/tsim/sync/3Replica1VgElect.sim @@ -55,7 +55,7 @@ $loop_cnt = 0 check_db_ready: $loop_cnt = $loop_cnt + 1 sleep 200 -if $loop_cnt == 100 then +if $loop_cnt == 500 then print ====> db not ready! return -1 endi diff --git a/tests/script/tsim/tag/bigint.sim b/tests/script/tsim/tag/bigint.sim index 26a5addf6a3f9d5e717b21b5003ac719d8b4d04d..34fcc094118e6160057a010424942fb3d5532a17 100644 --- a/tests/script/tsim/tag/bigint.sim +++ b/tests/script/tsim/tag/bigint.sim @@ -123,6 +123,17 @@ sql select * from $mt where tgcol = 1 if $rows != 100 then return -1 endi + +sql select * from $mt where tgcol = '1' +if $rows != 100 then + return -1 +endi + +sql select * from $mt where tgcol = "1" +if $rows != 100 then + return -1 +endi + sql select * from $mt where tgcol <> 1 if $rows != 100 then return -1 diff --git a/tests/script/tsim/tag/double.sim b/tests/script/tsim/tag/double.sim index fbdf9733370b19eb2506801aaf61490e05ae6ed0..acc026c13d25099ffaed1baf63b4429bd098b9a8 100644 --- a/tests/script/tsim/tag/double.sim +++ b/tests/script/tsim/tag/double.sim @@ -123,6 +123,15 @@ sql select * from $mt where tgcol = 1 if $rows != 100 then return -1 endi + +sql select * from $mt where tgcol = '1'; +if $rows != 100 then + return -1 +endi +sql select * from $mt where tgcol = "1.0" +if $rows != 100 then + return -1 +endi sql select * from $mt where tgcol <> 1 if $rows != 100 then return -1 diff --git a/tests/script/tsim/tag/float.sim b/tests/script/tsim/tag/float.sim index 10fac93d5d547fb2232a26abb9c68e5baa5cd77a..f62feba057d4fb48d9ce2003ddb4caae464058ee 100644 --- a/tests/script/tsim/tag/float.sim +++ b/tests/script/tsim/tag/float.sim @@ -123,6 +123,16 @@ sql select * from $mt where tgcol = 1 if $rows != 100 then return -1 endi + +sql select * from $mt where tgcol = "1.0" +if $rows != 100 then + return -1 +endi + +sql select * from $mt where tgcol = "1" +if $rows != 100 then + return -1 +endi sql select * from $mt where tgcol <> 1 if $rows != 100 then return -1 diff --git a/tests/script/tsim/tag/int.sim b/tests/script/tsim/tag/int.sim index ac8d31db3bb181489311c9bec7b31abf1a39b305..084b7e74d7f2d3c357626b75c2d95e6a72537855 100644 --- a/tests/script/tsim/tag/int.sim +++ b/tests/script/tsim/tag/int.sim @@ -123,6 +123,16 @@ sql select * from $mt where tgcol = 1 if $rows != 100 then return -1 endi + +sql select * from $mt where tgcol = '1' +if $rows != 100 then + return -1 +endi + +sql select * from $mt where tgcol = "1"; +if $rows != 100 then + return -1 +endi sql select * from $mt where tgcol <> 1 if $rows != 100 then return -1 diff --git a/tests/script/tsim/tag/int_float.sim b/tests/script/tsim/tag/int_float.sim index 009629aac97fbfb0c7dc9fe26acb848ea0ec3a49..3034f8b64ebe8de46537d904b8770422a53288e5 100644 --- a/tests/script/tsim/tag/int_float.sim +++ b/tests/script/tsim/tag/int_float.sim @@ -85,10 +85,22 @@ sql select * from $mt where tgcol <> 1 if $rows != 100 then return -1 endi + sql select * from $mt where tgcol = 1 if $rows != 100 then return -1 endi + +sql select * from $mt where tgcol = '1' +if $rows != 100 then + return -1 +endi + +sql select * from $mt where tgcol = "1" +if $rows != 100 then + return -1 +endi + sql select * from $mt where tgcol <> 1 if $rows != 100 then return -1 diff --git a/tests/script/tsim/tag/tbNameIn.sim b/tests/script/tsim/tag/tbNameIn.sim index 1af4bd6a9e34dbb33298ddcab5c28d0d1b716745..f5119208ba3f091eb7d97cc108dd3e9ba5a65728 100644 --- a/tests/script/tsim/tag/tbNameIn.sim +++ b/tests/script/tsim/tag/tbNameIn.sim @@ -99,4 +99,14 @@ if $rows != 7 then return -1 endi +sql select * from st1 where tbname in('tb1') and tbname in ('tb2'); +if $rows != 0 then + return -1 +endi + +sql select * from st1 where tbname in ('tb1') and tbname != 'tb1'; +if $rows != 0 then + return -1 +endi + system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/tag/tinyint.sim b/tests/script/tsim/tag/tinyint.sim index 8560def34cc22cc73a592ac062d5bb8f9867b8c0..89b0134bb30444141cd075cc4b0648784f50cb3e 100644 --- a/tests/script/tsim/tag/tinyint.sim +++ b/tests/script/tsim/tag/tinyint.sim @@ -115,14 +115,36 @@ sql select * from $mt where tgcol = 0 if $rows != 100 then return -1 endi + +sql select * from $mt where tgcol = '0' +if $rows != 100 then + return -1 +endi + +sql select * from $mt where tgcol = "0" +if $rows != 100 then + return -1 +endi sql select * from $mt where tgcol <> 0 if $rows != 100 then return -1 endi + sql select * from $mt where tgcol = 1 if $rows != 100 then return -1 endi +sql select * from $mt where tgcol = "1" +if $rows != 100 then + return -1 +endi + +sql select * from $mt where tgcol = '1' +if $rows != 100 then + return -1 +endi + + sql select * from $mt where tgcol <> 1 if $rows != 100 then return -1 diff --git a/tests/script/tsim/tagindex/add_index.sim b/tests/script/tsim/tagindex/add_index.sim new file mode 100644 index 0000000000000000000000000000000000000000..cfbec905426a64547c8695905af0986be668d586 --- /dev/null +++ b/tests/script/tsim/tagindex/add_index.sim @@ -0,0 +1,271 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print ======== step0 +$dbPrefix = ta_3_db +$tbPrefix = ta_3_tb +$mtPrefix = ta_3_mt +$tbNum = 500 +$rowNum = 20 +$totalNum = 200 + +print =============== create database +sql create database $dbPrefix +sql use $dbPrefix + +print =============== create super table and register tag index +sql create table if not exists $mtPrefix (ts timestamp, c1 int) tags (t1 int, t2 int, t3 int, t4 int, t5 int) + +sql show stables +if $rows != 1 then + return -1 +endi + +print =============== create child table + +$i = 0 +$val = 1 +while $i < $tbNum + $tb = $tbPrefix . $i + sql create table $tb using $mtPrefix tags( $i , $i , $i , $i , $val ); + $i = $i + 1 +endw + +sql show tables +if $rows != $tbNum then + return -1 +endi + + + +print =============== insert data into each table +$i = 0 +while $i < $tbNum + $tb = $tbPrefix . $i + sql insert into $tb values(now, $i ); + $i = $i + 1 +endw + + +sql create index ti2 on $mtPrefix (t2) +sql create index ti5 on $mtPrefix (t5) + +print ==== test name conflict +# +sql_error create index ti3 on $mtPrefix(t2) + +sql_error create index ti2 on $mtPrefix(t2) +sql_error create index ti2 on $mtPrefix(t1) +sql_error create index ti2 on $mtPrefix(t3) +sql_error create index ti2 on $mtPrefix(txx) + + +print ===== test operator equal + +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2= $i ; + if $rows != 1 then + return -1 + endi + $i = $i + 1 +endw + + + +print ===== test operator great equal +# great equal than +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2 >= $i ; + $tmp = $tbNum - $i + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + +print ===== test operator great +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2 > $i ; + $tmp = $tbNum - $i + $tmp = $tmp - 1 + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + +print ===== test operator lower +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2 <= $i ; + $tmp = $i + 1 + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + +print ===== test operator lower than +# lower equal than +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2 < $i ; + $tmp = $i + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + + + +# test special boundary condtion +print ===== test operator low on ti5 +# great equal than +sql select * from $mtPrefix where t5 < 0 ; +if $rows != 0 then + return -1 +endi + +print ===== test operator lower equal on ti5 +# great equal than +sql select * from $mtPrefix where t5 <= $val ; +if $rows != $tbNum then + return -1 +endi + +print ===== test operator equal on ti5 +# great equal than +sql select * from $mtPrefix where t5 = $val ; +if $rows != $tbNum then + return -1 +endi + +print ===== test operator great equal on ti5 +# great equal than +sql select * from $mtPrefix where t5 >= $val ; +if $rows != $tbNum then + return -1 +endi + +print ===== test operator great than on ti5 +# great equal than +sql select * from $mtPrefix where t5 > $val ; +if $rows != 0 then + return -1 +endi + +print ===== test operator great on ti5 +# great equal than +sql select * from $mtPrefix where t5 > $val + 1 ; +if $rows != 0 then + return -1 +endi + +sql drop index ti5 + +print ===== add table after index created +$interval = $tbNum + $tbNum +$i = $interval +$limit = $interval + $tbNum +while $i < $limit + $tb = $tbPrefix . $i + sql insert into $tb using $mtPrefix tags( $i , $i , $i , $i , $i ) values( now, $i ) + $i = $i + 1 +endw + +print ===== add table after index created (opeator great equal than) +# great equal than +$i = $interval +while $i < $limit + sql select * from $mtPrefix where t2 >= $i ; + $tmp = $limit - $i + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + + +print ===== add table after index created (opeator great than) +# great than +$i = $interval +while $i < $limit + sql select * from $mtPrefix where t2 > $i ; + $tmp = $limit - $i + $tmp = $tmp - 1 + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + +print ===== drop table after index created + +# drop table +$dropTbNum = $tbNum / 2 +$i = 0 + +while $i < $tbNum + $tb = $tbPrefix . $i + sql drop table $tb + $i = $i + 1 +endw + +print ===== drop table after index created(opeator lower than) + +# lower equal than +$i = $interval +while $i < $limit + sql select * from $mtPrefix where t2 < $i ; + $tmp = $i - $interval + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + + +print ===== drop table after index created(opeator lower equal than) + +# lower equal than +$i = $interval +while $i < $limit + sql select * from $mtPrefix where t2 <= $i ; + + $tmp = $i - $interval + $tmp = $tmp + 1 + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + + +print === show index + +sql select * from information_schema.ins_indexes +if $rows != 1 then + return -1 +endi + + +print === drop index ti2 +sql drop index ti2 + +print === drop not exist index +sql_error drop index t2 +sql_error drop index t3 + + + +sql_error create index ti0 on $mtPrefix (t1) +sql_error create index t2i on ta_3_tb17 (t2) + + +system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/tsim/tagindex/drop_index.sim b/tests/script/tsim/tagindex/drop_index.sim new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/script/tsim/tagindex/perf.sim b/tests/script/tsim/tagindex/perf.sim new file mode 100644 index 0000000000000000000000000000000000000000..88d7579ecc0a72d600d48df786a99fdb17b74b54 --- /dev/null +++ b/tests/script/tsim/tagindex/perf.sim @@ -0,0 +1,225 @@ + +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print ======== step0 +$dbPrefix = ta_3_db +$tbPrefix = ta_3_tb +$mtPrefix = ta_3_mt +$tbNum = 100000 +$rowNum = 20 +$totalNum = 200 + +print =============== create database +sql create database $dbPrefix +sql use $dbPrefix + +print =============== create super table and register tag index +sql create table if not exists $mtPrefix (ts timestamp, c1 int) tags (t1 int, t2 int, t3 int, t4 int, t5 int) + +sql show stables +if $rows != 1 then + return -1 +endi + +print =============== create child table + +$i = 0 +while $i < $tbNum + $tb = $tbPrefix . $i + sql create table $tb using $mtPrefix tags( $i , $i , $i , $i , $i ); + $i = $i + 1 +endw + +sql show tables +if $rows != $tbNum then + return -1 +endi + + + +print =============== insert data into each table +$i = 0 +while $i < $tbNum + $tb = $tbPrefix . $i + sql insert into $tb values(now, $i ); + $i = $i + 1 +endw + + +sql create index ti2 on $mtPrefix (t2) + +print ==== test name conflict +# +sql_error create index ti3 on $mtPrefix(t2) + +sql_error create index ti2 on $mtPrefix(t2) +sql_error create index ti2 on $mtPrefix(t1) +sql_error create index ti2 on $mtPrefix(t3) +sql_error create index ti2 on $mtPrefix(txx) + + +print ===== test operator equal + +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2= $i ; + if $rows != 1 then + return -1 + endi + $i = $i + 1 +endw + + + +print ===== test operator great equal +# great equal than +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2 >= $i ; + $tmp = $tbNum - $i + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + +print ===== test operator great +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2 > $i ; + $tmp = $tbNum - $i + $tmp = $tmp - 1 + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + +print ===== test operator lower +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2 <= $i ; + $tmp = $i + 1 + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + +print ===== test operator lower than +# lower equal than +$i = 0 +while $i < $tbNum + sql select * from $mtPrefix where t2 < $i ; + $tmp = $i + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + +print ===== add table after index created +$interval = $tbNum + $tbNum +$i = $interval +$limit = $interval + $tbNum +while $i < $limit + $tb = $tbPrefix . $i + sql insert into $tb using $mtPrefix tags( $i , $i , $i , $i , $i ) values( now, $i ) + $i = $i + 1 +endw + + + +print ===== add table after index created (opeator great equal than) +# great equal than +$i = $interval +while $i < $limit + sql select * from $mtPrefix where t2 >= $i ; + $tmp = $limit - $i + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + + +print ===== add table after index created (opeator great than) +# great than +$i = $interval +while $i < $limit + sql select * from $mtPrefix where t2 > $i ; + $tmp = $limit - $i + $tmp = $tmp - 1 + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + +print ===== drop table after index created + +# drop table +$dropTbNum = $tbNum / 2 +$i = 0 + +while $i < $tbNum + $tb = $tbPrefix . $i + sql drop table $tb + $i = $i + 1 +endw + +print ===== drop table after index created(opeator lower than) + +# lower equal than +$i = $interval +while $i < $limit + sql select * from $mtPrefix where t2 < $i ; + $tmp = $i - $interval + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + + +print ===== drop table after index created(opeator lower equal than) + +# lower equal than +$i = $interval +while $i < $limit + sql select * from $mtPrefix where t2 <= $i ; + + $tmp = $i - $interval + $tmp = $tmp + 1 + if $rows != $tmp then + return -1 + endi + $i = $i + 1 +endw + + +print === show index + +sql select * from information_schema.ins_indexes +if $rows != 1 then + return -1 +endi + + +print === drop index ti2 +sql drop index ti2 + +print === drop not exist index +sql_error drop index t2 +sql_error drop index t3 + + + +sql_error create index ti0 on $mtPrefix (t1) +sql_error create index t2i on ta_3_tb17 (t2) + + +system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/tsim/tagindex/sma_and_tag_index.sim b/tests/script/tsim/tagindex/sma_and_tag_index.sim new file mode 100644 index 0000000000000000000000000000000000000000..b15d22d43996ef82f6733698abefcb0f6b0054ed --- /dev/null +++ b/tests/script/tsim/tagindex/sma_and_tag_index.sim @@ -0,0 +1,162 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print ======== step0 +$dbPrefix = ta_3_db +$dbPrefix1 = ta_3_db1 +$tbPrefix = ta_3_tb +$mtPrefix = ta_3_mt +$tbNum = 1 +$rowNum = 20 +$totalNum = 200 + +print =============== create database +sql create database $dbPrefix +sql use $dbPrefix + +print =============== create super table and register tag index +sql create table if not exists $mtPrefix (ts timestamp, c1 int) tags (t1 int, t2 int, t3 int, t4 int, t5 int) + +sql show stables +if $rows != 1 then + return -1 +endi + +print =============== create child table + +$i = 0 +while $i < $tbNum + $tb = $tbPrefix . $i + sql create table $tb using $mtPrefix tags( $i , $i , $i , $i , $i ); + $i = $i + 1 +endw + +sql show tables +if $rows != $tbNum then + return -1 +endi + + + +print =============== insert data into each table +$i = 0 +while $i < $tbNum + $tb = $tbPrefix . $i + sql insert into $tb values(now, $i ); + $i = $i + 1 +endw + + +print ==== create sma and tag index, global name conflict +sql create sma index t2i on $mtPrefix function(max(c1)) interval(6m,10s) sliding(6m); +sql_error create index t2i on $mtPrefix (t2) +sql drop index t2i + + +print ==== create tagindex and sma index, global name conflict +sql create index t2i on $mtPrefix (t2) +sql_error create sma index t2i on $mtPrefix function(max(c1)) interval(6m,10s) sliding(6m); + +sql drop index t2i + + +print ===== iter sma and tag index + +sql create index tagt2i on $mtPrefix (t2) +sql create sma index smat2i on $mtPrefix function(max(c1)) interval(6m,10s) sliding(6m); + + +sql select * from information_schema.ins_indexes +if $rows != 2 then + return -1 +endi + +sql drop index smat2i + +$i = 0 +$smaPre = sma3 +while $i < 5 + $sma = $smaPre . $i + $i = $i + 1 + sql create sma index $sma on $mtPrefix function(max(c1)) interval(6m,10s) sliding(6m); +endw + +sql select * from information_schema.ins_indexes +if $rows != 6 then + return -1 +endi + + + +sql drop stable $mtPrefix +sql select * from information_schema.ins_indexes +if $rows != 0 then + return -1 +endi + +sql create table if not exists $mtPrefix (ts timestamp, c1 int) tags (t1 int, t2 int, t3 int, t4 int, t5 int) +sql create index tagt2i on $mtPrefix (t2) +sql drop database $dbPrefix + +sql select * from information_schema.ins_indexes +if $rows != 0 then + return -1 +endi + + +print ===== drop tag and del tag index + +sql create database $dbPrefix +sql use $dbPrefix + +sql create table if not exists $mtPrefix (ts timestamp, c1 int) tags (t1 int, t2 int, t3 int, t4 int, t5 int) +sql create index tagt2i on $mtPrefix (t2) +sql select * from information_schema.ins_indexes +if $rows != 1 then + return -1 +endi +sql alter table $mtPrefix drop tag t2 + +sql select * from information_schema.ins_indexes +if $rows != 0 then + return -1 +endi + + +print ==== rename tag name, and update index colName +sql create index tagt3i on $mtPrefix (t3) +sql select * from information_schema.ins_indexes +if $rows != 1 then + return -1 +endi + +sql alter table $mtPrefix rename tag t3 txxx +sql select * from information_schema.ins_indexes +if $rows != 1 then + return -1 +endi + +if $data05 != txxx then + return -1 +endi + + + +print ====== diff db has same index name + +sql create database $dbPrefix1 +sql use $dbPrefix1 + +sql create table if not exists $mtPrefix (ts timestamp, c1 int) tags (t1 int, t2 int, t3 int, t4 int, t5 int) +sql create index tagt3i on $mtPrefix (t3) +sql select * from information_schema.ins_indexes + +if $rows != 2 then + return -1 +endi + + + +system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file diff --git a/tests/script/tsim/testsuit.sim b/tests/script/tsim/testsuit.sim index c5fbf41b66fcba4088e6480c721d4a6e21811d7a..0abe56ab3c3d7d09b6f441aed813445be0d2df92 100644 --- a/tests/script/tsim/testsuit.sim +++ b/tests/script/tsim/testsuit.sim @@ -114,6 +114,7 @@ run tsim/insert/basic1.sim run tsim/insert/commit-merge0.sim run tsim/insert/basic0.sim run tsim/insert/update0.sim +run tsim/insert/delete0.sim run tsim/insert/backquote.sim run tsim/insert/null.sim run tsim/catalog/alterInCurrent.sim diff --git a/tests/script/tsim/tmq/basic1.sim b/tests/script/tsim/tmq/basic1.sim index 6880f290f5fda796cbf5b90f98cf5d40c1976eff..4551228f2f67e6da9beed93f984e93113a77055f 100644 --- a/tests/script/tsim/tmq/basic1.sim +++ b/tests/script/tsim/tmq/basic1.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -83,6 +86,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -111,8 +117,8 @@ endi $consumerId = 0 $totalMsgOfStb = $ctbNum * $rowsPerCtb -$expectmsgcnt = $totalMsgOfStb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from stb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $cdbName -s start @@ -134,7 +140,7 @@ if $data[0][2] != $expectmsgcnt then print expect $expectmsgcnt , actual $data02 return -1 endi -if $data[0][3] != $expectmsgcnt then +if $data[0][3] != $totalMsgOfStb then return -1 endi $loop_cnt = $loop_cnt + 1 @@ -155,6 +161,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -183,8 +192,8 @@ endi $consumerId = 0 $totalMsgOfCtb = $rowsPerCtb -$expectmsgcnt = $totalMsgOfCtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ctb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -202,7 +211,7 @@ endi if $data[0][1] != $consumerId then return -1 endi -if $data[0][2] != $totalMsgOfCtb then +if $data[0][2] != $expectmsgcnt then return -1 endi if $data[0][3] != $totalMsgOfCtb then @@ -226,6 +235,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -254,8 +266,8 @@ endi $consumerId = 0 $totalMsgOfNtb = $rowsPerCtb -$expectmsgcnt = $totalMsgOfNtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ntb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -273,7 +285,7 @@ endi if $data[0][1] != $consumerId then return -1 endi -if $data[0][2] != $totalMsgOfNtb then +if $data[0][2] != $expectmsgcnt then return -1 endi if $data[0][3] != $totalMsgOfNtb then diff --git a/tests/script/tsim/tmq/basic1Of2Cons.sim b/tests/script/tsim/tmq/basic1Of2Cons.sim index 11b645c4d1a008dc82af07999b86ce32c5484947..51d39e8d110f0be00e3a16cf7cdd47e6be226a78 100644 --- a/tests/script/tsim/tmq/basic1Of2Cons.sim +++ b/tests/script/tsim/tmq/basic1Of2Cons.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -83,6 +86,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table for stb sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -111,11 +117,11 @@ endi $consumerId = 0 $totalMsgOfStb = $ctbNum * $rowsPerCtb -$expectmsgcnt = $totalMsgOfStb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from stb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $cdbName -s start @@ -142,14 +148,14 @@ if $data[0][1] == 1 then endi endi -# either $data[0][2] == $totalMsgOfStb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfStb -if $data[0][2] == $totalMsgOfStb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_0 endi elif $data[0][2] == 0 then - if $data[1][2] == $totalMsgOfStb then + if $data[1][2] == $expectmsgcnt then goto check_ok_0 endi endi @@ -186,6 +192,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table for ctb sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -214,10 +223,10 @@ endi $consumerId = 0 $totalMsgOfCtb = $rowsPerCtb -$expectmsgcnt = $totalMsgOfCtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ctb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -244,14 +253,14 @@ if $data[0][1] == 1 then endi endi -# either $data[0][2] == $totalMsgOfCtb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfCtb -if $data[0][2] == $totalMsgOfCtb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_2 endi elif $data[0][2] == 0 then - if $data[1][2] == $totalMsgOfCtb then + if $data[1][2] == $expectmsgcnt then goto check_ok_2 endi endi @@ -288,6 +297,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table for ntb sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -316,10 +328,10 @@ endi $consumerId = 0 $totalMsgOfNtb = $rowsPerCtb -$expectmsgcnt = $totalMsgOfNtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ntb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -346,14 +358,14 @@ if $data[1][1] == 0 then endi endi -# either $data[0][2] == $totalMsgOfNtb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfNtb -if $data[0][2] == $totalMsgOfNtb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_4 endi elif $data[0][2] == 0 then - if $data[1][2] == $totalMsgOfNtb then + if $data[1][2] == $expectmsgcnt then goto check_ok_4 endi endi diff --git a/tests/script/tsim/tmq/basic2.sim b/tests/script/tsim/tmq/basic2.sim index dce73be592e459264916f67b4390141115c05bc8..8356a60b672c54feb37663d5c3b8f3391c99a456 100644 --- a/tests/script/tsim/tmq/basic2.sim +++ b/tests/script/tsim/tmq/basic2.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -83,8 +86,8 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfStb = $ctbNum * $rowsPerCtb $totalMsgOfStb = $totalMsgOfStb * $topicNum -$expectmsgcnt = $totalMsgOfStb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from stb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $dbName -s start @@ -105,7 +108,7 @@ endi if $data[0][2] != $expectmsgcnt then return -1 endi -if $data[0][3] != $expectmsgcnt then +if $data[0][3] != $totalMsgOfStb then return -1 endi @@ -118,6 +121,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -140,8 +146,8 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfCtb = $rowsPerCtb * $topicNum -$expectmsgcnt = $totalMsgOfCtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ctb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -159,7 +165,7 @@ endi if $data[0][1] != $consumerId then return -1 endi -if $data[0][2] != $totalMsgOfCtb then +if $data[0][2] != $expectmsgcnt then return -1 endi if $data[0][3] != $totalMsgOfCtb then @@ -175,6 +181,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -197,8 +206,8 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfNtb = $rowsPerCtb * $topicNum -$expectmsgcnt = $totalMsgOfNtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ntb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -216,7 +225,7 @@ endi if $data[0][1] != $consumerId then return -1 endi -if $data[0][2] != $totalMsgOfNtb then +if $data[0][2] != $expectmsgcnt then return -1 endi if $data[0][3] != $totalMsgOfNtb then diff --git a/tests/script/tsim/tmq/basic2Of2Cons.sim b/tests/script/tsim/tmq/basic2Of2Cons.sim index 87559305ba19cb30b7c8f7928a1437f3246cc139..63e7e2dcf4e600e340f6c3767ab91dfd19fc5338 100644 --- a/tests/script/tsim/tmq/basic2Of2Cons.sim +++ b/tests/script/tsim/tmq/basic2Of2Cons.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -82,10 +85,10 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfStb = $ctbNum * $rowsPerCtb $totalMsgOfStb = $totalMsgOfStb * $topicNum -$expectmsgcnt = $totalMsgOfStb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from stb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $dbName -s start @@ -112,14 +115,14 @@ if $data[0][1] == 1 then endi endi -# either $data[0][2] == $totalMsgOfStb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfStb -if $data[0][2] == $totalMsgOfStb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_0 endi elif $data[0][2] == 0 then - if $data[1][2] == $totalMsgOfStb then + if $data[1][2] == $expectmsgcnt then goto check_ok_0 endi endi @@ -147,6 +150,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table for ctb sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -169,10 +175,10 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfCtb = $rowsPerCtb * $topicNum -$expectmsgcnt = $totalMsgOfCtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ctb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -199,14 +205,14 @@ if $data[0][1] == 1 then endi endi -# either $data[0][2] == $totalMsgOfCtb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfCtb -if $data[0][2] == $totalMsgOfCtb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_2 endi elif $data[0][2] == 0 then - if $data[1][2] == $totalMsgOfCtb then + if $data[1][2] == $expectmsgcnt then goto check_ok_2 endi endi @@ -234,6 +240,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table for ntb sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -256,10 +265,10 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfNtb = $rowsPerCtb * $topicNum -$expectmsgcnt = $totalMsgOfNtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ntb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -286,14 +295,14 @@ if $data[1][1] == 0 then endi endi -# either $data[0][2] == $totalMsgOfNtb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfNtb -if $data[0][2] == $totalMsgOfNtb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_4 endi elif $data[0][2] == 0 then - if $data[1][2] == $totalMsgOfNtb then + if $data[1][2] == $expectmsgcnt then goto check_ok_4 endi endi diff --git a/tests/script/tsim/tmq/basic2Of2ConsOverlap.sim b/tests/script/tsim/tmq/basic2Of2ConsOverlap.sim index dda5e0059e5c760925e7944b13089b1d3897c0f8..cfdae059dc862d4177d12891ffd9499900ba3b41 100644 --- a/tests/script/tsim/tmq/basic2Of2ConsOverlap.sim +++ b/tests/script/tsim/tmq/basic2Of2ConsOverlap.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -80,8 +83,8 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfOneTopic = $ctbNum * $rowsPerCtb $totalMsgOfStb = $totalMsgOfOneTopic * $topicNum -$expectmsgcnt = $totalMsgOfStb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 3 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) $topicList = ' . topic_stb_all @@ -89,7 +92,7 @@ $topicList = $topicList . , $topicList = $topicList . topic_stb_function $topicList = $topicList . ' $consumerId = 1 -sql insert into consumeinfo values (now +1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now +1s , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from stb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $dbName -s start @@ -118,40 +121,40 @@ endi # $data[0][2]/$data[1][2] should be between $totalMsgOfOneTopic and $totalMsgOfStb. -if $data[0][2] < $totalMsgOfOneTopic then - return -1 -endi -if $data[0][2] > $totalMsgOfStb then - return -1 -endi -if $data[1][2] < $totalMsgOfOneTopic then +#if $data[0][2] < $totalMsgOfOneTopic then +# return -1 +#endi +if $data[0][2] > $expectmsgcnt then return -1 endi -if $data[1][2] > $totalMsgOfStb then +#if $data[1][2] < $totalMsgOfOneTopic then +# return -1 +#endi +if $data[1][2] > $expectmsgcnt then return -1 endi -$totalMsgCons = $totalMsgOfOneTopic + $totalMsgOfStb +#$totalMsgCons = $totalMsgOfOneTopic + $totalMsgOfStb $sumOfMsgCnt = $data[0][2] + $data[1][2] -if $sumOfMsgCnt != $totalMsgCons then - print total: $totalMsgCons +if $sumOfMsgCnt != $expectmsgcnt then + print total: $expectmsgcnt print sum: $sumOfMsgCnt return -1 endi # $data[0][3]/$data[1][3] should be between $totalMsgOfOneTopic and $totalMsgOfStb. -if $data[0][3] < $totalMsgOfOneTopic then - return -1 -endi -if $data[0][3] > $totalMsgOfStb then - return -1 -endi -if $data[1][3] < $totalMsgOfOneTopic then - return -1 -endi -if $data[1][3] > $totalMsgOfStb then - return -1 -endi +#if $data[0][3] < $totalMsgOfStb then +# return -1 +#endi +#if $data[0][3] > $totalMsgOfStb then +# return -1 +#endi +#if $data[1][3] < $totalMsgOfStb then +# return -1 +#endi +#if $data[1][3] > $totalMsgOfStb then +# return -1 +#endi $totalMsgCons = $totalMsgOfOneTopic + $totalMsgOfStb $sumOfRows = $data[0][3] + $data[1][3] @@ -168,6 +171,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table for ctb sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -189,15 +195,15 @@ $consumerId = 0 $totalMsgOfOneTopic = $rowsPerCtb $totalMsgOfCtb = $totalMsgOfOneTopic * $topicNum -$expectmsgcnt = $totalMsgOfCtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) $topicList = ' . topic_ctb_function $topicList = $topicList . , $topicList = $topicList . topic_ctb_all $topicList = $topicList . ' $consumerId = 1 -sql insert into consumeinfo values (now +1s, $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now +1s, $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ctb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $cdbName -s start @@ -226,24 +232,24 @@ endi # either $data[0][2] $totalMsgOfOneTopic and $data[1][2] == $totalMsgOfCtb # or $data[0][2] $totalMsgOfCtb and $data[1][2] == $totalMsgOfOneTopic -if $data[0][2] == $totalMsgOfOneTopic then - if $data[1][2] == $totalMsgOfCtb then +if $data[0][2] == $topicNum then + if $data[1][2] == 1 then goto check_ok_0 endi -elif $data[1][2] == $totalMsgOfOneTopic then - if $data[0][2] == $totalMsgOfCtb then +elif $data[0][2] == 1 then + if $data[1][2] == $topicNum then goto check_ok_0 endi endi return -1 check_ok_0: -if $data[0][3] == $totalMsgOfOneTopic then - if $data[1][3] == $totalMsgOfCtb then +if $data[0][3] == $totalMsgOfCtb then + if $data[1][3] == $totalMsgOfOneTopic then goto check_ok_1 endi -elif $data[1][3] == $totalMsgOfOneTopic then - if $data[0][3] == $totalMsgOfCtb then +elif $data[0][3] == $totalMsgOfOneTopic then + if $data[1][3] == $totalMsgOfCtb then goto check_ok_1 endi endi @@ -259,6 +265,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table for ntb sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -280,8 +289,8 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfOneTopic = $rowsPerCtb $totalMsgOfNtb = $totalMsgOfOneTopic * $topicNum -$expectmsgcnt = $totalMsgOfNtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) $topicList = ' . topic_ntb_function @@ -289,7 +298,7 @@ $topicList = $topicList . , $topicList = $topicList . topic_ntb_all $topicList = $topicList . ' $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ntb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -318,12 +327,12 @@ endi # either $data[0][2] $totalMsgOfOneTopic and $data[1][2] == $totalMsgOfNtb # or $data[0][2] $totalMsgOfNtb and $data[1][2] == $totalMsgOfOneTopic -if $data[0][2] == $totalMsgOfOneTopic then - if $data[1][2] == $totalMsgOfNtb then +if $data[0][2] == $expectmsgcnt then + if $data[1][2] == 1 then goto check_ok_2 endi -elif $data[1][2] == $totalMsgOfOneTopic then - if $data[0][2] == $totalMsgOfNtb then +elif $data[0][2] == 1 then + if $data[1][2] == $expectmsgcnt then goto check_ok_2 endi endi @@ -334,8 +343,8 @@ if $data[0][3] == $totalMsgOfOneTopic then if $data[1][3] == $totalMsgOfNtb then goto check_ok_3 endi -elif $data[1][3] == $totalMsgOfOneTopic then - if $data[0][3] == $totalMsgOfNtb then +elif $data[0][3] == $totalMsgOfNtb then + if $data[1][3] == $totalMsgOfOneTopic then goto check_ok_3 endi endi diff --git a/tests/script/tsim/tmq/basic3.sim b/tests/script/tsim/tmq/basic3.sim index 8d677766d74371209e53bab94b62a524318146ee..a64dd6924d7c30dec12e315924439b37019af500 100644 --- a/tests/script/tsim/tmq/basic3.sim +++ b/tests/script/tsim/tmq/basic3.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -83,6 +86,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -111,8 +117,8 @@ endi $consumerId = 0 $totalMsgOfStb = $ctbNum * $rowsPerCtb -$expectmsgcnt = $totalMsgOfStb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from stb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $cdbName -s start @@ -130,10 +136,10 @@ endi if $data[0][1] != $consumerId then return -1 endi -if $data[0][2] != $expectmsgcnt then - return -1 -endi -if $data[0][3] != $expectmsgcnt then +#if $data[0][2] != $expectmsgcnt then +# return -1 +#endi +if $data[0][3] != $totalMsgOfStb then return -1 endi $loop_cnt = $loop_cnt + 1 @@ -154,6 +160,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -182,8 +191,8 @@ endi $consumerId = 0 $totalMsgOfCtb = $rowsPerCtb -$expectmsgcnt = $totalMsgOfCtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ctb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -201,7 +210,7 @@ endi if $data[0][1] != $consumerId then return -1 endi -if $data[0][2] != $totalMsgOfCtb then +if $data[0][2] != $expectmsgcnt then return -1 endi if $data[0][3] != $totalMsgOfCtb then @@ -225,6 +234,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -253,8 +265,8 @@ endi $consumerId = 0 $totalMsgOfNtb = $rowsPerCtb -$expectmsgcnt = $totalMsgOfNtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ntb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -272,7 +284,7 @@ endi if $data[0][1] != $consumerId then return -1 endi -if $data[0][2] != $totalMsgOfNtb then +if $data[0][2] != $expectmsgcnt then return -1 endi if $data[0][3] != $totalMsgOfNtb then diff --git a/tests/script/tsim/tmq/basic3Of2Cons.sim b/tests/script/tsim/tmq/basic3Of2Cons.sim index 4921c86c4574174b06af4d906b9a3e74e8ee9c3c..4e47e3dbf9a0eeaf4380e43ceb6caef81f3c8770 100644 --- a/tests/script/tsim/tmq/basic3Of2Cons.sim +++ b/tests/script/tsim/tmq/basic3Of2Cons.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -82,6 +85,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -110,10 +116,10 @@ endi $consumerId = 0 $totalMsgOfStb = $ctbNum * $rowsPerCtb -$expectmsgcnt = $totalMsgOfStb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 3 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from stb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $cdbName -s start @@ -163,19 +169,19 @@ endi if $data[0][3] <= 0 then return -1 endi -if $data[0][3] >= $expectmsgcnt then +if $data[0][3] >= $totalMsgOfStb then return -1 endi if $data[1][3] <= 0 then return -1 endi -if $data[1][3] >= $expectmsgcnt then +if $data[1][3] >= $totalMsgOfStb then return -1 endi $sumOfMsgRows = $data[0][3] + $data[1][3] -if $sumOfMsgRows != $expectmsgcnt then +if $sumOfMsgRows != $totalMsgOfStb then return -1 endi @@ -197,6 +203,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -225,10 +234,10 @@ endi $consumerId = 0 $totalMsgOfCtb = $rowsPerCtb -$expectmsgcnt = $totalMsgOfCtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ctb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -255,13 +264,13 @@ if $data[0][1] == 1 then endi endi -# either $data[0][2] == $totalMsgOfCtb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfCtb -if $data[0][2] == $totalMsgOfCtb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_0 endi -elif $data[1][2] == $totalMsgOfCtb then +elif $data[1][2] == $expectmsgcnt then if $data[0][2] == 0 then goto check_ok_0 endi @@ -299,6 +308,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -327,10 +339,10 @@ endi $consumerId = 0 $totalMsgOfNtb = $rowsPerCtb -$expectmsgcnt = $totalMsgOfNtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 1 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ntb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -357,13 +369,13 @@ if $data[1][1] == 0 then endi endi -# either $data[0][2] == $totalMsgOfNtb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfNtb -if $data[0][2] == $totalMsgOfNtb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_2 endi -elif $data[1][2] == $totalMsgOfNtb then +elif $data[1][2] == $expectmsgcnt then if $data[0][2] == 0 then goto check_ok_2 endi diff --git a/tests/script/tsim/tmq/basic4.sim b/tests/script/tsim/tmq/basic4.sim index 9b418f12f2b95410994cf52fd4e140a8dcc73889..6b35342ad119431d1eece232486069c9792015d9 100644 --- a/tests/script/tsim/tmq/basic4.sim +++ b/tests/script/tsim/tmq/basic4.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -80,8 +83,8 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfStb = $ctbNum * $rowsPerCtb $totalMsgOfStb = $totalMsgOfStb * $topicNum -$expectmsgcnt = $totalMsgOfStb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 9 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from stb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $dbName -s start @@ -102,7 +105,7 @@ endi if $data[0][2] != $expectmsgcnt then return -1 endi -if $data[0][3] != $expectmsgcnt then +if $data[0][3] != $totalMsgOfStb then return -1 endi @@ -115,6 +118,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -137,8 +143,8 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfCtb = $rowsPerCtb * $topicNum -$expectmsgcnt = $totalMsgOfCtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ctb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -156,7 +162,7 @@ endi if $data[0][1] != $consumerId then return -1 endi -if $data[0][2] != $totalMsgOfCtb then +if $data[0][2] != $expectmsgcnt then return -1 endi if $data[0][3] != $totalMsgOfCtb then @@ -172,6 +178,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -194,8 +203,8 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfNtb = $rowsPerCtb * $topicNum -$expectmsgcnt = $totalMsgOfNtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ntb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -213,7 +222,7 @@ endi if $data[0][1] != $consumerId then return -1 endi -if $data[0][2] != $totalMsgOfNtb then +if $data[0][2] != $expectmsgcnt then return -1 endi if $data[0][3] != $totalMsgOfNtb then diff --git a/tests/script/tsim/tmq/basic4Of2Cons.sim b/tests/script/tsim/tmq/basic4Of2Cons.sim index f1755f732baa365689653d83e117d2780c40f621..122a91af3627fb12d00be61a503942e32dca604d 100644 --- a/tests/script/tsim/tmq/basic4Of2Cons.sim +++ b/tests/script/tsim/tmq/basic4Of2Cons.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -79,10 +82,10 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfStb = $ctbNum * $rowsPerCtb $totalMsgOfStb = $totalMsgOfStb * $topicNum -$expectmsgcnt = $totalMsgOfStb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = 9 +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfStb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from stb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -w $dbName -s start @@ -131,19 +134,19 @@ endi if $data[0][3] <= 0 then return -1 endi -if $data[0][3] >= $expectmsgcnt then +if $data[0][3] >= $totalMsgOfStb then return -1 endi if $data[1][3] <= 0 then return -1 endi -if $data[1][3] >= $expectmsgcnt then +if $data[1][3] >= $totalMsgOfStb then return -1 endi $sumOfConsRow = $data[0][3] + $data[1][3] -if $sumOfConsRow != $expectmsgcnt then +if $sumOfConsRow != $totalMsgOfStb then return -1 endi @@ -156,6 +159,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -178,10 +184,10 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfCtb = $rowsPerCtb * $topicNum -$expectmsgcnt = $totalMsgOfCtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfCtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ctb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -208,14 +214,14 @@ if $data[0][1] == 1 then endi endi -# either $data[0][2] == $totalMsgOfCtb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfCtb -if $data[0][2] == $totalMsgOfCtb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_0 endi elif $data[0][2] == 0 then - if $data[1][2] == $totalMsgOfCtb then + if $data[1][2] == $expectmsgcnt then goto check_ok_0 endi endi @@ -244,6 +250,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -266,10 +275,10 @@ $topicList = $topicList . ' $consumerId = 0 $totalMsgOfNtb = $rowsPerCtb * $topicNum -$expectmsgcnt = $totalMsgOfNtb -sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +$expectmsgcnt = $topicNum +sql insert into consumeinfo values (now , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) $consumerId = 1 -sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $expectmsgcnt , $ifcheckdata , $ifmanualcommit ) +sql insert into consumeinfo values (now+1s , $consumerId , $topicList , $keyList , $totalMsgOfNtb , $ifcheckdata , $ifmanualcommit ) print == start consumer to pull msgs from ntb print == tsim/tmq/consume.sh -d $dbName -y $pullDelay -g $showMsg -r $showRow -s start @@ -296,14 +305,14 @@ if $data[1][1] == 0 then endi endi -# either $data[0][2] == $totalMsgOfNtb and $data[1][2] == 0 -# or $data[0][2] == 0 and $data[1][2] == $totalMsgOfNtb -if $data[0][2] == $totalMsgOfNtb then +# either $data[0][2] == $expectmsgcnt and $data[1][2] == 0 +# or $data[0][2] == 0 and $data[1][2] == $expectmsgcnt +if $data[0][2] == $expectmsgcnt then if $data[1][2] == 0 then goto check_ok_2 endi elif $data[0][2] == 0 then - if $data[1][2] == $totalMsgOfNtb then + if $data[1][2] == $expectmsgcnt then goto check_ok_2 endi endi diff --git a/tests/script/tsim/tmq/consume.sh b/tests/script/tsim/tmq/consume.sh index 001ce6ae496cc7e5f7b4c5a3bf5b92b0c7cf12b3..f0c9197a5908d2be9d21baa7aca5f193415a29d5 100755 --- a/tests/script/tsim/tmq/consume.sh +++ b/tests/script/tsim/tmq/consume.sh @@ -79,15 +79,15 @@ CFG_DIR=$PRG_DIR/cfg LOG_DIR=$PRG_DIR/log echo "------------------------------------------------------------------------" +echo "TOP_DIR: $TOP_DIR" echo "BUILD_DIR: $BUILD_DIR" echo "SIM_DIR : $SIM_DIR" echo "CFG_DIR : $CFG_DIR" - -echo "PROGRAM: $PROGRAM -echo "CFG_DIR: $CFG_DIR -echo "POLL_DELAY: $POLL_DELAY -echo "DB_NAME: $DB_NAME +echo "PROGRAM: $PROGRAM" +echo "CFG_DIR: $CFG_DIR" +echo "POLL_DELAY: $POLL_DELAY" +echo "DB_NAME: $DB_NAME" echo "------------------------------------------------------------------------" if [ "$EXEC_OPTON" = "start" ]; then diff --git a/tests/script/tsim/tmq/snapshot.sim b/tests/script/tsim/tmq/snapshot.sim index de0468e6f26871cc4b5118889a0fcd1262c291e4..81fff3522499ff99ccfa9a92be5483ea42d775ba 100644 --- a/tests/script/tsim/tmq/snapshot.sim +++ b/tests/script/tsim/tmq/snapshot.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -83,6 +86,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -152,6 +158,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -223,6 +232,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) diff --git a/tests/script/tsim/tmq/snapshot1.sim b/tests/script/tsim/tmq/snapshot1.sim index e586719db2fa7646d487658d09e71693ff557c7a..c79892ae1d943a071c58fe2236eb90ef9a5e10d4 100644 --- a/tests/script/tsim/tmq/snapshot1.sim +++ b/tests/script/tsim/tmq/snapshot1.sim @@ -34,6 +34,9 @@ $showRow = 0 sql connect sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 + print == create topics from super table sql create topic topic_stb_column as select ts, c3 from stb sql create topic topic_stb_all as select ts, c1, c2, c3 from stb @@ -147,6 +150,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table for ctb sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) @@ -224,6 +230,9 @@ sql create database $cdbName vgroups 1 sleep 500 sql use $cdbName +print == alter database +sql alter database $cdbName wal_retention_period 3600 + print == create consume info table and consume result table for ntb sql create table consumeinfo (ts timestamp, consumerid int, topiclist binary(1024), keylist binary(1024), expectmsgcnt bigint, ifcheckdata int, ifmanualcommit int) sql create table consumeresult (ts timestamp, consumerid int, consummsgcnt bigint, consumrowcnt bigint, checkresult int) diff --git a/tests/script/tsim/tmq/topic.sim b/tests/script/tsim/tmq/topic.sim index cb1e74798ea072a03d2ea2570a5a245222b5c8c5..0bf0873e9f0513b08b6868bed220c5e3d74072f9 100644 --- a/tests/script/tsim/tmq/topic.sim +++ b/tests/script/tsim/tmq/topic.sim @@ -39,6 +39,8 @@ endi sql use $dbName +print == alter database +sql alter database $dbName wal_retention_period 3600 print == create super table sql create table $stbPrefix (ts timestamp, c1 int, c2 float, c3 binary(16)) tags (t1 int) diff --git a/tests/script/tsim/trans/create_stb.sim b/tests/script/tsim/trans/create_stb.sim new file mode 100644 index 0000000000000000000000000000000000000000..94041645d570296480b2557a3ec9bb21aca7241f --- /dev/null +++ b/tests/script/tsim/trans/create_stb.sim @@ -0,0 +1,72 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/deploy.sh -n dnode2 -i 2 +system sh/deploy.sh -n dnode3 -i 3 +system sh/deploy.sh -n dnode4 -i 4 +system sh/cfg.sh -n dnode1 -c transPullupInterval -v 1 +system sh/cfg.sh -n dnode2 -c transPullupInterval -v 1 +system sh/cfg.sh -n dnode3 -c transPullupInterval -v 1 +system sh/cfg.sh -n dnode4 -c transPullupInterval -v 1 +system sh/exec.sh -n dnode1 -s start +system sh/exec.sh -n dnode2 -s start +system sh/exec.sh -n dnode3 -s start +system sh/exec.sh -n dnode4 -s start +sql connect + +print =============== step1: create dnodes +sql create dnode $hostname port 7200 +sql create dnode $hostname port 7300 +sql create dnode $hostname port 7400 + +$x = 0 +step1: + $x = $x + 1 + sleep 1000 + if $x == 10 then + return -1 + endi +sql select * from information_schema.ins_dnodes -x step1 +if $data(1)[4] != ready then + goto step1 +endi +if $data(2)[4] != ready then + goto step1 +endi +if $data(3)[4] != ready then + goto step1 +endi + +print =============== step2: create mnode 2 and 3 +sql create mnode on dnode 2 +sql create mnode on dnode 3 +sql create database db vgroups 2 + +print =============== step3: kill dnode4 +system sh/exec.sh -n dnode4 -s stop -x SIGKILL +sql use db +sql_error create table stb (ts timestamp, i int) tags (j int) + +print =============== step4: create database +sql show transactions +if $rows != 1 then + return -1 +endi + +sleep 3000 +system sh/exec.sh -n dnode4 -s start + +$wt = 0 +step4: +$wt = $wt + 1 +sleep 1000 +if $wt == 200 then + print ====> transaction already running + return -1 +endi + +sql show transactions +if $rows != 0 then + print wait 1 seconds to alter + goto step4 +endi + diff --git a/tests/script/tsim/user/privilege_db.sim b/tests/script/tsim/user/privilege_db.sim index b708fdab64c1931d6a86c67a8f3ec86cb880677a..50eaa1210866dcfb98f0c889a5eef9960d2faf81 100644 --- a/tests/script/tsim/user/privilege_db.sim +++ b/tests/script/tsim/user/privilege_db.sim @@ -4,13 +4,13 @@ system sh/exec.sh -n dnode1 -s start sql connect print =============== create db -sql create database d1 vgroups 1; +sql create database d1 vgroups 1 wal_retention_period 3600; sql use d1 sql create table d1_stb (ts timestamp, i int) tags (j int) sql create topic d1_topic_1 as select ts, i from d1_stb -sql create database d2 vgroups 1; -sql create database d3 vgroups 1; +sql create database d2 vgroups 1 wal_retention_period 3600; +sql create database d3 vgroups 1 wal_retention_period 3600; sql select * from information_schema.ins_databases if $rows != 5 then return -1 diff --git a/tests/script/tsim/user/privilege_table.sim b/tests/script/tsim/user/privilege_table.sim new file mode 100644 index 0000000000000000000000000000000000000000..05f91ff5b0228e0ecbd40a99ba38af2e69229bb2 --- /dev/null +++ b/tests/script/tsim/user/privilege_table.sim @@ -0,0 +1,302 @@ +system sh/stop_dnodes.sh +system sh/deploy.sh -n dnode1 -i 1 +system sh/exec.sh -n dnode1 -s start +sql connect + +print =============== init env +sql drop database if exists test; +sql create database test vgroups 1; +sql use test; +sql create stable st1(ts timestamp, i int) tags(id int, loc varchar(20)); +sql create table st1s1 using st1 tags(1, 'beijing'); +sql create table st1s2 using st1 tags(2, 'shanghai'); +sql insert into st1s1 values(now, 1) st1s2 values(now, 2); +sql create stable st2(ts timestamp, i int) tags(id int, loc varchar(20)); +sql create table st2s1 using st2 tags(1, 'beijing'); +sql create table st2s2 using st2 tags(2, 'shanghai'); +sql insert into st2s1 values(now, 1) st2s2 values(now, 2); +sql create user wxy pass 'taosdata'; + +print =============== case 1: database unauthorized and table unauthorized +sql close +sql connect wxy + +sql reset query cache; +sql_error select * from test.st1; +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + + +print =============== case 2: database unauthorized and table read privilege +sql close +sql connect + +sql grant read on test.st1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 3: database unauthorized and table read privilege with condition +sql close +sql connect + +sql revoke read on test.st1 from wxy; +sql grant read on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 1 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10); +sql_error insert into test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 4: database unauthorized and table write privilege +sql close +sql connect + +sql revoke read on test.st1 with id = 1 from wxy; +sql grant write on test.st1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql_error select tbname, * from test.st1; +sql insert into test.st1s1 values(now, 10); +sql insert into test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 5: database unauthorized and table write privilege with condition +sql close +sql connect + +sql revoke write on test.st1 from wxy; +sql grant write on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql_error select tbname, * from test.st1; +sql insert into test.st1s1 values(now, 10); +sql insert into test.st1s3 using test.st1 tags(1, 'dachang') values(now, 100); +sql_error insert into test.st1s2 values(now, 20); +sql_error insert into test.st1s4 using test.st1 tags(3, 'dachang') values(now, 300); +sql_error select * from test.st2; +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 6: database read privilege and table unauthorized +sql close +sql connect + +sql revoke write on test.st1 with id = 1 from wxy; +sql grant read on test.* to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 6 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql select * from test.st2; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 7: database read privilege and table read privilege +sql close +sql connect + +sql grant read on test.st1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 6 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql select * from test.st2; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 8: database read privilege and table read privilege with condition +sql close +sql connect + +sql revoke read on test.st1 from wxy; +sql grant read on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 4 then + return -1 +endi +sql_error insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql select * from test.st2; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 9: database read privilege and table write privilege +sql close +sql connect + +sql revoke read on test.st1 with id = 1 from wxy; +sql grant write on test.st1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 6 then + return -1 +endi +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql select * from test.st2; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 10: database read privilege and table write privilege with condition +sql close +sql connect + +sql revoke write on test.st1 from wxy; +sql grant write on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 8 then + return -1 +endi +sql insert into test.st1s1 values(now, 10); +sql_error insert into test.st1s2 values(now, 20); +sql select * from test.st2; +if $rows != 2 then + return -1 +endi +sql_error insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 11: database write privilege and table unauthorized +sql close +sql connect + +sql revoke read on test.* from wxy; +sql revoke write on test.st1 with id = 1 from wxy; +sql grant write on test.* to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql_error select * from test.st1; +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 12: database write privilege and table read privilege +sql close +sql connect + +sql grant read on test.st1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 11 then + return -1 +endi +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 13: database write privilege and table read privilege with condition +sql close +sql connect + +sql revoke read on test.st1 from wxy; +sql grant read on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql select * from test.st1; +if $rows != 8 then + return -1 +endi +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 14: database write privilege and table write privilege +sql close +sql connect + +sql revoke read on test.st1 with id = 1 from wxy; +sql grant write on test.st1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql_error select * from test.st1; +sql insert into test.st1s1 values(now, 10) test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +print =============== case 15: database write privilege and table write privilege with condition +sql close +sql connect + +sql revoke write on test.st1 from wxy; +sql grant write on test.st1 with id = 1 to wxy; + +sql close +sql connect wxy + +sql reset query cache; +sql_error select * from test.st1; +sql insert into test.st1s1 values(now, 10); +sql_error insert into test.st1s2 values(now, 20); +sql_error select * from test.st2; +sql insert into test.st2s1 values(now, 10) test.st2s2 values(now, 20); + +system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/user/privilege_topic.sim b/tests/script/tsim/user/privilege_topic.sim index 9ce5bebec3d68761fb5364896f81e4a5e1428878..9d096a97807a70dfe34297c7fac688502b236a5a 100644 --- a/tests/script/tsim/user/privilege_topic.sim +++ b/tests/script/tsim/user/privilege_topic.sim @@ -4,9 +4,9 @@ system sh/exec.sh -n dnode1 -s start sql connect print =============== create db -sql create database root_d1 vgroups 1; -sql create database root_d2 vgroups 1; -sql create database root_d3 vgroups 1; +sql create database root_d1 vgroups 1 wal_retention_period 3600; +sql create database root_d2 vgroups 1 wal_retention_period 3600; +sql create database root_d3 vgroups 1 wal_retention_period 3600; sql show user privileges if $rows != 1 then diff --git a/tests/script/tsim/valgrind/checkError7.sim b/tests/script/tsim/valgrind/checkError7.sim index af42d1e76b50bc07e9c7a484bd24c9544517f980..edfe8816c9d0e83f705032c64da2dd5ccd7034f2 100644 --- a/tests/script/tsim/valgrind/checkError7.sim +++ b/tests/script/tsim/valgrind/checkError7.sim @@ -8,8 +8,9 @@ sql create database d1 sql use d1 $x = 0 -while $x < 128 +while $x < 5 $tb = d1.s . $x + print create table $tb (ts timestamp, i int) tags (j int) sql create table $tb (ts timestamp, i int) tags (j int) $x = $x + 1 endw @@ -17,7 +18,7 @@ endw print ======================== describe stables # TODO : create stable error $m = 0 -while $m < 128 +while $m < 5 $tb = s . $m $filter = ' . $tb $filter = $filter . ' @@ -36,15 +37,16 @@ print ======================== show stables sql show d1.stables print num of stables is $rows -if $rows != 128 then +if $rows != 5 then return -1 endi print ======================== create table $x = 0 -while $x < 424 +while $x < 42 $tb = d1.t . $x + print create table $tb using d1.s0 tags( $x ) sql create table $tb using d1.s0 tags( $x ) $x = $x + 1 endw @@ -54,7 +56,7 @@ print ======================== show stables sql show d1.tables print num of tables is $rows -if $rows != 424 then +if $rows != 42 then return -1 endi diff --git a/tests/script/tsim/valgrind/checkUdf.sim b/tests/script/tsim/valgrind/checkUdf.sim index caf316bd868a057cd8a161817c85d8664a9db82e..e316c104ed68bcc32bc4f84fa3ee803b5a91ae1a 100644 --- a/tests/script/tsim/valgrind/checkUdf.sim +++ b/tests/script/tsim/valgrind/checkUdf.sim @@ -15,10 +15,10 @@ sql insert into t values(now, 1)(now+1s, 2); system_content printf %OS% if $system_content == Windows_NT then - sql create function udf1 as 'C:\\Windows\\Temp\\udf1.dll' outputtype int bufSize 8; + sql create function udf1 as 'C:\\Windows\\Temp\\udf1.dll' outputtype int; sql create aggregate function udf2 as 'C:\\Windows\\Temp\\udf2.dll' outputtype double bufSize 8; else - sql create function udf1 as '/tmp/udf/libudf1.so' outputtype int bufSize 8; + sql create function udf1 as '/tmp/udf/libudf1.so' outputtype int; sql create aggregate function udf2 as '/tmp/udf/libudf2.so' outputtype double bufSize 8; endi sql show functions; @@ -29,10 +29,10 @@ sql select udf1(f) from t; if $rows != 2 then return -1 endi -if $data00 != 88 then +if $data00 != 1 then return -1 endi -if $data10 != 88 then +if $data10 != 1 then return -1 endi @@ -51,10 +51,10 @@ sql select udf1(f1, f2) from t2; if $rows != 2 then return -1 endi -if $data00 != 88 then +if $data00 != 1 then return -1 endi -if $data10 != 88 then +if $data10 != 1 then return -1 endi @@ -72,10 +72,10 @@ print $rows , $data00 , $data10 , $data20 , $data30 if $rows != 4 then return -1 endi -if $data00 != 88 then +if $data00 != 1 then return -1 endi -if $data10 != 88 then +if $data10 != 1 then return -1 endi @@ -114,10 +114,10 @@ print $rows , $data00 , $data01 if $rows != 1 then return -1 endi -if $data00 != 176.000000000 then +if $data00 != 2.000000000 then return -1 endi -if $data01 != 152.420471066 then +if $data01 != 1.732050808 then return -1 endi diff --git a/tests/script/win-test-file b/tests/script/win-test-file new file mode 100644 index 0000000000000000000000000000000000000000..3b358993fa1e9f9c1e2264399c434f4df3c07d0d --- /dev/null +++ b/tests/script/win-test-file @@ -0,0 +1,403 @@ +./test.sh -f tsim/user/basic.sim +./test.sh -f tsim/user/password.sim +./test.sh -f tsim/user/privilege_db.sim +./test.sh -f tsim/user/privilege_sysinfo.sim +./test.sh -f tsim/user/privilege_topic.sim +./test.sh -f tsim/user/privilege_table.sim +./test.sh -f tsim/db/alter_option.sim +rem ./test.sh -f tsim/db/alter_replica_13.sim +./test.sh -f tsim/db/alter_replica_31.sim +./test.sh -f tsim/db/basic1.sim +./test.sh -f tsim/db/basic2.sim +./test.sh -f tsim/db/basic3.sim +./test.sh -f tsim/db/basic4.sim +./test.sh -f tsim/db/basic5.sim +./test.sh -f tsim/db/basic6.sim +./test.sh -f tsim/db/commit.sim +./test.sh -f tsim/db/create_all_options.sim +./test.sh -f tsim/db/delete_reuse1.sim +./test.sh -f tsim/db/delete_reuse2.sim +./test.sh -f tsim/db/delete_reusevnode.sim +./test.sh -f tsim/db/delete_reusevnode2.sim +./test.sh -f tsim/db/delete_writing1.sim +./test.sh -f tsim/db/delete_writing2.sim +./test.sh -f tsim/db/error1.sim +./test.sh -f tsim/db/keep.sim +./test.sh -f tsim/db/len.sim +./test.sh -f tsim/db/repeat.sim +./test.sh -f tsim/db/show_create_db.sim +./test.sh -f tsim/db/show_create_table.sim +./test.sh -f tsim/db/tables.sim +./test.sh -f tsim/db/taosdlog.sim +./test.sh -f tsim/dnode/balance_replica1.sim +./test.sh -f tsim/dnode/balance_replica3.sim +./test.sh -f tsim/dnode/balance1.sim +./test.sh -f tsim/dnode/balance2.sim +./test.sh -f tsim/dnode/balance3.sim +./test.sh -f tsim/dnode/balancex.sim +./test.sh -f tsim/dnode/create_dnode.sim +./test.sh -f tsim/dnode/drop_dnode_has_mnode.sim +./test.sh -f tsim/dnode/drop_dnode_has_qnode_snode.sim +./test.sh -f tsim/dnode/drop_dnode_has_vnode_replica1.sim +./test.sh -f tsim/dnode/drop_dnode_has_vnode_replica3.sim +./test.sh -f tsim/dnode/drop_dnode_has_multi_vnode_replica1.sim +./test.sh -f tsim/dnode/drop_dnode_has_multi_vnode_replica3.sim +./test.sh -f tsim/dnode/drop_dnode_force.sim +./test.sh -f tsim/dnode/offline_reason.sim +./test.sh -f tsim/dnode/redistribute_vgroup_replica1.sim +./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v1_leader.sim +./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v1_follower.sim +./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v2.sim +./test.sh -f tsim/dnode/redistribute_vgroup_replica3_v3.sim +./test.sh -f tsim/dnode/vnode_clean.sim +./test.sh -f tsim/dnode/use_dropped_dnode.sim +./test.sh -f tsim/dnode/split_vgroup_replica1.sim +./test.sh -f tsim/dnode/split_vgroup_replica3.sim +./test.sh -f tsim/import/basic.sim +./test.sh -f tsim/import/commit.sim +./test.sh -f tsim/import/large.sim +./test.sh -f tsim/import/replica1.sim +./test.sh -f tsim/insert/backquote.sim +./test.sh -f tsim/insert/basic.sim +./test.sh -f tsim/insert/basic0.sim +./test.sh -f tsim/insert/basic1.sim +./test.sh -f tsim/insert/basic2.sim +./test.sh -f tsim/insert/commit-merge0.sim +./test.sh -f tsim/insert/insert_drop.sim +./test.sh -f tsim/insert/insert_select.sim +./test.sh -f tsim/insert/null.sim +./test.sh -f tsim/insert/query_block1_file.sim +./test.sh -f tsim/insert/query_block1_memory.sim +./test.sh -f tsim/insert/query_block2_file.sim +./test.sh -f tsim/insert/query_block2_memory.sim +./test.sh -f tsim/insert/query_file_memory.sim +./test.sh -f tsim/insert/query_multi_file.sim +./test.sh -f tsim/insert/tcp.sim +./test.sh -f tsim/insert/update0.sim +./test.sh -f tsim/insert/update1_sort_merge.sim +./test.sh -f tsim/insert/update2.sim +./test.sh -f tsim/parser/alter__for_community_version.sim +./test.sh -f tsim/parser/alter_column.sim +./test.sh -f tsim/parser/alter_stable.sim +./test.sh -f tsim/parser/alter.sim +./test.sh -f tsim/parser/alter1.sim +./test.sh -f tsim/parser/auto_create_tb_drop_tb.sim +./test.sh -f tsim/parser/auto_create_tb.sim +./test.sh -f tsim/parser/between_and.sim +./test.sh -f tsim/parser/binary_escapeCharacter.sim +./test.sh -f tsim/parser/col_arithmetic_operation.sim +./test.sh -f tsim/parser/columnValue_bigint.sim +./test.sh -f tsim/parser/columnValue_bool.sim +./test.sh -f tsim/parser/columnValue_double.sim +./test.sh -f tsim/parser/columnValue_float.sim +./test.sh -f tsim/parser/columnValue_int.sim +./test.sh -f tsim/parser/columnValue_smallint.sim +./test.sh -f tsim/parser/columnValue_tinyint.sim +./test.sh -f tsim/parser/columnValue_unsign.sim +./test.sh -f tsim/parser/commit.sim +./test.sh -f tsim/parser/condition.sim +./test.sh -f tsim/parser/constCol.sim +./test.sh -f tsim/parser/create_db.sim +./test.sh -f tsim/parser/create_mt.sim +./test.sh -f tsim/parser/create_tb_with_tag_name.sim +./test.sh -f tsim/parser/create_tb.sim +./test.sh -f tsim/parser/dbtbnameValidate.sim +./test.sh -f tsim/parser/distinct.sim +./test.sh -f tsim/parser/fill_us.sim +./test.sh -f tsim/parser/fill.sim +./test.sh -f tsim/parser/first_last.sim +./test.sh -f tsim/parser/fill_stb.sim +./test.sh -f tsim/parser/interp.sim +./test.sh -f tsim/parser/fourArithmetic-basic.sim +./test.sh -f tsim/parser/function.sim +./test.sh -f tsim/parser/groupby-basic.sim +./test.sh -f tsim/parser/groupby.sim +./test.sh -f tsim/parser/having_child.sim +./test.sh -f tsim/parser/having.sim +./test.sh -f tsim/parser/import_commit1.sim +./test.sh -f tsim/parser/import_commit2.sim +./test.sh -f tsim/parser/import_commit3.sim +./test.sh -f tsim/parser/import_file.sim +./test.sh -f tsim/parser/import.sim +./test.sh -f tsim/parser/insert_multiTbl.sim +./test.sh -f tsim/parser/insert_tb.sim +./test.sh -f tsim/parser/join_manyblocks.sim +./test.sh -f tsim/parser/join_multitables.sim +./test.sh -f tsim/parser/join_multivnode.sim +./test.sh -f tsim/parser/join.sim +./test.sh -f tsim/parser/last_cache.sim +./test.sh -f tsim/parser/last_groupby.sim +./test.sh -f tsim/parser/lastrow.sim +./test.sh -f tsim/parser/lastrow2.sim +./test.sh -f tsim/parser/like.sim +./test.sh -f tsim/parser/limit.sim +./test.sh -f tsim/parser/limit1.sim +./test.sh -f tsim/parser/mixed_blocks.sim +./test.sh -f tsim/parser/nchar.sim +./test.sh -f tsim/parser/nestquery.sim +./test.sh -f tsim/parser/null_char.sim +./test.sh -f tsim/parser/precision_ns.sim +./test.sh -f tsim/parser/projection_limit_offset.sim +./test.sh -f tsim/parser/regex.sim +./test.sh -f tsim/parser/regressiontest.sim +./test.sh -f tsim/parser/select_across_vnodes.sim +./test.sh -f tsim/parser/select_distinct_tag.sim +./test.sh -f tsim/parser/select_from_cache_disk.sim +./test.sh -f tsim/parser/select_with_tags.sim +./test.sh -f tsim/parser/selectResNum.sim +./test.sh -f tsim/parser/set_tag_vals.sim +./test.sh -f tsim/parser/single_row_in_tb.sim +./test.sh -f tsim/parser/sliding.sim +./test.sh -f tsim/parser/slimit_alter_tags.sim +./test.sh -f tsim/parser/slimit.sim +./test.sh -f tsim/parser/slimit1.sim +./test.sh -f tsim/parser/stableOp.sim +./test.sh -f tsim/parser/tags_dynamically_specifiy.sim +./test.sh -f tsim/parser/tags_filter.sim +./test.sh -f tsim/parser/tbnameIn.sim +./test.sh -f tsim/parser/timestamp.sim +./test.sh -f tsim/parser/top_groupby.sim +./test.sh -f tsim/parser/topbot.sim +./test.sh -f tsim/parser/union.sim +./test.sh -f tsim/parser/union_sysinfo.sim +./test.sh -f tsim/parser/where.sim +./test.sh -f tsim/query/tagLikeFilter.sim +./test.sh -f tsim/query/charScalarFunction.sim +./test.sh -f tsim/query/explain.sim +./test.sh -f tsim/query/interval-offset.sim +./test.sh -f tsim/query/interval.sim +./test.sh -f tsim/query/scalarFunction.sim +./test.sh -f tsim/query/scalarNull.sim +./test.sh -f tsim/query/session.sim +./test.sh -f tsim/query/sys_tbname.sim +./test.sh -f tsim/query/groupby.sim +./test.sh -f tsim/query/event.sim +./test.sh -f tsim/query/forceFill.sim +./test.sh -f tsim/query/emptyTsRange.sim +./test.sh -f tsim/query/partitionby.sim +./test.sh -f tsim/qnode/basic1.sim +./test.sh -f tsim/snode/basic1.sim +./test.sh -f tsim/mnode/basic1.sim +./test.sh -f tsim/mnode/basic2.sim +./test.sh -f tsim/mnode/basic3.sim +./test.sh -f tsim/mnode/basic4.sim +./test.sh -f tsim/mnode/basic5.sim +./test.sh -f tsim/show/basic.sim +./test.sh -f tsim/table/autocreate.sim +./test.sh -f tsim/table/basic1.sim +./test.sh -f tsim/table/basic2.sim +./test.sh -f tsim/table/basic3.sim +./test.sh -f tsim/table/bigint.sim +./test.sh -f tsim/table/binary.sim +./test.sh -f tsim/table/bool.sim +./test.sh -f tsim/table/column_name.sim +./test.sh -f tsim/table/column_num.sim +./test.sh -f tsim/table/column_value.sim +./test.sh -f tsim/table/column2.sim +./test.sh -f tsim/table/createmulti.sim +./test.sh -f tsim/table/date.sim +./test.sh -f tsim/table/db.table.sim +./test.sh -f tsim/table/delete_reuse1.sim +./test.sh -f tsim/table/delete_reuse2.sim +./test.sh -f tsim/table/delete_writing.sim +./test.sh -f tsim/table/describe.sim +./test.sh -f tsim/table/double.sim +./test.sh -f tsim/table/float.sim +./test.sh -f tsim/table/hash.sim +./test.sh -f tsim/table/int.sim +./test.sh -f tsim/table/limit.sim +./test.sh -f tsim/table/smallint.sim +./test.sh -f tsim/table/table_len.sim +./test.sh -f tsim/table/table.sim +./test.sh -f tsim/table/tinyint.sim +./test.sh -f tsim/table/vgroup.sim +./test.sh -f tsim/stream/basic0.sim -g +./test.sh -f tsim/stream/basic1.sim +./test.sh -f tsim/stream/basic2.sim +./test.sh -f tsim/stream/drop_stream.sim +./test.sh -f tsim/stream/fillHistoryBasic1.sim +./test.sh -f tsim/stream/fillHistoryBasic2.sim +./test.sh -f tsim/stream/fillHistoryBasic3.sim +./test.sh -f tsim/stream/distributeInterval0.sim +./test.sh -f tsim/stream/distributeIntervalRetrive0.sim +./test.sh -f tsim/stream/distributeSession0.sim +./test.sh -f tsim/stream/session0.sim +./test.sh -f tsim/stream/session1.sim +./test.sh -f tsim/stream/state0.sim +./test.sh -f tsim/stream/triggerInterval0.sim +./test.sh -f tsim/stream/triggerSession0.sim +./test.sh -f tsim/stream/partitionby.sim +./test.sh -f tsim/stream/partitionby1.sim +./test.sh -f tsim/stream/schedSnode.sim +./test.sh -f tsim/stream/windowClose.sim +./test.sh -f tsim/stream/ignoreExpiredData.sim +./test.sh -f tsim/stream/sliding.sim +./test.sh -f tsim/stream/partitionbyColumnInterval.sim +./test.sh -f tsim/stream/partitionbyColumnSession.sim +./test.sh -f tsim/stream/partitionbyColumnState.sim +./test.sh -f tsim/stream/deleteInterval.sim +./test.sh -f tsim/stream/deleteSession.sim +./test.sh -f tsim/stream/deleteState.sim +./test.sh -f tsim/stream/fillIntervalDelete0.sim +./test.sh -f tsim/stream/fillIntervalDelete1.sim +./test.sh -f tsim/stream/fillIntervalLinear.sim +./test.sh -f tsim/stream/fillIntervalPartitionBy.sim +./test.sh -f tsim/stream/fillIntervalPrevNext.sim +./test.sh -f tsim/stream/fillIntervalValue.sim +./test.sh -f tsim/stream/udTableAndTag0.sim +./test.sh -f tsim/stream/udTableAndTag1.sim +./test.sh -f tsim/trans/lossdata1.sim +./test.sh -f tsim/trans/create_db.sim +./test.sh -f tsim/tmq/basic1.sim +./test.sh -f tsim/tmq/basic2.sim +./test.sh -f tsim/tmq/basic3.sim +./test.sh -f tsim/tmq/basic4.sim +./test.sh -f tsim/tmq/basic1Of2Cons.sim +./test.sh -f tsim/tmq/basic2Of2Cons.sim +./test.sh -f tsim/tmq/basic3Of2Cons.sim +./test.sh -f tsim/tmq/basic4Of2Cons.sim +./test.sh -f tsim/tmq/basic2Of2ConsOverlap.sim +./test.sh -f tsim/tmq/topic.sim +./test.sh -f tsim/tmq/snapshot.sim +./test.sh -f tsim/tmq/snapshot1.sim +./test.sh -f tsim/stable/alter_comment.sim +./test.sh -f tsim/stable/alter_count.sim +./test.sh -f tsim/stable/alter_import.sim +./test.sh -f tsim/stable/alter_insert1.sim +./test.sh -f tsim/stable/alter_insert2.sim +./test.sh -f tsim/stable/alter_metrics.sim +./test.sh -f tsim/stable/column_add.sim +./test.sh -f tsim/stable/column_drop.sim +./test.sh -f tsim/stable/column_modify.sim +./test.sh -f tsim/stable/disk.sim +./test.sh -f tsim/stable/dnode3.sim +./test.sh -f tsim/stable/metrics.sim +./test.sh -f tsim/stable/refcount.sim +./test.sh -f tsim/stable/tag_add.sim +./test.sh -f tsim/stable/tag_drop.sim +./test.sh -f tsim/stable/tag_filter.sim +./test.sh -f tsim/stable/tag_modify.sim +./test.sh -f tsim/stable/tag_rename.sim +./test.sh -f tsim/stable/values.sim +./test.sh -f tsim/stable/vnode3.sim +./test.sh -f tsim/stable/metrics_idx.sim +./test.sh -f tsim/sma/drop_sma.sim +./test.sh -f tsim/sma/sma_leak.sim +./test.sh -f tsim/sma/tsmaCreateInsertQuery.sim +./test.sh -f tsim/sma/rsmaCreateInsertQuery.sim +./test.sh -f tsim/sma/rsmaPersistenceRecovery.sim +./test.sh -f tsim/valgrind/checkError1.sim +./test.sh -f tsim/valgrind/checkError2.sim +./test.sh -f tsim/valgrind/checkError3.sim +./test.sh -f tsim/valgrind/checkError4.sim +./test.sh -f tsim/valgrind/checkError5.sim +./test.sh -f tsim/valgrind/checkError6.sim +./test.sh -f tsim/valgrind/checkError7.sim +./test.sh -f tsim/valgrind/checkError8.sim +./test.sh -f tsim/vnode/replica3_basic.sim +./test.sh -f tsim/vnode/replica3_repeat.sim +./test.sh -f tsim/vnode/replica3_vgroup.sim +./test.sh -f tsim/vnode/replica3_many.sim +./test.sh -f tsim/vnode/replica3_import.sim +./test.sh -f tsim/vnode/stable_balance_replica1.sim +./test.sh -f tsim/vnode/stable_dnode2_stop.sim +./test.sh -f tsim/vnode/stable_dnode2.sim +./test.sh -f tsim/vnode/stable_dnode3.sim +./test.sh -f tsim/vnode/stable_replica3_dnode6.sim +./test.sh -f tsim/vnode/stable_replica3_vnode3.sim +./test.sh -f tsim/sync/3Replica1VgElect.sim +./test.sh -f tsim/sync/3Replica5VgElect.sim +./test.sh -f tsim/sync/oneReplica1VgElect.sim +./test.sh -f tsim/sync/oneReplica5VgElect.sim +./test.sh -f tsim/catalog/alterInCurrent.sim +./test.sh -f tsim/scalar/in.sim +./test.sh -f tsim/scalar/scalar.sim +./test.sh -f tsim/scalar/filter.sim +./test.sh -f tsim/scalar/caseWhen.sim +./test.sh -f tsim/scalar/tsConvert.sim +./test.sh -f tsim/alter/cached_schema_after_alter.sim +./test.sh -f tsim/alter/dnode.sim +./test.sh -f tsim/alter/table.sim +./test.sh -f tsim/cache/new_metrics.sim +./test.sh -f tsim/cache/restart_table.sim +./test.sh -f tsim/cache/restart_metrics.sim +./test.sh -f tsim/column/commit.sim +./test.sh -f tsim/column/metrics.sim +./test.sh -f tsim/column/table.sim +./test.sh -f tsim/compress/commitlog.sim +./test.sh -f tsim/compress/compress2.sim +./test.sh -f tsim/compress/compress.sim +./test.sh -f tsim/compress/uncompress.sim +./test.sh -f tsim/compute/avg.sim +./test.sh -f tsim/compute/block_dist.sim +./test.sh -f tsim/compute/bottom.sim +./test.sh -f tsim/compute/count.sim +./test.sh -f tsim/compute/diff.sim +./test.sh -f tsim/compute/diff2.sim +./test.sh -f tsim/compute/first.sim +./test.sh -f tsim/compute/interval.sim +./test.sh -f tsim/compute/last_row.sim +./test.sh -f tsim/compute/last.sim +./test.sh -f tsim/compute/leastsquare.sim +./test.sh -f tsim/compute/max.sim +./test.sh -f tsim/compute/min.sim +./test.sh -f tsim/compute/null.sim +./test.sh -f tsim/compute/percentile.sim +./test.sh -f tsim/compute/stddev.sim +./test.sh -f tsim/compute/sum.sim +./test.sh -f tsim/compute/top.sim +./test.sh -f tsim/field/2.sim +./test.sh -f tsim/field/3.sim +./test.sh -f tsim/field/4.sim +./test.sh -f tsim/field/5.sim +./test.sh -f tsim/field/6.sim +./test.sh -f tsim/field/binary.sim +./test.sh -f tsim/field/bigint.sim +./test.sh -f tsim/field/bool.sim +./test.sh -f tsim/field/double.sim +./test.sh -f tsim/field/float.sim +./test.sh -f tsim/field/int.sim +./test.sh -f tsim/field/single.sim +./test.sh -f tsim/field/smallint.sim +./test.sh -f tsim/field/tinyint.sim +./test.sh -f tsim/field/unsigined_bigint.sim +./test.sh -f tsim/vector/metrics_field.sim +./test.sh -f tsim/vector/metrics_mix.sim +./test.sh -f tsim/vector/metrics_query.sim +./test.sh -f tsim/vector/metrics_tag.sim +./test.sh -f tsim/vector/metrics_time.sim +./test.sh -f tsim/vector/multi.sim +./test.sh -f tsim/vector/single.sim +./test.sh -f tsim/vector/table_field.sim +./test.sh -f tsim/vector/table_mix.sim +./test.sh -f tsim/vector/table_query.sim +./test.sh -f tsim/vector/table_time.sim +./test.sh -f tsim/wal/kill.sim +./test.sh -f tsim/tag/3.sim +./test.sh -f tsim/tag/4.sim +./test.sh -f tsim/tag/5.sim +./test.sh -f tsim/tag/6.sim +./test.sh -f tsim/tag/add.sim +./test.sh -f tsim/tag/bigint.sim +./test.sh -f tsim/tag/binary_binary.sim +./test.sh -f tsim/tag/binary.sim +./test.sh -f tsim/tag/bool_binary.sim +./test.sh -f tsim/tag/bool_int.sim +./test.sh -f tsim/tag/bool.sim +./test.sh -f tsim/tag/change.sim +./test.sh -f tsim/tag/column.sim +./test.sh -f tsim/tag/commit.sim +./test.sh -f tsim/tag/create.sim +./test.sh -f tsim/tag/delete.sim +./test.sh -f tsim/tag/double.sim +./test.sh -f tsim/tag/filter.sim +./test.sh -f tsim/tag/float.sim +./test.sh -f tsim/tag/int_binary.sim +./test.sh -f tsim/tag/int_float.sim +./test.sh -f tsim/tag/int.sim +./test.sh -f tsim/tag/set.sim +./test.sh -f tsim/tag/smallint.sim +./test.sh -f tsim/tag/tinyint.sim +./test.sh -f tsim/tag/drop_tag.sim +./test.sh -f tsim/tag/tbNameIn.sim +./test.sh -f tmp/monitor.sim diff --git a/tests/script/wtest.bat b/tests/script/wtest.bat index f674277df9455d0abac76bc4f214b9c53a62ce91..b642bad285864fd2fd423d0e28c739bc4680bcd0 100644 --- a/tests/script/wtest.bat +++ b/tests/script/wtest.bat @@ -33,7 +33,7 @@ if exist %LOG_DIR% rmdir /s/q %LOG_DIR% if not exist %CFG_DIR% mkdir %CFG_DIR% if not exist %LOG_DIR% mkdir %LOG_DIR% -rem set "fqdn=" +set "fqdn=localhost" for /f "skip=1" %%A in ( 'wmic computersystem get caption' ) do if not defined fqdn set "fqdn=%%A" diff --git a/tests/system-test/0-others/TS-3131.tsql b/tests/system-test/0-others/TS-3131.tsql new file mode 100644 index 0000000000000000000000000000000000000000..6d4b4c53f4800a416020b9e0c6f829eee5a56909 --- /dev/null +++ b/tests/system-test/0-others/TS-3131.tsql @@ -0,0 +1,71 @@ +drop database if exists d0; +create database d0 replica 1 keep 365 minRows 100 maxRows 4096 comp 2 vgroups 2 precision 'ms'; +use d0; +create table if not exists almlog (starttime timestamp,endtime timestamp,durationtime int, alarmno int, alarmtext nchar(256),isactive nchar(64)) tags (mcid nchar(16)); +create table if not exists mplog (starttime timestamp,mpid int, paravalue nchar(256),mptype nchar(32)) tags (mcid nchar(16)); +create table if not exists mdlog (starttime timestamp,endtime timestamp,durationtime int, statuscode int, npcgmname nchar(256),attr int) tags (mcid nchar(16)); +create table if not exists nrglog (updatetime timestamp,energyvalue double,enerygyincrease double) tags (mcid nchar(16),enerygytype nchar(16)); + +create table almlog_m201 using almlog tags("m201"); +create table almlog_m0103 using almlog tags("m0103"); +create table almlog_m0103_20031 using almlog tags("m0103"); +create table almlog_m0103_20032 using almlog tags("m0103"); +create table almlog_m0103_3003 using almlog tags("m0103"); +create table almlog_m0103_20033 using almlog tags("m0103"); +create table almlog_m0103_30031 using almlog tags("m0103"); +create table almlog_m0201 using almlog tags("m0201"); +create table almlog_m0102 using almlog tags("m0102"); +create table almlog_m0101 using almlog tags("m0101"); +create table almlog_m1002 using almlog tags("m1002"); + +create table mplog_m0204_4 using mplog tags("m0204"); +create table mplog_m0204_5 using mplog tags("m0204"); +create table mplog_m0204_6 using mplog tags("m0204"); +create table mplog_m0204_12 using mplog tags("m0204"); +create table mplog_m0204 using mplog tags("m0204"); +create table mplog_m201 using mplog tags("m201"); +create table mplog_m0102 using mplog tags("m0102"); +create table mplog_m1101 using mplog tags("m1101"); + +create table mdlog_m0102 using mplog tags("m0102"); +create table mdlog_m0504 using mplog tags("m0504"); +create table mdlog_m0505 using mplog tags("m0505"); +create table mdlog_m0507 using mplog tags("m0507"); +create table mdlog_m1002 using mplog tags("m1002"); +create table mdlog_m3201 using mplog tags("m3201"); +create table mdlog_m0201 using mplog tags("m0201"); +create table mdlog_m1102 using mplog tags("m1102"); +create table mdlog_m201 using mplog tags("m201"); + +create table nrglog_m201_electricvalue1 using nrglog tags("m201","electricValue1"); +create table nrglog_m201_oilvalue1 using nrglog tags("m201","oilValue1"); +create table nrglog_m201_gasvalue1 using nrglog tags("m201","gasValue1"); +create table nrglog_m201_watervalue1 using nrglog tags("m201","waterValue1"); +create table nrglog_m0101_oilvalue1 using nrglog tags("m0101","oilValue1"); +create table nrglog_m0101_watervalue1 using nrglog tags("m0101","waterValue1"); +create table nrglog_m0102_gasvalue1 using nrglog tags("m0102","gasValue1"); +create table nrglog_m1903 using nrglog tags("m1903",NULL); +create table nrglog_m2802 using nrglog tags("m2802",NULL); +create table nrglog_m2101 using nrglog tags("m2101",NULL); +create table nrglog_m0102 using nrglog tags("m0102",NULL); +create table nrglog_m0101_electricvalue1 using nrglog tags("m0101","electricValue1"); +create table nrglog_m0101_gasvalue1 using nrglog tags("m0101","gasValue1"); +create table nrglog_m0102_electricvalue1 using nrglog tags("m0102","electricValue1"); +create table nrglog_m0102_oilvalue1 using nrglog tags("m0102","oilValue1"); +create table nrglog_m0102_watervalue1 using nrglog tags("m0102","waterValue1"); + + +insert into almlog_m0103 values(now,now+1s,10,0,'','dismissed'); +insert into almlog_m0103_20031 values(now,now+1s,10,20031,'','dismissed'); +insert into almlog_m0103_20032 values(now,now+1s,10,20032,'','dismissed'); +insert into almlog_m0103_3003 values(now,now+1s,10,3003,'','dismissed'); +insert into almlog_m0103_20033 values(now,now+1s,10,20033,'','dismissed'); +insert into almlog_m0103_30031 values(now,now+1s,10,30031,'','dismissed'); + +flush database d0; + +show table tags from almlog; + +select *,tbname from d0.almlog where mcid='m0103'; + +select table_name from information_schema.ins_tables where db_name='d0'; diff --git a/tests/system-test/0-others/backquote_check.py b/tests/system-test/0-others/backquote_check.py index 33577232538074953457830934fa853ba81aec6a..be8590f913f110e0156d71fa81560fc99fa39132 100644 --- a/tests/system-test/0-others/backquote_check.py +++ b/tests/system-test/0-others/backquote_check.py @@ -29,7 +29,7 @@ class TDTestCase: self.streamname = 'stm' self.streamtb = 'stm_stb' def topic_name_check(self): - tdSql.execute(f'create database if not exists {self.dbname}') + tdSql.execute(f'create database if not exists {self.dbname} wal_retention_period 3600') tdSql.execute(f'use {self.dbname}') tdSql.execute(f'create stable {self.stbname} (ts timestamp,c0 int) tags(t0 int)') for name in [self.dbname,self.stbname]: @@ -56,12 +56,12 @@ class TDTestCase: tdSql.execute(f'drop topic `{name}`') def db_name_check(self): - tdSql.execute(f'create database if not exists `{self.dbname}`') + tdSql.execute(f'create database if not exists `{self.dbname}` wal_retention_period 3600') tdSql.execute(f'use `{self.dbname}`') tdSql.execute(f'drop database {self.dbname}') def stream_name_check(self): - tdSql.execute(f'create database if not exists {self.dbname}') + tdSql.execute(f'create database if not exists {self.dbname} wal_retention_period 3600') tdSql.execute(f'use {self.dbname}') tdSql.execute(f'create stable {self.stbname} (ts timestamp,c0 int) tags(t0 int)') tdSql.execute(f'create stream `{self.streamname}` into `{self.streamtb}` as select count(*) from {self.stbname} interval(10s);') @@ -84,4 +84,4 @@ class TDTestCase: tdLog.success("%s successfully executed" % __file__) tdCases.addWindows(__file__, TDTestCase()) -tdCases.addLinux(__file__, TDTestCase()) \ No newline at end of file +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/0-others/check_assert.py b/tests/system-test/0-others/check_assert.py new file mode 100644 index 0000000000000000000000000000000000000000..ff69b9eeec02caddfe989eacfe3a4a16a5e6d656 --- /dev/null +++ b/tests/system-test/0-others/check_assert.py @@ -0,0 +1,219 @@ +################################################################### +# 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 * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import * + +''' + +import sys +import random +import os + +#define code +NO_FOUND = 0 # not found assert or ASSERT +FOUND_OK = 1 # found ASSERT and valid usage +FOUND_NOIF = 2 # found ASSERT but no if like ASSERT(...) +FOUND_LOWER = 3 # found assert write with system assert +FOUND_HAVENOT = 4 # found ASSERT have if but have not like if(!ASSERT) + +code_strs = ["not found", "valid", "found but no if", "system assert","found but have not"] + + +# +# check assert +# +class CheckAssert: + def __init__(self): + self.files = 0 + self.total = [0,0,0,0,0] + + def wholeMatched(self, line, pos, n): + before = False + after = False + if pos != -1: + if pos == 0 or line[pos-1] == ' ' or line[pos-1] == '!' or line[pos-1] == '(': + before = True + if n > pos + 6 + 1: + last = line[pos+6] + if last == ' ' or last == '(': + after = True + + if before and after: + return True + else: + return False + + + def parseLine(self, line): + + # see FOUND_xxx define below + code = 0 + + n = len(line) + if(n < 7): + return NO_FOUND + s1 = line.find("//") # commit line + + # assert + pos = line.find("assert") + if pos != -1: + if self.wholeMatched(line, pos, n): + # comment line check + if not (s1 != -1 and s1 < pos): + return FOUND_LOWER + + # ASSERT + pos = 0 + while pos < n: + pos = line.find("ASSERT", pos) + #print(f" pos={pos} {line}") + if pos == -1: + return NO_FOUND + if self.wholeMatched(line, pos, n): + break + # next + pos += 6 + + # + # found + # + + # comment line + if s1 != -1 and s1 < pos: + return NO_FOUND + # check if + s2 = line.find("if") + if s2 == -1 or s2 > pos or pos - s2 > 5: + return FOUND_NOIF + s3 = line.find("!") + # if(!ASSERT + if s3 > s2 and s3 < pos: + return FOUND_HAVENOT + + return FOUND_OK + + + def checkFile(self, pathfile): + # check .h .c + ext = pathfile[-2:].lower() + if ext != ".h" and ext != ".c": + return + + print(" check file %s"%pathfile) + self.files += 1 + err = 0 + ok = 0 + i = 0 + + # read file context + with open(pathfile, "r") as fp: + lines = fp.readlines() + for line in lines: + i += 1 + code = self.parseLine(line) + self.total[code] += 1 + if code == FOUND_OK: + ok += 1 + if code != NO_FOUND and code != FOUND_OK: + err += 1 + if code != NO_FOUND: + print(f" line: {i} code: {code} {line}") + + # parse end output total + if err > 0 or ok > 0: + print(f" found problem: {err} \n") + + + def scanPath(self, path): + #print(" check path %s"%path) + + ignores = ["/test/"] + for ignore in ignores: + if ignore in path: + print(f" ignore {path} keyword: {ignore}") + return + + with os.scandir(path) as childs: + for child in childs: + if child.is_file(): + self.checkFile(os.path.join(path, child.name)) + elif child.is_dir(): + self.scanPath(child.path) + + + def doCheck(self, path): + print(f" start check path:{path}") + self.scanPath(path) + + # print total + print("\n") + print(f" --------------- total ({self.files} files)--------------") + for i in range(5): + print(f" code : {i} num: {self.total[i]} ({code_strs[i]})") + print(" --------------- end ----------------") + print(f"\n") + +# +# main function +# + +if __name__ == "__main__": + print(" hello, welcome to use check assert tools 1.0.") + path = os.path.dirname(os.path.realpath(__file__)) + label = "TDengine" + pos = path.find(label) + if pos != -1: + pos += len(label) + 1 + src = path[0:pos] + "source" + else: + src = path + + checker = CheckAssert() + checker.doCheck(src) + print(" check assert finished") + + + +''' +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + self.checker = CheckAssert() + + # run + def run(self): + # calc + selfPath = os.path.dirname(os.path.realpath(__file__)) + projPath = "" + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + src = self.projPath + "src/" + self.checker.checkAssert(src) + + 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/system-test/0-others/compa4096.json b/tests/system-test/0-others/compa4096.json index 5cc5d2084dd52ccc198446698f9a745664aeb054..5e203ded45311e88654af35c498853246b687925 100644 --- a/tests/system-test/0-others/compa4096.json +++ b/tests/system-test/0-others/compa4096.json @@ -53,18 +53,8 @@ "sample_format": "csv", "sample_file": "./sample.csv", "tags_file": "", - "columns": [ - { - "type": "INT", - "count": 4094 - } - ], - "tags": [ - { - "type": "TINYINT", - "count": 1 - } - ] + "columns": [{ "type": "INT","count": 4093}], + "tags": [{"type": "TINYINT", "count": 1},{"type": "NCHAR","count": 1}] } ] } diff --git a/tests/system-test/0-others/compatibility.py b/tests/system-test/0-others/compatibility.py index cd4acae43826ec942a6a46b97a501b888ec951ff..22e319fdaf076190f3fc31390f5ca88d9e5561b1 100644 --- a/tests/system-test/0-others/compatibility.py +++ b/tests/system-test/0-others/compatibility.py @@ -3,6 +3,9 @@ import taos import sys import os import time +import platform +import inspect +from taos.tmq import Consumer from pathlib import Path from util.log import * @@ -12,13 +15,14 @@ from util.dnodes import * from util.dnodes import TDDnodes from util.dnodes import TDDnode from util.cluster import * +import subprocess -BASEVERSION = "3.0.1.8" +BASEVERSION = "3.0.2.3" class TDTestCase: def caseDescription(self): - ''' + f''' 3.0 data compatibility test - case1: basedata version is 3.0.1.8 + case1: basedata version is {BASEVERSION} ''' return @@ -26,8 +30,21 @@ class TDTestCase: self.replicaVar = int(replicaVar) tdLog.debug(f"start to excute {__file__}") tdSql.init(conn.cursor()) + + def checkProcessPid(self,processName): + i=0 + while i<60: + print(f"wait stop {processName}") + processPid = subprocess.getstatusoutput(f'ps aux|grep {processName} |grep -v "grep"|awk \'{{print $2}}\'')[1] + print(f"times:{i},{processName}-pid:{processPid}") + if(processPid == ""): + break + i += 1 + sleep(1) + else: + print(f'this processName is not stoped in 60s') - + def getBuildPath(self): selfPath = os.path.dirname(os.path.realpath(__file__)) @@ -68,6 +85,7 @@ class TDTestCase: my_file = Path(f"{packagePath}/{packageName}") if not my_file.exists(): print(f"{packageName} is not exists") + tdLog.info(f"cd {packagePath} && wget https://www.tdengine.com/assets-download/3.0/{packageName}") os.system(f"cd {packagePath} && wget https://www.tdengine.com/assets-download/3.0/{packageName}") else: print(f"{packageName} has been exists") @@ -80,10 +98,21 @@ class TDTestCase: def buildTaosd(self,bPath): # os.system(f"mv {bPath}/build_bak {bPath}/build ") - os.system(f" cd {bPath} && make install ") - + os.system(f" cd {bPath} ") + def is_list_same_as_ordered_list(self,unordered_list, ordered_list): + sorted_list = sorted(unordered_list) + return sorted_list == ordered_list + def run(self): + scriptsPath = os.path.dirname(os.path.realpath(__file__)) + distro_id = distro.id() + if distro_id == "alpine": + tdLog.info(f"alpine skip compatibility test") + return True + if platform.system().lower() == 'windows': + tdLog.info(f"Windows skip compatibility test") + return True bPath = self.getBuildPath() cPath = self.getCfgPath() dbname = "test" @@ -109,20 +138,25 @@ class TDTestCase: tdLog.printNoPrefix(f"==========step1:prepare and check data in old version-{BASEVERSION}") tdLog.info(f" LD_LIBRARY_PATH=/usr/lib taosBenchmark -t {tableNumbers} -n {recordNumbers1} -y ") os.system(f"LD_LIBRARY_PATH=/usr/lib taosBenchmark -t {tableNumbers} -n {recordNumbers1} -y ") - sleep(3) + os.system(f"LD_LIBRARY_PATH=/usr/lib taos -s 'use test;create stream current_stream into current_stream_output_stb as select _wstart as `start`, _wend as wend, max(current) as max_current from meters where voltage <= 220 interval (5s);' ") + os.system('LD_LIBRARY_PATH=/usr/lib taos -s "use test;create stream power_stream into power_stream_output_stb as select ts, concat_ws(\\".\\", location, tbname) as meter_location, current*voltage*cos(phase) as active_power, current*voltage*sin(phase) as reactive_power from meters partition by tbname;" ') + os.system('LD_LIBRARY_PATH=/usr/lib taos -s "use test;show streams;" ') + os.system(f"sed -i 's/\/etc\/taos/{cPath}/' 0-others/tmqBasic.json ") + # os.system("LD_LIBRARY_PATH=/usr/lib taosBenchmark -f 0-others/tmqBasic.json -y ") + os.system('LD_LIBRARY_PATH=/usr/lib taos -s "create topic if not exists tmq_test_topic as select current,voltage,phase from test.meters where voltage <= 106 and current <= 5;" ') + os.system('LD_LIBRARY_PATH=/usr/lib taos -s "use test;show topics;" ') - # tdsqlF.query(f"select count(*) from {stb}") - # tdsqlF.checkData(0,0,tableNumbers*recordNumbers1) - os.system("pkill taosd") - sleep(2) - - print(f"start taosd: nohup taosd -c {cPath} & ") - os.system(f" nohup taosd -c {cPath} & " ) - sleep(10) tdLog.info(" LD_LIBRARY_PATH=/usr/lib taosBenchmark -f 0-others/compa4096.json -y ") os.system("LD_LIBRARY_PATH=/usr/lib taosBenchmark -f 0-others/compa4096.json -y") - os.system("pkill -9 taosd") + os.system("LD_LIBRARY_PATH=/usr/lib taos -s 'flush database db4096 '") + os.system("LD_LIBRARY_PATH=/usr/lib taos -f 0-others/TS-3131.tsql") + cmd = f" LD_LIBRARY_PATH={bPath}/build/lib {bPath}/build/bin/taos -h localhost ;" + if os.system(cmd) == 0: + raise Exception("failed to execute system command. cmd: %s" % cmd) + + os.system("pkill taosd") # make sure all the data are saved in disk. + self.checkProcessPid("taosd") tdLog.printNoPrefix("==========step2:update new version ") @@ -131,8 +165,10 @@ class TDTestCase: sleep(1) tdsql=tdCom.newTdSql() print(tdsql) - - + cmd = f" LD_LIBRARY_PATH=/usr/lib taos -h localhost ;" + if os.system(cmd) == 0: + raise Exception("failed to execute system command. cmd: %s" % cmd) + tdsql.query(f"SELECT SERVER_VERSION();") nowServerVersion=tdsql.queryResult[0][0] tdLog.info(f"New server version is {nowServerVersion}") @@ -142,10 +178,12 @@ class TDTestCase: tdLog.printNoPrefix(f"==========step3:prepare and check data in new version-{nowServerVersion}") tdsql.query(f"select count(*) from {stb}") - tdsql.checkData(0,0,tableNumbers*recordNumbers1) - os.system(f"taosBenchmark -t {tableNumbers} -n {recordNumbers2} -y ") - tdsql.query(f"select count(*) from {stb}") - tdsql.checkData(0,0,tableNumbers*recordNumbers2) + tdsql.checkData(0,0,tableNumbers*recordNumbers1) + # tdsql.query("show streams;") + # os.system(f"taosBenchmark -t {tableNumbers} -n {recordNumbers2} -y ") + # tdsql.query("show streams;") + # tdsql.query(f"select count(*) from {stb}") + # tdsql.checkData(0,0,tableNumbers*recordNumbers2) tdsql.query(f"select count(*) from db4096.stb0") tdsql.checkData(0,0,50000) @@ -154,6 +192,7 @@ class TDTestCase: tdsql.execute("drop database if exists db") tdsql.execute("create database db") tdsql.execute("use db") + tdsql.execute("alter database db wal_retention_period 3600") tdsql.execute("create stable db.stb1 (ts timestamp, c1 int) tags (t1 int);") tdsql.execute("insert into db.ct1 using db.stb1 TAGS(1) values(now(),11);") tdsql.error(" insert into `db.ct2` using db.stb1 TAGS(9) values(now(),11);") @@ -164,13 +203,69 @@ class TDTestCase: tdsql.execute("insert into db.`ct4` using db.stb1 TAGS(4) values(now(),14);") tdsql.query("select * from db.ct4") tdsql.checkData(0,1,14) + print(1) + tdsql=tdCom.newTdSql() tdsql.query("describe information_schema.ins_databases;") qRows=tdsql.queryRows - for i in range(qRows) : - if tdsql.queryResult[i][0]=="retentions" : - return True - else: - return False + comFlag=True + j=0 + while comFlag: + for i in range(qRows) : + if tdsql.queryResult[i][0] == "retentions" : + print("parameters include retentions") + comFlag=False + break + else : + comFlag=True + j=j+1 + if j == qRows: + print("parameters don't include retentions") + caller = inspect.getframeinfo(inspect.stack()[0][0]) + args = (caller.filename, caller.lineno) + tdLog.exit("%s(%d) failed" % args) + tdsql.query("show streams;") + tdsql.checkRows(2) + tdsql.query("select *,tbname from d0.almlog where mcid='m0103';") + tdsql.checkRows(6) + expectList = [0,3003,20031,20032,20033,30031] + resultList = [] + for i in range(6): + resultList.append(tdsql.queryResult[i][3]) + print(resultList) + if self.is_list_same_as_ordered_list(resultList,expectList): + print("The unordered list is the same as the ordered list.") + else: + tdlog.error("The unordered list is not the same as the ordered list.") + tdsql.execute("insert into test.d80 values (now+1s, 11, 103, 0.21);") + tdsql.execute("insert into test.d9 values (now+5s, 4.3, 104, 0.4);") + + conn = taos.connect() + + consumer = Consumer( + { + "group.id": "tg75", + "client.id": "124", + "td.connect.user": "root", + "td.connect.pass": "taosdata", + "enable.auto.commit": "true", + "experimental.snapshot.enable": "true", + } + ) + consumer.subscribe(["tmq_test_topic"]) + + while True: + res = consumer.poll(10) + if not res: + break + err = res.error() + if err is not None: + raise err + val = res.value() + + for block in val: + print(block.fetchall()) + tdsql.query("show topics;") + tdsql.checkRows(1) def stop(self): tdSql.close() tdLog.success(f"{__file__} successfully executed") diff --git a/tests/system-test/0-others/information_schema.py b/tests/system-test/0-others/information_schema.py index 1b82fa6e642bec0d3c24467be8a586a5bf8a7f6c..3c4a71c3e4e47baf7c6503f77ea9b588eaebec83 100644 --- a/tests/system-test/0-others/information_schema.py +++ b/tests/system-test/0-others/information_schema.py @@ -56,7 +56,7 @@ class TDTestCase: self.binary_str = 'taosdata' self.nchar_str = '涛思数据' self.ins_list = ['ins_dnodes','ins_mnodes','ins_modules','ins_qnodes','ins_snodes','ins_cluster','ins_databases','ins_functions',\ - 'ins_indexes','ins_stables','ins_tables','ins_tags','ins_users','ins_grants','ins_vgroups','ins_configs','ins_dnode_variables',\ + 'ins_indexes','ins_stables','ins_tables','ins_tags','ins_columns','ins_users','ins_grants','ins_vgroups','ins_configs','ins_dnode_variables',\ 'ins_topics','ins_subscriptions','ins_streams','ins_stream_tasks','ins_vnodes','ins_user_privileges'] self.perf_list = ['perf_connections','perf_queries','perf_consumers','perf_trans','perf_apps'] def insert_data(self,column_dict,tbname,row_num): @@ -93,7 +93,6 @@ class TDTestCase: tdSql.checkEqual(i[2],len(self.perf_list)) tdSql.execute('create table db1.ntb (ts timestamp,c0 int)') tdSql.query(f'select db_name, count(*) from information_schema.ins_tables group by db_name') - print(tdSql.queryResult) for i in tdSql.queryResult: if i[0].lower() == 'information_schema': tdSql.checkEqual(i[1],len(self.ins_list)) @@ -101,9 +100,77 @@ class TDTestCase: tdSql.checkEqual(i[1],len(self.perf_list)) elif i[0].lower() == self.dbname: tdSql.checkEqual(i[1],self.tbnum+1) + + + + def ins_col_check_4096(self): + tdSql.execute('create database db3 vgroups 2 replica 1') + col_str = tdCom.gen_tag_col_str("col", "int",4094) + tdSql.execute(f'create stable if not exists db3.stb (col_ts timestamp, {col_str}) tags (t1 int)') + for i in range(100): + tdLog.info(f"create table db3.ctb{i} using db3.stb tags({i})") + tdSql.execute(f"create table db3.ctb{i} using db3.stb tags({i})") + col_value_str = '1, ' * 4093 + '1' + tdSql.execute(f"insert into db3.ctb{i} values(now,{col_value_str})(now+1s,{col_value_str})(now+2s,{col_value_str})(now+3s,{col_value_str})") + tdSql.query("select * from information_schema.ins_columns") + + tdSql.execute('drop database db3') + def ins_stable_check(self): + tdSql.execute('create database db3 vgroups 2 replica 1') + tbnum = 10 + ctbnum = 10 + for i in range(tbnum): + tdSql.execute(f'create stable db3.stb_{i} (ts timestamp,c0 int) tags(t0 int)') + tdSql.execute(f'create table db3.ntb_{i} (ts timestamp,c0 int)') + for j in range(ctbnum): + tdSql.execute(f"create table db3.ctb_{i}_{j} using db3.stb_{i} tags({j})") + tdSql.query("select stable_name,count(table_name) from information_schema.ins_tables where db_name = 'db3' group by stable_name order by stable_name") + result = tdSql.queryResult + for i in range(len(result)): + if result[i][0] == None: + tdSql.checkEqual(result[0][1],tbnum) + else: + tdSql.checkEqual(result[i][0],f'stb_{i-1}') + tdSql.checkEqual(result[i][1],ctbnum) + + + + def ins_columns_check(self): + tdSql.execute('drop database if exists db2') + tdSql.execute('create database if not exists db2 vgroups 1 replica 1') + for i in range (5): + self.stb4096 = 'create table db2.stb%d (ts timestamp' % (i) + for j in range (4094 - i): + self.stb4096 += ', c%d int' % (j) + self.stb4096 += ') tags (t1 int)' + tdSql.execute(self.stb4096) + for k in range(10): + tdSql.execute("create table db2.ctb_%d_%dc using db2.stb%d tags(%d)" %(i,k,i,k)) + for t in range (2): + tdSql.query(f'select * from information_schema.ins_columns where db_name="db2" and table_type=="SUPER_TABLE"') + tdSql.checkEqual(20465,len(tdSql.queryResult)) + for t in range (2): + tdSql.query(f'select * from information_schema.ins_columns where db_name="db2" and table_type=="CHILD_TABLE"') + tdSql.checkEqual(204650,len(tdSql.queryResult)) + + for i in range (5): + self.ntb4096 = 'create table db2.ntb%d (ts timestamp' % (i) + for j in range (4095 - i): + self.ntb4096 += ', c%d binary(10)' % (j) + self.ntb4096 += ')' + tdSql.execute(self.ntb4096) + for t in range (2): + tdSql.query(f'select * from information_schema.ins_columns where db_name="db2" and table_type=="NORMAL_TABLE"') + tdSql.checkEqual(20470,len(tdSql.queryResult)) + + def run(self): self.prepare_data() self.count_check() + self.ins_columns_check() + # self.ins_col_check_4096() + self.ins_stable_check() + def stop(self): tdSql.close() diff --git a/tests/system-test/0-others/multilevel.py b/tests/system-test/0-others/multilevel.py new file mode 100644 index 0000000000000000000000000000000000000000..7ad4eba6453877149e2be6a01f76d6cf50b906bc --- /dev/null +++ b/tests/system-test/0-others/multilevel.py @@ -0,0 +1,263 @@ +################################################################### +# 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 * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import * + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + self.setsql = TDSetSql() + + def basic(self): + tdLog.info("============== basic test ===============") + cfg={ + '/mnt/data1' : 'dataDir', + '/mnt/data2 0 0' : 'dataDir' + } + tdSql.createDir('/mnt/data1') + tdSql.createDir('/mnt/data2') + + tdLog.info("================= step1") + tdDnodes.stop(1) + tdDnodes.deploy(1,cfg) + tdDnodes.start(1) + + tdLog.info("================= step2") + tdSql.haveFile('/mnt/data1/',1) + tdSql.haveFile('/mnt/data2/',0) + tdDnodes.stop(1) + def dir_not_exist(self): + tdLog.info("============== dir_not_exist test ===============") + cfg={ + '/mnt/data1 0 0' : 'dataDir', + '/mnt/data2 0 0' : 'dataDir' + } + tdSql.createDir('/mnt/data1') + os.system('rm -rf /mnt/data2') + + + tdLog.info("================= step1") + tdDnodes.deploy(1,cfg) + tdDnodes.startWithoutSleep(1) + + tdLog.info("================= step2") + tdSql.taosdStatus(0) + + def dir_permission_denied(self): + tdDnodes.stop(1) + tdLog.info("============== dir_permission_denied test ===============") + cfg={ + '/mnt/data1 0 0' : 'dataDir', + '/mnt/data2 0 0' : 'dataDir' + } + tdSql.createDir('/mnt/data1') + tdSql.createDir('/mnt/data2') + os.system('chmod 111 /mnt/data2') + + tdLog.info("================= step1") + tdDnodes.deploy(1,cfg) + tdDnodes.startWithoutSleep(1) + + tdLog.info("================= step2") + tdSql.taosdStatus(0) + + def file_distribution_same_level(self): + tdLog.info("============== file_distribution_same_level test ===============") + dataDir = ['data00','data01','data02','data03','data04'] + dataDict = {'data00':0,'data01':0,'data02':0,'data03':0,'data04':0} + tdDnodes.stop(1) + self.ntables = 1000 + self.ts = 1520000010000 + tdLog.info("================= step1") + cfg={ + '/mnt/data00 0 1' : 'dataDir', + '/mnt/data01 0 0' : 'dataDir', + '/mnt/data02 0 0' : 'dataDir', + '/mnt/data03 0 0' : 'dataDir', + '/mnt/data04 0 0' : 'dataDir' + } + dir_list = ['/mnt/data00','/mnt/data01','/mnt/data02','/mnt/data03','/mnt/data04'] + for i in dir_list: + tdSql.createDir(i) + tdDnodes.deploy(1,cfg) + tdDnodes.start(1) + + tdSql.execute("create database test duration 1") + tdSql.execute("use test") + + tdSql.execute("create table stb(ts timestamp, c int) tags(t int)") + + for i in range(self.ntables): + tdSql.execute("create table tb%d using stb tags(%d)" %(i, i)) + tdSql.execute("insert into tb%d values(%d, 1)" % (i,self.ts + int (i / 100) * 86400000)) + + tdLog.info("================= step2") + tdDnodes.stop(1) + tdDnodes.start(1) + tdSql.query("select * from test.stb") + tdSql.checkRows(1000) + tdLog.info("================= step3") + tdSql.execute('drop database test') + for i in range(50): + tdSql.execute("create database test%d duration 1" %(i)) + tdSql.execute("use test%d" %(i)) + tdSql.execute("create table tb (ts timestamp,i int)") + for j in range(10): + tdSql.execute("insert into tb values(%d, 1)" % (self.ts + int (i / 100) * 86400000)) + tdDnodes.stop(1) + tdDnodes.start(1) + flag = True + for i in range(4): + if dataDict[dataDir[i]] == dataDict[dataDir[i+1]]: + flag = flag & True + else: + flag = flag & False + break + if not flag : tdLog.exit("%s failed, expect not occured" % (sys.argv[0])) + + def three_level_basic(self): + tdLog.info("============== three_level_basic test ===============") + tdDnodes.stop(1) + # Test1 1 dataDir + cfg={ + '/mnt/data000 0 1' : 'dataDir', + '/mnt/data001 0 0' : 'dataDir', + '/mnt/data002 0 0' : 'dataDir', + '/mnt/data010 1 0' : 'dataDir', + '/mnt/data011 1 0' : 'dataDir', + '/mnt/data012 1 0' : 'dataDir', + '/mnt/data020 2 0' : 'dataDir', + '/mnt/data021 2 0' : 'dataDir', + '/mnt/data022 2 0' : 'dataDir' + } + dir_list = ['/mnt/data000','/mnt/data001','/mnt/data002','/mnt/data010','/mnt/data011','/mnt/data012','/mnt/data020','/mnt/data021''/mnt/data022'] + for i in dir_list: + tdSql.createDir(i) + + tdDnodes.deploy(1,cfg) + tdDnodes.start(1) + for i in dir_list: + if i == '/mnt/data000': + tdSql.haveFile(i,1) + else: + tdSql.haveFile(i,0) + + def more_than_16_disks(self): + tdLog.info("============== more_than_16_disks test ===============") + cfg={} + for i in range(17): + if i == 0 : + datadir = '/mnt/data%d 0 1' % (i+1) + else: + datadir = '/mnt/data%d 0 0' % (i+1) + cfg.update({ datadir : 'dataDir' }) + tdSql.createDir('/mnt/data%d' % (i+1)) + + tdLog.info("================= step1") + tdDnodes.stop(1) + tdDnodes.deploy(1,cfg) + tdDnodes.startWithoutSleep(1) + + tdLog.info("================= step2") + tdSql.taosdStatus(0) + + def missing_middle_level(self): + tdLog.info("============== missing_middle_level test ===============") + tdDnodes.stop(1) + # Test1 1 dataDir + cfg={ + '/mnt/data1 1 0' : 'dataDir' + } + tdSql.createDir('/mnt/data1') + + tdDnodes.deploy(1,cfg) + tdDnodes.startWithoutSleep(1) + + tdSql.taosdStatus(0) + tdDnodes.stop(1) + # Test2 2 dataDir + cfg = { + '/mnt/data1 0 1' : 'dataDir', + '/mnt/data1 2 0' : 'dataDir' + } + tdSql.createDir('/mnt/data1') + + tdDnodes.deploy(1,cfg) + tdDnodes.startWithoutSleep(1) + + tdSql.taosdStatus(0) + + def trim_database(self): + tdLog.info("============== trim_database test ===============") + tdDnodes.stop(1) + cfg = { + '/mnt/data1 0 1' : 'dataDir' + + } + tdSql.createDir('/mnt/data1') + tdDnodes.deploy(1,cfg) + tdDnodes.start(1) + + tdSql.execute('create database dbtest') + tdSql.execute('use dbtest') + tdSql.execute('create table stb (ts timestamp,c0 int) tags(t0 int)') + tdSql.execute('create table tb1 using stb tags(1)') + for i in range(10,30): + tdSql.execute(f'insert into tb1 values(now-{i}d,10)') + tdSql.execute('flush database dbtest') + tdSql.haveFile('/mnt/data1/',1) + tdDnodes.stop(1) + cfg={ + '/mnt/data1 0 1' : 'dataDir', + '/mnt/data2 1 0' : 'dataDir', + '/mnt/data3 2 0' : 'dataDir', + } + tdSql.createDir('/mnt/data2') + tdSql.createDir('/mnt/data3') + tdDnodes.deploy(1,cfg) + tdDnodes.start(1) + tdSql.haveFile('/mnt/data1/',1) + tdSql.haveFile('/mnt/data2/',0) + tdSql.haveFile('/mnt/data3/',0) + tdSql.execute('alter database dbtest keep 10d,365d,3650d') + tdSql.execute('trim database dbtest') + time.sleep(3) + tdSql.haveFile('/mnt/data1/',1) + tdSql.haveFile('/mnt/data2/',1) + + def run(self): + self.basic() + self.dir_not_exist() + self.dir_permission_denied() + self.file_distribution_same_level() + self.three_level_basic() + self.more_than_16_disks() + self.trim_database() + self.missing_middle_level() + + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/0-others/performance_schema.py b/tests/system-test/0-others/performance_schema.py new file mode 100755 index 0000000000000000000000000000000000000000..9d2a362254714a2daefc98787a3c1ec236c3e80c --- /dev/null +++ b/tests/system-test/0-others/performance_schema.py @@ -0,0 +1,214 @@ +################################################################### +# 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 * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import * +import threading +from taos.tmq import Consumer + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + self.conn=conn + self.setsql = TDSetSql() + self.dbname = 'db' + self.stbname = 'stb' + self.binary_length = 20 # the length of binary for column_dict + self.nchar_length = 20 # the length of nchar for column_dict + self.ts = 1537146000000 + self.user = "root" + self.groupName = "tg2" + self.topicName = "tmq_test_topic" + self.appName = "python3.10" #todo need to set to fixed name + self.ipAdd= "127.0.0.1"; + self.transTestDBName = "dbwithvgroup" + self.lastTranAction = "action:40 code:0x111(Action in progress) msgType:create-vnode numOfEps:1 inUse:0 ep:0-localhost:6030 " + self.column_dict = { + 'ts' : 'timestamp', #8 + 'col1': 'tinyint', #1 + 'col2': 'smallint', #2 + 'col3': 'int', #4 + 'col4': 'bigint', #8 + 'col5': 'tinyint unsigned', #1 + 'col6': 'smallint unsigned', #2 + 'col7': 'int unsigned', #4 + 'col8': 'bigint unsigned', #8 + 'col9': 'float', #4 + 'col10': 'double', #8 + 'col11': 'bool', #1 + 'col12': f'binary({self.binary_length})', #20 + 2 + 'col13': f'nchar({self.nchar_length})' #20 + 2 + } #95 + self.tbnum = 20 + self.rowNum = 10 + self.tag_dict = { + 't0':'int' #4 + } + self.tag_values = [ + f'1' + ] + self.binary_str = 'taosdata' + self.nchar_str = '涛思数据' + + def insert_data(self,column_dict,tbname,row_num): + insert_sql = self.setsql.set_insertsql(column_dict,tbname,self.binary_str,self.nchar_str) + for i in range(row_num): + insert_list = [] + self.setsql.insert_values(column_dict,i,insert_sql,insert_list,self.ts) + + def prepare_data(self): + tdSql.execute(f"create database if not exists {self.dbname} vgroups 2") #1 query + tdSql.execute(f'use {self.dbname}') #1 query + tdsql.execute(f"alter database {self.dbname} wal_retention_period 3600") + tdSql.execute(self.setsql.set_create_stable_sql(self.stbname,self.column_dict,self.tag_dict)) #1 query + + for i in range(self.tbnum): #self.tbnum query + tdSql.execute(f"create table {self.stbname}_{i} using {self.stbname} tags({self.tag_values[0]})") #self.tbnum query + self.insert_data(self.column_dict,f'{self.stbname}_{i}',self.rowNum) #self.stbname*self.rowNum query + + for i in range(self.tbnum): + tdSql.execute(f"select * from {self.stbname}_{i}") #self.tbnum query + + class myThread (threading.Thread): + def __init__(self, obj): + threading.Thread.__init__(self) + self.obj = obj + def run(self): + tdSqlTran = TDSql() + tdSqlTran.init(self.obj.conn.cursor()) + tdSqlTran.execute(f"create database if not exists %s vgroups 20 wal_retention_period 3600"%(self.obj.transTestDBName)) + tdSqlTran.execute(f"DROP DATABASE %s"%(self.obj.transTestDBName)) + + def init_tmq_env(self, db, topic): + self.conn.execute("drop topic if exists {}".format(topic)) + self.conn.execute("create database if not exists {} wal_retention_period 3600".format(db)) + self.conn.select_db(db) + self.conn.execute( + "create stable if not exists stb_sub (ts timestamp, c1 int, c2 float, c3 varchar(16)) tags(t1 int, t3 varchar(16))") + self.conn.execute("create topic if not exists {} as select ts, c1, c2, c3 from stb_sub".format(topic)) + + def count_check(self): + sleep(1) #performance table delay + tdSql.query('select * from performance_schema.perf_apps') #1 query + rowIndex = 0 #for debug + tdSql.checkRows(1) + tdSql.checkNotEqual(tdSql.queryResult[rowIndex][0], 0) #column 0:app_id + tdSql.checkEqual(tdSql.queryResult[rowIndex][1],self.ipAdd) #column 1:ip + tdSql.checkNotEqual(tdSql.queryResult[rowIndex][2], 0) #column 2:pid # show child process pid of this running python program, this is maybe related to test framework + P = psutil.Process() + tdLog.info(P) + chi = P.children() + tdLog.info(chi) # child process pid is not able to get, chi is empty here + tdSql.checkEqual(tdSql.queryResult[rowIndex][3],self.appName) #column 3:name + tdSql.checkNotEqual(tdSql.queryResult[rowIndex][4], 0) #column 4:start_time + tdSql.checkEqual(tdSql.queryResult[rowIndex][5], 0) #column 5:insert_req # zero ??? + tdSql.checkEqual(tdSql.queryResult[rowIndex][6],self.tbnum * self.rowNum) #column 6:insert_row + tdSql.checkEqual(tdSql.queryResult[rowIndex][7], 0) #column 7:insert_time #zeor??? + tdSql.checkEqual(tdSql.queryResult[rowIndex][8],self.tbnum * self.rowNum * 134) #column 8:insert_bytes # 134 bytes ??? + tdSql.checkEqual(tdSql.queryResult[rowIndex][9], 0) #column 9:fetch_bytes # zero ??? + tdSql.checkNotEqual(tdSql.queryResult[rowIndex][10], 0) #column 10:query_time + tdSql.checkEqual(tdSql.queryResult[rowIndex][11],0) #column 11:slow_query + tdSql.checkEqual(tdSql.queryResult[rowIndex][12],self.tbnum * self.rowNum + self.tbnum * 2 + 4) #column 11:total_req + tdSql.checkEqual(tdSql.queryResult[rowIndex][13], 1) #column 13:current_req + tdSql.checkNotEqual(tdSql.queryResult[rowIndex][14], 0) #column 14:last_access + + + tdSql.query('select * from performance_schema.perf_connections') + tdSql.checkRows(2) + for i in range(2): + if tdSql.queryResult[i][2]== self.appName : + tdSql.checkNotEqual(tdSql.queryResult[i][0],0) #column 0:conn_id + tdSql.checkEqual(tdSql.queryResult[i][1],self.user) #column 1:user + tdSql.checkEqual(tdSql.queryResult[i][2],self.appName) #column 2:app + tdSql.checkNotEqual(tdSql.queryResult[i][3],0) #column 3:pid + tdSql.checkNotEqual(tdSql.queryResult[i][4],0) #column 4:end_point + tdSql.checkNotEqual(tdSql.queryResult[i][5],0) #column 5:login_time + tdSql.checkNotEqual(tdSql.queryResult[i][6],0) #column 6:last_access + self.connId = tdSql.queryResult[i][0] + + self.init_tmq_env(self.dbname, self.topicName) + + consumer = Consumer( + { + "group.id": self.groupName, + "td.connect.user": self.user, + "td.connect.pass": "taosdata", + "td.connect.ip": self.ipAdd, + } + ) + consumer.subscribe([self.topicName]) + + tdSql.query('select * from performance_schema.perf_consumers') + tdSql.checkRows(1) + tdSql.checkNotEqual(tdSql.queryResult[0][0],0) #consumer_id + tdSql.checkEqual(tdSql.queryResult[0][1],self.groupName) #consumer_group + tdSql.checkNotEqual(tdSql.queryResult[0][2],0) #client_id + tdSql.checkEqual(tdSql.queryResult[0][3],"ready") #status + tdSql.checkEqual(tdSql.queryResult[0][4],self.topicName) #topics + tdSql.checkNotEqual(tdSql.queryResult[0][5],0) #up_time + tdSql.checkNotEqual(tdSql.queryResult[0][6],0) #subscribe_time + tdSql.checkNotEqual(tdSql.queryResult[0][7],0) #rebalance_time + + sleep(3) #performance_schema delay, wait for last query + + tdSql.query('select * from performance_schema.perf_queries') + tdSql.checkEqual(tdSql.queryResult[0][12],"select * from performance_schema.perf_consumers") #sql + tdSql.checkNotEqual(tdSql.queryResult[0][0],0) #kill_id + tdSql.checkNotEqual(tdSql.queryResult[0][1],0) #query_id + tdSql.checkEqual(tdSql.queryResult[0][2],self.connId) #conn_id + tdSql.checkEqual(tdSql.queryResult[0][3],self.appName) #app + tdSql.checkNotEqual(tdSql.queryResult[0][4],0) #pid + tdSql.checkEqual(tdSql.queryResult[0][5],self.user) #user + tdSql.checkNotEqual(tdSql.queryResult[0][6],0) #end_point + tdSql.checkNotEqual(tdSql.queryResult[0][7],0) #create_time + tdSql.checkNotEqual(tdSql.queryResult[0][8],0) #exec_usec + tdSql.checkEqual(tdSql.queryResult[0][9],0) #stable_query + tdSql.checkEqual(tdSql.queryResult[0][10],1) #sub_num + tdSql.checkEqual(tdSql.queryResult[0][11],"243:SUCCEED") #sub_status + + t1 = self.myThread(self) + t1.start() + + sleep(0.5) # there is delay + tdSql.query('select * from performance_schema.perf_trans') + tdSql.checkNotEqual(tdSql.queryResult[0][0],0) #id + tdSql.checkNotEqual(tdSql.queryResult[0][1],0) #create_time + tdSql.checkEqual(tdSql.queryResult[0][2],"redoAction") #stage + tdSql.checkEqual(tdSql.queryResult[0][3],"create-db") #oper + tdSql.checkEqual(tdSql.queryResult[0][4],self.transTestDBName) #db + tdSql.checkNotEqual(tdSql.queryResult[0][5],0) #stable + tdSql.checkEqual(tdSql.queryResult[0][6],0) #failed_times + tdSql.checkNotEqual(tdSql.queryResult[0][7],0) #last_exec_time + tdSql.checkEqual(tdSql.queryResult[0][8],self.lastTranAction) #last_action_info + + t1.join() + + tdSql.query('select * from performance_schema.perf_apps') + tdSql.checkNotEqual(tdSql.queryResult[rowIndex][11],0) #column 11:slow_query at least one slow query: create db. + + def run(self): + self.prepare_data() + self.count_check() + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/0-others/show.py b/tests/system-test/0-others/show.py index b5d6a0d1a34e570c2ffe0f61d67538f2ec881dfd..b284605a0e8dc619c5ab004d4a65d022b0eb8946 100644 --- a/tests/system-test/0-others/show.py +++ b/tests/system-test/0-others/show.py @@ -11,14 +11,13 @@ # -*- coding: utf-8 -*- - +import re from util.log import * from util.cases import * from util.sql import * from util.common import * from util.sqlset import * - class TDTestCase: def init(self, conn, logSql, replicaVar=1): self.replicaVar = int(replicaVar) @@ -28,10 +27,35 @@ class TDTestCase: self.ins_param_list = ['dnodes','mnodes','qnodes','cluster','functions','users','grants','topics','subscriptions','streams'] self.perf_param = ['apps','connections','consumers','queries','transactions'] self.perf_param_list = ['apps','connections','consumers','queries','trans'] - + self.dbname = "db" + self.vgroups = 4 + self.stbname = f'`{tdCom.getLongName(5)}`' + self.tbname = f'`{tdCom.getLongName(3)}`' + self.db_param = { + "database":f"{self.dbname}", + "buffer":100, + "cachemodel":"'none'", + "cachesize":1, + "comp":2, + "maxrows":1000, + "minrows":200, + "pages":512, + "pagesize":16, + "precision":"'ms'", + "replica":1, + "wal_level":1, + "wal_fsync_period":6000, + "wal_roll_period":0, + "wal_segment_size":1024, + "vgroups":self.vgroups, + "stt_trigger":1, + "tsdb_pagesize":16 + } def ins_check(self): tdSql.prepare() for param in self.ins_param_list: + if param.lower() == 'qnodes': + tdSql.execute('create qnode on dnode 1') tdSql.query(f'show {param}') show_result = tdSql.queryResult tdSql.query(f'select * from information_schema.ins_{param}') @@ -59,11 +83,32 @@ class TDTestCase: tag_sql += f"{k} {v}, " create_stb_sql = f'create stable {stbname} ({column_sql[:-2]}) tags ({tag_sql[:-2]})' return create_stb_sql - def show_sql(self): - tdSql.prepare() - tdSql.execute('use db') - stbname = f'`{tdCom.getLongName(5)}`' - tbname = f'`{tdCom.getLongName(3)}`' + + def set_create_database_sql(self,sql_dict): + create_sql = 'create' + for key,value in sql_dict.items(): + create_sql += f' {key} {value}' + return create_sql + def show_create_sql(self): + create_db_sql = self.set_create_database_sql(self.db_param) + print(create_db_sql) + tdSql.execute(create_db_sql) + tdSql.query(f'show create database {self.dbname}') + tdSql.checkEqual(self.dbname,tdSql.queryResult[0][0]) + for key,value in self.db_param.items(): + if key == 'database': + continue + else: + param = f'{key} {value}' + if param in tdSql.queryResult[0][1].lower(): + tdLog.info(f'show create database check success with {key} {value}') + continue + else: + tdLog.exit(f"show create database check failed with {key} {value}") + tdSql.query('show vnodes 1') + tdSql.checkRows(self.vgroups) + tdSql.execute(f'use {self.dbname}') + column_dict = { '`ts`': 'timestamp', '`col1`': 'tinyint', @@ -98,25 +143,56 @@ class TDTestCase: '`t14`': 'timestamp' } - create_table_sql = self.set_stb_sql(stbname,column_dict,tag_dict) + create_table_sql = self.set_stb_sql(self.stbname,column_dict,tag_dict) tdSql.execute(create_table_sql) - tdSql.query(f'show create table {stbname}') + tdSql.query(f'show create stable {self.stbname}') query_result = tdSql.queryResult tdSql.checkEqual(query_result[0][1].lower(),create_table_sql) - tdSql.execute(f'create table {tbname} using {stbname} tags(1,1,1,1,1,1,1,1,1.000000e+00,1.000000e+00,true,"abc","abc123",0)') + tdSql.execute(f'create table {self.tbname} using {self.stbname} tags(1,1,1,1,1,1,1,1,1.000000e+00,1.000000e+00,true,"abc","abc123",0)') tag_sql = '(' for tag_keys in tag_dict.keys(): tag_sql += f'{tag_keys}, ' tags = f'{tag_sql[:-2]})' - sql = f'create table {tbname} using {stbname} {tags} tags (1, 1, 1, 1, 1, 1, 1, 1, 1.000000e+00, 1.000000e+00, true, "abc", "abc123", 0)' - tdSql.query(f'show create table {tbname}') + sql = f'create table {self.tbname} using {self.stbname} {tags} tags (1, 1, 1, 1, 1, 1, 1, 1, 1.000000e+00, 1.000000e+00, true, "abc", "abc123", 0)' + tdSql.query(f'show create table {self.tbname}') query_result = tdSql.queryResult tdSql.checkEqual(query_result[0][1].lower(),sql) - tdSql.execute('drop database db') + tdSql.execute(f'drop database {self.dbname}') + def check_gitinfo(self): + taosd_gitinfo_sql = '' + tdSql.query('show dnode 1 variables') + for i in tdSql.queryResult: + if i[1].lower() == "gitinfo": + taosd_gitinfo_sql = f"gitinfo: {i[2]}" + taos_gitinfo_sql = '' + tdSql.query('show local variables') + for i in tdSql.queryResult: + if i[0].lower() == "gitinfo": + taos_gitinfo_sql = f"gitinfo: {i[1]}" + taos_info = os.popen('taos -V').read() + taos_gitinfo = re.findall("^gitinfo.*",taos_info,re.M) + tdSql.checkEqual(taos_gitinfo_sql,taos_gitinfo[0]) + taosd_info = os.popen('taosd -V').read() + taosd_gitinfo = re.findall("^gitinfo.*",taosd_info,re.M) + tdSql.checkEqual(taosd_gitinfo_sql,taosd_gitinfo[0]) + + def show_base(self): + for sql in ['dnodes','mnodes','cluster']: + tdSql.query(f'show {sql}') + print(tdSql.queryResult) + tdSql.checkRows(1) + tdSql.query('show grants') + grants_info = tdSql.queryResult + tdSql.query('show licences') + licences_info = tdSql.queryResult + tdSql.checkEqual(grants_info,licences_info) + def run(self): + self.check_gitinfo() + self.show_base() self.ins_check() self.perf_check() - self.show_sql() + self.show_create_sql() def stop(self): tdSql.close() @@ -124,4 +200,3 @@ class TDTestCase: tdCases.addWindows(__file__, TDTestCase()) tdCases.addLinux(__file__, TDTestCase()) - diff --git a/tests/system-test/0-others/sysinfo.py b/tests/system-test/0-others/sysinfo.py index 9ffa6ca9e60e104cebb51fc1a94eacd7aa494773..43a0400f1880ded44bbbaadfa1a3467a8c3d9775 100644 --- a/tests/system-test/0-others/sysinfo.py +++ b/tests/system-test/0-others/sysinfo.py @@ -49,8 +49,6 @@ class TDTestCase: #!for bug tdDnodes.stoptaosd(1) sleep(self.delaytime * 5) - if platform.system().lower() == 'windows': - sleep(10) tdSql.error('select server_status()') def run(self): diff --git a/tests/system-test/0-others/tag_index_advance.py b/tests/system-test/0-others/tag_index_advance.py new file mode 100644 index 0000000000000000000000000000000000000000..cc942bbf03da12e2c74885577ed9418086795745 --- /dev/null +++ b/tests/system-test/0-others/tag_index_advance.py @@ -0,0 +1,524 @@ +################################################################### +# 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 random +import socket +import string +import subprocess +import sys +import time +from ssl import ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE + +import taos +from util.cases import * +from util.common import * +from util.dnodes import * +from util.dnodes import TDDnode, TDDnodes +from util.log import * +from util.sql import * +from util.sqlset import * + + +# +# -------------- util -------------------------- +# +def pathSize(path): + + total_size = 0 + for dirpath, dirnames, filenames in os.walk(path): + for i in filenames: + # use join to concatenate all the components of path + f = os.path.join(dirpath, i) + # use getsize to generate size in bytes and add it to the total size + total_size += os.path.getsize(f) + # print(dirpath) + + print(" %s %.02f MB" % (path, total_size/1024/1024)) + return total_size + + ''' + total = 0 + with os.scandir(path) as it: + for entry in it: + if entry.is_file(): + total += entry.stat().st_size + elif entry.is_dir(): + total += pathSize(entry.path) + + print(" %s %.02f MB"%(path, total/1024/1024)) + return total + ''' + +# +# --------------- cluster ------------------------ +# + + +class MyDnodes(TDDnodes): + def __init__(self, dnodes_lists): + super(MyDnodes, self).__init__() + self.dnodes = dnodes_lists # dnode must be TDDnode instance + self.simDeployed = False + + +class TagCluster: + noConn = True + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + self.depoly_cluster(5) + self.master_dnode = self.TDDnodes.dnodes[0] + self.host = self.master_dnode.cfgDict["fqdn"] + conn1 = taos.connect( + self.master_dnode.cfgDict["fqdn"], config=self.master_dnode.cfgDir) + tdSql.init(conn1.cursor()) + + 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 or "taosd.exe" 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 depoly_cluster(self, dnodes_nums): + + testCluster = False + valgrind = 0 + hostname = socket.gethostname() + dnodes = [] + start_port = 6030 + for num in range(1, dnodes_nums+1): + dnode = TDDnode(num) + dnode.addExtraCfg("firstEp", f"{hostname}:{start_port}") + dnode.addExtraCfg("fqdn", f"{hostname}") + dnode.addExtraCfg("serverPort", f"{start_port + (num-1)*100}") + dnode.addExtraCfg("monitorFqdn", hostname) + dnode.addExtraCfg("monitorPort", 7043) + dnodes.append(dnode) + + self.TDDnodes = MyDnodes(dnodes) + self.TDDnodes.init("") + self.TDDnodes.setTestCluster(testCluster) + self.TDDnodes.setValgrind(valgrind) + + self.TDDnodes.setAsan(tdDnodes.getAsan()) + self.TDDnodes.stopAll() + for dnode in self.TDDnodes.dnodes: + self.TDDnodes.deploy(dnode.index, {}) + + for dnode in self.TDDnodes.dnodes: + self.TDDnodes.starttaosd(dnode.index) + + # create cluster + dnode_first_host = "" + sql = "" + for dnode in self.TDDnodes.dnodes[1:]: + # print(dnode.cfgDict) + dnode_id = dnode.cfgDict["fqdn"] + \ + ":" + dnode.cfgDict["serverPort"] + if dnode_first_host == "": + dnode_first_host = dnode.cfgDict["firstEp"].split(":")[0] + dnode_first_port = dnode.cfgDict["firstEp"].split(":")[-1] + sql += f"create dnode '{dnode_id}'; " + + cmd = f"{self.getBuildPath()}/build/bin/taos -h {dnode_first_host} -P {dnode_first_port} -s " + cmd += f'"{sql}"' + print(cmd) + os.system(cmd) + + time.sleep(2) + tdLog.info(" create cluster done! ") + + def getConnection(self, dnode): + host = dnode.cfgDict["fqdn"] + port = dnode.cfgDict["serverPort"] + config_dir = dnode.cfgDir + return taos.connect(host=host, port=int(port), config=config_dir) + + def run(self): + tdLog.info(" create cluster ok.") + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + + +class PerfDB: + def __init__(self): + self.sqls = [] + self.spends = [] + + # execute + def execute(self, sql): + print(f" perfdb execute {sql}") + stime = time.time() + ret = tdSql.execute(sql, 1) + spend = time.time() - stime + + self.sqls.append(sql) + self.spends.append(spend) + return ret + + # query + def query(self, sql): + print(f" perfdb query {sql}") + start = time.time() + ret = tdSql.query(sql, None, 1) + spend = time.time() - start + self.sqls.append(sql) + self.spends.append(spend) + return ret + + +# +# ----------------- TDTestCase ------------------ +# +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + tdLog.debug("start to execute %s" % __file__) + self.dbs = [PerfDB(), PerfDB()] + self.cur = 0 + self.tagCluster = TagCluster() + self.tagCluster.init(conn, logSql, replicaVar) + self.lenBinary = 64 + self.lenNchar = 32 + + # column + self.column_dict = { + 'ts': 'timestamp', + 'col1': 'tinyint', + 'col2': 'smallint', + 'col3': 'int', + 'col4': 'bigint', + 'col5': 'tinyint unsigned', + 'col6': 'smallint unsigned', + 'col7': 'int unsigned', + 'col8': 'bigint unsigned', + 'col9': 'float', + 'col10': 'double', + 'col11': 'bool', + 'col12': f'varchar({self.lenBinary})', + 'col13': f'nchar({self.lenNchar})' + } + # tag + self.tag_dict = { + 't1': 'tinyint', + 't2': 'smallint', + 't3': 'int', + 't4': 'bigint', + 't5': 'tinyint unsigned', + 't6': 'smallint unsigned', + 't7': 'int unsigned', + 't8': 'bigint unsigned', + 't9': 'float', + 't10': 'double', + 't11': 'bool', + 't12': f'varchar({self.lenBinary})', + 't13': f'nchar({self.lenNchar})', + 't14': 'timestamp' + } + + # generate specail wide random string + def random_string(self, count): + letters = string.ascii_letters + return ''.join(random.choice(letters) for i in range(count)) + + # execute + def execute(self, sql): + obj = self.dbs[self.cur] + return obj.execute(sql) + + # query + def query(self, sql): + return self.dbs[self.cur].query(sql) + + def set_stb_sql(self, stbname, column_dict, tag_dict): + column_sql = '' + tag_sql = '' + for k, v in column_dict.items(): + column_sql += f"{k} {v}, " + for k, v in tag_dict.items(): + tag_sql += f"{k} {v}, " + create_stb_sql = f'create stable {stbname} ({column_sql[:-2]}) tags ({tag_sql[:-2]})' + return create_stb_sql + + # create datbase + def create_database(self, dbname, vgroups, replica): + sql = f'create database {dbname} vgroups {vgroups} replica {replica}' + tdSql.execute(sql) + # tdSql.execute(sql) + tdSql.execute(f'use {dbname}') + + # create stable and child tables + def create_table(self, stbname, tbname, count): + # create stable + create_table_sql = self.set_stb_sql( + stbname, self.column_dict, self.tag_dict) + tdSql.execute(create_table_sql) + + # create child table + tdLog.info(f" start create {count} child tables.") + batchSql = "" + batchSize = 5000 + for i in range(int(count/batchSize)): + batchSql = "create table" + for j in range(batchSize): + ti = (i * batchSize + j) % 128 + binTxt = self.random_string(self.lenBinary) + idx = i * batchSize + j + tags = f'{ti},{ti},{idx},{idx},{ti},{ti},{idx},{idx},{idx}.000{idx},{idx}.000{idx},true,"{binTxt}","nch{idx}",now' + sql = f'{tbname}{idx} using {stbname} tags({tags})' + batchSql = batchSql + " " + sql + tdSql.execute(batchSql) + tdLog.info(f" child table count = {i * batchSize}") + + # create stable and child tables + + def create_tagidx(self, stbname): + cnt = -1 + for key in self.tag_dict.keys(): + # first tag have default index, so skip + if cnt == -1: + cnt = 0 + continue + sql = f'create index idx_{key} on {stbname} ({key})' + tdLog.info(f" sql={sql}") + tdSql.execute(sql) + cnt += 1 + tdLog.info(f' create {cnt} tag indexs ok.') + + # insert to child table d1 data + def insert_data(self, tbname): + # d1 insert 3 rows + for i in range(3): + sql = f'insert into {tbname}1(ts,col1) values(now+{i}s,{i});' + tdSql.execute(sql) + # d20 insert 4 + for i in range(4): + sql = f'insert into {tbname}20(ts,col1) values(now+{i}s,{i});' + tdSql.execute(sql) + + # check show indexs + def show_tagidx(self, dbname, stbname): + sql = f'select index_name,column_name from information_schema.ins_indexes where db_name="{dbname}"' + tdSql.query(sql) + rows = len(self.tag_dict.keys())-1 + tdSql.checkRows(rows) + + for i in range(rows): + col_name = tdSql.getData(i, 1) + idx_name = f'idx_{col_name}' + tdSql.checkData(i, 0, idx_name) + + tdLog.info(f' show {rows} tag indexs ok.') + + # query with tag idx + def query_tagidx(self, stbname): + sql = f'select * from meters where t2=1' + self.query(sql) + tdSql.checkRows(3) + + sql = f'select * from meters where t2<10' + self.query(sql) + tdSql.checkRows(3) + + sql = f'select * from meters where t2>10' + self.query(sql) + tdSql.checkRows(4) + + sql = f'select * from meters where t3<30' + self.query(sql) + tdSql.checkRows(7) + + sql = f'select * from meters where t12="11"' + tdSql.query(sql) + tdSql.checkRows(0) + + sql = f'select * from meters where (t4 < 10 or t5 = 20) and t6= 30' + self.query(sql) + tdSql.checkRows(0) + + sql = f'select * from meters where (t7 < 20 and t8 = 20) or t4 = 20' + self.query(sql) + tdSql.checkRows(4) + + sql = f'select * from meters where t12 like "%ab%" ' + self.query(sql) + tdSql.checkRows(0) + + sql = f'select * from meters where t13 = "d20" ' + self.query(sql) + tdSql.checkRows(0) + + sql = f'select * from meters where t13 = "nch20" ' + self.query(sql) + tdSql.checkRows(4) + + sql = f'select * from meters where tbname = "d20" ' + self.query(sql) + tdSql.checkRows(4) + + # drop child table + + def drop_tables(self, tbname, count): + # table d1 and d20 have verify data , so can not drop + start = random.randint(21, count/2) + end = random.randint(count/2 + 1, count - 1) + for i in range(start, end): + sql = f'drop table {tbname}{i}' + tdSql.execute(sql) + cnt = end - start + 1 + tdLog.info(f' drop table from {start} to {end} count={cnt}') + + # drop tag index + def drop_tagidx(self, dbname, stbname): + # drop index + cnt = -1 + for key in self.tag_dict.keys(): + # first tag have default index, so skip + if cnt == -1: + cnt = 0 + continue + sql = f'drop index idx_{key}' + tdSql.execute(sql) + cnt += 1 + + # check idx result is 0 + sql = f'select index_name,column_name from information_schema.ins_indexes where db_name="{dbname}"' + tdSql.query(sql) + tdSql.checkRows(0) + tdLog.info(f' drop {cnt} tag indexs ok.') + + # show performance + def show_performance(self, count): + db = self.dbs[0] + db1 = self.dbs[1] + cnt = len(db.sqls) + cnt1 = len(db1.sqls) + if cnt != len(db1.sqls): + tdLog.info( + f" datebase sql count not equal. cnt={cnt} cnt1={cnt1}\n") + return False + + tdLog.info(f" database sql cnt ={cnt}") + print( + f" ----------------- performance (child tables = {count})--------------------") + print(" No time(index) time(no-index) diff(col3-col2) rate(col2/col3) sql") + for i in range(cnt): + key = db.sqls[i] + value = db.spends[i] + key1 = db1.sqls[i] + value1 = db1.spends[i] + diff = value1 - value + rate = value/value1*100 + print(" %d %.3fs %.3fs %.3fs %d%% %s" % ( + i+1, value, value1, diff, rate, key)) + print(" --------------------- end ------------------------") + return True + + def show_diskspace(self): + # calc + selfPath = os.path.dirname(os.path.realpath(__file__)) + projPath = "" + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + # total + vnode2_size = pathSize(projPath + "sim/dnode2/data/vnode/vnode2/") + vnode3_size = pathSize(projPath + "sim/dnode3/data/vnode/vnode3/") + vnode4_size = pathSize(projPath + "sim/dnode4/data/vnode/vnode4/") + vnode5_size = pathSize(projPath + "sim/dnode5/data/vnode/vnode5/") + + # show + print(" ----------------- disk space --------------------") + idx_size = vnode2_size + vnode3_size + noidx_size = vnode4_size + vnode5_size + + print(" index = %.02f M" % (idx_size/1024/1024)) + print(" no-index = %.02f M" % (noidx_size/1024/1024)) + print(" index/no-index = %.2f multiple" % (idx_size/noidx_size)) + + print(" -------------------- end ------------------------") + + # main + + def testdb(self, dbname, stable, tbname, count, createidx): + # cur + if createidx: + self.cur = 0 + else: + self.cur = 1 + + # do + self.create_database(dbname, 2, 1) + self.create_table(stable, tbname, count) + if (createidx): + self.create_tagidx(stable) + self.insert_data(tbname) + if (createidx): + self.show_tagidx(dbname, stable) + self.query_tagidx(stable) + # self.drop_tables(tbname, count) + # if(createidx): + # self.drop_tagidx(dbname, stable) + # query after delete , expect no crash + # self.query_tagidx(stable) + tdSql.execute(f'flush database {dbname}') + + # run + def run(self): + self.tagCluster.run() + + # var + dbname = "tagindex" + dbname1 = dbname + "1" + stable = "meters" + tbname = "d" + count = 10000 + + # test db + tdLog.info(f" ------------- {dbname} ----------") + self.testdb(dbname, stable, tbname, count, True) + tdLog.info(f" ------------- {dbname1} ----------") + self.testdb(dbname1, stable, tbname, count, False) + + # show test result + self.show_performance(count) + + self.tagCluster.TDDnodes.stopAll() + sec = 10 + print(f" sleep {sec}s wait taosd stopping ...") + time.sleep(sec) + + self.show_diskspace() + + def stop(self): + self.tagCluster.stop() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/0-others/tag_index_basic.py b/tests/system-test/0-others/tag_index_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..72ed559ffd94f808a906d0547c8b10f2ea6f1500 --- /dev/null +++ b/tests/system-test/0-others/tag_index_basic.py @@ -0,0 +1,247 @@ +################################################################### +# 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 * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import * +import random + + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), True) + self.setsql = TDSetSql() + self.column_dict = { + 'ts': 'timestamp', + 'col1': 'tinyint', + 'col2': 'smallint', + 'col3': 'int', + 'col4': 'bigint', + 'col5': 'tinyint unsigned', + 'col6': 'smallint unsigned', + 'col7': 'int unsigned', + 'col8': 'bigint unsigned', + 'col9': 'float', + 'col10': 'double', + 'col11': 'bool', + 'col12': 'varchar(20)', + 'col13': 'nchar(20)' + } + self.tag_dict = { + 't1': 'tinyint', + 't2': 'smallint', + 't3': 'int', + 't4': 'bigint', + 't5': 'tinyint unsigned', + 't6': 'smallint unsigned', + 't7': 'int unsigned', + 't8': 'bigint unsigned', + 't9': 'float', + 't10': 'double', + 't11': 'bool', + 't12': 'varchar(20)', + 't13': 'nchar(20)', + 't14': 'timestamp' + } + + + def set_stb_sql(self,stbname,column_dict,tag_dict): + column_sql = '' + tag_sql = '' + for k,v in column_dict.items(): + column_sql += f"{k} {v}, " + for k,v in tag_dict.items(): + tag_sql += f"{k} {v}, " + create_stb_sql = f'create stable {stbname} ({column_sql[:-2]}) tags ({tag_sql[:-2]})' + return create_stb_sql + + # create stable and child tables + def create_table(self, stbname, tbname, count): + tdSql.prepare() + tdSql.execute('use db') + + # create stable + create_table_sql = self.set_stb_sql(stbname, self.column_dict, self.tag_dict) + tdSql.execute(create_table_sql) + + # create child table + for i in range(count): + ti = i % 128 + tags = f'{ti},{ti},{i},{i},{ti},{ti},{i},{i},{i}.000{i},{i}.000{i},true,"var{i}","nch{i}",now' + sql = f'create table {tbname}{i} using {stbname} tags({tags})' + tdSql.execute(sql) + + tdLog.info(f" create {count} child tables ok.") + + + # create stable and child tables + def create_tagidx(self, stbname): + cnt = -1 + for key in self.tag_dict.keys(): + # first tag have default index, so skip + if cnt == -1: + cnt = 0 + continue; + sql = f'create index idx_{key} on {stbname} ({key})' + tdLog.info(f" sql={sql}") + tdSql.execute(sql) + cnt += 1 + tdLog.info(f' create {cnt} tag indexs ok.') + + # insert to child table d1 data + def insert_data(self, tbname): + # d1 insert 3 rows + for i in range(3): + sql = f'insert into {tbname}1(ts,col1) values(now+{i}s,{i});' + tdSql.execute(sql) + # d20 insert 4 + for i in range(4): + sql = f'insert into {tbname}20(ts,col1) values(now+{i}s,{i});' + tdSql.execute(sql) + + # check show indexs + def show_tagidx(self, stbname): + sql = f'select index_name,column_name from information_schema.ins_indexes where db_name="db"' + tdSql.query(sql) + rows = len(self.tag_dict.keys())-1 + tdSql.checkRows(rows) + + for i in range(rows): + col_name = tdSql.getData(i, 1) + idx_name = f'idx_{col_name}' + tdSql.checkData(i, 0, idx_name) + + tdLog.info(f' show {rows} tag indexs ok.') + + # query with tag idx + def query_tagidx(self, stbname): + sql = f'select * from meters where t1=1' + tdSql.query(sql) + tdSql.checkRows(3) + + sql = f'select * from meters where t2<10' + tdSql.query(sql) + tdSql.checkRows(3) + + sql = f'select * from meters where t2>10' + tdSql.query(sql) + tdSql.checkRows(4) + + sql = f'select * from meters where t3<30' + tdSql.query(sql) + tdSql.checkRows(7) + + sql = f'select * from meters where t12="11"' + tdSql.query(sql) + tdSql.checkRows(0) + + sql = f'select t12 ,t13,tbname from meters where t13="nch20"' + tdSql.query(sql) + tdSql.checkRows(4) + + sql = f'select * from meters where t12 like "%ab%" ' + tdSql.query(sql) + tdSql.checkRows(0) + + sql = f'select * from meters where t13 = "d20" ' + tdSql.query(sql) + tdSql.checkRows(0) + + sql = f'select * from meters where tbname = "d20" ' + tdSql.query(sql) + tdSql.checkRows(4) + + sql = f'select * from meters where (t4 < 10 or t5 = 20) and t6= 30' + tdSql.query(sql) + tdSql.checkRows(0) + + sql = f'select * from meters where (t7 < 20 and t8 = 20) or t4 = 20' + tdSql.query(sql) + tdSql.checkRows(4) + + # drop child table + def drop_tables(self, tbname, count): + # table d1 and d20 have verify data , so can not drop + start = random.randint(21, count/2) + end = random.randint(count/2 + 1, count - 1) + for i in range(start, end): + sql = f'drop table {tbname}{i}' + tdSql.execute(sql) + cnt = end - start + 1 + tdLog.info(f' drop table from {start} to {end} count={cnt}') + + # drop tag index + def drop_tagidx(self, stbname): + # drop index + cnt = -1 + for key in self.tag_dict.keys(): + # first tag have default index, so skip + if cnt == -1: + cnt = 0 + continue; + sql = f'drop index idx_{key}' + tdSql.execute(sql) + cnt += 1 + + # check idx result is 0 + sql = f'select index_name,column_name from information_schema.ins_indexes where db_name="db"' + tdSql.query(sql) + tdSql.checkRows(0) + tdLog.info(f' drop {cnt} tag indexs ok.') + + # create long name idx + def longname_idx(self, stbname): + long_name = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllllmmmmmmmmmm" + key = "t3" + sql = f'create index {long_name} on {stbname} ({key})' + tdSql.error(sql) + + long_name = "aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffff" + key = "t3" + sql = f'create index {long_name} on {stbname} ({key})' + tdLog.info(f"{sql}") + tdSql.execute(sql) + sql = f'drop index {long_name}' + tdLog.info(f"{sql}") + tdSql.execute(sql) + + # run + def run(self): + # var + stable = "meters" + tbname = "d" + count = 1000 + # do + self.create_table(stable, tbname, count) + self.create_tagidx(stable) + self.insert_data(tbname) + self.show_tagidx(stable) + self.query_tagidx(stable) + self.drop_tables(tbname, count) + self.drop_tagidx(stable) + # query after delete , expect no crash + self.query_tagidx(stable) + self.longname_idx(stable) + + + 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/system-test/0-others/taosShell.py b/tests/system-test/0-others/taosShell.py index 5c7bb0443a282c4be28cfaa359eb8f41fb4c4ce4..1227378799e35b88a3aa33d109e6c347601c00c6 100644 --- a/tests/system-test/0-others/taosShell.py +++ b/tests/system-test/0-others/taosShell.py @@ -373,7 +373,7 @@ class TDTestCase: version = 'version: ' + version retVal = retVal.replace("\n", "") retVal = retVal.replace("\r", "") - if retVal != version: + if retVal.startswith(version) == False: print ("return version: [%s]"%retVal) print ("dict version: [%s]"%version) tdLog.exit("taos -V version not match") diff --git a/tests/system-test/0-others/taosdMonitor.py b/tests/system-test/0-others/taosdMonitor.py index 944ff52d5bacf386369c80b8561229f48d554008..8094c4e0f555dcd7a5a7340c439a0a34948b212d 100644 --- a/tests/system-test/0-others/taosdMonitor.py +++ b/tests/system-test/0-others/taosdMonitor.py @@ -292,7 +292,7 @@ class TDTestCase: def run(self): # sourcery skip: extract-duplicate-method, remove-redundant-fstring tdSql.prepare() # time.sleep(2) - vgroups = "30" + vgroups = "4" sql = "create database db3 vgroups " + vgroups tdSql.query(sql) sql = "create table db3.stb (ts timestamp, f int) tags (t int)" diff --git a/tests/system-test/0-others/taosdShell.py b/tests/system-test/0-others/taosdShell.py index 7ad7e4d0ef90b7f30f692cb40596c14b653e903d..3b9eb66705407e80a9e130680675a618283679e0 100644 --- a/tests/system-test/0-others/taosdShell.py +++ b/tests/system-test/0-others/taosdShell.py @@ -4,6 +4,7 @@ import sys import time from datetime import datetime import socket +import psutil import os import platform if platform.system().lower() == 'windows': @@ -67,19 +68,25 @@ class TDTestCase: return buildPath def get_process_pid(self,processname): - #origin artical link:https://blog.csdn.net/weixin_45623536/article/details/122099062 - process_info_list = [] - process = os.popen('ps -A | grep %s'% processname) - process_info = process.read() - for i in process_info.split(' '): - if i != "": - process_info_list.append(i) - print(process_info_list) - if len(process_info_list) != 0 : - pid = int(process_info_list[0]) - else : - pid = 0 - return pid + if platform.system().lower() == 'windows': + pids = psutil.process_iter() + for pid in pids: + if(pid.name() == processname): + return pid.pid + return 0 + else: + process_info_list = [] + process = os.popen('ps -A | grep %s'% processname) + process_info = process.read() + for i in process_info.split(' '): + if i != "": + process_info_list.append(i) + print(process_info_list) + if len(process_info_list) != 0 : + pid = int(process_info_list[0]) + else : + pid = 0 + return pid def checkAndstopPro(self,processName,startAction): i = 1 @@ -88,23 +95,29 @@ class TDTestCase: taosdPid=self.get_process_pid(processName) if taosdPid != 0 and taosdPid != "" : tdLog.info("stop taosd %s ,kill pid :%s "%(startAction,taosdPid)) - os.system("kill -9 %d"%taosdPid) + os.system("kill -9 %d"%taosdPid) break else: tdLog.info( "wait start taosd ,times: %d "%i) time.sleep(1) i+= 1 else : - tdLog.exit("taosd %s is not running "%startAction) + tdLog.exit("taosd %s is not running "%startAction) def taosdCommandStop(self,startAction,taosdCmdRun): processName="taosd" + if platform.system().lower() == 'windows': + processName="taosd.exe" taosdCmd = taosdCmdRun + startAction tdLog.printNoPrefix("%s"%taosdCmd) - logTime=datetime.now().strftime('%Y%m%d_%H%M%S_%f') - os.system(f"nohup {taosdCmd} > {logTime}.log 2>&1 & ") - self.checkAndstopPro(processName,startAction) - os.system(f"rm -rf {logTime}.log") + if platform.system().lower() == 'windows': + cmd = f"mintty -h never {taosdCmd}" + os.system(cmd) + else: + logTime=datetime.now().strftime('%Y%m%d_%H%M%S_%f') + os.system(f"nohup {taosdCmd} > {logTime}.log 2>&1 & ") + self.checkAndstopPro(processName,startAction) + os.system(f"rm -rf {logTime}.log") def taosdCommandExe(self,startAction,taosdCmdRun): @@ -116,7 +129,7 @@ class TDTestCase: # database\stb\tb\chiild-tb\rows\topics tdSql.execute("create user testpy pass 'testpy'") tdSql.execute("drop database if exists db0;") - tdSql.execute("create database db0;") + tdSql.execute("create database db0 wal_retention_period 3600;") tdSql.execute("use db0;") tdSql.execute("create table if not exists db0.stb (ts timestamp, c1 int, c2 float, c3 double) tags (t1 int unsigned);") tdSql.execute("create table db0.ct1 using db0.stb tags(1000);") @@ -132,14 +145,14 @@ class TDTestCase: #stream tdSql.execute("drop database if exists source_db;") - tdSql.query("create database source_db vgroups 3;") + tdSql.query("create database source_db vgroups 3 wal_retention_period 3600;") tdSql.query("use source_db") tdSql.query("create table if not exists source_db.stb (ts timestamp, k int) tags (a int);") tdSql.query("create table source_db.ct1 using source_db.stb tags(1000);create table source_db.ct2 using source_db.stb tags(2000);create table source_db.ct3 using source_db.stb tags(3000);") - tdSql.query("create stream s1 into source_db.output_stb as select _wstart AS start, min(k), max(k), sum(k) from source_db.stb interval(10m);") + tdSql.query("create stream s1 into source_db.output_stb as select _wstart AS startts, min(k), max(k), sum(k) from source_db.stb interval(10m);") - #TD-19944 -Q=3 + #TD-19944 -Q=3 tdsqlN=tdCom.newTdSql() tdsqlN.query("select * from source_db.stb") @@ -186,7 +199,11 @@ class TDTestCase: startAction=" -a jsonFile:./taosdCaseTmp.json" tdLog.printNoPrefix("================================ parameter: %s"%startAction) - os.system("echo \'{\"queryPolicy\":\"3\"}\' > taosdCaseTmp.json") + + if platform.system().lower() == 'windows': + os.system("echo {\"queryPolicy\":\"3\"} > taosdCaseTmp.json") + else: + os.system("echo \'{\"queryPolicy\":\"3\"}\' > taosdCaseTmp.json") self.taosdCommandStop(startAction,taosdCmdRun) startAction = " -a jsonFile:./taosdCaseTmp.json -C " @@ -206,12 +223,12 @@ class TDTestCase: self.taosdCommandStop(startAction,taosdCmdRun) - startAction=" -E taosdCaseTmp/.env" + startAction=f" -E taosdCaseTmp{os.sep}.env" tdLog.printNoPrefix("================================ parameter: %s"%startAction) - os.system(" mkdir -p taosdCaseTmp ") - os.system("echo \'TAOS_QUERY_POLICY=3\' > taosdCaseTmp/.env ") + os.system(" mkdir -p taosdCaseTmp ") + os.system("echo TAOS_QUERY_POLICY=3 > taosdCaseTmp/.env ") self.taosdCommandStop(startAction,taosdCmdRun) - os.system(" rm -rf taosdCaseTmp ") + os.system(" rm -rf taosdCaseTmp ") startAction = " -V" tdLog.printNoPrefix("================================ parameter: %s"%startAction) diff --git a/tests/system-test/0-others/telemetry.py b/tests/system-test/0-others/telemetry.py index bc5d276faa92e2ec6226a7b36c4ac5b0b3d46420..3b6cb105099dfacebc705d347b320005e4b3d109 100644 --- a/tests/system-test/0-others/telemetry.py +++ b/tests/system-test/0-others/telemetry.py @@ -181,7 +181,7 @@ class TDTestCase: def run(self): # sourcery skip: extract-duplicate-method, remove-redundant-fstring tdSql.prepare() # time.sleep(2) - vgroups = "30" + vgroups = "4" sql = "create database db3 vgroups " + vgroups tdSql.query(sql) diff --git a/tests/system-test/0-others/testRoll.py b/tests/system-test/0-others/testRoll.py new file mode 100644 index 0000000000000000000000000000000000000000..c5489146dc4edff7c77a6e2888925bb284dd3fc3 --- /dev/null +++ b/tests/system-test/0-others/testRoll.py @@ -0,0 +1,83 @@ +from taos.tmq import Consumer +import taos +import taosrest +import socket + + +def init_tmq_env(db, topic): + conn = taos.connect() + # conn.execute("create dnode test209") + # conn.execute("create dnode test216") + # conn.execute("create mnode on dnode 2") + # conn.execute("create mnode on dnode 3") + + conn.execute("drop topic if exists {}".format(topic)) + conn.execute("drop database if exists {}".format(db)) + conn.execute("create database if not exists {} replica 1 wal_retention_period 3600".format(db)) + conn.select_db(db) + conn.execute( + "create stable if not exists stb1 (ts timestamp, c1 int, c2 float, c3 varchar(16)) tags(t1 int, t3 varchar(16))") + conn.execute("create table if not exists tb1 using stb1 tags(1, 't1')") + conn.execute("create table if not exists tb2 using stb1 tags(2, 't2')") + conn.execute("create table if not exists tb3 using stb1 tags(3, 't3')") + conn.execute("create topic if not exists {} as select ts, c1, c2, c3 from stb1".format(topic)) + conn.execute("insert into tb1 values (now+10s, 1, 1.0, 'tmq test')") + conn.execute("insert into tb2 values (now+100s, 2, 2.0, 'tmq test')") + conn.execute("insert into tb3 values (now+20s, 3, 3.0, 'tmq test')") + conn.execute("insert into tb3 values (now+30s, 4, 4.0, 'tmq test4')") + +def init_tmq_rest_env(db, topic): + host = socket.gethostname() + conn = taosrest.connect(url=f"http://{host}:6041") + + # conn.execute("create dnode test209") + # conn.execute("create dnode test216") + # conn.execute("create mnode on dnode 2") + # conn.execute("create mnode on dnode 3") + + conn.execute("drop topic if exists {}".format(topic)) + conn.execute("drop database if exists {}".format(db)) + conn.execute("create database if not exists {} replica 3 wal_retention_period 3600".format(db)) + conn.select_db(db) + conn.execute( + "create stable if not exists stb1 (ts timestamp, c1 int, c2 float, c3 varchar(16)) tags(t1 int, t3 varchar(16))") + conn.execute("create table if not exists tb1 using stb1 tags(1, 't1')") + conn.execute("create table if not exists tb2 using stb1 tags(2, 't2')") + conn.execute("create table if not exists tb3 using stb1 tags(3, 't3')") + conn.execute("create topic if not exists {} as select ts, c1, c2, c3 from stb1".format(topic)) + conn.execute("insert into tb1 values (now+10s, 1, 1.0, 'tmq test')") + conn.execute("insert into tb2 values (now+100s, 2, 2.0, 'tmq test')") + conn.execute("insert into tb3 values (now+20s, 3, 3.0, 'tmq test')") + conn.execute("insert into tb3 values (now+30s, 4, 4.0, 'tmq test4')") + + + + +if __name__ == '__main__': + conn = taos.connect() + + init_tmq_env("tmq_test", "tmq_test_topic") # init env + # init_tmq_rest_env("tmq_test", "tmq_test_topic") + consumer = Consumer( + { + "group.id": "tg75", + "client.id": "124", + "td.connect.user": "root", + "td.connect.pass": "taosdata", + "enable.auto.commit": "true", + "experimental.snapshot.enable": "true", + } + ) + consumer.subscribe(["tmq_test_topic"]) + + while True: + res = consumer.poll(10) + if not res: + break + err = res.error() + if err is not None: + raise err + val = res.value() + + for block in val: + print(block.fetchall()) diff --git a/tests/system-test/0-others/tmqBasic.json b/tests/system-test/0-others/tmqBasic.json new file mode 100644 index 0000000000000000000000000000000000000000..d716bff3ac254c3d1106c25bd0a45ce8f43603d4 --- /dev/null +++ b/tests/system-test/0-others/tmqBasic.json @@ -0,0 +1,23 @@ +{ + "filetype": "subscribe", + "cfgdir": "/etc/taos", + "host": "127.0.0.1", + "port": 6030, + "user": "root", + "password": "taosdata", + "confirm_parameter_prompt": "no", + "tmq_info": { + "concurrent": 1, + "poll_delay": 10000, + "group.id": "grpId_0", + "client.id": "clientId", + "auto.offset.reset": "earliest", + "enable.auto.commit": "true", + "auto.commit.interval.ms": 1000, + "experimental.snapshot.enable": "true", + "msg.with.table.name": "false", + "topic_list": [ + {"name": "tmq_topic_1", "sql": "select current,voltage,phase from test.meters where voltage <= 106 ;"} + ] + } +} \ No newline at end of file diff --git a/tests/system-test/0-others/udfTest.py b/tests/system-test/0-others/udfTest.py index 15253df0c4eda40378ed2c875f01a8448f73003d..78020cb9586e6c59f7c0f84e5aeacdbb596b421c 100644 --- a/tests/system-test/0-others/udfTest.py +++ b/tests/system-test/0-others/udfTest.py @@ -146,7 +146,7 @@ class TDTestCase: for i in range(5): # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) # create aggregate functions @@ -171,7 +171,7 @@ class TDTestCase: tdLog.info("drop two udf functions success ") # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) # create aggregate functions @@ -191,20 +191,20 @@ class TDTestCase: tdSql.checkData(0,0,None) tdSql.checkData(0,1,None) tdSql.checkData(0,2,1) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.checkData(0,4,1.000000000) - tdSql.checkData(0,5,88) + tdSql.checkData(0,5,1) tdSql.checkData(0,6,"binary1") - tdSql.checkData(0,7,88) + tdSql.checkData(0,7,1) tdSql.checkData(3,0,3) - tdSql.checkData(3,1,88) + tdSql.checkData(3,1,1) tdSql.checkData(3,2,33333) - tdSql.checkData(3,3,88) + tdSql.checkData(3,3,1) tdSql.checkData(3,4,33.000000000) - tdSql.checkData(3,5,88) + tdSql.checkData(3,5,1) tdSql.checkData(3,6,"binary1") - tdSql.checkData(3,7,88) + tdSql.checkData(3,7,1) tdSql.checkData(11,0,None) tdSql.checkData(11,1,None) @@ -213,7 +213,7 @@ class TDTestCase: tdSql.checkData(11,4,None) tdSql.checkData(11,5,None) tdSql.checkData(11,6,"binary1") - tdSql.checkData(11,7,88) + tdSql.checkData(11,7,1) tdSql.query("select c1 , udf1(c1) ,c2 ,udf1(c2), c3 ,udf1(c3), c4 ,udf1(c4) from stb1 order by c1") tdSql.checkData(0,0,None) @@ -226,13 +226,13 @@ class TDTestCase: tdSql.checkData(0,7,None) tdSql.checkData(20,0,8) - tdSql.checkData(20,1,88) + tdSql.checkData(20,1,1) tdSql.checkData(20,2,88888) - tdSql.checkData(20,3,88) + tdSql.checkData(20,3,1) tdSql.checkData(20,4,888) - tdSql.checkData(20,5,88) + tdSql.checkData(20,5,1) tdSql.checkData(20,6,88) - tdSql.checkData(20,7,88) + tdSql.checkData(20,7,1) # aggregate functions @@ -375,14 +375,14 @@ class TDTestCase: tdSql.checkRows(25) tdSql.checkData(0,0,None) tdSql.checkData(0,1,None) - tdSql.checkData(1,0,88) + tdSql.checkData(1,0,1) tdSql.checkData(1,1,8) tdSql.query("select abs(udf1(c1)) , abs(ceil(c1)) from ct1 order by ts;") tdSql.checkRows(13) - tdSql.checkData(0,0,88) + tdSql.checkData(0,0,1) tdSql.checkData(0,1,8) - tdSql.checkData(1,0,88) + tdSql.checkData(1,0,1) tdSql.checkData(1,1,7) # bug fix for crash @@ -401,9 +401,9 @@ class TDTestCase: tdSql.query("select c1 ,udf1(c1) , c6 ,udf1(c6) from stb1 where c1 > 8 order by ts") tdSql.checkRows(3) tdSql.checkData(0,0,9) - tdSql.checkData(0,1,88) + tdSql.checkData(0,1,1) tdSql.checkData(0,2,-99.990000000) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.query("select sub1.c1, sub2.c2 from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,0) @@ -412,20 +412,20 @@ class TDTestCase: tdSql.checkData(1,1,10) tdSql.query("select udf1(sub1.c1), udf1(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") - tdSql.checkData(0,0,88) - tdSql.checkData(0,1,88) - tdSql.checkData(1,0,88) - tdSql.checkData(1,1,88) + tdSql.checkData(0,0,1) + tdSql.checkData(0,1,1) + tdSql.checkData(1,0,1) + tdSql.checkData(1,1,1) tdSql.query("select sub1.c1 , udf1(sub1.c1), sub2.c2 ,udf1(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,0) - tdSql.checkData(0,1,88) + tdSql.checkData(0,1,1) tdSql.checkData(0,2,0) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.checkData(1,0,1) - tdSql.checkData(1,1,88) + tdSql.checkData(1,1,1) tdSql.checkData(1,2,10) - tdSql.checkData(1,3,88) + tdSql.checkData(1,3,1) tdSql.query("select udf2(sub1.c1), udf2(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,16.881943016) @@ -562,7 +562,7 @@ class TDTestCase: # create function without buffer tdSql.execute("create aggregate function udf1 as '%s' outputtype int bufSize 8 "%self.libudf1) - tdSql.execute("create function udf2 as '%s' outputtype double bufSize 8"%self.libudf2) + tdSql.execute("create function udf2 as '%s' outputtype double"%self.libudf2) udf1_sqls ,udf2_sqls = self.try_query_sql() for scalar_sql in udf1_sqls: @@ -570,7 +570,7 @@ class TDTestCase: for aggregate_sql in udf2_sqls: tdSql.error(aggregate_sql) - tdSql.execute(" create function db as '%s' outputtype int bufSize 8 "%self.libudf1) + tdSql.execute(" create function db as '%s' outputtype int "%self.libudf1) tdSql.execute(" create aggregate function test as '%s' outputtype int bufSize 8 "%self.libudf1) tdSql.error(" select db(c1) from stb1 ") tdSql.error(" select db(c1,c6), db(c6) from stb1 ") @@ -619,9 +619,9 @@ class TDTestCase: tdLog.info(" create function name is not build_in functions ") tdSql.execute(" drop function udf1 ") tdSql.execute(" drop function udf2 ") - tdSql.error("create function max as '%s' outputtype int bufSize 8"%self.libudf1) + tdSql.error("create function max as '%s' outputtype int "%self.libudf1) tdSql.error("create aggregate function sum as '%s' outputtype double bufSize 8"%self.libudf2) - tdSql.error("create function max as '%s' outputtype int bufSize 8"%self.libudf1) + tdSql.error("create function max as '%s' outputtype int "%self.libudf1) tdSql.error("create aggregate function sum as '%s' outputtype double bufSize 8"%self.libudf2) tdSql.error("create aggregate function tbname as '%s' outputtype double bufSize 8"%self.libudf2) tdSql.error("create aggregate function function as '%s' outputtype double bufSize 8"%self.libudf2) diff --git a/tests/system-test/0-others/udf_cfg1.py b/tests/system-test/0-others/udf_cfg1.py index 35d43ea9b73eedc7b9432cf0590d90927ad2932c..913e5fcca14283579f6d2cc72d9674b448fc0c2b 100644 --- a/tests/system-test/0-others/udf_cfg1.py +++ b/tests/system-test/0-others/udf_cfg1.py @@ -148,7 +148,7 @@ class TDTestCase: for i in range(5): # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) # create aggregate functions @@ -173,7 +173,7 @@ class TDTestCase: tdLog.info("drop two udf functions success ") # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) # create aggregate functions diff --git a/tests/system-test/0-others/udf_cfg2.py b/tests/system-test/0-others/udf_cfg2.py index 869cb098e2e0415acf931179dc4e6887aa781f4a..b535b4f626cdf92de1a406185d9c1af807ea6c7c 100644 --- a/tests/system-test/0-others/udf_cfg2.py +++ b/tests/system-test/0-others/udf_cfg2.py @@ -148,7 +148,7 @@ class TDTestCase: for i in range(5): # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) # create aggregate functions @@ -173,7 +173,7 @@ class TDTestCase: tdLog.info("drop two udf functions success ") # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) # create aggregate functions @@ -193,20 +193,20 @@ class TDTestCase: tdSql.checkData(0,0,None) tdSql.checkData(0,1,None) tdSql.checkData(0,2,1) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.checkData(0,4,1.000000000) - tdSql.checkData(0,5,88) + tdSql.checkData(0,5,1) tdSql.checkData(0,6,"binary1") - tdSql.checkData(0,7,88) + tdSql.checkData(0,7,1) tdSql.checkData(3,0,3) - tdSql.checkData(3,1,88) + tdSql.checkData(3,1,1) tdSql.checkData(3,2,33333) - tdSql.checkData(3,3,88) + tdSql.checkData(3,3,1) tdSql.checkData(3,4,33.000000000) - tdSql.checkData(3,5,88) + tdSql.checkData(3,5,1) tdSql.checkData(3,6,"binary1") - tdSql.checkData(3,7,88) + tdSql.checkData(3,7,1) tdSql.checkData(11,0,None) tdSql.checkData(11,1,None) @@ -215,7 +215,7 @@ class TDTestCase: tdSql.checkData(11,4,None) tdSql.checkData(11,5,None) tdSql.checkData(11,6,"binary1") - tdSql.checkData(11,7,88) + tdSql.checkData(11,7,1) tdSql.query("select c1 , udf1(c1) ,c2 ,udf1(c2), c3 ,udf1(c3), c4 ,udf1(c4) from stb1 order by c1") tdSql.checkData(0,0,None) @@ -228,13 +228,13 @@ class TDTestCase: tdSql.checkData(0,7,None) tdSql.checkData(20,0,8) - tdSql.checkData(20,1,88) + tdSql.checkData(20,1,1) tdSql.checkData(20,2,88888) - tdSql.checkData(20,3,88) + tdSql.checkData(20,3,1) tdSql.checkData(20,4,888) - tdSql.checkData(20,5,88) + tdSql.checkData(20,5,1) tdSql.checkData(20,6,88) - tdSql.checkData(20,7,88) + tdSql.checkData(20,7,1) # aggregate functions @@ -377,14 +377,14 @@ class TDTestCase: tdSql.checkRows(25) tdSql.checkData(0,0,None) tdSql.checkData(0,1,None) - tdSql.checkData(1,0,88) + tdSql.checkData(1,0,1) tdSql.checkData(1,1,8) tdSql.query("select abs(udf1(c1)) , abs(ceil(c1)) from ct1 order by ts;") tdSql.checkRows(13) - tdSql.checkData(0,0,88) + tdSql.checkData(0,0,1) tdSql.checkData(0,1,8) - tdSql.checkData(1,0,88) + tdSql.checkData(1,0,1) tdSql.checkData(1,1,7) # bug fix for crash @@ -403,9 +403,9 @@ class TDTestCase: tdSql.query("select c1 ,udf1(c1) , c6 ,udf1(c6) from stb1 where c1 > 8 order by ts") tdSql.checkRows(3) tdSql.checkData(0,0,9) - tdSql.checkData(0,1,88) + tdSql.checkData(0,1,1) tdSql.checkData(0,2,-99.990000000) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.query("select sub1.c1, sub2.c2 from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,0) @@ -414,20 +414,20 @@ class TDTestCase: tdSql.checkData(1,1,10) tdSql.query("select udf1(sub1.c1), udf1(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") - tdSql.checkData(0,0,88) - tdSql.checkData(0,1,88) - tdSql.checkData(1,0,88) - tdSql.checkData(1,1,88) + tdSql.checkData(0,0,1) + tdSql.checkData(0,1,1) + tdSql.checkData(1,0,1) + tdSql.checkData(1,1,1) tdSql.query("select sub1.c1 , udf1(sub1.c1), sub2.c2 ,udf1(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,0) - tdSql.checkData(0,1,88) + tdSql.checkData(0,1,1) tdSql.checkData(0,2,0) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.checkData(1,0,1) - tdSql.checkData(1,1,88) + tdSql.checkData(1,1,1) tdSql.checkData(1,2,10) - tdSql.checkData(1,3,88) + tdSql.checkData(1,3,1) tdSql.query("select udf2(sub1.c1), udf2(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,16.881943016) @@ -564,7 +564,7 @@ class TDTestCase: # create function without buffer tdSql.execute("create aggregate function udf1 as '%s' outputtype int bufSize 8 "%self.libudf1) - tdSql.execute("create function udf2 as '%s' outputtype double bufSize 8"%self.libudf2) + tdSql.execute("create function udf2 as '%s' outputtype double"%self.libudf2) udf1_sqls ,udf2_sqls = self.try_query_sql() for scalar_sql in udf1_sqls: @@ -572,7 +572,7 @@ class TDTestCase: for aggregate_sql in udf2_sqls: tdSql.error(aggregate_sql) - tdSql.execute(" create function db as '%s' outputtype int bufSize 8 "%self.libudf1) + tdSql.execute(" create function db as '%s' outputtype int "%self.libudf1) tdSql.execute(" create aggregate function test as '%s' outputtype int bufSize 8 "%self.libudf1) tdSql.error(" select db(c1) from stb1 ") tdSql.error(" select db(c1,c6), db(c6) from stb1 ") @@ -621,9 +621,9 @@ class TDTestCase: tdLog.info(" create function name is not build_in functions ") tdSql.execute(" drop function udf1 ") tdSql.execute(" drop function udf2 ") - tdSql.error("create function max as '%s' outputtype int bufSize 8"%self.libudf1) + tdSql.error("create function max as '%s' outputtype int"%self.libudf1) tdSql.error("create aggregate function sum as '%s' outputtype double bufSize 8"%self.libudf2) - tdSql.error("create function max as '%s' outputtype int bufSize 8"%self.libudf1) + tdSql.error("create function max as '%s' outputtype int"%self.libudf1) tdSql.error("create aggregate function sum as '%s' outputtype double bufSize 8"%self.libudf2) tdSql.error("create aggregate function tbname as '%s' outputtype double bufSize 8"%self.libudf2) tdSql.error("create aggregate function function as '%s' outputtype double bufSize 8"%self.libudf2) diff --git a/tests/system-test/0-others/udf_create.py b/tests/system-test/0-others/udf_create.py index 65dad6400041e8c52d39d0ff4e484bdc29099894..ee1a0ef5b343ce1ec29edc2e5a7062b40525ee88 100644 --- a/tests/system-test/0-others/udf_create.py +++ b/tests/system-test/0-others/udf_create.py @@ -47,17 +47,27 @@ class TDTestCase: if platform.system().lower() == 'windows': self.libudf1 = subprocess.Popen('(for /r %s %%i in ("udf1.d*") do @echo %%i)|grep lib|head -n1'%projPath , shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode("utf-8") + self.libudf1_dup = subprocess.Popen('(for /r %s %%i in ("udf1_dup.d*") do @echo %%i)|grep lib|head -n1'%projPath , shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode("utf-8") self.libudf2 = subprocess.Popen('(for /r %s %%i in ("udf2.d*") do @echo %%i)|grep lib|head -n1'%projPath , shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode("utf-8") + self.libudf2_dup = subprocess.Popen('(for /r %s %%i in ("udf2_dup.d*") do @echo %%i)|grep lib|head -n1'%projPath , shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode("utf-8") if (not tdDnodes.dnodes[0].remoteIP == ""): tdDnodes.dnodes[0].remote_conn.get(tdDnodes.dnodes[0].config["path"]+'/debug/build/lib/libudf1.so',projPath+"\\debug\\build\\lib\\") + tdDnodes.dnodes[0].remote_conn.get(tdDnodes.dnodes[0].config["path"]+'/debug/build/lib/libudf1_dup.so',projPath+"\\debug\\build\\lib\\") tdDnodes.dnodes[0].remote_conn.get(tdDnodes.dnodes[0].config["path"]+'/debug/build/lib/libudf2.so',projPath+"\\debug\\build\\lib\\") + tdDnodes.dnodes[0].remote_conn.get(tdDnodes.dnodes[0].config["path"]+'/debug/build/lib/libudf2_dup.so',projPath+"\\debug\\build\\lib\\") self.libudf1 = self.libudf1.replace('udf1.dll','libudf1.so') + self.libudf1_dup = self.libudf1_dup.replace('udf1_dup.dll','libudf1_dup.so') self.libudf2 = self.libudf2.replace('udf2.dll','libudf2.so') + self.libudf2_dup = self.libudf2_dup.replace('udf2_dup.dll','libudf2_dup.so') else: self.libudf1 = subprocess.Popen('find %s -name "libudf1.so"|grep lib|head -n1'%projPath , shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode("utf-8") + self.libudf1_dup = subprocess.Popen('find %s -name "libudf1_dup.so"|grep lib|head -n1'%projPath , shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode("utf-8") self.libudf2 = subprocess.Popen('find %s -name "libudf2.so"|grep lib|head -n1'%projPath , shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode("utf-8") + self.libudf2_dup = subprocess.Popen('find %s -name "libudf2_dup.so"|grep lib|head -n1'%projPath , shell=True, stdout=subprocess.PIPE,stderr=subprocess.STDOUT).stdout.read().decode("utf-8") self.libudf1 = self.libudf1.replace('\r','').replace('\n','') + self.libudf1_dup = self.libudf1_dup.replace('\r','').replace('\n','') self.libudf2 = self.libudf2.replace('\r','').replace('\n','') + self.libudf2_dup = self.libudf2_dup.replace('\r','').replace('\n','') def prepare_data(self): @@ -148,7 +158,7 @@ class TDTestCase: for i in range(5): # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) # create aggregate functions @@ -173,11 +183,13 @@ class TDTestCase: tdLog.info("drop two udf functions success ") # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) + tdSql.execute("create function udf1_dup as '%s' outputtype int;"%self.libudf1_dup) # create aggregate functions tdSql.execute("create aggregate function udf2 as '%s' outputtype double bufSize 8;"%self.libudf2) + tdSql.execute("create aggregate function udf2_dup as '%s' outputtype double bufSize 8;"%self.libudf2_dup) functions = tdSql.getResult("show functions") function_nums = len(functions) @@ -188,25 +200,32 @@ class TDTestCase: # scalar functions + # udf1_dup + tdSql.query("select udf1(num1) ,udf1_dup(num1) from tb") + tdSql.checkData(1,0,1) + tdSql.checkData(1,1,2) + tdSql.checkData(2,0,1) + tdSql.checkData(2,1,2) + tdSql.execute("use db ") tdSql.query("select num1 , udf1(num1) ,num2 ,udf1(num2),num3 ,udf1(num3),num4 ,udf1(num4) from tb") tdSql.checkData(0,0,None) tdSql.checkData(0,1,None) tdSql.checkData(0,2,1) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.checkData(0,4,1.000000000) - tdSql.checkData(0,5,88) + tdSql.checkData(0,5,1) tdSql.checkData(0,6,"binary1") - tdSql.checkData(0,7,88) + tdSql.checkData(0,7,1) tdSql.checkData(3,0,3) - tdSql.checkData(3,1,88) + tdSql.checkData(3,1,1) tdSql.checkData(3,2,33333) - tdSql.checkData(3,3,88) + tdSql.checkData(3,3,1) tdSql.checkData(3,4,33.000000000) - tdSql.checkData(3,5,88) + tdSql.checkData(3,5,1) tdSql.checkData(3,6,"binary1") - tdSql.checkData(3,7,88) + tdSql.checkData(3,7,1) tdSql.checkData(11,0,None) tdSql.checkData(11,1,None) @@ -215,7 +234,7 @@ class TDTestCase: tdSql.checkData(11,4,None) tdSql.checkData(11,5,None) tdSql.checkData(11,6,"binary1") - tdSql.checkData(11,7,88) + tdSql.checkData(11,7,1) tdSql.query("select c1 , udf1(c1) ,c2 ,udf1(c2), c3 ,udf1(c3), c4 ,udf1(c4) from stb1 order by c1") tdSql.checkData(0,0,None) @@ -228,16 +247,20 @@ class TDTestCase: tdSql.checkData(0,7,None) tdSql.checkData(20,0,8) - tdSql.checkData(20,1,88) + tdSql.checkData(20,1,1) tdSql.checkData(20,2,88888) - tdSql.checkData(20,3,88) + tdSql.checkData(20,3,1) tdSql.checkData(20,4,888) - tdSql.checkData(20,5,88) + tdSql.checkData(20,5,1) tdSql.checkData(20,6,88) - tdSql.checkData(20,7,88) + tdSql.checkData(20,7,1) # aggregate functions + tdSql.query("select udf2(num1) ,udf2_dup(num1) from tb") + val = tdSql.queryResult[0][0] + 100 + tdSql.checkData(0,1,val) + tdSql.query("select udf2(num1) ,udf2(num2), udf2(num3) from tb") tdSql.checkData(0,0,15.362291496) tdSql.checkData(0,1,10000949.553189287) @@ -377,14 +400,14 @@ class TDTestCase: tdSql.checkRows(25) tdSql.checkData(0,0,None) tdSql.checkData(0,1,None) - tdSql.checkData(1,0,88) + tdSql.checkData(1,0,1) tdSql.checkData(1,1,8) tdSql.query("select abs(udf1(c1)) , abs(ceil(c1)) from ct1 order by ts;") tdSql.checkRows(13) - tdSql.checkData(0,0,88) + tdSql.checkData(0,0,1) tdSql.checkData(0,1,8) - tdSql.checkData(1,0,88) + tdSql.checkData(1,0,1) tdSql.checkData(1,1,7) # bug fix for crash @@ -403,9 +426,9 @@ class TDTestCase: tdSql.query("select c1 ,udf1(c1) , c6 ,udf1(c6) from stb1 where c1 > 8 order by ts") tdSql.checkRows(3) tdSql.checkData(0,0,9) - tdSql.checkData(0,1,88) + tdSql.checkData(0,1,1) tdSql.checkData(0,2,-99.990000000) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.query("select sub1.c1, sub2.c2 from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,0) @@ -414,20 +437,20 @@ class TDTestCase: tdSql.checkData(1,1,10) tdSql.query("select udf1(sub1.c1), udf1(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") - tdSql.checkData(0,0,88) - tdSql.checkData(0,1,88) - tdSql.checkData(1,0,88) - tdSql.checkData(1,1,88) + tdSql.checkData(0,0,1) + tdSql.checkData(0,1,1) + tdSql.checkData(1,0,1) + tdSql.checkData(1,1,1) tdSql.query("select sub1.c1 , udf1(sub1.c1), sub2.c2 ,udf1(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,0) - tdSql.checkData(0,1,88) + tdSql.checkData(0,1,1) tdSql.checkData(0,2,0) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.checkData(1,0,1) - tdSql.checkData(1,1,88) + tdSql.checkData(1,1,1) tdSql.checkData(1,2,10) - tdSql.checkData(1,3,88) + tdSql.checkData(1,3,1) tdSql.query("select udf2(sub1.c1), udf2(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,16.881943016) @@ -574,7 +597,7 @@ class TDTestCase: # create function without buffer tdSql.execute("create aggregate function udf1 as '%s' outputtype int bufSize 8 "%self.libudf1) - tdSql.execute("create function udf2 as '%s' outputtype double bufSize 8"%self.libudf2) + tdSql.execute("create function udf2 as '%s' outputtype double "%self.libudf2) udf1_sqls ,udf2_sqls = self.try_query_sql() for scalar_sql in udf1_sqls: @@ -582,7 +605,7 @@ class TDTestCase: for aggregate_sql in udf2_sqls: tdSql.error(aggregate_sql) - tdSql.execute(" create function db as '%s' outputtype int bufSize 8 "%self.libudf1) + tdSql.execute(" create function db as '%s' outputtype int "%self.libudf1) tdSql.execute(" create aggregate function test as '%s' outputtype int bufSize 8 "%self.libudf1) tdSql.error(" select db(c1) from stb1 ") tdSql.error(" select db(c1,c6), db(c6) from stb1 ") @@ -631,9 +654,9 @@ class TDTestCase: tdLog.info(" create function name is not build_in functions ") tdSql.execute(" drop function udf1 ") tdSql.execute(" drop function udf2 ") - tdSql.error("create function max as '%s' outputtype int bufSize 8"%self.libudf1) + tdSql.error("create function max as '%s' outputtype int"%self.libudf1) tdSql.error("create aggregate function sum as '%s' outputtype double bufSize 8"%self.libudf2) - tdSql.error("create function max as '%s' outputtype int bufSize 8"%self.libudf1) + tdSql.error("create function max as '%s' outputtype int"%self.libudf1) tdSql.error("create aggregate function sum as '%s' outputtype double bufSize 8"%self.libudf2) tdSql.error("create aggregate function tbname as '%s' outputtype double bufSize 8"%self.libudf2) tdSql.error("create aggregate function function as '%s' outputtype double bufSize 8"%self.libudf2) diff --git a/tests/system-test/0-others/udf_restart_taosd.py b/tests/system-test/0-others/udf_restart_taosd.py index dae707520f55e2e2c6b02c60e5d9015f8c613d3d..61b6a4ea684f6150834cfc1e7c6ce1dc03a8b91b 100644 --- a/tests/system-test/0-others/udf_restart_taosd.py +++ b/tests/system-test/0-others/udf_restart_taosd.py @@ -145,7 +145,7 @@ class TDTestCase: for i in range(5): # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) # create aggregate functions @@ -170,7 +170,7 @@ class TDTestCase: tdLog.info("drop two udf functions success ") # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) # create aggregate functions @@ -190,20 +190,20 @@ class TDTestCase: tdSql.checkData(0,0,None) tdSql.checkData(0,1,None) tdSql.checkData(0,2,1) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.checkData(0,4,1.000000000) - tdSql.checkData(0,5,88) + tdSql.checkData(0,5,1) tdSql.checkData(0,6,"binary1") - tdSql.checkData(0,7,88) + tdSql.checkData(0,7,1) tdSql.checkData(3,0,3) - tdSql.checkData(3,1,88) + tdSql.checkData(3,1,1) tdSql.checkData(3,2,33333) - tdSql.checkData(3,3,88) + tdSql.checkData(3,3,1) tdSql.checkData(3,4,33.000000000) - tdSql.checkData(3,5,88) + tdSql.checkData(3,5,1) tdSql.checkData(3,6,"binary1") - tdSql.checkData(3,7,88) + tdSql.checkData(3,7,1) tdSql.checkData(11,0,None) tdSql.checkData(11,1,None) @@ -212,7 +212,7 @@ class TDTestCase: tdSql.checkData(11,4,None) tdSql.checkData(11,5,None) tdSql.checkData(11,6,"binary1") - tdSql.checkData(11,7,88) + tdSql.checkData(11,7,1) tdSql.query("select c1 , udf1(c1) ,c2 ,udf1(c2), c3 ,udf1(c3), c4 ,udf1(c4) from stb1 order by c1") tdSql.checkData(0,0,None) @@ -225,13 +225,13 @@ class TDTestCase: tdSql.checkData(0,7,None) tdSql.checkData(20,0,8) - tdSql.checkData(20,1,88) + tdSql.checkData(20,1,1) tdSql.checkData(20,2,88888) - tdSql.checkData(20,3,88) + tdSql.checkData(20,3,1) tdSql.checkData(20,4,888) - tdSql.checkData(20,5,88) + tdSql.checkData(20,5,1) tdSql.checkData(20,6,88) - tdSql.checkData(20,7,88) + tdSql.checkData(20,7,1) # aggregate functions @@ -374,14 +374,14 @@ class TDTestCase: tdSql.checkRows(25) tdSql.checkData(0,0,None) tdSql.checkData(0,1,None) - tdSql.checkData(1,0,88) + tdSql.checkData(1,0,1) tdSql.checkData(1,1,8) tdSql.query("select abs(udf1(c1)) , abs(ceil(c1)) from ct1 order by ts;") tdSql.checkRows(13) - tdSql.checkData(0,0,88) + tdSql.checkData(0,0,1) tdSql.checkData(0,1,8) - tdSql.checkData(1,0,88) + tdSql.checkData(1,0,1) tdSql.checkData(1,1,7) # bug fix for crash @@ -400,9 +400,9 @@ class TDTestCase: tdSql.query("select c1 ,udf1(c1) , c6 ,udf1(c6) from stb1 where c1 > 8 order by ts") tdSql.checkRows(3) tdSql.checkData(0,0,9) - tdSql.checkData(0,1,88) + tdSql.checkData(0,1,1) tdSql.checkData(0,2,-99.990000000) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.query("select sub1.c1, sub2.c2 from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,0) @@ -411,20 +411,20 @@ class TDTestCase: tdSql.checkData(1,1,10) tdSql.query("select udf1(sub1.c1), udf1(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") - tdSql.checkData(0,0,88) - tdSql.checkData(0,1,88) - tdSql.checkData(1,0,88) - tdSql.checkData(1,1,88) + tdSql.checkData(0,0,1) + tdSql.checkData(0,1,1) + tdSql.checkData(1,0,1) + tdSql.checkData(1,1,1) tdSql.query("select sub1.c1 , udf1(sub1.c1), sub2.c2 ,udf1(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,0) - tdSql.checkData(0,1,88) + tdSql.checkData(0,1,1) tdSql.checkData(0,2,0) - tdSql.checkData(0,3,88) + tdSql.checkData(0,3,1) tdSql.checkData(1,0,1) - tdSql.checkData(1,1,88) + tdSql.checkData(1,1,1) tdSql.checkData(1,2,10) - tdSql.checkData(1,3,88) + tdSql.checkData(1,3,1) tdSql.query("select udf2(sub1.c1), udf2(sub2.c2) from sub1, sub2 where sub1.ts=sub2.ts and sub1.c1 is not null") tdSql.checkData(0,0,16.881943016) @@ -468,12 +468,12 @@ class TDTestCase: tdSql.checkData(1,0,1) tdSql.checkData(1,1,1) tdSql.checkData(1,2,1.110000000) - tdSql.checkData(1,3,88) + tdSql.checkData(1,3,1) tdSql.query("select c1,c6,udf1(c1,c6) from stb1 order by ts") tdSql.checkData(1,0,8) tdSql.checkData(1,1,88.880000000) - tdSql.checkData(1,2,88) + tdSql.checkData(1,2,1) tdSql.query("select abs(udf1(c1,c6,c1,c6)) , abs(ceil(c1)) from stb1 where c1 is not null order by ts;") tdSql.checkRows(22) @@ -561,7 +561,7 @@ class TDTestCase: # create function without buffer tdSql.execute("create aggregate function udf1 as '%s' outputtype int bufSize 8 "%self.libudf1) - tdSql.execute("create function udf2 as '%s' outputtype double bufSize 8"%self.libudf2) + tdSql.execute("create function udf2 as '%s' outputtype double"%self.libudf2) udf1_sqls ,udf2_sqls = self.try_query_sql() for scalar_sql in udf1_sqls: @@ -569,7 +569,7 @@ class TDTestCase: for aggregate_sql in udf2_sqls: tdSql.error(aggregate_sql) - tdSql.execute(" create function db as '%s' outputtype int bufSize 8 "%self.libudf1) + tdSql.execute(" create function db as '%s' outputtype int "%self.libudf1) tdSql.execute(" create aggregate function test as '%s' outputtype int bufSize 8 "%self.libudf1) tdSql.error(" select db(c1) from stb1 ") tdSql.error(" select db(c1,c6), db(c6) from stb1 ") @@ -618,9 +618,9 @@ class TDTestCase: tdLog.info(" create function name is not build_in functions ") tdSql.execute(" drop function udf1 ") tdSql.execute(" drop function udf2 ") - tdSql.error("create function max as '%s' outputtype int bufSize 8"%self.libudf1) + tdSql.error("create function max as '%s' outputtype int"%self.libudf1) tdSql.error("create aggregate function sum as '%s' outputtype double bufSize 8"%self.libudf2) - tdSql.error("create function max as '%s' outputtype int bufSize 8"%self.libudf1) + tdSql.error("create function max as '%s' outputtype int"%self.libudf1) tdSql.error("create aggregate function sum as '%s' outputtype double bufSize 8"%self.libudf2) tdSql.error("create aggregate function tbname as '%s' outputtype double bufSize 8"%self.libudf2) tdSql.error("create aggregate function function as '%s' outputtype double bufSize 8"%self.libudf2) diff --git a/tests/system-test/0-others/udfpy/af_count.py b/tests/system-test/0-others/udfpy/af_count.py new file mode 100644 index 0000000000000000000000000000000000000000..ce29abca13866f9f311d1e868a5df68c71c5f735 --- /dev/null +++ b/tests/system-test/0-others/udfpy/af_count.py @@ -0,0 +1,23 @@ +import pickle + +def init(): + pass + +def destroy(): + pass + +def start(): + return pickle.dumps(0) + +def finish(buf): + count = pickle.loads(buf) + return count + +def reduce(datablock, buf): + (rows, cols) = datablock.shape() + count = pickle.loads(buf) + for i in range(rows): + val = datablock.data(i, 0) + if val is not None: + count += 1 + return pickle.dumps(count) \ No newline at end of file diff --git a/tests/system-test/0-others/udfpy/af_min.py b/tests/system-test/0-others/udfpy/af_min.py new file mode 100644 index 0000000000000000000000000000000000000000..9f1aadf4145c7bb585040d1f05640c913aab2aee --- /dev/null +++ b/tests/system-test/0-others/udfpy/af_min.py @@ -0,0 +1,30 @@ +import pickle + +def init(): + pass + +def destroy(): + pass + +def start(): + return pickle.dumps([]) + +def finish(buf): + mins = pickle.loads(buf) + min_val = None + for min in mins: + if min_val is None or (min is not None and min < min_val): + min_val = min + return min_val + +def reduce(datablock, buf): + (rows, cols) = datablock.shape() + mins = pickle.loads(buf) + min = None + for i in range(rows): + val = datablock.data(i, 0) + if min is None or (val is not None and val < min) : + min = val + if min is not None: + mins.append(min) + return pickle.dumps(mins) diff --git a/tests/system-test/0-others/udfpy/af_null.py b/tests/system-test/0-others/udfpy/af_null.py new file mode 100644 index 0000000000000000000000000000000000000000..230eac6888245444a4f902274a83bb5671626515 --- /dev/null +++ b/tests/system-test/0-others/udfpy/af_null.py @@ -0,0 +1,19 @@ +import pickle + +def init(): + pass + +def destroy(): + pass + +def start(): + return pickle.dumps([]) + +def finish(buf): + return None + +def reduce(datablock, buf): + (rows, cols) = datablock.shape() + mins = pickle.loads(buf) + mins.append(None) + return pickle.dumps(mins) diff --git a/tests/system-test/0-others/udfpy/af_sum.py b/tests/system-test/0-others/udfpy/af_sum.py new file mode 100644 index 0000000000000000000000000000000000000000..8b88aba56ca08f64249f85a4df596d9fd204b05a --- /dev/null +++ b/tests/system-test/0-others/udfpy/af_sum.py @@ -0,0 +1,26 @@ +import pickle + +def init(): + pass + +def destroy(): + pass + +def start(): + return pickle.dumps(None) + +def finish(buf): + sum = pickle.loads(buf) + return sum + +def reduce(datablock, buf): + (rows, cols) = datablock.shape() + sum = pickle.loads(buf) + for i in range(rows): + val = datablock.data(i, 0) + if val is not None: + if sum is None: + sum = val + else: + sum += val + return pickle.dumps(sum) diff --git a/tests/system-test/0-others/udfpy/sf_concat_nch.py b/tests/system-test/0-others/udfpy/sf_concat_nch.py new file mode 100644 index 0000000000000000000000000000000000000000..84d8eb2c961c11282784f81b6206a36fba0f2edc --- /dev/null +++ b/tests/system-test/0-others/udfpy/sf_concat_nch.py @@ -0,0 +1,27 @@ +# init +def init(): + pass + +# destroy +def destroy(): + pass + +def process(block): + (nrows, ncols) = block.shape() + results = [] + for i in range(nrows): + row = [] + for j in range(ncols): + val = block.data(i, j) + if val is None: + row = None + break + row.append(val.decode('utf_32_le')) + if row is None: + results.append(None) + else: + row_str = ''.join(row) + results.append(row_str.encode('utf_32_le')) + return results + + diff --git a/tests/system-test/0-others/udfpy/sf_concat_var.py b/tests/system-test/0-others/udfpy/sf_concat_var.py new file mode 100644 index 0000000000000000000000000000000000000000..fc8292c718d5c8def7cebc87ee7938b2c7bd3849 --- /dev/null +++ b/tests/system-test/0-others/udfpy/sf_concat_var.py @@ -0,0 +1,26 @@ +# init +def init(): + pass + +# destroy +def destroy(): + pass + +def process(block): + (nrows, ncols) = block.shape() + results = [] + for i in range(nrows): + row = [] + for j in range(ncols): + val = block.data(i, j) + if val is None: + row = None + break + row.append(val.decode('utf-8')) + if row is None: + results.append(None) + else: + results.append(''.join(row)) + return results + + diff --git a/tests/system-test/0-others/udfpy/sf_multi_args.py b/tests/system-test/0-others/udfpy/sf_multi_args.py new file mode 100644 index 0000000000000000000000000000000000000000..1026661d8d127eeb52b6b79f9b81dd29ccc24ba5 --- /dev/null +++ b/tests/system-test/0-others/udfpy/sf_multi_args.py @@ -0,0 +1,23 @@ +# init +def init(): + pass + +# destroy +def destroy(): + pass + +# return origin column one value +def process(block): + (nrows, ncols) = block.shape() + results = [] + for i in range(nrows): + rows = [] + for j in range(ncols): + val = block.data(i, j) + if type(val) is bytes: + rows.append(val.decode('utf-8')) + else: + rows.append(repr(val)) + results.append(','.join(rows)) + return results + diff --git a/tests/system-test/0-others/udfpy/sf_null.py b/tests/system-test/0-others/udfpy/sf_null.py new file mode 100644 index 0000000000000000000000000000000000000000..c22ca95b19f93d2d494a4890154923626a6a445a --- /dev/null +++ b/tests/system-test/0-others/udfpy/sf_null.py @@ -0,0 +1,16 @@ + +# init +def init(): + pass + +# destroy +def destroy(): + pass + +# return origin column one value +def process(block): + (rows, cols) = block.shape() + results = [] + for i in range(rows): + results.append(None) + return results \ No newline at end of file diff --git a/tests/system-test/0-others/udfpy/sf_origin.py b/tests/system-test/0-others/udfpy/sf_origin.py new file mode 100644 index 0000000000000000000000000000000000000000..9158e044d2defb118683f56b889bf95bb7d04ee6 --- /dev/null +++ b/tests/system-test/0-others/udfpy/sf_origin.py @@ -0,0 +1,15 @@ +# init +def init(): + pass + +# destroy +def destroy(): + pass + +# return origin column one value +def process(block): + (rows, cols) = block.shape() + results = [] + for i in range(rows): + results.append(block.data(i,0)) + return results diff --git a/tests/system-test/0-others/udfpy_main.py b/tests/system-test/0-others/udfpy_main.py new file mode 100644 index 0000000000000000000000000000000000000000..916b032edbde72a4ddc011608b924f95bb035c58 --- /dev/null +++ b/tests/system-test/0-others/udfpy_main.py @@ -0,0 +1,464 @@ +################################################################### +# 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 * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import * + +import random +import os +import subprocess + + +class PerfDB: + def __init__(self): + self.sqls = [] + self.spends = [] + + # execute + def execute(self, sql): + print(f" perfdb execute {sql}") + stime = time.time() + ret = tdSql.execute(sql, 1) + spend = time.time() - stime + + self.sqls.append(sql) + self.spends.append(spend) + return ret + + # query + def query(self, sql): + print(f" perfdb query {sql}") + start = time.time() + ret = tdSql.query(sql, None, 1) + spend = time.time() - start + self.sqls.append(sql) + self.spends.append(spend) + return ret + + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + self.setsql = TDSetSql() + + # udf path + self.udf_path = os.path.dirname(os.path.realpath(__file__)) + "/udfpy" + + + self.column_dict = { + 'ts': 'timestamp', + 'col1': 'tinyint', + 'col2': 'smallint', + 'col3': 'int', + 'col4': 'bigint', + 'col5': 'tinyint unsigned', + 'col6': 'smallint unsigned', + 'col7': 'int unsigned', + 'col8': 'bigint unsigned', + 'col9': 'float', + 'col10': 'double', + 'col11': 'bool', + 'col12': 'varchar(120)', + 'col13': 'nchar(100)', + } + self.tag_dict = { + 't1': 'tinyint', + 't2': 'smallint', + 't3': 'int', + 't4': 'bigint', + 't5': 'tinyint unsigned', + 't6': 'smallint unsigned', + 't7': 'int unsigned', + 't8': 'bigint unsigned', + 't9': 'float', + 't10': 'double', + 't11': 'bool', + 't12': 'varchar(120)', + 't13': 'nchar(100)', + } + + def set_stb_sql(self,stbname,column_dict,tag_dict): + column_sql = '' + tag_sql = '' + for k,v in column_dict.items(): + column_sql += f"{k} {v}, " + for k,v in tag_dict.items(): + tag_sql += f"{k} {v}, " + create_stb_sql = f'create stable {stbname} ({column_sql[:-2]}) tags ({tag_sql[:-2]})' + return create_stb_sql + + # create stable and child tables + def create_table(self, stbname, tbname, count): + tdSql.execute("create database db wal_retention_period 4") + tdSql.execute('use db') + self.child_count = count + self.stbname = stbname + self.tbname = tbname + + # create stable + create_table_sql = self.set_stb_sql(stbname, self.column_dict, self.tag_dict) + tdSql.execute(create_table_sql) + + batch_size = 1000 + # create child table + for i in range(count): + ti = i % 128 + tags = f'{ti},{ti},{i},{i},{ti},{ti},{i},{i},{i}.000{i},{i}.000{i},true,"var{i}","nch{i}"' + sql = f'create table {tbname}{i} using {stbname} tags({tags});' + tdSql.execute(sql) + if i % batch_size == 0: + tdLog.info(f" create child table {i} ...") + + tdLog.info(f" create {count} child tables ok.") + + # create with dicts + def create_sf_dicts(self, dicts, filename): + for fun_name, out_type in dicts.items(): + sql = f' create function {fun_name} as "{self.udf_path}/{filename}" outputtype {out_type} language "Python" ' + tdSql.execute(sql) + tdLog.info(sql) + + # create_udfpy_function + def create_scalar_udfpy(self): + # scalar funciton + self.scalar_funs = { + 'sf0': 'timestamp', + 'sf1': 'tinyint', + 'sf2': 'smallint', + 'sf3': 'int', + 'sf4': 'bigint', + 'sf5': 'tinyint unsigned', + 'sf6': 'smallint unsigned', + 'sf7': 'int unsigned', + 'sf8': 'bigint unsigned', + 'sf9': 'float', + 'sf10': 'double', + 'sf11': 'bool', + 'sf12': 'varchar(120)', + 'sf13': 'nchar(100)' + } + # agg function + self.agg_funs = { + 'af1': 'tinyint', + 'af2': 'smallint', + 'af3': 'int', + 'af4': 'bigint', + 'af5': 'tinyint unsigned', + 'af6': 'smallint unsigned', + 'af7': 'int unsigned', + 'af8': 'bigint unsigned', + 'af9': 'float', + 'af10': 'double', + 'af11': 'bool', + 'af12': 'varchar(120)', + 'af13': 'nchar(100)', + 'af14': 'timestamp' + } + + # multi_args + self.create_sf_dicts(self.scalar_funs, "sf_origin.py") + fun_name = "sf_multi_args" + self.create_udf_sf(fun_name, f'{fun_name}.py', "binary(1024)") + + # all type check null + for col_name, col_type in self.column_dict.items(): + self.create_udf_sf(f"sf_null_{col_name}", "sf_null.py", col_type) + + # concat + fun_name = "sf_concat_var" + self.create_udf_sf(fun_name, f'{fun_name}.py', "varchar(1024)") + fun_name = "sf_concat_nch" + self.create_udf_sf(fun_name, f'{fun_name}.py', "nchar(1024)") + + + # fun_name == fun_name.py + def create_udf_sf(self, fun_name, file_name, out_type): + sql = f'create function {fun_name} as "{self.udf_path}/{file_name}" outputtype {out_type} language "Python" ' + tdSql.execute(sql) + tdLog.info(sql) + + def create_udf_af(self, fun_name, file_name, out_type, bufsize): + sql = f'create aggregate function {fun_name} as "{self.udf_path}/{file_name}" outputtype {out_type} bufsize {bufsize} language "Python" ' + tdSql.execute(sql) + tdLog.info(sql) + + + # sql1 query result eual with sql2 + def verify_same_result(self, sql1, sql2): + # query + result1 = tdSql.getResult(sql1) + tdSql.query(sql2) + + for i, row in enumerate(result1): + for j , val in enumerate(row): + tdSql.checkData(i, j, result1[i][j]) + + # same value like select col1, udf_fun1(col1) from st + def verify_same_value(self, sql, col=0): + tdSql.query(sql) + nrows = tdSql.getRows() + for i in range(nrows): + val = tdSql.getData(i, col) + tdSql.checkData(i, col + 1, val) + + # verify multi values + def verify_same_multi_values(self, sql): + tdSql.query(sql) + nrows = tdSql.getRows() + for i in range(nrows): + udf_val = tdSql.getData(i, 0) + vals = udf_val.split(',') + for j,val in enumerate(vals, 1): + tdSql.checkData(i, j, val) + + # query multi-args + def query_multi_args(self): + cols = list(self.column_dict.keys()) + list(self.tag_dict.keys()) + cols.remove("col13") + cols.remove("t13") + cols.remove("ts") + ncols = len(cols) + print(cols) + for i in range(2, ncols): + sample = random.sample(cols, i) + print(sample) + cols_name = ','.join(sample) + sql = f'select sf_multi_args({cols_name}),{cols_name} from {self.stbname} limit 10' + self.verify_same_multi_values(sql) + tdLog.info(sql) + + + # query_udfpy + def query_scalar_udfpy(self): + # col + for col_name, col_type in self.column_dict.items(): + for fun_name, out_type in self.scalar_funs.items(): + if col_type == out_type : + sql = f'select {col_name}, {fun_name}({col_name}) from {self.stbname} limit 10' + tdLog.info(sql) + self.verify_same_value(sql) + sql = f'select * from (select {col_name} as a, {fun_name}({col_name}) as b from {self.stbname} limit 100) order by b,a desc' + tdLog.info(sql) + self.verify_same_value(sql) + + # multi-args + self.query_multi_args() + + # all type check null + for col_name, col_type in self.column_dict.items(): + fun_name = f"sf_null_{col_name}" + sql = f'select {fun_name}({col_name}) from {self.stbname}' + tdSql.query(sql) + if col_type != "timestamp": + tdSql.checkData(0, 0, "None") + else: + val = tdSql.getData(0, 0) + if val is not None: + tdLog.exit(f" check {sql} not expect None.") + + # concat + sql = f'select sf_concat_var(col12, t12), concat(col12, t12) from {self.stbname} limit 1000' + self.verify_same_value(sql) + sql = f'select sf_concat_nch(col13, t13), concat(col13, t13) from {self.stbname} limit 1000' + self.verify_same_value(sql) + + # create aggregate + def create_aggr_udfpy(self): + + bufsize = 200 * 1024 + # all type check null + for col_name, col_type in self.column_dict.items(): + self.create_udf_af(f"af_null_{col_name}", "af_null.py", col_type, bufsize) + + # min + file_name = "af_min.py" + fun_name = "af_min_float" + self.create_udf_af(fun_name, file_name, f"float", bufsize) + fun_name = "af_min_int" + self.create_udf_af(fun_name, file_name, f"int", bufsize) + + # sum + file_name = "af_sum.py" + fun_name = "af_sum_float" + self.create_udf_af(fun_name, file_name, f"float", bufsize) + fun_name = "af_sum_int" + self.create_udf_af(fun_name, file_name, f"int", bufsize) + fun_name = "af_sum_bigint" + self.create_udf_af(fun_name, file_name, f"bigint", bufsize) + + # count + file_name = "af_count.py" + fun_name = "af_count_float" + self.create_udf_af(fun_name, file_name, f"float", bufsize) + fun_name = "af_count_int" + self.create_udf_af(fun_name, file_name, f"int", bufsize) + fun_name = "af_count_bigint" + self.create_udf_af(fun_name, file_name, f"bigint", bufsize) + + + # query aggregate + def query_aggr_udfpy(self) : + # all type check null + for col_name, col_type in self.column_dict.items(): + fun_name = f"af_null_{col_name}" + sql = f'select {fun_name}({col_name}) from {self.stbname}' + tdSql.query(sql) + if col_type != "timestamp": + tdSql.checkData(0, 0, "None") + else: + val = tdSql.getData(0, 0) + if val is not None: + tdLog.exit(f" check {sql} not expect None.") + + # min + sql = f'select min(col3), af_min_int(col3) from {self.stbname}' + self.verify_same_value(sql) + sql = f'select min(col7), af_min_int(col7) from {self.stbname}' + self.verify_same_value(sql) + sql = f'select min(col9), af_min_float(col9) from {self.stbname}' + self.verify_same_value(sql) + + # sum + sql = f'select sum(col1), af_sum_int(col1) from d0' + self.verify_same_value(sql) + sql = f'select sum(col3), af_sum_bigint(col3) from {self.stbname}' + self.verify_same_value(sql) + sql = f'select sum(col9), af_sum_float(col9) from {self.stbname}' + self.verify_same_value(sql) + + # count + sql = f'select count(col1), af_count_int(col1) from {self.stbname}' + self.verify_same_value(sql) + sql = f'select count(col7), af_count_bigint(col7) from {self.stbname}' + self.verify_same_value(sql) + sql = f'select count(col8), af_count_float(col8) from {self.stbname}' + self.verify_same_value(sql) + + # nest + sql = f'select a+1000,b+1000 from (select count(col8) as a, af_count_float(col8) as b from {self.stbname})' + self.verify_same_value(sql) + # group by + sql = f'select a+1000,b+1000 from (select count(col8) as a, af_count_float(col8) as b from {self.stbname} group by tbname)' + self.verify_same_value(sql) + # two filed expr + sql = f'select sum(col1+col2),af_sum_float(col1+col2) from {self.stbname};' + self.verify_same_value(sql) + # interval + sql = f'select af_sum_float(col2+col3),sum(col3+col2) from {self.stbname} interval(1s)' + self.verify_same_value(sql) + + + # insert to child table d1 data + def insert_data(self, tbname, rows): + ts = 1670000000000 + values = "" + batch_size = 500 + child_name = "" + for i in range(self.child_count): + for j in range(rows): + tj = j % 128 + cols = f'{tj},{tj},{j},{j},{tj},{tj},{j},{j},{j}.000{j},{j}.000{j},true,"var{j}","nch{j}涛思数据codepage is utf_32_le"' + value = f'({ts+j},{cols})' + if values == "": + values = value + else: + values += f",{value}" + if j % batch_size == 0 or j + 1 == rows: + sql = f'insert into {tbname}{i} values {values};' + tdSql.execute(sql) + tdLog.info(f" child table={i} rows={j} insert data.") + values = "" + + # partial columns upate + sql = f'insert into {tbname}0(ts, col1, col9, col11) values(now, 100, 200, 0)' + tdSql.execute(sql) + sql = f'insert into {tbname}0(ts, col2, col5, col8) values(now, 100, 200, 300)' + tdSql.execute(sql) + sql = f'insert into {tbname}0(ts, col3, col7, col13) values(now, null, null, null)' + tdSql.execute(sql) + sql = f'insert into {tbname}0(ts) values(now)' + tdSql.execute(sql) + tdLog.info(f" insert {rows} to child table {self.child_count} .") + + + # create stream + def create_stream(self): + sql = f"create stream ma into sta subtable(concat('sta_',tbname)) \ + as select _wstart,count(col1),af_count_bigint(col1) from {self.stbname} partition by tbname interval(1s);" + tdSql.execute(sql) + tdLog.info(sql) + + # query stream + def verify_stream(self): + sql = f"select * from sta limit 10" + self.verify_same_value(sql, 1) + + # create tmq + def create_tmq(self): + sql = f"create topic topa as select concat(col12,t12),sf_concat_var(col12,t12) from {self.stbname};" + tdSql.execute(sql) + tdLog.info(sql) + + def install_taospy(self): + tdLog.info("install taospyudf...") + packs = ["taospyudf"] + for pack in packs: + subprocess.check_call([sys.executable, '-m', 'pip', 'install', '-i', 'https://pypi.org/simple', '-U', pack]) + tdLog.info("call ldconfig...") + os.system("ldconfig") + tdLog.info("install taospyudf successfully.") + + # run + def run(self): + self.install_taospy() + + # var + stable = "meters" + tbname = "d" + count = 10 + rows = 5000 + # do + self.create_table(stable, tbname, count) + + # create + self.create_scalar_udfpy() + self.create_aggr_udfpy() + + # create stream + self.create_stream() + + # create tmq + self.create_tmq() + + # insert data + self.insert_data(tbname, rows) + + # query + self.query_scalar_udfpy() + self.query_aggr_udfpy() + + # show performance + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/0-others/user_control.py b/tests/system-test/0-others/user_control.py index d27892b588a832ff1edeb581b1975e9771510383..7b5578ba45f66bd3a993f0ce2ee666dcf802d3b3 100644 --- a/tests/system-test/0-others/user_control.py +++ b/tests/system-test/0-others/user_control.py @@ -444,7 +444,7 @@ class TDTestCase: self.__grant_user_privileges(privilege="", dbname="db", user_name=self.__user_list[0]) , self.__grant_user_privileges(privilege=" ".join(self.__privilege), user_name=self.__user_list[0]) , f"GRANT {self.__privilege[0]} ON * TO {self.__user_list[0]}" , - f"GRANT {self.__privilege[0]} ON {DBNAME}.{NTBNAME} TO {self.__user_list[0]}" , + # f"GRANT {self.__privilege[0]} ON {DBNAME}.{NTBNAME} TO {self.__user_list[0]}" , ] def __revoke_err(self): @@ -456,7 +456,7 @@ class TDTestCase: self.__revoke_user_privileges(privilege="", dbname="db", user_name=self.__user_list[0]) , self.__revoke_user_privileges(privilege=" ".join(self.__privilege), user_name=self.__user_list[0]) , f"REVOKE {self.__privilege[0]} ON * FROM {self.__user_list[0]}" , - f"REVOKE {self.__privilege[0]} ON {DBNAME}.{NTBNAME} FROM {self.__user_list[0]}" , + # f"REVOKE {self.__privilege[0]} ON {DBNAME}.{NTBNAME} FROM {self.__user_list[0]}" , ] def test_grant_err(self): diff --git a/tests/system-test/0-others/user_manage.py b/tests/system-test/0-others/user_manage.py index 5148e26b396355389a605b42058ddcbdb8524bb2..1e33d4bb1c628bd43569b68d8f7fc07e68f2bec8 100644 --- a/tests/system-test/0-others/user_manage.py +++ b/tests/system-test/0-others/user_manage.py @@ -12,12 +12,13 @@ # -*- coding: utf-8 -*- import taos -from util.log import * +from taos.tmq import * from util.cases import * -from util.sql import * from util.common import * +from util.log import * +from util.sql import * from util.sqlset import * -from taos.tmq import * + class TDTestCase: def init(self, conn, logSql, replicaVar=1): @@ -26,10 +27,10 @@ class TDTestCase: tdSql.init(conn.cursor()) self.setsql = TDSetSql() self.stbname = 'stb' - self.binary_length = 20 # the length of binary for column_dict + self.binary_length = 20 # the length of binary for column_dict self.nchar_length = 20 # the length of nchar for column_dict self.column_dict = { - 'ts' : 'timestamp', + 'ts': 'timestamp', 'col1': 'tinyint', 'col2': 'smallint', 'col3': 'int', @@ -45,7 +46,7 @@ class TDTestCase: 'col13': f'nchar({self.nchar_length})' } self.tag_dict = { - 'ts_tag' : 'timestamp', + 'ts_tag': 'timestamp', 't1': 'tinyint', 't2': 'smallint', 't3': 'int', @@ -67,25 +68,28 @@ class TDTestCase: f'now,1,2,3,4,5,6,7,8,9.9,10.1,true,"abcd","涛思数据"' ] self.tbnum = 1 + def prepare_data(self): - tdSql.execute(self.setsql.set_create_stable_sql(self.stbname,self.column_dict,self.tag_dict)) + tdSql.execute(self.setsql.set_create_stable_sql(self.stbname, self.column_dict, self.tag_dict)) for i in range(self.tbnum): tdSql.execute(f'create table {self.stbname}_{i} using {self.stbname} tags({self.tag_list[i]})') for j in self.values_list: tdSql.execute(f'insert into {self.stbname}_{i} values({j})') + def create_user(self): - for user_name in ['jiacy1_all','jiacy1_read','jiacy1_write','jiacy1_none','jiacy0_all','jiacy0_read','jiacy0_write','jiacy0_none']: + for user_name in ['jiacy1_all', 'jiacy1_read', 'jiacy1_write', 'jiacy1_none', 'jiacy0_all', 'jiacy0_read', + 'jiacy0_write', 'jiacy0_none']: if 'jiacy1' in user_name.lower(): tdSql.execute(f'create user {user_name} pass "123" sysinfo 1') elif 'jiacy0' in user_name.lower(): tdSql.execute(f'create user {user_name} pass "123" sysinfo 0') - for user_name in ['jiacy1_all','jiacy1_read','jiacy0_all','jiacy0_read']: + for user_name in ['jiacy1_all', 'jiacy1_read', 'jiacy0_all', 'jiacy0_read']: tdSql.execute(f'grant read on db to {user_name}') - for user_name in ['jiacy1_all','jiacy1_write','jiacy0_all','jiacy0_write']: + for user_name in ['jiacy1_all', 'jiacy1_write', 'jiacy0_all', 'jiacy0_write']: tdSql.execute(f'grant write on db to {user_name}') def user_privilege_check(self): - jiacy1_read_conn = taos.connect(user='jiacy1_read',password='123') + jiacy1_read_conn = taos.connect(user='jiacy1_read', password='123') sql = "create table ntb (ts timestamp,c0 int)" expectErrNotOccured = True try: @@ -94,32 +98,35 @@ class TDTestCase: expectErrNotOccured = False if expectErrNotOccured: caller = inspect.getframeinfo(inspect.stack()[1][0]) - tdLog.exit(f"{caller.filename}({caller.lineno}) failed: sql:{sql}, expect error not occured" ) + tdLog.exit(f"{caller.filename}({caller.lineno}) failed: sql:{sql}, expect error not occured") else: self.queryRows = 0 self.queryCols = 0 self.queryResult = None tdLog.info(f"sql:{sql}, expect error occured") pass + def drop_topic(self): - jiacy1_all_conn = taos.connect(user='jiacy1_all',password='123') - jiacy1_read_conn = taos.connect(user='jiacy1_read',password='123') - jiacy1_write_conn = taos.connect(user='jiacy1_write',password='123') - jiacy1_none_conn = taos.connect(user='jiacy1_none',password='123') - jiacy0_all_conn = taos.connect(user='jiacy0_all',password='123') - jiacy0_read_conn = taos.connect(user='jiacy0_read',password='123') - jiacy0_write_conn = taos.connect(user='jiacy0_write',password='123') - jiacy0_none_conn = taos.connect(user='jiacy0_none',password='123') + jiacy1_all_conn = taos.connect(user='jiacy1_all', password='123') + jiacy1_read_conn = taos.connect(user='jiacy1_read', password='123') + jiacy1_write_conn = taos.connect(user='jiacy1_write', password='123') + jiacy1_none_conn = taos.connect(user='jiacy1_none', password='123') + jiacy0_all_conn = taos.connect(user='jiacy0_all', password='123') + jiacy0_read_conn = taos.connect(user='jiacy0_read', password='123') + jiacy0_write_conn = taos.connect(user='jiacy0_write', password='123') + jiacy0_none_conn = taos.connect(user='jiacy0_none', password='123') + tdSql.execute('alter database db wal_retention_period 3600') tdSql.execute('create topic root_db as select * from db.stb') - for user in [jiacy1_all_conn,jiacy1_read_conn,jiacy0_all_conn,jiacy0_read_conn]: + for user in [jiacy1_all_conn, jiacy1_read_conn, jiacy0_all_conn, jiacy0_read_conn]: user.execute(f'create topic db_jiacy as select * from db.stb') user.execute('drop topic db_jiacy') - for user in [jiacy1_write_conn,jiacy1_none_conn,jiacy0_write_conn,jiacy0_none_conn,jiacy1_all_conn,jiacy1_read_conn,jiacy0_all_conn,jiacy0_read_conn]: + for user in [jiacy1_write_conn, jiacy1_none_conn, jiacy0_write_conn, jiacy0_none_conn, jiacy1_all_conn, + jiacy1_read_conn, jiacy0_all_conn, jiacy0_read_conn]: sql_list = [] - if user in [jiacy1_all_conn,jiacy1_read_conn,jiacy0_all_conn,jiacy0_read_conn]: + if user in [jiacy1_all_conn, jiacy1_read_conn, jiacy0_all_conn, jiacy0_read_conn]: sql_list = ['drop topic root_db'] - elif user in [jiacy1_write_conn,jiacy1_none_conn,jiacy0_write_conn,jiacy0_none_conn]: - sql_list = ['drop topic root_db','create topic db_jiacy as select * from db.stb'] + elif user in [jiacy1_write_conn, jiacy1_none_conn, jiacy0_write_conn, jiacy0_none_conn]: + sql_list = ['drop topic root_db', 'create topic db_jiacy as select * from db.stb'] for sql in sql_list: expectErrNotOccured = True try: @@ -128,33 +135,26 @@ class TDTestCase: expectErrNotOccured = False if expectErrNotOccured: caller = inspect.getframeinfo(inspect.stack()[1][0]) - tdLog.exit(f"{caller.filename}({caller.lineno}) failed: sql:{sql}, expect error not occured" ) + tdLog.exit(f"{caller.filename}({caller.lineno}) failed: sql:{sql}, expect error not occured") else: self.queryRows = 0 self.queryCols = 0 self.queryResult = None tdLog.info(f"sql:{sql}, expect error occured") + def tmq_commit_cb_print(tmq, resp, param=None): print(f"commit: {resp}, tmq: {tmq}, param: {param}") + def subscribe_topic(self): print("create topic") tdSql.execute('create topic db_topic as select * from db.stb') tdSql.execute('grant subscribe on db_topic to jiacy1_all') print("build consumer") - conf = TaosTmqConf() - conf.set("group.id", "tg2") - conf.set("td.connect.user", "jiacy1_all") - conf.set("td.connect.pass", "123") - conf.set("enable.auto.commit", "true") - conf.set_auto_commit_cb(self.tmq_commit_cb_print, None) - tmq = conf.new_consumer() + tmq = Consumer({"group.id": "tg2", "td.connect.user": "jiacy1_all", "td.connect.pass": "123", + "enable.auto.commit": "true"}) print("build topic list") - topic_list = TaosTmqList() - topic_list.append("db_topic") + tmq.subscribe(["db_topic"]) print("basic consume loop") - tmq.subscribe(topic_list) - sub_list = tmq.subscription() - print("subscribed topics: ", sub_list) c = 0 l = 0 for i in range(10): @@ -163,20 +163,23 @@ class TDTestCase: res = tmq.poll(10) print(f"loop {l}") l += 1 - if res: - c += 1 - topic = res.get_topic_name() - vg = res.get_vgroup_id() - db = res.get_db_name() - print(f"topic: {topic}\nvgroup id: {vg}\ndb: {db}") - for row in res: - print(row) - print("* committed") - tmq.commit(res) - else: + if not res: print(f"received empty message at loop {l} (committed {c})") - pass - + continue + if res.error(): + print(f"consumer error at loop {l} (committed {c}) {res.error()}") + continue + + c += 1 + topic = res.topic() + db = res.database() + print(f"topic: {topic}\ndb: {db}") + + for row in res: + print(row.fetchall()) + print("* committed") + tmq.commit(res) + def run(self): tdSql.prepare() self.create_user() @@ -184,9 +187,11 @@ class TDTestCase: self.drop_topic() self.user_privilege_check() self.subscribe_topic() + 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 +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/0-others/user_privilege.py b/tests/system-test/0-others/user_privilege.py new file mode 100644 index 0000000000000000000000000000000000000000..d1b93f6942a548aab79dc0e3da69d5e38ea4bd42 --- /dev/null +++ b/tests/system-test/0-others/user_privilege.py @@ -0,0 +1,144 @@ +################################################################### +# 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 taos +from taos.tmq import * +from util.cases import * +from util.common import * +from util.log import * +from util.sql import * +from util.sqlset import * + + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + self.setsql = TDSetSql() + self.stbname = 'stb' + self.binary_length = 20 # the length of binary for column_dict + self.nchar_length = 20 # the length of nchar for column_dict + self.dbnames = ['db1', 'db2'] + self.column_dict = { + 'ts': 'timestamp', + 'col1': 'float', + 'col2': 'int', + 'col3': 'float', + } + + self.tag_dict = { + 't1': 'int', + 't2': f'binary({self.binary_length})' + } + + self.tag_list = [ + f'1, "Beijing"', + f'2, "Shanghai"', + f'3, "Guangzhou"', + f'4, "Shenzhen"' + ] + + self.values_list = [ + f'now, 9.1, 200, 0.3' + ] + + self.tbnum = 4 + + def create_user(self): + user_name = 'test' + tdSql.execute(f'create user {user_name} pass "test"') + tdSql.execute(f'grant read on {self.dbnames[0]}.{self.stbname} with t2 = "Beijing" to {user_name}') + tdSql.execute(f'grant write on {self.dbnames[1]}.{self.stbname} with t1 = 2 to {user_name}') + + def prepare_data(self): + for db in self.dbnames: + tdSql.execute(f"create database {db}") + tdSql.execute(f"use {db}") + tdSql.execute(self.setsql.set_create_stable_sql(self.stbname, self.column_dict, self.tag_dict)) + for i in range(self.tbnum): + tdSql.execute(f'create table {self.stbname}_{i} using {self.stbname} tags({self.tag_list[i]})') + for j in self.values_list: + tdSql.execute(f'insert into {self.stbname}_{i} values({j})') + + def user_read_privilege_check(self, dbname): + testconn = taos.connect(user='test', password='test') + expectErrNotOccured = False + + try: + sql = f"select count(*) from {dbname}.stb where t2 = 'Beijing'" + res = testconn.query(sql) + data = res.fetch_all() + count = data[0][0] + except BaseException: + expectErrNotOccured = True + + if expectErrNotOccured: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + tdLog.exit(f"{caller.filename}({caller.lineno}) failed: sql:{sql}, expect error not occured") + elif count != 1: + tdLog.exit(f"{sql}, expect result doesn't match") + pass + + def user_write_privilege_check(self, dbname): + testconn = taos.connect(user='test', password='test') + expectErrNotOccured = False + + try: + sql = f"insert into {dbname}.stb_1 values(now, 1.1, 200, 0.3)" + testconn.execute(sql) + except BaseException: + expectErrNotOccured = True + + if expectErrNotOccured: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + tdLog.exit(f"{caller.filename}({caller.lineno}) failed: sql:{sql}, expect error not occured") + else: + pass + + def user_privilege_error_check(self): + testconn = taos.connect(user='test', password='test') + expectErrNotOccured = False + + sql_list = [f"alter talbe {self.dbnames[0]}.stb_1 set t2 = 'Wuhan'", + f"insert into {self.dbnames[0]}.stb_1 values(now, 1.1, 200, 0.3)", + f"drop table {self.dbnames[0]}.stb_1", + f"select count(*) from {self.dbnames[1]}.stb"] + + for sql in sql_list: + try: + res = testconn.execute(sql) + except BaseException: + expectErrNotOccured = True + + if expectErrNotOccured: + pass + else: + caller = inspect.getframeinfo(inspect.stack()[1][0]) + tdLog.exit(f"{caller.filename}({caller.lineno}) failed: sql:{sql}, expect error not occured") + pass + + def run(self): + self.prepare_data() + self.create_user() + self.user_read_privilege_check(self.dbnames[0]) + self.user_write_privilege_check(self.dbnames[1]) + self.user_privilege_error_check() + + 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/system-test/0-others/walFileIdex.py b/tests/system-test/0-others/walFileIdex.py index cd34c7e5e30315df92b0f0aa4c0dda7c460b450a..f8309519cd77a63d863105a8a1cd2227021a4ff4 100644 --- a/tests/system-test/0-others/walFileIdex.py +++ b/tests/system-test/0-others/walFileIdex.py @@ -58,7 +58,7 @@ class TDTestCase: #stream tdSql.execute("drop database if exists source_db;") - tdSql.query("create database source_db vgroups 3;") + tdSql.query("create database source_db vgroups 3 wal_retention_period 3600;") tdSql.query("use source_db") tdSql.query("create table if not exists source_db.stb (ts timestamp, k int) tags (a int);") tdSql.query("create table source_db.ct1 using source_db.stb tags(1000);create table source_db.ct2 using source_db.stb tags(2000);create table source_db.ct3 using source_db.stb tags(3000);") diff --git a/tests/system-test/0-others/walRetention.py b/tests/system-test/0-others/walRetention.py new file mode 100644 index 0000000000000000000000000000000000000000..2b340b79697f874a1e300970fac74f90529f0cc9 --- /dev/null +++ b/tests/system-test/0-others/walRetention.py @@ -0,0 +1,472 @@ +################################################################### +# 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 -*- + +# +# The option for wal_retetion_period and wal_retention_size is work well +# + +import taos +from taos.tmq import Consumer + +from util.log import * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import * + + +import os +import threading +import json +import time +from datetime import date +from datetime import datetime +from datetime import timedelta +from os import path + + +# +# -------------- util -------------------------- +# +def pathSize(path): + + total_size = 0 + for dirpath, dirnames, filenames in os.walk(path): + for i in filenames: + # use join to concatenate all the components of path + f = os.path.join(dirpath, i) + # use getsize to generate size in bytes and add it to the total size + total_size += os.path.getsize(f) + # print(dirpath) + + print(" %s %.02f MB" % (path, total_size/1024/1024)) + return total_size + + +# load json from file +def jsonFromFile(jsonFile): + fp = open(jsonFile) + return json.load(fp) + + +# +# ----------------- class ------------------ +# + +# wal file object +class WalFile: + def __init__(self, pathFile, fileName): + self.mtime = os.path.getmtime(pathFile) + self.startVer = int(fileName) + self.fsize = os.path.getsize(pathFile) + self.endVer = -1 + self.pathFile = pathFile + + def needDelete(self, delTsLine): + return True + +# VNode object +class VNode : + # init + def __init__(self, dnodeId, path, walPeriod, walSize, walStayRange): + self.path = path + self.dnodeId = dnodeId + self.vgId = 0 + self.snapVer = 0 + self.firstVer = 0 + self.lastVer = -1 + self.walPeriod = walPeriod + self.walSize = walSize + self.walStayRange = walStayRange + self.walFiles = [] + self.load(path) + + # load + def load(self, path): + # load wal + walPath = os.path.join(path, "wal") + metaFile = "" + with os.scandir(walPath) as items: + for item in items: + if item.is_file(): + fileName, fileExt = os.path.splitext(item.name) + pathFile = os.path.join(walPath, item) + if fileExt == ".log": + self.walFiles.append(WalFile(pathFile, fileName)) + elif fileExt == "": + if fileName[:8] == "meta-ver": + metaFile = pathFile + # load config + tdLog.info(f' meta-ver file={metaFile}') + if metaFile != "": + jsonVer = jsonFromFile(metaFile) + metaNode = jsonVer["meta"] + self.snapVer = int(metaNode["snapshotVer"]) + self.firstVer = int(metaNode["firstVer"]) + self.lastVer = int(metaNode["lastVer"]) + + # sort with startVer + self.walFiles = sorted(self.walFiles, key=lambda x : x.startVer, reverse=True) + # set endVer + startVer = -1 + for walFile in self.walFiles: + if startVer == -1: + startVer = walFile.startVer + continue + walFile.endVer = startVer - 1 + startVer = walFile.startVer + + # print total + tdLog.info(f" ---- dnode{self.dnodeId} snapVer={self.snapVer} firstVer={self.firstVer} lastVer={self.lastVer} {self.path} --------") + for walFile in self.walFiles: + mt = datetime.fromtimestamp(walFile.mtime) + tdLog.info(f" {walFile.pathFile} {mt} startVer={walFile.startVer} endVer={walFile.endVer}") + + # snapVer compare + def canDelete(self, walFile): + if walFile.endVer == -1: + # end file + return False + + # check snapVer + ret = False + if self.snapVer > walFile.endVer: + ret = True + + # check stayRange + if self.lastVer != -1 and ret: + # first wal file ignore + if walFile.startVer == self.firstVer: + tdLog.info(f" {walFile.pathFile} can del, but is first. snapVer={self.snapVer} firstVer={self.firstVer}") + return False + + # ver in stay range + smallVer = self.snapVer - self.walStayRange -1 + if walFile.startVer >= smallVer: + tdLog.info(f" {walFile.pathFile} can del, but range not arrived. snapVer={self.snapVer} smallVer={smallVer}") + return False + + return ret + + # get log size + def getWalsSize(self): + size = 0 + for walFile in self.walFiles: + size += walFile.fsize + + return size + + # vnode + def check_retention(self): + # + # check period + # + delta = self.walPeriod + if self.walPeriod == 0: + delta += 1 * 60 # delete after 1 minutes + elif self.walPeriod < 3600: + delta += 3 * 60 # 5 minutes + else: + delta += 5 * 60 # 10 minutes + + delTsLine = datetime.now() - timedelta(seconds = delta) + delTs = delTsLine.timestamp() + for walFile in self.walFiles: + mt = datetime.fromtimestamp(walFile.mtime) + info = f" {walFile.pathFile} mt={mt} line={delTsLine} start={walFile.startVer} snap={self.snapVer} end= {walFile.endVer}" + tdLog.info(info) + if walFile.mtime < delTs and self.canDelete(walFile): + # wait a moment then check file exist + time.sleep(1) + if os.path.exists(walFile.pathFile): + #report error + tdLog.exit(f" wal file expired need delete. \n {walFile.pathFile} \n modify time={mt} \n delTsLine={delTsLine}\n start={walFile.startVer} snap={self.snapVer} end= {walFile.endVer}") + return False + + # + # check size + # + if self.walSize == 0: + return True + + vnodeSize = self.getWalsSize() + if vnodeSize < self.walSize: + tdLog.info(f" wal size valid. {self.path} real = {vnodeSize} set = {self.walSize} ") + return True + + # check valid + tdLog.info(f" wal size over set. {self.path} real = {vnodeSize} set = {self.walSize} ") + for walFile in self.walFiles: + if self.canDelete(walFile): + # wait a moment then check file exist + time.sleep(1) + if os.path.exists(walFile.pathFile): + tdLog.exit(f" wal file size over .\ + \n wal file = {walFile.pathFile}\ + \n snapVer = {self.snapVer}\ + \n real = {vnodeSize} bytes\ + \n set = {self.walSize} bytes") + return False + return True + + +# insert by async +def thread_insert(testCase, tbname, rows): + print(f"start thread... {tbname} - {rows} \n") + new_conn = testCase.new_connect() + testCase.insert_data(tbname, rows, new_conn) + new_conn.close() + print("end thread\n") + +# case +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.ts = 1670000000000 + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + self.setsql = TDSetSql() + self.conn = conn + + # init cluster path + selfPath = os.path.dirname(os.path.realpath(__file__)) + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + self.projDir = f"{projPath}sim/" + tdLog.info(f" init projPath={self.projDir}") + + self.column_dict = { + 'ts': 'timestamp', + 'col1': 'tinyint', + 'col2': 'smallint', + 'col3': 'int', + 'col4': 'bigint', + 'col5': 'tinyint unsigned', + 'col6': 'smallint unsigned', + 'col7': 'int unsigned', + 'col8': 'bigint unsigned', + 'col9': 'float', + 'col10': 'double', + 'col11': 'bool', + 'col12': 'varchar(120)', + 'col13': 'nchar(100)', + } + self.tag_dict = { + 't1': 'tinyint', + 't2': 'smallint', + 't3': 'int', + 't4': 'bigint', + 't5': 'tinyint unsigned', + 't6': 'smallint unsigned', + 't7': 'int unsigned', + 't8': 'bigint unsigned', + 't9': 'float', + 't10': 'double', + 't11': 'bool', + 't12': 'varchar(120)', + 't13': 'nchar(100)', + } + + # malloc new connect + def new_connect(self): + return taos.connect(host = self.conn._host, + user = self.conn._user, + password = self.conn._password, + database = self.dbname, + port = self.conn._port, + config = self.conn._config) + + def set_stb_sql(self,stbname,column_dict,tag_dict): + column_sql = '' + tag_sql = '' + for k,v in column_dict.items(): + column_sql += f"{k} {v}, " + for k,v in tag_dict.items(): + tag_sql += f"{k} {v}, " + create_stb_sql = f'create stable {stbname} ({column_sql[:-2]}) tags ({tag_sql[:-2]})' + return create_stb_sql + + def create_database(self, dbname, wal_period, wal_size_kb, vgroups): + self.wal_period = wal_period + self.wal_size = wal_size_kb * 1024 + self.vgroups = vgroups + self.dbname = dbname + tdSql.execute(f"create database {dbname} wal_retention_period {wal_period} wal_retention_size {wal_size_kb} vgroups {vgroups} replica 3") + tdSql.execute(f'use {dbname}') + + # create stable and child tables + def create_table(self, stbname, tbname, count): + self.child_count = count + self.stbname = stbname + self.tbname = tbname + + # create stable + create_table_sql = self.set_stb_sql(stbname, self.column_dict, self.tag_dict) + tdSql.execute(create_table_sql) + + batch_size = 1000 + # create child table + for i in range(count): + ti = i % 128 + tags = f'{ti},{ti},{i},{i},{ti},{ti},{i},{i},{i}.000{i},{i}.000{i},true,"var{i}","nch{i}"' + sql = f'create table {tbname}{i} using {stbname} tags({tags});' + tdSql.execute(sql) + if i % batch_size == 0: + tdLog.info(f" create child table {i} ...") + + tdLog.info(f" create {count} child tables ok.") + + + # insert to child table d1 data + def insert_data(self, tbname, insertTime): + start = time.time() + values = "" + child_name = "" + cnt = 0 + rows = 10000000000 + for j in range(rows): + for i in range(self.child_count): + tj = j % 128 + cols = f'{tj},{tj},{j},{j},{tj},{tj},{j},{j},{j}.000{j},{j}.000{j},true,"var{j}","nch{j}涛思数据codepage is utf_32_le"' + sql = f'insert into {tbname}{i} values ({self.ts},{cols});' + tdSql.execute(sql) + self.ts += 1 + #tdLog.info(f" child table={i} rows={j} insert data.") + cost = time.time() - start + if j % 100 == 0: + tdSql.execute(f"flush database {self.dbname}") + tdLog.info(" insert row cost time = %ds rows = %d"%(cost, j)) + self.consume_topic("topic1", 5) + + if cost > insertTime and j > 100: + tdLog.info(" insert finished. cost time = %ds rows = %d"%(cost, j)) + return + + # create tmq + def create_tmq(self): + sql = f"create topic topic1 as select ts, col1, concat(col12,t12) from {self.stbname};" + tdSql.execute(sql) + sql = f"create topic topic2 as select * from {self.stbname};" + tdSql.execute(sql) + #tdLog.info(sql) + + def check_retention(self, walStayRange): + # flash database + tdSql.execute(f"flush database {self.dbname}") + time.sleep(0.5) + + vnodes = [] + # put all vnode to list + for dnode in os.listdir(self.projDir): + vnodeDir = self.projDir + f"{dnode}/data/vnode/" + print(f"vnodeDir={vnodeDir}") + if os.path.isdir(vnodeDir) == False or dnode[:5] != "dnode": + continue + # enum all vnode + for entry in os.listdir(vnodeDir): + entryPath = path.join(vnodeDir, entry) + + if os.path.isdir(entryPath): + if path.exists(path.join(entryPath, "vnode.json")): + vnode = VNode(int(dnode[5:]), entryPath, self.wal_period, self.wal_size, walStayRange) + vnodes.append(vnode) + + # do check + for vnode in vnodes: + vnode.check_retention() + + # consume topic + def consume_topic(self, topic_name, consume_cnt): + print("start consume...") + consumer = Consumer( + { + "group.id": "tg2", + "td.connect.user": "root", + "td.connect.pass": "taosdata", + "enable.auto.commit": "true", + } + ) + print("start subscrite...") + consumer.subscribe([topic_name]) + + cnt = 0 + try: + while True and cnt < consume_cnt: + res = consumer.poll(1) + if not res: + break + err = res.error() + if err is not None: + raise err + val = res.value() + cnt += 1 + print(f" consume {cnt} ") + for block in val: + print(block.fetchall()) + finally: + consumer.unsubscribe() + consumer.close() + + + # test db1 + def test_db(self, dbname, checkTime ,wal_period, wal_size_kb): + # var + stable = "meters" + tbname = "d" + vgroups = 6 + count = 10 + + # do + self.create_database(dbname, wal_period, wal_size_kb, vgroups) + self.create_table(stable, tbname, count) + + # create tmq + self.create_tmq() + + # insert data + self.insert_data(tbname, checkTime) + + #stopInsert = False + #tobj = threading.Thread(target = thread_insert, args=(self, tbname, rows)) + #tobj.start() + + # check retention + tdLog.info(f" -------------- do check retention ---------------") + self.check_retention(walStayRange = 256) + + + # stop insert and wait exit + tdLog.info(f" {dbname} stop insert ...") + tdLog.info(f" {dbname} test_db end.") + + + # run + def run(self): + # period + #self.test_db("db1", 10, 60, 0) + # size + #self.test_db("db2", 5, 10*24*3600, 2*1024) # 2M size + + # period + size + self.test_db("db", checkTime = 5*60, wal_period = 60, wal_size_kb=10) + #self.test_db("db", checkTime = 3*60, wal_period = 0, wal_size_kb=0) + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/1-insert/alter_replica.py b/tests/system-test/1-insert/alter_replica.py new file mode 100644 index 0000000000000000000000000000000000000000..900b64d9433ce3f0ec9b971926019c84f669744d --- /dev/null +++ b/tests/system-test/1-insert/alter_replica.py @@ -0,0 +1,114 @@ +import taos +import sys +import time +import socket +import os +import threading +import datetime + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import * + + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def checkVgroups(self, dbName, vgNum): + sleepNum = vgNum * 60 + flag = 0 + while (sleepNum > 0): + sql = f'show {dbName}.vgroups' + tdSql.query(sql) + flag = 0 + for vgid in range (vgNum) : + v1_status = tdSql.queryResult[vgid][4] + v2_status = tdSql.queryResult[vgid][6] + v3_status = tdSql.queryResult[vgid][8] + if ((v1_status == 'leader') and (v2_status == 'follower') and (v3_status == 'follower')) \ + or ((v2_status == 'leader') and (v1_status == 'follower') and (v3_status == 'follower')) \ + or ((v3_status == 'leader') and (v2_status == 'follower') and (v1_status == 'follower')): + continue + else: + sleepNum = sleepNum - 1 + time.sleep(1) + flag = 1 + break + if (0 == flag): + return 0 + tdLog.debug("vgroup[%d] status: %s, %s, %s" %(vgid,v1_status,v2_status,v3_status)) + return -1 + + def alter_replica(self): + # create db and alter replica + tdLog.debug("====alter db repica 1====") + vgNum = 3 + dbName = 'db1' + sql = f'create database {dbName} vgroups {vgNum}' + tdSql.execute(sql) + sql = f'alter database {dbName} replica 3' + tdSql.execute(sql) + tdLog.debug("start check time: %s"%(str(datetime.datetime.now()))) + res = self.checkVgroups(dbName, vgNum) + tdLog.debug("end check time: %s"%(str(datetime.datetime.now()))) + if (0 != res): + tdLog.exit(f'fail: alter database {dbName} replica 3') + + # create db, stable, child tables, and insert data, then alter replica + tdLog.debug("====alter db repica 2====") + dbName = 'db2' + sql = f'create database {dbName} vgroups {vgNum}' + tdSql.execute(sql) + sql = f'use {dbName}' + tdSql.execute(sql) + sql = f'create stable stb (ts timestamp, c int) tags (t int)' + tdSql.execute(sql) + sql = f'create table ctb using stb tags (1)' + tdSql.execute(sql) + sql = f'insert into ctb values (now, 1) (now+1s, 2) (now+2s, 3)' + tdSql.execute(sql) + sql = f'alter database {dbName} replica 3' + tdSql.execute(sql) + tdLog.debug("start check time: %s"%(str(datetime.datetime.now()))) + res = self.checkVgroups(dbName, vgNum) + tdLog.debug("end check time: %s"%(str(datetime.datetime.now()))) + if (0 != res): + tdLog.exit(f'fail: alter database {dbName} replica 3') + + # firstly create db, stable, child tables, and insert data, then drop stable, and then alter replica + tdLog.debug("====alter db repica 3====") + dbName = 'db3' + sql = f'create database {dbName} vgroups {vgNum}' + tdSql.execute(sql) + sql = f'use {dbName}' + tdSql.execute(sql) + sql = f'create stable stb (ts timestamp, c int) tags (t int)' + tdSql.execute(sql) + sql = f'create table ctb using stb tags (1)' + tdSql.execute(sql) + sql = f'insert into ctb values (now, 1) (now+1s, 2) (now+2s, 3)' + tdSql.execute(sql) + sql = f'drop table stb' + tdSql.execute(sql) + sql = f'alter database {dbName} replica 3' + tdSql.execute(sql) + tdLog.debug("start check time: %s"%(str(datetime.datetime.now()))) + res = self.checkVgroups(dbName, vgNum) + tdLog.debug("end check time: %s"%(str(datetime.datetime.now()))) + if (0 != res): + tdLog.exit(f'fail: alter database {dbName} replica 3') + + def run(self): + self.alter_replica() + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/1-insert/database_pre_suf.py b/tests/system-test/1-insert/database_pre_suf.py index 862edbdde9b795f151b9d17f3c74abc8ebc4de63..2e993b9a405eab3ac76f0318fffaadd805808686 100755 --- a/tests/system-test/1-insert/database_pre_suf.py +++ b/tests/system-test/1-insert/database_pre_suf.py @@ -24,9 +24,7 @@ from util.dnodes import tdDnodes from util.dnodes import * class TDTestCase: - updatecfgDict = {'maxSQLLength':1048576,'debugFlag': 143 ,"cDebugFlag":143,"uDebugFlag":143 ,"rpcDebugFlag":143 , "tmrDebugFlag":143 , - "jniDebugFlag":143 ,"simDebugFlag":143,"dDebugFlag":143, "dDebugFlag":143,"vDebugFlag":143,"mDebugFlag":143,"qDebugFlag":143, - "wDebugFlag":143,"sDebugFlag":143,"tsdbDebugFlag":143,"tqDebugFlag":143 ,"fsDebugFlag":143 ,"fnDebugFlag":143} + updatecfgDict = {'maxSQLLength':1048576,'debugFlag': 135} def init(self, conn, logSql, replicaVar=1): self.replicaVar = int(replicaVar) @@ -39,7 +37,9 @@ class TDTestCase: self.db = "pre_suf" - def dropandcreateDB_random(self,database,n,vgroups,table_prefix,table_suffix,check_result): + def dropandcreateDB_random(self,database,n,vgroups,table_prefix,table_suffix,check_result_positive,check_result_negative): + #check_result_positive 检查前缀后缀是正数的,check_result_negative 检查前缀后缀是负数的(TS-3249) + tdLog.info(f"create start:n:{n},vgroups:{vgroups},table_prefix:{table_prefix},table_suffix:{table_suffix},check_result_positive:{check_result_positive},check_result_negative:{check_result_negative}") ts = 1630000000000 num_random = 100 fake = Faker('zh_CN') @@ -56,6 +56,7 @@ class TDTestCase: q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) \ tags(loc nchar(100) , t_int int , t_bigint bigint , t_smallint smallint , t_tinyint tinyint, t_bool bool , t_binary binary(100) , t_nchar nchar(100) ,t_float float , t_double double , t_ts timestamp);''') + #positive for i in range(10*n): tdSql.execute('''create table bj_%d (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp ) ;'''%i) tdSql.execute('''create table sh_%d (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp ) ;'''%i) @@ -106,11 +107,60 @@ class TDTestCase: fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) - + #negative + for i in range(10*n): + tdSql.execute('''create table bj_table_%d_r_negative (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp ) ;'''%i) + tdSql.execute('''create table sh_table_%d_r_negative (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp ) ;'''%i) + tdSql.execute('''create table hn_table_%d_r_negative \ + (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , \ + q_binary1 binary(100) , q_nchar1 nchar(100) ,q_binary2 binary(100) , q_nchar2 nchar(100) ,q_binary3 binary(100) , q_nchar3 nchar(100) ,q_binary4 binary(100) , q_nchar4 nchar(100) ,\ + q_binary5 binary(100) , q_nchar5 nchar(100) ,q_binary6 binary(100) , q_nchar6 nchar(100) ,q_binary7 binary(100) , q_nchar7 nchar(100) ,q_binary8 binary(100) , q_nchar8 nchar(100) ,\ + q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) ;'''%i) + + tdSql.execute('''create table bj_stable_1_%d_negative using stable_1 tags('bj_stable_1_%d', '%d' , '%d', '%d' , '%d' , 1 , 'binary1.%s' , 'nchar1.%s' , '%f', '%f' ,'%d') ;''' + %(i,i,fake.random_int(min=-2147483647, max=2147483647, step=1), fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) + tdSql.execute('''create table sh_table_%d_a_negative using stable_1 tags('sh_a_table_1_%d', '%d' , '%d', '%d' , '%d' , 1 , 'binary1.%s' , 'nchar1.%s' , '%f', '%f' ,'%d') ;''' + %(i,i,fake.random_int(min=-2147483647, max=2147483647, step=1), fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) + tdSql.execute('''create table sh_table_%d_b_negative using stable_1 tags('sh_b_table_1_%d', '%d' , '%d', '%d' , '%d' , 1 , 'binary1.%s' , 'nchar1.%s' , '%f', '%f' ,'%d') ;''' + %(i,i,fake.random_int(min=-2147483647, max=2147483647, step=1), fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) + tdSql.execute('''create table sh_table_%d_c_negative using stable_1 tags('sh_c_table_1_%d', '%d' , '%d', '%d' , '%d' , 1 , 'binary1.%s' , 'nchar1.%s' , '%f', '%f' ,'%d') ;''' + %(i,i,fake.random_int(min=-2147483647, max=2147483647, step=1), fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) + + tdSql.execute('''create table bj_table_%d_a_negative using stable_1 tags('bj_a_table_1_%d', '%d' , '%d', '%d' , '%d' , 1 , 'binary1.%s' , 'nchar1.%s' , '%f', '%f' ,'%d') ;''' + %(i,i,fake.random_int(min=-2147483647, max=2147483647, step=1), fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) + tdSql.execute('''create table bj_table_%d_b_negative using stable_1 tags('bj_b_table_1_%d', '%d' , '%d', '%d' , '%d' , 1 , 'binary1.%s' , 'nchar1.%s' , '%f', '%f' ,'%d') ;''' + %(i,i,fake.random_int(min=-2147483647, max=2147483647, step=1), fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) + tdSql.execute('''create table bj_table_%d_c_negative using stable_1 tags('bj_c_table_1_%d', '%d' , '%d', '%d' , '%d' , 1 , 'binary1.%s' , 'nchar1.%s' , '%f', '%f' ,'%d') ;''' + %(i,i,fake.random_int(min=-2147483647, max=2147483647, step=1), fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) + + + tdSql.execute('''create table tj_table_%d_a_negative using stable_2 tags('tj_a_table_2_%d', '%d' , '%d', '%d' , '%d' , 1 , 'binary1.%s' , 'nchar1.%s' , '%f', '%f' ,'%d') ;''' + %(i,i,fake.random_int(min=-2147483647, max=2147483647, step=1), fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) + tdSql.execute('''create table tj_table_%d_b_negative using stable_2 tags('tj_b_table_2_%d', '%d' , '%d', '%d' , '%d' , 1 , 'binary1.%s' , 'nchar1.%s' , '%f', '%f' ,'%d') ;''' + %(i,i,fake.random_int(min=-2147483647, max=2147483647, step=1), fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pystr() ,fake.pystr() ,fake.pyfloat(),fake.pyfloat(),fake.random_int(min=-2147483647, max=2147483647, step=1))) + # create stream - tdSql.execute('''create stream current_stream into stream_max_stable_1 as select _wstart as start, _wend as wend, max(q_int) as max_int, min(q_bigint) as min_int from stable_1 where ts is not null interval (5s);''') + tdSql.execute('''create stream current_stream trigger at_once IGNORE EXPIRED 0 into stream_max_stable_1 as select _wstart as startts, _wend as wend, max(q_int) as max_int, min(q_bigint) as min_int from stable_1 where ts is not null interval (5s);''') - # insert data + # insert data positive for i in range(num_random*n): tdSql.execute('''insert into bj_stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts,\ q_binary1 , q_nchar1 , q_binary2 , q_nchar2 , q_binary3 , q_nchar3 , q_binary4 , q_nchar4 , q_binary5 , q_nchar5 , q_binary6 , q_nchar6 , q_binary7 , q_nchar7, q_binary8 , q_nchar8) \ @@ -180,27 +230,79 @@ class TDTestCase: fake.pyfloat() , fake.pyfloat() , fake.pystr() , fake.pystr() , ts + i, fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr())) + # insert data negative + for i in range(num_random*n): + tdSql.execute('''insert into bj_stable_1_1_negative (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts,\ + q_binary1 , q_nchar1 , q_binary2 , q_nchar2 , q_binary3 , q_nchar3 , q_binary4 , q_nchar4 , q_binary5 , q_nchar5 , q_binary6 , q_nchar6 , q_binary7 , q_nchar7, q_binary8 , q_nchar8) \ + values(%d, %d, %d, %d, %d, %f, %f, 0, 'binary.%s', 'nchar.%s', %d, 'binary1.%s', 'nchar1.%s', 'binary2.%s', 'nchar2.%s', 'binary3.%s', 'nchar3.%s', \ + 'binary4.%s', 'nchar4.%s', 'binary5.%s', 'nchar5.%s', 'binary6.%s', 'nchar6.%s', 'binary7.%s', 'nchar7.%s', 'binary8.%s', 'nchar8.%s') ;''' + % (ts + i*1000, fake.random_int(min=-2147483647, max=2147483647, step=1), + fake.random_int(min=-9223372036854775807, max=9223372036854775807, step=1), + fake.random_int(min=-32767, max=32767, step=1) , fake.random_int(min=-127, max=127, step=1) , + fake.pyfloat() , fake.pyfloat() , fake.pystr() , fake.pystr() , ts + i , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , + fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr())) + + tdSql.execute('''insert into bj_stable_1_2_negative (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts,\ + q_binary1 , q_nchar1 , q_binary2 , q_nchar2 , q_binary3 , q_nchar3 , q_binary4 , q_nchar4 , q_binary5 , q_nchar5 , q_binary6 , q_nchar6 , q_binary7 , q_nchar7, q_binary8 , q_nchar8)\ + values(%d, %d, %d, %d, %d, %f, %f, 1, 'binary.%s', 'nchar.%s', %d, 'binary1.%s', 'nchar1.%s', 'binary2.%s', 'nchar2.%s', 'binary3.%s', 'nchar3.%s', \ + 'binary4.%s', 'nchar4.%s', 'binary5.%s', 'nchar5.%s', 'binary6.%s', 'nchar6.%s', 'binary7.%s', 'nchar7.%s', 'binary8.%s', 'nchar8.%s') ;''' + % (ts + i*1000, fake.random_int(min=0, max=2147483647, step=1), + fake.random_int(min=0, max=9223372036854775807, step=1), + fake.random_int(min=0, max=32767, step=1) , fake.random_int(min=0, max=127, step=1) , + fake.pyfloat() , fake.pyfloat() , fake.pystr() , fake.pystr() , ts + i, fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , + fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr())) + + tdSql.execute('''insert into bj_stable_1_3_negative (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts,\ + q_binary1 , q_nchar1 , q_binary2 , q_nchar2 , q_binary3 , q_nchar3 , q_binary4 , q_nchar4 , q_binary5 , q_nchar5 , q_binary6 , q_nchar6 , q_binary7 , q_nchar7, q_binary8 , q_nchar8) \ + values(%d, %d, %d, %d, %d, %f, %f, 0, 'binary.%s', 'nchar.%s', %d, 'binary1.%s', 'nchar1.%s', 'binary2.%s', 'nchar2.%s', 'binary3.%s', 'nchar3.%s', \ + 'binary4.%s', 'nchar4.%s', 'binary5.%s', 'nchar5.%s', 'binary6.%s', 'nchar6.%s', 'binary7.%s', 'nchar7.%s', 'binary8.%s', 'nchar8.%s') ;''' + % (ts + i*1000, fake.random_int(min=-0, max=2147483647, step=1), + fake.random_int(min=-0, max=9223372036854775807, step=1), + fake.random_int(min=-0, max=32767, step=1) , fake.random_int(min=-0, max=127, step=1) , + fake.pyfloat() , fake.pyfloat() , fake.pystr() , fake.pystr() , ts + i, fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , + fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr())) + + tdSql.execute('''insert into bj_stable_1_4_negative (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts,\ + q_binary1 , q_nchar1 , q_binary2 , q_nchar2 , q_binary3 , q_nchar3 , q_binary4 , q_nchar4 , q_binary5 , q_nchar5 , q_binary6 , q_nchar6 , q_binary7 , q_nchar7, q_binary8 , q_nchar8) \ + values(%d, %d, %d, %d, %d, %f, %f, 0, 'binary.%s', 'nchar.%s', %d, 'binary1.%s', 'nchar1.%s', 'binary2.%s', 'nchar2.%s', 'binary3.%s', 'nchar3.%s', \ + 'binary4.%s', 'nchar4.%s', 'binary5.%s', 'nchar5.%s', 'binary6.%s', 'nchar6.%s', 'binary7.%s', 'nchar7.%s', 'binary8.%s', 'nchar8.%s') ;''' + % (ts + i*1000 +1, fake.random_int(min=-0, max=2147483647, step=1), + fake.random_int(min=-0, max=9223372036854775807, step=1), + fake.random_int(min=-0, max=32767, step=1) , fake.random_int(min=-0, max=127, step=1) , + fake.pyfloat() , fake.pyfloat() , fake.pystr() , fake.pystr() , ts + i, fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , + fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr())) + + tdSql.execute('''insert into bj_stable_1_5_negative (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts,\ + q_binary1 , q_nchar1 , q_binary2 , q_nchar2 , q_binary3 , q_nchar3 , q_binary4 , q_nchar4 , q_binary5 , q_nchar5 , q_binary6 , q_nchar6 , q_binary7 , q_nchar7, q_binary8 , q_nchar8) \ + values(%d, %d, %d, %d, %d, %f, %f, 0, 'binary.%s', 'nchar.%s', %d, 'binary1.%s', 'nchar1.%s', 'binary2.%s', 'nchar2.%s', 'binary3.%s', 'nchar3.%s', \ + 'binary4.%s', 'nchar4.%s', 'binary5.%s', 'nchar5.%s', 'binary6.%s', 'nchar6.%s', 'binary7.%s', 'nchar7.%s', 'binary8.%s', 'nchar8.%s') ;''' + % (ts + i*1000 +10, fake.random_int(min=-0, max=2147483647, step=1), + fake.random_int(min=-0, max=9223372036854775807, step=1), + fake.random_int(min=-0, max=32767, step=1) , fake.random_int(min=-0, max=127, step=1) , + fake.pyfloat() , fake.pyfloat() , fake.pystr() , fake.pystr() , ts + i, fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , + fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr() , fake.pystr())) + tdSql.query("select count(*) from stable_1;") - tdSql.checkData(0,0,5*num_random*n) + tdSql.checkData(0,0,10*num_random*n) tdSql.query("select count(*) from hn_table_1_r;") tdSql.checkData(0,0,num_random*n) sleep(5) # stream data check - tdSql.query("select start,wend,max_int from stream_max_stable_1 ;") + tdSql.query("select startts,wend,max_int from stream_max_stable_1 ;") tdSql.checkRows(20) tdSql.query("select sum(max_int) from stream_max_stable_1 ;") stream_data_1 = tdSql.queryResult[0][0] tdSql.query("select sum(min_int) from stream_max_stable_1 ;") stream_data_2 = tdSql.queryResult[0][0] - tdSql.query("select sum(max_int),sum(min_int) from (select _wstart as start, _wend as wend, max(q_int) as max_int, min(q_bigint) as min_int from stable_1 where ts is not null interval (5s));") + tdSql.query("select sum(max_int),sum(min_int) from (select _wstart as startts, _wend as wend, max(q_int) as max_int, min(q_bigint) as min_int from stable_1 where ts is not null interval (5s));") sql_data_1 = tdSql.queryResult[0][0] sql_data_2 = tdSql.queryResult[0][1] self.stream_value_check(stream_data_1,sql_data_1) self.stream_value_check(stream_data_2,sql_data_2) - tdSql.query("select sum(max_int),sum(min_int) from (select _wstart as start, _wend as wend, max(q_int) as max_int, min(q_bigint) as min_int from stable_1 interval (5s));") + tdSql.query("select sum(max_int),sum(min_int) from (select _wstart as startts, _wend as wend, max(q_int) as max_int, min(q_bigint) as min_int from stable_1 interval (5s));") sql_data_1 = tdSql.queryResult[0][0] sql_data_2 = tdSql.queryResult[0][1] @@ -220,39 +322,28 @@ class TDTestCase: tdSql.query(" select * from information_schema.ins_databases where name = '%s';" %database) - print(tdSql.queryResult) - - # tdSql.query(" select table_prefix,table_suffix from information_schema.ins_databases where name = '%s';" %database) - # print(tdSql.queryResult) - #TD-19082 - - #tdSql.query(" select * from information_schema.ins_tables where db_name = '%s';" %database) - #print(tdSql.queryResult) + tdLog.info(tdSql.queryResult) - tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s';" %database) + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' limit 3;" %database) queryRows = len(tdSql.queryResult) for i in range(queryRows): - print("row=%d, vgroup_id=%s, tbname=%s " %(i,tdSql.queryResult[i][1],tdSql.queryResult[i][0])) + tdLog.info("row=%d, vgroup_id=%s, tbname=%s " %(i,tdSql.queryResult[i][1],tdSql.queryResult[i][0])) tdLog.info("\n=============flush database ====================\n") tdSql.execute(" flush database %s;" %database) tdSql.query(" select * from information_schema.ins_databases where name = '%s';" %database) - print(tdSql.queryResult) - - # tdSql.query(" select table_prefix,table_suffix from information_schema.ins_databases where name = '%s';" %database) - # print(tdSql.queryResult) - #TD-19082 - - tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s';" %database) + tdLog.info(tdSql.queryResult) + + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' limit 3;" %database) queryRows = len(tdSql.queryResult) for i in range(queryRows): - print("row=%d, vgroup_id=%s, tbname=%s " %(i,tdSql.queryResult[i][1],tdSql.queryResult[i][0])) + tdLog.info("row=%d, vgroup_id=%s, tbname=%s " %(i,tdSql.queryResult[i][1],tdSql.queryResult[i][0])) # check in one vgroup - if check_result == 'Y': + if check_result_positive == 'Y': #base table : sh_table_0_a tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='sh_table_0_a';" %(database)) base_value_table_name = tdSql.queryResult[0][0] @@ -324,8 +415,100 @@ class TDTestCase: tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='tj_table_%d_b';" %(database,i)) self.value_check(base_value_table_name,base_value_table_vgroup) + elif check_result_negative == 'Y': + #base table : sh_table_0_a + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='sh_table_0_a_negative';" %(database)) + base_value_table_name = tdSql.queryResult[0][0] + base_value_table_vgroup = tdSql.queryResult[0][1] + + #check table :sh_table_i_a + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'sh_table_%%_a_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='sh_table_%d_a_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + #check table :sh_table_i_b + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'sh_table_%%_b_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='sh_table_%d_b_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + #check table :sh_table_i_c + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'sh_table_%%_c_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='sh_table_%d_c_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + #check table :sh_table_i_r + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'sh_table_%%_r_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='sh_table_%d_r_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + #base table : bj_table_0_a + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='bj_table_0_a_negative';" %(database)) + base_value_table_name = tdSql.queryResult[0][0] + base_value_table_vgroup = tdSql.queryResult[0][1] + + #check table :bj_table_i_a + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'bj_table_%%_a_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='bj_table_%d_a_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + #check table :bj_table_i_b + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'bj_table_%%_b_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='bj_table_%d_b_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + #check table :bj_table_i_c + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'bj_table_%%_c_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='bj_table_%d_c_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + #check table :bj_table_i_r + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'bj_table_%%_r_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='bj_table_%d_r_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + #base table : hn_table_0_r + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='hn_table_0_r_negative';" %(database)) + base_value_table_name = tdSql.queryResult[0][0] + base_value_table_vgroup = tdSql.queryResult[0][1] + + #check table :hn_table_i_r + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'hn_table_%%_r_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='hn_table_%d_r_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + + #base table : tj_table_0_r + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='tj_table_0_a_negative';" %(database)) + base_value_table_name = tdSql.queryResult[0][0] + base_value_table_vgroup = tdSql.queryResult[0][1] + + #check table :tj_table_i_a + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'tj_table_%%_a_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='tj_table_%d_a_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + #check table :tj_table_i_b + check_rows = tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name like 'tj_table_%%_b_negative';" %(database)) + for i in range(check_rows): + tdSql.query(" select table_name,vgroup_id from information_schema.ins_tables where db_name = '%s' and table_name='tj_table_%d_b_negative';" %(database,i)) + self.value_check(base_value_table_name,base_value_table_vgroup) + + else: pass + + tdLog.info(f"create end:n:{n},vgroups:{vgroups},table_prefix:{table_prefix},table_suffix:{table_suffix},check_result_positive:{check_result_positive},check_result_negative:{check_result_negative}") + def value_check(self,base_value_table_name,base_value_table_vgroup): check_value_table_name = tdSql.queryResult[0][0] @@ -348,17 +531,28 @@ class TDTestCase: os.system("rm -rf %s/%s.sql" % (self.testcasePath,self.testcaseFilename)) - #(self,database,n,vgroups,table_prefix,table_suffix) - self.dropandcreateDB_random("%s" %self.db, 1,2,0,0,'N') - self.dropandcreateDB_random("%s" %self.db, 1,2,0,2,'N') - self.dropandcreateDB_random("%s" %self.db, 1,2,2,0,'N') - self.dropandcreateDB_random("%s" %self.db, 1,2,3,3,'Y') - self.dropandcreateDB_random("%s" %self.db, 1,3,3,3,'Y') - self.dropandcreateDB_random("%s" %self.db, 1,4,4,4,'Y') - self.dropandcreateDB_random("%s" %self.db, 1,5,5,5,'Y') + #(self,database,n,vgroups,table_prefix,table_suffix,check_result_positive,check_result_negative): + #check_result_positive 检查前缀后缀是正数的,check_result_negative 检查前缀后缀是负数的(TS-3249) + # self.dropandcreateDB_random("%s" %self.db, 1,2,0,0,'N','N') + # self.dropandcreateDB_random("%s" %self.db, 1,2,0,2,'N','N') + # self.dropandcreateDB_random("%s" %self.db, 1,2,2,0,'N','N') + + self.dropandcreateDB_random("%s" %self.db, 1,random.randint(1,5),random.randint(0,3),random.randint(0,3),'N','N') + self.dropandcreateDB_random("%s" %self.db, 1,random.randint(1,5),random.randint(-10,0),random.randint(-10,0),'N','N') + self.dropandcreateDB_random("%s" %self.db, 1,random.randint(1,5),random.randint(-191,0),random.randint(-191,0),'N','N') + self.dropandcreateDB_random("%s" %self.db, 1,random.randint(1,5),random.randint(0,100),random.randint(0,91),'N','N') + + # self.dropandcreateDB_random("%s" %self.db, 1,2,3,3,'Y','N') + # self.dropandcreateDB_random("%s" %self.db, 1,3,3,3,'Y','N') + # self.dropandcreateDB_random("%s" %self.db, 1,4,4,4,'Y','N') + # self.dropandcreateDB_random("%s" %self.db, 1,5,5,5,'Y','N') + self.dropandcreateDB_random("%s" %self.db, 1,random.randint(1,5),random.randint(3,5),random.randint(3,5),'Y','N') + + self.dropandcreateDB_random("%s" %self.db, 1,random.randint(1,5),random.randint(-5,-1),0,'N','Y') + self.dropandcreateDB_random("%s" %self.db, 1,random.randint(1,5),random.randint(-5,-1),random.randint(-9,-0),'N','Y') - #taos -f sql + # #taos -f sql print("taos -f sql start!") taos_cmd1 = "taos -f %s/%s.sql" % (self.testcasePath,self.testcaseFilename) _ = subprocess.check_output(taos_cmd1, shell=True) diff --git a/tests/system-test/1-insert/delete_childtable.py b/tests/system-test/1-insert/delete_childtable.py index e3144edb4594521bb849b579b9c264e44b156de5..a12f8849812bcf5d72bf24c654e92cc8c8da2cb8 100644 --- a/tests/system-test/1-insert/delete_childtable.py +++ b/tests/system-test/1-insert/delete_childtable.py @@ -27,7 +27,7 @@ class TDTestCase: def init(self, conn, logSql, replicaVar=1): self.replicaVar = int(replicaVar) tdLog.debug("start to execute %s" % __file__) - tdSql.init(conn.cursor()) + tdSql.init(conn.cursor(), True) self.dbname = 'db_test' self.setsql = TDSetSql() self.stbname = 'stb' diff --git a/tests/system-test/1-insert/delete_stable.py b/tests/system-test/1-insert/delete_stable.py index 313b6ce731fe98aaed6fdfe1f9fe71fa4313d3cd..8ebe7b6692e31bba12bdc0a3cbc885112eb96562 100644 --- a/tests/system-test/1-insert/delete_stable.py +++ b/tests/system-test/1-insert/delete_stable.py @@ -29,6 +29,9 @@ class TDTestCase: tdLog.debug("start to execute %s" % __file__) tdSql.init(conn.cursor()) self.dbname = 'db_test' + self.ns_dbname = 'ns_test' + self.us_dbname = 'us_test' + self.ms_dbname = 'ms_test' self.setsql = TDSetSql() self.stbname = 'stb' self.ntbname = 'ntb' @@ -220,11 +223,45 @@ class TDTestCase: tdSql.query(f'select {func}(*) from {self.stbname}') tdSql.execute(f'drop table {self.stbname}') tdSql.execute(f'drop database {self.dbname}') + + def precision_now_check(self): + for dbname in [self.ms_dbname, self.us_dbname, self.ns_dbname]: + self.ts = 1537146000000 + if dbname == self.us_dbname: + self.ts = int(self.ts*1000) + precision = "us" + elif dbname == self.ns_dbname: + precision = "ns" + self.ts = int(self.ts*1000000) + else: + precision = "ms" + self.ts = int(self.ts) + tdSql.execute(f'drop database if exists {dbname}') + tdSql.execute(f'create database if not exists {dbname} precision "{precision}"') + tdSql.execute(f'use {dbname}') + self.base_data = { + 'tinyint':self.tinyint_val + } + self.column_dict = { + 'col1': 'tinyint' + } + for col_name,col_type in self.column_dict.items(): + tdSql.execute(f'create table if not exists {self.stbname} (ts timestamp,{col_name} {col_type}) tags(t1 int)') + for i in range(self.tbnum): + tdSql.execute(f'create table if not exists {self.stbname}_{i} using {self.stbname} tags(1)') + self.insert_base_data(col_type,f'{self.stbname}_{i}',self.rowNum,self.base_data) + tdSql.query(f'select * from {self.stbname}') + tdSql.checkEqual(tdSql.queryRows, self.tbnum*self.rowNum) + tdSql.execute(f'delete from {self.stbname} where ts < now()') + tdSql.query(f'select * from {self.stbname}') + tdSql.checkEqual(tdSql.queryRows, 0) + def run(self): self.delete_data_stb() tdDnodes.stoptaosd(1) tdDnodes.starttaosd(1) self.delete_data_stb() + self.precision_now_check() def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/system-test/1-insert/delete_systable.py b/tests/system-test/1-insert/delete_systable.py new file mode 100644 index 0000000000000000000000000000000000000000..40422a7515e7d327803e69b2fb39b2468124b54b --- /dev/null +++ b/tests/system-test/1-insert/delete_systable.py @@ -0,0 +1,111 @@ + +################################################################### +# 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 numpy import logspace +from util import constant +from util.log import * +from util.cases import * +from util.sql import * +from util.common import * +from util.sqlset import TDSetSql + +info_schema_db = "information_schema" +perf_schema_db = "performance_schema" + +info_schema_tables = [ + "ins_dnodes", + "ins_mnodes", + "ins_modules", + "ins_qnodes", + "ins_snodes", + "ins_cluster", + "ins_databases", + "ins_functions", + "ins_indexes", + "ins_stables", + "ins_tables", + "ins_tags", + "ins_columns", + "ins_users", + "ins_grants", + "ins_vgroups", + "ins_configs", + "ins_dnode_variables", + "ins_topics", + "ins_subscriptions", + "ins_streams", + "ins_streams_tasks", + "ins_vnodes", + "ins_user_privileges" +] + +perf_schema_tables = [ + "perf_connections", + "perf_queries", + "perf_consumers", + "perf_trans", + "perf_apps" +] + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + + def delete_systb(self): + tdSql.execute(f'use {info_schema_db}') + for i in info_schema_tables: + tdSql.error(f'delete from {i}') + tdSql.error(f'delete from {info_schema_db}.{i}') + tdSql.error(f'delete from {i} where ts >= 0') + tdSql.error(f'delete from {info_schema_db}.{i} where ts >= 0') + + tdSql.execute(f'use {perf_schema_db}') + for i in perf_schema_tables: + tdSql.error(f'delete from {i}') + tdSql.error(f'delete from {perf_schema_db}.{i}') + tdSql.error(f'delete from {i} where ts >= 0') + tdSql.error(f'delete from {perf_schema_db}.{i} where ts >= 0') + + def drop_systb(self): + tdSql.execute(f'use {info_schema_db}') + for i in info_schema_tables: + tdSql.error(f'drop table {i}') + tdSql.error(f'drop {info_schema_db}.{i}') + tdSql.error(f'drop database {info_schema_db}') + + tdSql.execute(f'use {perf_schema_db}') + for i in perf_schema_tables: + tdSql.error(f'drop table {i}') + tdSql.error(f'drop table {perf_schema_db}.{i}') + tdSql.error(f'drop database {perf_schema_db}') + + def delete_from_systb(self): + self.delete_systb() + self.drop_systb() + def run(self): + self.delete_from_systb() + tdDnodes.stoptaosd(1) + tdDnodes.starttaosd(1) + self.delete_from_systb() + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/1-insert/drop.py b/tests/system-test/1-insert/drop.py index c15a9bbc35bc28a8679b3400ff37569e6d7955aa..9954b3557e23df193a4c4f84c819fc508c39f5bb 100644 --- a/tests/system-test/1-insert/drop.py +++ b/tests/system-test/1-insert/drop.py @@ -54,7 +54,7 @@ class TDTestCase: insert_list = [] self.setsql.insert_values(column_dict,i,insert_sql,insert_list,self.ts) def drop_ntb_check(self): - tdSql.execute(f'create database if not exists {self.dbname} replica {self.replicaVar}') + tdSql.execute(f'create database if not exists {self.dbname} replica {self.replicaVar} wal_retention_period 3600') tdSql.execute(f'use {self.dbname}') tdSql.execute(self.setsql.set_create_normaltable_sql(self.ntbname,self.column_dict)) self.insert_data(self.column_dict,self.ntbname,self.rowNum) @@ -80,7 +80,7 @@ class TDTestCase: tag_values = [ f'1' ] - tdSql.execute(f"create database if not exists {self.dbname} replica {self.replicaVar}") + tdSql.execute(f"create database if not exists {self.dbname} replica {self.replicaVar} wal_retention_period 3600") tdSql.execute(f'use {self.dbname}') tdSql.execute(self.setsql.set_create_stable_sql(stbname,self.column_dict,tag_dict)) for i in range(self.tbnum): @@ -116,7 +116,7 @@ class TDTestCase: tdSql.checkRows(self.tbnum) tdSql.execute(f'drop database {self.dbname}') def drop_topic_check(self): - tdSql.execute(f'create database {self.dbname} replica {self.replicaVar}') + tdSql.execute(f'create database {self.dbname} replica {self.replicaVar} wal_retention_period 3600') tdSql.execute(f'use {self.dbname}') stbname = tdCom.getLongName(5,"letters") topic_name = tdCom.getLongName(5,"letters") @@ -132,20 +132,20 @@ class TDTestCase: tdSql.execute(f'drop database {self.dbname}') def drop_stream_check(self): - tdSql.execute(f'create database {self.dbname} replica 1') + tdSql.execute(f'create database {self.dbname} replica 1 wal_retention_period 3600') tdSql.execute(f'use {self.dbname}') stbname = tdCom.getLongName(5,"letters") stream_name = tdCom.getLongName(5,"letters") tdSql.execute(f'create table {stbname} (ts timestamp,c0 int) tags(t0 int)') tdSql.execute(f'create table tb using {stbname} tags(1)') - tdSql.execute(f'create stream {stream_name} into stb as select * from {self.dbname}.{stbname} partition by tbname') + tdSql.execute(f'create stream {stream_name} trigger at_once ignore expired 0 into stb as select * from {self.dbname}.{stbname} partition by tbname') tdSql.query(f'select * from information_schema.ins_streams where stream_name = "{stream_name}"') print(tdSql.queryResult) - tdSql.checkEqual(tdSql.queryResult[0][2],f'create stream {stream_name} into stb as select * from {self.dbname}.{stbname} partition by tbname') + tdSql.checkEqual(tdSql.queryResult[0][2],f'create stream {stream_name} trigger at_once ignore expired 0 into stb as select * from {self.dbname}.{stbname} partition by tbname') tdSql.execute(f'drop stream {stream_name}') - tdSql.execute(f'create stream {stream_name} into stb1 as select * from tb') + tdSql.execute(f'create stream {stream_name} trigger at_once ignore expired 0 into stb1 as select * from tb') tdSql.query(f'select * from information_schema.ins_streams where stream_name = "{stream_name}"') - tdSql.checkEqual(tdSql.queryResult[0][2],f'create stream {stream_name} into stb1 as select * from tb') + tdSql.checkEqual(tdSql.queryResult[0][2],f'create stream {stream_name} trigger at_once ignore expired 0 into stb1 as select * from tb') tdSql.execute(f'drop database {self.dbname}') def run(self): self.drop_ntb_check() diff --git a/tests/system-test/1-insert/insert_wide_column.py b/tests/system-test/1-insert/insert_wide_column.py new file mode 100644 index 0000000000000000000000000000000000000000..e383675a41dbc63c320f58fe9fe60938f81c5a84 --- /dev/null +++ b/tests/system-test/1-insert/insert_wide_column.py @@ -0,0 +1,87 @@ +################################################################### +# 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 threading +import random +import string +import time + +from util.log import * +from util.cases import * +from util.sql import * +from util.autogen import * + + +# +# Test Main class +# + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + self.autoGen = AutoGen() + + def query_test(self, stbname): + sql = f"select count(*) from {stbname}" + tdSql.execute(sql) + sql = f"select * from {stbname} order by ts desc;" + tdSql.execute(sql) + sql = f"select * from (select * from {stbname} where c1=c2 or c3=c4 or c5=c6) order by ts desc;" + tdSql.execute(sql) + + tdLog.info(" test query ok!") + + + def test_db(self, dbname, stbname, childname, tag_cnt, column_cnt, child_cnt, insert_rows, binary_len, nchar_len): + self.autoGen.create_db(dbname) + self.autoGen.create_stable(stbname, tag_cnt, column_cnt, binary_len, nchar_len) + self.autoGen.create_child(stbname, childname, child_cnt) + self.autoGen.insert_data(insert_rows) + self.autoGen.insert_samets(insert_rows) + self.query_test(stbname) + + def run(self): + dbname = "test" + stbname = "st" + childname = "d" + child_cnt = 2 + insert_rows = 10 + tag_cnt = 15 + column_cnt = 20 + binary_len = 10240 + nchar_len = 1025 + self.autoGen.set_batch_size(1) + + # normal + self.test_db(dbname, stbname, childname, tag_cnt, column_cnt, child_cnt, insert_rows, binary_len, nchar_len) + + # max + dbname = "test_max_col" + child_cnt = 3 + insert_rows = 50 + tag_cnt = 128 + binary_len = 3 + nchar_len = 4 + column_cnt = 4096 - tag_cnt + self.autoGen.set_batch_size(1) + self.test_db(dbname, stbname, childname, tag_cnt, column_cnt, child_cnt, insert_rows, binary_len, nchar_len) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/1-insert/mutil_stage.py b/tests/system-test/1-insert/mutil_stage.py index 8780ecc477f6c6a9ec1076967aa27da63eb09f97..970554c6c17f8b50eb9261dfe1da2f307740cbd0 100644 --- a/tests/system-test/1-insert/mutil_stage.py +++ b/tests/system-test/1-insert/mutil_stage.py @@ -75,7 +75,7 @@ class TDTestCase: tdLog.exit(cmd) def cfg_str(self, filename, update_str): - cmd = f'echo "{update_str}" >> {filename}' + cmd = f'echo {update_str} >> {filename}' if os.system(cmd) != 0: tdLog.exit(cmd) @@ -94,41 +94,41 @@ class TDTestCase: def __err_cfg(self): cfg_list = [] err_case1 = [ - f"dataDir {self.taos_data_dir}/{DATA_PRE0}0 {L0} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE1}1 {L1} {PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE2}2 {L2} {NON_PRIMARY_DIR}" + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}0 {L0} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE1}1 {L1} {PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE2}2 {L2} {NON_PRIMARY_DIR}" ] err_case2 = [ - f"dataDir {self.taos_data_dir}/{DATA_PRE0}0 {L0} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE1}1 {L1} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE2}2 {L2} {PRIMARY_DIR}" + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}0 {L0} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE1}1 {L1} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE2}2 {L2} {PRIMARY_DIR}" ] err_case3 = [ - f"dataDir {self.taos_data_dir}/data33 3 {NON_PRIMARY_DIR}" + f"dataDir {self.taos_data_dir}{os.sep}data33 3 {NON_PRIMARY_DIR}" ] err_case4 = [ - f"dataDir {self.taos_data_dir}/{DATA_PRE0}0 {L0} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE1}1 {L1} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE2}2 {L2} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE2}2 {L1} {NON_PRIMARY_DIR}" + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}0 {L0} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE1}1 {L1} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE2}2 {L2} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE2}2 {L1} {NON_PRIMARY_DIR}" ] - err_case5 = [f"dataDir {self.taos_data_dir}/{DATA_PRE0}0 {L0} {PRIMARY_DIR}"] + err_case5 = [f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}0 {L0} {PRIMARY_DIR}"] for i in range(16): - err_case5.append(f"dataDir {self.taos_data_dir}/{DATA_PRE0}{i+1} {L0} {NON_PRIMARY_DIR}") + err_case5.append(f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}{i+1} {L0} {NON_PRIMARY_DIR}") err_case6 = [ - f"dataDir {self.taos_data_dir}/{DATA_PRE0}0 {L0} {PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE0}1 {L0} {PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}0 {L0} {PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}1 {L0} {PRIMARY_DIR}", ] err_case7 = [ - f"dataDir {self.taos_data_dir}/{DATA_PRE0}0 {L0} {PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE2}2 {L2} {PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}0 {L0} {PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE2}2 {L2} {PRIMARY_DIR}", ] err_case8 = [ - f"dataDir {self.taos_data_dir}/data33 3 {PRIMARY_DIR}" + f"dataDir {self.taos_data_dir}{os.sep}data33 3 {PRIMARY_DIR}" ] err_case9 = [ - f"dataDir {self.taos_data_dir}/data33 -1 {NON_PRIMARY_DIR}" + f"dataDir {self.taos_data_dir}{os.sep}data33 -1 {NON_PRIMARY_DIR}" ] cfg_list.append(err_case1) @@ -147,23 +147,23 @@ class TDTestCase: def __current_cfg(self): cfg_list = [] current_case1 = [ - #f"dataDir {self.taos_data_dir}/{DATA_PRE0}0 {L0} {PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE0}1 {L0} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE1}1 {L1} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE2}2 {L2} {NON_PRIMARY_DIR}" + #f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}0 {L0} {PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}1 {L0} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE1}1 {L1} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE2}2 {L2} {NON_PRIMARY_DIR}" ] - #current_case2 = [f"dataDir {self.taos_data_dir}/{DATA_PRE0}0 {L0} {PRIMARY_DIR}"] + #current_case2 = [f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}0 {L0} {PRIMARY_DIR}"] current_case2 = [] for i in range(9): - current_case2.append(f"dataDir {self.taos_data_dir}/{DATA_PRE0}{i+1} {L0} {NON_PRIMARY_DIR}") + current_case2.append(f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}{i+1} {L0} {NON_PRIMARY_DIR}") # TD-17773bug current_case3 = [ - #f"dataDir {self.taos_data_dir}/{DATA_PRE0}0 ", - f"dataDir {self.taos_data_dir}/{DATA_PRE0}1 {L0} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE1}0 {L1} {NON_PRIMARY_DIR}", - f"dataDir {self.taos_data_dir}/{DATA_PRE2}0 {L2} {NON_PRIMARY_DIR}", + #f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}0 ", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE0}1 {L0} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE1}0 {L1} {NON_PRIMARY_DIR}", + f"dataDir {self.taos_data_dir}{os.sep}{DATA_PRE2}0 {L2} {NON_PRIMARY_DIR}", ] cfg_list.append(current_case1) cfg_list.append(current_case3) diff --git a/tests/system-test/1-insert/opentsdb_json_taosc_insert.py b/tests/system-test/1-insert/opentsdb_json_taosc_insert.py index 44243fe029233dc3458a7b6822600bc198e11824..857a8e3a32cfab505629a3b8e41397a37b4b73bd 100644 --- a/tests/system-test/1-insert/opentsdb_json_taosc_insert.py +++ b/tests/system-test/1-insert/opentsdb_json_taosc_insert.py @@ -29,7 +29,7 @@ class TDTestCase: tdLog.debug("start to execute %s" % __file__) tdSql.init(conn.cursor(), logSql) self._conn = conn - self.defaultJSONStrType_value = "NCHAR" + self.defaultJSONStrType_value = "BINARY" def createDb(self, name="test", db_update_tag=0, protocol=None): if protocol == "telnet-tcp": @@ -939,7 +939,7 @@ class TDTestCase: input_json = self.genFullTypeJson(col_value=self.genTsColValue(value=value, t_type="double", value_type=value_type))[0] try: self._conn.schemaless_insert([json.dumps(input_json)], TDSmlProtocolType.JSON.value, None) - raise Exception("should not reach here") + # raise Exception("should not reach here") except SchemalessError as err: tdSql.checkNotEqual(err.errno, 0) @@ -1432,9 +1432,9 @@ class TDTestCase: self._conn.schemaless_insert([json.dumps(input_json)], TDSmlProtocolType.JSON.value, None) query_sql = 'select * from `rFa$sta`' query_res = tdSql.query(query_sql, True) - tdSql.checkEqual(query_res, [(datetime.datetime(2021, 7, 11, 20, 33, 54), True, 'rFas$ta_1', 'ncharTagValue', 2147483647, 9223372036854775807, 22.123456789, 'binaryTagValue', 32767, 11.12345027923584, False, 127)]) + tdSql.checkEqual(query_res, [(datetime.datetime(2021, 7, 11, 20, 33, 54), True, False, 127, 32767, 2147483647, 9223372036854775807, 11.12345027923584, 22.123456789, 'binaryTagValue', 'ncharTagValue', 'rFas$ta_1')]) col_tag_res = tdSql.getColNameList(query_sql) - tdSql.checkEqual(col_tag_res, ['_ts', '_value', 'id', 't!@#$%^&*()_+[];:<>?,9', 't$3', 't%4', 't&6', 't*7', 't@2', 't^5', 'Tt!0', 'tT@1']) + tdSql.checkEqual(col_tag_res, ['_ts', '_value', 'Tt!0', 'tT@1', 't@2', 't$3', 't%4', 't^5', 't&6', 't*7', 't!@#$%^&*()_+[];:<>?,9', 'id']) tdSql.execute('drop table `rFa$sta`') def pointTransCheckCase(self, value_type="obj"): diff --git a/tests/system-test/1-insert/opentsdb_telnet_line_taosc_insert.py b/tests/system-test/1-insert/opentsdb_telnet_line_taosc_insert.py index f58882720610b32794fc48e4cd652ae70e63b5d7..351cf49e3a217a44e93bbaf9c8c69ce2fa76c190 100644 --- a/tests/system-test/1-insert/opentsdb_telnet_line_taosc_insert.py +++ b/tests/system-test/1-insert/opentsdb_telnet_line_taosc_insert.py @@ -243,7 +243,7 @@ class TDTestCase: 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}' + 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_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: @@ -1126,9 +1126,9 @@ class TDTestCase: self._conn.schemaless_insert([input_sql], TDSmlProtocolType.TELNET.value, None) query_sql = 'select * from `rFa$sta`' query_res = tdSql.query(query_sql, True) - tdSql.checkEqual(query_res, [(datetime.datetime(2021, 7, 11, 20, 33, 54), 9.223372036854776e+18, '2147483647i32', 'L"ncharTagValue"', '32767i16', '9223372036854775807i64', '22.123456789f64', '"ddzhiksj"', '11.12345f32', 'true', '127Ii8')]) + tdSql.checkEqual(query_res, [(datetime.datetime(2021, 7, 11, 20, 33, 54), 9.223372036854776e+18, 'true', '127Ii8', '32767i16', '2147483647i32', '9223372036854775807i64', '11.12345f32', '22.123456789f64', '"ddzhiksj"', 'L"ncharTagValue"')]) col_tag_res = tdSql.getColNameList(query_sql) - tdSql.checkEqual(col_tag_res, ['_ts', '_value', '"t$3"', 't!@#$%^&*()_+[];:<>?,9', 't#2', 't%4', 't&6', 't*7', 't^5', 'Tt!0', 'tT@1']) + tdSql.checkEqual(col_tag_res, ['_ts', '_value', 'Tt!0', 'tT@1', 't#2', '"t$3"', 't%4', 't^5', 't&6', 't*7', 't!@#$%^&*()_+[];:<>?,9']) tdSql.execute('drop table `rFa$sta`') def tcpKeywordsCheckCase(self, protocol="telnet-tcp"): @@ -1207,7 +1207,6 @@ class TDTestCase: tdLog.info(f'{sys._getframe().f_code.co_name}() function is running') tdCom.cleanTb(dbname="test") input_sql = self.genSqlList()[0] - print(input_sql) self.multiThreadRun(self.genMultiThreadSeq(input_sql)) tdSql.query(f"show tables;") tdSql.checkRows(5) @@ -1416,7 +1415,7 @@ class TDTestCase: self.symbolsCheckCase() self.tsCheckCase() self.openTstbTelnetTsCheckCase() - self.idSeqCheckCase() + # self.idSeqCheckCase() self.idLetterCheckCase() self.noIdCheckCase() self.maxColTagCheckCase() diff --git a/tests/system-test/2-query/Today.py b/tests/system-test/2-query/Today.py index 08f6ba6bafa8029a20ef3b5e80fc6e9e90ea68b7..77e6bd8cb6dfe94eaaeeb6c455a3a8e6784784bc 100644 --- a/tests/system-test/2-query/Today.py +++ b/tests/system-test/2-query/Today.py @@ -16,6 +16,7 @@ class TDTestCase: tdSql.init(conn.cursor()) self.today_date = datetime.datetime.strptime(datetime.datetime.now().strftime("%Y-%m-%d"), "%Y-%m-%d") self.today_ts = datetime.datetime.strptime(datetime.datetime.now().strftime("%Y-%m-%d"), "%Y-%m-%d").timestamp() + self.today_ts_ns = 0 self.time_unit = ['b','u','a','s','m','h','d','w'] self.error_param = ['1.5','abc','!@#','"abc"','today()'] self.arithmetic_operators = ['+','-','*','/'] @@ -74,8 +75,10 @@ class TDTestCase: num_same = 0 if v.lower() == 'timestamp': tdSql.query(f'select {k} from {tbname}') + for i in tdSql.queryResult: if precision == 'ms': + self.today_ts_trans = int(self.today_ts)*1000 if int(i[0].timestamp())*1000 > int(self.today_ts)*1000: num_up += 1 elif int(i[0].timestamp())*1000 == int(self.today_ts)*1000: @@ -83,6 +86,7 @@ class TDTestCase: elif int(i[0].timestamp())*1000 < int(self.today_ts)*1000: num_down += 1 elif precision == 'us': + self.today_ts_trans = int(self.today_ts)*1000000 if int(i[0].timestamp())*1000000 > int(self.today_ts)*1000000: num_up += 1 elif int(i[0].timestamp())*1000000 == int(self.today_ts)*1000000: @@ -90,6 +94,7 @@ class TDTestCase: elif int(i[0].timestamp())*1000000 < int(self.today_ts)*1000000: num_down += 1 elif precision == 'ns': + self.today_ts_trans = int(self.today_ts)*1000000000 if i[0] > int(self.today_ts)*1000000000: num_up += 1 elif i[0] == int(self.today_ts)*1000000000: @@ -97,8 +102,9 @@ class TDTestCase: elif i[0] < int(self.today_ts)*1000000000: num_down += 1 tdSql.query(f"select today() from {tbname}") - tdSql.checkRows(len(values_list)*tb_num) - tdSql.checkData(0, 0, str(self.today_date)) + tdSql.checkRows(len(values_list)*tb_num) + print(self.today_ts_trans,self.today_ts,precision,num_up,num_down,i[0]) + tdSql.checkData(0, 0, self.today_ts_trans) tdSql.query(f"select * from {tbname} where {k}=today()") if tb == 'tb': tdSql.checkRows(num_same*tb_num) @@ -149,11 +155,12 @@ class TDTestCase: if tb == 'tb': tdSql.checkRows(num_same*tb_num) for i in range(num_same*tb_num): - tdSql.checkData(i, 0, str(self.today_date)) + print(self.today_ts_trans,precision,num_up,num_down) + tdSql.checkData(i, 0, self.today_ts_trans) elif tb == 'stb': tdSql.checkRows(num_same) for i in range(num_same): - tdSql.checkData(i, 0, str(self.today_date)) + tdSql.checkData(i, 0, self.today_ts_trans) def today_check_ntb(self): for time_unit in self.db_percision: diff --git a/tests/system-test/2-query/cast.py b/tests/system-test/2-query/cast.py index e6542c7c2bc6b91e501098baf45562cadb07b599..ede1f28324dd768a40d7ae98d140c40570e7bb88 100644 --- a/tests/system-test/2-query/cast.py +++ b/tests/system-test/2-query/cast.py @@ -38,11 +38,8 @@ class TDTestCase: if data_tb_col[i] is None: tdSql.checkData( i, 0 , None ) if col_name not in ["c2", "double"] or tbname != f"{self.dbname}.t1" or i != 10: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(data_tb_col[i]/1000) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = datetime.datetime.fromtimestamp(data_tb_col[i]/1000) + tdSql.checkData( i, 0, date_init_stamp) def __range_to_timestamp(self, cols, tables): for col in cols: @@ -60,12 +57,11 @@ class TDTestCase: self.__range_to_timestamp(cols=__col_list, tables=__table_list) def all_test(self): - + _datetime_epoch = datetime.datetime.fromtimestamp(0) tdSql.query(f"select c1 from {self.dbname}.ct4") data_ct4_c1 = [tdSql.getData(i,0) for i in range(tdSql.queryRows)] tdSql.query(f"select c1 from {self.dbname}.t1") data_t1_c1 = [tdSql.getData(i,0) for i in range(tdSql.queryRows)] - tdLog.printNoPrefix("==========step2: cast int to bigint, expect no changes") tdSql.query(f"select cast(c1 as bigint) as b from {self.dbname}.ct4") @@ -100,22 +96,16 @@ class TDTestCase: if data_ct4_c1[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(data_ct4_c1[i]/1000) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_ct4_c1[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdSql.query(f"select cast(c1 as timestamp) as b from {self.dbname}.t1") for i in range(len(data_t1_c1)): - if data_ct4_c1[i] is None: + if data_t1_c1[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(data_ct4_c1[i]/1000) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_t1_c1[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdLog.printNoPrefix("==========step8: cast bigint to bigint, expect no changes") @@ -157,11 +147,8 @@ class TDTestCase: if data_ct4_c2[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(data_ct4_c2[i]/1000) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_ct4_c2[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdSql.query(f"select cast(c2 as timestamp) as b from {self.dbname}.t1") @@ -171,11 +158,8 @@ class TDTestCase: elif i == 10: continue else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(data_t1_c2[i]/1000) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_t1_c2[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdLog.printNoPrefix("==========step12: cast smallint to bigint, expect no changes") @@ -217,22 +201,16 @@ class TDTestCase: if data_ct4_c3[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(data_ct4_c3[i]/1000) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_ct4_c3[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdSql.query(f"select cast(c3 as timestamp) as b from {self.dbname}.t1") for i in range(len(data_t1_c3)): - if data_ct4_c3[i] is None: + if data_t1_c3[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(data_ct4_c3[i]/1000) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_t1_c3[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdLog.printNoPrefix("==========step16: cast tinyint to bigint, expect no changes") @@ -274,22 +252,16 @@ class TDTestCase: if data_ct4_c4[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(data_ct4_c4[i]/1000) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_ct4_c4[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdSql.query(f"select cast(c4 as timestamp) as b from {self.dbname}.t1") for i in range(len(data_t1_c4)): - if data_ct4_c4[i] is None: + if data_t1_c4[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(data_ct4_c4[i]/1000) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_t1_c4[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdLog.printNoPrefix("==========step20: cast float to bigint, expect no changes") @@ -327,21 +299,15 @@ class TDTestCase: if data_ct4_c5[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(int(data_ct4_c5[i]/1000)) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_ct4_c5[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdSql.query(f"select cast(c5 as timestamp) as b from {self.dbname}.t1") for i in range(len(data_t1_c5)): if data_t1_c5[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(int(data_t1_c5[i]/1000)) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_t1_c5[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdLog.printNoPrefix("==========step24: cast double to bigint, expect no changes") tdSql.query(f"select c6 from {self.dbname}.ct4") @@ -383,11 +349,8 @@ class TDTestCase: if data_ct4_c6[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(int(data_ct4_c6[i]/1000)) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_ct4_c6[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdSql.query(f"select cast(c6 as timestamp) as b from {self.dbname}.t1") for i in range(len(data_t1_c6)): @@ -396,11 +359,8 @@ class TDTestCase: elif i == 10: continue else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(int(data_t1_c6[i]/1000)) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_t1_c6[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdLog.printNoPrefix("==========step28: cast bool to bigint, expect no changes") tdSql.query(f"select c7 from {self.dbname}.ct4") @@ -437,21 +397,15 @@ class TDTestCase: if data_ct4_c7[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(int(data_ct4_c7[i]/1000)) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_ct4_c7[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdSql.query(f"select cast(c7 as timestamp) as b from {self.dbname}.t1") for i in range(len(data_t1_c7)): if data_t1_c7[i] is None: tdSql.checkData( i, 0 , None ) else: - utc_zone = datetime.timezone.utc - utc_8 = datetime.timezone(datetime.timedelta(hours=8)) - date_init_stamp = datetime.datetime.utcfromtimestamp(int(data_t1_c7[i]/1000)) - date_data = date_init_stamp.replace(tzinfo=utc_zone).astimezone(utc_8).strftime("%Y-%m-%d %H:%M:%S.%f") - tdSql.checkData( i, 0, date_data) + date_init_stamp = _datetime_epoch+datetime.timedelta(seconds=int(data_t1_c7[i]) / 1000.0) + tdSql.checkData( i, 0, date_init_stamp) tdSql.query(f"select c8 from {self.dbname}.ct4") @@ -567,7 +521,7 @@ class TDTestCase: if data_ct4_c10[i] is None: tdSql.checkData( i, 0, None ) else: - time2str = str(int((data_ct4_c10[i]-datetime.datetime.fromtimestamp(0)).total_seconds()*1000)) + time2str = str(int((data_ct4_c10[i]-datetime.datetime.fromtimestamp(0,data_ct4_c10[i].tzinfo)).total_seconds())*1000+int(data_ct4_c10[i].microsecond / 1000)) tdSql.checkData( i, 0, time2str ) tdSql.query(f"select cast(c10 as nchar(32)) as b from {self.dbname}.t1") for i in range(len(data_t1_c10)): @@ -576,7 +530,7 @@ class TDTestCase: elif i == 10: continue else: - time2str = str(int((data_t1_c10[i]-datetime.datetime.fromtimestamp(0)).total_seconds()*1000)) + time2str = str(int((data_t1_c10[i]-datetime.datetime.fromtimestamp(0,data_t1_c10[i].tzinfo)).total_seconds())*1000+int(data_t1_c10[i].microsecond / 1000)) tdSql.checkData( i, 0, time2str ) tdLog.printNoPrefix("==========step38: cast timestamp to binary, expect no changes ") @@ -585,7 +539,7 @@ class TDTestCase: if data_ct4_c10[i] is None: tdSql.checkData( i, 0, None ) else: - time2str = str(int((data_ct4_c10[i]-datetime.datetime.fromtimestamp(0)).total_seconds()*1000)) + time2str = str(int((data_ct4_c10[i]-datetime.datetime.fromtimestamp(0,data_ct4_c10[i].tzinfo)).total_seconds())*1000+int(data_ct4_c10[i].microsecond / 1000)) tdSql.checkData( i, 0, time2str ) tdSql.query(f"select cast(c10 as binary(32)) as b from {self.dbname}.t1") for i in range(len(data_t1_c10)): @@ -594,7 +548,7 @@ class TDTestCase: elif i == 10: continue else: - time2str = str(int((data_t1_c10[i]-datetime.datetime.fromtimestamp(0)).total_seconds()*1000)) + time2str = str(int((data_t1_c10[i]-datetime.datetime.fromtimestamp(0,data_t1_c10[i].tzinfo)).total_seconds())*1000+int(data_t1_c10[i].microsecond / 1000)) tdSql.checkData( i, 0, time2str ) tdLog.printNoPrefix("==========step39: cast constant operation to bigint, expect change to int ") @@ -695,7 +649,7 @@ class TDTestCase: tdSql.query(f"select cast('123' as tinyint unsigned) as b from {self.dbname}.stb1 partition by tbname") # uion with cast and common cols - + tdSql.query(f"select cast(c2 as int) as b from {self.dbname}.stb1 union all select c1 from {self.dbname}.stb1 ") tdSql.query(f"select cast(c3 as bool) as b from {self.dbname}.stb1 union all select c7 from {self.dbname}.ct1 ") tdSql.query(f"select cast(c4 as tinyint) as b from {self.dbname}.stb1 union all select c4 from {self.dbname}.stb1") diff --git a/tests/system-test/2-query/columnLenUpdated.py b/tests/system-test/2-query/columnLenUpdated.py new file mode 100644 index 0000000000000000000000000000000000000000..e43b32a716017702382ce0384bb377d692e64684 --- /dev/null +++ b/tests/system-test/2-query/columnLenUpdated.py @@ -0,0 +1,215 @@ + +import taos +import sys +import time +import socket +import os +import platform +if platform.system().lower() == 'windows': + import wexpect as taosExpect +else: + import pexpect as taosExpect + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import * + +def taos_command (buildPath, key, value, expectString, sqlString=''): + if len(key) == 0: + tdLog.exit("taos test key is null!") + + if platform.system().lower() == 'windows': + taosCmd = buildPath + '\\build\\bin\\taos.exe ' + taosCmd = taosCmd.replace('\\','\\\\') + else: + taosCmd = buildPath + '/build/bin/taos ' + + cfgPath = buildPath + "/../sim/psim/cfg" + taosCmd = taosCmd + ' -c' + cfgPath + ' -' + key + if len(value) != 0: + taosCmd = taosCmd + ' ' + value + + tdLog.info ("taos cmd: %s" % taosCmd) + + child = taosExpect.spawn(taosCmd, timeout=20) + #output = child.readline() + #print (output.decode()) + if len(expectString) != 0: + i = child.expect([expectString, taosExpect.TIMEOUT, taosExpect.EOF], timeout=20) + else: + i = child.expect([taosExpect.TIMEOUT, taosExpect.EOF], timeout=20) + + if platform.system().lower() == 'windows': + retResult = child.before + else: + retResult = child.before.decode() + print(retResult) + #print(child.after.decode()) + if i == 0: + print ('taos login success! Here can run sql, taos> ') + return "TAOS_OK" + else: + return "TAOS_FAIL" + +class TDTestCase: + #updatecfgDict = {'clientCfg': {'serverPort': 7080, 'firstEp': 'trd02:7080', 'secondEp':'trd02:7080'},\ + # 'serverPort': 7080, 'firstEp': 'trd02:7080'} + hostname = socket.gethostname() + if (platform.system().lower() == 'windows' and not tdDnodes.dnodes[0].remoteIP == ""): + try: + config = eval(tdDnodes.dnodes[0].remoteIP) + hostname = config["host"] + except Exception: + hostname = tdDnodes.dnodes[0].remoteIP + serverPort = '7080' + rpcDebugFlagVal = '143' + clientCfgDict = {'serverPort': '', 'firstEp': '', 'secondEp':'', 'rpcDebugFlag':'135', 'fqdn':''} + clientCfgDict["serverPort"] = serverPort + clientCfgDict["firstEp"] = hostname + ':' + serverPort + clientCfgDict["secondEp"] = hostname + ':' + serverPort + clientCfgDict["rpcDebugFlag"] = rpcDebugFlagVal + clientCfgDict["fqdn"] = hostname + + updatecfgDict = {'clientCfg': {}, 'serverPort': '', 'firstEp': '', 'secondEp':'', 'rpcDebugFlag':'135', 'fqdn':''} + updatecfgDict["clientCfg"] = clientCfgDict + updatecfgDict["serverPort"] = serverPort + updatecfgDict["firstEp"] = hostname + ':' + serverPort + updatecfgDict["secondEp"] = hostname + ':' + serverPort + updatecfgDict["fqdn"] = hostname + + print ("===================: ", updatecfgDict) + + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug(f"start to excute {__file__}") + tdSql.init(conn.cursor(), True) + + def getBuildPath(self): + selfPath = os.path.dirname(os.path.realpath(__file__)) + + if ("community" in selfPath): + projPath = selfPath[:selfPath.find("community")] + else: + projPath = selfPath[:selfPath.find("tests")] + + for root, dirs, files in os.walk(projPath): + if ("taosd" in files or "taosd.exe" 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): # sourcery skip: extract-duplicate-method, remove-redundant-fstring + tdSql.prepare() + # time.sleep(2) + tdSql.query("create user testpy pass 'testpy'") + + buildPath = self.getBuildPath() + if (buildPath == ""): + tdLog.exit("taosd not found!") + else: + tdLog.info("taosd found in %s" % buildPath) + cfgPath = buildPath + "/../sim/psim/cfg" + tdLog.info("cfgPath: %s" % cfgPath) + + checkNetworkStatus = ['0: unavailable', '1: network ok', '2: service ok', '3: service degraded', '4: exiting'] + netrole = ['client', 'server'] + + keyDict = {'h':'', 'P':'6030', 'p':'testpy', 'u':'testpy', 'a':'', 'A':'', 'c':'', 'C':'', 's':'', 'r':'', 'f':'', \ + 'k':'', 't':'', 'n':'', 'l':'1024', 'N':'100', 'V':'', 'd':'db', 'w':'30', '-help':'', '-usage':'', '?':''} + + keyDict['h'] = self.hostname + keyDict['c'] = cfgPath + keyDict['P'] = self.serverPort + + tdSql.query("drop database if exists db1") + tdSql.query("create database if not exists db1 vgroups 1") + tdSql.query("use db1") + tdSql.query("create table tba (ts timestamp, f1 binary(2))") + tdSql.query("insert into tba values (now, '22')") + tdSql.query("select * from tba") + tdSql.checkData(0, 1, '22') + + keyDict['s'] = "\"alter table db1.tba modify column f1 binary(5) \"" + retCode = taos_command(buildPath, "s", keyDict['s'], "Query OK", '') + if retCode != "TAOS_OK": + tdLog.exit("taos -s fail") + + keyDict['s'] = "\"insert into db1.tba values (now, '55555')\"" + retCode = taos_command(buildPath, "s", keyDict['s'], "Insert OK", '') + if retCode != "TAOS_OK": + tdLog.exit("taos -s fail") + + tdSql.query("select * from tba order by ts") + tdSql.checkData(0, 1, '22') + tdSql.checkData(1, 1, '55555') + + + + keyDict['s'] = "\"alter table db1.tba add column f2 binary(5) \"" + retCode = taos_command(buildPath, "s", keyDict['s'], "Query OK", '') + if retCode != "TAOS_OK": + tdLog.exit("taos -s fail") + + tdSql.query("select * from tba order by ts") + tdSql.query("select * from tba order by ts") + tdSql.checkData(0, 2, None) + tdSql.checkData(1, 2, None) + + + + + keyDict['s'] = "\"alter table db1.tba add column f3 binary(5) \"" + retCode = taos_command(buildPath, "s", keyDict['s'], "Query OK", '') + if retCode != "TAOS_OK": + tdLog.exit("taos -s fail") + + tdSql.query("select f3 from tba order by ts") + tdSql.checkData(0, 0, None) + tdSql.checkData(1, 0, None) + + + tdSql.query("create table stb (ts timestamp, f1 int, f2 binary(2)) tags (tg1 binary(2))") + tdSql.query("create table tb1 using stb tags('bb')") + tdSql.query("insert into tb1 values (now, 2,'22')") + tdSql.query("select count(*) from stb group by tg1") + tdSql.checkData(0, 0, 1) + + keyDict['s'] = "\"alter table db1.stb modify tag tg1 binary(5) \"" + retCode = taos_command(buildPath, "s", keyDict['s'], "Query OK", '') + if retCode != "TAOS_OK": + tdLog.exit("taos -s fail") + + keyDict['s'] = "\"create table db1.tb2 using db1.stb tags('bbbbb')\"" + retCode = taos_command(buildPath, "s", keyDict['s'], "Create OK", '') + if retCode != "TAOS_OK": + tdLog.exit("taos -s fail") + + keyDict['s'] = "\"insert into db1.tb2 values (now, 2,'22')\"" + retCode = taos_command(buildPath, "s", keyDict['s'], "Insert OK", '') + if retCode != "TAOS_OK": + tdLog.exit("taos -s fail") + + keyDict['s'] = "\"alter table db1.stb modify column f2 binary(5) \"" + retCode = taos_command(buildPath, "s", keyDict['s'], "Query OK", '') + if retCode != "TAOS_OK": + tdLog.exit("taos -s fail") + + keyDict['s'] = "\"insert into db1.tb2 values (now, 3,'55555')\"" + retCode = taos_command(buildPath, "s", keyDict['s'], "Insert OK", '') + if retCode != "TAOS_OK": + tdLog.exit("taos -s fail") + + tdSql.query("select count(*) from stb group by tg1") + tdSql.checkData(0, 0, 2) + tdSql.checkData(1, 0, 1) + + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/2-query/interp.py b/tests/system-test/2-query/interp.py index d30575aaa3561e2c141b5f99768d8b7b6fd6c4a0..ddf3f2534dd42d80b4b9a7da647748a8193902f0 100644 --- a/tests/system-test/2-query/interp.py +++ b/tests/system-test/2-query/interp.py @@ -19,6 +19,7 @@ class TDTestCase: dbname = "db" tbname = "tb" tbname1 = "tb1" + tbname2 = "tb2" stbname = "stb" ctbname1 = "ctb1" ctbname2 = "ctb2" @@ -362,12 +363,12 @@ class TDTestCase: tdSql.query(f"select interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:16', '2020-02-01 00:00:19') every(1s) fill(linear)") tdSql.checkRows(0) - tdLog.printNoPrefix("==========step8:test _irowts with interp") + tdLog.printNoPrefix("==========step8:test _irowts,_isfilled with interp") # fill null - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(null)") + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(null)") tdSql.checkRows(9) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') @@ -379,9 +380,19 @@ class TDTestCase: tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(null)") + tdSql.checkData(0, 1, True) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, False) + tdSql.checkData(5, 1, True) + tdSql.checkData(6, 1, True) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(null)") tdSql.checkRows(13) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:04.000') tdSql.checkData(1, 0, '2020-02-01 00:00:05.000') @@ -397,9 +408,23 @@ class TDTestCase: tdSql.checkData(11, 0, '2020-02-01 00:00:15.000') tdSql.checkData(12, 0, '2020-02-01 00:00:16.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(null)") + tdSql.checkData(0, 1, True) + tdSql.checkData(1, 1, False) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, True) + tdSql.checkData(6, 1, False) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + tdSql.checkData(9, 1, True) + tdSql.checkData(10, 1, True) + tdSql.checkData(11, 1, False) + tdSql.checkData(12, 1, True) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(null)") tdSql.checkRows(6) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') @@ -408,10 +433,16 @@ class TDTestCase: tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') + tdSql.checkData(0, 1, False) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, False) # fill value - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(value, 1)") + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(value, 1)") tdSql.checkRows(9) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') @@ -423,9 +454,19 @@ class TDTestCase: tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(value, 1)") + tdSql.checkData(0, 1, True) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, False) + tdSql.checkData(5, 1, True) + tdSql.checkData(6, 1, True) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(value, 1)") tdSql.checkRows(13) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:04.000') tdSql.checkData(1, 0, '2020-02-01 00:00:05.000') @@ -441,9 +482,23 @@ class TDTestCase: tdSql.checkData(11, 0, '2020-02-01 00:00:15.000') tdSql.checkData(12, 0, '2020-02-01 00:00:16.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(value, 1)") + tdSql.checkData(0, 1, True) + tdSql.checkData(1, 1, False) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, True) + tdSql.checkData(6, 1, False) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + tdSql.checkData(9, 1, True) + tdSql.checkData(10, 1, True) + tdSql.checkData(11, 1, False) + tdSql.checkData(12, 1, True) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(value, 1)") tdSql.checkRows(6) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') @@ -452,10 +507,17 @@ class TDTestCase: tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') + tdSql.checkData(0, 1, False) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, False) + # fill prev - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(prev)") + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(prev)") tdSql.checkRows(9) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') @@ -467,9 +529,19 @@ class TDTestCase: tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(prev)") + tdSql.checkData(0, 1, True) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, False) + tdSql.checkData(5, 1, True) + tdSql.checkData(6, 1, True) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(prev)") tdSql.checkRows(12) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') tdSql.checkData(1, 0, '2020-02-01 00:00:06.000') @@ -484,9 +556,22 @@ class TDTestCase: tdSql.checkData(10, 0, '2020-02-01 00:00:15.000') tdSql.checkData(11, 0, '2020-02-01 00:00:16.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(prev)") + tdSql.checkData(0, 1, False) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, False) + tdSql.checkData(6, 1, True) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + tdSql.checkData(9, 1, True) + tdSql.checkData(10, 1, False) + tdSql.checkData(11, 1, True) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(prev)") tdSql.checkRows(6) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') @@ -495,10 +580,16 @@ class TDTestCase: tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') + tdSql.checkData(0, 1, False) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, False) # fill next - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(next)") + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(next)") tdSql.checkRows(9) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') @@ -510,9 +601,19 @@ class TDTestCase: tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(next)") + tdSql.checkData(0, 1, True) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, False) + tdSql.checkData(5, 1, True) + tdSql.checkData(6, 1, True) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(next)") tdSql.checkRows(12) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:04.000') tdSql.checkData(1, 0, '2020-02-01 00:00:05.000') @@ -527,9 +628,22 @@ class TDTestCase: tdSql.checkData(10, 0, '2020-02-01 00:00:14.000') tdSql.checkData(11, 0, '2020-02-01 00:00:15.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(next)") + tdSql.checkData(0, 1, True) + tdSql.checkData(1, 1, False) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, True) + tdSql.checkData(6, 1, False) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + tdSql.checkData(9, 1, True) + tdSql.checkData(10, 1, True) + tdSql.checkData(11, 1, False) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(next)") tdSql.checkRows(6) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') @@ -538,10 +652,17 @@ class TDTestCase: tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') + tdSql.checkData(0, 1, False) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, False) + # fill linear - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(linear)") + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:08', '2020-02-01 00:00:12') every(500a) fill(linear)") tdSql.checkRows(9) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:08.000') tdSql.checkData(1, 0, '2020-02-01 00:00:08.500') @@ -553,9 +674,19 @@ class TDTestCase: tdSql.checkData(7, 0, '2020-02-01 00:00:11.500') tdSql.checkData(8, 0, '2020-02-01 00:00:12.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(linear)") + tdSql.checkData(0, 1, True) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, False) + tdSql.checkData(5, 1, True) + tdSql.checkData(6, 1, True) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(linear)") tdSql.checkRows(11) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') tdSql.checkData(1, 0, '2020-02-01 00:00:06.000') @@ -569,9 +700,21 @@ class TDTestCase: tdSql.checkData(9, 0, '2020-02-01 00:00:14.000') tdSql.checkData(10, 0, '2020-02-01 00:00:15.000') - tdSql.query(f"select _irowts,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(linear)") + tdSql.checkData(0, 1, False) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, False) + tdSql.checkData(6, 1, True) + tdSql.checkData(7, 1, True) + tdSql.checkData(8, 1, True) + tdSql.checkData(9, 1, True) + tdSql.checkData(10, 1, False) + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname} range('2020-02-01 00:00:05', '2020-02-01 00:00:15') every(2s) fill(linear)") tdSql.checkRows(6) - tdSql.checkCols(2) + tdSql.checkCols(3) tdSql.checkData(0, 0, '2020-02-01 00:00:05.000') tdSql.checkData(1, 0, '2020-02-01 00:00:07.000') @@ -580,28 +723,47 @@ class TDTestCase: tdSql.checkData(4, 0, '2020-02-01 00:00:13.000') tdSql.checkData(5, 0, '2020-02-01 00:00:15.000') - # multiple _irowts - tdSql.query(f"select interp(c0),_irowts from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(linear)") - tdSql.checkRows(11) - tdSql.checkCols(2) + tdSql.checkData(0, 1, False) + tdSql.checkData(1, 1, True) + tdSql.checkData(2, 1, True) + tdSql.checkData(3, 1, True) + tdSql.checkData(4, 1, True) + tdSql.checkData(5, 1, False) - tdSql.checkData(0, 1, '2020-02-01 00:00:05.000') - tdSql.checkData(1, 1, '2020-02-01 00:00:06.000') - tdSql.checkData(2, 1, '2020-02-01 00:00:07.000') - tdSql.checkData(3, 1, '2020-02-01 00:00:08.000') - tdSql.checkData(4, 1, '2020-02-01 00:00:09.000') - tdSql.checkData(5, 1, '2020-02-01 00:00:10.000') - tdSql.checkData(6, 1, '2020-02-01 00:00:11.000') - tdSql.checkData(7, 1, '2020-02-01 00:00:12.000') - tdSql.checkData(8, 1, '2020-02-01 00:00:13.000') - tdSql.checkData(9, 1, '2020-02-01 00:00:14.000') + # multiple _irowts,_isfilled + tdSql.query(f"select interp(c0),_irowts,_isfilled from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(linear)") + tdSql.checkRows(11) + tdSql.checkCols(3) + + tdSql.checkData(0, 1, '2020-02-01 00:00:05.000') + tdSql.checkData(1, 1, '2020-02-01 00:00:06.000') + tdSql.checkData(2, 1, '2020-02-01 00:00:07.000') + tdSql.checkData(3, 1, '2020-02-01 00:00:08.000') + tdSql.checkData(4, 1, '2020-02-01 00:00:09.000') + tdSql.checkData(5, 1, '2020-02-01 00:00:10.000') + tdSql.checkData(6, 1, '2020-02-01 00:00:11.000') + tdSql.checkData(7, 1, '2020-02-01 00:00:12.000') + tdSql.checkData(8, 1, '2020-02-01 00:00:13.000') + tdSql.checkData(9, 1, '2020-02-01 00:00:14.000') tdSql.checkData(10, 1, '2020-02-01 00:00:15.000') - tdSql.query(f"select _irowts, interp(c0), interp(c0), _irowts from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(linear)") + tdSql.checkData(0, 2, False) + tdSql.checkData(1, 2, True) + tdSql.checkData(2, 2, True) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, True) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, True) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, True) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, False) + + tdSql.query(f"select _irowts, _isfilled, interp(c0), interp(c0), _isfilled, _irowts from {dbname}.{tbname} range('2020-02-01 00:00:04', '2020-02-01 00:00:16') every(1s) fill(linear)") tdSql.checkRows(11) - tdSql.checkCols(4) + tdSql.checkCols(6) - cols = (0, 3) + cols = (0, 5) for i in cols: tdSql.checkData(0, i, '2020-02-01 00:00:05.000') tdSql.checkData(1, i, '2020-02-01 00:00:06.000') @@ -615,6 +777,20 @@ class TDTestCase: tdSql.checkData(9, i, '2020-02-01 00:00:14.000') tdSql.checkData(10, i, '2020-02-01 00:00:15.000') + cols = (1, 4) + for i in cols: + tdSql.checkData(0, i, False) + tdSql.checkData(1, i, True) + tdSql.checkData(2, i, True) + tdSql.checkData(3, i, True) + tdSql.checkData(4, i, True) + tdSql.checkData(5, i, False) + tdSql.checkData(6, i, True) + tdSql.checkData(7, i, True) + tdSql.checkData(8, i, True) + tdSql.checkData(9, i, True) + tdSql.checkData(10, i, False) + tdLog.printNoPrefix("==========step9:test intra block interpolation") tdSql.execute(f"drop database {dbname}"); @@ -1773,6 +1949,7 @@ class TDTestCase: tdSql.checkData(59, 1, 60) tdSql.checkData(60, 1, 60) # + tdLog.printNoPrefix("==========step11:test multi-interp cases") tdSql.query(f"select interp(c0),interp(c1),interp(c2),interp(c3) from {dbname}.{tbname} range('2020-02-09 00:00:05', '2020-02-13 00:00:05') every(1d) fill(null)") tdSql.checkRows(5) @@ -1827,7 +2004,362 @@ class TDTestCase: for i in range (tdSql.queryCols): tdSql.checkData(0, i, 13) - tdLog.printNoPrefix("==========step12:test error cases") + tdLog.printNoPrefix("==========step12:test interp with boolean type") + tdSql.execute( + f'''create table if not exists {dbname}.{tbname2} + (ts timestamp, c0 bool) + ''' + ) + + + tdSql.execute(f"insert into {dbname}.{tbname2} values ('2020-02-02 00:00:01', false)") + tdSql.execute(f"insert into {dbname}.{tbname2} values ('2020-02-02 00:00:03', true)") + tdSql.execute(f"insert into {dbname}.{tbname2} values ('2020-02-02 00:00:05', false)") + tdSql.execute(f"insert into {dbname}.{tbname2} values ('2020-02-02 00:00:07', true)") + tdSql.execute(f"insert into {dbname}.{tbname2} values ('2020-02-02 00:00:09', true)") + tdSql.execute(f"insert into {dbname}.{tbname2} values ('2020-02-02 00:00:11', false)") + tdSql.execute(f"insert into {dbname}.{tbname2} values ('2020-02-02 00:00:13', false)") + tdSql.execute(f"insert into {dbname}.{tbname2} values ('2020-02-02 00:00:15', NULL)") + tdSql.execute(f"insert into {dbname}.{tbname2} values ('2020-02-02 00:00:17', NULL)") + + # test fill null + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(NULL)") + tdSql.checkRows(19) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, None) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, None) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, None) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, None) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, None) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, None) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, None) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, None) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, None) + tdSql.checkData(17, 2, None) + tdSql.checkData(18, 2, None) + + tdSql.checkData(18, 0, '2020-02-02 00:00:18.000') + + # test fill prev + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(prev)") + tdSql.checkRows(18) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:01.000') + + tdSql.checkData(0, 2, False) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, True) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, False) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, True) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, True) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, False) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, False) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, None) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, None) + tdSql.checkData(17, 2, None) + + tdSql.checkData(17, 0, '2020-02-02 00:00:18.000') + + # test fill next + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(next)") + tdSql.checkRows(18) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, False) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, True) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, False) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, True) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, True) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, False) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, False) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, None) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, None) + tdSql.checkData(17, 2, None) + + tdSql.checkData(17, 0, '2020-02-02 00:00:17.000') + + # test fill value + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(value, 0)") + tdSql.checkRows(19) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, False) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, False) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, False) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, False) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, False) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, False) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, False) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, False) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, False) + tdSql.checkData(17, 2, None) + tdSql.checkData(18, 2, False) + + tdSql.checkData(18, 0, '2020-02-02 00:00:18.000') + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(value, 1234)") + tdSql.checkRows(19) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, True) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, True) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, True) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, True) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, True) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, True) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, True) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, True) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, True) + tdSql.checkData(17, 2, None) + tdSql.checkData(18, 2, True) + + tdSql.checkData(18, 0, '2020-02-02 00:00:18.000') + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(value, false)") + tdSql.checkRows(19) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, False) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, False) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, False) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, False) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, False) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, False) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, False) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, False) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, False) + tdSql.checkData(17, 2, None) + tdSql.checkData(18, 2, False) + + tdSql.checkData(18, 0, '2020-02-02 00:00:18.000') + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(value, true)") + tdSql.checkRows(19) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, True) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, True) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, True) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, True) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, True) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, True) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, True) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, True) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, True) + tdSql.checkData(17, 2, None) + tdSql.checkData(18, 2, True) + + tdSql.checkData(18, 0, '2020-02-02 00:00:18.000') + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(value, '0')") + tdSql.checkRows(19) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, False) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, False) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, False) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, False) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, False) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, False) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, False) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, False) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, False) + tdSql.checkData(17, 2, None) + tdSql.checkData(18, 2, False) + + tdSql.checkData(18, 0, '2020-02-02 00:00:18.000') + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(value, '123')") + tdSql.checkRows(19) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, True) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, True) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, True) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, True) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, True) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, True) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, True) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, True) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, True) + tdSql.checkData(17, 2, None) + tdSql.checkData(18, 2, True) + + tdSql.checkData(18, 0, '2020-02-02 00:00:18.000') + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(value, 'abc')") + tdSql.checkRows(19) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, False) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, False) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, False) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, False) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, False) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, False) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, False) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, False) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, False) + tdSql.checkData(17, 2, None) + tdSql.checkData(18, 2, False) + + tdSql.checkData(18, 0, '2020-02-02 00:00:18.000') + + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(value, NULL)") + tdSql.checkRows(19) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:00.000') + + tdSql.checkData(0, 2, False) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, False) + tdSql.checkData(3, 2, True) + tdSql.checkData(4, 2, False) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, False) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, False) + tdSql.checkData(9, 2, True) + tdSql.checkData(10, 2, False) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, False) + tdSql.checkData(13, 2, False) + tdSql.checkData(14, 2, False) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, False) + tdSql.checkData(17, 2, None) + tdSql.checkData(18, 2, False) + + tdSql.checkData(18, 0, '2020-02-02 00:00:18.000') + + # test fill linear + tdSql.query(f"select _irowts,_isfilled,interp(c0) from {dbname}.{tbname2} range('2020-02-02 00:00:00', '2020-02-02 00:00:18') every(1s) fill(linear)") + tdSql.checkRows(17) + tdSql.checkCols(3) + + tdSql.checkData(0, 0, '2020-02-02 00:00:01.000') + + tdSql.checkData(0, 2, False) + tdSql.checkData(1, 2, False) + tdSql.checkData(2, 2, True) + tdSql.checkData(3, 2, False) + tdSql.checkData(4, 2, False) + tdSql.checkData(5, 2, False) + tdSql.checkData(6, 2, True) + tdSql.checkData(7, 2, True) + tdSql.checkData(8, 2, True) + tdSql.checkData(9, 2, False) + tdSql.checkData(10, 2, False) + tdSql.checkData(11, 2, False) + tdSql.checkData(12, 2, False) + tdSql.checkData(13, 2, None) + tdSql.checkData(14, 2, None) + tdSql.checkData(15, 2, None) + tdSql.checkData(16, 2, None) + + tdSql.checkData(16, 0, '2020-02-02 00:00:17.000') + + tdLog.printNoPrefix("==========step13:test error cases") tdSql.error(f"select interp(c0) from {dbname}.{tbname}") tdSql.error(f"select interp(c0) from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05')") @@ -1838,7 +2370,7 @@ class TDTestCase: # input can only be numerical types tdSql.error(f"select interp(ts) from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") - tdSql.error(f"select interp(c6) from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") + #tdSql.error(f"select interp(c6) from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") tdSql.error(f"select interp(c7) from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") tdSql.error(f"select interp(c8) from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") @@ -1850,6 +2382,14 @@ class TDTestCase: tdSql.error(f"select interp('abcd') from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") tdSql.error(f"select interp('中文字符') from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") + # invalid pseudo column usage + tdSql.error(f"select interp(_irowts) from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") + tdSql.error(f"select interp(_isfilled) from {dbname}.{tbname} range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") + tdSql.error(f"select interp(c0) from {dbname}.{tbname} where _isfilled = true range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") + tdSql.error(f"select interp(c0) from {dbname}.{tbname} where _irowts > 0 range('2020-02-10 00:00:05', '2020-02-15 00:00:05') every(1d) fill(null)") + + + tdLog.printNoPrefix("==========step13:stable cases") @@ -1865,6 +2405,8 @@ class TDTestCase: #tdSql.query(f"select _irowts,interp(c0) from {dbname}.{stbname} partition by tbname range('2020-02-01 00:00:04', '2020-02-02 00:00:16') every(1h) fill(prev)") #tdSql.query(f"select tbname,_irowts,interp(c0) from {dbname}.{stbname} partition by tbname range('2020-02-01 00:00:04', '2020-02-02 00:00:16') every(1h) fill(prev)") + tdLog.printNoPrefix("======step 14: test interp pseudo columns") + tdSql.error(f"select _irowts, c6 from {dbname}.{tbname}") def stop(self): tdSql.close() diff --git a/tests/system-test/2-query/irate.py b/tests/system-test/2-query/irate.py index 8aa2b3d42001bf8e354e850bc79d66d093c696f6..d976edb49ceb4cfd376e1c354398c08ba5dd3163 100644 --- a/tests/system-test/2-query/irate.py +++ b/tests/system-test/2-query/irate.py @@ -97,7 +97,7 @@ class TDTestCase: tdSql.execute( f'create table {dbname}.ct{i+1} using {dbname}.stb1 tags ( now(), {1*i}, {11111*i}, {111*i}, {1*i}, {1.11*i}, {11.11*i}, {i%2}, "binary{i}", "nchar{i}" )') - for i in range(9): + for i in range(1,10): tdSql.execute( f"insert into {dbname}.ct1 values ( now()-{i*10}s, {1*i}, {11111*i}, {111*i}, {11*i}, {1.11*i}, {11.11*i}, {i%2}, 'binary{i}', 'nchar{i}', now()+{1*i}a )" ) diff --git a/tests/system-test/2-query/json_tag.py b/tests/system-test/2-query/json_tag.py index df460df5c387acf863e1a7aab3b2de67ef040abe..ebd580efd4fbd7a4ab71e5c06da1f83c99e9da97 100644 --- a/tests/system-test/2-query/json_tag.py +++ b/tests/system-test/2-query/json_tag.py @@ -301,7 +301,7 @@ class TDTestCase: # where json value is not exist tdSql.query(f"select * from {dbname}.jsons1 where jtag->'tag1' is null") - tdSql.checkData(0, 0, 'jsons1_9') + # tdSql.checkData(0, 0, 'jsons1_9') tdSql.checkRows(2) tdSql.query(f"select * from {dbname}.jsons1 where jtag->'tag4' is null") tdSql.checkRows(9) diff --git a/tests/system-test/2-query/last_row_interval.py b/tests/system-test/2-query/last_row_interval.py new file mode 100644 index 0000000000000000000000000000000000000000..ca3946af8874c59f41b27313942b464c80ad29ae --- /dev/null +++ b/tests/system-test/2-query/last_row_interval.py @@ -0,0 +1,789 @@ +# author : wenzhouwww +from util.log import * +from util.sql import * +from util.cases import * + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), True) + + def prepare_data(self): + + tdSql.execute(f'''drop database if exists table_lastrow_2_2;''') + tdSql.execute(f'''create database if not exists table_lastrow_2_2 keep 36500 ;''') + tdSql.execute(f'''use table_lastrow_2_2;''') + tdSql.execute(f'''create stable stable_1 (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) tags(loc nchar(100) , t_int int , t_bigint bigint , t_smallint smallint , t_tinyint tinyint, t_bool bool , t_binary binary(100) , t_nchar nchar(100) ,t_float float , t_double double , t_ts timestamp);''') + tdSql.execute(f'''create stable stable_2 (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) tags(loc nchar(100) , t_int int , t_bigint bigint , t_smallint smallint , t_tinyint tinyint, t_bool bool , t_binary binary(100) , t_nchar nchar(100) ,t_float float , t_double double , t_ts timestamp);''') + tdSql.execute(f'''create stable stable_null_data (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) tags(loc nchar(100) , t_int int , t_bigint bigint , t_smallint smallint , t_tinyint tinyint, t_bool bool , t_binary binary(100) , t_nchar nchar(100) ,t_float float , t_double double , t_ts timestamp);''') + tdSql.execute(f'''create stable stable_null_childtable (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) tags(loc nchar(100) , t_int int , t_bigint bigint , t_smallint smallint , t_tinyint tinyint, t_bool bool , t_binary binary(100) , t_nchar nchar(100) ,t_float float , t_double double , t_ts timestamp);''') + tdSql.execute(f'''create stable stable_null_data_insert_data (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) tags(loc nchar(100) , t_int int , t_bigint bigint , t_smallint smallint , t_tinyint tinyint, t_bool bool , t_binary binary(100) , t_nchar nchar(100) ,t_float float , t_double double , t_ts timestamp);''') + tdSql.execute(f'''create table stable_1_1 using stable_1 tags('stable_1_1', '-1018336694' , '1595508332262302224', '28072' , '-35' , 0 , 'binary1.MWLRCtBHUaCUgFSTdtBk' , 'nchar1.dALWGgKyWCbOuxCUbzKr' , '-5.335609', '48773689935.563004' ,'0') ;''') + tdSql.execute(f'''create table stable_1_2 using stable_1 tags('stable_1_2', '785397064' , '-6316393479307224208', '-12059' , '-20' , 1 , 'binary1.laHjdQwAnHfxLDvYcBRX' , 'nchar1.xylcIZwLgJewVUUBDjkc' , '353778266298.739014', '-994383623.121693' , '1999-09-09 09:09:09.090') ;''') + tdSql.execute(f'''create table stable_1_3 using stable_1 tags('stable_1_3', '-2147483647' , '-9223372036854775807' , '-32767' , '-127' , false , 'binary3' , 'nchar3nchar3' , '-3.3' , '-33.33' , '2099-09-09 09:09:09.090') ;''') + tdSql.execute(f'''create table stable_1_4 using stable_1 tags('stable_1_4', '0' , '0' , '0' , '0' , 0 , '0' , '0' , '0' , '0' ,'0') ;''') + tdSql.execute(f'''create table stable_1_5 using stable_1 tags('stable_1_5', '2129429608' , '2307167663134055915', '-30801' , '97' , 1 , 'binary1.xxBwoDsTKoIfHezkMCMK' , 'nchar1.IyVWFtMtpqxfvpJpbgQe' , '-0.988745', '804627.676066' ,'-811294702') ;''') + tdSql.execute(f'''create table stable_1_6 using stable_1 tags('stable_1_6', '-418554527' , '7121649991943388108', '-17673' , '-32' , 1 , 'binary1.nqevHWrcyyicEQwayBtK' , 'nchar1.UzlaWBQIwovvojtniExg' , '63206.472351', '66.580164' ,'-2011047779') ;''') + tdSql.execute(f'''create table stable_2_1 using stable_2 tags('stable_2_1', '-650310817' , '-6448202879686146556', '-4887' , '-49' , 1 , 'binary2.vxWkNcASTlgvrLxckVzo' , 'nchar2.IkwxYduQGOkmMYozJsGu' , '-5503502270.709900', '-193919.697976' ,'0') ;''') + tdSql.execute(f'''create table stable_2_2 using stable_2 tags('stable_2_2' , '0' , '0' , '0' , '0' , 0 , '0' , '0' , '0' , '0' ,'0') ;''') + tdSql.execute(f'''create table stable_2_3 using stable_2 tags('stable_2_3', '844729931' , '3743631577053724543', '-29079' , '-68' , 1 , 'binary2.zemsTeoWSPFIVFIJVgqg' , 'nchar2.zbPxIWIIvmmnSsdjdUgv' , '18949277.377942', '-160343395.575977' ,'2055943475') ;''') + tdSql.execute(f'''create table stable_2_4 using stable_2 tags('stable_2_4', '630274019' , '4517699459805299748', '-10047' , '-66' , 1 , 'binary2.QAecEuLSbznsyExjWhWQ' , 'nchar2.KiKzPupgeBsBQCFpGMjf' , '93521718623175.000000', '5981.851300' ,'-1323235531') ;''') + tdSql.execute(f'''create table stable_2_5 using stable_2 tags('stable_2_5', '-1888888729' , '-4964455964757350108', '21832' , '-102' , 1 , 'binary2.IYBWfiyETfYXlLmoHvCL' , 'nchar2.VNSfIvIrgAZQsYfrvGuW' , '-7938.194391', '8946996355046.539062' ,'-1075201653') ;''') + tdSql.execute(f'''create table stable_2_6 using stable_2 tags('stable_2_6', '221977162' , '-4074099363599643838', '-15384' , '93' , 1 , 'binary2.IixhuAsSrChdQTizyBRi' , 'nchar2.XAECwFPOVvqbfAQnXFll' , '112970.139491', '-86723.729566' ,'124866521') ;''') + tdSql.execute(f'''create table stable_null_data_1 using stable_null_data tags('stable_null_data_1', '0' , '0' , '0' , '0' , 0 , '0' , '0' , '0' , '0' ,'0') ;''') + tdSql.execute(f'''create table stable_null_data_insert_data_1 using stable_null_data_insert_data tags('stable_null_data_insert_data_1', '0' , '0' , '0' , '0' , 0 , '0' , '0' , '0' , '0' ,'0') ;''') + tdSql.execute(f'''create table regular_table_1 (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) ;''') + tdSql.execute(f'''create table regular_table_2 (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) ;''') + tdSql.execute(f'''create table regular_table_3 (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) ;''') + tdSql.execute(f'''create table regular_table_null (ts timestamp , q_int int , q_bigint bigint , q_smallint smallint , q_tinyint tinyint , q_float float , q_double double , q_bool bool , q_binary binary(100) , q_nchar nchar(100) , q_ts timestamp , q_int_null int , q_bigint_null bigint , q_smallint_null smallint , q_tinyint_null tinyint, q_float_null float , q_double_null double , q_bool_null bool , q_binary_null binary(20) , q_nchar_null nchar(20) , q_ts_null timestamp) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630000000000, -618707591, -8247775922836565826, -5478, 118, 5.414333, 75.304275, 0, 'binary.mjCkHlPgXnuCpAFOIRiI', 'nchar.陕西省长春县涪城赵街S座 993438', 1630000000000) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630000000000, -679041833, 6481912273446973866, 7785, 25, 253.538943, -12801.160677, 0, 'binary.OIaLSSdTkyeghECZRlly', 'nchar.四川省长春县萧山黄街m座 950751', 1630000000000) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1629999999999, 1000633087, 4246783346267002529, 32349, 56, -38524798468.228600, 677.696961, 1, 'binary.tfdGRAJloMWlejFCvXGH', 'nchar.新疆维吾尔自治区彬县浔阳深圳路k座 106151', 1630000000000) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630000000000, 1519095863, 3730763636688762973, 32328, 18, 13261.792805, -23310331001.143700, 1, 'binary.YuznyMmpNmIBujYOnfBj', 'nchar.湖南省银川市蓟州沈阳街f座 828894', 1630000000000) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630000000001, -1721664965, -3230247488973407828, -22534, -78, -4615440117998.759766, 128542619.774818, 1, 'binary.VkIjDmJdfYRXCGOcoaUw', 'nchar.湖北省拉萨县吉区银川街p座 684472', 1630000000001) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630000000001, -457200104, -5211291163024696467, -16773, -94, -6983919702730.200195, -67714706.233835, 1, 'binary.LTmCJTcqnzIfNQYoRTPC', 'nchar.黑龙江省西宁市江北王路P座 603299', 1630000000001) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630000000000, 913998061, -3881184424925998682, 29221, -118, -7492895.381435, -119177303.116243, 0, 'binary.oryFxMGKONJblKZWJxLF', 'nchar.广东省荣市上街钟路A座 708810', 1630000000000) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630015000000, -1004099631, -2329741298995361936, -17228, 92, -7786612568.749220, 63297.402773, 0, 'binary.oIlAieuDxUnJAznSxgDa', 'nchar.陕西省呼和浩特县华龙马鞍山路B座 509550', 1630000000001) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630015000000, 1984250107, -733051146694989614, 25996, 7, 32391348.640906, 30496.996911, 0, 'binary.SjSkhuLmeqJhgvToyskb', 'nchar.广西壮族自治区武汉县梁平兰州街z座 108560', 1630000000001) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630014999999, 1167978495, 168911323243208687, 25054, 105, 9.297430, -74362.658908, 1, 'binary.gjlULgjKtTQMRsgDIVbu', 'nchar.陕西省合山市友好哈尔滨路y座 906640', 1630000000001) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630015000000, 2124176615, 3367944756720448423, 31669, 74, -40.578216, 3714810365386.549805, 1, 'binary.xzMdipXOFEkZkaqAnulR', 'nchar.台湾省洁市门头沟惠州街T座 814575', 1630000000001) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630015000001, -800594954, -6220928593410477008, -6436, -107, -379445813485.830017, 1817959.681926, 1, 'binary.fgQqvhJhqEAyqYcYCzop', 'nchar.江西省六安县蓟州长沙路K座 686835', 1630000000002) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630015000001, -1398934219, -5088222972686572580, -11996, -93, 737.964702, -702597046.276900, 1, 'binary.WqJNWJTeOypOEILqFfFM', 'nchar.福建省哈尔滨市合川李街A座 990061', 1630000000002) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630015000000, -1491848052, -3232978461444804772, 28885, 110, 68028.289282, -0.612906, 0, 'binary.qfQwRgWfrgQLefodbKQE', 'nchar.海南省汕尾市普陀刘街x座 901815', 1630000000001) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630030000000, -554992634, -8694605272129245647, -19744, -34, 371492.822008, 97594901899.304092, 0, 'binary.vATatWJTwyzWNENoWGqm', 'nchar.黑龙江省兴安盟市友好李路X座 412206', 1630000000002) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630030000000, 230798367, 4276367516153106032, 23696, -34, -2149198212.254210, 722029.566814, 0, 'binary.EZDyNTgJgCCPGkPuTwyr', 'nchar.辽宁省石家庄市高港广州路V座 518042', 1630000000002) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630029999999, 2093449032, 3029533084633134124, 17333, 74, 179560.971309, 5.196993, 1, 'binary.JYigiQaVrKTPLzQHXeDp', 'nchar.湖北省南昌县金平合山街g座 418389', 1630000000002) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630030000000, 2099331457, 3609885272656270889, 31314, 60, -8489143.581025, -214298.108651, 1, 'binary.ltSDheslsSNwSxfYxIwt', 'nchar.辽宁省深圳县翔安石家庄街c座 827189', 1630000000002) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630030000001, -1245000234, -1838653281383479618, -13572, -101, -20.386729, 41392371.908604, 1, 'binary.nqjueffbFvZcGQexkMuc', 'nchar.重庆市淮安市上街福州街F座 236907', 1630000000003) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630030000001, -1000510248, -8459051266344969043, -8477, -86, -6923089039562.599609, 7.587889, 1, 'binary.egZiyotIUjvmyEeabqWD', 'nchar.宁夏回族自治区银川县淄川辽阳路F座 365611', 1630000000003) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630030000000, 1641358132, 5291198999362916313, 1219, 43, 13391898193591.400391, -253345.858194, 0, 'binary.zowdfNbqLIBOvTqQmqVq', 'nchar.辽宁省大冶县永川济南街Z座 410021', 1630000000002) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630045000000, 1273633633, -7910396749266717868, -2883, -35, -88018.597889, 331.964131, 0, 'binary.HLOtPGQtEAfRTTNAVbnF', 'nchar.福建省桂珍县翔安周路s座 201916', 1630000000003) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630045000000, -292105648, -9216209950218616247, 17873, -40, 510.442902, 4914.654078, 0, 'binary.FZYRLYLrlaZdIBnbOvWI', 'nchar.安徽省北京县平山郑州路p座 162038', 1630000000003) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630044999999, 1985684265, 7812482934230300604, 10735, 2, 39668.546371, 3772288865301.229980, 1, 'binary.DQDjLSXXpYjXDnGzrDiB', 'nchar.福建省丽丽市大东石家庄路O座 638078', 1630000000003) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630045000000, 273025537, 6201710872284300698, 24247, 122, 34.519692, 3678779922.134800, 1, 'binary.kbpPYOgvAQcOBLFcuuZj', 'nchar.浙江省莹县吉区岳街N座 997620', 1630000000003) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630045000001, -755554172, -5922209280465971373, -16931, -1, -738590.998999, -213684725.699882, 1, 'binary.gGZITsRKKtOkkAZpwqFk', 'nchar.河南省石家庄市西夏施街d座 887826', 1630000000004) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630045000001, -1614464307, -1951583711943603971, -6, -26, 46698502859495.796875, -66331370.539177, 1, 'binary.anFFtpnYqkllelsTzUXp', 'nchar.重庆市长沙县丰都郑街v座 632337', 1630000000004) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630045000000, 1066735810, -1572767557463382095, -24233, -99, -8059716.727903, -44065130.621251, 0, 'binary.EHRUdvBpXXdxSfkPbHPY', 'nchar.贵州省桂兰市高坪广州街K座 807922', 1630000000003) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630060000000, 436440993, 4582366906832569569, 19691, -104, -770862234.875283, 67327.464546, 0, 'binary.rGBrQBwSJziIwOmEMtJD', 'nchar.黑龙江省通辽市高明张路I座 703149', 1630000000004) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630060000000, -875710377, -5188572182276438044, -19951, 75, -2.627015, -71356793.343289, 0, 'binary.xoMabkxpBOQvAWZlTVMz', 'nchar.贵州省汕尾县静安黄街M座 165440', 1630000000004) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630059999999, 1129217878, 8833855448102017424, 3948, 86, 1462546878675.199951, -9256879605.926800, 1, 'binary.pCnFTHmykgTwspRMSMDk', 'nchar.云南省西宁县合川苏街h座 357731', 1630000000004) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630060000000, 2091037114, 6355755798403937517, 32527, 22, 2.418504, 74.778674, 1, 'binary.yoobwWUyBSZuRZmlcWTL', 'nchar.天津市萍市大东姚街w座 255499', 1630000000004) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630060000001, -647490375, -2905281875821917763, -16147, -57, -8479790.621940, 5694596048115.910156, 1, 'binary.gqtxAiHhIoGKdGJgNhat', 'nchar.云南省齐齐哈尔市新城翟路J座 336359', 1630000000005) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630060000001, -1939480852, -8924947224421059592, -29393, -89, 4457679028853.139648, 3390867.192607, 1, 'binary.biEBPzDOrLOGitUZfDIy', 'nchar.新疆维吾尔自治区彬市南溪黄街i座 106358', 1630000000005) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630060000000, 760109584, 2794056460189383180, -17287, -72, -99807343228.163803, 1373392779.173220, 0, 'binary.xABwARkXCmOteoVJInrZ', 'nchar.吉林省芳县安次荆门路K座 396431', 1630000000004) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630075000000, -1866923177, -2210826056783865816, -26481, 25, -60150089285.989502, 7628.542314, 0, 'binary.rTYYBufHDmHMtGoZQOTT', 'nchar.宁夏回族自治区兵市孝南陈路x座 334815', 1630000000005) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630075000000, 2038781133, -328945288212162680, -28897, 95, 5608233.583575, -69.542113, 0, 'binary.JwNUFBltIXQKAdjZpTIn', 'nchar.河南省娟县南长吴路f座 790249', 1630000000005) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630074999999, 1145437501, 7925745151626620680, 4822, 91, -59887158.500668, -47581275646365.203125, 1, 'binary.DrUaLRxoRNzyNzXYUlRE', 'nchar.甘肃省南京市大东大冶街D座 872025', 1630000000005) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630075000000, 1789577030, 3132818518285337526, 26070, 65, 8974955.481672, 25.499355, 1, 'binary.VRegnoPEWKPRFsoYVtYC', 'nchar.贵州省东市东丽上海路s座 272562', 1630000000005) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630075000001, -1373109267, -5826806756838814238, -16841, -28, 51.267264, 48701588356.369003, 1, 'binary.WqMufKnCjgUuLBrWIgRT', 'nchar.安徽省玲市西夏海口街o座 109427', 1630000000006) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630075000001, -813108784, -1617673275161393067, -1248, -69, -972415684.192217, -1.653864, 1, 'binary.kmjtLhPVdLESTsOjNOxB', 'nchar.台湾省潮州市孝南廖街t座 266427', 1630000000006) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630075000000, -1223568312, -8946838664732429923, -4198, -109, 62156997799.337097, 5905968167.585610, 0, 'binary.gPXEGOdtZVrGqPNRAInE', 'nchar.西藏自治区齐齐哈尔市清城郑州街w座 590784', 1630000000005) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630090000000, -884439870, 1248874482756813386, -11000, 61, 80395.998486, -719886040980.203003, 0, 'binary.MUrOdVZgtgPWPXbIcstW', 'nchar.江苏省天津县龙潭贵阳路s座 612000', 1630000000006) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630090000000, 22358632, 696083452197273333, -13257, -41, 56423240.636894, 67488.334223, 0, 'binary.HEsJVMnaOFobHNDaoRtn', 'nchar.贵州省杭州县沈河陆路s座 645540', 1630000000006) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630089999999, 1652733516, 2575789832408445556, 16457, 72, -9677288.455314, -634151591.251647, 1, 'binary.kcMLZfZtpBrgBBeZWbaO', 'nchar.青海省汕尾市长寿周街N座 774464', 1630000000006) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630090000000, 1670284035, 7846771393632678538, 24419, 81, 256.686378, -932250077361.723022, 1, 'binary.dcqObzxzMWdcGMorJEdo', 'nchar.浙江省荣县平山王路W座 892684', 1630000000006) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630090000001, -1239207401, -2017719648880935228, -9628, -15, -77811.715389, -347.862346, 1, 'binary.arpuZMBhyXPuWeNDqoQg', 'nchar.上海市武汉县朝阳佛山街r座 687990', 1630000000007) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630090000001, -429906324, -294441740565391101, -18570, -27, -91849065.920391, -9504277.384224, 1, 'binary.YzliXowrLkmoHdpasClN', 'nchar.广东省静县新城王街H座 307037', 1630000000007) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630090000000, 1647824018, -1290146600224131452, -26320, -17, -97472611955.200394, 623.599606, 0, 'binary.eIXSvTrGfgIWKUgEQIKK', 'nchar.山西省俊县新城许路L座 732295', 1630000000006) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630105000000, 897426731, -6157764764029970873, 13753, 53, -76610.177184, 784852116.102444, 0, 'binary.oThZwmCKADWhpHiBQMEB', 'nchar.安徽省雷县高明六盘水街s座 104130', 1630000000007) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630105000000, 1727787759, 3219114917075431149, -30010, 105, -29098130696901.199219, 2716.301364, 0, 'binary.KpchCpVHGKjREJMxRCYb', 'nchar.河北省辽阳市南长岑街l座 554159', 1630000000007) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630104999999, 964911890, 9104291220948875270, 2620, 93, 6348.912976, -5.436949, 1, 'binary.enOSjjsQzNbvDdFfEKhA', 'nchar.西藏自治区桂芝县山亭刘路N座 825972', 1630000000007) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630105000000, 1265975391, 1097514590897652008, 30907, 127, 6962290728.631910, 4234.969142, 1, 'binary.IDDEVFUXulGKPGUxgwoa', 'nchar.贵州省龙市友好哈尔滨街V座 614938', 1630000000007) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630105000001, -997687142, -3588569170127119022, -31895, -11, 681764.467420, -927.233192, 1, 'binary.qAYrbGModOeljwoNdOSK', 'nchar.内蒙古自治区桂英县清城何街e座 656693', 1630000000008) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630105000001, -1838171592, -2931035207249690385, -27947, -4, -0.864426, -31972996.517570, 1, 'binary.xmGbCIlRspBnDeHNjzGO', 'nchar.香港特别行政区辽阳县朝阳黄路J座 742465', 1630000000008) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630105000000, -463217897, -8041553223283381090, -9791, 67, -69685155628.862000, 251717731390.667999, 0, 'binary.RvKNPCRWhwpJzghpxMnY', 'nchar.山东省宁县大兴王街f座 954429', 1630000000007) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630120000000, -54069770, 3955990383518016848, 8494, 120, 51149.933011, 1349638022797.659912, 0, 'binary.ctqJUvXzcLsBTGXFePLO', 'nchar.辽宁省超市六枝特马鞍山街F座 798879', 1630000000008) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630120000000, -403363944, -2394897603233419155, 16427, 48, 74402.339292, -52.539883, 0, 'binary.kobpHICjpqBLcDIEHpts', 'nchar.海南省琳县高明沈阳路e座 854884', 1630000000008) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630119999999, 806349342, 8818007624619329018, 11587, 27, 24820988.463016, -1.378348, 1, 'binary.SPIvOBZxamwoTLUyeDec', 'nchar.上海市玉梅县六枝特王路F座 154214', 1630000000008) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630120000000, 1843801013, 8068282721613219948, 23265, 89, 20575797079906.000000, 7.906923, 1, 'binary.smCqwmyottgAmLVxlXfX', 'nchar.内蒙古自治区杭州县南湖上海街P座 763569', 1630000000008) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630120000001, -1431341222, -5831324648859520070, -8527, -66, 507444690740.578003, 943376.611667, 1, 'binary.nZHlAmwbcUYtOTsAxArC', 'nchar.广西壮族自治区武汉市海陵施路Z座 727105', 1630000000009) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630120000001, -781555629, -3682028760781093775, -1217, -88, 967.988362, -998747442791.562012, 1, 'binary.CMDWBFfYnlYEdTeiqtsW', 'nchar.云南省敏县白云柳州路Z座 839560', 1630000000009) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630120000000, -1229205179, 1269213658170093198, 15696, -110, 8232823752181.839844, 36569.580002, 0, 'binary.voGRWKSImlHklgUXdYMu', 'nchar.新疆维吾尔自治区红霞市南湖成都路L座 163545', 1630000000008) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630135000000, 801515319, -3418248827901909079, 26288, 51, -534837.671505, 15.631926, 0, 'binary.DnbpUExxknvANXEEsaWR', 'nchar.重庆市旭市清浦冯路W座 960766', 1630000000009) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630135000000, 1651702520, 7472881261358437437, 27039, 39, -901147931976.785034, -21.400440, 0, 'binary.PDCCWnKlBJjPqTBmUhYK', 'nchar.广西壮族自治区秀英县秀英惠州路c座 534464', 1630000000009) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630134999999, 1705176915, 3853689828781845374, 27488, 40, 8339786734.762860, 74741492928.878296, 1, 'binary.jUuMQjVuORGeBYLOtCvN', 'nchar.四川省飞县海陵林路s座 610723', 1630000000009) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630135000000, 1401375995, 4401644438738533904, 10408, 76, -65049698292.958000, 762130648498.933960, 1, 'binary.NgPdruMUwoLdCxyEbNqw', 'nchar.甘肃省长春市南溪张街Q座 680073', 1630000000009) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630135000001, -2067806949, -5140997933871627569, -3032, -3, -771419731758.264038, 30386355.304924, 1, 'binary.XlCFISTlcLIRsxjboWHn', 'nchar.台湾省六盘水县清浦成都街a座 796270', 1630000000010) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630135000001, -1774018458, -2530948670547381542, -23399, -94, -495376178.216937, 151170.247760, 1, 'binary.TnrFRvylqBaNDthXRBAm', 'nchar.山西省帆县清浦昆明街Q座 225961', 1630000000010) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630135000000, -1363931402, 5604209803537258593, -18300, -23, 790034130.791400, 9237371157.649290, 0, 'binary.gyQzvuCzIfMlTIPPFNsH', 'nchar.广西壮族自治区淑珍市徐汇包路e座 156670', 1630000000009) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630150000000, -1894195697, -5734755902035702132, -15870, 111, -2670.233773, -4237.280417, 0, 'binary.UorBnZYRMylozHQezSJY', 'nchar.北京市英市清河张街N座 217253', 1630000000010) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630150000000, 745446575, -9002015868827109100, 7664, 112, -360706186.393129, 47605535552382.398438, 0, 'binary.FZNKeCfgQVTcZyqRNJuK', 'nchar.贵州省桂芳县怀柔天津街b座 347544', 1630000000010) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630149999999, 672434773, 9109650904011996741, 14686, 14, -85079.408071, 86.251927, 1, 'binary.XKWsToLeAsNVsIygACBb', 'nchar.贵州省广州市海港长沙街d座 904810', 1630000000010) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630150000000, 1515726636, 8521257827234172880, 11241, 103, -10.526128, -45196916520756.703125, 1, 'binary.zcHOLLudfLMvmIiXrANq', 'nchar.青海省六安市新城哈尔滨路Z座 312342', 1630000000010) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630150000001, -1923997635, -1295412466812568520, -20900, -107, 86532721.258284, 65558167665.583397, 1, 'binary.zNkNRRNyFRDVubonqLSh', 'nchar.广东省艳市东丽东莞路X座 591920', 1630000000011) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630150000001, -1357505482, -7556497983653555349, -27964, -5, 254673.529731, -273710012885.143005, 1, 'binary.oDZRgFAkFNMiHLGdpWcM', 'nchar.内蒙古自治区太原县秀英吴街F座 707601', 1630000000011) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630150000000, 720531993, -6639843123954951373, 1904, 87, 90228483.253351, 671689.823567, 0, 'binary.pbWPxvdZNrUoUOjzRJiX', 'nchar.湖北省柳市合川台北街k座 351073', 1630000000010) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630165000000, -1222920932, 8032055023952251119, -10742, -10, -567677.518580, -365410143.799096, 0, 'binary.gSPyErqDINWrLLVhCvup', 'nchar.辽宁省慧县牧野沈阳路d座 158793', 1630000000011) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630165000000, 414746648, 5927295586580216537, 31761, -42, 29.776511, -773061167437.739990, 0, 'binary.clWyILBusmbzejzbBoFT', 'nchar.福建省雷县东城曾路t座 587170', 1630000000011) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630164999999, 824419604, 891106057873489263, 23278, 95, 407384.105632, -35575.873087, 1, 'binary.MNQmhqizvbnJgkkIQqJe', 'nchar.广东省郑州市江北王路P座 783592', 1630000000011) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630165000000, 1281221057, 7024877965980246423, 27117, 31, -310144.477215, 7651054.553459, 1, 'binary.glajyvvlfYaEeVkkGCkB', 'nchar.西藏自治区博县黄浦沈阳街J座 833215', 1630000000011) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630165000001, -1830990548, -4649870365451699133, -7796, -55, -7445.199016, 5969245.537249, 1, 'binary.acIrBxurCVUcZrlhKNWy', 'nchar.北京市雪市城北佛山街L座 344309', 1630000000012) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630165000001, -156703760, -5651707522314260232, -20357, -53, -48419.774656, -412073702153.369995, 1, 'binary.RalpwNQKJazBBUIsHJxe', 'nchar.辽宁省阜新市大东郑州街k座 364193', 1630000000012) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630165000000, 862504464, -5500398940730781742, -14444, -90, 83.855205, -42218010095700.703125, 0, 'binary.TDihZaaECjQhZSuXOJkw', 'nchar.台湾省香港县滨城丁路O座 978512', 1630000000011) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630180000000, 667837391, -3891675097346789325, -27238, -120, 1.955652, 9.112019, 0, 'binary.JzwDaPxfqmOCGLPvyrjl', 'nchar.湖北省合肥市朝阳贵阳路w座 542472', 1630000000012) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630180000000, -1060826174, 4656485123040609725, -2306, -49, -31070344.608357, 32855.487468, 0, 'binary.HuQooyRdCtqfxpfenEKD', 'nchar.福建省沈阳县门头沟合山街M座 860092', 1630000000012) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630179999999, 95309922, 7708532961668715531, 4871, 87, -2493.696406, -305230557.440988, 1, 'binary.sDzjVbzXXlrItKczJmNd', 'nchar.四川省彬市高明潜江街t座 525852', 1630000000012) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630180000000, 1834883689, 9087266843320529269, 10482, 90, 7620830515.391810, -42.560665, 1, 'binary.UNyjzeJnXfRpfYwqnoiq', 'nchar.宁夏回族自治区天津县门头沟韩街T座 460087', 1630000000012) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630180000001, -426435327, -3062037029747393786, -9095, -58, 3445.234181, -558141651179.500000, 1, 'binary.PPFhdHAqUnaKoAEmHsdU', 'nchar.湖南省霞市南湖石家庄街t座 857415', 1630000000013) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630180000001, -1181075026, -3180887222641598399, -31207, -111, -1782467190.826900, 5.516558, 1, 'binary.TGHKOSbljBlliohlXOWY', 'nchar.北京市华县南溪兰州路S座 340198', 1630000000013) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630180000000, -1179373775, -2798016462115894947, 13261, 81, -6.728964, -772564358011.891968, 0, 'binary.YugzktgmcxvJhQUFlTJx', 'nchar.重庆市大冶县新城蔡街a座 475876', 1630000000012) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630195000000, -1753829875, 9153441825434214315, 27033, 122, -736.689121, -92.766550, 0, 'binary.pUBZlnzauIFGdWqodaie', 'nchar.新疆维吾尔自治区海燕市高港刘路a座 320202', 1630000000013) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630195000000, 209604377, -5203497748513382294, 11811, 104, 6261702331.471590, 912558484347.494019, 0, 'binary.wZJaPJrGTgLaarzVLUSN', 'nchar.香港特别行政区武汉市海港长沙路y座 885641', 1630000000013) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630194999999, 927761777, 2507975814406403776, 19213, 90, -7617794.842135, -454202300.875154, 1, 'binary.icqbMuuToUNxqWXUeRPk', 'nchar.广东省西宁市丰都李路q座 597739', 1630000000013) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630195000000, 25571599, 9030074847417015485, 31156, 118, -75.396818, 48452341.676426, 1, 'binary.NqBtvtMnkQndvuYapikY', 'nchar.香港特别行政区南宁市长寿甘路u座 453721', 1630000000013) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630195000001, -428129781, -5700535713003042271, -10481, -28, 23726711.628846, -28428638085.690300, 1, 'binary.pCEqFOIEkNkTyynifvvP', 'nchar.西藏自治区张家港市上街阜新街O座 871243', 1630000000014) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630195000001, -848598147, -5339257050356453975, -18995, -126, -97029.616600, -142.756397, 1, 'binary.fnhJdkzuvTlaKyHNNFax', 'nchar.陕西省桂芝市永川马鞍山街k座 606648', 1630000000014) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630195000000, -1235643681, 7084534800526629066, -24801, 79, -145779524595.869995, 94.711588, 0, 'binary.zGptPlBGCsdKPNcWBTWB', 'nchar.湖南省莉市璧山王街S座 444986', 1630000000013) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630210000000, -257925835, 4113510788745659274, -7451, 82, -73680370.344940, 3976133.807981, 0, 'binary.RMHnWOvHGDkBnmnhajqK', 'nchar.甘肃省昆明县锡山东莞路f座 143739', 1630000000014) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630210000000, -441472850, 6731053996474537256, 25225, 88, 40422214874.591599, 23965.803627, 0, 'binary.EHzCItPZeIiFrqnZlZFx', 'nchar.广西壮族自治区丹丹市蓟州李街A座 716733', 1630000000014) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630209999999, 2038647205, 1189537624585781694, 7402, 77, -25786637314.127998, -8273884501116.790039, 1, 'binary.lQDfBPFCwRhZWQDOueFe', 'nchar.四川省南京县大东济南路X座 802062', 1630000000014) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630210000000, 479757528, 6749026723270202494, 13649, 38, -11785225102.777700, 474555902413.706970, 1, 'binary.gZeGdOiDSRQDrrutAJpP', 'nchar.吉林省桂英县门头沟巢湖路W座 373162', 1630000000014) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630210000001, -973859244, -7125967416228878252, -23978, -103, 9.174338, -9074.207791, 1, 'binary.spVrNBOtDUJKWtVfGkIs', 'nchar.云南省重庆县秀英张街w座 814757', 1630000000015) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630210000001, -1099659644, -5069485856549254463, -7663, -21, -77435917488084.906250, 6157980965629.839844, 1, 'binary.neMplXKNDoTZmfaWuQIv', 'nchar.海南省嘉禾县翔安上海街P座 777755', 1630000000015) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630210000000, 1262139840, -4971682912616802373, 32119, 52, -763639.969220, 4466.886880, 0, 'binary.BedkvagFaejmBsJjHkQk', 'nchar.上海市玉英县东丽辽阳街q座 311759', 1630000000014) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630225000000, 722222291, 150763568244594756, -22749, -105, 69152723689.975998, -5072701672145.320312, 0, 'binary.ZIoGBLOEmmhXJZvIxuMC', 'nchar.陕西省博市永川西安街H座 219040', 1630000000015) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630225000000, 591411352, 513820708206298423, -29944, 120, -7450006471858.410156, 28263898844.649300, 0, 'binary.OOYGFQjeyKSgnzgKjpfl', 'nchar.甘肃省南昌县龙潭张街q座 299631', 1630000000015) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630224999999, 1729527872, 858836292464061984, 26768, 61, 8045315.625506, 463874.574633, 1, 'binary.qPTkezKHzqZjenBLvfin', 'nchar.新疆维吾尔自治区汕尾市海陵齐齐哈尔街e座 364606', 1630000000015) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630225000000, 1643785412, 3613608845439721039, 2830, 6, 20141358.132227, -10515528.243744, 1, 'binary.OHifAxUhqgMCYnGFqNtd', 'nchar.福建省惠州县秀英胡路z座 617394', 1630000000015) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630225000001, -1458828697, -6767897245471753991, -5337, -110, 26.347447, -2088415765277.760010, 1, 'binary.nKdzFeMTCkibzMHIBYWp', 'nchar.北京市武汉县海陵沈阳街j座 275130', 1630000000016) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630225000001, -847285817, -4303648033804475519, -29035, -126, 46793.514585, -1507581042167.719971, 1, 'binary.xMmlUvSqOUKadNTjwVbR', 'nchar.湖南省琳市沙湾张路b座 512648', 1630000000016) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630225000000, -978219428, -2955103196936757566, 30178, 32, 1631732545944.110107, -393.171524, 0, 'binary.seXNZyWFCBIKtovhPcPH', 'nchar.江苏省慧县上街宜都路e座 880474', 1630000000015) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630240000000, -1972126026, -7574542606285760315, 28119, 80, -529670.435949, -24383.929895, 0, 'binary.xhubWGtXmHdWMLKNToaW', 'nchar.甘肃省桂英县萧山邱街M座 532318', 1630000000016) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630240000000, -1796898694, -764951623915204003, -15993, 27, 4657602445.591260, 4586648.134693, 0, 'binary.TEhGCTdxkZNmFnzFtObM', 'nchar.甘肃省东县徐汇昆明街P座 260669', 1630000000016) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630239999999, 357526998, 1276204587787008311, 29238, 42, -5156150330.293080, 978546.269907, 1, 'binary.cTaghgmdTbnmdzLMfprn', 'nchar.青海省齐齐哈尔市海港汕尾街S座 223338', 1630000000016) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630240000000, 719321885, 6211071132372294861, 26203, 4, 97973007280575.000000, 4917172790.726020, 1, 'binary.UrLJfXtkYMRsRzBKupLN', 'nchar.安徽省永安市城东六盘水街x座 616834', 1630000000016) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630240000001, -131148573, -7418806044708315561, -24075, -95, -939211006187.709961, -62673687782.380798, 1, 'binary.ioRcxRqlBPWWUslmpXot', 'nchar.河南省瑞市崇文北京路v座 915899', 1630000000017) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630240000001, -926921347, -7119582382885284043, -22204, -33, -843815.847483, -733624.538013, 1, 'binary.CDgPdtLeDlVKfKVxhxpv', 'nchar.浙江省磊县城东阜新路q座 382954', 1630000000017) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630240000000, -256678368, -5278293054518319714, -19250, 63, 76804691.667068, 56757245265557.898438, 0, 'binary.mWDyzgzWsYmwcclLnyKM', 'nchar.新疆维吾尔自治区宁德县平山武路C座 669860', 1630000000016) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630255000000, 105950788, 478455145201382299, 21202, 49, -492280820.857835, -59846.285166, 0, 'binary.bHXHFuvyzSODEypLHuvb', 'nchar.天津市惠州县兴山贵阳路q座 575823', 1630000000017) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630255000000, -1188272652, 3059329495007474279, 15772, 52, 97.388100, -179.239522, 0, 'binary.NcbSJdYAICljVIDdqLDs', 'nchar.河北省凤英市东丽曹路x座 451405', 1630000000017) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630254999999, 1374178023, 3719932182860509152, 15558, 26, -48778273445.594002, -4313900.906134, 1, 'binary.xrqMfwkMMYQAjZjHywqq', 'nchar.江西省广州市南湖汕尾街p座 889246', 1630000000017) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630255000000, 1682040807, 8317842464181056096, 1900, 87, 415547443.281930, 6910478.101601, 1, 'binary.CgZXfDNNfsnrMNDLhaFk', 'nchar.河南省海口县沈河长沙街D座 269675', 1630000000017) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630255000001, -1655416898, -6254408814439814177, -32731, -80, -926982830.629323, -59.656488, 1, 'binary.oerLzcmyCiDByTBvtqJC', 'nchar.贵州省关岭县涪城侯路y座 962245', 1630000000018) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630255000001, -1635083194, -8974109706346763955, -2735, -50, 3293.363373, 18681627453476.000000, 1, 'binary.GSVbHmgpelzbMoHbLPcC', 'nchar.内蒙古自治区晶县清城拉萨路X座 358275', 1630000000018) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630255000000, 1313669852, 6945103232995327793, 30581, 16, 85564937456162.203125, -77542.918719, 0, 'binary.XFHqNNaMVizYnZQgNXPC', 'nchar.新疆维吾尔自治区贵阳市崇文宁德街i座 343604', 1630000000017) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630270000000, 917363192, -2865889321649137964, 23695, 91, 5280836.562854, -3783947630346.270020, 0, 'binary.MNMoJuMUQGuncloQVsno', 'nchar.陕西省福州市吉区苏路s座 468218', 1630000000018) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630270000000, -2122120908, -2872995800597882541, 31983, 71, 6875560.276574, 5.493633, 0, 'binary.EPzGVtLuyIzhTxgbjEWF', 'nchar.山西省哈尔滨县浔阳蒲街L座 163917', 1630000000018) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630269999999, 795882903, 3280694140326918125, 20811, 108, 49.168498, 7651.321312, 1, 'binary.UikJWqrxtOeMoYKjVtNm', 'nchar.广东省桂芳县安次嘉禾街r座 604207', 1630000000018) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630270000000, 2120566264, 4722887562205021135, 28462, 1, 129.403026, 81642332991.346405, 1, 'binary.rFxHYhBonyaZGENLSiup', 'nchar.新疆维吾尔自治区建军市龙潭陈路N座 391792', 1630000000018) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630270000001, -426986357, -7028311428629812651, -4827, -64, -7.591949, -8288.667569, 1, 'binary.MTcHiKSZLMGfDPYnynMD', 'nchar.山东省辛集县东城汕尾路Y座 327226', 1630000000019) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630270000001, -1319979040, -1611680110566277558, -12591, -102, -0.766067, -9.985580, 1, 'binary.aSzFqnlqfbvcqqslssAX', 'nchar.北京市关岭县南长王路s座 855187', 1630000000019) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630270000000, -655731150, 952225036593449539, -12275, 62, 988070261.618785, 110828.718042, 0, 'binary.pwXbqQpeGiCAxVQjBByd', 'nchar.陕西省长沙县江北汕尾路F座 416889', 1630000000018) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630285000000, 1662865387, 6549115606741837921, 31658, -40, 6050748.290946, 850563444268.306030, 0, 'binary.PqxloDzsqJMLqHZQWCjg', 'nchar.上海市兰英市南湖乌鲁木齐路K座 550844', 1630000000019) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630285000000, 1925250353, -2675198429577937161, -954, 26, 42621483170.815201, -2.407178, 0, 'binary.UQoLagBLIXklApVNNHjj', 'nchar.福建省超县淄川大冶街R座 827801', 1630000000019) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630284999999, 1995360198, 5210480004052888682, 18624, 3, 97472570479742.500000, 1260.797791, 1, 'binary.ItgagWrnvwaUBcGaMaeN', 'nchar.广西壮族自治区重庆县平山香港路V座 260105', 1630000000019) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630285000000, 1294452263, 5523637851428821304, 15478, 5, 9507059.611693, 71182.768111, 1, 'binary.zGOYZBGdKbprwpIBOAyf', 'nchar.吉林省静县房山太原街o座 903227', 1630000000019) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630285000001, -1089491236, -4124928499125874309, -26711, -91, 102.262755, -86354.456039, 1, 'binary.wIAlEZNaSWVRvmnECAvO', 'nchar.浙江省梅县孝南广州街r座 602833', 1630000000020) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630285000001, -1857132633, -3826380662652726191, -2637, -78, -5244683893811.500000, 28720333520.104401, 1, 'binary.aCSuXOyNceiyMGbrnKiN', 'nchar.辽宁省海口市城东谌街E座 102059', 1630000000020) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630285000000, 1378099044, 2585214152437420786, 15693, -37, 9876.538042, -735632586.279405, 0, 'binary.SafiqluCtQtykHfilDhK', 'nchar.北京市雪市黄浦王路x座 719370', 1630000000019) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630300000000, 1474375413, 5114018721557230309, 17508, -51, 19062832.997828, -2871763657.353070, 0, 'binary.tQXLaCZMUMopSlkQosvw', 'nchar.甘肃省齐齐哈尔市花溪合山路F座 429081', 1630000000020) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630300000000, -388377907, -3327065272167311555, -118, 78, 891.667968, -939976.640106, 0, 'binary.vDLERQspegLuLpwaUwzM', 'nchar.安徽省潜江市南溪王街H座 114897', 1630000000020) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630299999999, 1778777098, 1247965499115398806, 31082, 36, -34708.444580, -9074056.186352, 1, 'binary.sSRJTkOuBEsIDUBYnvLI', 'nchar.重庆市倩市沈北新拉萨街s座 784670', 1630000000020) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630300000000, 1445490460, 8880599911239061729, 24463, 25, -3.382105, -1781392.553877, 1, 'binary.aoTqpxHvRtaSZcskkkvh', 'nchar.天津市北镇市牧野徐路j座 335208', 1630000000020) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630300000001, -414780851, -3272216576746070612, -22655, -77, 60986281647372.203125, 8206.582673, 1, 'binary.BYPTbfwFwATchckdDRGY', 'nchar.澳门特别行政区瑞市白云沈阳街D座 317572', 1630000000021) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630300000001, -1100845103, -4359114771451299690, -19221, -72, -454991497.458531, 66488519526.609200, 1, 'binary.IAUPjYJLQVMOrfjNhEGW', 'nchar.贵州省柳市丰都合山路I座 879430', 1630000000021) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630300000000, -1344260637, -2327749124997496795, 8396, 9, 53600362.915844, 39096334.438932, 0, 'binary.MCcnFYqPmshweRolVKXy', 'nchar.福建省辽阳市黄浦武汉路Z座 588915', 1630000000020) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630315000000, -355362703, -1297695182610353342, -9770, -89, 952785.346586, -74060980932193.796875, 0, 'binary.oxSCvbpFwbexlztlNbov', 'nchar.江西省阳县徐汇孙街A座 417152', 1630000000021) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630315000000, -1228614638, -3900819433463392818, -17590, -11, 8486255712070.299805, 776309237079.099976, 0, 'binary.lCmzbzWrnzVGWTlKKcLz', 'nchar.江西省健市花溪齐齐哈尔路s座 401365', 1630000000021) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630314999999, 2119897062, 705747859773422308, 11407, 81, -7145565.865688, -262229423.217684, 1, 'binary.eEvZPvUuQslbYxeHtVwF', 'nchar.山西省马鞍山县兴山台北街K座 317962', 1630000000021) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630315000000, 1675027583, 7700778986059081977, 16174, 9, -665864335638.520020, 71582.521862, 1, 'binary.tKmhWfIgqpVzDnSlVNyX', 'nchar.澳门特别行政区银川县高港侯路B座 867370', 1630000000021) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630315000001, -63872001, -6930483055721144761, -55, -27, -647803039.367343, 2303820.355916, 1, 'binary.cMZeLPHbvchDdpONluWD', 'nchar.海南省长沙县浔阳俞路y座 710843', 1630000000022) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630315000001, -550949355, -2196304875670875984, -11885, -39, -6711213741.192790, 743976.503579, 1, 'binary.ZjvtDrDegMEemNdVPYWI', 'nchar.江苏省丽华市东丽林路c座 701423', 1630000000022) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630315000000, -638988531, -238160149511091433, 5704, -64, -8.456931, 122326752.221053, 0, 'binary.bOAzwJsCnDilLpivHhcE', 'nchar.福建省台北县新城佛山街W座 190141', 1630000000021) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630330000000, -626643923, -2019791703137966083, 32109, -84, 3416720.968494, 9357038.426241, 0, 'binary.BaFBcjklAnYcYwGxAqoq', 'nchar.吉林省武汉县朝阳宜都街u座 246031', 1630000000022) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630330000000, 1744535925, -781319618567345160, 25699, 25, 5357.659882, -618.983367, 0, 'binary.VPobijbSHTufuAsIpKoJ', 'nchar.吉林省建华市城北刘路m座 189127', 1630000000022) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630329999999, 880112073, 3294754321072095965, 6900, 77, -89650901.379152, -40.193724, 1, 'binary.slgqehRyEWrrSqbAYVJh', 'nchar.甘肃省佛山县吉区吴路i座 371158', 1630000000022) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630330000000, 185074156, 4989180079312042024, 29358, 109, 553959035.299975, -336.524434, 1, 'binary.gsSAVskcQYNhhgdMqRao', 'nchar.内蒙古自治区海门市新城许路M座 262464', 1630000000022) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630330000001, -1466263570, -2228588793836525866, -21221, -43, -87005519974.974106, -660.194761, 1, 'binary.bxpguIjMdJUkxwsOGQEq', 'nchar.新疆维吾尔自治区杨县徐汇福州街W座 871563', 1630000000023) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630330000001, -1645451433, -4401356942676794117, -28334, -111, 279.991987, 22516.349037, 1, 'binary.dfdHQJlJuaDksxoabJoB', 'nchar.西藏自治区太原县涪城哈尔滨街p座 883295', 1630000000023) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630330000000, 2032301580, 4408736721579229542, -1683, -10, -14742.318595, -7092296.586329, 0, 'binary.GExwHTtWGjhZjTEeFYiG', 'nchar.江苏省大冶市闵行高街t座 870548', 1630000000022) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630345000000, -2137144022, 4079790010886186881, 25710, 117, -4064381240984.290039, 7015370675970.000000, 0, 'binary.CVqxsKDzVLudZenizkMH', 'nchar.澳门特别行政区广州县牧野北京街x座 612318', 1630000000023) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630345000000, 933500773, -9037818060698530179, -29395, 110, -635450613.922866, -7403.402429, 0, 'binary.BAfDibZjCIxGGNhZPzdE', 'nchar.天津市玉梅市六枝特曹街z座 306379', 1630000000023) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630344999999, 1707978124, 7108213046724490283, 23442, 53, -1690092798852.899902, -77.732195, 1, 'binary.CjoXkwnzCpbREZGghsfa', 'nchar.天津市俊市南长成都街Z座 386069', 1630000000023) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630345000000, 638219332, 7562431303377412667, 16354, 108, -1426154.974943, -5203.623256, 1, 'binary.YWcLHHceXXwuYatdWqpB', 'nchar.海南省武汉市闵行佛山路i座 350356', 1630000000023) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630345000001, -694792584, -5451159991441438649, -27358, -63, -421814477.346397, 658.908206, 1, 'binary.RjeNtbCwKmVzuSEznMIP', 'nchar.青海省兴城县双滦嘉禾街J座 854125', 1630000000024) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630345000001, -1486705498, -4529672645278837682, -21086, -87, 0.969525, -88911627001.666107, 1, 'binary.lFWwkNVbMUovcuYFIddp', 'nchar.澳门特别行政区拉萨市和平合山街j座 616189', 1630000000024) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630345000000, 1470276506, -7928540339509515647, -16251, -106, -75636523821237.203125, 1951788289389.639893, 0, 'binary.gAaAcTqtqUaUtILxCARx', 'nchar.广东省嘉禾县清河六盘水街k座 243900', 1630000000023) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630360000000, 1152276268, -8156217200537467815, 19660, 12, 28355311.730820, 6713567748470.700195, 0, 'binary.bmGZNDQVyGtLdMWCUUPh', 'nchar.云南省杰县南长兴城街P座 252275', 1630000000024) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630360000000, -504752588, 1971807127747770396, 27445, 121, -8539663.125419, 54448077.614627, 0, 'binary.cuEEkfEDPsfuHYlKnDOH', 'nchar.西藏自治区坤县金平澳门路Y座 688701', 1630000000024) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630359999999, 855880887, 4257747801443019050, 4002, 59, -651877334084.171021, -40661.869299, 1, 'binary.ZOOiXFRmbNwocDEGjyPI', 'nchar.山西省香港县沈河汕尾街w座 530063', 1630000000024) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630360000000, 24228908, 7366685839096261214, 24706, 108, -2895.104902, -690789994021.112061, 1, 'binary.WoiDFgqNXTSOSSqvghbK', 'nchar.香港特别行政区哈尔滨县萧山重庆路S座 626140', 1630000000024) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630360000001, -1979347419, -8086150063002929949, -31773, -59, -6758.131288, 67.389494, 1, 'binary.BdPhqWnyifozXNBeGuOa', 'nchar.吉林省重庆县东丽齐齐哈尔路T座 928550', 1630000000025) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630360000001, -796374629, -6586675874501163952, -28989, -41, 64993999.806191, -8554109097.403460, 1, 'binary.AjiqARctYieemihXJRgw', 'nchar.广东省嘉禾县房山李街d座 910194', 1630000000025) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630360000000, -2078983709, -5723824485424673203, -23688, -93, 7495606593.360470, 264203417504.108002, 0, 'binary.LvbrLfgWtSAHPeWnNyif', 'nchar.重庆市峰县华龙廉街i座 702040', 1630000000024) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630375000000, -2135854035, 3495311946004641041, -8066, -32, 794122420146.477051, 54762.831473, 0, 'binary.iKNdSNvujYgDbKTFUoWj', 'nchar.湖北省秀珍市东丽佛山街a座 727430', 1630000000025) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630375000000, 195905849, -4893460212808423867, 27472, -20, -60.648891, 9236.500458, 0, 'binary.fxBWbjZbbgBzyftfClnE', 'nchar.云南省春梅市普陀合山街d座 593581', 1630000000025) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630374999999, 1222537098, 2598300007761422980, 13555, 60, -21237649962112.101562, 56425481952996.296875, 1, 'binary.nljxYbIMonhZyPfyRWYU', 'nchar.河北省澳门市大兴贵阳街U座 357038', 1630000000025) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630375000000, 1255129224, 3767117331869115149, 20415, 43, -96039955.962346, -3228760442.535840, 1, 'binary.VjBuTRZJfGBAsllbmlCm', 'nchar.上海市潮州县长寿大冶街V座 568435', 1630000000025) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630375000001, -451008604, -9013008932944649264, -4123, -55, -858251929.793158, 54.556567, 1, 'binary.CGijFVktOvKYBbslrFnW', 'nchar.甘肃省丹市牧野刘街b座 221301', 1630000000026) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630375000001, -994075958, -3836907429942473253, -15968, -12, 4.809100, 97814318457.744095, 1, 'binary.ZkpIzssjZLBfwxySZcqJ', 'nchar.吉林省惠州市兴山辛路i座 132947', 1630000000026) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630375000000, -316707220, -6874259000415830359, -14656, -107, 9783647610530.900391, 6.913912, 0, 'binary.stonHOVphDrwzsFtAuEM', 'nchar.吉林省杭州县秀英任街B座 197635', 1630000000025) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630390000000, 1162924990, -5170396701176744771, 20522, -92, -96439892251.988800, 27285284869935.500000, 0, 'binary.VaAkDRQGuwRsRuHuWTBT', 'nchar.安徽省刚市璧山严路e座 453358', 1630000000026) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630390000000, -1787695146, -7200438941294278654, -1976, -22, -19864559903432.601562, -81662701579034.406250, 0, 'binary.cmeIZxizSzJowehZeTgi', 'nchar.甘肃省萍县吉区雷路Q座 278197', 1630000000026) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630389999999, 1569291471, 7500808657751046307, 17406, 11, 187598077622.457001, 9402508122.216591, 1, 'binary.rGPAUjewRUiNxuGlPQSI', 'nchar.湖北省宁德县永川邓街N座 873981', 1630000000026) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630390000000, 379511627, 959739624838461444, 32645, 40, 27073116046.845501, 9680357.747312, 1, 'binary.EnkonjEPYvAZMcbrIDhm', 'nchar.安徽省宇县南湖拉萨路l座 319850', 1630000000026) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630390000001, -367057952, -5935523220947872265, -31354, -124, 60936491.153154, -7459361.174603, 1, 'binary.ehReUikosMxxEsGOsivE', 'nchar.河北省宁德市六枝特武汉路j座 479101', 1630000000027) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630390000001, -1204076280, -9028857053490170794, -4305, -36, -4299.875188, 8440721199484.889648, 1, 'binary.LDFNunrLqdOUVBNKOEgL', 'nchar.湖北省西安县六枝特淮安街d座 633128', 1630000000027) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630390000000, -1734305566, 9014243322464991494, 2526, -91, 46980567127.508904, 2736.398653, 0, 'binary.kCqLuZWcVXncorOcRLOX', 'nchar.吉林省秀英市永川姜路P座 763227', 1630000000026) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630405000000, 493810102, 750963322474159528, -23750, -17, -22892331.104465, 24868217245883.800781, 0, 'binary.CFELPsklozusjREurYzN', 'nchar.浙江省云市吉区丁路H座 432525', 1630000000027) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630405000000, 1463044753, -1849311824110235905, 30811, -7, -17541415231.352200, 4359875.313503, 0, 'binary.XztqpyyklxsOpFMGQpdQ', 'nchar.内蒙古自治区兴城市和平李路f座 695390', 1630000000027) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630404999999, 1007184435, 7016082283155873873, 18680, 114, 921004.858357, -3749822553130.689941, 1, 'binary.nPsHiYGSrumTPlRhGlGo', 'nchar.内蒙古自治区长沙市海陵六盘水街Z座 569551', 1630000000027) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630405000000, 2001976992, 6444735120490802040, 10757, 75, 3812894583.717430, -70452173102543.796875, 1, 'binary.MPllmpddghzaoIRJmAJs', 'nchar.河南省西安县崇文李街d座 986692', 1630000000027) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630405000001, -1748589793, -7997812859393713894, -9028, -46, -35.226372, -6653121231.857540, 1, 'binary.eVMhMPninMDMThzngiZC', 'nchar.江苏省鹏县长寿深圳街V座 475898', 1630000000028) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630405000001, -952046898, -1003514831999138377, -10475, -121, 583096872.778729, 750.380516, 1, 'binary.NhUrjkWQZoYMHNgZcAur', 'nchar.辽宁省畅县南溪陈街Q座 816736', 1630000000028) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630405000000, 1203696901, 5857368026922559698, 26958, 20, 7943395.425475, 3479394471444.229980, 0, 'binary.EWZLkQdNEMzlxMRcWPIF', 'nchar.河北省凤兰市秀英王街h座 943022', 1630000000027) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630420000000, -1140109939, -7140478781384267748, 23888, -102, -463251528.501850, 58.564400, 0, 'binary.wBOWZRMsrPHnjovxpVtM', 'nchar.福建省桂香市魏都张街s座 891983', 1630000000028) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630420000000, 1596211207, -6399610783775225615, -6948, 18, 5279544962.478530, -3254512966322.680176, 0, 'binary.pkLdHCSKTBJtvlkQZFel', 'nchar.宁夏回族自治区志强市沈北新哈尔滨街V座 984662', 1630000000028) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630419999999, 1987333617, 2406177688984023332, 5515, 81, 93334135.435757, 15200180248105.500000, 1, 'binary.zunblBzpjKjvAprKttjO', 'nchar.陕西省娜市六枝特长春路u座 734021', 1630000000028) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630420000000, 1816593353, 6144436182936056183, 11139, 111, -5111160.608439, 3134629841.427010, 1, 'binary.SvSSddOyqqrLVbTuqmWK', 'nchar.黑龙江省北京市沙湾天津路l座 864505', 1630000000028) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630420000001, -1092293083, -6497162148443342823, -12861, -33, 7333968.460815, -786239055.465100, 1, 'binary.abpCKdOYaAAPNEGSEKTl', 'nchar.重庆市通辽市白云席路d座 390244', 1630000000029) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630420000001, -672330807, -1416095251335444839, -31617, -20, -268.247197, -187856842551.350006, 1, 'binary.ayrYptkczwLwwHSlrotJ', 'nchar.安徽省莹市崇文卓路D座 742319', 1630000000029) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630420000000, 1541531440, -8276464445557829911, -32389, 41, -205002775.660640, 773381214983.128052, 0, 'binary.DfbOMiMBChkQyxVRkVrV', 'nchar.江西省重庆县东城嘉禾路z座 664431', 1630000000028) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630435000000, 511355972, -4607655896423993759, -17667, -115, -72721.674990, -0.210169, 0, 'binary.TzInKrTBzLfzhusnMyJt', 'nchar.西藏自治区大冶县黄浦夏路c座 672141', 1630000000029) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630435000000, -794567134, -2235695034213568259, -18310, -76, 80256151932.389999, -0.448521, 0, 'binary.rSBKSseTjokrDbbUwbdS', 'nchar.新疆维吾尔自治区南宁市璧山王街D座 205832', 1630000000029) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630434999999, 1590979273, 8094673699827428920, 1803, 48, -6923.890078, -97907136406253.203125, 1, 'binary.GnrqLzMLFlinSCSmzsTt', 'nchar.辽宁省荆门县六枝特邯郸街p座 507994', 1630000000029) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630435000000, 1132029984, 2532896687056073497, 20663, 78, 72584604.270350, -52558156996.426201, 1, 'binary.hUBVgUHTpsSwyjcCwqYn', 'nchar.四川省邯郸县南湖张家港路V座 697294', 1630000000029) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630435000001, -214047405, -8929808789293020890, -14561, -75, 57922.963900, 629338050.201999, 1, 'binary.rUFdjCoxExrGdHJRdNrS', 'nchar.香港特别行政区艳市魏都香港街w座 547058', 1630000000030) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630435000001, -1769159233, -2980306744069119372, -24737, -85, 95463.992658, -3290730049210.250000, 1, 'binary.bcUBXvglPoTsHoRWOtZB', 'nchar.青海省建国市蓟州罗街V座 702124', 1630000000030) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630435000000, -787830057, 3539391148256582010, 8967, -84, -3405.578845, 6448387382.497230, 0, 'binary.nXPgVFiqtkagYaeMiBqc', 'nchar.宁夏回族自治区兴安盟县梁平沈阳街J座 590779', 1630000000029) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630450000000, 1186123659, -7951052163704337820, -29743, -14, -83621685835717.906250, 73159143.385460, 0, 'binary.VKjqDeckRehqfqnstQEu', 'nchar.河北省上海市门头沟梧州路n座 288381', 1630000000030) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630450000000, 1878200309, 7041626075528835244, -32078, -31, 37394.924981, -492.884685, 0, 'binary.tSYeYbpjVnhDUVatIqqr', 'nchar.云南省齐齐哈尔市朝阳王街j座 235227', 1630000000030) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630449999999, 1216265979, 1946865098328593924, 13349, 71, -8448.993057, -74684363814152.500000, 1, 'binary.HIQrJxrPESpsHxBeQTJr', 'nchar.香港特别行政区关岭县魏都呼和浩特路i座 304697', 1630000000030) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630450000000, 1436995521, 3840076561934756705, 24645, 53, 3385565140.362020, -18217011452.326302, 1, 'binary.RBEtocJRHaAIuNaYJMhP', 'nchar.辽宁省重庆市江北张路g座 561300', 1630000000030) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630450000001, -704813545, -8641984224483414170, -32490, -72, 305492940.896881, -3375029817498.339844, 1, 'binary.MUkAAGQFoHZIrYzgZIkn', 'nchar.甘肃省佛山市六枝特梧州街p座 155461', 1630000000031) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630450000001, -222045952, -7186471281941680094, -4325, -12, -4.504288, -107.133595, 1, 'binary.rYHScGxtnPQZbrvqmGLs', 'nchar.浙江省斌县西夏宁街i座 817397', 1630000000031) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630450000000, 1430474057, 6099257513015763510, -25953, -124, -4692.193024, 4.787536, 0, 'binary.ECCSIBNtxKQLYBfOfsJg', 'nchar.天津市西宁县璧山曾街N座 665290', 1630000000030) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630465000000, -1933715256, 1674195434522463261, 18595, -62, -2.112704, -1.361571, 0, 'binary.WFmGDlZbQZbxQoPTeYYD', 'nchar.江西省帅市秀英罗路i座 713857', 1630000000031) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630465000000, -1427366603, 348136735706226150, 11786, 45, 998.343140, -9.796246, 0, 'binary.mfnVlbsKfzjjqorEhocA', 'nchar.西藏自治区玉市安次成都街E座 433538', 1630000000031) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630464999999, 1659717258, 7758886491614905150, 8304, 125, 6399945699.318400, 86010265260.434601, 1, 'binary.PFttwdRtnOphOvIvENNh', 'nchar.山东省欣市沙湾孙路R座 922051', 1630000000031) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630465000000, 2080213156, 8048809385397600433, 18758, 65, -544332786.800377, 2865457.223765, 1, 'binary.oElRbKMuPpzhWDlPDXtl', 'nchar.北京市淑华县江北李路F座 469619', 1630000000031) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630465000001, -1260757693, -7052648703184778467, -19691, -58, 263396039624.993988, 4278958.521790, 1, 'binary.CZUckqTDCqkrcZvnYVOg', 'nchar.广东省秀珍市清城谢街t座 351701', 1630000000032) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630465000001, -716674007, -2090666240981221473, -8986, -13, 40900.288977, -311075618204.403015, 1, 'binary.svGVeKCsLqnIefICQikd', 'nchar.宁夏回族自治区哈尔滨市南湖梁路v座 181451', 1630000000032) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630465000000, -1114362408, 5527740642432952035, -26428, 12, -21611.508885, -307.575004, 0, 'binary.UdnFsgeAgiPHPPgFGuCS', 'nchar.天津市成市朝阳沈阳街c座 871777', 1630000000031) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630480000000, 572636870, -1348714871953192727, 11880, -9, 78191326.534929, 5.863674, 0, 'binary.ELYllxOgSmXkAHYWCKeC', 'nchar.河南省六安县和平惠州路b座 192567', 1630000000032) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630480000000, -1554586734, -5797603791431465981, 19152, -58, 376.263188, -9117680341029.800781, 0, 'binary.ItnjMhkccvDshKoJDFBL', 'nchar.广西壮族自治区上海县高明潜江街i座 632153', 1630000000032) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630479999999, 1889928969, 2650453196149359117, 1531, 101, 221512.929316, -89455817137.120804, 1, 'binary.JuOPYpivSOrAxirELGaK', 'nchar.云南省广州县清浦潜江路y座 321604', 1630000000032) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630480000000, 123268180, 7324096614566287829, 18716, 12, 727218062004.973999, 656857194.138679, 1, 'binary.LzrEjFPpRgwZHAABcyJl', 'nchar.宁夏回族自治区兴城县沈河济南路A座 434702', 1630000000032) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630480000001, -739224311, -3272068915371457037, -11723, -49, 952488.600157, -831167.359733, 1, 'binary.KMwlcGqAhCieyQLGVtBU', 'nchar.河北省玉梅县徐汇张街u座 155803', 1630000000033) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630480000001, -1363430935, -5467097084273074766, -2392, -77, -2426746190.920940, -72743043.214903, 1, 'binary.FYLJECmRlLXbWxOIZbkA', 'nchar.新疆维吾尔自治区荆门市沈河丁街Q座 909413', 1630000000033) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630480000000, -1790122655, -8076464905134511680, -30494, 39, -300117474923.549988, 64738074469674.398438, 0, 'binary.sleyeDsmwcqZzCKoASFB', 'nchar.江西省香港市西夏沈阳街A座 666990', 1630000000032) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630495000000, 500469874, -345787852149044362, 31942, 66, 218.280717, 7741245996.308220, 0, 'binary.WbODLLMuYAWsCiVGykXg', 'nchar.甘肃省哈尔滨市萧山邯郸路M座 577140', 1630000000033) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630495000000, 1790655569, -8921791989390937548, -7521, -10, 21190031.941426, 372852.384613, 0, 'binary.pvccoVhryCwBmdnzLuTc', 'nchar.云南省潮州市沈北新吴路C座 166459', 1630000000033) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630494999999, 175625025, 4866859483197899046, 22179, 83, -52019.335200, -315117.422010, 1, 'binary.EPoDgXsUUMvKeLUulmOd', 'nchar.上海市呼和浩特县孝南淮安街D座 688832', 1630000000033) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630495000000, 531699098, 9087043167036546370, 10882, 69, -343189.459391, 211280.823556, 1, 'binary.gZdLTctTatBiWQSJIJOv', 'nchar.黑龙江省鑫县友好石家庄路G座 894253', 1630000000033) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630495000001, -128692601, -3691685846078930525, -2891, -13, -473237.431473, 6.861402, 1, 'binary.PevuHflVwLyOeexwpRis', 'nchar.广西壮族自治区桂花县和平石家庄街b座 197395', 1630000000034) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630495000001, -1382111225, -8179715729898925736, -27170, -65, 94.689652, -9.323222, 1, 'binary.dQukgnOBymmhDJsngvdP', 'nchar.河北省西宁县六枝特谢街w座 636313', 1630000000034) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630495000000, -1067182718, 4525978413594477317, -15988, -12, 9592970.107203, -5857432670.557230, 0, 'binary.KmUaBLARuhpFnBlZhhjz', 'nchar.广西壮族自治区玲县丰都伍街N座 160120', 1630000000033) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630510000000, 834635110, 7524163623717860346, -32317, -74, -15228783.766541, 189210.220590, 0, 'binary.EMKiAeOicxSQHtyaVgJp', 'nchar.广西壮族自治区洋县沙湾太原街b座 616020', 1630000000034) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630510000000, 969850854, 946247056457664769, 21254, -118, -665960476591.563965, -26272792213245.500000, 0, 'binary.AmemAqKVRuTlgnqegQTU', 'nchar.四川省海门县牧野潜江路x座 318206', 1630000000034) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630509999999, 1292293650, 4182146421220552346, 9438, 26, 6515565137650.730469, 4326564.636935, 1, 'binary.sjAdlJbnpCLUoyTzXGLz', 'nchar.山东省杨市南湖刘街Y座 225115', 1630000000034) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630510000000, 122648893, 3568976233348927576, 4722, 101, 3692.808659, 8.426917, 1, 'binary.idKTOjMQWLcoovoLZCRY', 'nchar.天津市关岭市锡山蔡街f座 426508', 1630000000034) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630510000001, -103653848, -6515029160766267522, -13842, -21, 461152.967231, -451711.406503, 1, 'binary.axaNePeGlnNRTVkjQgqj', 'nchar.黑龙江省芳县海陵贺路c座 606589', 1630000000035) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630510000001, -1047587411, -3104445727812638863, -8586, -20, 551018.785658, -69672859.800138, 1, 'binary.rrQrHCANqfAEkPaQtSxY', 'nchar.江西省辛集市平山南京街X座 619416', 1630000000035) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630510000000, 849850958, 4247759734843437140, 25856, 61, 216972633.179206, -688453.180700, 0, 'binary.HFGqhFMKQtiuVGsRfHzo', 'nchar.台湾省柳县清浦长春街g座 249559', 1630000000034) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630525000000, -1263472959, -6789381028960214442, -24794, 114, -380257099.745964, -4055421597.527550, 0, 'binary.vYeuboTOIvXZsvEDJLRp', 'nchar.云南省淮安县浔阳南宁街s座 962460', 1630000000035) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630525000000, -912546236, -763230547896477749, -22937, -100, -61226717.838399, 59403.615805, 0, 'binary.RfopmCaAJeNFUhoHdGfp', 'nchar.北京市嘉禾市海港梧州路Y座 185275', 1630000000035) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630524999999, 1491974080, 3628020701059333562, 19419, 61, 87024838.439295, 563459.869036, 1, 'binary.MGCglbwygRPypvScTmBl', 'nchar.山东省霞市吉区哈尔滨路U座 372048', 1630000000035) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630525000000, 1133422966, 4026166323599059583, 27738, 105, -67481518.148927, -5675366548881.980469, 1, 'binary.LFpWlYqzLoxtHDCeMOWl', 'nchar.黑龙江省北京市沈河王街n座 817738', 1630000000035) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630525000001, -104646696, -5475621281854878817, -8285, -77, -25646075.949196, -671.169300, 1, 'binary.nEdnhlzGKPxpfWnmznnT', 'nchar.辽宁省凤兰市上街李路t座 977250', 1630000000036) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630525000001, -62177409, -7664099839058566322, -13160, -111, 2741718151170.200195, -3.737565, 1, 'binary.kkhcrwzjebqpTkpaFkPz', 'nchar.山东省淑华县六枝特长春街L座 836041', 1630000000036) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630525000000, 1330077191, -57050396993719408, -17322, -114, -17573257017538.599609, 131480451841.740005, 0, 'binary.nBjEjjCxPpyJZZokLLYj', 'nchar.辽宁省拉萨县普陀香港路u座 175740', 1630000000035) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630540000000, 1361888973, -4754878850289093930, -8386, -123, -73755105134.646896, 593521593.672730, 0, 'binary.aaJdLDhVgqXgbzOLtgEC', 'nchar.陕西省玉兰市城东东莞路y座 735950', 1630000000036) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630540000000, -2023047539, 207198366842950509, -16454, -51, -5064990.460660, -1880.742682, 0, 'binary.pgtomoahTdklLDwxLWlX', 'nchar.天津市哈尔滨市普陀赵路a座 285719', 1630000000036) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630539999999, 1161599505, 3137635940724704617, 16998, 16, 341287.343410, 3260540.642346, 1, 'binary.VpvoOstBpXhXgCFmTNbu', 'nchar.江西省坤县沙湾拉萨街f座 882807', 1630000000036) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630540000000, 927677922, 1982533905502059580, 28136, 88, -554.710032, 860334626423.604004, 1, 'binary.xigdKxGBhwDummTjgWpP', 'nchar.甘肃省兴安盟市大兴李街R座 743679', 1630000000036) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630540000001, -1715472820, -1384061899373736161, -15979, -21, -144230.332607, 3166307136.273820, 1, 'binary.keFGWYyGPVWHcgVZNKld', 'nchar.江苏省莉县沈河王街j座 843427', 1630000000037) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630540000001, -1691042073, -7186599605570808771, -14609, -94, -20270760488095.101562, -479065667910.349976, 1, 'binary.qNCwJqmtvmXEEJXuqVcD', 'nchar.安徽省鑫县西峰香港街Q座 197792', 1630000000037) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630540000000, 1494052790, -8128813094838655682, 26938, 0, -5026361458.157280, 48738437612.827003, 0, 'binary.beRVwfLpgmeKWVAywXMR', 'nchar.重庆市西宁县沙市南京路l座 534992', 1630000000036) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630555000000, 611413897, 4152857341280270300, -8759, -18, 2060373600.882190, 661904.107513, 0, 'binary.VNQYBgSikmUjTzZJlnVf', 'nchar.台湾省潮州县永川莫路h座 405659', 1630000000037) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630555000000, -2011948818, 7185570718886510818, -23571, 37, 224031795.273930, 529323.833439, 0, 'binary.gdqheapFdDFaeWrvvlFQ', 'nchar.黑龙江省丹市孝南白路Y座 681449', 1630000000037) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630554999999, 654809776, 1038278314990977803, 21715, 111, 9233.222241, 875.958899, 1, 'binary.zeHdYSkOUqnFvykwmfjx', 'nchar.山西省飞县淄川大冶路o座 582862', 1630000000037) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630555000000, 1280839364, 1109786269551140763, 28107, 83, -7163.528250, -98949521955313.296875, 1, 'binary.GPZyYjBdWvtWXNqtBBAi', 'nchar.吉林省秀云市浔阳石路k座 906496', 1630000000037) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630555000001, -1722544909, -25495015738455645, -17889, -9, 8051193952.303000, -0.243396, 1, 'binary.NUGayWaiLgkIttYyWPen', 'nchar.江苏省帅县合川嘉禾路d座 756609', 1630000000038) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630555000001, -712202888, -3214543942801667949, -11436, -24, -4230794569.824540, 541.605598, 1, 'binary.NPvfKAwLNUBrUsbNQBjL', 'nchar.青海省晨市长寿深圳街y座 565486', 1630000000038) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630555000000, 238745662, 5355356224239767868, -31138, 41, 22.830003, 4601.537342, 0, 'binary.PeqIYBTzojcHPPpbASyS', 'nchar.台湾省邯郸市六枝特海口路s座 355514', 1630000000037) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630570000000, 745693189, 4651138598564121948, -3614, -40, -41.868811, 96833493.796392, 0, 'binary.MRNQDZhMkAPOMwRDPLza', 'nchar.新疆维吾尔自治区坤市南湖蒙路z座 268958', 1630000000038) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630570000000, -2145996442, -3433600130799541776, -10809, -63, 855480.426782, 668870.374284, 0, 'binary.FlljuYVtUMddfJeXCePu', 'nchar.上海市林县永川深圳路h座 254543', 1630000000038) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630569999999, 1261953798, 314028281416970194, 7113, 92, 57276757.143326, 9980201888194.929688, 1, 'binary.CWKxzlTunbzsSgrpGTXp', 'nchar.河北省淑英县南湖武汉路Z座 875483', 1630000000038) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630570000000, 1435842767, 6578024513554467170, 17462, 68, 3980927396.535860, -442434194.149287, 1, 'binary.VGfEsMVqNVUjawdSRhQz', 'nchar.重庆市深圳市西夏刘路N座 212798', 1630000000038) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630570000001, -1529141111, -2552308375560945509, -3088, -52, 65625.681921, -544.669991, 1, 'binary.bfdhAjhpOMjvNqKKrBns', 'nchar.西藏自治区杨县崇文永安街j座 354402', 1630000000039) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630570000001, -541899245, -5991226110563542766, -707, -107, 35892171731.112297, 385.252012, 1, 'binary.TbAKAMxnTbMsqbiNmVzL', 'nchar.香港特别行政区南京市兴山广州街t座 824478', 1630000000039) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630570000000, 101231908, -1793754924693109102, 28121, 5, -27297115.590120, 235254039.488185, 0, 'binary.viiOyqfWQeKCCeqjJSna', 'nchar.台湾省秀华县沙湾辛集路L座 217819', 1630000000038) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630585000000, -979159064, -4405552399360058755, 29025, -61, -213.670605, 43.565732, 0, 'binary.VTPMgOjAfDTIkXvCBRvm', 'nchar.北京市莹县崇文万街c座 320902', 1630000000039) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630585000000, -732603316, 3291957888362983413, -27560, -5, 19536.856481, 81.835797, 0, 'binary.XyZczHSyVrPUQdbZGVqI', 'nchar.河南省香港市蓟州蔡街Y座 824988', 1630000000039) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630584999999, 1148581502, 1746383234690030123, 6204, 56, -838550587.270660, -7435199862.146900, 1, 'binary.jcVlbATHJidNqVsLaIMo', 'nchar.河北省关岭市浔阳任街A座 776594', 1630000000039) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630585000000, 1999818388, 7210586798654528078, 1630, 18, 6208.528721, -335.584522, 1, 'binary.aoQUSVWoTxqKJPqRozVe', 'nchar.河南省平县滨城兰州路a座 637800', 1630000000039) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630585000001, -884290007, -4556726278944994370, -16568, -42, 3252403692312.240234, 6802621362.778860, 1, 'binary.ppFYTcNMeEFxKGYyuqxK', 'nchar.江西省淮安市城东潘路U座 501030', 1630000000040) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630585000001, -1116869032, -271141834781987082, -15740, -33, -9594782340313.500000, -19702686640.119999, 1, 'binary.ptSTibfgYgBqxXBcljXJ', 'nchar.上海市乌鲁木齐县上街吴路k座 975956', 1630000000040) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630585000000, -435132639, -8699906763762846441, -23184, -19, -4717893819233.429688, 8709722.643050, 0, 'binary.RcLPKAxeNyCrFVgZBWDc', 'nchar.贵州省婷婷市永川香港路M座 438076', 1630000000039) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630600000000, 995611137, -3751963808881697081, -16228, -21, -96744.522458, -531.564886, 0, 'binary.uctNWRFZwpiODjjBdURc', 'nchar.江苏省琳县双滦乌鲁木齐街W座 315778', 1630000000040) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630600000000, -701305447, 7350533321420278894, 12461, -14, 637529643632.400024, -37006.524818, 0, 'binary.nBvNWvoxhJhaxlrXNwSq', 'nchar.河南省澳门市海港骆路d座 670505', 1630000000040) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630599999999, 2038087184, 3229395695102168112, 32164, 120, -60786248.451037, -66349595222.869400, 1, 'binary.jnEtTqkFChOMBYyRcHDQ', 'nchar.陕西省桂珍市秀英徐路N座 443126', 1630000000040) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630600000000, 2133331669, 3831296733741228684, 640, 101, -22204789596077.000000, 12726162933.525200, 1, 'binary.uKmymrIXqCovPNkWAJLg', 'nchar.广西壮族自治区瑞县龙潭深圳路g座 407714', 1630000000040) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630600000001, -1455494423, -4099795228613872218, -24485, -97, -42580895412.277603, 438688.561578, 1, 'binary.GqYiJMfzdIKHFsKfxVpu', 'nchar.贵州省建国县海港陆街z座 539355', 1630000000041) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630600000001, -743807783, -2365949684422468696, -5832, -55, 152697699639.433990, -847.354407, 1, 'binary.TEyMfkklGoyQyuhoMfGa', 'nchar.江西省秀华市黄浦刘路o座 900428', 1630000000041) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630600000000, 1164985515, -1528321163891719683, -5017, 59, -4685058576109.339844, 573635.987915, 0, 'binary.YRSxugbLdtCzYDQuPHiO', 'nchar.青海省刚市吉区成都路D座 183949', 1630000000040) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630615000000, 1552612066, 2109390087439052468, -31070, -121, 8636.758774, 54571.528229, 0, 'binary.xlsMBheXDBRIbHzbgzdk', 'nchar.河北省兴城市东城西宁路M座 385581', 1630000000041) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630615000000, 686960603, -6424166539989529553, 24333, 44, 8214.897773, -47431121552021.000000, 0, 'binary.RWvwTVykxTTNOYllQrFG', 'nchar.湖南省鹏县清河徐路D座 553544', 1630000000041) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630614999999, 68548265, 4587156226014614794, 16331, 57, 154895.265334, -2787.111072, 1, 'binary.ixnKFyhNgVkQywiDtpSq', 'nchar.广东省海燕市白云兴城路u座 101958', 1630000000041) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630615000000, 2266587, 2581645298895273135, 22522, 42, 3276944.200912, 911196.685350, 1, 'binary.rAZwQmSTbVawENHakqoC', 'nchar.北京市玉英市西夏台北路Z座 806985', 1630000000041) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630615000001, -982806837, -8813143395330268157, -9811, -65, 4240824286.641320, -949974.279935, 1, 'binary.IhdGdIOduEtBfgveDAUU', 'nchar.广西壮族自治区佳县怀柔西安街o座 181079', 1630000000042) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630615000001, -680593150, -6347717442100280854, -12839, -105, -3011259806.223000, -99641241686.436996, 1, 'binary.BZPuOZNfEoXwZqhyVXdb', 'nchar.内蒙古自治区南宁县丰都支路Y座 726362', 1630000000042) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630615000000, -417426465, -3607718287738436914, 28714, 52, -972051082.524374, -9817388374.836500, 0, 'binary.cWDUQzDHybUekMyDXMXD', 'nchar.四川省帅市黄浦荆门路A座 476400', 1630000000041) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630630000000, 1094499153, -8105793501718430866, 3482, -67, -190.752084, -5267142.925286, 0, 'binary.uxspDdfsvojZAgyJTRsp', 'nchar.贵州省香港县徐汇合山街F座 623037', 1630000000042) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630630000000, -1816628643, -2390834298866111036, -25491, 93, 421896.632317, 21603.217576, 0, 'binary.hrCIGqyoKXyOENntzjcy', 'nchar.湖南省广州市怀柔六安街a座 810265', 1630000000042) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630629999999, 237543427, 5776314153706817860, 8994, 66, 3092.121681, 4306303.541656, 1, 'binary.utVrWGltqteXbNHvQIuO', 'nchar.香港特别行政区建军市长寿刘街N座 294264', 1630000000042) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630630000000, 726605466, 7765148407017524476, 9380, 66, -725.184771, 4.785127, 1, 'binary.eCvUodgIQEPGQAlVRXHW', 'nchar.湖南省石家庄市海港林路K座 736274', 1630000000042) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630630000001, -2034983874, -1663495204537070761, -3507, -95, -26436104.684611, 3096688941.682010, 1, 'binary.buRNGkuUJrPnERgeimCX', 'nchar.湖南省海口市门头沟贵阳街c座 812797', 1630000000043) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630630000001, -1349842048, -6086664054622894661, -26154, -20, 9.257350, 73467.254310, 1, 'binary.VLQrxUICLTloHhOcsChH', 'nchar.福建省超市崇文通辽路p座 610024', 1630000000043) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630630000000, -1077532579, -4438737277090132487, -4021, -89, -1603199944.809290, 972619729.980217, 0, 'binary.bmvtStTuvDxOdnRZezwW', 'nchar.海南省成县闵行康街q座 877974', 1630000000042) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630645000000, 667040085, 5063347356651668746, -6033, 123, 372331463.295536, -1199.428365, 0, 'binary.yILHXSyMobxUzhCNgPvB', 'nchar.陕西省冬梅县高港谢路R座 540642', 1630000000043) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630645000000, 1643497791, -7930526570990406176, 31172, 28, -53.309129, -52475027161.967003, 0, 'binary.lznIQgSqYtbfWrGxFBvU', 'nchar.山西省南昌市翔安李街Z座 864233', 1630000000043) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630644999999, 1757612759, 453614548545492325, 5562, 26, -42197958317985.296875, -395.764533, 1, 'binary.gZRMNooJsuQCqUkKgObf', 'nchar.浙江省呼和浩特县闵行张路Y座 696051', 1630000000043) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630645000000, 716946034, 8100574991162286831, 8901, 92, 390.851634, -9995.448678, 1, 'binary.WChvjMXwNeLmicQzcpDK', 'nchar.湖南省丽华市江北张家港路O座 383877', 1630000000043) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630645000001, -1691922856, -2342118046897302678, -23270, -66, -172559.465035, 3039868.728966, 1, 'binary.RimPMjXlEtpLazOlwnuv', 'nchar.安徽省玉华市合川黄街F座 509787', 1630000000044) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630645000001, -1339923814, -5560716090143693393, -6671, -10, -84330915414.755005, -2113273814915.989990, 1, 'binary.YGgXnRFnSbGpfKSYyKgV', 'nchar.内蒙古自治区荣县永川朱路u座 853226', 1630000000044) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630645000000, 1122107930, -8861294204430315415, -1044, -23, -3031.346285, 18.218107, 0, 'binary.lUwNsZlGQGhpLpDYqvtB', 'nchar.广东省兴安盟市合川拉萨路K座 345819', 1630000000043) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630660000000, 815803254, -3671302785504904803, -3291, -47, 736.989253, -48462175883.852402, 0, 'binary.PcSjPekpFeCmxcWwgQcF', 'nchar.青海省深圳市黄浦淮安路P座 492194', 1630000000044) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630660000000, 484949428, -5416390991488308737, -14887, 67, 2398644.783561, 8171275.544491, 0, 'binary.BizAmDZxfvTsgphmgDgO', 'nchar.新疆维吾尔自治区齐齐哈尔市秀英杜路h座 144209', 1630000000044) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630659999999, 1440457969, 8606030504343208767, 24314, 96, 92496.379572, 0.813941, 1, 'binary.xAmVpiYdockKtVmdHSIc', 'nchar.河南省平市海港龚路P座 644038', 1630000000044) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630660000000, 1069631125, 7783641181026641655, 29140, 58, 69214.199993, 158732124515.929993, 1, 'binary.SBJQcfJBwhXLUJwatImS', 'nchar.广东省强市怀柔哈尔滨街L座 103945', 1630000000044) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630660000001, -899220871, -9196200436704202533, -27771, -90, -73.878944, -8912.628710, 1, 'binary.VQcAzgArqSQQZnbSiMNU', 'nchar.天津市沈阳市东丽西安街g座 810520', 1630000000045) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630660000001, -1450060823, -615484698684325866, -16629, -4, -8.793729, -23575246237039.601562, 1, 'binary.AESWGdfihvaPnTfmDemj', 'nchar.宁夏回族自治区帆县江北石家庄街M座 983792', 1630000000045) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630660000000, 1278398866, 5363278013106925425, 29093, -83, -70828.447306, -526391.541525, 0, 'binary.iFAFqKguHdrdQhGoCpuS', 'nchar.江苏省刚市江北东莞路b座 826956', 1630000000044) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630675000000, -1081748955, 720719842133998595, -22633, 24, -73662437394.636200, -2235207.112560, 0, 'binary.CdInxRzeRZrFBbTOVcoH', 'nchar.台湾省六盘水县兴山石家庄街l座 541218', 1630000000045) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630675000000, -1665303728, -6208374964158196325, -17938, -26, -12.743038, -6410996304252.719727, 0, 'binary.ESErZzoVFrwLvZLjvszF', 'nchar.宁夏回族自治区兵市南长沈阳路A座 196143', 1630000000045) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630674999999, 1830689374, 6847266081436213038, 27195, 56, -98.825225, -11.841657, 1, 'binary.bKBmkbDmVObIaINgcUkt', 'nchar.宁夏回族自治区六安县东丽黎路Z座 360011', 1630000000045) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630675000000, 905604744, 5992591234700515548, 30228, 29, -771431291465.423950, -75930131567683.500000, 1, 'binary.uJqjLxypwZAqCJHRMkKo', 'nchar.吉林省艳县城北贾街Y座 511120', 1630000000045) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630675000001, -1874157012, -4583327710928801759, -27522, -76, 53914287540.938499, -9385422.995425, 1, 'binary.wycnNJGrIpmtWWvFxuJY', 'nchar.宁夏回族自治区云市孝南江路A座 778572', 1630000000046) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630675000001, -1498560711, -9199781197179273356, -25882, -75, 4614968554.698110, -96421428706.153503, 1, 'binary.OOYjhYdCGZQViNShXiSg', 'nchar.吉林省惠州市江北关岭街W座 967516', 1630000000046) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630675000000, -596563585, -8961615493016741888, -10813, 102, 75.123805, 6555481001.569020, 0, 'binary.DVXQBGshLAcqMWMMeiDT', 'nchar.山西省桂兰市涪城佛山路C座 407229', 1630000000045) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630690000000, 81214187, -3182813081122938906, 4960, -50, 518940275802.109985, -7999305661.759080, 0, 'binary.fkEdEbNuIkBTKcrHnEjx', 'nchar.新疆维吾尔自治区佛山市怀柔呼和浩特街P座 745345', 1630000000046) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630690000000, -1132347210, -6643466065281753528, -27772, -3, 8162664758739.139648, -13662048540.698799, 0, 'binary.KmKfzpIUppEqzuPvExem', 'nchar.四川省莹市牧野哈尔滨路j座 521095', 1630000000046) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630689999999, 1019010549, 6975314636031351786, 28464, 43, -465.888140, 8910415.572030, 1, 'binary.rBiBGLvfQWmnGDquOTbn', 'nchar.广东省雷县南溪宋路F座 681268', 1630000000046) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630690000000, 378275737, 876425613508142928, 15367, 120, -49.379488, 7567.687919, 1, 'binary.BTwfiAxrnagWWuCCCSZQ', 'nchar.北京市南昌市南长香港街i座 314362', 1630000000046) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630690000001, -533673302, -4156210237594471836, -17141, -10, -931105.914523, 799382106.862106, 1, 'binary.NqTaorSXMNHGbcIiftLN', 'nchar.香港特别行政区淮安市牧野石家庄街R座 897882', 1630000000047) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630690000001, -1935282932, -2743254909741386818, -6325, -67, 25114142.334721, 78.857657, 1, 'binary.hLaIbMlaSZIaojoxNNAG', 'nchar.湖南省邯郸县新城重庆路W座 451361', 1630000000047) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630690000000, 693093205, 1731593666471158488, 32616, -34, 944511.517342, -3.585256, 0, 'binary.JGrrPFPHkdvblDPQLBzo', 'nchar.安徽省艳市龙潭陈街I座 824093', 1630000000046) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630705000000, 1768911737, 5728476461209604096, -29190, 66, -6177089795.760590, -21430.400483, 0, 'binary.KANmXakVbwmKTQEcoIkv', 'nchar.吉林省帆市静安福州路e座 331035', 1630000000047) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630705000000, -248617365, -4341045528963124184, 31755, -98, 124670342.644870, -654637491670.374023, 0, 'binary.IzfBodxsdDxJktqQeDDU', 'nchar.浙江省秀芳县黄浦郑州路L座 115314', 1630000000047) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630704999999, 27001027, 339256900217870846, 11700, 1, -1455323856048.100098, 447841.805243, 1, 'binary.tMfHAqfBuEMKIckNFKLY', 'nchar.内蒙古自治区亮县清城陈街k座 990698', 1630000000047) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630705000000, 1581778818, 8464425008394999321, 20061, 5, -5247104654.611190, -568125.266376, 1, 'binary.JAXQCWWoDrpJuxVSlCNu', 'nchar.宁夏回族自治区萍市安次六安街H座 295531', 1630000000047) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630705000001, -732869228, -2906753353691356694, -5441, -3, -109283.289234, 9159375.165842, 1, 'binary.VYdDCHOMFAhsntioQInn', 'nchar.澳门特别行政区璐县西夏海门街A座 607065', 1630000000048) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630705000001, -18474510, -5999800564410930013, -6311, -2, -398057879.913052, 8761.567919, 1, 'binary.fIJqDAvfpidoaJSJkpnq', 'nchar.安徽省宁德市浔阳长春街U座 799007', 1630000000048) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630705000000, 850296579, 8875126379280838717, 10524, 108, -2975287.612558, 0.445600, 0, 'binary.eoLmnRFaXvklftfvhFCU', 'nchar.四川省亮县东城南京路E座 405800', 1630000000047) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630720000000, -239418734, -7503726504441061411, -31831, 84, 69021572289.137802, -86475940923.449203, 0, 'binary.ApWGXJYAZWgkReWPsvDb', 'nchar.湖北省磊市璧山武汉路O座 323410', 1630000000048) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630720000000, -943706680, -214023538774872985, -12169, 127, 948155.120585, -65149.125324, 0, 'binary.sujGooIQzKvLdzqRekyb', 'nchar.河南省丽娟县华龙哈尔滨街l座 264772', 1630000000048) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630719999999, 1251825975, 5053354830656579627, 14919, 60, -7531018879634.370117, 310964263643.562988, 1, 'binary.RfrhrTWzkzBvUvupCUaE', 'nchar.海南省阳市平山马鞍山路I座 852814', 1630000000048) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630720000000, 1115544686, 4049894819935008122, 30814, 12, -75.765668, 1187804567.210350, 1, 'binary.hYtJJtMEzEnmlYixUssL', 'nchar.河南省哈尔滨县魏都杭州路z座 972095', 1630000000048) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630720000001, -1724765969, -736233583823352610, -6737, -57, 893.536927, -7421.472515, 1, 'binary.RsUbHbctLoVkgmtdCxjM', 'nchar.黑龙江省马鞍山市山亭孙街b座 213806', 1630000000049) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630720000001, -1986547513, -6324903826238608678, -14843, -46, 309302.506851, -614273917609.833008, 1, 'binary.vnLJpYckYTAcDOpDNuWh', 'nchar.天津市亮市南溪陈路q座 364119', 1630000000049) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630720000000, -1284939264, -9095077298976089415, -19239, -92, 31.280584, 7379.657977, 0, 'binary.knKChKaZsyhUfkgmgzph', 'nchar.贵州省兴安盟市淄川郭路G座 242776', 1630000000048) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630735000000, -762937350, 8729420312334257343, 27701, -108, -6.651477, -29.713736, 0, 'binary.fpjgqsvwAKHintMJaYER', 'nchar.黑龙江省淑华市花溪宁路W座 152088', 1630000000049) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630735000000, 1144380216, 5276665732684544642, -11205, -89, 8215.254115, -99811752553.775497, 0, 'binary.FflDToYYzhVTnyRGzKGA', 'nchar.江西省南京县金平孙街c座 254949', 1630000000049) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630734999999, 1075377727, 9020113518015848371, 11084, 28, 307417.308042, -87.561190, 1, 'binary.kEOyxbKVdHlFqhZZzYwq', 'nchar.青海省佛山市安次深圳街Z座 504751', 1630000000049) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630735000000, 582692563, 4638155561099114479, 23761, 48, -29824236570673.398438, -10200.908461, 1, 'binary.XziirLIHCuFKtpiXVrTy', 'nchar.广东省帅市西峰张街h座 174088', 1630000000049) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630735000001, -1716643044, -8326169264977759340, -4200, -30, -2.318414, -726141333.615880, 1, 'binary.FZBESQUiuERkOgEMEfQR', 'nchar.广西壮族自治区英市海港汪路W座 657875', 1630000000050) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630735000001, -686568708, -4371717027180867061, -6734, -88, -578830467.970145, 9456.996341, 1, 'binary.ybxyxSLSKWvhXIhIuTZo', 'nchar.西藏自治区鹏县华龙邯郸路K座 280464', 1630000000050) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630735000000, -463229385, 8322975415402188951, 7658, 81, 48067565948.430801, 1684.497042, 0, 'binary.VCPIPiYLkNeWVJRVYdAa', 'nchar.江苏省伟县新城杭州路U座 135067', 1630000000049) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630750000000, 229305482, -8755922362006582494, 15607, 16, 433186324.150179, -9760091.526296, 0, 'binary.vzKjmFtaWUQJWUmLYsoF', 'nchar.广西壮族自治区潮州县璧山深圳街u座 513872', 1630000000050) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630750000000, 887769742, 8828265476094538774, 15810, 6, -52009423024.988998, 457109451.488690, 0, 'binary.lFOSpWYYjCkwLqOGSclj', 'nchar.广西壮族自治区伟市大兴李街A座 575739', 1630000000050) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630749999999, 806743984, 7134986215003200921, 17680, 41, 80628998.429324, -398852949.893027, 1, 'binary.KNgNzEsWMMOErSdhZARB', 'nchar.台湾省大冶县西夏辛集路B座 294228', 1630000000050) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630750000000, 1218616066, 4338651506702922568, 20337, 121, 607218.969786, 29540695532115.398438, 1, 'binary.hXxPnZwhSlMFInaNEPGO', 'nchar.上海市桂兰市金平刘路x座 286919', 1630000000050) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630750000001, -592467708, -3107486233936469903, -26640, -37, -77805664.682649, -1730.324950, 1, 'binary.fpSPyrjwsVtXzEHRGCaS', 'nchar.福建省沈阳市东城张路k座 869492', 1630000000051) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630750000001, -547550314, -5200749799296792327, -27549, -59, 2034147.803264, 96891027.798801, 1, 'binary.cyVZnAOokBmkMGIbacqs', 'nchar.江西省宇市蓟州唐路K座 406871', 1630000000051) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630750000000, 756019639, -653863967829096798, -30967, 59, 68379.967777, -1154096688678.510010, 0, 'binary.fHCaNBTuAEHvVNpuNcxn', 'nchar.安徽省宁县永川东莞路X座 798708', 1630000000050) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630765000000, -1406057540, 1446134498171766899, 30680, 68, -9307952080739.890625, -1153314466.810470, 0, 'binary.aDuEaSxjYaNCTgFqMHlC', 'nchar.西藏自治区红县静安黎路I座 596984', 1630000000051) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630765000000, 133613101, -1336954935529805727, 585, 116, 30.398745, -613552078.887368, 0, 'binary.NgMivPQObBgUbKnAwWEj', 'nchar.湖北省金凤县门头沟刘街f座 712446', 1630000000051) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630764999999, 656042024, 1646194287674616827, 26191, 10, 6678822.415847, -95361406615.342804, 1, 'binary.LZeGatPnXBHGNQggCUgW', 'nchar.澳门特别行政区西安市清城汤路p座 810444', 1630000000051) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630765000000, 1983919127, 7730061788745380233, 12586, 75, 10716267.549970, 7.199934, 1, 'binary.rnitdHGQBawBYXtOfvDJ', 'nchar.北京市玉兰市清河海口街u座 800278', 1630000000051) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630765000001, -1382937017, -109262277060062044, -24986, -53, -431535423232.208008, 34209788.409645, 1, 'binary.WSTgldQbIqYUaOeVUhSk', 'nchar.云南省秀英市涪城张路H座 199974', 1630000000052) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630765000001, -1301473352, -6756208355269860322, -17139, -45, -689118.755923, -3373577.841810, 1, 'binary.rcYvJxobOrraprgqcGvR', 'nchar.台湾省洋市花溪宜都路I座 962472', 1630000000052) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630765000000, -691470080, 1659254673769147544, -23790, -47, -429810768489.799988, 93436.707719, 0, 'binary.SxTTHFObymUpnuAfgYSQ', 'nchar.贵州省海门县西夏海门街a座 133401', 1630000000051) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630780000000, 921298258, 8536844726148128680, 3660, 26, -34185874.434563, -26620.589344, 0, 'binary.xevnfxQByaOjIEnqHaqe', 'nchar.重庆市华县山亭赵路b座 801493', 1630000000052) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630780000000, 1233028572, -8019335724423257023, 31663, -58, 14.142909, -50404.483362, 0, 'binary.MgKDUmZIKAlVhLpazpsJ', 'nchar.青海省永安市清浦彭路P座 393906', 1630000000052) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630779999999, 1876585459, 2853158241768185532, 24232, 50, -38916414122.860901, 6486812.485190, 1, 'binary.fafedlhFPmPAyJJGuMuZ', 'nchar.青海省潜江市秀英沈阳路X座 835387', 1630000000052) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630780000000, 1194165890, 7697386066201959752, 12368, 15, -7467278746696.700195, -979006.127435, 1, 'binary.sEHpIDvtRWaxcUbqPHAn', 'nchar.新疆维吾尔自治区大冶县高明项街d座 680148', 1630000000052) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630780000001, -1899593535, -1379716049261187467, -26105, -97, -17.445226, -149.378109, 1, 'binary.sHyQLVjnSTQSXpcWxHjq', 'nchar.安徽省杭州市城东郑州街M座 499265', 1630000000053) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630780000001, -1856641529, -4102589906454836588, -24873, -61, 97710303188.778000, 9646.234878, 1, 'binary.fKSswvhHhMTcaIjfaUUk', 'nchar.安徽省建县牧野杨街U座 584763', 1630000000053) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630780000000, 542554488, -3045723568122762779, 18580, 33, 95242718247053.500000, -50170311.264161, 0, 'binary.PUzrCqSyZiemQmkCCdGz', 'nchar.重庆市玉兰县永川汪路N座 270623', 1630000000052) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630795000000, 1864777486, 9048501077169003317, 32497, 90, -21112693476.624199, 960.488977, 0, 'binary.EEwLsBOCVnXbQbGiHwjl', 'nchar.河北省天津市魏都徐街V座 183214', 1630000000053) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630795000000, -1607594419, 3244019062872113101, -3112, -38, 4371695.605750, -76333.232422, 0, 'binary.FoXqOarMdnRuIkzdWEfn', 'nchar.安徽省石家庄市上街李街j座 287811', 1630000000053) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630794999999, 173077592, 5900121444981917372, 31259, 47, -9.692719, -36537321184.241699, 1, 'binary.hAZkGTgZudTvNdAfGCrG', 'nchar.黑龙江省林县长寿长春街H座 568159', 1630000000053) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630795000000, 1357591704, 8166773293007138161, 11502, 15, 9824768605988.179688, 899.269307, 1, 'binary.ORKiLvVsgwUaMmmVzXYK', 'nchar.浙江省西安县海港关岭路w座 192982', 1630000000053) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630795000001, -1842197906, -1075636322848135854, -11343, -9, 9085057779.572281, -9427483311859.769531, 1, 'binary.urBDWyTekFLJVKfewubE', 'nchar.江西省静县高港辽阳街W座 980270', 1630000000054) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630795000001, -1534128171, -4579657021740144805, -28105, -23, -265482542779.970001, 74780.975545, 1, 'binary.sEpkrqnSpFfYKIgeSBvK', 'nchar.澳门特别行政区西宁市龙潭六安路X座 127241', 1630000000054) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630795000000, -760013920, -8462295357527459170, -31765, 11, -433.960695, 264.431691, 0, 'binary.DroLRaBIftSwkoEbBZUl', 'nchar.山东省丽丽县黄浦谢路f座 644732', 1630000000053) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630810000000, -1675325589, -360996985377003606, -2347, 24, -470.741524, -887230390.331345, 0, 'binary.udlpjXsecEvxMZCZyvrV', 'nchar.江苏省银川市山亭太原路J座 723211', 1630000000054) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630810000000, 1632642973, 7850590523192382300, 13631, 45, -47687.239109, -81863875.566057, 0, 'binary.jmfRTYATfWhgLdSwABgZ', 'nchar.新疆维吾尔自治区长春市龙潭刘路m座 413049', 1630000000054) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630809999999, 1959334832, 4568407287596246175, 27961, 84, -665950847.396483, -29596243749715.199219, 1, 'binary.JOlrzeKxQTwVbozdztiV', 'nchar.山东省广州县高明张街C座 757018', 1630000000054) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630810000000, 1375371462, 4011481089622391741, 11886, 126, 4.397144, 4202513.398747, 1, 'binary.EblbpxwjuFqWmvABRtpz', 'nchar.香港特别行政区坤县南长王路W座 576754', 1630000000054) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630810000001, -1132521267, -4710706752937901089, -27234, -102, -277590425.724995, 292916.997240, 1, 'binary.DaNIAqljzrMdiAdtjNrB', 'nchar.江苏省畅市梁平秦路K座 961783', 1630000000055) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630810000001, -394127423, -4195198128268963203, -5174, -112, -37786616.462910, -750832.942933, 1, 'binary.rDUuOHQMIpSTjzaBeDKl', 'nchar.青海省亮市城东惠州路R座 997920', 1630000000055) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630810000000, 415436252, 7840392447567623067, 18496, -2, -20101885975.533798, 789.450282, 0, 'binary.CIlEgPRwfDUmqTEAjBrU', 'nchar.山西省桂花市高港张家港路B座 439810', 1630000000054) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630825000000, 1382842369, -3387166153829557613, 5113, 67, -14533655399834.400391, -47045088950.955902, 0, 'binary.fdwVbTqALVxEKqxPmklJ', 'nchar.香港特别行政区桂芝县沙市桂路K座 439607', 1630000000055) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630825000000, 122830188, 5944964533814104404, -4275, -2, 503740.982450, -2713577716.766000, 0, 'binary.KnHTmENdKEWNLWdfvFxb', 'nchar.内蒙古自治区婷婷市大兴乔街a座 468770', 1630000000055) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630824999999, 609279903, 9143142539302518131, 18578, 58, 6.776714, 7355.869852, 1, 'binary.PsdCUwiiFfTfBdYWgMIf', 'nchar.广东省巢湖市高坪关岭街z座 165945', 1630000000055) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630825000000, 1229687800, 6229049320529684281, 13288, 61, 1136575.519568, -474.263794, 1, 'binary.UtlqumZjObldYJWTCHVF', 'nchar.上海市玉梅市城东陈街K座 187484', 1630000000055) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630825000001, -902381702, -6581003712798510587, -16241, -42, -136567151.288395, -81351450.825485, 1, 'binary.vZnItDAvBlQXFtrMrdAk', 'nchar.广东省合肥市闵行南昌路a座 421030', 1630000000056) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630825000001, -1633588040, -9147247193490618424, -16771, -115, -2.864546, -4.968001, 1, 'binary.OChQYNfkTrcSaZTJGfhO', 'nchar.云南省淑兰县牧野农街t座 752385', 1630000000056) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630825000000, -997989279, 7637562832426174518, -5, 72, 1838649266.575190, -32247151699394.300781, 0, 'binary.fLcdsxEDyCdsbzARmlzG', 'nchar.吉林省娟市秀英潘街u座 599699', 1630000000055) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630840000000, -1691466505, 3835361758424457104, -21465, 99, 17.423367, -927580467091.141968, 0, 'binary.ExYLmKXMaFjayqkBEWqC', 'nchar.浙江省乌鲁木齐市东丽康路s座 780818', 1630000000056) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630840000000, 990486101, -6476848417158885996, -6947, 34, -91088473.667455, 443265343.199751, 0, 'binary.dyTxrTzimrnLgwtLehEp', 'nchar.海南省帅市金平兴城街F座 303386', 1630000000056) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630839999999, 1355859529, 2260526383089822706, 30660, 63, -672086975563.209961, 9219879.518002, 1, 'binary.EEjtfcofhSPxOuFgMlug', 'nchar.山西省凤英市长寿胡路d座 722345', 1630000000056) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630840000000, 720225284, 8056479222648510406, 7870, 107, 3.205667, -15331943645.198200, 1, 'binary.qBFljuOsopeYwpczltun', 'nchar.海南省杭州市锡山杭州街Y座 563787', 1630000000056) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630840000001, -1666639404, -1502779151523040369, -32737, -27, -720231064.559860, 9483852418979.500000, 1, 'binary.sDGclxLTrGjIYGBWUzox', 'nchar.江苏省颖县华龙奚路M座 347083', 1630000000057) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630840000001, -513166008, -1798257110690905490, -17212, -65, -6875665232.854830, 1.501719, 1, 'binary.JioYSyYNMAmHQGKIwFpt', 'nchar.澳门特别行政区畅县永川淮安街i座 315960', 1630000000057) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630840000000, -784030741, -771760196117941650, 5269, -23, 488442494858.158997, 142.977034, 0, 'binary.RyfovtjrYYDbDQEVcHoA', 'nchar.福建省帅市兴山合山街z座 360892', 1630000000056) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630855000000, -759466985, 3260110813666913849, -21345, -118, 6001735483.766000, 811956391.434487, 0, 'binary.FgtcgDCGdWGhileXYeVC', 'nchar.辽宁省敏市城东潜江街t座 539658', 1630000000057) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630855000000, 1791483134, 1877345879709438108, 7122, 108, 649645.697610, -3.176571, 0, 'binary.VOAUXbpzoEXTfEombqFu', 'nchar.湖北省建国县双滦昆明街k座 555641', 1630000000057) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630854999999, 819862528, 8086075097163190658, 28478, 59, -8892423630966.660156, 927321477.432369, 1, 'binary.gEIBgRUfuMarfhivmcmN', 'nchar.海南省海门市沈河季街o座 938191', 1630000000057) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630855000000, 575972371, 8165684898549408541, 26532, 30, 2158.716179, 6332790959904.230469, 1, 'binary.RzgEyNIsdJwDbkhjuZhn', 'nchar.广西壮族自治区哈尔滨市双滦薛路M座 750545', 1630000000057) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630855000001, -568694685, -6156824576786534987, -5004, -80, -8796651.346065, 4.370643, 1, 'binary.vDKHYEXPpBzKIFbWrBHH', 'nchar.四川省春梅县永川董路R座 716271', 1630000000058) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630855000001, -202484706, -7242157303332761279, -5895, -39, 1369656077.152570, 45024.146483, 1, 'binary.UTIcQraFLhrzeKZQNGad', 'nchar.陕西省大冶市大东陈路V座 230063', 1630000000058) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630855000000, 968718547, -7083502452755942963, 30186, 34, -808.116870, -355374.445932, 0, 'binary.FIxenkYBuIDmoaBpvKJr', 'nchar.内蒙古自治区想市闵行合肥街m座 213729', 1630000000057) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630870000000, 259545745, 6793904417678601057, 29752, -91, 35083182.940608, 4579746.564176, 0, 'binary.wmnksDymOwGQownBXGRS', 'nchar.湖南省上海市淄川陈路f座 699980', 1630000000058) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630870000000, -798452451, -1421146164509922388, -30643, -44, -532.819299, 864903894.997066, 0, 'binary.FofIkZDYExLKhITHZjpy', 'nchar.北京市静县长寿刘路V座 929762', 1630000000058) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630869999999, 810375591, 6862940885997459592, 12888, 67, 1.743840, 42697.428148, 1, 'binary.OrGwClCMpfhfshmaeYAS', 'nchar.安徽省坤市长寿许街s座 864780', 1630000000058) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630870000000, 2141142518, 330171567484187630, 5038, 87, 73252.885684, 88624.734440, 1, 'binary.cdSnMdwrroFKtbPAJSbg', 'nchar.安徽省沈阳市清浦汕尾路C座 749970', 1630000000058) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630870000001, -702799898, -322816941471556942, -1394, -123, 9456805.646888, 2105.641243, 1, 'binary.rTaTBdXbBszZjTTwracU', 'nchar.四川省玉市海港大冶路h座 545972', 1630000000059) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630870000001, -706124307, -5958027025637340951, -30853, -27, -7966.705252, 2.270573, 1, 'binary.eOyuShSfdOAmaSNhUZUv', 'nchar.河南省长沙县萧山毛路H座 196587', 1630000000059) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630870000000, -486193469, 7258930411934958638, 23283, -84, -6.193098, 11.792424, 0, 'binary.KGiDWTZdgHETHLJePGIT', 'nchar.陕西省丽市白云兰州路x座 161175', 1630000000058) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630885000000, -282533404, 7684010141772871588, -23850, 17, -2997190086014.000000, 931579019.615816, 0, 'binary.kZsMznDmRkjSoUQCWmtw', 'nchar.宁夏回族自治区汕尾市清城北京街c座 432095', 1630000000059) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630885000000, 1596401672, -5390915537011895583, -19578, 118, -9665.572275, -7154265.495520, 0, 'binary.JkHelKKoDnnJzPHiEROB', 'nchar.西藏自治区晶市梁平梧州路b座 369190', 1630000000059) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630884999999, 1840788362, 568759292490183791, 18205, 21, 16.931152, 17691.251149, 1, 'binary.EDicJkxTXgqUtLXKDjKy', 'nchar.新疆维吾尔自治区勇县蓟州沈阳路U座 172773', 1630000000059) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630885000000, 365787442, 1666872794496374179, 13837, 37, 193390765070.401001, 546707.447097, 1, 'binary.lmEGkvWshsqnAktNzJbB', 'nchar.重庆市桂花县南湖巢湖街U座 689551', 1630000000059) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630885000001, -745755820, -8898782181578548041, -7682, -15, -443.639102, -255152262.128928, 1, 'binary.MWmdVCjrANIfsdHAAVmb', 'nchar.河北省淑珍县长寿谢街k座 131370', 1630000000060) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630885000001, -2029500216, -7380552851400848492, -3516, -8, 8.915821, -51.793696, 1, 'binary.vQnridOAWDVWkJYYdTtF', 'nchar.云南省六安县海陵宁德街t座 241913', 1630000000060) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630885000000, 1648193924, -5763807398275594930, 27798, -65, -3.657749, 9559111883869.490234, 0, 'binary.VLogQYbaHPpPpmgyuzos', 'nchar.台湾省志强县和平刘路a座 827192', 1630000000059) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630900000000, -997698344, -4360698110328218759, 31934, -79, 8770449833.941080, -71856107060.251297, 0, 'binary.trhWcwdEKeoGUcQdImgV', 'nchar.天津市西安市牧野天津街q座 880750', 1630000000060) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630900000000, -492616894, -7002758781471003065, 28164, -11, 4740658.868259, -5320539.530775, 0, 'binary.TzdNtGFTXZWMADJaayqx', 'nchar.西藏自治区西宁市秀英杨街A座 353774', 1630000000060) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630899999999, 1825013146, 1744104394556381743, 31778, 117, 908811698547.689941, 42.982948, 1, 'binary.FtOgWPVAvygSIYsTWnHX', 'nchar.澳门特别行政区梧州县海港六安路D座 341014', 1630000000060) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630900000000, 2076832076, 3306826763175476238, 29009, 65, 654125.128750, 23.786689, 1, 'binary.yRAQxkeArOAnSkFHvhjQ', 'nchar.青海省南昌县清河澳门街f座 357735', 1630000000060) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630900000001, -364752002, -5092648072975157908, -23087, -39, 9.504646, 93358807.508628, 1, 'binary.sFAvwLkiYcepPputybEK', 'nchar.四川省文县萧山惠州街i座 903240', 1630000000061) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630900000001, -1784446385, -2802855779017240513, -5552, -54, -860449735702.189941, -703215980204.104980, 1, 'binary.RtSNrxogNuhOoRhEPrMJ', 'nchar.青海省静市孝南李路H座 399925', 1630000000061) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630900000000, 1445349008, 992848000519415190, -17518, 28, 4014000610.625470, 592.602654, 0, 'binary.IFSsgUZILZuPRwXTuFEw', 'nchar.海南省沈阳市六枝特长春路n座 155408', 1630000000060) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630915000000, -134082975, 4026898983947505460, 20740, -64, 24146076.871632, -207518516.166626, 0, 'binary.irWEJqxWnIlrKDExOAvg', 'nchar.天津市太原县吉区拉萨路D座 176064', 1630000000061) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630915000000, 1299050318, 3065792171140876784, -12329, -3, 74005.658734, -418157994.246836, 0, 'binary.sqAYHZcIIihZMMauybjG', 'nchar.内蒙古自治区桂花市城北阜新街y座 784832', 1630000000061) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630914999999, 711052785, 2718796412708678637, 32243, 69, 4069895314.170900, 38406.385424, 1, 'binary.UgajoEPkcVXcWkUCGwkP', 'nchar.安徽省桂花县房山傅路O座 240748', 1630000000061) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630915000000, 2140137646, 1082661109056257532, 23250, 103, -44495004919076.296875, -7284.922434, 1, 'binary.ryfAsYaeEOkhesQMRitO', 'nchar.台湾省玉华县徐汇杨街C座 637917', 1630000000061) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630915000001, -1403755208, -3324715225642465377, -15193, -53, -3142.782618, 1794554.528658, 1, 'binary.aOAYKsmWzKDqjOpbOYrJ', 'nchar.河北省倩市清河黄路t座 205485', 1630000000062) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630915000001, -361144599, -8536611280568601202, -8124, -93, -13513340.923311, -20153.231767, 1, 'binary.XgncJmqFHazSpRWcMVeT', 'nchar.澳门特别行政区帅县清城深圳街j座 501390', 1630000000062) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630915000000, 929886382, 6830786048646808920, -26587, -84, 201249126.540132, -33020.844039, 0, 'binary.kUqBGPosKRCkaijDufGt', 'nchar.陕西省澳门市蓟州祁路C座 345922', 1630000000061) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630930000000, 1849726714, -3222927126454669927, 21701, 35, -764955573301.579956, -677588544809.604004, 0, 'binary.mXWIcnTunwqEKbKnJsRO', 'nchar.青海省云县南湖张路t座 577114', 1630000000062) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630930000000, 1948380077, 1829472867218108411, -2841, 62, -585408.996552, -8.398878, 0, 'binary.fZDJrrryXodeitdEZiDN', 'nchar.天津市辽阳市平山深圳街O座 892463', 1630000000062) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630929999999, 215833483, 6741487167704692542, 24982, 99, 7.720103, -4484984.118093, 1, 'binary.PUhvTciOFJERTXpNFDMf', 'nchar.海南省雪梅县萧山夏路s座 884246', 1630000000062) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630930000000, 283066224, 1560470331627072050, 2152, 14, 23735906455.603001, 977.642371, 1, 'binary.LQZzMIDAEVyjgirFHORu', 'nchar.河南省秀梅县房山黄街D座 578931', 1630000000062) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630930000001, -1383444081, -404967010555838935, -20478, -67, -29413948653.431301, 2289249875341.339844, 1, 'binary.gGaUfmagkabfKeDUnCCo', 'nchar.江苏省冬梅县六枝特张路g座 635526', 1630000000063) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630930000001, -821980909, -1357071288288006358, -23706, -57, 6152.175178, -26066560.757762, 1, 'binary.kmxekdKOIgvNnCSEZlwN', 'nchar.上海市宜都县双滦王路P座 262541', 1630000000063) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630930000000, 713911469, -6504806039884313820, -32386, 118, 431693877138.190002, 7127294.830732, 0, 'binary.FArXPzfLVQjsNuWiHLrQ', 'nchar.宁夏回族自治区秀华县长寿钟路t座 443656', 1630000000062) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630945000000, 1000635145, -6949456453535507535, -32142, 99, -7613228535871.339844, 5.367833, 0, 'binary.yafjOZqJhdMZFCxrvkjO', 'nchar.天津市志强县上街陈路g座 745449', 1630000000063) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630945000000, 2094975637, -590793247049504295, 92, 70, -846255.238019, 37.423177, 0, 'binary.IBHCEHNtLvmkpSCmVjQg', 'nchar.台湾省桂芝县华龙合肥路b座 733142', 1630000000063) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630944999999, 792673522, 2133996305758691365, 11545, 90, 8043187112236.719727, -328687222.743009, 1, 'binary.ZJIzomZBnRwLgnTtcylc', 'nchar.安徽省波市清河卢路e座 142743', 1630000000063) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630945000000, 1815853908, 1589355425036470987, 22184, 52, 8.753561, -0.772172, 1, 'binary.eqnhiDmrJHLxSTqywNzp', 'nchar.广东省合山市朝阳佛山街y座 254118', 1630000000063) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630945000001, -1908151355, -8449086371025617726, -31176, -107, -226488394.744318, 522688593.135097, 1, 'binary.mOQahkNsfbxPPiCysDOX', 'nchar.新疆维吾尔自治区潜江县魏都昆明路q座 187031', 1630000000064) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630945000001, -177205853, -5927588760169982955, -1616, -89, -3.764988, 22268450673521.398438, 1, 'binary.dIMAiZxTGtcVSpGTvrOy', 'nchar.重庆市南昌市房山上海街U座 493109', 1630000000064) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630945000000, -271977227, -4833640128107527469, -29661, -35, -25823270909397.800781, -215115.472476, 0, 'binary.FJHanbZZKKPTINTvFuJu', 'nchar.山西省太原县普陀海口路z座 522140', 1630000000063) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630960000000, -1061924199, 80315342405283554, -5983, -53, -35303358.173361, 823245211.259967, 0, 'binary.DHcLdCgRElelyoEjXxxo', 'nchar.云南省辽阳县兴山许街Q座 204291', 1630000000064) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630960000000, -2008448047, -2507465824745412203, 5703, 39, 3073425.192830, -4127246.560225, 0, 'binary.PGGakvXluJKSczwfkbFA', 'nchar.内蒙古自治区深圳市涪城韦路L座 184789', 1630000000064) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630959999999, 1731746435, 8656881002710317018, 24493, 42, -51366300790725.398438, 7057719908.426410, 1, 'binary.GcyDiiYlodcmmVYJcfsy', 'nchar.澳门特别行政区萍县长寿淮安路X座 216888', 1630000000064) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630960000000, 1535163067, 199892343902462919, 8312, 26, -5886360.892067, 99168508385732.296875, 1, 'binary.NajqJanSydLerCaBsTFl', 'nchar.西藏自治区六安县魏都邹路E座 600769', 1630000000064) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630960000001, -1744206201, -5989201622885398375, -9394, -16, -22156768397.647999, -313965437.622286, 1, 'binary.ljgVmLXQbdPjEOYMKEmN', 'nchar.辽宁省玉兰市新城邵街T座 422511', 1630000000065) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630960000001, -416139810, -6604173252994763764, -6397, -53, 826553399123.199951, 28094588.168751, 1, 'binary.hcinwRrwHHsWiQqvAaPk', 'nchar.山西省兰州县永川张家港路l座 400205', 1630000000065) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630960000000, 1411363822, -5559490192650806316, -24296, -124, -84520160618.765900, 48233.620153, 0, 'binary.duMCmTwWDPUzYzHdZrXk', 'nchar.海南省建国市萧山朱街m座 337644', 1630000000064) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630975000000, 63717118, -1781107297269354794, 14103, -107, 4455585.961990, -65419.341974, 0, 'binary.BlHycIqcHPSyynpSsDHt', 'nchar.广西壮族自治区桂芝市西峰史路K座 709908', 1630000000065) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630975000000, -108473967, 5316060064111515170, 7075, -74, 673543603.332905, 8011713.391465, 0, 'binary.ZsNVSCEilaFozvIMOgVn', 'nchar.山西省秀兰县萧山惠州街s座 291738', 1630000000065) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630974999999, 1701097332, 6995506575159608552, 22867, 47, 4495217807.100080, 38.526985, 1, 'binary.VTDyicwtvKBaCCmjUaDu', 'nchar.吉林省天津县长寿宜都路k座 930822', 1630000000065) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630975000000, 257457420, 8835364401886927960, 21297, 21, 0.844779, 716050955.344671, 1, 'binary.TCUqNtJoXousOXFzOaFV', 'nchar.湖北省旭县花溪宋街n座 825626', 1630000000065) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630975000001, -622389272, -4556948567877249858, -30519, -93, 3.569778, -2781.981860, 1, 'binary.SSnWtedSkSpZxzvsXKty', 'nchar.西藏自治区兴安盟县静安哈尔滨街c座 120405', 1630000000066) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630975000001, -84782654, -8863584638236264237, -5954, -44, -220.796336, 81484582682754.296875, 1, 'binary.tQzwvVqEIsBAxnymBEia', 'nchar.甘肃省永安市江北南昌街u座 555029', 1630000000066) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630975000000, -7406744, 4193139347325385474, -9523, 51, 96.656028, -858851298.663605, 0, 'binary.QfqialqEnUJEPhCtbzcy', 'nchar.青海省敏县淄川卢路v座 513752', 1630000000065) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1630990000000, 1127802865, 3673503514622188410, -1852, -113, -34837378.663679, -77832209110.181000, 0, 'binary.rdtbEFZKYFDDJcbwZQUI', 'nchar.上海市潮州县友好辽阳街J座 716345', 1630000000066) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630990000000, 222250382, 7102048992271642834, 30230, 0, -27475250902790.601562, -7.875430, 0, 'binary.okaTayFnJLFHVPbosPMw', 'nchar.湖北省娟县六枝特郑州街o座 923846', 1630000000066) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630989999999, 997138993, 291600547682899796, 8706, 49, 527231819.674759, -76.470030, 1, 'binary.gSCVCKyayTuQHeyozlnD', 'nchar.澳门特别行政区太原县江北六盘水路E座 813817', 1630000000066) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630990000000, 1527492158, 8131177329340856446, 16932, 24, -485902.216583, 47420.341433, 1, 'binary.xIJLktMoyieUcwAitKAf', 'nchar.广西壮族自治区丽娟县永川钱路D座 710055', 1630000000066) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630990000001, -1186362057, -8101517704046664109, -8133, 0, 15457163.632735, 790549863.502675, 1, 'binary.domgcCyjkvkGvnfhJchV', 'nchar.安徽省台北县蓟州张路V座 853541', 1630000000067) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630990000001, -2038096305, -9196878310965066696, -9437, -7, -8043032690399.879883, -3.291758, 1, 'binary.OXzBvNftjfwTqreAuCzo', 'nchar.台湾省西安市西夏贵阳路b座 196727', 1630000000067) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1630990000000, 22826804, -2627900666391071715, -20499, 51, 21.403443, -394389822812.973999, 0, 'binary.abnUGmLKuAKIaCxUeyBU', 'nchar.海南省玉珍县房山罗街t座 776991', 1630000000066) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631005000000, 808597268, 2078929531741697152, -30212, 18, -94851063704.977005, -73674.167661, 0, 'binary.hsfTIdNWdxTPvUwMVrpW', 'nchar.江西省桂荣市清河通辽路U座 806067', 1630000000067) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631005000000, -915524872, -8857255033160626964, 266, 91, 11153.892476, -331797474.177709, 0, 'binary.KRBAAEghraBqMLVZKLxR', 'nchar.河南省成都县浔阳傅路o座 233168', 1630000000067) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631004999999, 2045109124, 8620061599081376707, 21842, 65, -577475988406.473022, -230.252609, 1, 'binary.BdfsaHZLBvLoViCnpcaf', 'nchar.重庆市敏市涪城张街Y座 339115', 1630000000067) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631005000000, 667151973, 2042134679839477524, 30807, 18, 410455086008.659973, -111467516118.406006, 1, 'binary.MRXRSCLnwHZQLMuEpxxc', 'nchar.上海市秀英县南长南京街E座 857787', 1630000000067) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631005000001, -1754458857, -2336346102444691323, -21518, -78, -35328084917.622902, 6799588.766270, 1, 'binary.XKvGUqmEfwrFunqrTSnZ', 'nchar.广东省广州县西夏梁路f座 812202', 1630000000068) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631005000001, -1198184531, -2273612721150875492, -27273, -110, -5590.967174, -36.872012, 1, 'binary.mVuGzysfOhHacpboXfya', 'nchar.澳门特别行政区合肥市怀柔淮安路Q座 830162', 1630000000068) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631005000000, -806268791, 6849292639236533681, -6170, -10, 67.282833, 189646569.949903, 0, 'binary.TDFoHEPsCyCFagPtryZJ', 'nchar.云南省彬县淄川潮州路h座 848046', 1630000000067) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631020000000, -1073614153, 298267925059640970, -26581, 48, -95632.677072, -4.716783, 0, 'binary.VHldMJRfKiPhYVUwVuHn', 'nchar.黑龙江省南宁县清城曾街M座 383184', 1630000000068) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631020000000, 199565482, -5346899860399957284, -803, 119, 641654.245772, 6.968944, 0, 'binary.CdEpJsyAmonutUDWmrxV', 'nchar.山西省龙市新城任路n座 477007', 1630000000068) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631019999999, 117798603, 420439377677612553, 9253, 22, -1137.400660, -4635970947.218740, 1, 'binary.NJEFxITOCrCDbopXNjvy', 'nchar.广西壮族自治区通辽市华龙柳州路J座 634352', 1630000000068) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631020000000, 1124688237, 3000258188050272185, 14502, 16, -74396554878085.203125, -9.906537, 1, 'binary.sIxumMWCehMDSrpZPLqj', 'nchar.上海市峰县双滦荆门街i座 639698', 1630000000068) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631020000001, -1012596446, -5485827047721236689, -13273, -79, -85711452679.407806, -9188.884106, 1, 'binary.vCyjrKXeBvkNVeElgyZi', 'nchar.湖北省明县沙市武汉街E座 620206', 1630000000069) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631020000001, -460195462, -2468912047516302638, -8474, -48, 1519432858382.800049, 17871.504434, 1, 'binary.dixQMmtXAeagNODPIEEv', 'nchar.上海市阳市平山龚街J座 946821', 1630000000069) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631020000000, 1852200026, -6007978387233236224, 8798, -115, 421576343321.414001, 19100383480.317001, 0, 'binary.iRZrrVUoaDQXPuJZnyDI', 'nchar.贵州省南昌县合川成都路a座 820810', 1630000000068) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631035000000, -1253564785, 9123919785095917881, -15701, 31, -186733280.924988, -61.177294, 0, 'binary.NgOZqYryGuLTQMouuNHu', 'nchar.天津市鹏市沙湾兰州街O座 549919', 1630000000069) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631035000000, -1657246812, -4709259982252400503, -17351, -53, 81659768.995530, -7671201354.697040, 0, 'binary.nzcJiagtuSvVewKFNcaK', 'nchar.上海市天津市城北福州路U座 681143', 1630000000069) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631034999999, 1413434601, 2190691240505370364, 11770, 93, 3703815955153.799805, 8268264767.279480, 1, 'binary.oIubCOjKHdxCpeWbqIpp', 'nchar.陕西省秀华市徐汇合肥街s座 902856', 1630000000069) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631035000000, 1217613348, 7975114090727787456, 13738, 43, 355726833911.968994, -438162359629.995972, 1, 'binary.uLWXXVcGhcuWJiRaByBZ', 'nchar.河南省福州市东丽徐路w座 747585', 1630000000069) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631035000001, -2146084891, -23804698624528061, -29407, -115, 3824609640014.350098, -67783404809047.703125, 1, 'binary.RnZVUuAxugAtOZSTEkkn', 'nchar.青海省北京市门头沟陈路Q座 257513', 1630000000070) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631035000001, -1123855083, -2174482244567720750, -12610, -101, -13889290720.493999, -44730168.376831, 1, 'binary.bKiOAOxQmTuUxvfbdpdl', 'nchar.宁夏回族自治区坤市锡山宁德路j座 838367', 1630000000070) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631035000000, -1406844909, 6947966913619883113, -6412, -80, -5.700965, -15608.263924, 0, 'binary.ShuwgacOGYsjNECdcUUt', 'nchar.河北省婷市浔阳南宁路D座 449083', 1630000000069) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631050000000, 1665571243, 5875622308303693056, 26189, -3, 9184334500122.300781, 692.411491, 0, 'binary.mkdoDznGUjHxCWsEReic', 'nchar.天津市明市翔安王街K座 149828', 1630000000070) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631050000000, -866699485, 5150552413312365721, -26931, -72, 304388231344.469971, 1887123.429534, 0, 'binary.gXoNDsUhSIxwTtChSVKC', 'nchar.广东省阜新市牧野何街b座 893235', 1630000000070) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631049999999, 1647088140, 6276524783005291573, 18506, 126, 520220.525305, -11656506505.388300, 1, 'binary.uFvJUrDBxvRNfycpsATy', 'nchar.广西壮族自治区春梅县新城梧州街p座 914349', 1630000000070) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631050000000, 110172144, 3880079542176303291, 7450, 60, -70101821.922084, -766086105.175900, 1, 'binary.sGupuerrJMrewABhIOQF', 'nchar.重庆市永安市孝南东莞街p座 524436', 1630000000070) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631050000001, -2334950, -9174808951498480949, -25376, -56, -706896093828.322021, -7054905528.909860, 1, 'binary.eAsXnsSVfXpwSeWxjIep', 'nchar.新疆维吾尔自治区婷县清城李路R座 863352', 1630000000071) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631050000001, -1709242287, -1024364150913211829, -18517, -95, 612563.744410, 71675616881.702698, 1, 'binary.xwUGLqzyDiIWFYjQChPb', 'nchar.澳门特别行政区建国市东城汕尾街H座 310414', 1630000000071) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631050000000, -1438324283, -2616966529186093777, -15740, 119, -7052.121172, 6.860693, 0, 'binary.gwSKZcnvepcSGvGhQIhU', 'nchar.江苏省娜县安次长春街b座 373327', 1630000000070) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631065000000, 1572844268, 7954082573907623254, 28743, -77, 526200414.754712, -610.377887, 0, 'binary.dhmqewaCwxuZgymXkJYg', 'nchar.甘肃省六盘水市高坪刘街K座 997983', 1630000000071) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631065000000, -1997711328, -8305458100196327173, 15855, 65, -1.591103, 978771.885779, 0, 'binary.ErzqbmUDFqGBseJATzNB', 'nchar.福建省邯郸市龙潭天津路S座 700145', 1630000000071) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631064999999, 118186835, 7105850083426581209, 23043, 123, -294186.598870, 631977325.777490, 1, 'binary.jZYzFZwYbBOMfCYxLkEu', 'nchar.北京市宜都县山亭福州街B座 229199', 1630000000071) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631065000000, 84760302, 4023057210065827734, 20658, 50, -374538737.396905, 2.546280, 1, 'binary.GrfdYDSeONBkUWnVxrIE', 'nchar.重庆市关岭县兴山荆门街i座 354010', 1630000000071) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631065000001, -31117145, -6368825817854208301, -4679, -13, -193.784819, 9941696226439.189453, 1, 'binary.DtkHUqQYbIbRkWfoerGJ', 'nchar.湖南省建国市六枝特广州路d座 104163', 1630000000072) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631065000001, -1214911170, -3868394291968674672, -20441, -79, 567.284011, -99982135106.938004, 1, 'binary.LThAPucPiLueKWedudxF', 'nchar.青海省海门市牧野淮安街D座 825707', 1630000000072) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631065000000, 1697187351, 530203760413095118, -17911, -116, -501.905581, 98.459334, 0, 'binary.mEMXftUdsHdFpIbnKRsd', 'nchar.宁夏回族自治区峰市平山王街M座 201716', 1630000000071) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631080000000, 1610525794, -5290794365132208573, -15731, 123, -335854906.304436, -24139226804197.199219, 0, 'binary.daKMhFVbQQZKGiTKOlls', 'nchar.新疆维吾尔自治区坤市牧野武汉路f座 977660', 1630000000072) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631080000000, 1087333161, 2572492011929726786, 25923, -25, -4763484.301768, -5226373.298693, 0, 'binary.mmMznhJKAQPTjucpnZSc', 'nchar.澳门特别行政区杭州市南湖大冶街g座 395605', 1630000000072) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631079999999, 579193173, 5793829126142110648, 4490, 80, 78951.390551, 19287929360.243801, 1, 'binary.MUCIKFgmyfodWgXzBwpA', 'nchar.台湾省淮安市上街海门街G座 209332', 1630000000072) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631080000000, 1885599296, 5754849838280444727, 16958, 107, -53.481198, -9.937711, 1, 'binary.BrUGLflxCuUJqYeSVVsN', 'nchar.吉林省刚市高明夏路B座 373737', 1630000000072) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631080000001, -718949368, -4253205043582583806, -12561, -68, -134568795933.429993, -71046052762709.500000, 1, 'binary.gOwViQPVHLSImYonXzkV', 'nchar.台湾省红市永川六盘水路m座 707904', 1630000000073) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631080000001, -1419546071, -5628013404742242442, -19653, -61, 4641210572.820400, -516.363302, 1, 'binary.OhALrYMiHXSjCpcdfoPs', 'nchar.甘肃省玉华县高坪长沙路K座 553129', 1630000000073) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631080000000, 1801658141, 3654105358778411870, 18529, -80, 8.652081, -1554626.681517, 0, 'binary.GyuqMCRbacNJHUbGmkXh', 'nchar.台湾省芳市安次薛街o座 207547', 1630000000072) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631095000000, 2136843976, -1210226910088276755, 20600, 23, 539871237741.179993, 49233075000.644600, 0, 'binary.CoZYsjGjLcrAfxoNvULS', 'nchar.山东省嘉禾县平山呼和浩特街F座 641469', 1630000000073) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631095000000, 486220117, 2599712669438010104, -6519, 47, -0.673515, 55.218328, 0, 'binary.hUsJbjOwNFjCpNXnLWPF', 'nchar.广东省六安县秀英上海路E座 148463', 1630000000073) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631094999999, 17707398, 8375178158416972213, 1322, 112, -62111552150188.000000, -3.488348, 1, 'binary.iibUAdMnGmuQRjnCboca', 'nchar.海南省澳门市萧山冯路k座 476673', 1630000000073) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631095000000, 1540458244, 8608337136208602956, 13530, 122, -258.798333, -18390773070513.101562, 1, 'binary.dKifdiuRtzPzgDOgwskf', 'nchar.西藏自治区成市江北丁路k座 811706', 1630000000073) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631095000001, -295978274, -3611928104731611403, -928, -29, -349214171411.169983, 627603759.980824, 1, 'binary.tPAAsLZTOrrgDWhhbvPA', 'nchar.河北省深圳市和平李街k座 107359', 1630000000074) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631095000001, -1110370293, -2926428742790858456, -4685, -42, 594526965.911060, 979845489.815900, 1, 'binary.KCwadhHtPeNvxeOTurpC', 'nchar.四川省桂香市城北张路Z座 135595', 1630000000074) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631095000000, 1016372608, -248268842333445258, -24994, -40, -855742777.413557, 412898933.803171, 0, 'binary.oektpgoczIFkPkMZhePp', 'nchar.四川省楠市锡山王街T座 347259', 1630000000073) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631110000000, 1618012586, -4877738856165917254, -14321, -36, -2.446783, -8386.899686, 0, 'binary.cGuZNtDbGSgYATZIfhUQ', 'nchar.湖南省军县闵行沈街e座 942969', 1630000000074) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631110000000, 336517476, -2851549763879094055, 24260, 42, -284453185.760948, -82312598023267.500000, 0, 'binary.nNUcWFSnghHEXoJZyLSZ', 'nchar.台湾省玉英市海陵广州街D座 932017', 1630000000074) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631109999999, 325913454, 4965185676452141874, 1927, 45, 928.161230, 5002796.693905, 1, 'binary.KPSdukhCAQdFSCjoAXyb', 'nchar.天津市嘉禾市和平王街Y座 800951', 1630000000074) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631110000000, 2115611339, 5603712632691054487, 2040, 92, -88631.744485, -33319292708726.398438, 1, 'binary.nDvmXubKLBkwjQvBrowE', 'nchar.广西壮族自治区合山市大兴邯郸街C座 120130', 1630000000074) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631110000001, -416517208, -3563087064047686173, -32590, -97, 804.877418, -8174392626838.679688, 1, 'binary.yJGXGtGzgxaoyzDFNKzn', 'nchar.新疆维吾尔自治区建平市龙潭曹街X座 409242', 1630000000075) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631110000001, -1502953470, -2238010217654677886, -11068, -38, 69129137.954435, 599892.899153, 1, 'binary.OdnrQcfrzxIUYGMYkhgP', 'nchar.上海市霞县南溪曾路b座 536348', 1630000000075) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631110000000, 451771496, -7517497607249821959, -32099, -92, -213627.556542, -8726497.619554, 0, 'binary.DhxlHgZRZtmSyyhkGtuW', 'nchar.云南省洁县滨城梁路p座 996135', 1630000000074) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631125000000, 32878642, 8801402285444036889, 21539, 48, -596417925905.134033, 373248896.126035, 0, 'binary.RjzhwvLAyYAYYCfkjFJj', 'nchar.重庆市超县梁平温街z座 283315', 1630000000075) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631125000000, 71147814, -5159443215460099961, -15082, 102, 5968659.321019, -26592.753571, 0, 'binary.CljlscxcGjjciERgOxKg', 'nchar.宁夏回族自治区玉梅县吉区海口路d座 230176', 1630000000075) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631124999999, 1015662815, 4795567142964951653, 7167, 1, 325791556.701457, -143633938642.838013, 1, 'binary.JHrHPuhooNwLgDYQlFil', 'nchar.上海市玉华市门头沟长春街L座 619720', 1630000000075) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631125000000, 785489232, 7788643811202703115, 31943, 105, -9652684.346045, -250.125950, 1, 'binary.FkrDvYiLeZOqRVvYQpJr', 'nchar.贵州省璐市永川长沙街K座 573245', 1630000000075) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631125000001, -370350844, -2328721985404462718, -8114, -97, -65.996745, -23054596683.701000, 1, 'binary.YpDtIgmdxGtGOlkpYQbb', 'nchar.吉林省潜江市普陀哈尔滨街G座 354284', 1630000000076) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631125000001, -1104506218, -4613678193581849079, -1965, -116, 67350915247071.203125, -124.355022, 1, 'binary.cGsEpboYJbYsTSnKYKUz', 'nchar.宁夏回族自治区贵阳市永川刘街l座 557372', 1630000000076) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631125000000, -1975758915, -7017697117625132855, -2347, -78, 13301869.493635, 734276825210.396973, 0, 'binary.JMTLLJHKsHvKhVKhxUdD', 'nchar.湖北省淑华县上街郑路d座 249081', 1630000000075) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631140000000, -638220498, 7787936362129921947, 2622, -93, 80359528.879084, -6439.177632, 0, 'binary.KYZqgXaxguXpZiDTipOe', 'nchar.云南省台北县翔安淮安路T座 548657', 1630000000076) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631140000000, 1695929408, 6613622196219250257, -19521, 126, -294182.533903, 872281666.129710, 0, 'binary.bxqGrgGKqftbTFsJVxse', 'nchar.陕西省长春县梁平重庆街f座 969435', 1630000000076) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631139999999, 910799127, 3748990393909505200, 19872, 110, -1.774037, 962.107067, 1, 'binary.SMVCQwJbrLKRzlPTMAle', 'nchar.广东省淮安县南长陈路r座 442094', 1630000000076) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631140000000, 82578099, 1083300683395237822, 14840, 49, -2897441254294.259766, 78241.170285, 1, 'binary.zRnJDsiOdVdrjyezgNqk', 'nchar.新疆维吾尔自治区欣县上街郑州路T座 334404', 1630000000076) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631140000001, -1933040168, -8697939131006546022, -21092, -35, -3404654038.996900, 64905.498178, 1, 'binary.VlVdAdmtswNJQrRzSAPQ', 'nchar.河南省辽阳县长寿兴安盟路C座 114674', 1630000000077) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631140000001, -472785311, -4446555925790326535, -23024, -3, 430107081.785272, -5.140820, 1, 'binary.NUAVJEKQvBvlnJToDnoJ', 'nchar.河北省金凤县双滦石家庄街D座 264667', 1630000000077) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631140000000, -1325721293, 1101829200999493900, 13912, 72, 151194.856760, 931990832.169087, 0, 'binary.siTpYJVsmIUfmSUiacBG', 'nchar.海南省六盘水市房山重庆街R座 786868', 1630000000076) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631155000000, -622133611, 4304164307993590613, -1028, -75, -794.965943, 7129885424.126380, 0, 'binary.PxLiilJCeaWfrPEPswvJ', 'nchar.辽宁省齐齐哈尔县秀英王街V座 753913', 1630000000077) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631155000000, 601975873, -8460674145788246343, 26537, -18, -117.582363, 4.278494, 0, 'binary.DIEUsVGrYCIYpOHOMbYp', 'nchar.青海省玉市高港六安路n座 697115', 1630000000077) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631154999999, 794346686, 2813747690977192290, 19623, 118, -592938779870.880981, -691339105509.250000, 1, 'binary.IkXhYGsGOuGyQXxMcENO', 'nchar.新疆维吾尔自治区兴城市白云海门街z座 410778', 1630000000077) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631155000000, 2077153378, 6007901518953365006, 32590, 25, 8269699092873.599609, -3523058497792.450195, 1, 'binary.zDNlRsoVabJhMNFJfTBy', 'nchar.江西省冬梅县永川王路R座 198556', 1630000000077) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631155000001, -969135765, -1764680015243416710, -27020, -59, -8.491632, -14661.965520, 1, 'binary.jnObVGyDvkIgXvnFpKMn', 'nchar.广东省南宁县涪城沈阳路O座 754414', 1630000000078) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631155000001, -1576113711, -3627767440156041231, -18534, -66, 495.121273, 53596032.859107, 1, 'binary.lOIexILoDTNYoRmKXkCf', 'nchar.西藏自治区瑜县海港史路q座 848639', 1630000000078) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631155000000, -1548677743, -6457865964462190618, 21103, -53, -421862729108.307983, -2360116167608.370117, 0, 'binary.ZmmTgtzFlywNsFIAjzDE', 'nchar.台湾省秀荣市高港高街E座 134599', 1630000000077) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631170000000, 749993747, 3019243752157013695, -17619, 43, -1469831614725.439941, -6462342550.269600, 0, 'binary.PTOhqXMEYVQUAwAPztJg', 'nchar.广东省哈尔滨市花溪深圳街S座 621146', 1630000000078) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631170000000, 256334370, -4650384778595555945, -7069, 22, 596577877.192931, -70129653418.844894, 0, 'binary.zWNroTXoIVAfFKMCHdqU', 'nchar.广西壮族自治区梧州县崇文张路j座 870677', 1630000000078) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631169999999, 366270121, 4191114768474723941, 28897, 88, 36764251.456900, -819995344305.519043, 1, 'binary.KMQKIVvLXKZtzgvGXoZV', 'nchar.上海市深圳市朝阳王路c座 308052', 1630000000078) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631170000000, 904819741, 5165411582118084217, 22379, 49, 5.680573, -23448296491.688702, 1, 'binary.RksynZHDBofeCbnNeueF', 'nchar.西藏自治区秀兰县永川武汉街f座 720233', 1630000000078) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631170000001, -406248475, -3565233828007899422, -28694, -119, 6468114.299821, -9139.276334, 1, 'binary.yDkbSjlEhWxgIdEKjdyw', 'nchar.陕西省明市东丽郭街X座 797325', 1630000000079) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631170000001, -110865946, -7795005438146655234, -26791, -6, 614284367.384455, 50856740.580794, 1, 'binary.tpgIuOiJsKacrUZBOcHs', 'nchar.北京市太原县大兴高路N座 354025', 1630000000079) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631170000000, 1503400003, -80780332688017476, 31847, -84, -1188729980516.979980, 2115639995.697030, 0, 'binary.zMhdERtluQHYrYkarBsp', 'nchar.西藏自治区沈阳市沈河兰路O座 514687', 1630000000078) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631185000000, -703829541, -3015290584870545849, -26195, 25, 65051636.569539, -1355107949.868670, 0, 'binary.pFxWRymlGotRbPxBaKqU', 'nchar.重庆市拉萨县孝南刘路P座 393437', 1630000000079) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631185000000, 322375238, -6241662551377872210, 7578, -41, 9181.469818, 58823.373155, 0, 'binary.yeTYMVojTpBxHFVbiTVH', 'nchar.贵州省天津市吉区潜江街E座 745985', 1630000000079) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631184999999, 901680081, 2918745868131285426, 1954, 123, 799091.717635, 19529.323662, 1, 'binary.HriCdYQCgMqDJrsEPvId', 'nchar.香港特别行政区伟市蓟州崔路h座 182270', 1630000000079) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631185000000, 959830805, 8687660735074694942, 30908, 121, -56072935323.713600, -66360254180.759499, 1, 'binary.hnKLmxkdGfJPtsNffUnx', 'nchar.重庆市云市孝南深圳街D座 180484', 1630000000079) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631185000001, -88966985, -1936037048857392721, -18099, 0, -824204261009.363037, 1697.886509, 1, 'binary.pfXnsxKPgpyOLUjhDIlh', 'nchar.青海省辛集县东丽拉萨街Q座 914524', 1630000000080) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631185000001, -156903452, -7204919546158466118, -26775, -7, 3343624886104.990234, 25.895039, 1, 'binary.DVJPFxpqidEqIbsMkqvk', 'nchar.河南省桂香县普陀合山街y座 473206', 1630000000080) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631185000000, 242951644, -6425706509022302444, -115, -95, -7428172351326.129883, -243792.108001, 0, 'binary.XYfDpoamFuPazIzqqvyQ', 'nchar.江苏省六安县沙湾沈阳路D座 111215', 1630000000079) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631200000000, 917616213, -6105526769675738367, 16833, -4, -912283922.301867, -626.880806, 0, 'binary.UJhwYiRGgenyykMzvCIG', 'nchar.陕西省慧市沈北新台北街V座 622592', 1630000000080) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631200000000, -1010524677, -2564524247724824015, -31994, -48, 478258495629.161011, -2756525.506410, 0, 'binary.JqnispIFJYlFtxhJzBtt', 'nchar.贵州省梅市上街福州路U座 843893', 1630000000080) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631199999999, 1676885574, 5801667850572164138, 9268, 5, 81943569878020.000000, -2651878397664.700195, 1, 'binary.tJnMwFImycFDwadSKvfB', 'nchar.西藏自治区邯郸市东城刘路G座 620688', 1630000000080) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631200000000, 202560740, 8585057740824701967, 2754, 102, 4256312.669784, 2841641554.533030, 1, 'binary.iZuBXyHivNVGIECkZpgp', 'nchar.青海省北镇市永川广州路t座 650954', 1630000000080) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631200000001, -1469589614, -6328986345920555773, -13057, -114, 7124.472347, 1922792124.232900, 1, 'binary.IttYeshrxTWRQzrMpNEl', 'nchar.江苏省呼和浩特市大东钟路V座 373715', 1630000000081) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631200000001, -635536894, -7540406212992578302, -356, -42, 7506079.766892, -846620.925646, 1, 'binary.FBEKhNRXwVaIefMjxKLw', 'nchar.重庆市马鞍山市金平孔路A座 105425', 1630000000081) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631200000000, -1786041154, -5812150165598736743, 31691, -112, -99.932548, -78491263.832105, 0, 'binary.EeccUPRfABMAdtMqrUTP', 'nchar.海南省鑫市西夏兴城街R座 301651', 1630000000080) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631215000000, -1625191731, 6167214474139728168, 11139, 121, -94335581842.567902, 3059478274.613470, 0, 'binary.ZxUIonzZMsBhCCWqYrmZ', 'nchar.天津市拉萨县萧山上海路d座 252099', 1630000000081) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631215000000, -47135681, -6436433940308594642, -21351, 98, -8067393645072.580078, -55.209057, 0, 'binary.wklKlUzIzCbSAlTVhPtf', 'nchar.江西省通辽市西夏曾街D座 770856', 1630000000081) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631214999999, 1572527931, 6199432476029588286, 15047, 53, -329811.437951, -690962.952604, 1, 'binary.VQbrSGdoLASviEaZfVKb', 'nchar.河南省磊市城东曹路Y座 412471', 1630000000081) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631215000000, 1025618009, 8668297953739699167, 6895, 36, 809883.310963, -1830.234393, 1, 'binary.bSASugSRycgShDfZVaRz', 'nchar.天津市亮县江北潜江街S座 540483', 1630000000081) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631215000001, -256464376, -896102382541120115, -19194, -122, 4123590577424.399902, 2656422.305476, 1, 'binary.CyxinbAlvUlbbQCMCmuX', 'nchar.青海省东莞市蓟州叶路g座 257461', 1630000000082) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631215000001, -425746119, -8056851883105951074, -32462, -51, -590076.331164, 324718675328.812988, 1, 'binary.MqmXkQoSJpKeTWWfLSjQ', 'nchar.青海省宁市高坪何街L座 312122', 1630000000082) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631215000000, -1005159716, 5814777795009857976, -20922, -120, -5.121036, 72269204554.118393, 0, 'binary.krPFwdRphWiLhiLWffGj', 'nchar.云南省太原市翔安叶街s座 968090', 1630000000081) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631230000000, 300807334, -1393720031020538944, -10631, 114, -7497311.501447, -7843875.126062, 0, 'binary.gUfZXmtuaUyEMqvzCGVT', 'nchar.甘肃省潮州市海陵张路j座 111530', 1630000000082) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631230000000, -61728336, -6277168556471947655, -14631, 121, 108260.570588, -6225158.445263, 0, 'binary.wjIFBHVvPkzNnyfFqcez', 'nchar.内蒙古自治区小红县锡山张路q座 451673', 1630000000082) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631229999999, 456695922, 6065595906254092225, 13855, 95, -9.750988, 52263.948430, 1, 'binary.HpsqFduULuvFgUNWLaIS', 'nchar.上海市辽阳市友好宜都街J座 260640', 1630000000082) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631230000000, 1314422800, 2343245198878315836, 4530, 110, 5.523721, 52.963146, 1, 'binary.BqILcPWCGdFitnkIUITX', 'nchar.黑龙江省萍市兴山香港街w座 689416', 1630000000082) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631230000001, -1404438854, -6648294746644259055, -29920, -45, -4879.347387, -397204029.641602, 1, 'binary.hWYLNHYZihIwrBwiQKLu', 'nchar.内蒙古自治区大冶县上街谢街p座 354579', 1630000000083) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631230000001, -1560018283, -8582655292633538077, -7916, -9, -813743561.246321, 180605419479.515991, 1, 'binary.rBKhOAPgsFlVbktylkBZ', 'nchar.海南省贵阳县新城张家港路o座 184911', 1630000000083) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631230000000, -1185224620, 3781565114446947943, -32425, -124, -966176.836584, -6194.817285, 0, 'binary.MAHjOJrSnXwRnDjhjhgs', 'nchar.湖北省哈尔滨县璧山嘉禾路W座 107867', 1630000000082) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631245000000, -629005742, 2962477037931783881, 30753, -22, 97626628.877839, -55509075810587.898438, 0, 'binary.bHeXAGMGzghlOuWCGmyS', 'nchar.内蒙古自治区荆门市上街王路f座 313159', 1630000000083) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631245000000, 1289038189, 208643021208222754, 24329, -84, 528626.682214, 4631263449.782700, 0, 'binary.VBcGIQKGeBlgodeKkqIO', 'nchar.天津市梅县孝南许街M座 955579', 1630000000083) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631244999999, 1089857524, 8092714018391461421, 30637, 62, 822.840197, 86578529728.784698, 1, 'binary.ReHWrHhhULYKBWJbDHAl', 'nchar.安徽省合肥县大兴太原街z座 183173', 1630000000083) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631245000000, 1508646219, 5498801626248258629, 6153, 2, -6981.974013, -1.262354, 1, 'binary.rKJJrwLYFsmeLilRmdII', 'nchar.云南省秀英市静安罗路N座 799241', 1630000000083) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631245000001, -1072147772, -6285554104164008129, -13029, -38, 399653108.497808, 9.954981, 1, 'binary.CrzTcvxjDbWSNGHlnGgZ', 'nchar.福建省文市沙市聂路v座 919011', 1630000000084) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631245000001, -1744587122, -4289304118779607521, -3261, -49, 578908.973758, -3283275.161042, 1, 'binary.hnKdQBaXRtRTvdBMxxki', 'nchar.四川省秀荣市江北韩路N座 794727', 1630000000084) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631245000000, -1768419964, 6812389139494481536, -22315, 57, -3991350668.256720, 272847.980876, 0, 'binary.eaKoadYSnHxIAwGvMADW', 'nchar.内蒙古自治区颖市城北呼和浩特路M座 270782', 1630000000083) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631260000000, 62032825, 2419036897017949691, -18301, 34, -34067326787.909401, -4490033.331223, 0, 'binary.vcjOGKOcKjTDVUVgwDDP', 'nchar.福建省太原县上街宁街J座 989695', 1630000000084) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631260000000, -955905466, 8811462063140315136, -25829, 76, 4112554.855015, -353081090.814735, 0, 'binary.sjVkMmweDnQHqIahYBJg', 'nchar.宁夏回族自治区佛山市清浦陈街C座 507576', 1630000000084) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631259999999, 1740302532, 7618062051313344766, 24234, 108, 19.258022, -481986511.838220, 1, 'binary.FHckvgRsNysvnrkBnxPi', 'nchar.河北省丽华市朝阳龚路E座 249405', 1630000000084) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631260000000, 25207874, 8557074180207725958, 5121, 76, -27.837670, 7472.845942, 1, 'binary.yuETGYVvdZgoTrKTDVlM', 'nchar.甘肃省红霞市牧野关岭街C座 146380', 1630000000084) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631260000001, -368156241, -8290129222861749037, -32369, -87, 8778614.707332, -8.396911, 1, 'binary.oTlXrpmNqzuPQFtdJXAL', 'nchar.广东省淑珍市东丽周街e座 132961', 1630000000085) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631260000001, -1391854623, -5255734908673798063, -25898, -63, 6.380914, -981.272293, 1, 'binary.fRTcoeHlACSZuECHxLsF', 'nchar.西藏自治区兴城市东丽惠州街w座 939232', 1630000000085) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631260000000, -1478713358, -7256379885586266224, 7456, -127, 39.210475, -37429036261.203003, 0, 'binary.iLHDKCeEycRrHQjdctpP', 'nchar.贵州省琴市锡山嘉禾街V座 586837', 1630000000084) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631275000000, 1637182628, -7252330432834078022, -13577, -34, -21982.383242, 851033.725636, 0, 'binary.qbwfbTcZcBXRYDFLPsYc', 'nchar.西藏自治区香港县门头沟袁路c座 659900', 1630000000085) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631275000000, -226012380, 714907917095146625, 26998, 45, -378863.223518, 63837840.367547, 0, 'binary.wLhqoOhYDhOLDWgTquSO', 'nchar.广东省淮安县城东惠州街H座 226497', 1630000000085) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631274999999, 1196830217, 7803469523299853932, 4057, 68, -72455041894.121094, 31008329.254161, 1, 'binary.tnTDmSbUwexajzyGQKbU', 'nchar.天津市桂香市海港邱路v座 930985', 1630000000085) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631275000000, 1896164509, 1992693218102163749, 20742, 127, 3279876658623.740234, 97971293613823.203125, 1, 'binary.EwwiwjOJeqmxqOmBSCvF', 'nchar.宁夏回族自治区秀英县高坪银川街T座 599205', 1630000000085) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631275000001, -238216455, -6595002088264755363, -17352, -35, 30291122943460.601562, -523766877.255375, 1, 'binary.JiuAgoqIJOWzLvLnmvBq', 'nchar.四川省六盘水市梁平佛山街Y座 160978', 1630000000086) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631275000001, -1959680714, -5838771977352828969, -30312, -80, -40302216017.319298, 65262645551.558701, 1, 'binary.kKcTvQecUQcVNHCxdbMq', 'nchar.吉林省亮市海陵汕尾街y座 455171', 1630000000086) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631275000000, -1454514443, 2104326254606882084, -3977, 31, -10.683775, 8146970744.319100, 0, 'binary.baHWrZaiEoVOFqPQVViT', 'nchar.上海市明市锡山台北街g座 112480', 1630000000085) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631290000000, 202676239, -997640316674086097, -22675, 17, -597819.667252, -989103790.253560, 0, 'binary.rdoqbRUQFOZbxDrDpEXv', 'nchar.福建省斌市清河刘路r座 438569', 1630000000086) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631290000000, 274493417, -5455741168804436813, -27247, -111, 9288775.263537, -3826.901732, 0, 'binary.eWJNzFpYfQFYqDTlVEuS', 'nchar.广西壮族自治区深圳市海陵邓路e座 598287', 1630000000086) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631289999999, 995318978, 44640273583296417, 14989, 72, 86411387362.516006, -21052069.696864, 1, 'binary.WhVBrissKQCBrAUpwRHT', 'nchar.陕西省桂香市清浦米街p座 269494', 1630000000086) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631290000000, 2136730540, 5315445691851854143, 14450, 103, -6335650603.174980, 501305134.199676, 1, 'binary.zljXuXtZduZhLQoCTEYI', 'nchar.辽宁省凯县西夏太原街R座 148010', 1630000000086) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631290000001, -1917806640, -4720258233332513149, -31214, -45, -8113.185976, -82050.442684, 1, 'binary.dwHmbtStCEgnJspmTqwD', 'nchar.新疆维吾尔自治区桂芝县长寿巢湖路A座 782531', 1630000000087) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631290000001, -981665942, -278699770296496646, -13050, -47, -41130.414162, 453641642.546780, 1, 'binary.BkkbbPyxvTkDiTzQpRiV', 'nchar.浙江省合肥市东城成都路c座 895347', 1630000000087) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631290000000, -834112430, -6635305571569691219, -19258, 73, 919646.148350, 321.289191, 0, 'binary.XzCcSXArLMKFLjFRyHJe', 'nchar.上海市阳县崇文丁路I座 548147', 1630000000086) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631305000000, -568876147, 4115921496929882007, 21876, 118, -766463785.889029, -63.898006, 0, 'binary.WPbsfDfyJKEoZCpyfhuq', 'nchar.青海省贵阳市大兴彭街W座 571855', 1630000000087) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631305000000, -1963919658, -7528759656724736232, -15462, -49, 82.771605, 228.648728, 0, 'binary.gvsIwjOVqnvwPYubIriV', 'nchar.浙江省合肥县蓟州蒋路s座 450606', 1630000000087) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631304999999, 862001048, 8289879675128879554, 10897, 54, -31560046.871248, -2510800476075.919922, 1, 'binary.ZakYSeKJSEQfAnbEPpdl', 'nchar.湖南省秀华市锡山牟街K座 639697', 1630000000087) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631305000000, 1928593809, 5104651015083770612, 32255, 58, 804488379.612065, 9429749762380.500000, 1, 'binary.wgTbKbFYQRosfKvUQSkH', 'nchar.重庆市桂珍市梁平乌鲁木齐街N座 153448', 1630000000087) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631305000001, -1547198379, -350643391542151214, -13828, -103, 64477812.167046, -2903.526723, 1, 'binary.vJieiALrJbMqqRhnMbqe', 'nchar.澳门特别行政区丹丹市丰都南宁街Q座 989300', 1630000000088) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631305000001, -134242385, -3869570405276188197, -32581, -104, 43107832.702441, 44056.657014, 1, 'binary.IkbIEnMQPVXBWOjcanNo', 'nchar.香港特别行政区东莞县丰都朱路U座 249243', 1630000000088) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631305000000, -597984033, -3361517834367129147, 75, -104, -7409.500037, -91.360942, 0, 'binary.TNnOUCoNllHJVskqaqWO', 'nchar.上海市玉梅市和平李街k座 583138', 1630000000087) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631320000000, 904033245, 1599598424557218108, -30005, -24, 4541.289136, -54.239926, 0, 'binary.iEBPEAmKXlpBUXwoALUt', 'nchar.吉林省刚县璧山刘路g座 682546', 1630000000088) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631320000000, -2079364817, -654287221384079565, 15782, -26, 748.766841, -4.965685, 0, 'binary.WEJkxJeFLZZByzCPoRdY', 'nchar.福建省太原县永川兴城街w座 961260', 1630000000088) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631319999999, 526847966, 5775445950760637967, 14304, 60, 81172141354.356293, 870255843.925099, 1, 'binary.MdntNFfvvyCStMNHBKIQ', 'nchar.广西壮族自治区合肥县西夏刘路q座 990741', 1630000000088) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631320000000, 537739308, 5090468389474927294, 22579, 33, 3433128.844123, 3872298849645.379883, 1, 'binary.abGKYFWBPWLVPYEvggCd', 'nchar.陕西省马鞍山市海港韩路B座 339379', 1630000000088) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631320000001, -795092969, -3711201539316715587, -11107, -98, -286579.413055, -3.739221, 1, 'binary.thHeWmYWAcgObBqqwqqB', 'nchar.四川省成县大东张街u座 740678', 1630000000089) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631320000001, -1559644142, -9027525835433685991, -2711, 0, 5557460.651989, -40007573640075.203125, 1, 'binary.NglLAfkhOUvNACXvlutl', 'nchar.西藏自治区丽市兴山萧路O座 326707', 1630000000089) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631320000000, -1107831086, -1823478878718094475, -27832, -90, 99212399503.662796, -74696134214106.500000, 0, 'binary.drlMMrbdDWnwUwkvFszC', 'nchar.青海省利市西夏辛集街A座 820543', 1630000000088) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631335000000, -1747665689, -3268703357637921126, -3204, 118, -7.843951, 5236837072088.639648, 0, 'binary.fKLvQiBIrygGolyqKaVe', 'nchar.福建省淮安县金平海口街k座 430777', 1630000000089) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631335000000, -828294034, 2657326032914454094, 21837, 8, -69702504398061.000000, -4450579.238900, 0, 'binary.esplmUmrLBFMyAKMDAzP', 'nchar.福建省北镇市兴山长沙路D座 908303', 1630000000089) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631334999999, 1804609738, 6857866489996684420, 32112, 37, -2477401204.802390, -3021.525948, 1, 'binary.DCLURcwhhaDhNKDcTLYq', 'nchar.安徽省西宁县江北郑州路R座 729863', 1630000000089) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631335000000, 437917493, 1733585568524751775, 14155, 38, 3358226.279225, -1184.537102, 1, 'binary.KYgSrTTQzSmndNwhbsxY', 'nchar.黑龙江省丽丽县双滦包路i座 494311', 1630000000089) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631335000001, -1727537263, -5460926119155540560, -9690, -95, 9289065.542646, 7.188845, 1, 'binary.yMKTfSNsTiIkXhhIQCtC', 'nchar.新疆维吾尔自治区柳州县东丽高街d座 298894', 1630000000090) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631335000001, -2120093363, -4777070161903130182, -8197, -30, -383000.885433, 9678.947342, 1, 'binary.xYtVuqPnZXiCBdRdskEu', 'nchar.海南省沈阳市大兴邓街P座 552544', 1630000000090) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631335000000, 1750088050, 3697839127781862571, -675, -53, -99724.435061, -28255356.108959, 0, 'binary.ZoJveGLeqQgcoitfoHqY', 'nchar.广东省丽丽市城北呼和浩特路P座 380188', 1630000000089) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631350000000, 1880035325, -4802629856794707608, 22068, 100, 718062376.187030, -506130.634445, 0, 'binary.CfGiHufKQulMxwAItOfy', 'nchar.山西省想市黄浦邯郸路X座 818941', 1630000000090) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631350000000, 165546984, -6984734151301447256, -16166, 96, -1236884449.480500, -639029206.988874, 0, 'binary.AvOGTRfAVrYaxEAHhJKk', 'nchar.四川省坤市清河文街M座 728309', 1630000000090) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631349999999, 1514387404, 2958688219263646841, 21127, 20, -46918158932248.000000, 2353213017.825450, 1, 'binary.bfrSvHvqHlFluwivEgxS', 'nchar.山西省玉市白云马街p座 592361', 1630000000090) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631350000000, 697337569, 7135356390013225753, 32569, 116, -6611897.211005, -1.935866, 1, 'binary.ETaNjgpPPzwvOkzPbLMs', 'nchar.台湾省敏市朝阳余路L座 739835', 1630000000090) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631350000001, -1737290956, -4744278138504720755, -23704, -13, -20682554.975530, -5505407.317856, 1, 'binary.lqhFKjcHzvbkdWVoYtwW', 'nchar.河南省兰英县朝阳天津街A座 102658', 1630000000091) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631350000001, -1792783313, -6546177515445472740, -17996, -82, -2785.518995, 406175.862275, 1, 'binary.ZSgzqADQgOFLGnOSTTgl', 'nchar.云南省丽华县浔阳黄街u座 463279', 1630000000091) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631350000000, 1675171705, 4482392883505129283, 3877, 60, -529410318.578000, 87242703.165205, 0, 'binary.pPrjATzIWSjGnAQlByfg', 'nchar.澳门特别行政区玉珍县南溪刘路J座 234624', 1630000000090) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631365000000, -120996932, 7464290233605180116, -21030, 89, -7265.737889, 38451.519083, 0, 'binary.NdYvAIsMTcBJbRZBuEMZ', 'nchar.四川省成都县六枝特武汉路u座 796761', 1630000000091) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631365000000, 1626331139, -3444691871293469179, 1200, 69, -2719528.747073, 35.186089, 0, 'binary.SfqGXOabBHmYWmwbjAmD', 'nchar.江西省彬县清浦丁街f座 768134', 1630000000091) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631364999999, 1201642931, 3048123187871650645, 5183, 51, 5407076381615.250000, -94.505271, 1, 'binary.pCxeaejTSQlmBlttHhTg', 'nchar.江苏省六盘水市兴山宋街z座 229812', 1630000000091) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631365000000, 606859861, 3791676681420995058, 12977, 20, -11.820203, -60910962808.638702, 1, 'binary.dkXKTqEjhmKoFQauhwjf', 'nchar.甘肃省慧县淄川何街t座 472618', 1630000000091) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631365000001, -639050810, -5288142338710158760, -32726, -35, 1750485995849.620117, -5947212091.364470, 1, 'binary.hQfgaAPxYdJOaIkPUQJT', 'nchar.甘肃省宁德县孝南北京街f座 436022', 1630000000092) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631365000001, -592064320, -9093756286157608735, -19004, -37, -60515553533903.898438, 4852.484564, 1, 'binary.DyLlxTKVpmVQoztjwPWn', 'nchar.辽宁省武汉县徐汇王路u座 155320', 1630000000092) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631365000000, -168837427, 5524670347645121945, -687, 105, -33530.533779, -857595946215.329956, 0, 'binary.dWHryceFSxVdkHDrNfYa', 'nchar.山东省博市六枝特银川路k座 264255', 1630000000091) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631380000000, -144505842, 9031683748543148709, 30839, 37, 75951623525931.296875, -356608030036.447021, 0, 'binary.YAmFEuHOeLIMgXCOGnRf', 'nchar.黑龙江省秀珍市白云广州街Z座 558462', 1630000000092) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631380000000, -202930007, 2539365322373297240, 30035, -11, 3987179954447.959961, 166663.706087, 0, 'binary.aQPbQkWFDKuugEWfofTC', 'nchar.陕西省建国市江北阜新街O座 931583', 1630000000092) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631379999999, 340191939, 190224560698109215, 7127, 125, 41587961603.659103, -37646578.644303, 1, 'binary.ZClsyheJcXtiVXWSTmJC', 'nchar.内蒙古自治区南京市吉区海门街X座 981848', 1630000000092) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631380000000, 1141439964, 5703107595817904511, 17318, 70, 20244282326280.398438, -374.976792, 1, 'binary.ECmfqstJJJGVfXRSlipY', 'nchar.山东省秀珍市长寿嘉禾街H座 668408', 1630000000092) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631380000001, -822942850, -5193915838519507313, -6726, -109, 12.862186, -308.656139, 1, 'binary.fiNIskGvJlLuWiySSzcR', 'nchar.辽宁省太原市合川沈路K座 765732', 1630000000093) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631380000001, -1084726805, -1799418590653312591, -316, -61, -43.289435, -5628.101135, 1, 'binary.nYWtrJedHHgNuftngNzv', 'nchar.福建省小红市沈北新王街j座 802142', 1630000000093) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631380000000, 2145419646, 1580239203992480528, -14574, 100, -94259.299402, 2214154.396490, 0, 'binary.GZbUYTSXnACDqnrhbNFC', 'nchar.青海省淑华市沙湾阜新路Q座 663492', 1630000000092) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631395000000, -752146752, 8221071117818639487, -24048, -125, -4922542596.502000, 69.541336, 0, 'binary.DpfvmRBpvyGTcVOJPyJo', 'nchar.江西省刚县房山安街D座 955283', 1630000000093) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631395000000, -878950287, -8422331468601695661, -13558, 43, 339844.201301, 9.764866, 0, 'binary.RefVNTHmgyVTPXRzLkLd', 'nchar.浙江省马鞍山县海陵王街B座 867693', 1630000000093) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631394999999, 1783522942, 6078410931639616068, 9495, 98, 727091818.991834, 8165776010706.599609, 1, 'binary.dtkNAQMwyepAJbdqweVh', 'nchar.河北省天津市沈河贵阳街N座 113675', 1630000000093) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631395000000, 1165805677, 1114429668955803199, 26742, 75, 965648.432436, 67940.285447, 1, 'binary.STtpcklCmoPcTqcnVEYp', 'nchar.湖北省荆门县静安拉萨街x座 767367', 1630000000093) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631395000001, -1314056119, -4268557454181639559, -17681, -70, 9569.520951, -3.709641, 1, 'binary.eAxSwIhCTWRsxHmnyhOO', 'nchar.四川省建华县沙市沈阳路f座 959538', 1630000000094) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631395000001, -1195931348, -3234878011308908109, -8224, -81, 68272155.434104, 2277301.750441, 1, 'binary.cCbIERRNYVmzqgdEkLyn', 'nchar.宁夏回族自治区长春市山亭海门路i座 441560', 1630000000094) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631395000000, 1044986483, 708621525043415947, 23174, 25, -87522059062286.000000, 91518.977374, 0, 'binary.KWZOCXHGUnswxAQvgLbX', 'nchar.甘肃省上海市大东合肥路v座 576201', 1630000000093) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631410000000, -883689952, -6467532462337897809, -20092, 56, 2802216728037.279785, -9.303156, 0, 'binary.qwPhaldJXqLHFGOeyrHw', 'nchar.甘肃省南宁市孝南彭街T座 566484', 1630000000094) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631410000000, 972297407, -5877490557670044529, -27447, 44, 40.846479, -4231.348093, 0, 'binary.DwlvVHWtVzbpJAeCWIMr', 'nchar.山西省莹县魏都张街A座 689281', 1630000000094) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631409999999, 1032579814, 2390187777440316314, 19171, 78, -63005465989151.203125, 5961100651288.120117, 1, 'binary.VAqPpjxEFxcYSxnzUAwL', 'nchar.贵州省辽阳县静安安街c座 964229', 1630000000094) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631410000000, 241342224, 8497667456001609204, 18172, 104, -906790925488.797974, 36707840437.474998, 1, 'binary.FLLdUdBRMRgvzrMSflyN', 'nchar.甘肃省哈尔滨县翔安拉萨路L座 242629', 1630000000094) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631410000001, -1560976462, -1082805904642279032, -24035, -84, 5518722837.437610, 99553268986.260300, 1, 'binary.yXYqlIPBknzcrQaHQVBK', 'nchar.山西省福州县白云乌鲁木齐街I座 977466', 1630000000095) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631410000001, -1279270656, -127272614642938342, -18488, -105, 820203443079.204956, -39324.928647, 1, 'binary.vcWaeUuquQmpiNmaMFTJ', 'nchar.重庆市红市友好张家港街h座 853577', 1630000000095) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631410000000, -810546809, 4707087124402946180, 14228, -33, 401.288641, -573136.630366, 0, 'binary.oglpZSvAEAkKdUTqMhCy', 'nchar.安徽省大冶县锡山高路Q座 272097', 1630000000094) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631425000000, -1291692620, -3976582859582309880, 99, -107, -643212263540.171997, 91650599.279398, 0, 'binary.QtWoywiZBLMnNCtJddrC', 'nchar.海南省凤英市新城单路Y座 332919', 1630000000095) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631425000000, -1636741671, 6149617241982859450, -29331, -23, 53068143981197.398438, 507.769638, 0, 'binary.rwiKvwHMRitScXUVmJhW', 'nchar.陕西省辛集县清浦李路H座 631016', 1630000000095) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631424999999, 2070489093, 3407988531094502611, 31121, 105, -797.417546, -5114.871991, 1, 'binary.VKDzqKpnljjtWvPxhJtw', 'nchar.台湾省淑英县黄浦齐齐哈尔街c座 143348', 1630000000095) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631425000000, 1536720383, 3880153804085171184, 11796, 82, 45989.231323, 92.649541, 1, 'binary.tbEDrcIJyjZTjRieTqRC', 'nchar.上海市北镇市怀柔阜新路R座 405512', 1630000000095) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631425000001, -955300022, -7851370978801274222, -14072, -90, -91217.776216, -9476202.110944, 1, 'binary.wYLmyHTheIfPsDKWcbvP', 'nchar.河南省丹市金平潮州路n座 514612', 1630000000096) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631425000001, -1019361248, -57576815854175575, -24873, -4, -32984292266917.800781, 58.748899, 1, 'binary.HNDdWAeDLFDTfTKRiPvW', 'nchar.云南省桂芝市长寿王街C座 833966', 1630000000096) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631425000000, 1923224809, -2907800501658168815, -9896, 49, -33656345.811017, -671677543.932121, 0, 'binary.PJVocGHwGGXYBPOAxHSo', 'nchar.内蒙古自治区柳县崇文王街n座 759363', 1630000000095) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631440000000, 1147520901, -7715180528849786436, -17616, -76, 6.545288, -50974540.927085, 0, 'binary.vSYpvPIBkKueVfRtelNq', 'nchar.江西省亮市孝南合肥路t座 737452', 1630000000096) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631440000000, -113454687, -5823484358741527503, 28969, 121, -64687699.492563, -79961693.274913, 0, 'binary.eNlgFeimPdtilNzjMToG', 'nchar.辽宁省通辽县东丽廖路E座 551853', 1630000000096) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631439999999, 1457091374, 8334151643776472564, 2662, 82, 323215.440926, -9805209441096.250000, 1, 'binary.rMLCVjMtmxFxYRYbvQQh', 'nchar.安徽省武汉县城东萧路w座 417063', 1630000000096) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631440000000, 199139943, 2468266181580361696, 6282, 45, 938749.350559, -728777906039.301025, 1, 'binary.QCaxrlOInebbkEcnmLYI', 'nchar.天津市拉萨县魏都李街D座 325624', 1630000000096) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631440000001, -1074274106, -6116630471404653549, -13682, -70, 513137.327759, -588918896.561140, 1, 'binary.TyKIxNLJfeZgAKvWAFfB', 'nchar.海南省济南县闵行西宁路m座 451609', 1630000000097) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631440000001, -565301435, -4026730978460667946, -19020, -77, -8.983572, -43.480820, 1, 'binary.ydTJczfbrhMoGjzUmQfP', 'nchar.香港特别行政区柳州市璧山张家港街l座 596812', 1630000000097) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631440000000, 625692002, -7425751090292284243, 10228, 1, 750.678719, -90.988373, 0, 'binary.xzExJqxxmHYoAUDKciSV', 'nchar.湖北省婷县龙潭兰州街n座 199763', 1630000000096) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631455000000, 2072736931, -3329284412762274677, 12268, -69, 5910.358156, 997044108049.300049, 0, 'binary.aBqZKnHzsSpmRSwSQPYY', 'nchar.山西省郑州市孝南王路e座 167062', 1630000000097) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631455000000, 1463682034, 990280305241763342, -3488, 89, 419973.481918, -55750492618.939903, 0, 'binary.OybEvgqNWyaCiEEvxpeR', 'nchar.青海省荆门县孝南东莞路a座 305732', 1630000000097) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631454999999, 1438955591, 8811422557823062850, 15737, 98, 1754297.282564, 567752594.816600, 1, 'binary.OMjmDDXPGGJaZZRMlpqF', 'nchar.上海市台北市黄浦周街v座 378966', 1630000000097) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631455000000, 1828878609, 7873820745339300844, 23138, 106, 9.263627, 946712871592.369995, 1, 'binary.wDtceAzvXHGjCqbAGulx', 'nchar.浙江省邯郸县长寿张路V座 106929', 1630000000097) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631455000001, -1388085018, -6219226483229634812, -21928, -116, -896801017371.463989, 91302.519671, 1, 'binary.YMYcdmnGDpGZSmUvXpYa', 'nchar.重庆市刚县江北北镇路o座 294056', 1630000000098) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631455000001, -1225032046, -2776099211554722026, -11329, -26, 22948.709678, -47848.985287, 1, 'binary.muQMoYipLCOlIkSyKxUk', 'nchar.山东省郑州市合川张家港街X座 960693', 1630000000098) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631455000000, 1161217978, 1842781937217393115, 17682, -46, 286163234.229566, -2.426507, 0, 'binary.CRKBkwUTzvgcBPDSNWiy', 'nchar.广西壮族自治区浩市安次苏街L座 929528', 1630000000097) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631470000000, -821482750, -6759948063516530731, -16375, 89, -84205.305774, 768242.497026, 0, 'binary.vMJVGyqMTgaGrLmmbZIE', 'nchar.天津市琴市江北孙街m座 262672', 1630000000098) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631470000000, 717271992, 7986931673188494197, -9479, 52, 4711.839591, -5371732.797787, 0, 'binary.kPRwzfEKYpYgWRWaeGzP', 'nchar.重庆市乌鲁木齐市闵行南京路R座 883727', 1630000000098) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631469999999, 1077620215, 2558543784745208971, 25857, 52, -47179130892.244499, -20848774363.230000, 1, 'binary.BQGtKbxrxZCgjfTUjLJe', 'nchar.黑龙江省岩市海陵天津街v座 971806', 1630000000098) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631470000000, 1977913093, 3861242852069723630, 20743, 59, 9464902993.309589, -5024.160475, 1, 'binary.lzQOJDAUyRQtQDjNrWZJ', 'nchar.甘肃省齐齐哈尔市华龙沈阳街I座 777477', 1630000000098) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631470000001, -428527206, -547566441621156192, -12808, -31, -74278620895119.906250, 50537841781.787697, 1, 'binary.FkYBhPfxSWPoKPiVwaNT', 'nchar.吉林省南宁市平山张路Z座 293046', 1630000000099) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631470000001, -1181912125, -427873392135772867, -13447, -55, 3457499617.219500, -7038680.198896, 1, 'binary.ozhZqPebRJOHopCsXWpU', 'nchar.上海市伟市闵行北京街i座 107708', 1630000000099) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631470000000, 744599275, 5384505142686943052, 30013, -71, -4.424027, -5.984967, 0, 'binary.RcgJmYOFSSkGHfTHlqvY', 'nchar.陕西省东县大东窦路E座 174935', 1630000000098) ;''') + tdSql.execute(f'''insert into stable_1_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double , q_bool , q_binary , q_nchar, q_ts) values(1631485000000, -1492370578, 4514526083062070789, 31730, -102, -717.383970, 52910.663266, 0, 'binary.jsHQYTHKPARRqiGzZKOz', 'nchar.澳门特别行政区邯郸县丰都宋街W座 598200', 1630000000099) ;''') + tdSql.execute(f'''insert into regular_table_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631485000000, 963480452, 5458394487863298148, -21434, 125, -1656.168120, 5768934065.605500, 0, 'binary.rCnbtltacJIWEVZWlXVF', 'nchar.湖北省合肥县龙潭马路o座 149144', 1630000000099) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631484999999, 224551324, 4933122153940335639, 2537, 23, -4225000.312926, -7035665314327.099609, 1, 'binary.RgTacOhlKMDWwPcrKsZK', 'nchar.山西省杭州市长寿沈阳街K座 225610', 1630000000099) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631485000000, 336564804, 2661017413987846119, 26066, 127, 2271.487346, 26543272352747.398438, 1, 'binary.FKgzwzTQzUHULzcaEmAd', 'nchar.贵州省成都市清河李路w座 620531', 1630000000099) ;''') + tdSql.execute(f'''insert into stable_1_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631485000001, -1922225927, -8001645480178976724, -25777, -111, -789464.882012, -360094093.372387, 1, 'binary.pxrkoGUZiddEAkYHiVjK', 'nchar.湖北省太原市永川吴路b座 333484', 1630000000100) ;''') + tdSql.execute(f'''insert into regular_table_2 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631485000001, -1213998634, -4431806460604559923, -22976, -105, -49517009982577.796875, -959039647940.217041, 1, 'binary.VxnbNGXEiRmRkEseJUFg', 'nchar.西藏自治区张家港县浔阳张路z座 876862', 1630000000100) ;''') + tdSql.execute(f'''insert into stable_2_1 (ts , q_int , q_bigint , q_smallint , q_tinyint , q_float , q_double, q_bool , q_binary , q_nchar, q_ts) values(1631485000000, -1591388398, 1970187840324683506, 20196, -59, 28171713.207903, 6.598821, 0, 'binary.fDSGiJNSRdOTovcESQFl', 'nchar.山西省梅市沙市王街r座 815669', 1630000000099) ;''') + tdSql.execute(f'''flush database table_lastrow_2_2;''') + + def basic_query(self): + # TD-23175 + tdSql.query(f'''select _wstart, LAST_ROW(q_float) from stable_2_1 where q_ts <= now +1h and _C0 <= now +1h and q_bool in (0 , 1) interval(11s) order by ts''') + tdSql.checkRows(100) + + # TD-23178 + tdSql.query(f'''select count(*) from (select LAST(q_tinyint) from stable_2 where q_ts between 1600000000000 and now +1h interval(12s) sliding(3s) order by ts)''') + tdSql.checkData(0, 0, 400) + tdSql.query(f'''select count(*) from (select LAST(q_tinyint) from stable_2 where q_ts between 1600000000000 and now +1h interval(12s) sliding(3s) order by ts)''') + tdSql.checkData(0, 0, 400) + + # TD-23173 + tdSql.query(f'''select _wstart,_wend,LAST_ROW(q_nchar) from stable_1 interval(17d) sliding(5d) order by _wstart;''') + tdSql.checkRows(7) + tdSql.checkData(0, 2, 'nchar.安徽省玲市西夏海口街o座 109427') + tdSql.checkData(1, 2, 'nchar.黑龙江省芳县海陵贺路c座 606589') + tdSql.checkData(2, 2, 'nchar.江苏省冬梅县六枝特张路g座 635526') + tdSql.checkData(3, 2, 'nchar.甘肃省宁德县孝南北京街f座 436022') + tdSql.checkData(4, 2, 'nchar.湖北省太原市永川吴路b座 333484') + tdSql.checkData(5, 2, 'nchar.湖北省太原市永川吴路b座 333484') + tdSql.checkData(6, 2, 'nchar.湖北省太原市永川吴路b座 333484') + + tdSql.query(f'''select _wstart,_wend,LAST_ROW(q_nchar) from stable_1 where q_ts between 1600000000000 and now +1h interval(17d) sliding(5d) order by _wstart;''') + tdSql.checkRows(7) + tdSql.checkData(0, 2, 'nchar.安徽省玲市西夏海口街o座 109427') + tdSql.checkData(1, 2, 'nchar.黑龙江省芳县海陵贺路c座 606589') + tdSql.checkData(2, 2, 'nchar.江苏省冬梅县六枝特张路g座 635526') + tdSql.checkData(3, 2, 'nchar.甘肃省宁德县孝南北京街f座 436022') + tdSql.checkData(4, 2, 'nchar.湖北省太原市永川吴路b座 333484') + tdSql.checkData(5, 2, 'nchar.湖北省太原市永川吴路b座 333484') + tdSql.checkData(6, 2, 'nchar.湖北省太原市永川吴路b座 333484') + + # TD-23222 + tdSql.query(f'''select LAST_ROW(q_tinyint) from stable_2 where q_ts between 1600000000000 and now +1h and _c0 <= now +1h and (q_nchar like 'nchar%' or q_binary = '0' or q_nchar = 'nchar_' ) and (q_bool = 0 or q_bool = 1 or q_bool is null) interval(15a,9a);''') + tdSql.checkRows(100) + + def run(self): + self.prepare_data() + self.basic_query() + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/2-query/leastsquares.py b/tests/system-test/2-query/leastsquares.py index 8ece4c46f0d430ec540468467e8b9e89b35e1349..1718802a82a0ffb740918e1ff0e083a11168b3f4 100644 --- a/tests/system-test/2-query/leastsquares.py +++ b/tests/system-test/2-query/leastsquares.py @@ -19,12 +19,17 @@ BINARY_COL = "c8" NCHAR_COL = "c9" TS_COL = "c10" -NUM_COL = [ INT_COL, BINT_COL, SINT_COL, TINT_COL, FLOAT_COL, DOUBLE_COL, ] +UINT_COL = "c11" +UBINT_COL = "c12" +USINT_COL = "c13" +UTINT_COL = "c14" + +NUM_COL = [ INT_COL, BINT_COL, SINT_COL, TINT_COL, FLOAT_COL, DOUBLE_COL, UINT_COL, UBINT_COL, USINT_COL, UTINT_COL] CHAR_COL = [ BINARY_COL, NCHAR_COL, ] BOOLEAN_COL = [ BOOL_COL, ] TS_TYPE_COL = [ TS_COL, ] -ALL_COL = [ INT_COL, BINT_COL, SINT_COL, TINT_COL, FLOAT_COL, DOUBLE_COL, BOOL_COL, BINARY_COL, NCHAR_COL, TS_COL ] +ALL_COL = [ INT_COL, BINT_COL, SINT_COL, TINT_COL, FLOAT_COL, DOUBLE_COL, BOOL_COL, BINARY_COL, NCHAR_COL, TS_COL, UINT_COL, UBINT_COL, USINT_COL, UTINT_COL ] DBNAME = "db" class TDTestCase: @@ -208,6 +213,13 @@ class TDTestCase: tdLog.info(f"sql: {current_sqls[i]}") tdSql.query(current_sqls[i]) + def check_result(self): + for col in NUM_COL: + tdSql.query("select leastsquares(%s, 1, 9) from %s.stb1" % (col, DBNAME)) + tdSql.checkRows(1) + res = tdSql.getData(0, 0) + if res is None: + tdLog.exit("result is not correct") def __test_current(self): # tdSql.query("explain select c1 from {dbname}.ct1") @@ -236,6 +248,7 @@ class TDTestCase: def all_test(self): self.__test_error() self.__test_current() + self.check_result() def __create_tb(self, dbname=DBNAME): @@ -243,13 +256,15 @@ class TDTestCase: create_stb_sql = f'''create table {dbname}.stb1( ts timestamp, {INT_COL} int, {BINT_COL} bigint, {SINT_COL} smallint, {TINT_COL} tinyint, {FLOAT_COL} float, {DOUBLE_COL} double, {BOOL_COL} bool, - {BINARY_COL} binary(16), {NCHAR_COL} nchar(32), {TS_COL} timestamp + {BINARY_COL} binary(16), {NCHAR_COL} nchar(32), {TS_COL} timestamp, {UINT_COL} int unsigned, + {UBINT_COL} bigint unsigned, {USINT_COL} smallint unsigned, {UTINT_COL} tinyint unsigned ) tags (t1 int) ''' create_ntb_sql = f'''create table {dbname}.nt1( ts timestamp, {INT_COL} int, {BINT_COL} bigint, {SINT_COL} smallint, {TINT_COL} tinyint, {FLOAT_COL} float, {DOUBLE_COL} double, {BOOL_COL} bool, - {BINARY_COL} binary(16), {NCHAR_COL} nchar(32), {TS_COL} timestamp + {BINARY_COL} binary(16), {NCHAR_COL} nchar(32), {TS_COL} timestamp, {UINT_COL} int unsigned, + {UBINT_COL} bigint unsigned, {USINT_COL} smallint unsigned, {UTINT_COL} tinyint unsigned ) ''' tdSql.execute(create_stb_sql) @@ -262,49 +277,49 @@ class TDTestCase: now_time = int(datetime.datetime.timestamp(datetime.datetime.now()) * 1000) for i in range(rows): tdSql.execute( - f"insert into {dbname}.ct1 values ( { now_time - i * 1000 }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127}, {1.11*i}, {1100.0011*i}, {i%2}, 'binary{i}', 'nchar_测试_{i}', { now_time + 1 * i } )" + f"insert into {dbname}.ct1 values ( { now_time - i * 1000 }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127}, {1.11*i}, {1100.0011*i}, {i%2}, 'binary{i}', 'nchar_测试_{i}', { now_time + 1 * i }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127} )" ) tdSql.execute( - f"insert into {dbname}.ct4 values ( { now_time - i * 7776000000 }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127}, {1.11*i}, {1100.0011*i}, {i%2}, 'binary{i}', 'nchar_测试_{i}', { now_time + 1 * i } )" + f"insert into {dbname}.ct4 values ( { now_time - i * 7776000000 }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127}, {1.11*i}, {1100.0011*i}, {i%2}, 'binary{i}', 'nchar_测试_{i}', { now_time + 1 * i }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127} )" ) tdSql.execute( - f"insert into {dbname}.ct2 values ( { now_time - i * 7776000000 }, {-i}, {-11111 * i}, {-111 * i % 32767 }, {-11 * i % 127}, {-1.11*i}, {-1100.0011*i}, {i%2}, 'binary{i}', 'nchar_测试_{i}', { now_time + 1 * i } )" + f"insert into {dbname}.ct2 values ( { now_time - i * 7776000000 }, {-i}, {-11111 * i}, {-111 * i % 32767 }, {-11 * i % 127}, {-1.11*i}, {-1100.0011*i}, {i%2}, 'binary{i}', 'nchar_测试_{i}', { now_time + 1 * i }, {i}, {11111 * i}, {111 * i % 32767 }, {11 * i % 127} )" ) tdSql.execute( f'''insert into {dbname}.ct1 values - ( { now_time - rows * 5 }, 0, 0, 0, 0, 0, 0, 0, 'binary0', 'nchar_测试_0', { now_time + 8 } ) - ( { now_time + 10000 }, { rows }, -99999, -999, -99, -9.99, -99.99, 1, 'binary9', 'nchar_测试_9', { now_time + 9 } ) + ( { now_time - rows * 5 }, 0, 0, 0, 0, 0, 0, 0, 'binary0', 'nchar_测试_0', { now_time + 8 }, 0, 0, 0, 0) + ( { now_time + 10000 }, { rows }, -99999, -999, -99, -9.99, -99.99, 1, 'binary9', 'nchar_测试_9', { now_time + 9 }, 0, 0, 0, NULL ) ''' ) tdSql.execute( f'''insert into {dbname}.ct4 values - ( { now_time - rows * 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) - ( { now_time - rows * 3888000000 + 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) - ( { now_time + 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time - rows * 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time - rows * 3888000000 + 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time + 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ( { now_time + 5184000000}, {pow(2,31)-pow(2,15)}, {pow(2,63)-pow(2,30)}, 32767, 127, - { 3.3 * pow(10,38) }, { 1.3 * pow(10,308) }, { rows % 2 }, "binary_limit-1", "nchar_测试_limit-1", { now_time - 86400000} + { 3.3 * pow(10,38) }, { 1.3 * pow(10,308) }, { rows % 2 }, "binary_limit-1", "nchar_测试_limit-1", { now_time - 86400000}, NULL, NULL, NULL, NULL ) ( { now_time + 2592000000 }, {pow(2,31)-pow(2,16)}, {pow(2,63)-pow(2,31)}, 32766, 126, - { 3.2 * pow(10,38) }, { 1.2 * pow(10,308) }, { (rows-1) % 2 }, "binary_limit-2", "nchar_测试_limit-2", { now_time - 172800000} + { 3.2 * pow(10,38) }, { 1.2 * pow(10,308) }, { (rows-1) % 2 }, "binary_limit-2", "nchar_测试_limit-2", { now_time - 172800000}, NULL, NULL, NULL, NULL ) ''' ) tdSql.execute( f'''insert into {dbname}.ct2 values - ( { now_time - rows * 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) - ( { now_time - rows * 3888000000 + 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) - ( { now_time + 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time - rows * 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) + ( { now_time - rows * 3888000000 + 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time + 7776000000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ( { now_time + 5184000000 }, { -1 * pow(2,31) + pow(2,15) }, { -1 * pow(2,63) + pow(2,30) }, -32766, -126, - { -1 * 3.2 * pow(10,38) }, { -1.2 * pow(10,308) }, { rows % 2 }, "binary_limit-1", "nchar_测试_limit-1", { now_time - 86400000 } + { -1 * 3.2 * pow(10,38) }, { -1.2 * pow(10,308) }, { rows % 2 }, "binary_limit-1", "nchar_测试_limit-1", { now_time - 86400000 }, NULL, NULL, NULL, NULL ) ( { now_time + 2592000000 }, { -1 * pow(2,31) + pow(2,16) }, { -1 * pow(2,63) + pow(2,31) }, -32767, -127, - { - 3.3 * pow(10,38) }, { -1.3 * pow(10,308) }, { (rows-1) % 2 }, "binary_limit-2", "nchar_测试_limit-2", { now_time - 172800000 } + { - 3.3 * pow(10,38) }, { -1.3 * pow(10,308) }, { (rows-1) % 2 }, "binary_limit-2", "nchar_测试_limit-2", { now_time - 172800000 }, NULL, NULL, NULL, NULL ) ''' ) @@ -312,22 +327,22 @@ class TDTestCase: for i in range(rows): insert_data = f'''insert into {dbname}.nt1 values ( { now_time - i * 3600000 }, {i}, {i * 11111}, { i % 32767 }, { i % 127}, { i * 1.11111 }, { i * 1000.1111 }, { i % 2}, - "binary_{i}", "nchar_测试_{i}", { now_time - 1000 * i } ) + "binary_{i}", "nchar_测试_{i}", { now_time - 1000 * i }, NULL, NULL, NULL, NULL ) ''' tdSql.execute(insert_data) tdSql.execute( f'''insert into {dbname}.nt1 values - ( { now_time + 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) - ( { now_time - (( rows // 2 ) * 60 + 30) * 60000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) - ( { now_time - rows * 3600000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time + 10800000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time - (( rows // 2 ) * 60 + 30) * 60000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) + ( { now_time - rows * 3600000 }, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ( { now_time + 7200000 }, { pow(2,31) - pow(2,15) }, { pow(2,63) - pow(2,30) }, 32767, 127, { 3.3 * pow(10,38) }, { 1.3 * pow(10,308) }, { rows % 2 }, - "binary_limit-1", "nchar_测试_limit-1", { now_time - 86400000 } + "binary_limit-1", "nchar_测试_limit-1", { now_time - 86400000 }, NULL, NULL, NULL, NULL ) ( { now_time + 3600000 } , { pow(2,31) - pow(2,16) }, { pow(2,63) - pow(2,31) }, 32766, 126, { 3.2 * pow(10,38) }, { 1.2 * pow(10,308) }, { (rows-1) % 2 }, - "binary_limit-2", "nchar_测试_limit-2", { now_time - 172800000 } + "binary_limit-2", "nchar_测试_limit-2", { now_time - 172800000 }, NULL, NULL, NULL, NULL ) ''' ) diff --git a/tests/system-test/2-query/limit.py b/tests/system-test/2-query/limit.py index 91719aa21b0ce4245a096686aa1f5089e10ef542..c00e3b7d56af46f662ddb855a34e154e7c723b80 100644 --- a/tests/system-test/2-query/limit.py +++ b/tests/system-test/2-query/limit.py @@ -140,7 +140,7 @@ class TDTestCase: val2 = paraDict["ctbNum"] - 1 # select count(*), t1, t2, t3, t4, t5, t6 from $stb where t1 > $val1 and t1 < $val2 group by t1, t2, t3, t4, t5, t6 order by t1 asc limit 1 offset 0 sqlStr = f"select count(*), t1, t2, t3, t4, t5, t6 from %s where t1 > %d and t1 < %d group by t1, t2, t3, t4, t5, t6 order by t1 asc limit 1 offset 0"%(paraDict["stbName"], val1, val2) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(1) tdSql.checkData(0, 0, paraDict["rowsPerTbl"]) @@ -152,7 +152,7 @@ class TDTestCase: # select count(*), t3, t4 from $stb where t2 like '%' and t1 > 2 and t1 < 5 group by t3, t4 order by t3 desc limit 2 offset 0 sqlStr = f"select count(*), t3, t4 from %s where t2 like '%%' and t1 > 2 and t1 < 5 group by t3, t4 order by t3 desc limit 2 offset 0"%(paraDict["stbName"]) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(2) tdSql.checkData(0, 0, paraDict["rowsPerTbl"]) @@ -164,7 +164,7 @@ class TDTestCase: # select count(*) from $stb where t2 like '%' and t1 > 2 and t1 < 5 group by t3, t4 order by t3 desc limit 1 offset 1 sqlStr = f"select count(*) from %s where t2 like '%%' and t1 > 2 and t1 < 5 group by t3, t4 order by t3 desc limit 1 offset 1"%(paraDict["stbName"]) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(1) @@ -179,18 +179,18 @@ class TDTestCase: tb = paraDict["ctbPrefix"] + '0' # select _wstart, max(c1) from $tb where ts >= $ts0 and ts <= $tsu interval(5m) fill(value, -1) limit 10 offset 1 sqlStr = f"select _wstart, max(c1) from %s where ts >= %d and ts <= %d interval(5m) fill(value, -1) limit 10 offset 1"%(tb, ts0, tsu) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(10) - tdSql.checkData(0, 0, "18-09-17 09:05:00.000") + tdSql.checkData(0, 0, "2018-09-17 09:05:00.000") tdSql.checkData(0, 1, -1) tdSql.checkData(1, 1, 1) - tdSql.checkData(9, 0, "18-09-17 09:50:00.000") + tdSql.checkData(9, 0, "2018-09-17 09:50:00.000") tdSql.checkData(9, 1, 5) - + tb5 = paraDict["ctbPrefix"] + '5' sqlStr = f"select max(c1), min(c2) from %s where ts >= %d and ts <= %d interval(5m) fill(value, -1, -2) limit 10 offset 1"%(tb5, ts0, tsu) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(10) tdSql.checkData(0, 0, -1) @@ -206,22 +206,22 @@ class TDTestCase: limit = paraDict["rowsPerTbl"] offset = limit / 2 sqlStr = f"select max(c1), min(c2), sum(c3), avg(c4), stddev(c5), spread(c6), first(c7), last(c8), first(c9) from %s where ts >= %d and ts <= %d interval(5m) fill(value, -1, -2 ,-3, -4 , -5, -6 ,-7 ,'-8', '-9') limit %d offset %d"%(tb, ts0, tsu, limit, offset) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(limit) tdSql.checkData(0, 1, 0) sqlStr = f"select max(c1) from lm2_tb0 where ts >= 1537146000000 and ts <= 1543145400000 interval(5m) fill(value, -1000) limit 8200" - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(8200) sqlStr = f"select max(c1) from lm2_tb0 where ts >= 1537146000000 and ts <= 1543145400000 interval(5m) fill(value, -1000) limit 100000;" - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) sqlStr = f"select max(c1) from lm2_tb0 where ts >= 1537146000000 and ts <= 1543145400000 interval(5m) fill(value, -1000) limit 10 offset 8190;" - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(10) tdSql.checkData(0, 0, 5) @@ -231,7 +231,7 @@ class TDTestCase: sqlStr = f"select max(c1) from lm2_tb0 where ts >= 1537146000000 and ts <= 1543145400000 interval(5m) fill(value, -1000) limit 10 offset 10001;" - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(10) tdSql.checkData(0, 0, -1000) @@ -240,13 +240,13 @@ class TDTestCase: tdSql.checkData(3, 0, 2) sqlStr = f"select max(c1) from lm2_tb0 where ts >= 1537146000000 and ts <= 1543145400000 interval(5m) fill(value, -1000) limit 10000 offset 10001;" - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(9998) sqlStr = f"select max(c1) from lm2_tb0 where ts >= 1537146000000 and ts <= 1543145400000 interval(5m) fill(value, -1000) limit 100 offset 20001;" - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(0) @@ -254,7 +254,7 @@ class TDTestCase: limit = paraDict["rowsPerTbl"] offset = limit / 2 sqlStr = f"select _wstart,max(c1), min(c2), sum(c3), avg(c4), stddev(c5), spread(c6), first(c7), last(c8), first(c9) from %s where ts >= %d and ts <= %d interval(5m) fill(linear) limit %d offset %d"%(tb,ts0,tsu,limit, offset) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(limit) tdSql.checkData(0, 1, 0) @@ -272,7 +272,7 @@ class TDTestCase: limit = paraDict["rowsPerTbl"] offset = limit / 2 sqlStr = f"select max(c1), min(c2), sum(c3), avg(c4), stddev(c5), spread(c6), first(c7), last(c8), first(c9) from %s where ts >= %d and ts <= %d interval(5m) fill(prev) limit %d offset %d"%(tb,ts0,tsu,limit, offset) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(limit) @@ -280,7 +280,7 @@ class TDTestCase: limit = paraDict["rowsPerTbl"] offset = limit / 2 + 10 sqlStr = f"select _wstart,max(c1), min(c2), sum(c3), avg(c4), stddev(c5), spread(c6), first(c7), last(c8), first(c9) from %s where ts >= %d and ts <= %d and c1 = 5 interval(5m) fill(value, -1, -2 ,-3, -4 , -5, -6 ,-7 ,'-8', '-9') limit %d offset %d"%(tb,ts0,tsu,limit, offset) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(limit) tdSql.checkData(0, 1, 5) @@ -298,7 +298,7 @@ class TDTestCase: limit = paraDict["rowsPerTbl"] offset = limit * 2 - 11 sqlStr = f"select _wstart,max(c1), min(c2), sum(c3), avg(c4), stddev(c5), spread(c6), first(c7), last(c8), first(c9) from %s where ts >= %d and ts <= %d and c1 = 5 interval(5m) fill(value, -1, -2 ,-3, -4 , -5, -6 ,-7 ,'-8', '-9') limit %d offset %d"%(tb,ts0,tsu,limit, offset) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(10) tdSql.checkData(0, 1, -1) @@ -314,7 +314,7 @@ class TDTestCase: ### [TBASE-350] ## stb + interval + fill + group by + limit offset sqlStr = f"select max(c1), min(c2), sum(c3), avg(c4), first(c7), last(c8), first(c9) from lm2_tb0 where ts >= 1537146000000 and ts <= 1543145400000 partition by t1 interval(5m) fill(value, -1, -2, -3, -4 ,-7 ,'-8', '-9') limit 2 offset 10" - print("====sql:%s"%(sqlStr)) + tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(2) @@ -322,7 +322,7 @@ class TDTestCase: offset = paraDict["rowsPerTbl"] * 2 offset = offset - 2 sqlStr = f"select max(c1), min(c2), sum(c3), avg(c4), first(c7), last(c8), first(c9) from lm2_tb0 where ts >= 1537146000000 and ts <= 1543145400000 partition by t1 interval(5m) fill(value, -1, -2, -3, -4 ,-7 ,'-8', '-9') order by t1 limit %d offset %d"%(limit, offset) - print("====sql:%s"%(sqlStr)) + # tdLog.info("====sql:%s"%(sqlStr)) tdSql.query(sqlStr) tdSql.checkRows(1) tdSql.checkData(0, 0, 9) @@ -339,7 +339,7 @@ class TDTestCase: tdLog.printNoPrefix("======== test case 1 end ...... ") def run(self): - tdSql.prepare() + # tdSql.prepare() self.prepareTestEnv() self.tmqCase1() diff --git a/tests/system-test/2-query/mavg.py b/tests/system-test/2-query/mavg.py index d659a682b10ea9876595c0680d02295774967d15..798d0e290b8bf88ac6c9a6230651d6c44e17c68b 100644 --- a/tests/system-test/2-query/mavg.py +++ b/tests/system-test/2-query/mavg.py @@ -716,8 +716,6 @@ class TDTestCase: tdSql.checkRows(2) # partition by col - tdSql.query(f"select c1 , mavg(c1,3) from {dbname}.stb1 partition by c1") - tdSql.checkRows(0) tdSql.query(f"select c1 , mavg(c1,1) from {dbname}.stb1 partition by c1") tdSql.checkRows(40) tdSql.query(f"select c1, c2, c3, c4, mavg(c1,3) from {dbname}.stb1 partition by tbname ") diff --git a/tests/system-test/2-query/max.py b/tests/system-test/2-query/max.py index b8da02b9a6da6bfadc93d301d135464a1c7566f1..ba6ab53fc7c2503bfcdcd1b79474dc22f2717211 100644 --- a/tests/system-test/2-query/max.py +++ b/tests/system-test/2-query/max.py @@ -20,8 +20,8 @@ class TDTestCase: intData = [] floatData = [] tdSql.execute(f'''create table {dbname}.stb(ts timestamp, col1 tinyint, col2 smallint, col3 int, col4 bigint, col5 tinyint unsigned, col6 smallint unsigned, - col7 int unsigned, col8 bigint unsigned, col9 float, col10 double, col11 bool, col12 binary(20), col13 nchar(20)) tags(loc nchar(20))''') - tdSql.execute(f"create table {dbname}.stb_1 using {dbname}.stb tags('beijing')") + col7 int unsigned, col8 bigint unsigned, col9 float, col10 double, col11 bool, col12 binary(20), col13 nchar(20)) tags(t0 tinyint, t1 float, loc nchar(20))''') + tdSql.execute(f"create table {dbname}.stb_1 using {dbname}.stb tags(5, 5.5, 'beijing')") for i in range(self.rowNum): tdSql.execute(f"insert into {dbname}.stb_1 values(%d, %d, %d, %d, %d, %d, %d, %d, %d, %f, %f, %d, '{self.binary_str}%d', '{self.nchar_str}%d')" % (self.ts + i, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1, i + 1, i + 0.1, i + 0.1, i % 2, i + 1, i + 1)) @@ -55,13 +55,20 @@ class TDTestCase: tdSql.checkData(0, 1, np.max(intData)) tdSql.query(f"select ts, min(col9) from {dbname}.stb") - tdSql.checkRows(1) + tdSql.checkRows(1) tdSql.checkData(0, 1, np.min(floatData)) tdSql.query(f"select ts, min(col9) from {dbname}.stb_1") - tdSql.checkRows(1) + tdSql.checkRows(1) tdSql.checkData(0, 1, np.min(floatData)) + # check tags + tdSql.query(f"select max(t0) from {dbname}.stb") + tdSql.checkData(0,0,5) + + tdSql.query(f"select max(t1) from {dbname}.stb") + tdSql.checkData(0,0,5.5) + def max_check_ntb_base(self, dbname="db"): tdSql.prepare() intData = [] diff --git a/tests/system-test/2-query/mode.py b/tests/system-test/2-query/mode.py index 72bae552618f7e772481035c079a2d9507045d79..8321ef167585ac31d7d8086bfa24ccb34926ecb8 100644 --- a/tests/system-test/2-query/mode.py +++ b/tests/system-test/2-query/mode.py @@ -53,6 +53,7 @@ class TDTestCase: ( '2022-02-01 01:01:20.000', 6, 66666, 666, 66, 6.66, 66.66, 1, "binary6", "nchar6", now()+6a ) ( '2022-10-28 01:01:26.000', 7, 00000, 000, 00, 0.00, 00.00, 1, "binary7", "nchar7", "1970-01-01 08:00:00.000" ) ( '2022-12-01 01:01:30.000', 8, -88888, -888, -88, -8.88, -88.88, 0, "binary8", "nchar8", "1969-01-01 01:00:00.000" ) + ( '2022-12-31 01:01:32.000', 9, -99999999999999999, -999, -99, -9.99, -999999999999999999999.99, 1, "binary9", "nchar9", "1900-01-01 00:00:00.000" ) ( '2022-12-31 01:01:36.000', 9, -99999999999999999, -999, -99, -9.99, -999999999999999999999.99, 1, "binary9", "nchar9", "1900-01-01 00:00:00.000" ) ( '2023-02-21 01:01:01.000', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ''' @@ -64,61 +65,61 @@ class TDTestCase: tdSql.query(f"select ts,mode(c1) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, 9) tdSql.query(f"select ts,mode(c2) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -99999999999999999) tdSql.query(f"select ts,mode(c3) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -999) tdSql.query(f"select ts,mode(c4) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -99) tdSql.query(f"select ts,mode(c5) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -9.99) tdSql.query(f"select ts,mode(c6) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -1e+21) tdSql.query(f"select ts,mode(c7) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, True) tdSql.query(f"select ts,mode(c8) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, 'binary9') tdSql.query(f"select ts,mode(c9) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, 'nchar9') tdSql.query(f"select ts,c3,c5,c8,mode(c1) from {dbname}.tb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2022, 12, 31, 1, 1, 36)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2022, 12, 31, 1, 1, 36).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -999) tdSql.checkData(0, 2, -9.99) tdSql.checkData(0, 3, 'binary9') @@ -128,61 +129,61 @@ class TDTestCase: tdSql.query(f"select ts,mode(c1) from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 3)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 3).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, 9) tdSql.query(f"select ts,mode(c2) from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 3)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 3).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -99999) tdSql.query(f"select ts,mode(c3) from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 3)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 3).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -999) tdSql.query(f"select ts,mode(c4) from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 2)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 2).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -99) tdSql.query(f"select ts,mode(c5) from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 3)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 3).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -9.99) tdSql.query(f"select ts,mode(c6) from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 3)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 3).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, -99.99) tdSql.query(f"select ts,mode(c7) from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 3)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 3).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, True) tdSql.query(f"select ts,mode(c8) from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 3)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 3).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, 'binary9') tdSql.query(f"select ts,mode(c9) from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 3)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 3).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, 'nchar9') tdSql.query(f"select ts,mode(c1),c3,c5,c8 from {dbname}.stb") tdSql.checkRows(1) ts = tdSql.getData(0, 0) - tdSql.checkEqual(ts, datetime.datetime(2020, 12, 11, 0, 0, 3)) + tdSql.checkEqual(ts.astimezone(datetime.timezone.utc), datetime.datetime(2020, 12, 11, 0, 0, 3).astimezone(datetime.timezone.utc)) tdSql.checkData(0, 1, 9) tdSql.checkData(0, 2, -999) tdSql.checkData(0, 3, -9.99) diff --git a/tests/system-test/2-query/nestedQuery.py b/tests/system-test/2-query/nestedQuery.py index 6557aad05f7dc0d3021f1e0bbba8dfb08964ad0f..1b843defcef09ceb8bece595cae1b4b7611c33ae 100755 --- a/tests/system-test/2-query/nestedQuery.py +++ b/tests/system-test/2-query/nestedQuery.py @@ -6144,7 +6144,7 @@ class TDTestCase: startTime = time.time() - self.function_before_26() + #self.function_before_26() self.math_nest(['UNIQUE']) self.math_nest(['MODE']) @@ -6157,9 +6157,9 @@ class TDTestCase: # self.math_nest(['MAVG']) # self.math_nest(['HYPERLOGLOG']) # self.math_nest(['TAIL']) - # self.math_nest(['CSUM']) - # self.math_nest(['statecount','stateduration']) - # self.math_nest(['HISTOGRAM']) + self.math_nest(['CSUM']) + self.math_nest(['statecount','stateduration']) + self.math_nest(['HISTOGRAM']) # self.str_nest(['LTRIM','RTRIM','LOWER','UPPER']) # self.str_nest(['LENGTH','CHAR_LENGTH']) diff --git a/tests/system-test/2-query/nestedQuery_26.py b/tests/system-test/2-query/nestedQuery_26.py new file mode 100755 index 0000000000000000000000000000000000000000..9d5f31d1e067969f30f74d3f3de41236e346712e --- /dev/null +++ b/tests/system-test/2-query/nestedQuery_26.py @@ -0,0 +1,76 @@ +################################################################### +# 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.cases import tdCases +from .nestedQuery import * + +class TDTestCase(TDTestCase): + + + def run(self): + tdSql.prepare() + + startTime = time.time() + + self.function_before_26() + + # self.math_nest(['UNIQUE']) + # self.math_nest(['MODE']) + # self.math_nest(['SAMPLE']) + + # self.math_nest(['ABS','SQRT']) + # self.math_nest(['SIN','COS','TAN','ASIN','ACOS','ATAN']) + # self.math_nest(['POW','LOG']) + # self.math_nest(['FLOOR','CEIL','ROUND']) + # self.math_nest(['MAVG']) + # self.math_nest(['HYPERLOGLOG']) + # self.math_nest(['TAIL']) + # self.math_nest(['CSUM']) + # self.math_nest(['statecount','stateduration']) + # self.math_nest(['HISTOGRAM']) + + # self.str_nest(['LTRIM','RTRIM','LOWER','UPPER']) + # self.str_nest(['LENGTH','CHAR_LENGTH']) + # self.str_nest(['SUBSTR']) + # self.str_nest(['CONCAT']) + # self.str_nest(['CONCAT_WS']) + # self.time_nest(['CAST']) #放到time里起来弄 + # self.time_nest(['CAST_1']) + # self.time_nest(['CAST_2']) + # self.time_nest(['CAST_3']) + # self.time_nest(['CAST_4']) + + + + # self.time_nest(['NOW','TODAY']) + # self.time_nest(['TIMEZONE']) + # self.time_nest(['TIMETRUNCATE']) + # self.time_nest(['TO_ISO8601']) + # self.time_nest(['TO_UNIXTIMESTAMP']) + # self.time_nest(['ELAPSED']) + #self.time_nest(['TIMEDIFF_1']) + #self.time_nest(['TIMEDIFF_2']) + + + endTime = time.time() + print("total time %ds" % (endTime - startTime)) + + + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/2-query/nestedQuery_math.py b/tests/system-test/2-query/nestedQuery_math.py index 2d0bbcb352a4cfc732a2ccd4ec83604733146d32..3e37a2c15e6f2db8d657bc9dcbd001b1ec8c7aea 100755 --- a/tests/system-test/2-query/nestedQuery_math.py +++ b/tests/system-test/2-query/nestedQuery_math.py @@ -34,9 +34,9 @@ class TDTestCase(TDTestCase): self.math_nest(['MAVG']) self.math_nest(['HYPERLOGLOG']) self.math_nest(['TAIL']) - self.math_nest(['CSUM']) - self.math_nest(['statecount','stateduration']) - self.math_nest(['HISTOGRAM']) + # self.math_nest(['CSUM']) + # self.math_nest(['statecount','stateduration']) + # self.math_nest(['HISTOGRAM']) # self.str_nest(['LTRIM','RTRIM','LOWER','UPPER']) # self.str_nest(['LENGTH','CHAR_LENGTH']) diff --git a/tests/system-test/2-query/odbc.py b/tests/system-test/2-query/odbc.py new file mode 100644 index 0000000000000000000000000000000000000000..a05e05704279bfa4a96df9a755da3dcd78126a38 --- /dev/null +++ b/tests/system-test/2-query/odbc.py @@ -0,0 +1,76 @@ +import taos +import sys +import datetime +import inspect + +from util.log import * +from util.sql import * +from util.cases import * +from util.common import tdCom + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug(f"start to excute {__file__}") + tdSql.init(conn.cursor(), False) + + def check_ins_cols(self): + tdSql.execute("create database if not exists db") + tdSql.execute("create table db.ntb (ts timestamp, c1 bool, c2 tinyint, c3 smallint, c4 int, c5 bigint, c6 tinyint unsigned, c7 smallint unsigned, c8 int unsigned, c9 bigint unsigned, c10 float, c11 double, c12 varchar(100), c13 nchar(100))") + tdSql.execute("create table db.stb (ts timestamp, c1 bool, c2 tinyint, c3 smallint, c4 int, c5 bigint, c6 tinyint unsigned, c7 smallint unsigned, c8 int unsigned, c9 bigint unsigned, c10 float, c11 double, c12 varchar(100), c13 nchar(100)) tags(t int)") + tdSql.execute("insert into db.ctb using db.stb tags(1) (ts, c1) values (now, 1)") + + tdSql.query("select count(*) from information_schema.ins_columns") + tdSql.checkData(0, 0, 277) + + tdSql.query("select * from information_schema.ins_columns where table_name = 'ntb'") + tdSql.checkRows(14) + tdSql.checkData(0, 2, "NORMAL_TABLE") + + + tdSql.query("select * from information_schema.ins_columns where table_name = 'stb'") + tdSql.checkRows(14) + tdSql.checkData(0, 2, "SUPER_TABLE") + + + tdSql.query("select db_name,table_type,col_name,col_type,col_length from information_schema.ins_columns where table_name = 'ctb'") + tdSql.checkRows(14) + tdSql.checkData(0, 0, "db") + tdSql.checkData(1, 1, "CHILD_TABLE") + tdSql.checkData(3, 2, "c3") + tdSql.checkData(4, 3, "INT") + tdSql.checkData(5, 4, 8) + + tdSql.query("desc information_schema.ins_columns") + tdSql.checkRows(9) + tdSql.checkData(0, 0, "table_name") + tdSql.checkData(5, 0, "col_length") + tdSql.checkData(1, 2, 64) + + def check_get_db_name(self): + buildPath = tdCom.getBuildPath() + cmdStr = '%s/build/bin/get_db_name_test'%(buildPath) + tdLog.info(cmdStr) + ret = os.system(cmdStr) + if ret != 0: + tdLog.exit("sml_test get_db_name_test != 0") + + def run(self): # sourcery skip: extract-duplicate-method, remove-redundant-fstring + tdSql.prepare(replica = self.replicaVar) + + tdLog.printNoPrefix("==========start check_ins_cols run ...............") + self.check_ins_cols() + tdLog.printNoPrefix("==========end check_ins_cols run ...............") + + tdLog.printNoPrefix("==========start check_get_db_name run ...............") + self.check_get_db_name() + tdLog.printNoPrefix("==========end check_get_db_name run ...............") + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/2-query/out_of_order.py b/tests/system-test/2-query/out_of_order.py index 5b52661bae2244d482e150f7afcfde58e8cca123..8685b112068b5fbba72db009f6bd707a74dd6dbc 100644 --- a/tests/system-test/2-query/out_of_order.py +++ b/tests/system-test/2-query/out_of_order.py @@ -25,7 +25,7 @@ class TDTestCase: def init(self, conn, logSql, replicaVar): tdLog.debug("start to execute %s" % __file__) tdSql.init(conn.cursor(), logSql) - + def getBuildPath(self): selfPath = os.path.dirname(os.path.realpath(__file__)) @@ -35,15 +35,18 @@ class TDTestCase: projPath = selfPath[:selfPath.find("tests")] for root, dirs, files in os.walk(projPath): - if ("taosd" in files): + taosdFileName = "taosd" + if platform.system().lower() == 'windows': + taosdFileName = "taosd.exe" + if (taosdFileName 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_benchmark(self,dbname,tables,per_table_num,order,replica): - #O :Out of order + #O :Out of order #A :Repliaca buildPath = self.getBuildPath() if (buildPath == ""): @@ -52,136 +55,150 @@ class TDTestCase: tdLog.info("taosd found in %s" % buildPath) binPath = buildPath+ "/build/bin/" - os.system("%staosBenchmark -d %s -t %d -n %d -O %d -a %d -b float,double,nchar\(200\),binary\(50\) -T 50 -y " % (binPath,dbname,tables,per_table_num,order,replica)) - + cmd = "%staosBenchmark -d %s -t %d -n %d -O %d -a %d -b float,double,nchar\(200\),binary\(50\) -T 50 -y " % (binPath,dbname,tables,per_table_num,order,replica) + if platform.system().lower() == 'windows': + cmd = "%staosBenchmark -d %s -t %d -n %d -O %d -a %d -b float,double,nchar(200),binary(50) -T 50 -y " % (binPath,dbname,tables,per_table_num,order,replica) + os.system(cmd) + def sql_base(self,dbname): self.check_sub(dbname) sql1 = "select count(*) from %s.meters" %dbname self.sql_base_check(sql1,sql1) - + self.check_sub(dbname) sql2 = "select count(ts) from %s.meters" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(_c0) from %s.meters" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(c0) from %s.meters" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(c1) from %s.meters" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(c2) from %s.meters" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(c3) from %s.meters" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(t0) from %s.meters" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(t1) from %s.meters" %dbname self.sql_base_check(sql1,sql2) - - + + self.check_sub(dbname) sql2 = "select count(ts) from (select * from %s.meters)" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(_c0) from (select * from %s.meters)" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(c0) from (select * from %s.meters)" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(c1) from (select * from %s.meters)" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(c2) from (select * from %s.meters)" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(c3) from (select * from %s.meters)" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(t0) from (select * from %s.meters)" %dbname self.sql_base_check(sql1,sql2) - + self.check_sub(dbname) sql2 = "select count(t1) from (select * from %s.meters)" %dbname self.sql_base_check(sql1,sql2) - - + + # TD-22520 + tdSql.query("select tbname, ts from %s.meters where ts < '2017-07-14 10:40:00' order by ts asc limit 150;" %dbname) + tdSql.checkRows(150) + + tdSql.query("select tbname, ts from %s.meters where ts < '2017-07-14 10:40:00' order by ts asc limit 300;" %dbname) + tdSql.checkRows(300) + + tdSql.query("select tbname, ts from %s.meters where ts < '2017-07-14 10:40:00' order by ts desc limit 150;" %dbname) + tdSql.checkRows(150) + + tdSql.query("select tbname, ts from %s.meters where ts < '2017-07-14 10:40:00' order by ts desc limit 300;" %dbname) + tdSql.checkRows(300) + def sql_base_check(self,sql1,sql2): tdSql.query(sql1) sql1_result = tdSql.getData(0,0) tdLog.info("sql:%s , result: %s" %(sql1,sql1_result)) - + tdSql.query(sql2) sql2_result = tdSql.getData(0,0) tdLog.info("sql:%s , result: %s" %(sql2,sql2_result)) - + if sql1_result==sql2_result: - tdLog.info(f"checkEqual success, sql1_result={sql1_result},sql2_result={sql2_result}") + tdLog.info(f"checkEqual success, sql1_result={sql1_result},sql2_result={sql2_result}") else : - tdLog.exit(f"checkEqual error, sql1_result=={sql1_result},sql2_result={sql2_result}") - + tdLog.exit(f"checkEqual error, sql1_result=={sql1_result},sql2_result={sql2_result}") + def run_sql(self,dbname): self.sql_base(dbname) - + tdSql.execute(" flush database %s;" %dbname) - + self.sql_base(dbname) - + def check_sub(self,dbname): - + sql = "select count(*) from (select distinct(tbname) from %s.meters)" %dbname tdSql.query(sql) - num = tdSql.getData(0,0) - - for i in range(0,num): - sql1 = "select count(*) from %s.d%d" %(dbname,i) - tdSql.query(sql1) - sql1_result = tdSql.getData(0,0) - tdLog.info("sql:%s , result: %s" %(sql1,sql1_result)) - + # 目前不需要了 + # num = tdSql.getData(0,0) + + # for i in range(0,num): + # sql1 = "select count(*) from %s.d%d" %(dbname,i) + # tdSql.query(sql1) + # sql1_result = tdSql.getData(0,0) + # tdLog.info("sql:%s , result: %s" %(sql1,sql1_result)) + + def check_out_of_order(self,dbname,tables,per_table_num,order,replica): self.run_benchmark(dbname,tables,per_table_num,order,replica) - print("sleep 10 seconds") - #time.sleep(10) - print("sleep 10 seconds finish") - + self.run_sql(dbname) - + def run(self): - startTime = time.time() - - #self.check_out_of_order('db1',10,random.randint(10000,50000),random.randint(1,10),1) - self.check_out_of_order('db1',random.randint(50,200),random.randint(10000,20000),random.randint(1,5),1) - - # self.check_out_of_order('db2',random.randint(50,200),random.randint(10000,50000),random.randint(5,50),1) - - # self.check_out_of_order('db3',random.randint(50,200),random.randint(10000,50000),random.randint(50,100),1) - - # self.check_out_of_order('db4',random.randint(50,200),random.randint(10000,50000),100,1) - + startTime = time.time() + + #self.check_out_of_order('db1',10,random.randint(10000,50000),random.randint(1,10),1) + self.check_out_of_order('db1',random.randint(50,100),random.randint(10000,20000),random.randint(1,5),1) + + # self.check_out_of_order('db2',random.randint(50,200),random.randint(10000,50000),random.randint(5,50),1) + + # self.check_out_of_order('db3',random.randint(50,200),random.randint(10000,50000),random.randint(50,100),1) + + # self.check_out_of_order('db4',random.randint(50,200),random.randint(10000,50000),100,1) + endTime = time.time() print("total time %ds" % (endTime - startTime)) - - + + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/system-test/2-query/percentile.py b/tests/system-test/2-query/percentile.py index 935f55a8c21b9ac986fc10c9580ebfbc944c851d..e01aae97c00e0241401e631aeb8280aded7e1108 100644 --- a/tests/system-test/2-query/percentile.py +++ b/tests/system-test/2-query/percentile.py @@ -50,7 +50,7 @@ class TDTestCase: 'col12': f'binary({self.binary_length})', 'col13': f'nchar({self.nchar_length})' } - + self.tag_dict = { 'ts_tag' : 'timestamp', 't1': 'tinyint', @@ -85,19 +85,19 @@ class TDTestCase: self.tag_values = [ f'{self.tag_ts},{self.tag_tinyint},{self.tag_smallint},{self.tag_int},{self.tag_bigint},\ {self.tag_utint},{self.tag_usint},{self.tag_uint},{self.tag_ubint},{self.tag_float},{self.tag_double},{self.tag_bool},"{self.binary_str}","{self.nchar_str}"' - + ] - + self.param = [1,50,100] - + def insert_data(self,column_dict,tbname,row_num): - intData = [] + intData = [] floatData = [] insert_sql = self.setsql.set_insertsql(column_dict,tbname,self.binary_str,self.nchar_str) for i in range(row_num): insert_list = [] self.setsql.insert_values(column_dict,i,insert_sql,insert_list,self.ts) - intData.append(i) + intData.append(i) floatData.append(i + 0.1) return intData,floatData def check_tags(self,tags,param,num,value): @@ -117,6 +117,20 @@ class TDTestCase: else: tdSql.query(f'select percentile({k}, {param}) from {self.ntbname}') tdSql.checkData(0, 0, np.percentile(floatData, param)) + + tdSql.query(f'select percentile(col1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100) from {self.ntbname}') + tdSql.checkData(0, 0, '[0.900000, 1.800000, 2.700000, 3.600000, 4.500000, 5.400000, 6.300000, 7.200000, 8.100000, 9.000000]') + + tdSql.query(f'select percentile(col1, 9.9, 19.9, 29.9, 39.9, 49.9, 59.9, 69.9, 79.9, 89.9, 99.9) from {self.ntbname}') + tdSql.checkData(0, 0, '[0.891000, 1.791000, 2.691000, 3.591000, 4.491000, 5.391000, 6.291000, 7.191000, 8.091000, 8.991000]') + + tdSql.error(f'select percentile(col1) from {self.ntbname}') + tdSql.error(f'select percentile(col1, -1) from {self.ntbname}') + tdSql.error(f'select percentile(col1, 101) from {self.ntbname}') + tdSql.error(f'select percentile(col1, col2) from {self.ntbname}') + tdSql.error(f'select percentile(1, col1) from {self.ntbname}') + tdSql.error(f'select percentile(col1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 101) from {self.ntbname}') + tdSql.execute(f'drop database {self.dbname}') def function_check_ctb(self): tdSql.execute(f'create database {self.dbname}') @@ -135,7 +149,7 @@ class TDTestCase: else: tdSql.query(f'select percentile({k}, {param}) from {self.stbname}_{i}') tdSql.checkData(0, 0, np.percentile(floatData, param)) - + for k,v in self.tag_dict.items(): for param in self.param: if v.lower() in ['timestamp','bool'] or 'binary' in v.lower() or 'nchar' in v.lower(): @@ -145,11 +159,25 @@ class TDTestCase: data_num = tdSql.queryResult[0][0] tdSql.query(f'select percentile({k},{param}) from {self.stbname}_{i}') tdSql.checkData(0,0,data_num) - tdSql.execute(f'drop database {self.dbname}') + + tdSql.query(f'select percentile(col1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100) from {self.stbname}_0') + tdSql.checkData(0, 0, '[0.900000, 1.800000, 2.700000, 3.600000, 4.500000, 5.400000, 6.300000, 7.200000, 8.100000, 9.000000]') + + tdSql.query(f'select percentile(col1, 9.9, 19.9, 29.9, 39.9, 49.9, 59.9, 69.9, 79.9, 89.9, 99.9) from {self.stbname}_0') + tdSql.checkData(0, 0, '[0.891000, 1.791000, 2.691000, 3.591000, 4.491000, 5.391000, 6.291000, 7.191000, 8.091000, 8.991000]') + + tdSql.error(f'select percentile(col1) from {self.stbname}_0') + tdSql.error(f'select percentile(col1, -1) from {self.stbname}_0') + tdSql.error(f'select percentile(col1, 101) from {self.stbname}_0') + tdSql.error(f'select percentile(col1, col2) from {self.stbname}_0') + tdSql.error(f'select percentile(1, col1) from {self.stbname}_0') + tdSql.error(f'select percentile(col1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 101) from {self.stbname}_0') + + tdSql.execute(f'drop database {self.dbname}') def run(self): self.function_check_ntb() self.function_check_ctb() - + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__) diff --git a/tests/system-test/2-query/projectionDesc.py b/tests/system-test/2-query/projectionDesc.py new file mode 100644 index 0000000000000000000000000000000000000000..1edceaa6f2ced20595132149c8d8f135111ce097 --- /dev/null +++ b/tests/system-test/2-query/projectionDesc.py @@ -0,0 +1,48 @@ +from wsgiref.headers import tspecials +from util.log import * +from util.cases import * +from util.sql import * +import numpy as np + + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + + self.rowNum = 10 + self.batchNum = 5 + self.ts = 1537146000000 + + def run(self): + dbname = "db" + tdSql.prepare() + + intData = [] + floatData = [] + + tdSql.execute(f'''create table {dbname}.stb(ts timestamp, col1 tinyint, col2 smallint, col3 int, col4 bigint, col5 float, col6 double, + col7 bool, col8 binary(20), col9 nchar(20), col11 tinyint unsigned, col12 smallint unsigned, col13 int unsigned, col14 bigint unsigned) tags(loc nchar(20))''') + tdSql.execute(f"create table {dbname}.stb_1 using {dbname}.stb tags('beijing')") + for n in range(self.batchNum): + for i in range(self.rowNum): + tdSql.execute(f"insert into {dbname}.stb_1 values(%d, %d, %d, %d, %d, %f, %f, %d, 'taosdata%d', '涛思数据%d', %d, %d, %d, %d)" + % (self.ts, 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)) + intData.append(i + 1) + floatData.append(i + 0.1) + tdSql.execute(f"flush database {dbname}") + + tdSql.query(f"select * from {dbname}.stb_1 order by ts desc") + tdSql.checkRows(1) + #tdSql.checkData(0,0,1537146000000) + tdSql.checkData(0,1,10) + + tdSql.query(f"select * from {dbname}.stb_1 order by 'aaa' desc") + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/2-query/queryQnode.py b/tests/system-test/2-query/queryQnode.py index fec553436c04f6b1cca231dc917874de4a883f5f..9c4091d0dfb58c05484f32cfbdd27a55c4b20dbd 100644 --- a/tests/system-test/2-query/queryQnode.py +++ b/tests/system-test/2-query/queryQnode.py @@ -292,9 +292,9 @@ class TDTestCase: maxQnode=tdSql.getData(0,0) tdSql.query("select min(c1) from stb11;") minQnode=tdSql.getData(0,0) - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") unionQnode=tdSql.queryResult - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") unionallQnode=tdSql.queryResult # tdSql.query("select * from information_schema.ins_qnodes;") @@ -306,10 +306,10 @@ class TDTestCase: tdSql.checkData(0, 0, "%s"%maxQnode) tdSql.query("select min(c1) from stb11;") tdSql.checkData(0, 0, "%s"%minQnode) - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") unionVnode=tdSql.queryResult assert unionQnode == unionVnode - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") unionallVnode=tdSql.queryResult assert unionallQnode == unionallVnode @@ -340,9 +340,9 @@ class TDTestCase: assert maxQnode==tdSql.getData(0,0) tdSql.query("select min(c1) from stb11;") assert minQnode==tdSql.getData(0,0) - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") assert unionQnode==tdSql.queryResult - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") assert unionallQnode==tdSql.queryResult # tdSql.query("select * from information_schema.ins_qnodes;") @@ -354,8 +354,8 @@ class TDTestCase: assert maxQnode==tdSql.getData(0,0) tdSql.query("select min(c1) from stb11;") assert minQnode==tdSql.getData(0,0) - tdSql.error("select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000;") - tdSql.error("select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000;") + tdSql.error("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") + tdSql.error("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") # tdSql.execute("create qnode on dnode %s"%dnodeId) @@ -387,9 +387,9 @@ class TDTestCase: assert maxQnode==tdSql.getData(0,0) tdSql.query("select min(c1) from stb11;") assert minQnode==tdSql.getData(0,0) - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") assert unionQnode==tdSql.queryResult - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") assert unionallQnode==tdSql.queryResult queryPolicy=1 @@ -412,9 +412,9 @@ class TDTestCase: assert maxQnode==tdSql.getData(0,0) tdSql.query("select min(c1) from stb11;") assert minQnode==tdSql.getData(0,0) - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") assert unionQnode==tdSql.queryResult - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") assert unionallQnode==tdSql.queryResult # test case : queryPolicy = 2 @@ -443,8 +443,8 @@ class TDTestCase: tdSql.execute("use db1;") tdSql.error("select max(c1) from stb10;") tdSql.error("select min(c1) from stb11;") - tdSql.error("select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000;") - tdSql.error("select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000;") + tdSql.error("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") + tdSql.error("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") tdSql.query("select max(c1) from stb10_0;") tdSql.query("select min(c1) from stb11_0;") @@ -464,9 +464,9 @@ class TDTestCase: maxQnode=tdSql.getData(0,0) tdSql.query("select min(c1) from stb11;") minQnode=tdSql.getData(0,0) - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") unionQnode=tdSql.queryResult - tdSql.query("select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000;") + tdSql.query("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") unionallQnode=tdSql.queryResult # tdSql.query("select * from information_schema.ins_qnodes;") @@ -478,8 +478,8 @@ class TDTestCase: tdSql.error("select max(c1) from stb10;") tdSql.error("select min(c1) from stb11;") - tdSql.error("select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000;") - tdSql.error("select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000;") + tdSql.error("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") + tdSql.error("select c0,c1 from(select c0,c1 from stb11_1 where (c0>1000) union all select c0,c1 from stb11_1 where c0>2000) order by c0,c1;") # run case def run(self): diff --git a/tests/system-test/2-query/sample.py b/tests/system-test/2-query/sample.py index a09d6a2b856bca40f1df55673c7d8e555f1df0f6..a43c2e635eb771687a237cabdb61d1311f29a1de 100644 --- a/tests/system-test/2-query/sample.py +++ b/tests/system-test/2-query/sample.py @@ -171,6 +171,7 @@ class TDTestCase: if any(parm in condition.lower().strip() for parm in condition_exception): print(f"case in {line}: ", end='') + print(f"condition : {condition}: ", end='') return tdSql.error(self.sample_query_form( sel=sel, func=func, col=col, m_comm=m_comm, k=k, r_comm=r_comm, alias=alias, fr=fr, table_expr=table_expr, condition=condition @@ -391,16 +392,6 @@ class TDTestCase: self.checksample(**case25) case26 = {"k": 1000} self.checksample(**case26) - case27 = { - "table_expr": f"{DBNAME}.stb1", - "condition": "group by tbname slimit 1 " - } - self.checksample(**case27) # with slimit - case28 = { - "table_expr": f"{DBNAME}.stb1", - "condition": "group by tbname slimit 1 soffset 1" - } - self.checksample(**case28) # with soffset pass diff --git a/tests/system-test/2-query/select_null.py b/tests/system-test/2-query/select_null.py new file mode 100755 index 0000000000000000000000000000000000000000..68eea8bc67cad78d44b3c5bd3ad7888b06e9cc00 --- /dev/null +++ b/tests/system-test/2-query/select_null.py @@ -0,0 +1,446 @@ +################################################################### +# 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 os +import time +import taos +import subprocess +from faker import Faker +from util.log import tdLog +from util.cases import tdCases +from util.sql import tdSql +from util.dnodes import tdDnodes +from util.dnodes import * + +class TDTestCase: + + def init(self, conn, logSql, replicaVar): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + self.testcasePath = os.path.split(__file__)[0] + self.testcaseFilename = os.path.split(__file__)[-1] + os.system("rm -rf %s/%s.sql" % (self.testcasePath,self.testcaseFilename)) + + self.db = "sel_null" + + def insert_data(self,database,vgroups): + num_random = 10 + tdSql.execute('''drop database if exists %s ;''' %database) + tdSql.execute('''create database %s keep 36500 vgroups %d PRECISION 'us';'''%(database,vgroups)) + tdSql.execute('''use %s;'''%database) + + tdSql.execute('''create stable %s.stb0 (ts timestamp , c0 int , c1 double , c0null int , c1null double ) tags( t0 tinyint , t1 varchar(16) , t_int int , t_bigint bigint , t_smallint smallint , t_tinyint tinyint , t_bool bool , t_binary binary(100) , t_nchar nchar(100) ,t_float float , t_double double , t_ts timestamp);'''%database) + + for i in range(5): + tdSql.execute('''create table %s.stb0_%d using %s.stb0 tags(%d,'varchar%d',%d,%d, %d, %d,%d,'binary%d','nchar%d',%d,%d,%d ) ;'''%(database,i,database,i,i,i,i,i,i,i,i,i,i,i,i)) + + # insert data + for i in range(num_random): + for j in range(50): + tdSql.execute('''insert into %s.stb0_0 (ts , c1 , c0) values(now, %d, %d) ;''' % (database,j,j)) + tdSql.execute('''insert into %s.stb0_1 (ts , c1 , c0) values(now, %d, %d) ;''' % (database,j,j)) + tdSql.execute('''insert into %s.stb0_2 (ts , c1 , c0) values(now, %d, %d) ;''' % (database,j,j)) + tdSql.execute('''insert into %s.stb0_3 (ts , c1 , c0) values(now, %d, %d) ;''' % (database,j,j)) + tdSql.execute('''insert into %s.stb0_4 (ts , c1 , c0) values(now, %d, %d) ;''' % (database,j,j)) + + tdSql.query("select count(*) from %s.stb0;" %database) + tdSql.checkData(0,0,5*num_random*50) + tdSql.query("select count(*) from %s.stb0_0;"%database) + tdSql.checkData(0,0,num_random*50) + + def ts_3085(self,database): + sql = "select count(c0null) from(select * from %s.stb0 limit 20,4) "%(database) + tdSql.query(sql) + tdSql.checkData(0,0,0) + + offset = random.randint(10,100) + for i in range(offset): + sql = "select count(c0null) from(select * from %s.stb0 limit %d,%d) "%(database,offset,i) + tdSql.query(sql) + tdSql.checkData(0,0,0) + sql = "select count(c1null) from(select * from %s.stb0 limit %d,%d) "%(database,offset,i) + tdSql.query(sql) + tdSql.checkData(0,0,0) + sql = "select count(c0) from(select * from %s.stb0 limit %d,%d) "%(database,offset,i) + tdSql.query(sql) + tdSql.checkData(0,0,i) + sql = "select count(c1) from(select * from %s.stb0 limit %d,%d) "%(database,offset,i) + tdSql.query(sql) + tdSql.checkData(0,0,i) + sql = "select count(t0) from(select * from %s.stb0 limit %d,%d) "%(database,offset,i) + tdSql.query(sql) + tdSql.checkData(0,0,i) + sql = "select count(t1) from(select * from %s.stb0 limit %d,%d) "%(database,offset,i) + tdSql.query(sql) + tdSql.checkData(0,0,i) + + + def ts_2974_max(self,database): + sql = "select max(c0) from %s.stb0 where ts= 1 or rows <= 4): + tdLog.info("sql checkrows success") + else: + tdLog.exit(f"checkEqual error, sql_rows=={rows}") + + + self.sql_query_time_cost(nest_sql) + rows = tdSql.queryRows + if (rows >= 1 or rows <= 4): + tdLog.info("sql checkrows success") + else: + tdLog.exit(f"checkEqual error, sql_rows=={rows}") + + sql_0 = re.sub(r'\d+',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + sql = sql.replace('limit','slimit') + tdSql.error(sql) + nest_sql = nest_sql.replace('limit','slimit') + tdSql.error(nest_sql) + + sql_0 = re.sub(r'\d+',"0",sql) + tdSql.error(sql_0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + tdSql.error(nest_sql_0) + + def sql_limit_retun_tables_slimit_return_error(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n;sql limit 0 = 0 ;sql slmit n = error;sql slimit 0 = error + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkRows(tables) + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(tables) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + sql = sql.replace('limit','slimit') + tdSql.error(sql) + nest_sql = nest_sql.replace('limit','slimit') + tdSql.error(nest_sql) + + sql_0 = re.sub(r'\d+',"0",sql) + tdSql.error(sql_0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + tdSql.error(nest_sql_0) + + def sql_limit_retun_tables_slimit_return_n(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =tables;sql limit 0 = 0 ;sql slmit n = n;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkRows(tables) + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(tables) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + sql = sql.replace('limit','slimit') + self.sql_query_time_cost(sql) + tdSql.checkRows(num) + nest_sql = nest_sql.replace('limit','slimit') + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + def sql_data_limit_retun_tables_slimit_return_n(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =tables;sql limit 0 = 0 ;sql slmit n = n;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,tables) + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,tables) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + sql = sql.replace('limit','slimit') + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,num) + nest_sql = nest_sql.replace('limit','slimit') + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + def sql_limit_retun_n_slimit_return_tables(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n;sql limit 0 = 0 ;sql slmit n = 100;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkRows(num) + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + sql = sql.replace('limit','slimit') + self.sql_query_time_cost(sql) + tdSql.checkRows(tables) + nest_sql = nest_sql.replace('limit','slimit') + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(tables) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + def sql_data_limit_retun_n_slimit_return_tables(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n;sql limit 0 = 0 ;sql slmit n = 100;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,num) + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + sql = sql.replace('limit','slimit') + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,tables) + nest_sql = nest_sql.replace('limit','slimit') + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,tables) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + def sql_limit_retun_tables_times_n_slimit_return_error(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n*tables;sql limit 0 = 0 ;sql slmit n = tables*n;sql slimit 0 = 0 + #interval + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkRows(num*tables) + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num*tables) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + sql = sql.replace('limit','slimit') + tdSql.error(sql) + nest_sql = nest_sql.replace('limit','slimit') + tdSql.error(nest_sql) + + sql_0 = re.sub(r'\d\d',"0",sql) + tdSql.error(sql_0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + tdSql.error(nest_sql_0) + + def sql_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n*tables;sql limit 0 = 0 ;sql slmit n = per_table_num*n;sql slimit 0 = 0 + #interval + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkRows(num*tables) + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num*tables) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + sql = sql.replace('limit','slimit') + self.sql_query_time_cost(sql) + tdSql.checkRows(num*per_table_num) + nest_sql = nest_sql.replace('limit','slimit') + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num*per_table_num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + def sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n*tables;sql limit 0 = 0 ;sql slmit n = per_table_num*n;sql slimit 0 = 0 + #interval + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,num*tables) + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,num*tables) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + sql = sql.replace('limit','slimit') + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,num*per_table_num) + nest_sql = nest_sql.replace('limit','slimit') + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,num*per_table_num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + def sql_limit_retun_n_slimit_return_per_table_num_times_tables(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n*tables;sql limit 0 = 0 ;sql slmit n = per_table_num*n;sql slimit 0 = 0 + #interval + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkRows(num) + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + sql = sql.replace('limit','slimit') + self.sql_query_time_cost(sql) + tdSql.checkRows(tables*per_table_num) + nest_sql = nest_sql.replace('limit','slimit') + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(tables*per_table_num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + def sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n*tables;sql limit 0 = 0 ;sql slmit n = per_table_num*n;sql slimit 0 = 0 + #interval + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,num) + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) # \d是匹配数字字符[0-9],+匹配一个或多个 + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + sql = sql.replace('limit','slimit') + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,tables*per_table_num) + nest_sql = nest_sql.replace('limit','slimit') + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,tables*per_table_num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + def sql_limit_not_test_slimitkeep_return_per_table_num_times_n(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql sql slmit n = per_table_num*n;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + sql = sql.replace('limit','limit') + self.sql_query_time_cost(sql) + tdSql.checkRows(num*per_table_num) + + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num*per_table_num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + def sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql sql slmit n = per_table_num*n;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + sql = sql.replace('limit','limit') + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,num*per_table_num) + + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,num*per_table_num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + def sql_limit_not_test_slimitkeep_return_per_table_num_times_tables(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql sql slmit n = per_table_num*tables;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkRows(tables*per_table_num) + + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(tables*per_table_num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + def sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(self,sql,num,tables,per_table_num,base_fun,replace_fun): + #sql sql slmit n = per_table_num*tables;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,tables*per_table_num) + + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,tables*per_table_num) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + def sql_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(self,sql,num,num2,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n*num2;sql limit 0 = 0 ;sql slmit n = num2*n;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkRows(num*num2) + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num*num2) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + sql = sql.replace('limit','limit') + self.sql_query_time_cost(sql) + tdSql.checkRows(num*num2) + nest_sql = nest_sql.replace('limit','limit') + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num*num2) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + def sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(self,sql,num,num2,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n*num2;sql limit 0 = 0 ;sql slmit n = num2*n;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,num*num2) + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,num*num2) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + sql = sql.replace('limit','limit') + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,num*num2) + nest_sql = nest_sql.replace('limit','limit') + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,num*num2) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + def sql_limit_times_slimitkeep_return_n2(self,sql,num,num2,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n*num2;sql limit 0 = 0 ;sql slmit n = num2*n;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkRows(num2) + self.sql_query_time_cost(nest_sql) + tdSql.checkRows(num2) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkRows(0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkRows(0) + + def sql_data_limit_times_slimitkeep_return_n2(self,sql,num,num2,tables,per_table_num,base_fun,replace_fun): + #sql limit n =n*num2;sql limit 0 = 0 ;sql slmit n = num2*n;sql slimit 0 = 0 + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,num2) + self.sql_query_time_cost(nest_sql) + tdSql.checkData(0,0,num2) + + sql_0 = re.sub(r'\d\d',"0",sql) + self.sql_query_time_cost(sql_0) + tdSql.checkData(0,0,0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + self.sql_query_time_cost(nest_sql_0) + tdSql.checkData(0,0,0) + + def sql_retun_error(self,sql,base_fun,replace_fun): + #sql limit n = error;sql limit 0 = error ;sql slmit n = error ;sql slimit 0 = error + sql = sql.replace('%s'%base_fun,'%s'%replace_fun) + + nest_sql =" select * from (%s) " %sql + tdSql.error(sql) + tdSql.error(nest_sql) + + sql_0 = re.sub(r'\d+',"0",sql) + tdSql.error(sql) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + tdSql.error(nest_sql_0) + + sql = sql.replace('limit','slimit') + tdSql.error(sql) + nest_sql = nest_sql.replace('limit','slimit') + tdSql.error(nest_sql) + + sql_0 = re.sub(r'\d+',"0",sql) + tdSql.error(sql_0) + nest_sql_0 = re.sub(r'\d\d',"0",nest_sql) + tdSql.error(nest_sql_0) + + def fun_base(self,dbname,num,num2,tables,per_table_num,dbnamejoin,base_fun,replace_fun): + + tdLog.info("base query ---------1----------") + sql = "select * from %s.meters limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.* from %s.meters a,%s.meters b where a.ts = b.ts limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("base query ---------2----------") + sql = "select * from %s.meters where ts is not null limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.* from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("base query ---------3----------") + sql = "select * from %s.meters where ts is not null order by ts limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.* from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts order by b.ts limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + tdLog.info("base query ---------4----------") + sql = "select * from %s.meters where ts is not null order by ts desc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.* from %s.meters a,%s.meters b where b.ts is not null and a.ts = b.ts order by a.ts desc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + def fun_count(self,dbname,num,num2,tables,per_table_num,dbnamejoin,base_fun,replace_fun): + + tdLog.info("count query ---------1----------") + sql = "select count(*) from %s.meters limit %d" %(dbname,num) + self.sql_limit_retun_1_slimit_return_error(sql,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_1_slimit_return_error(sql,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_1_slimit_return_error(sql_union,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_1_slimit_return_error(sql_union_all,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select count(a.*) from %s.meters a,%s.meters b where a.ts = b.ts limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_1_slimit_return_error(sql_join,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_1_slimit_return_error(sql_join,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_1_slimit_return_error(sql_union,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_1_slimit_return_error(sql_union_all,tables,per_table_num,base_fun,replace_fun) + + + + + tdLog.info("count query ---------2----------") + sql = "select count(*) from %s.meters where ts is not null limit %d" %(dbname,num) + self.sql_limit_retun_1_slimit_return_error(sql,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_1_slimit_return_error(sql,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_1_slimit_return_error(sql_union,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_1_slimit_return_error(sql_union_all,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select count(a.*) from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_1_slimit_return_error(sql_join,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_1_slimit_return_error(sql_join,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_1_slimit_return_error(sql_union,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_1_slimit_return_error(sql_union_all,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------3----------") + sql = "select count(*) from %s.meters where ts is not null order by ts limit %d" %(dbname,num) + self.sql_retun_error(sql,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_retun_error(sql,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + sql_join = "select count(a.*) from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts order by b.ts limit %d" %(dbname,dbnamejoin,num) + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + + + tdLog.info("count query ---------4----------") + sql = "select count(*) from %s.meters where ts is not null order by ts desc limit %d" %(dbname,num) + self.sql_retun_error(sql,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_retun_error(sql,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + sql_join = "select count(a.*) from %s.meters a,%s.meters b where b.ts is not null and a.ts = b.ts order by a.ts desc limit %d" %(dbname,dbnamejoin,num) + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + + + tdLog.info("count query ---------5----------") + sql = "select count(*) from %s.meters where ts is not null group by tbname limit %d" %(dbname,num) + self.sql_limit_retun_tables_slimit_return_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_tables_slimit_return_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select count(*) from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts group by b.tbname limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_tables_slimit_return_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_tables_slimit_return_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + + tdLog.info("count query ---------6----------") + sql = "select count(*) from %s.meters where ts is not null partition by tbname limit %d" %(dbname,num) + self.sql_limit_retun_tables_slimit_return_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_tables_slimit_return_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select count(*) from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by b.tbname limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_tables_slimit_return_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_tables_slimit_return_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------7----------") + sql = "select count(*) cc from %s.meters where ts is not null group by tbname order by cc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts group by b.tbname order by cc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------8----------") + sql = "select count(*) cc from %s.meters where ts is not null partition by tbname order by cc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by b.tbname order by cc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------9----------") + sql = "select count(*) cc from %s.meters where ts is not null interval(1a) limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------10----------") + sql = "select count(*) cc from %s.meters where ts is not null interval(1a) order by cc asc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) order by cc asc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------11----------") + sql = "select count(*) cc from %s.meters where ts is not null interval(1a) order by cc desc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) order by cc desc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------12----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null interval(1a) group by tbname limit %d" %(dbname,num) + self.sql_retun_error(sql,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_retun_error(sql,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) group by b.tbname limit %d" %(dbname,dbnamejoin,num) + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + + + tdLog.info("count query ---------13----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null interval(1a) partition by tbname limit %d" %(dbname,num) + self.sql_retun_error(sql,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_retun_error(sql,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) partition by b.tbname limit %d" %(dbname,dbnamejoin,num) + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + + + tdLog.info("count query ---------14----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null partition by tbname interval(1a) limit %d" %(dbname,num) + self.sql_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------15----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc asc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc asc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------16----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc desc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc desc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------17----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null partition by tbname interval(1a) slimit %d" %(dbname,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) slimit %d" %(dbname,dbnamejoin,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------18----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc asc slimit %d" %(dbname,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc asc slimit %d" %(dbname,dbnamejoin,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + tdLog.info("count query ---------19----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc desc slimit %d" %(dbname,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc desc slimit %d" %(dbname,dbnamejoin,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("count query ---------20----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null partition by tbname interval(1a) slimit %d limit %d" %(dbname,num,num2) + self.sql_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) slimit %d limit %d" %(dbname,dbnamejoin,num,num2) + self.sql_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + + tdLog.info("count query ---------21----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc asc slimit %d limit %d" %(dbname,num,num2) + self.sql_limit_times_slimitkeep_return_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_times_slimitkeep_return_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc asc slimit %d limit %d" %(dbname,dbnamejoin,num,num2) + self.sql_limit_times_slimitkeep_return_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_times_slimitkeep_return_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + + tdLog.info("count query ---------22----------") + sql = "select tbname,count(*) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc desc slimit %d limit %d" %(dbname,num,num2) + self.sql_limit_times_slimitkeep_return_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_times_slimitkeep_return_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,count(*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc desc slimit %d limit %d" %(dbname,dbnamejoin,num,num2) + self.sql_limit_times_slimitkeep_return_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_times_slimitkeep_return_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + + def fun_last(self,dbname,num,num2,tables,per_table_num,dbnamejoin,base_fun,replace_fun): + + tdLog.info("last query ---------1----------") + sql = "select last(*) from %s.meters limit %d" %(dbname,num) + self.sql_limit_retun_1_slimit_return_error(sql,tables,per_table_num,base_fun,replace_fun) + sql = "select last(*) from (%s)" %sql + self.sql_limit_retun_1_slimit_return_error(sql,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_last_limit_retun_1_slimit_return_error(sql_union,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_last_limit_retun_1_slimit_return_error(sql_union_all,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select last(a.*) from %s.meters a,%s.meters b where a.ts = b.ts limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_1_slimit_return_error(sql_join,tables,per_table_num,base_fun,replace_fun) + sql_join = "select last(*) from (%s)" %sql_join + self.sql_limit_retun_1_slimit_return_error(sql_join,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_last_limit_retun_1_slimit_return_error(sql_union,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_last_limit_retun_1_slimit_return_error(sql_union_all,tables,per_table_num,base_fun,replace_fun) + + + + + tdLog.info("last query ---------2----------") + sql = "select last(*) from %s.meters where ts is not null limit %d" %(dbname,num) + self.sql_limit_retun_1_slimit_return_error(sql,tables,per_table_num,base_fun,replace_fun) + sql = "select last(*) from (%s)" %sql + self.sql_limit_retun_1_slimit_return_error(sql,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_last_limit_retun_1_slimit_return_error(sql_union,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_last_limit_retun_1_slimit_return_error(sql_union_all,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select last(a.*) from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_1_slimit_return_error(sql_join,tables,per_table_num,base_fun,replace_fun) + sql_join = "select last(*) from (%s)" %sql_join + self.sql_limit_retun_1_slimit_return_error(sql_join,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_last_limit_retun_1_slimit_return_error(sql_union,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_last_limit_retun_1_slimit_return_error(sql_union_all,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------3----------") + sql = "select last(*) from %s.meters where ts is not null order by ts limit %d" %(dbname,num) + self.sql_retun_error(sql,base_fun,replace_fun) + sql = "select last(*) from (%s)" %sql + self.sql_retun_error(sql,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + sql_join = "select last(a.*) from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts order by b.ts limit %d" %(dbname,dbnamejoin,num) + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_join = "select last(*) from (%s)" %sql_join + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + + + tdLog.info("last query ---------4----------") + sql = "select last(*) from %s.meters where ts is not null order by ts desc limit %d" %(dbname,num) + self.sql_retun_error(sql,base_fun,replace_fun) + sql = "select last(*) from (%s)" %sql + self.sql_retun_error(sql,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + sql_join = "select last(a.*) from %s.meters a,%s.meters b where b.ts is not null and a.ts = b.ts order by a.ts desc limit %d" %(dbname,dbnamejoin,num) + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_join = "select last(*) from (%s)" %sql_join + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + + + tdLog.info("last query ---------5----------") + sql = "select last(*) from %s.meters where ts is not null group by tbname limit %d" %(dbname,num) + self.sql_limit_retun_tables_slimit_return_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_tables_slimit_return_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select last(a.*) from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts group by b.tbname limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_tables_slimit_return_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_tables_slimit_return_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + + tdLog.info("last query ---------6----------") + sql = "select last(*) from %s.meters where ts is not null partition by tbname limit %d" %(dbname,num) + self.sql_limit_retun_tables_slimit_return_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_tables_slimit_return_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select last(a.*) from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by b.tbname limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_tables_slimit_return_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_tables_slimit_return_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_tables_slimit_return_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------7----------") + sql = "select last(ts) cc from %s.meters where ts is not null group by tbname order by cc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts group by b.tbname order by cc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------8----------") + sql = "select last(ts) cc from %s.meters where ts is not null partition by tbname order by cc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by b.tbname order by cc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------9----------") + sql = "select last(*) from %s.meters where ts is not null interval(1a) limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------10----------") + sql = "select last(ts) cc from %s.meters where ts is not null interval(1a) order by cc asc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) order by cc asc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------11----------") + sql = "select last(ts) cc from %s.meters where ts is not null interval(1a) order by cc desc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_error(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) order by cc desc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_error(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_error(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_error(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------12----------") + sql = "select tbname,last(ts) cc from %s.meters where ts is not null interval(1a) group by tbname limit %d" %(dbname,num) + self.sql_retun_error(sql,base_fun,replace_fun) + sql = "select last(*) from (%s)" %sql + self.sql_retun_error(sql,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) group by b.tbname limit %d" %(dbname,dbnamejoin,num) + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_join = "select last(*) from (%s)" %sql_join + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + + + tdLog.info("last query ---------13----------") + sql = "select tbname,last(ts) cc from %s.meters where ts is not null interval(1a) partition by tbname limit %d" %(dbname,num) + self.sql_retun_error(sql,base_fun,replace_fun) + sql = "select last(*) from (%s)" %sql + self.sql_retun_error(sql,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts interval(1a) partition by b.tbname limit %d" %(dbname,dbnamejoin,num) + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_join = "select last(*) from (%s)" %sql_join + self.sql_retun_error(sql_join,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_retun_error(sql_union,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_retun_error(sql_union_all,base_fun,replace_fun) + + + + tdLog.info("last query ---------14----------") + sql = "select tbname,last(*) cc from %s.meters where ts is not null partition by tbname interval(1a) limit %d" %(dbname,num) + self.sql_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_tables_times_n_slimit_return_per_table_num_times_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------15----------") + sql = "select tbname,last(ts) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc asc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc asc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------16----------") + sql = "select tbname,last(ts) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc desc limit %d" %(dbname,num) + self.sql_limit_retun_n_slimit_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc desc limit %d" %(dbname,dbnamejoin,num) + self.sql_limit_retun_n_slimit_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_slimit_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------17----------") + sql = "select tbname,last(*) cc from %s.meters where ts is not null partition by tbname interval(1a) slimit %d" %(dbname,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) slimit %d" %(dbname,dbnamejoin,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_n(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------18----------") + sql = "select tbname,last(ts) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc asc slimit %d" %(dbname,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc asc slimit %d" %(dbname,dbnamejoin,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + tdLog.info("last query ---------19----------") + sql = "select tbname,last(ts) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc desc slimit %d" %(dbname,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc desc slimit %d" %(dbname,dbnamejoin,num) + self.sql_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_join,num,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union,num,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_not_test_slimitkeep_return_per_table_num_times_tables(sql_union_all,num,tables,per_table_num,base_fun,replace_fun) + + + + tdLog.info("last query ---------20----------") + sql = "select tbname,last(*) cc from %s.meters where ts is not null partition by tbname interval(1a) slimit %d limit %d" %(dbname,num,num2) + self.sql_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.*) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) slimit %d limit %d" %(dbname,dbnamejoin,num,num2) + self.sql_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_retun_n_times_n2_slimitkeep_return_n_times_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + + tdLog.info("last query ---------21----------") + sql = "select tbname,last(ts) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc asc slimit %d limit %d" %(dbname,num,num2) + self.sql_limit_times_slimitkeep_return_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_times_slimitkeep_return_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc asc slimit %d limit %d" %(dbname,dbnamejoin,num,num2) + self.sql_limit_times_slimitkeep_return_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_times_slimitkeep_return_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + + tdLog.info("last query ---------22----------") + sql = "select tbname,last(ts) cc from %s.meters where ts is not null partition by tbname interval(1a) order by cc desc slimit %d limit %d" %(dbname,num,num2) + self.sql_limit_times_slimitkeep_return_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql = "select count(*) from (%s)" %sql + self.sql_data_limit_times_slimitkeep_return_n2(sql,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql,sql) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql,sql_union) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + sql_join = "select a.tbname,last(a.ts) cc from %s.meters a,%s.meters b where a.ts is not null and a.ts = b.ts partition by a.tbname interval(1a) order by cc desc slimit %d limit %d" %(dbname,dbnamejoin,num,num2) + self.sql_limit_times_slimitkeep_return_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_join = "select count(*) from (%s)" %sql_join + self.sql_data_limit_times_slimitkeep_return_n2(sql_join,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union = "(%s) union (%s)" %(sql_join,sql_join) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union,num,num2,tables,per_table_num,base_fun,replace_fun) + sql_union_all = "(%s) union all (%s)" %(sql_join,sql_union) + self.sql_data_limit_times_slimitkeep_return_n2(sql_union_all,num,num2,tables,per_table_num,base_fun,replace_fun) + + + + + + def sql_base_check(self,sql1,sql2): + tdSql.query(sql1) + sql1_result = tdSql.getData(0,0) + tdLog.info("sql:%s , result: %s" %(sql1,sql1_result)) + + tdSql.query(sql2) + sql2_result = tdSql.getData(0,0) + tdLog.info("sql:%s , result: %s" %(sql2,sql2_result)) + + if sql1_result==sql2_result: + tdLog.info(f"checkEqual success, sql1_result={sql1_result},sql2_result={sql2_result}") + else : + tdLog.exit(f"checkEqual error, sql1_result=={sql1_result},sql2_result={sql2_result}") + + def run_limit_slimit_sql(self,dbname,tables,per_table_num,dbnamejoin): + + num,num2 = random.randint(10,100),random.randint(10,100) + self.sql_base(dbname,num,num2,tables,per_table_num,dbnamejoin) + + tdSql.execute(" flush database %s;" %dbname) + + self.sql_base(dbname,num,num2,tables,per_table_num,dbnamejoin) + + def check_sub(self,dbname): + + sql = "select count(*) from (select distinct(tbname) from %s.meters)" %dbname + self.sql_query_time_cost(sql) + num = tdSql.getData(0,0) + + for i in range(0,num): + sql1 = "select count(*) from %s.d%d" %(dbname,i) + self.sql_query_time_cost(sql1) + sql1_result = tdSql.getData(0,0) + tdLog.info("sql:%s , result: %s" %(sql1,sql1_result)) + + + def sql_base(self,dbname,num,num2,tables,per_table_num,dbnamejoin): + + sql = "select count(*) from %s.meters" %dbname + self.sql_query_time_cost(sql) + tdSql.checkData(0,0,tables*per_table_num) + sql = "select count(*) from %s.meters" %dbnamejoin + self.sql_query_time_cost(sql) + + self.fun_base(dbname,num,num2,tables,per_table_num,dbnamejoin,'*','*') + # self.fun_count(dbname,num,num2,tables,per_table_num,dbnamejoin,'count','count') + # self.fun_last(dbname,num,num2,tables,per_table_num,dbnamejoin,'last','last') + # #self.fun_last(dbname,num,num2,tables,per_table_num,dbnamejoin,'last','last_row') + # self.fun_last(dbname,num,num2,tables,per_table_num,dbnamejoin,'last','first') + + def test(self,dbname,tables,per_table_num,vgroups,replica,dbnamejoin): + self.run_benchmark(dbname,tables,per_table_num,vgroups,replica) + self.run_benchmark(dbnamejoin,tables,per_table_num,vgroups,replica) + self.run_limit_slimit_sql(dbname,tables,per_table_num,dbnamejoin) + + def run(self): + startTime = time.time() + + dbname = 'test' + dbnamejoin = 'testjoin' + vgroups = random.randint(1,8) + tables = random.randint(100,300) + per_table_num = random.randint(100,500) + replica = 1 + #self.test('test',tables,per_table_num,vgroup,1) + #self.test('test',10000,150,vgroup,1) + + self.test('test',100,150,vgroups,1,'testjoin') #方便调试,调试时不执行下面3个 + + # self.run_benchmark(dbname,tables,per_table_num,vgroups,replica) + # self.run_benchmark(dbnamejoin,tables*vgroups,per_table_num*vgroups,vgroups*2,replica) #方便测试不同数据量 + # self.run_limit_slimit_sql(dbname,tables,per_table_num,dbnamejoin) + + endTime = time.time() + print("total time %ds" % (endTime - startTime)) + + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/system-test/2-query/sml.py b/tests/system-test/2-query/sml.py index 78b633cf94259058b5a50eca2de66d6b2f922d26..2f97118fbf0893a253499ab7c9ba9425bd9e9c5d 100644 --- a/tests/system-test/2-query/sml.py +++ b/tests/system-test/2-query/sml.py @@ -21,10 +21,10 @@ class TDTestCase: def init(self, conn, logSql, replicaVar=1): self.replicaVar = int(replicaVar) tdLog.debug(f"start to excute {__file__}") - tdSql.init(conn.cursor()) + tdSql.init(conn.cursor(), True) #tdSql.init(conn.cursor(), logSql) # output sql.txt file - def checkFileContent(self, dbname="sml_db"): + def checkContent(self, dbname="sml_db"): simClientCfg="%s/taos.cfg"%tdDnodes.getSimCfgPath() buildPath = tdCom.getBuildPath() cmdStr = '%s/build/bin/sml_test %s'%(buildPath, simClientCfg) @@ -34,6 +34,9 @@ class TDTestCase: if ret != 0: tdLog.info("sml_test ret != 0") + tdSql.query(f"select * from ts3303.stb2") + tdSql.query(f"select * from ts3303.meters") + # tdSql.execute('use sml_db') tdSql.query(f"select * from {dbname}.t_b7d815c9222ca64cdf2614c61de8f211") tdSql.checkRows(1) @@ -76,29 +79,33 @@ class TDTestCase: tdSql.checkData(0, 2, "web01") tdSql.query(f"select distinct tbname from {dbname}.`sys.cpu.nice`") - tdSql.checkRows(2) + tdSql.checkRows(3) tdSql.query(f"select * from {dbname}.`sys.cpu.nice` order by _ts") - tdSql.checkRows(2) - tdSql.checkData(0, 1, 9.000000000) - tdSql.checkData(0, 2, "lga") - tdSql.checkData(0, 3, "web02") - tdSql.checkData(0, 4, None) - tdSql.checkData(1, 1, 18.000000000) - tdSql.checkData(1, 2, "lga") - tdSql.checkData(1, 3, "web01") - tdSql.checkData(1, 4, "t1") + tdSql.checkRows(4) + tdSql.checkData(0, 1, 13.000000000) + tdSql.checkData(0, 2, "web01") + tdSql.checkData(0, 3, None) + tdSql.checkData(0, 4, "lga") + + tdSql.checkData(1, 1, 9.000000000) + tdSql.checkData(1, 2, "web02") + tdSql.checkData(3, 3, "t1") + tdSql.checkData(0, 4, "lga") tdSql.query(f"select * from {dbname}.macylr") tdSql.checkRows(2) + tdSql.query(f"select * from {dbname}.qelhxo") + tdSql.checkRows(5) + tdSql.query(f"desc {dbname}.macylr") tdSql.checkRows(25) return def run(self): tdSql.prepare() - self.checkFileContent() + self.checkContent() def stop(self): tdSql.close() diff --git a/tests/system-test/2-query/tagFilter.py b/tests/system-test/2-query/tagFilter.py new file mode 100644 index 0000000000000000000000000000000000000000..b03776c31b5979450d98e3166cac176093516d74 --- /dev/null +++ b/tests/system-test/2-query/tagFilter.py @@ -0,0 +1,67 @@ +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import * + + +INT_COL = "c1" +BINT_COL = "c2" +SINT_COL = "c3" +TINT_COL = "c4" +FLOAT_COL = "c5" +DOUBLE_COL = "c6" +BOOL_COL = "c7" + +BINARY_COL = "c8" +NCHAR_COL = "c9" +TS_COL = "c10" + +NUM_COL = [INT_COL, BINT_COL, SINT_COL, TINT_COL, FLOAT_COL, DOUBLE_COL, ] +UN_NUM_COL = [BOOL_COL, BINARY_COL, NCHAR_COL, ] +TS_TYPE_COL = [TS_COL] + +DBNAME = "db" + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug(f"start to excute {__file__}") + tdSql.init(conn.cursor()) + tdSql.execute(f'drop database if exists db') + tdSql.execute(f'create database if not exists db vgroups 1') + + def __create_tb(self, dbname="db"): + create_stb_sql = f'''create table {dbname}.stb1( + ts timestamp, f1 int + ) tags (tag1 binary(16300)) + ''' + tdSql.execute(create_stb_sql) + + tag_value = 'a' + for i in range(1200): + tag_value = tag_value + 'a' + + for i in range(8000): + tdSql.execute(f"create table {dbname}.ct{i+1} using {dbname}.stb1 tags ( '{tag_value}' )") + + def __query_data(self, rows, dbname="db"): + tdSql.execute( + f'''select count(*) from {dbname}.stb1 where tag1 like '%a' + ''' + ) + tdSql.checkRows(0) + + def run(self): + tdLog.printNoPrefix("==========step1:create table") + self.__create_tb() + + tdLog.printNoPrefix("==========step2:query data") + self.__query_data(10) + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/2-query/timeerror.py b/tests/system-test/2-query/timeerror.py new file mode 100644 index 0000000000000000000000000000000000000000..f43dc91de6a7c9faeeb3f86d92214f309f02c3e3 --- /dev/null +++ b/tests/system-test/2-query/timeerror.py @@ -0,0 +1,69 @@ +import taos +import sys +from time import sleep +from util.log import * +from util.sql import * +from util.cases import * + + + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug(f"start to excute {__file__}") + tdSql.init(conn.cursor()) + + def run(self): + rows = 10 + + tdSql.execute("create database dbus PRECISION 'us' ") + tdSql.execute("create database dbns PRECISION 'ns' ") + tdSql.execute("create database dbms PRECISION 'ms' ") + dball = ["dbns","dbus","dbms"] + for i in range(len(dball)): + dbname = dball[i] + stb = f"{dbname}.stb1" + if i == 0 : + qts = 1678883666951061471 + qts1 = 1678883666951061471 + + qtime = "2023-03-15 20:34:26.951061471" + elif i == 1 : + qts = 1678883666951061 + qts1 = 1678883666951061 + + qtime = "2023-03-15 20:34:26.951061" + else: + qts = 1678883666951 + qts1 = 1678883666953 + + qtime = "2023-03-15 20:34:26.951" + + tdSql.execute(f"use {dbname}") + tdLog.printNoPrefix("==========step1:create table") + tdSql.execute( + f'''create table if not exists {stb} + (ts timestamp, c1 int, c2 float, c3 bigint, c4 double, c5 smallint, c6 tinyint) + tags(location binary(64), type int, isused bool , family nchar(64))''' + ) + tdSql.execute(f"create table {dbname}.t1 using {stb} tags('beijing', 1, 1, 'nchar1')") + tdSql.execute(f"create table {dbname}.t2 using {stb} tags('shanghai', 2, 0, 'nchar2')") + tdSql.execute(f"create table {dbname}.t3 using {stb} tags('shanghai', 3, 0, 'nchar3')") + + tdLog.printNoPrefix("==========step2:insert data") + tdSql.execute( + f"insert into {dbname}.t3 values ({qts}, null , {-3.4*10**38}, null , {-1.7*10**308}, null , null)" + ) + + tdLog.printNoPrefix("==========step3:query timestamp type") + tdSql.query(f"select ts from {dbname}.t3 limit 1") + tdSql.checkData(0,0,qtime) + tdSql.checkData(0,0,qts) + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/2-query/tsbsQuery.py b/tests/system-test/2-query/tsbsQuery.py index 106d43ea388ed450766a811a525415c16954555b..0e2975cdba02fc7b5a6ffda879b56f712649b43f 100644 --- a/tests/system-test/2-query/tsbsQuery.py +++ b/tests/system-test/2-query/tsbsQuery.py @@ -86,7 +86,7 @@ class TDTestCase: self.ctbNums=ctbNums rowNUms=5000 ts=1451606400000 - tdSql.execute(f"create database {dbname};") + tdSql.execute(f"create database {dbname} cachemodel 'both';") tdSql.execute(f"use {dbname} ") tdSql.execute(f''' create table {stabname1} (ts timestamp,latitude double,longitude double,elevation double,velocity double,heading double,grade double,fuel_consumption double) tags (name binary(30),fleet binary(30),driver binary(30),model binary(30),device_version binary(30),load_capacity double,fuel_capacity double,nominal_fuel_consumption double); @@ -211,15 +211,16 @@ class TDTestCase: tdSql.query(f"select model,state_changed,count(state_changed) FROM (SELECT model,diff(broken_down) AS state_changed FROM (SELECT _wstart,model,cast(cast(floor(2*(sum(nzs)/count(nzs))) as bool) as int) AS broken_down FROM (SELECT ts,model, cast(cast(status as bool) as int) AS nzs from {dbname}.diagnostics WHERE ts >= '2016-01-01T00:00:00Z' AND ts < '2016-01-05T00:00:01Z' ) WHERE ts >= '2016-01-01T00:00:00Z' AND ts < '2016-01-05T00:00:01Z' partition BY model interval(10m)) partition BY model) where state_changed =1 partition BY model,state_changed ;") - sql=f"select model,ctc from (SELECT model,count(state_changed) as ctc FROM (SELECT model,diff(broken_down) AS state_changed FROM (SELECT model,cast(cast(floor(2*(sum(nzs)/count(nzs))) as bool) as int) AS broken_down FROM (SELECT ts,model, cast(cast(status as bool) as int) AS nzs from {dbname}.diagnostics WHERE ts >= 1451606400000 AND ts < 1451952001000 ) WHERE ts >= 1451606400000 AND ts < 1451952001000 partition BY model interval(10m)) partition BY model) WHERE state_changed = 1 partition BY model )where model is null;" - - # for i in range(2): - # tdSql.query("%s"%sql) - # quertR1=tdSql.queryResult - # for j in range(50): - # tdSql.query("%s"%sql) - # quertR2=tdSql.queryResult - # assert quertR1 == quertR2 , "%s != %s ,The results of multiple queries are different" %(quertR1,quertR2) + sql=f"SELECT model,count(state_changed) FROM (SELECT _rowts,model,diff(broken_down) AS state_changed FROM (SELECT ts,model,tb,cast(cast(floor(2*(nzs)) as bool) as int) AS broken_down FROM (SELECT _wstart as ts,model,tbname as tb, sum(cast(cast(status as bool) as int))/count(cast(cast(status as bool) as int)) AS nzs FROM {dbname}.diagnostics WHERE ts >= 1451606400000 AND ts < 1451952001000 partition BY tbname,model interval(10m))order by ts) partition BY tb,model ) WHERE state_changed = 1 partition BY model;" + tdSql.query(f"{sql}") + tdSql.checkRows(46) + for i in range(2): + tdSql.query("%s"%sql) + quertR1=tdSql.queryResult + for j in range(50): + tdSql.query("%s"%sql) + quertR2=tdSql.queryResult + assert quertR1 == quertR2 , "%s != %s ,The results of multiple queries are different" %(quertR1,quertR2) #it's already supported: diff --git a/tests/system-test/6-cluster/5dnode1mnode.py b/tests/system-test/6-cluster/5dnode1mnode.py index d0157ec7c772182a2e24064dfec3cc29ed2a7ed6..61451f03b1927352f9d0a227925f33227458c12f 100644 --- a/tests/system-test/6-cluster/5dnode1mnode.py +++ b/tests/system-test/6-cluster/5dnode1mnode.py @@ -18,7 +18,10 @@ class MyDnodes(TDDnodes): def __init__(self ,dnodes_lists): super(MyDnodes,self).__init__() self.dnodes = dnodes_lists # dnode must be TDDnode instance - self.simDeployed = False + if platform.system().lower() == 'windows': + self.simDeployed = True + else: + self.simDeployed = False class TDTestCase: noConn = True @@ -29,7 +32,7 @@ class TDTestCase: self.master_dnode = self.TDDnodes.dnodes[0] self.host=self.master_dnode.cfgDict["fqdn"] conn1 = taos.connect(self.master_dnode.cfgDict["fqdn"] , config=self.master_dnode.cfgDir) - tdSql.init(conn1.cursor()) + tdSql.init(conn1.cursor(), True) def getBuildPath(self): @@ -137,11 +140,34 @@ class TDTestCase: config_dir = dnode.cfgDir return taos.connect(host=host, port=int(port), config=config_dir) + def check_alive(self): + # check cluster alive + tdLog.printNoPrefix("======== test cluster alive: ") + tdSql.checkDataLoop(0, 0, 1, "show cluster alive;", 20, 0.5) + + tdSql.query("show db.alive;") + tdSql.checkData(0, 0, 1) + + # stop 3 dnode + self.TDDnodes.stoptaosd(3) + tdSql.checkDataLoop(0, 0, 2, "show cluster alive;", 20, 0.5) + + tdSql.query("show db.alive;") + tdSql.checkData(0, 0, 2) + + # stop 2 dnode + self.TDDnodes.stoptaosd(2) + tdSql.checkDataLoop(0, 0, 0, "show cluster alive;", 20, 0.5) + + tdSql.query("show db.alive;") + tdSql.checkData(0, 0, 0) + def run(self): # print(self.master_dnode.cfgDict) self.five_dnode_one_mnode() - + # check cluster and db alive + self.check_alive() def stop(self): tdSql.close() diff --git a/tests/system-test/6-cluster/5dnode3mnodeDrop.py b/tests/system-test/6-cluster/5dnode3mnodeDrop.py index 9dd3c568054948d7062c2f87f145149509b1b575..c4b30a16f71ba1331fd3f146aa3245375326588e 100644 --- a/tests/system-test/6-cluster/5dnode3mnodeDrop.py +++ b/tests/system-test/6-cluster/5dnode3mnodeDrop.py @@ -19,7 +19,10 @@ class MyDnodes(TDDnodes): def __init__(self ,dnodes_lists): super(MyDnodes,self).__init__() self.dnodes = dnodes_lists # dnode must be TDDnode instance - self.simDeployed = False + if platform.system().lower() == 'windows': + self.simDeployed = True + else: + self.simDeployed = False class TDTestCase: @@ -111,6 +114,8 @@ class TDTestCase: dnode_first_host = dnode.cfgDict["firstEp"].split(":")[0] dnode_first_port = dnode.cfgDict["firstEp"].split(":")[-1] cmd = f" taos -h {dnode_first_host} -P {dnode_first_port} -s ' create dnode \"{dnode_id} \" ' ;" + if platform.system().lower() == 'windows': + cmd = f" taos -h {dnode_first_host} -P {dnode_first_port} -s \"create dnode \\\"{dnode_id}\\\"" tdLog.debug(cmd) if os.system(cmd) != 0: raise Exception("failed to execute system command. cmd: %s" % cmd) diff --git a/tests/system-test/6-cluster/5dnode3mnodeRestartDnodeInsertData.py b/tests/system-test/6-cluster/5dnode3mnodeRestartDnodeInsertData.py index 94e02b77b307281975ff7393298f182f233a7c65..392b0d7764c4404a4e2282b7bf5708a79556acf8 100644 --- a/tests/system-test/6-cluster/5dnode3mnodeRestartDnodeInsertData.py +++ b/tests/system-test/6-cluster/5dnode3mnodeRestartDnodeInsertData.py @@ -161,6 +161,19 @@ class TDTestCase: stableName= '%s_%d'%(paraDict['stbName'],i) newTdSql=tdCom.newTdSql() threads.append(threading.Thread(target=clusterComCreate.insert_data, args=(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]))) + + for i in range(5): + clusterComCreate.createUser(newTdSql,f"user{i}",f"pass{i}") + userTdSql=tdCom.newTdSql(user=f"user{i}",password=f"pass{i}") + clusterComCreate.alterUser(userTdSql,f"user{i}",f"pass{i+1}") + clusterComCreate.deleteUser(newTdSql,f"user{i}") + for j in range(5): + i=100 + clusterComCreate.createUser(newTdSql,f"user{i}",f"pass{i}") + userTdSql=tdCom.newTdSql(user=f"user{i}",password=f"pass{i}") + clusterComCreate.alterUser(userTdSql,f"user{i}",f"pass{i+1}") + clusterComCreate.deleteUser(newTdSql,f"user{i}") + for tr in threads: tr.start() for tr in threads: diff --git a/tests/system-test/6-cluster/5dnode3mnodeRestartDnodeInsertDataAsync.py b/tests/system-test/6-cluster/5dnode3mnodeRestartDnodeInsertDataAsync.py index d6d06446a1ab60c0dabdf0a676f7067a3497c799..04c69ad6188a657cd37651a01d417d790a9830af 100644 --- a/tests/system-test/6-cluster/5dnode3mnodeRestartDnodeInsertDataAsync.py +++ b/tests/system-test/6-cluster/5dnode3mnodeRestartDnodeInsertDataAsync.py @@ -67,29 +67,11 @@ class TDTestCase: self._async_raise(thread.ident, SystemExit) - def insertData(self,countstart,countstop): - # fisrt add data : db\stable\childtable\general table - - for couti in range(countstart,countstop): - tdLog.debug("drop database if exists db%d" %couti) - tdSql.execute("drop database if exists db%d" %couti) - print("create database if not exists db%d replica 1 duration 300" %couti) - tdSql.execute("create database if not exists db%d replica 1 duration 300" %couti) - tdSql.execute("use db%d" %couti) - tdSql.execute( - '''create table stb1 - (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) - tags (t1 int) - ''' - ) - tdSql.execute( - ''' - create table t1 - (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) - ''' - ) - for i in range(4): - tdSql.execute(f'create table ct{i+1} using stb1 tags ( {i+1} )') + def reCreateUser(self, tdsql, count, user, passwd): + clusterComCreate.createUser(tdsql,f"{user}{count}",f"{passwd}{count}") + userTdSql=tdCom.newTdSql(user=f"{user}{count}",password=f"{passwd}{count}") + clusterComCreate.alterUser(userTdSql,f"{user}{count}",f"{passwd}{count+1}") + clusterComCreate.deleteUser(tdsql,f"{user}{count}") def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): @@ -161,6 +143,9 @@ class TDTestCase: stableName= '%s_%d'%(paraDict['stbName'],i) newTdSql=tdCom.newTdSql() threads.append(threading.Thread(target=clusterComCreate.insert_data, args=(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]))) + createTdSql=tdCom.newTdSql() + threads.append(threading.Thread(target=self.reCreateUser,args=(createTdSql,i,"user","passwd"))) + for tr in threads: tr.start() diff --git a/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateDb.py b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateDb.py index 881f383b8c07b66987290e07cda6eda99d01dce5..b55c689eee88ef6f4f19893f6d6bf18a91d6acc4 100644 --- a/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateDb.py +++ b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateDb.py @@ -147,6 +147,9 @@ class TDTestCase: # print(f"==================={dbNameIndex},{a11111}") threads.append(threading.Thread(target=clusterComCreate.createDeltedatabases, args=(newTdSql, dbNameIndex,repeatNumber,paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']))) + redbNameIndex = '%s%d'%(paraDict["dbName"],i+100) + threads.append(threading.Thread(target=clusterComCreate.createDeltedatabases, args=(newTdSql, redbNameIndex,1,paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']))) + for tr in threads: tr.start() @@ -199,7 +202,7 @@ class TDTestCase: def run(self): # print(self.master_dnode.cfgDict) - self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=4,stopRole='dnode') + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=1,stopRole='dnode') def stop(self): tdSql.close() diff --git a/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeInsertData.py b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeInsertData.py index 265000bdc9d0c5530fdcbd7d4e6ed633c58b0a29..296e9daecaf16d3ef4016bafa7454ff0c7d62af9 100644 --- a/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeInsertData.py +++ b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeInsertData.py @@ -97,7 +97,7 @@ class TDTestCase: 'dropFlag': 1, 'event': '', 'vgroups': 4, - 'replica': 1, + 'replica': 3, 'stbName': 'stb', 'stbNumbers': 2, 'colPrefix': 'c', @@ -105,9 +105,9 @@ class TDTestCase: 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], 'ctbPrefix': 'ctb', - 'ctbNum': 200, + 'ctbNum': 100, 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 - "rowsPerTbl": 10000, + "rowsPerTbl": 100000, "batchNum": 5000 } @@ -198,16 +198,16 @@ class TDTestCase: clusterComCheck.checkDbRows(dbNumbers) # clusterComCheck.checkDb(dbNumbers,1,paraDict["dbName"]) - tdSql.execute("use %s" %(paraDict["dbName"])) - tdSql.query("show stables") + # tdSql.execute("use %s" %(paraDict["dbName"])) + tdSql.query("show %s.stables"%(paraDict["dbName"])) tdSql.checkRows(paraDict["stbNumbers"]) for i in range(paraDict['stbNumbers']): - stableName= '%s_%d'%(paraDict['stbName'],i) - tdSql.query("select * from %s"%stableName) - tdSql.checkRows(rowsPerStb) + stableName= '%s.%s_%d'%(paraDict["dbName"],paraDict['stbName'],i) + tdSql.query("select count(*) from %s"%stableName) + tdSql.checkData(0,0,rowsPerStb) def run(self): # print(self.master_dnode.cfgDict) - self.fiveDnodeThreeMnode(dnodeNumbers=5,mnodeNums=3,restartNumbers=2,stopRole='dnode') + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=1,stopRole='dnode') def stop(self): tdSql.close() diff --git a/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeModifyMeta.py b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeModifyMeta.py new file mode 100644 index 0000000000000000000000000000000000000000..06d626b77cc8d9e67f1ecbe2fc524a1d9a69decc --- /dev/null +++ b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeModifyMeta.py @@ -0,0 +1,202 @@ +from ssl import ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE +from numpy import row_stack +import taos +import sys +import time +import os + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import TDDnodes +from util.dnodes import TDDnode +from util.cluster import * +sys.path.append("./6-cluster") +from clusterCommonCreate import * +from clusterCommonCheck import clusterComCheck + +import time +import socket +import subprocess +from multiprocessing import Process +import threading +import time +import inspect +import ctypes + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + tdSql.init(conn.cursor()) + self.host = socket.gethostname() + + + 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 _async_raise(self, tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + exctype = type(exctype) + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) + if res == 0: + raise ValueError("invalid thread id") + elif res != 1: + # """if it returns a number greater than one, you're in trouble, + # and you should call it again with exc=NULL to revert the effect""" + ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + def stopThread(self,thread): + self._async_raise(thread.ident, SystemExit) + + + def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'db0_0', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'replica': 3, + 'stbName': 'stb', + 'stbNumbers': 2, + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 200, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + "rowsPerTbl": 1000, + "batchNum": 5000 + } + + dnodeNumbers=int(dnodeNumbers) + mnodeNums=int(mnodeNums) + vnodeNumbers = int(dnodeNumbers-mnodeNums) + allctbNumbers=(paraDict['stbNumbers']*paraDict["ctbNum"]) + rowsPerStb=paraDict["ctbNum"]*paraDict["rowsPerTbl"] + rowsall=rowsPerStb*paraDict['stbNumbers'] + dbNumbers = 1 + + tdLog.info("first check dnode and mnode") + tdSql.query("select * from information_schema.ins_dnodes;") + tdSql.checkData(0,1,'%s:6030'%self.host) + tdSql.checkData(4,1,'%s:6430'%self.host) + clusterComCheck.checkDnodes(dnodeNumbers) + + #check mnode status + tdLog.info("check mnode status") + clusterComCheck.checkMnodeStatus(mnodeNums) + + # add some error operations and + tdLog.info("Confirm the status of the dnode again") + tdSql.error("create mnode on dnode 2") + tdSql.query("select * from information_schema.ins_dnodes;") + print(tdSql.queryResult) + clusterComCheck.checkDnodes(dnodeNumbers) + + # create database and stable + clusterComCreate.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']) + tdLog.info("Take turns stopping Mnodes ") + + tdDnodes=cluster.dnodes + stopcount =0 + threads=[] + + # create stable:stb_0 + stableName= paraDict['stbName'] + newTdSql=tdCom.newTdSql() + clusterComCreate.create_stables(newTdSql, paraDict["dbName"],stableName,paraDict['stbNumbers']) + #create child table:ctb_0 + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + clusterComCreate.create_ctable(newTdSql, paraDict["dbName"],stableName,stableName, paraDict['ctbNum']) + #insert date + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + threads.append(threading.Thread(target=clusterComCreate.insert_data, args=(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]))) + for tr in threads: + tr.start() + for tr in threads: + tr.join() + + while stopcount < restartNumbers: + tdLog.info(" restart loop: %d"%stopcount ) + if stopRole == "mnode": + for i in range(mnodeNums): + tdDnodes[i].stoptaosd() + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + elif stopRole == "vnode": + for i in range(vnodeNumbers): + tdDnodes[i+mnodeNums].stoptaosd() + # sleep(10) + tdDnodes[i+mnodeNums].starttaosd() + # sleep(10) + elif stopRole == "dnode": + for i in range(dnodeNumbers): + tdDnodes[i].stoptaosd() + clusterComCheck.checkDbRows(dbNumbers) + if i == 0 : + stableName= '%s_%d'%(paraDict['stbName'],0) + newTdSql=tdCom.newTdSql() + clusterComCreate.alterStbMetaData(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"]) + # sleep(10) + tdDnodes[i].starttaosd() + + + # dnodeNumbers don't include database of schema + if clusterComCheck.checkDnodes(dnodeNumbers): + tdLog.info("123") + else: + print("456") + + self.stopThread(threads) + tdLog.exit("one or more of dnodes failed to start ") + # self.check3mnode() + stopcount+=1 + + + clusterComCheck.checkDnodes(dnodeNumbers) + clusterComCheck.checkDbRows(dbNumbers) + # clusterComCheck.checkDb(dbNumbers,1,paraDict["dbName"]) + + # tdSql.execute("use %s" %(paraDict["dbName"])) + tdSql.query("show %s.stables"%(paraDict["dbName"])) + tdSql.checkRows(paraDict["stbNumbers"]) + for i in range(paraDict['stbNumbers']): + stableName= '%s.%s_%d'%(paraDict["dbName"],paraDict['stbName'],i) + tdSql.query("select count(*) from %s"%stableName) + if i == 0 : + tdSql.checkData(0,0,rowsPerStb*2) + else: + tdSql.checkData(0,0,rowsPerStb) + def run(self): + # print(self.master_dnode.cfgDict) + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=1,stopRole='dnode') + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeRCreateDb.py b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeRCreateDb.py new file mode 100644 index 0000000000000000000000000000000000000000..9d99980b88081607d825f8f9198bb3d0487906df --- /dev/null +++ b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopDnodeRCreateDb.py @@ -0,0 +1,209 @@ +from ssl import ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE +import taos +import sys +import time +import os + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import TDDnodes +from util.dnodes import TDDnode +from util.cluster import * +sys.path.append("./6-cluster") +from clusterCommonCreate import * +from clusterCommonCheck import clusterComCheck + +import time +import socket +import subprocess +from multiprocessing import Process +import threading +import time +import inspect +import ctypes + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + tdSql.init(conn.cursor()) + self.host = socket.gethostname() + self.replicaVar=int(replicaVar) + + 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 _async_raise(self, tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + exctype = type(exctype) + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) + if res == 0: + raise ValueError("invalid thread id") + elif res != 1: + # """if it returns a number greater than one, you're in trouble, + # and you should call it again with exc=NULL to revert the effect""" + ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + def stopThread(self,thread): + self._async_raise(thread.ident, SystemExit) + + + def insertData(self,countstart,countstop): + # fisrt add data : db\stable\childtable\general table + + for couti in range(countstart,countstop): + tdLog.debug("drop database if exists db%d" %couti) + tdSql.execute("drop database if exists db%d" %couti) + print("create database if not exists db%d replica 1 duration 300" %couti) + tdSql.execute("create database if not exists db%d replica 1 duration 300" %couti) + tdSql.execute("use db%d" %couti) + tdSql.execute( + '''create table stb1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + tags (t1 int) + ''' + ) + tdSql.execute( + ''' + create table t1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + ''' + ) + for i in range(4): + tdSql.execute(f'create table ct{i+1} using stb1 tags ( {i+1} )') + + + def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'db', + 'dbNumbers': 4, + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'replica': 3, + 'stbName': 'stb', + 'stbNumbers': 100, + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 1, + } + + dnodeNumbers=int(dnodeNumbers) + dbNumbers=paraDict['dbNumbers'] + mnodeNums=int(mnodeNums) + repeatNumber = 2 + vnodeNumbers = int(dnodeNumbers-mnodeNums) + allDbNumbers=dbNumbers + allStbNumbers=(paraDict['stbNumbers']*restartNumbers) + paraDict['replica'] = self.replicaVar + + tdLog.info("first check dnode and mnode") + tdSql.query("select * from information_schema.ins_dnodes;") + tdSql.checkData(0,1,'%s:6030'%self.host) + tdSql.checkData(4,1,'%s:6430'%self.host) + clusterComCheck.checkDnodes(dnodeNumbers) + + #check mnode status + tdLog.info("check mnode status") + clusterComCheck.checkMnodeStatus(mnodeNums) + + # add some error operations and + tdLog.info("Confirm the status of the dnode again") + tdSql.error("create mnode on dnode 2") + tdSql.query("select * from information_schema.ins_dnodes;") + print(tdSql.queryResult) + clusterComCheck.checkDnodes(dnodeNumbers) + + # create database and stable + + + tdDnodes=cluster.dnodes + stopcount =0 + threads=[] + for i in range(dbNumbers): + dbNameIndex = '%s%d'%(paraDict["dbName"],0) + newTdSql=tdCom.newTdSql() + # a11111=paraDict["dbNumbers"] + # print(f"==================={dbNameIndex},{a11111}") + clusterComCreate.createDeltedatabases(newTdSql, dbNameIndex,repeatNumber,paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']) + + redbNameIndex = '%s%d'%(paraDict["dbName"],100) + clusterComCreate.createDeltedatabases(newTdSql, redbNameIndex,1,paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']) + + + tdLog.info("Take turns stopping Mnodes ") + while stopcount < restartNumbers: + tdLog.info(" restart loop: %d"%stopcount ) + if stopRole == "mnode": + for i in range(mnodeNums): + tdDnodes[i].stoptaosd() + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + elif stopRole == "vnode": + for i in range(vnodeNumbers): + tdDnodes[i+mnodeNums].stoptaosd() + # sleep(10) + tdDnodes[i+mnodeNums].starttaosd() + # sleep(10) + elif stopRole == "dnode": + for i in range(dnodeNumbers): + tdDnodes[i].stoptaosd() + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + + # dnodeNumbers don't include database of schema + if clusterComCheck.checkDnodes(dnodeNumbers): + tdLog.info("check dnodes status is ready") + else: + tdLog.info("check dnodes status is not ready") + self.stopThread(threads) + tdLog.exit("one or more of dnodes failed to start ") + # self.check3mnode() + stopcount+=1 + + + tdLog.info("check dnode number:") + clusterComCheck.checkDnodes(dnodeNumbers) + tdSql.query("select * from information_schema.ins_databases") + tdLog.debug("we find %d databases but exepect to create %d databases "%(tdSql.queryRows-2,allDbNumbers)) + + # tdLog.info("check DB Rows:") + # clusterComCheck.checkDbRows(allDbNumbers) + # tdLog.info("check DB Status on by on") + # for i in range(restartNumbers): + # clusterComCheck.checkDb(paraDict['dbNumbers'],restartNumbers,dbNameIndex = '%s%d'%(paraDict["dbName"],i)) + + + + def run(self): + # print(self.master_dnode.cfgDict) + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=2,stopRole='dnode') + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopMnodeModifyMeta.py b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopMnodeModifyMeta.py new file mode 100644 index 0000000000000000000000000000000000000000..3e4dc2483f2222fe9f5cd04c2e4dc529d1e83c7d --- /dev/null +++ b/tests/system-test/6-cluster/5dnode3mnodeSep1VnodeStopMnodeModifyMeta.py @@ -0,0 +1,207 @@ +from ssl import ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE +from numpy import row_stack +import taos +import sys +import time +import os + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import TDDnodes +from util.dnodes import TDDnode +from util.cluster import * +sys.path.append("./6-cluster") +from clusterCommonCreate import * +from clusterCommonCheck import clusterComCheck + +import time +import socket +import subprocess +from multiprocessing import Process +import threading +import time +import inspect +import ctypes + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + tdSql.init(conn.cursor()) + self.host = socket.gethostname() + + + 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 _async_raise(self, tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + exctype = type(exctype) + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) + if res == 0: + raise ValueError("invalid thread id") + elif res != 1: + # """if it returns a number greater than one, you're in trouble, + # and you should call it again with exc=NULL to revert the effect""" + ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + def stopThread(self,thread): + self._async_raise(thread.ident, SystemExit) + + + def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'db0_0', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'replica': 3, + 'stbName': 'stb', + 'stbNumbers': 2, + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 200, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + "rowsPerTbl": 1000, + "batchNum": 5000 + } + + dnodeNumbers=int(dnodeNumbers) + mnodeNums=int(mnodeNums) + vnodeNumbers = int(dnodeNumbers-mnodeNums) + allctbNumbers=(paraDict['stbNumbers']*paraDict["ctbNum"]) + rowsPerStb=paraDict["ctbNum"]*paraDict["rowsPerTbl"] + rowsall=rowsPerStb*paraDict['stbNumbers'] + dbNumbers = 1 + + tdLog.info("first check dnode and mnode") + tdSql.query("select * from information_schema.ins_dnodes;") + tdSql.checkData(0,1,'%s:6030'%self.host) + tdSql.checkData(4,1,'%s:6430'%self.host) + clusterComCheck.checkDnodes(dnodeNumbers) + + #check mnode status + tdLog.info("check mnode status") + clusterComCheck.checkMnodeStatus(mnodeNums) + + # add some error operations and + tdLog.info("Confirm the status of the dnode again") + tdSql.error("create mnode on dnode 2") + tdSql.query("select * from information_schema.ins_dnodes;") + print(tdSql.queryResult) + clusterComCheck.checkDnodes(dnodeNumbers) + + # create database and stable + clusterComCreate.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']) + tdLog.info("Take turns stopping Mnodes ") + + tdDnodes=cluster.dnodes + stopcount =0 + threads=[] + + # create stable:stb_0 + stableName= paraDict['stbName'] + newTdSql=tdCom.newTdSql() + clusterComCreate.create_stables(newTdSql, paraDict["dbName"],stableName,paraDict['stbNumbers']) + #create child table:ctb_0 + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + clusterComCreate.create_ctable(newTdSql, paraDict["dbName"],stableName,stableName, paraDict['ctbNum']) + #insert date + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + threads.append(threading.Thread(target=clusterComCreate.insert_data, args=(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]))) + for tr in threads: + tr.start() + for tr in threads: + tr.join() + + while stopcount < restartNumbers: + tdLog.info(" restart loop: %d"%stopcount ) + if stopRole == "mnode": + for i in range(mnodeNums): + tdDnodes[i].stoptaosd() + if i == 0 : + stableName= '%s_%d'%(paraDict['stbName'],0) + newTdSql=tdCom.newTdSql() + clusterComCreate.alterStbMetaData(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"]) + elif i == 1 : + tdSql.execute("ALTER TABLE db0_0.stb_0_0 SET TAG t1r=10000;") + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + elif stopRole == "vnode": + for i in range(vnodeNumbers): + tdDnodes[i+mnodeNums].stoptaosd() + # sleep(10) + tdDnodes[i+mnodeNums].starttaosd() + # sleep(10) + elif stopRole == "dnode": + for i in range(dnodeNumbers): + tdDnodes[i].stoptaosd() + clusterComCheck.checkDbRows(dbNumbers) + + # sleep(10) + tdDnodes[i].starttaosd() + + + # dnodeNumbers don't include database of schema + if clusterComCheck.checkDnodes(dnodeNumbers): + tdLog.info("123") + else: + print("456") + + self.stopThread(threads) + tdLog.exit("one or more of dnodes failed to start ") + # self.check3mnode() + stopcount+=1 + + + clusterComCheck.checkDnodes(dnodeNumbers) + clusterComCheck.checkDbRows(dbNumbers) + # clusterComCheck.checkDb(dbNumbers,1,paraDict["dbName"]) + + # tdSql.execute("use %s" %(paraDict["dbName"])) + tdSql.query("select t1r from db0_0.stb_0_0 limit 1;") + tdSql.checkData(0,0,10000) + tdSql.query("show %s.stables"%(paraDict["dbName"])) + tdSql.checkRows(paraDict["stbNumbers"]) + for i in range(paraDict['stbNumbers']): + stableName= '%s.%s_%d'%(paraDict["dbName"],paraDict['stbName'],i) + tdSql.query("select count(*) from %s"%stableName) + if i == 0 : + tdSql.checkData(0,0,rowsPerStb*2) + else: + tdSql.checkData(0,0,rowsPerStb) + def run(self): + # print(self.master_dnode.cfgDict) + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=1,stopRole='mnode') + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/6-cluster/5dnode3mnodeSepVnodeStopDnodeCreateUser.py b/tests/system-test/6-cluster/5dnode3mnodeSepVnodeStopDnodeCreateUser.py new file mode 100644 index 0000000000000000000000000000000000000000..94e02b77b307281975ff7393298f182f233a7c65 --- /dev/null +++ b/tests/system-test/6-cluster/5dnode3mnodeSepVnodeStopDnodeCreateUser.py @@ -0,0 +1,224 @@ +from ssl import ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE +from numpy import row_stack +import taos +import sys +import time +import os + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import TDDnodes +from util.dnodes import TDDnode +from util.cluster import * +sys.path.append("./6-cluster") +from clusterCommonCreate import * +from clusterCommonCheck import clusterComCheck + +import time +import socket +import subprocess +from multiprocessing import Process +import threading +import time +import inspect +import ctypes + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + tdSql.init(conn.cursor()) + self.host = socket.gethostname() + self.replicaVar = int(replicaVar) + + + 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 _async_raise(self, tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + exctype = type(exctype) + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) + if res == 0: + raise ValueError("invalid thread id") + elif res != 1: + # """if it returns a number greater than one, you're in trouble, + # and you should call it again with exc=NULL to revert the effect""" + ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + def stopThread(self,thread): + self._async_raise(thread.ident, SystemExit) + + + def insertData(self,countstart,countstop): + # fisrt add data : db\stable\childtable\general table + + for couti in range(countstart,countstop): + tdLog.debug("drop database if exists db%d" %couti) + tdSql.execute("drop database if exists db%d" %couti) + print("create database if not exists db%d replica 1 duration 300" %couti) + tdSql.execute("create database if not exists db%d replica 1 duration 300" %couti) + tdSql.execute("use db%d" %couti) + tdSql.execute( + '''create table stb1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + tags (t1 int) + ''' + ) + tdSql.execute( + ''' + create table t1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + ''' + ) + for i in range(4): + tdSql.execute(f'create table ct{i+1} using stb1 tags ( {i+1} )') + + + def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'db0_0', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'replica': 1, + 'stbName': 'stb', + 'stbNumbers': 2, + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 200, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + "rowsPerTbl": 100, + "batchNum": 5000 + } + + dnodeNumbers=int(dnodeNumbers) + mnodeNums=int(mnodeNums) + vnodeNumbers = int(dnodeNumbers-mnodeNums) + allctbNumbers=(paraDict['stbNumbers']*paraDict["ctbNum"]) + rowsPerStb=paraDict["ctbNum"]*paraDict["rowsPerTbl"] + rowsall=rowsPerStb*paraDict['stbNumbers'] + dbNumbers = 1 + paraDict['replica'] = self.replicaVar + + tdLog.info("first check dnode and mnode") + tdSql.query("select * from information_schema.ins_dnodes;") + tdSql.checkData(0,1,'%s:6030'%self.host) + tdSql.checkData(4,1,'%s:6430'%self.host) + clusterComCheck.checkDnodes(dnodeNumbers) + + #check mnode status + tdLog.info("check mnode status") + clusterComCheck.checkMnodeStatus(mnodeNums) + + + # add some error operations and + tdLog.info("Confirm the status of the dnode again") + tdSql.error("create mnode on dnode 2") + tdSql.query("select * from information_schema.ins_dnodes;") + print(tdSql.queryResult) + clusterComCheck.checkDnodes(dnodeNumbers) + + # create database and stable + clusterComCreate.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']) + tdLog.info("Take turns stopping Mnodes ") + + tdDnodes=cluster.dnodes + stopcount =0 + threads=[] + + # create stable:stb_0 + stableName= paraDict['stbName'] + newTdSql=tdCom.newTdSql() + clusterComCreate.create_stables(newTdSql, paraDict["dbName"],stableName,paraDict['stbNumbers']) + #create child table:ctb_0 + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + clusterComCreate.create_ctable(newTdSql, paraDict["dbName"],stableName,stableName, paraDict['ctbNum']) + #insert data + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + threads.append(threading.Thread(target=clusterComCreate.insert_data, args=(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]))) + for tr in threads: + tr.start() + for tr in threads: + tr.join() + + while stopcount < restartNumbers: + tdLog.info(" restart loop: %d"%stopcount ) + if stopRole == "mnode": + for i in range(mnodeNums): + tdDnodes[i].stoptaosd() + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + elif stopRole == "vnode": + for i in range(vnodeNumbers): + tdDnodes[i+mnodeNums].stoptaosd() + # sleep(10) + tdDnodes[i+mnodeNums].starttaosd() + # sleep(10) + elif stopRole == "dnode": + for i in range(dnodeNumbers): + tdDnodes[i].stoptaosd() + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + + # dnodeNumbers don't include database of schema + if clusterComCheck.checkDnodes(dnodeNumbers): + tdLog.info("dnode is ready") + else: + print("dnodes is not ready") + self.stopThread(threads) + tdLog.exit("one or more of dnodes failed to start ") + # self.check3mnode() + stopcount+=1 + + + clusterComCheck.checkDnodes(dnodeNumbers) + clusterComCheck.checkDbRows(dbNumbers) + # clusterComCheck.checkDb(dbNumbers,1,paraDict["dbName"]) + + newTdSql=tdCom.newTdSql() + newTdSql.execute("reset query cache") + newTdSql.execute("use %s" %(paraDict["dbName"])) + newTdSql.query("show %s.stables"%(paraDict["dbName"])) + newTdSql.checkRows(paraDict["stbNumbers"]) + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql.query("select * from %s"%stableName) + newTdSql.checkRows(rowsPerStb) + + def run(self): + # print(self.master_dnode.cfgDict) + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=2,stopRole='dnode') + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/6-cluster/5dnode3mnodeSeperate1VnodeStopInsert.py b/tests/system-test/6-cluster/5dnode3mnodeSeperate1VnodeStopInsert.py deleted file mode 100644 index a34895ff42c94e5b4b201b0edbaf2d782eee3f60..0000000000000000000000000000000000000000 --- a/tests/system-test/6-cluster/5dnode3mnodeSeperate1VnodeStopInsert.py +++ /dev/null @@ -1,324 +0,0 @@ -from ssl import ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE -import taos -import sys -import time -import os - -from util.log import * -from util.sql import * -from util.cases import * -from util.dnodes import TDDnodes -from util.dnodes import TDDnode -from util.cluster import * -from util.common import * -sys.path.append("./7-tmq") -from tmqCommon import * - -import time -import socket -import subprocess -from multiprocessing import Process -import threading -import time -import inspect -import ctypes - -class TDTestCase: - - def init(self, conn, logSql, replicaVar=1): - tdLog.debug(f"start to excute {__file__}") - # tdSql.init(conn.cursor()) - # self.host = socket.gethostname() - - 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 _async_raise(self, tid, exctype): - """raises the exception, performs cleanup if needed""" - if not inspect.isclass(exctype): - exctype = type(exctype) - res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) - if res == 0: - raise ValueError("invalid thread id") - elif res != 1: - # """if it returns a number greater than one, you're in trouble, - # and you should call it again with exc=NULL to revert the effect""" - ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) - raise SystemError("PyThreadState_SetAsyncExc failed") - - def stop_thread(self,thread): - self._async_raise(thread.ident, SystemExit) - - - def insert_data(self,countstart,countstop): - # fisrt add data : db\stable\childtable\general table - - for couti in range(countstart,countstop): - tdLog.debug("drop database if exists db%d" %couti) - tdSql.execute("drop database if exists db%d" %couti) - print("create database if not exists db%d replica 1 duration 300" %couti) - tdSql.execute("create database if not exists db%d replica 1 duration 300" %couti) - tdSql.execute("use db%d" %couti) - tdSql.execute( - '''create table stb1 - (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) - tags (t1 int) - ''' - ) - tdSql.execute( - ''' - create table t1 - (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) - ''' - ) - for i in range(4): - tdSql.execute(f'create table ct{i+1} using stb1 tags ( {i+1} )') - - def checkData(self,dbname,stbname,stableCount,CtableCount,rowsPerSTable,): - tdSql.execute("use %s"%dbname) - tdSql.query("show stables") - tdSql.checkRows(stableCount) - tdSql.query("show tables") - tdSql.checkRows(CtableCount) - for i in range(stableCount): - tdSql.query("select count(*) from %s%d"%(stbname,i)) - tdSql.checkData(0,0,rowsPerSTable) - return - - def checkdnodes(self,dnodenumber): - count=0 - while count < 100: - time.sleep(1) - statusReadyBumber=0 - tdSql.query("select * from information_schema.ins_dnodes;") - if tdSql.checkRows(dnodenumber) : - print("dnode is %d nodes"%dnodenumber) - for i in range(dnodenumber): - if tdSql.queryResult[i][4] !='ready' : - status=tdSql.queryResult[i][4] - print("dnode:%d status is %s "%(i,status)) - break - else: - statusReadyBumber+=1 - print(statusReadyBumber) - if statusReadyBumber == dnodenumber : - print("all of %d mnodes is ready in 10s "%dnodenumber) - return True - break - count+=1 - else: - print("%d mnodes is not ready in 10s "%dnodenumber) - return False - - - def check3mnode(self): - count=0 - while count < 10: - time.sleep(1) - tdSql.query("select * from information_schema.ins_mnodes;") - if tdSql.checkRows(3) : - print("mnode is three nodes") - if tdSql.queryResult[0][2]=='leader' : - if tdSql.queryResult[1][2]=='follower': - if tdSql.queryResult[2][2]=='follower': - print("three mnodes is ready in 10s") - break - elif tdSql.queryResult[0][2]=='follower' : - if tdSql.queryResult[1][2]=='leader': - if tdSql.queryResult[2][2]=='follower': - print("three mnodes is ready in 10s") - break - elif tdSql.queryResult[0][2]=='follower' : - if tdSql.queryResult[1][2]=='follower': - if tdSql.queryResult[2][2]=='leader': - print("three mnodes is ready in 10s") - break - count+=1 - else: - print("three mnodes is not ready in 10s ") - return -1 - - tdSql.query("select * from information_schema.ins_mnodes;") - tdSql.checkRows(3) - tdSql.checkData(0,1,'%s:6030'%self.host) - tdSql.checkData(0,3,'ready') - tdSql.checkData(1,1,'%s:6130'%self.host) - tdSql.checkData(1,3,'ready') - tdSql.checkData(2,1,'%s:6230'%self.host) - tdSql.checkData(2,3,'ready') - - def check3mnode1off(self): - count=0 - while count < 10: - time.sleep(1) - tdSql.query("select * from information_schema.ins_mnodes;") - if tdSql.checkRows(3) : - print("mnode is three nodes") - if tdSql.queryResult[0][2]=='offline' : - if tdSql.queryResult[1][2]=='leader': - if tdSql.queryResult[2][2]=='follower': - print("stop mnodes on dnode 2 successfully in 10s") - break - elif tdSql.queryResult[1][2]=='follower': - if tdSql.queryResult[2][2]=='leader': - print("stop mnodes on dnode 2 successfully in 10s") - break - count+=1 - else: - print("stop mnodes on dnode 2 failed in 10s ") - return -1 - tdSql.error("drop mnode on dnode 1;") - - tdSql.query("select * from information_schema.ins_mnodes;") - tdSql.checkRows(3) - tdSql.checkData(0,1,'%s:6030'%self.host) - tdSql.checkData(0,2,'offline') - tdSql.checkData(0,3,'ready') - tdSql.checkData(1,1,'%s:6130'%self.host) - tdSql.checkData(1,3,'ready') - tdSql.checkData(2,1,'%s:6230'%self.host) - tdSql.checkData(2,3,'ready') - - def check3mnode2off(self): - count=0 - while count < 40: - time.sleep(1) - tdSql.query("select * from information_schema.ins_mnodes;") - if tdSql.checkRows(3) : - print("mnode is three nodes") - if tdSql.queryResult[0][2]=='leader' : - if tdSql.queryResult[1][2]=='offline': - if tdSql.queryResult[2][2]=='follower': - print("stop mnodes on dnode 2 successfully in 10s") - break - count+=1 - else: - print("stop mnodes on dnode 2 failed in 10s ") - return -1 - tdSql.error("drop mnode on dnode 2;") - - tdSql.query("select * from information_schema.ins_mnodes;") - tdSql.checkRows(3) - tdSql.checkData(0,1,'%s:6030'%self.host) - tdSql.checkData(0,2,'leader') - tdSql.checkData(0,3,'ready') - tdSql.checkData(1,1,'%s:6130'%self.host) - tdSql.checkData(1,2,'offline') - tdSql.checkData(1,3,'ready') - tdSql.checkData(2,1,'%s:6230'%self.host) - tdSql.checkData(2,2,'follower') - tdSql.checkData(2,3,'ready') - - def check3mnode3off(self): - count=0 - while count < 10: - time.sleep(1) - tdSql.query("select * from information_schema.ins_mnodes;") - if tdSql.checkRows(3) : - print("mnode is three nodes") - if tdSql.queryResult[0][2]=='leader' : - if tdSql.queryResult[2][2]=='offline': - if tdSql.queryResult[1][2]=='follower': - print("stop mnodes on dnode 3 successfully in 10s") - break - count+=1 - else: - print("stop mnodes on dnode 3 failed in 10s") - return -1 - tdSql.error("drop mnode on dnode 3;") - tdSql.query("select * from information_schema.ins_mnodes;") - tdSql.checkRows(3) - tdSql.checkData(0,1,'%s:6030'%self.host) - tdSql.checkData(0,2,'leader') - tdSql.checkData(0,3,'ready') - tdSql.checkData(1,1,'%s:6130'%self.host) - tdSql.checkData(1,2,'follower') - tdSql.checkData(1,3,'ready') - tdSql.checkData(2,1,'%s:6230'%self.host) - tdSql.checkData(2,2,'offline') - tdSql.checkData(2,3,'ready') - - - def check5dnode(self): - tdSql.query("select * from information_schema.ins_dnodes;") - tdSql.checkData(0,1,'%s:6030'%self.host) - tdSql.checkData(4,1,'%s:6430'%self.host) - tdSql.checkData(0,4,'ready') - tdSql.checkData(4,4,'ready') - - def five_dnode_three_mnode(self,dnodenumber): - tdSql.query("select * from information_schema.ins_dnodes;") - tdSql.checkData(0,1,'%s:6030'%self.host) - tdSql.checkData(4,1,'%s:6430'%self.host) - tdSql.checkData(0,4,'ready') - tdSql.checkData(4,4,'ready') - tdSql.query("select * from information_schema.ins_mnodes;") - tdSql.checkRows(1) - tdSql.checkData(0,1,'%s:6030'%self.host) - tdSql.checkData(0,2,'leader') - tdSql.checkData(0,3,'ready') - - # fisr add three mnodes; - tdSql.execute("create mnode on dnode 2") - tdSql.execute("create mnode on dnode 3") - - # fisrt check statut ready - self.check3mnode() - - tdSql.error("create mnode on dnode 2") - tdSql.query("select * from information_schema.ins_dnodes;") - print(tdSql.queryResult) - tdLog.debug("stop all of mnode ") - - # seperate vnode and mnode in different dnodes. - # create database and stable - stopcount =0 - while stopcount < 2: - for i in range(dnodenumber): - # threads=[] - # threads = MyThreadFunc(self.insert_data(i*2,i*2+2)) - threads=threading.Thread(target=self.insert_data, args=(i,i+1)) - threads.start() - self.TDDnodes.stoptaosd(i+1) - self.TDDnodes.starttaosd(i+1) - - if self.checkdnodes(5): - print("123") - threads.join() - else: - print("456") - threads.join() - self.stop_thread(threads) - assert 1 == 2 ,"some dnode started failed" - return False - # self.check3mnode() - self.check3mnode() - - - stopcount+=1 - self.check3mnode() - - - def run(self): - # print(self.master_dnode.cfgDict) - self.five_dnode_three_mnode(5) - - def stop(self): - tdSql.close() - tdLog.success(f"{__file__} successfully executed") - -tdCases.addLinux(__file__, TDTestCase()) -tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/6-cluster/clusterCommonCheck.py b/tests/system-test/6-cluster/clusterCommonCheck.py index a69d9707e41ccc5f67f011999154cf59ac7de012..f5926321da38fa52af2f974543a881a4fa46894f 100644 --- a/tests/system-test/6-cluster/clusterCommonCheck.py +++ b/tests/system-test/6-cluster/clusterCommonCheck.py @@ -64,7 +64,7 @@ class ClusterComCheck: dbNumbers=int(dbNumbers) count=0 while count < 5: - tdSql.query("select * from information_schema.ins_databases;") + tdSql.query("select * from information_schema.ins_databases where name!='collectd' ;") count+=1 if tdSql.checkRows(dbNumbers+2): tdLog.success("we find %d databases and expect %d in clusters! " %(tdSql.queryRows,dbNumbers+2)) @@ -207,7 +207,7 @@ class ClusterComCheck: count+=1 else: tdLog.debug(tdSql.queryResult) - tdLog.exit("stop mnodes on dnode %d failed in 10s ") + tdLog.exit(f"stop mnodes on dnode {offlineDnodeNo} failed in 10s ") def check3mnode2off(self,mnodeNums=3): count=0 @@ -226,7 +226,45 @@ class ClusterComCheck: count+=1 else: tdLog.debug(tdSql.queryResult) - tdLog.exit("stop mnodes on dnode %d failed in 10s ") + tdLog.exit("stop mnodes on dnode 2 or 3 failed in 10s") + + def check_vgroups_status(self,vgroup_numbers=2,db_replica=3,count_number=10,db_name="db"): + """ check vgroups status in 10s after db vgroups status is changed """ + vgroup_numbers = int(vgroup_numbers) + self.db_replica = int(db_replica) + tdLog.debug("start to check status of vgroups") + count=0 + last_number=vgroup_numbers-1 + while count < count_number: + time.sleep(1) + tdSql.query(f"show {db_name}.vgroups;") + if count == 0 : + if tdSql.checkRows(vgroup_numbers) : + tdLog.success(f"{db_name} has {vgroup_numbers} vgroups" ) + else: + tdLog.exit(f"vgroup number of {db_name} is not correct") + if self.db_replica == 1 : + if tdSql.queryResult[0][4] == 'leader' and tdSql.queryResult[1][4] == 'leader' and tdSql.queryResult[last_number][4] == 'leader': + ready_time= (count + 1) + tdLog.success(f"all vgroups of {db_name} are leaders in {count + 1} s") + return True + count+=1 + elif self.db_replica == 3 : + vgroup_status_first=[tdSql.queryResult[0][4],tdSql.queryResult[0][6],tdSql.queryResult[0][8]] + + vgroup_status_last=[tdSql.queryResult[last_number][4],tdSql.queryResult[last_number][6],tdSql.queryResult[last_number][8]] + if vgroup_status_first.count('leader') == 1 and vgroup_status_first.count('follower') == 2: + if vgroup_status_last.count('leader') == 1 and vgroup_status_last.count('follower') == 2: + ready_time= (count + 1) + tdLog.success(f"all vgroups of {db_name} are ready in {ready_time} s") + return True + count+=1 + else: + tdLog.debug(tdSql.queryResult) + tdLog.notice(f"all vgroups leader of {db_name} is selected {count}s ") + caller = inspect.getframeinfo(inspect.stack()[1][0]) + args = (caller.filename, caller.lineno) + tdLog.exit("%s(%d) failed " % args) diff --git a/tests/system-test/6-cluster/clusterCommonCreate.py b/tests/system-test/6-cluster/clusterCommonCreate.py index 236708cf072b72fed0381311e770252f58b82889..a06c1233d83d7395a2edccb2dfe7d747adbd1527 100644 --- a/tests/system-test/6-cluster/clusterCommonCreate.py +++ b/tests/system-test/6-cluster/clusterCommonCreate.py @@ -94,26 +94,26 @@ class ClusterComCreate: tdLog.info(shellCmd) os.system(shellCmd) - def getStartConsumeNotifyFromTmqsim(self,cdbName='cdb'): - while 1: - tdSql.query("select * from %s.notifyinfo"%cdbName) - #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) - if (tdSql.getRows() == 1) and (tdSql.getData(0, 1) == 0): - break - else: - time.sleep(0.1) - return - - def getStartCommitNotifyFromTmqsim(self,cdbName='cdb'): - while 1: - tdSql.query("select * from %s.notifyinfo"%cdbName) - #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) - if tdSql.getRows() == 2 : - print(tdSql.getData(0, 1), tdSql.getData(1, 1)) - if tdSql.getData(1, 1) == 1: - break - time.sleep(0.1) - return + # def getStartConsumeNotifyFromTmqsim(self,cdbName='cdb'): + # while 1: + # tdSql.query("select * from %s.notifyinfo"%cdbName) + # #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) + # if (tdSql.getRows() == 1) and (tdSql.getData(0, 1) == 0): + # break + # else: + # time.sleep(0.1) + # return + # + # def getStartCommitNotifyFromTmqsim(self,cdbName='cdb'): + # while 1: + # tdSql.query("select * from %s.notifyinfo"%cdbName) + # #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) + # if tdSql.getRows() == 2 : + # print(tdSql.getData(0, 1), tdSql.getData(1, 1)) + # if tdSql.getData(1, 1) == 1: + # break + # time.sleep(0.1) + # return def create_database(self,tsql, dbName,dropFlag=1,vgroups=4,replica=1): if dropFlag == 1: @@ -137,12 +137,24 @@ class ClusterComCreate: # for i in range(dbNumbers): for i in range(dbNumbers): if dropFlag == 1: - tsql.execute("drop database if exists %s_%d"%(dbNameIndex,1)) - tdLog.debug("create database if not exists %s_%d vgroups %d replica %d"%(dbNameIndex,1, vgroups, replica)) - tsql.execute("create database if not exists %s_%d vgroups %d replica %d"%(dbNameIndex,1, vgroups, replica)) - tdLog.debug("complete to create database %s_%d"%(dbNameIndex,1)) + tsql.execute("drop database if exists %s_%d"%(dbNameIndex,i)) + tdLog.debug("create database if not exists %s_%d vgroups %d replica %d"%(dbNameIndex,i, vgroups, replica)) + tsql.execute("create database if not exists %s_%d vgroups %d replica %d"%(dbNameIndex,i, vgroups, replica)) + tdLog.debug("complete to create database %s_%d"%(dbNameIndex,i)) + def createUser(self,tsql,user,password): + tdLog.info(f"create new user f{user}") + tsql.execute(f"CREATE USER {user} PASS '{password}';") + + def alterUser(self,tsql,user,password): + tdLog.info(f"alter user {user} pass '{password}'") + tsql.execute(f"alter USER {user} pass '{password}' ;") + + def deleteUser(self,tsql,user): + tdLog.info(f"drop user f{user}") + tsql.execute(f"DROP USER {user} ;") + def create_stable(self,tsql, dbName,stbName): tsql.execute("create table if not exists %s.%s (ts timestamp, c1 int, c2 int, c3 binary(16)) tags(t1 int, t2 binary(32))"%(dbName, stbName)) tdLog.debug("complete to create %s.%s" %(dbName, stbName)) @@ -202,6 +214,52 @@ class ClusterComCreate: tdLog.debug("insert data ............ [OK]") return + def alterStbMetaData(self,tsql,dbName,stbName,ctbNum,rowsPerTbl,batchNum,startTs=None): + tdLog.debug("alter Stb column ............") + tdLog.debug(f"ALTER STABLE {dbName}.{stbName} MODIFY COLUMN c3 binary(20);") + tsql.execute(f" ALTER STABLE {dbName}.{stbName} MODIFY COLUMN c3 binary(20);") + tdLog.debug(f"ALTER STABLE {dbName}.{stbName} ADD COLUMN c4 DOUBLE;") + tsql.execute(f" ALTER STABLE {dbName}.{stbName} ADD COLUMN c4 DOUBLE;") + tdLog.debug(f"ALTER STABLE {dbName}.{stbName} DROP COLUMN c2;") + tsql.execute(f" ALTER STABLE {dbName}.{stbName} DROP COLUMN c2;") + tdLog.debug(f"ALTER STABLE {dbName}.{stbName} RENAME TAG t1 t1r;") + tsql.execute(f" ALTER STABLE {dbName}.{stbName} RENAME TAG t1 t1r;") + tdLog.debug(f"ALTER STABLE {dbName}.{stbName} DROP TAG t2;") + tsql.execute(f" ALTER STABLE {dbName}.{stbName} DROP TAG t2;") + tdLog.debug(f"ALTER STABLE {dbName}.{stbName} ADD TAG t2 binary(32) ;") + tsql.execute(f" ALTER STABLE {dbName}.{stbName} ADD TAG t2 binary(32);") + tdLog.debug(f"ALTER STABLE {dbName}.{stbName} MODIFY TAG t2 binary(34) ;") + tsql.execute(f" ALTER STABLE {dbName}.{stbName} MODIFY TAG t2 binary(34);") + tdLog.debug(f"ALTER STABLE {dbName}.{stbName} ADD TAG t3 double ;") + tsql.execute(f" ALTER STABLE {dbName}.{stbName} ADD TAG t3 double;") + tsql.error(f" ALTER STABLE {dbName}.{stbName} ADD TAG t2 double;") + + tdLog.debug("start to insert data ............") + # tsql.execute("use %s" %dbName) + pre_insert = "insert into " + sql = pre_insert + + if startTs is None: + t = time.time() + startTs = int(round(t * 1000)) + #tdLog.debug("doing insert data into stable:%s rows:%d ..."%(stbName, allRows)) + for i in range(ctbNum): + sql += " %s.%s_%d values "%(dbName,stbName,i) + for j in range(rowsPerTbl): + sql += "(%d, %d,'mnode_%d', %d ) "%(startTs + j, j, j,j) + if (j > 0) and ((j%batchNum == 0) or (j == rowsPerTbl - 1)): + tsql.execute(sql) + if j < rowsPerTbl - 1: + sql = "insert into %s.%s_%d values " %(dbName,stbName,i) + else: + sql = "insert into " + #end sql + if sql != pre_insert: + #print("insert sql:%s"%sql) + tsql.execute(sql) + tdLog.debug("insert data ............ [OK]") + return + def insert_data_1(self,tsql,dbName,ctbPrefix,ctbNum,rowsPerTbl,batchNum,startTs): tdLog.debug("start to insert data ............") tsql.execute("use %s" %dbName) diff --git a/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertDataRebootModifyMetaAlterRep1to3.py b/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertDataRebootModifyMetaAlterRep1to3.py new file mode 100644 index 0000000000000000000000000000000000000000..7d46b3143d26ad99b4e02c92518a02af0d3be2db --- /dev/null +++ b/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertDataRebootModifyMetaAlterRep1to3.py @@ -0,0 +1,206 @@ +import taos +import sys +import time +import os + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import TDDnodes +from util.dnodes import TDDnode +from util.cluster import * +sys.path.append("./6-cluster") +from clusterCommonCreate import * +from clusterCommonCheck import clusterComCheck + +import time +import socket +import subprocess +from multiprocessing import Process +import threading +import time +import inspect +import ctypes + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + tdSql.init(conn.cursor()) + self.host = socket.gethostname() + + + 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 _async_raise(self, tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + exctype = type(exctype) + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) + if res == 0: + raise ValueError("invalid thread id") + elif res != 1: + # """if it returns a number greater than one, you're in trouble, + # and you should call it again with exc=NULL to revert the effect""" + ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + def stopThread(self,thread): + self._async_raise(thread.ident, SystemExit) + + + def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'db0_0', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'replica': 1, + 'stbName': 'stb', + 'stbNumbers': 2, + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 200, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + "rowsPerTbl": 1000, + "batchNum": 5000 + } + + dnodeNumbers=int(dnodeNumbers) + mnodeNums=int(mnodeNums) + vnodeNumbers = int(dnodeNumbers-mnodeNums) + allctbNumbers=(paraDict['stbNumbers']*paraDict["ctbNum"]) + rowsPerStb=paraDict["ctbNum"]*paraDict["rowsPerTbl"] + rowsall=rowsPerStb*paraDict['stbNumbers'] + dbNumbers = 1 + + tdLog.info("first check dnode and mnode") + tdSql.query("select * from information_schema.ins_dnodes;") + tdSql.checkData(0,1,'%s:6030'%self.host) + tdSql.checkData(4,1,'%s:6430'%self.host) + clusterComCheck.checkDnodes(dnodeNumbers) + + #check mnode status + tdLog.info("check mnode status") + clusterComCheck.checkMnodeStatus(mnodeNums) + + # add some error operations and + tdLog.info("Confirm the status of the dnode again") + tdSql.error("create mnode on dnode 2") + tdSql.query("select * from information_schema.ins_dnodes;") + print(tdSql.queryResult) + clusterComCheck.checkDnodes(dnodeNumbers) + + # create database and stable + clusterComCreate.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']) + tdLog.info("Take turns stopping Mnodes ") + + tdDnodes=cluster.dnodes + stopcount =0 + threads=[] + + # create stable:stb_0 + stableName= paraDict['stbName'] + newTdSql=tdCom.newTdSql() + clusterComCreate.create_stables(newTdSql, paraDict["dbName"],stableName,paraDict['stbNumbers']) + #create child table:ctb_0 + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + clusterComCreate.create_ctable(newTdSql, paraDict["dbName"],stableName,stableName, paraDict['ctbNum']) + #insert date + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + threads.append(threading.Thread(target=clusterComCreate.insert_data, args=(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]))) + for tr in threads: + tr.start() + for tr in threads: + tr.join() + + while stopcount < restartNumbers: + tdLog.info(" restart loop: %d"%stopcount ) + if stopRole == "mnode": + for i in range(mnodeNums): + tdDnodes[i].stoptaosd() + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + elif stopRole == "vnode": + for i in range(vnodeNumbers): + tdDnodes[i+mnodeNums].stoptaosd() + # sleep(10) + tdDnodes[i+mnodeNums].starttaosd() + # sleep(10) + elif stopRole == "dnode": + for i in range(dnodeNumbers): + if i == 0 : + stableName= '%s_%d'%(paraDict['stbName'],0) + newTdSql=tdCom.newTdSql() + # newTdSql.execute('alter database db0_0 replica 3') + clusterComCreate.alterStbMetaData(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"]) + tdDnodes[i].stoptaosd() + clusterComCheck.checkDbRows(dbNumbers) + # sleep(10) + tdDnodes[i].starttaosd() + if i == 3 : + TdSqlEx=tdCom.newTdSql() + tdLog.info("alter database db0_0 replica 3") + TdSqlEx.execute('alter database db0_0 replica 3') + + + # dnodeNumbers don't include database of schema + if clusterComCheck.checkDnodes(dnodeNumbers): + tdLog.info("123") + else: + print("456") + + self.stopThread(threads) + tdLog.exit("one or more of dnodes failed to start ") + # self.check3mnode() + stopcount+=1 + + + clusterComCheck.checkDnodes(dnodeNumbers) + clusterComCheck.checkDbRows(dbNumbers) + # clusterComCheck.checkDb(dbNumbers,1,paraDict["dbName"]) + + # tdSql.execute("use %s" %(paraDict["dbName"])) + tdSql.query("show %s.stables"%(paraDict["dbName"])) + tdSql.checkRows(paraDict["stbNumbers"]) + for i in range(paraDict['stbNumbers']): + stableName= '%s.%s_%d'%(paraDict["dbName"],paraDict['stbName'],i) + tdSql.query("select count(*) from %s"%stableName) + if i == 0 : + tdSql.checkData(0,0,rowsPerStb*2) + else: + tdSql.checkData(0,0,rowsPerStb) + clusterComCheck.check_vgroups_status(vgroup_numbers=paraDict["vgroups"],db_replica=3,db_name=paraDict["dbName"],count_number=150) + def run(self): + # print(self.master_dnode.cfgDict) + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=1,stopRole='dnode') + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertDataRebootModifyMetaAlterRep3to1.py b/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertDataRebootModifyMetaAlterRep3to1.py new file mode 100644 index 0000000000000000000000000000000000000000..5b5fb04969468e6febe91feb8263c8045b1e64eb --- /dev/null +++ b/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertDataRebootModifyMetaAlterRep3to1.py @@ -0,0 +1,206 @@ +import taos +import sys +import time +import os + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import TDDnodes +from util.dnodes import TDDnode +from util.cluster import * +sys.path.append("./6-cluster") +from clusterCommonCreate import * +from clusterCommonCheck import clusterComCheck + +import time +import socket +import subprocess +from multiprocessing import Process +import threading +import time +import inspect +import ctypes + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + tdSql.init(conn.cursor()) + self.host = socket.gethostname() + + + 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 _async_raise(self, tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + exctype = type(exctype) + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) + if res == 0: + raise ValueError("invalid thread id") + elif res != 1: + # """if it returns a number greater than one, you're in trouble, + # and you should call it again with exc=NULL to revert the effect""" + ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + def stopThread(self,thread): + self._async_raise(thread.ident, SystemExit) + + + def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'db0_0', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'replica': 3, + 'stbName': 'stb', + 'stbNumbers': 2, + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 200, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + "rowsPerTbl": 1000, + "batchNum": 5000 + } + + dnodeNumbers=int(dnodeNumbers) + mnodeNums=int(mnodeNums) + vnodeNumbers = int(dnodeNumbers-mnodeNums) + allctbNumbers=(paraDict['stbNumbers']*paraDict["ctbNum"]) + rowsPerStb=paraDict["ctbNum"]*paraDict["rowsPerTbl"] + rowsall=rowsPerStb*paraDict['stbNumbers'] + dbNumbers = 1 + + tdLog.info("first check dnode and mnode") + tdSql.query("select * from information_schema.ins_dnodes;") + tdSql.checkData(0,1,'%s:6030'%self.host) + tdSql.checkData(4,1,'%s:6430'%self.host) + clusterComCheck.checkDnodes(dnodeNumbers) + + #check mnode status + tdLog.info("check mnode status") + clusterComCheck.checkMnodeStatus(mnodeNums) + + # add some error operations and + tdLog.info("Confirm the status of the dnode again") + tdSql.error("create mnode on dnode 2") + tdSql.query("select * from information_schema.ins_dnodes;") + print(tdSql.queryResult) + clusterComCheck.checkDnodes(dnodeNumbers) + + # create database and stable + clusterComCreate.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']) + tdLog.info("Take turns stopping Mnodes ") + + tdDnodes=cluster.dnodes + stopcount =0 + threads=[] + + # create stable:stb_0 + stableName= paraDict['stbName'] + newTdSql=tdCom.newTdSql() + clusterComCreate.create_stables(newTdSql, paraDict["dbName"],stableName,paraDict['stbNumbers']) + #create child table:ctb_0 + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + clusterComCreate.create_ctable(newTdSql, paraDict["dbName"],stableName,stableName, paraDict['ctbNum']) + #insert date + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + threads.append(threading.Thread(target=clusterComCreate.insert_data, args=(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]))) + for tr in threads: + tr.start() + for tr in threads: + tr.join() + + while stopcount < restartNumbers: + tdLog.info(" restart loop: %d"%stopcount ) + if stopRole == "mnode": + for i in range(mnodeNums): + tdDnodes[i].stoptaosd() + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + elif stopRole == "vnode": + for i in range(vnodeNumbers): + tdDnodes[i+mnodeNums].stoptaosd() + # sleep(10) + tdDnodes[i+mnodeNums].starttaosd() + # sleep(10) + elif stopRole == "dnode": + for i in range(dnodeNumbers): + tdDnodes[i].stoptaosd() + clusterComCheck.checkDbRows(dbNumbers) + if i == 0 : + stableName= '%s_%d'%(paraDict['stbName'],0) + newTdSql=tdCom.newTdSql() + # newTdSql.execute('alter database db0_0 replica 3') + clusterComCreate.alterStbMetaData(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"]) + # sleep(10) + tdDnodes[i].starttaosd() + if i == 3 : + TdSqlEx=tdCom.newTdSql() + tdLog.info("alter database db0_0 replica 1") + TdSqlEx.execute('alter database db0_0 replica 1') + + + # dnodeNumbers don't include database of schema + if clusterComCheck.checkDnodes(dnodeNumbers): + tdLog.info("123") + else: + print("456") + + self.stopThread(threads) + tdLog.exit("one or more of dnodes failed to start ") + # self.check3mnode() + stopcount+=1 + + + clusterComCheck.checkDnodes(dnodeNumbers) + clusterComCheck.checkDbRows(dbNumbers) + # clusterComCheck.checkDb(dbNumbers,1,paraDict["dbName"]) + + # tdSql.execute("use %s" %(paraDict["dbName"])) + tdSql.query("show %s.stables"%(paraDict["dbName"])) + tdSql.checkRows(paraDict["stbNumbers"]) + for i in range(paraDict['stbNumbers']): + stableName= '%s.%s_%d'%(paraDict["dbName"],paraDict['stbName'],i) + tdSql.query("select count(*) from %s"%stableName) + if i == 0 : + tdSql.checkData(0,0,rowsPerStb*2) + else: + tdSql.checkData(0,0,rowsPerStb) + clusterComCheck.check_vgroups_status(vgroup_numbers=paraDict["vgroups"],db_replica=1,db_name=paraDict["dbName"],count_number=150) + def run(self): + # print(self.master_dnode.cfgDict) + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=1,stopRole='dnode') + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertDatarRebootAlterRep1-3.py b/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertDatarRebootAlterRep1-3.py new file mode 100644 index 0000000000000000000000000000000000000000..aa3ed8e3fd4596f0f9f6afa98f43d10101265b96 --- /dev/null +++ b/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertDatarRebootAlterRep1-3.py @@ -0,0 +1,222 @@ +import taos +import sys +import time +import os + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import TDDnodes +from util.dnodes import TDDnode +from util.cluster import * +sys.path.append("./6-cluster") +from clusterCommonCreate import * +from clusterCommonCheck import clusterComCheck + +import time +import socket +import subprocess +from multiprocessing import Process +import threading +import time +import inspect +import ctypes + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + tdSql.init(conn.cursor()) + self.host = socket.gethostname() + + + 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 _async_raise(self, tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + exctype = type(exctype) + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) + if res == 0: + raise ValueError("invalid thread id") + elif res != 1: + # """if it returns a number greater than one, you're in trouble, + # and you should call it again with exc=NULL to revert the effect""" + ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + def stopThread(self,thread): + self._async_raise(thread.ident, SystemExit) + + + def insertData(self,countstart,countstop): + # fisrt add data : db\stable\childtable\general table + + for couti in range(countstart,countstop): + tdLog.debug("drop database if exists db%d" %couti) + tdSql.execute("drop database if exists db%d" %couti) + print("create database if not exists db%d replica 1 duration 300" %couti) + tdSql.execute("create database if not exists db%d replica 1 duration 300" %couti) + tdSql.execute("use db%d" %couti) + tdSql.execute( + '''create table stb1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + tags (t1 int) + ''' + ) + tdSql.execute( + ''' + create table t1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + ''' + ) + for i in range(4): + tdSql.execute(f'create table ct{i+1} using stb1 tags ( {i+1} )') + + + def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'db0_0', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'replica': 1, + 'stbName': 'stb', + 'stbNumbers': 2, + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 1000, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + "rowsPerTbl": 100, + "batchNum": 5000 + } + + dnodeNumbers = int(dnodeNumbers) + mnodeNums = int(mnodeNums) + vnodeNumbers = int(dnodeNumbers-mnodeNums) + allctbNumbers = (paraDict['stbNumbers']*paraDict["ctbNum"]) + rowsPerStb = paraDict["ctbNum"]*paraDict["rowsPerTbl"] + rowsall = rowsPerStb*paraDict['stbNumbers'] + dbNumbers = 1 + replica3 = 3 + tdLog.info("first check dnode and mnode") + tdSql.query("select * from information_schema.ins_dnodes;") + tdSql.checkData(0,1,'%s:6030'%self.host) + tdSql.checkData(4,1,'%s:6430'%self.host) + clusterComCheck.checkDnodes(dnodeNumbers) + + #check mnode status + tdLog.info("check mnode status") + clusterComCheck.checkMnodeStatus(mnodeNums) + + # add some error operations and + tdLog.info("Confirm the status of the dnode again") + tdSql.error("create mnode on dnode 2") + tdSql.query("select * from information_schema.ins_dnodes;") + print(tdSql.queryResult) + clusterComCheck.checkDnodes(dnodeNumbers) + + # create database and stable + clusterComCreate.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']) + tdLog.info("Take turns stopping Mnodes ") + + tdDnodes=cluster.dnodes + stopcount =0 + threads=[] + + # create stable:stb_0 + stableName= paraDict['stbName'] + newTdSql=tdCom.newTdSql() + clusterComCreate.create_stables(newTdSql, paraDict["dbName"],stableName,paraDict['stbNumbers']) + #create child table:ctb_0 + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + clusterComCreate.create_ctable(newTdSql, paraDict["dbName"],stableName,stableName, paraDict['ctbNum']) + #insert date + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + threads.append(threading.Thread(target=clusterComCreate.insert_data, args=(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]))) + for tr in threads: + tr.start() + TdSqlEx=tdCom.newTdSql() + tdLog.info("alter database db0_0 replica 3") + TdSqlEx.execute('alter database db0_0 replica 3') + while stopcount < restartNumbers: + tdLog.info(" restart loop: %d"%stopcount ) + if stopRole == "mnode": + for i in range(mnodeNums): + tdDnodes[i].stoptaosd() + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + elif stopRole == "vnode": + for i in range(vnodeNumbers): + tdDnodes[i+mnodeNums].stoptaosd() + # sleep(10) + tdDnodes[i+mnodeNums].starttaosd() + # sleep(10) + elif stopRole == "dnode": + for i in range(dnodeNumbers): + tdDnodes[i].stoptaosd() + # tdLog.info('select cast(c2 as nchar(10)) from db0_0.stb_1;') + # TdSqlEx.execute('select cast(c2 as nchar(10)) from db0_0.stb_1;') + # tdLog.info('select avg(c1) from db0_0.stb_0 interval(10s);') + # TdSqlEx.execute('select avg(c1) from db0_0.stb_0 interval(10s);') + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + # dnodeNumbers don't include database of schema + if clusterComCheck.checkDnodes(dnodeNumbers): + tdLog.info("123") + else: + print("456") + + self.stopThread(threads) + tdLog.exit("one or more of dnodes failed to start ") + # self.check3mnode() + stopcount+=1 + + for tr in threads: + tr.join() + clusterComCheck.checkDnodes(dnodeNumbers) + clusterComCheck.checkDbRows(dbNumbers) + # clusterComCheck.checkDb(dbNumbers,1,paraDict["dbName"]) + + # tdSql.execute("use %s" %(paraDict["dbName"])) + tdSql.query("show %s.stables"%(paraDict["dbName"])) + tdSql.checkRows(paraDict["stbNumbers"]) + # for i in range(paraDict['stbNumbers']): + # stableName= '%s.%s_%d'%(paraDict["dbName"],paraDict['stbName'],i) + # tdSql.query("select count(*) from %s"%stableName) + # tdSql.checkData(0,0,rowsPerStb) + clusterComCheck.check_vgroups_status(vgroup_numbers=paraDict["vgroups"],db_replica=replica3,db_name=paraDict["dbName"],count_number=240) + def run(self): + # print(self.master_dnode.cfgDict) + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=4,stopRole='dnode') + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertLessDataAlterRep3to1to3.py b/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertLessDataAlterRep3to1to3.py new file mode 100644 index 0000000000000000000000000000000000000000..ed7b99a880716b85ded5238b80eb11691166bc1e --- /dev/null +++ b/tests/system-test/6-cluster/manually-test/6dnode3mnodeInsertLessDataAlterRep3to1to3.py @@ -0,0 +1,196 @@ +import taos +import sys +import time +import os + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import TDDnodes +from util.dnodes import TDDnode +from util.cluster import * +sys.path.append("./6-cluster") +from clusterCommonCreate import * +from clusterCommonCheck import clusterComCheck + +import time +import socket +import subprocess +from multiprocessing import Process +import threading +import time +import inspect +import ctypes + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + tdSql.init(conn.cursor()) + self.host = socket.gethostname() + + + 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 _async_raise(self, tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + exctype = type(exctype) + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) + if res == 0: + raise ValueError("invalid thread id") + elif res != 1: + # """if it returns a number greater than one, you're in trouble, + # and you should call it again with exc=NULL to revert the effect""" + ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + def stopThread(self,thread): + self._async_raise(thread.ident, SystemExit) + + + def insertData(self,countstart,countstop): + # fisrt add data : db\stable\childtable\general table + + for couti in range(countstart,countstop): + tdLog.debug("drop database if exists db%d" %couti) + tdSql.execute("drop database if exists db%d" %couti) + print("create database if not exists db%d replica 1 duration 300" %couti) + tdSql.execute("create database if not exists db%d replica 1 duration 300" %couti) + tdSql.execute("use db%d" %couti) + tdSql.execute( + '''create table stb1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + tags (t1 int) + ''' + ) + tdSql.execute( + ''' + create table t1 + (ts timestamp, c1 int, c2 bigint, c3 smallint, c4 tinyint, c5 float, c6 double, c7 bool, c8 binary(16),c9 nchar(32), c10 timestamp) + ''' + ) + for i in range(4): + tdSql.execute(f'create table ct{i+1} using stb1 tags ( {i+1} )') + + + def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'db0_0', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'replica': 3, + 'stbName': 'stb', + 'stbNumbers': 2, + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 1, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + "rowsPerTbl": 1, + "batchNum": 5000 + } + + dnodeNumbers=int(dnodeNumbers) + mnodeNums=int(mnodeNums) + vnodeNumbers = int(dnodeNumbers-mnodeNums) + replica1 = 1 + replica3 = 3 + allctbNumbers=(paraDict['stbNumbers']*paraDict["ctbNum"]) + rowsPerStb=paraDict["ctbNum"]*paraDict["rowsPerTbl"] + rowsall=rowsPerStb*paraDict['stbNumbers'] + dbNumbers = 1 + + tdLog.info("first check dnode and mnode") + tdSql.query("select * from information_schema.ins_dnodes;") + tdSql.checkData(0,1,'%s:6030'%self.host) + tdSql.checkData(4,1,'%s:6430'%self.host) + clusterComCheck.checkDnodes(dnodeNumbers) + + #check mnode status + tdLog.info("check mnode status") + clusterComCheck.checkMnodeStatus(mnodeNums) + + # add some error operations and + tdLog.info("Confirm the status of the dnode again") + tdSql.error("create mnode on dnode 2") + tdSql.query("select * from information_schema.ins_dnodes;") + print(tdSql.queryResult) + clusterComCheck.checkDnodes(dnodeNumbers) + + # create database and stable + clusterComCreate.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], paraDict["vgroups"],paraDict['replica']) + tdLog.info("Take turns stopping Mnodes ") + + tdDnodes=cluster.dnodes + stopcount =0 + threads=[] + + # create stable:stb_0 + stableName= paraDict['stbName'] + newTdSql=tdCom.newTdSql() + clusterComCreate.create_stables(newTdSql, paraDict["dbName"],stableName,paraDict['stbNumbers']) + #create child table:ctb_0 + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + clusterComCreate.create_ctable(newTdSql, paraDict["dbName"],stableName,stableName, paraDict['ctbNum']) + #insert date + for i in range(paraDict['stbNumbers']): + stableName= '%s_%d'%(paraDict['stbName'],i) + newTdSql=tdCom.newTdSql() + threads.append(threading.Thread(target=clusterComCreate.insert_data, args=(newTdSql, paraDict["dbName"],stableName,paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]))) + for tr in threads: + tr.start() + TdSqlEx=tdCom.newTdSql() + tdLog.info(f"alter database db0_0 replica {replica1}") + TdSqlEx.execute(f'alter database db0_0 replica {replica1}') + for tr in threads: + tr.join() + clusterComCheck.checkDnodes(dnodeNumbers) + clusterComCheck.checkDbRows(dbNumbers) + # clusterComCheck.checkDb(dbNumbers,1,paraDict["dbName"]) + + # tdSql.execute("use %s" %(paraDict["dbName"])) + tdSql.query("show %s.stables"%(paraDict["dbName"])) + tdSql.checkRows(paraDict["stbNumbers"]) + for i in range(paraDict['stbNumbers']): + stableName= '%s.%s_%d'%(paraDict["dbName"],paraDict['stbName'],i) + tdSql.query("select count(*) from %s"%stableName) + tdSql.checkData(0,0,rowsPerStb) + + clusterComCheck.check_vgroups_status(vgroup_numbers=paraDict["vgroups"],db_replica=replica1,db_name=paraDict["dbName"],count_number=20) + sleep(5) + tdLog.info(f"show transactions;alter database db0_0 replica {replica3};") + TdSqlEx.execute(f'show transactions;') + TdSqlEx.execute(f'alter database db0_0 replica {replica3};') + clusterComCheck.check_vgroups_status(vgroup_numbers=paraDict["vgroups"],db_replica=replica3,db_name=paraDict["dbName"],count_number=120) + + def run(self): + # print(self.master_dnode.cfgDict) + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=4,stopRole='dnode') + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/6-cluster/manually-test/6dnode3mnodeStopDnodeInsertDatatb.py b/tests/system-test/6-cluster/manually-test/6dnode3mnodeStopDnodeInsertDatatb.py new file mode 100644 index 0000000000000000000000000000000000000000..e02af29a050c3812ef3b27a6b2c9aa126cb2146c --- /dev/null +++ b/tests/system-test/6-cluster/manually-test/6dnode3mnodeStopDnodeInsertDatatb.py @@ -0,0 +1,191 @@ +import taos +import sys +import time +import os + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import TDDnodes +from util.dnodes import TDDnode +from util.cluster import * +sys.path.append("./6-cluster") +from clusterCommonCreate import * +from clusterCommonCheck import clusterComCheck + +import time +import socket +import subprocess +from multiprocessing import Process +import threading +import time +import inspect +import ctypes + +class TDTestCase: + + def init(self, conn, logSql, replicaVar=1): + tdLog.debug(f"start to excute {__file__}") + self.TDDnodes = None + tdSql.init(conn.cursor()) + self.host = socket.gethostname() + + + 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 _async_raise(self, tid, exctype): + """raises the exception, performs cleanup if needed""" + if not inspect.isclass(exctype): + exctype = type(exctype) + res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype)) + if res == 0: + raise ValueError("invalid thread id") + elif res != 1: + # """if it returns a number greater than one, you're in trouble, + # and you should call it again with exc=NULL to revert the effect""" + ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None) + raise SystemError("PyThreadState_SetAsyncExc failed") + + def stopThread(self,thread): + self._async_raise(thread.ident, SystemExit) + + + def insertData(self,dbname,tableCount,rowsPerCount): + # tableCount : create table number + # rowsPerCount : rows per table + # fisrt add data : db\stable\childtable\general table + os.system(f"taosBenchmark -d {dbname} -n {tableCount} -t {rowsPerCount} -z 1 -k 10000 -y ") + + + def fiveDnodeThreeMnode(self,dnodeNumbers,mnodeNums,restartNumbers,stopRole): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'db0_0', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'replica': 1, + 'stbName': 'stb', + 'stbNumbers': 2, + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 10000, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + "rowsPerTbl": 10000, + "batchNum": 5000 + } + + dnodeNumbers=int(dnodeNumbers) + mnodeNums=int(mnodeNums) + vnodeNumbers = int(dnodeNumbers-mnodeNums) + allctbNumbers=(paraDict['stbNumbers']*paraDict["ctbNum"]) + rowsPerStb=paraDict["ctbNum"]*paraDict["rowsPerTbl"] + rowsall=rowsPerStb*paraDict['stbNumbers'] + dbNumbers = 1 + + tdLog.info("first check dnode and mnode") + tdSql.query("select * from information_schema.ins_dnodes;") + tdSql.checkData(0,1,'%s:6030'%self.host) + tdSql.checkData(4,1,'%s:6430'%self.host) + clusterComCheck.checkDnodes(dnodeNumbers) + + #check mnode status + tdLog.info("check mnode status") + clusterComCheck.checkMnodeStatus(mnodeNums) + + # add some error operations and + tdLog.info("Confirm the status of the dnode again") + tdSql.error("create mnode on dnode 2") + tdSql.query("select * from information_schema.ins_dnodes;") + print(tdSql.queryResult) + clusterComCheck.checkDnodes(dnodeNumbers) + + # create database and stable + tdLog.info("Take turns stopping Mnodes ") + + tdDnodes=cluster.dnodes + stopcount =0 + threads=[] + + # create stable:stb_0 + threads.append(threading.Thread(target=self.insertData, args=(paraDict["dbName"],paraDict["ctbNum"],paraDict["rowsPerTbl"]))) + for tr in threads: + tr.start() + TdSqlEx=tdCom.newTdSql() + tdLog.info("alter database db0_0 replica 3") + TdSqlEx.execute('alter database db0_0 replica 3') + while stopcount < restartNumbers: + tdLog.info(" restart loop: %d"%stopcount ) + if stopRole == "mnode": + for i in range(mnodeNums): + tdDnodes[i].stoptaosd() + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + elif stopRole == "vnode": + for i in range(vnodeNumbers): + tdDnodes[i+mnodeNums].stoptaosd() + # sleep(10) + tdDnodes[i+mnodeNums].starttaosd() + # sleep(10) + elif stopRole == "dnode": + for i in range(dnodeNumbers): + tdDnodes[i].stoptaosd() + # tdLog.info('select cast(c2 as nchar(10)) from db0_0.stb_1;') + # TdSqlEx.execute('select cast(c2 as nchar(10)) from db0_0.stb_1;') + # tdLog.info('select avg(c1) from db0_0.stb_0 interval(10s);') + # TdSqlEx.execute('select avg(c1) from db0_0.stb_0 interval(10s);') + # sleep(10) + tdDnodes[i].starttaosd() + # sleep(10) + # dnodeNumbers don't include database of schema + if clusterComCheck.checkDnodes(dnodeNumbers): + tdLog.info("123") + else: + print("456") + + self.stopThread(threads) + tdLog.exit("one or more of dnodes failed to start ") + # self.check3mnode() + stopcount+=1 + + for tr in threads: + tr.join() + clusterComCheck.checkDnodes(dnodeNumbers) + clusterComCheck.checkDbRows(dbNumbers) + # clusterComCheck.checkDb(dbNumbers,1,paraDict["dbName"]) + + # tdSql.execute("use %s" %(paraDict["dbName"])) + tdSql.query("show %s.stables"%(paraDict["dbName"])) + tdSql.checkRows(paraDict["stbNumbers"]) + for i in range(paraDict['stbNumbers']): + stableName= '%s.%s_%d'%(paraDict["dbName"],paraDict['stbName'],i) + tdSql.query("select count(*) from %s"%stableName) + tdSql.checkData(0,0,rowsPerStb) + clusterComCheck.check_vgroups_status(vgroup_numbers=paraDict["vgroups"],db_replica=3,db_name=paraDict["dbName"],count_number=240) + def run(self): + # print(self.master_dnode.cfgDict) + self.fiveDnodeThreeMnode(dnodeNumbers=6,mnodeNums=3,restartNumbers=4,stopRole='dnode') + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/7-tmq/basic5.py b/tests/system-test/7-tmq/basic5.py index 69cf378da3da0b12e56242125c49bfe33afcb3a6..080b431ffe54f43e725e22d84a3f365f8bfc4cea 100644 --- a/tests/system-test/7-tmq/basic5.py +++ b/tests/system-test/7-tmq/basic5.py @@ -57,7 +57,7 @@ class TDTestCase: return cur def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum,rowsPerTbl): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table if not exists %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" @@ -149,6 +149,7 @@ class TDTestCase: topicFromStb = 'topic_stb_column' topicFromCtb = 'topic_ctb_column' + tdSql.execute("alter database %s wal_retention_period 3600" % (parameterDict['dbName'])) tdSql.execute("create topic %s as select ts, c1, c2 from %s.%s" %(topicFromStb, parameterDict['dbName'], parameterDict['stbName'])) tdSql.execute("create topic %s as select ts, c1, c2 from %s.%s_0" %(topicFromCtb, parameterDict['dbName'], parameterDict['stbName'])) diff --git a/tests/system-test/7-tmq/create_wrong_topic.py b/tests/system-test/7-tmq/create_wrong_topic.py index 39d519fec1be19009860408dd02d26630070af44..77d43149cd611225d2ee8f7b017013b0fc784bfb 100644 --- a/tests/system-test/7-tmq/create_wrong_topic.py +++ b/tests/system-test/7-tmq/create_wrong_topic.py @@ -44,6 +44,7 @@ class TDTestCase: def wrong_topic(self): tdSql.prepare() tdSql.execute('use db') + tdSql.execute('alter database db wal_retention_period 3600') stbname = f'db.{tdCom.getLongName(5, "letters")}' tag_dict = { 't0':'int' @@ -75,4 +76,4 @@ class TDTestCase: tdLog.success(f"{__file__} successfully executed") tdCases.addLinux(__file__, TDTestCase()) -tdCases.addWindows(__file__, TDTestCase()) \ No newline at end of file +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/7-tmq/dataFromTsdbNWal-multiCtb.py b/tests/system-test/7-tmq/dataFromTsdbNWal-multiCtb.py index 808a4935e30ccec4d06863e54e5e2ff3e1ba635d..44f58279be2df9cc97ee504babebbbfda1793f44 100644 --- a/tests/system-test/7-tmq/dataFromTsdbNWal-multiCtb.py +++ b/tests/system-test/7-tmq/dataFromTsdbNWal-multiCtb.py @@ -67,6 +67,7 @@ class TDTestCase: tdLog.info("flush db to let data falls into the disk") tdSql.query("flush database %s"%(paraDict['dbName'])) + tdSql.execute("alter database %s wal_retention_period 3600"%(paraDict['dbName'])) return def tmqCase1(self): diff --git a/tests/system-test/7-tmq/dataFromTsdbNWal.py b/tests/system-test/7-tmq/dataFromTsdbNWal.py index 8386c22cd0430128a1b873f3f5150ef51704b245..0f4f1694c17701d9d4361c788980215ae418db5e 100644 --- a/tests/system-test/7-tmq/dataFromTsdbNWal.py +++ b/tests/system-test/7-tmq/dataFromTsdbNWal.py @@ -67,6 +67,7 @@ class TDTestCase: tdLog.info("flush db to let data falls into the disk") tdSql.query("flush database %s"%(paraDict['dbName'])) + tdSql.execute("alter database %s wal_retention_period 3600"%(paraDict['dbName'])) return def tmqCase1(self): diff --git a/tests/system-test/7-tmq/db.py b/tests/system-test/7-tmq/db.py index 04f5aac559b060e17b23618cea1007e41ffb858d..e0d1e2c5b6190ed28f9e8ad9f3e4c8b15d57bb51 100644 --- a/tests/system-test/7-tmq/db.py +++ b/tests/system-test/7-tmq/db.py @@ -60,7 +60,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") tdSql.query("drop database if exists %s "%(cdbName)) - tdSql.query("create database %s vgroups 1"%(cdbName)) + tdSql.query("create database %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) diff --git a/tests/system-test/7-tmq/dropDbR3ConflictTransaction.py b/tests/system-test/7-tmq/dropDbR3ConflictTransaction.py index 4371a909c253b3aaf1f7f4d5fad931ee35665519..7d11684ed81fd79584253e032f67cae1bd833de8 100644 --- a/tests/system-test/7-tmq/dropDbR3ConflictTransaction.py +++ b/tests/system-test/7-tmq/dropDbR3ConflictTransaction.py @@ -32,34 +32,6 @@ class TDTestCase: tdSql.init(conn.cursor()) #tdSql.init(conn.cursor(), logSql) # output sql.txt file - def checkFileContent(self, consumerId, queryString): - buildPath = tdCom.getBuildPath() - cfgPath = tdCom.getClientCfgPath() - dstFile = '%s/../log/dstrows_%d.txt'%(cfgPath, consumerId) - cmdStr = '%s/build/bin/taos -c %s -s "%s >> %s"'%(buildPath, cfgPath, queryString, dstFile) - tdLog.info(cmdStr) - os.system(cmdStr) - - consumeRowsFile = '%s/../log/consumerid_%d.txt'%(cfgPath, consumerId) - tdLog.info("rows file: %s, %s"%(consumeRowsFile, dstFile)) - - consumeFile = open(consumeRowsFile, mode='r') - queryFile = open(dstFile, mode='r') - - # skip first line for it is schema - queryFile.readline() - - while True: - dst = queryFile.readline() - src = consumeFile.readline() - - if dst: - if dst != src: - tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) - else: - break - return - def prepareTestEnv(self): tdLog.printNoPrefix("======== prepare test env include database, stable, ctables, and insert data: ") paraDict = {'dbName': 'dbt', @@ -134,6 +106,7 @@ class TDTestCase: paraDict['ctbNum'] = self.ctbNum paraDict['rowsPerTbl'] = self.rowsPerTbl + tdSql.execute("alter database dbt wal_retention_period 3600") tdLog.info("create topics from stb1") topicFromStb1 = 'topic_stb1' queryString = "select ts, c1, c2 from %s.%s where t4 == 'beijing' or t4 == 'changsha' "%(paraDict['dbName'], paraDict['stbName']) diff --git a/tests/system-test/7-tmq/raw_block_interface_test.py b/tests/system-test/7-tmq/raw_block_interface_test.py new file mode 100644 index 0000000000000000000000000000000000000000..1e89de1cce397e8c64e2a78bb6fb8614d011d47d --- /dev/null +++ b/tests/system-test/7-tmq/raw_block_interface_test.py @@ -0,0 +1,54 @@ + +import taos +import sys +import time +import socket +import os +import threading + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import * +from util.common import * +sys.path.append("./7-tmq") +from tmqCommon import * + +class TDTestCase: + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug(f"start to excute {__file__}") + tdSql.init(conn.cursor()) + + def checkData(self): + tdSql.execute('use db_raw') + tdSql.query("select * from d1") + tdSql.checkRows(1) + tdSql.checkData(0, 1, 120) + + tdSql.query("select * from d2") + tdSql.checkRows(1) + tdSql.checkData(0, 1, None) + + return + + def check(self): + buildPath = tdCom.getBuildPath() + cmdStr = '%s/build/bin/write_raw_block_test'%(buildPath) + tdLog.info(cmdStr) + os.system(cmdStr) + + self.checkData() + + return + + def run(self): + tdSql.prepare() + self.check() + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/7-tmq/schema.py b/tests/system-test/7-tmq/schema.py index 04224fbc7e86d177829f898855067986aae81746..95c1839964eeb20ac9aa1672713527d197c179b1 100644 --- a/tests/system-test/7-tmq/schema.py +++ b/tests/system-test/7-tmq/schema.py @@ -60,7 +60,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") tdSql.query("drop database if exists %s "%(cdbName)) - tdSql.query("create database %s vgroups 1"%(cdbName)) + tdSql.query("create database %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -115,7 +115,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return diff --git a/tests/system-test/7-tmq/stbFilter.py b/tests/system-test/7-tmq/stbFilter.py index 6b48a6d57076b4baf54d7c08db7cd8a625fab29c..3f862ae0472f6a1312ac5f2ea680adbd4b95f172 100644 --- a/tests/system-test/7-tmq/stbFilter.py +++ b/tests/system-test/7-tmq/stbFilter.py @@ -45,6 +45,7 @@ class TDTestCase: tmqCom.initConsumerTable() tmqCom.create_database(tsql=tdSql, dbName=paraDict["dbName"],dropFlag=paraDict["dropFlag"], vgroups=paraDict['vgroups'],replica=paraDict['replica']) + tdSql.execute("alter database %s wal_retention_period 3600"%(paraDict["dbName"])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/stbTagFilter-1ctb.py b/tests/system-test/7-tmq/stbTagFilter-1ctb.py index c4a7c8cae5551c6374d683f941148f8f054dd53c..1867dc54cb3744077f477f976f88edf59f744dc3 100644 --- a/tests/system-test/7-tmq/stbTagFilter-1ctb.py +++ b/tests/system-test/7-tmq/stbTagFilter-1ctb.py @@ -106,11 +106,12 @@ class TDTestCase: # ctbNum=paraDict["ctbNum"],rowsPerTbl=paraDict["rowsPerTbl"],batchNum=paraDict["batchNum"], # startTs=paraDict["startTs"],ctbStartIdx=paraDict['ctbStartIdx']) + tdSql.execute("alter database dbt wal_retention_period 3600") tdLog.info("create topics from stb1") topicFromStb1 = 'topic_UpperCase_stb1' # queryString = "select ts, c1, c2 from %s.%s where t4 == 'shanghai' or t4 == 'changsha'"%(paraDict['dbName'], paraDict['stbName']) queryString = "select ts, c1, c2, t4 from %s.%s where t4 == 'shanghai' or t4 == 'changsha'"%(paraDict['dbName'], paraDict['stbName']) - sqlString = "create topic %s as %s" %(topicFromStb1, queryString) + sqlString = "create topic `%s` as %s" %(topicFromStb1, queryString) tdLog.info("create topic sql: %s"%sqlString) tdSql.execute(sqlString) @@ -147,7 +148,7 @@ class TDTestCase: tmqCom.checkFileContent(consumerId, queryString) - tdSql.query("drop topic %s"%topicFromStb1) + tdSql.query("drop topic `%s`"%topicFromStb1) tdLog.printNoPrefix("======== test case 1 end ...... ") def tmqCase2(self): @@ -195,7 +196,7 @@ class TDTestCase: topicFromStb1 = 'topic_UpperCase_stb1' queryString = "select ts, c1, c2 from %s.%s where t4 == 'shanghai' or t4 == 'changsha'"%(paraDict['dbName'], paraDict['stbName']) # queryString = "select ts, c1, c2, t4 from %s.%s where t4 == 'shanghai' or t4 == 'changsha'"%(paraDict['dbName'], paraDict['stbName']) - sqlString = "create topic %s as %s" %(topicFromStb1, queryString) + sqlString = "create topic `%s` as %s" %(topicFromStb1, queryString) tdLog.info("create topic sql: %s"%sqlString) tdSql.execute(sqlString) @@ -241,7 +242,7 @@ class TDTestCase: # tmqCom.checkFileContent(consumerId, queryString) - tdSql.query("drop topic %s"%topicFromStb1) + tdSql.query("drop topic `%s`"%topicFromStb1) tdLog.printNoPrefix("======== test case 2 end ...... ") diff --git a/tests/system-test/7-tmq/stbTagFilter-multiCtb.py b/tests/system-test/7-tmq/stbTagFilter-multiCtb.py index c380d201b2d8827c6e3d12f03a0168ed47af0362..67cc60d196bfd31f75e71978145f58ac40b698c7 100644 --- a/tests/system-test/7-tmq/stbTagFilter-multiCtb.py +++ b/tests/system-test/7-tmq/stbTagFilter-multiCtb.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" %(paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -110,7 +111,7 @@ class TDTestCase: topicFromStb1 = 'topic_UpperCase_stb1' queryString = "select ts, c1, c2 from %s.%s where t4 == 'beijing' or t4 == 'changsha'"%(paraDict['dbName'], paraDict['stbName']) # queryString = "select ts, c1, c2, t4 from %s.%s where t4 == 'beijing' or t4 == 'changsha'"%(paraDict['dbName'], paraDict['stbName']) - sqlString = "create topic %s as %s" %(topicFromStb1, queryString) + sqlString = "create topic `%s` as %s" %(topicFromStb1, queryString) tdLog.info("create topic sql: %s"%sqlString) tdSql.execute(sqlString) @@ -147,7 +148,7 @@ class TDTestCase: # tmqCom.checkFileContent(consumerId, queryString) - tdSql.query("drop topic %s"%topicFromStb1) + tdSql.query("drop topic `%s`"%topicFromStb1) tdLog.printNoPrefix("======== test case 1 end ...... ") def tmqCase2(self): @@ -195,7 +196,7 @@ class TDTestCase: topicFromStb1 = 'topic_UpperCase_stb1' # queryString = "select ts, c1, c2 from %s.%s where t4 == 'beijing' or t4 == 'changsha'"%(paraDict['dbName'], paraDict['stbName']) queryString = "select ts, c1, c2, t4 from %s.%s where t4 == 'beijing' or t4 == 'changsha'"%(paraDict['dbName'], paraDict['stbName']) - sqlString = "create topic %s as %s" %(topicFromStb1, queryString) + sqlString = "create topic `%s` as %s" %(topicFromStb1, queryString) tdLog.info("create topic sql: %s"%sqlString) tdSql.execute(sqlString) @@ -243,7 +244,7 @@ class TDTestCase: # tmqCom.checkFileContent(consumerId, queryString) - tdSql.query("drop topic %s"%topicFromStb1) + tdSql.query("drop topic `%s`"%topicFromStb1) tdLog.printNoPrefix("======== test case 2 end ...... ") diff --git a/tests/system-test/7-tmq/subscribeDb.py b/tests/system-test/7-tmq/subscribeDb.py index 0fa9bcfbd461c0498d301e7b702a2ee3f8dd8aa4..631813e7ab864d486411bbd437079181ba9711bb 100644 --- a/tests/system-test/7-tmq/subscribeDb.py +++ b/tests/system-test/7-tmq/subscribeDb.py @@ -13,11 +13,11 @@ from util.dnodes import * class TDTestCase: hostname = socket.gethostname() - #rpcDebugFlagVal = '143' + # rpcDebugFlagVal = '143' #clientCfgDict = {'serverPort': '', 'firstEp': '', 'secondEp':'', 'rpcDebugFlag':'135', 'fqdn':''} #clientCfgDict["rpcDebugFlag"] = rpcDebugFlagVal #updatecfgDict = {'clientCfg': {}, 'serverPort': '', 'firstEp': '', 'secondEp':'', 'rpcDebugFlag':'135', 'fqdn':''} - #updatecfgDict["rpcDebugFlag"] = rpcDebugFlagVal + # updatecfgDict["rpcDebugFlag"] = rpcDebugFlagVal #print ("===================: ", updatecfgDict) def init(self, conn, logSql, replicaVar=1): @@ -52,7 +52,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -99,7 +99,7 @@ class TDTestCase: os.system(shellCmd) def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table if not exists %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" @@ -180,7 +180,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d replica %d" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) + tdSql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -278,7 +278,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d replica %d" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) + tdSql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -345,7 +345,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) tdSql.execute("create table if not exists %s.%s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%(parameterDict['dbName'], parameterDict['stbName'])) tdLog.info("create topics from db") @@ -415,7 +415,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d replica %d" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) + tdSql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() diff --git a/tests/system-test/7-tmq/subscribeDb0.py b/tests/system-test/7-tmq/subscribeDb0.py index 50ef52cb15a5336395154813619976c7933f2dc7..ed13fcbe06be1c82590752b7257528190b972192 100644 --- a/tests/system-test/7-tmq/subscribeDb0.py +++ b/tests/system-test/7-tmq/subscribeDb0.py @@ -52,7 +52,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -99,7 +99,7 @@ class TDTestCase: os.system(shellCmd) def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table if not exists %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" @@ -180,7 +180,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d replica %d" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) + tdSql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -262,7 +262,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d replica %d" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) + tdSql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() diff --git a/tests/system-test/7-tmq/subscribeDb1.py b/tests/system-test/7-tmq/subscribeDb1.py index c5ae44214a0cea58f2c4f3cfee03dd0c3e5918a2..605e862950799b81fe57451a94e62ba086fa0a47 100644 --- a/tests/system-test/7-tmq/subscribeDb1.py +++ b/tests/system-test/7-tmq/subscribeDb1.py @@ -52,7 +52,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -99,7 +99,7 @@ class TDTestCase: os.system(shellCmd) def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table if not exists %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" @@ -123,8 +123,9 @@ class TDTestCase: pre_insert = "insert into " sql = pre_insert - t = time.time() - startTs = int(round(t * 1000)) + # t = 1678609778776 #time.time() + t = 1600000000000 + startTs = t #int(round(t * 1000)) #tdLog.debug("doing insert data into stable:%s rows:%d ..."%(stbName, allRows)) for i in range(ctbNum): sql += " %s_%d values "%(stbName,i) @@ -179,8 +180,8 @@ class TDTestCase: parameterDict['cfg'] = cfgPath self.initConsumerTable() - tdLog.info("create database if not exists %s vgroups %d replica %d" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) - tdSql.execute("create database if not exists %s vgroups %d replica %d" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) + tdLog.info("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) + tdSql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -196,7 +197,7 @@ class TDTestCase: 'startTs': 1640966400000} # 2022-01-01 00:00:00.000 parameterDict['cfg'] = cfgPath - tdSql.execute("create database if not exists %s vgroups %d replica %d" %(parameterDict2['dbName'], parameterDict2['vgroups'], parameterDict2['replica'])) + tdSql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict2['dbName'], parameterDict2['vgroups'], parameterDict2['replica'])) prepareEnvThread2 = threading.Thread(target=self.prepareEnv, kwargs=parameterDict2) prepareEnvThread2.start() @@ -267,7 +268,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d replica %d" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) + tdSql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'], parameterDict['replica'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -283,7 +284,7 @@ class TDTestCase: 'startTs': 1640966400000} # 2022-01-01 00:00:00.000 parameterDict['cfg'] = cfgPath - tdSql.execute("create database if not exists %s vgroups %d replica %d" %(parameterDict2['dbName'], parameterDict2['vgroups'], parameterDict2['replica'])) + tdSql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600" %(parameterDict2['dbName'], parameterDict2['vgroups'], parameterDict2['replica'])) prepareEnvThread2 = threading.Thread(target=self.prepareEnv, kwargs=parameterDict2) prepareEnvThread2.start() diff --git a/tests/system-test/7-tmq/subscribeDb2.py b/tests/system-test/7-tmq/subscribeDb2.py index d045842e45f4f526e5916081774177b22847ef11..60cde8d7f0940a8427e7f76ae31f5c682e36ca57 100644 --- a/tests/system-test/7-tmq/subscribeDb2.py +++ b/tests/system-test/7-tmq/subscribeDb2.py @@ -53,7 +53,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -100,7 +100,7 @@ class TDTestCase: os.system(shellCmd) def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum,rowsPerTbl): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table if not exists %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" @@ -185,7 +185,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -263,7 +263,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() diff --git a/tests/system-test/7-tmq/subscribeDb3.py b/tests/system-test/7-tmq/subscribeDb3.py index 747ea3ba86c56a4008014e044fad5de6f8536f32..b66334a6a66ce3c7818715e74891cb680ac0b2b3 100644 --- a/tests/system-test/7-tmq/subscribeDb3.py +++ b/tests/system-test/7-tmq/subscribeDb3.py @@ -10,6 +10,8 @@ from util.log import * from util.sql import * from util.cases import * from util.dnodes import * +sys.path.append("./7-tmq") +from tmqCommon import * class TDTestCase: hostname = socket.gethostname() @@ -52,7 +54,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) tdSql.query("drop table if exists %s.notifyinfo "%(cdbName)) @@ -67,26 +69,26 @@ class TDTestCase: tdLog.info("consume info sql: %s"%sql) tdSql.query(sql) - def getStartConsumeNotifyFromTmqsim(self,cdbName='cdb'): - while 1: - tdSql.query("select * from %s.notifyinfo"%cdbName) - #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) - if (tdSql.getRows() == 1) and (tdSql.getData(0, 1) == 0): - break - else: - time.sleep(0.1) - return - - def getStartCommitNotifyFromTmqsim(self,cdbName='cdb'): - while 1: - tdSql.query("select * from %s.notifyinfo"%cdbName) - #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) - if tdSql.getRows() == 2 : - print(tdSql.getData(0, 1), tdSql.getData(1, 1)) - if tdSql.getData(1, 1) == 1: - break - time.sleep(0.1) - return + # def getStartConsumeNotifyFromTmqsim(self,cdbName='cdb'): + # while 1: + # tdSql.query("select * from %s.notifyinfo"%cdbName) + # #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) + # if (tdSql.getRows() == 1) and (tdSql.getData(0, 1) == 0): + # break + # else: + # time.sleep(0.1) + # return + # + # def getStartCommitNotifyFromTmqsim(self,cdbName='cdb'): + # while 1: + # tdSql.query("select * from %s.notifyinfo"%cdbName) + # #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) + # if tdSql.getRows() == 2 : + # tdLog.info("row[0][1]: %d, row[1][1]: %d"%(tdSql.getData(0, 1), tdSql.getData(1, 1))) + # if tdSql.getData(1, 1) == 1: + # break + # time.sleep(0.1) + # return def selectConsumeResult(self,expectRows,cdbName='cdb'): resultList=[] @@ -122,7 +124,8 @@ class TDTestCase: os.system(shellCmd) def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum,rowsPerTbl): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tdLog.info("start create tables......") + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table if not exists %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" @@ -137,11 +140,11 @@ class TDTestCase: tsql.execute(sql) event.set() - tdLog.debug("complete to create database[%s], stable[%s] and %d child tables" %(dbName, stbName, ctbNum)) + tdLog.info("complete to create database[%s], stable[%s] and %d child tables" %(dbName, stbName, ctbNum)) return def insert_data(self,tsql,dbName,stbName,ctbNum,rowsPerTbl,batchNum,startTs): - tdLog.debug("start to insert data ............") + tdLog.info("start to insert data ............") tsql.execute("use %s" %dbName) pre_insert = "insert into " sql = pre_insert @@ -163,7 +166,7 @@ class TDTestCase: if sql != pre_insert: #print("insert sql:%s"%sql) tsql.execute(sql) - tdLog.debug("insert data ............ [OK]") + tdLog.info("insert data ............ [OK]") return def prepareEnv(self, **parameterDict): @@ -203,7 +206,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -226,13 +229,13 @@ class TDTestCase: event.wait() tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 20 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) tdLog.info("wait the notify info of start consume") - self.getStartConsumeNotifyFromTmqsim() + tmqCom.getStartConsumeNotifyFromTmqsim() tdLog.info("pkill consume processor") if (platform.system().lower() == 'windows'): @@ -280,13 +283,13 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() tdLog.info("create topics from db") - topicName1 = 'topic_db1' + topicName1 = 'topic_db11' tdSql.execute("create topic %s as database %s" %(topicName1, parameterDict['dbName'])) consumerId = 0 @@ -310,7 +313,7 @@ class TDTestCase: # time.sleep(6) tdLog.info("start to wait commit notify") - self.getStartCommitNotifyFromTmqsim() + tmqCom.getStartCommitNotifyFromTmqsim() tdLog.info("pkill consume processor") if (platform.system().lower() == 'windows'): @@ -333,7 +336,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows >= expectrowcnt or totalConsumeRows <= 0: + if totalConsumeRows > expectrowcnt or totalConsumeRows <= 0: tdLog.info("act consume rows: %d, expect consume rows between %d and 0"%(totalConsumeRows, expectrowcnt)) tdLog.exit("tmq consume rows error!") diff --git a/tests/system-test/7-tmq/subscribeDb4.py b/tests/system-test/7-tmq/subscribeDb4.py index 7f5169361c1e3130bef0c29fd8eef1e6837248d8..764362c70882e0851d3cd5eb80ac4f0096a71113 100644 --- a/tests/system-test/7-tmq/subscribeDb4.py +++ b/tests/system-test/7-tmq/subscribeDb4.py @@ -31,7 +31,8 @@ class TDTestCase: 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 'pollDelay': 20, 'showMsg': 1, - 'showRow': 1} + 'showRow': 1, + 'snapshot': 1} cdbName = 'cdb' # some parameter to consumer processor @@ -42,7 +43,7 @@ class TDTestCase: ifManualCommit = 1 groupId = 'group.id:cgrp1' autoCommit = 'enable.auto.commit:true' - autoCommitInterval = 'auto.commit.interval.ms:1000' + autoCommitInterval = 'auto.commit.interval.ms:100' autoOffset = 'auto.offset.reset:earliest' pollDelay = 20 @@ -64,6 +65,7 @@ class TDTestCase: tmqCom.initConsumerTable(self.cdbName) tdCom.create_database(tdSql,self.paraDict["dbName"],self.paraDict["dropFlag"]) + tdSql.execute("alter database %s wal_retention_period 3600" % (self.paraDict['dbName'])) self.paraDict["stbName"] = 'stb1' tdCom.create_stable(tdSql,dbname=self.paraDict["dbName"],stbname=self.paraDict["stbName"],column_elm_list=self.paraDict["colSchema"],tag_elm_list=self.paraDict["tagSchema"],count=1, default_stbname_prefix=self.paraDict["stbName"]) @@ -86,7 +88,7 @@ class TDTestCase: tmqCom.insertConsumerInfo(self.consumerId, self.expectrowcnt,topicList,keyList,self.ifcheckdata,self.ifManualCommit) tdLog.info("start consume processor") - tmqCom.startTmqSimProcess(self.pollDelay,self.paraDict["dbName"],self.showMsg, self.showRow,self.cdbName) + tmqCom.startTmqSimProcess(self.pollDelay,self.paraDict["dbName"],self.showMsg, self.showRow,self.cdbName,0,0,self.paraDict["snapshot"]) tdLog.info("After waiting for a commit notify, drop one stable") #time.sleep(3) diff --git a/tests/system-test/7-tmq/subscribeStb.py b/tests/system-test/7-tmq/subscribeStb.py index 3ff0b25ff6b4585a8abc4061e7e46abced77d15e..53f1a34d58d36ea9b4ac28fee1bfef2ab9d1d7c0 100644 --- a/tests/system-test/7-tmq/subscribeStb.py +++ b/tests/system-test/7-tmq/subscribeStb.py @@ -59,7 +59,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -114,7 +114,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return @@ -226,12 +226,11 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 10 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) - time.sleep(5) self.create_ctables(tdSql, parameterDict["dbName"], parameterDict["stbName"], parameterDict["ctbNum"]) self.insert_data(tdSql,\ parameterDict["dbName"],\ @@ -307,7 +306,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 10 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) diff --git a/tests/system-test/7-tmq/subscribeStb0.py b/tests/system-test/7-tmq/subscribeStb0.py index 1463cad627a23dd106d6afb78a4ee274345a840f..06aa18c9b6c79a1ee11a4e236340023c08714137 100644 --- a/tests/system-test/7-tmq/subscribeStb0.py +++ b/tests/system-test/7-tmq/subscribeStb0.py @@ -59,7 +59,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -114,7 +114,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return @@ -228,7 +228,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -303,7 +303,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt/4,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -315,7 +315,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt/4: + if totalConsumeRows < expectrowcnt/4: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt/4)) tdLog.exit("tmq consume rows error!") @@ -333,7 +333,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt: + if totalConsumeRows < expectrowcnt: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt)) tdLog.exit("tmq consume rows error!") @@ -386,7 +386,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt/4,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -398,7 +398,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt/4: + if totalConsumeRows < expectrowcnt/4: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt/4)) tdLog.exit("tmq consume rows error!") @@ -416,7 +416,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != (expectrowcnt * (1 + 1/4)): + if totalConsumeRows < (expectrowcnt * (1 + 1/4)): tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt)) tdLog.exit("tmq consume rows error!") diff --git a/tests/system-test/7-tmq/subscribeStb1.py b/tests/system-test/7-tmq/subscribeStb1.py index edbe1bc3c6dbcbef26a9068c3d644db03d1d9d12..25d09c38e2060dc0c5ef213a0c36a4bde4738866 100644 --- a/tests/system-test/7-tmq/subscribeStb1.py +++ b/tests/system-test/7-tmq/subscribeStb1.py @@ -59,7 +59,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -114,7 +114,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return @@ -233,7 +233,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt/4,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -245,8 +245,8 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt/4: - tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt/4)) + tdLog.info("act consume rows: %d, expect consume rows greater than or equal to: %d"%(totalConsumeRows, expectrowcnt/4)) + if totalConsumeRows < expectrowcnt/4: tdLog.exit("tmq consume rows error!") self.initConsumerInfoTable() @@ -267,8 +267,8 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt: - tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt)) + tdLog.info("act consume rows: %d, expect consume rows greater than or equal to: %d"%(totalConsumeRows, expectrowcnt)) + if totalConsumeRows < expectrowcnt: tdLog.exit("tmq consume rows error!") tdSql.query("drop topic %s"%topicFromStb1) @@ -320,7 +320,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) diff --git a/tests/system-test/7-tmq/subscribeStb2.py b/tests/system-test/7-tmq/subscribeStb2.py index 6c3e122902cc907dacd8297d95f27c6289cad176..cdbc41a59351c0f67205244ffdae69f32bf59e6b 100644 --- a/tests/system-test/7-tmq/subscribeStb2.py +++ b/tests/system-test/7-tmq/subscribeStb2.py @@ -59,7 +59,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -114,7 +114,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return @@ -233,7 +233,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume 0 processor") - pollDelay = 100 + pollDelay = 10 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -251,6 +251,7 @@ class TDTestCase: tdLog.info("start consume 1 processor") self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) + tdLog.sleep(2) tdLog.info("start one new thread to insert data") parameterDict['actionType'] = actionType.INSERT_DATA @@ -271,6 +272,7 @@ class TDTestCase: tdLog.info("start consume 2 processor") self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) + tdLog.sleep(2) tdLog.info("start one new thread to insert data") parameterDict['actionType'] = actionType.INSERT_DATA @@ -338,7 +340,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume 0 processor") - pollDelay = 100 + pollDelay = 20 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -380,6 +382,7 @@ class TDTestCase: tdLog.info("start consume 2 processor") self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) + tdLog.sleep(2) tdLog.info("start one new thread to insert data") parameterDict['actionType'] = actionType.INSERT_DATA @@ -394,7 +397,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt*2: + if totalConsumeRows < expectrowcnt*2: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt*2)) tdLog.exit("tmq consume rows error!") diff --git a/tests/system-test/7-tmq/subscribeStb3.py b/tests/system-test/7-tmq/subscribeStb3.py index 025f403282e46eab4893062069bcea820124203b..6f3230e68791c9c1806abf576936cd5878bd7b06 100644 --- a/tests/system-test/7-tmq/subscribeStb3.py +++ b/tests/system-test/7-tmq/subscribeStb3.py @@ -59,7 +59,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -114,7 +114,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return @@ -215,7 +215,8 @@ class TDTestCase: parameterDict["stbName"],\ parameterDict["ctbNum"],\ parameterDict["rowsPerTbl"],\ - parameterDict["batchNum"]) + parameterDict["batchNum"],\ + parameterDict["startTs"]) tdLog.info("create topics from stb1") topicFromStb1 = 'topic_stb1' @@ -233,7 +234,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume 0 processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -269,7 +270,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt-10000: + if totalConsumeRows < expectrowcnt-10000: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt-10000)) tdLog.exit("tmq consume rows error!") @@ -328,7 +329,8 @@ class TDTestCase: parameterDict["stbName"],\ parameterDict["ctbNum"],\ parameterDict["rowsPerTbl"],\ - parameterDict["batchNum"]) + parameterDict["batchNum"],\ + parameterDict["startTs"]) tdLog.info("create topics from stb1") topicFromStb1 = 'topic_stb1' @@ -346,7 +348,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt/4,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -415,7 +417,8 @@ class TDTestCase: parameterDict["stbName"],\ parameterDict["ctbNum"],\ parameterDict["rowsPerTbl"],\ - parameterDict["batchNum"]) + parameterDict["batchNum"],\ + parameterDict["startTs"]) tdLog.info("create topics from stb1") topicFromStb1 = 'topic_stb1' @@ -433,7 +436,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt/4,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -445,7 +448,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt/4: + if totalConsumeRows < expectrowcnt/4: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt/4)) tdLog.exit("tmq consume rows error!") @@ -467,7 +470,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt/4: + if totalConsumeRows < expectrowcnt/4: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt/4)) tdLog.exit("tmq consume rows error!") @@ -502,7 +505,8 @@ class TDTestCase: parameterDict["stbName"],\ parameterDict["ctbNum"],\ parameterDict["rowsPerTbl"],\ - parameterDict["batchNum"]) + parameterDict["batchNum"],\ + parameterDict["startTs"]) tdLog.info("create topics from stb1") topicFromStb1 = 'topic_stb1' @@ -520,7 +524,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt/4,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -532,7 +536,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt/4: + if totalConsumeRows < expectrowcnt/4: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt/4)) tdLog.exit("tmq consume rows error!") @@ -555,7 +559,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - if totalConsumeRows != expectrowcnt*(1/2+1/4): + if totalConsumeRows < expectrowcnt*(1/2+1/4): tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt*(1/2+1/4))) tdLog.exit("tmq consume rows error!") diff --git a/tests/system-test/7-tmq/subscribeStb4.py b/tests/system-test/7-tmq/subscribeStb4.py index 6aa3da66a46b316c55b2586bfc4c82f96fc33a8c..ed467b09b32aa862eabd1ef22c1872aeedf8d7d0 100644 --- a/tests/system-test/7-tmq/subscribeStb4.py +++ b/tests/system-test/7-tmq/subscribeStb4.py @@ -59,7 +59,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -114,7 +114,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return @@ -231,7 +231,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) @@ -305,7 +305,7 @@ class TDTestCase: self.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor") - pollDelay = 100 + pollDelay = 5 showMsg = 1 showRow = 1 self.startTmqSimProcess(buildPath,cfgPath,pollDelay,parameterDict["dbName"],showMsg, showRow) diff --git a/tests/system-test/7-tmq/tmq3mnodeSwitch.py b/tests/system-test/7-tmq/tmq3mnodeSwitch.py index abe8ed29450fc105efb983ce2083a63e717d3e39..0740830696987a6009db020de14bdc768d56c69a 100644 --- a/tests/system-test/7-tmq/tmq3mnodeSwitch.py +++ b/tests/system-test/7-tmq/tmq3mnodeSwitch.py @@ -138,34 +138,6 @@ class TDTestCase: else: tdLog.exit("three mnodes is not ready in 10s ") - def checkFileContent(self, consumerId, queryString): - buildPath = tdCom.getBuildPath() - cfgPath = tdCom.getClientCfgPath() - dstFile = '%s/../log/dstrows_%d.txt'%(cfgPath, consumerId) - cmdStr = '%s/build/bin/taos -c %s -s "%s >> %s"'%(buildPath, cfgPath, queryString, dstFile) - tdLog.info(cmdStr) - os.system(cmdStr) - - consumeRowsFile = '%s/../log/consumerid_%d.txt'%(cfgPath, consumerId) - tdLog.info("rows file: %s, %s"%(consumeRowsFile, dstFile)) - - consumeFile = open(consumeRowsFile, mode='r') - queryFile = open(dstFile, mode='r') - - # skip first line for it is schema - queryFile.readline() - - while True: - dst = queryFile.readline() - src = consumeFile.readline() - - if dst: - if dst != src: - tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) - else: - break - return - def tmqCase1(self): tdLog.printNoPrefix("======== test case 1: ") paraDict = {'dbName': 'db1', @@ -200,6 +172,7 @@ class TDTestCase: tdLog.info("async insert data") pThread = tmqCom.asyncInsertData(paraDict) + tdSql.execute("alter database %s wal_retention_period 3600" %(paraDict['dbName'])) tdLog.info("create topics from stb with filter") # queryString = "select ts, log(c1), ceil(pow(c1,3)) from %s.%s where c1 %% 7 == 0" %(paraDict['dbName'], paraDict['stbName']) @@ -211,7 +184,7 @@ class TDTestCase: # init consume info, and start tmq_sim, then check consume result tdLog.info("insert consume info to consume processor") consumerId = 0 - expectrowcnt = paraDict["rowsPerTbl"] * paraDict["ctbNum"] + expectrowcnt = paraDict["rowsPerTbl"] * paraDict["ctbNum"] * 2 # because taosd switch, may be consume duplication data topicList = topicNameList[0] ifcheckdata = 1 ifManualCommit = 1 @@ -236,8 +209,8 @@ class TDTestCase: tdDnodes[0].starttaosd() self.check3mnode() - tdLog.info("3. stop dnode 1") - tdDnodes[1].stoptaosd() + tdLog.info("3. stop dnode 2") + tdDnodes[2].stoptaosd() time.sleep(10) self.check3mnode1off() @@ -251,11 +224,12 @@ class TDTestCase: expectRows = 1 resultList = tmqCom.selectConsumeResult(expectRows) - if expectRowsList[0] != resultList[0]: - tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) + tdLog.info("expect consume rows: %d should less/equal than act consume rows: %d"%(expectRowsList[0], resultList[0])) + if expectRowsList[0] > resultList[0]: tdLog.exit("0 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + if expectRowsList[0] == resultList[0]: + tmqCom.checkFileContent(consumerId, queryString) time.sleep(10) for i in range(len(topicNameList)): diff --git a/tests/system-test/7-tmq/tmqAlterSchema.py b/tests/system-test/7-tmq/tmqAlterSchema.py index a70678219f15ba94b7f9ceb1f81b9aa3881660d4..1a8b0693b86cae8d12eaeb11f3af91f587a23a6f 100644 --- a/tests/system-test/7-tmq/tmqAlterSchema.py +++ b/tests/system-test/7-tmq/tmqAlterSchema.py @@ -65,6 +65,7 @@ class TDTestCase: queryStringList = [] tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" %(paraDict['dbName'])) tdLog.info("create stb") tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) tdLog.info("create ctb") @@ -175,6 +176,7 @@ class TDTestCase: queryStringList = [] tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" %(paraDict['dbName'])) tdLog.info("create stb") tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) tdLog.info("create ntb") diff --git a/tests/system-test/7-tmq/tmqAutoCreateTbl.py b/tests/system-test/7-tmq/tmqAutoCreateTbl.py index 41073d83ae13b5a3828bbc758d8d1d2c600f8ca6..5d0af636b206e5c13ca403dd35c70fabeb2601cd 100644 --- a/tests/system-test/7-tmq/tmqAutoCreateTbl.py +++ b/tests/system-test/7-tmq/tmqAutoCreateTbl.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1, wal_retention_size=-1,wal_retention_period=-1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) # tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqCheckData.py b/tests/system-test/7-tmq/tmqCheckData.py index 04d0744ab595279ac834e62669cb100df113d253..cb5a40642aab7ba2053780b898fa498e2c8b49a3 100644 --- a/tests/system-test/7-tmq/tmqCheckData.py +++ b/tests/system-test/7-tmq/tmqCheckData.py @@ -5,6 +5,7 @@ import time import socket import os import threading +import math from util.log import * from util.sql import * @@ -21,34 +22,6 @@ class TDTestCase: tdSql.init(conn.cursor()) #tdSql.init(conn.cursor(), logSql) # output sql.txt file - def checkFileContent(self, consumerId, queryString): - buildPath = tdCom.getBuildPath() - cfgPath = tdCom.getClientCfgPath() - dstFile = '%s/../log/dstrows_%d.txt'%(cfgPath, consumerId) - cmdStr = '%s/build/bin/taos -c %s -s "%s >> %s"'%(buildPath, cfgPath, queryString, dstFile) - tdLog.info(cmdStr) - os.system(cmdStr) - - consumeRowsFile = '%s/../log/consumerid_%d.txt'%(cfgPath, consumerId) - tdLog.info("rows file: %s, %s"%(consumeRowsFile, dstFile)) - - consumeFile = open(consumeRowsFile, mode='r') - queryFile = open(dstFile, mode='r') - - # skip first line for it is schema - queryFile.readline() - - while True: - dst = queryFile.readline() - src = consumeFile.readline() - - if dst: - if dst != src: - tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) - else: - break - return - def tmqCase1(self): tdLog.printNoPrefix("======== test case 1: ") paraDict = {'dbName': 'db1', @@ -80,6 +53,7 @@ class TDTestCase: tdLog.info("insert data") tmqCom.insert_data(tdSql,paraDict["dbName"],paraDict["ctbPrefix"],paraDict["ctbNum"],paraDict["rowsPerTbl"],paraDict["batchNum"],paraDict["startTs"]) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create topics from stb with filter") queryString = "select ts, log(c1), ceil(pow(c1,3)) from %s.%s where c1 %% 7 == 0" %(paraDict['dbName'], paraDict['stbName']) sqlString = "create topic %s as %s" %(topicNameList[0], queryString) @@ -109,7 +83,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) tdLog.exit("0 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) # reinit consume info, and start tmq_sim, then check consume result tmqCom.initConsumerTable() @@ -135,7 +109,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[1], resultList[0])) tdLog.exit("1 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) # reinit consume info, and start tmq_sim, then check consume result tmqCom.initConsumerTable() @@ -161,7 +135,7 @@ class TDTestCase: # tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[2], resultList[0])) # tdLog.exit("2 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) time.sleep(10) for i in range(len(topicNameList)): diff --git a/tests/system-test/7-tmq/tmqCheckData1.py b/tests/system-test/7-tmq/tmqCheckData1.py index b9dac62833ba45dc63fca65e1b6f642265b655dd..b4fec94dcc3a2a266a35400dc789ee13aa463caf 100644 --- a/tests/system-test/7-tmq/tmqCheckData1.py +++ b/tests/system-test/7-tmq/tmqCheckData1.py @@ -21,34 +21,6 @@ class TDTestCase: tdSql.init(conn.cursor()) #tdSql.init(conn.cursor(), logSql) # output sql.txt file - def checkFileContent(self, consumerId, queryString): - buildPath = tdCom.getBuildPath() - cfgPath = tdCom.getClientCfgPath() - dstFile = '%s/../log/dstrows_%d.txt'%(cfgPath, consumerId) - cmdStr = '%s/build/bin/taos -c %s -s "%s >> %s"'%(buildPath, cfgPath, queryString, dstFile) - tdLog.info(cmdStr) - os.system(cmdStr) - - consumeRowsFile = '%s/../log/consumerid_%d.txt'%(cfgPath, consumerId) - tdLog.info("rows file: %s, %s"%(consumeRowsFile, dstFile)) - - consumeFile = open(consumeRowsFile, mode='r') - queryFile = open(dstFile, mode='r') - - # skip first line for it is schema - queryFile.readline() - - while True: - dst = queryFile.readline() - src = consumeFile.readline() - - if dst: - if dst != src: - tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) - else: - break - return - def tmqCase1(self): tdLog.printNoPrefix("======== test case 1: ") paraDict = {'dbName': 'db1', @@ -73,6 +45,7 @@ class TDTestCase: expectRowsList = [] tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) tdLog.info("create ctb") @@ -109,7 +82,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) tdLog.exit("0 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) # reinit consume info, and start tmq_sim, then check consume result tmqCom.initConsumerTable() @@ -134,7 +107,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[1], resultList[0])) tdLog.exit("1 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) # reinit consume info, and start tmq_sim, then check consume result tmqCom.initConsumerTable() @@ -159,7 +132,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[2], resultList[0])) tdLog.exit("2 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) time.sleep(10) for i in range(len(topicNameList)): diff --git a/tests/system-test/7-tmq/tmqCommon.py b/tests/system-test/7-tmq/tmqCommon.py index 4cda0624010305743e4249dd87594f1cf255b037..6b633fa19384dbd1a8afcbb088e9660800969b65 100644 --- a/tests/system-test/7-tmq/tmqCommon.py +++ b/tests/system-test/7-tmq/tmqCommon.py @@ -10,7 +10,7 @@ ################################################################### # -*- coding: utf-8 -*- - +import math from asyncore import loop from collections import defaultdict import subprocess @@ -129,11 +129,16 @@ class TMQCom: def stopTmqSimProcess(self, processorName): psCmd = "unset LD_PRELOAD; ps -ef|grep -w %s|grep -v grep | awk '{print $2}'"%(processorName) + if platform.system().lower() == 'windows': + psCmd = "ps -ef|grep -w %s|grep -v grep | awk '{print $2}'"%(processorName) processID = subprocess.check_output(psCmd, shell=True).decode("utf-8") onlyKillOnceWindows = 0 while(processID): if not platform.system().lower() == 'windows' or (onlyKillOnceWindows == 0 and platform.system().lower() == 'windows'): - killCmd = "unset LD_PRELOAD; kill -INT %s > /dev/null 2>&1" % processID + if platform.system().lower() == 'windows': + killCmd = "kill -INT %s > /dev/nul 2>&1" % processID + else: + killCmd = "unset LD_PRELOAD; kill -INT %s > /dev/null 2>&1" % processID os.system(killCmd) onlyKillOnceWindows = 1 time.sleep(0.2) @@ -143,29 +148,23 @@ class TMQCom: def getStartConsumeNotifyFromTmqsim(self,cdbName='cdb',rows=1): loopFlag = 1 while loopFlag: - tdSql.query("select * from %s.notifyinfo"%cdbName) - #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) + tdSql.query("select * from %s.notifyinfo where cmdid = 0"%cdbName) actRows = tdSql.getRows() + tdLog.info("row: %d"%(actRows)) if (actRows >= rows): - for i in range(actRows): - if tdSql.getData(i, 1) == 0: - loopFlag = 0 - break - time.sleep(0.1) + loopFlag = 0 + time.sleep(0.02) return - def getStartCommitNotifyFromTmqsim(self,cdbName='cdb',rows=2): + def getStartCommitNotifyFromTmqsim(self,cdbName='cdb',rows=1): loopFlag = 1 while loopFlag: - tdSql.query("select * from %s.notifyinfo"%cdbName) - #tdLog.info("row: %d, %l64d, %l64d"%(tdSql.getData(0, 1),tdSql.getData(0, 2),tdSql.getData(0, 3)) + tdSql.query("select * from %s.notifyinfo where cmdid = 1"%cdbName) actRows = tdSql.getRows() + tdLog.info("row: %d"%(actRows)) if (actRows >= rows): - for i in range(actRows): - if tdSql.getData(i, 1) == 1: - loopFlag = 0 - break - time.sleep(0.1) + loopFlag = 0 + time.sleep(0.02) return def create_database(self,tsql, dbName,dropFlag=1,vgroups=4,replica=1): @@ -462,18 +461,24 @@ class TMQCom: for i in range(0,skipRowsOfCons): consumeFile.readline() - lines = 0 while True: dst = queryFile.readline() src = consumeFile.readline() - lines += 1 - if dst: - if dst != src: - tdLog.info("src row: %s"%src) - tdLog.info("dst row: %s"%dst) - tdLog.exit("consumerId %d consume rows[%d] is not match the rows by direct query"%(consumerId, lines)) - else: + dstSplit = dst.split(',') + srcSplit = src.split(',') + + if not dst or not src: break + if len(dstSplit) != len(srcSplit): + tdLog.exit("consumerId %d consume rows len is not match the rows by direct query,len(dstSplit):%d != len(srcSplit):%d, dst:%s, src:%s" + %(consumerId, len(dstSplit), len(srcSplit), dst, src)) + + for i in range(len(dstSplit)): + if srcSplit[i] != dstSplit[i]: + srcFloat = float(srcSplit[i]) + dstFloat = float(dstSplit[i]) + if not math.isclose(srcFloat, dstFloat, abs_tol=1e-9): + tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) return def getResultFileByTaosShell(self, consumerId, queryString): diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb-1ctb-funcNFilter.py b/tests/system-test/7-tmq/tmqConsFromTsdb-1ctb-funcNFilter.py index f372a2b7428a77b02b8dcdb5c4c546756ef7e1f7..3ad1d097e11b85f04f1d0cc9b2cd75a9ea1bdb0a 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb-1ctb-funcNFilter.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb-1ctb-funcNFilter.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb-1ctb.py b/tests/system-test/7-tmq/tmqConsFromTsdb-1ctb.py index c7f95f6f41cbf72e8d64c3a9bd8218dfd7a1c6d5..fdd683d08daba5625017029a3363b379d2a206b1 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb-1ctb.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb-1ctb.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb-funcNFilter.py b/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb-funcNFilter.py index 26dacf514d4f66273d36f6ac3fe49ee17602747a..f05f0abeff3f3f6dabde18ac3d3543d9df032f4e 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb-funcNFilter.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb-funcNFilter.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb.py b/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb.py index d6f100041b15c205e8294cca964353d880b9ecc4..75b49a34fc583217e5ee0bb81324abc8421ed31a 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg.py b/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg.py index 87832ac0ef2169ad2895928ceb20121ae17ecba9..26f7a9fb4d1300907807651a5e2fd9dd80579725 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb-mutilVg.py @@ -16,6 +16,8 @@ sys.path.append("./7-tmq") from tmqCommon import * class TDTestCase: + updatecfgDict = {"tsdbDebugFlag":135} + def __init__(self): self.vgroups = 4 self.ctbNum = 10 @@ -54,6 +56,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb.py b/tests/system-test/7-tmq/tmqConsFromTsdb.py index 8ed4a6df973b57f7302d5a2c193debffbf7286a1..cca29c178db281b86d145b8623f72a2dd8df1366 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=self.replicaVar) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb1-1ctb-funcNFilter.py b/tests/system-test/7-tmq/tmqConsFromTsdb1-1ctb-funcNFilter.py index 6a03f0f75192dda0b8b8394b1733bdec02222bda..00d2491c97b0a178fbfd289cf44e2617107fdfe9 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb1-1ctb-funcNFilter.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb1-1ctb-funcNFilter.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb1-1ctb.py b/tests/system-test/7-tmq/tmqConsFromTsdb1-1ctb.py index 4dcc0b963f8e883326132f5db3bc04a6edd349d1..3b1dbae443f0e8d6f71dc3c8127975790c23401a 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb1-1ctb.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb1-1ctb.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -200,7 +201,7 @@ class TDTestCase: tdLog.info("pkill consume processor") tdCom.killProcessor("tmq_sim") - # time.sleep(10) + time.sleep(10) # reinit consume info, and start tmq_sim, then check consume result tmqCom.initConsumerTable() diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb-funcNFilter.py b/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb-funcNFilter.py index 95ce03e6533223288b2424dcc22932b1e9b54a5a..a799fa57195fe84065c7bb0b295dc7c0f14cdd09 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb-funcNFilter.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb-funcNFilter.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -192,7 +193,7 @@ class TDTestCase: topicList = topicNameList[0] ifcheckdata = 1 ifManualCommit = 1 - keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:300, auto.offset.reset:earliest' + keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:100, auto.offset.reset:earliest' tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor 0") diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb.py b/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb.py index 8ff01444f81c5b5bdb52c3885970faca5b779a1b..f0bedbb187b9987e8f367f1afed7b69fb4c41001 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb.py @@ -18,8 +18,8 @@ from tmqCommon import * class TDTestCase: def __init__(self): self.vgroups = 4 - self.ctbNum = 3000 - self.rowsPerTbl = 70 + self.ctbNum = 1000 + self.rowsPerTbl = 100 def init(self, conn, logSql, replicaVar=1): self.replicaVar = int(replicaVar) @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -112,15 +113,15 @@ class TDTestCase: # init consume info, and start tmq_sim, then check consume result tdLog.info("insert consume info to consume processor") consumerId = 3 - expectrowcnt = math.ceil(paraDict["rowsPerTbl"] * paraDict["ctbNum"] / 3) + expectrowcnt = math.ceil(paraDict["rowsPerTbl"] * paraDict["ctbNum"]) topicList = topicNameList[0] ifcheckdata = 1 ifManualCommit = 1 - keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:1000, auto.offset.reset:earliest' + keyList = 'group.id:cgrp3, enable.auto.commit:true, auto.commit.interval.ms:100, auto.offset.reset:earliest' tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) consumerId = 4 - expectrowcnt = math.ceil(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * 2/3) + expectrowcnt = math.ceil(paraDict["rowsPerTbl"] * paraDict["ctbNum"]) tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor 0") @@ -131,8 +132,8 @@ class TDTestCase: resultList = tmqCom.selectConsumeResult(expectRows) actConsumeTotalRows = resultList[0] + resultList[1] - if not (totalRowsInserted == actConsumeTotalRows): - tdLog.info("sum of two consume rows: %d should be equal to total inserted rows: %d"%(actConsumeTotalRows, totalRowsInserted)) + tdLog.info("sum of two consume rows: %d should be greater than or equal to total inserted rows: %d"%(actConsumeTotalRows, totalRowsInserted)) + if not (totalRowsInserted <= actConsumeTotalRows): tdLog.exit("%d tmq consume rows error!"%consumerId) time.sleep(10) @@ -188,7 +189,7 @@ class TDTestCase: topicList = topicNameList[0] ifcheckdata = 1 ifManualCommit = 1 - keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:1000, auto.offset.reset:earliest' + keyList = 'group.id:cgrp4, enable.auto.commit:true, auto.commit.interval.ms:100, auto.offset.reset:earliest' tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor 0") @@ -216,9 +217,9 @@ class TDTestCase: actConsumeTotalRows = resultList[0] - if not (actConsumeTotalRows > 0 and actConsumeTotalRows < totalRowsInserted): - tdLog.info("act consume rows: %d"%(actConsumeTotalRows)) - tdLog.info("and second consume rows should be between 0 and %d"%(totalRowsInserted)) + tdLog.info("act consume rows: %d"%(actConsumeTotalRows)) + tdLog.info("and second consume rows should be between 0 and %d"%(totalRowsInserted)) + if not (actConsumeTotalRows > 0 and actConsumeTotalRows <= totalRowsInserted): tdLog.exit("%d tmq consume rows error!"%consumerId) time.sleep(10) diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg.py b/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg.py index da8ac6c57deaf99d9871134489b290381b570306..a63927dd8bdee0483cc943ececaac1855248ef57 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb1-mutilVg.py @@ -18,7 +18,7 @@ from tmqCommon import * class TDTestCase: def __init__(self): self.vgroups = 4 - self.ctbNum = 10 + self.ctbNum = 4 self.rowsPerTbl = 10000 def init(self, conn, logSql, replicaVar=1): @@ -41,7 +41,7 @@ class TDTestCase: 'ctbStartIdx': 0, 'ctbNum': 10, 'rowsPerTbl': 10000, - 'batchNum': 10, + 'batchNum': 1000, 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 'pollDelay': 3, 'showMsg': 1, @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -112,15 +113,15 @@ class TDTestCase: # init consume info, and start tmq_sim, then check consume result tdLog.info("insert consume info to consume processor") consumerId = 3 - expectrowcnt = math.ceil(paraDict["rowsPerTbl"] * paraDict["ctbNum"] / 3) + expectrowcnt = math.ceil(paraDict["rowsPerTbl"] * paraDict["ctbNum"]) topicList = topicNameList[0] ifcheckdata = 1 ifManualCommit = 1 - keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:200, auto.offset.reset:earliest' + keyList = 'group.id:cgrp3, enable.auto.commit:true, auto.commit.interval.ms:200, auto.offset.reset:earliest' tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) consumerId = 4 - expectrowcnt = math.ceil(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * 2/3) + expectrowcnt = math.ceil(paraDict["rowsPerTbl"] * paraDict["ctbNum"]) tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor 0") @@ -130,9 +131,9 @@ class TDTestCase: expectRows = 2 resultList = tmqCom.selectConsumeResult(expectRows) actConsumeTotalRows = resultList[0] + resultList[1] - - if not (totalRowsInserted == actConsumeTotalRows): - tdLog.info("sum of two consume rows: %d should be equal to total inserted rows: %d"%(actConsumeTotalRows, totalRowsInserted)) + + tdLog.info("sum of two consume rows: %d should be greater than or equal to total inserted rows: %d"%(actConsumeTotalRows, totalRowsInserted)) + if not (totalRowsInserted <= actConsumeTotalRows): tdLog.exit("%d tmq consume rows error!"%consumerId) time.sleep(10) @@ -188,7 +189,7 @@ class TDTestCase: topicList = topicNameList[0] ifcheckdata = 1 ifManualCommit = 1 - keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:200, auto.offset.reset:earliest' + keyList = 'group.id:cgrp4, enable.auto.commit:true, auto.commit.interval.ms:200, auto.offset.reset:earliest' tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor 0") @@ -216,7 +217,7 @@ class TDTestCase: actConsumeTotalRows = resultList[0] - if not (actConsumeTotalRows > 0 and actConsumeTotalRows < totalRowsInserted): + if not (actConsumeTotalRows > 0 and actConsumeTotalRows <= totalRowsInserted): tdLog.info("act consume rows: %d"%(actConsumeTotalRows)) tdLog.info("and second consume rows should be between 0 and %d"%(totalRowsInserted)) tdLog.exit("%d tmq consume rows error!"%consumerId) diff --git a/tests/system-test/7-tmq/tmqConsFromTsdb1.py b/tests/system-test/7-tmq/tmqConsFromTsdb1.py index b910caf420de5efd6fef315e220920599f946435..8fcc991d4e3904da04480c7bbc28cac49cf5c068 100644 --- a/tests/system-test/7-tmq/tmqConsFromTsdb1.py +++ b/tests/system-test/7-tmq/tmqConsFromTsdb1.py @@ -41,7 +41,7 @@ class TDTestCase: 'ctbStartIdx': 0, 'ctbNum': 10, 'rowsPerTbl': 10000, - 'batchNum': 10, + 'batchNum': 100, 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 'pollDelay': 3, 'showMsg': 1, @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=self.replicaVar) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -87,7 +88,7 @@ class TDTestCase: 'rowsPerTbl': 10000, 'batchNum': 10, 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 - 'pollDelay': 25, + 'pollDelay': 10, 'showMsg': 1, 'showRow': 1, 'snapshot': 1} @@ -116,7 +117,7 @@ class TDTestCase: topicList = topicNameList[0] ifcheckdata = 1 ifManualCommit = 1 - keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:200, auto.offset.reset:earliest' + keyList = 'group.id:cgrp3, enable.auto.commit:true, auto.commit.interval.ms:200, auto.offset.reset:earliest' tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) consumerId = 4 @@ -131,8 +132,8 @@ class TDTestCase: resultList = tmqCom.selectConsumeResult(expectRows) actConsumeTotalRows = resultList[0] + resultList[1] + tdLog.info("sum of two consume rows: %d should be equal to total inserted rows: %d"%(actConsumeTotalRows, totalRowsInserted)) if not (totalRowsInserted == actConsumeTotalRows): - tdLog.info("sum of two consume rows: %d should be equal to total inserted rows: %d"%(actConsumeTotalRows, totalRowsInserted)) tdLog.exit("%d tmq consume rows error!"%consumerId) time.sleep(10) @@ -188,7 +189,7 @@ class TDTestCase: topicList = topicNameList[0] ifcheckdata = 1 ifManualCommit = 1 - keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:200, auto.offset.reset:earliest' + keyList = 'group.id:cgrp4, enable.auto.commit:true, auto.commit.interval.ms:200, auto.offset.reset:earliest' tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) tdLog.info("start consume processor 0") @@ -213,12 +214,11 @@ class TDTestCase: expectRows = 1 resultList = tmqCom.selectConsumeResult(expectRows) - actConsumeTotalRows = resultList[0] - if not (actConsumeTotalRows > 0 and actConsumeTotalRows < totalRowsInserted): - tdLog.info("act consume rows: %d"%(actConsumeTotalRows)) - tdLog.info("and second consume rows should be between 0 and %d"%(totalRowsInserted)) + tdLog.info("act consume rows: %d"%(actConsumeTotalRows)) + tdLog.info("and second consume rows should be between 0 and %d"%(totalRowsInserted)) + if not ((actConsumeTotalRows > 0) and (actConsumeTotalRows <= totalRowsInserted)): tdLog.exit("%d tmq consume rows error!"%consumerId) time.sleep(10) diff --git a/tests/system-test/7-tmq/tmqConsumerGroup.py b/tests/system-test/7-tmq/tmqConsumerGroup.py index 02093a2d889f1f7138e29055145bc63318dd2873..f05f600f27b1d1c3194c85a03edfbcac1aeee3b7 100644 --- a/tests/system-test/7-tmq/tmqConsumerGroup.py +++ b/tests/system-test/7-tmq/tmqConsumerGroup.py @@ -21,34 +21,6 @@ class TDTestCase: tdSql.init(conn.cursor()) #tdSql.init(conn.cursor(), logSql) # output sql.txt file - def checkFileContent(self, consumerId, queryString): - buildPath = tdCom.getBuildPath() - cfgPath = tdCom.getClientCfgPath() - dstFile = '%s/../log/dstrows_%d.txt'%(cfgPath, consumerId) - cmdStr = '%s/build/bin/taos -c %s -s "%s >> %s"'%(buildPath, cfgPath, queryString, dstFile) - tdLog.info(cmdStr) - os.system(cmdStr) - - consumeRowsFile = '%s/../log/consumerid_%d.txt'%(cfgPath, consumerId) - tdLog.info("rows file: %s, %s"%(consumeRowsFile, dstFile)) - - consumeFile = open(consumeRowsFile, mode='r') - queryFile = open(dstFile, mode='r') - - # skip first line for it is schema - queryFile.readline() - - while True: - dst = queryFile.readline() - src = consumeFile.readline() - - if dst: - if dst != src: - tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) - else: - break - return - def tmqCase1(self): tdLog.printNoPrefix("======== test case 1: ") paraDict = {'dbName': 'db1', @@ -70,9 +42,10 @@ class TDTestCase: 'showRow': 1} topicNameList = ['topic1', 'topic2'] - expectRowsList = [] + queryRowsList = [] tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) tdLog.info("create ctb") @@ -87,7 +60,7 @@ class TDTestCase: tdLog.info("create topic sql: %s"%sqlString) tdSql.execute(sqlString) tdSql.query(queryString) - expectRowsList.append(tdSql.getRows()) + queryRowsList.append(tdSql.getRows()) # create one stb2 paraDict["stbName"] = 'stb2' @@ -104,7 +77,7 @@ class TDTestCase: tdLog.info("create topic sql: %s"%sqlString) tdSql.execute(sqlString) # tdSql.query(queryString) - # expectRowsList.append(tdSql.getRows()) + # queryRowsList.append(tdSql.getRows()) # init consume info, and start tmq_sim, then check consume result tdLog.info("insert consume info to consume processor") @@ -126,7 +99,8 @@ class TDTestCase: pThread = tmqCom.asyncInsertData(paraDict) tdLog.info("wait consumer commit notify") - tmqCom.getStartCommitNotifyFromTmqsim(rows=4) + # tmqCom.getStartCommitNotifyFromTmqsim(rows=4) + tmqCom.getStartConsumeNotifyFromTmqsim(rows=2) tdLog.info("pkill one consume processor") tmqCom.stopTmqSimProcess('tmq_sim_new') @@ -136,19 +110,21 @@ class TDTestCase: tdLog.info("wait the consume result") expectRows = 2 resultList = tmqCom.selectConsumeResult(expectRows) - actTotalRows = 0 + actConsumTotalRows = 0 for i in range(len(resultList)): - actTotalRows += resultList[i] + actConsumTotalRows += resultList[i] + + tdLog.info("act consumer1 rows: %d, consumer2 rows: %d"%(resultList[0], resultList[1])) tdSql.query(queryString) - expectRowsList.append(tdSql.getRows()) - expectTotalRows = 0 - for i in range(len(expectRowsList)): - expectTotalRows += expectRowsList[i] - - tdLog.info("act consume rows: %d, expect consume rows: %d"%(actTotalRows, expectTotalRows)) - if expectTotalRows <= resultList[0]: - tdLog.info("act consume rows: %d should >= expect consume rows: %d"%(actTotalRows, expectTotalRows)) + queryRowsList.append(tdSql.getRows()) + queryTotalRows = 0 + for i in range(len(queryRowsList)): + queryTotalRows += queryRowsList[i] + + tdLog.info("act consume rows: %d, query consume rows: %d"%(actConsumTotalRows, queryTotalRows)) + if actConsumTotalRows < queryTotalRows: + tdLog.info("act consume rows: %d should >= query consume rows: %d"%(actConsumTotalRows, queryTotalRows)) tdLog.exit("0 tmq consume rows error!") # time.sleep(10) @@ -157,9 +133,95 @@ class TDTestCase: tdLog.printNoPrefix("======== test case 1 end ...... ") + + def tmqCase2(self): + tdLog.printNoPrefix("======== test case 2: ") + paraDict = {'dbName': 'db1', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'stbName': 'stb', + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':2}, {'type': 'binary', 'len':20, 'count':1},{'type': 'TIMESTAMP', 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1}, {'type': 'binary', 'len':20, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbNum': 10, + 'rowsPerTbl': 1000, + 'batchNum': 10, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + 'pollDelay': 20, + 'showMsg': 1, + 'showRow': 1} + + topicNameList = ['topic3', 'topic4'] + queryRowsList = [] + tmqCom.initConsumerTable() + + tdLog.info("create topics from stb with filter") + # queryString = "select ts, log(c1), ceil(pow(c1,3)) from %s.%s where c1 %% 7 == 0" %(paraDict['dbName'], paraDict['stbName']) + queryString = "select ts, log(c1), ceil(pow(c1,3)) from %s.%s" %(paraDict['dbName'], paraDict['stbName']) + sqlString = "create topic %s as %s" %(topicNameList[0], queryString) + tdLog.info("create topic sql: %s"%sqlString) + tdSql.execute(sqlString) + tdSql.query(queryString) + queryRowsList.append(tdSql.getRows()) + + # create one stb2 + paraDict["stbName"] = 'stb2' + # queryString = "select ts, sin(c1), abs(pow(c1,3)) from %s.%s where c1 %% 7 == 0" %(paraDict['dbName'], paraDict['stbName']) + queryString = "select ts, sin(c1), abs(pow(c1,3)) from %s.%s" %(paraDict['dbName'], paraDict['stbName']) + sqlString = "create topic %s as %s" %(topicNameList[1], queryString) + tdLog.info("create topic sql: %s"%sqlString) + tdSql.execute(sqlString) + tdSql.query(queryString) + queryRowsList.append(tdSql.getRows()) + + # init consume info, and start tmq_sim, then check consume result + tdLog.info("insert consume info to consume processor") + consumerId = 0 + paraDict["rowsPerTbl"] = 5000 + expectrowcnt = paraDict["rowsPerTbl"] * paraDict["ctbNum"] * 2 + topicList = "%s,%s"%(topicNameList[0],topicNameList[1]) + ifcheckdata = 1 + ifManualCommit = 1 + keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:3000, auto.offset.reset:earliest' + tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) + + tdLog.info("start consume processor 1") + tmqCom.startTmqSimProcess(paraDict['pollDelay'],paraDict["dbName"],paraDict['showMsg'], paraDict['showRow']) + + tdLog.info("start consume processor 2") + tmqCom.startTmqSimProcess(paraDict['pollDelay'],paraDict["dbName"],paraDict['showMsg'], paraDict['showRow'],'cdb',0,1) + + tdLog.info("wait the consume result") + expectRows = 2 + resultList = tmqCom.selectConsumeResult(expectRows) + actConsumTotalRows = 0 + for i in range(len(resultList)): + actConsumTotalRows += resultList[i] + + tdLog.info("act consumer1 rows: %d, consumer2 rows: %d"%(resultList[0], resultList[1])) + + queryTotalRows = 0 + for i in range(len(queryRowsList)): + queryTotalRows += queryRowsList[i] + + tdLog.info("act consume rows: %d, query consume rows: %d"%(actConsumTotalRows, queryTotalRows)) + if actConsumTotalRows < queryTotalRows: + tdLog.info("act consume rows: %d should >= query consume rows: %d"%(actConsumTotalRows, queryTotalRows)) + tdLog.exit("0 tmq consume rows error!") + + # time.sleep(10) + # for i in range(len(topicNameList)): + # tdSql.query("drop topic %s"%topicNameList[i]) + + tdLog.printNoPrefix("======== test case 2 end ...... ") + def run(self): tdSql.prepare() self.tmqCase1() + self.tmqCase2() def stop(self): tdSql.close() diff --git a/tests/system-test/7-tmq/tmqDelete-1ctb.py b/tests/system-test/7-tmq/tmqDelete-1ctb.py index 4b45b1a83410437db56b1b9d89f0af3f55c06b01..aa9c8d25d0364635b11ba6c867cad67f2085c08e 100644 --- a/tests/system-test/7-tmq/tmqDelete-1ctb.py +++ b/tests/system-test/7-tmq/tmqDelete-1ctb.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1,wal_retention_size=-1, wal_retention_period=-1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -80,16 +81,16 @@ class TDTestCase: tdLog.debug("del data ............ [OK]") return - def threadFunctionForDeletaData(self, **paraDict): + def threadFunctionForDeletaData(self, paraDict): # create new connector for new tdSql instance in my thread newTdSql = tdCom.newTdSql() self.delData(newTdSql,paraDict["dbName"],paraDict["ctbPrefix"],paraDict["ctbNum"],paraDict["startTs"],paraDict["endTs"],paraDict["ctbStartIdx"]) return - def asyncDeleteData(self, paraDict): - pThread = threading.Thread(target=self.threadFunctionForDeletaData, kwargs=paraDict) - pThread.start() - return pThread + # def asyncDeleteData(self, paraDict): + # pThread = threading.Thread(target=self.threadFunctionForDeletaData, kwargs=paraDict) + # pThread.start() + # return pThread def tmqCase1(self): tdLog.printNoPrefix("======== test case 1: ") @@ -109,7 +110,7 @@ class TDTestCase: 'batchNum': 3000, 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 'endTs': 0, - 'pollDelay': 5, + 'pollDelay': 15, 'showMsg': 1, 'showRow': 1, 'snapshot': 0} @@ -194,7 +195,7 @@ class TDTestCase: 'rowsPerTbl': 10000, 'batchNum': 5000, 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 - 'pollDelay': 5, + 'pollDelay': 15, 'showMsg': 1, 'showRow': 1, 'snapshot': 0} @@ -237,10 +238,10 @@ class TDTestCase: if self.snapshot == 0: consumerId = 2 - expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1 + 1/4 + 3/4)) + expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"]) * 2 elif self.snapshot == 1: consumerId = 3 - expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1 - 1/4 + 1/4 + 3/4)) + expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1 + 1/4)) topicList = topicFromStb1 ifcheckdata = 1 @@ -270,7 +271,7 @@ class TDTestCase: if totalConsumeRows != expectrowcnt: tdLog.exit("tmq consume rows error with snapshot = 0!") elif self.snapshot == 1: - if totalConsumeRows != totalRowsFromQuery: + if totalConsumeRows != expectrowcnt: tdLog.exit("tmq consume rows error with snapshot = 1!") # tmqCom.checkFileContent(consumerId, queryString) @@ -296,7 +297,7 @@ class TDTestCase: 'rowsPerTbl': 10000, 'batchNum': 5000, 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 - 'pollDelay': 5, + 'pollDelay': 15, 'showMsg': 1, 'showRow': 1, 'snapshot': 0} @@ -323,7 +324,7 @@ class TDTestCase: if self.snapshot == 0: consumerId = 4 - expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1 + 1/4 + 3/4)) + expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"]) * 2 elif self.snapshot == 1: consumerId = 5 expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1 - 1/4 + 1/4 + 3/4)) @@ -340,7 +341,8 @@ class TDTestCase: # del some data rowsOfDelete = int(self.rowsPerTbl / 4 ) paraDict["endTs"] = paraDict["startTs"] + rowsOfDelete - 1 - pDeleteThread = self.asyncDeleteData(paraDict) + # pDeleteThread = self.asyncDeleteData(paraDict) + self.threadFunctionForDeletaData(paraDict) tdLog.info("start consume processor") tmqCom.startTmqSimProcess(pollDelay=paraDict['pollDelay'],dbName=paraDict["dbName"],showMsg=paraDict['showMsg'], showRow=paraDict['showRow'],snapshot=paraDict['snapshot']) @@ -368,9 +370,10 @@ class TDTestCase: tdLog.info("act consume rows: %d, act query rows: %d, expect consume rows: %d, "%(totalConsumeRows, totalRowsFromQuery, expectrowcnt)) if self.snapshot == 0: - if totalConsumeRows != expectrowcnt: + if (totalConsumeRows != expectrowcnt): tdLog.exit("tmq consume rows error with snapshot = 0!") elif self.snapshot == 1: + tdLog.info("consume rows should be between %d and %d, "%(totalRowsFromQuery, expectrowcnt)) if not ((totalConsumeRows >= totalRowsFromQuery) and (totalConsumeRows <= expectrowcnt)): tdLog.exit("tmq consume rows error with snapshot = 1!") @@ -380,9 +383,115 @@ class TDTestCase: tdLog.printNoPrefix("======== test case 3 end ...... ") + def tmqCase4(self): + tdLog.printNoPrefix("======== test case 4: ") + paraDict = {'dbName': 'dbt', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'stbName': 'stb', + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1},{'type': 'BIGINT', 'count':1},{'type': 'DOUBLE', 'count':1},{'type': 'BINARY', 'len':32, 'count':1},{'type': 'NCHAR', 'len':32, 'count':1},{'type': 'TIMESTAMP', 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1},{'type': 'BIGINT', 'count':1},{'type': 'DOUBLE', 'count':1},{'type': 'BINARY', 'len':32, 'count':1},{'type': 'NCHAR', 'len':32, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbStartIdx': 0, + 'ctbNum': 1, + 'rowsPerTbl': 10000, + 'batchNum': 5000, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + 'pollDelay': 15, + 'showMsg': 1, + 'showRow': 1, + 'snapshot': 0} + + paraDict['snapshot'] = self.snapshot + paraDict['vgroups'] = self.vgroups + paraDict['ctbNum'] = self.ctbNum + paraDict['rowsPerTbl'] = self.rowsPerTbl + + tdLog.info("restart taosd to ensure that the data falls into the disk") + tdSql.query("flush database %s"%(paraDict['dbName'])) + + tmqCom.initConsumerTable() + tdLog.info("create topics from stb1") + topicFromStb1 = 'topic_stb1' + queryString = "select ts, c1, c2 from %s.%s"%(paraDict['dbName'], paraDict['stbName']) + sqlString = "create topic %s as %s" %(topicFromStb1, queryString) + tdLog.info("create topic sql: %s"%sqlString) + tdSql.execute(sqlString) + + # paraDict['ctbNum'] = self.ctbNum + paraDict['rowsPerTbl'] = self.rowsPerTbl + consumerId = 1 + + if self.snapshot == 0: + consumerId = 4 + expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"]) + elif self.snapshot == 1: + consumerId = 5 + expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1 - 1/4 + 1/4 + 3/4)) + + topicList = topicFromStb1 + ifcheckdata = 1 + ifManualCommit = 1 + keyList = 'group.id:cgrp1,\ + enable.auto.commit:true,\ + auto.commit.interval.ms:1000,\ + auto.offset.reset:earliest' + tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) + + # del some data + rowsOfDelete = int(self.rowsPerTbl / 4 ) + paraDict["endTs"] = paraDict["startTs"] + rowsOfDelete - 1 + # pDeleteThread = self.asyncDeleteData(paraDict) + self.threadFunctionForDeletaData(paraDict) + + tdLog.info("start consume processor") + tmqCom.startTmqSimProcess(pollDelay=paraDict['pollDelay'],dbName=paraDict["dbName"],showMsg=paraDict['showMsg'], showRow=paraDict['showRow'],snapshot=paraDict['snapshot']) + + tmqCom.getStartConsumeNotifyFromTmqsim() + + # update to 1/4 rows and insert 3/4 new rows + paraDict['startTs'] = paraDict['startTs'] + int(self.rowsPerTbl * 3 / 4) + # paraDict['rowsPerTbl'] = self.rowsPerTbl + # tmqCom.insert_data_with_autoCreateTbl(tsql=tdSql,dbName=paraDict["dbName"],stbName=paraDict["stbName"],ctbPrefix=paraDict["ctbPrefix"], + # ctbNum=paraDict["ctbNum"],rowsPerTbl=paraDict["rowsPerTbl"],batchNum=paraDict["batchNum"], + # startTs=paraDict["startTs"],ctbStartIdx=paraDict['ctbStartIdx']) + pInsertThread = tmqCom.asyncInsertDataByInterlace(paraDict) + + pInsertThread.join() + + tdLog.info("start to check consume result") + expectRows = 1 + resultList = tmqCom.selectConsumeResult(expectRows) + totalConsumeRows = 0 + for i in range(expectRows): + totalConsumeRows += resultList[i] + tdSql.query(queryString) + totalRowsFromQuery = tdSql.getRows() + + tdLog.info("act consume rows: %d, act query rows: %d, expect consume rows: %d, "%(totalConsumeRows, totalRowsFromQuery, expectrowcnt)) + + if self.snapshot == 0: + tdLog.info("consume rows should be %d"%(expectrowcnt)) + if (totalConsumeRows != expectrowcnt): + tdLog.exit("tmq consume rows error with snapshot = 0!") + elif self.snapshot == 1: + # If data writing has not started before consumer get snapshot, will consume 10000 from wal, and consumer 7500 from tsdb; + tdLog.info("consume rows should be %d, "%(expectrowcnt)) + if (totalConsumeRows != expectrowcnt): + tdLog.exit("tmq consume rows error with snapshot = 1!") + + # tmqCom.checkFileContent(consumerId, queryString) + + tdSql.query("drop topic %s"%topicFromStb1) + + tdLog.printNoPrefix("======== test case 4 end ...... ") + def run(self): - # tdSql.prepare() + tdSql.prepare() tdLog.printNoPrefix("=============================================") tdLog.printNoPrefix("======== snapshot is 0: only consume from wal") self.snapshot = 0 @@ -408,6 +517,17 @@ class TDTestCase: self.prepareTestEnv() self.tmqCase3() + # tdLog.printNoPrefix("=============================================") + # tdLog.printNoPrefix("======== snapshot is 0: only consume from wal") + # self.snapshot = 0 + # self.prepareTestEnv() + # self.tmqCase4() + tdLog.printNoPrefix("====================================================================") + tdLog.printNoPrefix("======== snapshot is 1: firstly consume from tsbs, and then from wal") + self.snapshot = 1 + self.prepareTestEnv() + self.tmqCase4() + def stop(self): tdSql.close() tdLog.success(f"{__file__} successfully executed") diff --git a/tests/system-test/7-tmq/tmqDelete-multiCtb.py b/tests/system-test/7-tmq/tmqDelete-multiCtb.py index e59e3d6ecda6e13127eba3f087029ad281cc55b3..7a47cd6025ccffab89656caf017f21aa2005c1c6 100644 --- a/tests/system-test/7-tmq/tmqDelete-multiCtb.py +++ b/tests/system-test/7-tmq/tmqDelete-multiCtb.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=self.replicaVar,wal_retention_size=-1, wal_retention_period=-1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqDnode.py b/tests/system-test/7-tmq/tmqDnode.py index e1d6d91e2d620fe6a1ca7b28a5762047eaaa9bed..b96ca24ac5ad372eb5e3b15fbbebc63adeb9f63e 100644 --- a/tests/system-test/7-tmq/tmqDnode.py +++ b/tests/system-test/7-tmq/tmqDnode.py @@ -110,7 +110,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return diff --git a/tests/system-test/7-tmq/tmqDnodeRestart.py b/tests/system-test/7-tmq/tmqDnodeRestart.py index a44ff916e5a22c92e68d743333e4c4b921929111..648d629e5cc2e5cbcc8d60cf1599ba93c37d080a 100644 --- a/tests/system-test/7-tmq/tmqDnodeRestart.py +++ b/tests/system-test/7-tmq/tmqDnodeRestart.py @@ -55,6 +55,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1,wal_retention_size=-1, wal_retention_period=-1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -136,7 +137,7 @@ class TDTestCase: tdLog.info("================= restart dnode ===========================") tdDnodes.stoptaosd(1) tdDnodes.starttaosd(1) - # time.sleep(3) + time.sleep(5) tdLog.info(" restart taosd end and wait to check consume result") expectRows = 1 @@ -145,7 +146,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - tdSql.query(queryString) + tdSql.query(queryString, None, 50) totalRowsFromQury = tdSql.getRows() tdLog.info("act consume rows: %d, act query rows: %d"%(totalConsumeRows, totalRowsFromQury)) @@ -186,6 +187,7 @@ class TDTestCase: tmqCom.initConsumerTable() # tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + # tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) # tdLog.info("create stb") # tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) # tdLog.info("create ctb") @@ -220,7 +222,7 @@ class TDTestCase: tdLog.info("================= restart dnode ===========================") tdDnodes.stoptaosd(1) tdDnodes.starttaosd(1) - # time.sleep(3) + time.sleep(5) tdLog.info("create some new child table and insert data ") paraDict["batchNum"] = 100 @@ -234,7 +236,7 @@ class TDTestCase: for i in range(expectRows): totalConsumeRows += resultList[i] - tdSql.query(queryString) + tdSql.query(queryString, None, 50) totalRowsFromQuery = tdSql.getRows() tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, totalRowsFromQuery)) diff --git a/tests/system-test/7-tmq/tmqDnodeRestart1.py b/tests/system-test/7-tmq/tmqDnodeRestart1.py index 982cc0a6313f8482031290acd89ea9f556dd5be3..2bde32800b71fa851a5351d9331a4358114f29e8 100644 --- a/tests/system-test/7-tmq/tmqDnodeRestart1.py +++ b/tests/system-test/7-tmq/tmqDnodeRestart1.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1,wal_retention_size=-1, wal_retention_period=-1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -120,7 +121,7 @@ class TDTestCase: tmqCom.startTmqSimProcess(pollDelay=paraDict['pollDelay'],dbName=paraDict["dbName"],showMsg=paraDict['showMsg'], showRow=paraDict['showRow'],snapshot=paraDict['snapshot']) # time.sleep(3) - tmqCom.getStartCommitNotifyFromTmqsim('cdb',1) + tmqCom.getStartCommitNotifyFromTmqsim() tdLog.info("create some new child table and insert data for latest mode") paraDict["batchNum"] = 100 @@ -204,7 +205,7 @@ class TDTestCase: tdLog.info("start consume processor") tmqCom.startTmqSimProcess(pollDelay=paraDict['pollDelay'],dbName=paraDict["dbName"],showMsg=paraDict['showMsg'], showRow=paraDict['showRow'],snapshot=paraDict['snapshot']) - tmqCom.getStartCommitNotifyFromTmqsim('cdb',1) + tmqCom.getStartCommitNotifyFromTmqsim() tdLog.info("create some new child table and insert data for latest mode") paraDict["batchNum"] = 10 diff --git a/tests/system-test/7-tmq/tmqDropNtb-snapshot0.py b/tests/system-test/7-tmq/tmqDropNtb-snapshot0.py index 6c49fae299ac68aac99892acf5de3011df0ab1a0..7a9c1bbb8c808fe62e8fede76640ac78e19f2f30 100644 --- a/tests/system-test/7-tmq/tmqDropNtb-snapshot0.py +++ b/tests/system-test/7-tmq/tmqDropNtb-snapshot0.py @@ -57,6 +57,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdLog.info("start create database....") tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("start create normal tables....") tmqCom.create_ntable(tsql=tdSql, dbname=paraDict["dbName"], tbname_prefix=paraDict["ctbPrefix"], tbname_index_start_num = 1, column_elm_list=paraDict["colSchema"], colPrefix='c', tblNum=paraDict["ctbNum"]) tdLog.info("start insert data into normal tables....") @@ -100,7 +101,7 @@ class TDTestCase: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt)) - if not ((totalConsumeRows >= expectrowcnt * 3/4) and (totalConsumeRows < expectrowcnt)): + if not ((totalConsumeRows >= expectrowcnt * 3/4) and (totalConsumeRows <= expectrowcnt)): tdLog.exit("tmq consume rows error with snapshot = 0!") tdLog.info("wait subscriptions exit ....") @@ -131,7 +132,7 @@ class TDTestCase: 'batchNum': 100, 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 'endTs': 0, - 'pollDelay': 10, + 'pollDelay': 20, 'showMsg': 1, 'showRow': 1, 'snapshot': 0} @@ -143,6 +144,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdLog.info("start create database....") tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("start create normal tables....") tmqCom.create_ntable(tsql=tdSql, dbname=paraDict["dbName"], tbname_prefix=paraDict["ctbPrefix"], tbname_index_start_num = 1, column_elm_list=paraDict["colSchema"], colPrefix='c', tblNum=paraDict["ctbNum"]) tdLog.info("start insert data into normal tables....") @@ -193,7 +195,7 @@ class TDTestCase: tdLog.info("act consume rows: %d, expect consume rows: %d"%(totalConsumeRows, expectrowcnt)) - if not ((totalConsumeRows >= expectrowcnt / 2 * (1 + 3/4)) and (totalConsumeRows < expectrowcnt)): + if not ((totalConsumeRows >= expectrowcnt / 2 * (1 + 3/4)) and (totalConsumeRows <= expectrowcnt)): tdLog.exit("tmq consume rows error with snapshot = 0!") tdLog.info("wait subscriptions exit ....") diff --git a/tests/system-test/7-tmq/tmqDropNtb-snapshot1.py b/tests/system-test/7-tmq/tmqDropNtb-snapshot1.py index 3fc5a2fdc70b64ec95324c370625f5397287ae7d..0b9cb7e66a2d481f6162f1e5e92d8c1f68dcb300 100644 --- a/tests/system-test/7-tmq/tmqDropNtb-snapshot1.py +++ b/tests/system-test/7-tmq/tmqDropNtb-snapshot1.py @@ -57,6 +57,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdLog.info("start create database....") tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("start create normal tables....") tmqCom.create_ntable(tsql=tdSql, dbname=paraDict["dbName"], tbname_prefix=paraDict["ctbPrefix"], tbname_index_start_num = 1, column_elm_list=paraDict["colSchema"], colPrefix='c', tblNum=paraDict["ctbNum"]) tdLog.info("start insert data into normal tables....") @@ -143,6 +144,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdLog.info("start create database....") tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("start create normal tables....") tmqCom.create_ntable(tsql=tdSql, dbname=paraDict["dbName"], tbname_prefix=paraDict["ctbPrefix"], tbname_index_start_num = 1, column_elm_list=paraDict["colSchema"], colPrefix='c', tblNum=paraDict["ctbNum"]) tdLog.info("start insert data into normal tables....") diff --git a/tests/system-test/7-tmq/tmqDropStb.py b/tests/system-test/7-tmq/tmqDropStb.py index 3789632984c91e49358ea21124824138642162ea..0b252a733495041464a3504a3bc8d94e54fcf48c 100644 --- a/tests/system-test/7-tmq/tmqDropStb.py +++ b/tests/system-test/7-tmq/tmqDropStb.py @@ -64,6 +64,7 @@ class TDTestCase: tmqCom.initConsumerTable(self.cdbName) tdCom.create_database(tdSql,self.paraDict["dbName"],self.paraDict["dropFlag"]) + tdSql.execute("alter database %s wal_retention_period 3600" % (self.paraDict['dbName'])) self.paraDict["stbName"] = 'stb1' tdCom.create_stable(tdSql,dbname=self.paraDict["dbName"],stbname=self.paraDict["stbName"],column_elm_list=self.paraDict["colSchema"],tag_elm_list=self.paraDict["tagSchema"],count=1, default_stbname_prefix=self.paraDict["stbName"]) @@ -81,7 +82,7 @@ class TDTestCase: tdLog.info("create topics from db") topicName1 = 'UpperCasetopic_%s'%(self.paraDict['dbName']) - tdSql.execute("create topic %s as database %s" %(topicName1, self.paraDict['dbName'])) + tdSql.execute("create topic `%s` as database %s" %(topicName1, self.paraDict['dbName'])) topicList = topicName1 + ',' +topicName1 keyList = '%s,%s,%s,%s'%(self.groupId,self.autoCommit,self.autoCommitInterval,self.autoOffset) @@ -112,7 +113,7 @@ class TDTestCase: tdLog.exit("tmq consume rows error!") time.sleep(10) - tdSql.query("drop topic %s"%topicName1) + tdSql.query("drop topic `%s`"%topicName1) tdLog.printNoPrefix("======== test case 1 end ...... ") diff --git a/tests/system-test/7-tmq/tmqDropStbCtb.py b/tests/system-test/7-tmq/tmqDropStbCtb.py index c9e34136cc1e59af173205a8e0cb2796acb1a14a..587baf12aab02a3ae3e7d4d9783cafab6ac0ceca 100644 --- a/tests/system-test/7-tmq/tmqDropStbCtb.py +++ b/tests/system-test/7-tmq/tmqDropStbCtb.py @@ -54,6 +54,7 @@ class TDTestCase: # tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqError.py b/tests/system-test/7-tmq/tmqError.py index a39bac8dd194360196ccad80c1352b6028474a0b..b2038f1644e70cd2a6f4f7c2eb979ac58ff9a27e 100644 --- a/tests/system-test/7-tmq/tmqError.py +++ b/tests/system-test/7-tmq/tmqError.py @@ -116,7 +116,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return diff --git a/tests/system-test/7-tmq/tmqModule.py b/tests/system-test/7-tmq/tmqModule.py index d6b4aff9380bb8f5337ce4b52088e105449a1d07..187152c9ce9a1fd6afba1a718cd82e7e81ae0e4f 100644 --- a/tests/system-test/7-tmq/tmqModule.py +++ b/tests/system-test/7-tmq/tmqModule.py @@ -110,7 +110,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return diff --git a/tests/system-test/7-tmq/tmqMultiConsumer.py b/tests/system-test/7-tmq/tmqMultiConsumer.py new file mode 100644 index 0000000000000000000000000000000000000000..cc217e0c4c2c3b185a6e7cba656dbcf1e4740ac2 --- /dev/null +++ b/tests/system-test/7-tmq/tmqMultiConsumer.py @@ -0,0 +1,174 @@ + +import taos +import sys +import time +import socket +import os +import threading +import math +# from tests.pytest.util.common import TDCom +# from tests.pytest.util.log import TDLog + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import * +from util.common import * +sys.path.append("./7-tmq") +from tmqCommon import * + +class TDTestCase: + def __init__(self): + self.vgroups = 32 + self.ctbNum = 100 + self.rowsPerTbl = 1000 + self.snapshot = 1 + self.replicaVar = 3 + + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug(f"start to excute {__file__}") + tdSql.init(conn.cursor(), False) + + def prepareTestEnv(self): + tdLog.printNoPrefix("======== prepare test env include database, stable, ctables, and insert data: ") + paraDict = {'dbName': 'dbt', + 'dropFlag': 1, + 'event': '', + 'vgroups': 4, + 'stbName': 'stb', + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1},{'type': 'BIGINT', 'count':1},{'type': 'DOUBLE', 'count':1},{'type': 'BINARY', 'len':32, 'count':1},{'type': 'NCHAR', 'len':32, 'count':1},{'type': 'TIMESTAMP', 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1},{'type': 'BIGINT', 'count':1},{'type': 'DOUBLE', 'count':1},{'type': 'BINARY', 'len':32, 'count':1},{'type': 'NCHAR', 'len':32, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbStartIdx': 0, + 'ctbNum': 10, + 'rowsPerTbl': 10000, + 'batchNum': 1000, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + 'pollDelay': 10, + 'showMsg': 1, + 'showRow': 1, + 'snapshot': 0} + + paraDict['vgroups'] = self.vgroups + paraDict['ctbNum'] = self.ctbNum + paraDict['rowsPerTbl'] = self.rowsPerTbl + + tmqCom.initConsumerTable() + tmqCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=self.replicaVar) + tdLog.info("create stb") + tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) + tdLog.info("create ctb") + tmqCom.create_ctable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"],ctbPrefix=paraDict['ctbPrefix'], + ctbNum=paraDict["ctbNum"],ctbStartIdx=paraDict['ctbStartIdx']) + tdLog.info("insert data") + tmqCom.insert_data_interlaceByMultiTbl(tsql=tdSql,dbName=paraDict["dbName"],ctbPrefix=paraDict["ctbPrefix"], + ctbNum=paraDict["ctbNum"],rowsPerTbl=paraDict["rowsPerTbl"],batchNum=paraDict["batchNum"], + startTs=paraDict["startTs"],ctbStartIdx=paraDict['ctbStartIdx']) + + # tdLog.info("restart taosd to ensure that the data falls into the disk") + # tdDnodes.stop(1) + # tdDnodes.start(1) + # tdSql.query("flush database %s"%(paraDict['dbName'])) + return + + def tmqCase1(self): + tdLog.printNoPrefix("======== test case 1: ") + paraDict = {'dbName': 'dbt', + 'dropFlag': 1, + 'event': '', + 'vgroups': 1, + 'stbName': 'stb', + 'colPrefix': 'c', + 'tagPrefix': 't', + 'colSchema': [{'type': 'INT', 'count':1},{'type': 'BIGINT', 'count':1},{'type': 'DOUBLE', 'count':1},{'type': 'BINARY', 'len':32, 'count':1},{'type': 'NCHAR', 'len':32, 'count':1},{'type': 'TIMESTAMP', 'count':1}], + 'tagSchema': [{'type': 'INT', 'count':1},{'type': 'BIGINT', 'count':1},{'type': 'DOUBLE', 'count':1},{'type': 'BINARY', 'len':32, 'count':1},{'type': 'NCHAR', 'len':32, 'count':1}], + 'ctbPrefix': 'ctb', + 'ctbStartIdx': 0, + 'ctbNum': 1, + 'rowsPerTbl': 10000, + 'batchNum': 1000, + 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 + 'pollDelay': 20, + 'showMsg': 1, + 'showRow': 1, + 'snapshot': 1} + + paraDict['vgroups'] = self.vgroups + paraDict['ctbNum'] = self.ctbNum + paraDict['rowsPerTbl'] = self.rowsPerTbl + paraDict['snapshot'] = self.snapshot + + topicNameList = ['topic1', 'topic2'] + tmqCom.initConsumerTable() + + tdLog.info("create topics from stb with filter") + # queryString = "select ts, acos(c1), ceil(pow(c1,3)) from %s.%s where (sin(c2) >= 0) and (c1 %% 4 == 0) and (ts >= %d) and (t4 like 'shanghai')"%(paraDict['dbName'], paraDict['stbName'], paraDict["startTs"]+9379) + queryString = "select ts, acos(c1), ceil(pow(c1,3)) from %s.%s "%(paraDict['dbName'], paraDict['stbName']) + # sqlString = "create topic %s as stable %s" %(topicNameList[0], paraDict['stbName']) + sqlString = "create topic %s as %s" %(topicNameList[0], queryString) + tdLog.info("create topic sql: %s"%sqlString) + tdSql.execute(sqlString) + + sqlString = "create topic %s as %s" %(topicNameList[1], queryString) + tdLog.info("create topic sql: %s"%sqlString) + tdSql.execute(sqlString) + # tdSql.query(queryString) + # expectRowsList.append(tdSql.getRows()) + + # init consume info, and start tmq_sim, then check consume result + tdLog.info("insert consume info to consume processor") + consumerId = 0 + expectrowcnt = paraDict["rowsPerTbl"] * paraDict["ctbNum"] * 4 + topicList = topicNameList[0] + ',' + topicNameList[0] + ',' + topicNameList[1] + ifcheckdata = 0 + ifManualCommit = 1 + keyList = 'group.id:cgrp1, enable.auto.commit:true, auto.commit.interval.ms:1000, auto.offset.reset:earliest' + tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) + + consumerId = 1 + tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) + + tdLog.info("start consume processor") + tmqCom.startTmqSimProcess(pollDelay=paraDict['pollDelay'],dbName=paraDict["dbName"],showMsg=paraDict['showMsg'], showRow=paraDict['showRow'],snapshot=paraDict['snapshot']) + tdLog.info("wait the consume result") + + # continue to insert new rows + paraDict['startTs'] = paraDict['startTs'] + int(self.rowsPerTbl) + pInsertThread = tmqCom.asyncInsertDataByInterlace(paraDict) + pInsertThread.join() + + expectRows = 2 + resultList = tmqCom.selectConsumeResult(expectRows) + actConsumeTotalRows = resultList[0] + resultList[1] + + tdLog.info("act consume rows: %d, expect consume rows: %d"%(actConsumeTotalRows, expectrowcnt)) + + if not ((expectrowcnt <= actConsumeTotalRows) or ((resultList[0] == 0) and (resultList[1] >= expectrowcnt)) or ((resultList[1] == 0) and (resultList[0] >= expectrowcnt))): + tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectrowcnt, actConsumeTotalRows)) + tdLog.exit("%d tmq consume rows error!"%consumerId) + + # tmqCom.checkFileContent(consumerId, queryString) + + time.sleep(10) + for i in range(len(topicNameList)): + tdSql.query("drop topic %s"%topicNameList[i]) + + tdLog.printNoPrefix("======== test case 1 end ...... ") + + + def run(self): + tdSql.prepare() + self.prepareTestEnv() + self.tmqCase1() + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +event = threading.Event() + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/7-tmq/tmqShow.py b/tests/system-test/7-tmq/tmqShow.py index 31ddc1b0f831df5d6e10f4337536488ddeaa892e..e9234f6c7aea99cf339be76ed799b34d3ec44721 100644 --- a/tests/system-test/7-tmq/tmqShow.py +++ b/tests/system-test/7-tmq/tmqShow.py @@ -51,6 +51,7 @@ class TDTestCase: consumerIdList = [0, 1, 2, 3] tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict['vgroups'],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqSubscribeStb-r3.py b/tests/system-test/7-tmq/tmqSubscribeStb-r3.py index 85222a941bf466631feedd1ead0387ef5f984096..7f322dc2583201bce47f40a9c1883daabadf8e42 100644 --- a/tests/system-test/7-tmq/tmqSubscribeStb-r3.py +++ b/tests/system-test/7-tmq/tmqSubscribeStb-r3.py @@ -94,6 +94,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=self.replica) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqUdf-multCtb-snapshot0.py b/tests/system-test/7-tmq/tmqUdf-multCtb-snapshot0.py index 297429b495b4bbc42e6d53a58295ef306b5d6903..bee38ca8ee192c542ebc2c09718d4e4224904c1e 100644 --- a/tests/system-test/7-tmq/tmqUdf-multCtb-snapshot0.py +++ b/tests/system-test/7-tmq/tmqUdf-multCtb-snapshot0.py @@ -50,7 +50,7 @@ class TDTestCase: def create_udf_function(self): # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) functions = tdSql.getResult("show functions") function_nums = len(functions) @@ -60,34 +60,6 @@ class TDTestCase: tdLog.exit("create udf functions fail") return - def checkFileContent(self, consumerId, queryString): - buildPath = tdCom.getBuildPath() - cfgPath = tdCom.getClientCfgPath() - dstFile = '%s/../log/dstrows_%d.txt'%(cfgPath, consumerId) - cmdStr = '%s/build/bin/taos -c %s -s "%s >> %s"'%(buildPath, cfgPath, queryString, dstFile) - tdLog.info(cmdStr) - os.system(cmdStr) - - consumeRowsFile = '%s/../log/consumerid_%d.txt'%(cfgPath, consumerId) - tdLog.info("rows file: %s, %s"%(consumeRowsFile, dstFile)) - - consumeFile = open(consumeRowsFile, mode='r') - queryFile = open(dstFile, mode='r') - - # skip first line for it is schema - queryFile.readline() - - while True: - dst = queryFile.readline() - src = consumeFile.readline() - - if dst: - if dst != src: - tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) - else: - break - return - def prepareTestEnv(self): tdLog.printNoPrefix("======== prepare test env include database, stable, ctables, and insert data: ") paraDict = {'dbName': 'dbt', @@ -116,6 +88,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -163,6 +136,7 @@ class TDTestCase: expectRowsList = [] tmqCom.initConsumerTable() # tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + # tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) # tdLog.info("create stb") # tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) # tdLog.info("create ctb") @@ -199,7 +173,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) tdLog.exit("0 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) # tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) # reinit consume info, and start tmq_sim, then check consume result @@ -226,7 +200,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[1], resultList[0])) tdLog.exit("1 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) # tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) time.sleep(10) @@ -265,6 +239,7 @@ class TDTestCase: expectRowsList = [] tmqCom.initConsumerTable() # tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + # tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) # tdLog.info("create stb") # tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) # tdLog.info("create ctb") @@ -309,7 +284,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) tdLog.exit("2 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) # tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) # reinit consume info, and start tmq_sim, then check consume result @@ -336,7 +311,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[1], resultList[0])) tdLog.exit("3 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) # tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) time.sleep(10) diff --git a/tests/system-test/7-tmq/tmqUdf-multCtb-snapshot1.py b/tests/system-test/7-tmq/tmqUdf-multCtb-snapshot1.py index 9c139b50de71902d743236c503d6cca12cb8296a..d3b64d2b2150521c1a3bc98fe41734390609084f 100644 --- a/tests/system-test/7-tmq/tmqUdf-multCtb-snapshot1.py +++ b/tests/system-test/7-tmq/tmqUdf-multCtb-snapshot1.py @@ -50,7 +50,7 @@ class TDTestCase: def create_udf_function(self): # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) functions = tdSql.getResult("show functions") function_nums = len(functions) @@ -60,34 +60,6 @@ class TDTestCase: tdLog.exit("create udf functions fail") return - def checkFileContent(self, consumerId, queryString): - buildPath = tdCom.getBuildPath() - cfgPath = tdCom.getClientCfgPath() - dstFile = '%s/../log/dstrows_%d.txt'%(cfgPath, consumerId) - cmdStr = '%s/build/bin/taos -c %s -s "%s >> %s"'%(buildPath, cfgPath, queryString, dstFile) - tdLog.info(cmdStr) - os.system(cmdStr) - - consumeRowsFile = '%s/../log/consumerid_%d.txt'%(cfgPath, consumerId) - tdLog.info("rows file: %s, %s"%(consumeRowsFile, dstFile)) - - consumeFile = open(consumeRowsFile, mode='r') - queryFile = open(dstFile, mode='r') - - # skip first line for it is schema - queryFile.readline() - - while True: - dst = queryFile.readline() - src = consumeFile.readline() - - if dst: - if dst != src: - tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) - else: - break - return - def prepareTestEnv(self): tdLog.printNoPrefix("======== prepare test env include database, stable, ctables, and insert data: ") paraDict = {'dbName': 'dbt', @@ -116,6 +88,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -163,6 +136,7 @@ class TDTestCase: expectRowsList = [] tmqCom.initConsumerTable() # tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + # tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) # tdLog.info("create stb") # tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) # tdLog.info("create ctb") @@ -199,7 +173,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) tdLog.exit("0 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) # tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) # reinit consume info, and start tmq_sim, then check consume result @@ -226,7 +200,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[1], resultList[0])) tdLog.exit("1 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) # tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) time.sleep(10) @@ -265,6 +239,7 @@ class TDTestCase: expectRowsList = [] tmqCom.initConsumerTable() # tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + # tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) # tdLog.info("create stb") # tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) # tdLog.info("create ctb") @@ -309,7 +284,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) tdLog.exit("2 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) # tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) # reinit consume info, and start tmq_sim, then check consume result @@ -336,7 +311,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[1], resultList[0])) tdLog.exit("3 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) # tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) time.sleep(10) diff --git a/tests/system-test/7-tmq/tmqUdf.py b/tests/system-test/7-tmq/tmqUdf.py index 8593fd4f1e5969d9eb8083a66200301a6524d8c1..5da1625cb125091dddc6ddbe3e635dc404352bbb 100644 --- a/tests/system-test/7-tmq/tmqUdf.py +++ b/tests/system-test/7-tmq/tmqUdf.py @@ -50,7 +50,7 @@ class TDTestCase: def create_udf_function(self): # create scalar functions - tdSql.execute("create function udf1 as '%s' outputtype int bufSize 8;"%self.libudf1) + tdSql.execute("create function udf1 as '%s' outputtype int;"%self.libudf1) functions = tdSql.getResult("show functions") function_nums = len(functions) @@ -60,34 +60,6 @@ class TDTestCase: tdLog.exit("create udf functions fail") return - def checkFileContent(self, consumerId, queryString): - buildPath = tdCom.getBuildPath() - cfgPath = tdCom.getClientCfgPath() - dstFile = '%s/../log/dstrows_%d.txt'%(cfgPath, consumerId) - cmdStr = '%s/build/bin/taos -c %s -s "%s >> %s"'%(buildPath, cfgPath, queryString, dstFile) - tdLog.info(cmdStr) - os.system(cmdStr) - - consumeRowsFile = '%s/../log/consumerid_%d.txt'%(cfgPath, consumerId) - tdLog.info("rows file: %s, %s"%(consumeRowsFile, dstFile)) - - consumeFile = open(consumeRowsFile, mode='r') - queryFile = open(dstFile, mode='r') - - # skip first line for it is schema - queryFile.readline() - - while True: - dst = queryFile.readline() - src = consumeFile.readline() - - if dst: - if dst != src: - tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) - else: - break - return - def prepareTestEnv(self): tdLog.printNoPrefix("======== prepare test env include database, stable, ctables, and insert data: ") paraDict = {'dbName': 'dbt', @@ -116,6 +88,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -163,6 +136,7 @@ class TDTestCase: expectRowsList = [] tmqCom.initConsumerTable() # tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + # tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) # tdLog.info("create stb") # tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) # tdLog.info("create ctb") @@ -199,7 +173,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) tdLog.exit("0 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) @@ -227,7 +201,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[1], resultList[0])) tdLog.exit("1 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) time.sleep(10) @@ -266,6 +240,7 @@ class TDTestCase: expectRowsList = [] tmqCom.initConsumerTable() # tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + # tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) # tdLog.info("create stb") # tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) # tdLog.info("create ctb") @@ -310,7 +285,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) tdLog.exit("2 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) # reinit consume info, and start tmq_sim, then check consume result @@ -337,7 +312,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[1], resultList[0])) tdLog.exit("3 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) tdLog.printNoPrefix("consumerId %d check data ok!"%(consumerId)) time.sleep(10) diff --git a/tests/system-test/7-tmq/tmqUpdate-1ctb.py b/tests/system-test/7-tmq/tmqUpdate-1ctb.py index db2ec3285dd87de532a29021142e4285c05718db..8fdf7748a3425b1efe7966949a1098e5867b6ee2 100644 --- a/tests/system-test/7-tmq/tmqUpdate-1ctb.py +++ b/tests/system-test/7-tmq/tmqUpdate-1ctb.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -183,6 +184,7 @@ class TDTestCase: tdLog.info("restart taosd to ensure that the data falls into the disk") tdSql.query("flush database %s"%(paraDict['dbName'])) + time.sleep(10) # update to half tables paraDict['startTs'] = paraDict['startTs'] + int(self.rowsPerTbl / 2) @@ -206,7 +208,7 @@ class TDTestCase: paraDict['rowsPerTbl'] = self.rowsPerTbl consumerId = 1 if self.snapshot == 0: - expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1/2)) + expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1+ 1/2 + 1/2)) elif self.snapshot == 1: expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1)) diff --git a/tests/system-test/7-tmq/tmqUpdate-multiCtb-snapshot0.py b/tests/system-test/7-tmq/tmqUpdate-multiCtb-snapshot0.py index daffff44c1cf0dda7c4ecf5ac2dfd3dadfdf5504..8b67f6f8252e5e3682284c5c2d5b4295308db26c 100644 --- a/tests/system-test/7-tmq/tmqUpdate-multiCtb-snapshot0.py +++ b/tests/system-test/7-tmq/tmqUpdate-multiCtb-snapshot0.py @@ -55,6 +55,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -128,7 +129,7 @@ class TDTestCase: ifManualCommit = 1 keyList = 'group.id:cgrp1,\ enable.auto.commit:true,\ - auto.commit.interval.ms:1000,\ + auto.commit.interval.ms:200,\ auto.offset.reset:earliest' tmqCom.insertConsumerInfo(consumerId, expectrowcnt,topicList,keyList,ifcheckdata,ifManualCommit) @@ -213,7 +214,7 @@ class TDTestCase: paraDict['rowsPerTbl'] = self.rowsPerTbl consumerId = 1 if self.snapshot == 0: - expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1/2) * (1/2*3)) + expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] *(2 + 1/2*1/2*2 + 1/2 + 1/4)) elif self.snapshot == 1: expectrowcnt = int(paraDict["rowsPerTbl"] * paraDict["ctbNum"] * (1 + 1/2)) diff --git a/tests/system-test/7-tmq/tmqUpdate-multiCtb-snapshot1.py b/tests/system-test/7-tmq/tmqUpdate-multiCtb-snapshot1.py index 6b8c10de271b28726639baad8648e2586c02f9a1..5a35c4f5ee84c950ee7a611e5be93fe13371b031 100644 --- a/tests/system-test/7-tmq/tmqUpdate-multiCtb-snapshot1.py +++ b/tests/system-test/7-tmq/tmqUpdate-multiCtb-snapshot1.py @@ -55,6 +55,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqUpdate-multiCtb.py b/tests/system-test/7-tmq/tmqUpdate-multiCtb.py index 3975013e747f09d8cc0548b5e32f9f01c63fb9a4..84617efae4d78cf57cf6d522a7b3fbf50321e5f2 100644 --- a/tests/system-test/7-tmq/tmqUpdate-multiCtb.py +++ b/tests/system-test/7-tmq/tmqUpdate-multiCtb.py @@ -55,6 +55,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmqUpdateWithConsume.py b/tests/system-test/7-tmq/tmqUpdateWithConsume.py index 4f595788daee975f26cd2e30c1a0fe973e35aa68..6a9bb0ae924d0c0a6366ae6ccb0a6f8a1cec6e0d 100644 --- a/tests/system-test/7-tmq/tmqUpdateWithConsume.py +++ b/tests/system-test/7-tmq/tmqUpdateWithConsume.py @@ -54,6 +54,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=self.replicaVar, wal_retention_size=-1, wal_retention_period=-1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") diff --git a/tests/system-test/7-tmq/tmq_taosx.py b/tests/system-test/7-tmq/tmq_taosx.py index 0596241ce1f6c892313ccca219c131476246770c..c3ec4875ceeeb25a0ee3b9f921a8e7d5c40fdc07 100644 --- a/tests/system-test/7-tmq/tmq_taosx.py +++ b/tests/system-test/7-tmq/tmq_taosx.py @@ -43,9 +43,9 @@ class TDTestCase: tdSql.execute('use db_taosx') tdSql.query("show tables") if drop: - tdSql.checkRows(10) + tdSql.checkRows(11) else: - tdSql.checkRows(15) + tdSql.checkRows(16) tdSql.query("select * from jt order by i") tdSql.checkRows(2) tdSql.checkData(0, 1, 1) @@ -63,20 +63,20 @@ class TDTestCase: tdSql.checkData(1, 5, "sttb4") tdSql.query("select * from stt order by ts") - tdSql.checkRows(2) + tdSql.checkRows(3) tdSql.checkData(0, 1, 1) - tdSql.checkData(1, 1, 21) + tdSql.checkData(2, 1, 21) tdSql.checkData(0, 2, 2) - tdSql.checkData(1, 2, 21) + tdSql.checkData(2, 2, 21) tdSql.checkData(0, 5, "stt3") - tdSql.checkData(1, 5, "stt4") + tdSql.checkData(2, 5, "stt4") tdSql.execute('use abc1') tdSql.query("show tables") if drop: - tdSql.checkRows(10) + tdSql.checkRows(11) else: - tdSql.checkRows(15) + tdSql.checkRows(16) tdSql.query("select * from jt order by i") tdSql.checkRows(2) tdSql.checkData(0, 1, 1) @@ -94,13 +94,13 @@ class TDTestCase: tdSql.checkData(1, 5, "sttb4") tdSql.query("select * from stt order by ts") - tdSql.checkRows(2) + tdSql.checkRows(3) tdSql.checkData(0, 1, 1) - tdSql.checkData(1, 1, 21) + tdSql.checkData(2, 1, 21) tdSql.checkData(0, 2, 2) - tdSql.checkData(1, 2, 21) + tdSql.checkData(2, 2, 21) tdSql.checkData(0, 5, "stt3") - tdSql.checkData(1, 5, "stt4") + tdSql.checkData(2, 5, "stt4") return @@ -123,6 +123,11 @@ class TDTestCase: def checkData(self): tdSql.execute('use db_taosx') + tdSql.query("select * from tb1") + tdSql.checkRows(1) + tdSql.checkData(0, 1, 0) + tdSql.checkData(0, 2, 1) + tdSql.query("select * from ct3 order by c1 desc") tdSql.checkRows(2) tdSql.checkData(0, 1, 51) @@ -195,6 +200,7 @@ class TDTestCase: tdSql.checkData(1, 1, 1) tdSql.checkData(1, 2, '{"k1":1,"k2":"hello"}') + time.sleep(10) tdSql.query("select * from information_schema.ins_tables where table_name = 'stt4'") uid1 = tdSql.getData(0, 5) uid2 = tdSql.getData(1, 5) diff --git a/tests/system-test/99-TDcase/TD-15517.py b/tests/system-test/99-TDcase/TD-15517.py index db06700284d6de78139aef2f2678e2eb75d379fd..aeb28063e47253b085fe664e3109dcb4855539c9 100644 --- a/tests/system-test/99-TDcase/TD-15517.py +++ b/tests/system-test/99-TDcase/TD-15517.py @@ -51,7 +51,7 @@ class TDTestCase: return cur def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum,rowsPerTbl): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" diff --git a/tests/system-test/99-TDcase/TD-15554.py b/tests/system-test/99-TDcase/TD-15554.py index 51934ccd4408cc002060049f8c32fb6706a41fd3..c8ddeca3c3426c22efe3c4ddbbc6ad5b5992a108 100644 --- a/tests/system-test/99-TDcase/TD-15554.py +++ b/tests/system-test/99-TDcase/TD-15554.py @@ -50,7 +50,7 @@ class TDTestCase: return cur def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum,rowsPerTbl): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table if not exists %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" diff --git a/tests/system-test/99-TDcase/TD-15557.py b/tests/system-test/99-TDcase/TD-15557.py index 884c028a6567d62ce5141eb5ad16240830168f51..f9e676f4f89d9e356d9ede59793f2b8cc431039b 100644 --- a/tests/system-test/99-TDcase/TD-15557.py +++ b/tests/system-test/99-TDcase/TD-15557.py @@ -64,7 +64,7 @@ class TDTestCase: os.system(shellCmd) def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum,rowsPerTbl): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table if not exists %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" @@ -141,7 +141,7 @@ class TDTestCase: 'startTs': 1640966400000} # 2022-01-01 00:00:00.000 parameterDict['cfg'] = cfgPath - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -214,7 +214,7 @@ class TDTestCase: 'startTs': 1640966400000} # 2022-01-01 00:00:00.000 parameterDict['cfg'] = cfgPath - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -298,7 +298,7 @@ class TDTestCase: 'startTs': 1640966400000} # 2022-01-01 00:00:00.000 parameterDict['cfg'] = cfgPath - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() diff --git a/tests/system-test/99-TDcase/TD-15563.py b/tests/system-test/99-TDcase/TD-15563.py index 5ea652b4fb6fe5b441ea4a946026115431ec24b2..cc4c3f3b39a6ff6259b62a18d39d91265d87ba13 100644 --- a/tests/system-test/99-TDcase/TD-15563.py +++ b/tests/system-test/99-TDcase/TD-15563.py @@ -52,7 +52,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -95,7 +95,7 @@ class TDTestCase: os.system(shellCmd) def create_tables(self,tsql, dbName,vgroups,stbName,ctbNum,rowsPerTbl): - tsql.execute("create database if not exists %s vgroups %d"%(dbName, vgroups)) + tsql.execute("create database if not exists %s vgroups %d wal_retention_period 3600"%(dbName, vgroups)) tsql.execute("use %s" %dbName) tsql.execute("create table if not exists %s (ts timestamp, c1 bigint, c2 binary(16)) tags(t1 int)"%stbName) pre_create = "create table" @@ -176,7 +176,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -238,7 +238,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() @@ -304,7 +304,7 @@ class TDTestCase: self.initConsumerTable() - tdSql.execute("create database if not exists %s vgroups %d" %(parameterDict['dbName'], parameterDict['vgroups'])) + tdSql.execute("create database if not exists %s vgroups %d wal_retention_period 3600" %(parameterDict['dbName'], parameterDict['vgroups'])) prepareEnvThread = threading.Thread(target=self.prepareEnv, kwargs=parameterDict) prepareEnvThread.start() diff --git a/tests/system-test/99-TDcase/TD-16025.py b/tests/system-test/99-TDcase/TD-16025.py index 8c9fa9319f8071db436e4f71a597dc7d5de8758e..3e25b8c8334013b5dbb56b77ead3473994cd8e9e 100644 --- a/tests/system-test/99-TDcase/TD-16025.py +++ b/tests/system-test/99-TDcase/TD-16025.py @@ -59,7 +59,7 @@ class TDTestCase: def initConsumerTable(self,cdbName='cdb'): tdLog.info("create consume database, and consume info table, and consume result table") - tdSql.query("create database if not exists %s vgroups 1"%(cdbName)) + tdSql.query("create database if not exists %s vgroups 1 wal_retention_period 3600"%(cdbName)) tdSql.query("drop table if exists %s.consumeinfo "%(cdbName)) tdSql.query("drop table if exists %s.consumeresult "%(cdbName)) @@ -110,7 +110,7 @@ class TDTestCase: if dropFlag == 1: tsql.execute("drop database if exists %s"%(dbName)) - tsql.execute("create database if not exists %s vgroups %d replica %d"%(dbName, vgroups, replica)) + tsql.execute("create database if not exists %s vgroups %d replica %d wal_retention_period 3600"%(dbName, vgroups, replica)) tdLog.debug("complete to create database %s"%(dbName)) return diff --git a/tests/system-test/99-TDcase/TD-16821.py b/tests/system-test/99-TDcase/TD-16821.py index f57fae752f8d2d07f730f791ce0b5a63eb7dc832..2e23002059c5d157b3e1f6edf2f21a5d291739bc 100644 --- a/tests/system-test/99-TDcase/TD-16821.py +++ b/tests/system-test/99-TDcase/TD-16821.py @@ -21,34 +21,6 @@ class TDTestCase: tdSql.init(conn.cursor()) #tdSql.init(conn.cursor(), logSql) # output sql.txt file - def checkFileContent(self, consumerId, queryString): - buildPath = tdCom.getBuildPath() - cfgPath = tdCom.getClientCfgPath() - dstFile = '%s/../log/dstrows_%d.txt'%(cfgPath, consumerId) - cmdStr = '%s/build/bin/taos -c %s -s "%s >> %s"'%(buildPath, cfgPath, queryString, dstFile) - tdLog.info(cmdStr) - os.system(cmdStr) - - consumeRowsFile = '%s/../log/consumerid_%d.txt'%(cfgPath, consumerId) - tdLog.info("rows file: %s, %s"%(consumeRowsFile, dstFile)) - - consumeFile = open(consumeRowsFile, mode='r') - queryFile = open(dstFile, mode='r') - - # skip first line for it is schema - queryFile.readline() - - while True: - dst = queryFile.readline() - src = consumeFile.readline() - - if dst: - if dst != src: - tdLog.exit("consumerId %d consume rows is not match the rows by direct query"%consumerId) - else: - break - return - def tmqCase1(self): tdLog.printNoPrefix("======== test case 1: ") paraDict = {'dbName': 'db1', @@ -73,6 +45,7 @@ class TDTestCase: expectRowsList = [] tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=4,replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tdCom.create_stable(tdSql, dbname=paraDict["dbName"],stbname=paraDict["stbName"], column_elm_list=paraDict['colSchema'], tag_elm_list=paraDict['tagSchema']) tdLog.info("create ctb") @@ -113,7 +86,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[0], resultList[0])) tdLog.exit("0 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) # reinit consume info, and start tmq_sim, then check consume result tmqCom.initConsumerTable() @@ -139,7 +112,7 @@ class TDTestCase: tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[1], resultList[0])) tdLog.exit("1 tmq consume rows error!") - self.checkFileContent(consumerId, queryString) + tmqCom.checkFileContent(consumerId, queryString) # reinit consume info, and start tmq_sim, then check consume result tmqCom.initConsumerTable() @@ -165,7 +138,7 @@ class TDTestCase: # tdLog.info("expect consume rows: %d, act consume rows: %d"%(expectRowsList[2], resultList[0])) # tdLog.exit("2 tmq consume rows error!") - # self.checkFileContent(consumerId, queryString) + # tmqCom.checkFileContent(consumerId, queryString) time.sleep(10) for i in range(len(topicNameList)): diff --git a/tests/system-test/99-TDcase/TD-17255.py b/tests/system-test/99-TDcase/TD-17255.py index 0f83468754783ee5adca78113c7a8df5c78bbe99..5f68a5b7389d3ea095a8886e2801dd82fb6af8d9 100644 --- a/tests/system-test/99-TDcase/TD-17255.py +++ b/tests/system-test/99-TDcase/TD-17255.py @@ -53,6 +53,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -97,6 +98,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -181,6 +183,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("create ctb") @@ -267,6 +270,7 @@ class TDTestCase: tmqCom.initConsumerTable() tdCom.create_database(tdSql, paraDict["dbName"],paraDict["dropFlag"], vgroups=paraDict["vgroups"],replica=1) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) tdLog.info("create stb") tmqCom.create_stable(tdSql, dbName=paraDict["dbName"],stbName=paraDict["stbName"]) tdLog.info("insert data by auto create ctb") diff --git a/tests/system-test/99-TDcase/TD-17699.py b/tests/system-test/99-TDcase/TD-17699.py index 2862f4a78d5391098f0493afa35e482c5a032817..6956e88aec7d0c8adb84c8af9aff31cb6d80fa1f 100644 --- a/tests/system-test/99-TDcase/TD-17699.py +++ b/tests/system-test/99-TDcase/TD-17699.py @@ -65,6 +65,7 @@ class TDTestCase: tmqCom.initConsumerTable(self.cdbName) tdCom.create_database(tdSql,self.paraDict["dbName"],self.paraDict["dropFlag"]) + tdSql.execute("alter database %s wal_retention_period 3600" % (paraDict['dbName'])) self.paraDict["stbName"] = 'stb1' tdCom.create_stable(tdSql,dbname=self.paraDict["dbName"],stbname=self.paraDict["stbName"],column_elm_list=self.paraDict["colSchema"],tag_elm_list=self.paraDict["tagSchema"],count=1, default_stbname_prefix=self.paraDict["stbName"]) diff --git a/tests/system-test/99-TDcase/TS-3404.py b/tests/system-test/99-TDcase/TS-3404.py new file mode 100644 index 0000000000000000000000000000000000000000..3fdfb9a19378747b276678fe3c350bae5de18bc2 --- /dev/null +++ b/tests/system-test/99-TDcase/TS-3404.py @@ -0,0 +1,101 @@ +import taos +import sys +import time +import socket +import os +import threading + +from util.log import * +from util.sql import * +from util.cases import * +from util.dnodes import * + +class TDTestCase: + hostname = socket.gethostname() + + def init(self, conn, logSql, replicaVar=1): + self.replicaVar = int(replicaVar) + tdLog.debug(f"start to excute {__file__}") + #tdSql.init(conn.cursor()) + tdSql.init(conn.cursor(), logSql) # output sql.txt 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 ("taosd" in files or "taosd.exe" 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 create_tables(self): + tdSql.execute(f"CREATE STABLE `stb5` (`ts` TIMESTAMP, `ip_value` FLOAT, `ip_quality` INT) TAGS (`t1` INT)") + tdSql.execute(f"CREATE TABLE `t_11` USING `stb5` (`t1`) TAGS (1)") + + def insert_data(self): + tdLog.debug("start to insert data ............") + + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-10 09:30:47.722', 10.30000, 100)") + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-10 09:30:56.383', 12.30000, 100)") + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-10 09:48:55.778', 13.30000, 100)") + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-10 09:51:50.821', 9.30000, 100)") + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-10 09:58:07.162', 9.30000, 100)") + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-10 13:41:16.075', 9.30000, 100)") + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-13 14:12:58.318', 21.00000, 100)") + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-13 14:13:21.328', 1.10000, 100)") + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-13 14:35:24.258', 1.30000, 100)") + tdSql.execute(f"INSERT INTO `t_11` VALUES ('2023-05-13 16:56:49.033', 1.80000, 100)") + + tdLog.debug("insert data ............ [OK]") + + def run(self): + tdSql.prepare() + self.create_tables() + self.insert_data() + tdLog.printNoPrefix("======== test TS-3404") + + tdSql.query(f"select _irowts, interp(ip_value) from t_11 range('2023-05-13 14:00:00', '2023-05-13 15:00:00') every(300s) fill(linear);") + tdSql.checkRows(13) + + tdSql.checkData(0, 0, '2023-05-13 14:00:00.000') + tdSql.checkData(1, 0, '2023-05-13 14:05:00.000') + tdSql.checkData(2, 0, '2023-05-13 14:10:00.000') + tdSql.checkData(3, 0, '2023-05-13 14:15:00.000') + tdSql.checkData(4, 0, '2023-05-13 14:20:00.000') + tdSql.checkData(5, 0, '2023-05-13 14:25:00.000') + tdSql.checkData(6, 0, '2023-05-13 14:30:00.000') + tdSql.checkData(7, 0, '2023-05-13 14:35:00.000') + tdSql.checkData(8, 0, '2023-05-13 14:40:00.000') + tdSql.checkData(9, 0, '2023-05-13 14:45:00.000') + tdSql.checkData(10, 0, '2023-05-13 14:50:00.000') + tdSql.checkData(11, 0, '2023-05-13 14:55:00.000') + tdSql.checkData(12, 0, '2023-05-13 15:00:00.000') + + tdSql.checkData(0, 1, 20.96512) + tdSql.checkData(1, 1, 20.97857) + tdSql.checkData(2, 1, 20.99201) + tdSql.checkData(3, 1, 1.114917) + tdSql.checkData(4, 1, 1.160271) + tdSql.checkData(5, 1, 1.205625) + tdSql.checkData(6, 1, 1.250978) + tdSql.checkData(7, 1, 1.296333) + tdSql.checkData(8, 1, 1.316249) + tdSql.checkData(9, 1, 1.333927) + tdSql.checkData(10, 1, 1.351607) + tdSql.checkData(11, 1, 1.369285) + tdSql.checkData(12, 1, 1.386964) + + + def stop(self): + tdSql.close() + tdLog.success(f"{__file__} successfully executed") + +tdCases.addLinux(__file__, TDTestCase()) +tdCases.addWindows(__file__, TDTestCase()) diff --git a/tests/system-test/pytest.sh b/tests/system-test/pytest.sh index 68d49f5d06c48d7ffcbfa564d802762b7f120b4f..dfdfc32ed0c60122926f4472ae80923d98778541 100755 --- a/tests/system-test/pytest.sh +++ b/tests/system-test/pytest.sh @@ -8,15 +8,23 @@ set +e #set -x +if [[ "$OSTYPE" == "darwin"* ]]; then + TD_OS="Darwin" +else + OS=$(cat /etc/*-release | grep "^NAME=" | cut -d= -f2) + len=$(echo ${#OS}) + len=$((len - 2)) + TD_OS=$(echo -ne ${OS:1:${len}} | cut -d" " -f1) +fi -UNAME_BIN=`which uname` -OS_TYPE=`$UNAME_BIN` +UNAME_BIN=$(which uname) +OS_TYPE=$($UNAME_BIN) cd . # Get responsible directories -CODE_DIR=`dirname $0` -CODE_DIR=`pwd` +CODE_DIR=$(dirname $0) +CODE_DIR=$(pwd) IN_TDINTERNAL="community" if [[ "$CODE_DIR" == *"$IN_TDINTERNAL"* ]]; then @@ -25,19 +33,15 @@ else cd ../../ fi -TOP_DIR=`pwd` -TAOSD_DIR=`find . -name "taosd"|grep bin|head -n1` +TOP_DIR=$(pwd) +TAOSD_DIR=$(find . -name "taosd" | grep bin | head -n1) -if [[ "$OS_TYPE" != "Darwin" ]]; then - cut_opt="--field=" -else - cut_opt="-f " -fi +cut_opt="-f " if [[ "$TAOSD_DIR" == *"$IN_TDINTERNAL"* ]]; then - BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2,3` + BIN_DIR=$(find . -name "taosd" | grep bin | head -n1 | cut -d '/' ${cut_opt}2,3) else - BIN_DIR=`find . -name "taosd"|grep bin|head -n1|cut -d '/' ${cut_opt}2` + BIN_DIR=$(find . -name "taosd" | grep bin | head -n1 | cut -d '/' ${cut_opt}2) fi declare -x BUILD_DIR=$TOP_DIR/$BIN_DIR @@ -66,35 +70,38 @@ ulimit -c unlimited #sudo sysctl -w kernel.core_pattern=$TOP_DIR/core.%p.%e echo "ExcuteCmd:" $* -AsanFile=$ASAN_DIR/psim.info -echo "AsanFile:" $AsanFile - -unset LD_PRELOAD -#export LD_PRELOAD=libasan.so.5 -export LD_PRELOAD=`gcc -print-file-name=libasan.so` -echo "Preload AsanSo:" $? - -$* -a 2> $AsanFile - -unset LD_PRELOAD -for ((i=1;i<=20;i++)) -do - AsanFileLen=`cat $AsanFile | wc -l` - echo "AsanFileLen:" $AsanFileLen - if [ $AsanFileLen -gt 10 ]; then - break - fi - sleep 1 -done -AsanFileSuccessLen=`grep -w successfully $AsanFile | wc -l` -echo "AsanFileSuccessLen:" $AsanFileSuccessLen - -if [ $AsanFileSuccessLen -gt 0 ]; then - echo "Execute script successfully and check asan" - $CODE_DIR/../script/sh/checkAsan.sh +if [[ "$TD_OS" == "Alpine" ]]; then + $* else - echo "Execute script failure" - exit 1 -fi - + AsanFile=$ASAN_DIR/psim.info + echo "AsanFile:" $AsanFile + + unset LD_PRELOAD + #export LD_PRELOAD=libasan.so.5 + export LD_PRELOAD=$(gcc -print-file-name=libasan.so) + echo "Preload AsanSo:" $? + + $* -a 2>$AsanFile + + unset LD_PRELOAD + for ((i = 1; i <= 20; i++)); do + AsanFileLen=$(cat $AsanFile | wc -l) + echo "AsanFileLen:" $AsanFileLen + if [ $AsanFileLen -gt 10 ]; then + break + fi + sleep 1 + done + # check case successful + AsanFileSuccessLen=$(grep -w "successfully executed" $AsanFile | wc -l) + echo "AsanFileSuccessLen:" $AsanFileSuccessLen + + if [ $AsanFileSuccessLen -gt 0 ]; then + echo "Execute script successfully and check asan" + $CODE_DIR/../script/sh/checkAsan.sh + else + echo "Execute script failure" + exit 1 + fi +fi \ No newline at end of file diff --git a/tests/system-test/runAllOne.sh b/tests/system-test/runAllOne.sh new file mode 100644 index 0000000000000000000000000000000000000000..5a8d358d989355127f3971d1127aeb43fa0323bd --- /dev/null +++ b/tests/system-test/runAllOne.sh @@ -0,0 +1,688 @@ +# start -N3 +echo " ********** -N 3 *************" +python3 ./test.py -f 7-tmq/tmqDelete-multiCtb.py -N 3 -n 3 +python3 ./test.py -f 1-insert/alter_database.py -P +python3 ./test.py -f 1-insert/influxdb_line_taosc_insert.py -P +python3 ./test.py -f 1-insert/opentsdb_telnet_line_taosc_insert.py -P +python3 ./test.py -f 1-insert/opentsdb_json_taosc_insert.py -P +python3 ./test.py -f 1-insert/test_stmt_muti_insert_query.py -P +python3 ./test.py -f 1-insert/test_stmt_set_tbname_tag.py -P +python3 ./test.py -f 1-insert/alter_stable.py -P +python3 ./test.py -f 1-insert/alter_table.py -P +python3 ./test.py -f 1-insert/boundary.py -P +python3 ./test.py -f 1-insert/insertWithMoreVgroup.py -P +python3 ./test.py -f 1-insert/table_comment.py -P +python3 ./test.py -f 1-insert/time_range_wise.py -P +python3 ./test.py -f 1-insert/block_wise.py -P +python3 ./test.py -f 1-insert/create_retentions.py -P +python3 ./test.py -f 1-insert/mutil_stage.py -P +python3 ./test.py -f 1-insert/table_param_ttl.py -P +python3 ./test.py -f 1-insert/table_param_ttl.py -P -R +python3 ./test.py -f 1-insert/update_data_muti_rows.py -P +python3 ./test.py -f 1-insert/db_tb_name_check.py -P +python3 ./test.py -f 1-insert/InsertFuturets.py -P +python3 ./test.py -f 1-insert/insert_wide_column.py -P +python3 ./test.py -f 2-query/nestedQuery.py -P +python3 ./test.py -f 2-query/nestedQuery_str.py -P +python3 ./test.py -f 2-query/nestedQuery_math.py -P +python3 ./test.py -f 2-query/nestedQuery_time.py -P +python3 ./test.py -f 2-query/nestedQuery_26.py -P +python3 ./test.py -f 2-query/nestedQuery_str.py -P -Q 2 +python3 ./test.py -f 2-query/nestedQuery_math.py -P -Q 2 +python3 ./test.py -f 2-query/nestedQuery_time.py -P -Q 2 +python3 ./test.py -f 2-query/nestedQuery.py -P -Q 2 +python3 ./test.py -f 2-query/nestedQuery_26.py -P -Q 2 +python3 ./test.py -f 2-query/columnLenUpdated.py -P +python3 ./test.py -f 2-query/columnLenUpdated.py -P -Q 2 +python3 ./test.py -f 2-query/columnLenUpdated.py -P -Q 3 +python3 ./test.py -f 2-query/columnLenUpdated.py -P -Q 4 +python3 ./test.py -f 2-query/nestedQuery.py -P -Q 4 +python3 ./test.py -f 2-query/nestedQuery_str.py -P -Q 4 +python3 ./test.py -f 2-query/nestedQuery_math.py -P -Q 4 +python3 ./test.py -f 2-query/nestedQuery_time.py -P -Q 4 +python3 ./test.py -f 2-query/nestedQuery_26.py -P -Q 4 +python3 ./test.py -f 7-tmq/tmqShow.py -P +python3 ./test.py -f 7-tmq/tmqDropStb.py -P +python3 ./test.py -f 7-tmq/subscribeStb0.py -P +python3 ./test.py -f 7-tmq/subscribeStb1.py -P +python3 ./test.py -f 7-tmq/subscribeStb2.py -P +python3 ./test.py -f 7-tmq/subscribeStb3.py -P +python3 ./test.py -f 7-tmq/subscribeDb0.py -P -N 3 -n 3 +python3 ./test.py -f 1-insert/delete_stable.py -P +python3 ./test.py -f 2-query/out_of_order.py -P -Q 3 +python3 ./test.py -f 2-query/out_of_order.py -P +python3 ./test.py -f 2-query/insert_null_none.py -P +python3 ./test.py -f 2-query/insert_null_none.py -P -R +python3 ./test.py -f 2-query/insert_null_none.py -P -Q 2 +python3 ./test.py -f 2-query/insert_null_none.py -P -Q 3 +python3 ./test.py -f 2-query/insert_null_none.py -P -Q 4 +python3 ./test.py -f 1-insert/database_pre_suf.py -P +python3 ./test.py -f 2-query/concat.py -P -Q 3 +python3 ./test.py -f 2-query/out_of_order.py -P -Q 2 +python3 ./test.py -f 2-query/out_of_order.py -P -Q 4 +python3 ./test.py -f 2-query/nestedQuery.py -P -Q 3 +python3 ./test.py -f 2-query/nestedQuery_str.py -P -Q 3 +python3 ./test.py -f 2-query/nestedQuery_math.py -P -Q 3 +python3 ./test.py -f 2-query/nestedQuery_time.py -P -Q 3 +python3 ./test.py -f 2-query/nestedQuery_26.py -P -Q 3 +python3 ./test.py -f 7-tmq/create_wrong_topic.py -P +python3 ./test.py -f 7-tmq/dropDbR3ConflictTransaction.py -P -N 3 +python3 ./test.py -f 7-tmq/basic5.py -P +python3 ./test.py -f 7-tmq/subscribeDb.py -P -N 3 -n 3 +python3 ./test.py -f 7-tmq/subscribeDb1.py -P +python3 ./test.py -f 7-tmq/subscribeDb2.py -P +python3 ./test.py -f 7-tmq/subscribeDb3.py -P +python3 ./test.py -f 7-tmq/subscribeDb4.py -P +python3 ./test.py -f 7-tmq/subscribeStb.py -P +python3 ./test.py -f 7-tmq/subscribeStb4.py -P +python3 ./test.py -f 7-tmq/db.py -P +python3 ./test.py -f 7-tmq/tmqError.py -P +python3 ./test.py -f 7-tmq/schema.py -P +python3 ./test.py -f 7-tmq/stbFilter.py -P +python3 ./test.py -f 7-tmq/tmqCheckData.py -P +python3 ./test.py -f 7-tmq/tmqCheckData1.py -P +python3 ./test.py -f 7-tmq/tmqConsumerGroup.py -P +python3 ./test.py -f 7-tmq/tmqAlterSchema.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb.py -P -N 3 -n 3 +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1.py -P -N 3 -n 3 +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-1ctb.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-1ctb.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-1ctb-funcNFilter.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb-funcNFilter.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-1ctb-funcNFilter.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb-funcNFilter.py -P +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb.py -P +python3 ./test.py -f 7-tmq/tmqAutoCreateTbl.py -P +python3 ./test.py -f 7-tmq/tmqDnodeRestart.py -P +python3 ./test.py -f 7-tmq/tmqDnodeRestart1.py -P +python3 ./test.py -f 7-tmq/tmqUpdate-1ctb.py -P +python3 ./test.py -f 7-tmq/tmqUpdate-multiCtb-snapshot0.py -P +python3 ./test.py -f 7-tmq/tmqUpdate-multiCtb-snapshot1.py -P +python3 ./test.py -f 7-tmq/tmqDropStbCtb.py -P +python3 ./test.py -f 7-tmq/tmqDropNtb-snapshot0.py -P +python3 ./test.py -f 7-tmq/tmqDropNtb-snapshot1.py -P +python3 ./test.py -f 7-tmq/tmqUdf-multCtb-snapshot0.py -P +python3 ./test.py -f 7-tmq/tmqUdf-multCtb-snapshot1.py -P +python3 ./test.py -f 7-tmq/stbTagFilter-1ctb.py -P +python3 ./test.py -f 7-tmq/dataFromTsdbNWal.py -P +python3 ./test.py -f 7-tmq/dataFromTsdbNWal-multiCtb.py -P +python3 ./test.py -f 7-tmq/tmq_taosx.py -P +python3 ./test.py -f 7-tmq/raw_block_interface_test.py -P +python3 ./test.py -f 7-tmq/stbTagFilter-multiCtb.py -P +python3 ./test.py -f 99-TDcase/TD-19201.py -P +python3 ./test.py -f 99-TDcase/TD-21561.py -P +python3 ./test.py -f 0-others/taosShell.py -P +python3 ./test.py -f 0-others/taosShellError.py -P +python3 ./test.py -f 0-others/taosShellNetChk.py -P +python3 ./test.py -f 0-others/telemetry.py -P +python3 ./test.py -f 0-others/backquote_check.py -P +python3 ./test.py -f 0-others/taosdMonitor.py -P +python3 ./test.py -f 0-others/udfTest.py -P +python3 ./test.py -f 0-others/udf_create.py -P +python3 ./test.py -f 0-others/udf_restart_taosd.py -P +python3 ./test.py -f 0-others/udf_cfg1.py -P +python3 ./test.py -f 0-others/udf_cfg2.py -P +python3 ./test.py -f 0-others/cachemodel.py -P +python3 ./test.py -f 0-others/sysinfo.py -P +python3 ./test.py -f 0-others/user_control.py -P +python3 ./test.py -f 0-others/user_manage.py -P +python3 ./test.py -f 0-others/fsync.py -P +python3 ./test.py -f 0-others/tag_index_basic.py -P +python3 ./test.py -f 0-others/show.py -P +python3 ./test.py -f 0-others/information_schema.py -P +python3 ./test.py -f 2-query/abs.py -P +python3 ./test.py -f 2-query/abs.py -P -R +python3 ./test.py -f 2-query/and_or_for_byte.py -P +python3 ./test.py -f 2-query/and_or_for_byte.py -P -R +python3 ./test.py -f 2-query/apercentile.py -P +python3 ./test.py -f 2-query/apercentile.py -P -R +python3 ./test.py -f 2-query/arccos.py -P +python3 ./test.py -f 2-query/arccos.py -P -R +python3 ./test.py -f 2-query/arcsin.py -P +python3 ./test.py -f 2-query/arcsin.py -P -R +python3 ./test.py -f 2-query/arctan.py -P +python3 ./test.py -f 2-query/arctan.py -P -R +python3 ./test.py -f 2-query/avg.py -P +python3 ./test.py -f 2-query/avg.py -P -R +python3 ./test.py -f 2-query/between.py -P +python3 ./test.py -f 2-query/between.py -P -R +python3 ./test.py -f 2-query/bottom.py -P +python3 ./test.py -f 2-query/bottom.py -P -R +python3 ./test.py -f 2-query/cast.py -P +python3 ./test.py -f 2-query/cast.py -P -R +python3 ./test.py -f 2-query/ceil.py -P +python3 ./test.py -f 2-query/ceil.py -P -R +python3 ./test.py -f 2-query/char_length.py -P +python3 ./test.py -f 2-query/char_length.py -P -R +python3 ./test.py -f 2-query/check_tsdb.py -P +python3 ./test.py -f 2-query/check_tsdb.py -P -R +python3 ./test.py -f 2-query/concat.py -P +python3 ./test.py -f 2-query/concat.py -P -R +python3 ./test.py -f 2-query/concat_ws.py -P +python3 ./test.py -f 2-query/concat_ws.py -P -R +python3 ./test.py -f 2-query/concat_ws2.py -P +python3 ./test.py -f 2-query/concat_ws2.py -P -R +python3 ./test.py -f 2-query/cos.py -P +python3 ./test.py -f 2-query/cos.py -P -R +python3 ./test.py -f 2-query/count_partition.py -P +python3 ./test.py -f 2-query/count_partition.py -P -R +python3 ./test.py -f 2-query/count.py -P +python3 ./test.py -f 2-query/count.py -P -R +python3 ./test.py -f 2-query/countAlwaysReturnValue.py -P +python3 ./test.py -f 2-query/countAlwaysReturnValue.py -P -R +python3 ./test.py -f 2-query/db.py -P +python3 ./test.py -f 2-query/diff.py -P +python3 ./test.py -f 2-query/diff.py -P -R +python3 ./test.py -f 2-query/distinct.py -P +python3 ./test.py -f 2-query/distinct.py -P -R +python3 ./test.py -f 2-query/distribute_agg_apercentile.py -P +python3 ./test.py -f 2-query/distribute_agg_apercentile.py -P -R +python3 ./test.py -f 2-query/distribute_agg_avg.py -P +python3 ./test.py -f 2-query/distribute_agg_avg.py -P -R +python3 ./test.py -f 2-query/distribute_agg_count.py -P +python3 ./test.py -f 2-query/distribute_agg_count.py -P -R +python3 ./test.py -f 2-query/distribute_agg_max.py -P +python3 ./test.py -f 2-query/distribute_agg_max.py -P -R +python3 ./test.py -f 2-query/distribute_agg_min.py -P +python3 ./test.py -f 2-query/distribute_agg_min.py -P -R +python3 ./test.py -f 2-query/distribute_agg_spread.py -P +python3 ./test.py -f 2-query/distribute_agg_spread.py -P -R +python3 ./test.py -f 2-query/distribute_agg_stddev.py -P +python3 ./test.py -f 2-query/distribute_agg_stddev.py -P -R +python3 ./test.py -f 2-query/distribute_agg_sum.py -P +python3 ./test.py -f 2-query/distribute_agg_sum.py -P -R +python3 ./test.py -f 2-query/explain.py -P +python3 ./test.py -f 2-query/explain.py -P -R +python3 ./test.py -f 2-query/first.py -P +python3 ./test.py -f 2-query/first.py -P -R +python3 ./test.py -f 2-query/floor.py -P +python3 ./test.py -f 2-query/floor.py -P -R +python3 ./test.py -f 2-query/function_null.py -P +python3 ./test.py -f 2-query/function_null.py -P -R +python3 ./test.py -f 2-query/function_stateduration.py -P +python3 ./test.py -f 2-query/function_stateduration.py -P -R +python3 ./test.py -f 2-query/histogram.py -P +python3 ./test.py -f 2-query/histogram.py -P -R +python3 ./test.py -f 2-query/hyperloglog.py -P +python3 ./test.py -f 2-query/hyperloglog.py -P -R +python3 ./test.py -f 2-query/interp.py -P +python3 ./test.py -f 2-query/interp.py -P -R +python3 ./test.py -f 2-query/irate.py -P +python3 ./test.py -f 2-query/irate.py -P -R +python3 ./test.py -f 2-query/join.py -P +python3 ./test.py -f 2-query/join.py -P -R +python3 ./test.py -f 2-query/last_row.py -P +python3 ./test.py -f 2-query/last_row.py -P -R +python3 ./test.py -f 2-query/last.py -P +python3 ./test.py -f 2-query/last.py -P -R +python3 ./test.py -f 2-query/leastsquares.py -P +python3 ./test.py -f 2-query/leastsquares.py -P -R +python3 ./test.py -f 2-query/length.py -P +python3 ./test.py -f 2-query/length.py -P -R +python3 ./test.py -f 2-query/limit.py -P +python3 ./test.py -f 2-query/log.py -P +python3 ./test.py -f 2-query/log.py -P -R +python3 ./test.py -f 2-query/lower.py -P +python3 ./test.py -f 2-query/lower.py -P -R +python3 ./test.py -f 2-query/ltrim.py -P +python3 ./test.py -f 2-query/ltrim.py -P -R +python3 ./test.py -f 2-query/mavg.py -P +python3 ./test.py -f 2-query/mavg.py -P -R +python3 ./test.py -f 2-query/max_partition.py -P +python3 ./test.py -f 2-query/max_partition.py -P -R +python3 ./test.py -f 2-query/max_min_last_interval.py -P +python3 ./test.py -f 2-query/last_row_interval.py -P +python3 ./test.py -f 2-query/max.py -P +python3 ./test.py -f 2-query/max.py -P -R +python3 ./test.py -f 2-query/min.py -P +python3 ./test.py -f 2-query/min.py -P -R +python3 ./test.py -f 2-query/mode.py -P +python3 ./test.py -f 2-query/mode.py -P -R +python3 ./test.py -f 2-query/Now.py -P +python3 ./test.py -f 2-query/Now.py -P -R +python3 ./test.py -f 2-query/percentile.py -P +python3 ./test.py -f 2-query/percentile.py -P -R +python3 ./test.py -f 2-query/pow.py -P +python3 ./test.py -f 2-query/pow.py -P -R +python3 ./test.py -f 2-query/query_cols_tags_and_or.py -P +python3 ./test.py -f 2-query/query_cols_tags_and_or.py -P -R +python3 ./test.py -f 2-query/round.py -P +python3 ./test.py -f 2-query/round.py -P -R +python3 ./test.py -f 2-query/rtrim.py -P +python3 ./test.py -f 2-query/rtrim.py -P -R +python3 ./test.py -f 1-insert/drop.py -P -N 3 -M 3 -i False -n 3 +python3 ./test.py -f 7-tmq/tmqUpdateWithConsume.py -P -N 3 -n 3 +python3 ./test.py -f 2-query/db.py -P -N 3 -n 3 -R +python3 ./test.py -f 2-query/stablity.py -P +python3 ./test.py -f 2-query/stablity_1.py -P +python3 ./test.py -f 2-query/elapsed.py -P +python3 ./test.py -f 2-query/csum.py -P +python3 ./test.py -f 2-query/function_diff.py -P +python3 ./test.py -f 2-query/tagFilter.py -P +python3 ./test.py -f 2-query/projectionDesc.py -P +python3 ./test.py -f 2-query/queryQnode.py -P +python3 ./test.py -f 6-cluster/5dnode1mnode.py -P + + +# -N 4 +echo " ********** -N 4 *************" +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_createDb_replica1.py -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica1_insertdatas.py -P -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica1_insertdatas_querys.py -P -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica3_insertdatas.py -P -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica3_insertdatas_querys.py -P -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica3_vgroups.py -P -N 4 -M 1 +python3 ./test.py -f 2-query/varchar.py -P -R +python3 ./test.py -f 2-query/case_when.py -P +python3 ./test.py -f 2-query/case_when.py -P -R +python3 ./test.py -f 2-query/blockSMA.py -P +python3 ./test.py -f 2-query/blockSMA.py -P -R +python3 ./test.py -f 2-query/projectionDesc.py -P +python3 ./test.py -f 2-query/projectionDesc.py -P -R +python3 ./test.py -f 1-insert/update_data.py -P +python3 ./test.py -f 1-insert/tb_100w_data_order.py -P +python3 ./test.py -f 1-insert/delete_childtable.py -P +python3 ./test.py -f 1-insert/delete_normaltable.py -P +python3 ./test.py -f 1-insert/keep_expired.py -P +python3 ./test.py -f 1-insert/drop.py -P +python3 ./test.py -f 2-query/join2.py -P +python3 ./test.py -f 2-query/union1.py -P +python3 ./test.py -f 2-query/concat2.py -P +python3 ./test.py -f 2-query/json_tag.py -P +python3 ./test.py -f 2-query/nestedQueryInterval.py -P + + +# -N 5 +echo " ********** -N 5 *************" +python3 ./test.py -f 6-cluster/5dnode2mnode.py -P -N 5 +python3 ./test.py -f 6-cluster/5dnode3mnodeStop.py -P -N 5 -M 3 -i False +python3 ./test.py -f 6-cluster/5dnode3mnodeStop2Follower.py -P -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeStop2Follower.py -P -N 5 -M 3 -i False +python3 ./test.py -f 6-cluster/5dnode3mnodeStopLoop.py -P -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeRecreateMnode.py -P -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeStopFollowerLeader.py -P -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeStop2Follower.py -P -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeStop.py -P -N 5 -M 3 +python3 ./test.py -f 0-others/taosdShell.py -P -N 5 -M 3 -Q 3 +python3 ./test.py -f 7-tmq/tmqSubscribeStb-r3.py -P -N 5 +python3 ./test.py -f 2-query/timezone.py -P +python3 ./test.py -f 2-query/timezone.py -P -R +python3 ./test.py -f 2-query/To_iso8601.py -P +python3 ./test.py -f 2-query/To_iso8601.py -P -R +python3 ./test.py -f 2-query/To_unixtimestamp.py -P +python3 ./test.py -f 2-query/To_unixtimestamp.py -P -R +python3 ./test.py -f 2-query/Today.py -P +python3 ./test.py -f 2-query/Today.py -P -R +python3 ./test.py -f 2-query/top.py -P +python3 ./test.py -f 2-query/top.py -P -R +python3 ./test.py -f 2-query/tsbsQuery.py -P +python3 ./test.py -f 2-query/tsbsQuery.py -P -R +python3 ./test.py -f 2-query/ttl_comment.py -P +python3 ./test.py -f 2-query/ttl_comment.py -P -R +python3 ./test.py -f 2-query/twa.py -P +python3 ./test.py -f 2-query/twa.py -P -R +python3 ./test.py -f 2-query/union.py -P +python3 ./test.py -f 2-query/union.py -P -R +python3 ./test.py -f 2-query/unique.py -P +python3 ./test.py -f 2-query/unique.py -P -R +python3 ./test.py -f 2-query/upper.py -P +python3 ./test.py -f 2-query/upper.py -P -R +python3 ./test.py -f 2-query/varchar.py -P + +# -N6 +echo " ********** -N 6 *************" +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateDb.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateDb.py -P -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateDb.py -P -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateDb.py -P -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateDb.py -P -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateDb.py -P -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeModifyMeta.py -P -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeModifyMeta.py -P -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateStb.py -P -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateStb.py -P -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateStb.py -P -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateStb.py -P -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateStb.py -P -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateStb.py -P -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeRestartDnodeInsertData.py -P -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeRestartDnodeInsertData.py -P -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeRestartDnodeInsertDataAsync.py -P -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeRestartDnodeInsertDataAsync.py -P -N 6 -M 3 -n 3 +python3 ./test.py -f 7-tmq/tmq3mnodeSwitch.py -P -N 6 -M 3 +python3 ./test.py -f 7-tmq/tmq3mnodeSwitch.py -P -N 6 -M 3 -n 3 +python3 ./test.py -f 0-others/balance_vgroups_r1.py -P -N 6 + +python3 ./test.py -f 2-query/sample.py -P +python3 ./test.py -f 2-query/sample.py -P -R +python3 ./test.py -f 2-query/sin.py -P +python3 ./test.py -f 2-query/sin.py -P -R +python3 ./test.py -f 2-query/smaTest.py -P +python3 ./test.py -f 2-query/smaTest.py -P -R +python3 ./test.py -f 2-query/sml.py -P +python3 ./test.py -f 2-query/sml.py -P -R +python3 ./test.py -f 2-query/spread.py -P +python3 ./test.py -f 2-query/spread.py -P -R +python3 ./test.py -f 2-query/sqrt.py -P +python3 ./test.py -f 2-query/sqrt.py -P -R +python3 ./test.py -f 2-query/statecount.py -P +python3 ./test.py -f 2-query/statecount.py -P -R +python3 ./test.py -f 2-query/stateduration.py -P +python3 ./test.py -f 2-query/stateduration.py -P -R +python3 ./test.py -f 2-query/substr.py -P +python3 ./test.py -f 2-query/substr.py -P -R +python3 ./test.py -f 2-query/sum.py -P +python3 ./test.py -f 2-query/sum.py -P -R +python3 ./test.py -f 2-query/tail.py -P +python3 ./test.py -f 2-query/tail.py -P -R +python3 ./test.py -f 2-query/tan.py -P +python3 ./test.py -f 2-query/tan.py -P -R +python3 ./test.py -f 2-query/Timediff.py -P +python3 ./test.py -f 2-query/Timediff.py -P -R +python3 ./test.py -f 2-query/timetruncate.py -P +python3 ./test.py -f 2-query/timetruncate.py -P -R + +# N-7 +echo " ********** -N 7 *************" +python3 ./test.py -f 6-cluster/5dnode3mnodeAdd1Ddnoe.py -N 7 -M 3 -C 6 +python3 ./test.py -f 6-cluster/5dnode3mnodeAdd1Ddnoe.py -P -N 7 -M 3 -C 6 -n 3 + +python3 ./test.py -f 2-query/between.py -P -Q 2 +python3 ./test.py -f 2-query/distinct.py -P -Q 2 +python3 ./test.py -f 2-query/varchar.py -P -Q 2 +python3 ./test.py -f 2-query/ltrim.py -P -Q 2 +python3 ./test.py -f 2-query/rtrim.py -P -Q 2 +python3 ./test.py -f 2-query/length.py -P -Q 2 +python3 ./test.py -f 2-query/char_length.py -P -Q 2 +python3 ./test.py -f 2-query/upper.py -P -Q 2 +python3 ./test.py -f 2-query/lower.py -P -Q 2 +python3 ./test.py -f 2-query/join.py -P -Q 2 +python3 ./test.py -f 2-query/join2.py -P -Q 2 +python3 ./test.py -f 2-query/cast.py -P -Q 2 +python3 ./test.py -f 2-query/substr.py -P -Q 2 +python3 ./test.py -f 2-query/union.py -P -Q 2 +python3 ./test.py -f 2-query/union1.py -P -Q 2 +python3 ./test.py -f 2-query/concat.py -P -Q 2 +python3 ./test.py -f 2-query/concat2.py -P -Q 2 +python3 ./test.py -f 2-query/concat_ws.py -P -Q 2 +python3 ./test.py -f 2-query/concat_ws2.py -P -Q 2 +python3 ./test.py -f 2-query/check_tsdb.py -P -Q 2 +python3 ./test.py -f 2-query/spread.py -P -Q 2 +python3 ./test.py -f 2-query/hyperloglog.py -P -Q 2 +python3 ./test.py -f 2-query/explain.py -P -Q 2 +python3 ./test.py -f 2-query/leastsquares.py -P -Q 2 +python3 ./test.py -f 2-query/timezone.py -P -Q 2 +python3 ./test.py -f 2-query/Now.py -P -Q 2 +python3 ./test.py -f 2-query/Today.py -P -Q 2 +python3 ./test.py -f 2-query/max.py -P -Q 2 +python3 ./test.py -f 2-query/min.py -P -Q 2 +python3 ./test.py -f 2-query/mode.py -P -Q 2 +python3 ./test.py -f 2-query/count.py -P -Q 2 +python3 ./test.py -f 2-query/countAlwaysReturnValue.py -P -Q 2 +python3 ./test.py -f 2-query/last.py -P -Q 2 +python3 ./test.py -f 2-query/first.py -P -Q 2 +python3 ./test.py -f 2-query/To_iso8601.py -P -Q 2 +python3 ./test.py -f 2-query/To_unixtimestamp.py -P -Q 2 +python3 ./test.py -f 2-query/timetruncate.py -P -Q 2 +python3 ./test.py -f 2-query/diff.py -P -Q 2 +python3 ./test.py -f 2-query/Timediff.py -P -Q 2 +python3 ./test.py -f 2-query/json_tag.py -P -Q 2 +python3 ./test.py -f 2-query/top.py -P -Q 2 +python3 ./test.py -f 2-query/bottom.py -P -Q 2 +python3 ./test.py -f 2-query/percentile.py -P -Q 2 +python3 ./test.py -f 2-query/apercentile.py -P -Q 2 +python3 ./test.py -f 2-query/abs.py -P -Q 2 +python3 ./test.py -f 2-query/ceil.py -P -Q 2 +python3 ./test.py -f 2-query/floor.py -P -Q 2 +python3 ./test.py -f 2-query/round.py -P -Q 2 +python3 ./test.py -f 2-query/log.py -P -Q 2 +python3 ./test.py -f 2-query/pow.py -P -Q 2 +python3 ./test.py -f 2-query/sqrt.py -P -Q 2 +python3 ./test.py -f 2-query/sin.py -P -Q 2 +python3 ./test.py -f 2-query/cos.py -P -Q 2 +python3 ./test.py -f 2-query/tan.py -P -Q 2 +python3 ./test.py -f 2-query/arcsin.py -P -Q 2 +python3 ./test.py -f 2-query/arccos.py -P -Q 2 +python3 ./test.py -f 2-query/arctan.py -P -Q 2 +python3 ./test.py -f 2-query/query_cols_tags_and_or.py -P -Q 2 +python3 ./test.py -f 2-query/interp.py -P -Q 2 +python3 ./test.py -f 2-query/nestedQueryInterval.py -P -Q 2 +python3 ./test.py -f 2-query/stablity.py -P -Q 2 +python3 ./test.py -f 2-query/stablity_1.py -P -Q 2 +python3 ./test.py -f 2-query/avg.py -P -Q 2 +python3 ./test.py -f 2-query/elapsed.py -P -Q 2 +python3 ./test.py -f 2-query/csum.py -P -Q 2 +python3 ./test.py -f 2-query/mavg.py -P -Q 2 +python3 ./test.py -f 2-query/sample.py -P -Q 2 +python3 ./test.py -f 2-query/function_diff.py -P -Q 2 +python3 ./test.py -f 2-query/unique.py -P -Q 2 +python3 ./test.py -f 2-query/stateduration.py -P -Q 2 +python3 ./test.py -f 2-query/function_stateduration.py -P -Q 2 +python3 ./test.py -f 2-query/statecount.py -P -Q 2 +python3 ./test.py -f 2-query/tail.py -P -Q 2 +python3 ./test.py -f 2-query/ttl_comment.py -P -Q 2 +python3 ./test.py -f 2-query/distribute_agg_count.py -P -Q 2 +python3 ./test.py -f 2-query/distribute_agg_max.py -P -Q 2 +python3 ./test.py -f 2-query/distribute_agg_min.py -P -Q 2 +python3 ./test.py -f 2-query/distribute_agg_sum.py -P -Q 2 +python3 ./test.py -f 2-query/distribute_agg_spread.py -P -Q 2 +python3 ./test.py -f 2-query/distribute_agg_apercentile.py -P -Q 2 +python3 ./test.py -f 2-query/distribute_agg_avg.py -P -Q 2 +python3 ./test.py -f 2-query/distribute_agg_stddev.py -P -Q 2 +python3 ./test.py -f 2-query/twa.py -P -Q 2 +python3 ./test.py -f 2-query/irate.py -P -Q 2 +python3 ./test.py -f 2-query/function_null.py -P -Q 2 +python3 ./test.py -f 2-query/count_partition.py -P -Q 2 +python3 ./test.py -f 2-query/max_partition.py -P -Q 2 +python3 ./test.py -f 2-query/max_min_last_interval.py -P -Q 2 +python3 ./test.py -f 2-query/last_row_interval.py -P -Q 2 +python3 ./test.py -f 2-query/last_row.py -P -Q 2 +python3 ./test.py -f 2-query/tsbsQuery.py -P -Q 2 +python3 ./test.py -f 2-query/sml.py -P -Q 2 +python3 ./test.py -f 2-query/case_when.py -P -Q 2 +python3 ./test.py -f 2-query/blockSMA.py -P -Q 2 +python3 ./test.py -f 2-query/projectionDesc.py -P -Q 2 +python3 ./test.py -f 99-TDcase/TD-21561.py -P -Q 2 + +python3 ./test.py -f 2-query/between.py -P -Q 3 +python3 ./test.py -f 2-query/distinct.py -P -Q 3 +python3 ./test.py -f 2-query/varchar.py -P -Q 3 +python3 ./test.py -f 2-query/ltrim.py -P -Q 3 +python3 ./test.py -f 2-query/rtrim.py -P -Q 3 +python3 ./test.py -f 2-query/length.py -P -Q 3 +python3 ./test.py -f 2-query/char_length.py -P -Q 3 +python3 ./test.py -f 2-query/upper.py -P -Q 3 +python3 ./test.py -f 2-query/lower.py -P -Q 3 +python3 ./test.py -f 2-query/join.py -P -Q 3 +python3 ./test.py -f 2-query/join2.py -P -Q 3 +python3 ./test.py -f 2-query/cast.py -P -Q 3 +python3 ./test.py -f 2-query/substr.py -P -Q 3 +python3 ./test.py -f 2-query/union.py -P -Q 3 +python3 ./test.py -f 2-query/union1.py -P -Q 3 +python3 ./test.py -f 2-query/concat2.py -P -Q 3 +python3 ./test.py -f 2-query/concat_ws.py -P -Q 3 +python3 ./test.py -f 2-query/concat_ws2.py -P -Q 3 +python3 ./test.py -f 2-query/check_tsdb.py -P -Q 3 +python3 ./test.py -f 2-query/spread.py -P -Q 3 +python3 ./test.py -f 2-query/hyperloglog.py -P -Q 3 +python3 ./test.py -f 2-query/explain.py -P -Q 3 +python3 ./test.py -f 2-query/leastsquares.py -P -Q 3 +python3 ./test.py -f 2-query/timezone.py -P -Q 3 +python3 ./test.py -f 2-query/Now.py -P -Q 3 +python3 ./test.py -f 2-query/Today.py -P -Q 3 +python3 ./test.py -f 2-query/max.py -P -Q 3 +python3 ./test.py -f 2-query/min.py -P -Q 3 +python3 ./test.py -f 2-query/mode.py -P -Q 3 +python3 ./test.py -f 2-query/count.py -P -Q 3 +python3 ./test.py -f 2-query/countAlwaysReturnValue.py -P -Q 3 +python3 ./test.py -f 2-query/last.py -P -Q 3 +python3 ./test.py -f 2-query/first.py -P -Q 3 +python3 ./test.py -f 2-query/To_iso8601.py -P -Q 3 +python3 ./test.py -f 2-query/To_unixtimestamp.py -P -Q 3 +python3 ./test.py -f 2-query/timetruncate.py -P -Q 3 +python3 ./test.py -f 2-query/diff.py -P -Q 3 +python3 ./test.py -f 2-query/Timediff.py -P -Q 3 +python3 ./test.py -f 2-query/json_tag.py -P -Q 3 +python3 ./test.py -f 2-query/top.py -P -Q 3 +python3 ./test.py -f 2-query/bottom.py -P -Q 3 +python3 ./test.py -f 2-query/percentile.py -P -Q 3 +python3 ./test.py -f 2-query/apercentile.py -P -Q 3 +python3 ./test.py -f 2-query/abs.py -P -Q 3 +python3 ./test.py -f 2-query/ceil.py -P -Q 3 +python3 ./test.py -f 2-query/floor.py -P -Q 3 +python3 ./test.py -f 2-query/round.py -P -Q 3 +python3 ./test.py -f 2-query/log.py -P -Q 3 +python3 ./test.py -f 2-query/pow.py -P -Q 3 +python3 ./test.py -f 2-query/sqrt.py -P -Q 3 +python3 ./test.py -f 2-query/sin.py -P -Q 3 +python3 ./test.py -f 2-query/cos.py -P -Q 3 +python3 ./test.py -f 2-query/tan.py -P -Q 3 +python3 ./test.py -f 2-query/arcsin.py -P -Q 3 +python3 ./test.py -f 2-query/arccos.py -P -Q 3 +python3 ./test.py -f 2-query/arctan.py -P -Q 3 +python3 ./test.py -f 2-query/query_cols_tags_and_or.py -P -Q 3 +python3 ./test.py -f 2-query/nestedQueryInterval.py -P -Q 3 +python3 ./test.py -f 2-query/stablity.py -P -Q 3 +python3 ./test.py -f 2-query/stablity_1.py -P -Q 3 +python3 ./test.py -f 2-query/avg.py -P -Q 3 +python3 ./test.py -f 2-query/elapsed.py -P -Q 3 +python3 ./test.py -f 2-query/csum.py -P -Q 3 +python3 ./test.py -f 2-query/mavg.py -P -Q 3 +python3 ./test.py -f 2-query/sample.py -P -Q 3 +python3 ./test.py -f 2-query/function_diff.py -P -Q 3 +python3 ./test.py -f 2-query/unique.py -P -Q 3 +python3 ./test.py -f 2-query/stateduration.py -P -Q 3 +python3 ./test.py -f 2-query/function_stateduration.py -P -Q 3 +python3 ./test.py -f 2-query/statecount.py -P -Q 3 +python3 ./test.py -f 2-query/tail.py -P -Q 3 +python3 ./test.py -f 2-query/ttl_comment.py -P -Q 3 +python3 ./test.py -f 2-query/distribute_agg_count.py -P -Q 3 +python3 ./test.py -f 2-query/distribute_agg_max.py -P -Q 3 +python3 ./test.py -f 2-query/distribute_agg_min.py -P -Q 3 +python3 ./test.py -f 2-query/distribute_agg_sum.py -P -Q 3 +python3 ./test.py -f 2-query/distribute_agg_spread.py -P -Q 3 +python3 ./test.py -f 2-query/distribute_agg_apercentile.py -P -Q 3 +python3 ./test.py -f 2-query/distribute_agg_avg.py -P -Q 3 +python3 ./test.py -f 2-query/distribute_agg_stddev.py -P -Q 3 +python3 ./test.py -f 2-query/twa.py -P -Q 3 +python3 ./test.py -f 2-query/irate.py -P -Q 3 +python3 ./test.py -f 2-query/function_null.py -P -Q 3 +python3 ./test.py -f 2-query/count_partition.py -P -Q 3 +python3 ./test.py -f 2-query/max_partition.py -P -Q 3 +python3 ./test.py -f 2-query/max_min_last_interval.py -P -Q 3 +python3 ./test.py -f 2-query/last_row_interval.py -P -Q 3 +python3 ./test.py -f 2-query/last_row.py -P -Q 3 +python3 ./test.py -f 2-query/tsbsQuery.py -P -Q 3 +python3 ./test.py -f 2-query/sml.py -P -Q 3 +python3 ./test.py -f 2-query/interp.py -P -Q 3 +python3 ./test.py -f 2-query/case_when.py -P -Q 3 +python3 ./test.py -f 2-query/blockSMA.py -P -Q 3 +python3 ./test.py -f 2-query/projectionDesc.py -P -Q 3 +python3 ./test.py -f 99-TDcase/TD-21561.py -P -Q 3 +python3 ./test.py -f 2-query/between.py -P -Q 4 +python3 ./test.py -f 2-query/distinct.py -P -Q 4 +python3 ./test.py -f 2-query/varchar.py -P -Q 4 +python3 ./test.py -f 2-query/ltrim.py -P -Q 4 +python3 ./test.py -f 2-query/rtrim.py -P -Q 4 +python3 ./test.py -f 2-query/length.py -P -Q 4 +python3 ./test.py -f 2-query/char_length.py -P -Q 4 +python3 ./test.py -f 2-query/upper.py -P -Q 4 +python3 ./test.py -f 2-query/lower.py -P -Q 4 +python3 ./test.py -f 2-query/join.py -P -Q 4 +python3 ./test.py -f 2-query/join2.py -P -Q 4 +python3 ./test.py -f 2-query/substr.py -P -Q 4 +python3 ./test.py -f 2-query/union.py -P -Q 4 +python3 ./test.py -f 2-query/union1.py -P -Q 4 +python3 ./test.py -f 2-query/concat.py -P -Q 4 +python3 ./test.py -f 2-query/concat2.py -P -Q 4 +python3 ./test.py -f 2-query/concat_ws.py -P -Q 4 +python3 ./test.py -f 2-query/concat_ws2.py -P -Q 4 +python3 ./test.py -f 2-query/check_tsdb.py -P -Q 4 +python3 ./test.py -f 2-query/spread.py -P -Q 4 +python3 ./test.py -f 2-query/hyperloglog.py -P -Q 4 +python3 ./test.py -f 2-query/explain.py -P -Q 4 +python3 ./test.py -f 2-query/leastsquares.py -P -Q 4 +python3 ./test.py -f 2-query/timezone.py -P -Q 4 +python3 ./test.py -f 2-query/Now.py -P -Q 4 +python3 ./test.py -f 2-query/Today.py -P -Q 4 +python3 ./test.py -f 2-query/max.py -P -Q 4 +python3 ./test.py -f 2-query/min.py -P -Q 4 +python3 ./test.py -f 2-query/mode.py -P -Q 4 +python3 ./test.py -f 2-query/count.py -P -Q 4 +python3 ./test.py -f 2-query/countAlwaysReturnValue.py -P -Q 4 +python3 ./test.py -f 2-query/last.py -P -Q 4 +python3 ./test.py -f 2-query/first.py -P -Q 4 +python3 ./test.py -f 2-query/To_iso8601.py -P -Q 4 +python3 ./test.py -f 2-query/To_unixtimestamp.py -P -Q 4 +python3 ./test.py -f 2-query/timetruncate.py -P -Q 4 +python3 ./test.py -f 2-query/diff.py -P -Q 4 +python3 ./test.py -f 2-query/Timediff.py -P -Q 4 +python3 ./test.py -f 2-query/json_tag.py -P -Q 4 +python3 ./test.py -f 2-query/top.py -P -Q 4 +python3 ./test.py -f 2-query/bottom.py -P -Q 4 +python3 ./test.py -f 2-query/percentile.py -P -Q 4 +python3 ./test.py -f 2-query/apercentile.py -P -Q 4 +python3 ./test.py -f 2-query/abs.py -P -Q 4 +python3 ./test.py -f 2-query/ceil.py -P -Q 4 +python3 ./test.py -f 2-query/floor.py -P -Q 4 +python3 ./test.py -f 2-query/round.py -P -Q 4 +python3 ./test.py -f 2-query/log.py -P -Q 4 +python3 ./test.py -f 2-query/pow.py -P -Q 4 +python3 ./test.py -f 2-query/sqrt.py -P -Q 4 +python3 ./test.py -f 2-query/sin.py -P -Q 4 +python3 ./test.py -f 2-query/cos.py -P -Q 4 +python3 ./test.py -f 2-query/tan.py -P -Q 4 +python3 ./test.py -f 2-query/arcsin.py -P -Q 4 +python3 ./test.py -f 2-query/arccos.py -P -Q 4 +python3 ./test.py -f 2-query/arctan.py -P -Q 4 +python3 ./test.py -f 2-query/query_cols_tags_and_or.py -P -Q 4 +python3 ./test.py -f 2-query/nestedQueryInterval.py -P -Q 4 +python3 ./test.py -f 2-query/stablity.py -P -Q 4 +python3 ./test.py -f 2-query/stablity_1.py -P -Q 4 +python3 ./test.py -f 2-query/avg.py -P -Q 4 +python3 ./test.py -f 2-query/elapsed.py -P -Q 4 +python3 ./test.py -f 2-query/csum.py -P -Q 4 +python3 ./test.py -f 2-query/mavg.py -P -Q 4 +python3 ./test.py -f 2-query/sample.py -P -Q 4 +python3 ./test.py -f 2-query/cast.py -P -Q 4 +python3 ./test.py -f 2-query/function_diff.py -P -Q 4 +python3 ./test.py -f 2-query/unique.py -P -Q 4 +python3 ./test.py -f 2-query/stateduration.py -P -Q 4 +python3 ./test.py -f 2-query/function_stateduration.py -P -Q 4 +python3 ./test.py -f 2-query/statecount.py -P -Q 4 +python3 ./test.py -f 2-query/tail.py -P -Q 4 +python3 ./test.py -f 2-query/ttl_comment.py -P -Q 4 +python3 ./test.py -f 2-query/distribute_agg_count.py -P -Q 4 +python3 ./test.py -f 2-query/distribute_agg_max.py -P -Q 4 +python3 ./test.py -f 2-query/distribute_agg_min.py -P -Q 4 +python3 ./test.py -f 2-query/distribute_agg_sum.py -P -Q 4 +python3 ./test.py -f 2-query/distribute_agg_spread.py -P -Q 4 +python3 ./test.py -f 2-query/distribute_agg_apercentile.py -P -Q 4 +python3 ./test.py -f 2-query/distribute_agg_avg.py -P -Q 4 +python3 ./test.py -f 2-query/distribute_agg_stddev.py -P -Q 4 +python3 ./test.py -f 2-query/twa.py -P -Q 4 +python3 ./test.py -f 2-query/irate.py -P -Q 4 +python3 ./test.py -f 2-query/function_null.py -P -Q 4 +python3 ./test.py -f 2-query/count_partition.py -P -Q 4 +python3 ./test.py -f 2-query/max_partition.py -P -Q 4 +python3 ./test.py -f 2-query/max_min_last_interval.py -P -Q 4 +python3 ./test.py -f 2-query/last_row_interval.py -P -Q 4 +python3 ./test.py -f 2-query/last_row.py -P -Q 4 +python3 ./test.py -f 2-query/tsbsQuery.py -P -Q 4 +python3 ./test.py -f 2-query/sml.py -P -Q 4 +python3 ./test.py -f 2-query/interp.py -P -Q 4 +python3 ./test.py -f 2-query/case_when.py -P -Q 4 +python3 ./test.py -f 2-query/insert_select.py -P +python3 ./test.py -f 2-query/insert_select.py -P -R +python3 ./test.py -f 2-query/insert_select.py -P -Q 2 +python3 ./test.py -f 2-query/insert_select.py -P -Q 3 +python3 ./test.py -f 2-query/insert_select.py -P -Q 4 +python3 ./test.py -f 2-query/out_of_order.py -P -R +python3 ./test.py -f 2-query/blockSMA.py -P -Q 4 +python3 ./test.py -f 2-query/projectionDesc.py -P -Q 4 +python3 ./test.py -f 2-query/odbc.py -P +python3 ./test.py -f 99-TDcase/TD-21561.py -P -Q 4 +python3 ./test.py -f 99-TDcase/TD-20582.py -P \ No newline at end of file diff --git a/tests/system-test/test-win.bat b/tests/system-test/test-win.bat new file mode 100644 index 0000000000000000000000000000000000000000..662adf3987a254c62da0fb68708e7b0d48cdfb21 --- /dev/null +++ b/tests/system-test/test-win.bat @@ -0,0 +1,96 @@ +@echo off +SETLOCAL EnableDelayedExpansion +for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do ( set "DEL=%%a") +set /a a=0 +if "%1" == "full" ( + echo Windows Taosd Full Test + set /a exitNum=0 + del /Q /F failed.txt + set caseFile="win-test-file" + if not "%2" == "" ( + set caseFile="%2" + ) + for /F "usebackq tokens=*" %%i in (!caseFile!) do ( + call :CheckSkipCase %%i + if !skipCase! == false ( + set line=%%i + if "!line:~,7!" == "python3" ( + set /a a+=1 + echo !a! Processing %%i + call :GetTimeSeconds !time! + set time1=!_timeTemp! + echo Start at !time! + call %%i ARG1 > result_!a!.txt 2>error_!a!.txt || set errorlevel=8 + if errorlevel 1 ( call :colorEcho 0c "failed" &echo. && set /a exitNum=8 && echo %%i >>failed.txt ) else ( call :colorEcho 0a "Success" &echo. ) + ) + ) + ) + exit /b !exitNum! +) +echo Windows Taosd Test +for /F "usebackq tokens=*" %%i in (win-test-file) do ( + for /f "tokens=1* delims= " %%a in ("%%i") do if not "%%a" == "@REM" ( + set /a a+=1 + set timeNow=!time! + echo !a! Processing %%i + call :GetTimeSeconds !timeNow! + set time1=!_timeTemp! + echo Start at !timeNow! + call %%i ARG1 > result_!a!.txt 2>error_!a!.txt || set errorlevel=8 + if errorlevel 1 ( call :colorEcho 0c "failed" &echo. && echo result: && cat result_!a!.txt && echo error: && cat error_!a!.txt && exit /b 8 ) else ( call :colorEcho 0a "Success" &echo. ) + ) +) +@REM echo Linux Taosd Test +@REM for /F "usebackq tokens=*" %%i in (simpletest.bat) do ( +@REM for /f "tokens=1* delims= " %%a in ("%%i") do if not "%%a" == "@REM" ( +@REM set /a a+=1 +@REM echo !a! Processing %%i +@REM call :GetTimeSeconds !time! +@REM set time1=!_timeTemp! +@REM echo Start at !time! +@REM call %%i ARG1 -m %1 > result_!a!.txt 2>error_!a!.txt +@REM if errorlevel 1 ( call :colorEcho 0c "failed" &echo. && echo result: && cat result_!a!.txt && echo error: && cat error_!a!.txt && exit 8 ) else ( call :colorEcho 0a "Success" &echo. ) +@REM ) +@REM ) +exit /b + +:colorEcho +set timeNow=%time% +call :GetTimeSeconds %timeNow% +set time2=%_timeTemp% +set /a interTime=%time2% - %time1% +echo End at %timeNow% , cast %interTime%s +echo off + "%~2" +findstr /v /a:%1 /R "^$" "%~2" nul +del "%~2" > nul 2>&1i +goto :eof + +:GetTimeSeconds +set tt=%1 +set tt=%tt:.= % +set tt=%tt::= % +set tt=%tt: 0= % +set /a index=1 +for %%a in (%tt%) do ( + if !index! EQU 1 ( + set /a hh=%%a + )^ + else if !index! EQU 2 ( + set /a mm=%%a + + )^ + else if !index! EQU 3 ( + set /a ss=%%a + ) + set /a index=index+1 +) +set /a _timeTemp=(%hh%*60+%mm%)*60+%ss% +goto :eof + +:CheckSkipCase +set skipCase=false +if "%*" == "python3 ./test.py -f 1-insert/insertWithMoreVgroup.py" ( set skipCase=false ) +if "%*" == "python3 ./test.py -f 2-query/queryQnode.py" ( set skipCase=false ) +echo %* | grep "\-R" && set skipCase=true +:goto eof \ No newline at end of file diff --git a/tests/system-test/test.py b/tests/system-test/test.py index 2017aad1ca7c980b2040d90e389e0101d8fd734e..7082bb0f22f0ae2ab98a5c8ca8e87f895e1dea54 100644 --- a/tests/system-test/test.py +++ b/tests/system-test/test.py @@ -13,6 +13,7 @@ # pip install src/connector/python/ # -*- coding: utf-8 -*- +import os import sys import getopt import subprocess @@ -22,6 +23,7 @@ import json import platform import socket import threading +import importlib import toml sys.path.append("../pytest") @@ -53,8 +55,39 @@ def checkRunTimeError(): if hwnd: os.system("TASKKILL /F /IM taosd.exe") +# +# run case on previous cluster +# +def runOnPreviousCluster(host, config, fileName): + print("enter run on previeous") + + # load case module + sep = "/" + if platform.system().lower() == 'windows': + sep = os.sep + moduleName = fileName.replace(".py", "").replace(sep, ".") + uModule = importlib.import_module(moduleName) + case = uModule.TDTestCase() + + # create conn + conn = taos.connect(host, config) + + # run case + case.init(conn, False) + try: + case.run() + except Exception as e: + tdLog.notice(repr(e)) + tdLog.exit("%s failed" % (fileName)) + # stop + case.stop() + + if __name__ == "__main__": + # + # analysis paramaters + # fileName = "all" deployPath = "" masterIp = "" @@ -75,8 +108,9 @@ if __name__ == "__main__": replicaVar = 1 asan = False independentMnode = True - opts, args = getopt.gnu_getopt(sys.argv[1:], 'f:p:m:l:scghrd:k:e:N:M:Q:C:RD:n:i:a', [ - 'file=', 'path=', 'master', 'logSql', 'stop', 'cluster', 'valgrind', 'help', 'restart', 'updateCfgDict', 'killv', 'execCmd','dnodeNums','mnodeNums','queryPolicy','createDnodeNums','restful','adaptercfgupdate','replicaVar','independentMnode']) + previousCluster = False + opts, args = getopt.gnu_getopt(sys.argv[1:], 'f:p:m:l:scghrd:k:e:N:M:Q:C:RD:n:i:aP', [ + 'file=', 'path=', 'master', 'logSql', 'stop', 'cluster', 'valgrind', 'help', 'restart', 'updateCfgDict', 'killv', 'execCmd','dnodeNums','mnodeNums','queryPolicy','createDnodeNums','restful','adaptercfgupdate','replicaVar','independentMnode','previous']) for key, value in opts: if key in ['-h', '--help']: tdLog.printNoPrefix( @@ -101,6 +135,7 @@ if __name__ == "__main__": tdLog.printNoPrefix('-n the number of replicas') tdLog.printNoPrefix('-i independentMnode Mnode') tdLog.printNoPrefix('-a address sanitizer mode') + tdLog.printNoPrefix('-P run case with [P]revious cluster, do not create new cluster to run case.') sys.exit(0) @@ -182,6 +217,12 @@ if __name__ == "__main__": if key in ['-n', '--replicaVar']: replicaVar = value + if key in ['-P', '--previous']: + previousCluster = True + + # + # do exeCmd command + # if not execCmd == "": if restful: tAdapter.init(deployPath) @@ -191,6 +232,9 @@ if __name__ == "__main__": exec(execCmd) quit() + # + # do stop option + # if (stop != 0): if (valgrind == 0): toBeKilled = "taosd" @@ -248,6 +292,9 @@ if __name__ == "__main__": tdLog.info('stop All dnodes') + # + # get hostname + # if masterIp == "": host = socket.gethostname() else: @@ -256,8 +303,20 @@ if __name__ == "__main__": host = config["host"] except Exception as r: host = masterIp - tdLog.info("Procedures for tdengine deployed in %s" % (host)) + + # + # do previousCluster option + # + if previousCluster: + tdDnodes.init(deployPath, masterIp) + runOnPreviousCluster(host, tdDnodes.getSimCfgPath(), fileName) + tdLog.info("run on previous cluster end.") + quit() + + # + # windows run + # if platform.system().lower() == 'windows': fileName = fileName.replace("/", os.sep) if (masterIp == "" and not fileName == "0-others\\udf_create.py"): @@ -291,9 +350,9 @@ if __name__ == "__main__": print(r) else: pass - if restful: - tAdapter.init(deployPath, masterIp) - tAdapter.stop(force_kill=True) + # if restful: + tAdapter.init(deployPath, masterIp) + tAdapter.stop(force_kill=True) if dnodeNums == 1 : tdDnodes.deploy(1,updateCfgDict) @@ -306,7 +365,7 @@ if __name__ == "__main__": if queryPolicy != 1: queryPolicy=int(queryPolicy) if restful: - conn = taosrest.connect(url=f"http://{host}:6041") + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") else: conn = taos.connect(host,config=tdDnodes.getSimCfgPath()) @@ -318,7 +377,7 @@ if __name__ == "__main__": for i in range(cursor.rowcount): if res[i][0] == "queryPolicy" : if int(res[i][1]) == int(queryPolicy): - tdLog.success(f'alter queryPolicy to {queryPolicy} successfully') + tdLog.info(f'alter queryPolicy to {queryPolicy} successfully') else: tdLog.debug(res) tdLog.exit(f"alter queryPolicy to {queryPolicy} failed") @@ -343,7 +402,7 @@ if __name__ == "__main__": if not restful: conn = taos.connect(host,config=tdDnodes.getSimCfgPath()) else: - conn = taosrest.connect(url=f"http://{host}:6041") + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") # tdLog.info(tdDnodes.getSimCfgPath(),host) if createDnodeNums == 1: createDnodeNums=dnodeNums @@ -359,7 +418,7 @@ if __name__ == "__main__": if queryPolicy != 1: queryPolicy=int(queryPolicy) if restful: - conn = taosrest.connect(url=f"http://{host}:6041") + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") else: conn = taos.connect(host,config=tdDnodes.getSimCfgPath()) @@ -371,7 +430,7 @@ if __name__ == "__main__": for i in range(cursor.rowcount): if res[i][0] == "queryPolicy" : if int(res[i][1]) == int(queryPolicy): - tdLog.success(f'alter queryPolicy to {queryPolicy} successfully') + tdLog.info(f'alter queryPolicy to {queryPolicy} successfully') else: tdLog.debug(res) tdLog.exit(f"alter queryPolicy to {queryPolicy} failed") @@ -382,11 +441,44 @@ if __name__ == "__main__": if not restful: conn = taos.connect(host="%s"%(host), config=tdDnodes.sim.getCfgDir()) else: - conn = taosrest.connect(url=f"http://{host}:6041") - if is_test_framework: - tdCases.runOneWindows(conn, fileName) + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") + + if testCluster: + tdLog.info("Procedures for testing cluster") + if fileName == "all": + tdCases.runAllCluster() + else: + tdCases.runOneCluster(fileName) else: - tdCases.runAllWindows(conn) + tdLog.info("Procedures for testing self-deployment") + if not restful: + conn = taos.connect(host,config=tdDnodes.getSimCfgPath()) + else: + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") + + if fileName == "all": + tdCases.runAllWindows(conn) + else: + tdCases.runOneWindows(conn, fileName, replicaVar) + + if restart: + if fileName == "all": + tdLog.info("not need to query ") + else: + sp = fileName.rsplit(".", 1) + if len(sp) == 2 and sp[1] == "py": + tdDnodes.stopAll() + tdDnodes.start(1) + time.sleep(1) + if not restful: + conn = taos.connect( host, config=tdDnodes.getSimCfgPath()) + else: + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") + tdLog.info("Procedures for tdengine deployed in %s" % (host)) + tdLog.info("query test after taosd restart") + tdCases.runOneWindows(conn, sp[0] + "_" + "restart.py", replicaVar) + else: + tdLog.info("not need to query") else: tdDnodes.setKillValgrind(killValgrind) tdDnodes.init(deployPath, masterIp) @@ -418,6 +510,7 @@ if __name__ == "__main__": tAdapter.stop(force_kill=True) if dnodeNums == 1 : + # dnode is one tdDnodes.deploy(1,updateCfgDict) tdDnodes.start(1) tdCases.logSql(logSql) @@ -431,7 +524,7 @@ if __name__ == "__main__": if not restful: conn = taos.connect(host,config=tdDnodes.getSimCfgPath()) else: - conn = taosrest.connect(url=f"http://{host}:6041") + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") # tdSql.init(conn.cursor()) # tdSql.execute("create qnode on dnode 1") # tdSql.execute('alter local "queryPolicy" "%d"'%queryPolicy) @@ -439,7 +532,7 @@ if __name__ == "__main__": # for i in range(tdSql.queryRows): # if tdSql.queryResult[i][0] == "queryPolicy" : # if int(tdSql.queryResult[i][1]) == int(queryPolicy): - # tdLog.success('alter queryPolicy to %d successfully'%queryPolicy) + # tdLog.info('alter queryPolicy to %d successfully'%queryPolicy) # else : # tdLog.debug(tdSql.queryResult) # tdLog.exit("alter queryPolicy to %d failed"%queryPolicy) @@ -452,12 +545,13 @@ if __name__ == "__main__": for i in range(cursor.rowcount): if res[i][0] == "queryPolicy" : if int(res[i][1]) == int(queryPolicy): - tdLog.success(f'alter queryPolicy to {queryPolicy} successfully') + tdLog.info(f'alter queryPolicy to {queryPolicy} successfully') else: tdLog.debug(res) tdLog.exit(f"alter queryPolicy to {queryPolicy} failed") else : + # dnode > 1 cluster tdLog.debug("create an cluster with %s nodes and make %s dnode as independent mnode"%(dnodeNums,mnodeNums)) dnodeslist = cluster.configure_cluster(dnodeNums=dnodeNums, mnodeNums=mnodeNums, independentMnode=independentMnode) tdDnodes = ClusterDnodes(dnodeslist) @@ -476,10 +570,11 @@ if __name__ == "__main__": tAdapter.deploy(adapter_cfg_dict) tAdapter.start() + # create taos connect if not restful: conn = taos.connect(host,config=tdDnodes.getSimCfgPath()) else: - conn = taosrest.connect(url=f"http://{host}:6041") + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") print(tdDnodes.getSimCfgPath(),host) if createDnodeNums == 1: createDnodeNums=dnodeNums @@ -494,10 +589,11 @@ if __name__ == "__main__": except Exception as r: print(r) + # do queryPolicy option if queryPolicy != 1: queryPolicy=int(queryPolicy) if restful: - conn = taosrest.connect(url=f"http://{host}:6041") + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") else: conn = taos.connect(host,config=tdDnodes.getSimCfgPath()) @@ -509,12 +605,13 @@ if __name__ == "__main__": for i in range(cursor.rowcount): if res[i][0] == "queryPolicy" : if int(res[i][1]) == int(queryPolicy): - tdLog.success(f'alter queryPolicy to {queryPolicy} successfully') + tdLog.info(f'alter queryPolicy to {queryPolicy} successfully') else: tdLog.debug(res) tdLog.exit(f"alter queryPolicy to {queryPolicy} failed") + # run case if testCluster: tdLog.info("Procedures for testing cluster") if fileName == "all": @@ -526,13 +623,14 @@ if __name__ == "__main__": if not restful: conn = taos.connect(host,config=tdDnodes.getSimCfgPath()) else: - conn = taosrest.connect(url=f"http://{host}:6041") + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") if fileName == "all": tdCases.runAllLinux(conn) else: tdCases.runOneLinux(conn, fileName, replicaVar) + # do restart option if restart: if fileName == "all": tdLog.info("not need to query ") @@ -545,13 +643,14 @@ if __name__ == "__main__": if not restful: conn = taos.connect( host, config=tdDnodes.getSimCfgPath()) else: - conn = taosrest.connect(url=f"http://{host}:6041") + conn = taosrest.connect(url=f"http://{host}:6041",timezone="utc") tdLog.info("Procedures for tdengine deployed in %s" % (host)) tdLog.info("query test after taosd restart") tdCases.runOneLinux(conn, sp[0] + "_" + "restart.py", replicaVar) else: tdLog.info("not need to query") + # close for end if conn is not None: conn.close() if asan: diff --git a/tests/system-test/win-test-file b/tests/system-test/win-test-file new file mode 100644 index 0000000000000000000000000000000000000000..7e68c40fd8b355d3d3cd40161bb2df09886e8570 --- /dev/null +++ b/tests/system-test/win-test-file @@ -0,0 +1,637 @@ +python3 ./test.py -f 1-insert/database_pre_suf.py +python3 ./test.py -f 0-others/balance_vgroups_r1.py -N 6 +python3 ./test.py -f 0-others/taosShell.py +python3 ./test.py -f 0-others/taosShellError.py +python3 ./test.py -f 0-others/taosShellNetChk.py +python3 ./test.py -f 0-others/telemetry.py +python3 ./test.py -f 0-others/backquote_check.py +python3 ./test.py -f 0-others/taosdMonitor.py +python3 ./test.py -f 0-others/taosdShell.py -N 5 -M 3 -Q 3 +python3 ./test.py -f 0-others/cachemodel.py +python3 ./test.py -f 0-others/sysinfo.py +python3 ./test.py -f 0-others/user_control.py +python3 ./test.py -f 0-others/user_manage.py +python3 ./test.py -f 0-others/fsync.py +python3 ./test.py -f 0-others/compatibility.py +python3 ./test.py -f 0-others/tag_index_basic.py +# python3 ./test.py -f 1-insert/alter_database.py +python3 ./test.py -f 1-insert/influxdb_line_taosc_insert.py +python3 ./test.py -f 1-insert/opentsdb_telnet_line_taosc_insert.py +python3 ./test.py -f 1-insert/opentsdb_json_taosc_insert.py +python3 ./test.py -f 1-insert/test_stmt_muti_insert_query.py +python3 ./test.py -f 1-insert/test_stmt_set_tbname_tag.py +python3 ./test.py -f 1-insert/alter_stable.py +python3 ./test.py -f 1-insert/alter_table.py +python3 ./test.py -f 1-insert/boundary.py +python3 ./test.py -f 1-insert/insertWithMoreVgroup.py +python3 ./test.py -f 1-insert/table_comment.py +python3 ./test.py -f 1-insert/time_range_wise.py +python3 ./test.py -f 1-insert/block_wise.py +python3 ./test.py -f 1-insert/create_retentions.py +python3 ./test.py -f 1-insert/mutil_stage.py +python3 ./test.py -f 1-insert/table_param_ttl.py +python3 ./test.py -f 1-insert/table_param_ttl.py -R +python3 ./test.py -f 1-insert/update_data_muti_rows.py +python3 ./test.py -f 1-insert/db_tb_name_check.py +python3 ./test.py -f 1-insert/InsertFuturets.py +python3 ./test.py -f 0-others/show.py +python3 ./test.py -f 0-others/information_schema.py +python3 ./test.py -f 2-query/abs.py +python3 ./test.py -f 2-query/abs.py -R +python3 ./test.py -f 2-query/and_or_for_byte.py +python3 ./test.py -f 2-query/and_or_for_byte.py -R +python3 ./test.py -f 2-query/apercentile.py +python3 ./test.py -f 2-query/apercentile.py -R +python3 ./test.py -f 2-query/arccos.py +python3 ./test.py -f 2-query/arccos.py -R +python3 ./test.py -f 2-query/arcsin.py +python3 ./test.py -f 2-query/arcsin.py -R +python3 ./test.py -f 2-query/arctan.py +python3 ./test.py -f 2-query/arctan.py -R +python3 ./test.py -f 2-query/avg.py +python3 ./test.py -f 2-query/avg.py -R +python3 ./test.py -f 2-query/between.py +python3 ./test.py -f 2-query/between.py -R +python3 ./test.py -f 2-query/bottom.py +python3 ./test.py -f 2-query/bottom.py -R +python3 ./test.py -f 2-query/cast.py +python3 ./test.py -f 2-query/cast.py -R +python3 ./test.py -f 2-query/ceil.py +python3 ./test.py -f 2-query/ceil.py -R +python3 ./test.py -f 2-query/char_length.py +python3 ./test.py -f 2-query/char_length.py -R +python3 ./test.py -f 2-query/check_tsdb.py +python3 ./test.py -f 2-query/check_tsdb.py -R +python3 ./test.py -f 2-query/concat.py +python3 ./test.py -f 2-query/concat.py -R +python3 ./test.py -f 2-query/concat_ws.py +python3 ./test.py -f 2-query/concat_ws.py -R +python3 ./test.py -f 2-query/concat_ws2.py +python3 ./test.py -f 2-query/concat_ws2.py -R +python3 ./test.py -f 2-query/cos.py +python3 ./test.py -f 2-query/cos.py -R +python3 ./test.py -f 2-query/count_partition.py +python3 ./test.py -f 2-query/count_partition.py -R +python3 ./test.py -f 2-query/count.py +python3 ./test.py -f 2-query/count.py -R +python3 ./test.py -f 2-query/countAlwaysReturnValue.py +python3 ./test.py -f 2-query/countAlwaysReturnValue.py -R +python3 ./test.py -f 2-query/db.py +python3 ./test.py -f 2-query/db.py -N 3 -n 3 -R +python3 ./test.py -f 2-query/diff.py +python3 ./test.py -f 2-query/diff.py -R +python3 ./test.py -f 2-query/distinct.py +python3 ./test.py -f 2-query/distinct.py -R +python3 ./test.py -f 2-query/distribute_agg_apercentile.py +python3 ./test.py -f 2-query/distribute_agg_apercentile.py -R +python3 ./test.py -f 2-query/distribute_agg_avg.py +python3 ./test.py -f 2-query/distribute_agg_avg.py -R +python3 ./test.py -f 2-query/distribute_agg_count.py +python3 ./test.py -f 2-query/distribute_agg_count.py -R +python3 ./test.py -f 2-query/distribute_agg_max.py +python3 ./test.py -f 2-query/distribute_agg_max.py -R +python3 ./test.py -f 2-query/distribute_agg_min.py +python3 ./test.py -f 2-query/distribute_agg_min.py -R +python3 ./test.py -f 2-query/distribute_agg_spread.py +python3 ./test.py -f 2-query/distribute_agg_spread.py -R +python3 ./test.py -f 2-query/distribute_agg_stddev.py +python3 ./test.py -f 2-query/distribute_agg_stddev.py -R +python3 ./test.py -f 2-query/distribute_agg_sum.py +python3 ./test.py -f 2-query/distribute_agg_sum.py -R +python3 ./test.py -f 2-query/explain.py +python3 ./test.py -f 2-query/explain.py -R +python3 ./test.py -f 2-query/first.py +python3 ./test.py -f 2-query/first.py -R +python3 ./test.py -f 2-query/floor.py +python3 ./test.py -f 2-query/floor.py -R +python3 ./test.py -f 2-query/function_null.py +python3 ./test.py -f 2-query/function_null.py -R +python3 ./test.py -f 2-query/function_stateduration.py +python3 ./test.py -f 2-query/function_stateduration.py -R +python3 ./test.py -f 2-query/histogram.py +python3 ./test.py -f 2-query/histogram.py -R +python3 ./test.py -f 2-query/hyperloglog.py +python3 ./test.py -f 2-query/hyperloglog.py -R +python3 ./test.py -f 2-query/interp.py +python3 ./test.py -f 2-query/interp.py -R +python3 ./test.py -f 2-query/irate.py +python3 ./test.py -f 2-query/irate.py -R +python3 ./test.py -f 2-query/join.py +python3 ./test.py -f 2-query/join.py -R +python3 ./test.py -f 2-query/last_row.py +python3 ./test.py -f 2-query/last_row.py -R +python3 ./test.py -f 2-query/last.py +python3 ./test.py -f 2-query/last.py -R +python3 ./test.py -f 2-query/leastsquares.py +python3 ./test.py -f 2-query/leastsquares.py -R +python3 ./test.py -f 2-query/length.py +python3 ./test.py -f 2-query/length.py -R +python3 ./test.py -f 2-query/limit.py +python3 ./test.py -f 2-query/log.py +python3 ./test.py -f 2-query/log.py -R +python3 ./test.py -f 2-query/lower.py +python3 ./test.py -f 2-query/lower.py -R +python3 ./test.py -f 2-query/ltrim.py +python3 ./test.py -f 2-query/ltrim.py -R +python3 ./test.py -f 2-query/mavg.py +python3 ./test.py -f 2-query/mavg.py -R +python3 ./test.py -f 2-query/max_partition.py +python3 ./test.py -f 2-query/max_partition.py -R +python3 ./test.py -f 2-query/max_min_last_interval.py +python3 ./test.py -f 2-query/max.py +python3 ./test.py -f 2-query/max.py -R +python3 ./test.py -f 2-query/min.py +python3 ./test.py -f 2-query/min.py -R +python3 ./test.py -f 2-query/mode.py +python3 ./test.py -f 2-query/mode.py -R +python3 ./test.py -f 2-query/Now.py +python3 ./test.py -f 2-query/Now.py -R +python3 ./test.py -f 2-query/percentile.py +python3 ./test.py -f 2-query/percentile.py -R +python3 ./test.py -f 2-query/pow.py +python3 ./test.py -f 2-query/pow.py -R +python3 ./test.py -f 2-query/query_cols_tags_and_or.py +python3 ./test.py -f 2-query/query_cols_tags_and_or.py -R +python3 ./test.py -f 2-query/round.py +python3 ./test.py -f 2-query/round.py -R +python3 ./test.py -f 2-query/rtrim.py +python3 ./test.py -f 2-query/rtrim.py -R +python3 ./test.py -f 2-query/sample.py +python3 ./test.py -f 2-query/sample.py -R +python3 ./test.py -f 2-query/sin.py +python3 ./test.py -f 2-query/sin.py -R +python3 ./test.py -f 2-query/smaTest.py +python3 ./test.py -f 2-query/smaTest.py -R +python3 ./test.py -f 2-query/sml.py +python3 ./test.py -f 2-query/sml.py -R +python3 ./test.py -f 2-query/spread.py +python3 ./test.py -f 2-query/spread.py -R +python3 ./test.py -f 2-query/sqrt.py +python3 ./test.py -f 2-query/sqrt.py -R +python3 ./test.py -f 2-query/statecount.py +python3 ./test.py -f 2-query/statecount.py -R +python3 ./test.py -f 2-query/stateduration.py +python3 ./test.py -f 2-query/stateduration.py -R +python3 ./test.py -f 2-query/substr.py +python3 ./test.py -f 2-query/substr.py -R +python3 ./test.py -f 2-query/sum.py +python3 ./test.py -f 2-query/sum.py -R +python3 ./test.py -f 2-query/tail.py +python3 ./test.py -f 2-query/tail.py -R +python3 ./test.py -f 2-query/tan.py +python3 ./test.py -f 2-query/tan.py -R +python3 ./test.py -f 2-query/Timediff.py +python3 ./test.py -f 2-query/Timediff.py -R +python3 ./test.py -f 2-query/timetruncate.py +python3 ./test.py -f 2-query/timetruncate.py -R +python3 ./test.py -f 2-query/timezone.py +python3 ./test.py -f 2-query/timezone.py -R +python3 ./test.py -f 2-query/To_iso8601.py +python3 ./test.py -f 2-query/To_iso8601.py -R +python3 ./test.py -f 2-query/To_unixtimestamp.py +python3 ./test.py -f 2-query/To_unixtimestamp.py -R +python3 ./test.py -f 2-query/Today.py +python3 ./test.py -f 2-query/Today.py -R +python3 ./test.py -f 2-query/top.py +python3 ./test.py -f 2-query/top.py -R +python3 ./test.py -f 2-query/tsbsQuery.py +python3 ./test.py -f 2-query/tsbsQuery.py -R +python3 ./test.py -f 2-query/ttl_comment.py +python3 ./test.py -f 2-query/ttl_comment.py -R +python3 ./test.py -f 2-query/twa.py +python3 ./test.py -f 2-query/twa.py -R +python3 ./test.py -f 2-query/union.py +python3 ./test.py -f 2-query/union.py -R +python3 ./test.py -f 2-query/unique.py +python3 ./test.py -f 2-query/unique.py -R +python3 ./test.py -f 2-query/upper.py +python3 ./test.py -f 2-query/upper.py -R +python3 ./test.py -f 2-query/varchar.py +python3 ./test.py -f 2-query/varchar.py -R +python3 ./test.py -f 2-query/case_when.py +python3 ./test.py -f 2-query/case_when.py -R +python3 ./test.py -f 2-query/blockSMA.py +python3 ./test.py -f 2-query/blockSMA.py -R +python3 ./test.py -f 1-insert/update_data.py +python3 ./test.py -f 1-insert/tb_100w_data_order.py +python3 ./test.py -f 1-insert/delete_stable.py +python3 ./test.py -f 1-insert/delete_childtable.py +python3 ./test.py -f 1-insert/delete_normaltable.py +python3 ./test.py -f 1-insert/keep_expired.py +python3 ./test.py -f 1-insert/drop.py +python3 ./test.py -f 1-insert/drop.py -N 3 -M 3 -i False -n 3 +python3 ./test.py -f 2-query/join2.py +python3 ./test.py -f 2-query/union1.py +python3 ./test.py -f 2-query/concat2.py +python3 ./test.py -f 2-query/json_tag.py +python3 ./test.py -f 2-query/nestedQuery.py +python3 ./test.py -f 2-query/nestedQueryInterval.py +python3 ./test.py -f 2-query/nestedQuery_str.py +python3 ./test.py -f 2-query/nestedQuery_math.py +python3 ./test.py -f 2-query/nestedQuery_time.py +python3 ./test.py -f 2-query/stablity.py +python3 ./test.py -f 2-query/stablity_1.py +python3 ./test.py -f 2-query/elapsed.py +python3 ./test.py -f 2-query/csum.py +python3 ./test.py -f 2-query/function_diff.py +python3 ./test.py -f 2-query/tagFilter.py +python3 ./test.py -f 2-query/queryQnode.py +python3 ./test.py -f 6-cluster/5dnode1mnode.py +python3 ./test.py -f 6-cluster/5dnode2mnode.py -N 5 +python3 ./test.py -f 6-cluster/5dnode3mnodeStop.py -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeStop.py -N 5 -M 3 -i False +python3 ./test.py -f 6-cluster/5dnode3mnodeStop2Follower.py -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeStop2Follower.py -N 5 -M 3 -i False +python3 ./test.py -f 6-cluster/5dnode3mnodeStopLoop.py -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateDb.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateDb.py -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateDb.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateDb.py -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateDb.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateDb.py -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeModifyMeta.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeModifyMeta.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateStb.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopDnodeCreateStb.py -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateStb.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopMnodeCreateStb.py -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateStb.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeSep1VnodeStopVnodeCreateStb.py -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeRestartDnodeInsertData.py -N 6 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeRestartDnodeInsertData.py -N 6 -M 3 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeAdd1Ddnoe.py -N 7 -M 3 -C 6 +python3 ./test.py -f 6-cluster/5dnode3mnodeAdd1Ddnoe.py -N 7 -M 3 -C 6 -n 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeRecreateMnode.py -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeStopFollowerLeader.py -N 5 -M 3 +python3 ./test.py -f 6-cluster/5dnode3mnodeStop2Follower.py -N 5 -M 3 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_createDb_replica1.py -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica1_insertdatas.py -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica1_insertdatas_querys.py -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica3_insertdatas.py -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica3_insertdatas_querys.py -N 4 -M 1 +python3 ./test.py -f 6-cluster/vnode/4dnode1mnode_basic_replica3_vgroups.py -N 4 -M 1 +python3 ./test.py -f 7-tmq/create_wrong_topic.py +python3 ./test.py -f 7-tmq/dropDbR3ConflictTransaction.py -N 3 +python3 ./test.py -f 7-tmq/basic5.py +python3 ./test.py -f 7-tmq/subscribeDb.py -N 3 -n 3 +python3 ./test.py -f 7-tmq/subscribeDb0.py -N 3 -n 3 +python3 ./test.py -f 7-tmq/subscribeDb1.py +python3 ./test.py -f 7-tmq/subscribeDb2.py +python3 ./test.py -f 7-tmq/subscribeDb3.py +python3 ./test.py -f 7-tmq/subscribeDb4.py +python3 ./test.py -f 7-tmq/subscribeStb.py +python3 ./test.py -f 7-tmq/subscribeStb0.py +python3 ./test.py -f 7-tmq/subscribeStb1.py +python3 ./test.py -f 7-tmq/subscribeStb2.py +python3 ./test.py -f 7-tmq/subscribeStb3.py +python3 ./test.py -f 7-tmq/subscribeStb4.py +python3 ./test.py -f 7-tmq/db.py +python3 ./test.py -f 7-tmq/tmqError.py +python3 ./test.py -f 7-tmq/schema.py +python3 ./test.py -f 7-tmq/stbFilter.py +python3 ./test.py -f 7-tmq/tmqCheckData.py +python3 ./test.py -f 7-tmq/tmqCheckData1.py +python3 ./test.py -f 7-tmq/tmqConsumerGroup.py +python3 ./test.py -f 7-tmq/tmqShow.py +python3 ./test.py -f 7-tmq/tmqAlterSchema.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb.py -N 3 -n 3 +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1.py -N 3 -n 3 +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-1ctb.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-1ctb.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-1ctb-funcNFilter.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb-funcNFilter.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb-mutilVg-mutilCtb.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-1ctb-funcNFilter.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb-funcNFilter.py +python3 ./test.py -f 7-tmq/tmqConsFromTsdb1-mutilVg-mutilCtb.py +python3 ./test.py -f 7-tmq/tmqAutoCreateTbl.py +python3 ./test.py -f 7-tmq/tmqDnodeRestart.py +python3 ./test.py -f 7-tmq/tmqDnodeRestart1.py +python3 ./test.py -f 7-tmq/tmqUpdate-1ctb.py +python3 ./test.py -f 7-tmq/tmqUpdateWithConsume.py -N 3 -n 3 +python3 ./test.py -f 7-tmq/tmqUpdate-multiCtb-snapshot0.py +python3 ./test.py -f 7-tmq/tmqUpdate-multiCtb-snapshot1.py +python3 ./test.py -f 7-tmq/tmqDelete-1ctb.py +python3 ./test.py -f 7-tmq/tmqDelete-multiCtb.py -N 3 -n 3 +python3 ./test.py -f 7-tmq/tmqDropStb.py +python3 ./test.py -f 7-tmq/tmqDropStbCtb.py +python3 ./test.py -f 7-tmq/tmqDropNtb-snapshot0.py +python3 ./test.py -f 7-tmq/tmqDropNtb-snapshot1.py +python3 ./test.py -f 7-tmq/stbTagFilter-1ctb.py +python3 ./test.py -f 7-tmq/dataFromTsdbNWal.py +python3 ./test.py -f 7-tmq/dataFromTsdbNWal-multiCtb.py +python3 ./test.py -f 7-tmq/tmq_taosx.py +python3 ./test.py -f 7-tmq/stbTagFilter-multiCtb.py +python3 ./test.py -f 99-TDcase/TD-19201.py +python3 ./test.py -f 99-TDcase/TD-21561.py +python3 ./test.py -f 7-tmq/tmqSubscribeStb-r3.py -N 5 +python3 ./test.py -f 7-tmq/tmq3mnodeSwitch.py -N 6 -M 3 +python3 ./test.py -f 7-tmq/tmq3mnodeSwitch.py -N 6 -M 3 -n 3 +python3 ./test.py -f 2-query/between.py -Q 2 +python3 ./test.py -f 2-query/distinct.py -Q 2 +python3 ./test.py -f 2-query/varchar.py -Q 2 +python3 ./test.py -f 2-query/ltrim.py -Q 2 +python3 ./test.py -f 2-query/rtrim.py -Q 2 +python3 ./test.py -f 2-query/length.py -Q 2 +python3 ./test.py -f 2-query/char_length.py -Q 2 +python3 ./test.py -f 2-query/upper.py -Q 2 +python3 ./test.py -f 2-query/lower.py -Q 2 +python3 ./test.py -f 2-query/join.py -Q 2 +python3 ./test.py -f 2-query/join2.py -Q 2 +python3 ./test.py -f 2-query/cast.py -Q 2 +python3 ./test.py -f 2-query/substr.py -Q 2 +python3 ./test.py -f 2-query/union.py -Q 2 +python3 ./test.py -f 2-query/union1.py -Q 2 +python3 ./test.py -f 2-query/concat.py -Q 2 +python3 ./test.py -f 2-query/concat2.py -Q 2 +python3 ./test.py -f 2-query/concat_ws.py -Q 2 +python3 ./test.py -f 2-query/concat_ws2.py -Q 2 +python3 ./test.py -f 2-query/check_tsdb.py -Q 2 +python3 ./test.py -f 2-query/spread.py -Q 2 +python3 ./test.py -f 2-query/hyperloglog.py -Q 2 +python3 ./test.py -f 2-query/explain.py -Q 2 +python3 ./test.py -f 2-query/leastsquares.py -Q 2 +python3 ./test.py -f 2-query/timezone.py -Q 2 +python3 ./test.py -f 2-query/Now.py -Q 2 +python3 ./test.py -f 2-query/Today.py -Q 2 +python3 ./test.py -f 2-query/max.py -Q 2 +python3 ./test.py -f 2-query/min.py -Q 2 +python3 ./test.py -f 2-query/mode.py -Q 2 +python3 ./test.py -f 2-query/count.py -Q 2 +python3 ./test.py -f 2-query/countAlwaysReturnValue.py -Q 2 +python3 ./test.py -f 2-query/last.py -Q 2 +python3 ./test.py -f 2-query/first.py -Q 2 +python3 ./test.py -f 2-query/To_iso8601.py -Q 2 +python3 ./test.py -f 2-query/To_unixtimestamp.py -Q 2 +python3 ./test.py -f 2-query/timetruncate.py -Q 2 +python3 ./test.py -f 2-query/diff.py -Q 2 +python3 ./test.py -f 2-query/Timediff.py -Q 2 +python3 ./test.py -f 2-query/json_tag.py -Q 2 +python3 ./test.py -f 2-query/top.py -Q 2 +python3 ./test.py -f 2-query/bottom.py -Q 2 +python3 ./test.py -f 2-query/percentile.py -Q 2 +python3 ./test.py -f 2-query/apercentile.py -Q 2 +python3 ./test.py -f 2-query/abs.py -Q 2 +python3 ./test.py -f 2-query/ceil.py -Q 2 +python3 ./test.py -f 2-query/floor.py -Q 2 +python3 ./test.py -f 2-query/round.py -Q 2 +python3 ./test.py -f 2-query/log.py -Q 2 +python3 ./test.py -f 2-query/pow.py -Q 2 +python3 ./test.py -f 2-query/sqrt.py -Q 2 +python3 ./test.py -f 2-query/sin.py -Q 2 +python3 ./test.py -f 2-query/cos.py -Q 2 +python3 ./test.py -f 2-query/tan.py -Q 2 +python3 ./test.py -f 2-query/arcsin.py -Q 2 +python3 ./test.py -f 2-query/arccos.py -Q 2 +python3 ./test.py -f 2-query/arctan.py -Q 2 +python3 ./test.py -f 2-query/query_cols_tags_and_or.py -Q 2 +python3 ./test.py -f 2-query/interp.py -Q 2 +python3 ./test.py -f 2-query/nestedQuery.py -Q 2 +python3 ./test.py -f 2-query/nestedQueryInterval.py -Q 2 +python3 ./test.py -f 2-query/nestedQuery_str.py -Q 2 +python3 ./test.py -f 2-query/nestedQuery_math.py -Q 2 +python3 ./test.py -f 2-query/nestedQuery_time.py -Q 2 +python3 ./test.py -f 2-query/stablity.py -Q 2 +python3 ./test.py -f 2-query/stablity_1.py -Q 2 +python3 ./test.py -f 2-query/avg.py -Q 2 +python3 ./test.py -f 2-query/elapsed.py -Q 2 +python3 ./test.py -f 2-query/csum.py -Q 2 +python3 ./test.py -f 2-query/mavg.py -Q 2 +python3 ./test.py -f 2-query/sample.py -Q 2 +python3 ./test.py -f 2-query/function_diff.py -Q 2 +python3 ./test.py -f 2-query/unique.py -Q 2 +python3 ./test.py -f 2-query/stateduration.py -Q 2 +python3 ./test.py -f 2-query/function_stateduration.py -Q 2 +python3 ./test.py -f 2-query/statecount.py -Q 2 +python3 ./test.py -f 2-query/tail.py -Q 2 +python3 ./test.py -f 2-query/ttl_comment.py -Q 2 +python3 ./test.py -f 2-query/distribute_agg_count.py -Q 2 +python3 ./test.py -f 2-query/distribute_agg_max.py -Q 2 +python3 ./test.py -f 2-query/distribute_agg_min.py -Q 2 +python3 ./test.py -f 2-query/distribute_agg_sum.py -Q 2 +python3 ./test.py -f 2-query/distribute_agg_spread.py -Q 2 +python3 ./test.py -f 2-query/distribute_agg_apercentile.py -Q 2 +python3 ./test.py -f 2-query/distribute_agg_avg.py -Q 2 +python3 ./test.py -f 2-query/distribute_agg_stddev.py -Q 2 +python3 ./test.py -f 2-query/twa.py -Q 2 +python3 ./test.py -f 2-query/irate.py -Q 2 +python3 ./test.py -f 2-query/function_null.py -Q 2 +python3 ./test.py -f 2-query/count_partition.py -Q 2 +python3 ./test.py -f 2-query/max_partition.py -Q 2 +python3 ./test.py -f 2-query/max_min_last_interval.py -Q 2 +python3 ./test.py -f 2-query/last_row.py -Q 2 +python3 ./test.py -f 2-query/tsbsQuery.py -Q 2 +python3 ./test.py -f 2-query/sml.py -Q 2 +python3 ./test.py -f 2-query/case_when.py -Q 2 +python3 ./test.py -f 2-query/blockSMA.py -Q 2 +python3 ./test.py -f 99-TDcase/TD-21561.py -Q 2 +python3 ./test.py -f 2-query/between.py -Q 3 +python3 ./test.py -f 2-query/distinct.py -Q 3 +python3 ./test.py -f 2-query/varchar.py -Q 3 +python3 ./test.py -f 2-query/ltrim.py -Q 3 +python3 ./test.py -f 2-query/rtrim.py -Q 3 +python3 ./test.py -f 2-query/length.py -Q 3 +python3 ./test.py -f 2-query/char_length.py -Q 3 +python3 ./test.py -f 2-query/upper.py -Q 3 +python3 ./test.py -f 2-query/lower.py -Q 3 +python3 ./test.py -f 2-query/join.py -Q 3 +python3 ./test.py -f 2-query/join2.py -Q 3 +python3 ./test.py -f 2-query/cast.py -Q 3 +python3 ./test.py -f 2-query/substr.py -Q 3 +python3 ./test.py -f 2-query/union.py -Q 3 +python3 ./test.py -f 2-query/union1.py -Q 3 +python3 ./test.py -f 2-query/concat.py -Q 3 +python3 ./test.py -f 2-query/concat2.py -Q 3 +python3 ./test.py -f 2-query/concat_ws.py -Q 3 +python3 ./test.py -f 2-query/concat_ws2.py -Q 3 +python3 ./test.py -f 2-query/check_tsdb.py -Q 3 +python3 ./test.py -f 2-query/spread.py -Q 3 +python3 ./test.py -f 2-query/hyperloglog.py -Q 3 +python3 ./test.py -f 2-query/explain.py -Q 3 +python3 ./test.py -f 2-query/leastsquares.py -Q 3 +python3 ./test.py -f 2-query/timezone.py -Q 3 +python3 ./test.py -f 2-query/Now.py -Q 3 +python3 ./test.py -f 2-query/Today.py -Q 3 +python3 ./test.py -f 2-query/max.py -Q 3 +python3 ./test.py -f 2-query/min.py -Q 3 +python3 ./test.py -f 2-query/mode.py -Q 3 +python3 ./test.py -f 2-query/count.py -Q 3 +python3 ./test.py -f 2-query/countAlwaysReturnValue.py -Q 3 +python3 ./test.py -f 2-query/last.py -Q 3 +python3 ./test.py -f 2-query/first.py -Q 3 +python3 ./test.py -f 2-query/To_iso8601.py -Q 3 +python3 ./test.py -f 2-query/To_unixtimestamp.py -Q 3 +python3 ./test.py -f 2-query/timetruncate.py -Q 3 +python3 ./test.py -f 2-query/diff.py -Q 3 +python3 ./test.py -f 2-query/Timediff.py -Q 3 +python3 ./test.py -f 2-query/json_tag.py -Q 3 +python3 ./test.py -f 2-query/top.py -Q 3 +python3 ./test.py -f 2-query/bottom.py -Q 3 +python3 ./test.py -f 2-query/percentile.py -Q 3 +python3 ./test.py -f 2-query/apercentile.py -Q 3 +python3 ./test.py -f 2-query/abs.py -Q 3 +python3 ./test.py -f 2-query/ceil.py -Q 3 +python3 ./test.py -f 2-query/floor.py -Q 3 +python3 ./test.py -f 2-query/round.py -Q 3 +python3 ./test.py -f 2-query/log.py -Q 3 +python3 ./test.py -f 2-query/pow.py -Q 3 +python3 ./test.py -f 2-query/sqrt.py -Q 3 +python3 ./test.py -f 2-query/sin.py -Q 3 +python3 ./test.py -f 2-query/cos.py -Q 3 +python3 ./test.py -f 2-query/tan.py -Q 3 +python3 ./test.py -f 2-query/arcsin.py -Q 3 +python3 ./test.py -f 2-query/arccos.py -Q 3 +python3 ./test.py -f 2-query/arctan.py -Q 3 +python3 ./test.py -f 2-query/query_cols_tags_and_or.py -Q 3 +python3 ./test.py -f 2-query/nestedQueryInterval.py -Q 3 +python3 ./test.py -f 2-query/stablity.py -Q 3 +python3 ./test.py -f 2-query/stablity_1.py -Q 3 +python3 ./test.py -f 2-query/avg.py -Q 3 +python3 ./test.py -f 2-query/elapsed.py -Q 3 +python3 ./test.py -f 2-query/csum.py -Q 3 +python3 ./test.py -f 2-query/mavg.py -Q 3 +python3 ./test.py -f 2-query/sample.py -Q 3 +python3 ./test.py -f 2-query/function_diff.py -Q 3 +python3 ./test.py -f 2-query/unique.py -Q 3 +python3 ./test.py -f 2-query/stateduration.py -Q 3 +python3 ./test.py -f 2-query/function_stateduration.py -Q 3 +python3 ./test.py -f 2-query/statecount.py -Q 3 +python3 ./test.py -f 2-query/tail.py -Q 3 +python3 ./test.py -f 2-query/ttl_comment.py -Q 3 +python3 ./test.py -f 2-query/distribute_agg_count.py -Q 3 +python3 ./test.py -f 2-query/distribute_agg_max.py -Q 3 +python3 ./test.py -f 2-query/distribute_agg_min.py -Q 3 +python3 ./test.py -f 2-query/distribute_agg_sum.py -Q 3 +python3 ./test.py -f 2-query/distribute_agg_spread.py -Q 3 +python3 ./test.py -f 2-query/distribute_agg_apercentile.py -Q 3 +python3 ./test.py -f 2-query/distribute_agg_avg.py -Q 3 +python3 ./test.py -f 2-query/distribute_agg_stddev.py -Q 3 +python3 ./test.py -f 2-query/twa.py -Q 3 +python3 ./test.py -f 2-query/irate.py -Q 3 +python3 ./test.py -f 2-query/function_null.py -Q 3 +python3 ./test.py -f 2-query/count_partition.py -Q 3 +python3 ./test.py -f 2-query/max_partition.py -Q 3 +python3 ./test.py -f 2-query/max_min_last_interval.py -Q 3 +python3 ./test.py -f 2-query/last_row.py -Q 3 +python3 ./test.py -f 2-query/tsbsQuery.py -Q 3 +python3 ./test.py -f 2-query/sml.py -Q 3 +python3 ./test.py -f 2-query/interp.py -Q 3 +python3 ./test.py -f 2-query/case_when.py -Q 3 +python3 ./test.py -f 2-query/blockSMA.py -Q 3 +python3 ./test.py -f 99-TDcase/TD-21561.py -Q 3 +python3 ./test.py -f 2-query/between.py -Q 4 +python3 ./test.py -f 2-query/distinct.py -Q 4 +python3 ./test.py -f 2-query/varchar.py -Q 4 +python3 ./test.py -f 2-query/ltrim.py -Q 4 +python3 ./test.py -f 2-query/rtrim.py -Q 4 +python3 ./test.py -f 2-query/length.py -Q 4 +python3 ./test.py -f 2-query/char_length.py -Q 4 +python3 ./test.py -f 2-query/upper.py -Q 4 +python3 ./test.py -f 2-query/lower.py -Q 4 +python3 ./test.py -f 2-query/join.py -Q 4 +python3 ./test.py -f 2-query/join2.py -Q 4 +python3 ./test.py -f 2-query/substr.py -Q 4 +python3 ./test.py -f 2-query/union.py -Q 4 +python3 ./test.py -f 2-query/union1.py -Q 4 +python3 ./test.py -f 2-query/concat.py -Q 4 +python3 ./test.py -f 2-query/concat2.py -Q 4 +python3 ./test.py -f 2-query/concat_ws.py -Q 4 +python3 ./test.py -f 2-query/concat_ws2.py -Q 4 +python3 ./test.py -f 2-query/check_tsdb.py -Q 4 +python3 ./test.py -f 2-query/spread.py -Q 4 +python3 ./test.py -f 2-query/hyperloglog.py -Q 4 +python3 ./test.py -f 2-query/explain.py -Q 4 +python3 ./test.py -f 2-query/leastsquares.py -Q 4 +python3 ./test.py -f 2-query/timezone.py -Q 4 +python3 ./test.py -f 2-query/Now.py -Q 4 +python3 ./test.py -f 2-query/Today.py -Q 4 +python3 ./test.py -f 2-query/max.py -Q 4 +python3 ./test.py -f 2-query/min.py -Q 4 +python3 ./test.py -f 2-query/mode.py -Q 4 +python3 ./test.py -f 2-query/count.py -Q 4 +python3 ./test.py -f 2-query/countAlwaysReturnValue.py -Q 4 +python3 ./test.py -f 2-query/last.py -Q 4 +python3 ./test.py -f 2-query/first.py -Q 4 +python3 ./test.py -f 2-query/To_iso8601.py -Q 4 +python3 ./test.py -f 2-query/To_unixtimestamp.py -Q 4 +python3 ./test.py -f 2-query/timetruncate.py -Q 4 +python3 ./test.py -f 2-query/diff.py -Q 4 +python3 ./test.py -f 2-query/Timediff.py -Q 4 +python3 ./test.py -f 2-query/top.py -Q 4 +python3 ./test.py -f 2-query/bottom.py -Q 4 +python3 ./test.py -f 2-query/percentile.py -Q 4 +python3 ./test.py -f 2-query/apercentile.py -Q 4 +python3 ./test.py -f 2-query/abs.py -Q 4 +python3 ./test.py -f 2-query/ceil.py -Q 4 +python3 ./test.py -f 2-query/floor.py -Q 4 +python3 ./test.py -f 2-query/round.py -Q 4 +python3 ./test.py -f 2-query/log.py -Q 4 +python3 ./test.py -f 2-query/pow.py -Q 4 +python3 ./test.py -f 2-query/sqrt.py -Q 4 +python3 ./test.py -f 2-query/sin.py -Q 4 +python3 ./test.py -f 2-query/cos.py -Q 4 +python3 ./test.py -f 2-query/tan.py -Q 4 +python3 ./test.py -f 2-query/arcsin.py -Q 4 +python3 ./test.py -f 2-query/arccos.py -Q 4 +python3 ./test.py -f 2-query/arctan.py -Q 4 +python3 ./test.py -f 2-query/query_cols_tags_and_or.py -Q 4 +python3 ./test.py -f 2-query/nestedQuery.py -Q 4 +python3 ./test.py -f 2-query/nestedQueryInterval.py -Q 4 +python3 ./test.py -f 2-query/nestedQuery_str.py -Q 4 +python3 ./test.py -f 2-query/nestedQuery_math.py -Q 4 +python3 ./test.py -f 2-query/nestedQuery_time.py -Q 4 +python3 ./test.py -f 2-query/avg.py -Q 4 +python3 ./test.py -f 2-query/elapsed.py -Q 4 +python3 ./test.py -f 2-query/csum.py -Q 4 +python3 ./test.py -f 2-query/mavg.py -Q 4 +python3 ./test.py -f 2-query/sample.py -Q 4 +python3 ./test.py -f 2-query/cast.py -Q 4 +python3 ./test.py -f 2-query/function_diff.py -Q 4 +python3 ./test.py -f 2-query/unique.py -Q 4 +python3 ./test.py -f 2-query/tail.py -Q 4 +python3 ./test.py -f 2-query/ttl_comment.py -Q 4 +python3 ./test.py -f 2-query/distribute_agg_count.py -Q 4 +python3 ./test.py -f 2-query/distribute_agg_max.py -Q 4 +python3 ./test.py -f 2-query/distribute_agg_min.py -Q 4 +python3 ./test.py -f 2-query/distribute_agg_sum.py -Q 4 +python3 ./test.py -f 2-query/distribute_agg_spread.py -Q 4 +python3 ./test.py -f 2-query/distribute_agg_apercentile.py -Q 4 +python3 ./test.py -f 2-query/distribute_agg_avg.py -Q 4 +python3 ./test.py -f 2-query/distribute_agg_stddev.py -Q 4 +python3 ./test.py -f 2-query/twa.py -Q 4 +python3 ./test.py -f 2-query/irate.py -Q 4 +python3 ./test.py -f 2-query/function_null.py -Q 4 +python3 ./test.py -f 2-query/count_partition.py -Q 4 +python3 ./test.py -f 2-query/max_partition.py -Q 4 +python3 ./test.py -f 2-query/max_min_last_interval.py -Q 4 +python3 ./test.py -f 2-query/last_row.py -Q 4 +python3 ./test.py -f 2-query/tsbsQuery.py -Q 4 +python3 ./test.py -f 2-query/sml.py -Q 4 +python3 ./test.py -f 2-query/interp.py -Q 4 +python3 ./test.py -f 2-query/case_when.py -Q 4 +python3 ./test.py -f 2-query/insert_select.py +python3 ./test.py -f 2-query/insert_select.py -R +python3 ./test.py -f 2-query/insert_select.py -Q 2 +python3 ./test.py -f 2-query/insert_select.py -Q 3 +python3 ./test.py -f 2-query/insert_select.py -Q 4 +python3 ./test.py -f 2-query/insert_null_none.py +python3 ./test.py -f 2-query/insert_null_none.py -R +python3 ./test.py -f 2-query/insert_null_none.py -Q 2 +python3 ./test.py -f 2-query/insert_null_none.py -Q 3 +python3 ./test.py -f 2-query/insert_null_none.py -Q 4 +python3 ./test.py -f 2-query/out_of_order.py +python3 ./test.py -f 2-query/out_of_order.py -R +python3 ./test.py -f 2-query/out_of_order.py -Q 2 +python3 ./test.py -f 2-query/out_of_order.py -Q 3 +python3 ./test.py -f 2-query/out_of_order.py -Q 4 +python3 ./test.py -f 2-query/max_min_data.py +python3 ./test.py -f 2-query/max_min_data.py -R +python3 ./test.py -f 2-query/max_min_data.py -Q 2 +python3 ./test.py -f 2-query/max_min_data.py -Q 3 +python3 ./test.py -f 2-query/max_min_data.py -Q 4 +python3 ./test.py -f 2-query/blockSMA.py -Q 4 +python3 ./test.py -f 2-query/odbc.py +python3 ./test.py -f 99-TDcase/TD-21561.py -Q 4 +python3 ./test.py -f 99-TDcase/TD-20582.py diff --git a/tests/unit-test/win-test-file b/tests/unit-test/win-test-file new file mode 100644 index 0000000000000000000000000000000000000000..7ddca165e55c15048841effe860d255befc3955f --- /dev/null +++ b/tests/unit-test/win-test-file @@ -0,0 +1 @@ +bash test.sh diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index d61d25602b081d9cc6e7609f7e807add5a71e597..1461a7b373e3395ed3f4afc111a2df8ca0e5ed60 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -7,25 +7,45 @@ IF (TD_WEBSOCKET) SET(websocket_lib_file "{taosws.dll,taosws.dll.lib}") ENDIF () MESSAGE("${Green} use libtaos-ws${ColourReset}") - - include(ExternalProject) - ExternalProject_Add(taosws-rs - PREFIX "taosws-rs" - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/taosws-rs - BUILD_ALWAYS off - DEPENDS taos - BUILD_IN_SOURCE 1 - CONFIGURE_COMMAND cmake -E echo "taosws-rs no need cmake to config" - PATCH_COMMAND - COMMAND git clean -f -d - BUILD_COMMAND - COMMAND cargo update - COMMAND cargo build --release -p taos-ws-sys --features native-tls-vendored - INSTALL_COMMAND - COMMAND cp target/release/${websocket_lib_file} ${CMAKE_BINARY_DIR}/build/lib - COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/build/include - COMMAND cmake -E copy target/release/taosws.h ${CMAKE_BINARY_DIR}/build/include - ) + IF (TD_ALPINE) + include(ExternalProject) + ExternalProject_Add(taosws-rs + PREFIX "taosws-rs" + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/taosws-rs + BUILD_ALWAYS off + DEPENDS taos + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND cmake -E echo "taosws-rs no need cmake to config" + PATCH_COMMAND + COMMAND git clean -f -d + BUILD_COMMAND + COMMAND cargo update + COMMAND RUSTFLAGS=-Ctarget-feature=-crt-static cargo build --release -p taos-ws-sys --features native-tls + INSTALL_COMMAND + COMMAND cp target/release/${websocket_lib_file} ${CMAKE_BINARY_DIR}/build/lib + COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/build/include + COMMAND cmake -E copy target/release/taosws.h ${CMAKE_BINARY_DIR}/build/include + ) + ELSE() + include(ExternalProject) + ExternalProject_Add(taosws-rs + PREFIX "taosws-rs" + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/taosws-rs + BUILD_ALWAYS off + DEPENDS taos + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND cmake -E echo "taosws-rs no need cmake to config" + PATCH_COMMAND + COMMAND git clean -f -d + BUILD_COMMAND + COMMAND cargo update + COMMAND cargo build --release -p taos-ws-sys --features native-tls-vendored + INSTALL_COMMAND + COMMAND cp target/release/${websocket_lib_file} ${CMAKE_BINARY_DIR}/build/lib + COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/build/include + COMMAND cmake -E copy target/release/taosws.h ${CMAKE_BINARY_DIR}/build/include + ) + ENDIF () ENDIF () IF (TD_TAOS_TOOLS) diff --git a/tools/shell/CMakeLists.txt b/tools/shell/CMakeLists.txt index 1e7d0ed1406d9fc251ffdb6319fede131febef78..7b1dc3a541416335dca761aba8634679473ecdd2 100644 --- a/tools/shell/CMakeLists.txt +++ b/tools/shell/CMakeLists.txt @@ -26,15 +26,23 @@ ELSE () SET(LINK_WEBSOCKET "") ENDIF () +IF (TD_LINUX AND TD_ALPINE) + SET(LINK_ARGP "/usr/lib/libargp.a") +ELSE () + SET(LINK_ARGP "") +ENDIF () + if(TD_WINDOWS) target_link_libraries(shell PUBLIC taos_static ${LINK_WEBSOCKET}) else() - target_link_libraries(shell PUBLIC taos ${LINK_WEBSOCKET} ${LINK_JEMALLOC}) + target_link_libraries(shell PUBLIC taos ${LINK_WEBSOCKET} ${LINK_JEMALLOC} ${LINK_ARGP}) endif () + target_link_libraries( shell PRIVATE os common transport util ) + target_include_directories( shell PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc" diff --git a/tools/shell/inc/shellAuto.h b/tools/shell/inc/shellAuto.h index 151f6da8c6555118699eedbf791da32e47e4283e..6a317fe5c93f273f5dfd78cf409d1f14a9d9f43c 100644 --- a/tools/shell/inc/shellAuto.h +++ b/tools/shell/inc/shellAuto.h @@ -16,6 +16,8 @@ #ifndef __SHELL_AUTO__ #define __SHELL_AUTO__ +#include "shellInt.h" + #define TAB_KEY 0x09 // press tab key @@ -24,13 +26,13 @@ void pressTabKey(SShellCmd* cmd); // press othr key void pressOtherKey(char c); -// init shell auto funciton , shell start call once +// init shell auto function , shell start call once bool shellAutoInit(); // set conn void shellSetConn(TAOS* conn, bool runOnce); -// exit shell auto funciton, shell exit call once +// exit shell auto function, shell exit call once void shellAutoExit(); // callback autotab module @@ -39,7 +41,7 @@ void callbackAutoTab(char* sqlstr, TAOS* pSql, bool usedb); // introduction void printfIntroduction(); -// show all commands help +// show all commands help void showHelp(); #endif diff --git a/tools/shell/inc/shellInt.h b/tools/shell/inc/shellInt.h index e2da695c9200b201878fd8861db81c5cc493d4c5..6345647e2f24b1a87cee8a6a0c60275907946dfe 100644 --- a/tools/shell/inc/shellInt.h +++ b/tools/shell/inc/shellInt.h @@ -28,6 +28,10 @@ #ifdef WEBSOCKET #include "taosws.h" + +#define SHELL_WS_TIMEOUT 30 +#define SHELL_WS_DSN_BUFF 256 +#define SHELL_WS_DSN_MASK 10 #endif #define SHELL_MAX_HISTORY_SIZE 1000 @@ -80,12 +84,13 @@ typedef struct { } SShellArgs; typedef struct { - const char* clientVersion; - const char* promptHeader; - const char* promptContinue; + const char *clientVersion; + char cusName[32]; + char promptHeader[32]; + char promptContinue[32]; const char* osname; int32_t promptSize; - char programVersion[32]; + char programVersion[256]; } SShellOsDetails; typedef struct { @@ -98,7 +103,7 @@ typedef struct { bool exit; #ifdef WEBSOCKET WS_TAOS* ws_conn; - bool stop_query; + bool stop_query; #endif } SShellObj; @@ -138,7 +143,7 @@ void shellExit(); void shellTestNetWork(); #ifdef WEBSOCKET -void shellCheckConnectMode(); +void shellCheckConnectMode(); // shellWebsocket.c int shell_conn_ws_server(bool first); int32_t shell_run_websocket(); diff --git a/tools/shell/inc/shellTire.h b/tools/shell/inc/shellTire.h index bdcf7bcfb3310832b60cc66af5d07c16b7eb6134..e87c3ee4f33726171d107544a137bac7b649174a 100644 --- a/tools/shell/inc/shellTire.h +++ b/tools/shell/inc/shellTire.h @@ -19,7 +19,7 @@ // // The prefix search tree is a efficient storage words and search words tree, it support 95 visible ascii code character // -#define FIRST_ASCII 40 // first visiable char is '0' +#define FIRST_ASCII 40 // first visible char is '0' #define LAST_ASCII 122 // last visilbe char is 'z' // capacity save char is 95 diff --git a/tools/shell/src/shellArguments.c b/tools/shell/src/shellArguments.c index 4d40de66bde2c8504369110c436275b27268ac08..52cb524e3bfb98875e4f93a20bf21fa185674a29 100644 --- a/tools/shell/src/shellArguments.c +++ b/tools/shell/src/shellArguments.c @@ -18,11 +18,15 @@ #endif #include "shellInt.h" +#include "version.h" + +#if defined(CUS_NAME) || defined(CUS_PROMPT) || defined(CUS_EMAIL) +#include "cus_name.h" +#endif -#define TAOS_CONSOLE_PROMPT_HEADER "taos> " #define TAOS_CONSOLE_PROMPT_CONTINUE " -> " -#define SHELL_HOST "TDengine server FQDN to connect. The default host is localhost." +#define SHELL_HOST "The server FQDN to connect. The default host is localhost." #define SHELL_PORT "The TCP/IP port number to use for the connection." #define SHELL_USER "The user name to use when connecting to the server." #define SHELL_PASSWORD "The password to use when connecting to the server." @@ -41,12 +45,11 @@ #define SHELL_PKT_LEN "Packet length used for net test, default is 1024 bytes." #define SHELL_PKT_NUM "Packet numbers used for net test, default is 100." #define SHELL_VERSION "Print program version." -#define SHELL_EMAIL "" #ifdef WEBSOCKET -#define SHELL_DSN "The dsn to use when connecting to cloud server." -#define SHELL_REST "Use restful mode when connecting." -#define SHELL_TIMEOUT "Set the timeout for websocket query in seconds, default is 10." +#define SHELL_DSN "Use dsn to connect to the cloud server or to a remote server which provides WebSocket connection." +#define SHELL_REST "Use RESTful mode when connecting." +#define SHELL_TIMEOUT "Set the timeout for websocket query in seconds, default is 30." #endif static int32_t shellParseSingleOpt(int32_t key, char *arg); @@ -78,15 +81,27 @@ void shellPrintHelp() { #endif printf("%s%s%s%s\r\n", indent, "-w,", indent, SHELL_WIDTH); printf("%s%s%s%s\r\n", indent, "-V,", indent, SHELL_VERSION); - printf("\r\n\r\nReport bugs to %s.\r\n", SHELL_EMAIL); +#ifdef CUS_EMAIL + printf("\r\n\r\nReport bugs to %s.\r\n", CUS_EMAIL); +#else + printf("\r\n\r\nReport bugs to %s.\r\n", "support@taosdata.com"); +#endif } #ifdef LINUX #include +#ifdef _ALPINE +#include +#else #include +#endif const char *argp_program_version = version; -const char *argp_program_bug_address = SHELL_EMAIL; +#ifdef CUS_EMAIL +const char *argp_program_bug_address = CUS_EMAIL; +#else +const char *argp_program_bug_address = "support@taosdata.com"; +#endif static struct argp_option shellOptions[] = { {"host", 'h', "HOST", 0, SHELL_HOST}, @@ -109,7 +124,7 @@ static struct argp_option shellOptions[] = { #ifdef WEBSOCKET {"dsn", 'E', "DSN", 0, SHELL_DSN}, {"restful", 'R', 0, 0, SHELL_REST}, - {"timeout", 'T', "SECONDS", 0, SHELL_TIMEOUT}, + {"timeout", 'T', "SECONDS", 0, SHELL_TIMEOUT}, #endif {"pktnum", 'N', "PKTNUM", 0, SHELL_PKT_NUM}, {0}, @@ -127,7 +142,7 @@ static void shellParseArgsUseArgp(int argc, char *argv[]) { #endif #ifndef ARGP_ERR_UNKNOWN - #define ARGP_ERR_UNKNOWN E2BIG +#define ARGP_ERR_UNKNOWN E2BIG #endif static int32_t shellParseSingleOpt(int32_t key, char *arg) { @@ -205,9 +220,9 @@ static int32_t shellParseSingleOpt(int32_t key, char *arg) { pArgs->dsn = arg; pArgs->cloud = true; break; - case 'T': - pArgs->timeout = atoi(arg); - break; + case 'T': + pArgs->timeout = atoi(arg); + break; #endif case 'V': pArgs->is_version = true; @@ -228,7 +243,8 @@ int32_t shellParseArgsWithoutArgp(int argc, char *argv[]) { SShellArgs *pArgs = &shell.args; for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--usage") == 0 || strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "/?") == 0) { + if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--usage") == 0 + || strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "/?") == 0) { shellParseSingleOpt('?', NULL); return 0; } @@ -244,12 +260,14 @@ int32_t shellParseArgsWithoutArgp(int argc, char *argv[]) { return -1; } - if (key[1] == 'h' || key[1] == 'P' || key[1] == 'u' || key[1] == 'a' || key[1] == 'c' || key[1] == 's' || - key[1] == 'f' || key[1] == 'd' || key[1] == 'w' || key[1] == 'n' || key[1] == 'l' || key[1] == 'N' + if (key[1] == 'h' || key[1] == 'P' || key[1] == 'u' + || key[1] == 'a' || key[1] == 'c' || key[1] == 's' + || key[1] == 'f' || key[1] == 'd' || key[1] == 'w' + || key[1] == 'n' || key[1] == 'l' || key[1] == 'N' #ifdef WEBSOCKET - || key[1] == 'E' || key[1] == 'T' + || key[1] == 'E' || key[1] == 'T' #endif - ) { + ) { if (i + 1 >= argc) { fprintf(stderr, "option %s requires an argument\r\n", key); return -1; @@ -261,12 +279,14 @@ int32_t shellParseArgsWithoutArgp(int argc, char *argv[]) { } shellParseSingleOpt(key[1], val); i++; - } else if (key[1] == 'p' || key[1] == 'A' || key[1] == 'C' || key[1] == 'r' || key[1] == 'k' || - key[1] == 't' || key[1] == 'V' || key[1] == '?' || key[1] == 1 + } else if (key[1] == 'p' || key[1] == 'A' || key[1] == 'C' + || key[1] == 'r' || key[1] == 'k' + || key[1] == 't' || key[1] == 'V' + || key[1] == '?' || key[1] == 1 #ifdef WEBSOCKET - ||key[1] == 'R' + ||key[1] == 'R' #endif - ) { + ) { shellParseSingleOpt(key[1], NULL); } else { fprintf(stderr, "invalid option %s\r\n", key); @@ -389,12 +409,32 @@ static int32_t shellCheckArgs() { int32_t shellParseArgs(int32_t argc, char *argv[]) { shellInitArgs(argc, argv); shell.info.clientVersion = - "Welcome to the TDengine Command Line Interface, Client Version:%s\r\n" - "Copyright (c) 2022 by TDengine, all rights reserved.\r\n\r\n"; - shell.info.promptHeader = TAOS_CONSOLE_PROMPT_HEADER; - shell.info.promptContinue = TAOS_CONSOLE_PROMPT_CONTINUE; - shell.info.promptSize = 6; - snprintf(shell.info.programVersion, sizeof(shell.info.programVersion), "version: %s", version); + "Welcome to the %s Command Line Interface, Client Version:%s\r\n" + "Copyright (c) 2022 by %s, all rights reserved.\r\n\r\n"; +#ifdef CUS_NAME + strcpy(shell.info.cusName, CUS_NAME); +#else + strcpy(shell.info.cusName, "TDengine"); +#endif + char promptContinueFormat[32] = {0}; +#ifdef CUS_PROMPT + sprintf(shell.info.promptHeader, "%s> ", CUS_PROMPT); + sprintf(promptContinueFormat, "%%%zus> ", strlen(CUS_PROMPT)); +#else + sprintf(shell.info.promptHeader, "taos> "); + sprintf(promptContinueFormat, "%%%zus> ", strlen("taos")); +#endif + sprintf(shell.info.promptContinue, promptContinueFormat, " "); + shell.info.promptSize = strlen(shell.info.promptHeader); +#ifdef TD_ENTERPRISE + snprintf(shell.info.programVersion, sizeof(shell.info.programVersion), + "version: %s compatible_version: %s\ngitinfo: %s\ngitinfoOfInternal: %s\nbuildInfo: %s", version, + compatible_version, gitinfo, gitinfoOfInternal, buildinfo); +#else + snprintf(shell.info.programVersion, sizeof(shell.info.programVersion), + "version: %s compatible_version: %s\ngitinfo: %s\nbuildInfo: %s", version, compatible_version, gitinfo, + buildinfo); +#endif #if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32) shell.info.osname = "Windows"; diff --git a/tools/shell/src/shellAuto.c b/tools/shell/src/shellAuto.c index f58a5d09315cc0f53401da8424263e21af7d55cf..140720af815cf317bf7665c40750b2d0fb2ebd37 100644 --- a/tools/shell/src/shellAuto.c +++ b/tools/shell/src/shellAuto.c @@ -15,8 +15,8 @@ #define __USE_XOPEN -#include "shellInt.h" #include "shellAuto.h" +#include "shellInt.h" #include "shellTire.h" #include "tthread.h" @@ -26,14 +26,14 @@ #define UNION_ALL " union all " // extern function -void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos); -void shellGetPrevCharSize(const char* str, int32_t pos, int32_t* size, int32_t* width); -void shellShowOnScreen(SShellCmd* cmd); -void shellInsertChar(SShellCmd* cmd, char* c, int size); -void shellInsertStr(SShellCmd* cmd, char* str, int size); -bool appendAfterSelect(TAOS* con, SShellCmd* cmd, char* p, int32_t len); +void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos); +void shellGetPrevCharSize(const char* str, int32_t pos, int32_t* size, int32_t* width); +void shellShowOnScreen(SShellCmd* cmd); +void shellInsertChar(SShellCmd* cmd, char* c, int size); +void shellInsertStr(SShellCmd* cmd, char* str, int size); +bool appendAfterSelect(TAOS* con, SShellCmd* cmd, char* p, int32_t len); char* tireSearchWord(int type, char* pre); -bool updateTireValue(int type, bool autoFill) ; +bool updateTireValue(int type, bool autoFill); typedef struct SAutoPtr { STire* p; @@ -84,27 +84,28 @@ SWords shellCommands[] = { {"create table using tags(", 0, 0, NULL}, {"create database " " " - " ;", - 0, 0, NULL}, - {"create dnode ", 0, 0, NULL}, - {"create index ", 0, 0, NULL}, + " ;", 0, 0, NULL}, + {"create dnode ", 0, 0, NULL}, + {"create index on ()", 0, 0, NULL}, {"create mnode on dnode ;", 0, 0, NULL}, {"create qnode on dnode ;", 0, 0, NULL}, {"create stream into as select", 0, 0, NULL}, // 26 append sub sql {"create topic as select", 0, 0, NULL}, // 27 append sub sql - {"create function ", 0, 0, NULL}, + {"create function as outputtype language ", 0, 0, NULL}, + {"create aggregate function as outputtype bufsize language ", 0, 0, NULL}, {"create user pass sysinfo 0;", 0, 0, NULL}, {"create user pass sysinfo 1;", 0, 0, NULL}, {"describe ", 0, 0, NULL}, {"delete from where ", 0, 0, NULL}, {"drop database ", 0, 0, NULL}, + {"drop index ", 0, 0, NULL}, {"drop table ", 0, 0, NULL}, {"drop dnode ", 0, 0, NULL}, {"drop mnode on dnode ;", 0, 0, NULL}, {"drop qnode on dnode ;", 0, 0, NULL}, {"drop user ;", 0, 0, NULL}, // 40 - {"drop function", 0, 0, NULL}, + {"drop function ;", 0, 0, NULL}, {"drop consumer group on ", 0, 0, NULL}, {"drop topic ;", 0, 0, NULL}, {"drop stream ;", 0, 0, NULL}, @@ -139,6 +140,7 @@ SWords shellCommands[] = { {"show create table \\G;", 0, 0, NULL}, {"show connections;", 0, 0, NULL}, {"show cluster;", 0, 0, NULL}, + {"show cluster alive;", 0, 0, NULL}, {"show databases;", 0, 0, NULL}, {"show dnodes;", 0, 0, NULL}, {"show dnode variables;", 0, 0, NULL}, @@ -248,7 +250,7 @@ char* db_options[] = {"keep ", "wal_retention_size ", "wal_segment_size "}; -char* alter_db_options[] = {"cachemodel ", "replica ", "keep ", "cachesize ", "wal_fsync_period ", "wal_level "}; +char* alter_db_options[] = {"cachemodel ", "replica ", "keep ", "cachesize ", "wal_fsync_period ", "wal_level "}; char* data_types[] = {"timestamp", "int", "int unsigned", "varchar(16)", @@ -270,9 +272,10 @@ char* key_systable[] = { "ins_subscriptions", "ins_streams", "ins_stream_tasks", "ins_vnodes", "ins_user_privileges", "perf_connections", "perf_queries", "perf_consumers", "perf_trans", "perf_apps"}; +char* udf_language[] = {"\'Python\'", "\'C\'"}; // -// ------- gobal variant define --------- +// ------- global variant define --------- // int32_t firstMatchIndex = -1; // first match shellCommands index int32_t lastMatchIndex = -1; // last match shellCommands index @@ -290,25 +293,29 @@ bool waitAutoFill = false; #define WT_VAR_USERNAME 4 #define WT_VAR_TOPIC 5 #define WT_VAR_STREAM 6 -#define WT_VAR_ALLTABLE 7 -#define WT_VAR_FUNC 8 -#define WT_VAR_KEYWORD 9 -#define WT_VAR_TBACTION 10 -#define WT_VAR_DBOPTION 11 -#define WT_VAR_ALTER_DBOPTION 12 -#define WT_VAR_DATATYPE 13 -#define WT_VAR_KEYTAGS 14 -#define WT_VAR_ANYWORD 15 -#define WT_VAR_TBOPTION 16 -#define WT_VAR_USERACTION 17 -#define WT_VAR_KEYSELECT 18 -#define WT_VAR_SYSTABLE 19 - -#define WT_VAR_CNT 20 - -#define WT_FROM_DB_MAX 6 // max get content from db +#define WT_VAR_UDFNAME 7 + +#define WT_FROM_DB_MAX 7 // max get content from db #define WT_FROM_DB_CNT (WT_FROM_DB_MAX + 1) +#define WT_VAR_ALLTABLE 8 +#define WT_VAR_FUNC 9 +#define WT_VAR_KEYWORD 10 +#define WT_VAR_TBACTION 11 +#define WT_VAR_DBOPTION 12 +#define WT_VAR_ALTER_DBOPTION 13 +#define WT_VAR_DATATYPE 14 +#define WT_VAR_KEYTAGS 15 +#define WT_VAR_ANYWORD 16 +#define WT_VAR_TBOPTION 17 +#define WT_VAR_USERACTION 18 +#define WT_VAR_KEYSELECT 19 +#define WT_VAR_SYSTABLE 20 +#define WT_VAR_LANGUAGE 21 + +#define WT_VAR_CNT 22 + + #define WT_TEXT 0xFF char dbName[256] = ""; // save use database name; @@ -318,13 +325,13 @@ TdThreadMutex tiresMutex; // save thread handle obtain var name from db server TdThread* threads[WT_FROM_DB_CNT]; // obtain var name with sql from server -char varTypes[WT_VAR_CNT][64] = {"", "", "", "", "", - "", "", "", "", "", - "", "", "", "", "", - "", "", "", ""}; +char varTypes[WT_VAR_CNT][64] = { + "", "", "", "", "", "", "", + "", "", "", "", "", "", "", + "", "", "", "", "", "", "", ""}; char varSqls[WT_FROM_DB_CNT][64] = {"show databases;", "show stables;", "show tables;", "show dnodes;", - "show users;", "show topics;", "show streams;"}; + "show users;", "show topics;", "show streams;", "show functions;"}; // var words current cursor, if user press any one key except tab, cursorVar can be reset to -1 int cursorVar = -1; @@ -338,23 +345,30 @@ int cntDel = 0; // delete byte count after next press tab // show auto tab introduction void printfIntroduction() { - printf(" ****************************** Tab Completion *************************************\n"); - printf(" * The TDengine CLI supports tab completion for a variety of items, *\n"); - printf(" * including database names, table names, function names and keywords. *\n"); - printf(" * The full list of shortcut keys is as follows: *\n"); - printf(" * [ TAB ] ...... complete the current word *\n"); - printf(" * ...... if used on a blank line, display all supported commands *\n"); - printf(" * [ Ctrl + A ] ...... move cursor to the st[A]rt of the line *\n"); - printf(" * [ Ctrl + E ] ...... move cursor to the [E]nd of the line *\n"); - printf(" * [ Ctrl + W ] ...... move cursor to the middle of the line *\n"); - printf(" * [ Ctrl + L ] ...... clear the entire screen *\n"); - printf(" * [ Ctrl + K ] ...... clear the screen after the cursor *\n"); - printf(" * [ Ctrl + U ] ...... clear the screen before the cursor *\n"); - printf(" *************************************************************************************\n\n"); + printf(" ****************************** Tab Completion **********************************\n"); + char secondLine[160] = "\0"; + sprintf(secondLine, " * The %s CLI supports tab completion for a variety of items, ", shell.info.cusName); + printf("%s", secondLine); + int secondLineLen = strlen(secondLine); + while (84 - (secondLineLen++) > 0) { + printf(" "); + } + printf("*\n"); + printf(" * including database names, table names, function names and keywords. *\n"); + printf(" * The full list of shortcut keys is as follows: *\n"); + printf(" * [ TAB ] ...... complete the current word *\n"); + printf(" * ...... if used on a blank line, display all supported commands *\n"); + printf(" * [ Ctrl + A ] ...... move cursor to the st[A]rt of the line *\n"); + printf(" * [ Ctrl + E ] ...... move cursor to the [E]nd of the line *\n"); + printf(" * [ Ctrl + W ] ...... move cursor to the middle of the line *\n"); + printf(" * [ Ctrl + L ] ...... clear the entire screen *\n"); + printf(" * [ Ctrl + K ] ...... clear the screen after the cursor *\n"); + printf(" * [ Ctrl + U ] ...... clear the screen before the cursor *\n"); + printf(" **************************************************************************************\n\n"); } void showHelp() { - printf("\nThe TDengine CLI supports the following commands:"); + printf("\nThe %s CLI supports the following commands:", shell.info.cusName); printf( "\n\ ----- A ----- \n\ @@ -377,12 +391,13 @@ void showHelp() { create table using tags ...\n\ create database ...\n\ create dnode \"fqdn:port\" ...\n\ - create index ...\n\ + create index on (tag_column_name);\n\ create mnode on dnode ;\n\ create qnode on dnode ;\n\ create stream into as select ...\n\ create topic as select ...\n\ - create function ...\n\ + create function as outputtype language \'C\' | \'Python\' ;\n\ + create aggregate function as outputtype bufsize language \'C\' | \'Python\';\n\ create user pass ...\n\ ----- D ----- \n\ describe \n\ @@ -393,10 +408,11 @@ void showHelp() { drop mnode on dnode ;\n\ drop qnode on dnode ;\n\ drop user ;\n\ - drop function ;\n\ + drop function ;\n\ drop consumer group ... \n\ drop topic ;\n\ drop stream ;\n\ + drop index ;\n\ ----- E ----- \n\ explain select clause ...\n\ ----- F ----- \n\ @@ -438,6 +454,7 @@ void showHelp() { show create table ;\n\ show connections;\n\ show cluster;\n\ + show cluster alive;\n\ show databases;\n\ show dnodes;\n\ show dnode variables;\n\ @@ -526,7 +543,7 @@ SWord* addWord(const char* p, int32_t len, bool pattern) { word->len = len; // check format - if (pattern) { + if (pattern && len > 0) { word->type = wordType(p, len); } else { word->type = WT_TEXT; @@ -606,7 +623,7 @@ void GenerateVarType(int type, char** p, int count) { // -------------------- shell auto ---------------- // -// init shell auto funciton , shell start call once +// init shell auto function , shell start call once bool shellAutoInit() { // command int32_t count = SHELL_COMMAND_COUNT(); @@ -633,6 +650,7 @@ bool shellAutoInit() { GenerateVarType(WT_VAR_USERACTION, user_actions, sizeof(user_actions) / sizeof(char*)); GenerateVarType(WT_VAR_KEYSELECT, key_select, sizeof(key_select) / sizeof(char*)); GenerateVarType(WT_VAR_SYSTABLE, key_systable, sizeof(key_systable) / sizeof(char*)); + GenerateVarType(WT_VAR_LANGUAGE, udf_language, sizeof(udf_language) / sizeof(char*)); return true; } @@ -645,7 +663,7 @@ void shellSetConn(TAOS* conn, bool runOnce) { if (!runOnce) updateTireValue(WT_VAR_DBNAME, false); } -// exit shell auto funciton, shell exit call once +// exit shell auto function, shell exit call once void shellAutoExit() { // free command int32_t count = SHELL_COMMAND_COUNT(); @@ -662,7 +680,7 @@ void shellAutoExit() { } } taosThreadMutexUnlock(&tiresMutex); - // destory + // destroy taosThreadMutexDestroy(&tiresMutex); // free threads @@ -683,7 +701,7 @@ void shellAutoExit() { // // ------------------- auto ptr for tires -------------------------- // -bool setNewAuotPtr(int type, STire* pNew) { +bool setNewAutoPtr(int type, STire* pNew) { if (pNew == NULL) return false; taosThreadMutexLock(&tiresMutex); @@ -726,13 +744,13 @@ void putBackAutoPtr(int type, STire* tire) { if (tires[type] != tire) { // update by out, can't put back , so free if (--tire->ref == 1) { - // support multi thread getAuotPtr + // support multi thread getAutoPtr freeTire(tire); } } else { tires[type]->ref--; - assert(tires[type]->ref > 0); + ASSERT(tires[type]->ref > 0); } taosThreadMutexUnlock(&tiresMutex); @@ -781,13 +799,16 @@ int writeVarNames(int type, TAOS_RES* tres) { } while (row != NULL); // replace old tire - setNewAuotPtr(type, tire); + setNewAutoPtr(type, tire); return numOfRows; } void setThreadNull(int type) { taosThreadMutexLock(&tiresMutex); + if (threads[type]) { + taosMemoryFree(threads[type]); + } threads[type] = NULL; taosThreadMutexUnlock(&tiresMutex); } @@ -862,7 +883,7 @@ bool updateTireValue(int type, bool autoFill) { // only match next one word from all match words, return valuue must free by caller char* matchNextPrefix(STire* tire, char* pre) { SMatch* match = NULL; - if(tire == NULL) return NULL; + if (tire == NULL) return NULL; // re-use last result if (lastMatch) { @@ -900,7 +921,7 @@ char* matchNextPrefix(STire* tire, char* pre) { if (cursorVar == -1) { // first cursorVar = 0; - return strdup(match->head->word); + return taosStrdup(match->head->word); } // according to cursorVar , calculate next one @@ -916,7 +937,7 @@ char* matchNextPrefix(STire* tire, char* pre) { cursorVar = i; } - return strdup(item->word); + return taosStrdup(item->word); } // check end item @@ -924,7 +945,7 @@ char* matchNextPrefix(STire* tire, char* pre) { // if cursorVar > var list count, return last and reset cursorVar cursorVar = -1; - return strdup(item->word); + return taosStrdup(item->word); } // move next @@ -948,7 +969,7 @@ char* tireSearchWord(int type, char* pre) { return matchNextPrefix(tire, pre); } - if(updateTireValue(type, true)) { + if (updateTireValue(type, true)) { return NULL; } @@ -1067,7 +1088,7 @@ SWords* matchCommand(SWords* input, bool continueSearch) { for (int32_t i = 0; i < count; i++) { SWords* shellCommand = shellCommands + i; if (continueSearch && lastMatchIndex != -1 && i <= lastMatchIndex) { - // new match must greate than lastMatchIndex + // new match must greater than lastMatchIndex if (varMode && i == lastMatchIndex) { // do nothing, var match on lastMatchIndex } else { @@ -1153,7 +1174,7 @@ void printScreen(TAOS* con, SShellCmd* cmd, SWords* match) { // main key press tab , matched return true else false bool firstMatchCommand(TAOS* con, SShellCmd* cmd) { - if(con == NULL || cmd == NULL) return false; + if (con == NULL || cmd == NULL) return false; // parse command SWords* input = (SWords*)taosMemoryMalloc(sizeof(SWords)); memset(input, 0, sizeof(SWords)); @@ -1197,7 +1218,7 @@ void createInputFromFirst(SWords* input, SWords* firstMatch) { for (int i = 0; i < firstMatch->matchIndex && word; i++) { // combine source from each word strncpy(input->source + input->source_len, word->word, word->len); - strcat(input->source, " "); // append blank splite + strcat(input->source, " "); // append blank space input->source_len += word->len + 1; // 1 is blank length // move next word = word->next; @@ -1426,7 +1447,7 @@ bool appendAfterSelect(TAOS* con, SShellCmd* cmd, char* sql, int32_t len) { return true; } - // fill funciton + // fill function if (fieldEnd) { // fields is end , need match keyword ret = fillWithType(con, cmd, last, WT_VAR_KEYWORD); @@ -1524,9 +1545,9 @@ bool matchSelectQuery(TAOS* con, SShellCmd* cmd) { // if is input create fields or tags area, return true bool isCreateFieldsArea(char* p) { - // put to while, support like create table st(ts timestamp, bin1 binary(16), bin2 + blank + TAB - char* p1 = strdup(p); - bool ret = false; + // put to while, support like create table st(ts timestamp, bin1 binary(16), bin2 + blank + TAB + char* p1 = taosStrdup(p); + bool ret = false; while (1) { char* left = strrchr(p1, '('); if (left == NULL) { @@ -1547,7 +1568,7 @@ bool isCreateFieldsArea(char* p) { ret = true; break; } - + // set string end by small for next strrchr search *left = 0; } @@ -1609,7 +1630,7 @@ bool matchCreateTable(TAOS* con, SShellCmd* cmd) { // tb options if (!ret) { - // find like create talbe st (...) tags(..) + // find like create table st (...) tags(..) char* p1 = strchr(ps, ')'); // first ')' end if (p1) { if (strchr(p1 + 1, ')')) { // second ')' end @@ -1701,21 +1722,24 @@ bool matchOther(TAOS* con, SShellCmd* cmd) { // last match if nothing matched bool matchEnd(TAOS* con, SShellCmd* cmd) { // str dump - bool ret = false; + bool ret = false; char* ps = strndup(cmd->command, cmd->commandSize); char* last = lastWord(ps); - char* elast = strrchr(last, '.'); // find end last - if(elast) { + char* elast = strrchr(last, '.'); // find end last + if (elast) { last = elast + 1; } // less one char can match - if(strlen(last) == 0 ) { + if (strlen(last) == 0) { + goto _return; + } + if (strcmp(last, " ") == 0) { goto _return; } // match database - if(elast == NULL) { + if (elast == NULL) { // dot need not completed with dbname if (fillWithType(con, cmd, last, WT_VAR_DBNAME)) { ret = true; @@ -1735,10 +1759,12 @@ _return: // main key press tab void pressTabKey(SShellCmd* cmd) { - // check + // check empty tab key if (cmd->commandSize == 0) { - // empty - showHelp(); + // have multi line tab key + if (cmd->bufferSize == 0) { + showHelp(); + } shellShowOnScreen(cmd); return; } diff --git a/tools/shell/src/shellCommand.c b/tools/shell/src/shellCommand.c index 5235030cf91cac5d41b782544da9d8a7be4e1349..0e305f57e9c781a8149db1fecccd06a703bc1465 100644 --- a/tools/shell/src/shellCommand.c +++ b/tools/shell/src/shellCommand.c @@ -40,7 +40,7 @@ static void shellPositionCursorEnd(SShellCmd *cmd); static void shellPrintChar(char c, int32_t times); static void shellPositionCursor(int32_t step, int32_t direction); static void shellUpdateBuffer(SShellCmd *cmd); -static int32_t shellIsReadyGo(SShellCmd *cmd); +static bool shellIsReadyGo(SShellCmd *cmd); static void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width); static void shellResetCommand(SShellCmd *cmd, const char s[]); void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos); @@ -62,7 +62,8 @@ int32_t shellCountPrefixOnes(uint8_t c) { } void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width) { - assert(pos > 0); + ASSERT(pos > 0); + if (pos <= 0) return; TdWchar wc; *size = 0; @@ -75,13 +76,14 @@ void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t * } taosMbToWchar(&wc, str + pos, MB_CUR_MAX); - // assert(rc == *size); // it will be core, if str is encode by utf8 and taos charset is gbk + // ASSERT(rc == *size); // it will be core, if str is encode by utf8 and taos charset is gbk *width = taosWcharWidth(wc); } void shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width) { - assert(pos >= 0); + ASSERT(pos >= 0); + if(pos < 0) return; TdWchar wc; *size = taosMbToWchar(&wc, str + pos, MB_CUR_MAX); @@ -89,7 +91,8 @@ void shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t * } void shellInsertChar(SShellCmd *cmd, char *c, int32_t size) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; TdWchar wc; if (taosMbToWchar(&wc, c, size) < 0) return; @@ -135,7 +138,8 @@ void shellInsertStr(SShellCmd *cmd, char *str, int32_t size) { } void shellBackspaceChar(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; if (cmd->cursorOffset > 0) { shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); @@ -155,7 +159,8 @@ void shellBackspaceChar(SShellCmd *cmd) { } void shellClearLineBefore(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); memmove(cmd->command, cmd->command + cmd->cursorOffset, cmd->commandSize - cmd->cursorOffset); @@ -169,7 +174,8 @@ void shellClearLineBefore(SShellCmd *cmd) { } void shellClearLineAfter(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); cmd->commandSize -= cmd->endOffset - cmd->cursorOffset; @@ -178,7 +184,8 @@ void shellClearLineAfter(SShellCmd *cmd) { } void shellDeleteChar(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; if (cmd->cursorOffset < cmd->commandSize) { shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); @@ -196,7 +203,8 @@ void shellDeleteChar(SShellCmd *cmd) { } void shellMoveCursorLeft(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; if (cmd->cursorOffset > 0) { shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); @@ -210,7 +218,8 @@ void shellMoveCursorLeft(SShellCmd *cmd) { } void shellMoveCursorRight(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; if (cmd->cursorOffset < cmd->commandSize) { shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); @@ -224,7 +233,8 @@ void shellMoveCursorRight(SShellCmd *cmd) { } void shellPositionCursorHome(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; if (cmd->cursorOffset > 0) { shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); @@ -244,7 +254,8 @@ void positionCursorMiddle(SShellCmd *cmd) { } void shellPositionCursorEnd(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; if (cmd->cursorOffset < cmd->commandSize) { shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); @@ -279,7 +290,8 @@ void shellPositionCursor(int32_t step, int32_t direction) { } void shellUpdateBuffer(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; if (shellRegexMatch(cmd->buffer, "(\\s+$)|(^$)", REG_EXTENDED)) strcat(cmd->command, " "); strcat(cmd->buffer, cmd->command); @@ -293,8 +305,9 @@ void shellUpdateBuffer(SShellCmd *cmd) { shellShowOnScreen(cmd); } -int32_t shellIsReadyGo(SShellCmd *cmd) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); +bool shellIsReadyGo(SShellCmd *cmd) { + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return false; char *total = (char *)taosMemoryCalloc(1, SHELL_MAX_COMMAND_SIZE); memset(cmd->command + cmd->commandSize, 0, SHELL_MAX_COMMAND_SIZE - cmd->commandSize); @@ -305,11 +318,11 @@ int32_t shellIsReadyGo(SShellCmd *cmd) { "\\s*clear\\s*$)"; if (shellRegexMatch(total, reg_str, REG_EXTENDED | REG_ICASE)) { taosMemoryFree(total); - return 1; + return true; } taosMemoryFree(total); - return 0; + return false; } void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width) { @@ -321,7 +334,8 @@ void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width) { } void shellResetCommand(SShellCmd *cmd, const char s[]) { - assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + ASSERT(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); + if(cmd->cursorOffset > cmd->commandSize || cmd->endOffset < cmd->screenOffset) return; shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); memset(cmd->buffer, 0, SHELL_MAX_COMMAND_SIZE); @@ -399,7 +413,7 @@ void shellShowOnScreen(SShellCmd *cmd) { int32_t ret = taosMbToWchar(&wc, str, MB_CUR_MAX); if (ret < 0) break; size += ret; - /* assert(size >= 0); */ + /* ASSERT(size >= 0); */ int32_t width = taosWcharWidth(wc); if (remain_column > width) { printf("%lc", wc); diff --git a/tools/shell/src/shellEngine.c b/tools/shell/src/shellEngine.c index 9b842a9e6f0ba38e90804ff853bc9cad07cfcd52..0f91bdeeda3a76f93d8cfa3c168de20887608752 100644 --- a/tools/shell/src/shellEngine.c +++ b/tools/shell/src/shellEngine.c @@ -58,7 +58,6 @@ int32_t shellRunSingleCommand(char *command) { } if (shellRegexMatch(command, "^[ \t]*(quit|q|exit)[ \t;]*$", REG_EXTENDED | REG_ICASE)) { - shellWriteHistory(); return -1; } @@ -102,10 +101,10 @@ int32_t shellRunSingleCommand(char *command) { } #ifdef WEBSOCKET if (shell.args.restful || shell.args.cloud) { - shellRunSingleCommandWebsocketImp(command); + shellRunSingleCommandWebsocketImp(command); } else { #endif - shellRunSingleCommandImp(command); + shellRunSingleCommandImp(command); #ifdef WEBSOCKET } #endif @@ -127,7 +126,7 @@ void shellRecordCommandToHistory(char *command) { if (pHistory->hist[pHistory->hend] != NULL) { taosMemoryFreeClear(pHistory->hist[pHistory->hend]); } - pHistory->hist[pHistory->hend] = strdup(command); + pHistory->hist[pHistory->hend] = taosStrdup(command); pHistory->hend = (pHistory->hend + 1) % SHELL_MAX_HISTORY_SIZE; if (pHistory->hend == pHistory->hstart) { @@ -291,7 +290,9 @@ char *shellFormatTimestamp(char *buf, int64_t val, int32_t precision) { } struct tm ptm = {0}; - taosLocalTime(&tt, &ptm); + if (taosLocalTime(&tt, &ptm, buf) == NULL) { + return buf; + } size_t pos = strftime(buf, 35, "%Y-%m-%d %H:%M:%S", &ptm); if (precision == TSDB_TIME_PRECISION_NANO) { @@ -346,14 +347,23 @@ void shellDumpFieldToFile(TdFilePtr pFile, const char *val, TAOS_FIELD *field, i taosFprintfFile(pFile, "%" PRIu64, *((uint64_t *)val)); break; case TSDB_DATA_TYPE_FLOAT: - taosFprintfFile(pFile, "%.5f", GET_FLOAT_VAL(val)); + if (tsEnableScience) { + taosFprintfFile(pFile, "%e", GET_FLOAT_VAL(val)); + } else { + taosFprintfFile(pFile, "%.5f", GET_FLOAT_VAL(val)); + } break; case TSDB_DATA_TYPE_DOUBLE: - n = snprintf(buf, TSDB_MAX_BYTES_PER_ROW, "%*.9f", length, GET_DOUBLE_VAL(val)); - if (n > TMAX(25, length)) { - taosFprintfFile(pFile, "%*.15e", length, GET_DOUBLE_VAL(val)); - } else { + if (tsEnableScience) { + snprintf(buf, TSDB_MAX_BYTES_PER_ROW, "%*.9e", 23, GET_DOUBLE_VAL(val)); taosFprintfFile(pFile, "%s", buf); + } else { + n = snprintf(buf, TSDB_MAX_BYTES_PER_ROW, "%*.9f", length, GET_DOUBLE_VAL(val)); + if (n > TMAX(25, length)) { + taosFprintfFile(pFile, "%*.15e", length, GET_DOUBLE_VAL(val)); + } else { + taosFprintfFile(pFile, "%s", buf); + } } break; case TSDB_DATA_TYPE_BINARY: @@ -541,14 +551,28 @@ void shellPrintField(const char *val, TAOS_FIELD *field, int32_t width, int32_t printf("%*" PRIu64, width, *((uint64_t *)val)); break; case TSDB_DATA_TYPE_FLOAT: - printf("%*.5f", width, GET_FLOAT_VAL(val)); + if (tsEnableScience) { + printf("%*e", width, GET_FLOAT_VAL(val)); + } else { + n = snprintf(buf, TSDB_MAX_BYTES_PER_ROW, "%*.5f", width, GET_FLOAT_VAL(val)); + if (n > TMAX(20, width)) { + printf("%*e", width, GET_FLOAT_VAL(val)); + } else { + printf("%s", buf); + } + } break; case TSDB_DATA_TYPE_DOUBLE: - n = snprintf(buf, TSDB_MAX_BYTES_PER_ROW, "%*.9f", width, GET_DOUBLE_VAL(val)); - if (n > TMAX(25, width)) { - printf("%*.15e", width, GET_DOUBLE_VAL(val)); + if (tsEnableScience) { + snprintf(buf, TSDB_MAX_BYTES_PER_ROW, "%.9e", GET_DOUBLE_VAL(val)); + printf("%*s", width, buf); } else { - printf("%s", buf); + n = snprintf(buf, TSDB_MAX_BYTES_PER_ROW, "%*.9f", width, GET_DOUBLE_VAL(val)); + if (n > TMAX(25, width)) { + printf("%*.15e", width, GET_DOUBLE_VAL(val)); + } else { + printf("%s", buf); + } } break; case TSDB_DATA_TYPE_BINARY: @@ -713,7 +737,7 @@ int32_t shellCalcColWidth(TAOS_FIELD *field, int32_t precision) { } default: - assert(false); + ASSERT(false); } return 0; @@ -821,7 +845,7 @@ void shellReadHistory() { while ((read_size = taosGetsFile(pFile, TSDB_MAX_ALLOWED_SQL_LEN, line)) != -1) { line[read_size - 1] = '\0'; taosMemoryFree(pHistory->hist[pHistory->hend]); - pHistory->hist[pHistory->hend] = strdup(line); + pHistory->hist[pHistory->hend] = taosStrdup(line); pHistory->hend = (pHistory->hend + 1) % SHELL_MAX_HISTORY_SIZE; @@ -845,6 +869,8 @@ void shellReadHistory() { i = (i + SHELL_MAX_HISTORY_SIZE - 1) % SHELL_MAX_HISTORY_SIZE; } taosFprintfFile(pFile, "%s\n", pHistory->hist[endIndex]); + + /* coverity[+retval] */ taosFsyncFile(pFile); taosCloseFile(&pFile); } @@ -865,7 +891,6 @@ void shellWriteHistory() { } i = (i + 1) % SHELL_MAX_HISTORY_SIZE; } - taosFsyncFile(pFile); taosCloseFile(&pFile); } @@ -1023,15 +1048,15 @@ void *shellCancelHandler(void *arg) { } #ifdef WEBSOCKET - if (shell.args.restful || shell.args.cloud) { - shell.stop_query = true; - } else { + if (shell.args.restful || shell.args.cloud) { + shell.stop_query = true; + } else { #endif - if (shell.conn) { - taos_kill_query(shell.conn); - } + if (shell.conn) { + taos_kill_query(shell.conn); + } #ifdef WEBSOCKET - } + } #endif #ifdef WINDOWS printf("\n%s", shell.info.promptHeader); @@ -1046,53 +1071,56 @@ void *shellThreadLoop(void *arg) { taosGetOldTerminalMode(); taosThreadCleanupPush(shellCleanup, NULL); - char *command = taosMemoryMalloc(SHELL_MAX_COMMAND_SIZE); - if (command == NULL) { - printf("failed to malloc command\r\n"); - return NULL; - } - do { - memset(command, 0, SHELL_MAX_COMMAND_SIZE); - taosSetTerminalMode(); - - if (shellReadCommand(command) != 0) { + char *command = taosMemoryMalloc(SHELL_MAX_COMMAND_SIZE); + if (command == NULL) { + printf("failed to malloc command\r\n"); break; } - taosResetTerminalMode(); - } while (shellRunCommand(command, true) == 0); + do { + memset(command, 0, SHELL_MAX_COMMAND_SIZE); + taosSetTerminalMode(); + + if (shellReadCommand(command) != 0) { + break; + } - taosMemoryFreeClear(command); - shellWriteHistory(); - shellExit(); + taosResetTerminalMode(); + } while (shellRunCommand(command, true) == 0); + + taosMemoryFreeClear(command); + shellWriteHistory(); + shellExit(); + } while (0); taosThreadCleanupPop(1); return NULL; } int32_t shellExecute() { - printf(shell.info.clientVersion, taos_get_client_info()); + printf(shell.info.clientVersion, shell.info.cusName, + taos_get_client_info(), shell.info.cusName); fflush(stdout); SShellArgs *pArgs = &shell.args; #ifdef WEBSOCKET if (shell.args.restful || shell.args.cloud) { - if (shell_conn_ws_server(1)) { - return -1; - } + if (shell_conn_ws_server(1)) { + return -1; + } } else { #endif - if (shell.args.auth == NULL) { - shell.conn = taos_connect(pArgs->host, pArgs->user, pArgs->password, pArgs->database, pArgs->port); - } else { - shell.conn = taos_connect_auth(pArgs->host, pArgs->user, pArgs->auth, pArgs->database, pArgs->port); - } - - if (shell.conn == NULL) { - fflush(stdout); - return -1; - } + if (shell.args.auth == NULL) { + shell.conn = taos_connect(pArgs->host, pArgs->user, pArgs->password, pArgs->database, pArgs->port); + } else { + shell.conn = taos_connect_auth(pArgs->host, pArgs->user, pArgs->auth, pArgs->database, pArgs->port); + } + + if (shell.conn == NULL) { + fflush(stdout); + return -1; + } #ifdef WEBSOCKET } #endif @@ -1104,7 +1132,7 @@ int32_t shellExecute() { if (runOnce) { if (pArgs->commands != NULL) { printf("%s%s\r\n", shell.info.promptHeader, pArgs->commands); - char *cmd = strdup(pArgs->commands); + char *cmd = taosStrdup(pArgs->commands); shellRunCommand(cmd, true); taosMemoryFree(cmd); } @@ -1113,13 +1141,13 @@ int32_t shellExecute() { shellSourceFile(pArgs->file); } #ifdef WEBSOCKET - if (shell.args.restful || shell.args.cloud) { - ws_close(shell.ws_conn); - } else { + if (shell.args.restful || shell.args.cloud) { + ws_close(shell.ws_conn); + } else { #endif - taos_close(shell.conn); + taos_close(shell.conn); #ifdef WEBSOCKET - } + } #endif shellWriteHistory(); @@ -1128,7 +1156,7 @@ int32_t shellExecute() { } if (tsem_init(&shell.cancelSem, 0, 0) != 0) { - printf("failed to create cancel semphore\r\n"); + printf("failed to create cancel semaphore\r\n"); return -1; } @@ -1143,9 +1171,9 @@ int32_t shellExecute() { if (!shell.args.restful && !shell.args.cloud) { #endif #ifndef WINDOWS - printfIntroduction(); + printfIntroduction(); #endif - shellGetGrantInfo(); + shellGetGrantInfo(); #ifdef WEBSOCKET } #endif diff --git a/tools/shell/src/shellMain.c b/tools/shell/src/shellMain.c index 22b8e89959593e9da18124908fedac31bd6b45ed..795621dfddba857483df6c35240cdbbd8b944289 100644 --- a/tools/shell/src/shellMain.c +++ b/tools/shell/src/shellMain.c @@ -45,7 +45,7 @@ void shellCrashHandler(int signum, void *sigInfo, void *context) { int main(int argc, char *argv[]) { shell.exit = false; #ifdef WEBSOCKET - shell.args.timeout = 10; + shell.args.timeout = SHELL_WS_TIMEOUT; shell.args.cloud = true; #endif @@ -83,6 +83,9 @@ int main(int argc, char *argv[]) { #endif taos_init(); + // kill heart-beat thread when quit + taos_set_hb_quit(1); + if (shell.args.is_dump_config) { shellDumpConfig(); taos_cleanup(); diff --git a/tools/shell/src/shellNettest.c b/tools/shell/src/shellNettest.c index 52ce37b22c7666e5c068937e5b073b6ffb0c530c..1a6ac3489dad818feac855625d5cc502875973e0 100644 --- a/tools/shell/src/shellNettest.c +++ b/tools/shell/src/shellNettest.c @@ -21,7 +21,7 @@ static void shellWorkAsClient() { SRpcInit rpcInit = {0}; SEpSet epSet = {.inUse = 0, .numOfEps = 1}; SRpcMsg rpcRsp = {0}; - void * clientRpc = NULL; + void *clientRpc = NULL; char pass[TSDB_PASSWORD_LEN + 1] = {0}; taosEncryptPass_c((uint8_t *)("_pwd"), strlen("_pwd"), pass); @@ -31,6 +31,7 @@ static void shellWorkAsClient() { rpcInit.connType = TAOS_CONN_CLIENT; rpcInit.idleTime = tsShellActivityTimer * 1000; rpcInit.user = "_dnd"; + rpcInit.timeToGetConn = tsTimeToGetAvailableConn; clientRpc = rpcOpen(&rpcInit); if (clientRpc == NULL) { diff --git a/tools/shell/src/shellTire.c b/tools/shell/src/shellTire.c index 0ce0588cce8c143693576adaa08ea3c329a6d45c..a8726f312652734cbff34da1f4a2af0307b2822f 100644 --- a/tools/shell/src/shellTire.c +++ b/tools/shell/src/shellTire.c @@ -75,7 +75,7 @@ void freeTire(STire* tire) { // insert a new word to list bool insertToList(STire* tire, char* word) { StrName* p = (StrName*)taosMemoryMalloc(sizeof(StrName)); - p->name = strdup(word); + p->name = taosStrdup(word); p->next = NULL; if (tire->head == NULL) { @@ -218,7 +218,7 @@ void addWordToMatch(SMatch* match, char* word) { // malloc new SMatchNode* node = (SMatchNode*)taosMemoryMalloc(sizeof(SMatchNode)); memset(node, 0, sizeof(SMatchNode)); - node->word = strdup(word); + node->word = taosStrdup(word); // append to match if (match->head == NULL) { diff --git a/tools/shell/src/shellUtil.c b/tools/shell/src/shellUtil.c index 8c47d165557317dbcf710dda7d72b77037340692..e15b49efcc35da2682d003243c0a19eb278acbc7 100644 --- a/tools/shell/src/shellUtil.c +++ b/tools/shell/src/shellUtil.c @@ -50,19 +50,19 @@ bool shellRegexMatch(const char *s, const char *reg, int32_t cflags) { int32_t shellCheckIntSize() { if (sizeof(int8_t) != 1) { - printf("taos int8 size is %d(!= 1)", (int)sizeof(int8_t)); + printf("int8 size is %d(!= 1)", (int)sizeof(int8_t)); return -1; } if (sizeof(int16_t) != 2) { - printf("taos int16 size is %d(!= 2)", (int)sizeof(int16_t)); + printf("int16 size is %d(!= 2)", (int)sizeof(int16_t)); return -1; } if (sizeof(int32_t) != 4) { - printf("taos int32 size is %d(!= 4)", (int)sizeof(int32_t)); + printf("int32 size is %d(!= 4)", (int)sizeof(int32_t)); return -1; } if (sizeof(int64_t) != 8) { - printf("taos int64 size is %d(!= 8)", (int)sizeof(int64_t)); + printf("int64 size is %d(!= 8)", (int)sizeof(int64_t)); return -1; } return 0; @@ -80,7 +80,7 @@ void shellGenerateAuth() { void shellDumpConfig() { SConfig *pCfg = taosGetCfg(); if (pCfg == NULL) { - printf("TDengine read global config failed!\r\n"); + printf("read global config failed!\r\n"); } else { cfgDumpCfg(pCfg, 1, true); } diff --git a/tools/shell/src/shellWebsocket.c b/tools/shell/src/shellWebsocket.c index b93cc029643ec264f0d62ae7ff90dc73c3d5b29b..d8920cb4c3d79aacb441bf9a1f512f4a5a4f62b6 100644 --- a/tools/shell/src/shellWebsocket.c +++ b/tools/shell/src/shellWebsocket.c @@ -14,22 +14,51 @@ * along with this program. If not, see . */ #ifdef WEBSOCKET -#include "taosws.h" -#include "shellInt.h" +#include +#include int shell_conn_ws_server(bool first) { - shell.ws_conn = ws_connect_with_dsn(shell.args.dsn); - if (!shell.ws_conn) { - fprintf(stderr, "failed to connect %s, reason: %s\n", - shell.args.dsn, ws_errstr(NULL)); + char cuttedDsn[SHELL_WS_DSN_BUFF] = {0}; + int dsnLen = strlen(shell.args.dsn); + snprintf(cuttedDsn, + ((dsnLen-SHELL_WS_DSN_MASK) > SHELL_WS_DSN_BUFF)? + SHELL_WS_DSN_BUFF:(dsnLen-SHELL_WS_DSN_MASK), + "%s", shell.args.dsn); + fprintf(stdout, "trying to connect %s****** ", cuttedDsn); + fflush(stdout); + for (int i = 0; i < shell.args.timeout; i++) { + shell.ws_conn = ws_connect_with_dsn(shell.args.dsn); + if (NULL == shell.ws_conn) { + int errNo = ws_errno(NULL); + if (0xE001 == errNo) { + fprintf(stdout, "."); + fflush(stdout); + taosMsleep(1000); // sleep 1 second then try again + continue; + } else { + fprintf(stderr, "\nfailed to connect %s***, reason: %s\n", + cuttedDsn, ws_errstr(NULL)); + return -1; + } + } else { + break; + } + } + if (NULL == shell.ws_conn) { + fprintf(stdout, "\n timeout\n"); + fprintf(stderr, "\nfailed to connect %s***, reason: %s\n", + cuttedDsn, ws_errstr(NULL)); return -1; + } else { + fprintf(stdout, "\n"); } if (first && shell.args.restful) { - fprintf(stdout, "successfully connect to %s\n\n", + fprintf(stdout, "successfully connected to %s\n\n", shell.args.dsn); } else if (first && shell.args.cloud) { - fprintf(stdout, "successfully connect to cloud service\n"); + fprintf(stdout, "successfully connected to cloud service\n"); } + fflush(stdout); return 0; } @@ -37,7 +66,9 @@ static int horizontalPrintWebsocket(WS_RES* wres, double* execute_time) { const void* data = NULL; int rows; ws_fetch_block(wres, &data, &rows); - *execute_time += (double)(ws_take_timing(wres)/1E6); + if (wres) { + *execute_time += (double)(ws_take_timing(wres)/1E6); + } if (!rows) { return 0; } @@ -77,7 +108,9 @@ static int verticalPrintWebsocket(WS_RES* wres, double* pexecute_time) { int rows = 0; const void* data = NULL; ws_fetch_block(wres, &data, &rows); - *pexecute_time += (double)(ws_take_timing(wres)/1E6); + if (wres) { + *pexecute_time += (double)(ws_take_timing(wres)/1E6); + } if (!rows) { return 0; } @@ -114,7 +147,8 @@ static int verticalPrintWebsocket(WS_RES* wres, double* pexecute_time) { return numOfRows; } -static int dumpWebsocketToFile(const char* fname, WS_RES* wres, double* pexecute_time) { +static int dumpWebsocketToFile(const char* fname, WS_RES* wres, + double* pexecute_time) { char fullname[PATH_MAX] = {0}; if (taosExpandDir(fname, fullname, PATH_MAX) != 0) { tstrncpy(fullname, fname, PATH_MAX); @@ -129,7 +163,9 @@ static int dumpWebsocketToFile(const char* fname, WS_RES* wres, double* pexecute int rows = 0; const void* data = NULL; ws_fetch_block(wres, &data, &rows); - *pexecute_time += (double)(ws_take_timing(wres)/1E6); + if (wres) { + *pexecute_time += (double)(ws_take_timing(wres)/1E6); + } if (!rows) { taosCloseFile(&pFile); return 0; @@ -144,7 +180,7 @@ static int dumpWebsocketToFile(const char* fname, WS_RES* wres, double* pexecute } taosFprintfFile(pFile, "%s", fields[col].name); } - taosFprintfFile(pFile, "\r\n"); + taosFprintfFile(pFile, "\r\n"); do { uint8_t ty; uint32_t len; @@ -155,7 +191,8 @@ static int dumpWebsocketToFile(const char* fname, WS_RES* wres, double* pexecute taosFprintfFile(pFile, ","); } const void *value = ws_get_value_in_block(wres, i, j, &ty, &len); - shellDumpFieldToFile(pFile, (const char*)value, fields + j, len, precision); + shellDumpFieldToFile(pFile, (const char*)value, + fields + j, len, precision); } taosFprintfFile(pFile, "\r\n"); } @@ -165,7 +202,9 @@ static int dumpWebsocketToFile(const char* fname, WS_RES* wres, double* pexecute return numOfRows; } -static int shellDumpWebsocket(WS_RES *wres, char *fname, int *error_no, bool vertical, double* pexecute_time) { +static int shellDumpWebsocket(WS_RES *wres, char *fname, + int *error_no, bool vertical, + double* pexecute_time) { int numOfRows = 0; if (fname != NULL) { numOfRows = dumpWebsocketToFile(fname, wres, pexecute_time); @@ -218,29 +257,39 @@ void shellRunSingleCommandWebsocketImp(char *command) { res = ws_query_timeout(shell.ws_conn, command, shell.args.timeout); int code = ws_errno(res); if (code != 0 && !shell.stop_query) { - // websocket interface masked off first bit from standard error number. - if (TSDB_CODE_PAR_SYNTAX_ERROR == (code|0x80000000)) { + // if it's not a ws connection error + if (TSDB_CODE_WS_DSN_ERROR != (code&TSDB_CODE_WS_DSN_ERROR)) { et = taosGetTimestampUs(); - fprintf(stderr, "\nDB: error: %s (%.6fs)\n", ws_errstr(res), (et - st)/1E6); + fprintf(stderr, "\nDB: error: %s (%.6fs)\n", + ws_errstr(res), (et - st)/1E6); ws_free_result(res); return; } - if (code == TSDB_CODE_WS_SEND_TIMEOUT || code == TSDB_CODE_WS_RECV_TIMEOUT) { + if (code == TSDB_CODE_WS_SEND_TIMEOUT + || code == TSDB_CODE_WS_RECV_TIMEOUT) { fprintf(stderr, "Hint: use -t to increase the timeout in seconds\n"); - } else if (code == TSDB_CODE_WS_INTERNAL_ERRO || code == TSDB_CODE_WS_CLOSED) { - fprintf(stderr, "TDengine server is disconnected, will try to reconnect\n"); + } else if (code == TSDB_CODE_WS_INTERNAL_ERRO + || code == TSDB_CODE_WS_CLOSED) { shell.ws_conn = NULL; } ws_free_result(res); - if (reconnectNum == 0) continue; + if (reconnectNum == 0) { + continue; + } else { + fprintf(stderr, "The server is disconnected, will try to reconnect\n"); + } return; } break; } - double execute_time = ws_take_timing(res)/1E6; + double execute_time = 0; + if (res) { + execute_time = ws_take_timing(res)/1E6; + } - if (shellRegexMatch(command, "^\\s*use\\s+[a-zA-Z0-9_]+\\s*;\\s*$", REG_EXTENDED | REG_ICASE)) { + if (shellRegexMatch(command, "^\\s*use\\s+[a-zA-Z0-9_]+\\s*;\\s*$", + REG_EXTENDED | REG_ICASE)) { fprintf(stdout, "Database changed.\r\n\r\n"); fflush(stdout); ws_free_result(res); @@ -254,10 +303,12 @@ void shellRunSingleCommandWebsocketImp(char *command) { double total_time = (et - st)/1E3; double net_time = total_time - (double)execute_time; printf("Query Ok, %d of %d row(s) in database\n", numOfRows, numOfRows); - printf("Execute: %.2f ms Network: %.2f ms Total: %.2f ms\n", execute_time, net_time, total_time); + printf("Execute: %.2f ms Network: %.2f ms Total: %.2f ms\n", + execute_time, net_time, total_time); } else { int error_no = 0; - numOfRows = shellDumpWebsocket(res, fname, &error_no, printMode, &execute_time); + numOfRows = shellDumpWebsocket(res, fname, &error_no, + printMode, &execute_time); if (numOfRows < 0) { ws_free_result(res); return; @@ -267,11 +318,13 @@ void shellRunSingleCommandWebsocketImp(char *command) { double net_time = total_time - execute_time; if (error_no == 0 && !shell.stop_query) { printf("Query OK, %d row(s) in set\n", numOfRows); - printf("Execute: %.2f ms Network: %.2f ms Total: %.2f ms\n", execute_time, net_time, total_time); + printf("Execute: %.2f ms Network: %.2f ms Total: %.2f ms\n", + execute_time, net_time, total_time); } else { printf("Query interrupted, %d row(s) in set (%.6fs)\n", numOfRows, (et - st)/1E6); - printf("Execute: %.2f ms Network: %.2f ms Total: %.2f ms\n", execute_time, net_time, total_time); + printf("Execute: %.2f ms Network: %.2f ms Total: %.2f ms\n", + execute_time, net_time, total_time); } } printf("\n"); diff --git a/utils/test/c/CMakeLists.txt b/utils/test/c/CMakeLists.txt index b048b79e9b71058faaccdadeb723c1e0f46dce58..87b0d11d1c00f631c7c09081952af82174e2432f 100644 --- a/utils/test/c/CMakeLists.txt +++ b/utils/test/c/CMakeLists.txt @@ -3,7 +3,17 @@ add_dependencies(tmq_demo taos) add_executable(tmq_sim tmqSim.c) add_executable(create_table createTable.c) add_executable(tmq_taosx_ci tmq_taosx_ci.c) +add_executable(write_raw_block_test write_raw_block_test.c) add_executable(sml_test sml_test.c) +add_executable(get_db_name_test get_db_name_test.c) +add_executable(tmq_offset tmqOffset.c) +target_link_libraries( + tmq_offset + PUBLIC taos_static + PUBLIC util + PUBLIC common + PUBLIC os +) target_link_libraries( create_table PUBLIC taos_static @@ -33,6 +43,14 @@ target_link_libraries( PUBLIC os ) +target_link_libraries( + write_raw_block_test + PUBLIC taos_static + PUBLIC util + PUBLIC common + PUBLIC os +) + target_link_libraries( sml_test PUBLIC taos_static @@ -40,3 +58,11 @@ target_link_libraries( PUBLIC common PUBLIC os ) + +target_link_libraries( + get_db_name_test + PUBLIC taos_static + PUBLIC util + PUBLIC common + PUBLIC os +) diff --git a/utils/test/c/get_db_name_test.c b/utils/test/c/get_db_name_test.c new file mode 100644 index 0000000000000000000000000000000000000000..ebbfdc84a77a0eb3d76a5b561c9b280b3930c7a6 --- /dev/null +++ b/utils/test/c/get_db_name_test.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include "taos.h" +#include "types.h" +#include "tlog.h" + +int get_db_test() { + TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); + + TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db vgroups 2"); + taos_free_result(pRes); + + pRes = taos_query(taos, "use sml_db"); + int code = taos_errno(pRes); + taos_free_result(pRes); + ASSERT(code == 0); + + code = taos_get_current_db(taos, NULL, 0, NULL); + ASSERT(code != 0); + + int required = 0; + code = taos_get_current_db(taos, NULL, 0, &required); + ASSERT(code != 0); + ASSERT(required == 7); + + char database[10] = {0}; + code = taos_get_current_db(taos, database, 3, &required); + ASSERT(code != 0); + ASSERT(required == 7); + ASSERT(strcpy(database, "sm")); + + char database1[10] = {0}; + code = taos_get_current_db(taos, database1, 10, &required); + ASSERT(code == 0); + ASSERT(strcpy(database1, "sml_db")); + + taos_close(taos); + + return code; +} + +int main(int argc, char *argv[]) { + int ret = 0; + ret = get_db_test(); + ASSERT(!ret); + return ret; +} diff --git a/utils/test/c/sml_test.c b/utils/test/c/sml_test.c index c6073541fdfadacebc4ef49e8fd00cd0a5ef0fbb..f1dc8ebe79dd65de5f07592c96ea42f1ab26ddf6 100644 --- a/utils/test/c/sml_test.c +++ b/utils/test/c/sml_test.c @@ -19,8 +19,8 @@ #include #include #include "taos.h" -#include "types.h" #include "tlog.h" +#include "types.h" int smlProcess_influx_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); @@ -78,12 +78,23 @@ int smlProcess_telnet_Test() { pRes = taos_query(taos, "use sml_db"); taos_free_result(pRes); - const char *sql[] = {"sys.if.bytes.out 1479496100 1.3E0 host=web01 interface=eth0", - "sys.if.bytes.out 1479496101 1.3E1 interface=eth0 host=web01 ", - "sys.if.bytes.out 1479496102 1.3E3 network=tcp", - " sys.procs.running 1479496100 42 host=web01 "}; - - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_TELNET_PROTOCOL, + // char *sql[4] = {0}; + // sql[0] = taosMemoryCalloc(1, 128); + // sql[1] = taosMemoryCalloc(1, 128); + // sql[2] = taosMemoryCalloc(1, 128); + // sql[3] = taosMemoryCalloc(1, 128); + const char *sql1[] = {"sys.if.bytes.out 1479496100 1.3E0 host=web01 interface=eth0", + "sys.if.bytes.out 1479496101 1.3E1 interface=eth0 host=web01 ", + "sys.if.bytes.out 1479496102 1.3E3 network=tcp", + " sys.procs.running 1479496100 42 host=web01 "}; + + // for(int i = 0; i < 4; i++){ + // strncpy(sql[i], sql1[i], 128); + // } + + // pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_TELNET_PROTOCOL, + // TSDB_SML_TIMESTAMP_NANO_SECONDS); + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_TELNET_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); @@ -103,41 +114,92 @@ int smlProcess_json1_Test() { taos_free_result(pRes); const char *sql[] = { - "[{\"metric\":\"sys.cpu.nice\",\"timestamp\":0,\"value\":18,\"tags\":{\"host\":\"web01\",\"id\":\"t1\",\"dc\":\"lga\"}},{\"metric\":\"sys.cpu.nice\",\"timestamp\":1662344042,\"value\":9,\"tags\":{\"host\":\"web02\",\"dc\":\"lga\"}}]" - }; - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_JSON_PROTOCOL, + "[{\"metric\":\"sys.cpu.nice\",\"timestamp\":0,\"value\":18,\"tags\":{\"host\":\"web01\",\"id\":\"t1\",\"dc\":" + "\"lga\"}},{\"metric\":\"sys.cpu.nice\",\"timestamp\":1662344045,\"value\":9,\"tags\":{\"host\":\"web02\",\"dc\":" + "\"lga\"}}]"}; + + char *sql1[1] = {0}; + for (int i = 0; i < 1; i++) { + sql1[i] = taosMemoryCalloc(1, 1024); + strncpy(sql1[i], sql[i], 1023); + } + + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); + if (code != 0) { + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + } else { + printf("%s result:success\n", __FUNCTION__); + } taos_free_result(pRes); - taos_close(taos); - return code; -} + for (int i = 0; i < 1; i++) { + taosMemoryFree(sql1[i]); + } + ASSERT(code == 0); -int smlProcess_json2_Test() { - TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); - TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); - taos_free_result(pRes); + const char *sql2[] = { + "[{\"metric\":\"sys.cpu.nice\",\"timestamp\":1662344041,\"value\":13,\"tags\":{\"host\":\"web01\",\"dc\":\"lga\"}" + "},{\"metric\":\"sys.cpu.nice\",\"timestamp\":1662344042,\"value\":9,\"tags\":{\"host\":\"web02\",\"dc\":\"lga\"}" + "}]", + }; - pRes = taos_query(taos, "use sml_db"); + char *sql3[1] = {0}; + for (int i = 0; i < 1; i++) { + sql3[i] = taosMemoryCalloc(1, 1024); + strncpy(sql3[i], sql2[i], 1023); + } + + pRes = taos_schemaless_insert(taos, (char **)sql3, sizeof(sql3) / sizeof(sql3[0]), TSDB_SML_JSON_PROTOCOL, + TSDB_SML_TIMESTAMP_NANO_SECONDS); + code = taos_errno(pRes); + if (code != 0) { + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + } else { + printf("%s result:success\n", __FUNCTION__); + } taos_free_result(pRes); - const char *sql[] = { - "{\"metric\":\"meter_current0\",\"timestamp\":{\"value\":1662344042,\"type\":\"s\"},\"value\":{\"value\":10.3,\"type\":\"i64\"},\"tags\":{\"groupid\":{\"value\":2,\"type\":\"bigint\"},\"location\":{\"value\":\"北京\",\"type\":\"binary\"},\"id\":\"d1001\"}}" + for (int i = 0; i < 1; i++) { + taosMemoryFree(sql3[i]); + } + + ASSERT(code == 0); + + + // TD-22903 + const char *sql4[] = { + "[{\"metric\": \"test_us\", \"timestamp\": {\"value\": 1626006833639, \"type\": \"ms\"}, \"value\": true, \"tags\": {\"t0\": true}}, {\"metric\": \"test_us\", \"timestamp\": {\"value\": 1626006833638, \"type\": \"ms\"}, \"value\": false, \"tags\": {\"t0\": true}}]" }; - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_JSON_PROTOCOL, + char *sql5[1] = {0}; + for (int i = 0; i < 1; i++) { + sql5[i] = taosMemoryCalloc(1, 1024); + strncpy(sql5[i], sql4[i], 1023); + } + + pRes = taos_schemaless_insert(taos, (char **)sql5, sizeof(sql5) / sizeof(sql5[0]), TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); - int code = taos_errno(pRes); + code = taos_errno(pRes); + if (code != 0) { + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + } else { + printf("%s result:success\n", __FUNCTION__); + } taos_free_result(pRes); + + for (int i = 0; i < 1; i++) { + taosMemoryFree(sql5[i]); + } + ASSERT(code == 0); + taos_close(taos); return code; } -int smlProcess_json3_Test() { +int smlProcess_json2_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); @@ -147,18 +209,33 @@ int smlProcess_json3_Test() { taos_free_result(pRes); const char *sql[] = { - "{\"metric\":\"meter_current1\",\"timestamp\":{\"value\":1662344042,\"type\":\"s\"},\"value\":{\"value\":10.3,\"type\":\"i64\"},\"tags\":{\"t1\":{\"value\":2,\"type\":\"bigint\"},\"t2\":{\"value\":2,\"type\":\"int\"},\"t3\":{\"value\":2,\"type\":\"i16\"},\"t4\":{\"value\":2,\"type\":\"i8\"},\"t5\":{\"value\":2,\"type\":\"f32\"},\"t6\":{\"value\":2,\"type\":\"double\"},\"t7\":{\"value\":\"8323\",\"type\":\"binary\"},\"t8\":{\"value\":\"北京\",\"type\":\"nchar\"},\"t9\":{\"value\":true,\"type\":\"bool\"},\"id\":\"d1001\"}}"}; - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_JSON_PROTOCOL, + "{\"metric\":\"meter_current0\",\"timestamp\":{\"value\":1662344042,\"type\":\"s\"},\"value\":{\"value\":10.3," + "\"type\":\"i64\"},\"tags\":{\"groupid\":{\"value\":2,\"type\":\"bigint\"},\"location\":{\"value\":\"北京\"," + "\"type\":\"binary\"},\"id\":\"d1001\"}}"}; + char *sql1[1] = {0}; + for (int i = 0; i < 1; i++) { + sql1[i] = taosMemoryCalloc(1, 1024); + strncpy(sql1[i], sql[i], 1023); + } + + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); + if (code != 0) { + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + } else { + printf("%s result:success\n", __FUNCTION__); + } taos_free_result(pRes); taos_close(taos); + for (int i = 0; i < 1; i++) { + taosMemoryFree(sql1[i]); + } return code; } -int smlProcess_json4_Test() { +int smlProcess_json3_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); @@ -168,15 +245,27 @@ int smlProcess_json4_Test() { taos_free_result(pRes); const char *sql[] = { - "{\"metric\":\"meter_current2\",\"timestamp\":{\"value\":1662344042000,\"type\":\"ms\"},\"value\":\"ni\",\"tags\":{\"t1\":{\"value\":20,\"type\":\"i64\"},\"t2\":{\"value\":25,\"type\":\"i32\"},\"t3\":{\"value\":2,\"type\":\"smallint\"},\"t4\":{\"value\":2,\"type\":\"tinyint\"},\"t5\":{\"value\":2,\"type\":\"float\"},\"t6\":{\"value\":0.2,\"type\":\"f64\"},\"t7\":\"nsj\",\"t8\":{\"value\":\"北京\",\"type\":\"nchar\"},\"t9\":false,\"id\":\"d1001\"}}" - }; - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_JSON_PROTOCOL, + "[{\"metric\":\"sys.cpu.nice3\",\"timestamp\":0,\"value\":\"18\",\"tags\":{\"host\":\"web01\",\"id\":\"t1\",\"dc\":\"lga\"}}]"}; + char *sql1[1] = {0}; + for (int i = 0; i < 1; i++) { + sql1[i] = taosMemoryCalloc(1, 1024); + strncpy(sql1[i], sql[i], 1023); + } + + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); - printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); + if (code != 0) { + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + } else { + printf("%s result:success\n", __FUNCTION__); + } taos_free_result(pRes); taos_close(taos); + for (int i = 0; i < 1; i++) { + taosMemoryFree(sql1[i]); + } return code; } @@ -242,10 +331,10 @@ int sml_16384_Test() { printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); taos_free_result(pRes); - if(code) return code; + if (code) return code; const char *sql1[] = { - "qelhxo,id=pnnqhsa,t0=t,t1=127i8 c0=f,c1=127i8,c11=L\"ncharColValue\",c10=t 1626006833639000000", + "qelhxo,id=pnnqhsa,t0=t,t1=127i8 c0=f,c1=127i8,c11=L\"ncharColValue\",c10=t 1626006833631000000", }; pRes = taos_schemaless_insert(taos, (char **)sql1, 1, TSDB_SML_LINE_PROTOCOL, 0); printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); @@ -677,44 +766,37 @@ int sml_oom_Test() { return code; } -int sml_16368_Test() { +int sml_dup_time_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); taos_free_result(pRes); + const char *sql[] = {//"test_ms,t0=t c0=f 1626006833641", + "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." + "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " + "c0=f,c1=1i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." + "123456789f64,c7=\"xcxvwjvf\",c8=L\"ncharColValue\",c9=7u64 1626006833639000000", + "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." + "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " + "c0=T,c1=2i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." + "123456789f64,c7=\"fixrzcuq\",c8=L\"ncharColValue\",c9=7u64 1626006834639000000", + "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." + "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " + "c0=t,c1=3i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." + "123456789f64,c7=\"iupzdqub\",c8=L\"ncharColValue\",c9=7u64 1626006835639000000", + "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." + "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " + "c0=t,c1=4i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." + "123456789f64,c7=\"yvvtzzof\",c8=L\"ncharColValue\",c9=7u64 1626006836639000000", + "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." + "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " + "c0=t,c1=5i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." + "123456789f64,c7=\"vbxpilkj\",c8=L\"ncharColValue\",c9=7u64 1626006837639000000"}; pRes = taos_query(taos, "use sml_db"); taos_free_result(pRes); - const char *sql[] = { - "[{\"metric\": \"st123456\", \"timestamp\": {\"value\": 1626006833639000, \"type\": \"us\"}, \"value\": 1, " - "\"tags\": {\"t1\": 3, \"t2\": {\"value\": 4, \"type\": \"double\"}, \"t3\": {\"value\": \"t3\", \"type\": " - "\"binary\"}}}," - "{\"metric\": \"st123456\", \"timestamp\": {\"value\": 1626006833739000, \"type\": \"us\"}, \"value\": 2, " - "\"tags\": {\"t1\": {\"value\": 4, \"type\": \"double\"}, \"t3\": {\"value\": \"t4\", \"type\": \"binary\"}, " - "\"t2\": {\"value\": 5, \"type\": \"double\"}, \"t4\": {\"value\": 5, \"type\": \"double\"}}}," - "{\"metric\": \"stb_name\", \"timestamp\": {\"value\": 1626006833639100, \"type\": \"us\"}, \"value\": 3, " - "\"tags\": {\"t2\": {\"value\": 5, \"type\": \"double\"}, \"t3\": {\"value\": \"ste\", \"type\": \"nchar\"}}}," - "{\"metric\": \"stf567890\", \"timestamp\": {\"value\": 1626006833639200, \"type\": \"us\"}, \"value\": 4, " - "\"tags\": {\"t1\": {\"value\": 4, \"type\": \"bigint\"}, \"t3\": {\"value\": \"t4\", \"type\": \"binary\"}, " - "\"t2\": {\"value\": 5, \"type\": \"double\"}, \"t4\": {\"value\": 5, \"type\": \"double\"}}}," - "{\"metric\": \"st123456\", \"timestamp\": {\"value\": 1626006833639300, \"type\": \"us\"}, \"value\": " - "{\"value\": 5, \"type\": \"double\"}, \"tags\": {\"t1\": {\"value\": 4, \"type\": \"double\"}, \"t2\": 5.0, " - "\"t3\": {\"value\": \"t4\", \"type\": \"binary\"}}}," - "{\"metric\": \"stb_name\", \"timestamp\": {\"value\": 1626006833639400, \"type\": \"us\"}, \"value\": " - "{\"value\": 6, \"type\": \"double\"}, \"tags\": {\"t2\": 5.0, \"t3\": {\"value\": \"ste2\", \"type\": " - "\"nchar\"}}}," - "{\"metric\": \"stb_name\", \"timestamp\": {\"value\": 1626006834639400, \"type\": \"us\"}, \"value\": " - "{\"value\": 7, \"type\": \"double\"}, \"tags\": {\"t2\": {\"value\": 5.0, \"type\": \"double\"}, \"t3\": " - "{\"value\": \"ste2\", \"type\": \"nchar\"}}}," - "{\"metric\": \"st123456\", \"timestamp\": {\"value\": 1626006833839006, \"type\": \"us\"}, \"value\": " - "{\"value\": 8, \"type\": \"double\"}, \"tags\": {\"t1\": {\"value\": 4, \"type\": \"double\"}, \"t3\": " - "{\"value\": \"t4\", \"type\": \"binary\"}, \"t2\": {\"value\": 5, \"type\": \"double\"}, \"t4\": {\"value\": 5, " - "\"type\": \"double\"}}}," - "{\"metric\": \"st123456\", \"timestamp\": {\"value\": 1626006833939007, \"type\": \"us\"}, \"value\": " - "{\"value\": 9, \"type\": \"double\"}, \"tags\": {\"t1\": 4, \"t3\": {\"value\": \"t4\", \"type\": \"binary\"}, " - "\"t2\": {\"value\": 5, \"type\": \"double\"}, \"t4\": {\"value\": 5, \"type\": \"double\"}}}]"}; - pRes = taos_schemaless_insert(taos, (char **)sql, 0, TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_MICRO_SECONDS); + pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, 0); printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); taos_free_result(pRes); @@ -723,33 +805,17 @@ int sml_16368_Test() { return code; } -int sml_dup_time_Test() { +int sml_add_tag_col_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); taos_free_result(pRes); - const char *sql[] = {//"test_ms,t0=t c0=f 1626006833641", - "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." - "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " - "c0=false,c1=1i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." - "123456789f64,c7=\"xcxvwjvf\",c8=L\"ncharColValue\",c9=7u64 1626006833639000000", - "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." - "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " - "c0=T,c1=2i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." - "123456789f64,c7=\"fixrzcuq\",c8=L\"ncharColValue\",c9=7u64 1626006834639000000", - "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." - "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " - "c0=t,c1=3i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." - "123456789f64,c7=\"iupzdqub\",c8=L\"ncharColValue\",c9=7u64 1626006835639000000", - "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." - "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " - "c0=t,c1=4i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." - "123456789f64,c7=\"yvvtzzof\",c8=L\"ncharColValue\",c9=7u64 1626006836639000000", - "ubzlsr,id=qmtcvgd,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11." - "12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " - "c0=t,c1=5i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22." - "123456789f64,c7=\"vbxpilkj\",c8=L\"ncharColValue\",c9=7u64 1626006837639000000"}; + const char *sql[] = { + "macylr,t0=f,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64," + "t7=\"binaryTagValue\",t8=L\"ncharTagValue\" " + "c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=" + "\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64 1626006833639000000"}; pRes = taos_query(taos, "use sml_db"); taos_free_result(pRes); @@ -757,296 +823,126 @@ int sml_dup_time_Test() { printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); taos_free_result(pRes); - taos_close(taos); - - return code; -} - -int sml_16960_Test() { - TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); - - TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); - taos_free_result(pRes); + if (code) return code; - pRes = taos_query(taos, "use sml_db"); - taos_free_result(pRes); + const char *sql1[] = { + "macylr,id=macylr_17875_1804,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=" + "22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\",t11=127i8,t10=L\"ncharTagValue\" " + "c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c8=" + "L\"ncharColValue\",c9=7u64,c11=L\"ncharColValue\",c10=f 1626006833639000000"}; - const char *sql[] = { - "[" - "{" - "\"timestamp\":" - "" - "{ \"value\": 1664418955000, \"type\": \"ms\" }" - "," - "\"value\":" - "" - "{ \"value\": 830525384, \"type\": \"int\" }" - "," - "\"tags\": {" - "\"id\": \"stb00_0\"," - "\"t0\":" - "" - "{ \"value\": 83972721, \"type\": \"int\" }" - "," - "\"t1\":" - "" - "{ \"value\": 539147525, \"type\": \"int\" }" - "," - "\"t2\":" - "" - "{ \"value\": 618258572, \"type\": \"int\" }" - "," - "\"t3\":" - "" - "{ \"value\": -10536201, \"type\": \"int\" }" - "," - "\"t4\":" - "" - "{ \"value\": 349227409, \"type\": \"int\" }" - "," - "\"t5\":" - "" - "{ \"value\": 249347042, \"type\": \"int\" }" - "}," - "\"metric\": \"stb0\"" - "}," - "{" - "\"timestamp\":" - "" - "{ \"value\": 1664418955001, \"type\": \"ms\" }" - "," - "\"value\":" - "" - "{ \"value\": -588348364, \"type\": \"int\" }" - "," - "\"tags\": {" - "\"id\": \"stb00_0\"," - "\"t0\":" - "" - "{ \"value\": 83972721, \"type\": \"int\" }" - "," - "\"t1\":" - "" - "{ \"value\": 539147525, \"type\": \"int\" }" - "," - "\"t2\":" - "" - "{ \"value\": 618258572, \"type\": \"int\" }" - "," - "\"t3\":" - "" - "{ \"value\": -10536201, \"type\": \"int\" }" - "," - "\"t4\":" - "" - "{ \"value\": 349227409, \"type\": \"int\" }" - "," - "\"t5\":" - "" - "{ \"value\": 249347042, \"type\": \"int\" }" - "}," - "\"metric\": \"stb0\"" - "}," - "{" - "\"timestamp\":" - "" - "{ \"value\": 1664418955002, \"type\": \"ms\" }" - "," - "\"value\":" - "" - "{ \"value\": -370310823, \"type\": \"int\" }" - "," - "\"tags\": {" - "\"id\": \"stb00_0\"," - "\"t0\":" - "" - "{ \"value\": 83972721, \"type\": \"int\" }" - "," - "\"t1\":" - "" - "{ \"value\": 539147525, \"type\": \"int\" }" - "," - "\"t2\":" - "" - "{ \"value\": 618258572, \"type\": \"int\" }" - "," - "\"t3\":" - "" - "{ \"value\": -10536201, \"type\": \"int\" }" - "," - "\"t4\":" - "" - "{ \"value\": 349227409, \"type\": \"int\" }" - "," - "\"t5\":" - "" - "{ \"value\": 249347042, \"type\": \"int\" }" - "}," - "\"metric\": \"stb0\"" - "}," - "{" - "\"timestamp\":" - "" - "{ \"value\": 1664418955003, \"type\": \"ms\" }" - "," - "\"value\":" - "" - "{ \"value\": -811250191, \"type\": \"int\" }" - "," - "\"tags\": {" - "\"id\": \"stb00_0\"," - "\"t0\":" - "" - "{ \"value\": 83972721, \"type\": \"int\" }" - "," - "\"t1\":" - "" - "{ \"value\": 539147525, \"type\": \"int\" }" - "," - "\"t2\":" - "" - "{ \"value\": 618258572, \"type\": \"int\" }" - "," - "\"t3\":" - "" - "{ \"value\": -10536201, \"type\": \"int\" }" - "," - "\"t4\":" - "" - "{ \"value\": 349227409, \"type\": \"int\" }" - "," - "\"t5\":" - "" - "{ \"value\": 249347042, \"type\": \"int\" }" - "}," - "\"metric\": \"stb0\"" - "}," - "{" - "\"timestamp\":" - "" - "{ \"value\": 1664418955004, \"type\": \"ms\" }" - "," - "\"value\":" - "" - "{ \"value\": -330340558, \"type\": \"int\" }" - "," - "\"tags\": {" - "\"id\": \"stb00_0\"," - "\"t0\":" - "" - "{ \"value\": 83972721, \"type\": \"int\" }" - "," - "\"t1\":" - "" - "{ \"value\": 539147525, \"type\": \"int\" }" - "," - "\"t2\":" - "" - "{ \"value\": 618258572, \"type\": \"int\" }" - "," - "\"t3\":" - "" - "{ \"value\": -10536201, \"type\": \"int\" }" - "," - "\"t4\":" - "" - "{ \"value\": 349227409, \"type\": \"int\" }" - "," - "\"t5\":" - "" - "{ \"value\": 249347042, \"type\": \"int\" }" - "}," - "\"metric\": \"stb0\"" - "}" - "]"}; - - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_JSON_PROTOCOL, - TSDB_SML_TIMESTAMP_MILLI_SECONDS); + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_LINE_PROTOCOL, 0); printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); - int code = taos_errno(pRes); + code = taos_errno(pRes); taos_free_result(pRes); taos_close(taos); return code; } -int sml_add_tag_col_Test() { +int smlProcess_18784_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); - TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); + TAOS_RES *pRes = taos_query(taos, "create database if not exists db_18784 schemaless 1"); taos_free_result(pRes); - const char *sql[] = { - "macylr,t0=f,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64 1626006833639000000" - }; - pRes = taos_query(taos, "use sml_db"); + pRes = taos_query(taos, "use db_18784"); taos_free_result(pRes); + const char *sql[] = { + "disk,device=sdc inodes_used=176059i,total=1076048383523889174i 1661943960000000000", + "disk,device=sdc inodes_free=66932805i 1661943960000000000", + }; pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, 0); - printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + printf("%s result:%s, rows:%d\n", __FUNCTION__, taos_errstr(pRes), taos_affected_rows(pRes)); int code = taos_errno(pRes); + ASSERT(!code); + ASSERT(taos_affected_rows(pRes) == 1); taos_free_result(pRes); - if (code) return code; - const char *sql1[] = { - "macylr,id=macylr_17875_1804,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\",t11=127i8,t10=L\"ncharTagValue\" c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c8=L\"ncharColValue\",c9=7u64,c11=L\"ncharColValue\",c10=f 1626006833639000000" - }; - - pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_LINE_PROTOCOL, 0); - printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); - code = taos_errno(pRes); + pRes = taos_query(taos, "select * from disk"); + ASSERT(pRes); + int fieldNum = taos_field_count(pRes); + ASSERT(fieldNum == 5); + printf("fieldNum:%d\n", fieldNum); + TAOS_ROW row = NULL; + int32_t rowIndex = 0; + while ((row = taos_fetch_row(pRes)) != NULL) { + int64_t ts = *(int64_t *)row[0]; + int64_t used = *(int64_t *)row[1]; + int64_t total = *(int64_t *)row[2]; + int64_t freed = *(int64_t *)row[3]; + if (rowIndex == 0) { + ASSERT(ts == 1661943960000); + ASSERT(used == 176059); + ASSERT(total == 1076048383523889174); + ASSERT(freed == 66932805); + // ASSERT_EQ(latitude, 24.5208); + // ASSERT_EQ(longitude, 28.09377); + // ASSERT_EQ(elevation, 428); + // ASSERT_EQ(velocity, 0); + // ASSERT_EQ(heading, 304); + // ASSERT_EQ(grade, 0); + // ASSERT_EQ(fuel_consumption, 25); + } else { + // ASSERT(0); + } + rowIndex++; + } taos_free_result(pRes); taos_close(taos); return code; } -int smlProcess_18784_Test() { +int sml_escape_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); - TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); + TAOS_RES *pRes = taos_query(taos, "create database if not exists db_escape"); taos_free_result(pRes); - pRes = taos_query(taos, "use sml_db"); + pRes = taos_query(taos, "use db_escape"); taos_free_result(pRes); const char *sql[] = { - "disk,device=sdc inodes_used=176059i,total=1081101176832i 1661943960000000000", - "disk,device=sdc inodes_free=66932805i 1661943960000000000", + "d\\,i=\\ s\\k\",dev\"i\\,\\=\\ ce=s\"i\\,\\=\\ dc inode\"i\\,\\=\\ s_used=176059i,total=1076048383523889174i 1661943960000000000", + "d\\,i=\\ s\\k\",dev\"i\\,\\=\\ ce=s\"i\\,\\=\\ dc inode\"i\\,\\=\\ s_f\\\\ree=\"\\\"id,= ei\\\\\\f\" 1661943960000000000", }; pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, 0); printf("%s result:%s, rows:%d\n", __FUNCTION__, taos_errstr(pRes), taos_affected_rows(pRes)); int code = taos_errno(pRes); ASSERT(!code); - ASSERT(taos_affected_rows(pRes) == 2); + ASSERT(taos_affected_rows(pRes) == 1); taos_free_result(pRes); - pRes = taos_query(taos, "select * from disk"); + pRes = taos_query(taos, "select * from `d,i= s\\k\"`"); //check stable name ASSERT(pRes); int fieldNum = taos_field_count(pRes); ASSERT(fieldNum == 5); printf("fieldNum:%d\n", fieldNum); + + int numFields = taos_num_fields(pRes); + TAOS_FIELD *fields = taos_fetch_fields(pRes); + ASSERT(numFields == 5); + ASSERT(strncmp(fields[1].name, "inode\"i,= s_used", sizeof("inode\"i,= s_used") - 1) == 0); + ASSERT(strncmp(fields[2].name, "total", sizeof("total") - 1) == 0); + ASSERT(strncmp(fields[3].name, "inode\"i,= s_f\\\\ree", sizeof("inode\"i,= s_f\\\\ree") - 1) == 0); + ASSERT(strncmp(fields[4].name, "dev\"i,= ce", sizeof("dev\"i,= ce") - 1) == 0); + TAOS_ROW row = NULL; - int32_t rowIndex = 0; - while((row = taos_fetch_row(pRes)) != NULL) { - int64_t ts = *(int64_t*)row[0]; - int64_t used = *(int64_t*)row[1]; - int64_t total = *(int64_t*)row[2]; - int64_t freed = *(int64_t*)row[3]; - if(rowIndex == 0){ + int32_t rowIndex = 0; + while ((row = taos_fetch_row(pRes)) != NULL) { + int64_t ts = *(int64_t *)row[0]; + int64_t used = *(int64_t *)row[1]; + int64_t total = *(int64_t *)row[2]; + + if (rowIndex == 0) { ASSERT(ts == 1661943960000); ASSERT(used == 176059); - ASSERT(total == 1081101176832); - ASSERT(freed == 66932805); -// ASSERT_EQ(latitude, 24.5208); -// ASSERT_EQ(longitude, 28.09377); -// ASSERT_EQ(elevation, 428); -// ASSERT_EQ(velocity, 0); -// ASSERT_EQ(heading, 304); -// ASSERT_EQ(grade, 0); -// ASSERT_EQ(fuel_consumption, 25); - }else{ -// ASSERT(0); + ASSERT(total == 1076048383523889174); + ASSERT(strncmp(row[3], "\"id,= ei\\\\f", sizeof("\"id,= ei\\\\f") - 1) == 0); + ASSERT(strncmp(row[4], "s\"i,= dc", sizeof("s\"i,= dc") - 1) == 0); + } rowIndex++; } @@ -1063,17 +959,21 @@ int sml_19221_Test() { taos_free_result(pRes); const char *sql[] = { - "qelhxo,id=pnnqhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 1626006833639000000\nqelhxo,id=pnnhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 1626006833639000000\n#comment\nqelhxo,id=pnqhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 1626006833639000000", + "qelhxo,id=pnnqhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 " + "1626006833632000000\nqelhxo,id=pnnhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 " + "1626006833633000000\n#comment\nqelhxo,id=pnqhsa,t0=t,t1=127i8 c11=L\"ncharColValue\",c0=t,c1=127i8 " + "1626006833634000000", }; pRes = taos_query(taos, "use sml_db"); taos_free_result(pRes); - char* tmp = (char*)taosMemoryCalloc(1024, 1); + char *tmp = (char *)taosMemoryCalloc(1024, 1); memcpy(tmp, sql[0], strlen(sql[0])); - *(char*)(tmp+44) = 0; + *(char *)(tmp + 44) = 0; int32_t totalRows = 0; - pRes = taos_schemaless_insert_raw(taos, tmp, strlen(sql[0]), &totalRows, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + pRes = taos_schemaless_insert_raw(taos, tmp, strlen(sql[0]), &totalRows, TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_NANO_SECONDS); ASSERT(totalRows == 3); printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); @@ -1088,19 +988,168 @@ int sml_19221_Test() { int sml_ts2164_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); - TAOS_RES *pRes = taos_query(taos, "CREATE DATABASE IF NOT EXISTS line_test BUFFER 384 MINROWS 1000 PAGES 256 PRECISION 'ns'"); + TAOS_RES *pRes = + taos_query(taos, "CREATE DATABASE IF NOT EXISTS line_test BUFFER 384 MINROWS 1000 PAGES 256 PRECISION 'ns'"); taos_free_result(pRes); const char *sql[] = { + // "meters,location=la,groupid=ca current=11.8,voltage=221,phase=0.27", + "meters,location=la,groupid=ca current=11.8,voltage=221", "meters,location=la,groupid=ca current=11.8,voltage=221,phase=0.27", - "meters,location=la,groupid=ca current=11.8,voltage=221,phase=0.27", - "meters,location=la,groupid=cb current=11.8,voltage=221,phase=0.27", + "ts3038,location=l2a,groupid=ca current=L\"11.8\"", + "ts3038,location=l2a,groupid=ca voltage=L\"221\"", + "ts3038,location=l2a,groupid=ca phase=L\"221\"", +// "qgyltizmkq,id=sub_table_0123456,t0=f,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64", +// "qgyltizmkq,id=sub_table_0123456,t=3,t0=f,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64" + // "meters,location=la,groupid=cb current=11.8,voltage=221,phase=0.27", + }; + + pRes = taos_query(taos, "use line_test"); + taos_free_result(pRes); + + pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_MILLI_SECONDS); + + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + int code = taos_errno(pRes); + taos_free_result(pRes); + taos_close(taos); + + return code; +} + + +int sml_ts3116_Test() { + TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); + + TAOS_RES *pRes = + taos_query(taos, "DROP DATABASE IF EXISTS ts3116"); + taos_free_result(pRes); + + pRes = taos_query(taos, "CREATE DATABASE IF NOT EXISTS ts3116 BUFFER 384 MINROWS 1000 PAGES 256 PRECISION 'ns'"); + taos_free_result(pRes); + + char *sql = { + "meters,location=la,groupid=ca current=11.8,voltage=221", + }; + + pRes = taos_query(taos, "use ts3116"); + taos_free_result(pRes); + int32_t totalRows = 0; + char *tmp = (char *)taosMemoryCalloc(1024, 1); + memcpy(tmp, sql, strlen(sql)); + totalRows = 0; + pRes = taos_schemaless_insert_raw(taos, tmp, strlen(tmp), &totalRows, TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_MILLI_SECONDS); + taosMemoryFree(tmp); + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + int code = taos_errno(pRes); + taos_free_result(pRes); + + char *sql1 = { + "meters,location=la,groupid=ca\\=3 current=11.8,voltage=221\nmeters,location=la,groupid=ca current=11.8,voltage=221,phase=0.27", + }; + + pRes = taos_query(taos, "use ts3116"); + taos_free_result(pRes); + + tmp = (char *)taosMemoryCalloc(1024, 1); + memcpy(tmp, sql1, strlen(sql1)); + totalRows = 0; + pRes = taos_schemaless_insert_raw(taos, tmp, strlen(tmp), &totalRows, TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_MILLI_SECONDS); + taosMemoryFree(tmp); + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + code = taos_errno(pRes); + taos_free_result(pRes); + taos_close(taos); + + return code; +} + +int sml_td22898_Test() { + TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); + + TAOS_RES *pRes = + taos_query(taos, "CREATE DATABASE IF NOT EXISTS line_test BUFFER 384 MINROWS 1000 PAGES 256 PRECISION 'ns'"); + taos_free_result(pRes); + + const char *sql[] = { + "svlzxdfutx,id=nyavpjyfas,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" c0=t,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64 1626006833639" + }; + + pRes = taos_query(taos, "use line_test"); + taos_free_result(pRes); + + pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_MILLI_SECONDS); + + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + int code = taos_errno(pRes); + taos_free_result(pRes); + + const char *sql1[] = { + "svlzxdfutx,id=nyavpjyfas,t0=True,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"tgqkvsws\",t8=L\"ncharTagValue\" c0=f,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"htvnnldm\",c8=L\"ncharColValue\",c9=7u64 1626006833639" + }; + + pRes = taos_schemaless_insert(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_MILLI_SECONDS); + + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + code = taos_errno(pRes); + taos_free_result(pRes); + + pRes = taos_query(taos, "select * from svlzxdfutx"); + taos_free_result(pRes); + + taos_close(taos); + + return code; +} + +int sml_td22900_Test() { + TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); + + TAOS_RES *pRes = + taos_query(taos, "CREATE DATABASE IF NOT EXISTS line_test BUFFER 384 MINROWS 1000 PAGES 256 PRECISION 'ns'"); + taos_free_result(pRes); + + const char *sql[] = { + "qddkgilwfu,id=qddkgilwfu_42383_49198,t0=t,t1=127i8 c4=9223372036854775807i64,c6=11.12345f32,c6=22.123456789f64 1626006833639" }; pRes = taos_query(taos, "use line_test"); taos_free_result(pRes); - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_MILLI_SECONDS); + pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_MILLI_SECONDS); + + printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); + int code = taos_errno(pRes); + taos_free_result(pRes); + taos_close(taos); + + return code; +} + +int sml_td23881_Test() { + TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); + + TAOS_RES *pRes = + taos_query(taos, "CREATE DATABASE IF NOT EXISTS line_23881 PRECISION 'ns'"); + taos_free_result(pRes); + + char tmp[16375] = {0}; + memset(tmp, 'a', 16374); + char sql[102400] = {0}; + sprintf(sql,"lujixfvqor,t0=t c0=f,c1=\"%s\",c2=\"%s\",c3=\"%s\",c4=\"wthvqxcsrlps\" 1626006833639000000", tmp, tmp, tmp); + + pRes = taos_query(taos, "use line_23881"); + taos_free_result(pRes); + + int totalRows = 0; + pRes = taos_schemaless_insert_raw(taos, sql, strlen(sql), &totalRows, TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_NANO_SECONDS); printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); @@ -1110,29 +1159,96 @@ int sml_ts2164_Test() { return code; } +int sml_ts3303_Test() { + TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); + + TAOS_RES *pRes = taos_query(taos, "drop database if exists ts3303"); + taos_free_result(pRes); + + pRes = taos_query(taos, "create database if not exists ts3303"); + taos_free_result(pRes); + + const char *sql[] = { + "stb2,t1=1,dataModelName=t0 f1=283i32 1632299372000", + "stb2,t1=1,dataModelName=t0 f1=106i32 1632299378000", + "stb2,t1=4,dataModelName=t0 f1=144i32 1629716944000", + "stb2,t1=4,dataModelName=t0 f1=125i32 1629717012000", + "stb2,t1=4,dataModelName=t0 f1=144i32 1629717012000", + "stb2,t1=4,dataModelName=t0 f1=107i32 1629717013000", + "stb2,t1=6,dataModelName=t0 f1=154i32 1629717140000", + "stb2,t1=6,dataModelName=t0 f1=93i32 1629717140000", + "stb2,t1=6,dataModelName=t0 f1=134i32 1629717140000", + "stb2,t1=4,dataModelName=t0 f1=73i32 1629717140000", + "stb2,t1=4,dataModelName=t0 f1=83i32 1629717140000", + "stb2,t1=4,dataModelName=t0 f1=72i32 1629717140000", + }; + + const char *sql1[] = { + "meters,location=California.LosAngeles,groupid=2 current=11.8,voltage=221,phase=\"2022-02-0210:22:22\" 1626006833339000000", + "meters,groupid=2,location=California.LosAngeles current=11.8,voltage=221,phase=\"2022-02-0210:22:22\" 1626006833339000000", + }; + + pRes = taos_query(taos, "use ts3303"); + taos_free_result(pRes); + + pRes = taos_schemaless_insert_ttl(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_MILLI_SECONDS, 20); + + int code = taos_errno(pRes); + printf("%s result0:%s\n", __FUNCTION__, taos_errstr(pRes)); + taos_free_result(pRes); + ASSERT(code == 0); + + pRes = taos_schemaless_insert_ttl(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_NANO_SECONDS, 20); + + printf("%s result1:%s\n", __FUNCTION__, taos_errstr(pRes)); + taos_free_result(pRes); + + taos_close(taos); + + return code; +} + int sml_ttl_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); - TAOS_RES *pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); + TAOS_RES *pRes = taos_query(taos, "drop database if exists sml_db"); + taos_free_result(pRes); + + pRes = taos_query(taos, "create database if not exists sml_db schemaless 1"); taos_free_result(pRes); const char *sql[] = { - "meters,location=California.LosAngeles,groupid=2 current=11.8,voltage=221,phase=\"2022-02-0210:22:22\" 1626006833739000000", + "meters,location=California.LosAngeles,groupid=2 current=11.8,voltage=221,phase=\"2022-02-0210:22:22\" " + "1626006833739000000", + }; + const char *sql1[] = { + "meters,location=California.LosAngeles,groupid=2 current=11.8,voltage=221,phase=\"2022-02-0210:22:22\" " + "1626006833339000000", }; pRes = taos_query(taos, "use sml_db"); taos_free_result(pRes); - pRes = taos_schemaless_insert_ttl(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS, 20); + pRes = taos_schemaless_insert_ttl(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_NANO_SECONDS, 20); printf("%s result1:%s\n", __FUNCTION__, taos_errstr(pRes)); taos_free_result(pRes); - pRes = taos_query(taos, "select `ttl` from information_schema.ins_tables where table_name='t_be97833a0e1f523fcdaeb6291d6fdf27'"); + pRes = taos_schemaless_insert_ttl(taos, (char **)sql1, sizeof(sql1) / sizeof(sql1[0]), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_NANO_SECONDS, 20); + + printf("%s result1:%s\n", __FUNCTION__, taos_errstr(pRes)); + taos_free_result(pRes); + + pRes = taos_query( + taos, "select `ttl` from information_schema.ins_tables where table_name='t_be97833a0e1f523fcdaeb6291d6fdf27'"); printf("%s result2:%s\n", __FUNCTION__, taos_errstr(pRes)); TAOS_ROW row = taos_fetch_row(pRes); - if(row != NULL && row[0] != NULL){ - int32_t ttl = *(int32_t*)row[0]; + if (row != NULL && *row != NULL) { + int32_t ttl = *(int32_t *)row[0]; ASSERT(ttl == 20); } @@ -1143,23 +1259,91 @@ int sml_ttl_Test() { return code; } +// char *str[] ={ +// "", +// "f64", +// "F64", +// "f32", +// "F32", +// "i", +// "I", +// "i64", +// "I64", +// "u", +// "U", +// "u64", +// "U64", +// "i32", +// "I32", +// "u32", +// "U32", +// "i16", +// "I16", +// "u16", +// "U16", +// "i8", +// "I8", +// "u8", +// "U8", +// }; +// uint8_t smlCalTypeSum(char* endptr, int32_t left){ +// uint8_t sum = 0; +// for(int i = 0; i < left; i++){ +// sum += endptr[i]; +// } +// return sum; +// } + int sml_ts2385_Test() { TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0); TAOS_RES *pRes = taos_query(taos, "CREATE DATABASE IF NOT EXISTS ts2385"); taos_free_result(pRes); - const char *sql[] ={ - "DataRTU,deviceId=2211230C94K0_1,dataModelName=DataRTU_2211230C94K0_1 s5=false,s18=false,k14=0,k2=0,k8=0,k10=0,s9=false,s19=false,k11=0,k13=0,s22=false,k15=0,m2=37.416671660000006,m8=600,m10=1532,m1=20.25,m13=0,s7=false,k7=0,m16=0,s17=false,k4=0,s11=false,s15=true,m7=600,m12=1490,s1=true,m14=0,s14=false,s16=true,k5=0,hex=\"7b3b00000001030301030200000000323231313233304339344b30002b01012a10028003000000070d05da025802580258025802580258045305fc05f505d200000000000000000afc7d\",k6=0,m3=600,s3=false,s24=false,k3=0,m6=600,m15=0,s12=false,k1=0,k16=0,s10=false,s21=false,k12=0,m5=600,s8=false,m4=600,m9=1107,s2=false,s13=false,s20=false,s23=false,k9=0,m11=1525,s4=false,s6=false 1672818929178749400", - "DataRTU,deviceId=2211230C94K0_1,dataModelName=DataRTU_2211230C94K0_1 k2=0,k11=0,m3=600,m12=1506,s17=false,m5=600,s11=false,s22=false,k6=0,m13=0,s16=true,k5=0,s21=false,m4=600,m7=600,s9=false,s10=false,s18=false,k7=0,m8=600,k1=0,hex=\"7b3a00000001030301030200000000323231313233304339344b30002b01012a10028003000000071105e8025802580258025802580258044905eb05ef05e200000000000000000afc7d\",m11=1519,m16=0,s19=false,s23=false,s24=false,s14=false,s6=false,k10=0,k15=0,k14=0,s2=false,s4=false,s8=false,s13=false,s15=true,s20=false,m2=38.000005040000005,s3=false,s7=false,k3=0,k8=0,k13=0,m6=600,m14=0,m15=0,k4=0,m1=20.450000000000003,m9=1097,s1=true,m10=1515,s5=false,s12=false,k9=0,k12=0,k16=0 1672818919126971000", - "DataRTU,deviceId=2211230C94K0_1,dataModelName=DataRTU_2211230C94K0_1 k7=0,k14=0,m3=600,m7=600,s5=false,k2=0,k3=0,k8=0,s3=false,s20=false,k15=0,m10=1482,s17=false,k1=0,k16=0,m15=0,s12=false,k9=0,m16=0,s11=false,m4=600,s10=false,s15=true,s24=false,m8=600,m13=0,s2=false,s18=false,k12=0,s14=false,s19=false,hex=\"7b3900000001030301030200000000323231313233304339344b30002b01012a10028003000000071505ef025802580258025802580258045005ca05b105d800000000000000000aa47d\",s1=true,s4=false,s7=false,s8=false,s13=false,m6=600,s6=false,s21=false,k11=0,m12=1496,m9=1104,s16=true,k5=0,s9=false,k10=0,k13=0,m2=38.291671730000004,s22=false,m5=600,m11=1457,m14=0,k4=0,m1=20.650000000000006,s23=false,k6=0 1672818909130866800", - "DataRTU,deviceId=2211230C94K0_1,dataModelName=DataRTU_2211230C94K0_1 m7=600,k4=0,k14=0,s22=false,k13=0,s2=false,m11=1510,m14=0,s4=false,s10=false,m1=21,m16=0,m13=0,s9=false,s13=false,s14=false,k10=0,m3=600,m9=1107,s18=false,s19=false,k2=0,hex=\"7b3600000001030301030200000000323231313233304339344b30002b01012a10028003000000071c0619025802580258025802580258045305dc05e6058d00000000000000000ad27d\",m2=40.04167187,m8=600,k7=0,k8=0,m10=1500,s23=false,k5=0,s11=false,s21=false,k9=0,m15=0,m12=1421,s1=true,s5=false,s8=false,m5=600,k16=0,k15=0,m6=600,s3=false,s6=false,s7=false,s15=true,s20=false,s24=false,k11=0,k1=0,k6=0,k12=0,m4=600,s16=true,s17=false,k3=0,s12=false 1672818879189483200", - "DataRTU,deviceId=2106070C11M0_2,dataModelName=DataRTU_2106070C11M0_2 m1=5691,k14=0,m6=0,s14=false,k8=0,s19=false,s20=false,k12=0,s17=false,k3=0,m8=0,s8=false,m7=0,s9=false,s4=false,s11=false,s13=false,s16=false,k5=0,k15=0,k16=0,s10=false,s23=false,s1=false,s2=false,s3=false,s12=false,s24=false,k2=0,k10=0,hex=\"7b1400000001030301030200000000323130363037304331314d30002b01022a080400000000000008af0c000000000000000000000000000000000000000000000000000000000ad47d\",m2=0,s7=false,s18=false,s21=false,m3=0,m5=0,k4=0,k11=0,m4=0,k1=0,k6=0,k13=0,s6=false,s15=false,s5=false,s22=false,k7=0,k9=0 1672818779549848800" - }; + const char *sql[] = { + "DataRTU,deviceId=2211230C94K0_1,dataModelName=DataRTU_2211230C94K0_1 " + "s5=false,s18=false,k14=0,k2=0,k8=0,k10=0,s9=false,s19=false,k11=0,k13=0,s22=false,k15=0,m2=37.416671660000006," + "m8=600,m10=1532,m1=20.25,m13=0,s7=false,k7=0,m16=0,s17=false,k4=0,s11=false,s15=true,m7=600,m12=1490,s1=true," + "m14=0,s14=false,s16=true,k5=0,hex=" + "\"7b3b00000001030301030200000000323231313233304339344b30002b01012a10028003000000070d05da025802580258025802580258" + "045305fc05f505d200000000000000000afc7d\",k6=0,m3=600,s3=false,s24=false,k3=0,m6=600,m15=0,s12=false,k1=0,k16=0," + "s10=false,s21=false,k12=0,m5=600,s8=false,m4=600,m9=1107,s2=false,s13=false,s20=false,s23=false,k9=0,m11=1525," + "s4=false,s6=false 1672818929178749400", + "DataRTU,deviceId=2211230C94K0_1,dataModelName=DataRTU_2211230C94K0_1 " + "k2=0,k11=0,m3=600,m12=1506,s17=false,m5=600,s11=false,s22=false,k6=0,m13=0,s16=true,k5=0,s21=false,m4=600,m7=" + "600,s9=false,s10=false,s18=false,k7=0,m8=600,k1=0,hex=" + "\"7b3a00000001030301030200000000323231313233304339344b30002b01012a10028003000000071105e8025802580258025802580258" + "044905eb05ef05e200000000000000000afc7d\",m11=1519,m16=0,s19=false,s23=false,s24=false,s14=false,s6=false,k10=0," + "k15=0,k14=0,s2=false,s4=false,s8=false,s13=false,s15=true,s20=false,m2=38.000005040000005,s3=false,s7=false,k3=" + "0,k8=0,k13=0,m6=600,m14=0,m15=0,k4=0,m1=20.450000000000003,m9=1097,s1=true,m10=1515,s5=false,s12=false,k9=0,k12=" + "0,k16=0 1672818919126971000", + "DataRTU,deviceId=2211230C94K0_1,dataModelName=DataRTU_2211230C94K0_1 " + "k7=0,k14=0,m3=600,m7=600,s5=false,k2=0,k3=0,k8=0,s3=false,s20=false,k15=0,m10=1482,s17=false,k1=0,k16=0,m15=0," + "s12=false,k9=0,m16=0,s11=false,m4=600,s10=false,s15=true,s24=false,m8=600,m13=0,s2=false,s18=false,k12=0,s14=" + "false,s19=false,hex=" + "\"7b3900000001030301030200000000323231313233304339344b30002b01012a10028003000000071505ef025802580258025802580258" + "045005ca05b105d800000000000000000aa47d\",s1=true,s4=false,s7=false,s8=false,s13=false,m6=600,s6=false,s21=false," + "k11=0,m12=1496,m9=1104,s16=true,k5=0,s9=false,k10=0,k13=0,m2=38.291671730000004,s22=false,m5=600,m11=1457,m14=0," + "k4=0,m1=20.650000000000006,s23=false,k6=0 1672818909130866800", + "DataRTU,deviceId=2211230C94K0_1,dataModelName=DataRTU_2211230C94K0_1 " + "m7=600,k4=0,k14=0,s22=false,k13=0,s2=false,m11=1510,m14=0,s4=false,s10=false,m1=21,m16=0,m13=0,s9=false,s13=" + "false,s14=false,k10=0,m3=600,m9=1107,s18=false,s19=false,k2=0,hex=" + "\"7b3600000001030301030200000000323231313233304339344b30002b01012a10028003000000071c0619025802580258025802580258" + "045305dc05e6058d00000000000000000ad27d\",m2=40.04167187,m8=600,k7=0,k8=0,m10=1500,s23=false,k5=0,s11=false,s21=" + "false,k9=0,m15=0,m12=1421,s1=true,s5=false,s8=false,m5=600,k16=0,k15=0,m6=600,s3=false,s6=false,s7=false,s15=" + "true,s20=false,s24=false,k11=0,k1=0,k6=0,k12=0,m4=600,s16=true,s17=false,k3=0,s12=false 1672818879189483200", + "DataRTU,deviceId=2106070C11M0_2,dataModelName=DataRTU_2106070C11M0_2 " + "m1=5691,k14=0,m6=0,s14=false,k8=0,s19=false,s20=false,k12=0,s17=false,k3=0,m8=0,s8=false,m7=0,s9=false,s4=false," + "s11=false,s13=false,s16=false,k5=0,k15=0,k16=0,s10=false,s23=false,s1=false,s2=false,s3=false,s12=false,s24=" + "false,k2=0,k10=0,hex=" + "\"7b1400000001030301030200000000323130363037304331314d30002b01022a080400000000000008af0c000000000000000000000000" + "000000000000000000000000000000000ad47d\",m2=0,s7=false,s18=false,s21=false,m3=0,m5=0,k4=0,k11=0,m4=0,k1=0,k6=0," + "k13=0,s6=false,s15=false,s5=false,s22=false,k7=0,k9=0 1672818779549848800"}; pRes = taos_query(taos, "use ts2385"); taos_free_result(pRes); - pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS); + pRes = taos_schemaless_insert(taos, (char **)sql, sizeof(sql) / sizeof(sql[0]), TSDB_SML_LINE_PROTOCOL, + TSDB_SML_TIMESTAMP_NANO_SECONDS); printf("%s result:%s\n", __FUNCTION__, taos_errstr(pRes)); int code = taos_errno(pRes); @@ -1168,14 +1352,14 @@ int sml_ts2385_Test() { pRes = taos_query(taos, "select distinct tbname from `DataRTU` order by tbname"); printf("%s result2:%s\n", __FUNCTION__, taos_errstr(pRes)); - int num = 0; + int num = 0; TAOS_ROW row = NULL; - while((row = taos_fetch_row(pRes))){ - if(row[0] != NULL && num == 0){ + while ((row = taos_fetch_row(pRes))) { + if (row[0] != NULL && num == 0) { ASSERT(strncmp((char *)row[0], "DataRTU_2106070C11M0_2", sizeof("DataRTU_2106070C11M0_2") - 1) == 0); } - if(row[0] != NULL && num == 1){ + if (row[0] != NULL && num == 1) { ASSERT(strncmp((char *)row[0], "DataRTU_2211230C94K0_1", sizeof("DataRTU_2211230C94K0_1") - 1) == 0); } num++; @@ -1190,17 +1374,34 @@ int sml_ts2385_Test() { } int main(int argc, char *argv[]) { - if(argc == 2){ + if (argc == 2) { taos_options(TSDB_OPTION_CONFIGDIR, argv[1]); } int ret = 0; - ret = sml_ts2385_Test(); + ret = sml_td23881_Test(); + ASSERT(ret); + ret = sml_escape_Test(); ASSERT(!ret); + ret = sml_ts3116_Test(); + ASSERT(!ret); + ret = sml_ts2385_Test(); // this test case need config sml table name using ./sml_test config_file + ASSERT(!ret); + ret = sml_ts3303_Test(); // this test case need config sml table name using ./sml_test config_file + ASSERT(!ret); + + // for(int i = 0; i < sizeof(str)/sizeof(str[0]); i++){ + // printf("str:%s \t %d\n", str[i], smlCalTypeSum(str[i], strlen(str[i]))); + // } + // int ret = 0; ret = sml_ttl_Test(); ASSERT(!ret); ret = sml_ts2164_Test(); ASSERT(!ret); + ret = sml_td22898_Test(); + ASSERT(!ret); + ret = sml_td22900_Test(); + ASSERT(ret); ret = smlProcess_influx_Test(); ASSERT(!ret); ret = smlProcess_telnet_Test(); @@ -1211,8 +1412,6 @@ int main(int argc, char *argv[]) { ASSERT(!ret); ret = smlProcess_json3_Test(); ASSERT(!ret); - ret = smlProcess_json4_Test(); - ASSERT(!ret); ret = sml_TD15662_Test(); ASSERT(!ret); ret = sml_TD15742_Test(); @@ -1221,12 +1420,8 @@ int main(int argc, char *argv[]) { ASSERT(!ret); ret = sml_oom_Test(); ASSERT(!ret); - ret = sml_16368_Test(); - ASSERT(!ret); ret = sml_dup_time_Test(); ASSERT(!ret); - ret = sml_16960_Test(); - ASSERT(!ret); ret = sml_add_tag_col_Test(); ASSERT(!ret); ret = smlProcess_18784_Test(); diff --git a/utils/test/c/tmqDemo.c b/utils/test/c/tmqDemo.c index d105b505793eae17068af9e9db02eff5071f5bd4..ce069c2b05878cb6806f2784be896942cb701ae4 100644 --- a/utils/test/c/tmqDemo.c +++ b/utils/test/c/tmqDemo.c @@ -597,7 +597,7 @@ void printParaIntoFile() { time_t tTime = taosGetTimestampSec(); struct tm tm; - taosLocalTime(&tTime, &tm); + taosLocalTime(&tTime, &tm, NULL); taosFprintfFile(pFile, "###################################################################\n"); taosFprintfFile(pFile, "# configDir: %s\n", configDir); diff --git a/utils/test/c/tmqOffset.c b/utils/test/c/tmqOffset.c new file mode 100644 index 0000000000000000000000000000000000000000..7225cb87bdcbf77807c1861d22cef72f955d49bd --- /dev/null +++ b/utils/test/c/tmqOffset.c @@ -0,0 +1,64 @@ +// +// Created by mingming wanng on 2023/4/7. +// +#include +#include +#include "taoserror.h" +#include "tlog.h" +#include "tmsg.h" + +typedef struct { + int32_t size; +} STqOffsetHead; + +int32_t tqOffsetRestoreFromFile(const char* fname) { + TdFilePtr pFile = taosOpenFile(fname, TD_FILE_READ); + if (pFile != NULL) { + STqOffsetHead head = {0}; + int32_t code; + + while (1) { + if ((code = taosReadFile(pFile, &head, sizeof(STqOffsetHead))) != sizeof(STqOffsetHead)) { + if (code == 0) { + break; + } else { + printf("code:%d != 0\n", code); + return -1; + } + } + int32_t size = htonl(head.size); + void* memBuf = taosMemoryCalloc(1, size); + if (memBuf == NULL) { + printf("memBuf == NULL\n"); + return -1; + } + if ((code = taosReadFile(pFile, memBuf, size)) != size) { + taosMemoryFree(memBuf); + printf("code:%d != size:%d\n", code, size); + return -1; + } + STqOffset offset; + SDecoder decoder; + tDecoderInit(&decoder, memBuf, size); + if (tDecodeSTqOffset(&decoder, &offset) < 0) { + taosMemoryFree(memBuf); + tDecoderClear(&decoder); + printf("tDecodeSTqOffset error\n"); + return -1; + } + + tDecoderClear(&decoder); + printf("subkey:%s, type:%d, uid/version:%"PRId64", ts:%"PRId64"\n", + offset.subKey, offset.val.type, offset.val.uid, offset.val.ts); + taosMemoryFree(memBuf); + } + + taosCloseFile(&pFile); + } + return 0; +} + +int main(int argc, char *argv[]) { + tqOffsetRestoreFromFile("offset-ver0"); + return 0; +} diff --git a/utils/test/c/tmqSim.c b/utils/test/c/tmqSim.c index 9c1dc2e063ee96e7e593154fcc602c6b3be9073f..d98a45f0d3c3873f16ddc0134c58eeea2e6555dd 100644 --- a/utils/test/c/tmqSim.c +++ b/utils/test/c/tmqSim.c @@ -166,7 +166,7 @@ static void printHelp() { char* getCurrentTimeString(char* timeString) { time_t tTime = taosGetTimestampSec(); struct tm tm; - taosLocalTime(&tTime, &tm); + taosLocalTime(&tTime, &tm, NULL); sprintf(timeString, "%d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); @@ -232,7 +232,7 @@ void saveConfigToLogFile() { taosFprintfFile(g_fp, "%s:%s, ", g_stConfInfo.stThreads[i].key[k], g_stConfInfo.stThreads[i].value[k]); } taosFprintfFile(g_fp, "\n"); - taosFprintfFile(g_fp, " expect rows: %" PRIx64 "\n", g_stConfInfo.stThreads[i].expectMsgCnt); + taosFprintfFile(g_fp, " expect rows: %" PRId64 "\n", g_stConfInfo.stThreads[i].expectMsgCnt); } char tmpString[128]; @@ -386,7 +386,7 @@ void addRowsToVgroupId(SThreadInfo* pInfo, int32_t vgroupId, int32_t rows) { pInfo->rowsOfPerVgroups[pInfo->numOfVgroups][1] += rows; pInfo->numOfVgroups++; - taosFprintfFile(g_fp, "consume id %d, add one new vogroup id: %d\n", pInfo->consumerId, vgroupId); + taosFprintfFile(g_fp, "consume id %d, add new vgroupId:%d\n", pInfo->consumerId, vgroupId); if (pInfo->numOfVgroups > MAX_VGROUP_CNT) { taosFprintfFile(g_fp, "====consume id %d, vgroup num %d over than 32. new vgroupId: %d\n", pInfo->consumerId, pInfo->numOfVgroups, vgroupId); @@ -400,7 +400,7 @@ TAOS* createNewTaosConnect() { int32_t retryCnt = 10; while (retryCnt--) { - TAOS* taos = taos_connect(NULL, "root", "taosdata", NULL, 0); + taos = taos_connect(NULL, "root", "taosdata", NULL, 0); if (NULL != taos) { return taos; } @@ -472,7 +472,9 @@ static char* shellFormatTimestamp(char* buf, int64_t val, int32_t precision) { } struct tm ptm; - taosLocalTime(&tt, &ptm); + if (taosLocalTime(&tt, &ptm, buf) == NULL) { + return buf; + } size_t pos = strftime(buf, 35, "%Y-%m-%d %H:%M:%S", &ptm); if (precision == TSDB_TIME_PRECISION_NANO) { @@ -578,18 +580,25 @@ static int32_t data_msg_process(TAOS_RES* msg, SThreadInfo* pInfo, int32_t msgIn char buf[1024]; int32_t totalRows = 0; - // printf("topic: %s\n", tmq_get_topic_name(msg)); int32_t vgroupId = tmq_get_vgroup_id(msg); const char* dbName = tmq_get_db_name(msg); taosFprintfFile(g_fp, "consumerId: %d, msg index:%d\n", pInfo->consumerId, msgIndex); - taosFprintfFile(g_fp, "dbName: %s, topic: %s, vgroupId: %d\n", dbName != NULL ? dbName : "invalid table", - tmq_get_topic_name(msg), vgroupId); + int32_t index = 0; + for (index = 0; index < pInfo->numOfVgroups; index++) { + if (vgroupId == pInfo->rowsOfPerVgroups[index][0]) { + break; + } + } + + taosFprintfFile(g_fp, "dbName: %s, topic: %s, vgroupId:%d, currentRows:%d\n", dbName != NULL ? dbName : "invalid table", + tmq_get_topic_name(msg), vgroupId, pInfo->rowsOfPerVgroups[index][1]); while (1) { TAOS_ROW row = taos_fetch_row(msg); - - if (row == NULL) break; + if (row == NULL) { + break; + } TAOS_FIELD* fields = taos_fetch_fields(msg); int32_t numOfFields = taos_field_count(msg); @@ -607,7 +616,6 @@ static int32_t data_msg_process(TAOS_RES* msg, SThreadInfo* pInfo, int32_t msgIn #endif dumpToFileForCheck(pInfo->pConsumeRowsFile, row, fields, length, numOfFields, precision); - taos_print_row(buf, row, fields, numOfFields); if (0 != g_stConfInfo.showRowFlag) { @@ -621,7 +629,6 @@ static int32_t data_msg_process(TAOS_RES* msg, SThreadInfo* pInfo, int32_t msgIn } addRowsToVgroupId(pInfo, vgroupId, totalRows); - return totalRows; } @@ -683,16 +690,17 @@ int32_t notifyMainScript(SThreadInfo* pInfo, int32_t cmdId) { } static int32_t g_once_commit_flag = 0; -static void tmq_commit_cb_print(tmq_t* tmq, int32_t code, void* param) { - taosFprintfFile(g_fp, "tmq_commit_cb_print() commit %d\n", code); - if (0 == g_once_commit_flag) { - g_once_commit_flag = 1; - notifyMainScript((SThreadInfo*)param, (int32_t)NOTIFY_CMD_START_COMMIT); +static void tmq_commit_cb_print(tmq_t* tmq, int32_t code, void* param) { + taosFprintfFile(g_fp, "tmq_commit_cb_print() commit %d\n", code); + + if (0 == g_once_commit_flag) { + g_once_commit_flag = 1; + notifyMainScript((SThreadInfo*)param, (int32_t)NOTIFY_CMD_START_COMMIT); } - char tmpString[128]; - taosFprintfFile(g_fp, "%s tmq_commit_cb_print() be called\n", getCurrentTimeString(tmpString)); + char tmpString[128]; + taosFprintfFile(g_fp, "%s tmq_commit_cb_print() be called\n", getCurrentTimeString(tmpString)); } void build_consumer(SThreadInfo* pInfo) { @@ -730,9 +738,7 @@ void build_consumer(SThreadInfo* pInfo) { } pInfo->tmq = tmq_consumer_new(conf, NULL, 0); - tmq_conf_destroy(conf); - return; } @@ -780,7 +786,8 @@ void loop_consume(SThreadInfo* pInfo) { if (pInfo->ifCheckData) { char filename[256] = {0}; - char tmpString[128]; + memset(tmpString, 0, tListLen(tmpString)); + // sprintf(filename, "%s/../log/consumerid_%d_%s.txt", configDir, pInfo->consumerId, // getCurrentTimeString(tmpString)); sprintf(filename, "%s/../log/consumerid_%d.txt", configDir, pInfo->consumerId); @@ -816,7 +823,6 @@ void loop_consume(SThreadInfo* pInfo) { } taos_free_result(tmqMsg); - totalMsgs++; int64_t currentPrintTime = taosGetTimestampMs(); @@ -834,12 +840,12 @@ void loop_consume(SThreadInfo* pInfo) { } if ((totalRows >= pInfo->expectMsgCnt) || (totalMsgs >= pInfo->expectMsgCnt)) { - char tmpString[128]; + memset(tmpString, 0, tListLen(tmpString)); taosFprintfFile(g_fp, "%s over than expect rows, so break consume\n", getCurrentTimeString(tmpString)); break; } } else { - char tmpString[128]; + memset(tmpString, 0, tListLen(tmpString)); taosFprintfFile(g_fp, "%s no poll more msg when time over, break consume\n", getCurrentTimeString(tmpString)); break; } @@ -855,7 +861,9 @@ void loop_consume(SThreadInfo* pInfo) { taosFprintfFile(g_fp, "==== consumerId: %d, consumeMsgCnt: %" PRId64 ", consumeRowCnt: %" PRId64 "\n", pInfo->consumerId, pInfo->consumeMsgCnt, pInfo->consumeRowCnt); - taosFsyncFile(pInfo->pConsumeRowsFile); + if(taosFsyncFile(pInfo->pConsumeRowsFile) < 0){ + printf("taosFsyncFile error:%s", strerror(errno)); + } taosCloseFile(&pInfo->pConsumeRowsFile); } @@ -1113,7 +1121,7 @@ void omb_loop_consume(SThreadInfo* pInfo) { lastTotalLenOfMsg = totalLenOfMsg; } } else { - char tmpString[128]; + memset(tmpString, 0, tListLen(tmpString)); taosFprintfFile(g_fp, "%s no poll more msg when time over, break consume\n", getCurrentTimeString(tmpString)); printf("%s no poll more msg when time over, break consume\n", getCurrentTimeString(tmpString)); int64_t currentPrintTime = taosGetTimestampMs(); @@ -1381,7 +1389,7 @@ void startOmbConsume() { printf("SQL: %s\n", sql); queryDbExec(taos, sql, NO_INSERT_TYPE); - int32_t producerRate = ceil(g_stConfInfo.producerRate / g_stConfInfo.producers); + int32_t producerRate = ceil(((double)g_stConfInfo.producerRate) / g_stConfInfo.producers); printf("==== create %d produce thread ====\n", g_stConfInfo.producers); for (int32_t i = 0; i < g_stConfInfo.producers; ++i) { diff --git a/utils/test/c/tmq_taosx_ci.c b/utils/test/c/tmq_taosx_ci.c index 024a253a2e2aad97b0639468b79ff04cb177b8a4..c4becdd38196727b0ac3417c028fb4f9d698ae80 100644 --- a/utils/test/c/tmq_taosx_ci.c +++ b/utils/test/c/tmq_taosx_ci.c @@ -21,20 +21,20 @@ #include "taos.h" #include "types.h" -static int running = 1; -TdFilePtr g_fp = NULL; -typedef struct{ +static int running = 1; +TdFilePtr g_fp = NULL; +typedef struct { bool snapShot; bool dropTable; bool subTable; int srcVgroups; int dstVgroups; char dir[64]; -}Config; +} Config; Config g_conf = {0}; -static TAOS* use_db(){ +static TAOS* use_db() { TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); if (pConn == NULL) { return NULL; @@ -53,12 +53,12 @@ static void msg_process(TAOS_RES* msg) { printf("-----------topic-------------: %s\n", tmq_get_topic_name(msg)); printf("db: %s\n", tmq_get_db_name(msg)); printf("vg: %d\n", tmq_get_vgroup_id(msg)); - TAOS *pConn = use_db(); + TAOS* pConn = use_db(); if (tmq_get_res_type(msg) == TMQ_RES_TABLE_META || tmq_get_res_type(msg) == TMQ_RES_METADATA) { char* result = tmq_get_json_meta(msg); if (result) { printf("meta result: %s\n", result); - if(g_fp && strcmp(result, "") != 0){ + if (g_fp && strcmp(result, "") != 0) { taosFprintfFile(g_fp, result); taosFprintfFile(g_fp, "\n"); } @@ -71,35 +71,35 @@ static void msg_process(TAOS_RES* msg) { printf("write raw data type: %d\n", raw.raw_type); int32_t ret = tmq_write_raw(pConn, raw); printf("write raw data: %s\n", tmq_err2str(ret)); + ASSERT(ret == 0); + tmq_free_raw(raw); taos_close(pConn); } -int buildDatabase(TAOS* pConn, TAOS_RES* pRes){ - +int buildDatabase(TAOS* pConn, TAOS_RES* pRes) { /* test for TD-20612 start*/ -// pRes = taos_query(pConn,"create table tb1 (ts timestamp, c1 int, c2 int)"); -// if (taos_errno(pRes) != 0) { -// printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes)); -// return -1; -// } -// taos_free_result(pRes); -// -// pRes = taos_query(pConn,"insert into tb1 (ts, c1) values(1669092069069, 0)"); -// if (taos_errno(pRes) != 0) { -// printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes)); -// return -1; -// } -// taos_free_result(pRes); -// -// pRes = taos_query(pConn,"insert into tb1 (ts, c2) values(1669092069069, 1)"); -// if (taos_errno(pRes) != 0) { -// printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes)); -// return -1; -// } -// taos_free_result(pRes); -// -// return 0; + pRes = taos_query(pConn, "create table tb1 (ts timestamp, c1 int, c2 int)"); + if (taos_errno(pRes) != 0) { + printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + pRes = taos_query(pConn, "insert into tb1 (ts, c1) values(1669092069069, 0)"); + if (taos_errno(pRes) != 0) { + printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + pRes = taos_query(pConn, "insert into tb1 (ts, c2) values(1669092069069, 1)"); + if (taos_errno(pRes) != 0) { + printf("failed to create super table st1, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + /* test for TD-20612 end*/ pRes = taos_query(pConn, @@ -153,7 +153,10 @@ int buildDatabase(TAOS* pConn, TAOS_RES* pRes){ } taos_free_result(pRes); - pRes = taos_query(pConn, "insert into ct3 values(1626006833600, 5, 6, 'c') ct1 values(1626006833601, 2, 3, 'sds') (1626006833602, 4, 5, 'ddd') ct0 values(1626006833603, 4, 3, 'hwj') ct1 values(now+5s, 23, 32, 's21ds')"); + pRes = taos_query( + pConn, + "insert into ct3 values(1626006833600, 5, 6, 'c') ct1 values(1626006833601, 2, 3, 'sds') (1626006833602, 4, 5, " + "'ddd') ct0 values(1626006833603, 4, 3, 'hwj') ct1 values(now+5s, 23, 32, 's21ds')"); if (taos_errno(pRes) != 0) { printf("failed to insert into ct3, reason:%s\n", taos_errstr(pRes)); return -1; @@ -174,7 +177,9 @@ int buildDatabase(TAOS* pConn, TAOS_RES* pRes){ } taos_free_result(pRes); - pRes = taos_query(pConn, "insert into ct3 values(1626006833605, 53, 63, 'cffffffffffffffffffffffffffff', 8989898899999) (1626006833609, 51, 62, 'c333', 940)"); + pRes = taos_query(pConn, + "insert into ct3 values(1626006833605, 53, 63, 'cffffffffffffffffffffffffffff', 8989898899999) " + "(1626006833609, 51, 62, 'c333', 940)"); if (taos_errno(pRes) != 0) { printf("failed to insert into ct3, reason:%s\n", taos_errstr(pRes)); return -1; @@ -209,8 +214,8 @@ int buildDatabase(TAOS* pConn, TAOS_RES* pRes){ } taos_free_result(pRes); - if(g_conf.dropTable){ - pRes = taos_query(pConn, "drop table ct3 ct1"); + if (g_conf.dropTable) { + pRes = taos_query(pConn, "drop table ct3, ct1"); if (taos_errno(pRes) != 0) { printf("failed to drop child table ct3, reason:%s\n", taos_errstr(pRes)); return -1; @@ -274,7 +279,7 @@ int buildDatabase(TAOS* pConn, TAOS_RES* pRes){ } taos_free_result(pRes); - if(g_conf.dropTable){ + if (g_conf.dropTable) { pRes = taos_query(pConn, "drop table n1"); if (taos_errno(pRes) != 0) { printf("failed to drop normal table n1, reason:%s\n", taos_errstr(pRes)); @@ -318,7 +323,7 @@ int buildDatabase(TAOS* pConn, TAOS_RES* pRes){ } taos_free_result(pRes); - if(g_conf.dropTable){ + if (g_conf.dropTable) { pRes = taos_query(pConn, "create stable if not exists st1 (ts timestamp, c1 int, c2 float, c3 binary(16)) tags(t1 int, t3 " "nchar(8), t4 bool)"); @@ -354,16 +359,22 @@ int buildDatabase(TAOS* pConn, TAOS_RES* pRes){ } taos_free_result(pRes); - pRes = taos_query(pConn, "create table if not exists stt1 using stt tags(2, \"stt1\", true) sttb1 using sttb tags(4, \"sttb1\", true) " - "stt2 using stt tags(43, \"stt2\", false) sttb2 using sttb tags(54, \"sttb2\", true)"); + pRes = taos_query( + pConn, + "create table if not exists stt1 using stt tags(2, \"stt1\", true) sttb1 using sttb tags(4, \"sttb1\", true) " + "stt2 using stt tags(43, \"stt2\", false) sttb2 using sttb tags(54, \"sttb2\", true)"); if (taos_errno(pRes) != 0) { printf("failed to create child table stt1, reason:%s\n", taos_errstr(pRes)); return -1; } taos_free_result(pRes); - pRes = taos_query(pConn, "insert into stt3 using stt tags(23, \"stt3\", true) values(now + 1s, 1, 2, 'stt3') sttb3 using sttb tags(4, \"sttb3\", true) values(now + 2s, 13, 22, 'sttb3') " - "stt4 using stt tags(433, \"stt4\", false) values(now + 3s, 21, 21, 'stt4') sttb4 using sttb tags(543, \"sttb4\", true) values(now + 4s, 16, 25, 'sttb4')"); + pRes = + taos_query(pConn, + "insert into stt1 values(now + 2s, 3, 2, 'stt1') stt3 using stt tags(23, \"stt3\", true) values(now + " + "1s, 1, 2, 'stt3') sttb3 using sttb tags(4, \"sttb3\", true) values(now + 2s, 13, 22, 'sttb3') " + "stt4 using stt tags(433, \"stt4\", false) values(now + 3s, 21, 21, 'stt4') sttb4 using sttb " + "tags(543, \"sttb4\", true) values(now + 4s, 16, 25, 'sttb4')"); if (taos_errno(pRes) != 0) { printf("failed to create child table stt1, reason:%s\n", taos_errstr(pRes)); return -1; @@ -373,8 +384,10 @@ int buildDatabase(TAOS* pConn, TAOS_RES* pRes){ return 0; } -int buildStable(TAOS* pConn, TAOS_RES* pRes){ - pRes = taos_query(pConn, "CREATE STABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) TAGS (`groupid` INT, `location` VARCHAR(16))"); +int buildStable(TAOS* pConn, TAOS_RES* pRes) { + pRes = taos_query(pConn, + "CREATE STABLE `meters` (`ts` TIMESTAMP, `current` FLOAT, `voltage` INT, `phase` FLOAT) TAGS " + "(`groupid` INT, `location` VARCHAR(16))"); if (taos_errno(pRes) != 0) { printf("failed to create super table meters, reason:%s\n", taos_errstr(pRes)); return -1; @@ -395,7 +408,9 @@ int buildStable(TAOS* pConn, TAOS_RES* pRes){ } taos_free_result(pRes); - pRes = taos_query(pConn, "create stream meters_summary_s into meters_summary as select _wstart, max(current) as current, groupid, location from meters partition by groupid, location interval(10m)"); + pRes = taos_query(pConn, + "create stream meters_summary_s trigger at_once IGNORE EXPIRED 0 into meters_summary as select _wstart, max(current) as current, " + "groupid, location from meters partition by groupid, location interval(10m)"); if (taos_errno(pRes) != 0) { printf("failed to create super table meters_summary, reason:%s\n", taos_errstr(pRes)); return -1; @@ -426,7 +441,7 @@ int32_t init_env() { taos_free_result(pRes); char sql[128] = {0}; - snprintf(sql, 128, "create database if not exists db_taosx vgroups %d", g_conf.dstVgroups); + snprintf(sql, 128, "create database if not exists db_taosx vgroups %d wal_retention_period 3600", g_conf.dstVgroups); pRes = taos_query(pConn, sql); if (taos_errno(pRes) != 0) { printf("error in create db_taosx, reason:%s\n", taos_errstr(pRes)); @@ -455,7 +470,7 @@ int32_t init_env() { } taos_free_result(pRes); - snprintf(sql, 128, "create database if not exists abc1 vgroups %d", g_conf.srcVgroups); + snprintf(sql, 128, "create database if not exists abc1 vgroups %d wal_retention_period 3600", g_conf.srcVgroups); pRes = taos_query(pConn, sql); if (taos_errno(pRes) != 0) { printf("error in create db, reason:%s\n", taos_errstr(pRes)); @@ -470,9 +485,9 @@ int32_t init_env() { } taos_free_result(pRes); - if(g_conf.subTable){ + if (g_conf.subTable) { buildStable(pConn, pRes); - }else{ + } else { buildDatabase(pConn, pRes); } @@ -495,14 +510,14 @@ int32_t create_topic() { } taos_free_result(pRes); - if(g_conf.subTable){ + if (g_conf.subTable) { pRes = taos_query(pConn, "create topic meters_summary_t1 with meta as stable meters_summary"); if (taos_errno(pRes) != 0) { printf("failed to create topic meters_summary_t1, reason:%s\n", taos_errstr(pRes)); return -1; } taos_free_result(pRes); - }else{ + } else { pRes = taos_query(pConn, "create topic topic_db with meta as database abc1"); if (taos_errno(pRes) != 0) { printf("failed to create topic topic_db, reason:%s\n", taos_errstr(pRes)); @@ -527,9 +542,8 @@ tmq_t* build_consumer() { tmq_conf_set(conf, "td.connect.pass", "taosdata"); tmq_conf_set(conf, "msg.with.table.name", "true"); tmq_conf_set(conf, "enable.auto.commit", "true"); - tmq_conf_set(conf, "enable.heartbeat.background", "true"); - if(g_conf.snapShot){ + if (g_conf.snapShot) { tmq_conf_set(conf, "experimental.snapshot.enable", "true"); } @@ -542,9 +556,9 @@ tmq_t* build_consumer() { tmq_list_t* build_topic_list() { tmq_list_t* topic_list = tmq_list_new(); - if(g_conf.subTable){ + if (g_conf.subTable) { tmq_list_append(topic_list, "meters_summary_t1"); - }else{ + } else { tmq_list_append(topic_list, "topic_db"); } return topic_list; @@ -565,7 +579,7 @@ void basic_consume_loop(tmq_t* tmq, tmq_list_t* topics) { cnt++; msg_process(tmqmessage); taos_free_result(tmqmessage); - }else{ + } else { break; } } @@ -581,10 +595,10 @@ void initLogFile() { char f1[256] = {0}; char f2[256] = {0}; - if(g_conf.snapShot){ + if (g_conf.snapShot) { sprintf(f1, "%s/../log/tmq_taosx_tmp_snapshot.source", g_conf.dir); sprintf(f2, "%s/../log/tmq_taosx_tmp_snapshot.result", g_conf.dir); - }else{ + } else { sprintf(f1, "%s/../log/tmq_taosx_tmp.source", g_conf.dir); sprintf(f2, "%s/../log/tmq_taosx_tmp.result", g_conf.dir); } @@ -602,82 +616,169 @@ void initLogFile() { exit(-1); } - if(g_conf.snapShot){ - if(g_conf.subTable){ - char *result[] = { - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"meters_summary\",\"columns\":[{\"name\":\"_wstart\",\"type\":9},{\"name\":\"current\",\"type\":6},{\"name\":\"groupid\",\"type\":4},{\"name\":\"location\",\"type\":8,\"length\":16}],\"tags\":[{\"name\":\"group_id\",\"type\":14}]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"t_d2a450ee819dcf7576f0282d9ac22dbc\",\"using\":\"meters_summary\",\"tagNum\":1,\"tags\":[{\"name\":\"group_id\",\"type\":14,\"value\":1.313555008277358e+19}],\"createList\":[]}" - }; - for(int i = 0; i < sizeof(result)/sizeof(result[0]); i++){ + if (g_conf.snapShot) { + if (g_conf.subTable) { + char* result[] = { + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"meters_summary\",\"columns\":[{\"name\":\"_" + "wstart\",\"type\":9},{\"name\":\"current\",\"type\":6},{\"name\":\"groupid\",\"type\":4},{\"name\":" + "\"location\",\"type\":8,\"length\":16}],\"tags\":[{\"name\":\"group_id\",\"type\":14}]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"t_d2a450ee819dcf7576f0282d9ac22dbc\",\"using\":" + "\"meters_summary\",\"tagNum\":1,\"tags\":[{\"name\":\"group_id\",\"type\":14,\"value\":1.313555008277358e+" + "19}],\"createList\":[]}"}; + for (int i = 0; i < sizeof(result) / sizeof(result[0]); i++) { taosFprintfFile(pFile2, result[i]); taosFprintfFile(pFile2, "\n"); } - }else{ - char *result[] = { - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"st1\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":64},{\"name\":\"c4\",\"type\":5}],\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":1},{\"name\":\"t2\",\"type\":8,\"length\":64}]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct0\",\"using\":\"st1\",\"tagNum\":4,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":1000},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"ttt\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct1\",\"using\":\"st1\",\"tagNum\":4,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":2000}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct2\",\"using\":\"st1\",\"tagNum\":4,\"tags\":[],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct3\",\"using\":\"st1\",\"tagNum\":4,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":5000}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"c2\",\"type\":10,\"length\":8},{\"name\":\"cc3\",\"type\":5}],\"tags\":[]}", - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"jt\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"i\",\"type\":4}],\"tags\":[{\"name\":\"t\",\"type\":15}]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"jt1\",\"using\":\"jt\",\"tagNum\":1,\"tags\":[{\"name\":\"t\",\"type\":15,\"value\":\"{\\\"k1\\\":1,\\\"k2\\\":\\\"hello\\\"}\"}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"jt2\",\"using\":\"jt\",\"tagNum\":1,\"tags\":[],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"stt\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}],\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":1}]}", - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"sttb\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}],\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":1}]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt1\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":2},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt1\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"sttb1\",\"using\":\"sttb\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":4},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb1\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt2\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":43},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt2\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":0}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"sttb2\",\"using\":\"sttb\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":54},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb2\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt3\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":23},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt3\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"sttb3\",\"using\":\"sttb\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":4},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb3\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt4\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":433},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt4\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":0}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"sttb4\",\"using\":\"sttb\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":543},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb4\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}" - }; - for(int i = 0; i < sizeof(result)/sizeof(result[0]); i++){ + } else { + char* result[] = { + "{\"type\":\"create\",\"tableType\":\"normal\",\"tableName\":\"tb1\",\"columns\":[{\"name\":\"ts\",\"type\":" + "9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":4}],\"tags\":[]}", + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"st1\",\"columns\":[{\"name\":\"ts\",\"type\":9}" + ",{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":64},{" + "\"name\":\"c4\",\"type\":5}],\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":" + "8},{\"name\":\"t4\",\"type\":1},{\"name\":\"t2\",\"type\":8,\"length\":64}]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct0\",\"using\":\"st1\",\"tagNum\":4,\"tags\":[" + "{\"name\":\"t1\",\"type\":4,\"value\":1000},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"ttt\\\"\"},{" + "\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct1\",\"using\":\"st1\",\"tagNum\":4,\"tags\":[" + "{\"name\":\"t1\",\"type\":4,\"value\":2000}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct2\",\"using\":\"st1\",\"tagNum\":4,\"tags\":[" + "],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct3\",\"using\":\"st1\",\"tagNum\":4,\"tags\":[" + "{\"name\":\"t1\",\"type\":4,\"value\":5000}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"columns\":[{\"name\":\"ts\",\"type\":9}" + ",{\"name\":\"c2\",\"type\":10,\"length\":8},{\"name\":\"cc3\",\"type\":5}],\"tags\":[]}", + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"jt\",\"columns\":[{\"name\":\"ts\",\"type\":9}," + "{\"name\":\"i\",\"type\":4}],\"tags\":[{\"name\":\"t\",\"type\":15}]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"jt1\",\"using\":\"jt\",\"tagNum\":1,\"tags\":[{" + "\"name\":\"t\",\"type\":15,\"value\":\"{\\\"k1\\\":1,\\\"k2\\\":\\\"hello\\\"}\"}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"jt2\",\"using\":\"jt\",\"tagNum\":1,\"tags\":[]" + ",\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"stt\",\"columns\":[{\"name\":\"ts\",\"type\":9}" + ",{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}]," + "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":" + "1}]}", + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"sttb\",\"columns\":[{\"name\":\"ts\",\"type\":" + "9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}]," + "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":" + "1}]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt1\",\"using\":\"stt\",\"tagNum\":3,\"tags\":" + "[{\"name\":\"t1\",\"type\":4,\"value\":2},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt1\\\"\"},{" + "\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"sttb1\",\"using\":\"sttb\",\"tagNum\":3," + "\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":4},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb1\\\"\"}" + ",{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt2\",\"using\":\"stt\",\"tagNum\":3,\"tags\":" + "[{\"name\":\"t1\",\"type\":4,\"value\":43},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt2\\\"\"},{" + "\"name\":\"t4\",\"type\":1,\"value\":0}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"sttb2\",\"using\":\"sttb\",\"tagNum\":3," + "\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":54},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"sttb2\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt3\",\"using\":\"stt\",\"tagNum\":3,\"tags\":" + "[{\"name\":\"t1\",\"type\":4,\"value\":23},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt3\\\"\"},{" + "\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"sttb3\",\"using\":\"sttb\",\"tagNum\":3," + "\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":4},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb3\\\"\"}" + ",{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt4\",\"using\":\"stt\",\"tagNum\":3,\"tags\":" + "[{\"name\":\"t1\",\"type\":4,\"value\":433},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt4\\\"\"},{" + "\"name\":\"t4\",\"type\":1,\"value\":0}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"sttb4\",\"using\":\"sttb\",\"tagNum\":3," + "\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":543},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"sttb4\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}"}; + for (int i = 0; i < sizeof(result) / sizeof(result[0]); i++) { taosFprintfFile(pFile2, result[i]); taosFprintfFile(pFile2, "\n"); } } - }else{ - if(g_conf.subTable){ - char *result[] = { - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"meters_summary\",\"columns\":[{\"name\":\"_wstart\",\"type\":9},{\"name\":\"current\",\"type\":6},{\"name\":\"groupid\",\"type\":4},{\"name\":\"location\",\"type\":8,\"length\":16}],\"tags\":[{\"name\":\"group_id\",\"type\":14}]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"t_d2a450ee819dcf7576f0282d9ac22dbc\",\"using\":\"meters_summary\",\"tagNum\":1,\"tags\":[{\"name\":\"group_id\",\"type\":14,\"value\":1.313555008277358e+19}],\"createList\":[]}" - }; - - for(int i = 0; i < sizeof(result)/sizeof(result[0]); i++){ + } else { + if (g_conf.subTable) { + char* result[] = { + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"meters_summary\",\"columns\":[{\"name\":\"_" + "wstart\",\"type\":9},{\"name\":\"current\",\"type\":6},{\"name\":\"groupid\",\"type\":4},{\"name\":" + "\"location\",\"type\":8,\"length\":16}],\"tags\":[{\"name\":\"group_id\",\"type\":14}]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"t_d2a450ee819dcf7576f0282d9ac22dbc\",\"using\":" + "\"meters_summary\",\"tagNum\":1,\"tags\":[{\"name\":\"group_id\",\"type\":14,\"value\":1.313555008277358e+" + "19}],\"createList\":[]}"}; + + for (int i = 0; i < sizeof(result) / sizeof(result[0]); i++) { taosFprintfFile(pFile2, result[i]); taosFprintfFile(pFile2, "\n"); } - }else{ - char *result[] = { - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"st1\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}],\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":1}]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct0\",\"using\":\"st1\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":1000},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"ttt\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct1\",\"using\":\"st1\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":2000}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct2\",\"using\":\"st1\",\"tagNum\":3,\"tags\":[],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct3\",\"using\":\"st1\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":3000}],\"createList\":[]}", - "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":5,\"colName\":\"c4\",\"colType\":5}", - "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":7,\"colName\":\"c3\",\"colType\":8,\"colLength\":64}", - "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":1,\"colName\":\"t2\",\"colType\":8,\"colLength\":64}", - "{\"type\":\"alter\",\"tableType\":\"child\",\"tableName\":\"ct3\",\"alterType\":4,\"colName\":\"t1\",\"colValue\":\"5000\",\"colValueNull\":false}", + } else { + char* result[] = { + "{\"type\":\"create\",\"tableType\":\"normal\",\"tableName\":\"tb1\",\"columns\":[{\"name\":\"ts\",\"type\":" + "9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":4}],\"tags\":[]}", + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"st1\",\"columns\":[{\"name\":\"ts\",\"type\":9}" + ",{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}]," + "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":" + "1}]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct0\",\"using\":\"st1\",\"tagNum\":3,\"tags\":[" + "{\"name\":\"t1\",\"type\":4,\"value\":1000},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"ttt\\\"\"},{" + "\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct1\",\"using\":\"st1\",\"tagNum\":3,\"tags\":[" + "{\"name\":\"t1\",\"type\":4,\"value\":2000}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct2\",\"using\":\"st1\",\"tagNum\":3,\"tags\":[" + "],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"ct3\",\"using\":\"st1\",\"tagNum\":3,\"tags\":[" + "{\"name\":\"t1\",\"type\":4,\"value\":3000}],\"createList\":[]}", + "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":5,\"colName\":\"c4\"," + "\"colType\":5}", + "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":7,\"colName\":\"c3\"," + "\"colType\":8,\"colLength\":64}", + "{\"type\":\"alter\",\"tableType\":\"super\",\"tableName\":\"st1\",\"alterType\":1,\"colName\":\"t2\"," + "\"colType\":8,\"colLength\":64}", + "{\"type\":\"alter\",\"tableType\":\"child\",\"tableName\":\"ct3\",\"alterType\":4,\"colName\":\"t1\"," + "\"colValue\":\"5000\",\"colValueNull\":false}", "{\"type\":\"delete\",\"sql\":\"delete from `ct3` where `ts` >= 1626006833600 and `ts` <= 1626006833605\"}", - "{\"type\":\"create\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":10,\"length\":4}],\"tags\":[]}", - "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":5,\"colName\":\"c3\",\"colType\":5}", - "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":7,\"colName\":\"c2\",\"colType\":10,\"colLength\":8}", - "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":10,\"colName\":\"c3\",\"colNewName\":\"cc3\"}", + "{\"type\":\"create\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"columns\":[{\"name\":\"ts\",\"type\":9}" + ",{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":10,\"length\":4}],\"tags\":[]}", + "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":5,\"colName\":\"c3\"," + "\"colType\":5}", + "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":7,\"colName\":\"c2\"," + "\"colType\":10,\"colLength\":8}", + "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":10,\"colName\":\"c3\"," + "\"colNewName\":\"cc3\"}", "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":9}", "{\"type\":\"alter\",\"tableType\":\"normal\",\"tableName\":\"n1\",\"alterType\":6,\"colName\":\"c1\"}", - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"jt\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"i\",\"type\":4}],\"tags\":[{\"name\":\"t\",\"type\":15}]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"jt1\",\"using\":\"jt\",\"tagNum\":1,\"tags\":[{\"name\":\"t\",\"type\":15,\"value\":\"{\\\"k1\\\":1,\\\"k2\\\":\\\"hello\\\"}\"}],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"jt2\",\"using\":\"jt\",\"tagNum\":1,\"tags\":[],\"createList\":[]}", - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"stt\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}],\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":1}]}", - "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"sttb\",\"columns\":[{\"name\":\"ts\",\"type\":9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}],\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":1}]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt1\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":2},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt1\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[{\"tableName\":\"stt1\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":2},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt1\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]},{\"tableName\":\"sttb1\",\"using\":\"sttb\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":4},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb1\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]},{\"tableName\":\"stt2\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":43},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt2\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":0}]},{\"tableName\":\"sttb2\",\"using\":\"sttb\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":54},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb2\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]}]}", - "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt3\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":23},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt3\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[{\"tableName\":\"stt3\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":23},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt3\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]},{\"tableName\":\"sttb3\",\"using\":\"sttb\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":4},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb3\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]},{\"tableName\":\"stt4\",\"using\":\"stt\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":433},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt4\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":0}]},{\"tableName\":\"sttb4\",\"using\":\"sttb\",\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":543},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"sttb4\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]}]}" - }; - - for(int i = 0; i < sizeof(result)/sizeof(result[0]); i++){ + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"jt\",\"columns\":[{\"name\":\"ts\",\"type\":9}," + "{\"name\":\"i\",\"type\":4}],\"tags\":[{\"name\":\"t\",\"type\":15}]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"jt1\",\"using\":\"jt\",\"tagNum\":1,\"tags\":[{" + "\"name\":\"t\",\"type\":15,\"value\":\"{\\\"k1\\\":1,\\\"k2\\\":\\\"hello\\\"}\"}],\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"jt2\",\"using\":\"jt\",\"tagNum\":1,\"tags\":[]" + ",\"createList\":[]}", + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"stt\",\"columns\":[{\"name\":\"ts\",\"type\":9}" + ",{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}]," + "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":" + "1}]}", + "{\"type\":\"create\",\"tableType\":\"super\",\"tableName\":\"sttb\",\"columns\":[{\"name\":\"ts\",\"type\":" + "9},{\"name\":\"c1\",\"type\":4},{\"name\":\"c2\",\"type\":6},{\"name\":\"c3\",\"type\":8,\"length\":16}]," + "\"tags\":[{\"name\":\"t1\",\"type\":4},{\"name\":\"t3\",\"type\":10,\"length\":8},{\"name\":\"t4\",\"type\":" + "1}]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt1\",\"using\":\"stt\",\"tagNum\":3,\"tags\":" + "[{\"name\":\"t1\",\"type\":4,\"value\":2},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt1\\\"\"},{" + "\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[{\"tableName\":\"stt1\",\"using\":\"stt\"," + "\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":2},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"stt1\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]},{\"tableName\":\"sttb1\",\"using\":\"sttb\"," + "\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":4},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"sttb1\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]},{\"tableName\":\"stt2\",\"using\":\"stt\"," + "\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":43},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"stt2\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":0}]},{\"tableName\":\"sttb2\",\"using\":\"sttb\"," + "\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":54},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"sttb2\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]}]}", + "{\"type\":\"create\",\"tableType\":\"child\",\"tableName\":\"stt3\",\"using\":\"stt\",\"tagNum\":3,\"tags\":" + "[{\"name\":\"t1\",\"type\":4,\"value\":23},{\"name\":\"t3\",\"type\":10,\"value\":\"\\\"stt3\\\"\"},{" + "\"name\":\"t4\",\"type\":1,\"value\":1}],\"createList\":[{\"tableName\":\"stt3\",\"using\":\"stt\"," + "\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":23},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"stt3\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]},{\"tableName\":\"sttb3\",\"using\":\"sttb\"," + "\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":4},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"sttb3\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]},{\"tableName\":\"stt4\",\"using\":\"stt\"," + "\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":433},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"stt4\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":0}]},{\"tableName\":\"sttb4\",\"using\":\"sttb\"," + "\"tagNum\":3,\"tags\":[{\"name\":\"t1\",\"type\":4,\"value\":543},{\"name\":\"t3\",\"type\":10,\"value\":" + "\"\\\"sttb4\\\"\"},{\"name\":\"t4\",\"type\":1,\"value\":1}]}]}"}; + + for (int i = 0; i < sizeof(result) / sizeof(result[0]); i++) { taosFprintfFile(pFile2, result[i]); taosFprintfFile(pFile2, "\n"); } @@ -689,23 +790,23 @@ void initLogFile() { int main(int argc, char* argv[]) { for (int32_t i = 1; i < argc; i++) { - if(strcmp(argv[i], "-c") == 0){ + if (strcmp(argv[i], "-c") == 0) { tstrncpy(g_conf.dir, argv[++i], sizeof(g_conf.dir)); - }else if(strcmp(argv[i], "-s") == 0){ + } else if (strcmp(argv[i], "-s") == 0) { g_conf.snapShot = true; - }else if(strcmp(argv[i], "-d") == 0){ + } else if (strcmp(argv[i], "-d") == 0) { g_conf.dropTable = true; - }else if(strcmp(argv[i], "-sv") == 0){ + } else if (strcmp(argv[i], "-sv") == 0) { g_conf.srcVgroups = atol(argv[++i]); - }else if(strcmp(argv[i], "-dv") == 0){ + } else if (strcmp(argv[i], "-dv") == 0) { g_conf.dstVgroups = atol(argv[++i]); - }else if(strcmp(argv[i], "-t") == 0){ + } else if (strcmp(argv[i], "-t") == 0) { g_conf.subTable = true; } } printf("env init\n"); - if(strlen(g_conf.dir) != 0){ + if (strlen(g_conf.dir) != 0) { initLogFile(); } diff --git a/utils/test/c/write_raw_block_test.c b/utils/test/c/write_raw_block_test.c new file mode 100644 index 0000000000000000000000000000000000000000..8e5dd6275217b194fa4154fdd1235fdb27e397f1 --- /dev/null +++ b/utils/test/c/write_raw_block_test.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "taos.h" +#include "types.h" + +int buildStable(TAOS* pConn, TAOS_RES* pRes) { + pRes = taos_query(pConn, + "CREATE STABLE `meters` (`ts` TIMESTAMP, `current` INT, `voltage` INT, `phase` FLOAT) TAGS " + "(`groupid` INT, `location` VARCHAR(16))"); + if (taos_errno(pRes) != 0) { + printf("failed to create super table meters, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + pRes = taos_query(pConn, "create table d0 using meters tags(1, 'San Francisco')"); + if (taos_errno(pRes) != 0) { + printf("failed to create child table d0, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + pRes = taos_query(pConn, "insert into d0 (ts, current) values (now, 120)"); + if (taos_errno(pRes) != 0) { + printf("failed to insert into table d0, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + pRes = taos_query(pConn, "create table d1 using meters tags(2, 'San Francisco')"); + if (taos_errno(pRes) != 0) { + printf("failed to create child table d1, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + pRes = taos_query(pConn, "create table d2 using meters tags(3, 'San Francisco')"); + if (taos_errno(pRes) != 0) { + printf("failed to create child table d1, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + return 0; +} + +int32_t init_env() { + TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0); + if (pConn == NULL) { + return -1; + } + + TAOS_RES* pRes = taos_query(pConn, "drop database if exists db_raw"); + if (taos_errno(pRes) != 0) { + printf("error in drop db_taosx, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + pRes = taos_query(pConn, "create database if not exists db_raw vgroups 2"); + if (taos_errno(pRes) != 0) { + printf("error in create db_taosx, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + pRes = taos_query(pConn, "use db_raw"); + if (taos_errno(pRes) != 0) { + printf("error in create db_taosx, reason:%s\n", taos_errstr(pRes)); + return -1; + } + taos_free_result(pRes); + + buildStable(pConn, pRes); + + pRes = taos_query(pConn, "select * from d0"); + if (taos_errno(pRes) != 0) { + printf("error in drop db_taosx, reason:%s\n", taos_errstr(pRes)); + return -1; + } + void *data = NULL; + int32_t numOfRows = 0; + int error_code = taos_fetch_raw_block(pRes, &numOfRows, &data); + ASSERT(error_code == 0); + ASSERT(numOfRows == 1); + + taos_write_raw_block(pConn, numOfRows, data, "d1"); + taos_free_result(pRes); + + pRes = taos_query(pConn, "select ts,phase from d0"); + if (taos_errno(pRes) != 0) { + printf("error in drop db_taosx, reason:%s\n", taos_errstr(pRes)); + return -1; + } + error_code = taos_fetch_raw_block(pRes, &numOfRows, &data); + ASSERT(error_code == 0); + ASSERT(numOfRows == 1); + + int numFields = taos_num_fields(pRes); + TAOS_FIELD *fields = taos_fetch_fields(pRes); + taos_write_raw_block_with_fields(pConn, numOfRows, data, "d2", fields, numFields); + taos_free_result(pRes); + + taos_close(pConn); + return 0; +} + +int main(int argc, char* argv[]) { + if (init_env() < 0) { + return -1; + } +} diff --git a/utils/tsim/src/simExe.c b/utils/tsim/src/simExe.c index 258c61155769be2d3aef314ee1602a4ba1b8af3d..1be28635ef721167d67a33e7837f782c70e17d49 100644 --- a/utils/tsim/src/simExe.c +++ b/utils/tsim/src/simExe.c @@ -31,21 +31,21 @@ void simLogSql(char *sql, bool useSharp) { taosFprintfFile(pFile, "%s;\n", sql); } - taosFsyncFile(pFile); + UNUSED(taosFsyncFile(pFile)); } } char *simParseHostName(char *varName) { static char hostName[140]; -#ifdef WINDOWS - hostName[0] = '\"'; - taosGetFqdn(&hostName[1]); - int strEndIndex = strlen(hostName); - hostName[strEndIndex] = '\"'; - hostName[strEndIndex + 1] = '\0'; -#else +//#ifdef WINDOWS +// hostName[0] = '\"'; +// taosGetFqdn(&hostName[1]); +// int strEndIndex = strlen(hostName); +// hostName[strEndIndex] = '\"'; +// hostName[strEndIndex + 1] = '\0'; +//#else sprintf(hostName, "%s", "localhost"); -#endif +//#endif return hostName; } @@ -376,6 +376,20 @@ bool simExecuteRunBackCmd(SScript *script, char *option) { return true; } +void simReplaceDirSep (char *buf){ +#ifdef WINDOWS + int i=0; + while(buf[i] != '\0') + { + if(buf[i] == '/') + { + buf[i] = '\\'; + } + i++; + } +#endif +} + bool simReplaceStr(char *buf, char *src, char *dst) { bool replaced = false; char *begin = strstr(buf, src); @@ -407,9 +421,10 @@ bool simExecuteSystemCmd(SScript *script, char *option) { sprintf(buf, "cd %s; ", simScriptDir); simVisuallizeOption(script, option, buf + strlen(buf)); #else - sprintf(buf, "%s", simScriptDir); + sprintf(buf, "cd %s && ", simScriptDir); simVisuallizeOption(script, option, buf + strlen(buf)); simReplaceStr(buf, ".sh", ".bat"); + simReplaceDirSep(buf); #endif if (useValgrind) { @@ -471,6 +486,8 @@ bool simExecuteSystemContentCmd(SScript *script, char *option) { #ifdef WINDOWS sprintf(buf, "cd %s && ", simScriptDir); simVisuallizeOption(script, option, buf + strlen(buf)); + simReplaceStr(buf, ".sh", ".bat"); + simReplaceDirSep(buf); sprintf(buf1, "%s > %s 2>nul", buf, filename); #else sprintf(buf, "cd %s; ", simScriptDir); @@ -755,7 +772,9 @@ bool simExecuteNativeSqlCommand(SScript *script, char *rest, bool isSlow) { tt = (*(int64_t *)row[i]) / 1000000000; } - taosLocalTime(&tt, &tp); + if (taosLocalTime(&tt, &tp, timeStr) == NULL) { + break; + } strftime(timeStr, 64, "%y-%m-%d %H:%M:%S", &tp); if (precision == TSDB_TIME_PRECISION_MILLI) { sprintf(value, "%s.%03d", timeStr, (int32_t)(*((int64_t *)row[i]) % 1000));